svgfusion 1.12.0 → 1.13.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.
Files changed (2) hide show
  1. package/README.md +110 -237
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -16,37 +16,33 @@ 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
19
+ ## What's New in v1.12.0
20
20
 
21
- - **Custom SVGFusion Engine**: Complete rewrite with custom SVG parser replacing SVGR/SVGO
21
+ - **Enhanced Color Splitting**: Smart color extraction with intelligent fill/stroke="none" handling
22
+ - **Improved CLI**: Streamlined command structure with better option handling
22
23
  - **Native SVG Props**: Full React.SVGProps and Vue SVGAttributes support
23
24
  - **Enhanced Type Safety**: Better TypeScript integration and type inference
24
- - **Improved Performance**: Faster processing with streamlined architecture
25
+ - **SVGFusion Engine**: Built-in SVG parser with reliable transformations
25
26
  - **Better Control**: Fine-grained control over SVG transformations and output
26
27
 
27
28
  ## Features
28
29
 
29
- - **Native SVG Props**: Generated components extend React.SVGProps<SVGSVGElement> and Vue SVGAttributes
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
32
- - **Complex SVG Support**: Handles gradients, masks, filters, patterns, and Figma exports
33
- - **ID Collision Prevention**: Automatic unique ID generation for complex SVGs
34
- - **Optimized Output**: Smart optimization with customizable settings
35
- - **Icon Builder Ready**: Perfect for design systems and icon libraries
36
- - **TypeScript Ready**: Full TypeScript support with proper type definitions
37
- - **Flexible API**: Both CLI and programmatic usage
38
- - **Batch Processing**: Convert entire directories of SVG files
39
- - **Production Ready**: Robust output with proper error handling
40
- - **Zero Configuration**: Works out of the box with sensible defaults
41
- - **Simple CLI**: Direct, intuitive command structure without subcommands
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
30
+ **Native SVG Props**: Generated components extend React.SVGProps<SVGSVGElement> and Vue SVGAttributes
31
+ **React & Vue Support**: Generate both React and Vue 3 components from the same SVG
32
+ **Complex SVG Support**: Handles gradients, masks, filters, patterns, and Figma exports
33
+ **TypeScript Ready**: Full TypeScript support with proper type definitions
34
+ **Batch Processing**: Convert entire directories of SVG files
35
+ **Production Ready**: Optimized output, error handling, and accessibility
36
+ **Simple CLI**: Direct, intuitive command structure
37
+
38
+ ### Color Splitting (splitColors)
39
+
40
+ Extracts all unique fill, stroke, and gradient colors from your SVG and generates props for each color and color class. Automatically adds `fill="none"` or `stroke="none"` to prevent unwanted browser defaults:
41
+
42
+ - Path with only fill gets `stroke="none"`
43
+ - Path with only stroke → gets `fill="none"`
44
+ - Path with both → keeps both as props
45
+ - Path with neither → stays unchanged
50
46
 
51
47
  ## Quick Start
52
48
 
@@ -127,34 +123,53 @@ svgfusion ./icons --output ./components --recursive
127
123
  # Generate index file for tree-shaking
128
124
  svgfusion ./icons --output ./components --index
129
125
 
130
- # Skip optimization
131
- svgfusion ./icons --output ./components --no-optimize
126
+ # Advanced: Split colors for maximum customization
127
+ svgfusion ./icons --output ./components --split-colors
128
+
129
+ # Advanced: Fixed stroke width with split colors
130
+ svgfusion ./icons --output ./components --split-colors --fixed-stroke-width
132
131
 
133
132
  # Using npx (no global install needed)
134
133
  npx svgfusion ./icons --output ./components --framework react
135
134
  ```
136
135
 
137
- ### CLI Options
136
+ ### Available CLI Options
138
137
 
139
138
  ```bash
140
139
  svgfusion <input> [options]
141
140
 
141
+ Arguments:
142
+ <input> SVG file or directory to convert
143
+
142
144
  Options:
