diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8280246b7..c25dc9674 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -265,7 +265,7 @@ The project supports three types of icons, all with automatic imports (no manual 2. **Iconify Icons** - 200,000+ icons from various libraries: ``, `` 3. **Custom Icons** - Your own SVG icons: `` -Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `src/assets/icons/custom/` and processed by `build/customIconCollection.ts` with automatic validation. +Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `src/assets/icons/custom/`. For detailed instructions and code examples, see [src/assets/icons/README.md](src/assets/icons/README.md). diff --git a/build/customIconCollection.js b/build/customIconCollection.js new file mode 100644 index 000000000..ae52b97ae --- /dev/null +++ b/build/customIconCollection.js @@ -0,0 +1,29 @@ +import { readFileSync, readdirSync } from 'fs' +import { join } from 'path' +import { dirname } from 'path' +import { fileURLToPath } from 'url' + +const fileName = fileURLToPath(import.meta.url) +const dirName = dirname(fileName) +const customIconsPath = join(dirName, '..', 'src', 'assets', 'icons', 'custom') + +// Create an Iconify collection for custom icons +export const iconCollection = { + prefix: 'comfy', + icons: {}, + width: 16, + height: 16 +} + +// Read all SVG files from the custom icons directory +const files = readdirSync(customIconsPath) +files.forEach((file) => { + if (file.endsWith('.svg')) { + const name = file.replace('.svg', '') + const content = readFileSync(join(customIconsPath, file), 'utf-8') + + iconCollection.icons[name] = { + body: content + } + } +}) diff --git a/build/customIconCollection.ts b/build/customIconCollection.ts deleted file mode 100644 index f2d823ed5..000000000 --- a/build/customIconCollection.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { existsSync, readFileSync, readdirSync } from 'fs' -import { join } from 'path' -import { dirname } from 'path' -import { fileURLToPath } from 'url' - -const fileName = fileURLToPath(import.meta.url) -const dirName = dirname(fileName) -const customIconsPath = join(dirName, '..', 'src', 'assets', 'icons', 'custom') - -// Iconify collection structure -interface IconifyIcon { - body: string - width?: number - height?: number -} - -interface IconifyCollection { - prefix: string - icons: Record - width?: number - height?: number -} - -// Create an Iconify collection for custom icons -export const iconCollection: IconifyCollection = { - prefix: 'comfy', - icons: {}, - width: 16, - height: 16 -} - -/** - * Validates that an SVG file contains valid SVG content - */ -function validateSvgContent(content: string, filename: string): void { - if (!content.trim()) { - throw new Error(`Empty SVG file: ${filename}`) - } - - if (!content.includes(' tag): ${filename}`) - } - - // Basic XML structure validation - const openTags = (content.match(/]*>/g) || []).length - const closeTags = (content.match(/<\/svg>/g) || []).length - - if (openTags !== closeTags) { - throw new Error(`Malformed SVG file (mismatched svg tags): ${filename}`) - } -} - -/** - * Loads custom SVG icons from the icons directory - */ -function loadCustomIcons(): void { - if (!existsSync(customIconsPath)) { - console.warn(`Custom icons directory not found: ${customIconsPath}`) - return - } - - try { - const files = readdirSync(customIconsPath) - const svgFiles = files.filter((file) => file.endsWith('.svg')) - - if (svgFiles.length === 0) { - console.warn('No SVG files found in custom icons directory') - return - } - - svgFiles.forEach((file) => { - const name = file.replace('.svg', '') - const filePath = join(customIconsPath, file) - - try { - const content = readFileSync(filePath, 'utf-8') - validateSvgContent(content, file) - - iconCollection.icons[name] = { - body: content - } - } catch (error) { - console.error( - `Failed to load custom icon ${file}:`, - error instanceof Error ? error.message : error - ) - // Continue loading other icons instead of failing the entire build - } - }) - } catch (error) { - console.error( - 'Failed to read custom icons directory:', - error instanceof Error ? error.message : error - ) - // Don't throw here - allow build to continue without custom icons - } -} - -// Load icons when this module is imported -loadCustomIcons() diff --git a/package-lock.json b/package-lock.json index 2193dd5fc..2031b3341 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2344,6 +2344,7 @@ "resolved": "https://registry.npmjs.org/@iconify/tailwind/-/tailwind-1.2.0.tgz", "integrity": "sha512-KgpIHWOTcRYw1XcoUqyNSrmYyfLLqZYu3AmP8zdfLk0F5TqRO8YerhlvlQmGfn7rJXgPeZN569xPAJnJ53zZxA==", "dev": true, + "license": "MIT", "dependencies": { "@iconify/types": "^2.0.0" }, diff --git a/src/assets/icons/README.md b/src/assets/icons/README.md index b01a3e3ef..cd92f1ddf 100644 --- a/src/assets/icons/README.md +++ b/src/assets/icons/README.md @@ -247,29 +247,9 @@ Icons are automatically imported using `unplugin-icons` - no manual imports need ### Configuration -The icon system has two layers: - -1. **Build-time Processing** (`build/customIconCollection.ts`): - - Scans `src/assets/icons/custom/` for SVG files - - Validates SVG content and structure - - Creates Iconify collection for Tailwind CSS - - Provides error handling for malformed files - -2. **Vite Runtime** (`vite.config.mts`): - - Enables direct SVG import as Vue components - - Supports dynamic icon loading +The icon system is configured in `vite.config.mts`: ```typescript -// Build script creates Iconify collection -export const iconCollection: IconifyCollection = { - prefix: 'comfy', - icons: { - 'workflow': { body: '...' }, - 'node': { body: '...' } - } -} - -// Vite configuration for component-based usage Icons({ compiler: 'vue3', customCollections: { @@ -291,9 +271,8 @@ Icons are fully typed. If TypeScript doesn't recognize a new custom icon: ### Icon Not Showing 1. **Check filename**: Must be kebab-case without special characters 2. **Restart dev server**: Required after adding new icons -3. **Verify SVG**: Ensure it's valid SVG syntax (build script validates automatically) +3. **Verify SVG**: Ensure it's valid SVG syntax 4. **Check console**: Look for Vue component resolution errors -5. **Build script errors**: Check console during build - malformed SVGs are logged but don't break builds ### Icon Wrong Color - Replace hardcoded colors with `currentColor` diff --git a/tailwind.config.js b/tailwind.config.js index 9c809eaa8..19cb6507d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,7 +1,7 @@ /** @type {import('tailwindcss').Config} */ import { addDynamicIconSelectors } from '@iconify/tailwind' -import { iconCollection } from './build/customIconCollection.ts' +import { iconCollection } from './build/customIconCollection.js' export default { content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],