Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | /*
* Generates `public/icons-all.json` for the previewer.
*
* Scans the source `svg/<type>/common` and `svg/<type>/ltr` folders and emits a
* JSON map of icon names per type, split into `common` and `directional`
* (ltr) lists. The previewer loads this to enumerate available icons without
* reading the filesystem at runtime.
*/
import fs from 'node:fs';
import path from 'node:path';
import { writeIconPaletteCss } from './icon-palette.js';
import { writeAllIconsHtml } from './generate-all-icons-html.js';
import type { IconsData } from '../src/icon-catalog.js';
const rootDir = path.resolve(import.meta.dirname, '..');
const iconTypes = ['action', 'custom', 'doctype', 'standard', 'utility'] as const;
/*
* Returns an icon type's symbol names, split into `common` (svg/<type>/common)
* and `directional` (svg/<type>/ltr). Each list is sorted; missing folders
* yield empty lists.
*/
function getIconNames(iconType: string): { common: string[]; directional: string[] } {
const svgDir = path.join(rootDir, 'svg', iconType);
const commonDir = path.join(svgDir, 'common');
const ltrDir = path.join(svgDir, 'ltr');
const common: string[] = [];
const directional: string[] = [];
// Get common icons
if (fs.existsSync(commonDir)) {
const files = fs.readdirSync(commonDir);
files.forEach((file) => {
if (file.endsWith('.svg')) {
common.push(path.basename(file, '.svg'));
}
});
}
// Get directional icons (ltr)
if (fs.existsSync(ltrDir)) {
const files = fs.readdirSync(ltrDir);
files.forEach((file) => {
if (file.endsWith('.svg')) {
directional.push(path.basename(file, '.svg'));
}
});
}
return {
common: common.sort(),
directional: directional.sort(),
};
}
/* Builds the full icons map by collecting names for every icon type. */
export function generateIconsData(): IconsData {
const data: IconsData = {};
iconTypes.forEach((iconType) => {
data[iconType] = getIconNames(iconType);
});
return data;
}
/*
* Stages the icon assets the previewer serves at runtime into `public/icons/`,
* where Next.js exposes them as static files. The previewer's <img>/<use> tags
* fetch source SVGs from `/icons/svg/...` and built assets (dist SVGs, sprites,
* PNGs) from `/icons/dist/...`, so both trees must be copied under `public`.
*
* The `svg/` source is always present; `dist/` only exists after `yarn build`.
* When dist is missing we skip it with a warning rather than failing — the
* source-SVG column still renders, and the built columns light up once the
* user runs a build.
*/
function stagePreviewerAssets() {
const publicIconsDir = path.join(rootDir, 'public', 'icons');
const stage = (srcDir: string, destName: string) => {
const dest = path.join(publicIconsDir, destName);
fs.rmSync(dest, { recursive: true, force: true });
fs.cpSync(srcDir, dest, { recursive: true });
console.log(`Staged ${srcDir} -> ${dest}`);
};
fs.mkdirSync(publicIconsDir, { recursive: true });
stage(path.join(rootDir, 'svg'), 'svg');
const distDir = path.join(rootDir, 'dist');
if (fs.existsSync(distDir)) {
stage(distDir, 'dist');
} else {
console.warn(
'No dist/ found — built SVG, sprite, and PNG columns will 404. Run `yarn build` to populate them.',
);
}
}
/*
* Entry point: builds the icons map and writes it to `public/icons-all.json`,
* extracts SLDS2 icon background colors to `public/icon-palette.css`, then
* stages previewer assets and compiles `public/index.html` unless
* `--data-only` (used by `typecheck` so tsc can resolve the JSON import
* without copying the svg/dist trees). `--html-only` skips staging `svg/` and
* `dist/` and only rewrites `public/index.html`.
*/
function main() {
const dataOnly = process.argv.includes('--data-only');
const iconsData = generateIconsData();
const outputPath = path.join(rootDir, 'public', 'icons-all.json');
// Ensure output directory exists
const outputDir = path.dirname(outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
fs.writeFileSync(outputPath, JSON.stringify(iconsData, null, 2));
console.log(`Generated ${outputPath}`);
const palettePath = writeIconPaletteCss(path.join(rootDir, 'public', 'icon-palette.css'));
console.log(`Generated ${palettePath}`);
if (!dataOnly) {
if (!process.argv.includes('--html-only')) {
stagePreviewerAssets();
}
const catalogPath = writeAllIconsHtml(rootDir, iconsData);
console.log(`Generated ${catalogPath}`);
}
}
main();
|