@vscode/codicons
Version:
The icon font for Visual Studio Code
127 lines (105 loc) • 3.81 kB
JavaScript
/**
* This script checks which icons are missing metadata and reports them.
* It helps maintain the metadata.json file by identifying gaps.
*/
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');
const metadataPath = path.join(__dirname, '..', 'src', 'template', 'metadata.json');
if (!fs.existsSync(mappingPath)) {
console.error('Error: mapping.json not found at', mappingPath);
process.exit(1);
}
if (!fs.existsSync(metadataPath)) {
console.error('Error: metadata.json not found at', 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]);
}
});
// Find icons without metadata
const missingMetadata = [];
allIconNames.forEach(iconName => {
if (!metadata[iconName]) {
missingMetadata.push(iconName);
}
});
// Find metadata for icons that don't exist
const orphanedMetadata = [];
Object.keys(metadata).forEach(iconName => {
if (!allIconNames.has(iconName)) {
orphanedMetadata.push(iconName);
}
});
// Report results
console.log('='.repeat(60));
console.log('Icon Metadata Coverage Report');
console.log('='.repeat(60));
console.log();
console.log(`Total icons: ${allIconNames.size}`);
console.log(`Icons with metadata: ${allIconNames.size - missingMetadata.length}`);
console.log(`Coverage: ${Math.round(((allIconNames.size - missingMetadata.length) / allIconNames.size) * 100)}%`);
console.log();
if (missingMetadata.length > 0) {
console.log(`Icons missing metadata (${missingMetadata.length}):`);
console.log('-'.repeat(60));
missingMetadata.sort().forEach(name => {
console.log(` - ${name}`);
});
console.log();
}
if (orphanedMetadata.length > 0) {
console.log(`Metadata entries for non-existent icons (${orphanedMetadata.length}):`);
console.log('-'.repeat(60));
orphanedMetadata.sort().forEach(name => {
console.log(` - ${name}`);
});
console.log();
}
if (missingMetadata.length === 0 && orphanedMetadata.length === 0) {
console.log('✓ All icons have metadata and no orphaned entries found!');
console.log();
}
// Validate existing metadata structure
const invalidEntries = [];
Object.entries(metadata).forEach(([name, meta]) => {
const issues = [];
if (!meta.tags || !Array.isArray(meta.tags)) {
issues.push('missing or invalid tags array');
} else if (meta.tags.length === 0) {
issues.push('empty tags array');
}
if (!meta.category || typeof meta.category !== 'string') {
issues.push('missing or invalid category');
}
if (!meta.description || typeof meta.description !== 'string') {
issues.push('missing or invalid description');
}
if (issues.length > 0) {
invalidEntries.push({ name, issues });
}
});
if (invalidEntries.length > 0) {
console.log(`Metadata entries with validation issues (${invalidEntries.length}):`);
console.log('-'.repeat(60));
invalidEntries.forEach(({ name, issues }) => {
console.log(` - ${name}:`);
issues.forEach(issue => {
console.log(` * ${issue}`);
});
});
console.log();
}
// Exit with error if there are missing entries
if (missingMetadata.length > 0 || orphanedMetadata.length > 0 || invalidEntries.length > 0) {
process.exit(1);
}