// DSMMG icon builder // - Émet un bundle complet (icons.css) avec base + toutes les classes // - Émet aussi des modules par icône (each/.css) pour permettre le // tree-shaking côté consommateur (import "@managemate/icons/each/check-line"). // - Émet le module base.css (la classe .mmg-icon + sizes) en stand-alone, // utile quand on n'importe que des icônes individuelles. import { readFile, writeFile, mkdir, rm } from "node:fs/promises"; import { join, dirname } from "node:path"; import { fileURLToPath } from "node:url"; import { existsSync } from "node:fs"; const __dirname = dirname(fileURLToPath(import.meta.url)); const REMIX_DIR = join(__dirname, "node_modules", "remixicon", "icons"); const DIST_DIR = join(__dirname, "dist"); const EACH_DIR = join(DIST_DIR, "each"); if (existsSync(DIST_DIR)) await rm(DIST_DIR, { recursive: true }); await mkdir(EACH_DIR, { recursive: true }); const ICONS = [ ["Arrows", "arrow-right"], ["Arrows", "arrow-left"], ["Arrows", "arrow-up"], ["Arrows", "arrow-down"], ["Arrows", "arrow-right-up"], ["Arrows", "arrow-go-back"], ["Arrows", "expand-up-down"], ["System", "external-link"], ["System", "check"], ["System", "close"], ["System", "add"], ["System", "subtract"], ["System", "search-2"], ["System", "filter-3"], ["System", "more"], ["System", "more-2"], ["System", "menu"], ["System", "settings-3"], ["System", "refresh"], ["System", "delete-bin"], ["Design", "edit"], ["System", "share"], ["System", "download"], ["System", "upload"], ["System", "information"], ["System", "alert"], ["System", "error-warning"], ["System", "checkbox-circle"], ["System", "close-circle"], ["System", "question"], ["System", "spam"], ["System", "shield-check"], ["User & Faces", "user"], ["User & Faces", "user-add"], ["User & Faces", "team"], ["User & Faces", "account-circle"], ["System", "logout-box-r"], ["System", "login-box"], ["System", "lock"], ["System", "lock-unlock"], ["System", "eye"], ["System", "eye-off"], ["Business", "mail"], ["Business", "mail-send"], ["Communication", "message-2"], ["Device", "phone"], ["Media", "notification-3"], ["Communication", "chat-3"], ["Business", "global"], ["Business", "calendar"], ["Business", "calendar-check"], ["System", "time"], ["System", "history"], ["Document", "file-text"], ["Document", "file"], ["Document", "folder"], ["Document", "folder-open"], ["Document", "file-pdf"], ["Document", "file-copy"], ["Editor", "attachment"], ["Document", "draft"], ["Business", "inbox"], ["Map", "rocket-2"], ["Buildings", "home-4"], ["Buildings", "building"], ["Buildings", "store-2"], ["Buildings", "community"], ["Map", "map-pin-2"], ["Map", "map-2"], ["Finance", "money-euro-circle"], ["Finance", "bank-card"], ["Finance", "shopping-cart-2"], ["Finance", "shopping-bag-3"], ["Finance", "price-tag-3"], ["Finance", "coins"], ["Business", "briefcase-4"], ["Business", "line-chart"], ["Business", "bar-chart"], ["Business", "pie-chart"], ["Business", "stack"], ["System", "dashboard"], ["System", "apps-2"], ["System", "function"], ["Business", "presentation"], ["Document", "newspaper"], ["Document", "article"], ["Document", "book-open"], ["Business", "bookmark-3"], ["Health & Medical", "heart-3"], ["System", "star"], ["System", "thumb-up"], ["Design", "palette"], ["Design", "magic"], ["Weather", "flashlight"], ["Weather", "sun"], ["Weather", "moon"], ]; const BASE_CSS = `/* DSMMG icons — base (auto-generated). */ .mmg-icon { display: inline-block; width: 1.25em; height: 1.25em; vertical-align: -0.225em; background: currentColor; mask-repeat: no-repeat; mask-position: center; mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center; -webkit-mask-size: contain; flex-shrink: 0; } .mmg-icon--xs { width: 12px; height: 12px; } .mmg-icon--sm { width: 14px; height: 14px; } .mmg-icon--md { width: 18px; height: 18px; } .mmg-icon--lg { width: 24px; height: 24px; } .mmg-icon--xl { width: 32px; height: 32px; } .mmg-icon--2xl { width: 48px; height: 48px; } `; const rules = []; const names = []; const missing = []; for (const [category, base, alias] of ICONS) { for (const variant of ["line", "fill"]) { const file = join(REMIX_DIR, category, `${base}-${variant}.svg`); if (!existsSync(file)) { missing.push(`${category}/${base}-${variant}`); continue; } const svg = (await readFile(file, "utf8")) .replace(/[\r\n]+/g, "") .replace(/"/g, "'") .replace(/\s+/g, " ") .trim(); const url = `data:image/svg+xml,${encodeURIComponent(svg)}`; const className = `${alias ?? base}-${variant}`; const rule = `.mmg-icon-${className} { mask-image: url("${url}"); -webkit-mask-image: url("${url}"); }`; rules.push(rule); names.push(className); // Module subset par icône — n'inclut PAS la base, à charger séparément ou // implicitement via @managemate/icons/base. await writeFile(join(EACH_DIR, `${className}.css`), rule + "\n"); } } // Bundle complet — base + toutes les classes await writeFile(join(DIST_DIR, "icons.css"), BASE_CSS + "\n" + rules.join("\n") + "\n"); // Base seule — utile pour ceux qui font du subset await writeFile(join(DIST_DIR, "base.css"), BASE_CSS); await writeFile(join(DIST_DIR, "icons.json"), JSON.stringify(names, null, 2)); await writeFile( join(DIST_DIR, "names.js"), `export default ${JSON.stringify(names, null, 2)};\n`, ); await writeFile( join(DIST_DIR, "names.d.ts"), `declare const names: string[];\nexport default names;\n`, ); console.log(`Built ${names.length} icon classes (${ICONS.length} icons × 2 variants)`); console.log(` - dist/icons.css (bundle, ${BASE_CSS.length + rules.join("\n").length} bytes)`); console.log(` - dist/base.css (base only)`); console.log(` - dist/each/.css (${names.length} per-icon modules)`); if (missing.length) { console.warn(`Missing ${missing.length} files:`, missing.slice(0, 5)); }