import { mkdir, readFile, rm, writeFile } from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' import { importSvgCollections } from 'iconify-import-svg' type IconData = { body: string left?: number top?: number width?: number height?: number rotate?: 0 | 1 | 2 | 3 hFlip?: boolean vFlip?: boolean } type AliasData = Omit & { parent: string } type ImportedCollection = { icons?: Record aliases?: Record lastModified?: number } type ImportedCollections = Record type CollectionInfo = { prefix: string name: string total: number version: string author: { name: string url: string } license: { title: string spdx: string url: string } samples: string[] palette: false } type PackageJson = { version: string } const __dirname = path.dirname(fileURLToPath(import.meta.url)) const packageDir = path.resolve(__dirname, '..') const flattenCollections = (collections: ImportedCollections, prefix: string) => { const icons: Record = {} const aliases: Record = {} let lastModified = 0 for (const [collectionKey, collection] of Object.entries(collections)) { const segment = collectionKey.slice(prefix.length + 1) const namePrefix = segment ? `${segment}-` : '' for (const [iconName, iconData] of Object.entries(collection.icons ?? {})) icons[`${namePrefix}${iconName}`] = iconData for (const [aliasName, aliasData] of Object.entries(collection.aliases ?? {})) aliases[`${namePrefix}${aliasName}`] = aliasData if (typeof collection.lastModified === 'number') lastModified = Math.max(lastModified, collection.lastModified) } return { prefix, ...(lastModified ? { lastModified } : {}), icons, ...(Object.keys(aliases).length ? { aliases } : {}), } } const customPublicCollections = importSvgCollections({ source: path.resolve(packageDir, 'assets/public'), prefix: 'custom-public', ignoreImportErrors: true, cleanupSVG: true, deOptimisePaths: true, runSVGO: true, parseColors: false, }) as ImportedCollections const customVenderCollections = importSvgCollections({ source: path.resolve(packageDir, 'assets/vender'), prefix: 'custom-vender', ignoreImportErrors: true, cleanupSVG: true, deOptimisePaths: true, runSVGO: false, parseColors: { callback: () => 'currentColor', }, }) as ImportedCollections const createCollectionInfo = ( prefix: string, name: string, icons: Record, version: string, ): CollectionInfo => ({ prefix, name, total: Object.keys(icons).length, version, author: { name: 'LangGenius, Inc.', url: 'https://github.com/langgenius/dify', }, license: { title: 'Modified Apache 2.0', spdx: 'Apache-2.0', url: 'https://github.com/langgenius/dify/blob/main/LICENSE', }, samples: Object.keys(icons).slice(0, 6), palette: false, }) const createIndexMjs = (): string => `import icons from './icons.json' with { type: 'json' } import info from './info.json' with { type: 'json' } import metadata from './metadata.json' with { type: 'json' } import chars from './chars.json' with { type: 'json' } export { icons, info, metadata, chars } ` const createIndexJs = (): string => `'use strict' const icons = require('./icons.json') const info = require('./info.json') const metadata = require('./metadata.json') const chars = require('./chars.json') module.exports = { icons, info, metadata, chars } ` const createIndexTypes = (): string => `export interface IconifyJSON { prefix: string icons: Record aliases?: Record width?: number height?: number lastModified?: number } export interface IconifyIcon { body: string left?: number top?: number width?: number height?: number rotate?: 0 | 1 | 2 | 3 hFlip?: boolean vFlip?: boolean } export interface IconifyAlias extends Omit { parent: string } export interface IconifyInfo { prefix: string name: string total: number version: string author?: { name: string url?: string } license?: { title: string spdx?: string url?: string } samples?: string[] palette?: boolean } export interface IconifyMetaData { [key: string]: unknown } export interface IconifyChars { [key: string]: string } export declare const icons: IconifyJSON export declare const info: IconifyInfo export declare const metadata: IconifyMetaData export declare const chars: IconifyChars ` const writeCollectionPackage = async ( directoryName: string, collection: ReturnType, name: string, version: string, ): Promise => { const targetDir = path.resolve(packageDir, directoryName) const info = createCollectionInfo(collection.prefix, name, collection.icons, version) await mkdir(targetDir, { recursive: true }) await writeFile(path.resolve(targetDir, 'icons.json'), `${JSON.stringify(collection, null, 2)}\n`) await writeFile(path.resolve(targetDir, 'info.json'), `${JSON.stringify(info, null, 2)}\n`) await writeFile(path.resolve(targetDir, 'metadata.json'), '{}\n') await writeFile(path.resolve(targetDir, 'chars.json'), '{}\n') await writeFile(path.resolve(targetDir, 'index.mjs'), `${createIndexMjs()}\n`) await writeFile(path.resolve(targetDir, 'index.js'), `${createIndexJs()}\n`) await writeFile(path.resolve(targetDir, 'index.d.ts'), `${createIndexTypes()}\n`) } async function main(): Promise { const packageJson = JSON.parse( await readFile(path.resolve(packageDir, 'package.json'), 'utf8'), ) as PackageJson const customPublicCollection = flattenCollections(customPublicCollections, 'custom-public') const customVenderCollection = flattenCollections(customVenderCollections, 'custom-vender') await rm(path.resolve(packageDir, 'src'), { recursive: true, force: true }) await rm(path.resolve(packageDir, 'custom-public'), { recursive: true, force: true }) await rm(path.resolve(packageDir, 'custom-vender'), { recursive: true, force: true }) await writeCollectionPackage( 'custom-public', customPublicCollection, 'Dify Custom Public', packageJson.version, ) await writeCollectionPackage( 'custom-vender', customVenderCollection, 'Dify Custom Vender', packageJson.version, ) } main().catch((error: unknown) => { console.error(error) process.exitCode = 1 })