import { readFileSync, writeFile, mkdir, rmSync } from 'fs'; import * as globModule from 'tiny-glob'; import * as pathModule from 'path'; const path = pathModule.default; const getDirName = path.dirname; const glob = globModule.default; const moduleDirectory = 'src/packages/core/icon-registry'; const iconsOutputDirectory = `${moduleDirectory}/icons`; const umbracoSvgDirectory = `${moduleDirectory}/svgs`; const iconMapJson = `${moduleDirectory}/icon-dictionary.json`; const lucideSvgDirectory = 'node_modules/lucide-static/icons'; const simpleIconsSvgDirectory = 'node_modules/simple-icons/icons'; const run = async () => { // Empty output directory: rmSync(iconsOutputDirectory, { recursive: true }); var icons = await collectDictionaryIcons(); icons = await collectDiskIcons(icons); writeIconsToDisk(icons); generateJS(icons); }; const collectDictionaryIcons = async () => { const rawData = readFileSync(iconMapJson); const fileRaw = rawData.toString(); const fileJSON = JSON.parse(fileRaw); let icons = []; // Lucide: fileJSON.lucide.forEach((iconDef) => { if (iconDef.file && iconDef.name) { const path = lucideSvgDirectory + '/' + iconDef.file; try { const rawData = readFileSync(path); // For Lucide icons specially we adjust the icons a bit for them to work in our case: [NL] let svg = rawData.toString().replace(' width="24"\n', ''); svg = svg.replace(' height="24"\n', ''); svg = svg.replace('stroke-width="2"', 'stroke-width="1.75"'); const iconFileName = iconDef.name; const icon = { name: iconDef.name, legacy: iconDef.legacy, fileName: iconFileName, svg, output: `${iconsOutputDirectory}/${iconFileName}.ts`, }; icons.push(icon); } catch (e) { console.log(`[Lucide] Could not load file: '${path}'`); } } }); // SimpleIcons: fileJSON.simpleIcons.forEach((iconDef) => { if (iconDef.file && iconDef.name) { const path = simpleIconsSvgDirectory + '/' + iconDef.file; try { const rawData = readFileSync(path); let svg = rawData.toString(); const iconFileName = iconDef.name; // SimpleIcons need to use fill="currentColor" const pattern = /fill=/g; if (!pattern.test(svg)) { svg = svg.replace(/ { if (iconDef.file && iconDef.name) { const path = umbracoSvgDirectory + '/' + iconDef.file; try { const rawData = readFileSync(path); const svg = rawData.toString(); const iconFileName = iconDef.name; const icon = { name: iconDef.name, legacy: iconDef.legacy, fileName: iconFileName, svg, output: `${iconsOutputDirectory}/${iconFileName}.ts`, }; icons.push(icon); } catch (e) { console.log(`[Umbraco] Could not load file: '${path}'`); } } }); return icons; }; const collectDiskIcons = async (icons) => { const iconPaths = await glob(`${umbracoSvgDirectory}/icon-*.svg`); iconPaths.forEach((path) => { const rawData = readFileSync(path); const svg = rawData.toString(); const pattern = /\/([^/]+)\.svg$/; const match = path.match(pattern); if (!match) { console.log('No match found.'); return; } const SVGFileName = match[1]; const iconFileName = SVGFileName.replace('.svg', ''); const iconName = iconFileName; // Only append not already defined icons: if (!icons.find((x) => x.name === iconName)) { const icon = { name: iconName, legacy: true, fileName: iconFileName, svg, output: `${iconsOutputDirectory}/${iconFileName}.ts`, }; icons.push(icon); } }); return icons; }; const writeIconsToDisk = (icons) => { icons.forEach((icon) => { const content = 'export default `' + icon.svg + '`;'; writeFileWithDir(icon.output, content, (err) => { if (err) { // eslint-disable-next-line no-undef console.log(err); } // eslint-disable-next-line no-undef console.log(`icon: ${icon.name} generated`); }); }); }; const generateJS = (icons) => { const JSPath = `${moduleDirectory}/icons.ts`; const iconDescriptors = icons.map((icon) => { return `{ name: "${icon.name}", ${icon.legacy ? 'legacy: true,' : ''} path: () => import("./icons/${icon.fileName}.js"), }`.replace(/\t/g, ''); // Regex removes white space [NL] }); const content = `export default [${iconDescriptors.join(',')}];`; writeFileWithDir(JSPath, content, (err) => { if (err) { // eslint-disable-next-line no-undef console.log(err); } // eslint-disable-next-line no-undef console.log('icon manifests generated'); }); }; const writeFileWithDir = (path, contents, cb) => { mkdir(getDirName(path), { recursive: true }, function (err) { if (err) return cb(err); writeFile(path, contents, cb); }); }; run();