@dsai-io/tools 1.0.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/icons/core/optimizer.ts","../../src/icons/core/scanner.ts","../../src/icons/utils/naming.ts","../../src/icons/core/parser.ts","../../src/icons/core/index.ts","../../src/icons/generators/react.ts","../../src/icons/generators/svg-sprite.ts","../../src/icons/index.ts"],"names":["defaultSVGOConfig","readFileSync","statSync","basename","existsSync","mkdirSync","join","writeFileSync","skipOptimization"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * SVG optimizer (SVGO integration)\n *\n * Optimizes SVG files using SVGO for smaller file sizes.\n *\n * @packageDocumentation\n */\n\nimport type { OptimizedSVG, ParsedSVG, RawSVGData, SVGOConfig } from '../types.js';\n\n/**\n * Default SVGO configuration\n *\n * Provides sensible defaults for icon optimization.\n */\nexport const defaultSVGOConfig: SVGOConfig = {\n multipass: true,\n plugins: [\n { name: 'preset-default' },\n { name: 'removeXMLNS' },\n { name: 'removeDimensions' },\n { name: 'removeStyleElement' },\n { name: 'removeScriptElement' },\n {\n name: 'removeAttrs',\n params: {\n attrs: ['class', 'style', 'data-name', 'xmlns:xlink'],\n },\n },\n {\n name: 'addAttributesToSVGElement',\n params: {\n attributes: [{ 'aria-hidden': 'true' }, { focusable: 'false' }],\n },\n },\n {\n name: 'sortAttrs',\n params: {\n xmlnsOrder: 'alphabetical',\n },\n },\n ],\n};\n\n/**\n * Optimize a single SVG\n *\n * @param parsed - Parsed SVG data\n * @param raw - Raw SVG data (for size comparison)\n * @param config - SVGO configuration\n * @returns Optimized SVG data\n */\nexport async function optimizeSVG(\n parsed: ParsedSVG,\n raw: RawSVGData,\n config: SVGOConfig = defaultSVGOConfig\n): Promise<OptimizedSVG> {\n // Dynamic import of SVGO\n const svgo = await import('svgo');\n\n // Merge plugins with defaults if provided\n const plugins = config.plugins ?? defaultSVGOConfig.plugins ?? [];\n\n // Convert our plugin format to SVGO's expected format\n const svgoPlugins = plugins.map((p) => ({\n name: p.name,\n ...(p.params ? { params: p.params } : {}),\n }));\n\n // Run SVGO optimization\n const result = svgo.optimize(raw.content, {\n multipass: config.multipass ?? true,\n plugins: svgoPlugins as NonNullable<Parameters<typeof svgo.optimize>[1]>['plugins'],\n });\n\n const optimizedContent = result.data;\n const optimizedSize = Buffer.byteLength(optimizedContent, 'utf-8');\n const sizeReduction =\n raw.originalSize > 0 ? ((raw.originalSize - optimizedSize) / raw.originalSize) * 100 : 0;\n\n // Re-parse optimized content to get updated inner content\n const innerContentMatch = optimizedContent.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\n const innerContent = innerContentMatch?.[1]?.trim() ?? parsed.innerContent;\n\n // Extract updated viewBox\n const viewBoxMatch = optimizedContent.match(/viewBox=[\"']([^\"']*)[\"']/i);\n const viewBox = viewBoxMatch?.[1] ?? parsed.viewBox;\n\n return {\n ...parsed,\n innerContent,\n fullContent: optimizedContent,\n viewBox,\n optimizedSize,\n sizeReduction,\n };\n}\n\n/**\n * Optimize multiple SVGs\n *\n * @param parsedFiles - Array of parsed SVG data\n * @param rawFiles - Array of raw SVG data\n * @param config - SVGO configuration\n * @returns Array of optimized SVG data\n */\nexport async function optimizeSVGFiles(\n parsedFiles: ParsedSVG[],\n rawFiles: RawSVGData[],\n config: SVGOConfig = defaultSVGOConfig\n): Promise<OptimizedSVG[]> {\n const results: OptimizedSVG[] = [];\n\n for (const parsed of parsedFiles) {\n const raw = rawFiles.find((r) => r.fileName === parsed.fileName);\n if (!raw) {\n throw new Error(`Raw file not found for ${parsed.fileName}`);\n }\n const optimized = await optimizeSVG(parsed, raw, config);\n results.push(optimized);\n }\n\n return results;\n}\n\n/**\n * Skip optimization and just add size metadata\n *\n * Useful when SVGO is not needed but the type structure is required.\n *\n * @param parsed - Parsed SVG data\n * @param raw - Raw SVG data\n * @returns Optimized SVG data (without actual optimization)\n */\nexport function skipOptimization(parsed: ParsedSVG, raw: RawSVGData): OptimizedSVG {\n return {\n ...parsed,\n optimizedSize: raw.originalSize,\n sizeReduction: 0,\n };\n}\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * SVG file scanner\n *\n * Scans directories for SVG files and reads their contents.\n *\n * @packageDocumentation\n */\n\nimport { readFileSync, statSync } from 'node:fs';\nimport { basename } from 'node:path';\n\nimport type { RawSVGData, ScannerOptions } from '../types.js';\n\n/**\n * Scan directory for SVG files\n *\n * Uses fast-glob to find SVG files matching the specified patterns.\n *\n * @param options - Scanner options\n * @returns Array of raw SVG data\n *\n * @example\n * ```typescript\n * const files = await scanSVGFiles({\n * sourceDir: './icons',\n * include: ['**\\/*.svg'],\n * exclude: ['**\\/node_modules\\/**'],\n * });\n * ```\n */\nexport async function scanSVGFiles(options: ScannerOptions): Promise<RawSVGData[]> {\n const {\n sourceDir,\n include = ['**/*.svg'],\n exclude = ['**/node_modules/**', '**/dist/**'],\n } = options;\n\n // Dynamic import of fast-glob (ESM module)\n const { default: fg } = await import('fast-glob');\n\n // Find all SVG files\n const files = await fg(include, {\n cwd: sourceDir,\n ignore: exclude,\n absolute: true,\n onlyFiles: true,\n });\n\n // Read each file\n const svgFiles: RawSVGData[] = [];\n\n for (const filePath of files) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n const stats = statSync(filePath);\n\n // Extract file name without extension\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\n\n svgFiles.push({\n filePath,\n fileName,\n content,\n originalSize: stats.size,\n });\n } catch {\n console.warn(`Warning: Failed to read ${filePath}`);\n }\n }\n\n // Sort by name for consistent output\n svgFiles.sort((a, b) => a.fileName.localeCompare(b.fileName));\n\n return svgFiles;\n}\n\n/**\n * Read a single SVG file\n *\n * @param filePath - Path to SVG file\n * @returns Raw SVG data or null if failed\n */\nexport function readSVGFile(filePath: string): RawSVGData | null {\n try {\n const content = readFileSync(filePath, 'utf-8');\n const stats = statSync(filePath);\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\n\n return {\n filePath,\n fileName,\n content,\n originalSize: stats.size,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Icon naming utilities\n *\n * @packageDocumentation\n */\n\n/**\n * Convert string to PascalCase component name\n *\n * @param input - Input string (e.g., file name)\n * @returns PascalCase component name\n *\n * @example\n * ```typescript\n * toComponentName('arrow-left') // 'ArrowLeft'\n * toComponentName('24px-icon') // 'Icon24px'\n * toComponentName('my_icon') // 'MyIcon'\n * toComponentName('chevron-down-small') // 'ChevronDownSmall'\n * ```\n */\nexport function toComponentName(input: string): string {\n // Handle numbers at start by prefixing with 'Icon'\n let processed = input;\n if (/^\\d/.test(processed)) {\n processed = `icon-${processed}`;\n }\n\n return (\n processed\n // Split on non-alphanumeric characters\n .split(/[^a-zA-Z0-9]+/)\n // Filter empty strings\n .filter((word) => word.length > 0)\n // Capitalize each word\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n // Join into single string\n .join('')\n );\n}\n\n/**\n * Convert string to kebab-case icon name\n *\n * @param input - Input string (e.g., component name)\n * @returns kebab-case icon name\n *\n * @example\n * ```typescript\n * toIconName('ArrowLeft') // 'arrow-left'\n * toIconName('ChevronDownSmall') // 'chevron-down-small'\n * toIconName('Icon24px') // 'icon-24px'\n * ```\n */\nexport function toIconName(input: string): string {\n return (\n input\n // Insert hyphen before uppercase letters\n .replace(/([A-Z])/g, '-$1')\n // Insert hyphen before number sequences\n .replace(/(\\d+)/g, '-$1')\n // Clean up multiple hyphens\n .replace(/-+/g, '-')\n // Remove leading hyphen\n .replace(/^-/, '')\n // Lowercase\n .toLowerCase()\n );\n}\n\n/**\n * Validate icon name\n *\n * @param name - Icon name to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidIconName(name: string): boolean {\n // Must be non-empty\n if (!name || name.length === 0) {\n return false;\n }\n\n // Must be valid identifier-like (alphanumeric, hyphens, underscores)\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Normalize icon name from file name\n *\n * @param fileName - File name (without extension)\n * @returns Normalized icon name\n */\nexport function normalizeIconName(fileName: string): string {\n return fileName\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n}\n","/**\n * SVG parser\n *\n * Parses SVG content into structured data.\n *\n * @packageDocumentation\n */\n\nimport { normalizeIconName, toComponentName } from '../utils/naming.js';\n\nimport type { ParsedSVG, RawSVGData } from '../types.js';\n\n/**\n * Parse raw SVG data into structured format\n *\n * Extracts viewBox, attributes, inner content, and accessibility info.\n *\n * @param raw - Raw SVG data\n * @returns Parsed SVG data\n */\nexport function parseSVG(raw: RawSVGData): ParsedSVG {\n const { content, fileName } = raw;\n\n // Extract SVG opening tag attributes\n const svgMatch = content.match(/<svg([^>]*)>/i);\n const svgAttributes = svgMatch?.[1] ?? '';\n\n // Parse attributes into object\n const attributes: Record<string, string> = {};\n const attrRegex = /([a-zA-Z][a-zA-Z0-9-]*)=[\"']([^\"']*)[\"']/g;\n\n for (const attrMatch of svgAttributes.matchAll(attrRegex)) {\n const key = attrMatch[1];\n const value = attrMatch[2];\n if (key && value !== undefined) {\n Object.assign(attributes, { [key]: value });\n }\n }\n\n // Extract viewBox (or construct from width/height)\n let viewBox = attributes['viewBox'] ?? '';\n if (!viewBox) {\n const width = attributes['width']?.replace(/[^\\d.]/g, '') ?? '24';\n const height = attributes['height']?.replace(/[^\\d.]/g, '') ?? '24';\n viewBox = `0 0 ${width} ${height}`;\n }\n\n // Extract inner content (everything between <svg> and </svg>)\n const innerContentMatch = content.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\n const innerContent = innerContentMatch?.[1]?.trim() ?? '';\n\n // Extract title for accessibility\n const titleMatch = content.match(/<title>([^<]*)<\\/title>/i);\n const title = titleMatch?.[1];\n\n // Extract description for accessibility\n const descMatch = content.match(/<desc>([^<]*)<\\/desc>/i);\n const description = descMatch?.[1];\n\n // Generate normalized name and component name\n const name = normalizeIconName(fileName);\n const componentName = toComponentName(fileName);\n\n return {\n name,\n componentName,\n fileName,\n viewBox,\n width: attributes['width'],\n height: attributes['height'],\n innerContent,\n fullContent: content,\n attributes,\n title,\n description,\n };\n}\n\n/**\n * Parse multiple SVG files\n *\n * @param rawFiles - Array of raw SVG data\n * @returns Array of parsed SVG data\n */\nexport function parseSVGFiles(rawFiles: RawSVGData[]): ParsedSVG[] {\n return rawFiles.map(parseSVG);\n}\n\n/**\n * Clean SVG content for React compatibility\n *\n * Converts kebab-case attributes to camelCase for JSX.\n *\n * @param svg - SVG content string\n * @returns Cleaned SVG content\n */\nexport function cleanSVGForReact(svg: string): string {\n return (\n svg\n // Convert kebab-case attributes to camelCase for React\n .replace(\n /(stroke|fill|line|clip|stop|color|font|text|letter|word|alignment|dominant|glyph|horiz|overline|paint|pointer|shape|strikethrough|underline|unicode|units|vert|writing)-([a-z])/g,\n (_, p1, p2) => p1 + p2.toUpperCase()\n )\n // Convert specific attributes\n .replace(/class=\"/g, 'className=\"')\n .replace(/xlink:href/g, 'xlinkHref')\n .replace(/xmlns:xlink/g, 'xmlnsXlink')\n // Use currentColor for strokes and fills (inherits from CSS)\n .replace(/stroke=\"#[^\"]+\"/g, 'stroke=\"currentColor\"')\n .replace(/fill=\"#[^\"]+\"/g, 'fill=\"currentColor\"')\n // Handle fill=\"none\" (keep as-is, common for stroke-only icons)\n .replace(/fill=\"currentColor\"([^>]*stroke)/g, 'fill=\"none\"$1')\n );\n}\n\n/**\n * Extract viewBox from SVG string\n *\n * @param svg - SVG content string\n * @returns ViewBox string or default\n */\nexport function extractViewBox(svg: string): string {\n const match = svg.match(/viewBox=\"([^\"]+)\"/);\n return match?.[1] ?? '0 0 24 24';\n}\n","/**\n * Core icon processing exports\n *\n * @packageDocumentation\n */\n\nexport { readSVGFile, scanSVGFiles } from './scanner.js';\nexport { cleanSVGForReact, extractViewBox, parseSVG, parseSVGFiles } from './parser.js';\nexport {\n defaultSVGOConfig,\n optimizeSVG,\n optimizeSVGFiles,\n skipOptimization,\n} from './optimizer.js';\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * React component generator\n *\n * Generates React icon components from optimized SVG data.\n *\n * @packageDocumentation\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { cleanSVGForReact } from '../core/parser.js';\n\nimport type {\n GeneratedIcon,\n GeneratorOptions,\n IconTemplate,\n IndexTemplate,\n OptimizedSVG,\n TypesTemplate,\n} from '../types.js';\n\n/**\n * Default React icon template\n *\n * Generates a forwardRef component with size, title, and aria support.\n */\nexport const defaultReactTemplate: IconTemplate = (icon) => {\n const cleanedContent = cleanSVGForReact(icon.innerContent);\n\n return `/**\n * ${icon.componentName} icon\n *\n * @generated by @dsai-io/tools\n */\n\nimport * as React from 'react';\n\nimport type { SVGProps } from 'react';\n\nexport interface ${icon.componentName}Props extends SVGProps<SVGSVGElement> {\n /** Icon size */\n size?: number | string;\n /** Icon title for accessibility */\n title?: string;\n}\n\nexport const ${icon.componentName} = React.forwardRef<SVGSVGElement, ${icon.componentName}Props>(\n ({ size = 24, title${icon.title ? ` = \"${icon.title}\"` : ''}, ...props }, ref) => (\n <svg\n ref={ref}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"${icon.viewBox}\"\n width={size}\n height={size}\n fill=\"currentColor\"\n role={title ? 'img' : 'presentation'}\n aria-label={title}\n {...props}\n >\n {title && <title>{title}</title>}\n ${cleanedContent}\n </svg>\n )\n);\n\n${icon.componentName}.displayName = '${icon.componentName}';\n\nexport default ${icon.componentName};\n`;\n};\n\n/**\n * Default React index template\n *\n * Exports all icon components from a single entry point.\n */\nexport const defaultReactIndexTemplate: IndexTemplate = (icons) => `/**\n * Icon exports\n *\n * @generated by @dsai-io/tools\n */\n\n${icons.map((icon) => `export { ${icon.componentName} } from './${icon.componentName}.js';`).join('\\n')}\n\n// Re-export types\nexport type { SVGProps } from 'react';\n`;\n\n/**\n * Default React types template\n *\n * Generates TypeScript types for all icons.\n */\nexport const defaultReactTypesTemplate: TypesTemplate = (icons) => `/**\n * Icon types\n *\n * @generated by @dsai-io/tools\n */\n\nimport type { ForwardRefExoticComponent, RefAttributes, SVGProps } from 'react';\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n title?: string;\n}\n\nexport type IconComponent = ForwardRefExoticComponent<\n IconProps & RefAttributes<SVGSVGElement>\n>;\n\n/**\n * Available icon names\n */\nexport type IconName =\n${icons.map((icon) => ` | '${icon.name}'`).join('\\n')};\n\n/**\n * Icon component map\n */\nexport interface IconMap {\n${icons.map((icon) => ` '${icon.name}': IconComponent;`).join('\\n')}\n}\n\n/**\n * Icon metadata\n */\nexport interface IconMeta {\n name: IconName;\n componentName: string;\n viewBox: string;\n}\n\nexport const iconMeta: IconMeta[] = [\n${icons.map((icon) => ` { name: '${icon.name}', componentName: '${icon.componentName}', viewBox: '${icon.viewBox}' },`).join('\\n')}\n];\n`;\n\n/**\n * Generate React icon components\n *\n * @param icons - Optimized SVG data\n * @param outputDir - Output directory\n * @param options - Generator options\n * @returns Generated icons\n *\n * @example\n * ```typescript\n * const generated = await generateReactIcons(optimizedIcons, './dist/icons/react', {\n * dryRun: false,\n * });\n * console.log(\\`Generated \\${generated.length} files\\`);\n * ```\n */\nexport async function generateReactIcons(\n icons: OptimizedSVG[],\n outputDir: string,\n options: GeneratorOptions = {}\n): Promise<GeneratedIcon[]> {\n const {\n template = defaultReactTemplate,\n indexTemplate = defaultReactIndexTemplate,\n typesTemplate = defaultReactTypesTemplate,\n dryRun = false,\n } = options;\n\n const generated: GeneratedIcon[] = [];\n\n // Ensure output directory exists\n if (!dryRun && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Generate individual icon components\n for (const icon of icons) {\n const code = template(icon);\n const outputPath = join(outputDir, `${icon.componentName}.tsx`);\n\n if (!dryRun) {\n writeFileSync(outputPath, code, 'utf-8');\n }\n\n generated.push({\n name: icon.name,\n componentName: icon.componentName,\n code,\n outputPath,\n format: 'react',\n });\n }\n\n // Generate index file\n const indexCode = indexTemplate(icons);\n const indexPath = join(outputDir, 'index.ts');\n\n if (!dryRun) {\n writeFileSync(indexPath, indexCode, 'utf-8');\n }\n\n generated.push({\n name: 'index',\n componentName: 'index',\n code: indexCode,\n outputPath: indexPath,\n format: 'react',\n });\n\n // Generate types file\n const typesCode = typesTemplate(icons);\n const typesPath = join(outputDir, 'types.ts');\n\n if (!dryRun) {\n writeFileSync(typesPath, typesCode, 'utf-8');\n }\n\n generated.push({\n name: 'types',\n componentName: 'types',\n code: typesCode,\n outputPath: typesPath,\n format: 'react',\n });\n\n return generated;\n}\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * SVG sprite generator\n *\n * Generates SVG sprite files with symbol definitions.\n *\n * @packageDocumentation\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { GeneratedIcon, OptimizedSVG } from '../types.js';\n\n/**\n * SVG sprite generator options\n */\nexport interface SpriteOptions {\n /** Sprite file name */\n fileName?: string;\n\n /** Generate preview HTML file */\n generatePreview?: boolean;\n\n /** Dry run - don't write files */\n dryRun?: boolean;\n}\n\n/**\n * Generate SVG sprite\n *\n * Creates an SVG sprite with symbol definitions for all icons.\n *\n * @param icons - Optimized SVG data\n * @param outputDir - Output directory\n * @param options - Generator options\n * @returns Generated files\n *\n * @example\n * ```typescript\n * const generated = await generateSVGSprite(optimizedIcons, './dist/icons/sprite', {\n * fileName: 'icons.svg',\n * generatePreview: true,\n * });\n * ```\n */\nexport async function generateSVGSprite(\n icons: OptimizedSVG[],\n outputDir: string,\n options: SpriteOptions = {}\n): Promise<GeneratedIcon[]> {\n const { fileName = 'sprite.svg', generatePreview = true, dryRun = false } = options;\n\n const generated: GeneratedIcon[] = [];\n\n // Ensure output directory exists\n if (!dryRun && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Generate sprite symbols\n const symbols = icons\n .map(\n (icon) => ` <symbol id=\"${icon.name}\" viewBox=\"${icon.viewBox}\">\n ${icon.innerContent}\n </symbol>`\n )\n .join('\\n');\n\n // Create sprite SVG\n const spriteCode = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n SVG Sprite\n @generated by @dsai-io/tools\n Contains ${icons.length} icons\n-->\n<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <defs>\n${symbols}\n </defs>\n</svg>\n`;\n\n const outputPath = join(outputDir, fileName);\n\n if (!dryRun) {\n writeFileSync(outputPath, spriteCode, 'utf-8');\n }\n\n generated.push({\n name: 'sprite',\n componentName: 'sprite',\n code: spriteCode,\n outputPath,\n format: 'svg-sprite',\n });\n\n // Generate usage helper HTML\n if (generatePreview) {\n const usageCode = generatePreviewHTML(icons, fileName);\n const usagePath = join(outputDir, 'sprite-preview.html');\n\n if (!dryRun) {\n writeFileSync(usagePath, usageCode, 'utf-8');\n }\n\n generated.push({\n name: 'preview',\n componentName: 'preview',\n code: usageCode,\n outputPath: usagePath,\n format: 'svg-sprite',\n });\n }\n\n return generated;\n}\n\n/**\n * Generate preview HTML for sprite\n */\nfunction generatePreviewHTML(icons: OptimizedSVG[], spriteFileName: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Icon Sprite Preview</title>\n <style>\n * { box-sizing: border-box; }\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 1200px; margin: 0 auto; }\n h1 { margin-bottom: 0.5rem; }\n .meta { color: #666; margin-bottom: 2rem; }\n .icon { width: 24px; height: 24px; fill: currentColor; }\n .icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 1rem; }\n .icon-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1rem; border: 1px solid #eee; border-radius: 8px; transition: background 0.2s; }\n .icon-item:hover { background: #f5f5f5; }\n .icon-name { font-size: 11px; color: #666; text-align: center; word-break: break-all; }\n pre { background: #f5f5f5; padding: 1rem; border-radius: 8px; overflow-x: auto; }\n code { font-family: ui-monospace, monospace; font-size: 13px; }\n </style>\n</head>\n<body>\n <h1>Icon Sprite Preview</h1>\n <p class=\"meta\">${icons.length} icons • Generated by @dsai-io/tools</p>\n\n <h2>Usage</h2>\n <pre><code>&lt;svg class=\"icon\"&gt;\n &lt;use href=\"${spriteFileName}#icon-name\"&gt;&lt;/use&gt;\n&lt;/svg&gt;</code></pre>\n\n <h2>All Icons</h2>\n <div class=\"icon-grid\">\n${icons\n .map(\n (icon) => ` <div class=\"icon-item\">\n <svg class=\"icon\"><use href=\"${spriteFileName}#${icon.name}\"></use></svg>\n <span class=\"icon-name\">${icon.name}</span>\n </div>`\n )\n .join('\\n')}\n </div>\n</body>\n</html>\n`;\n}\n","/**\n * Icon tooling module for @dsai-io/tools\n *\n * Provides utilities for generating icon components from SVG source files.\n * Supports React components, SVG sprites, with SVGO optimization.\n *\n * @packageDocumentation\n */\n\nimport { join } from 'node:path';\n\nimport { optimizeSVGFiles, parseSVGFiles, scanSVGFiles } from './core/index.js';\nimport { generateReactIcons } from './generators/react.js';\nimport { generateSVGSprite } from './generators/svg-sprite.js';\n\nimport type {\n GeneratedIcon,\n IconBuildOptions,\n IconBuildResult,\n IconFormat,\n OptimizedSVG,\n SVGOConfig,\n} from './types.js';\nimport type { ResolvedConfig } from '../config/types.js';\n\n/**\n * Build icons from SVG source files\n *\n * Scans the source directory, parses and optimizes SVGs, then generates\n * output in the specified formats (React, SVG sprite).\n *\n * @param config - Resolved DSAi configuration\n * @param options - Build options\n * @returns Build result with generated files\n *\n * @example\n * ```typescript\n * import { loadConfig } from '@dsai-io/tools/config';\n * import { buildIcons } from '@dsai-io/tools/icons';\n *\n * const { config } = await loadConfig();\n * const result = await buildIcons(config, {\n * formats: ['react', 'svg-sprite'],\n * });\n *\n * console.log(\\`Generated \\${result.totalIcons} icons\\`);\n * ```\n */\nexport async function buildIcons(\n config: ResolvedConfig,\n options: IconBuildOptions = {}\n): Promise<IconBuildResult> {\n const startTime = Date.now();\n const defaultFormat = config.icons.framework === 'react' ? 'react' : 'svg-sprite';\n const { formats = [defaultFormat as IconFormat], icons: iconFilter, dryRun = false } = options;\n\n const result: IconBuildResult = {\n success: false,\n icons: [],\n totalIcons: 0,\n filesWritten: 0,\n totalSizeReduction: 0,\n errors: [],\n warnings: [],\n duration: 0,\n };\n\n try {\n // Step 1: Scan for SVG files\n const rawFiles = await scanSVGFiles({\n sourceDir: config.icons.sourceDir,\n });\n\n if (rawFiles.length === 0) {\n result.warnings.push({\n icon: '*',\n message: `No SVG files found in ${config.icons.sourceDir}`,\n });\n result.success = true;\n result.duration = Date.now() - startTime;\n return result;\n }\n\n // Filter by specific icons if provided\n const filteredFiles = iconFilter\n ? rawFiles.filter((f) => iconFilter.includes(f.fileName))\n : rawFiles;\n\n // Step 2: Parse SVG content\n const parsedFiles = parseSVGFiles(filteredFiles);\n\n // Step 3: Optimize SVGs (if enabled)\n let optimizedFiles: OptimizedSVG[];\n if (config.icons.optimize) {\n const svgoConfig: SVGOConfig = {\n multipass: true,\n };\n optimizedFiles = await optimizeSVGFiles(parsedFiles, filteredFiles, svgoConfig);\n\n // Calculate total size reduction\n const totalReduction = optimizedFiles.reduce((sum, f) => sum + f.sizeReduction, 0);\n result.totalSizeReduction =\n optimizedFiles.length > 0 ? totalReduction / optimizedFiles.length : 0;\n } else {\n // Skip optimization - just add size metadata\n const { skipOptimization } = await import('./core/optimizer.js');\n optimizedFiles = parsedFiles.map((parsed, index) => {\n const rawFile = filteredFiles.at(index);\n if (!rawFile) {\n throw new Error(`Missing raw file for ${parsed.fileName}`);\n }\n return skipOptimization(parsed, rawFile);\n });\n }\n\n result.totalIcons = optimizedFiles.length;\n\n // Step 4: Generate output for each format\n const generated: GeneratedIcon[] = [];\n\n for (const format of formats) {\n const outputDir = join(config.icons.outputDir, format);\n\n switch (format) {\n case 'react':\n generated.push(...(await generateReactIcons(optimizedFiles, outputDir, { dryRun })));\n break;\n\n case 'svg':\n case 'svg-sprite':\n generated.push(...(await generateSVGSprite(optimizedFiles, outputDir, { dryRun })));\n break;\n\n default:\n result.warnings.push({\n icon: '*',\n message: `Unknown format: ${format}`,\n });\n }\n }\n\n result.icons = generated;\n result.filesWritten = dryRun ? 0 : generated.length;\n result.success = true;\n } catch (error) {\n result.errors.push({\n icon: '*',\n message: error instanceof Error ? error.message : 'Unknown error',\n code: 'BUILD_ERROR',\n });\n }\n\n result.duration = Date.now() - startTime;\n return result;\n}\n\n// Re-export types\nexport type {\n GeneratedIcon,\n GeneratorOptions,\n IconBuildOptions,\n IconBuildResult,\n IconError,\n IconErrorCode,\n IconFormat,\n IconTemplate,\n IconWarning,\n IndexTemplate,\n OptimizedSVG,\n ParsedSVG,\n RawSVGData,\n ScannerOptions,\n SVGOConfig,\n SVGOPlugin,\n TypesTemplate,\n} from './types.js';\n\n// Re-export core utilities\nexport {\n cleanSVGForReact,\n defaultSVGOConfig,\n extractViewBox,\n optimizeSVG,\n optimizeSVGFiles,\n parseSVG,\n parseSVGFiles,\n readSVGFile,\n scanSVGFiles,\n skipOptimization,\n} from './core/index.js';\n\n// Re-export generators\nexport {\n defaultReactIndexTemplate,\n defaultReactTemplate,\n defaultReactTypesTemplate,\n generateReactIcons,\n generateSVGSprite,\n} from './generators/index.js';\n\n// Re-export naming utilities\nexport {\n isValidIconName,\n normalizeIconName,\n toComponentName,\n toIconName,\n} from './utils/index.js';\n"]}
1
+ {"version":3,"sources":["../../src/icons/core/optimizer.ts","../../src/icons/core/scanner.ts","../../src/icons/utils/naming.ts","../../src/icons/core/parser.ts","../../src/icons/core/index.ts","../../src/icons/generators/react.ts","../../src/icons/generators/svg-sprite.ts","../../src/icons/index.ts"],"names":["defaultSVGOConfig","readFileSync","statSync","basename","existsSync","mkdirSync","join","writeFileSync","skipOptimization"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * SVG optimizer (SVGO integration)\r\n *\r\n * Optimizes SVG files using SVGO for smaller file sizes.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport type { OptimizedSVG, ParsedSVG, RawSVGData, SVGOConfig } from '../types.js';\r\n\r\n/**\r\n * Default SVGO configuration\r\n *\r\n * Provides sensible defaults for icon optimization.\r\n */\r\nexport const defaultSVGOConfig: SVGOConfig = {\r\n multipass: true,\r\n plugins: [\r\n { name: 'preset-default' },\r\n { name: 'removeXMLNS' },\r\n { name: 'removeDimensions' },\r\n { name: 'removeStyleElement' },\r\n { name: 'removeScriptElement' },\r\n {\r\n name: 'removeAttrs',\r\n params: {\r\n attrs: ['class', 'style', 'data-name', 'xmlns:xlink'],\r\n },\r\n },\r\n {\r\n name: 'addAttributesToSVGElement',\r\n params: {\r\n attributes: [{ 'aria-hidden': 'true' }, { focusable: 'false' }],\r\n },\r\n },\r\n {\r\n name: 'sortAttrs',\r\n params: {\r\n xmlnsOrder: 'alphabetical',\r\n },\r\n },\r\n ],\r\n};\r\n\r\n/**\r\n * Optimize a single SVG\r\n *\r\n * @param parsed - Parsed SVG data\r\n * @param raw - Raw SVG data (for size comparison)\r\n * @param config - SVGO configuration\r\n * @returns Optimized SVG data\r\n */\r\nexport async function optimizeSVG(\r\n parsed: ParsedSVG,\r\n raw: RawSVGData,\r\n config: SVGOConfig = defaultSVGOConfig\r\n): Promise<OptimizedSVG> {\r\n // Dynamic import of SVGO\r\n const svgo = await import('svgo');\r\n\r\n // Merge plugins with defaults if provided\r\n const plugins = config.plugins ?? defaultSVGOConfig.plugins ?? [];\r\n\r\n // Convert our plugin format to SVGO's expected format\r\n const svgoPlugins = plugins.map((p) => ({\r\n name: p.name,\r\n ...(p.params ? { params: p.params } : {}),\r\n }));\r\n\r\n // Run SVGO optimization\r\n const result = svgo.optimize(raw.content, {\r\n multipass: config.multipass ?? true,\r\n plugins: svgoPlugins as NonNullable<Parameters<typeof svgo.optimize>[1]>['plugins'],\r\n });\r\n\r\n const optimizedContent = result.data;\r\n const optimizedSize = Buffer.byteLength(optimizedContent, 'utf-8');\r\n const sizeReduction =\r\n raw.originalSize > 0 ? ((raw.originalSize - optimizedSize) / raw.originalSize) * 100 : 0;\r\n\r\n // Re-parse optimized content to get updated inner content\r\n const innerContentMatch = optimizedContent.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\r\n const innerContent = innerContentMatch?.[1]?.trim() ?? parsed.innerContent;\r\n\r\n // Extract updated viewBox\r\n const viewBoxMatch = optimizedContent.match(/viewBox=[\"']([^\"']*)[\"']/i);\r\n const viewBox = viewBoxMatch?.[1] ?? parsed.viewBox;\r\n\r\n return {\r\n ...parsed,\r\n innerContent,\r\n fullContent: optimizedContent,\r\n viewBox,\r\n optimizedSize,\r\n sizeReduction,\r\n };\r\n}\r\n\r\n/**\r\n * Optimize multiple SVGs\r\n *\r\n * @param parsedFiles - Array of parsed SVG data\r\n * @param rawFiles - Array of raw SVG data\r\n * @param config - SVGO configuration\r\n * @returns Array of optimized SVG data\r\n */\r\nexport async function optimizeSVGFiles(\r\n parsedFiles: ParsedSVG[],\r\n rawFiles: RawSVGData[],\r\n config: SVGOConfig = defaultSVGOConfig\r\n): Promise<OptimizedSVG[]> {\r\n const results: OptimizedSVG[] = [];\r\n\r\n for (const parsed of parsedFiles) {\r\n const raw = rawFiles.find((r) => r.fileName === parsed.fileName);\r\n if (!raw) {\r\n throw new Error(`Raw file not found for ${parsed.fileName}`);\r\n }\r\n const optimized = await optimizeSVG(parsed, raw, config);\r\n results.push(optimized);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Skip optimization and just add size metadata\r\n *\r\n * Useful when SVGO is not needed but the type structure is required.\r\n *\r\n * @param parsed - Parsed SVG data\r\n * @param raw - Raw SVG data\r\n * @returns Optimized SVG data (without actual optimization)\r\n */\r\nexport function skipOptimization(parsed: ParsedSVG, raw: RawSVGData): OptimizedSVG {\r\n return {\r\n ...parsed,\r\n optimizedSize: raw.originalSize,\r\n sizeReduction: 0,\r\n };\r\n}\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * SVG file scanner\r\n *\r\n * Scans directories for SVG files and reads their contents.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { readFileSync, statSync } from 'node:fs';\r\nimport { basename } from 'node:path';\r\n\r\nimport type { RawSVGData, ScannerOptions } from '../types.js';\r\n\r\n/**\r\n * Scan directory for SVG files\r\n *\r\n * Uses fast-glob to find SVG files matching the specified patterns.\r\n *\r\n * @param options - Scanner options\r\n * @returns Array of raw SVG data\r\n *\r\n * @example\r\n * ```typescript\r\n * const files = await scanSVGFiles({\r\n * sourceDir: './icons',\r\n * include: ['**\\/*.svg'],\r\n * exclude: ['**\\/node_modules\\/**'],\r\n * });\r\n * ```\r\n */\r\nexport async function scanSVGFiles(options: ScannerOptions): Promise<RawSVGData[]> {\r\n const {\r\n sourceDir,\r\n include = ['**/*.svg'],\r\n exclude = ['**/node_modules/**', '**/dist/**'],\r\n } = options;\r\n\r\n // Dynamic import of fast-glob (ESM module)\r\n const { default: fg } = await import('fast-glob');\r\n\r\n // Find all SVG files\r\n const files = await fg(include, {\r\n cwd: sourceDir,\r\n ignore: exclude,\r\n absolute: true,\r\n onlyFiles: true,\r\n });\r\n\r\n // Read each file\r\n const svgFiles: RawSVGData[] = [];\r\n\r\n for (const filePath of files) {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8');\r\n const stats = statSync(filePath);\r\n\r\n // Extract file name without extension\r\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\r\n\r\n svgFiles.push({\r\n filePath,\r\n fileName,\r\n content,\r\n originalSize: stats.size,\r\n });\r\n } catch {\r\n console.warn(`Warning: Failed to read ${filePath}`);\r\n }\r\n }\r\n\r\n // Sort by name for consistent output\r\n svgFiles.sort((a, b) => a.fileName.localeCompare(b.fileName));\r\n\r\n return svgFiles;\r\n}\r\n\r\n/**\r\n * Read a single SVG file\r\n *\r\n * @param filePath - Path to SVG file\r\n * @returns Raw SVG data or null if failed\r\n */\r\nexport function readSVGFile(filePath: string): RawSVGData | null {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8');\r\n const stats = statSync(filePath);\r\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\r\n\r\n return {\r\n filePath,\r\n fileName,\r\n content,\r\n originalSize: stats.size,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Icon naming utilities\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n/**\r\n * Convert string to PascalCase component name\r\n *\r\n * @param input - Input string (e.g., file name)\r\n * @returns PascalCase component name\r\n *\r\n * @example\r\n * ```typescript\r\n * toComponentName('arrow-left') // 'ArrowLeft'\r\n * toComponentName('24px-icon') // 'Icon24px'\r\n * toComponentName('my_icon') // 'MyIcon'\r\n * toComponentName('chevron-down-small') // 'ChevronDownSmall'\r\n * ```\r\n */\r\nexport function toComponentName(input: string): string {\r\n // Handle numbers at start by prefixing with 'Icon'\r\n let processed = input;\r\n if (/^\\d/.test(processed)) {\r\n processed = `icon-${processed}`;\r\n }\r\n\r\n return (\r\n processed\r\n // Split on non-alphanumeric characters\r\n .split(/[^a-zA-Z0-9]+/)\r\n // Filter empty strings\r\n .filter((word) => word.length > 0)\r\n // Capitalize each word\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n // Join into single string\r\n .join('')\r\n );\r\n}\r\n\r\n/**\r\n * Convert string to kebab-case icon name\r\n *\r\n * @param input - Input string (e.g., component name)\r\n * @returns kebab-case icon name\r\n *\r\n * @example\r\n * ```typescript\r\n * toIconName('ArrowLeft') // 'arrow-left'\r\n * toIconName('ChevronDownSmall') // 'chevron-down-small'\r\n * toIconName('Icon24px') // 'icon-24px'\r\n * ```\r\n */\r\nexport function toIconName(input: string): string {\r\n return (\r\n input\r\n // Insert hyphen before uppercase letters\r\n .replace(/([A-Z])/g, '-$1')\r\n // Insert hyphen before number sequences\r\n .replace(/(\\d+)/g, '-$1')\r\n // Clean up multiple hyphens\r\n .replace(/-+/g, '-')\r\n // Remove leading hyphen\r\n .replace(/^-/, '')\r\n // Lowercase\r\n .toLowerCase()\r\n );\r\n}\r\n\r\n/**\r\n * Validate icon name\r\n *\r\n * @param name - Icon name to validate\r\n * @returns True if valid, false otherwise\r\n */\r\nexport function isValidIconName(name: string): boolean {\r\n // Must be non-empty\r\n if (!name || name.length === 0) {\r\n return false;\r\n }\r\n\r\n // Must be valid identifier-like (alphanumeric, hyphens, underscores)\r\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Normalize icon name from file name\r\n *\r\n * @param fileName - File name (without extension)\r\n * @returns Normalized icon name\r\n */\r\nexport function normalizeIconName(fileName: string): string {\r\n return fileName\r\n .replace(/[^a-zA-Z0-9]+/g, '-')\r\n .replace(/^-+|-+$/g, '')\r\n .toLowerCase();\r\n}\r\n","/**\r\n * SVG parser\r\n *\r\n * Parses SVG content into structured data.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { normalizeIconName, toComponentName } from '../utils/naming.js';\r\n\r\nimport type { ParsedSVG, RawSVGData } from '../types.js';\r\n\r\n/**\r\n * Parse raw SVG data into structured format\r\n *\r\n * Extracts viewBox, attributes, inner content, and accessibility info.\r\n *\r\n * @param raw - Raw SVG data\r\n * @returns Parsed SVG data\r\n */\r\nexport function parseSVG(raw: RawSVGData): ParsedSVG {\r\n const { content, fileName } = raw;\r\n\r\n // Extract SVG opening tag attributes\r\n const svgMatch = content.match(/<svg([^>]*)>/i);\r\n const svgAttributes = svgMatch?.[1] ?? '';\r\n\r\n // Parse attributes into object\r\n const attributes: Record<string, string> = {};\r\n const attrRegex = /([a-zA-Z][a-zA-Z0-9-]*)=[\"']([^\"']*)[\"']/g;\r\n\r\n for (const attrMatch of svgAttributes.matchAll(attrRegex)) {\r\n const key = attrMatch[1];\r\n const value = attrMatch[2];\r\n if (key && value !== undefined) {\r\n Object.assign(attributes, { [key]: value });\r\n }\r\n }\r\n\r\n // Extract viewBox (or construct from width/height)\r\n let viewBox = attributes['viewBox'] ?? '';\r\n if (!viewBox) {\r\n const width = attributes['width']?.replace(/[^\\d.]/g, '') ?? '24';\r\n const height = attributes['height']?.replace(/[^\\d.]/g, '') ?? '24';\r\n viewBox = `0 0 ${width} ${height}`;\r\n }\r\n\r\n // Extract inner content (everything between <svg> and </svg>)\r\n const innerContentMatch = content.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\r\n const innerContent = innerContentMatch?.[1]?.trim() ?? '';\r\n\r\n // Extract title for accessibility\r\n const titleMatch = content.match(/<title>([^<]*)<\\/title>/i);\r\n const title = titleMatch?.[1];\r\n\r\n // Extract description for accessibility\r\n const descMatch = content.match(/<desc>([^<]*)<\\/desc>/i);\r\n const description = descMatch?.[1];\r\n\r\n // Generate normalized name and component name\r\n const name = normalizeIconName(fileName);\r\n const componentName = toComponentName(fileName);\r\n\r\n return {\r\n name,\r\n componentName,\r\n fileName,\r\n viewBox,\r\n width: attributes['width'],\r\n height: attributes['height'],\r\n innerContent,\r\n fullContent: content,\r\n attributes,\r\n title,\r\n description,\r\n };\r\n}\r\n\r\n/**\r\n * Parse multiple SVG files\r\n *\r\n * @param rawFiles - Array of raw SVG data\r\n * @returns Array of parsed SVG data\r\n */\r\nexport function parseSVGFiles(rawFiles: RawSVGData[]): ParsedSVG[] {\r\n return rawFiles.map(parseSVG);\r\n}\r\n\r\n/**\r\n * Clean SVG content for React compatibility\r\n *\r\n * Converts kebab-case attributes to camelCase for JSX.\r\n *\r\n * @param svg - SVG content string\r\n * @returns Cleaned SVG content\r\n */\r\nexport function cleanSVGForReact(svg: string): string {\r\n return (\r\n svg\r\n // Convert kebab-case attributes to camelCase for React\r\n .replace(\r\n /(stroke|fill|line|clip|stop|color|font|text|letter|word|alignment|dominant|glyph|horiz|overline|paint|pointer|shape|strikethrough|underline|unicode|units|vert|writing)-([a-z])/g,\r\n (_, p1, p2) => p1 + p2.toUpperCase()\r\n )\r\n // Convert specific attributes\r\n .replace(/class=\"/g, 'className=\"')\r\n .replace(/xlink:href/g, 'xlinkHref')\r\n .replace(/xmlns:xlink/g, 'xmlnsXlink')\r\n // Use currentColor for strokes and fills (inherits from CSS)\r\n .replace(/stroke=\"#[^\"]+\"/g, 'stroke=\"currentColor\"')\r\n .replace(/fill=\"#[^\"]+\"/g, 'fill=\"currentColor\"')\r\n // Handle fill=\"none\" (keep as-is, common for stroke-only icons)\r\n .replace(/fill=\"currentColor\"([^>]*stroke)/g, 'fill=\"none\"$1')\r\n );\r\n}\r\n\r\n/**\r\n * Extract viewBox from SVG string\r\n *\r\n * @param svg - SVG content string\r\n * @returns ViewBox string or default\r\n */\r\nexport function extractViewBox(svg: string): string {\r\n const match = svg.match(/viewBox=\"([^\"]+)\"/);\r\n return match?.[1] ?? '0 0 24 24';\r\n}\r\n","/**\r\n * Core icon processing exports\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nexport { readSVGFile, scanSVGFiles } from './scanner.js';\r\nexport { cleanSVGForReact, extractViewBox, parseSVG, parseSVGFiles } from './parser.js';\r\nexport {\r\n defaultSVGOConfig,\r\n optimizeSVG,\r\n optimizeSVGFiles,\r\n skipOptimization,\r\n} from './optimizer.js';\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * React component generator\r\n *\r\n * Generates React icon components from optimized SVG data.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\n\r\nimport { cleanSVGForReact } from '../core/parser.js';\r\n\r\nimport type {\r\n GeneratedIcon,\r\n GeneratorOptions,\r\n IconTemplate,\r\n IndexTemplate,\r\n OptimizedSVG,\r\n TypesTemplate,\r\n} from '../types.js';\r\n\r\n/**\r\n * Default React icon template\r\n *\r\n * Generates a forwardRef component with size, title, and aria support.\r\n */\r\nexport const defaultReactTemplate: IconTemplate = (icon) => {\r\n const cleanedContent = cleanSVGForReact(icon.innerContent);\r\n\r\n return `/**\r\n * ${icon.componentName} icon\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\nimport * as React from 'react';\r\n\r\nimport type { SVGProps } from 'react';\r\n\r\nexport interface ${icon.componentName}Props extends SVGProps<SVGSVGElement> {\r\n /** Icon size */\r\n size?: number | string;\r\n /** Icon title for accessibility */\r\n title?: string;\r\n}\r\n\r\nexport const ${icon.componentName} = React.forwardRef<SVGSVGElement, ${icon.componentName}Props>(\r\n ({ size = 24, title${icon.title ? ` = \"${icon.title}\"` : ''}, ...props }, ref) => (\r\n <svg\r\n ref={ref}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"${icon.viewBox}\"\r\n width={size}\r\n height={size}\r\n fill=\"currentColor\"\r\n role={title ? 'img' : 'presentation'}\r\n aria-label={title}\r\n {...props}\r\n >\r\n {title && <title>{title}</title>}\r\n ${cleanedContent}\r\n </svg>\r\n )\r\n);\r\n\r\n${icon.componentName}.displayName = '${icon.componentName}';\r\n\r\nexport default ${icon.componentName};\r\n`;\r\n};\r\n\r\n/**\r\n * Default React index template\r\n *\r\n * Exports all icon components from a single entry point.\r\n */\r\nexport const defaultReactIndexTemplate: IndexTemplate = (icons) => `/**\r\n * Icon exports\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\n${icons.map((icon) => `export { ${icon.componentName} } from './${icon.componentName}.js';`).join('\\n')}\r\n\r\n// Re-export types\r\nexport type { SVGProps } from 'react';\r\n`;\r\n\r\n/**\r\n * Default React types template\r\n *\r\n * Generates TypeScript types for all icons.\r\n */\r\nexport const defaultReactTypesTemplate: TypesTemplate = (icons) => `/**\r\n * Icon types\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\nimport type { ForwardRefExoticComponent, RefAttributes, SVGProps } from 'react';\r\n\r\nexport interface IconProps extends SVGProps<SVGSVGElement> {\r\n size?: number | string;\r\n title?: string;\r\n}\r\n\r\nexport type IconComponent = ForwardRefExoticComponent<\r\n IconProps & RefAttributes<SVGSVGElement>\r\n>;\r\n\r\n/**\r\n * Available icon names\r\n */\r\nexport type IconName =\r\n${icons.map((icon) => ` | '${icon.name}'`).join('\\n')};\r\n\r\n/**\r\n * Icon component map\r\n */\r\nexport interface IconMap {\r\n${icons.map((icon) => ` '${icon.name}': IconComponent;`).join('\\n')}\r\n}\r\n\r\n/**\r\n * Icon metadata\r\n */\r\nexport interface IconMeta {\r\n name: IconName;\r\n componentName: string;\r\n viewBox: string;\r\n}\r\n\r\nexport const iconMeta: IconMeta[] = [\r\n${icons.map((icon) => ` { name: '${icon.name}', componentName: '${icon.componentName}', viewBox: '${icon.viewBox}' },`).join('\\n')}\r\n];\r\n`;\r\n\r\n/**\r\n * Generate React icon components\r\n *\r\n * @param icons - Optimized SVG data\r\n * @param outputDir - Output directory\r\n * @param options - Generator options\r\n * @returns Generated icons\r\n *\r\n * @example\r\n * ```typescript\r\n * const generated = await generateReactIcons(optimizedIcons, './dist/icons/react', {\r\n * dryRun: false,\r\n * });\r\n * console.log(\\`Generated \\${generated.length} files\\`);\r\n * ```\r\n */\r\nexport async function generateReactIcons(\r\n icons: OptimizedSVG[],\r\n outputDir: string,\r\n options: GeneratorOptions = {}\r\n): Promise<GeneratedIcon[]> {\r\n const {\r\n template = defaultReactTemplate,\r\n indexTemplate = defaultReactIndexTemplate,\r\n typesTemplate = defaultReactTypesTemplate,\r\n dryRun = false,\r\n } = options;\r\n\r\n const generated: GeneratedIcon[] = [];\r\n\r\n // Ensure output directory exists\r\n if (!dryRun && !existsSync(outputDir)) {\r\n mkdirSync(outputDir, { recursive: true });\r\n }\r\n\r\n // Generate individual icon components\r\n for (const icon of icons) {\r\n const code = template(icon);\r\n const outputPath = join(outputDir, `${icon.componentName}.tsx`);\r\n\r\n if (!dryRun) {\r\n writeFileSync(outputPath, code, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: icon.name,\r\n componentName: icon.componentName,\r\n code,\r\n outputPath,\r\n format: 'react',\r\n });\r\n }\r\n\r\n // Generate index file\r\n const indexCode = indexTemplate(icons);\r\n const indexPath = join(outputDir, 'index.ts');\r\n\r\n if (!dryRun) {\r\n writeFileSync(indexPath, indexCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'index',\r\n componentName: 'index',\r\n code: indexCode,\r\n outputPath: indexPath,\r\n format: 'react',\r\n });\r\n\r\n // Generate types file\r\n const typesCode = typesTemplate(icons);\r\n const typesPath = join(outputDir, 'types.ts');\r\n\r\n if (!dryRun) {\r\n writeFileSync(typesPath, typesCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'types',\r\n componentName: 'types',\r\n code: typesCode,\r\n outputPath: typesPath,\r\n format: 'react',\r\n });\r\n\r\n return generated;\r\n}\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * SVG sprite generator\r\n *\r\n * Generates SVG sprite files with symbol definitions.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\n\r\nimport type { GeneratedIcon, OptimizedSVG } from '../types.js';\r\n\r\n/**\r\n * SVG sprite generator options\r\n */\r\nexport interface SpriteOptions {\r\n /** Sprite file name */\r\n fileName?: string;\r\n\r\n /** Generate preview HTML file */\r\n generatePreview?: boolean;\r\n\r\n /** Dry run - don't write files */\r\n dryRun?: boolean;\r\n}\r\n\r\n/**\r\n * Generate SVG sprite\r\n *\r\n * Creates an SVG sprite with symbol definitions for all icons.\r\n *\r\n * @param icons - Optimized SVG data\r\n * @param outputDir - Output directory\r\n * @param options - Generator options\r\n * @returns Generated files\r\n *\r\n * @example\r\n * ```typescript\r\n * const generated = await generateSVGSprite(optimizedIcons, './dist/icons/sprite', {\r\n * fileName: 'icons.svg',\r\n * generatePreview: true,\r\n * });\r\n * ```\r\n */\r\nexport async function generateSVGSprite(\r\n icons: OptimizedSVG[],\r\n outputDir: string,\r\n options: SpriteOptions = {}\r\n): Promise<GeneratedIcon[]> {\r\n const { fileName = 'sprite.svg', generatePreview = true, dryRun = false } = options;\r\n\r\n const generated: GeneratedIcon[] = [];\r\n\r\n // Ensure output directory exists\r\n if (!dryRun && !existsSync(outputDir)) {\r\n mkdirSync(outputDir, { recursive: true });\r\n }\r\n\r\n // Generate sprite symbols\r\n const symbols = icons\r\n .map(\r\n (icon) => ` <symbol id=\"${icon.name}\" viewBox=\"${icon.viewBox}\">\r\n ${icon.innerContent}\r\n </symbol>`\r\n )\r\n .join('\\n');\r\n\r\n // Create sprite SVG\r\n const spriteCode = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!--\r\n SVG Sprite\r\n @generated by @dsai-io/tools\r\n Contains ${icons.length} icons\r\n-->\r\n<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n <defs>\r\n${symbols}\r\n </defs>\r\n</svg>\r\n`;\r\n\r\n const outputPath = join(outputDir, fileName);\r\n\r\n if (!dryRun) {\r\n writeFileSync(outputPath, spriteCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'sprite',\r\n componentName: 'sprite',\r\n code: spriteCode,\r\n outputPath,\r\n format: 'svg-sprite',\r\n });\r\n\r\n // Generate usage helper HTML\r\n if (generatePreview) {\r\n const usageCode = generatePreviewHTML(icons, fileName);\r\n const usagePath = join(outputDir, 'sprite-preview.html');\r\n\r\n if (!dryRun) {\r\n writeFileSync(usagePath, usageCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'preview',\r\n componentName: 'preview',\r\n code: usageCode,\r\n outputPath: usagePath,\r\n format: 'svg-sprite',\r\n });\r\n }\r\n\r\n return generated;\r\n}\r\n\r\n/**\r\n * Generate preview HTML for sprite\r\n */\r\nfunction generatePreviewHTML(icons: OptimizedSVG[], spriteFileName: string): string {\r\n return `<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>Icon Sprite Preview</title>\r\n <style>\r\n * { box-sizing: border-box; }\r\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 1200px; margin: 0 auto; }\r\n h1 { margin-bottom: 0.5rem; }\r\n .meta { color: #666; margin-bottom: 2rem; }\r\n .icon { width: 24px; height: 24px; fill: currentColor; }\r\n .icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 1rem; }\r\n .icon-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1rem; border: 1px solid #eee; border-radius: 8px; transition: background 0.2s; }\r\n .icon-item:hover { background: #f5f5f5; }\r\n .icon-name { font-size: 11px; color: #666; text-align: center; word-break: break-all; }\r\n pre { background: #f5f5f5; padding: 1rem; border-radius: 8px; overflow-x: auto; }\r\n code { font-family: ui-monospace, monospace; font-size: 13px; }\r\n </style>\r\n</head>\r\n<body>\r\n <h1>Icon Sprite Preview</h1>\r\n <p class=\"meta\">${icons.length} icons • Generated by @dsai-io/tools</p>\r\n\r\n <h2>Usage</h2>\r\n <pre><code>&lt;svg class=\"icon\"&gt;\r\n &lt;use href=\"${spriteFileName}#icon-name\"&gt;&lt;/use&gt;\r\n&lt;/svg&gt;</code></pre>\r\n\r\n <h2>All Icons</h2>\r\n <div class=\"icon-grid\">\r\n${icons\r\n .map(\r\n (icon) => ` <div class=\"icon-item\">\r\n <svg class=\"icon\"><use href=\"${spriteFileName}#${icon.name}\"></use></svg>\r\n <span class=\"icon-name\">${icon.name}</span>\r\n </div>`\r\n )\r\n .join('\\n')}\r\n </div>\r\n</body>\r\n</html>\r\n`;\r\n}\r\n","/**\r\n * Icon tooling module for @dsai-io/tools\r\n *\r\n * Provides utilities for generating icon components from SVG source files.\r\n * Supports React components, SVG sprites, with SVGO optimization.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { join } from 'node:path';\r\n\r\nimport { optimizeSVGFiles, parseSVGFiles, scanSVGFiles } from './core/index.js';\r\nimport { generateReactIcons } from './generators/react.js';\r\nimport { generateSVGSprite } from './generators/svg-sprite.js';\r\n\r\nimport type {\r\n GeneratedIcon,\r\n IconBuildOptions,\r\n IconBuildResult,\r\n IconFormat,\r\n OptimizedSVG,\r\n SVGOConfig,\r\n} from './types.js';\r\nimport type { ResolvedConfig } from '../config/types.js';\r\n\r\n/**\r\n * Build icons from SVG source files\r\n *\r\n * Scans the source directory, parses and optimizes SVGs, then generates\r\n * output in the specified formats (React, SVG sprite).\r\n *\r\n * @param config - Resolved DSAi configuration\r\n * @param options - Build options\r\n * @returns Build result with generated files\r\n *\r\n * @example\r\n * ```typescript\r\n * import { loadConfig } from '@dsai-io/tools/config';\r\n * import { buildIcons } from '@dsai-io/tools/icons';\r\n *\r\n * const { config } = await loadConfig();\r\n * const result = await buildIcons(config, {\r\n * formats: ['react', 'svg-sprite'],\r\n * });\r\n *\r\n * console.log(\\`Generated \\${result.totalIcons} icons\\`);\r\n * ```\r\n */\r\nexport async function buildIcons(\r\n config: ResolvedConfig,\r\n options: IconBuildOptions = {}\r\n): Promise<IconBuildResult> {\r\n const startTime = Date.now();\r\n const defaultFormat = config.icons.framework === 'react' ? 'react' : 'svg-sprite';\r\n const { formats = [defaultFormat as IconFormat], icons: iconFilter, dryRun = false } = options;\r\n\r\n const result: IconBuildResult = {\r\n success: false,\r\n icons: [],\r\n totalIcons: 0,\r\n filesWritten: 0,\r\n totalSizeReduction: 0,\r\n errors: [],\r\n warnings: [],\r\n duration: 0,\r\n };\r\n\r\n try {\r\n // Step 1: Scan for SVG files\r\n const rawFiles = await scanSVGFiles({\r\n sourceDir: config.icons.sourceDir,\r\n });\r\n\r\n if (rawFiles.length === 0) {\r\n result.warnings.push({\r\n icon: '*',\r\n message: `No SVG files found in ${config.icons.sourceDir}`,\r\n });\r\n result.success = true;\r\n result.duration = Date.now() - startTime;\r\n return result;\r\n }\r\n\r\n // Filter by specific icons if provided\r\n const filteredFiles = iconFilter\r\n ? rawFiles.filter((f) => iconFilter.includes(f.fileName))\r\n : rawFiles;\r\n\r\n // Step 2: Parse SVG content\r\n const parsedFiles = parseSVGFiles(filteredFiles);\r\n\r\n // Step 3: Optimize SVGs (if enabled)\r\n let optimizedFiles: OptimizedSVG[];\r\n if (config.icons.optimize) {\r\n const svgoConfig: SVGOConfig = {\r\n multipass: true,\r\n };\r\n optimizedFiles = await optimizeSVGFiles(parsedFiles, filteredFiles, svgoConfig);\r\n\r\n // Calculate total size reduction\r\n const totalReduction = optimizedFiles.reduce((sum, f) => sum + f.sizeReduction, 0);\r\n result.totalSizeReduction =\r\n optimizedFiles.length > 0 ? totalReduction / optimizedFiles.length : 0;\r\n } else {\r\n // Skip optimization - just add size metadata\r\n const { skipOptimization } = await import('./core/optimizer.js');\r\n optimizedFiles = parsedFiles.map((parsed, index) => {\r\n const rawFile = filteredFiles.at(index);\r\n if (!rawFile) {\r\n throw new Error(`Missing raw file for ${parsed.fileName}`);\r\n }\r\n return skipOptimization(parsed, rawFile);\r\n });\r\n }\r\n\r\n result.totalIcons = optimizedFiles.length;\r\n\r\n // Step 4: Generate output for each format\r\n const generated: GeneratedIcon[] = [];\r\n\r\n for (const format of formats) {\r\n const outputDir = join(config.icons.outputDir, format);\r\n\r\n switch (format) {\r\n case 'react':\r\n generated.push(...(await generateReactIcons(optimizedFiles, outputDir, { dryRun })));\r\n break;\r\n\r\n case 'svg':\r\n case 'svg-sprite':\r\n generated.push(...(await generateSVGSprite(optimizedFiles, outputDir, { dryRun })));\r\n break;\r\n\r\n default:\r\n result.warnings.push({\r\n icon: '*',\r\n message: `Unknown format: ${format}`,\r\n });\r\n }\r\n }\r\n\r\n result.icons = generated;\r\n result.filesWritten = dryRun ? 0 : generated.length;\r\n result.success = true;\r\n } catch (error) {\r\n result.errors.push({\r\n icon: '*',\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n code: 'BUILD_ERROR',\r\n });\r\n }\r\n\r\n result.duration = Date.now() - startTime;\r\n return result;\r\n}\r\n\r\n// Re-export types\r\nexport type {\r\n GeneratedIcon,\r\n GeneratorOptions,\r\n IconBuildOptions,\r\n IconBuildResult,\r\n IconError,\r\n IconErrorCode,\r\n IconFormat,\r\n IconTemplate,\r\n IconWarning,\r\n IndexTemplate,\r\n OptimizedSVG,\r\n ParsedSVG,\r\n RawSVGData,\r\n ScannerOptions,\r\n SVGOConfig,\r\n SVGOPlugin,\r\n TypesTemplate,\r\n} from './types.js';\r\n\r\n// Re-export core utilities\r\nexport {\r\n cleanSVGForReact,\r\n defaultSVGOConfig,\r\n extractViewBox,\r\n optimizeSVG,\r\n optimizeSVGFiles,\r\n parseSVG,\r\n parseSVGFiles,\r\n readSVGFile,\r\n scanSVGFiles,\r\n skipOptimization,\r\n} from './core/index.js';\r\n\r\n// Re-export generators\r\nexport {\r\n defaultReactIndexTemplate,\r\n defaultReactTemplate,\r\n defaultReactTypesTemplate,\r\n generateReactIcons,\r\n generateSVGSprite,\r\n} from './generators/index.js';\r\n\r\n// Re-export naming utilities\r\nexport {\r\n isValidIconName,\r\n normalizeIconName,\r\n toComponentName,\r\n toIconName,\r\n} from './utils/index.js';\r\n"]}
@@ -1,4 +1,4 @@
1
- import { R as ResolvedConfig } from '../types-DabOzcsj.cjs';
1
+ import { n as ResolvedConfig } from '../types-CtE9f0G0.cjs';
2
2
 
3
3
  /**
4
4
  * Icon system type definitions
@@ -1,4 +1,4 @@
1
- import { R as ResolvedConfig } from '../types-DabOzcsj.js';
1
+ import { n as ResolvedConfig } from '../types-CtE9f0G0.js';
2
2
 
3
3
  /**
4
4
  * Icon system type definitions
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/icons/core/optimizer.ts","../../src/icons/core/scanner.ts","../../src/icons/utils/naming.ts","../../src/icons/core/parser.ts","../../src/icons/core/index.ts","../../src/icons/generators/react.ts","../../src/icons/generators/svg-sprite.ts","../../src/icons/index.ts"],"names":["existsSync","mkdirSync","join","writeFileSync","skipOptimization"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * SVG optimizer (SVGO integration)\n *\n * Optimizes SVG files using SVGO for smaller file sizes.\n *\n * @packageDocumentation\n */\n\nimport type { OptimizedSVG, ParsedSVG, RawSVGData, SVGOConfig } from '../types.js';\n\n/**\n * Default SVGO configuration\n *\n * Provides sensible defaults for icon optimization.\n */\nexport const defaultSVGOConfig: SVGOConfig = {\n multipass: true,\n plugins: [\n { name: 'preset-default' },\n { name: 'removeXMLNS' },\n { name: 'removeDimensions' },\n { name: 'removeStyleElement' },\n { name: 'removeScriptElement' },\n {\n name: 'removeAttrs',\n params: {\n attrs: ['class', 'style', 'data-name', 'xmlns:xlink'],\n },\n },\n {\n name: 'addAttributesToSVGElement',\n params: {\n attributes: [{ 'aria-hidden': 'true' }, { focusable: 'false' }],\n },\n },\n {\n name: 'sortAttrs',\n params: {\n xmlnsOrder: 'alphabetical',\n },\n },\n ],\n};\n\n/**\n * Optimize a single SVG\n *\n * @param parsed - Parsed SVG data\n * @param raw - Raw SVG data (for size comparison)\n * @param config - SVGO configuration\n * @returns Optimized SVG data\n */\nexport async function optimizeSVG(\n parsed: ParsedSVG,\n raw: RawSVGData,\n config: SVGOConfig = defaultSVGOConfig\n): Promise<OptimizedSVG> {\n // Dynamic import of SVGO\n const svgo = await import('svgo');\n\n // Merge plugins with defaults if provided\n const plugins = config.plugins ?? defaultSVGOConfig.plugins ?? [];\n\n // Convert our plugin format to SVGO's expected format\n const svgoPlugins = plugins.map((p) => ({\n name: p.name,\n ...(p.params ? { params: p.params } : {}),\n }));\n\n // Run SVGO optimization\n const result = svgo.optimize(raw.content, {\n multipass: config.multipass ?? true,\n plugins: svgoPlugins as NonNullable<Parameters<typeof svgo.optimize>[1]>['plugins'],\n });\n\n const optimizedContent = result.data;\n const optimizedSize = Buffer.byteLength(optimizedContent, 'utf-8');\n const sizeReduction =\n raw.originalSize > 0 ? ((raw.originalSize - optimizedSize) / raw.originalSize) * 100 : 0;\n\n // Re-parse optimized content to get updated inner content\n const innerContentMatch = optimizedContent.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\n const innerContent = innerContentMatch?.[1]?.trim() ?? parsed.innerContent;\n\n // Extract updated viewBox\n const viewBoxMatch = optimizedContent.match(/viewBox=[\"']([^\"']*)[\"']/i);\n const viewBox = viewBoxMatch?.[1] ?? parsed.viewBox;\n\n return {\n ...parsed,\n innerContent,\n fullContent: optimizedContent,\n viewBox,\n optimizedSize,\n sizeReduction,\n };\n}\n\n/**\n * Optimize multiple SVGs\n *\n * @param parsedFiles - Array of parsed SVG data\n * @param rawFiles - Array of raw SVG data\n * @param config - SVGO configuration\n * @returns Array of optimized SVG data\n */\nexport async function optimizeSVGFiles(\n parsedFiles: ParsedSVG[],\n rawFiles: RawSVGData[],\n config: SVGOConfig = defaultSVGOConfig\n): Promise<OptimizedSVG[]> {\n const results: OptimizedSVG[] = [];\n\n for (const parsed of parsedFiles) {\n const raw = rawFiles.find((r) => r.fileName === parsed.fileName);\n if (!raw) {\n throw new Error(`Raw file not found for ${parsed.fileName}`);\n }\n const optimized = await optimizeSVG(parsed, raw, config);\n results.push(optimized);\n }\n\n return results;\n}\n\n/**\n * Skip optimization and just add size metadata\n *\n * Useful when SVGO is not needed but the type structure is required.\n *\n * @param parsed - Parsed SVG data\n * @param raw - Raw SVG data\n * @returns Optimized SVG data (without actual optimization)\n */\nexport function skipOptimization(parsed: ParsedSVG, raw: RawSVGData): OptimizedSVG {\n return {\n ...parsed,\n optimizedSize: raw.originalSize,\n sizeReduction: 0,\n };\n}\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * SVG file scanner\n *\n * Scans directories for SVG files and reads their contents.\n *\n * @packageDocumentation\n */\n\nimport { readFileSync, statSync } from 'node:fs';\nimport { basename } from 'node:path';\n\nimport type { RawSVGData, ScannerOptions } from '../types.js';\n\n/**\n * Scan directory for SVG files\n *\n * Uses fast-glob to find SVG files matching the specified patterns.\n *\n * @param options - Scanner options\n * @returns Array of raw SVG data\n *\n * @example\n * ```typescript\n * const files = await scanSVGFiles({\n * sourceDir: './icons',\n * include: ['**\\/*.svg'],\n * exclude: ['**\\/node_modules\\/**'],\n * });\n * ```\n */\nexport async function scanSVGFiles(options: ScannerOptions): Promise<RawSVGData[]> {\n const {\n sourceDir,\n include = ['**/*.svg'],\n exclude = ['**/node_modules/**', '**/dist/**'],\n } = options;\n\n // Dynamic import of fast-glob (ESM module)\n const { default: fg } = await import('fast-glob');\n\n // Find all SVG files\n const files = await fg(include, {\n cwd: sourceDir,\n ignore: exclude,\n absolute: true,\n onlyFiles: true,\n });\n\n // Read each file\n const svgFiles: RawSVGData[] = [];\n\n for (const filePath of files) {\n try {\n const content = readFileSync(filePath, 'utf-8');\n const stats = statSync(filePath);\n\n // Extract file name without extension\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\n\n svgFiles.push({\n filePath,\n fileName,\n content,\n originalSize: stats.size,\n });\n } catch {\n console.warn(`Warning: Failed to read ${filePath}`);\n }\n }\n\n // Sort by name for consistent output\n svgFiles.sort((a, b) => a.fileName.localeCompare(b.fileName));\n\n return svgFiles;\n}\n\n/**\n * Read a single SVG file\n *\n * @param filePath - Path to SVG file\n * @returns Raw SVG data or null if failed\n */\nexport function readSVGFile(filePath: string): RawSVGData | null {\n try {\n const content = readFileSync(filePath, 'utf-8');\n const stats = statSync(filePath);\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\n\n return {\n filePath,\n fileName,\n content,\n originalSize: stats.size,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Icon naming utilities\n *\n * @packageDocumentation\n */\n\n/**\n * Convert string to PascalCase component name\n *\n * @param input - Input string (e.g., file name)\n * @returns PascalCase component name\n *\n * @example\n * ```typescript\n * toComponentName('arrow-left') // 'ArrowLeft'\n * toComponentName('24px-icon') // 'Icon24px'\n * toComponentName('my_icon') // 'MyIcon'\n * toComponentName('chevron-down-small') // 'ChevronDownSmall'\n * ```\n */\nexport function toComponentName(input: string): string {\n // Handle numbers at start by prefixing with 'Icon'\n let processed = input;\n if (/^\\d/.test(processed)) {\n processed = `icon-${processed}`;\n }\n\n return (\n processed\n // Split on non-alphanumeric characters\n .split(/[^a-zA-Z0-9]+/)\n // Filter empty strings\n .filter((word) => word.length > 0)\n // Capitalize each word\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n // Join into single string\n .join('')\n );\n}\n\n/**\n * Convert string to kebab-case icon name\n *\n * @param input - Input string (e.g., component name)\n * @returns kebab-case icon name\n *\n * @example\n * ```typescript\n * toIconName('ArrowLeft') // 'arrow-left'\n * toIconName('ChevronDownSmall') // 'chevron-down-small'\n * toIconName('Icon24px') // 'icon-24px'\n * ```\n */\nexport function toIconName(input: string): string {\n return (\n input\n // Insert hyphen before uppercase letters\n .replace(/([A-Z])/g, '-$1')\n // Insert hyphen before number sequences\n .replace(/(\\d+)/g, '-$1')\n // Clean up multiple hyphens\n .replace(/-+/g, '-')\n // Remove leading hyphen\n .replace(/^-/, '')\n // Lowercase\n .toLowerCase()\n );\n}\n\n/**\n * Validate icon name\n *\n * @param name - Icon name to validate\n * @returns True if valid, false otherwise\n */\nexport function isValidIconName(name: string): boolean {\n // Must be non-empty\n if (!name || name.length === 0) {\n return false;\n }\n\n // Must be valid identifier-like (alphanumeric, hyphens, underscores)\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Normalize icon name from file name\n *\n * @param fileName - File name (without extension)\n * @returns Normalized icon name\n */\nexport function normalizeIconName(fileName: string): string {\n return fileName\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n}\n","/**\n * SVG parser\n *\n * Parses SVG content into structured data.\n *\n * @packageDocumentation\n */\n\nimport { normalizeIconName, toComponentName } from '../utils/naming.js';\n\nimport type { ParsedSVG, RawSVGData } from '../types.js';\n\n/**\n * Parse raw SVG data into structured format\n *\n * Extracts viewBox, attributes, inner content, and accessibility info.\n *\n * @param raw - Raw SVG data\n * @returns Parsed SVG data\n */\nexport function parseSVG(raw: RawSVGData): ParsedSVG {\n const { content, fileName } = raw;\n\n // Extract SVG opening tag attributes\n const svgMatch = content.match(/<svg([^>]*)>/i);\n const svgAttributes = svgMatch?.[1] ?? '';\n\n // Parse attributes into object\n const attributes: Record<string, string> = {};\n const attrRegex = /([a-zA-Z][a-zA-Z0-9-]*)=[\"']([^\"']*)[\"']/g;\n\n for (const attrMatch of svgAttributes.matchAll(attrRegex)) {\n const key = attrMatch[1];\n const value = attrMatch[2];\n if (key && value !== undefined) {\n Object.assign(attributes, { [key]: value });\n }\n }\n\n // Extract viewBox (or construct from width/height)\n let viewBox = attributes['viewBox'] ?? '';\n if (!viewBox) {\n const width = attributes['width']?.replace(/[^\\d.]/g, '') ?? '24';\n const height = attributes['height']?.replace(/[^\\d.]/g, '') ?? '24';\n viewBox = `0 0 ${width} ${height}`;\n }\n\n // Extract inner content (everything between <svg> and </svg>)\n const innerContentMatch = content.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\n const innerContent = innerContentMatch?.[1]?.trim() ?? '';\n\n // Extract title for accessibility\n const titleMatch = content.match(/<title>([^<]*)<\\/title>/i);\n const title = titleMatch?.[1];\n\n // Extract description for accessibility\n const descMatch = content.match(/<desc>([^<]*)<\\/desc>/i);\n const description = descMatch?.[1];\n\n // Generate normalized name and component name\n const name = normalizeIconName(fileName);\n const componentName = toComponentName(fileName);\n\n return {\n name,\n componentName,\n fileName,\n viewBox,\n width: attributes['width'],\n height: attributes['height'],\n innerContent,\n fullContent: content,\n attributes,\n title,\n description,\n };\n}\n\n/**\n * Parse multiple SVG files\n *\n * @param rawFiles - Array of raw SVG data\n * @returns Array of parsed SVG data\n */\nexport function parseSVGFiles(rawFiles: RawSVGData[]): ParsedSVG[] {\n return rawFiles.map(parseSVG);\n}\n\n/**\n * Clean SVG content for React compatibility\n *\n * Converts kebab-case attributes to camelCase for JSX.\n *\n * @param svg - SVG content string\n * @returns Cleaned SVG content\n */\nexport function cleanSVGForReact(svg: string): string {\n return (\n svg\n // Convert kebab-case attributes to camelCase for React\n .replace(\n /(stroke|fill|line|clip|stop|color|font|text|letter|word|alignment|dominant|glyph|horiz|overline|paint|pointer|shape|strikethrough|underline|unicode|units|vert|writing)-([a-z])/g,\n (_, p1, p2) => p1 + p2.toUpperCase()\n )\n // Convert specific attributes\n .replace(/class=\"/g, 'className=\"')\n .replace(/xlink:href/g, 'xlinkHref')\n .replace(/xmlns:xlink/g, 'xmlnsXlink')\n // Use currentColor for strokes and fills (inherits from CSS)\n .replace(/stroke=\"#[^\"]+\"/g, 'stroke=\"currentColor\"')\n .replace(/fill=\"#[^\"]+\"/g, 'fill=\"currentColor\"')\n // Handle fill=\"none\" (keep as-is, common for stroke-only icons)\n .replace(/fill=\"currentColor\"([^>]*stroke)/g, 'fill=\"none\"$1')\n );\n}\n\n/**\n * Extract viewBox from SVG string\n *\n * @param svg - SVG content string\n * @returns ViewBox string or default\n */\nexport function extractViewBox(svg: string): string {\n const match = svg.match(/viewBox=\"([^\"]+)\"/);\n return match?.[1] ?? '0 0 24 24';\n}\n","/**\n * Core icon processing exports\n *\n * @packageDocumentation\n */\n\nexport { readSVGFile, scanSVGFiles } from './scanner.js';\nexport { cleanSVGForReact, extractViewBox, parseSVG, parseSVGFiles } from './parser.js';\nexport {\n defaultSVGOConfig,\n optimizeSVG,\n optimizeSVGFiles,\n skipOptimization,\n} from './optimizer.js';\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * React component generator\n *\n * Generates React icon components from optimized SVG data.\n *\n * @packageDocumentation\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { cleanSVGForReact } from '../core/parser.js';\n\nimport type {\n GeneratedIcon,\n GeneratorOptions,\n IconTemplate,\n IndexTemplate,\n OptimizedSVG,\n TypesTemplate,\n} from '../types.js';\n\n/**\n * Default React icon template\n *\n * Generates a forwardRef component with size, title, and aria support.\n */\nexport const defaultReactTemplate: IconTemplate = (icon) => {\n const cleanedContent = cleanSVGForReact(icon.innerContent);\n\n return `/**\n * ${icon.componentName} icon\n *\n * @generated by @dsai-io/tools\n */\n\nimport * as React from 'react';\n\nimport type { SVGProps } from 'react';\n\nexport interface ${icon.componentName}Props extends SVGProps<SVGSVGElement> {\n /** Icon size */\n size?: number | string;\n /** Icon title for accessibility */\n title?: string;\n}\n\nexport const ${icon.componentName} = React.forwardRef<SVGSVGElement, ${icon.componentName}Props>(\n ({ size = 24, title${icon.title ? ` = \"${icon.title}\"` : ''}, ...props }, ref) => (\n <svg\n ref={ref}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"${icon.viewBox}\"\n width={size}\n height={size}\n fill=\"currentColor\"\n role={title ? 'img' : 'presentation'}\n aria-label={title}\n {...props}\n >\n {title && <title>{title}</title>}\n ${cleanedContent}\n </svg>\n )\n);\n\n${icon.componentName}.displayName = '${icon.componentName}';\n\nexport default ${icon.componentName};\n`;\n};\n\n/**\n * Default React index template\n *\n * Exports all icon components from a single entry point.\n */\nexport const defaultReactIndexTemplate: IndexTemplate = (icons) => `/**\n * Icon exports\n *\n * @generated by @dsai-io/tools\n */\n\n${icons.map((icon) => `export { ${icon.componentName} } from './${icon.componentName}.js';`).join('\\n')}\n\n// Re-export types\nexport type { SVGProps } from 'react';\n`;\n\n/**\n * Default React types template\n *\n * Generates TypeScript types for all icons.\n */\nexport const defaultReactTypesTemplate: TypesTemplate = (icons) => `/**\n * Icon types\n *\n * @generated by @dsai-io/tools\n */\n\nimport type { ForwardRefExoticComponent, RefAttributes, SVGProps } from 'react';\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n title?: string;\n}\n\nexport type IconComponent = ForwardRefExoticComponent<\n IconProps & RefAttributes<SVGSVGElement>\n>;\n\n/**\n * Available icon names\n */\nexport type IconName =\n${icons.map((icon) => ` | '${icon.name}'`).join('\\n')};\n\n/**\n * Icon component map\n */\nexport interface IconMap {\n${icons.map((icon) => ` '${icon.name}': IconComponent;`).join('\\n')}\n}\n\n/**\n * Icon metadata\n */\nexport interface IconMeta {\n name: IconName;\n componentName: string;\n viewBox: string;\n}\n\nexport const iconMeta: IconMeta[] = [\n${icons.map((icon) => ` { name: '${icon.name}', componentName: '${icon.componentName}', viewBox: '${icon.viewBox}' },`).join('\\n')}\n];\n`;\n\n/**\n * Generate React icon components\n *\n * @param icons - Optimized SVG data\n * @param outputDir - Output directory\n * @param options - Generator options\n * @returns Generated icons\n *\n * @example\n * ```typescript\n * const generated = await generateReactIcons(optimizedIcons, './dist/icons/react', {\n * dryRun: false,\n * });\n * console.log(\\`Generated \\${generated.length} files\\`);\n * ```\n */\nexport async function generateReactIcons(\n icons: OptimizedSVG[],\n outputDir: string,\n options: GeneratorOptions = {}\n): Promise<GeneratedIcon[]> {\n const {\n template = defaultReactTemplate,\n indexTemplate = defaultReactIndexTemplate,\n typesTemplate = defaultReactTypesTemplate,\n dryRun = false,\n } = options;\n\n const generated: GeneratedIcon[] = [];\n\n // Ensure output directory exists\n if (!dryRun && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Generate individual icon components\n for (const icon of icons) {\n const code = template(icon);\n const outputPath = join(outputDir, `${icon.componentName}.tsx`);\n\n if (!dryRun) {\n writeFileSync(outputPath, code, 'utf-8');\n }\n\n generated.push({\n name: icon.name,\n componentName: icon.componentName,\n code,\n outputPath,\n format: 'react',\n });\n }\n\n // Generate index file\n const indexCode = indexTemplate(icons);\n const indexPath = join(outputDir, 'index.ts');\n\n if (!dryRun) {\n writeFileSync(indexPath, indexCode, 'utf-8');\n }\n\n generated.push({\n name: 'index',\n componentName: 'index',\n code: indexCode,\n outputPath: indexPath,\n format: 'react',\n });\n\n // Generate types file\n const typesCode = typesTemplate(icons);\n const typesPath = join(outputDir, 'types.ts');\n\n if (!dryRun) {\n writeFileSync(typesPath, typesCode, 'utf-8');\n }\n\n generated.push({\n name: 'types',\n componentName: 'types',\n code: typesCode,\n outputPath: typesPath,\n format: 'react',\n });\n\n return generated;\n}\n","/* eslint-disable security/detect-non-literal-fs-filename */\n/**\n * SVG sprite generator\n *\n * Generates SVG sprite files with symbol definitions.\n *\n * @packageDocumentation\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { GeneratedIcon, OptimizedSVG } from '../types.js';\n\n/**\n * SVG sprite generator options\n */\nexport interface SpriteOptions {\n /** Sprite file name */\n fileName?: string;\n\n /** Generate preview HTML file */\n generatePreview?: boolean;\n\n /** Dry run - don't write files */\n dryRun?: boolean;\n}\n\n/**\n * Generate SVG sprite\n *\n * Creates an SVG sprite with symbol definitions for all icons.\n *\n * @param icons - Optimized SVG data\n * @param outputDir - Output directory\n * @param options - Generator options\n * @returns Generated files\n *\n * @example\n * ```typescript\n * const generated = await generateSVGSprite(optimizedIcons, './dist/icons/sprite', {\n * fileName: 'icons.svg',\n * generatePreview: true,\n * });\n * ```\n */\nexport async function generateSVGSprite(\n icons: OptimizedSVG[],\n outputDir: string,\n options: SpriteOptions = {}\n): Promise<GeneratedIcon[]> {\n const { fileName = 'sprite.svg', generatePreview = true, dryRun = false } = options;\n\n const generated: GeneratedIcon[] = [];\n\n // Ensure output directory exists\n if (!dryRun && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Generate sprite symbols\n const symbols = icons\n .map(\n (icon) => ` <symbol id=\"${icon.name}\" viewBox=\"${icon.viewBox}\">\n ${icon.innerContent}\n </symbol>`\n )\n .join('\\n');\n\n // Create sprite SVG\n const spriteCode = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n SVG Sprite\n @generated by @dsai-io/tools\n Contains ${icons.length} icons\n-->\n<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <defs>\n${symbols}\n </defs>\n</svg>\n`;\n\n const outputPath = join(outputDir, fileName);\n\n if (!dryRun) {\n writeFileSync(outputPath, spriteCode, 'utf-8');\n }\n\n generated.push({\n name: 'sprite',\n componentName: 'sprite',\n code: spriteCode,\n outputPath,\n format: 'svg-sprite',\n });\n\n // Generate usage helper HTML\n if (generatePreview) {\n const usageCode = generatePreviewHTML(icons, fileName);\n const usagePath = join(outputDir, 'sprite-preview.html');\n\n if (!dryRun) {\n writeFileSync(usagePath, usageCode, 'utf-8');\n }\n\n generated.push({\n name: 'preview',\n componentName: 'preview',\n code: usageCode,\n outputPath: usagePath,\n format: 'svg-sprite',\n });\n }\n\n return generated;\n}\n\n/**\n * Generate preview HTML for sprite\n */\nfunction generatePreviewHTML(icons: OptimizedSVG[], spriteFileName: string): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Icon Sprite Preview</title>\n <style>\n * { box-sizing: border-box; }\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 1200px; margin: 0 auto; }\n h1 { margin-bottom: 0.5rem; }\n .meta { color: #666; margin-bottom: 2rem; }\n .icon { width: 24px; height: 24px; fill: currentColor; }\n .icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 1rem; }\n .icon-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1rem; border: 1px solid #eee; border-radius: 8px; transition: background 0.2s; }\n .icon-item:hover { background: #f5f5f5; }\n .icon-name { font-size: 11px; color: #666; text-align: center; word-break: break-all; }\n pre { background: #f5f5f5; padding: 1rem; border-radius: 8px; overflow-x: auto; }\n code { font-family: ui-monospace, monospace; font-size: 13px; }\n </style>\n</head>\n<body>\n <h1>Icon Sprite Preview</h1>\n <p class=\"meta\">${icons.length} icons • Generated by @dsai-io/tools</p>\n\n <h2>Usage</h2>\n <pre><code>&lt;svg class=\"icon\"&gt;\n &lt;use href=\"${spriteFileName}#icon-name\"&gt;&lt;/use&gt;\n&lt;/svg&gt;</code></pre>\n\n <h2>All Icons</h2>\n <div class=\"icon-grid\">\n${icons\n .map(\n (icon) => ` <div class=\"icon-item\">\n <svg class=\"icon\"><use href=\"${spriteFileName}#${icon.name}\"></use></svg>\n <span class=\"icon-name\">${icon.name}</span>\n </div>`\n )\n .join('\\n')}\n </div>\n</body>\n</html>\n`;\n}\n","/**\n * Icon tooling module for @dsai-io/tools\n *\n * Provides utilities for generating icon components from SVG source files.\n * Supports React components, SVG sprites, with SVGO optimization.\n *\n * @packageDocumentation\n */\n\nimport { join } from 'node:path';\n\nimport { optimizeSVGFiles, parseSVGFiles, scanSVGFiles } from './core/index.js';\nimport { generateReactIcons } from './generators/react.js';\nimport { generateSVGSprite } from './generators/svg-sprite.js';\n\nimport type {\n GeneratedIcon,\n IconBuildOptions,\n IconBuildResult,\n IconFormat,\n OptimizedSVG,\n SVGOConfig,\n} from './types.js';\nimport type { ResolvedConfig } from '../config/types.js';\n\n/**\n * Build icons from SVG source files\n *\n * Scans the source directory, parses and optimizes SVGs, then generates\n * output in the specified formats (React, SVG sprite).\n *\n * @param config - Resolved DSAi configuration\n * @param options - Build options\n * @returns Build result with generated files\n *\n * @example\n * ```typescript\n * import { loadConfig } from '@dsai-io/tools/config';\n * import { buildIcons } from '@dsai-io/tools/icons';\n *\n * const { config } = await loadConfig();\n * const result = await buildIcons(config, {\n * formats: ['react', 'svg-sprite'],\n * });\n *\n * console.log(\\`Generated \\${result.totalIcons} icons\\`);\n * ```\n */\nexport async function buildIcons(\n config: ResolvedConfig,\n options: IconBuildOptions = {}\n): Promise<IconBuildResult> {\n const startTime = Date.now();\n const defaultFormat = config.icons.framework === 'react' ? 'react' : 'svg-sprite';\n const { formats = [defaultFormat as IconFormat], icons: iconFilter, dryRun = false } = options;\n\n const result: IconBuildResult = {\n success: false,\n icons: [],\n totalIcons: 0,\n filesWritten: 0,\n totalSizeReduction: 0,\n errors: [],\n warnings: [],\n duration: 0,\n };\n\n try {\n // Step 1: Scan for SVG files\n const rawFiles = await scanSVGFiles({\n sourceDir: config.icons.sourceDir,\n });\n\n if (rawFiles.length === 0) {\n result.warnings.push({\n icon: '*',\n message: `No SVG files found in ${config.icons.sourceDir}`,\n });\n result.success = true;\n result.duration = Date.now() - startTime;\n return result;\n }\n\n // Filter by specific icons if provided\n const filteredFiles = iconFilter\n ? rawFiles.filter((f) => iconFilter.includes(f.fileName))\n : rawFiles;\n\n // Step 2: Parse SVG content\n const parsedFiles = parseSVGFiles(filteredFiles);\n\n // Step 3: Optimize SVGs (if enabled)\n let optimizedFiles: OptimizedSVG[];\n if (config.icons.optimize) {\n const svgoConfig: SVGOConfig = {\n multipass: true,\n };\n optimizedFiles = await optimizeSVGFiles(parsedFiles, filteredFiles, svgoConfig);\n\n // Calculate total size reduction\n const totalReduction = optimizedFiles.reduce((sum, f) => sum + f.sizeReduction, 0);\n result.totalSizeReduction =\n optimizedFiles.length > 0 ? totalReduction / optimizedFiles.length : 0;\n } else {\n // Skip optimization - just add size metadata\n const { skipOptimization } = await import('./core/optimizer.js');\n optimizedFiles = parsedFiles.map((parsed, index) => {\n const rawFile = filteredFiles.at(index);\n if (!rawFile) {\n throw new Error(`Missing raw file for ${parsed.fileName}`);\n }\n return skipOptimization(parsed, rawFile);\n });\n }\n\n result.totalIcons = optimizedFiles.length;\n\n // Step 4: Generate output for each format\n const generated: GeneratedIcon[] = [];\n\n for (const format of formats) {\n const outputDir = join(config.icons.outputDir, format);\n\n switch (format) {\n case 'react':\n generated.push(...(await generateReactIcons(optimizedFiles, outputDir, { dryRun })));\n break;\n\n case 'svg':\n case 'svg-sprite':\n generated.push(...(await generateSVGSprite(optimizedFiles, outputDir, { dryRun })));\n break;\n\n default:\n result.warnings.push({\n icon: '*',\n message: `Unknown format: ${format}`,\n });\n }\n }\n\n result.icons = generated;\n result.filesWritten = dryRun ? 0 : generated.length;\n result.success = true;\n } catch (error) {\n result.errors.push({\n icon: '*',\n message: error instanceof Error ? error.message : 'Unknown error',\n code: 'BUILD_ERROR',\n });\n }\n\n result.duration = Date.now() - startTime;\n return result;\n}\n\n// Re-export types\nexport type {\n GeneratedIcon,\n GeneratorOptions,\n IconBuildOptions,\n IconBuildResult,\n IconError,\n IconErrorCode,\n IconFormat,\n IconTemplate,\n IconWarning,\n IndexTemplate,\n OptimizedSVG,\n ParsedSVG,\n RawSVGData,\n ScannerOptions,\n SVGOConfig,\n SVGOPlugin,\n TypesTemplate,\n} from './types.js';\n\n// Re-export core utilities\nexport {\n cleanSVGForReact,\n defaultSVGOConfig,\n extractViewBox,\n optimizeSVG,\n optimizeSVGFiles,\n parseSVG,\n parseSVGFiles,\n readSVGFile,\n scanSVGFiles,\n skipOptimization,\n} from './core/index.js';\n\n// Re-export generators\nexport {\n defaultReactIndexTemplate,\n defaultReactTemplate,\n defaultReactTypesTemplate,\n generateReactIcons,\n generateSVGSprite,\n} from './generators/index.js';\n\n// Re-export naming utilities\nexport {\n isValidIconName,\n normalizeIconName,\n toComponentName,\n toIconName,\n} from './utils/index.js';\n"]}
1
+ {"version":3,"sources":["../../src/icons/core/optimizer.ts","../../src/icons/core/scanner.ts","../../src/icons/utils/naming.ts","../../src/icons/core/parser.ts","../../src/icons/core/index.ts","../../src/icons/generators/react.ts","../../src/icons/generators/svg-sprite.ts","../../src/icons/index.ts"],"names":["existsSync","mkdirSync","join","writeFileSync","skipOptimization"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * SVG optimizer (SVGO integration)\r\n *\r\n * Optimizes SVG files using SVGO for smaller file sizes.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport type { OptimizedSVG, ParsedSVG, RawSVGData, SVGOConfig } from '../types.js';\r\n\r\n/**\r\n * Default SVGO configuration\r\n *\r\n * Provides sensible defaults for icon optimization.\r\n */\r\nexport const defaultSVGOConfig: SVGOConfig = {\r\n multipass: true,\r\n plugins: [\r\n { name: 'preset-default' },\r\n { name: 'removeXMLNS' },\r\n { name: 'removeDimensions' },\r\n { name: 'removeStyleElement' },\r\n { name: 'removeScriptElement' },\r\n {\r\n name: 'removeAttrs',\r\n params: {\r\n attrs: ['class', 'style', 'data-name', 'xmlns:xlink'],\r\n },\r\n },\r\n {\r\n name: 'addAttributesToSVGElement',\r\n params: {\r\n attributes: [{ 'aria-hidden': 'true' }, { focusable: 'false' }],\r\n },\r\n },\r\n {\r\n name: 'sortAttrs',\r\n params: {\r\n xmlnsOrder: 'alphabetical',\r\n },\r\n },\r\n ],\r\n};\r\n\r\n/**\r\n * Optimize a single SVG\r\n *\r\n * @param parsed - Parsed SVG data\r\n * @param raw - Raw SVG data (for size comparison)\r\n * @param config - SVGO configuration\r\n * @returns Optimized SVG data\r\n */\r\nexport async function optimizeSVG(\r\n parsed: ParsedSVG,\r\n raw: RawSVGData,\r\n config: SVGOConfig = defaultSVGOConfig\r\n): Promise<OptimizedSVG> {\r\n // Dynamic import of SVGO\r\n const svgo = await import('svgo');\r\n\r\n // Merge plugins with defaults if provided\r\n const plugins = config.plugins ?? defaultSVGOConfig.plugins ?? [];\r\n\r\n // Convert our plugin format to SVGO's expected format\r\n const svgoPlugins = plugins.map((p) => ({\r\n name: p.name,\r\n ...(p.params ? { params: p.params } : {}),\r\n }));\r\n\r\n // Run SVGO optimization\r\n const result = svgo.optimize(raw.content, {\r\n multipass: config.multipass ?? true,\r\n plugins: svgoPlugins as NonNullable<Parameters<typeof svgo.optimize>[1]>['plugins'],\r\n });\r\n\r\n const optimizedContent = result.data;\r\n const optimizedSize = Buffer.byteLength(optimizedContent, 'utf-8');\r\n const sizeReduction =\r\n raw.originalSize > 0 ? ((raw.originalSize - optimizedSize) / raw.originalSize) * 100 : 0;\r\n\r\n // Re-parse optimized content to get updated inner content\r\n const innerContentMatch = optimizedContent.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\r\n const innerContent = innerContentMatch?.[1]?.trim() ?? parsed.innerContent;\r\n\r\n // Extract updated viewBox\r\n const viewBoxMatch = optimizedContent.match(/viewBox=[\"']([^\"']*)[\"']/i);\r\n const viewBox = viewBoxMatch?.[1] ?? parsed.viewBox;\r\n\r\n return {\r\n ...parsed,\r\n innerContent,\r\n fullContent: optimizedContent,\r\n viewBox,\r\n optimizedSize,\r\n sizeReduction,\r\n };\r\n}\r\n\r\n/**\r\n * Optimize multiple SVGs\r\n *\r\n * @param parsedFiles - Array of parsed SVG data\r\n * @param rawFiles - Array of raw SVG data\r\n * @param config - SVGO configuration\r\n * @returns Array of optimized SVG data\r\n */\r\nexport async function optimizeSVGFiles(\r\n parsedFiles: ParsedSVG[],\r\n rawFiles: RawSVGData[],\r\n config: SVGOConfig = defaultSVGOConfig\r\n): Promise<OptimizedSVG[]> {\r\n const results: OptimizedSVG[] = [];\r\n\r\n for (const parsed of parsedFiles) {\r\n const raw = rawFiles.find((r) => r.fileName === parsed.fileName);\r\n if (!raw) {\r\n throw new Error(`Raw file not found for ${parsed.fileName}`);\r\n }\r\n const optimized = await optimizeSVG(parsed, raw, config);\r\n results.push(optimized);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Skip optimization and just add size metadata\r\n *\r\n * Useful when SVGO is not needed but the type structure is required.\r\n *\r\n * @param parsed - Parsed SVG data\r\n * @param raw - Raw SVG data\r\n * @returns Optimized SVG data (without actual optimization)\r\n */\r\nexport function skipOptimization(parsed: ParsedSVG, raw: RawSVGData): OptimizedSVG {\r\n return {\r\n ...parsed,\r\n optimizedSize: raw.originalSize,\r\n sizeReduction: 0,\r\n };\r\n}\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * SVG file scanner\r\n *\r\n * Scans directories for SVG files and reads their contents.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { readFileSync, statSync } from 'node:fs';\r\nimport { basename } from 'node:path';\r\n\r\nimport type { RawSVGData, ScannerOptions } from '../types.js';\r\n\r\n/**\r\n * Scan directory for SVG files\r\n *\r\n * Uses fast-glob to find SVG files matching the specified patterns.\r\n *\r\n * @param options - Scanner options\r\n * @returns Array of raw SVG data\r\n *\r\n * @example\r\n * ```typescript\r\n * const files = await scanSVGFiles({\r\n * sourceDir: './icons',\r\n * include: ['**\\/*.svg'],\r\n * exclude: ['**\\/node_modules\\/**'],\r\n * });\r\n * ```\r\n */\r\nexport async function scanSVGFiles(options: ScannerOptions): Promise<RawSVGData[]> {\r\n const {\r\n sourceDir,\r\n include = ['**/*.svg'],\r\n exclude = ['**/node_modules/**', '**/dist/**'],\r\n } = options;\r\n\r\n // Dynamic import of fast-glob (ESM module)\r\n const { default: fg } = await import('fast-glob');\r\n\r\n // Find all SVG files\r\n const files = await fg(include, {\r\n cwd: sourceDir,\r\n ignore: exclude,\r\n absolute: true,\r\n onlyFiles: true,\r\n });\r\n\r\n // Read each file\r\n const svgFiles: RawSVGData[] = [];\r\n\r\n for (const filePath of files) {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8');\r\n const stats = statSync(filePath);\r\n\r\n // Extract file name without extension\r\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\r\n\r\n svgFiles.push({\r\n filePath,\r\n fileName,\r\n content,\r\n originalSize: stats.size,\r\n });\r\n } catch {\r\n console.warn(`Warning: Failed to read ${filePath}`);\r\n }\r\n }\r\n\r\n // Sort by name for consistent output\r\n svgFiles.sort((a, b) => a.fileName.localeCompare(b.fileName));\r\n\r\n return svgFiles;\r\n}\r\n\r\n/**\r\n * Read a single SVG file\r\n *\r\n * @param filePath - Path to SVG file\r\n * @returns Raw SVG data or null if failed\r\n */\r\nexport function readSVGFile(filePath: string): RawSVGData | null {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8');\r\n const stats = statSync(filePath);\r\n const fileName = basename(filePath).replace(/\\.svg$/i, '');\r\n\r\n return {\r\n filePath,\r\n fileName,\r\n content,\r\n originalSize: stats.size,\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Icon naming utilities\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n/**\r\n * Convert string to PascalCase component name\r\n *\r\n * @param input - Input string (e.g., file name)\r\n * @returns PascalCase component name\r\n *\r\n * @example\r\n * ```typescript\r\n * toComponentName('arrow-left') // 'ArrowLeft'\r\n * toComponentName('24px-icon') // 'Icon24px'\r\n * toComponentName('my_icon') // 'MyIcon'\r\n * toComponentName('chevron-down-small') // 'ChevronDownSmall'\r\n * ```\r\n */\r\nexport function toComponentName(input: string): string {\r\n // Handle numbers at start by prefixing with 'Icon'\r\n let processed = input;\r\n if (/^\\d/.test(processed)) {\r\n processed = `icon-${processed}`;\r\n }\r\n\r\n return (\r\n processed\r\n // Split on non-alphanumeric characters\r\n .split(/[^a-zA-Z0-9]+/)\r\n // Filter empty strings\r\n .filter((word) => word.length > 0)\r\n // Capitalize each word\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n // Join into single string\r\n .join('')\r\n );\r\n}\r\n\r\n/**\r\n * Convert string to kebab-case icon name\r\n *\r\n * @param input - Input string (e.g., component name)\r\n * @returns kebab-case icon name\r\n *\r\n * @example\r\n * ```typescript\r\n * toIconName('ArrowLeft') // 'arrow-left'\r\n * toIconName('ChevronDownSmall') // 'chevron-down-small'\r\n * toIconName('Icon24px') // 'icon-24px'\r\n * ```\r\n */\r\nexport function toIconName(input: string): string {\r\n return (\r\n input\r\n // Insert hyphen before uppercase letters\r\n .replace(/([A-Z])/g, '-$1')\r\n // Insert hyphen before number sequences\r\n .replace(/(\\d+)/g, '-$1')\r\n // Clean up multiple hyphens\r\n .replace(/-+/g, '-')\r\n // Remove leading hyphen\r\n .replace(/^-/, '')\r\n // Lowercase\r\n .toLowerCase()\r\n );\r\n}\r\n\r\n/**\r\n * Validate icon name\r\n *\r\n * @param name - Icon name to validate\r\n * @returns True if valid, false otherwise\r\n */\r\nexport function isValidIconName(name: string): boolean {\r\n // Must be non-empty\r\n if (!name || name.length === 0) {\r\n return false;\r\n }\r\n\r\n // Must be valid identifier-like (alphanumeric, hyphens, underscores)\r\n if (!/^[a-zA-Z0-9_-]+$/.test(name)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Normalize icon name from file name\r\n *\r\n * @param fileName - File name (without extension)\r\n * @returns Normalized icon name\r\n */\r\nexport function normalizeIconName(fileName: string): string {\r\n return fileName\r\n .replace(/[^a-zA-Z0-9]+/g, '-')\r\n .replace(/^-+|-+$/g, '')\r\n .toLowerCase();\r\n}\r\n","/**\r\n * SVG parser\r\n *\r\n * Parses SVG content into structured data.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { normalizeIconName, toComponentName } from '../utils/naming.js';\r\n\r\nimport type { ParsedSVG, RawSVGData } from '../types.js';\r\n\r\n/**\r\n * Parse raw SVG data into structured format\r\n *\r\n * Extracts viewBox, attributes, inner content, and accessibility info.\r\n *\r\n * @param raw - Raw SVG data\r\n * @returns Parsed SVG data\r\n */\r\nexport function parseSVG(raw: RawSVGData): ParsedSVG {\r\n const { content, fileName } = raw;\r\n\r\n // Extract SVG opening tag attributes\r\n const svgMatch = content.match(/<svg([^>]*)>/i);\r\n const svgAttributes = svgMatch?.[1] ?? '';\r\n\r\n // Parse attributes into object\r\n const attributes: Record<string, string> = {};\r\n const attrRegex = /([a-zA-Z][a-zA-Z0-9-]*)=[\"']([^\"']*)[\"']/g;\r\n\r\n for (const attrMatch of svgAttributes.matchAll(attrRegex)) {\r\n const key = attrMatch[1];\r\n const value = attrMatch[2];\r\n if (key && value !== undefined) {\r\n Object.assign(attributes, { [key]: value });\r\n }\r\n }\r\n\r\n // Extract viewBox (or construct from width/height)\r\n let viewBox = attributes['viewBox'] ?? '';\r\n if (!viewBox) {\r\n const width = attributes['width']?.replace(/[^\\d.]/g, '') ?? '24';\r\n const height = attributes['height']?.replace(/[^\\d.]/g, '') ?? '24';\r\n viewBox = `0 0 ${width} ${height}`;\r\n }\r\n\r\n // Extract inner content (everything between <svg> and </svg>)\r\n const innerContentMatch = content.match(/<svg[^>]*>([\\s\\S]*?)<\\/svg>/i);\r\n const innerContent = innerContentMatch?.[1]?.trim() ?? '';\r\n\r\n // Extract title for accessibility\r\n const titleMatch = content.match(/<title>([^<]*)<\\/title>/i);\r\n const title = titleMatch?.[1];\r\n\r\n // Extract description for accessibility\r\n const descMatch = content.match(/<desc>([^<]*)<\\/desc>/i);\r\n const description = descMatch?.[1];\r\n\r\n // Generate normalized name and component name\r\n const name = normalizeIconName(fileName);\r\n const componentName = toComponentName(fileName);\r\n\r\n return {\r\n name,\r\n componentName,\r\n fileName,\r\n viewBox,\r\n width: attributes['width'],\r\n height: attributes['height'],\r\n innerContent,\r\n fullContent: content,\r\n attributes,\r\n title,\r\n description,\r\n };\r\n}\r\n\r\n/**\r\n * Parse multiple SVG files\r\n *\r\n * @param rawFiles - Array of raw SVG data\r\n * @returns Array of parsed SVG data\r\n */\r\nexport function parseSVGFiles(rawFiles: RawSVGData[]): ParsedSVG[] {\r\n return rawFiles.map(parseSVG);\r\n}\r\n\r\n/**\r\n * Clean SVG content for React compatibility\r\n *\r\n * Converts kebab-case attributes to camelCase for JSX.\r\n *\r\n * @param svg - SVG content string\r\n * @returns Cleaned SVG content\r\n */\r\nexport function cleanSVGForReact(svg: string): string {\r\n return (\r\n svg\r\n // Convert kebab-case attributes to camelCase for React\r\n .replace(\r\n /(stroke|fill|line|clip|stop|color|font|text|letter|word|alignment|dominant|glyph|horiz|overline|paint|pointer|shape|strikethrough|underline|unicode|units|vert|writing)-([a-z])/g,\r\n (_, p1, p2) => p1 + p2.toUpperCase()\r\n )\r\n // Convert specific attributes\r\n .replace(/class=\"/g, 'className=\"')\r\n .replace(/xlink:href/g, 'xlinkHref')\r\n .replace(/xmlns:xlink/g, 'xmlnsXlink')\r\n // Use currentColor for strokes and fills (inherits from CSS)\r\n .replace(/stroke=\"#[^\"]+\"/g, 'stroke=\"currentColor\"')\r\n .replace(/fill=\"#[^\"]+\"/g, 'fill=\"currentColor\"')\r\n // Handle fill=\"none\" (keep as-is, common for stroke-only icons)\r\n .replace(/fill=\"currentColor\"([^>]*stroke)/g, 'fill=\"none\"$1')\r\n );\r\n}\r\n\r\n/**\r\n * Extract viewBox from SVG string\r\n *\r\n * @param svg - SVG content string\r\n * @returns ViewBox string or default\r\n */\r\nexport function extractViewBox(svg: string): string {\r\n const match = svg.match(/viewBox=\"([^\"]+)\"/);\r\n return match?.[1] ?? '0 0 24 24';\r\n}\r\n","/**\r\n * Core icon processing exports\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nexport { readSVGFile, scanSVGFiles } from './scanner.js';\r\nexport { cleanSVGForReact, extractViewBox, parseSVG, parseSVGFiles } from './parser.js';\r\nexport {\r\n defaultSVGOConfig,\r\n optimizeSVG,\r\n optimizeSVGFiles,\r\n skipOptimization,\r\n} from './optimizer.js';\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * React component generator\r\n *\r\n * Generates React icon components from optimized SVG data.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\n\r\nimport { cleanSVGForReact } from '../core/parser.js';\r\n\r\nimport type {\r\n GeneratedIcon,\r\n GeneratorOptions,\r\n IconTemplate,\r\n IndexTemplate,\r\n OptimizedSVG,\r\n TypesTemplate,\r\n} from '../types.js';\r\n\r\n/**\r\n * Default React icon template\r\n *\r\n * Generates a forwardRef component with size, title, and aria support.\r\n */\r\nexport const defaultReactTemplate: IconTemplate = (icon) => {\r\n const cleanedContent = cleanSVGForReact(icon.innerContent);\r\n\r\n return `/**\r\n * ${icon.componentName} icon\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\nimport * as React from 'react';\r\n\r\nimport type { SVGProps } from 'react';\r\n\r\nexport interface ${icon.componentName}Props extends SVGProps<SVGSVGElement> {\r\n /** Icon size */\r\n size?: number | string;\r\n /** Icon title for accessibility */\r\n title?: string;\r\n}\r\n\r\nexport const ${icon.componentName} = React.forwardRef<SVGSVGElement, ${icon.componentName}Props>(\r\n ({ size = 24, title${icon.title ? ` = \"${icon.title}\"` : ''}, ...props }, ref) => (\r\n <svg\r\n ref={ref}\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"${icon.viewBox}\"\r\n width={size}\r\n height={size}\r\n fill=\"currentColor\"\r\n role={title ? 'img' : 'presentation'}\r\n aria-label={title}\r\n {...props}\r\n >\r\n {title && <title>{title}</title>}\r\n ${cleanedContent}\r\n </svg>\r\n )\r\n);\r\n\r\n${icon.componentName}.displayName = '${icon.componentName}';\r\n\r\nexport default ${icon.componentName};\r\n`;\r\n};\r\n\r\n/**\r\n * Default React index template\r\n *\r\n * Exports all icon components from a single entry point.\r\n */\r\nexport const defaultReactIndexTemplate: IndexTemplate = (icons) => `/**\r\n * Icon exports\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\n${icons.map((icon) => `export { ${icon.componentName} } from './${icon.componentName}.js';`).join('\\n')}\r\n\r\n// Re-export types\r\nexport type { SVGProps } from 'react';\r\n`;\r\n\r\n/**\r\n * Default React types template\r\n *\r\n * Generates TypeScript types for all icons.\r\n */\r\nexport const defaultReactTypesTemplate: TypesTemplate = (icons) => `/**\r\n * Icon types\r\n *\r\n * @generated by @dsai-io/tools\r\n */\r\n\r\nimport type { ForwardRefExoticComponent, RefAttributes, SVGProps } from 'react';\r\n\r\nexport interface IconProps extends SVGProps<SVGSVGElement> {\r\n size?: number | string;\r\n title?: string;\r\n}\r\n\r\nexport type IconComponent = ForwardRefExoticComponent<\r\n IconProps & RefAttributes<SVGSVGElement>\r\n>;\r\n\r\n/**\r\n * Available icon names\r\n */\r\nexport type IconName =\r\n${icons.map((icon) => ` | '${icon.name}'`).join('\\n')};\r\n\r\n/**\r\n * Icon component map\r\n */\r\nexport interface IconMap {\r\n${icons.map((icon) => ` '${icon.name}': IconComponent;`).join('\\n')}\r\n}\r\n\r\n/**\r\n * Icon metadata\r\n */\r\nexport interface IconMeta {\r\n name: IconName;\r\n componentName: string;\r\n viewBox: string;\r\n}\r\n\r\nexport const iconMeta: IconMeta[] = [\r\n${icons.map((icon) => ` { name: '${icon.name}', componentName: '${icon.componentName}', viewBox: '${icon.viewBox}' },`).join('\\n')}\r\n];\r\n`;\r\n\r\n/**\r\n * Generate React icon components\r\n *\r\n * @param icons - Optimized SVG data\r\n * @param outputDir - Output directory\r\n * @param options - Generator options\r\n * @returns Generated icons\r\n *\r\n * @example\r\n * ```typescript\r\n * const generated = await generateReactIcons(optimizedIcons, './dist/icons/react', {\r\n * dryRun: false,\r\n * });\r\n * console.log(\\`Generated \\${generated.length} files\\`);\r\n * ```\r\n */\r\nexport async function generateReactIcons(\r\n icons: OptimizedSVG[],\r\n outputDir: string,\r\n options: GeneratorOptions = {}\r\n): Promise<GeneratedIcon[]> {\r\n const {\r\n template = defaultReactTemplate,\r\n indexTemplate = defaultReactIndexTemplate,\r\n typesTemplate = defaultReactTypesTemplate,\r\n dryRun = false,\r\n } = options;\r\n\r\n const generated: GeneratedIcon[] = [];\r\n\r\n // Ensure output directory exists\r\n if (!dryRun && !existsSync(outputDir)) {\r\n mkdirSync(outputDir, { recursive: true });\r\n }\r\n\r\n // Generate individual icon components\r\n for (const icon of icons) {\r\n const code = template(icon);\r\n const outputPath = join(outputDir, `${icon.componentName}.tsx`);\r\n\r\n if (!dryRun) {\r\n writeFileSync(outputPath, code, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: icon.name,\r\n componentName: icon.componentName,\r\n code,\r\n outputPath,\r\n format: 'react',\r\n });\r\n }\r\n\r\n // Generate index file\r\n const indexCode = indexTemplate(icons);\r\n const indexPath = join(outputDir, 'index.ts');\r\n\r\n if (!dryRun) {\r\n writeFileSync(indexPath, indexCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'index',\r\n componentName: 'index',\r\n code: indexCode,\r\n outputPath: indexPath,\r\n format: 'react',\r\n });\r\n\r\n // Generate types file\r\n const typesCode = typesTemplate(icons);\r\n const typesPath = join(outputDir, 'types.ts');\r\n\r\n if (!dryRun) {\r\n writeFileSync(typesPath, typesCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'types',\r\n componentName: 'types',\r\n code: typesCode,\r\n outputPath: typesPath,\r\n format: 'react',\r\n });\r\n\r\n return generated;\r\n}\r\n","/* eslint-disable security/detect-non-literal-fs-filename */\r\n/**\r\n * SVG sprite generator\r\n *\r\n * Generates SVG sprite files with symbol definitions.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\r\nimport { join } from 'node:path';\r\n\r\nimport type { GeneratedIcon, OptimizedSVG } from '../types.js';\r\n\r\n/**\r\n * SVG sprite generator options\r\n */\r\nexport interface SpriteOptions {\r\n /** Sprite file name */\r\n fileName?: string;\r\n\r\n /** Generate preview HTML file */\r\n generatePreview?: boolean;\r\n\r\n /** Dry run - don't write files */\r\n dryRun?: boolean;\r\n}\r\n\r\n/**\r\n * Generate SVG sprite\r\n *\r\n * Creates an SVG sprite with symbol definitions for all icons.\r\n *\r\n * @param icons - Optimized SVG data\r\n * @param outputDir - Output directory\r\n * @param options - Generator options\r\n * @returns Generated files\r\n *\r\n * @example\r\n * ```typescript\r\n * const generated = await generateSVGSprite(optimizedIcons, './dist/icons/sprite', {\r\n * fileName: 'icons.svg',\r\n * generatePreview: true,\r\n * });\r\n * ```\r\n */\r\nexport async function generateSVGSprite(\r\n icons: OptimizedSVG[],\r\n outputDir: string,\r\n options: SpriteOptions = {}\r\n): Promise<GeneratedIcon[]> {\r\n const { fileName = 'sprite.svg', generatePreview = true, dryRun = false } = options;\r\n\r\n const generated: GeneratedIcon[] = [];\r\n\r\n // Ensure output directory exists\r\n if (!dryRun && !existsSync(outputDir)) {\r\n mkdirSync(outputDir, { recursive: true });\r\n }\r\n\r\n // Generate sprite symbols\r\n const symbols = icons\r\n .map(\r\n (icon) => ` <symbol id=\"${icon.name}\" viewBox=\"${icon.viewBox}\">\r\n ${icon.innerContent}\r\n </symbol>`\r\n )\r\n .join('\\n');\r\n\r\n // Create sprite SVG\r\n const spriteCode = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!--\r\n SVG Sprite\r\n @generated by @dsai-io/tools\r\n Contains ${icons.length} icons\r\n-->\r\n<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\r\n <defs>\r\n${symbols}\r\n </defs>\r\n</svg>\r\n`;\r\n\r\n const outputPath = join(outputDir, fileName);\r\n\r\n if (!dryRun) {\r\n writeFileSync(outputPath, spriteCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'sprite',\r\n componentName: 'sprite',\r\n code: spriteCode,\r\n outputPath,\r\n format: 'svg-sprite',\r\n });\r\n\r\n // Generate usage helper HTML\r\n if (generatePreview) {\r\n const usageCode = generatePreviewHTML(icons, fileName);\r\n const usagePath = join(outputDir, 'sprite-preview.html');\r\n\r\n if (!dryRun) {\r\n writeFileSync(usagePath, usageCode, 'utf-8');\r\n }\r\n\r\n generated.push({\r\n name: 'preview',\r\n componentName: 'preview',\r\n code: usageCode,\r\n outputPath: usagePath,\r\n format: 'svg-sprite',\r\n });\r\n }\r\n\r\n return generated;\r\n}\r\n\r\n/**\r\n * Generate preview HTML for sprite\r\n */\r\nfunction generatePreviewHTML(icons: OptimizedSVG[], spriteFileName: string): string {\r\n return `<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>Icon Sprite Preview</title>\r\n <style>\r\n * { box-sizing: border-box; }\r\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 1200px; margin: 0 auto; }\r\n h1 { margin-bottom: 0.5rem; }\r\n .meta { color: #666; margin-bottom: 2rem; }\r\n .icon { width: 24px; height: 24px; fill: currentColor; }\r\n .icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 1rem; }\r\n .icon-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1rem; border: 1px solid #eee; border-radius: 8px; transition: background 0.2s; }\r\n .icon-item:hover { background: #f5f5f5; }\r\n .icon-name { font-size: 11px; color: #666; text-align: center; word-break: break-all; }\r\n pre { background: #f5f5f5; padding: 1rem; border-radius: 8px; overflow-x: auto; }\r\n code { font-family: ui-monospace, monospace; font-size: 13px; }\r\n </style>\r\n</head>\r\n<body>\r\n <h1>Icon Sprite Preview</h1>\r\n <p class=\"meta\">${icons.length} icons • Generated by @dsai-io/tools</p>\r\n\r\n <h2>Usage</h2>\r\n <pre><code>&lt;svg class=\"icon\"&gt;\r\n &lt;use href=\"${spriteFileName}#icon-name\"&gt;&lt;/use&gt;\r\n&lt;/svg&gt;</code></pre>\r\n\r\n <h2>All Icons</h2>\r\n <div class=\"icon-grid\">\r\n${icons\r\n .map(\r\n (icon) => ` <div class=\"icon-item\">\r\n <svg class=\"icon\"><use href=\"${spriteFileName}#${icon.name}\"></use></svg>\r\n <span class=\"icon-name\">${icon.name}</span>\r\n </div>`\r\n )\r\n .join('\\n')}\r\n </div>\r\n</body>\r\n</html>\r\n`;\r\n}\r\n","/**\r\n * Icon tooling module for @dsai-io/tools\r\n *\r\n * Provides utilities for generating icon components from SVG source files.\r\n * Supports React components, SVG sprites, with SVGO optimization.\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\nimport { join } from 'node:path';\r\n\r\nimport { optimizeSVGFiles, parseSVGFiles, scanSVGFiles } from './core/index.js';\r\nimport { generateReactIcons } from './generators/react.js';\r\nimport { generateSVGSprite } from './generators/svg-sprite.js';\r\n\r\nimport type {\r\n GeneratedIcon,\r\n IconBuildOptions,\r\n IconBuildResult,\r\n IconFormat,\r\n OptimizedSVG,\r\n SVGOConfig,\r\n} from './types.js';\r\nimport type { ResolvedConfig } from '../config/types.js';\r\n\r\n/**\r\n * Build icons from SVG source files\r\n *\r\n * Scans the source directory, parses and optimizes SVGs, then generates\r\n * output in the specified formats (React, SVG sprite).\r\n *\r\n * @param config - Resolved DSAi configuration\r\n * @param options - Build options\r\n * @returns Build result with generated files\r\n *\r\n * @example\r\n * ```typescript\r\n * import { loadConfig } from '@dsai-io/tools/config';\r\n * import { buildIcons } from '@dsai-io/tools/icons';\r\n *\r\n * const { config } = await loadConfig();\r\n * const result = await buildIcons(config, {\r\n * formats: ['react', 'svg-sprite'],\r\n * });\r\n *\r\n * console.log(\\`Generated \\${result.totalIcons} icons\\`);\r\n * ```\r\n */\r\nexport async function buildIcons(\r\n config: ResolvedConfig,\r\n options: IconBuildOptions = {}\r\n): Promise<IconBuildResult> {\r\n const startTime = Date.now();\r\n const defaultFormat = config.icons.framework === 'react' ? 'react' : 'svg-sprite';\r\n const { formats = [defaultFormat as IconFormat], icons: iconFilter, dryRun = false } = options;\r\n\r\n const result: IconBuildResult = {\r\n success: false,\r\n icons: [],\r\n totalIcons: 0,\r\n filesWritten: 0,\r\n totalSizeReduction: 0,\r\n errors: [],\r\n warnings: [],\r\n duration: 0,\r\n };\r\n\r\n try {\r\n // Step 1: Scan for SVG files\r\n const rawFiles = await scanSVGFiles({\r\n sourceDir: config.icons.sourceDir,\r\n });\r\n\r\n if (rawFiles.length === 0) {\r\n result.warnings.push({\r\n icon: '*',\r\n message: `No SVG files found in ${config.icons.sourceDir}`,\r\n });\r\n result.success = true;\r\n result.duration = Date.now() - startTime;\r\n return result;\r\n }\r\n\r\n // Filter by specific icons if provided\r\n const filteredFiles = iconFilter\r\n ? rawFiles.filter((f) => iconFilter.includes(f.fileName))\r\n : rawFiles;\r\n\r\n // Step 2: Parse SVG content\r\n const parsedFiles = parseSVGFiles(filteredFiles);\r\n\r\n // Step 3: Optimize SVGs (if enabled)\r\n let optimizedFiles: OptimizedSVG[];\r\n if (config.icons.optimize) {\r\n const svgoConfig: SVGOConfig = {\r\n multipass: true,\r\n };\r\n optimizedFiles = await optimizeSVGFiles(parsedFiles, filteredFiles, svgoConfig);\r\n\r\n // Calculate total size reduction\r\n const totalReduction = optimizedFiles.reduce((sum, f) => sum + f.sizeReduction, 0);\r\n result.totalSizeReduction =\r\n optimizedFiles.length > 0 ? totalReduction / optimizedFiles.length : 0;\r\n } else {\r\n // Skip optimization - just add size metadata\r\n const { skipOptimization } = await import('./core/optimizer.js');\r\n optimizedFiles = parsedFiles.map((parsed, index) => {\r\n const rawFile = filteredFiles.at(index);\r\n if (!rawFile) {\r\n throw new Error(`Missing raw file for ${parsed.fileName}`);\r\n }\r\n return skipOptimization(parsed, rawFile);\r\n });\r\n }\r\n\r\n result.totalIcons = optimizedFiles.length;\r\n\r\n // Step 4: Generate output for each format\r\n const generated: GeneratedIcon[] = [];\r\n\r\n for (const format of formats) {\r\n const outputDir = join(config.icons.outputDir, format);\r\n\r\n switch (format) {\r\n case 'react':\r\n generated.push(...(await generateReactIcons(optimizedFiles, outputDir, { dryRun })));\r\n break;\r\n\r\n case 'svg':\r\n case 'svg-sprite':\r\n generated.push(...(await generateSVGSprite(optimizedFiles, outputDir, { dryRun })));\r\n break;\r\n\r\n default:\r\n result.warnings.push({\r\n icon: '*',\r\n message: `Unknown format: ${format}`,\r\n });\r\n }\r\n }\r\n\r\n result.icons = generated;\r\n result.filesWritten = dryRun ? 0 : generated.length;\r\n result.success = true;\r\n } catch (error) {\r\n result.errors.push({\r\n icon: '*',\r\n message: error instanceof Error ? error.message : 'Unknown error',\r\n code: 'BUILD_ERROR',\r\n });\r\n }\r\n\r\n result.duration = Date.now() - startTime;\r\n return result;\r\n}\r\n\r\n// Re-export types\r\nexport type {\r\n GeneratedIcon,\r\n GeneratorOptions,\r\n IconBuildOptions,\r\n IconBuildResult,\r\n IconError,\r\n IconErrorCode,\r\n IconFormat,\r\n IconTemplate,\r\n IconWarning,\r\n IndexTemplate,\r\n OptimizedSVG,\r\n ParsedSVG,\r\n RawSVGData,\r\n ScannerOptions,\r\n SVGOConfig,\r\n SVGOPlugin,\r\n TypesTemplate,\r\n} from './types.js';\r\n\r\n// Re-export core utilities\r\nexport {\r\n cleanSVGForReact,\r\n defaultSVGOConfig,\r\n extractViewBox,\r\n optimizeSVG,\r\n optimizeSVGFiles,\r\n parseSVG,\r\n parseSVGFiles,\r\n readSVGFile,\r\n scanSVGFiles,\r\n skipOptimization,\r\n} from './core/index.js';\r\n\r\n// Re-export generators\r\nexport {\r\n defaultReactIndexTemplate,\r\n defaultReactTemplate,\r\n defaultReactTypesTemplate,\r\n generateReactIcons,\r\n generateSVGSprite,\r\n} from './generators/index.js';\r\n\r\n// Re-export naming utilities\r\nexport {\r\n isValidIconName,\r\n normalizeIconName,\r\n toComponentName,\r\n toIconName,\r\n} from './utils/index.js';\r\n"]}