143
- -o, --output <output> Output directory (default: "./components")
144
- -f, --framework <framework> Target framework (react|vue) (default: "react")
145
- -t, --typescript Generate TypeScript files
146
- -r, --recursive Recursively scan input directory for SVG files
147
- --index Generate index file for tree-shaking
148
- --index-format <format> Index file format (ts|js) (default: "ts")
149
- --export-type <type> Export type (named|default) (default: "named")
150
- --no-optimize Skip SVG optimization
151
- --prefix <prefix> Add prefix to component name (sanitized)
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
145
+ -o, --output <dir> Output directory for generated components (default: "./components")
146
+ -f, --framework <framework> Target framework: react or vue (default: "react")
147
+ --typescript Generate TypeScript components (default: true)
148
+ --javascript Generate JavaScript components
149
+ --split-colors Enable color splitting feature
150
+ --fixed-stroke-width Enable fixed stroke width feature
151
+ --memo Wrap component with React.memo (default: true)
152
+ --no-memo Disable React.memo wrapping
153
+ --forward-ref Enable forwardRef support (default: true)
154
+ --no-forward-ref Disable forwardRef support
155
+ -n, --name <name> Custom component name
156
+ --optimize Enable SVG optimization (default: true)
157
+ --no-optimize Disable SVG optimization
158
+ --recursive Process directories recursively
159
+ --prefix <prefix> Add prefix to component names
160
+ --suffix <suffix> Add suffix to component names
161
+ --index Generate index.ts file for directory processing
155
162
  -h, --help Show help
156
163
  ```
157
164
 
165
+ --prefix <prefix> Add prefix to component name (sanitized)
166
+ --suffix <suffix> Add suffix to component name (sanitized)
167
+ --split-colors Extract individual color props for each SVG color
168
+ --fixed-stroke-width Add support for non-scaling stroke width
169
+ -h, --help Show help
170
+
171
+ ````
172
+
158
173
  ### Using with npx (No Installation Required)
159
174
 
160
175
  Perfect for trying out SVGFusion or one-time conversions:
@@ -180,170 +195,30 @@ npx svgfusion ./assets/icons --output ./src/components --split-colors --prefix I
180
195
 
181
196
  # Advanced: Fixed stroke width with split colors
182
197
  npx svgfusion ./assets/icons --output ./src/components --split-colors --fixed-stroke-width
183
- ```
198
+ ````
184
199
 
185
200
  ### Programmatic Usage
186
201
 
187
202
  #### Single File Conversion
188
203
 
189
204
  ```typescript
190
- import { SVGFusion, readFileSync } from 'svgfusion';
205
+ import { SVGFusion } from 'svgfusion';
191
206
 
192
- // Create SVGFusion engine instance
193
207
  const engine = new SVGFusion();
208
+ const svgContent = `<svg viewBox="0 0 24 24"><path fill="#FF0000" stroke="#00FF00" d="..."/></svg>`;
194
209
 
195
- // Read SVG file
196
- const svgContent = readFileSync('./icons/star.svg', 'utf8');
197
-
198
- // React conversion with native SVG props
199
- const reactResult = engine.convert(svgContent, {
200
- framework: 'react',
201
- componentName: 'StarIcon',
202
- typescript: true,
203
- features: {
204
- colorSplitting: true,
205
- strokeFixing: true,
206
- accessibility: true,
207
- },
208
- });
209
-
210
- // Vue conversion with native SVG attributes
211
- const vueResult = engine.convert(svgContent, {
212
- framework: 'vue',
213
- componentName: 'StarIcon',
214
- typescript: true,
215
- features: {
216
- colorSplitting: true,
217
- strokeFixing: true,
218
- accessibility: true,
219
- },
210
+ const result = await engine.convert(svgContent, {
211
+ framework: 'react', // or 'vue'
212
+ transformation: { splitColors: true },
213
+ generator: { componentName: 'MyIcon', typescript: true },
220
214
  });
221
215
 
222
- console.log(reactResult.code); // Generated React component with React.SVGProps
223
- console.log(vueResult.code); // Generated Vue component with SVGAttributes
224
- ```
225
-
226
- #### Batch Processing with CLI
227
-
228
- ```typescript
229
- import { processInput } from 'svgfusion/cli';
230
-
231
- // Convert entire directory
232
- processInput('./icons', {
233
- output: './components',
234
- framework: 'react',
235
- recursive: true,
236
- index: true,
237
- typescript: true,
238
- prefix: 'Icon',
239
- suffix: 'Component',
240
- splitColors: true,
241
- fixedStrokeWidth: true,
242
- });
216
+ console.log(result.code); // The generated component code
243
217
  ```
