mirror of
https://github.com/StepanovPlaton/AboutMe.git
synced 2026-07-28 19:35:51 +04:00
136 lines
3.8 KiB
JavaScript
136 lines
3.8 KiB
JavaScript
import { readFileSync, readdirSync, statSync, writeFileSync, mkdirSync } from "fs";
|
|
import { join, relative } from "path";
|
|
|
|
const ROOT = join(import.meta.dirname, "..");
|
|
const SRC = join(ROOT, "src");
|
|
const OUT_DIR = join(SRC, "generated");
|
|
const OUT_FILE = join(OUT_DIR, "icon-inventory.json");
|
|
const OUT_INCLUDE = join(OUT_DIR, "icon-include.mjs");
|
|
|
|
/** @type {Record<string, string>} */
|
|
const ICON_ALIASES = {
|
|
"eos-icons:loading": "material-symbols:progress-activity",
|
|
};
|
|
|
|
const KNOWN_PREFIXES = new Set([
|
|
"material-symbols",
|
|
"fa6-brands",
|
|
"fa6-regular",
|
|
"fa6-solid",
|
|
"mdi",
|
|
"logos",
|
|
"devicon",
|
|
"hugeicons",
|
|
"mingcute",
|
|
"skill-icons",
|
|
"vscode-icons",
|
|
"material-icon-theme",
|
|
"game-icons",
|
|
"iconoir",
|
|
]);
|
|
|
|
const ICON_PATTERN =
|
|
/(?:name|icon)=["'{]([a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9._-]*)/gi;
|
|
|
|
const JSON_ICON_PATTERN = /"icon"\s*:\s*"([^"]+)"/g;
|
|
const YAML_ICON_PATTERN = /\bicon:\s*["']([^"']+)["']/g;
|
|
const TS_ICON_PATTERN = /\bicon\s*:\s*["']([^"']+)["']/g;
|
|
const RETURN_ICON_PATTERN =
|
|
/return\s+["']([a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9._-]*)["']/g;
|
|
|
|
function walk(dir, files = []) {
|
|
for (const entry of readdirSync(dir)) {
|
|
const full = join(dir, entry);
|
|
if (statSync(full).isDirectory()) {
|
|
walk(full, files);
|
|
} else {
|
|
files.push(full);
|
|
}
|
|
}
|
|
return files;
|
|
}
|
|
|
|
function normalizeIcon(name) {
|
|
const trimmed = name.trim();
|
|
return ICON_ALIASES[trimmed] ?? trimmed;
|
|
}
|
|
|
|
function addIcon(icons, raw) {
|
|
const name = normalizeIcon(raw);
|
|
if (!name.includes(":")) return;
|
|
const [prefix, iconName] = name.split(":");
|
|
if (!prefix || !iconName || !KNOWN_PREFIXES.has(prefix)) return;
|
|
if (!icons[prefix]) icons[prefix] = new Set();
|
|
icons[prefix].add(iconName);
|
|
}
|
|
|
|
function scanFile(path, icons) {
|
|
const content = readFileSync(path, "utf8");
|
|
const rel = relative(ROOT, path).replace(/\\/g, "/");
|
|
|
|
if (rel.endsWith(".json")) {
|
|
for (const match of content.matchAll(JSON_ICON_PATTERN)) {
|
|
addIcon(icons, match[1]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (rel.endsWith(".yaml") || rel.endsWith(".yml")) {
|
|
for (const match of content.matchAll(YAML_ICON_PATTERN)) {
|
|
addIcon(icons, match[1]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!/\.(astro|svelte|ts|tsx|js|mjs)$/.test(rel)) return;
|
|
|
|
for (const match of content.matchAll(ICON_PATTERN)) {
|
|
addIcon(icons, match[1]);
|
|
}
|
|
for (const match of content.matchAll(TS_ICON_PATTERN)) {
|
|
addIcon(icons, match[1]);
|
|
}
|
|
for (const match of content.matchAll(RETURN_ICON_PATTERN)) {
|
|
addIcon(icons, match[1]);
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
/** @type {Record<string, Set<string>>} */
|
|
const icons = {};
|
|
|
|
const files = walk(SRC);
|
|
for (const file of files) {
|
|
if (file.includes("generated")) continue;
|
|
scanFile(file, icons);
|
|
}
|
|
|
|
const extraConfigFiles = [join(ROOT, "twilight.config.yaml")];
|
|
for (const file of extraConfigFiles) {
|
|
try {
|
|
scanFile(file, icons);
|
|
} catch {
|
|
/* optional config */
|
|
}
|
|
}
|
|
|
|
/** @type {Record<string, string[]>} */
|
|
const inventory = {};
|
|
for (const [prefix, names] of Object.entries(icons)) {
|
|
inventory[prefix] = [...names].sort();
|
|
}
|
|
|
|
mkdirSync(OUT_DIR, { recursive: true });
|
|
writeFileSync(OUT_FILE, `${JSON.stringify(inventory, null, 2)}\n`, "utf8");
|
|
writeFileSync(
|
|
OUT_INCLUDE,
|
|
`// AUTO-GENERATED by scripts/collect-icons.mjs — do not edit\nexport default ${JSON.stringify(inventory, null, 4)};\n`,
|
|
"utf8",
|
|
);
|
|
|
|
const total = Object.values(inventory).reduce((n, arr) => n + arr.length, 0);
|
|
console.log(`Collected ${total} icons in ${Object.keys(inventory).length} sets -> ${relative(ROOT, OUT_FILE)}`);
|
|
}
|
|
|
|
main();
|