You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.7 KiB
105 lines
2.7 KiB
|
6 months ago
|
import { readFileSync, readdirSync, writeFileSync } from 'fs';
|
||
|
|
import { join } from 'path';
|
||
|
|
|
||
|
|
const ICONS_SOURCE = join(process.cwd(), 'static/lucide/icons');
|
||
|
|
const OUTPUT_FILE = join(process.cwd(), 'src/uix/air/icons/categories.ts');
|
||
|
|
|
||
|
|
function toPascalCase(str) {
|
||
|
|
return str
|
||
|
|
.split(/[-_]/)
|
||
|
|
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||
|
|
.join('');
|
||
|
|
}
|
||
|
|
|
||
|
|
const categoryLabels = {
|
||
|
|
arrows: 'Arrows',
|
||
|
|
communication: 'Communication',
|
||
|
|
design: 'Design',
|
||
|
|
dev: 'Development',
|
||
|
|
editors: 'Editors',
|
||
|
|
logo: 'Logos',
|
||
|
|
maps: 'Maps',
|
||
|
|
media: 'Media',
|
||
|
|
objects: 'Objects',
|
||
|
|
people: 'People',
|
||
|
|
science: 'Science',
|
||
|
|
sports: 'Sports',
|
||
|
|
text: 'Text',
|
||
|
|
weather: 'Weather',
|
||
|
|
ui: 'UI Elements',
|
||
|
|
currency: 'Currency',
|
||
|
|
animals: 'Animals',
|
||
|
|
food: 'Food',
|
||
|
|
health: 'Health',
|
||
|
|
home: 'Home',
|
||
|
|
navigation: 'Navigation',
|
||
|
|
shopping: 'Shopping',
|
||
|
|
social: 'Social',
|
||
|
|
transportation: 'Transportation',
|
||
|
|
accessibility: 'Accessibility',
|
||
|
|
security: 'Security',
|
||
|
|
files: 'Files',
|
||
|
|
datetime: 'Date & Time',
|
||
|
|
};
|
||
|
|
|
||
|
|
function main() {
|
||
|
|
const allFiles = readdirSync(ICONS_SOURCE).filter(f => f.endsWith('.json'));
|
||
|
|
const categoryMap = new Map();
|
||
|
|
|
||
|
|
for (const file of allFiles) {
|
||
|
|
const iconName = file.replace('.json', '');
|
||
|
|
const jsonPath = join(ICONS_SOURCE, file);
|
||
|
|
|
||
|
|
try {
|
||
|
|
const json = JSON.parse(readFileSync(jsonPath, 'utf-8'));
|
||
|
|
const categories = json.categories || ['uncategorized'];
|
||
|
|
|
||
|
|
for (const category of categories) {
|
||
|
|
if (!categoryMap.has(category)) {
|
||
|
|
categoryMap.set(category, []);
|
||
|
|
}
|
||
|
|
categoryMap.get(category).push({
|
||
|
|
name: iconName,
|
||
|
|
pascal: toPascalCase(iconName),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
console.error(`Error parsing ${file}:`, e.message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Sort icons within each category
|
||
|
|
for (const icons of categoryMap.values()) {
|
||
|
|
icons.sort((a, b) => a.name.localeCompare(b.name));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate TypeScript file
|
||
|
|
const sortedCategories = Array.from(categoryMap.entries()).sort(([a], [b]) =>
|
||
|
|
a.localeCompare(b)
|
||
|
|
);
|
||
|
|
|
||
|
|
let output = '// Auto-generated - DO NOT EDIT\n\n';
|
||
|
|
output += 'export interface IconCategory {\n';
|
||
|
|
output += ' name: string;\n';
|
||
|
|
output += ' label: string;\n';
|
||
|
|
output += ' icons: Array<{ name: string; pascal: string }>;\n';
|
||
|
|
output += '}\n\n';
|
||
|
|
output += 'export const iconCategories: IconCategory[] = [\n';
|
||
|
|
|
||
|
|
for (const [category, icons] of sortedCategories) {
|
||
|
|
const label = categoryLabels[category] || toPascalCase(category);
|
||
|
|
output += `\t{ name: '${category}', label: '${label}', icons: [\n`;
|
||
|
|
for (const icon of icons) {
|
||
|
|
output += `\t\t{ name: '${icon.name}', pascal: '${icon.pascal}' },\n`;
|
||
|
|
}
|
||
|
|
output += '\t] },\n';
|
||
|
|
}
|
||
|
|
|
||
|
|
output += '];\n';
|
||
|
|
|
||
|
|
writeFileSync(OUTPUT_FILE, output, 'utf-8');
|
||
|
|
console.log(`Generated ${OUTPUT_FILE} with ${categoryMap.size} categories`);
|
||
|
|
}
|
||
|
|
|
||
|
|
main();
|