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.
svelte-kit-vice/scripts/convert-icons.js

154 lines
4.0 KiB

import { readFileSync, writeFileSync, readdirSync, existsSync } from 'fs';
import { join } from 'path';
const ICONS_SOURCE = join(process.cwd(), 'static/lucide/icons');
const ICONS_TARGET = join(process.cwd(), 'src/uix/air/icons/lib');
const INDEX_FILE = join(process.cwd(), 'src/uix/air/icons/sound.svelte.ts');
function getExistingIcons() {
const files = readdirSync(ICONS_TARGET);
return new Set(files.map((f) => f.replace('.svelte', '')));
}
function parseSvgContent(svgContent) {
// Extract all child elements (path, circle, rect, polyline, line, polygon, ellipse)
const elements = [];
const patterns = [
/<path\s+([^>]*)>/g,
/<circle\s+([^>]*)>/g,
/<rect\s+([^>]*)>/g,
/<polyline\s+([^>]*)>/g,
/<line\s+([^>]*)>/g,
/<polygon\s+([^>]*)>/g,
/<ellipse\s+([^>]*)>/g
];
for (const pattern of patterns) {
let match;
while ((match = pattern.exec(svgContent)) !== null) {
const tagName = pattern.source.replace('\\s+([^>]*)>', '').replace('<', '').replace('\\', '');
const attrs = match[1];
elements.push(`<${tagName} ${attrs}>`);
}
}
return elements.join('\n\t');
}
function toPascalCase(str) {
return str
.split(/[-_]/)
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
}
function convertIcon(iconName) {
const svgPath = join(ICONS_SOURCE, `${iconName}.svg`);
if (!existsSync(svgPath)) {
return null;
}
const svgContent = readFileSync(svgPath, 'utf-8');
const innerContent = parseSvgContent(svgContent);
// Generate Svelte component
const component = `<script lang="ts">
import Icon from '../icon.svelte';
import type { AirIconProps } from '../types';
let props: AirIconProps = $props();
</script>
<Icon {...props}>
${innerContent}
</Icon>
`;
return component;
}
function updateIndex(icons) {
const existingIndex = readFileSync(INDEX_FILE, 'utf-8');
const lines = existingIndex.split('\n');
// Find the last export line (before export type)
const lastExportLine = lines.findIndex((l) => l.startsWith('export type'));
// Collect existing exports
const existingExports = new Set();
lines.forEach((line) => {
const match = line.match(/export \{ default as (\w+) \}/);
if (match) existingExports.add(match[1]);
});
// Add new exports
const newExports = [];
for (const icon of icons) {
const pascalName = toPascalCase(icon);
if (!existingExports.has(pascalName)) {
newExports.push(`export { default as ${pascalName} } from './lib/${icon}.svelte';`);
existingExports.add(pascalName);
}
}
if (newExports.length === 0) return;
// Insert new exports before the export type line
lines.splice(lastExportLine, 0, ...newExports);
// Sort exports (keep TooltipContext first, then alphabetically)
const rootLine = lines[0];
const otherExports = lines.slice(1, lastExportLine + newExports.length);
const typeLine = lines[lastExportLine + newExports.length];
otherExports.sort();
const newContent = [
rootLine,
...otherExports,
typeLine,
...lines.slice(lastExportLine + newExports.length + 1)
].join('\n');
writeFileSync(INDEX_FILE, newContent);
}
function main() {
const existingIcons = getExistingIcons();
const allSvgFiles = readdirSync(ICONS_SOURCE).filter((f) => f.endsWith('.svg'));
const missingIcons = allSvgFiles
.map((f) => f.replace('.svg', ''))
.filter((name) => !existingIcons.has(name));
console.log(`Found ${missingIcons.length} icons to convert...`);
if (missingIcons.length === 0) {
console.log('No new icons to convert!');
return;
}
// Limit to first 100 for testing
const toConvert = process.argv[2] === 'all' ? missingIcons : missingIcons.slice(0, 100);
console.log(`Converting ${toConvert.length} icons...`);
const converted = [];
for (const iconName of toConvert) {
const component = convertIcon(iconName);
if (component) {
const targetPath = join(ICONS_TARGET, `${iconName}.svelte`);
writeFileSync(targetPath, component);
converted.push(iconName);
console.log(`✓ ${iconName}`);
}
}
updateIndex(converted);
console.log(`\nDone! Converted ${converted.length} icons.`);
}
main();

Powered by TurnKey Linux.