svger-cli 2.0.2 → 2.0.3
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 +38 -0
- package/CHANGELOG.md +64 -0
- package/DEVELOPMENT.md +353 -0
- package/README.md +24 -5
- 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 +11 -11
- 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 +53 -17
- package/dist/services/config.js +11 -9
- package/dist/services/file-watcher.js +3 -3
- package/dist/services/svg-service.js +24 -12
- package/dist/templates/ComponentTemplate.js +25 -25
- package/dist/types/index.d.ts +7 -1
- package/dist/utils/native.d.ts +31 -1
- package/dist/utils/native.js +43 -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
package/dist/cli.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { CLI } from
|
|
3
|
-
import { svgService } from
|
|
4
|
-
import { configService } from
|
|
5
|
-
import { logger } from
|
|
2
|
+
import { CLI } from './utils/native.js';
|
|
3
|
+
import { svgService } from './services/svg-service.js';
|
|
4
|
+
import { configService } from './services/config.js';
|
|
5
|
+
import { logger } from './core/logger.js';
|
|
6
6
|
const program = new CLI();
|
|
7
7
|
/**
|
|
8
8
|
* svger-cli CLI
|
|
9
9
|
* Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter.
|
|
10
10
|
*/
|
|
11
11
|
program
|
|
12
|
-
.name(
|
|
13
|
-
.description(
|
|
14
|
-
.version(
|
|
12
|
+
.name('svger-cli')
|
|
13
|
+
.description('Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter')
|
|
14
|
+
.version('2.0.0');
|
|
15
15
|
// -------- Build Command --------
|
|
16
16
|
/**
|
|
17
17
|
* Build all SVGs from a source folder to an output folder.
|
|
18
18
|
*/
|
|
19
19
|
program
|
|
20
|
-
.command(
|
|
21
|
-
.description(
|
|
22
|
-
.option(
|
|
23
|
-
.option(
|
|
24
|
-
.option(
|
|
25
|
-
.option(
|
|
26
|
-
.option(
|
|
27
|
-
.option(
|
|
20
|
+
.command('build <src> <out>')
|
|
21
|
+
.description('Build all SVGs from source to output')
|
|
22
|
+
.option('--framework <type>', 'Target framework (react|vue|svelte|angular|solid|preact|lit|vanilla)')
|
|
23
|
+
.option('--typescript', 'Generate TypeScript components (default: true)')
|
|
24
|
+
.option('--no-typescript', 'Generate JavaScript components')
|
|
25
|
+
.option('--composition', 'Use Vue Composition API with <script setup>')
|
|
26
|
+
.option('--standalone', 'Generate Angular standalone components')
|
|
27
|
+
.option('--signals', 'Use Angular signals for reactive state')
|
|
28
28
|
.action(async (args, opts) => {
|
|
29
29
|
try {
|
|
30
30
|
const [src, out] = args;
|
|
@@ -62,8 +62,8 @@ program
|
|
|
62
62
|
* Watch a source folder and rebuild SVGs automatically on changes.
|
|
63
63
|
*/
|
|
64
64
|
program
|
|
65
|
-
.command(
|
|
66
|
-
.description(
|
|
65
|
+
.command('watch <src> <out>')
|
|
66
|
+
.description('Watch source folder and rebuild SVGs automatically')
|
|
67
67
|
.action(async (args) => {
|
|
68
68
|
try {
|
|
69
69
|
const [src, out] = args;
|
|
@@ -85,13 +85,13 @@ program
|
|
|
85
85
|
* Generate a component from a single SVG file.
|
|
86
86
|
*/
|
|
87
87
|
program
|
|
88
|
-
.command(
|
|
89
|
-
.description(
|
|
90
|
-
.option(
|
|
91
|
-
.option(
|
|
92
|
-
.option(
|
|
93
|
-
.option(
|
|
94
|
-
.option(
|
|
88
|
+
.command('generate <svgFile> <out>')
|
|
89
|
+
.description('Convert a single SVG file into a component')
|
|
90
|
+
.option('--framework <type>', 'Target framework (react|vue|svelte|angular|solid|preact|lit|vanilla)')
|
|
91
|
+
.option('--typescript', 'Generate TypeScript component (default: true)')
|
|
92
|
+
.option('--no-typescript', 'Generate JavaScript component')
|
|
93
|
+
.option('--composition', 'Use Vue Composition API with <script setup>')
|
|
94
|
+
.option('--standalone', 'Generate Angular standalone component')
|
|
95
95
|
.action(async (args, opts) => {
|
|
96
96
|
try {
|
|
97
97
|
const [svgFile, out] = args;
|
|
@@ -124,8 +124,8 @@ program
|
|
|
124
124
|
* Lock one or more SVG files to prevent accidental overwrites.
|
|
125
125
|
*/
|
|
126
126
|
program
|
|
127
|
-
.command(
|
|
128
|
-
.description(
|
|
127
|
+
.command('lock <files...>')
|
|
128
|
+
.description('Lock one or more SVG files')
|
|
129
129
|
.action((args) => {
|
|
130
130
|
try {
|
|
131
131
|
svgService.lockService.lockFiles(args);
|
|
@@ -139,8 +139,8 @@ program
|
|
|
139
139
|
* Unlock one or more SVG files to allow modifications.
|
|
140
140
|
*/
|
|
141
141
|
program
|
|
142
|
-
.command(
|
|
143
|
-
.description(
|
|
142
|
+
.command('unlock <files...>')
|
|
143
|
+
.description('Unlock one or more SVG files')
|
|
144
144
|
.action((args) => {
|
|
145
145
|
try {
|
|
146
146
|
svgService.lockService.unlockFiles(args);
|
|
@@ -155,19 +155,19 @@ program
|
|
|
155
155
|
* Manage svger-cli configuration.
|
|
156
156
|
*/
|
|
157
157
|
program
|
|
158
|
-
.command(
|
|
159
|
-
.description(
|
|
160
|
-
.option(
|
|
161
|
-
.option(
|
|
162
|
-
.option(
|
|
158
|
+
.command('config')
|
|
159
|
+
.description('Manage svger-cli configuration')
|
|
160
|
+
.option('--init', 'Create default .svgconfig.json')
|
|
161
|
+
.option('--set <keyValue>', 'Set config key=value')
|
|
162
|
+
.option('--show', 'Show current config')
|
|
163
163
|
.action(async (args, opts) => {
|
|
164
164
|
try {
|
|
165
165
|
if (opts.init)
|
|
166
166
|
return await configService.initConfig();
|
|
167
167
|
if (opts.set) {
|
|
168
|
-
const [key, value] = opts.set.split(
|
|
168
|
+
const [key, value] = opts.set.split('=');
|
|
169
169
|
if (!key || value === undefined) {
|
|
170
|
-
logger.error(
|
|
170
|
+
logger.error('Invalid format. Use key=value');
|
|
171
171
|
process.exit(1);
|
|
172
172
|
}
|
|
173
173
|
const parsedValue = !isNaN(Number(value)) ? Number(value) : value;
|
|
@@ -175,7 +175,7 @@ program
|
|
|
175
175
|
}
|
|
176
176
|
if (opts.show)
|
|
177
177
|
return configService.showConfig();
|
|
178
|
-
logger.error(
|
|
178
|
+
logger.error('No option provided. Use --init, --set, or --show');
|
|
179
179
|
}
|
|
180
180
|
catch (error) {
|
|
181
181
|
logger.error('Config operation failed:', error);
|
|
@@ -187,8 +187,8 @@ program
|
|
|
187
187
|
* Remove all generated SVG React components from an output folder.
|
|
188
188
|
*/
|
|
189
189
|
program
|
|
190
|
-
.command(
|
|
191
|
-
.description(
|
|
190
|
+
.command('clean <out>')
|
|
191
|
+
.description('Remove all generated SVG React components from output folder')
|
|
192
192
|
.action(async (args) => {
|
|
193
193
|
try {
|
|
194
194
|
const [out] = args;
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import path from
|
|
2
|
-
import { FileSystem } from
|
|
3
|
-
const CONFIG_FILE =
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { FileSystem } from './utils/native.js';
|
|
3
|
+
const CONFIG_FILE = '.svgconfig.json';
|
|
4
4
|
/**
|
|
5
5
|
* Get the absolute path to the configuration file.
|
|
6
6
|
*
|
|
@@ -31,24 +31,24 @@ export function writeConfig(config) {
|
|
|
31
31
|
*/
|
|
32
32
|
export async function initConfig() {
|
|
33
33
|
if (await FileSystem.exists(getConfigPath())) {
|
|
34
|
-
console.log(
|
|
34
|
+
console.log('⚠️ Config file already exists:', getConfigPath());
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
const defaultConfig = {
|
|
38
|
-
source:
|
|
39
|
-
output:
|
|
38
|
+
source: './src/assets/svg',
|
|
39
|
+
output: './src/components/icons',
|
|
40
40
|
watch: false,
|
|
41
41
|
defaultWidth: 24,
|
|
42
42
|
defaultHeight: 24,
|
|
43
|
-
defaultFill:
|
|
43
|
+
defaultFill: 'currentColor',
|
|
44
44
|
exclude: [],
|
|
45
45
|
styleRules: {
|
|
46
|
-
fill:
|
|
47
|
-
stroke:
|
|
46
|
+
fill: 'inherit',
|
|
47
|
+
stroke: 'none',
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
writeConfig(defaultConfig);
|
|
51
|
-
console.log(
|
|
51
|
+
console.log('✅ Config file created:', getConfigPath());
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Set a specific configuration key to a new value.
|
|
@@ -67,6 +67,6 @@ export function setConfig(key, value) {
|
|
|
67
67
|
*/
|
|
68
68
|
export function showConfig() {
|
|
69
69
|
const config = readConfig();
|
|
70
|
-
console.log(
|
|
70
|
+
console.log('📄 Current Config:');
|
|
71
71
|
console.log(JSON.stringify(config, null, 2));
|
|
72
72
|
}
|
|
@@ -47,7 +47,7 @@ export class SVGErrorHandler {
|
|
|
47
47
|
total: this.errorHistory.length,
|
|
48
48
|
bySeverity,
|
|
49
49
|
byCode,
|
|
50
|
-
recentErrors: this.errorHistory.slice(-10)
|
|
50
|
+
recentErrors: this.errorHistory.slice(-10),
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -70,7 +70,7 @@ export class SVGErrorHandler {
|
|
|
70
70
|
severity: this.determineSeverity(regularError),
|
|
71
71
|
context: context || {},
|
|
72
72
|
timestamp: Date.now(),
|
|
73
|
-
stack: regularError.stack
|
|
73
|
+
stack: regularError.stack,
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
categorizeError(error) {
|
|
@@ -156,15 +156,15 @@ export class SVGErrorHandler {
|
|
|
156
156
|
setupDefaultStrategies() {
|
|
157
157
|
// File not found recovery
|
|
158
158
|
this.registerRecoveryStrategy('FILE_NOT_FOUND', {
|
|
159
|
-
canRecover:
|
|
159
|
+
canRecover: error => error.context?.filePath && error.context?.canSkip === true,
|
|
160
160
|
recover: async (error, context) => {
|
|
161
161
|
logger.warn(`Skipping missing file: ${error.context?.filePath}`);
|
|
162
162
|
return { skipped: true, filePath: error.context?.filePath };
|
|
163
|
-
}
|
|
163
|
+
},
|
|
164
164
|
});
|
|
165
165
|
// Invalid SVG recovery
|
|
166
166
|
this.registerRecoveryStrategy('INVALID_SVG', {
|
|
167
|
-
canRecover:
|
|
167
|
+
canRecover: error => error.context?.svgContent,
|
|
168
168
|
recover: async (error, context) => {
|
|
169
169
|
logger.info('Attempting to clean invalid SVG content');
|
|
170
170
|
// Basic SVG cleanup
|
|
@@ -176,15 +176,15 @@ export class SVGErrorHandler {
|
|
|
176
176
|
.replace(/on\w+="[^"]*"/gi, '') // Remove event handlers
|
|
177
177
|
.replace(/javascript:[^"']*/gi, ''); // Remove javascript: URLs
|
|
178
178
|
return { cleanedContent: cleaned };
|
|
179
|
-
}
|
|
179
|
+
},
|
|
180
180
|
});
|
|
181
181
|
// Permission denied recovery
|
|
182
182
|
this.registerRecoveryStrategy('PERMISSION_DENIED', {
|
|
183
|
-
canRecover:
|
|
183
|
+
canRecover: error => error.context?.alternative,
|
|
184
184
|
recover: async (error, context) => {
|
|
185
185
|
logger.warn(`Using alternative path due to permission issue: ${error.context?.alternative}`);
|
|
186
186
|
return { alternativePath: error.context?.alternative };
|
|
187
|
-
}
|
|
187
|
+
},
|
|
188
188
|
});
|
|
189
189
|
logger.debug('Default error recovery strategies loaded');
|
|
190
190
|
}
|
|
@@ -218,7 +218,10 @@ export function handleErrors(context) {
|
|
|
218
218
|
return function (target, propertyName, descriptor) {
|
|
219
219
|
const method = descriptor.value;
|
|
220
220
|
descriptor.value = async function (...args) {
|
|
221
|
-
return withErrorHandling(() => method.apply(this, args), {
|
|
221
|
+
return withErrorHandling(() => method.apply(this, args), {
|
|
222
|
+
method: propertyName,
|
|
223
|
+
...context,
|
|
224
|
+
});
|
|
222
225
|
};
|
|
223
226
|
};
|
|
224
227
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export class FrameworkTemplateEngine {
|
|
2
2
|
generateComponent(options) {
|
|
3
|
-
const { framework, componentName, svgContent, typescript = true, frameworkOptions = {} } = options;
|
|
3
|
+
const { framework, componentName, svgContent, typescript = true, frameworkOptions = {}, } = options;
|
|
4
4
|
switch (framework) {
|
|
5
5
|
case 'react':
|
|
6
6
|
return this.generateReactComponent(componentName, svgContent, typescript, frameworkOptions);
|
|
@@ -215,8 +215,10 @@ export default defineComponent({
|
|
|
215
215
|
>
|
|
216
216
|
${innerContent}
|
|
217
217
|
</svg>
|
|
218
|
-
\`,${standalone
|
|
219
|
-
|
|
218
|
+
\`,${standalone
|
|
219
|
+
? `
|
|
220
|
+
changeDetection: ChangeDetectionStrategy.OnPush`
|
|
221
|
+
: ''}
|
|
220
222
|
})
|
|
221
223
|
export class ${componentName}Component {
|
|
222
224
|
@Input() className: string = '';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os from 'os';
|
|
1
2
|
import { logger } from '../core/logger.js';
|
|
2
3
|
import { svgProcessor } from '../processors/svg-processor.js';
|
|
3
4
|
/**
|
|
@@ -18,7 +19,7 @@ export class PerformanceEngine {
|
|
|
18
19
|
* Process multiple SVG files in parallel with optimized batching
|
|
19
20
|
*/
|
|
20
21
|
async processBatch(files, config = {}) {
|
|
21
|
-
const { batchSize = 10, parallel = true, maxConcurrency = Math.min(4,
|
|
22
|
+
const { batchSize = 10, parallel = true, maxConcurrency = Math.min(4, os.cpus().length), } = config;
|
|
22
23
|
logger.info(`Processing ${files.length} files with ${parallel ? 'parallel' : 'sequential'} execution`);
|
|
23
24
|
const startTime = Date.now();
|
|
24
25
|
const results = [];
|
|
@@ -57,7 +58,7 @@ export class PerformanceEngine {
|
|
|
57
58
|
return {
|
|
58
59
|
success: true,
|
|
59
60
|
filePath: file.path,
|
|
60
|
-
duration: Date.now() - startTime
|
|
61
|
+
duration: Date.now() - startTime,
|
|
61
62
|
};
|
|
62
63
|
}
|
|
63
64
|
try {
|
|
@@ -70,7 +71,7 @@ export class PerformanceEngine {
|
|
|
70
71
|
success: result.success,
|
|
71
72
|
filePath: file.path,
|
|
72
73
|
error: result.error,
|
|
73
|
-
duration: Date.now() - startTime
|
|
74
|
+
duration: Date.now() - startTime,
|
|
74
75
|
};
|
|
75
76
|
}
|
|
76
77
|
catch (error) {
|
|
@@ -78,7 +79,7 @@ export class PerformanceEngine {
|
|
|
78
79
|
success: false,
|
|
79
80
|
filePath: file.path,
|
|
80
81
|
error: error,
|
|
81
|
-
duration: Date.now() - startTime
|
|
82
|
+
duration: Date.now() - startTime,
|
|
82
83
|
};
|
|
83
84
|
}
|
|
84
85
|
}
|
|
@@ -131,7 +132,7 @@ export class PerformanceEngine {
|
|
|
131
132
|
heapTotal: heapTotalMB,
|
|
132
133
|
external: memUsage.external / 1024 / 1024,
|
|
133
134
|
cacheSize,
|
|
134
|
-
recommendations
|
|
135
|
+
recommendations,
|
|
135
136
|
};
|
|
136
137
|
}
|
|
137
138
|
/**
|
|
@@ -149,7 +150,7 @@ export class PerformanceEngine {
|
|
|
149
150
|
return {
|
|
150
151
|
cacheHitRate: 0, // Placeholder
|
|
151
152
|
averageProcessingTime: 0, // Placeholder
|
|
152
|
-
memoryUsage: this.monitorMemoryUsage()
|
|
153
|
+
memoryUsage: this.monitorMemoryUsage(),
|
|
153
154
|
};
|
|
154
155
|
}
|
|
155
156
|
// Private helper methods
|
|
@@ -188,7 +189,7 @@ export class PerformanceEngine {
|
|
|
188
189
|
setCachedResult(key, result) {
|
|
189
190
|
this.processingCache.set(key, {
|
|
190
191
|
result,
|
|
191
|
-
timestamp: Date.now()
|
|
192
|
+
timestamp: Date.now(),
|
|
192
193
|
});
|
|
193
194
|
}
|
|
194
195
|
applyFastOptimizations(content) {
|
|
@@ -234,7 +235,7 @@ class Semaphore {
|
|
|
234
235
|
this.permits--;
|
|
235
236
|
return Promise.resolve();
|
|
236
237
|
}
|
|
237
|
-
return new Promise(
|
|
238
|
+
return new Promise(resolve => {
|
|
238
239
|
this.waitQueue.push(resolve);
|
|
239
240
|
});
|
|
240
241
|
}
|
|
@@ -26,7 +26,7 @@ export class PluginManager {
|
|
|
26
26
|
process: async (content, options) => {
|
|
27
27
|
return this.optimizeSVG(content, options);
|
|
28
28
|
},
|
|
29
|
-
validate: (options) => true
|
|
29
|
+
validate: (options) => true,
|
|
30
30
|
});
|
|
31
31
|
// Color Theme Plugin
|
|
32
32
|
this.registerPlugin({
|
|
@@ -37,7 +37,7 @@ export class PluginManager {
|
|
|
37
37
|
},
|
|
38
38
|
validate: (options) => {
|
|
39
39
|
return options && typeof options.theme === 'object';
|
|
40
|
-
}
|
|
40
|
+
},
|
|
41
41
|
});
|
|
42
42
|
// Size Normalizer Plugin
|
|
43
43
|
this.registerPlugin({
|
|
@@ -45,7 +45,7 @@ export class PluginManager {
|
|
|
45
45
|
version: '1.0.0',
|
|
46
46
|
process: async (content, options) => {
|
|
47
47
|
return this.normalizeSizes(content, options);
|
|
48
|
-
}
|
|
48
|
+
},
|
|
49
49
|
});
|
|
50
50
|
logger.debug('Built-in plugins loaded');
|
|
51
51
|
}
|
|
@@ -67,7 +67,9 @@ export class PluginManager {
|
|
|
67
67
|
if (!plugin) {
|
|
68
68
|
throw new Error(`Plugin not found: ${name}`);
|
|
69
69
|
}
|
|
70
|
-
if (plugin.validate &&
|
|
70
|
+
if (plugin.validate &&
|
|
71
|
+
config?.options &&
|
|
72
|
+
!plugin.validate(config.options)) {
|
|
71
73
|
throw new Error(`Invalid options for plugin: ${name}`);
|
|
72
74
|
}
|
|
73
75
|
this.activePlugins.add(name);
|
|
@@ -113,7 +115,7 @@ export class PluginManager {
|
|
|
113
115
|
return Array.from(this.plugins.entries()).map(([name, plugin]) => ({
|
|
114
116
|
name,
|
|
115
117
|
version: plugin.version,
|
|
116
|
-
enabled: this.activePlugins.has(name)
|
|
118
|
+
enabled: this.activePlugins.has(name),
|
|
117
119
|
}));
|
|
118
120
|
}
|
|
119
121
|
/**
|
|
@@ -23,7 +23,7 @@ export class SVGStyleCompiler {
|
|
|
23
23
|
inline: {},
|
|
24
24
|
classes: [],
|
|
25
25
|
cssRules: [],
|
|
26
|
-
mediaQueries: []
|
|
26
|
+
mediaQueries: [],
|
|
27
27
|
};
|
|
28
28
|
// Get theme if specified
|
|
29
29
|
const theme = this.resolveTheme(options.theme);
|
|
@@ -76,7 +76,8 @@ export class SVGStyleCompiler {
|
|
|
76
76
|
const imports = hasCustomStyles
|
|
77
77
|
? `import React from 'react';\nimport type { SVGProps } from "react";`
|
|
78
78
|
: `import type { SVGProps } from "react";`;
|
|
79
|
-
const styledCSS = hasCustomStyles
|
|
79
|
+
const styledCSS = hasCustomStyles
|
|
80
|
+
? `
|
|
80
81
|
const ${componentName}Styles = \`
|
|
81
82
|
${compiled.cssRules.join('\n')}
|
|
82
83
|
${compiled.mediaQueries.join('\n')}
|
|
@@ -92,7 +93,8 @@ if (typeof document !== 'undefined') {
|
|
|
92
93
|
document.head.appendChild(style);
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
|
-
`
|
|
96
|
+
`
|
|
97
|
+
: '';
|
|
96
98
|
const inlineStyleObject = Object.keys(compiled.inline).length > 0
|
|
97
99
|
? `const defaultStyles = ${JSON.stringify(compiled.inline, null, 2)};`
|
|
98
100
|
: '';
|
|
@@ -295,28 +297,28 @@ if (typeof document !== 'undefined') {
|
|
|
295
297
|
danger: '#dc3545',
|
|
296
298
|
info: '#17a2b8',
|
|
297
299
|
light: '#f8f9fa',
|
|
298
|
-
dark: '#343a40'
|
|
300
|
+
dark: '#343a40',
|
|
299
301
|
},
|
|
300
302
|
sizes: {
|
|
301
303
|
xs: 12,
|
|
302
304
|
sm: 16,
|
|
303
305
|
md: 24,
|
|
304
306
|
lg: 32,
|
|
305
|
-
xl: 48
|
|
307
|
+
xl: 48,
|
|
306
308
|
},
|
|
307
309
|
spacing: {
|
|
308
310
|
1: '0.25rem',
|
|
309
311
|
2: '0.5rem',
|
|
310
312
|
3: '0.75rem',
|
|
311
313
|
4: '1rem',
|
|
312
|
-
5: '1.5rem'
|
|
314
|
+
5: '1.5rem',
|
|
313
315
|
},
|
|
314
316
|
breakpoints: {
|
|
315
317
|
sm: '576px',
|
|
316
318
|
md: '768px',
|
|
317
319
|
lg: '992px',
|
|
318
|
-
xl: '1200px'
|
|
319
|
-
}
|
|
320
|
+
xl: '1200px',
|
|
321
|
+
},
|
|
320
322
|
});
|
|
321
323
|
// Dark theme
|
|
322
324
|
this.registerTheme({
|
|
@@ -329,28 +331,28 @@ if (typeof document !== 'undefined') {
|
|
|
329
331
|
danger: '#dc3545',
|
|
330
332
|
info: '#0dcaf0',
|
|
331
333
|
light: '#212529',
|
|
332
|
-
dark: '#f8f9fa'
|
|
334
|
+
dark: '#f8f9fa',
|
|
333
335
|
},
|
|
334
336
|
sizes: {
|
|
335
337
|
xs: 12,
|
|
336
338
|
sm: 16,
|
|
337
339
|
md: 24,
|
|
338
340
|
lg: 32,
|
|
339
|
-
xl: 48
|
|
341
|
+
xl: 48,
|
|
340
342
|
},
|
|
341
343
|
spacing: {
|
|
342
344
|
1: '0.25rem',
|
|
343
345
|
2: '0.5rem',
|
|
344
346
|
3: '0.75rem',
|
|
345
347
|
4: '1rem',
|
|
346
|
-
5: '1.5rem'
|
|
348
|
+
5: '1.5rem',
|
|
347
349
|
},
|
|
348
350
|
breakpoints: {
|
|
349
351
|
sm: '576px',
|
|
350
352
|
md: '768px',
|
|
351
353
|
lg: '992px',
|
|
352
|
-
xl: '1200px'
|
|
353
|
-
}
|
|
354
|
+
xl: '1200px',
|
|
355
|
+
},
|
|
354
356
|
});
|
|
355
357
|
}
|
|
356
358
|
resolveTheme(theme) {
|
|
@@ -373,7 +375,7 @@ if (typeof document !== 'undefined') {
|
|
|
373
375
|
clipPath: 'clipPath',
|
|
374
376
|
mask: 'mask',
|
|
375
377
|
animation: 'animation',
|
|
376
|
-
transition: 'transition'
|
|
378
|
+
transition: 'transition',
|
|
377
379
|
};
|
|
378
380
|
for (const [cssProp, optionKey] of Object.entries(styleMap)) {
|
|
379
381
|
const value = options[optionKey];
|
|
@@ -416,7 +418,7 @@ if (typeof document !== 'undefined') {
|
|
|
416
418
|
sm: '576px',
|
|
417
419
|
md: '768px',
|
|
418
420
|
lg: '992px',
|
|
419
|
-
xl: '1200px'
|
|
421
|
+
xl: '1200px',
|
|
420
422
|
};
|
|
421
423
|
for (const [prop, value] of Object.entries(options)) {
|
|
422
424
|
if (this.isResponsiveValue(value)) {
|
|
@@ -25,37 +25,37 @@ export class TemplateManager {
|
|
|
25
25
|
this.registerTemplate({
|
|
26
26
|
name: 'react-functional',
|
|
27
27
|
generate: (options) => this.generateReactFunctional(options),
|
|
28
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
28
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
29
29
|
});
|
|
30
30
|
// React Functional Component with forwardRef
|
|
31
31
|
this.registerTemplate({
|
|
32
32
|
name: 'react-forwardref',
|
|
33
33
|
generate: (options) => this.generateReactForwardRef(options),
|
|
34
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
34
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
35
35
|
});
|
|
36
36
|
// React Class Component (legacy support)
|
|
37
37
|
this.registerTemplate({
|
|
38
38
|
name: 'react-class',
|
|
39
39
|
generate: (options) => this.generateReactClass(options),
|
|
40
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
40
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
41
41
|
});
|
|
42
42
|
// Styled Components Template
|
|
43
43
|
this.registerTemplate({
|
|
44
44
|
name: 'styled-components',
|
|
45
45
|
generate: (options) => this.generateStyledComponents(options),
|
|
46
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
46
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
47
47
|
});
|
|
48
48
|
// TypeScript Native (no React)
|
|
49
49
|
this.registerTemplate({
|
|
50
50
|
name: 'typescript-native',
|
|
51
51
|
generate: (options) => this.generateTypeScriptNative(options),
|
|
52
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
52
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
53
53
|
});
|
|
54
54
|
// Enhanced Styled Template
|
|
55
55
|
this.registerTemplate({
|
|
56
56
|
name: 'enhanced-styled',
|
|
57
57
|
generate: (options) => this.generateEnhancedStyled(options),
|
|
58
|
-
validate: (options) => !!options.componentName && !!options.svgContent
|
|
58
|
+
validate: (options) => !!options.componentName && !!options.svgContent,
|
|
59
59
|
});
|
|
60
60
|
logger.debug('Built-in templates loaded');
|
|
61
61
|
}
|
|
@@ -97,7 +97,7 @@ export class TemplateManager {
|
|
|
97
97
|
name: templateName,
|
|
98
98
|
generate: (options) => {
|
|
99
99
|
return this.processStringTemplate(templateContent, options);
|
|
100
|
-
}
|
|
100
|
+
},
|
|
101
101
|
});
|
|
102
102
|
logger.info(`Custom template loaded: ${templateName}`);
|
|
103
103
|
}
|
|
@@ -127,7 +127,7 @@ export class TemplateManager {
|
|
|
127
127
|
* Standard React Functional Component
|
|
128
128
|
*/
|
|
129
129
|
generateReactFunctional(options) {
|
|
130
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
130
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
131
131
|
return `import React from "react";
|
|
132
132
|
import type { SVGProps } from "react";
|
|
133
133
|
|
|
@@ -173,7 +173,7 @@ export default ${componentName};
|
|
|
173
173
|
* React Functional Component with forwardRef
|
|
174
174
|
*/
|
|
175
175
|
generateReactForwardRef(options) {
|
|
176
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
176
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
177
177
|
return `import { forwardRef } from "react";
|
|
178
178
|
import type { SVGProps } from "react";
|
|
179
179
|
|
|
@@ -208,7 +208,7 @@ export default ${componentName};
|
|
|
208
208
|
* React Class Component (legacy)
|
|
209
209
|
*/
|
|
210
210
|
generateReactClass(options) {
|
|
211
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
211
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
212
212
|
return `import { Component } from "react";
|
|
213
213
|
import type { SVGProps } from "react";
|
|
214
214
|
|
|
@@ -242,7 +242,7 @@ export default ${componentName};
|
|
|
242
242
|
* Styled Components Template
|
|
243
243
|
*/
|
|
244
244
|
generateStyledComponents(options) {
|
|
245
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
245
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
246
246
|
return `import styled from "styled-components";
|
|
247
247
|
import type { SVGProps } from "react";
|
|
248
248
|
|
|
@@ -275,7 +275,7 @@ export default ${componentName};
|
|
|
275
275
|
* TypeScript Native (no React dependencies)
|
|
276
276
|
*/
|
|
277
277
|
generateTypeScriptNative(options) {
|
|
278
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
278
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
279
279
|
return `/**
|
|
280
280
|
* ${componentName} SVG Icon (Native TypeScript)
|
|
281
281
|
* Generated by svger-cli
|
|
@@ -328,7 +328,7 @@ export default ${componentName};
|
|
|
328
328
|
...options,
|
|
329
329
|
defaultWidth: options.defaultWidth || 24,
|
|
330
330
|
defaultHeight: options.defaultHeight || 24,
|
|
331
|
-
defaultFill: options.defaultFill || 'currentColor'
|
|
331
|
+
defaultFill: options.defaultFill || 'currentColor',
|
|
332
332
|
};
|
|
333
333
|
let processed = template;
|
|
334
334
|
// Replace variables in the format {{variableName}}
|
|
@@ -342,7 +342,7 @@ export default ${componentName};
|
|
|
342
342
|
* Enhanced Styled Template with comprehensive styling support
|
|
343
343
|
*/
|
|
344
344
|
generateEnhancedStyled(options) {
|
|
345
|
-
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor' } = options;
|
|
345
|
+
const { componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = 'currentColor', } = options;
|
|
346
346
|
return `import React from "react";
|
|
347
347
|
import type { SVGProps } from "react";
|
|
348
348
|
|