import { readFileSync, writeFileSync, mkdirSync } from "fs"; import { join } from "path"; import { createRequire } from "module"; import { getIconData, iconToSVG } from "@iconify/utils"; const require = createRequire(import.meta.url); const ROOT = join(import.meta.dirname, ".."); const INVENTORY_FILE = join(ROOT, "src/generated/icon-inventory.json"); const OUT_DIR = join(ROOT, "src/generated"); const OUT_FILE = join(OUT_DIR, "site-icon-svgs.ts"); const PACKAGE_BY_PREFIX = { "fa6-brands": "@iconify-json/fa6-brands", "fa6-regular": "@iconify-json/fa6-regular", "fa6-solid": "@iconify-json/fa6-solid", mdi: "@iconify-json/mdi", "material-symbols": "@iconify-json/material-symbols", logos: "@iconify-json/logos", devicon: "@iconify-json/devicon", hugeicons: "@iconify-json/hugeicons", mingcute: "@iconify-json/mingcute", "skill-icons": "@iconify-json/skill-icons", "vscode-icons": "@iconify-json/vscode-icons", "material-icon-theme": "@iconify-json/material-icon-theme", "game-icons": "@iconify-json/game-icons", iconoir: "@iconify-json/iconoir", }; function loadIconSet(prefix) { const pkg = PACKAGE_BY_PREFIX[prefix]; if (!pkg) return null; return require(`${pkg}/icons.json`); } function buildSvg(iconName) { const [prefix, name] = iconName.split(":"); const iconSet = loadIconSet(prefix); if (!iconSet) { console.warn(`Unknown icon set: ${prefix} (${iconName})`); return null; } const data = getIconData(iconSet, name); if (!data) { console.warn(`Icon not found: ${iconName}`); return null; } const { body, attributes } = iconToSVG(data, { height: "1em" }); const attrs = Object.entries(attributes) .map(([k, v]) => `${k}="${v}"`) .join(" "); return `${body}`; } function main() { const inventory = JSON.parse(readFileSync(INVENTORY_FILE, "utf8")); /** @type {Record} */ const svgs = {}; for (const [prefix, names] of Object.entries(inventory)) { for (const name of names) { const fullName = `${prefix}:${name}`; const svg = buildSvg(fullName); if (svg) svgs[fullName] = svg; } } const fallback = svgs["material-symbols:help-outline"] ?? svgs["material-symbols:info"] ?? Object.values(svgs)[0] ?? ""; const lines = [ "// Generated by scripts/generate-site-icons.mjs — do not edit manually", "", `export const siteIconFallback = ${JSON.stringify(fallback)};`, "", "export const siteIconSvgs: Record = {", ]; for (const [name, svg] of Object.entries(svgs).sort(([a], [b]) => a.localeCompare(b))) { lines.push(` ${JSON.stringify(name)}: ${JSON.stringify(svg)},`); } lines.push("};", ""); mkdirSync(OUT_DIR, { recursive: true }); writeFileSync(OUT_FILE, `${lines.join("\n")}\n`, "utf8"); console.log(`Generated ${Object.keys(svgs).length} SVGs -> ${OUT_FILE}`); } main();