import { minify as minhtml } from "html-minifier" ; import * as path from "path" ; import { EMPTY , concat , concatMap , defer , map , merge , of , reduce , scan , startWith , switchMap , switchMapTo , toArray , zip } from "rxjs" ; import { extendDefaultPlugins , optimize } from "svgo" ; import { IconSearchIndex } from "_/components" ; import { base , read , resolve , watch , write } from "./_" ; import { copyAll } from "./copy" ; import { transformScript , transformStyle } from "./transform" ; /**
 * Twemoji icon
 */ interface TwemojiIcon { unicode : string ; } param file param extension returns function ext ( file , extension ) { return file . replace ( path . extname ( file ) , extension ) ; } param data returns function minsvg ( data ) { const result = optimize ( data , { plugins : extendDefaultPlugins ( [ { name : "removeDimensions" , active : true } , { name : "removeViewBox" , active : false } ] ) } ) ; return result . data || data ; } const assets$ = concat ( ... [ "*.svg" , "../LICENSE" ] . map ( pattern => copyAll ( pattern , { from : "node_modules/@mdi/svg/svg" , to : `${ base }/.icons/material` , transform : async ( data ) => minsvg ( data ) } ) ) , ... [ "*.svg" , "../../LICENSE" ] . map ( pattern => copyAll ( pattern , { from : "node_modules/@primer/octicons/build/svg" , to : `${ base }/.icons/octicons` , transform : async ( data ) => minsvg ( data ) } ) ) , ... [ "**/*.svg" , "../LICENSE.txt" ] . map ( pattern => copyAll ( pattern , { from : "node_modules/@fortawesome/fontawesome-free/svgs" , to : `${ base }/.icons/fontawesome` , transform : async ( data ) => minsvg ( data ) } ) ) , ... [ "min/*.js" , "tinyseg.js" , "wordcut.js" ] . map ( pattern => copyAll ( pattern , { from : "node_modules/lunr-languages" , to : `${ base }/assets/javascripts/lunr` } ) ) , ... [ ".icons/*.svg" , "assets/images/*" , "**/*.{py,yml}" ] . map ( pattern => copyAll ( pattern , { from : "src" , to : base } ) ) ) ; const stylesheets$ = resolve ( "**/[!_]*.scss" , { cwd : "src" } ) . pipe ( concatMap ( file => zip ( of ( ext ( file , ".css" ) ) , transformStyle ( { from : `src/${ file }` , to : ext ( `${ base }/${ file }` , ".css" ) } ) ) ) ) ; const javascripts$ = resolve ( "**/{bundle,search}.ts" , { cwd : "src" } ) . pipe ( concatMap ( file => zip ( of ( ext ( file , ".js" ) ) , transformScript ( { from : `src/${ file }` , to : ext ( `${ base }/${ file }` , ".js" ) } ) ) ) ) ; const manifest$ = merge ( ... Object . entries ( { "**/*.scss" : stylesheets$ , "**/*.ts*" : javascripts$ } ) . map ( ( [ pattern , observable$ ] ) => ( defer ( ( ) => process . argv . includes ( "--watch" ) ? watch ( pattern , { cwd : "src" } ) : EMPTY ) . pipe ( startWith ( "*" ) , switchMapTo ( observable$ . pipe ( toArray ( ) ) ) ) ) ) ) . pipe ( scan ( ( prev , mapping ) => ( mapping . reduce ( ( next , [ key , value ] ) => ( next . set ( key , value . replace ( `${ base }/` , "" ) ) ) , prev ) ) , new Map < string , string > ( ) ) ) ; const templates$ = manifest$ . pipe ( switchMap ( manifest => copyAll ( "**/*.html" , { from : "src" , to : base , watch : process . argv . includes ( "--watch" ) , transform : async ( data ) => { const metadata = require ( "../../package.json" ) ; const banner = "{#-\n" + "  This file was automatically generated - do not edit\n" + "-#}\n" ; if ( process . argv . includes ( "--optimize" ) ) for ( const [ key , value ] of manifest ) data = data . replace ( new RegExp ( `('|")${ key }\\1` , "g" ) , `$1${ value }$1` ) ; const html = data . replace ( /\r\n/gm , "\n" ) ; return banner + minhtml ( html , { collapseBooleanAttributes : true , includeAutoGeneratedTags : false , minifyCSS : true , minifyJS : true , removeComments : true , removeScriptTypeAttributes : true , removeStyleLinkTypeAttributes : true } ) . replace ( /^\s*[\r\n]/gm , "" ) . replace ( "$md-name$" , metadata . name ) . replace ( "$md-version$" , metadata . version ) ; } } ) ) ) ; const icons$ = defer ( ( ) => resolve ( "**/*.svg" , { cwd : "material/.icons" } ) ) . pipe ( reduce ( ( index , file ) => index . set ( file . replace ( /\.svg$/ , "" ) . replace ( /\//g , "-" ) , file ) , new Map < string , string > ( ) ) ) ; const emojis$ = defer ( ( ) => resolve ( "venv/**/twemoji_db.py" ) ) . pipe ( switchMap ( file => read ( file ) ) , map ( data => { const [ , payload ] = data . match ( /^emoji = ({.*})$.alias/ms ) ! ; return Object . entries < TwemojiIcon > ( JSON . parse ( payload ) ) . reduce ( ( index , [ name , { unicode } ] ) => index . set ( name . replace ( /(^:|:$)/g , "" ) , `${ unicode }.svg` ) , new Map < string , string > ( ) ) ; } ) ) ; const index$ = zip ( icons$ , emojis$ ) . pipe ( map ( ( [ icons , emojis ] ) => { const cdn = "https://raw.githubusercontent.com" ; return { icons : { base : `${ cdn }/squidfunk/mkdocs-material/master/material/.icons/` , data : Object . fromEntries ( icons ) } , emojis : { base : `${ cdn }/twitter/twemoji/master/assets/svg/` , data : Object . fromEntries ( emojis ) } } as IconSearchIndex ; } ) , switchMap ( data => write ( `${ base }/overrides/assets/javascripts/iconsearch_index.json` , JSON . stringify ( data ) ) ) ) ; const build$ = process . argv . includes ( "--dirty" ) ? templates$ : concat ( assets$ , merge ( templates$ , index$ ) ) ; build$ . subscribe ( ) ;