diff --git a/scripts/check-metadata.js b/scripts/check-metadata.js index 6505247..8409ff4 100644 --- a/scripts/check-metadata.js +++ b/scripts/check-metadata.js @@ -8,12 +8,12 @@ const fs = require('fs'); const path = require('path'); -// Load the mapping file to get all icon names -const mappingPath = path.join(__dirname, '..', 'src', 'template', 'mapping.json'); +// Load the icons directory to get all icon names +const iconsDir = path.join(__dirname, '..', 'src', 'icons'); const metadataPath = path.join(__dirname, '..', 'src', 'template', 'metadata.json'); -if (!fs.existsSync(mappingPath)) { - console.error('Error: mapping.json not found at', mappingPath); +if (!fs.existsSync(iconsDir)) { + console.error('Error: icons directory not found at', iconsDir); process.exit(1); } @@ -22,17 +22,15 @@ if (!fs.existsSync(metadataPath)) { process.exit(1); } -const mapping = JSON.parse(fs.readFileSync(mappingPath, 'utf8')); const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8')); -// Collect all unique icon names from mapping -const allIconNames = new Set(); -Object.values(mapping).forEach(aliases => { - // For each code point, add the first alias (primary name) - if (aliases && aliases.length > 0) { - allIconNames.add(aliases[0]); - } -}); +// Collect all icon names from the actual SVG files. Metadata is keyed by the +// SVG file name, which is the canonical identity for each icon. +const allIconNames = new Set( + fs.readdirSync(iconsDir) + .filter(file => file.endsWith('.svg')) + .map(file => path.basename(file, '.svg')) +); // Find icons without metadata const missingMetadata = []; diff --git a/scripts/svg-sprite.js b/scripts/svg-sprite.js index 7b3688a..0e04396 100644 --- a/scripts/svg-sprite.js +++ b/scripts/svg-sprite.js @@ -65,31 +65,37 @@ let processedFiles = 0; const processedIcons = new Set(); Object.entries(mapping).forEach(([code, aliases]) => { - // Use the first alias as the primary SVG file name - const primaryAlias = aliases[0]; - + // The SVG file backing this icon may be named after any of its aliases, + // not necessarily the primary one, so pick whichever file actually exists. + const sourceAlias = aliases.find(alias => + fs.existsSync(path.resolve(iconsDir, `${alias}.svg`)) + ); + + if (!sourceAlias) { + console.error(`Error: no SVG file found for code ${code} (aliases: ${aliases.join(", ")})`); + process.exit(1); + } + // Skip if we've already processed this icon - if (processedIcons.has(primaryAlias)) { + if (processedIcons.has(sourceAlias)) { return; } - + // Use path.resolve for cross-platform compatibility - const file = path.resolve(iconsDir, `${primaryAlias}.svg`); - - if (fs.existsSync(file)) { - processedFiles++; - processedIcons.add(primaryAlias); - - // Add sprite entries for all aliases of this icon - for (const name of aliases) { - // Use path.resolve for cross-platform compatibility - const svgPath = path.resolve(iconsDir, `${name}.svg`); - spriter.add( - svgPath, - name + ".svg", - fs.readFileSync(file, "utf-8"), - ); - } + const file = path.resolve(iconsDir, `${sourceAlias}.svg`); + + processedFiles++; + processedIcons.add(sourceAlias); + + // Add sprite entries for all aliases of this icon + for (const name of aliases) { + // Use path.resolve for cross-platform compatibility + const svgPath = path.resolve(iconsDir, `${name}.svg`); + spriter.add( + svgPath, + name + ".svg", + fs.readFileSync(file, "utf-8"), + ); } }); diff --git a/src/template/mapping.json b/src/template/mapping.json index e395160..6643a49 100644 --- a/src/template/mapping.json +++ b/src/template/mapping.json @@ -14,8 +14,8 @@ "repo-delete" ], "60003": [ - "gist-fork", - "repo-forked" + "repo-forked", + "gist-fork" ], "60004": [ "git-pull-request", @@ -45,30 +45,30 @@ "mirror-public" ], "60010": [ + "star-empty", "star", "star-add", - "star-delete", - "star-empty" + "star-delete" ], "60011": [ "comment", "comment-add" ], "60012": [ - "alert", - "warning" + "warning", + "alert" ], "60013": [ "search", "search-save" ], "60014": [ - "log-out", - "sign-out" + "sign-out", + "log-out" ], "60015": [ - "log-in", - "sign-in" + "sign-in", + "log-in" ], "60016": [ "eye", @@ -96,9 +96,9 @@ "issue-opened" ], "60021": [ + "lock", "gist-private", "git-fork-private", - "lock", "mirror-private" ], "60022": [ @@ -107,12 +107,12 @@ "x" ], "60023": [ - "repo-sync", - "sync" + "sync", + "repo-sync" ], "60024": [ - "clone", - "desktop-download" + "desktop-download", + "clone" ], "60025": [ "beaker", @@ -126,13 +126,13 @@ "file" ], "60028": [ - "more", "ellipsis", + "more", "kebab-horizontal" ], "60029": [ - "mail-reply", - "reply" + "reply", + "mail-reply" ], "60030": [ "organization", @@ -161,9 +161,9 @@ "symbol-folder" ], "60036": [ + "github", "logo-github", - "mark-github", - "github" + "mark-github" ], "60037": [ "terminal", @@ -171,25 +171,25 @@ "repl" ], "60038": [ - "zap", - "symbol-event" + "symbol-event", + "zap" ], "60039": [ "error", "stop" ], "60040": [ - "variable", - "symbol-variable" + "symbol-variable", + "variable" ], "60042": [ - "array", - "symbol-array" + "symbol-array", + "array" ], "60043": [ + "symbol-namespace", "symbol-module", "symbol-package", - "symbol-namespace", "symbol-object" ], "60044": [ @@ -218,8 +218,8 @@ "symbol-text" ], "60052": [ - "symbol-reference", - "go-to-file" + "go-to-file", + "symbol-reference" ], "60053": [ "symbol-enum", @@ -344,8 +344,8 @@ "chrome-restore" ], "60092": [ - "circle-outline", "circle", + "circle-outline", "debug-breakpoint-unverified", "terminal-decoration-incomplete" ], diff --git a/src/template/metadata.json b/src/template/metadata.json index b443067..8ba7ea6 100644 --- a/src/template/metadata.json +++ b/src/template/metadata.json @@ -82,18 +82,6 @@ "category": "ai", "description": "AI agent or bot (compact 12x12 variant)" }, - "alert": { - "tags": [ - "warning", - "error", - "danger", - "notification", - "triangle", - "exclamation" - ], - "category": "status", - "description": "Alert or warning" - }, "archive": { "tags": [ "save", @@ -106,17 +94,6 @@ "category": "file", "description": "Archive or package items" }, - "array": { - "tags": [ - "list", - "collection", - "brackets", - "data", - "structure" - ], - "category": "symbol", - "description": "Array data structure" - }, "arrow-both": { "tags": [ "switch", @@ -278,6 +255,17 @@ "category": "navigation", "description": "Arrow pointing up" }, + "arrow-up-compact": { + "tags": [ + "arrow", + "up", + "direction", + "point", + "compact" + ], + "category": "navigation", + "description": "Arrow pointing up (compact 12x12 variant)" + }, "ask": { "tags": [ "question", @@ -910,6 +898,17 @@ "category": "window", "description": "Restore window button" }, + "circle": { + "tags": [ + "round", + "shape", + "empty", + "ring", + "hollow" + ], + "category": "shape", + "description": "Circle outline shape" + }, "circle-filled": { "tags": [ "dot", @@ -955,17 +954,6 @@ "category": "shape", "description": "Large filled circle" }, - "circle-outline": { - "tags": [ - "round", - "shape", - "empty", - "ring", - "hollow" - ], - "category": "shape", - "description": "Circle outline shape" - }, "circle-slash": { "tags": [ "error", @@ -1086,17 +1074,6 @@ "category": "general", "description": "Clock face showing time" }, - "clone": { - "tags": [ - "copy", - "duplicate", - "replicate", - "git", - "repo" - ], - "category": "action", - "description": "Clone or duplicate" - }, "close": { "tags": [ "remove", @@ -1175,6 +1152,17 @@ "category": "action", "description": "Download from cloud" }, + "cloud-download-compact": { + "tags": [ + "cloud", + "download", + "arrow", + "save", + "compact" + ], + "category": "cloud", + "description": "Cloud download (compact 12x12 variant)" + }, "cloud-small": { "tags": [ "online", @@ -1196,6 +1184,17 @@ "category": "action", "description": "Upload to cloud" }, + "cloud-upload-compact": { + "tags": [ + "cloud", + "upload", + "arrow", + "send", + "compact" + ], + "category": "cloud", + "description": "Cloud upload (compact 12x12 variant)" + }, "code": { "tags": [ "embed", @@ -2097,6 +2096,17 @@ "category": "debug", "description": "Stop debugging" }, + "desktop-download": { + "tags": [ + "copy", + "duplicate", + "replicate", + "git", + "repo" + ], + "category": "action", + "description": "Clone or duplicate" + }, "developer-tools": { "tags": [ "developer", @@ -2325,6 +2335,17 @@ "category": "layout", "description": "Editor layout" }, + "ellipsis": { + "tags": [ + "ellipsis", + "menu", + "options", + "actions", + "dots" + ], + "category": "navigation", + "description": "More options" + }, "empty-window": { "tags": [ "blank", @@ -2989,31 +3010,6 @@ "category": "git", "description": "GitHub Gist" }, - "gist-fork": { - "tags": [ - "copy", - "branch", - "split", - "duplicate", - "share", - "code", - "pr" - ], - "category": "git", - "description": "Fork Gist" - }, - "gist-private": { - "tags": [ - "lock", - "secret", - "hidden", - "secure", - "code", - "pr" - ], - "category": "git", - "description": "Private Gist" - }, "gist-secret": { "tags": [ "lock", @@ -3276,6 +3272,17 @@ "category": "git", "description": "Pop git stash" }, + "github": { + "tags": [ + "brand", + "cat", + "octocat", + "git", + "social" + ], + "category": "brand", + "description": "GitHub logo" + }, "github-action": { "tags": [ "ci", @@ -3342,6 +3349,17 @@ "category": "action", "description": "Go to editing session" }, + "go-to-file": { + "tags": [ + "code", + "link", + "pointer", + "alias", + "use" + ], + "category": "symbol", + "description": "Reference symbol" + }, "go-to-search": { "tags": [ "find", @@ -4250,6 +4268,18 @@ "category": "general", "description": "Location or place" }, + "lock": { + "tags": [ + "lock", + "secret", + "hidden", + "secure", + "code", + "pr" + ], + "category": "git", + "description": "Private Gist" + }, "lock-small": { "tags": [ "secure", @@ -4262,39 +4292,6 @@ "category": "security", "description": "Small lock" }, - "log-in": { - "tags": [ - "sign in", - "enter", - "access", - "auth", - "arrow" - ], - "category": "user", - "description": "Log in" - }, - "log-out": { - "tags": [ - "sign out", - "exit", - "leave", - "disconnect", - "arrow" - ], - "category": "user", - "description": "Log out" - }, - "logo-github": { - "tags": [ - "brand", - "cat", - "octocat", - "git", - "social" - ], - "category": "brand", - "description": "GitHub logo" - }, "magnet": { "tags": [ "stick", @@ -4327,17 +4324,6 @@ "category": "communication", "description": "Read mail" }, - "mail-reply": { - "tags": [ - "email", - "respond", - "answer", - "back", - "arrow" - ], - "category": "communication", - "description": "Reply to mail" - }, "map": { "tags": [ "location", @@ -4487,6 +4473,18 @@ "category": "device", "description": "Microphone or audio" }, + "mic-compact": { + "tags": [ + "microphone", + "audio", + "sound", + "voice", + "record", + "compact" + ], + "category": "media", + "description": "Microphone (compact 12x12 variant)" + }, "mic-download": { "tags": [ "microphone", @@ -4591,17 +4589,6 @@ "category": "action", "description": "Mirror or reflect" }, - "more": { - "tags": [ - "ellipsis", - "menu", - "options", - "actions", - "dots" - ], - "category": "navigation", - "description": "More options" - }, "mortar-board": { "tags": [ "education", @@ -5376,6 +5363,17 @@ "category": "action", "description": "Replace all" }, + "reply": { + "tags": [ + "email", + "respond", + "answer", + "back", + "arrow" + ], + "category": "communication", + "description": "Reply to mail" + }, "repo": { "tags": [ "repository", @@ -5430,6 +5428,19 @@ "category": "git", "description": "Force push repository" }, + "repo-forked": { + "tags": [ + "copy", + "branch", + "split", + "duplicate", + "share", + "code", + "pr" + ], + "category": "git", + "description": "Fork Gist" + }, "repo-forked-compact": { "tags": [ "repository", @@ -5486,17 +5497,6 @@ "category": "git", "description": "Selected repository" }, - "repo-sync": { - "tags": [ - "git", - "refresh", - "update", - "cycle", - "arrows" - ], - "category": "git", - "description": "Sync repository" - }, "report": { "tags": [ "document", @@ -5999,11 +5999,33 @@ "category": "security", "description": "Security or protection (compact variant)" }, - "skip": { + "sign-in": { "tags": [ - "next", - "jump", - "pass", + "sign in", + "enter", + "access", + "auth", + "arrow" + ], + "category": "user", + "description": "Log in" + }, + "sign-out": { + "tags": [ + "sign out", + "exit", + "leave", + "disconnect", + "arrow" + ], + "category": "user", + "description": "Log out" + }, + "skip": { + "tags": [ + "next", + "jump", + "pass", "ignore", "arrow" ], @@ -6118,7 +6140,7 @@ "category": "general", "description": "Squirrel" }, - "star": { + "star-empty": { "tags": [ "favorite", "bookmark", @@ -6183,6 +6205,17 @@ "category": "development", "description": "Surround with" }, + "symbol-array": { + "tags": [ + "list", + "collection", + "brackets", + "data", + "structure" + ], + "category": "symbol", + "description": "Array data structure" + }, "symbol-boolean": { "tags": [ "code", @@ -6260,6 +6293,17 @@ "category": "symbol", "description": "Enum member symbol" }, + "symbol-event": { + "tags": [ + "flash", + "electric", + "power", + "energy", + "fast" + ], + "category": "general", + "description": "Zap or flash" + }, "symbol-field": { "tags": [ "code", @@ -6347,7 +6391,7 @@ "category": "symbol", "description": "Miscellaneous symbol" }, - "symbol-module": { + "symbol-namespace": { "tags": [ "code", "package", @@ -6402,17 +6446,6 @@ "category": "symbol", "description": "Property symbol" }, - "symbol-reference": { - "tags": [ - "code", - "link", - "pointer", - "alias", - "use" - ], - "category": "symbol", - "description": "Reference symbol" - }, "symbol-ruler": { "tags": [ "code", @@ -6457,6 +6490,28 @@ "category": "symbol", "description": "Structure symbol" }, + "symbol-variable": { + "tags": [ + "code", + "value", + "store", + "data", + "box" + ], + "category": "symbol", + "description": "Variable" + }, + "sync": { + "tags": [ + "git", + "refresh", + "update", + "cycle", + "arrows" + ], + "category": "git", + "description": "Sync repository" + }, "sync-compact": { "tags": [ "refresh", @@ -6918,17 +6973,6 @@ "category": "status", "description": "Unverified" }, - "variable": { - "tags": [ - "code", - "value", - "store", - "data", - "box" - ], - "category": "symbol", - "description": "Variable" - }, "variable-group": { "tags": [ "code", @@ -7062,6 +7106,57 @@ "category": "device", "description": "Small VM icon" }, + "voice-mode": { + "tags": [ + "voice", + "audio", + "waveform", + "sound", + "microphone", + "speech" + ], + "category": "media", + "description": "Voice mode waveform indicator" + }, + "voice-mode-compact": { + "tags": [ + "voice", + "audio", + "waveform", + "sound", + "microphone", + "speech", + "compact" + ], + "category": "media", + "description": "Compact voice mode waveform indicator" + }, + "voice-mode-download": { + "tags": [ + "voice", + "audio", + "waveform", + "sound", + "download", + "save", + "arrow" + ], + "category": "media", + "description": "Voice mode waveform with download indicator" + }, + "voice-mode-download-compact": { + "tags": [ + "voice", + "audio", + "waveform", + "sound", + "download", + "save", + "compact" + ], + "category": "media", + "description": "Compact voice mode waveform with download indicator" + }, "vr": { "tags": [ "virtual", @@ -7130,6 +7225,18 @@ "category": "tool", "description": "Magic wand" }, + "warning": { + "tags": [ + "warning", + "error", + "danger", + "notification", + "triangle", + "exclamation" + ], + "category": "status", + "description": "Alert or warning" + }, "warning-compact": { "tags": [ "alert", @@ -7287,16 +7394,18 @@ "category": "git", "description": "Git worktree (small variant)" }, - "zap": { + "xai": { "tags": [ - "flash", - "electric", - "power", - "energy", - "fast" + "xai", + "grok", + "ai", + "logo", + "model", + "assistant", + "brand" ], - "category": "general", - "description": "Zap or flash" + "category": "brand", + "description": "xAI logo" }, "zoom-in": { "tags": [ @@ -7317,114 +7426,5 @@ ], "category": "action", "description": "Zoom out or reduce" - }, - "voice-mode": { - "tags": [ - "voice", - "audio", - "waveform", - "sound", - "microphone", - "speech" - ], - "category": "media", - "description": "Voice mode waveform indicator" - }, - "voice-mode-compact": { - "tags": [ - "voice", - "audio", - "waveform", - "sound", - "microphone", - "speech", - "compact" - ], - "category": "media", - "description": "Compact voice mode waveform indicator" - }, - "voice-mode-download": { - "tags": [ - "voice", - "audio", - "waveform", - "sound", - "download", - "save", - "arrow" - ], - "category": "media", - "description": "Voice mode waveform with download indicator" - }, - "voice-mode-download-compact": { - "tags": [ - "voice", - "audio", - "waveform", - "sound", - "download", - "save", - "compact" - ], - "category": "media", - "description": "Compact voice mode waveform with download indicator" - }, - "arrow-up-compact": { - "tags": [ - "arrow", - "up", - "direction", - "point", - "compact" - ], - "category": "navigation", - "description": "Arrow pointing up (compact 12x12 variant)" - }, - "mic-compact": { - "tags": [ - "microphone", - "audio", - "sound", - "voice", - "record", - "compact" - ], - "category": "media", - "description": "Microphone (compact 12x12 variant)" - }, - "cloud-download-compact": { - "tags": [ - "cloud", - "download", - "arrow", - "save", - "compact" - ], - "category": "cloud", - "description": "Cloud download (compact 12x12 variant)" - }, - "cloud-upload-compact": { - "tags": [ - "cloud", - "upload", - "arrow", - "send", - "compact" - ], - "category": "cloud", - "description": "Cloud upload (compact 12x12 variant)" - }, - "xai": { - "tags": [ - "xai", - "grok", - "ai", - "logo", - "model", - "assistant", - "brand" - ], - "category": "brand", - "description": "xAI logo" } }