Files
Umbraco-CMS/src/Umbraco.Web.UI.Client/devops/icons/index.js
2024-07-03 11:30:45 +02:00

206 lines
5.0 KiB
JavaScript

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(/<path/g, '<path fill="currentColor"');
}
const icon = {
name: iconDef.name,
legacy: iconDef.legacy,
fileName: iconFileName,
svg,
output: `${iconsOutputDirectory}/${iconFileName}.ts`,
};
icons.push(icon);
} catch (e) {
console.log(`[SimpleIcons] Could not load file: '${path}'`);
}
}
});
// Umbraco:
fileJSON.umbraco.forEach((iconDef) => {
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();