svger-cli 4.0.2 → 4.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/CHANGELOG.md +114 -0
- package/README.md +27 -27
- package/dist/builder.d.ts +6 -3
- package/dist/builder.js +34 -24
- package/dist/cli.js +30 -24
- package/dist/config.d.ts +8 -2
- package/dist/config.js +17 -124
- package/dist/core/logger.js +8 -4
- package/dist/core/performance-engine.js +16 -3
- package/dist/core/style-compiler.js +6 -7
- package/dist/core/template-manager.js +18 -14
- package/dist/index.d.ts +1 -2
- package/dist/index.js +8 -2
- package/dist/integrations/jest-preset.js +30 -2
- package/dist/optimizers/path-parser.js +199 -115
- package/dist/optimizers/path-simplifier.js +27 -24
- package/dist/optimizers/shape-conversion.js +22 -27
- package/dist/optimizers/transform-collapsing.js +11 -15
- package/dist/optimizers/transform-optimizer.js +16 -21
- package/dist/optimizers/types.js +64 -74
- package/dist/processors/svg-processor.js +20 -20
- package/dist/services/config.js +8 -4
- package/dist/services/svg-service.js +9 -2
- package/dist/utils/native.d.ts +0 -1
- package/dist/utils/native.js +6 -14
- package/dist/watch.js +4 -3
- package/docs/ERROR-HANDLING-STANDARD.md +1 -1
- package/docs/OPTIONAL-DEPENDENCIES.md +1 -1
- package/package.json +1 -1
package/dist/config.js
CHANGED
|
@@ -1,158 +1,51 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { FileSystem } from './utils/native.js';
|
|
3
|
-
const CONFIG_FILE = '.svgconfig.json';
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
2
|
+
* Legacy configuration module - delegates to ConfigService.
|
|
6
3
|
*
|
|
7
|
-
* @
|
|
4
|
+
* @deprecated Use `configService` from `./services/config.js` instead.
|
|
5
|
+
* This module exists only for backward compatibility and will be removed in v5.0.0.
|
|
8
6
|
*/
|
|
9
|
-
|
|
10
|
-
return path.resolve(CONFIG_FILE);
|
|
11
|
-
}
|
|
7
|
+
import { configService } from './services/config.js';
|
|
12
8
|
/**
|
|
13
9
|
* Read the current svger-cli configuration.
|
|
14
10
|
*
|
|
15
|
-
* @
|
|
11
|
+
* @deprecated Use `configService.readConfig()` instead.
|
|
12
|
+
* @returns {Record<string, any>} Configuration object.
|
|
16
13
|
*/
|
|
17
14
|
export function readConfig() {
|
|
18
|
-
return
|
|
15
|
+
return configService.readConfig();
|
|
19
16
|
}
|
|
20
17
|
/**
|
|
21
18
|
* Write a configuration object to the config file.
|
|
22
19
|
*
|
|
20
|
+
* @deprecated Use `configService.writeConfig(config)` instead.
|
|
23
21
|
* @param {Record<string, any>} config - Configuration object to write.
|
|
24
22
|
*/
|
|
25
23
|
export function writeConfig(config) {
|
|
26
|
-
|
|
24
|
+
configService.writeConfig(config);
|
|
27
25
|
}
|
|
28
26
|
/**
|
|
29
27
|
* Initialize the svger-cli configuration with default values.
|
|
30
|
-
*
|
|
28
|
+
*
|
|
29
|
+
* @deprecated Use `configService.initConfig()` instead.
|
|
31
30
|
*/
|
|
32
31
|
export async function initConfig() {
|
|
33
|
-
|
|
34
|
-
console.log('⚠️ Config file already exists:', getConfigPath());
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const defaultConfig = {
|
|
38
|
-
// Configuration Version (for migration compatibility)
|
|
39
|
-
version: '4.0.0',
|
|
40
|
-
// Source & Output
|
|
41
|
-
source: './src/assets/svg',
|
|
42
|
-
output: './src/components/icons',
|
|
43
|
-
// Framework Configuration
|
|
44
|
-
framework: 'react',
|
|
45
|
-
typescript: true,
|
|
46
|
-
componentType: 'functional',
|
|
47
|
-
// Processing Options
|
|
48
|
-
watch: false,
|
|
49
|
-
parallel: true,
|
|
50
|
-
batchSize: 10,
|
|
51
|
-
maxConcurrency: 4,
|
|
52
|
-
cache: true,
|
|
53
|
-
// Default Properties
|
|
54
|
-
defaultWidth: 24,
|
|
55
|
-
defaultHeight: 24,
|
|
56
|
-
defaultFill: 'currentColor',
|
|
57
|
-
defaultStroke: 'none',
|
|
58
|
-
defaultStrokeWidth: 1,
|
|
59
|
-
// Styling Configuration
|
|
60
|
-
styleRules: {
|
|
61
|
-
fill: 'inherit',
|
|
62
|
-
stroke: 'none',
|
|
63
|
-
},
|
|
64
|
-
responsive: {
|
|
65
|
-
breakpoints: ['sm', 'md', 'lg', 'xl'],
|
|
66
|
-
values: {
|
|
67
|
-
width: ['16px', '20px', '24px', '32px'],
|
|
68
|
-
height: ['16px', '20px', '24px', '32px'],
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
theme: {
|
|
72
|
-
mode: 'auto',
|
|
73
|
-
variables: {
|
|
74
|
-
primary: 'currentColor',
|
|
75
|
-
secondary: '#6b7280',
|
|
76
|
-
accent: '#3b82f6',
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
animations: [],
|
|
80
|
-
// v4.0.0: Plugin System
|
|
81
|
-
plugins: [],
|
|
82
|
-
// Advanced Options
|
|
83
|
-
exclude: [],
|
|
84
|
-
include: [],
|
|
85
|
-
// Error Handling
|
|
86
|
-
errorHandling: {
|
|
87
|
-
strategy: 'continue',
|
|
88
|
-
maxRetries: 3,
|
|
89
|
-
timeout: 30000,
|
|
90
|
-
},
|
|
91
|
-
// Performance Settings
|
|
92
|
-
performance: {
|
|
93
|
-
optimization: 'balanced',
|
|
94
|
-
memoryLimit: 512,
|
|
95
|
-
cacheTimeout: 3600000,
|
|
96
|
-
},
|
|
97
|
-
// Output Customization
|
|
98
|
-
outputConfig: {
|
|
99
|
-
naming: 'pascal',
|
|
100
|
-
extension: 'tsx',
|
|
101
|
-
directory: './src/components/icons',
|
|
102
|
-
},
|
|
103
|
-
// Framework-specific configurations
|
|
104
|
-
react: {
|
|
105
|
-
componentType: 'functional',
|
|
106
|
-
forwardRef: true,
|
|
107
|
-
memo: false,
|
|
108
|
-
propsInterface: 'SVGProps',
|
|
109
|
-
styledComponents: false,
|
|
110
|
-
cssModules: false,
|
|
111
|
-
},
|
|
112
|
-
vue: {
|
|
113
|
-
api: 'composition',
|
|
114
|
-
setup: true,
|
|
115
|
-
typescript: true,
|
|
116
|
-
scoped: true,
|
|
117
|
-
cssVariables: true,
|
|
118
|
-
},
|
|
119
|
-
angular: {
|
|
120
|
-
standalone: true,
|
|
121
|
-
signals: true,
|
|
122
|
-
changeDetection: 'OnPush',
|
|
123
|
-
encapsulation: 'Emulated',
|
|
124
|
-
},
|
|
125
|
-
// Legacy support (deprecated)
|
|
126
|
-
template: {
|
|
127
|
-
type: 'default',
|
|
128
|
-
},
|
|
129
|
-
frameworkOptions: {
|
|
130
|
-
forwardRef: true,
|
|
131
|
-
memo: false,
|
|
132
|
-
scriptSetup: true,
|
|
133
|
-
standalone: true,
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
writeConfig(defaultConfig);
|
|
137
|
-
console.log('✅ Config file created:', getConfigPath());
|
|
32
|
+
return configService.initConfig();
|
|
138
33
|
}
|
|
139
34
|
/**
|
|
140
35
|
* Set a specific configuration key to a new value.
|
|
141
36
|
*
|
|
37
|
+
* @deprecated Use `configService.setConfig(key, value)` instead.
|
|
142
38
|
* @param {string} key - The config key to set.
|
|
143
39
|
* @param {any} value - The value to assign to the key.
|
|
144
40
|
*/
|
|
145
41
|
export function setConfig(key, value) {
|
|
146
|
-
|
|
147
|
-
config[key] = value;
|
|
148
|
-
writeConfig(config);
|
|
149
|
-
console.log(`✅ Set config ${key}=${value}`);
|
|
42
|
+
configService.setConfig(key, value);
|
|
150
43
|
}
|
|
151
44
|
/**
|
|
152
45
|
* Display the current configuration in the console.
|
|
46
|
+
*
|
|
47
|
+
* @deprecated Use `configService.showConfig()` instead.
|
|
153
48
|
*/
|
|
154
49
|
export function showConfig() {
|
|
155
|
-
|
|
156
|
-
console.log('📄 Current Config:');
|
|
157
|
-
console.log(JSON.stringify(config, null, 2));
|
|
50
|
+
configService.showConfig();
|
|
158
51
|
}
|
package/dist/core/logger.js
CHANGED
|
@@ -19,10 +19,14 @@ export class LoggerService {
|
|
|
19
19
|
this.enableColors = enabled;
|
|
20
20
|
}
|
|
21
21
|
shouldLog(level) {
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
// O(1) Map lookup instead of O(n) indexOf on array
|
|
23
|
+
const levelPriority = {
|
|
24
|
+
debug: 0,
|
|
25
|
+
info: 1,
|
|
26
|
+
warn: 2,
|
|
27
|
+
error: 3,
|
|
28
|
+
};
|
|
29
|
+
return (levelPriority[level] ?? 0) >= (levelPriority[this.logLevel] ?? 0);
|
|
26
30
|
}
|
|
27
31
|
formatMessage(level, message) {
|
|
28
32
|
const timestamp = new Date().toISOString();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
|
+
import fs from 'fs';
|
|
2
3
|
import { logger } from '../core/logger.js';
|
|
3
4
|
import { svgProcessor } from '../processors/svg-processor.js';
|
|
4
5
|
/**
|
|
@@ -41,7 +42,12 @@ export class PerformanceEngine {
|
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
const totalDuration = Date.now() - startTime;
|
|
44
|
-
|
|
45
|
+
// Single-pass counter instead of results.filter().length — O(n) → O(n) but avoids intermediate array allocation
|
|
46
|
+
let successful = 0;
|
|
47
|
+
for (let i = 0; i < results.length; i++) {
|
|
48
|
+
if (results[i].success)
|
|
49
|
+
successful++;
|
|
50
|
+
}
|
|
45
51
|
logger.info(`Batch processing complete: ${successful}/${files.length} successful in ${totalDuration}ms`);
|
|
46
52
|
return results;
|
|
47
53
|
}
|
|
@@ -166,8 +172,15 @@ export class PerformanceEngine {
|
|
|
166
172
|
}
|
|
167
173
|
}
|
|
168
174
|
generateCacheKey(filePath, options) {
|
|
169
|
-
//
|
|
170
|
-
|
|
175
|
+
// Include file modification time to invalidate cache when file changes
|
|
176
|
+
let mtimeMs = 0;
|
|
177
|
+
try {
|
|
178
|
+
mtimeMs = fs.statSync(filePath).mtimeMs;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// File may not exist yet; use 0 so caching still works
|
|
182
|
+
}
|
|
183
|
+
const key = JSON.stringify({ filePath, mtimeMs, options });
|
|
171
184
|
return Buffer.from(key).toString('base64');
|
|
172
185
|
}
|
|
173
186
|
getCachedResult(key) {
|
|
@@ -217,13 +217,12 @@ function getAnimationStyles(animationType: string): React.CSSProperties {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
function getThemeStyles(theme: _theme): React.CSSProperties {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
return {};
|
|
220
|
+
// O(1) object lookup instead of if-else chain
|
|
221
|
+
const themeStyleMap: Record<string, React.CSSProperties> = {
|
|
222
|
+
dark: { filter: 'invert(1) hue-rotate(180deg)' },
|
|
223
|
+
auto: { filter: 'var(--svger-theme-filter, none)' },
|
|
224
|
+
};
|
|
225
|
+
return themeStyleMap[theme as string] || {};
|
|
227
226
|
}
|
|
228
227
|
|
|
229
228
|
${componentName}.displayName = "${componentName}";
|
|
@@ -424,23 +424,27 @@ const ${componentName} = React.forwardRef<SVGSVGElement, ${componentName}Props>(
|
|
|
424
424
|
baseStyles.color = colorMap[variant];
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
-
// Apply theme
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
427
|
+
// Apply theme — O(1) object lookup instead of if-else chain
|
|
428
|
+
const themeFilters: Record<string, string> = {
|
|
429
|
+
dark: 'invert(1)',
|
|
430
|
+
auto: 'var(--svger-theme-filter, none)',
|
|
431
|
+
};
|
|
432
|
+
if (theme && themeFilters[theme]) {
|
|
433
|
+
baseStyles.filter = themeFilters[theme];
|
|
432
434
|
}
|
|
433
435
|
|
|
434
|
-
// Apply animation
|
|
436
|
+
// Apply animation — O(1) object lookup instead of if-else chain
|
|
435
437
|
if (animate) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
438
|
+
const animationMap: Record<string, string> = {
|
|
439
|
+
spin: 'svger-spin 2s linear infinite',
|
|
440
|
+
pulse: 'svger-pulse 2s ease-in-out infinite',
|
|
441
|
+
bounce: 'svger-bounce 1s infinite',
|
|
442
|
+
fade: 'svger-fade 2s ease-in-out infinite alternate',
|
|
443
|
+
};
|
|
444
|
+
const animKey = animate === true ? 'spin' : animate;
|
|
445
|
+
const anim = animationMap[animKey as string];
|
|
446
|
+
if (anim) {
|
|
447
|
+
baseStyles.animation = anim;
|
|
444
448
|
}
|
|
445
449
|
}
|
|
446
450
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* A high-performance, framework-agnostic SVG processing toolkit with enterprise-grade
|
|
5
5
|
* architecture and comprehensive styling capabilities.
|
|
6
6
|
*
|
|
7
|
-
* @version 2.0.0
|
|
8
7
|
* @author SVGER-CLI Development Team
|
|
9
8
|
* @license MIT
|
|
10
9
|
*/
|
|
@@ -148,7 +147,7 @@ export declare const SVGER: {
|
|
|
148
147
|
/**
|
|
149
148
|
* Package Version Information
|
|
150
149
|
*/
|
|
151
|
-
export declare const VERSION
|
|
150
|
+
export declare const VERSION: string;
|
|
152
151
|
export declare const PACKAGE_NAME = "svger-cli";
|
|
153
152
|
/**
|
|
154
153
|
* Webpack Plugin - Official webpack integration for SVGER-CLI
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,16 @@
|
|
|
4
4
|
* A high-performance, framework-agnostic SVG processing toolkit with enterprise-grade
|
|
5
5
|
* architecture and comprehensive styling capabilities.
|
|
6
6
|
*
|
|
7
|
-
* @version 2.0.0
|
|
8
7
|
* @author SVGER-CLI Development Team
|
|
9
8
|
* @license MIT
|
|
10
9
|
*/
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import { dirname, join } from 'path';
|
|
13
|
+
// Get package version dynamically
|
|
14
|
+
const __index_filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __index_dirname = dirname(__index_filename);
|
|
16
|
+
const __packageJson = JSON.parse(readFileSync(join(__index_dirname, '../package.json'), 'utf-8'));
|
|
11
17
|
// ============================================================================
|
|
12
18
|
// CORE SERVICES
|
|
13
19
|
// ============================================================================
|
|
@@ -149,7 +155,7 @@ export const SVGER = {
|
|
|
149
155
|
/**
|
|
150
156
|
* Package Version Information
|
|
151
157
|
*/
|
|
152
|
-
export const VERSION =
|
|
158
|
+
export const VERSION = __packageJson.version;
|
|
153
159
|
export const PACKAGE_NAME = 'svger-cli';
|
|
154
160
|
// ============================================================================
|
|
155
161
|
// BUILD TOOL INTEGRATIONS
|
|
@@ -72,12 +72,40 @@ module.exports.default = ${componentName};
|
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* Synchronous SVG content cleaning for Jest compatibility.
|
|
77
|
+
* svgProcessor.cleanSVGContent() is async (uses optimizer pipeline) and cannot
|
|
78
|
+
* be called from Jest's synchronous process() method. This provides equivalent
|
|
79
|
+
* basic cleaning without the async optimizer pipeline.
|
|
80
|
+
*/
|
|
81
|
+
function cleanSVGContentSync(svgContent) {
|
|
82
|
+
return (svgContent
|
|
83
|
+
// Remove XML declaration
|
|
84
|
+
.replace(/<\?xml.*?\?>/g, '')
|
|
85
|
+
// Remove DOCTYPE declaration
|
|
86
|
+
.replace(/<!DOCTYPE.*?>/g, '')
|
|
87
|
+
// Remove comments
|
|
88
|
+
.replace(/<!--[\s\S]*?-->/g, '')
|
|
89
|
+
// Normalize whitespace
|
|
90
|
+
.replace(/\r?\n|\r/g, '')
|
|
91
|
+
.replace(/\s{2,}/g, ' ')
|
|
92
|
+
// Remove xmlns attributes
|
|
93
|
+
.replace(/\s+xmlns(:xlink)?="[^"]*"/g, '')
|
|
94
|
+
// Remove metadata
|
|
95
|
+
.replace(/<metadata[\s\S]*?<\/metadata>/gi, '')
|
|
96
|
+
.replace(/<title[\s\S]*?<\/title>/gi, '')
|
|
97
|
+
.replace(/<desc[\s\S]*?<\/desc>/gi, '')
|
|
98
|
+
.trim()
|
|
99
|
+
// Extract inner content from <svg> tag
|
|
100
|
+
.replace(/^<svg[^>]*>([\s\S]*)<\/svg>$/i, '$1')
|
|
101
|
+
.trim());
|
|
102
|
+
}
|
|
75
103
|
/**
|
|
76
104
|
* Generate component synchronously (for Jest compatibility)
|
|
77
105
|
*/
|
|
78
106
|
function generateComponentSync(componentName, svgContent, options) {
|
|
79
|
-
// Clean SVG content
|
|
80
|
-
const cleanedContent =
|
|
107
|
+
// Clean SVG content synchronously (cleanSVGContent is async and cannot be used here)
|
|
108
|
+
const cleanedContent = cleanSVGContentSync(svgContent);
|
|
81
109
|
// For Jest, we'll generate a simple React component
|
|
82
110
|
const viewBox = svgProcessor.extractViewBox(svgContent);
|
|
83
111
|
const template = `
|