svgfusion 1.6.0 → 1.8.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.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  **Transform SVG files into production-ready React and Vue 3 components**
7
7
 
8
- A powerful Node.js CLI tool and library that converts SVG files into optimized React and Vue components with complex SVG support, TypeScript integration, and smart optimization for modern development workflows.
8
+ A powerful Node.js CLI tool and library that converts SVG files into optimized React and Vue components with native SVG props inheritance, TypeScript integration, and smart optimization for modern development workflows.
9
9
 
10
10
  [![npm version](https://img.shields.io/npm/v/svgfusion)](https://www.npmjs.com/package/svgfusion)
11
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=flat&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
@@ -16,12 +16,22 @@ A powerful Node.js CLI tool and library that converts SVG files into optimized R
16
16
 
17
17
  </div>
18
18
 
19
+ ## What's New in v2.0
20
+
21
+ - **Custom SVGFusion Engine**: Complete rewrite with custom SVG parser replacing SVGR/SVGO
22
+ - **Native SVG Props**: Full React.SVGProps and Vue SVGAttributes support
23
+ - **Enhanced Type Safety**: Better TypeScript integration and type inference
24
+ - **Improved Performance**: Faster processing with streamlined architecture
25
+ - **Better Control**: Fine-grained control over SVG transformations and output
26
+
19
27
  ## Features
20
28
 
29
+ - **Native SVG Props**: Generated components extend React.SVGProps<SVGSVGElement> and Vue SVGAttributes
21
30
  - **Dual Framework Support**: Generate both React and Vue 3 components from the same SVG
31
+ - **Custom Engine**: Built-in SVGFusion engine for reliable SVG parsing and transformation
22
32
  - **Complex SVG Support**: Handles gradients, masks, filters, patterns, and Figma exports
23
33
  - **ID Collision Prevention**: Automatic unique ID generation for complex SVGs
24
- - **Optimized Output**: Built-in SVGO optimization with customizable settings
34
+ - **Optimized Output**: Smart optimization with customizable settings
25
35
  - **Icon Builder Ready**: Perfect for design systems and icon libraries
26
36
  - **TypeScript Ready**: Full TypeScript support with proper type definitions
27
37
  - **Flexible API**: Both CLI and programmatic usage
@@ -30,6 +40,14 @@ A powerful Node.js CLI tool and library that converts SVG files into optimized R
30
40
  - **Zero Configuration**: Works out of the box with sensible defaults
31
41
  - **Simple CLI**: Direct, intuitive command structure without subcommands
32
42
 
43
+ ### Advanced Features
44
+
45
+ - **Split Colors Mode**: Extract individual color props for maximum Tailwind CSS compatibility
46
+ - **Fixed Stroke Width**: Add `vector-effect="non-scaling-stroke"` support for consistent strokes
47
+ - **Duplicate Detection**: Automatic validation prevents component name conflicts
48
+ - **Gradient Support**: Full support for linearGradient and radialGradient color extraction
49
+ - **Smart Naming**: Intelligent component naming with conflict resolution suggestions
50
+
33
51
  ## Quick Start
34
52
 
35
53
  ### Simple as One Command
@@ -40,6 +58,9 @@ npx svgfusion ./icons --output ./components
40
58
 
41
59
  # Add prefixes, suffixes, and generate index file
42
60
  npx svgfusion ./icons --prefix Icon --suffix Component --index
61
+
62
+ # Advanced: Split colors for Tailwind CSS with fixed stroke width
63
+ npx svgfusion ./icons --split-colors --fixed-stroke-width --prefix Icon
43
64
  ```
44
65
 
45
66
  ### Installation
@@ -61,7 +82,7 @@ pnpm add svgfusion
61
82
 
62
83
  ## CLI Options
63
84
 
64
- <img src="https://i.ibb.co/TD0QP5FC/cli.png" alt="SVGFusion CLI" width="512" >
85
+ <img src="https://i.ibb.co/mfRb84x/cli.png" alt="SVGFusion CLI" width="512" >
65
86
 
66
87
  svgfusion ./icons --output ./components --prefix Icon --suffix Svg
67
88
 
@@ -129,6 +150,8 @@ Options:
129
150
  --no-optimize Skip SVG optimization
130
151
  --prefix <prefix> Add prefix to component name (sanitized)
131
152
  --suffix <suffix> Add suffix to component name (sanitized)
153
+ --split-colors Extract individual color props for each SVG color
154
+ --fixed-stroke-width Add support for non-scaling stroke width
132
155
  -h, --help Show help
133
156
  ```
134
157
 
@@ -151,6 +174,12 @@ npx svgfusion ./assets/icons --output ./src/components --recursive --index
151
174
 
152
175
  # Convert with custom naming
153
176
  npx svgfusion ./assets/icons --output ./src/components --prefix Icon --suffix Component --index
177
+
178
+ # Advanced: Split colors for Tailwind CSS compatibility
179
+ npx svgfusion ./assets/icons --output ./src/components --split-colors --prefix Icon
180
+
181
+ # Advanced: Fixed stroke width with split colors
182
+ npx svgfusion ./assets/icons --output ./src/components --split-colors --fixed-stroke-width
154
183
  ```
155
184
 
156
185
  ### Programmatic Usage
@@ -158,138 +187,163 @@ npx svgfusion ./assets/icons --output ./src/components --prefix Icon --suffix Co
158
187
  #### Single File Conversion
159
188
 
160
189
  ```typescript
161
- import { convertToReact, convertToVue, readSvgFile } from 'svgfusion';
190
+ import { SVGFusion, readFileSync } from 'svgfusion';
191
+
192
+ // Create SVGFusion engine instance
193
+ const engine = new SVGFusion();
162
194
 
163
195
  // Read SVG file
164
- const svgContent = await readSvgFile('./icons/star.svg');
196
+ const svgContent = readFileSync('./icons/star.svg', 'utf8');
165
197
 
166
- // React conversion
167
- const reactResult = await convertToReact(svgContent, {
168
- name: 'StarIcon',
198
+ // React conversion with native SVG props
199
+ const reactResult = engine.convert(svgContent, {
200
+ framework: 'react',
201
+ componentName: 'StarIcon',
169
202
  typescript: true,
170
- memo: true,
171
- ref: true,
203
+ features: {
204
+ colorSplitting: true,
205
+ strokeFixing: true,
206
+ accessibility: true,
207
+ },
172
208
  });
173
209
 
174
- // Vue conversion
175
- const vueResult = convertToVue(svgContent, {
176
- name: 'StarIcon',
210
+ // Vue conversion with native SVG attributes
211
+ const vueResult = engine.convert(svgContent, {
212
+ framework: 'vue',
213
+ componentName: 'StarIcon',
177
214
  typescript: true,
178
- scriptSetup: true,
215
+ features: {
216
+ colorSplitting: true,
217
+ strokeFixing: true,
218
+ accessibility: true,
219
+ },
179
220
  });
180
221
 
181
- console.log(reactResult.code); // Generated React component
182
- console.log(vueResult.code); // Generated Vue component
222
+ console.log(reactResult.code); // Generated React component with React.SVGProps
223
+ console.log(vueResult.code); // Generated Vue component with SVGAttributes
183
224
  ```
184
225
 
185
- #### Batch Processing
226
+ #### Batch Processing with CLI
186
227
 
187
228
  ```typescript
188
- import { BatchConverter } from 'svgfusion';
189
-
190
- const batchConverter = new BatchConverter();
229
+ import { processInput } from 'svgfusion/cli';
191
230
 
192
231
  // Convert entire directory
193
- const result = await batchConverter.convertBatch({
194
- inputDir: './icons',
195
- outputDir: './components',
232
+ processInput('./icons', {
233
+ output: './components',
196
234
  framework: 'react',
197
235
  recursive: true,
198
- generateIndex: true,
236
+ index: true,
199
237
  typescript: true,
200
238
  prefix: 'Icon',
201
239
  suffix: 'Component',
202
- indexFormat: 'ts',
203
- exportType: 'named',
240
+ splitColors: true,
241
+ fixedStrokeWidth: true,
204
242
  });
243
+ ```
205
244
 
206
- // Check results
207
- console.log(`Processed ${result.summary.total} files`);
208
- console.log(`Successful: ${result.summary.successful}`);
209
- console.log(`Failed: ${result.summary.failed}`);
245
+ ## API Reference
210
246
 
211
- // Get component names
212
- const componentNames = batchConverter.getComponentNames(result);
213
- console.log('Generated components:', componentNames);
247
+ ### `SVGFusion`
214
248
 
215
- // Generate summary report
216
- const report = batchConverter.generateSummaryReport(result);
217
- console.log(report);
218
- ```
249
+ The main engine class for converting SVG content to framework components.
219
250
 
220
- ## API Reference
251
+ ```typescript
252
+ import { SVGFusion } from 'svgfusion';
253
+
254
+ const engine = new SVGFusion();
255
+ ```
221
256
 
222
- ### `convertToReact(svgContent, options)`
257
+ #### `convert(svgContent: string, options: SVGFusionOptions): ConversionResult`
223
258
 
224
- Convert SVG to React component.
259
+ Convert SVG content to React or Vue component.
225
260
 
226
261
  **Options:**
227
262
 
228
- - `name?: string` - Component name (auto-generated from filename if not provided)
229
- - `prefix?: string` - Add prefix to component name
230
- - `suffix?: string` - Add suffix to component name
263
+ - `framework: 'react' | 'vue'` - Target framework
264
+ - `componentName?: string` - Component name (auto-generated from filename if not provided)
231
265
  - `typescript?: boolean` - Generate TypeScript component (default: `true`)
232
- - `memo?: boolean` - Wrap with React.memo (default: `true`)
233
- - `ref?: boolean` - Add forwardRef support (default: `true`)
234
- - `optimize?: boolean` - Apply SVGO optimization (default: `true`)
266
+ - `features?: FeatureConfig` - Enable/disable transformation features
267
+ - `colorSplitting?: boolean` - Extract individual color props (default: `false`)
268
+ - `strokeFixing?: boolean` - Add fixed stroke width support (default: `false`)
269
+ - `accessibility?: boolean` - Add accessibility enhancements (default: `true`)
235
270
 
236
- ### `convertToVue(svgContent, options)`
271
+ **Returns:** `ConversionResult`
237
272
 
238
- Convert SVG to Vue 3 component. **Note: This is a synchronous function.**
273
+ - `code: string` - Generated component code
274
+ - `framework: string` - Target framework
275
+ - `componentName: string` - Final component name
276
+ - `warnings: string[]` - Any conversion warnings
239
277
 
240
- **Options:**
278
+ ### React Components
241
279
 
242
- - `name?: string` - Component name (auto-generated from filename if not provided)
243
- - `prefix?: string` - Add prefix to component name
244
- - `suffix?: string` - Add suffix to component name
245
- - `typescript?: boolean` - Generate TypeScript component (default: `true`)
246
- - `scriptSetup?: boolean` - Use script setup syntax (default: `true`)
247
- - `compositionApi?: boolean` - Use Composition API (default: `true`)
248
- - `optimize?: boolean` - Apply SVGO optimization (default: `true`)
280
+ Generated React components automatically extend `React.SVGProps<SVGSVGElement>`, providing:
249
281
 
250
- ### `BatchConverter`
282
+ - All native SVG element props (onClick, onMouseOver, className, style, etc.)
283
+ - Full TypeScript support with proper type inference
284
+ - Native event handling and accessibility features
251
285
 
252
- Process multiple SVG files in batch operations.
286
+ ```tsx
287
+ // Generated component signature
288
+ interface StarIconProps extends React.SVGProps<SVGSVGElement> {
289
+ // Custom color props if colorSplitting is enabled
290
+ color1?: string;
291
+ color2?: string;
292
+ }
253
293
 
254
- #### `convertBatch(options: BatchConversionOptions)`
294
+ const StarIcon: React.FC<StarIconProps> = props => {
295
+ // Component implementation with native SVG props support
296
+ };
297
+ ```
255
298
 
256
- Convert multiple SVG files to framework components.
299
+ ### Vue Components
257
300
 
258
- **Options:**
301
+ Generated Vue components extend `SVGAttributes` with `v-bind="$attrs"`, providing:
259
302
 
260
- - `inputDir: string` - Input directory path
261
- - `outputDir: string` - Output directory path
262
- - `framework?: 'react' | 'vue'` - Target framework (default: 'react')
263
- - `recursive?: boolean` - Recursively scan directories (default: false)
264
- - `extensions?: string[]` - File extensions to process (default: ['.svg'])
265
- - `generateIndex?: boolean` - Generate index file (default: false)
266
- - `indexFormat?: 'ts' | 'js'` - Index file format (default: 'ts')
267
- - `exportType?: 'named' | 'default'` - Export type (default: 'named')
268
- - `prefix?: string` - Add prefix to component names
269
- - `suffix?: string` - Add suffix to component names
270
- - `typescript?: boolean` - Generate TypeScript components (default: true)
271
- - All other conversion options from `convertToReact`/`convertToVue`
303
+ - All native SVG element attributes
304
+ - Event handlers (onClick, onMouseover, etc.)
305
+ - Full TypeScript support with proper attribute typing
272
306
 
273
- **Returns:** `Promise<BatchConversionResult>`
307
+ ```vue
308
+ <script setup lang="ts">
309
+ import type { SVGAttributes } from 'vue';
274
310
 
275
- #### `getComponentNames(results: BatchConversionResult)`
311
+ interface StarIconProps extends SVGAttributes {
312
+ // Custom color props if colorSplitting is enabled
313
+ color1?: string;
314
+ color2?: string;
315
+ }
276
316
 
277
- Get array of generated component names from batch results.
317
+ defineOptions({ inheritAttrs: false });
318
+ </script>
278
319
 
279
- #### `generateSummaryReport(results: BatchConversionResult)`
320
+ <template>
321
+ <svg v-bind="$attrs" viewBox="0 0 24 24">
322
+ <!-- SVG content -->
323
+ </svg>
324
+ </template>
325
+ ```
280
326
 
281
- Generate a detailed summary report of the conversion process.
327
+ ### CLI Integration
282
328
 
283
- ### `optimizeSvg(svgContent, config?)`
329
+ ```typescript
330
+ import { processInput } from 'svgfusion/cli';
284
331
 
285
- Optimize SVG content using SVGO. **Note: This is a synchronous function.**
332
+ // Process single file or directory
333
+ processInput(inputPath: string, options: CliOptions): void
334
+ ```
286
335
 
287
- ### File Utilities
336
+ **CLI Options:**
288
337
 
289
- - `readSvgFile(filePath)` - Read SVG file (async)
290
- - `writeSvgFile(filePath, content)` - Write SVG file (async)
291
- - `readSvgDirectory(dirPath, recursive?)` - Read SVG files from directory (async)
292
- - `writeComponentFile(filePath, content)` - Write component file (async)
338
+ - `output?: string` - Output directory (default: './components')
339
+ - `framework?: 'react' | 'vue'` - Target framework (default: 'react')
340
+ - `typescript?: boolean` - Generate TypeScript files (default: true)
341
+ - `recursive?: boolean` - Process directories recursively (default: false)
342
+ - `index?: boolean` - Generate index file (default: false)
343
+ - `prefix?: string` - Add prefix to component names
344
+ - `suffix?: string` - Add suffix to component names
345
+ - `splitColors?: boolean` - Enable color splitting feature
346
+ - `fixedStrokeWidth?: boolean` - Enable stroke fixing feature
293
347
 
294
348
  ## Examples
295
349
 
@@ -305,29 +359,46 @@ Optimize SVG content using SVGO. **Note: This is a synchronous function.**
305
359
  ### Generated React Component
306
360
 
307
361
  ```tsx
308
- import { SVGProps } from 'react';
309
- import { memo } from 'react';
310
- import { forwardRef } from 'react';
311
-
312
- const StarIcon = memo(
313
- forwardRef<SVGSVGElement, SVGProps<SVGSVGElement> & { className?: string }>(
314
- props => {
315
- return (
316
- <svg viewBox="0 0 24 24" {...props}>
317
- <path
318
- d="m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z"
319
- fill="currentColor"
320
- className="star-fill"
321
- />
322
- </svg>
323
- );
324
- }
325
- )
326
- );
327
-
328
- StarIcon.displayName = 'StarIcon';
329
-
330
- export default StarIcon;
362
+ import type { SVGProps } from 'react';
363
+
364
+ interface StarIconProps extends SVGProps<SVGSVGElement> {}
365
+
366
+ const StarIcon = (props: StarIconProps) => {
367
+ return (
368
+ <svg viewBox="0 0 24 24" {...props}>
369
+ <path
370
+ d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
371
+ fill="currentColor"
372
+ className="star-fill"
373
+ />
374
+ </svg>
375
+ );
376
+ };
377
+
378
+ export { StarIcon };
379
+ ```
380
+
381
+ ### Generated React Component with Color Splitting
382
+
383
+ ```tsx
384
+ import type { SVGProps } from 'react';
385
+
386
+ interface StarIconProps extends SVGProps<SVGSVGElement> {
387
+ fillColor?: string;
388
+ }
389
+
390
+ const StarIcon = ({ fillColor = 'currentColor', ...props }: StarIconProps) => {
391
+ return (
392
+ <svg viewBox="0 0 24 24" {...props}>
393
+ <path
394
+ d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
395
+ fill={fillColor}
396
+ className="star-fill"
397
+ />
398
+ </svg>
399
+ );
400
+ };
401
+
331
402
  export { StarIcon };
332
403
  ```
333
404
 
@@ -335,18 +406,52 @@ export { StarIcon };
335
406
 
336
407
  ```vue
337
408
  <script setup lang="ts">
338
- interface Props {
339
- class?: string;
340
- style?: string | Record<string, any>;
409
+ import type { SVGAttributes } from 'vue';
410
+
411
+ interface StarIconProps extends SVGAttributes {}
412
+
413
+ defineOptions({ inheritAttrs: false });
414
+ </script>
415
+
416
+ <template>
417
+ <svg v-bind="$attrs" viewBox="0 0 24 24">
418
+ <path
419
+ d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
420
+ fill="currentColor"
421
+ class="star-fill"
422
+ />
423
+ </svg>
424
+ </template>
425
+ ```
426
+
427
+ ### Generated Vue Component with Color Splitting
428
+
429
+ ```vue
430
+ <script setup lang="ts">
431
+ import type { SVGAttributes } from 'vue';
432
+
433
+ interface StarIconProps extends SVGAttributes {
434
+ fillColor?: string;
341
435
  }
342
436
 
343
- const props = withDefaults(defineProps<Props>(), {
344
- class: '',
345
- style: undefined,
437
+ const props = withDefaults(defineProps<StarIconProps>(), {
438
+ fillColor: 'currentColor',
346
439
  });
347
440
 
348
- // Component name for debugging
349
- const __name = 'StarIcon';
441
+ defineOptions({ inheritAttrs: false });
442
+ </script>
443
+
444
+ <template>
445
+ <svg v-bind="$attrs" viewBox="0 0 24 24">
446
+ <path
447
+ d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
448
+ :fill="fillColor"
449
+ class="star-fill"
450
+ />
451
+ </svg>
452
+ </template>
453
+ ```
454
+
350
455
  </script>
351
456
 
352
457
  <template>
@@ -362,10 +467,82 @@ const __name = 'StarIcon';
362
467
  <style scoped>
363
468
  /* Add component-specific styles here */
364
469
  </style>
365
- ```
470
+
471
+ ````
366
472
 
367
473
  ## Advanced Configuration
368
474
 
475
+ ### Split Colors for Tailwind CSS
476
+
477
+ The `splitColors` option extracts individual color properties from SVG elements, making them perfect for Tailwind CSS integration:
478
+
479
+ ```typescript
480
+ // Input SVG with colors
481
+ const svgContent = `
482
+ <svg viewBox="0 0 24 24">
483
+ <path fill="#FF0000" stroke="#00FF00" />
484
+ <circle fill="#0000FF" />
485
+ <linearGradient>
486
+ <stop stop-color="#FFFF00" />
487
+ <stop stop-color="#FF00FF" />
488
+ </linearGradient>
489
+ </svg>
490
+ `;
491
+
492
+ // Convert with split colors
493
+ const result = await convertToReact(svgContent, {
494
+ name: 'MultiColorIcon',
495
+ splitColors: true,
496
+ typescript: true,
497
+ });
498
+
499
+ // Generated component props:
500
+ // - fillColor1, fillColor2 (for fill colors)
501
+ // - strokeColor1 (for stroke colors)
502
+ // - gradientColor1, gradientColor2 (for gradient colors)
503
+ // - fillColor1Class, strokeColor1Class, etc. (for CSS classes)
504
+ ````
505
+
506
+ ### Fixed Stroke Width Support
507
+
508
+ The `isFixedStrokeWidth` option adds support for non-scaling stroke width:
509
+
510
+ ```typescript
511
+ const result = await convertToReact(svgContent, {
512
+ name: 'StrokeIcon',
513
+ isFixedStrokeWidth: true,
514
+ });
515
+
516
+ // Generated component includes:
517
+ // - isFixedStrokeWidth prop
518
+ // - vector-effect="non-scaling-stroke" when prop is true
519
+ ```
520
+
521
+ ### Duplicate Name Detection
522
+
523
+ The batch converter automatically detects and prevents duplicate component names:
524
+
525
+ ```typescript
526
+ // These files would generate the same component name "Icon"
527
+ const files = ['./icons/icon.svg', './assets/icon.svg', './ui/icon.svg'];
528
+
529
+ // Batch processing will throw an error with conflict details
530
+ try {
531
+ await batchConverter.convertBatch({
532
+ inputDir: './icons',
533
+ outputDir: './components',
534
+ // ... other options
535
+ });
536
+ } catch (error) {
537
+ console.error(error.message);
538
+ // Error: Duplicate component names detected:
539
+ // Component name "Icon" conflicts:
540
+ // - ./icons/icon.svg
541
+ // - ./assets/icon.svg
542
+ // - ./ui/icon.svg
543
+ }
544
+ ```
545
+
369
546
  ### Custom SVGO Configuration
370
547
 
371
548
  ```typescript
package/dist/cli.d.ts CHANGED
@@ -1,2 +1 @@
1
-
2
- export { }
1
+ #!/usr/bin/env node