import { createHash } from "crypto" ; import { build as esbuild } from "esbuild" ; import * as path from "path" ; import postcss , { Plugin , Rule } from "postcss" ; import { EMPTY , Observable , catchError , concat , defer , endWith , ignoreElements , merge , of , switchMap } from "rxjs" ; import { compile } from "sass" ; import { base , mkdir , write } from "../_" ; /**
 * Transform options
 */ interface TransformOptions { from : string ; to : string ; } /**
 * Base directory for source map resolution
 */ const root = new RegExp ( `file://${ path . resolve ( "." ) }/` , "g" ) ; param file param data returns function digest ( file , data ) { if ( process . argv . includes ( "--optimize" ) ) { const hash = createHash ( "sha256" ) . update ( data ) . digest ( "hex" ) ; return file . replace ( /\b(?=\.)/ , `.${ hash . slice ( 0 , 8 ) }.min` ) ; } else { return file ; } } returns function plugin ( ) { const rules = new Set < Rule > ( ) ; return { postcssPlugin : 'mkdocs-material' , Root ( root ) { root . walkRules ( /:is\(/ , rule => { if ( ! rules . has ( rule ) ) { rules . add ( rule ) ; for ( const pseudo of [ ":-webkit-any(" , ":-moz-any(" ] ) rule . cloneBefore ( { selectors : rule . selectors . map ( selector => ( selector . replace ( /:is\(/g , pseudo ) ) ) } ) ; } } ) ; } } ; } plugin . postcss = true ; param options returns export function transformStyle ( options ) { return defer ( ( ) => of ( compile ( options . from , { loadPaths : [ "src/assets/stylesheets" , "node_modules/modularscale-sass/stylesheets" , "node_modules/material-design-color" , "node_modules/material-shadows" ] , sourceMap : true } ) ) ) . pipe ( switchMap ( ( { css , sourceMap } ) => postcss ( [ require ( "autoprefixer" ) , require ( "postcss-logical" ) , require ( "postcss-dir-pseudo-class" ) , plugin , require ( "postcss-inline-svg" ) ( { paths : [ `${ base }/.icons` ] , encode : false } ) , ... process . argv . includes ( "--optimize" ) ? [ require ( "cssnano" ) ] : [ ] ] ) . process ( css , { from : options . from , to : options . to , map : { prev : sourceMap , inline : false } } ) ) , catchError ( err => { console . log ( err . formatted || err . message ) ; return EMPTY ; } ) , switchMap ( ( { css , map } ) => { const file = digest ( options . to , css ) ; return concat ( mkdir ( path . dirname ( file ) ) , merge ( write ( `${ file }.map` , `${ map }` . replace ( root , "" ) ) , write ( `${ file }` , css . replace ( options . from , path . basename ( file ) ) ) ) ) . pipe ( ignoreElements ( ) , endWith ( file ) ) ; } ) ) ; } param options returns export function transformScript ( options ) { return defer ( ( ) => esbuild ( { entryPoints : [ options . from ] , target : "es2015" , write : false , bundle : true , sourcemap : true , sourceRoot : "../../../.." , legalComments : "inline" , minify : process . argv . includes ( "--optimize" ) } ) ) . pipe ( switchMap ( ( { outputFiles : [ file ] } ) => { const contents = file . text . split ( "\n" ) ; const [ , data ] = contents [ contents . length - 2 ] . split ( "," ) ; return of ( { js : file . text , map : Buffer . from ( data , "base64" ) } ) ; } ) , catchError ( ( ) => EMPTY ) , switchMap ( ( { js , map } ) => { const file = digest ( options . to , js ) ; return concat ( mkdir ( path . dirname ( file ) ) , merge ( write ( `${ file }.map` , `${ map }` ) , write ( `${ file }` , js . replace ( /(sourceMappingURL=)(.*)/ , `$1${ path . basename ( file ) }.map\n` ) ) ) ) . pipe ( ignoreElements ( ) , endWith ( file ) ) ; } ) ) ; }