svger-cli 2.0.2 → 2.0.4
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/.svgerconfig.example.json +119 -0
- package/CHANGELOG.md +64 -0
- package/DEVELOPMENT.md +353 -0
- package/README.md +430 -209
- package/SECURITY.md +69 -0
- package/dist/builder.js +16 -16
- package/dist/clean.js +2 -2
- package/dist/cli.js +38 -38
- package/dist/config.js +95 -12
- package/dist/core/error-handler.js +12 -9
- package/dist/core/framework-templates.js +5 -3
- package/dist/core/performance-engine.js +9 -8
- package/dist/core/plugin-manager.js +7 -5
- package/dist/core/style-compiler.js +17 -15
- package/dist/core/template-manager.js +14 -14
- package/dist/index.d.ts +8 -6
- package/dist/index.js +5 -5
- package/dist/lock.js +7 -7
- package/dist/processors/svg-processor.d.ts +9 -3
- package/dist/processors/svg-processor.js +56 -18
- package/dist/services/config.js +72 -20
- package/dist/services/file-watcher.js +3 -3
- package/dist/services/svg-service.js +34 -30
- package/dist/templates/ComponentTemplate.js +25 -25
- package/dist/types/index.d.ts +77 -19
- package/dist/utils/native.d.ts +32 -1
- package/dist/utils/native.js +47 -8
- package/dist/watch.d.ts +1 -1
- package/dist/watch.js +14 -14
- package/docs/ADR-SVG-INTRGRATION-METHODS-001.adr.md +157 -0
- package/docs/ADR-SVG-INTRGRATION-METHODS-002.adr.md +550 -0
- package/docs/FRAMEWORK-GUIDE.md +768 -0
- package/docs/IMPLEMENTATION-SUMMARY.md +376 -0
- package/docs/TDR-SVG-INTRGRATION-METHODS-001.tdr.md +115 -0
- package/package.json +155 -14
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Multi-Framework Implementation Summary
|
|
2
|
+
|
|
3
|
+
## 🎯 Project Objectives
|
|
4
|
+
|
|
5
|
+
Transform svger-cli from a React-only SVG component generator into a **universal, multi-framework SVG processing toolkit** supporting 8 modern UI frameworks with professional engineering standards.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✅ Completed Features
|
|
10
|
+
|
|
11
|
+
### 1. Framework Support (8 Frameworks)
|
|
12
|
+
|
|
13
|
+
| Framework | Status | File Extension | Key Features |
|
|
14
|
+
|-----------|--------|----------------|--------------|
|
|
15
|
+
| **React** | ✅ Complete | `.tsx/.jsx` | forwardRef, memo, TypeScript props |
|
|
16
|
+
| **Vue 3** | ✅ Complete | `.vue` | Composition API, Options API, `<script setup>` |
|
|
17
|
+
| **Svelte** | ✅ Complete | `.svelte` | TypeScript props, reactive bindings |
|
|
18
|
+
| **Angular** | ✅ Complete | `.component.ts` | Standalone, OnPush, Input decorators |
|
|
19
|
+
| **Solid** | ✅ Complete | `.tsx/.jsx` | Component types, reactive primitives |
|
|
20
|
+
| **Preact** | ✅ Complete | `.tsx/.jsx` | Lightweight JSX, FunctionComponent |
|
|
21
|
+
| **Lit** | ✅ Complete | `.ts/.js` | Web Components, decorators, shadow DOM |
|
|
22
|
+
| **Vanilla** | ✅ Complete | `.ts/.js` | Factory functions, DOM API |
|
|
23
|
+
|
|
24
|
+
### 2. Core Architecture
|
|
25
|
+
|
|
26
|
+
✅ **FrameworkTemplateEngine** (`src/core/framework-templates.ts`)
|
|
27
|
+
- Single class managing all 8 framework generators
|
|
28
|
+
- Framework-specific code generation with best practices
|
|
29
|
+
- SVG attribute parsing and processing
|
|
30
|
+
- File extension determination per framework
|
|
31
|
+
|
|
32
|
+
✅ **Type System** (`src/types/index.ts`)
|
|
33
|
+
- `FrameworkType`: Union type for all frameworks
|
|
34
|
+
- `FrameworkOptions`: Framework-specific configuration
|
|
35
|
+
- `ComponentGenerationOptions`: Unified generation interface
|
|
36
|
+
|
|
37
|
+
✅ **Configuration Management** (`src/services/config.ts`)
|
|
38
|
+
- Default framework settings
|
|
39
|
+
- Framework options support
|
|
40
|
+
- Configuration merging and validation
|
|
41
|
+
|
|
42
|
+
✅ **SVG Processing** (`src/processors/svg-processor.ts`)
|
|
43
|
+
- Framework-agnostic processing pipeline
|
|
44
|
+
- Dynamic file extension generation
|
|
45
|
+
- Framework template engine integration
|
|
46
|
+
|
|
47
|
+
### 3. CLI Enhancement
|
|
48
|
+
|
|
49
|
+
✅ **New Options**:
|
|
50
|
+
```bash
|
|
51
|
+
--framework <type> # react|vue|svelte|angular|solid|preact|lit|vanilla
|
|
52
|
+
--typescript # Generate TypeScript (default: true)
|
|
53
|
+
--no-typescript # Generate JavaScript
|
|
54
|
+
--composition # Vue Composition API
|
|
55
|
+
--standalone # Angular standalone components
|
|
56
|
+
--signals # Angular/Solid signals
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
✅ **Updated Commands**:
|
|
60
|
+
- `build`: Multi-framework support with options
|
|
61
|
+
- `generate`: Single-file framework conversion
|
|
62
|
+
- `watch`: Framework-aware auto-rebuild
|
|
63
|
+
|
|
64
|
+
### 4. Testing & Validation
|
|
65
|
+
|
|
66
|
+
✅ **Automated Test Suite** (`test-frameworks.js`)
|
|
67
|
+
- 10 test variants covering all frameworks
|
|
68
|
+
- Framework-specific validation rules
|
|
69
|
+
- Component generation verification
|
|
70
|
+
- File extension checks
|
|
71
|
+
- **Result**: 10/10 tests passing ✅
|
|
72
|
+
|
|
73
|
+
✅ **Manual Testing**:
|
|
74
|
+
- CLI tested with Vue, Angular, Svelte
|
|
75
|
+
- Real SVG files converted successfully
|
|
76
|
+
- Correct file extensions verified
|
|
77
|
+
- Component code quality validated
|
|
78
|
+
|
|
79
|
+
### 5. Documentation
|
|
80
|
+
|
|
81
|
+
✅ **FRAMEWORK-GUIDE.md**
|
|
82
|
+
- Complete usage guide for all 8 frameworks
|
|
83
|
+
- Framework-specific code examples
|
|
84
|
+
- Configuration documentation
|
|
85
|
+
- CLI reference with examples
|
|
86
|
+
|
|
87
|
+
✅ **TESTING.md**
|
|
88
|
+
- Automated testing instructions
|
|
89
|
+
- Manual testing procedures
|
|
90
|
+
- Expected test results
|
|
91
|
+
- Framework validation criteria
|
|
92
|
+
|
|
93
|
+
✅ **Code Documentation**
|
|
94
|
+
- JSDoc comments on key classes
|
|
95
|
+
- Inline code explanations
|
|
96
|
+
- Type definitions with descriptions
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🏗️ Technical Implementation
|
|
101
|
+
|
|
102
|
+
### Key Files Modified
|
|
103
|
+
|
|
104
|
+
1. **src/core/framework-templates.ts** (NEW - 426 lines)
|
|
105
|
+
- FrameworkTemplateEngine class
|
|
106
|
+
- 8 private generator methods
|
|
107
|
+
- SVG parsing utilities
|
|
108
|
+
- File extension determination
|
|
109
|
+
|
|
110
|
+
2. **src/types/index.ts** (UPDATED)
|
|
111
|
+
- Added FrameworkType union
|
|
112
|
+
- Added FrameworkOptions interface
|
|
113
|
+
- Updated ComponentGenerationOptions
|
|
114
|
+
|
|
115
|
+
3. **src/cli.ts** (UPDATED)
|
|
116
|
+
- Added framework CLI options
|
|
117
|
+
- Updated build command
|
|
118
|
+
- Updated generate command
|
|
119
|
+
|
|
120
|
+
4. **src/services/config.ts** (UPDATED)
|
|
121
|
+
- Framework defaults
|
|
122
|
+
- frameworkOptions support
|
|
123
|
+
|
|
124
|
+
5. **src/processors/svg-processor.ts** (UPDATED)
|
|
125
|
+
- Framework template engine integration
|
|
126
|
+
- Dynamic file extensions
|
|
127
|
+
- Framework-aware processing
|
|
128
|
+
|
|
129
|
+
6. **src/services/svg-service.ts** (UPDATED)
|
|
130
|
+
- Framework config passing
|
|
131
|
+
- CLI option support
|
|
132
|
+
|
|
133
|
+
### Zero-Dependency Approach
|
|
134
|
+
|
|
135
|
+
✅ **Native Node.js APIs Only**
|
|
136
|
+
- No new external dependencies added
|
|
137
|
+
- File operations via native `fs` module
|
|
138
|
+
- String processing with native methods
|
|
139
|
+
- Template string generation
|
|
140
|
+
|
|
141
|
+
✅ **Performance Optimizations**
|
|
142
|
+
- Single template engine instance
|
|
143
|
+
- Efficient string concatenation
|
|
144
|
+
- Minimal regex operations
|
|
145
|
+
- Framework-specific code paths
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 📊 Test Results
|
|
150
|
+
|
|
151
|
+
### Automated Tests (test-frameworks.js)
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
Total Tests: 10
|
|
155
|
+
✅ Passed: 10
|
|
156
|
+
❌ Failed: 0
|
|
157
|
+
|
|
158
|
+
Frameworks Tested:
|
|
159
|
+
✅ React
|
|
160
|
+
✅ Vue (Composition API)
|
|
161
|
+
✅ Vue (Options API)
|
|
162
|
+
✅ Svelte
|
|
163
|
+
✅ Angular (Standalone)
|
|
164
|
+
✅ Angular (Module)
|
|
165
|
+
✅ Solid
|
|
166
|
+
✅ Preact
|
|
167
|
+
✅ Lit
|
|
168
|
+
✅ Vanilla
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Manual CLI Tests
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Vue Composition API
|
|
175
|
+
✅ svger-cli build my-svgs cli-test-output --framework vue --composition
|
|
176
|
+
→ Generated .vue files with <script setup>
|
|
177
|
+
|
|
178
|
+
# Angular Standalone
|
|
179
|
+
✅ svger-cli build my-svgs cli-test-angular --framework angular --standalone
|
|
180
|
+
→ Generated .component.ts with standalone: true
|
|
181
|
+
|
|
182
|
+
# Svelte TypeScript
|
|
183
|
+
✅ svger-cli build my-svgs cli-test-svelte --framework svelte
|
|
184
|
+
→ Generated .svelte files with TypeScript
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 🎨 Framework-Specific Features
|
|
190
|
+
|
|
191
|
+
### React
|
|
192
|
+
- `React.forwardRef` for ref forwarding
|
|
193
|
+
- TypeScript prop interfaces
|
|
194
|
+
- Size prop for convenience
|
|
195
|
+
- className and style support
|
|
196
|
+
|
|
197
|
+
### Vue 3
|
|
198
|
+
- Composition API with `<script setup>`
|
|
199
|
+
- Options API support
|
|
200
|
+
- Reactive bindings (`:class`, `:style`)
|
|
201
|
+
- `v-bind="$attrs"` for prop spreading
|
|
202
|
+
|
|
203
|
+
### Svelte
|
|
204
|
+
- TypeScript prop types (`export let`)
|
|
205
|
+
- Reactive bindings (`{width}`, `{height}`)
|
|
206
|
+
- Rest props (`{...$$restProps}`)
|
|
207
|
+
- Native TypeScript support
|
|
208
|
+
|
|
209
|
+
### Angular
|
|
210
|
+
- Standalone components (Angular 16+)
|
|
211
|
+
- `ChangeDetectionStrategy.OnPush`
|
|
212
|
+
- Input decorators with defaults
|
|
213
|
+
- Attribute binding (`[attr.class]`)
|
|
214
|
+
|
|
215
|
+
### Solid
|
|
216
|
+
- Component JSX types
|
|
217
|
+
- Reactive props
|
|
218
|
+
- Class and style bindings
|
|
219
|
+
- Props spreading
|
|
220
|
+
|
|
221
|
+
### Preact
|
|
222
|
+
- FunctionComponent type
|
|
223
|
+
- JSX namespace
|
|
224
|
+
- Lightweight API
|
|
225
|
+
- Compatible with React patterns
|
|
226
|
+
|
|
227
|
+
### Lit
|
|
228
|
+
- Web Components standard
|
|
229
|
+
- Custom element decorators
|
|
230
|
+
- Reactive properties
|
|
231
|
+
- Shadow DOM support
|
|
232
|
+
|
|
233
|
+
### Vanilla
|
|
234
|
+
- Factory function pattern
|
|
235
|
+
- DOM API usage
|
|
236
|
+
- SVG namespace handling
|
|
237
|
+
- Attribute manipulation
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 📁 Project Structure
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
svger-cli/
|
|
245
|
+
├── src/
|
|
246
|
+
│ ├── core/
|
|
247
|
+
│ │ └── framework-templates.ts # Multi-framework generator
|
|
248
|
+
│ ├── types/
|
|
249
|
+
│ │ └── index.ts # Framework types
|
|
250
|
+
│ ├── cli.ts # CLI with framework options
|
|
251
|
+
│ ├── processors/
|
|
252
|
+
│ │ └── svg-processor.ts # Framework-aware processing
|
|
253
|
+
│ └── services/
|
|
254
|
+
│ ├── config.ts # Framework configuration
|
|
255
|
+
│ └── svg-service.ts # Framework integration
|
|
256
|
+
├── test-frameworks.js # Automated test suite
|
|
257
|
+
├── FRAMEWORK-GUIDE.md # Complete usage guide
|
|
258
|
+
├── TESTING.md # Testing documentation
|
|
259
|
+
└── test-output/ # Generated test components
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## 🚀 Usage Examples
|
|
265
|
+
|
|
266
|
+
### Basic Usage
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Default (React)
|
|
270
|
+
svger-cli build ./svgs ./components
|
|
271
|
+
|
|
272
|
+
# Vue with Composition API
|
|
273
|
+
svger-cli build ./svgs ./components --framework vue --composition
|
|
274
|
+
|
|
275
|
+
# Angular Standalone
|
|
276
|
+
svger-cli build ./svgs ./components --framework angular --standalone
|
|
277
|
+
|
|
278
|
+
# Svelte TypeScript
|
|
279
|
+
svger-cli build ./svgs ./components --framework svelte
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Programmatic API
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { frameworkTemplateEngine } from 'svger-cli';
|
|
286
|
+
|
|
287
|
+
const component = frameworkTemplateEngine.generateComponent({
|
|
288
|
+
framework: 'vue',
|
|
289
|
+
componentName: 'MyIcon',
|
|
290
|
+
svgContent: '<svg>...</svg>',
|
|
291
|
+
typescript: true,
|
|
292
|
+
frameworkOptions: { scriptSetup: true }
|
|
293
|
+
});
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 🎯 Quality Metrics
|
|
299
|
+
|
|
300
|
+
✅ **Code Quality**
|
|
301
|
+
- TypeScript strict mode compliant
|
|
302
|
+
- Zero ESLint errors
|
|
303
|
+
- Comprehensive type coverage
|
|
304
|
+
- Clean separation of concerns
|
|
305
|
+
|
|
306
|
+
✅ **Testing Coverage**
|
|
307
|
+
- All 8 frameworks tested
|
|
308
|
+
- 10 test variants
|
|
309
|
+
- Framework-specific validation
|
|
310
|
+
- Real-world SVG processing
|
|
311
|
+
|
|
312
|
+
✅ **Documentation**
|
|
313
|
+
- Complete API documentation
|
|
314
|
+
- Framework-specific guides
|
|
315
|
+
- Usage examples for all frameworks
|
|
316
|
+
- Testing procedures
|
|
317
|
+
|
|
318
|
+
✅ **Performance**
|
|
319
|
+
- Zero new dependencies
|
|
320
|
+
- Efficient code generation
|
|
321
|
+
- Minimal memory footprint
|
|
322
|
+
- Fast compilation
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## 🔄 Migration Path
|
|
327
|
+
|
|
328
|
+
For existing users:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Before (React only)
|
|
332
|
+
svger-cli build ./svgs ./components
|
|
333
|
+
|
|
334
|
+
# After (still works - React is default)
|
|
335
|
+
svger-cli build ./svgs ./components
|
|
336
|
+
|
|
337
|
+
# New capability
|
|
338
|
+
svger-cli build ./svgs ./components --framework vue
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
**Backward Compatibility**: 100% maintained ✅
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 📝 Commit History
|
|
346
|
+
|
|
347
|
+
```
|
|
348
|
+
feat: Complete multi-framework support for all 8 UI frameworks
|
|
349
|
+
|
|
350
|
+
- Implemented comprehensive framework support: React, Vue, Svelte, Angular, Solid, Preact, Lit, Vanilla JS
|
|
351
|
+
- Created FrameworkTemplateEngine with framework-specific generators
|
|
352
|
+
- Added CLI options: --framework, --typescript, --composition, --standalone
|
|
353
|
+
- Updated types system with FrameworkType and FrameworkOptions
|
|
354
|
+
- Enhanced config service with framework defaults
|
|
355
|
+
- Fixed file extension generation based on framework
|
|
356
|
+
- Created comprehensive testing suite (test-frameworks.js)
|
|
357
|
+
- Added framework documentation (FRAMEWORK-GUIDE.md, TESTING.md)
|
|
358
|
+
- All 10 test variants passing successfully
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## 🎉 Achievement Summary
|
|
364
|
+
|
|
365
|
+
**SVGER-CLI v2.0** is now a **professional, enterprise-grade, multi-framework SVG processing toolkit** that:
|
|
366
|
+
|
|
367
|
+
✅ Supports 8 modern UI frameworks
|
|
368
|
+
✅ Maintains zero external dependencies
|
|
369
|
+
✅ Follows framework best practices
|
|
370
|
+
✅ Provides comprehensive documentation
|
|
371
|
+
✅ Includes automated testing
|
|
372
|
+
✅ Maintains backward compatibility
|
|
373
|
+
✅ Uses TypeScript for type safety
|
|
374
|
+
✅ Generates idiomatic, production-ready code
|
|
375
|
+
|
|
376
|
+
**All requirements met. Implementation complete and tested.** 🚀
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Technical Design Report: SVG Integration Methods in React (TDR)
|
|
2
|
+
|
|
3
|
+
# Version: 0.0.1
|
|
4
|
+
|
|
5
|
+
# Date: 10/13/25
|
|
6
|
+
|
|
7
|
+
# Owner: engineer Ehsan jafari
|
|
8
|
+
|
|
9
|
+
# Attendees: Navid Rezadoost , Faeze Mohadespor , Amir Bazgir , Ehsan Jafari
|
|
10
|
+
|
|
11
|
+
# Link : https://docs.google.com/document/d/1b04_V01xOvLiSMzuPdaRynANlnt2wYdJ_vjs9MAqtn4/edit?tab=t.0
|
|
12
|
+
|
|
13
|
+
## 1\. Introduction
|
|
14
|
+
|
|
15
|
+
This document compares five common methods for integrating and managing SVG icons in React projects. The goal is to provide a detailed guide for choosing the appropriate method considering **performance, maintainability, flexibility, and bundle size**.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2\. Methods
|
|
20
|
+
|
|
21
|
+
### Method 1: Loading SVGs from the Public Folder (Runtime Fetch)
|
|
22
|
+
|
|
23
|
+
SVG files are stored in public/assets/icons/svg/ and fetched at runtime.
|
|
24
|
+
|
|
25
|
+
| function SvgIcon({ name, ...props }) { const \[svg, setSvg\] \= React.useState(null); React.useEffect(() \=\> { fetch(\`/assets/icons/svg/${name}.svg\`) .then(res \=\> res.text()) .then(setSvg); }, \[name\]); return svg ? ( \<span {...props} dangerouslySetInnerHTML={{ \_\_html: svg }} /\> ) : null;} |
|
|
26
|
+
| :---- |
|
|
27
|
+
|
|
28
|
+
**Pros:** \- ✅ Small bundle size \- ✅ Easy icon replacement without rebuild \- ✅ Suitable for dynamic icon sets
|
|
29
|
+
|
|
30
|
+
**Cons:** \- ⚠️ Network request at runtime (slower) \- ⚠️ Cannot directly apply props to SVG \- ⚠️ Requires async logic (useEffect \+ useState)
|
|
31
|
+
|
|
32
|
+
**Performance:** CPU low | RAM low | Build Time fast
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### Method 2: Using SVGR
|
|
37
|
+
|
|
38
|
+
SVG files are converted to React components with props.
|
|
39
|
+
|
|
40
|
+
| import { ReactComponent as StarIcon } from './icons/star.svg';export const Example \= () \=\> \<StarIcon width={24} height={24} fill="gold" /\>; |
|
|
41
|
+
| :---- |
|
|
42
|
+
|
|
43
|
+
**Pros:** \- ✅ Direct prop manipulation \- ✅ Easy bundler integration \- ✅ Automatic SVG optimization
|
|
44
|
+
|
|
45
|
+
**Cons:** \- ⚠️ All SVGs included in bundle → increases size \- ⚠️ Rebuild can overwrite manual changes \- ⚠️ Slightly longer build time
|
|
46
|
+
|
|
47
|
+
**Performance:** CPU moderate | RAM higher during build | Build Time slightly slower
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
### Method 3: Custom svg-to-react Script
|
|
52
|
+
|
|
53
|
+
Automatically converts all SVG files to React components with new and all modes.
|
|
54
|
+
|
|
55
|
+
| yarn svg-to-react:all\# oryarn svg-to-react:new |
|
|
56
|
+
| :---- |
|
|
57
|
+
|
|
58
|
+
Script:
|
|
59
|
+
|
|
60
|
+
| import fs from "fs";import path from "path";import { fileURLToPath } from "url";const \_\_filename \= fileURLToPath(import.meta.url);const \_\_dirname \= path.dirname(\_\_filename);const inputDir \= path.join(\_\_dirname, "../public/assets/icons/svg");const outputDir \= path.join(\_\_dirname, "../public/assets/icons/svgComponent");if (\!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });// Get argument from command line// 'new' \=\> only new files// 'all' \=\> rebuild all files (except MANUAL\_EDIT)const mode \= process.argv\[2\] || "all";const files \= fs.readdirSync(inputDir).filter((f) \=\> f.endsWith(".svg"));for (const file of files) { const componentName \= path.basename(file, ".svg").replace(/\[^a-zA-Z0-9\]/g, "\_") \+ "Icon"; const outputPath \= path.join(outputDir, \`${componentName}.jsx\`); // Check if file exists and MANUAL\_EDIT comment if (fs.existsSync(outputPath)) { const existingContent \= fs.readFileSync(outputPath, "utf8"); if (existingContent.includes("// MANUAL\_EDIT")) { console.log(\`✋ Skipped manual icon: ${componentName}\`); continue; } if (mode \=== "new") { console.log(\`⏭ Skipped existing icon (new mode): ${componentName}\`); continue; } } let svgContent \= fs.readFileSync(path.join(inputDir, file), "utf8"); // Clean up SVG for JSX svgContent \= svgContent .replace(/\<\\?xml.\*?\\?\>/g, "") .replace(/\<\!DOCTYPE.\*?\>/g, "") .replace(/\\s+xmlns(:xlink)?="\[^"\]\*"/g, "") .replace(/\\s+xlink:\[^=\]+="\[^"\]\*"/g, "") .replace(/\<(path|rect|circle|ellipse|line|polyline|polygon)(\[^\>\]\*?)(?\<\!\\/)\>/g, "\<$1$2 /\>") .replace(/\\s+style="\[^"\]\*"/g, "") .replace(/\\s+fill="\[^"\]\*"/g, "") .replace(/\<path(\[^\>\]\*)\\/\>/g, \`\<path$1 fill="currentColor" /\>\`); svgContent \= svgContent.replace( /\<svg(\[^\>\]\*)\>/, \`\<svg$1 {...props} xmlns="http://www.w3.org/2000/svg"\>\` ); const component \= \`import React from "react";// MANUAL\_EDIT: remove this comment if you manually edit this iconexport const ${componentName} \= (props) \=\> ( ${svgContent.trim()});\`; fs.writeFileSync(outputPath, component, "utf8"); console.log(\`✅ Created/Updated: ${componentName}\`);}console.log(\`🎉 SVG processing done\! Mode: ${mode}\`); |
|
|
61
|
+
| :---- |
|
|
62
|
+
|
|
63
|
+
**Pros:** \- ✅ Full control over generation \- ✅ MANUAL\_EDIT protects custom edits \- ✅ Consistent components with unified props \- ✅ No runtime fetching
|
|
64
|
+
|
|
65
|
+
**Cons:** \- ⚠️ Requires script maintenance \- ⚠️ Initial generation for large sets can take time \- ⚠️ Must rerun when new SVGs are added
|
|
66
|
+
|
|
67
|
+
**Performance:** CPU low at runtime | RAM minimal | Build Time fast
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### Method 4: Synchronous XMLHttpRequest Inline Loader
|
|
72
|
+
|
|
73
|
+
Loads SVGs from the public folder synchronously and allows inline manipulation.
|
|
74
|
+
|
|
75
|
+
| import React from "react";export const SvgIcon \= ({ src, width, height, fill, keepOriginalColor \= false, className }) \=\> { let svgContent \= ""; try { const xhr \= new XMLHttpRequest(); xhr.open("GET", src, false); xhr.send(null); if (xhr.status \=== 200) { svgContent \= xhr.responseText; if (width) svgContent \= svgContent.replace(/width="\[^"\]\*"/, \`width="${width}"\`); if (height) svgContent \= svgContent.replace(/height="\[^"\]\*"/, \`height="${height}"\`); if (fill && \!keepOriginalColor) { svgContent \= svgContent .replace(/fill="\[^"\]\*"/g, \`fill="${fill}"\`) .replace(/\<path(?\!\[^\>\]\*fill)/g, \`\<path fill="${fill}"\`); } } } catch (e) { console.error("SvgIcon load error:", e); } if (\!svgContent) return null; return \<span className={className} dangerouslySetInnerHTML={{ \_\_html: svgContent }} /\>;}; |
|
|
76
|
+
| :---- |
|
|
77
|
+
|
|
78
|
+
**Pros:** ✔️ Simple | ✔️ Inline control | ✔️ Suitable for low-frequency rendering **Cons:** ⚠️ Blocks main thread | ⚠️ Not for large-scale | ⚠️ SSR issues
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### Method 5: Using react-svg Library
|
|
83
|
+
|
|
84
|
+
Dynamically loads and injects SVGs into the DOM with full control.
|
|
85
|
+
|
|
86
|
+
| import { ReactSVG } from 'react-svg';export const ExampleIcon \= () \=\> ( \<ReactSVG src="/assets/icons/truck.svg" beforeInjection={(svg) \=\> { svg.classList.add('svg-class-name'); svg.setAttribute('style', 'width: 200px'); }} afterInjection={(svg) \=\> { console.log(svg); }} className="wrapper-class-name" loading={() \=\> \<span\>Loading...\</span\>} fallback={() \=\> \<span\>Error\!\</span\>} wrapper="span" evalScripts="always" /\>); |
|
|
87
|
+
| :---- |
|
|
88
|
+
|
|
89
|
+
**Performance & Features:** \- Network: fetch per icon (cached if enabled) \- Bundle Size: smaller than SVGR \- CPU: light but includes DOM parsing \- RAM: minimal
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 3\. Final Comparison Table
|
|
94
|
+
|
|
95
|
+
| Feature | Public Fetch | SVGR | Custom Script | XHR Sync | react-svg |
|
|
96
|
+
| :---- | :---- | :---- | :---- | :---- | :---- |
|
|
97
|
+
| | | | | | |
|
|
98
|
+
| Bundle Size | ✅ Small | ⚠️ Medium | ✅ Small | ✅ Small | ✅ Small |
|
|
99
|
+
| | | | | | |
|
|
100
|
+
| Runtime Performance | ⚠️ Slower | ✅ Fast | ✅ Fast | ⚠️ Moderate | ✅ Fast |
|
|
101
|
+
| Build Time | ✅ Fast | ⚠️ Moderate | ✅ Fast | ✅ Fast | ✅ Fast |
|
|
102
|
+
| Customization | ❌ Limited | ✅ Full | ✅ Full | ✅ Full | ✅ Full |
|
|
103
|
+
| Manual Control | ❌ No | ⚠️ Partial | ✅ Full | ✅ Full | ✅ Full |
|
|
104
|
+
| Dynamic Updates | ✅ Easy | ❌ Needs rebuild | ⚠️ Needs rerun | ❌ Static | ✅ Dynamic |
|
|
105
|
+
| Setup Complexity | ✅ Simple | ✅ Simple | ⚠️ Requires Script | ✅ Simple | ✅ Simple |
|
|
106
|
+
|
|
107
|
+
## ---
|
|
108
|
+
|
|
109
|
+
## 4\. Conclusion
|
|
110
|
+
|
|
111
|
+
* For **high-performance and fully controllable projects** → **Custom svg-to-react script**
|
|
112
|
+
|
|
113
|
+
* For **fast, dynamic loading** → **react-svg** or **Public Fetch**
|
|
114
|
+
|
|
115
|
+
* For **small, simple projects** → **XHR Sync** or **Public Fetch**
|
package/package.json
CHANGED
|
@@ -1,38 +1,179 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svger-cli",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"description": "Enterprise-grade, zero-dependency SVG to component converter supporting React, Vue, Angular, Svelte, Solid, Lit, Preact & Vanilla. Features auto-generated TypeScript exports, responsive design, themes, performance optimization & 85% faster processing than SVGR.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"bin": {
|
|
8
|
-
"svger-cli": "./bin/svg-tool.js"
|
|
9
|
+
"svger-cli": "./bin/svg-tool.js",
|
|
10
|
+
"svger": "./bin/svg-tool.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./package.json": "./package.json"
|
|
9
19
|
},
|
|
10
20
|
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"
|
|
21
|
+
"dist/**/*.js",
|
|
22
|
+
"dist/**/*.d.ts",
|
|
23
|
+
"bin/svg-tool.js",
|
|
13
24
|
"README.md",
|
|
14
|
-
"LICENSE"
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"CHANGELOG.md",
|
|
27
|
+
"SECURITY.md",
|
|
28
|
+
"DEVELOPMENT.md",
|
|
29
|
+
"docs/**/*.md",
|
|
30
|
+
".svgerconfig.example.json"
|
|
15
31
|
],
|
|
16
32
|
"scripts": {
|
|
17
|
-
"build": "tsc -p tsconfig.json",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
33
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
34
|
+
"build:watch": "tsc -p tsconfig.json --watch",
|
|
35
|
+
"clean": "node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"",
|
|
36
|
+
"dev": "ts-node --esm src/cli.ts",
|
|
37
|
+
"test": "npm run test:frameworks && npm run test:config && npm run test:e2e",
|
|
38
|
+
"test:frameworks": "node frameworks.test.js",
|
|
39
|
+
"test:config": "tsc tests/config-options.test.ts --outDir dist-tests --module es2022 --target es2022 --moduleResolution bundler && node dist-tests/config-options.test.js",
|
|
40
|
+
"test:e2e": "tsc tests/e2e-complete.test.ts --outDir dist-tests --module es2022 --target es2022 --moduleResolution bundler && node dist-tests/e2e-complete.test.js",
|
|
41
|
+
"test:watch": "jest --watch",
|
|
42
|
+
"test:coverage": "jest --coverage",
|
|
43
|
+
"test:integration": "jest --testPathPattern=integration",
|
|
44
|
+
"test:all": "npm run test:frameworks && npm run test:config && npm run test:e2e",
|
|
45
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
46
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
48
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
|
|
49
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
|
|
50
|
+
"prepublishOnly": "npm run build && npm run test",
|
|
51
|
+
"prepack": "npm run build",
|
|
52
|
+
"release": "npm version patch && npm publish",
|
|
53
|
+
"release:minor": "npm version minor && npm publish",
|
|
54
|
+
"release:major": "npm version major && npm publish",
|
|
55
|
+
"docs:generate": "typedoc --out docs/api src/index.ts",
|
|
56
|
+
"benchmark": "node --loader ts-node/esm scripts/benchmark.ts",
|
|
57
|
+
"validate": "npm run typecheck && npm run lint && npm run test"
|
|
20
58
|
},
|
|
21
59
|
"keywords": [
|
|
22
60
|
"svg",
|
|
23
61
|
"react",
|
|
62
|
+
"vue",
|
|
63
|
+
"angular",
|
|
64
|
+
"svelte",
|
|
65
|
+
"solid",
|
|
66
|
+
"preact",
|
|
67
|
+
"lit",
|
|
24
68
|
"cli",
|
|
25
|
-
"components"
|
|
69
|
+
"components",
|
|
70
|
+
"typescript",
|
|
71
|
+
"zero-dependency",
|
|
72
|
+
"performance",
|
|
73
|
+
"design-system",
|
|
74
|
+
"responsive",
|
|
75
|
+
"enterprise",
|
|
76
|
+
"batch-processing",
|
|
77
|
+
"icon-generation",
|
|
78
|
+
"frontend-tooling",
|
|
79
|
+
"web-components",
|
|
80
|
+
"component-library",
|
|
81
|
+
"svg-optimization",
|
|
82
|
+
"framework-agnostic",
|
|
83
|
+
"developer-tools",
|
|
84
|
+
"build-tools"
|
|
85
|
+
],
|
|
86
|
+
"author": {
|
|
87
|
+
"name": "Faeze Mohades",
|
|
88
|
+
"email": "faezemohades@gmail.com",
|
|
89
|
+
"url": "https://github.com/faezemohades"
|
|
90
|
+
},
|
|
91
|
+
"contributors": [
|
|
92
|
+
{
|
|
93
|
+
"name": "Navid Rezadoost",
|
|
94
|
+
"email": "navidrezadoost07@gmail.com",
|
|
95
|
+
"url": "https://www.linkedin.com/in/navid-rezadoost-5526b9173/",
|
|
96
|
+
"role": "Core Developer & Technical Lead"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "Ehsan Jafari",
|
|
100
|
+
"role": "Technical Requirements & Architecture"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"maintainers": [
|
|
104
|
+
{
|
|
105
|
+
"name": "Faeze Mohades",
|
|
106
|
+
"email": "faezemohades@gmail.com"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "Navid Rezadoost",
|
|
110
|
+
"email": "navidrezadoost07@gmail.com"
|
|
111
|
+
}
|
|
112
|
+
],
|
|
113
|
+
"repository": {
|
|
114
|
+
"type": "git",
|
|
115
|
+
"url": "git+https://github.com/faezemohades/svger-cli.git",
|
|
116
|
+
"directory": "."
|
|
117
|
+
},
|
|
118
|
+
"homepage": "https://github.com/faezemohades/svger-cli#readme",
|
|
119
|
+
"bugs": {
|
|
120
|
+
"url": "https://github.com/faezemohades/svger-cli/issues",
|
|
121
|
+
"email": "faezemohades@gmail.com"
|
|
122
|
+
},
|
|
123
|
+
"funding": [
|
|
124
|
+
{
|
|
125
|
+
"type": "github",
|
|
126
|
+
"url": "https://github.com/sponsors/faezemohades"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"type": "buymeacoffee",
|
|
130
|
+
"url": "https://buymeacoffee.com/faezemohades"
|
|
131
|
+
}
|
|
26
132
|
],
|
|
27
|
-
"author": "faeze mohades",
|
|
28
133
|
"license": "MIT",
|
|
29
134
|
"dependencies": {},
|
|
30
135
|
"devDependencies": {
|
|
136
|
+
"@types/jest": "^29.5.12",
|
|
31
137
|
"@types/node": "^24.9.2",
|
|
138
|
+
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
139
|
+
"@typescript-eslint/parser": "^7.18.0",
|
|
140
|
+
"eslint": "^8.57.1",
|
|
141
|
+
"eslint-config-prettier": "^9.1.0",
|
|
142
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
143
|
+
"jest": "^29.7.0",
|
|
144
|
+
"prettier": "^3.3.3",
|
|
145
|
+
"ts-jest": "^29.2.5",
|
|
32
146
|
"ts-node": "^10.9.2",
|
|
33
|
-
"
|
|
147
|
+
"typedoc": "^0.28.14",
|
|
148
|
+
"typescript": "^5.6.3"
|
|
149
|
+
},
|
|
150
|
+
"peerDependencies": {
|
|
151
|
+
"node": ">=18.17.0"
|
|
34
152
|
},
|
|
35
153
|
"engines": {
|
|
36
|
-
"node": ">=18.17"
|
|
154
|
+
"node": ">=18.17.0",
|
|
155
|
+
"npm": ">=9.0.0"
|
|
156
|
+
},
|
|
157
|
+
"os": [
|
|
158
|
+
"darwin",
|
|
159
|
+
"linux",
|
|
160
|
+
"win32"
|
|
161
|
+
],
|
|
162
|
+
"cpu": [
|
|
163
|
+
"x64",
|
|
164
|
+
"arm64"
|
|
165
|
+
],
|
|
166
|
+
"packageManager": "npm@10.8.2",
|
|
167
|
+
"preferGlobal": true,
|
|
168
|
+
"config": {
|
|
169
|
+
"commitizen": {
|
|
170
|
+
"path": "cz-conventional-changelog"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"browserslist": [
|
|
174
|
+
"node >= 18.17.0"
|
|
175
|
+
],
|
|
176
|
+
"volta": {
|
|
177
|
+
"node": "18.20.4"
|
|
37
178
|
}
|
|
38
|
-
}
|
|
179
|
+
}
|