svger-cli 3.1.0 โ 3.1.1
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/CHANGELOG.md +67 -0
- package/README.md +20 -16
- package/dist/cli.js +1 -1
- package/dist/integrations/babel.js +30 -11
- package/dist/integrations/rollup.js +29 -10
- package/dist/integrations/vite.js +29 -14
- package/dist/integrations/webpack.d.ts +1 -0
- package/dist/integrations/webpack.js +29 -10
- package/dist/services/svg-service.d.ts +2 -0
- package/dist/services/svg-service.js +25 -9
- package/package.json +1 -1
- package/DEVELOPMENT.md +0 -353
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,73 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
|
|
6
6
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.1.1] - 2025-12-25
|
|
9
|
+
|
|
10
|
+
### ๐ Bug Fixes
|
|
11
|
+
|
|
12
|
+
#### **Critical: Locked Files Missing from Index Exports**
|
|
13
|
+
- **Fixed**: Locked SVG files are now correctly included in auto-generated `index.ts` exports
|
|
14
|
+
- **Issue**: When SVG files were locked using `svger-cli lock`, their generated components were excluded from the `index.ts` barrel file, breaking imports and requiring manual maintenance
|
|
15
|
+
- **Root Cause**: Index generation logic only included files processed in the current build session, excluding locked files that were intentionally skipped
|
|
16
|
+
- **Solution**: Modified index generation to scan output directory for ALL existing component files instead of relying on processed files list
|
|
17
|
+
|
|
18
|
+
#### **Files Changed**
|
|
19
|
+
- **Core Service** (`src/services/svg-service.ts`):
|
|
20
|
+
- Updated `generateIndexFile()` to scan output directory for all component files (`.tsx`, `.jsx`, `.ts`, `.js`)
|
|
21
|
+
- Now includes both newly generated and previously locked components in exports
|
|
22
|
+
- Fixed incorrect property access `output?.naming` โ `outputConfig?.naming`
|
|
23
|
+
|
|
24
|
+
- **Integration Plugins** (all updated to scan output directory):
|
|
25
|
+
- `src/integrations/babel.ts` - Babel plugin index generation
|
|
26
|
+
- `src/integrations/vite.ts` - Vite plugin index generation
|
|
27
|
+
- `src/integrations/webpack.ts` - Webpack plugin index generation (affects Next.js)
|
|
28
|
+
- `src/integrations/rollup.ts` - Rollup plugin index generation
|
|
29
|
+
|
|
30
|
+
#### **Framework Coverage**
|
|
31
|
+
- โ
React (TSX/JSX)
|
|
32
|
+
- โ
React Native
|
|
33
|
+
- โ
Vue (Composition & Options API)
|
|
34
|
+
- โ
Angular (Module & Standalone)
|
|
35
|
+
- โ
Svelte
|
|
36
|
+
- โ
Solid
|
|
37
|
+
- โ
Preact
|
|
38
|
+
- โ
Lit
|
|
39
|
+
- โ
Vanilla JS/TS
|
|
40
|
+
|
|
41
|
+
#### **Build Tool Coverage**
|
|
42
|
+
- โ
CLI (`svger-cli build`)
|
|
43
|
+
- โ
Babel Plugin
|
|
44
|
+
- โ
Vite Plugin
|
|
45
|
+
- โ
Webpack Plugin
|
|
46
|
+
- โ
Rollup Plugin
|
|
47
|
+
- โ
Next.js Plugin (uses Webpack)
|
|
48
|
+
|
|
49
|
+
#### **Testing**
|
|
50
|
+
- Added comprehensive test suite: `tests/locked-files-index.test.ts`
|
|
51
|
+
- Tests verify locked files remain in index after build
|
|
52
|
+
- Tests verify multiple locked files are handled correctly
|
|
53
|
+
- Tests verify unlocking allows regeneration
|
|
54
|
+
- Tests verify locked files aren't regenerated
|
|
55
|
+
- All existing tests pass (40+ tests)
|
|
56
|
+
|
|
57
|
+
#### **Lock Mechanism Behavior (Corrected)**
|
|
58
|
+
- **Locking a file**: Prevents regeneration/overwrite of component file โ
|
|
59
|
+
- **Building with locked files**: Skips locked file regeneration but **includes in index.ts** โ
|
|
60
|
+
- **Index exports**: Now includes ALL components (locked + unlocked) โ
|
|
61
|
+
|
|
62
|
+
### ๐งน Code Quality
|
|
63
|
+
- Removed unused `viteConfig` variable from Vite plugin
|
|
64
|
+
- Fixed TypeScript compilation warnings
|
|
65
|
+
- All linting rules pass
|
|
66
|
+
|
|
67
|
+
### ๐ Documentation
|
|
68
|
+
- Created detailed GitHub issue response documentation
|
|
69
|
+
- Updated fix summary with comprehensive coverage details
|
|
70
|
+
- No breaking changes
|
|
71
|
+
- No migration required
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
8
75
|
## [3.1.0] - 2025-12-04
|
|
9
76
|
|
|
10
77
|
### ๐ Major Improvements - Testing & DevOps
|
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./assets/svger-cli.png" alt="SVGER-CLI Banner" width="100%" />
|
|
3
|
+
|
|
4
|
+
<h1>SVGER-CLI v3.1.1</h1>
|
|
5
|
+
<h3>Enterprise SVG Processing Framework</h3>
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
<a href="https://badge.fury.io/js/svger-cli"><img src="https://badge.fury.io/js/svger-cli.svg" alt="npm version" /></a>
|
|
9
|
+
<a href="https://www.npmjs.com/package/svger-cli"><img src="https://img.shields.io/npm/dm/svger-cli.svg" alt="npm downloads" /></a>
|
|
10
|
+
<a href="https://www.npmjs.com/package/svger-cli"><img src="https://img.shields.io/npm/v/svger-cli.svg" alt="npm" /></a>
|
|
11
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
|
|
12
|
+
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-Ready-blue.svg" alt="TypeScript" /></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/svger-cli"><img src="https://img.shields.io/badge/Dependencies-Zero-green.svg" alt="Zero Dependencies" /></a>
|
|
14
|
+
<a href="https://github.com/faezemohades/svger-cli"><img src="https://img.shields.io/badge/Tests-114%20passing-success.svg" alt="Tests" /></a>
|
|
15
|
+
<a href="https://github.com/faezemohades/svger-cli"><img src="https://img.shields.io/badge/Coverage-82%25-yellow.svg" alt="Coverage" /></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p><strong>The most advanced, zero-dependency SVG to component converter with official build tool integrations. First-class support for Webpack, Vite, Rollup, Babel, Next.js, and Jest. Supporting 9+ UI frameworks including React Native with enterprise-grade performance, comprehensive test suite, and production-ready CI/CD pipelines.</strong></p>
|
|
19
|
+
</div>
|
|
16
20
|
|
|
17
21
|
---
|
|
18
22
|
|
|
@@ -2763,7 +2767,7 @@ svger-cli build --framework react --responsive --theme dark
|
|
|
2763
2767
|
|
|
2764
2768
|
### **Comprehensive Test Suite**
|
|
2765
2769
|
|
|
2766
|
-
SVGER-CLI v3.1.
|
|
2770
|
+
SVGER-CLI v3.1.1 includes a production-ready test suite with **114 automated tests** covering:
|
|
2767
2771
|
|
|
2768
2772
|
- โ
**Unit Tests** - Core modules, utilities, and processors
|
|
2769
2773
|
- โ
**Integration Tests** - Complete workflows and multi-framework support
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ const program = new CLI();
|
|
|
11
11
|
program
|
|
12
12
|
.name('svger-cli')
|
|
13
13
|
.description('Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter')
|
|
14
|
-
.version('
|
|
14
|
+
.version('3.0.0');
|
|
15
15
|
// -------- Build Command --------
|
|
16
16
|
/**
|
|
17
17
|
* Build all SVGs from a source folder to an output folder.
|
|
@@ -85,9 +85,9 @@ async function processAllSVGs(options, processedFiles) {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
// Generate index file if enabled
|
|
88
|
-
if (options.generateIndex
|
|
88
|
+
if (options.generateIndex) {
|
|
89
89
|
try {
|
|
90
|
-
await generateIndexFile(outputPath,
|
|
90
|
+
await generateIndexFile(outputPath, options);
|
|
91
91
|
}
|
|
92
92
|
catch (error) {
|
|
93
93
|
logger.error('Failed to generate index file:', error);
|
|
@@ -97,16 +97,35 @@ async function processAllSVGs(options, processedFiles) {
|
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Generate index file with all exports
|
|
100
|
+
* Scans the output directory for all existing component files
|
|
100
101
|
*/
|
|
101
|
-
async function generateIndexFile(outputDir,
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
async function generateIndexFile(outputDir, options) {
|
|
103
|
+
try {
|
|
104
|
+
// Scan output directory for all component files
|
|
105
|
+
const files = await FileSystem.readDir(outputDir);
|
|
106
|
+
const extension = options.typescript ? 'tsx' : 'jsx';
|
|
107
|
+
// Filter component files (exclude index files)
|
|
108
|
+
const componentFiles = files.filter(file => (file.endsWith(`.${extension}`) ||
|
|
109
|
+
file.endsWith('.ts') ||
|
|
110
|
+
file.endsWith('.js')) &&
|
|
111
|
+
!file.startsWith('index.'));
|
|
112
|
+
if (componentFiles.length === 0) {
|
|
113
|
+
logger.warn('No component files found for index generation');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Extract component names
|
|
117
|
+
const componentNames = componentFiles.map(file => path.basename(file, path.extname(file)));
|
|
118
|
+
const indexExtension = options.typescript ? 'ts' : 'js';
|
|
119
|
+
const exports = componentNames
|
|
120
|
+
.map(name => `export { default as ${name} } from './${name}';`)
|
|
121
|
+
.join('\n');
|
|
122
|
+
const indexPath = path.join(outputDir, `index.${indexExtension}`);
|
|
123
|
+
await FileSystem.writeFile(indexPath, exports, 'utf-8');
|
|
124
|
+
logger.debug(`Generated index file: ${indexPath}`);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
logger.error('Failed to generate index file:', error);
|
|
128
|
+
}
|
|
110
129
|
}
|
|
111
130
|
/**
|
|
112
131
|
* Transform SVG import path to component path
|
|
@@ -140,7 +140,7 @@ async function processAllSVGs(options, processedFiles) {
|
|
|
140
140
|
}
|
|
141
141
|
// Generate index file
|
|
142
142
|
if (options.generateIndex) {
|
|
143
|
-
await generateIndexFile(outputDir,
|
|
143
|
+
await generateIndexFile(outputDir, options);
|
|
144
144
|
}
|
|
145
145
|
const successful = results.filter(r => r.success).length;
|
|
146
146
|
logger.info(`SVGER: Processed ${successful}/${svgFiles.length} SVG files`);
|
|
@@ -182,16 +182,35 @@ async function processSVGFile(svgPath, outputDir, options) {
|
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
184
184
|
* Generate index file with all exports
|
|
185
|
+
* Scans the output directory for all existing component files
|
|
185
186
|
*/
|
|
186
|
-
async function generateIndexFile(outputDir,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
async function generateIndexFile(outputDir, options) {
|
|
188
|
+
try {
|
|
189
|
+
// Scan output directory for all component files
|
|
190
|
+
const files = await FileSystem.readDir(outputDir);
|
|
191
|
+
const extension = options.typescript ? 'tsx' : 'jsx';
|
|
192
|
+
// Filter component files (exclude index files)
|
|
193
|
+
const componentFiles = files.filter(file => (file.endsWith(`.${extension}`) ||
|
|
194
|
+
file.endsWith('.ts') ||
|
|
195
|
+
file.endsWith('.js')) &&
|
|
196
|
+
!file.startsWith('index.'));
|
|
197
|
+
if (componentFiles.length === 0) {
|
|
198
|
+
logger.warn('No component files found for index generation');
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Extract component names
|
|
202
|
+
const componentNames = componentFiles.map(file => path.basename(file, path.extname(file)));
|
|
203
|
+
const indexExtension = options.typescript ? 'ts' : 'js';
|
|
204
|
+
const exports = componentNames
|
|
205
|
+
.map(name => `export { default as ${name} } from './${name}';`)
|
|
206
|
+
.join('\n');
|
|
207
|
+
const indexPath = path.join(outputDir, `index.${indexExtension}`);
|
|
208
|
+
await FileSystem.writeFile(indexPath, exports, 'utf-8');
|
|
209
|
+
logger.debug(`Generated index file: ${indexPath}`);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
logger.error('Failed to generate index file:', error);
|
|
213
|
+
}
|
|
195
214
|
}
|
|
196
215
|
// Default export
|
|
197
216
|
export default svgerRollupPlugin;
|
|
@@ -47,13 +47,9 @@ export function svgerVitePlugin(options = {}) {
|
|
|
47
47
|
svgo: options.svgo !== undefined ? options.svgo : false,
|
|
48
48
|
generateIndex: options.generateIndex !== undefined ? options.generateIndex : true,
|
|
49
49
|
};
|
|
50
|
-
let viteConfig;
|
|
51
50
|
const processedFiles = new Set();
|
|
52
51
|
return {
|
|
53
52
|
name: PLUGIN_NAME,
|
|
54
|
-
configResolved(resolvedConfig) {
|
|
55
|
-
viteConfig = resolvedConfig;
|
|
56
|
-
},
|
|
57
53
|
async buildStart() {
|
|
58
54
|
logger.info('SVGER Vite Plugin: Processing SVG files...');
|
|
59
55
|
await processAllSVGs(pluginOptions, processedFiles);
|
|
@@ -164,7 +160,7 @@ async function processAllSVGs(options, processedFiles) {
|
|
|
164
160
|
}
|
|
165
161
|
// Generate index file
|
|
166
162
|
if (options.generateIndex) {
|
|
167
|
-
await generateIndexFile(outputDir,
|
|
163
|
+
await generateIndexFile(outputDir, options);
|
|
168
164
|
}
|
|
169
165
|
const successful = results.filter(r => r.success).length;
|
|
170
166
|
logger.info(`SVGER: Processed ${successful}/${svgFiles.length} SVG files`);
|
|
@@ -206,16 +202,35 @@ async function processSVGFile(svgPath, outputDir, options) {
|
|
|
206
202
|
}
|
|
207
203
|
/**
|
|
208
204
|
* Generate index file with all exports
|
|
205
|
+
* Scans the output directory for all existing component files
|
|
209
206
|
*/
|
|
210
|
-
async function generateIndexFile(outputDir,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
207
|
+
async function generateIndexFile(outputDir, options) {
|
|
208
|
+
try {
|
|
209
|
+
// Scan output directory for all component files
|
|
210
|
+
const files = await FileSystem.readDir(outputDir);
|
|
211
|
+
const extension = options.typescript ? 'tsx' : 'jsx';
|
|
212
|
+
// Filter component files (exclude index files)
|
|
213
|
+
const componentFiles = files.filter(file => (file.endsWith(`.${extension}`) ||
|
|
214
|
+
file.endsWith('.ts') ||
|
|
215
|
+
file.endsWith('.js')) &&
|
|
216
|
+
!file.startsWith('index.'));
|
|
217
|
+
if (componentFiles.length === 0) {
|
|
218
|
+
logger.warn('No component files found for index generation');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// Extract component names
|
|
222
|
+
const componentNames = componentFiles.map(file => path.basename(file, path.extname(file)));
|
|
223
|
+
const indexExtension = options.typescript ? 'ts' : 'js';
|
|
224
|
+
const exports = componentNames
|
|
225
|
+
.map(name => `export { default as ${name} } from './${name}';`)
|
|
226
|
+
.join('\n');
|
|
227
|
+
const indexPath = path.join(outputDir, `index.${indexExtension}`);
|
|
228
|
+
await FileSystem.writeFile(indexPath, exports, 'utf-8');
|
|
229
|
+
logger.debug(`Generated index file: ${indexPath}`);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
logger.error('Failed to generate index file:', error);
|
|
233
|
+
}
|
|
219
234
|
}
|
|
220
235
|
// Default export
|
|
221
236
|
export default svgerVitePlugin;
|
|
@@ -111,7 +111,7 @@ export class SvgerWebpackPlugin {
|
|
|
111
111
|
}
|
|
112
112
|
// Generate index file
|
|
113
113
|
if (this.options.generateIndex) {
|
|
114
|
-
await this.generateIndexFile(outputDir
|
|
114
|
+
await this.generateIndexFile(outputDir);
|
|
115
115
|
}
|
|
116
116
|
const successful = results.filter(r => r.success).length;
|
|
117
117
|
logger.info(`SVGER: Processed ${successful}/${svgFiles.length} SVG files`);
|
|
@@ -176,16 +176,35 @@ export class SvgerWebpackPlugin {
|
|
|
176
176
|
}
|
|
177
177
|
/**
|
|
178
178
|
* Generate index file with all exports
|
|
179
|
+
* Scans the output directory for all existing component files
|
|
179
180
|
*/
|
|
180
|
-
async generateIndexFile(outputDir
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
181
|
+
async generateIndexFile(outputDir) {
|
|
182
|
+
try {
|
|
183
|
+
// Scan output directory for all component files
|
|
184
|
+
const files = await FileSystem.readDir(outputDir);
|
|
185
|
+
const extension = this.options.typescript ? 'tsx' : 'jsx';
|
|
186
|
+
// Filter component files (exclude index files)
|
|
187
|
+
const componentFiles = files.filter(file => (file.endsWith(`.${extension}`) ||
|
|
188
|
+
file.endsWith('.ts') ||
|
|
189
|
+
file.endsWith('.js')) &&
|
|
190
|
+
!file.startsWith('index.'));
|
|
191
|
+
if (componentFiles.length === 0) {
|
|
192
|
+
logger.warn('No component files found for index generation');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// Extract component names
|
|
196
|
+
const componentNames = componentFiles.map(file => path.basename(file, path.extname(file)));
|
|
197
|
+
const indexExtension = this.options.typescript ? 'ts' : 'js';
|
|
198
|
+
const exports = componentNames
|
|
199
|
+
.map(name => `export { default as ${name} } from './${name}';`)
|
|
200
|
+
.join('\n');
|
|
201
|
+
const indexPath = path.join(outputDir, `index.${indexExtension}`);
|
|
202
|
+
await FileSystem.writeFile(indexPath, exports, 'utf-8');
|
|
203
|
+
logger.debug(`Generated index file: ${indexPath}`);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
logger.error('Failed to generate index file:', error);
|
|
207
|
+
}
|
|
189
208
|
}
|
|
190
209
|
/**
|
|
191
210
|
* Get changed files from webpack
|
|
@@ -42,6 +42,8 @@ export declare class SVGService {
|
|
|
42
42
|
clean(outDir: string): Promise<void>;
|
|
43
43
|
/**
|
|
44
44
|
* Generate index.ts file with all component exports
|
|
45
|
+
* Scans the output directory for all existing component files,
|
|
46
|
+
* including those from locked SVGs that weren't regenerated
|
|
45
47
|
*/
|
|
46
48
|
private generateIndexFile;
|
|
47
49
|
/**
|
|
@@ -76,7 +76,7 @@ export class SVGService {
|
|
|
76
76
|
defaultWidth: mergedConfig.defaultWidth,
|
|
77
77
|
defaultHeight: mergedConfig.defaultHeight,
|
|
78
78
|
defaultFill: mergedConfig.defaultFill,
|
|
79
|
-
namingConvention: mergedConfig.
|
|
79
|
+
namingConvention: mergedConfig.outputConfig?.naming || 'pascal',
|
|
80
80
|
styleRules: Object.fromEntries(Object.entries(mergedConfig.styleRules || {}).filter(([, v]) => v !== undefined)),
|
|
81
81
|
});
|
|
82
82
|
results.push({
|
|
@@ -107,9 +107,8 @@ export class SVGService {
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
// Generate index.ts file with all component exports
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
110
|
+
// This includes both newly generated components and existing locked components
|
|
111
|
+
await this.generateIndexFile(outDir, mergedConfig);
|
|
113
112
|
}
|
|
114
113
|
/**
|
|
115
114
|
* Generate a React component from a single SVG file
|
|
@@ -257,13 +256,30 @@ export class SVGService {
|
|
|
257
256
|
}
|
|
258
257
|
/**
|
|
259
258
|
* Generate index.ts file with all component exports
|
|
259
|
+
* Scans the output directory for all existing component files,
|
|
260
|
+
* including those from locked SVGs that weren't regenerated
|
|
260
261
|
*/
|
|
261
|
-
async generateIndexFile(outDir,
|
|
262
|
+
async generateIndexFile(outDir, config) {
|
|
262
263
|
try {
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
264
|
+
// Scan output directory for all component files
|
|
265
|
+
const files = await FileSystem.readDir(outDir);
|
|
266
|
+
// Get the file extension based on typescript setting
|
|
267
|
+
const typescript = config?.typescript !== false;
|
|
268
|
+
const ext = typescript ? '.tsx' : '.jsx';
|
|
269
|
+
// Filter component files (exclude index.ts/index.js)
|
|
270
|
+
const componentFiles = files.filter(file => (file.endsWith(ext) ||
|
|
271
|
+
file.endsWith('.ts') ||
|
|
272
|
+
file.endsWith('.js')) &&
|
|
273
|
+
!file.startsWith('index.'));
|
|
274
|
+
if (componentFiles.length === 0) {
|
|
275
|
+
logger.warn('No component files found in output directory for index generation');
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
// Extract component names from filenames
|
|
279
|
+
const componentNames = componentFiles.map(file => {
|
|
280
|
+
// Remove extension to get component name
|
|
281
|
+
const baseName = path.basename(file, path.extname(file));
|
|
282
|
+
return baseName;
|
|
267
283
|
});
|
|
268
284
|
const indexContent = this.generateIndexContent(componentNames);
|
|
269
285
|
const indexPath = path.join(outDir, 'index.ts');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svger-cli",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "Enterprise-grade, zero-dependency SVG to component converter with official Webpack, Vite, Rollup, Babel, Next.js & Jest integrations. Supporting React, React Native, Vue, Angular, Svelte, Solid, Lit, Preact & Vanilla. Features auto-generated TypeScript exports, HMR, responsive design, themes & 85% faster processing than SVGR.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/DEVELOPMENT.md
DELETED
|
@@ -1,353 +0,0 @@
|
|
|
1
|
-
# Development Guide
|
|
2
|
-
|
|
3
|
-
This guide will help you set up the development environment and contribute to SVGER-CLI.
|
|
4
|
-
|
|
5
|
-
## Prerequisites
|
|
6
|
-
|
|
7
|
-
- **Node.js**: >= 18.17.0 (we recommend using [nvm](https://github.com/nvm-sh/nvm))
|
|
8
|
-
- **npm**: >= 9.0.0
|
|
9
|
-
- **Git**: Latest version
|
|
10
|
-
|
|
11
|
-
## Setup Development Environment
|
|
12
|
-
|
|
13
|
-
1. **Clone the repository:**
|
|
14
|
-
```bash
|
|
15
|
-
git clone https://github.com/faezemohades/svger-cli.git
|
|
16
|
-
cd svger-cli
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
2. **Install dependencies:**
|
|
20
|
-
```bash
|
|
21
|
-
npm install
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
3. **Build the project:**
|
|
25
|
-
```bash
|
|
26
|
-
npm run build
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
4. **Run tests:**
|
|
30
|
-
```bash
|
|
31
|
-
npm test
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Development Workflow
|
|
35
|
-
|
|
36
|
-
### Building
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# Build once
|
|
40
|
-
npm run build
|
|
41
|
-
|
|
42
|
-
# Build and watch for changes
|
|
43
|
-
npm run build:watch
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Testing
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# Run all tests
|
|
50
|
-
npm test
|
|
51
|
-
|
|
52
|
-
# Run tests in watch mode
|
|
53
|
-
npm run test:watch
|
|
54
|
-
|
|
55
|
-
# Run with coverage
|
|
56
|
-
npm run test:coverage
|
|
57
|
-
|
|
58
|
-
# Run integration tests only
|
|
59
|
-
npm run test:integration
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Linting and Formatting
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
# Check for linting issues
|
|
66
|
-
npm run lint
|
|
67
|
-
|
|
68
|
-
# Fix linting issues
|
|
69
|
-
npm run lint:fix
|
|
70
|
-
|
|
71
|
-
# Check formatting
|
|
72
|
-
npm run format:check
|
|
73
|
-
|
|
74
|
-
# Fix formatting
|
|
75
|
-
npm run format
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Development Mode
|
|
79
|
-
|
|
80
|
-
To test the CLI during development:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# Run CLI directly from source
|
|
84
|
-
npm run dev -- build ./test-icons ./test-output
|
|
85
|
-
|
|
86
|
-
# Or install globally for testing
|
|
87
|
-
npm run build
|
|
88
|
-
npm link
|
|
89
|
-
svger-cli --version
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Project Structure
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
svger-cli/
|
|
96
|
-
โโโ src/ # Source code
|
|
97
|
-
โ โโโ core/ # Core functionality
|
|
98
|
-
โ โโโ processors/ # SVG processing logic
|
|
99
|
-
โ โโโ services/ # Business logic services
|
|
100
|
-
โ โโโ templates/ # Framework templates
|
|
101
|
-
โ โโโ types/ # TypeScript definitions
|
|
102
|
-
โ โโโ utils/ # Utility functions
|
|
103
|
-
โโโ bin/ # CLI entry point
|
|
104
|
-
โโโ docs/ # Documentation
|
|
105
|
-
โโโ dist/ # Compiled output (generated)
|
|
106
|
-
โโโ tests/ # Test files
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Adding New Framework Support
|
|
110
|
-
|
|
111
|
-
1. **Create framework template:**
|
|
112
|
-
```typescript
|
|
113
|
-
// src/core/framework-templates.ts
|
|
114
|
-
export const newFrameworkTemplate = {
|
|
115
|
-
name: 'newframework',
|
|
116
|
-
extension: '.jsx',
|
|
117
|
-
generate: (svgContent: string, componentName: string, options: any) => {
|
|
118
|
-
// Implementation
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
2. **Add to framework list:**
|
|
124
|
-
```typescript
|
|
125
|
-
// src/types/index.ts
|
|
126
|
-
export type FrameworkType = 'react' | 'vue' | 'angular' | 'newframework';
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
3. **Update CLI options:**
|
|
130
|
-
```typescript
|
|
131
|
-
// src/cli.ts - Add to framework choices
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
4. **Add tests:**
|
|
135
|
-
```typescript
|
|
136
|
-
// tests/frameworks/newframework.test.ts
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
## Testing Strategy
|
|
140
|
-
|
|
141
|
-
### Unit Tests
|
|
142
|
-
- Test individual functions and classes
|
|
143
|
-
- Mock external dependencies
|
|
144
|
-
- Focus on business logic
|
|
145
|
-
|
|
146
|
-
### Integration Tests
|
|
147
|
-
- Test CLI commands end-to-end
|
|
148
|
-
- Test file generation with real SVG files
|
|
149
|
-
- Verify output correctness
|
|
150
|
-
|
|
151
|
-
### Performance Tests
|
|
152
|
-
- Benchmark processing times
|
|
153
|
-
- Memory usage testing
|
|
154
|
-
- Regression detection
|
|
155
|
-
|
|
156
|
-
## Code Style Guidelines
|
|
157
|
-
|
|
158
|
-
### TypeScript
|
|
159
|
-
- Use strict TypeScript configuration
|
|
160
|
-
- Prefer interfaces over types for object shapes
|
|
161
|
-
- Use generics for reusable code
|
|
162
|
-
- Document complex types
|
|
163
|
-
|
|
164
|
-
### Naming Conventions
|
|
165
|
-
- **Files**: kebab-case (e.g., `svg-processor.ts`)
|
|
166
|
-
- **Classes**: PascalCase (e.g., `SVGProcessor`)
|
|
167
|
-
- **Functions/Variables**: camelCase (e.g., `processFile`)
|
|
168
|
-
- **Constants**: SCREAMING_SNAKE_CASE (e.g., `DEFAULT_SIZE`)
|
|
169
|
-
|
|
170
|
-
### Error Handling
|
|
171
|
-
- Use custom error classes
|
|
172
|
-
- Provide meaningful error messages
|
|
173
|
-
- Include context in errors
|
|
174
|
-
- Log appropriate levels
|
|
175
|
-
|
|
176
|
-
## Performance Considerations
|
|
177
|
-
|
|
178
|
-
### Optimization Guidelines
|
|
179
|
-
- Use streaming for large files
|
|
180
|
-
- Implement caching where appropriate
|
|
181
|
-
- Parallelize CPU-intensive tasks
|
|
182
|
-
- Monitor memory usage
|
|
183
|
-
|
|
184
|
-
### Benchmarking
|
|
185
|
-
```bash
|
|
186
|
-
# Run performance benchmarks
|
|
187
|
-
npm run benchmark
|
|
188
|
-
|
|
189
|
-
# Compare with previous versions
|
|
190
|
-
npm run benchmark -- --compare
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## Contributing Guidelines
|
|
194
|
-
|
|
195
|
-
### Before You Start
|
|
196
|
-
1. Check existing issues and PRs
|
|
197
|
-
2. Create an issue for new features
|
|
198
|
-
3. Follow coding standards
|
|
199
|
-
4. Write tests for new code
|
|
200
|
-
|
|
201
|
-
### Pull Request Process
|
|
202
|
-
1. **Create feature branch:**
|
|
203
|
-
```bash
|
|
204
|
-
git checkout -b feature/your-feature-name
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
2. **Make changes and test:**
|
|
208
|
-
```bash
|
|
209
|
-
npm run validate # runs typecheck, lint, and test
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
3. **Commit with conventional format:**
|
|
213
|
-
```bash
|
|
214
|
-
git commit -m "feat: add support for new framework"
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
4. **Push and create PR:**
|
|
218
|
-
```bash
|
|
219
|
-
git push origin feature/your-feature-name
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
### Commit Message Format
|
|
223
|
-
```
|
|
224
|
-
<type>(<scope>): <description>
|
|
225
|
-
|
|
226
|
-
[optional body]
|
|
227
|
-
|
|
228
|
-
[optional footer]
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
**Types:**
|
|
232
|
-
- `feat`: New feature
|
|
233
|
-
- `fix`: Bug fix
|
|
234
|
-
- `docs`: Documentation changes
|
|
235
|
-
- `style`: Formatting changes
|
|
236
|
-
- `refactor`: Code restructuring
|
|
237
|
-
- `test`: Adding tests
|
|
238
|
-
- `chore`: Maintenance tasks
|
|
239
|
-
|
|
240
|
-
## Debugging
|
|
241
|
-
|
|
242
|
-
### CLI Debugging
|
|
243
|
-
```bash
|
|
244
|
-
# Enable verbose logging
|
|
245
|
-
DEBUG=svger:* npm run dev -- build ./icons ./components
|
|
246
|
-
|
|
247
|
-
# Debug specific modules
|
|
248
|
-
DEBUG=svger:processor npm run dev -- build ./icons ./components
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### VS Code Configuration
|
|
252
|
-
Create `.vscode/launch.json`:
|
|
253
|
-
```json
|
|
254
|
-
{
|
|
255
|
-
"version": "0.2.0",
|
|
256
|
-
"configurations": [
|
|
257
|
-
{
|
|
258
|
-
"name": "Debug CLI",
|
|
259
|
-
"type": "node",
|
|
260
|
-
"request": "launch",
|
|
261
|
-
"program": "${workspaceFolder}/src/cli.ts",
|
|
262
|
-
"args": ["build", "./test-icons", "./test-output"],
|
|
263
|
-
"runtimeArgs": ["--loader", "ts-node/esm"],
|
|
264
|
-
"console": "integratedTerminal"
|
|
265
|
-
}
|
|
266
|
-
]
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## Release Process
|
|
271
|
-
|
|
272
|
-
### Version Management
|
|
273
|
-
```bash
|
|
274
|
-
# Patch release (bug fixes)
|
|
275
|
-
npm run release
|
|
276
|
-
|
|
277
|
-
# Minor release (new features)
|
|
278
|
-
npm run release:minor
|
|
279
|
-
|
|
280
|
-
# Major release (breaking changes)
|
|
281
|
-
npm run release:major
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Manual Release Steps
|
|
285
|
-
1. Update CHANGELOG.md
|
|
286
|
-
2. Run all tests and validation
|
|
287
|
-
3. Build and test package
|
|
288
|
-
4. Update version and tag
|
|
289
|
-
5. Publish to npm
|
|
290
|
-
6. Create GitHub release
|
|
291
|
-
|
|
292
|
-
## Documentation
|
|
293
|
-
|
|
294
|
-
### API Documentation
|
|
295
|
-
```bash
|
|
296
|
-
# Generate API docs
|
|
297
|
-
npm run docs:generate
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### Adding Documentation
|
|
301
|
-
- Update README.md for user-facing changes
|
|
302
|
-
- Add JSDoc comments for public APIs
|
|
303
|
-
- Update CHANGELOG.md for releases
|
|
304
|
-
- Create ADRs for architectural decisions
|
|
305
|
-
|
|
306
|
-
## Troubleshooting
|
|
307
|
-
|
|
308
|
-
### Common Issues
|
|
309
|
-
|
|
310
|
-
**Build Errors:**
|
|
311
|
-
```bash
|
|
312
|
-
# Clean and rebuild
|
|
313
|
-
npm run clean
|
|
314
|
-
npm install
|
|
315
|
-
npm run build
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
**Test Failures:**
|
|
319
|
-
```bash
|
|
320
|
-
# Update snapshots
|
|
321
|
-
npm test -- --updateSnapshot
|
|
322
|
-
|
|
323
|
-
# Run specific test
|
|
324
|
-
npm test -- --testNamePattern="specific test"
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
**TypeScript Errors:**
|
|
328
|
-
```bash
|
|
329
|
-
# Check types without emitting
|
|
330
|
-
npm run typecheck
|
|
331
|
-
|
|
332
|
-
# Check specific file
|
|
333
|
-
npx tsc --noEmit src/specific-file.ts
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
## Resources
|
|
337
|
-
|
|
338
|
-
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
|
|
339
|
-
- [Jest Testing Framework](https://jestjs.io/docs/getting-started)
|
|
340
|
-
- [ESLint Rules](https://eslint.org/docs/rules/)
|
|
341
|
-
- [Conventional Commits](https://www.conventionalcommits.org/)
|
|
342
|
-
|
|
343
|
-
## Support
|
|
344
|
-
|
|
345
|
-
If you need help with development:
|
|
346
|
-
|
|
347
|
-
1. Check existing issues and documentation
|
|
348
|
-
2. Ask in GitHub Discussions
|
|
349
|
-
3. Contact maintainers: faezemohades@gmail.com
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
Happy coding! ๐
|