svger-cli 2.0.1 → 2.0.2
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/dist/cli.js +0 -0
- package/dist/core/error-handler.d.ts +63 -0
- package/dist/core/error-handler.js +224 -0
- package/dist/core/framework-templates.d.ts +17 -0
- package/{src/core/framework-templates.ts → dist/core/framework-templates.js} +100 -137
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.js +85 -0
- package/dist/core/performance-engine.d.ts +67 -0
- package/dist/core/performance-engine.js +251 -0
- package/dist/core/plugin-manager.d.ts +56 -0
- package/dist/core/plugin-manager.js +189 -0
- package/dist/core/style-compiler.d.ts +88 -0
- package/dist/core/style-compiler.js +466 -0
- package/dist/core/template-manager.d.ts +64 -0
- package/{src/core/template-manager.ts → dist/core/template-manager.js} +172 -255
- package/dist/index.d.ts +151 -0
- package/{src/index.ts → dist/index.js} +30 -108
- package/dist/processors/svg-processor.d.ts +67 -0
- package/dist/processors/svg-processor.js +225 -0
- package/dist/services/config.d.ts +55 -0
- package/dist/services/config.js +209 -0
- package/dist/services/file-watcher.d.ts +54 -0
- package/dist/services/file-watcher.js +180 -0
- package/dist/services/svg-service.d.ts +81 -0
- package/dist/services/svg-service.js +383 -0
- package/dist/types/index.d.ts +140 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/native.d.ts +74 -0
- package/dist/utils/native.js +305 -0
- package/package.json +9 -10
- package/.svgconfig.json +0 -3
- package/CODE_OF_CONDUCT.md +0 -79
- package/CONTRIBUTING.md +0 -146
- package/TESTING.md +0 -143
- package/cli-framework.test.js +0 -16
- package/cli-test-angular/Arrowbenddownleft.component.ts +0 -27
- package/cli-test-angular/Vite.component.ts +0 -27
- package/cli-test-angular/index.ts +0 -25
- package/cli-test-output/Arrowbenddownleft.vue +0 -33
- package/cli-test-output/Vite.vue +0 -33
- package/cli-test-output/index.ts +0 -25
- package/cli-test-react/Arrowbenddownleft.tsx +0 -39
- package/cli-test-react/Vite.tsx +0 -39
- package/cli-test-react/index.ts +0 -25
- package/cli-test-svelte/Arrowbenddownleft.svelte +0 -22
- package/cli-test-svelte/Vite.svelte +0 -22
- package/cli-test-svelte/index.ts +0 -25
- package/docs/ADR-SVG-INTRGRATION-METHODS-001.adr.md +0 -157
- package/docs/ADR-SVG-INTRGRATION-METHODS-002.adr.md +0 -550
- package/docs/FRAMEWORK-GUIDE.md +0 -768
- package/docs/IMPLEMENTATION-SUMMARY.md +0 -376
- package/docs/TDR-SVG-INTRGRATION-METHODS-001.tdr.md +0 -115
- package/frameworks.test.js +0 -170
- package/my-svgs/ArrowBendDownLeft.svg +0 -6
- package/my-svgs/vite.svg +0 -1
- package/src/builder.ts +0 -104
- package/src/clean.ts +0 -21
- package/src/cli.ts +0 -221
- package/src/config.ts +0 -81
- package/src/core/error-handler.ts +0 -303
- package/src/core/logger.ts +0 -104
- package/src/core/performance-engine.ts +0 -327
- package/src/core/plugin-manager.ts +0 -228
- package/src/core/style-compiler.ts +0 -605
- package/src/lock.ts +0 -74
- package/src/processors/svg-processor.ts +0 -288
- package/src/services/config.ts +0 -241
- package/src/services/file-watcher.ts +0 -218
- package/src/services/svg-service.ts +0 -468
- package/src/templates/ComponentTemplate.ts +0 -57
- package/src/types/index.ts +0 -169
- package/src/utils/native.ts +0 -352
- package/src/watch.ts +0 -88
- package/test-output-mulit/TestIcon-angular-module.component.ts +0 -26
- package/test-output-mulit/TestIcon-angular-standalone.component.ts +0 -27
- package/test-output-mulit/TestIcon-lit.ts +0 -35
- package/test-output-mulit/TestIcon-preact.tsx +0 -38
- package/test-output-mulit/TestIcon-react.tsx +0 -35
- package/test-output-mulit/TestIcon-solid.tsx +0 -27
- package/test-output-mulit/TestIcon-svelte.svelte +0 -22
- package/test-output-mulit/TestIcon-vanilla.ts +0 -37
- package/test-output-mulit/TestIcon-vue-composition.vue +0 -33
- package/test-output-mulit/TestIcon-vue-options.vue +0 -31
- package/tsconfig.json +0 -18
|
@@ -1,376 +0,0 @@
|
|
|
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.** 🚀
|
|
@@ -1,115 +0,0 @@
|
|
|
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/frameworks.test.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Framework Testing Script for SVGER-CLI
|
|
5
|
-
* Tests all 8 supported frameworks: React, Vue, Svelte, Angular, Solid, Preact, Lit, Vanilla
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { frameworkTemplateEngine } from './dist/index.js';
|
|
9
|
-
import fs from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
|
|
12
|
-
const testSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="currentColor">
|
|
13
|
-
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
|
|
14
|
-
</svg>`;
|
|
15
|
-
|
|
16
|
-
const frameworks = [
|
|
17
|
-
{ name: 'react', typescript: true, options: {} },
|
|
18
|
-
{ name: 'vue', typescript: true, options: { scriptSetup: true } },
|
|
19
|
-
{ name: 'vue', typescript: true, options: { scriptSetup: false } },
|
|
20
|
-
{ name: 'svelte', typescript: true, options: {} },
|
|
21
|
-
{ name: 'angular', typescript: true, options: { standalone: true } },
|
|
22
|
-
{ name: 'angular', typescript: true, options: { standalone: false } },
|
|
23
|
-
{ name: 'solid', typescript: true, options: {} },
|
|
24
|
-
{ name: 'preact', typescript: true, options: {} },
|
|
25
|
-
{ name: 'lit', typescript: true, options: {} },
|
|
26
|
-
{ name: 'vanilla', typescript: true, options: {} }
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
console.log('🚀 SVGER-CLI Framework Testing Suite\n');
|
|
30
|
-
console.log('=' .repeat(80));
|
|
31
|
-
|
|
32
|
-
const testOutputDir = path.join(process.cwd(), 'test-output');
|
|
33
|
-
if (!fs.existsSync(testOutputDir)) {
|
|
34
|
-
fs.mkdirSync(testOutputDir, { recursive: true });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let passed = 0;
|
|
38
|
-
let failed = 0;
|
|
39
|
-
|
|
40
|
-
frameworks.forEach((config, index) => {
|
|
41
|
-
const { name, typescript, options } = config;
|
|
42
|
-
const variant = options.scriptSetup !== undefined
|
|
43
|
-
? (options.scriptSetup ? '-composition' : '-options')
|
|
44
|
-
: options.standalone !== undefined
|
|
45
|
-
? (options.standalone ? '-standalone' : '-module')
|
|
46
|
-
: '';
|
|
47
|
-
|
|
48
|
-
const testName = `${name}${variant}`;
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
console.log(`\n[${index + 1}/${frameworks.length}] Testing: ${testName.toUpperCase()}`);
|
|
52
|
-
console.log('-'.repeat(80));
|
|
53
|
-
|
|
54
|
-
const componentOptions = {
|
|
55
|
-
framework: name,
|
|
56
|
-
componentName: 'TestIcon',
|
|
57
|
-
svgContent: testSVG,
|
|
58
|
-
typescript,
|
|
59
|
-
frameworkOptions: options
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
// Generate component
|
|
63
|
-
const component = frameworkTemplateEngine.generateComponent(componentOptions);
|
|
64
|
-
|
|
65
|
-
// Validate component
|
|
66
|
-
if (!component || component.length === 0) {
|
|
67
|
-
throw new Error('Generated component is empty');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Get file extension
|
|
71
|
-
const extension = frameworkTemplateEngine.getFileExtension(name, typescript);
|
|
72
|
-
|
|
73
|
-
// Save to file
|
|
74
|
-
const fileName = `TestIcon-${testName}.${extension}`;
|
|
75
|
-
const filePath = path.join(testOutputDir, fileName);
|
|
76
|
-
fs.writeFileSync(filePath, component, 'utf8');
|
|
77
|
-
|
|
78
|
-
// Framework-specific validation
|
|
79
|
-
switch (name) {
|
|
80
|
-
case 'react':
|
|
81
|
-
case 'preact':
|
|
82
|
-
case 'solid':
|
|
83
|
-
if (!component.includes('export default')) {
|
|
84
|
-
throw new Error('Missing default export');
|
|
85
|
-
}
|
|
86
|
-
if (!component.includes('interface')) {
|
|
87
|
-
throw new Error('Missing TypeScript interface');
|
|
88
|
-
}
|
|
89
|
-
break;
|
|
90
|
-
|
|
91
|
-
case 'vue':
|
|
92
|
-
if (!component.includes('<template>')) {
|
|
93
|
-
throw new Error('Missing Vue template section');
|
|
94
|
-
}
|
|
95
|
-
if (!component.includes('<script')) {
|
|
96
|
-
throw new Error('Missing Vue script section');
|
|
97
|
-
}
|
|
98
|
-
if (options.scriptSetup && !component.includes('setup')) {
|
|
99
|
-
throw new Error('Missing composition API setup');
|
|
100
|
-
}
|
|
101
|
-
break;
|
|
102
|
-
|
|
103
|
-
case 'svelte':
|
|
104
|
-
if (!component.includes('<script')) {
|
|
105
|
-
throw new Error('Missing Svelte script section');
|
|
106
|
-
}
|
|
107
|
-
if (!component.includes('export let')) {
|
|
108
|
-
throw new Error('Missing Svelte props');
|
|
109
|
-
}
|
|
110
|
-
break;
|
|
111
|
-
|
|
112
|
-
case 'angular':
|
|
113
|
-
if (!component.includes('@Component')) {
|
|
114
|
-
throw new Error('Missing Angular decorator');
|
|
115
|
-
}
|
|
116
|
-
if (!component.includes('selector:')) {
|
|
117
|
-
throw new Error('Missing component selector');
|
|
118
|
-
}
|
|
119
|
-
if (options.standalone && !component.includes('standalone: true')) {
|
|
120
|
-
throw new Error('Missing standalone flag');
|
|
121
|
-
}
|
|
122
|
-
break;
|
|
123
|
-
|
|
124
|
-
case 'lit':
|
|
125
|
-
if (!component.includes('@customElement')) {
|
|
126
|
-
throw new Error('Missing Lit decorator');
|
|
127
|
-
}
|
|
128
|
-
if (!component.includes('extends LitElement')) {
|
|
129
|
-
throw new Error('Not extending LitElement');
|
|
130
|
-
}
|
|
131
|
-
break;
|
|
132
|
-
|
|
133
|
-
case 'vanilla':
|
|
134
|
-
if (!component.includes('export function')) {
|
|
135
|
-
throw new Error('Missing function export');
|
|
136
|
-
}
|
|
137
|
-
if (!component.includes('document.createElementNS')) {
|
|
138
|
-
throw new Error('Missing DOM manipulation');
|
|
139
|
-
}
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
console.log(`✅ SUCCESS: Generated valid ${name.toUpperCase()} component`);
|
|
144
|
-
console.log(` 📄 File: ${fileName}`);
|
|
145
|
-
console.log(` 📏 Size: ${component.length} characters`);
|
|
146
|
-
console.log(` 📝 Extension: .${extension}`);
|
|
147
|
-
|
|
148
|
-
passed++;
|
|
149
|
-
|
|
150
|
-
} catch (error) {
|
|
151
|
-
console.log(`❌ FAILED: ${testName.toUpperCase()}`);
|
|
152
|
-
console.log(` Error: ${error.message}`);
|
|
153
|
-
failed++;
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
console.log('\n' + '='.repeat(80));
|
|
158
|
-
console.log('\n📊 Test Results Summary\n');
|
|
159
|
-
console.log(` Total Tests: ${frameworks.length}`);
|
|
160
|
-
console.log(` ✅ Passed: ${passed}`);
|
|
161
|
-
console.log(` ❌ Failed: ${failed}`);
|
|
162
|
-
console.log(` 📂 Output: ${testOutputDir}\n`);
|
|
163
|
-
|
|
164
|
-
if (failed === 0) {
|
|
165
|
-
console.log('🎉 All framework tests passed successfully!\n');
|
|
166
|
-
process.exit(0);
|
|
167
|
-
} else {
|
|
168
|
-
console.log('⚠️ Some tests failed. Please review the errors above.\n');
|
|
169
|
-
process.exit(1);
|
|
170
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="24px" viewBox="0 0 24 24" version="1.1">
|
|
3
|
-
<g id="surface1">
|
|
4
|
-
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,48.235294%,82.352942%);fill-opacity:1;" d="M 2.25 5.25 C 2.253906 7.835938 3.28125 10.3125 5.109375 12.140625 C 6.9375 13.96875 9.414062 14.996094 12 15 L 19.1875 15 L 15.96875 18.21875 C 15.828125 18.359375 15.75 18.550781 15.75 18.75 C 15.75 18.949219 15.828125 19.140625 15.96875 19.28125 C 16.109375 19.421875 16.300781 19.5 16.5 19.5 C 16.699219 19.5 16.890625 19.421875 17.03125 19.28125 L 21.53125 14.78125 C 21.601562 14.710938 21.65625 14.628906 21.691406 14.539062 C 21.730469 14.445312 21.75 14.347656 21.75 14.25 C 21.75 14.152344 21.730469 14.054688 21.691406 13.960938 C 21.65625 13.871094 21.601562 13.789062 21.53125 13.71875 L 17.03125 9.21875 C 16.890625 9.078125 16.699219 9 16.5 9 C 16.300781 9 16.109375 9.078125 15.96875 9.21875 C 15.828125 9.359375 15.75 9.550781 15.75 9.75 C 15.75 9.949219 15.828125 10.140625 15.96875 10.28125 L 19.1875 13.5 L 12 13.5 C 9.8125 13.496094 7.714844 12.628906 6.167969 11.082031 C 4.621094 9.535156 3.75 7.4375 3.75 5.25 C 3.75 5.050781 3.671875 4.859375 3.53125 4.71875 C 3.390625 4.578125 3.199219 4.5 3 4.5 C 2.800781 4.5 2.609375 4.578125 2.46875 4.71875 C 2.328125 4.859375 2.25 5.050781 2.25 5.25 Z M 2.25 5.25 "/>
|
|
5
|
-
</g>
|
|
6
|
-
</svg>
|
package/my-svgs/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|