Skip to content

Commit 8107405

Browse files
authored
Merge pull request #408 from microsoft/mrleemurray/fuzzy-bonobo-green
Enhance icon search functionality and metadata handling
2 parents f8ff241 + e547c40 commit 8107405

File tree

5 files changed

+3159
-288
lines changed

5 files changed

+3159
-288
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
"replace-in-vscode": "cp -R ./dist/codicon.ttf ../vscode/src/vs/base/browser/ui/codicons/codicon/codicon.ttf && cp ./dist/codiconsLibrary.ts ../vscode/src/vs/base/common/codiconsLibrary.ts",
1313
"export-to-ts": "node ./scripts/export-to-ts.js -f ./src/template/mapping.json > ./dist/codiconsLibrary.ts",
1414
"export-to-csv": "node ./scripts/export-to-csv.js -f ./dist/codicon.ttf > ./dist/codicon.csv",
15+
"copy-metadata": "cp ./src/template/metadata.json ./dist/metadata.json",
16+
"embed-metadata": "node ./scripts/embed-metadata.js",
17+
"check-metadata": "node ./scripts/check-metadata.js",
1518
"fonts": "fantasticon",
1619
"dev": "npm run build && npm run replace-in-vscode",
17-
"build": "npm run clean && npm run svgo && npm run fonts && npm run export-to-ts && npm run export-to-csv && npm run sprite",
20+
"build": "npm run clean && npm run svgo && npm run fonts && npm run export-to-ts && npm run export-to-csv && npm run copy-metadata && npm run embed-metadata && npm run sprite",
1821
"version:bump": "node ./scripts/version-bump.js",
1922
"version:patch": "node ./scripts/version-bump.js patch minor",
2023
"version:minor": "node ./scripts/version-bump.js minor minor",

scripts/check-metadata.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* This script checks which icons are missing metadata and reports them.
5+
* It helps maintain the metadata.json file by identifying gaps.
6+
*/
7+
8+
const fs = require('fs');
9+
const path = require('path');
10+
11+
// Load the mapping file to get all icon names
12+
const mappingPath = path.join(__dirname, '..', 'src', 'template', 'mapping.json');
13+
const metadataPath = path.join(__dirname, '..', 'src', 'template', 'metadata.json');
14+
15+
if (!fs.existsSync(mappingPath)) {
16+
console.error('Error: mapping.json not found at', mappingPath);
17+
process.exit(1);
18+
}
19+
20+
if (!fs.existsSync(metadataPath)) {
21+
console.error('Error: metadata.json not found at', metadataPath);
22+
process.exit(1);
23+
}
24+
25+
const mapping = JSON.parse(fs.readFileSync(mappingPath, 'utf8'));
26+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
27+
28+
// Collect all unique icon names from mapping
29+
const allIconNames = new Set();
30+
Object.values(mapping).forEach(aliases => {
31+
// For each code point, add the first alias (primary name)
32+
if (aliases && aliases.length > 0) {
33+
allIconNames.add(aliases[0]);
34+
}
35+
});
36+
37+
// Find icons without metadata
38+
const missingMetadata = [];
39+
allIconNames.forEach(iconName => {
40+
if (!metadata[iconName]) {
41+
missingMetadata.push(iconName);
42+
}
43+
});
44+
45+
// Find metadata for icons that don't exist
46+
const orphanedMetadata = [];
47+
Object.keys(metadata).forEach(iconName => {
48+
if (!allIconNames.has(iconName)) {
49+
orphanedMetadata.push(iconName);
50+
}
51+
});
52+
53+
// Report results
54+
console.log('='.repeat(60));
55+
console.log('Icon Metadata Coverage Report');
56+
console.log('='.repeat(60));
57+
console.log();
58+
59+
console.log(`Total icons: ${allIconNames.size}`);
60+
console.log(`Icons with metadata: ${allIconNames.size - missingMetadata.length}`);
61+
console.log(`Coverage: ${Math.round(((allIconNames.size - missingMetadata.length) / allIconNames.size) * 100)}%`);
62+
console.log();
63+
64+
if (missingMetadata.length > 0) {
65+
console.log(`Icons missing metadata (${missingMetadata.length}):`);
66+
console.log('-'.repeat(60));
67+
missingMetadata.sort().forEach(name => {
68+
console.log(` - ${name}`);
69+
});
70+
console.log();
71+
}
72+
73+
if (orphanedMetadata.length > 0) {
74+
console.log(`Metadata entries for non-existent icons (${orphanedMetadata.length}):`);
75+
console.log('-'.repeat(60));
76+
orphanedMetadata.sort().forEach(name => {
77+
console.log(` - ${name}`);
78+
});
79+
console.log();
80+
}
81+
82+
if (missingMetadata.length === 0 && orphanedMetadata.length === 0) {
83+
console.log('✓ All icons have metadata and no orphaned entries found!');
84+
console.log();
85+
}
86+
87+
// Validate existing metadata structure
88+
const invalidEntries = [];
89+
Object.entries(metadata).forEach(([name, meta]) => {
90+
const issues = [];
91+
92+
if (!meta.tags || !Array.isArray(meta.tags)) {
93+
issues.push('missing or invalid tags array');
94+
} else if (meta.tags.length === 0) {
95+
issues.push('empty tags array');
96+
}
97+
98+
if (!meta.category || typeof meta.category !== 'string') {
99+
issues.push('missing or invalid category');
100+
}
101+
102+
if (!meta.description || typeof meta.description !== 'string') {
103+
issues.push('missing or invalid description');
104+
}
105+
106+
if (issues.length > 0) {
107+
invalidEntries.push({ name, issues });
108+
}
109+
});
110+
111+
if (invalidEntries.length > 0) {
112+
console.log(`Metadata entries with validation issues (${invalidEntries.length}):`);
113+
console.log('-'.repeat(60));
114+
invalidEntries.forEach(({ name, issues }) => {
115+
console.log(` - ${name}:`);
116+
issues.forEach(issue => {
117+
console.log(` * ${issue}`);
118+
});
119+
});
120+
console.log();
121+
}
122+
123+
// Exit with error if there are missing entries
124+
if (missingMetadata.length > 0 || orphanedMetadata.length > 0 || invalidEntries.length > 0) {
125+
process.exit(1);
126+
}

scripts/embed-metadata.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
const metadataPath = path.join(__dirname, '../src/template/metadata.json');
5+
const htmlPath = path.join(__dirname, '../dist/codicon.html');
6+
7+
if (!fs.existsSync(htmlPath)) {
8+
console.error('HTML file not found:', htmlPath);
9+
process.exit(1);
10+
}
11+
12+
const metadata = fs.readFileSync(metadataPath, 'utf8');
13+
let html = fs.readFileSync(htmlPath, 'utf8');
14+
15+
const placeholder = '{} // METADATA_PLACEHOLDER';
16+
const replacement = `${metadata} // METADATA_PLACEHOLDER`;
17+
18+
if (html.includes('// METADATA_PLACEHOLDER')) {
19+
// Use regex to replace the initialization
20+
html = html.replace(/let metadata = .* \/\/ METADATA_PLACEHOLDER/, `let metadata = ${metadata}; // METADATA_PLACEHOLDER`);
21+
fs.writeFileSync(htmlPath, html);
22+
console.log('Metadata embedded into HTML.');
23+
} else {
24+
console.warn('Metadata placeholder not found in HTML.');
25+
}

0 commit comments

Comments
 (0)