244
218
 
245
219
  ## API Reference
246
220
 
247
- ### `SVGFusion`
248
-
249
- The main engine class for converting SVG content to framework components.
250
-
251
- ```typescript
252
- import { SVGFusion } from 'svgfusion';
253
-
254
- const engine = new SVGFusion();
255
- ```
256
-
257
- #### `convert(svgContent: string, options: SVGFusionOptions): ConversionResult`
258
-
259
- Convert SVG content to React or Vue component.
260
-
261
- **Options:**
262
-
263
- - `framework: 'react' | 'vue'` - Target framework
264
- - `componentName?: string` - Component name (auto-generated from filename if not provided)
265
- - `typescript?: boolean` - Generate TypeScript component (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`)
270
-
271
- **Returns:** `ConversionResult`
272
-
273
- - `code: string` - Generated component code
274
- - `framework: string` - Target framework
275
- - `componentName: string` - Final component name
276
- - `warnings: string[]` - Any conversion warnings
277
-
278
- ### React Components
279
-
280
- Generated React components automatically extend `React.SVGProps<SVGSVGElement>`, providing:
281
-
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
285
-
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
- }
293
-
294
- const StarIcon: React.FC<StarIconProps> = props => {
295
- // Component implementation with native SVG props support
296
- };
297
- ```
298
-
299
- ### Vue Components
300
-
301
- Generated Vue components extend `SVGAttributes` with `v-bind="$attrs"`, providing:
302
-
303
- - All native SVG element attributes
304
- - Event handlers (onClick, onMouseover, etc.)
305
- - Full TypeScript support with proper attribute typing
306
-
307
- ```vue
308
- <script setup lang="ts">
309
- import type { SVGAttributes } from 'vue';
310
-
311
- interface StarIconProps extends SVGAttributes {
312
- // Custom color props if colorSplitting is enabled
313
- color1?: string;
314
- color2?: string;
315
- }
316
-
317
- defineOptions({ inheritAttrs: false });
318
- </script>
319
-
320
- <template>
321
- <svg v-bind="$attrs" viewBox="0 0 24 24">
322
- <!-- SVG content -->
323
- </svg>
324
- </template>
325
- ```
326
-
327
- ### CLI Integration
328
-
329
- ```typescript
330
- import { processInput } from 'svgfusion/cli';
331
-
332
- // Process single file or directory
333
- processInput(inputPath: string, options: CliOptions): void
334
- ```
335
-
336
- **CLI Options:**
337
-
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
221
+ For the complete API documentation, visit [svgfusion.netlify.app](https://svgfusion.netlify.app/docs/api-reference).
347
222
 
348
223
  ## Examples
349
224
 
@@ -472,20 +347,18 @@ defineOptions({ inheritAttrs: false });
472
347
 
473
348
  ## Advanced Configuration
474
349
 
475
- ### Split Colors for Tailwind CSS
350
+ ### Split Colors with Intelligent Attribute Handling
476
351
 
477
- The `splitColors` option extracts individual color properties from SVG elements, making them perfect for Tailwind CSS integration:
352
+ The `splitColors` option extracts individual color properties from SVG elements and intelligently manages fill/stroke attributes:
478
353
 
479
354
  ```typescript
480
- // Input SVG with colors
355
+ // Input SVG with mixed attributes
481
356
  const svgContent = `
482
357
  <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>
358
+ <path fill="#FF0000" d="..." /> <!-- Has fill only -->
359
+ <path stroke="#00FF00" d="..." /> <!-- Has stroke only -->
360
+ <path fill="#0000FF" stroke="#FFFF00" /> <!-- Has both -->
361
+ <path d="..." /> <!-- Has neither -->
489
362
  </svg>
490
363
  `;
491
364
 
@@ -496,11 +369,31 @@ const result = await convertToReact(svgContent, {
496
369
  typescript: true,
497
370
  });
498
371
 
372
+ // Generated component behavior:
373
+ // - Path with fill only: gets stroke="none" (prevents unwanted stroke)
374
+ // - Path with stroke only: gets fill="none" (prevents black fill default)
375
+ // - Path with both: keeps both as dynamic props
376
+ // - Path with neither: remains unchanged (no unnecessary attributes)
377
+
499
378
  // 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)
379
+ // - color, color2, color3 (for extracted colors in order)
380
+ // - colorClass, color2Class, color3Class (for CSS classes)
381
+ // - Colors are automatically converted to hex format
382
+ ```
383
+
384
+ **Color Extraction Rules:**
385
+ - Colors are extracted from `fill`, `stroke`, and `stop-color` attributes
386
+ - All colors are converted to lowercase hex format (e.g., `#ff0000`)
387
+ - Empty or invalid color values are ignored
388
+ - Duplicate colors are automatically deduplicated
389
+ - Colors are assigned as `color`, `color2`, `color3`, etc. in order
390
+
391
+ **Intelligent Attribute Handling:**
392
+ - Elements with `fill` only → adds `stroke="none"`
393
+ - Elements with `stroke` only → adds `fill="none"`
394
+ - Elements with both `fill` and `stroke` → keeps both as props
395
+ - Elements with neither → no attributes added
396
+ - Empty attribute values (`fill=""`) are treated as non-existent
504
397
  ````
505
398
 
506
399
  ### Fixed Stroke Width Support
@@ -518,31 +411,6 @@ const result = await convertToReact(svgContent, {
518
411
  // - vector-effect="non-scaling-stroke" when prop is true
519
412
  ```
520
413
 
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
-
546
414
  ### Custom SVGO Configuration
547
415
 
548
416
  ```typescript
@@ -557,25 +425,30 @@ const customConfig = createSvgoConfig({
557
425
  const optimizedSvg = optimizeSvg(svgContent, customConfig);
558
426
  ```
559
427
 
560
- ### Manual Batch Processing
428
+ ### Batch Processing with SVGFusion Engine
561
429
 
562
430
  ```typescript
563
- import {
564
- readSvgDirectory,
565
- convertToReact,
566
- writeComponentFile,
567
- } from 'svgfusion';
431
+ import { SVGFusion, readSvgDirectory } from 'svgfusion';
432
+ import { writeFileSync } from 'fs';
433
+ import path from 'path';
568
434
 
435
+ const engine = new SVGFusion();
569
436
  const svgFiles = await readSvgDirectory('./icons', true); // recursive
570
437
 
571
438
  for (const svgFile of svgFiles) {
572
- const svgContent = await readSvgFile(svgFile);
573
- const result = await convertToReact(svgContent, {
574
- name: path.basename(svgFile, '.svg'),
575
- prefix: 'Icon',
439
+ const svgContent = readFileSync(svgFile, 'utf-8');
440
+ const result = await engine.convert(svgContent, {
441
+ framework: 'react',
442
+ generator: {
443
+ componentName: path.basename(svgFile, '.svg'),
444
+ typescript: true,
445
+ },
446
+ transformation: {
447
+ splitColors: true,
448
+ },
576
449
  });
577
450
 
578
- await writeComponentFile(`./components/${result.filename}`, result.code);
451
+ writeFileSync(`./components/${result.filename}`, result.code);
579
452
  }
580
453
  ```
581
454
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svgfusion",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "A powerful CLI tool and library that converts SVG files into production-ready React and Vue 3 components with native SVG props inheritance, TypeScript support, and custom SVGFusion engine.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",