2018-08-26 23:23:57 +02:00
#!/usr/bin/env node
/ * *
* @ fileoverview
* Compiles our icons into static . js files that can be imported in the browser
2021-02-08 18:14:31 +02:00
* and are tree - shakeable . The static . js files go in icons / { filename } . js . Also
* generates an index . js that exports all icons by title , but is not
* tree - shakeable
2018-08-26 23:23:57 +02:00
* /
2021-12-25 16:22:56 +02:00
import { promises as fs } from 'node:fs' ;
import path from 'node:path' ;
import util from 'node:util' ;
import { transform as esbuildTransform } from 'esbuild' ;
import {
getIconSlug ,
svgToPath ,
titleToHtmlFriendly ,
slugToVariableName ,
getIconsData ,
getDirnameFromImportMeta ,
} from '../utils.js' ;
const _ _dirname = getDirnameFromImportMeta ( import . meta . url ) ;
2019-07-14 21:05:38 +02:00
2021-10-25 21:13:10 +02:00
const UTF8 = 'utf8' ;
2019-08-15 13:23:35 +02:00
2021-10-25 21:13:10 +02:00
const rootDir = path . resolve ( _ _dirname , '..' , '..' ) ;
const indexFile = path . resolve ( rootDir , 'index.js' ) ;
const iconsDir = path . resolve ( rootDir , 'icons' ) ;
2021-10-29 01:16:34 +02:00
const iconsJsFile = path . resolve ( rootDir , 'icons.js' ) ;
const iconsMjsFile = path . resolve ( rootDir , 'icons.mjs' ) ;
const iconsDtsFile = path . resolve ( rootDir , 'icons.d.ts' ) ;
2019-08-15 13:23:35 +02:00
2021-10-25 21:13:10 +02:00
const templatesDir = path . resolve ( _ _dirname , 'templates' ) ;
const indexTemplateFile = path . resolve ( templatesDir , 'index.js' ) ;
const iconObjectTemplateFile = path . resolve ( templatesDir , 'icon-object.js' ) ;
2019-08-15 13:23:35 +02:00
2021-11-24 04:01:24 +02:00
const build = async ( ) => {
2021-12-25 16:22:56 +02:00
const icons = await getIconsData ( ) ;
2021-11-24 04:01:24 +02:00
const indexTemplate = await fs . readFile ( indexTemplateFile , UTF8 ) ;
const iconObjectTemplate = await fs . readFile ( iconObjectTemplateFile , UTF8 ) ;
2019-07-14 17:07:24 +02:00
2021-11-24 04:01:24 +02:00
// Local helper functions
const escape = ( value ) => {
return value . replace ( /(?<!\\)'/g , "\\'" ) ;
} ;
const iconToKeyValue = ( icon ) => {
return ` ' ${ icon . slug } ': ${ iconToObject ( icon ) } ` ;
} ;
const licenseToObject = ( license ) => {
if ( license === undefined ) {
return ;
}
if ( license . url === undefined ) {
license . url = ` https://spdx.org/licenses/ ${ license . type } ` ;
}
return license ;
} ;
const iconToObject = ( icon ) => {
return util . format (
iconObjectTemplate ,
escape ( icon . title ) ,
escape ( icon . slug ) ,
escape ( titleToHtmlFriendly ( icon . title ) ) ,
escape ( icon . path ) ,
escape ( icon . source ) ,
escape ( icon . hex ) ,
icon . guidelines ? ` ' ${ escape ( icon . guidelines ) } ' ` : undefined ,
licenseToObject ( icon . license ) ,
) ;
} ;
const writeJs = async ( filepath , rawJavaScript ) => {
const { code } = await esbuildTransform ( rawJavaScript , {
minify : true ,
} ) ;
await fs . writeFile ( filepath , code ) ;
} ;
const writeTs = async ( filepath , rawTypeScript ) => {
await fs . writeFile ( filepath , rawTypeScript ) ;
} ;
// 'main'
const iconsBarrelMjs = [ ] ;
const iconsBarrelJs = [ ] ;
const iconsBarrelDts = [ ] ;
2021-12-25 16:22:56 +02:00
const buildIcons = [ ] ;
2021-11-24 04:01:24 +02:00
await Promise . all (
2021-12-25 16:22:56 +02:00
icons . map ( async ( icon ) => {
2021-11-24 04:01:24 +02:00
const filename = getIconSlug ( icon ) ;
const svgFilepath = path . resolve ( iconsDir , ` ${ filename } .svg ` ) ;
icon . svg = ( await fs . readFile ( svgFilepath , UTF8 ) ) . replace ( /\r?\n/ , '' ) ;
icon . path = svgToPath ( icon . svg ) ;
icon . slug = filename ;
2021-12-25 16:22:56 +02:00
buildIcons . push ( icon ) ;
2021-11-24 04:01:24 +02:00
const iconObject = iconToObject ( icon ) ;
const iconExportName = slugToVariableName ( icon . slug ) ;
// write the static .js file for the icon
const jsFilepath = path . resolve ( iconsDir , ` ${ filename } .js ` ) ;
const newImportMessage = ` use "const { ${ iconExportName } } = require('simple-icons/icons');" instead ` ;
const message = JSON . stringify (
` Imports like "const ${ icon . slug } = require('simple-icons/icons/ ${ icon . slug } ');" have been deprecated in v6.0.0 and will no longer work from v7.0.0, ${ newImportMessage } ` ,
) ;
const dtsFilepath = path . resolve ( iconsDir , ` ${ filename } .d.ts ` ) ;
await Promise . all ( [
writeJs (
jsFilepath ,
` console.warn("warn -", ${ message } );module.exports= ${ iconObject } ; ` ,
) ,
writeTs (
dtsFilepath ,
` /**@deprecated ${ newImportMessage } */declare const i:import("../alias").I;export default i; ` ,
) ,
] ) ;
// add object to the barrel file
iconsBarrelJs . push ( ` ${ iconExportName } : ${ iconObject } , ` ) ;
iconsBarrelMjs . push ( ` export const ${ iconExportName } = ${ iconObject } ` ) ;
iconsBarrelDts . push ( ` export const ${ iconExportName } :I; ` ) ;
} ) ,
2021-11-23 22:33:37 +02:00
) ;
2021-10-29 01:16:34 +02:00
2021-11-24 04:01:24 +02:00
// write our generic index.js
const rawIndexJs = util . format (
indexTemplate ,
2021-12-25 16:22:56 +02:00
buildIcons . map ( iconToKeyValue ) . join ( ',' ) ,
2021-10-29 01:16:34 +02:00
) ;
2021-11-24 04:01:24 +02:00
await writeJs ( indexFile , rawIndexJs ) ;
// write our file containing the exports of all icons in CommonJS ...
const rawIconsJs = ` module.exports={ ${ iconsBarrelJs . join ( '' ) } }; ` ;
await writeJs ( iconsJsFile , rawIconsJs ) ;
// and ESM
const rawIconsMjs = iconsBarrelMjs . join ( '' ) ;
await writeJs ( iconsMjsFile , rawIconsMjs ) ;
// and create a type declaration file
const rawIconsDts = ` import {I} from "./alias"; ${ iconsBarrelDts . join ( '' ) } ` ;
await writeTs ( iconsDtsFile , rawIconsDts ) ;
} ;
2021-10-29 01:16:34 +02:00
2021-11-24 04:01:24 +02:00
build ( ) ;