status-web/packages/icons/scripts/build.js

136 lines
4.3 KiB
JavaScript
Raw Normal View History

2023-01-19 22:59:31 +00:00
const fs = require('fs').promises
const camelcase = require('camelcase')
const { promisify } = require('util')
const rimraf = promisify(require('rimraf'))
const svgr = require('@svgr/core').default
const babel = require('@babel/core')
const { compile: compileVue } = require('@vue/compiler-dom')
const { dirname } = require('path')
let transform = {
react: async (svg, componentName, format) => {
let component = await svgr(
svg,
{ ref: true, titleProp: true },
{ componentName }
)
let { code } = await babel.transformAsync(component, {
plugins: [
[require('@babel/plugin-transform-react-jsx'), { useBuiltIns: true }],
],
})
if (format === 'esm') {
return code
}
return code
.replace(
'import * as React from "react"',
'const React = require("react")'
)
.replace('export default', 'module.exports =')
},
}
async function getIcons(style) {
let files = await fs.readdir(`./optimized/${style}`)
return Promise.all(
files.map(async file => ({
svg: await fs.readFile(`./optimized/${style}/${file}`, 'utf8'),
componentName: `${camelcase(file.replace(/\.svg$/, ''), {
pascalCase: true,
})}Icon`,
}))
)
}
function exportAll(icons, format, includeExtension = true) {
return icons
.map(({ componentName }) => {
let extension = includeExtension ? '.js' : ''
if (format === 'esm') {
return `export { default as ${componentName} } from './${componentName}${extension}'`
}
return `module.exports.${componentName} = require("./${componentName}${extension}")`
})
.join('\n')
}
async function ensureWrite(file, text) {
await fs.mkdir(dirname(file), { recursive: true })
await fs.writeFile(file, text, 'utf8')
}
async function ensureWriteJson(file, json) {
await ensureWrite(file, JSON.stringify(json, null, 2))
}
async function buildIcons(package, style, format) {
let outDir = `./${package}/${style}`
if (format === 'esm') {
outDir += '/esm'
}
let icons = await getIcons(style)
await Promise.all(
icons.flatMap(async ({ componentName, svg }) => {
let content = await transform[package](svg, componentName, format)
let types =
package === 'react'
? `import * as React from 'react';\ndeclare function ${componentName}(props: React.ComponentProps<'svg'> & { title?: string, titleId?: string }): JSX.Element;\nexport default ${componentName};\n`
: `import type { FunctionalComponent, HTMLAttributes, VNodeProps } from 'vue';\ndeclare const ${componentName}: FunctionalComponent<HTMLAttributes & VNodeProps>;\nexport default ${componentName};\n`
return [
ensureWrite(`${outDir}/${componentName}.js`, content),
...(types
? [ensureWrite(`${outDir}/${componentName}.d.ts`, types)]
: []),
]
})
)
await ensureWrite(`${outDir}/index.js`, exportAll(icons, format))
await ensureWrite(`${outDir}/index.d.ts`, exportAll(icons, 'esm', false))
}
async function main(package) {
const cjsPackageJson = { module: './esm/index.js', sideEffects: false }
const esmPackageJson = { type: 'module', sideEffects: false }
console.log(`Building ${package} package...`)
await Promise.all([
rimraf(`./${package}/20/solid/*`),
rimraf(`./${package}/24/outline/*`),
rimraf(`./${package}/24/solid/*`),
])
await Promise.all([
buildIcons(package, '20/solid', 'cjs'),
buildIcons(package, '20/solid', 'esm'),
buildIcons(package, '24/outline', 'cjs'),
buildIcons(package, '24/outline', 'esm'),
buildIcons(package, '24/solid', 'cjs'),
buildIcons(package, '24/solid', 'esm'),
ensureWriteJson(`./${package}/20/solid/esm/package.json`, esmPackageJson),
ensureWriteJson(`./${package}/20/solid/package.json`, cjsPackageJson),
ensureWriteJson(`./${package}/24/outline/esm/package.json`, esmPackageJson),
ensureWriteJson(`./${package}/24/outline/package.json`, cjsPackageJson),
ensureWriteJson(`./${package}/24/solid/esm/package.json`, esmPackageJson),
ensureWriteJson(`./${package}/24/solid/package.json`, cjsPackageJson),
])
return console.log(`Finished building ${package} package.`)
}
let [package] = process.argv.slice(2)
if (!package) {
throw new Error('Please specify a package')
}
main(package)