svger-cli 2.0.1 → 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.d.ts +63 -0
- package/dist/core/error-handler.js +227 -0
- package/dist/core/framework-templates.d.ts +17 -0
- package/{src/core/framework-templates.ts → dist/core/framework-templates.js} +104 -139
- 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 +252 -0
- package/dist/core/plugin-manager.d.ts +56 -0
- package/dist/core/plugin-manager.js +191 -0
- package/dist/core/style-compiler.d.ts +88 -0
- package/dist/core/style-compiler.js +468 -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 +153 -0
- package/{src/index.ts → dist/index.js} +32 -110
- package/dist/lock.js +7 -7
- package/dist/processors/svg-processor.d.ts +73 -0
- package/dist/processors/svg-processor.js +261 -0
- package/dist/services/config.d.ts +55 -0
- package/dist/services/config.js +211 -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 +395 -0
- package/dist/templates/ComponentTemplate.js +25 -25
- package/dist/types/index.d.ts +146 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/native.d.ts +104 -0
- package/dist/utils/native.js +340 -0
- package/dist/watch.d.ts +1 -1
- package/dist/watch.js +14 -14
- package/package.json +154 -14
- 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/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,235 +1,157 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SVGER-CLI - Zero-Dependency SVG to React Component Generator
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* A high-performance, framework-agnostic SVG processing toolkit with enterprise-grade
|
|
5
5
|
* architecture and comprehensive styling capabilities.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* @version 2.0.0
|
|
8
8
|
* @author SVGER-CLI Development Team
|
|
9
9
|
* @license MIT
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
11
|
// ============================================================================
|
|
13
12
|
// CORE SERVICES
|
|
14
13
|
// ============================================================================
|
|
15
|
-
|
|
16
14
|
/**
|
|
17
15
|
* Logger Service - Professional logging with configurable levels and color formatting
|
|
18
16
|
* Provides: debug, info, warn, error, success methods with timestamp and context
|
|
19
17
|
*/
|
|
20
18
|
export { LoggerService, logger } from './core/logger.js';
|
|
21
|
-
|
|
22
19
|
/**
|
|
23
20
|
* Configuration Management Service - Centralized configuration with validation and caching
|
|
24
21
|
* Provides: config loading, validation, defaults, and file-based persistence
|
|
25
22
|
*/
|
|
26
23
|
export { ConfigService, configService } from './services/config.js';
|
|
27
|
-
|
|
28
24
|
/**
|
|
29
25
|
* Error Handler - Comprehensive error management with recovery strategies
|
|
30
26
|
* Provides: structured error handling, recovery mechanisms, and user-friendly messages
|
|
31
27
|
*/
|
|
32
|
-
export { SVGErrorHandler, errorHandler, withErrorHandling, handleErrors } from './core/error-handler.js';
|
|
33
|
-
|
|
28
|
+
export { SVGErrorHandler, errorHandler, withErrorHandling, handleErrors, } from './core/error-handler.js';
|
|
34
29
|
// ============================================================================
|
|
35
30
|
// PROCESSING ENGINES
|
|
36
31
|
// ============================================================================
|
|
37
|
-
|
|
38
32
|
/**
|
|
39
33
|
* SVG Processor - Core SVG content processing and React component generation
|
|
40
34
|
* Provides: SVG parsing, optimization, React component generation, and batch processing
|
|
41
35
|
*/
|
|
42
36
|
export { SVGProcessor, svgProcessor } from './processors/svg-processor.js';
|
|
43
|
-
|
|
44
37
|
/**
|
|
45
38
|
* Performance Engine - Advanced optimization for batch processing and parallel execution
|
|
46
39
|
* Provides: batch processing, caching, memory optimization, and performance monitoring
|
|
47
40
|
*/
|
|
48
|
-
export { PerformanceEngine, performanceEngine } from './core/performance-engine.js';
|
|
49
|
-
|
|
41
|
+
export { PerformanceEngine, performanceEngine, } from './core/performance-engine.js';
|
|
50
42
|
/**
|
|
51
43
|
* Style Compiler - Comprehensive styling system with responsive design and theming
|
|
52
44
|
* Provides: CSS generation, theme management, responsive values, and style optimization
|
|
53
45
|
*/
|
|
54
46
|
export { SVGStyleCompiler, styleCompiler } from './core/style-compiler.js';
|
|
55
|
-
|
|
56
47
|
// ============================================================================
|
|
57
48
|
// TEMPLATE SYSTEMS
|
|
58
49
|
// ============================================================================
|
|
59
|
-
|
|
60
50
|
/**
|
|
61
51
|
* Template Manager - Extensible template system for React component generation
|
|
62
52
|
* Provides: multiple component patterns (functional, class, forwardRef, styled-components)
|
|
63
53
|
*/
|
|
64
54
|
export { TemplateManager, templateManager } from './core/template-manager.js';
|
|
65
|
-
|
|
66
55
|
/**
|
|
67
56
|
* Framework Template Engine - Universal template generator supporting multiple UI frameworks
|
|
68
57
|
* Provides: React, Vue, Svelte, Angular, Solid, Preact, Lit, and Vanilla JS components
|
|
69
58
|
*/
|
|
70
|
-
export {
|
|
71
|
-
FrameworkTemplateEngine,
|
|
72
|
-
frameworkTemplateEngine,
|
|
73
|
-
type FrameworkType,
|
|
74
|
-
type FrameworkOptions
|
|
75
|
-
} from './core/framework-templates.js';
|
|
76
|
-
|
|
59
|
+
export { FrameworkTemplateEngine, frameworkTemplateEngine, } from './core/framework-templates.js';
|
|
77
60
|
// ============================================================================
|
|
78
61
|
// PLUGIN ARCHITECTURE
|
|
79
62
|
// ============================================================================
|
|
80
|
-
|
|
81
63
|
/**
|
|
82
64
|
* Plugin Manager - Extensible plugin system for SVG processing enhancements
|
|
83
65
|
* Provides: plugin registration, lifecycle management, and content processing pipeline
|
|
84
66
|
*/
|
|
85
67
|
export { PluginManager, pluginManager } from './core/plugin-manager.js';
|
|
86
|
-
|
|
87
68
|
// ============================================================================
|
|
88
69
|
// UTILITY SERVICES
|
|
89
70
|
// ============================================================================
|
|
90
|
-
|
|
91
71
|
/**
|
|
92
72
|
* Native Node.js Utilities - Zero-dependency replacements for external libraries
|
|
93
73
|
* Provides: file operations, string manipulation, CLI parsing, and file watching
|
|
94
74
|
*/
|
|
95
|
-
export {
|
|
96
|
-
toPascalCase,
|
|
97
|
-
FileSystem,
|
|
98
|
-
CLI,
|
|
99
|
-
FileWatcher
|
|
100
|
-
} from './utils/native.js';
|
|
101
|
-
|
|
75
|
+
export { toPascalCase, toCamelCase, toKebabCase, FileSystem, CLI, FileWatcher, } from './utils/native.js';
|
|
102
76
|
/**
|
|
103
77
|
* File System Lock Functions - Concurrent file operation safety with advisory locking
|
|
104
78
|
* Provides: file locking, unlocking, and lock status checking for safe concurrent access
|
|
105
79
|
*/
|
|
106
80
|
export { lockFiles, unlockFiles, isLocked } from './lock.js';
|
|
107
|
-
|
|
108
81
|
/**
|
|
109
82
|
* File System Watcher - Real-time file system monitoring with change detection
|
|
110
83
|
* Provides: directory watching, file change detection, and event-driven processing
|
|
111
84
|
*/
|
|
112
85
|
export { watchSVGs } from './watch.js';
|
|
113
|
-
|
|
114
86
|
/**
|
|
115
87
|
* Project Builder - Automated project structure creation and dependency management
|
|
116
88
|
* Provides: project scaffolding, dependency resolution, and build automation
|
|
117
89
|
*/
|
|
118
90
|
export { buildAll, generateSVG } from './builder.js';
|
|
119
|
-
|
|
120
91
|
/**
|
|
121
92
|
* Content Cleaner - SVG content optimization and sanitization utilities
|
|
122
93
|
* Provides: SVG cleaning, attribute normalization, and content optimization
|
|
123
94
|
*/
|
|
124
95
|
export { clean } from './clean.js';
|
|
125
|
-
|
|
126
|
-
// ============================================================================
|
|
127
|
-
// TYPE DEFINITIONS
|
|
128
|
-
// ============================================================================
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* TypeScript Type Definitions - Comprehensive type system for all interfaces and configurations
|
|
132
|
-
* Provides: complete type safety for all operations, configurations, and data structures
|
|
133
|
-
*/
|
|
134
|
-
export type {
|
|
135
|
-
// Core configuration types
|
|
136
|
-
SVGConfig,
|
|
137
|
-
ComponentGenerationOptions,
|
|
138
|
-
|
|
139
|
-
// Processing types
|
|
140
|
-
SVGProcessorResult,
|
|
141
|
-
ProcessingJob,
|
|
142
|
-
ProcessingStatus,
|
|
143
|
-
|
|
144
|
-
// Plugin system types
|
|
145
|
-
Plugin,
|
|
146
|
-
PluginConfig,
|
|
147
|
-
|
|
148
|
-
// Template system types
|
|
149
|
-
Template,
|
|
150
|
-
TemplateConfig,
|
|
151
|
-
|
|
152
|
-
// File operation types
|
|
153
|
-
WatchOptions
|
|
154
|
-
} from './types/index.js';
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Error handling types - Available from core error handler
|
|
158
|
-
*/
|
|
159
|
-
export type { SVGError, ErrorRecoveryStrategy } from './core/error-handler.js';
|
|
160
|
-
|
|
161
96
|
// ============================================================================
|
|
162
97
|
// TEMPLATES
|
|
163
98
|
// ============================================================================
|
|
164
|
-
|
|
165
99
|
/**
|
|
166
100
|
* Component Templates - Pre-built component templates for various use cases
|
|
167
101
|
* Provides: functional React component template with TypeScript support
|
|
168
102
|
*/
|
|
169
103
|
export { reactTemplate } from './templates/ComponentTemplate.js';
|
|
170
|
-
|
|
171
104
|
// ============================================================================
|
|
172
105
|
// CONVENIENCE API
|
|
173
106
|
// ============================================================================
|
|
174
|
-
|
|
175
107
|
// Import instances for the convenience API
|
|
176
108
|
import { svgProcessor } from './processors/svg-processor.js';
|
|
177
109
|
import { watchSVGs } from './watch.js';
|
|
178
110
|
import { clean } from './clean.js';
|
|
179
111
|
import { buildAll } from './builder.js';
|
|
180
|
-
|
|
181
112
|
/**
|
|
182
113
|
* Quick Start API - Simplified API for common operations
|
|
183
114
|
* High-level functions for typical SVG processing workflows
|
|
184
115
|
*/
|
|
185
116
|
export const SVGER = {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Build all SVG files in directory
|
|
213
|
-
*/
|
|
214
|
-
build: buildAll
|
|
215
|
-
} as const;
|
|
216
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Process single SVG file to React component
|
|
119
|
+
*/
|
|
120
|
+
processFile: svgProcessor.processSVGFile.bind(svgProcessor),
|
|
121
|
+
/**
|
|
122
|
+
* Process multiple SVG files in batch
|
|
123
|
+
*/
|
|
124
|
+
processBatch: svgProcessor.processBatch.bind(svgProcessor),
|
|
125
|
+
/**
|
|
126
|
+
* Generate framework-agnostic component
|
|
127
|
+
*/
|
|
128
|
+
generateFrameworkComponent: svgProcessor.generateFrameworkComponent.bind(svgProcessor),
|
|
129
|
+
/**
|
|
130
|
+
* Watch directory for changes
|
|
131
|
+
*/
|
|
132
|
+
watch: watchSVGs,
|
|
133
|
+
/**
|
|
134
|
+
* Clean and optimize directory
|
|
135
|
+
*/
|
|
136
|
+
clean,
|
|
137
|
+
/**
|
|
138
|
+
* Build all SVG files in directory
|
|
139
|
+
*/
|
|
140
|
+
build: buildAll,
|
|
141
|
+
};
|
|
217
142
|
// ============================================================================
|
|
218
143
|
// VERSION INFORMATION
|
|
219
144
|
// ============================================================================
|
|
220
|
-
|
|
221
145
|
/**
|
|
222
146
|
* Package Version Information
|
|
223
147
|
*/
|
|
224
148
|
export const VERSION = '2.0.0';
|
|
225
149
|
export const PACKAGE_NAME = 'svger-cli';
|
|
226
|
-
|
|
227
150
|
// ============================================================================
|
|
228
151
|
// DEFAULT EXPORT
|
|
229
152
|
// ============================================================================
|
|
230
|
-
|
|
231
153
|
/**
|
|
232
154
|
* Default export - Primary SVG processor instance for quick access
|
|
233
155
|
* Most common entry point for programmatic usage
|
|
234
156
|
*/
|
|
235
|
-
export default svgProcessor;
|
|
157
|
+
export default svgProcessor;
|
package/dist/lock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
3
|
-
const LOCK_FILE =
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const LOCK_FILE = '.svg-lock';
|
|
4
4
|
/**
|
|
5
5
|
* Get the absolute path to the lock file.
|
|
6
6
|
*
|
|
@@ -18,7 +18,7 @@ function readLockFile() {
|
|
|
18
18
|
if (!fs.existsSync(getLockFilePath()))
|
|
19
19
|
return [];
|
|
20
20
|
try {
|
|
21
|
-
const data = fs.readFileSync(getLockFilePath(),
|
|
21
|
+
const data = fs.readFileSync(getLockFilePath(), 'utf-8');
|
|
22
22
|
return JSON.parse(data);
|
|
23
23
|
}
|
|
24
24
|
catch (e) {
|
|
@@ -31,7 +31,7 @@ function readLockFile() {
|
|
|
31
31
|
* @param {string[]} files - Array of SVG file names to lock.
|
|
32
32
|
*/
|
|
33
33
|
function writeLockFile(files) {
|
|
34
|
-
fs.writeFileSync(getLockFilePath(), JSON.stringify(files, null, 2),
|
|
34
|
+
fs.writeFileSync(getLockFilePath(), JSON.stringify(files, null, 2), 'utf-8');
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Lock one or more SVG files to prevent them from being processed.
|
|
@@ -43,7 +43,7 @@ export function lockFiles(files) {
|
|
|
43
43
|
const current = readLockFile();
|
|
44
44
|
const newFiles = Array.from(new Set([...current, ...fileNames]));
|
|
45
45
|
writeLockFile(newFiles);
|
|
46
|
-
console.log(`🔒 Locked files: ${newFiles.join(
|
|
46
|
+
console.log(`🔒 Locked files: ${newFiles.join(', ')}`);
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Unlock one or more SVG files, allowing them to be processed again.
|
|
@@ -55,7 +55,7 @@ export function unlockFiles(files) {
|
|
|
55
55
|
const current = readLockFile();
|
|
56
56
|
const remaining = current.filter(f => !fileNames.includes(f));
|
|
57
57
|
writeLockFile(remaining);
|
|
58
|
-
console.log(`🔓 Unlocked files: ${fileNames.join(
|
|
58
|
+
console.log(`🔓 Unlocked files: ${fileNames.join(', ')}`);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
61
|
* Check if a specific SVG file is locked.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ComponentGenerationOptions, SVGProcessorResult, NamingConvention } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* SVG content processor and component generator
|
|
4
|
+
*/
|
|
5
|
+
export declare class SVGProcessor {
|
|
6
|
+
private static instance;
|
|
7
|
+
private processingQueue;
|
|
8
|
+
private jobCounter;
|
|
9
|
+
private constructor();
|
|
10
|
+
static getInstance(): SVGProcessor;
|
|
11
|
+
/**
|
|
12
|
+
* Clean and optimize SVG content
|
|
13
|
+
*/
|
|
14
|
+
cleanSVGContent(svgContent: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Extract viewBox from SVG content
|
|
17
|
+
*/
|
|
18
|
+
extractViewBox(svgContent: string): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Generate component name from filename
|
|
21
|
+
*/
|
|
22
|
+
generateComponentName(fileName: string, namingConvention?: 'kebab' | 'pascal' | 'camel'): string;
|
|
23
|
+
/**
|
|
24
|
+
* Generate React component from SVG content
|
|
25
|
+
*/
|
|
26
|
+
generateComponent(componentName: string, svgContent: string, options?: Partial<ComponentGenerationOptions>): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Generate framework-agnostic component from SVG content
|
|
29
|
+
*/
|
|
30
|
+
generateFrameworkComponent(componentName: string, svgContent: string, options: ComponentGenerationOptions): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Process multiple SVG files in batch with performance optimization
|
|
33
|
+
*/
|
|
34
|
+
processBatch(files: Array<{
|
|
35
|
+
path: string;
|
|
36
|
+
outputDir: string;
|
|
37
|
+
options?: Partial<ComponentGenerationOptions>;
|
|
38
|
+
}>, config?: {
|
|
39
|
+
batchSize?: number;
|
|
40
|
+
parallel?: boolean;
|
|
41
|
+
maxConcurrency?: number;
|
|
42
|
+
}): Promise<Array<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
filePath: string;
|
|
45
|
+
error?: Error;
|
|
46
|
+
duration: number;
|
|
47
|
+
}>>;
|
|
48
|
+
/**
|
|
49
|
+
* Generate filename from component name using naming convention
|
|
50
|
+
*/
|
|
51
|
+
generateFileName(componentName: string, extension: string, namingConvention?: NamingConvention): string;
|
|
52
|
+
/**
|
|
53
|
+
* Process a single SVG file
|
|
54
|
+
*/
|
|
55
|
+
processSVGFile(svgFilePath: string, outputDir: string, options?: Partial<ComponentGenerationOptions & {
|
|
56
|
+
namingConvention?: NamingConvention;
|
|
57
|
+
}>): Promise<SVGProcessorResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Get processing statistics
|
|
60
|
+
*/
|
|
61
|
+
getProcessingStats(): {
|
|
62
|
+
total: number;
|
|
63
|
+
pending: number;
|
|
64
|
+
processing: number;
|
|
65
|
+
completed: number;
|
|
66
|
+
failed: number;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Clear processing queue
|
|
70
|
+
*/
|
|
71
|
+
clearQueue(): void;
|
|
72
|
+
}
|
|
73
|
+
export declare const svgProcessor: SVGProcessor;
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { toPascalCase, toKebabCase, toCamelCase, FileSystem, } from '../utils/native.js';
|
|
3
|
+
import { logger } from '../core/logger.js';
|
|
4
|
+
import { performanceEngine } from '../core/performance-engine.js';
|
|
5
|
+
import { frameworkTemplateEngine } from '../core/framework-templates.js';
|
|
6
|
+
/**
|
|
7
|
+
* SVG content processor and component generator
|
|
8
|
+
*/
|
|
9
|
+
export class SVGProcessor {
|
|
10
|
+
static instance;
|
|
11
|
+
processingQueue = new Map();
|
|
12
|
+
jobCounter = 0;
|
|
13
|
+
constructor() { }
|
|
14
|
+
static getInstance() {
|
|
15
|
+
if (!SVGProcessor.instance) {
|
|
16
|
+
SVGProcessor.instance = new SVGProcessor();
|
|
17
|
+
}
|
|
18
|
+
return SVGProcessor.instance;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Clean and optimize SVG content
|
|
22
|
+
*/
|
|
23
|
+
cleanSVGContent(svgContent) {
|
|
24
|
+
logger.debug('Cleaning SVG content');
|
|
25
|
+
return (svgContent
|
|
26
|
+
// Remove XML declaration
|
|
27
|
+
.replace(/<\?xml.*?\?>/g, '')
|
|
28
|
+
// Remove DOCTYPE declaration
|
|
29
|
+
.replace(/<!DOCTYPE.*?>/g, '')
|
|
30
|
+
// Remove comments
|
|
31
|
+
.replace(/<!--[\s\S]*?-->/g, '')
|
|
32
|
+
// Normalize whitespace
|
|
33
|
+
.replace(/\r?\n|\r/g, '')
|
|
34
|
+
.replace(/\s{2,}/g, ' ')
|
|
35
|
+
// Remove inline styles (they interfere with React styling)
|
|
36
|
+
.replace(/style="[^"]*"/g, '')
|
|
37
|
+
// Remove xmlns attributes (React will handle these)
|
|
38
|
+
.replace(/\s+xmlns(:xlink)?="[^"]*"/g, '')
|
|
39
|
+
// Convert attributes to camelCase for React
|
|
40
|
+
.replace(/fill-rule/g, 'fillRule')
|
|
41
|
+
.replace(/clip-rule/g, 'clipRule')
|
|
42
|
+
.replace(/stroke-width/g, 'strokeWidth')
|
|
43
|
+
.replace(/stroke-linecap/g, 'strokeLinecap')
|
|
44
|
+
.replace(/stroke-linejoin/g, 'strokeLinejoin')
|
|
45
|
+
.replace(/stroke-miterlimit/g, 'strokeMiterlimit')
|
|
46
|
+
.replace(/stroke-dasharray/g, 'strokeDasharray')
|
|
47
|
+
.replace(/stroke-dashoffset/g, 'strokeDashoffset')
|
|
48
|
+
.replace(/font-family/g, 'fontFamily')
|
|
49
|
+
.replace(/font-size/g, 'fontSize')
|
|
50
|
+
.replace(/font-weight/g, 'fontWeight')
|
|
51
|
+
.replace(/text-anchor/g, 'textAnchor')
|
|
52
|
+
// Remove outer SVG tag and keep inner content
|
|
53
|
+
.trim()
|
|
54
|
+
.replace(/^<svg[^>]*>([\s\S]*)<\/svg>$/i, '$1')
|
|
55
|
+
.trim());
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Extract viewBox from SVG content
|
|
59
|
+
*/
|
|
60
|
+
extractViewBox(svgContent) {
|
|
61
|
+
const viewBoxMatch = svgContent.match(/viewBox=["']([^"']+)["']/i);
|
|
62
|
+
return viewBoxMatch ? viewBoxMatch[1] : null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate component name from filename
|
|
66
|
+
*/
|
|
67
|
+
generateComponentName(fileName, namingConvention) {
|
|
68
|
+
const baseName = path.basename(fileName, '.svg');
|
|
69
|
+
// Apply naming convention if specified, otherwise default to PascalCase
|
|
70
|
+
switch (namingConvention) {
|
|
71
|
+
case 'kebab':
|
|
72
|
+
// Keep kebab-case for filename, but component still needs PascalCase
|
|
73
|
+
return toPascalCase(baseName);
|
|
74
|
+
case 'camel':
|
|
75
|
+
// Convert to camelCase
|
|
76
|
+
const pascalName = toPascalCase(baseName);
|
|
77
|
+
return pascalName.charAt(0).toLowerCase() + pascalName.slice(1);
|
|
78
|
+
case 'pascal':
|
|
79
|
+
default:
|
|
80
|
+
// Default to PascalCase
|
|
81
|
+
const componentName = toPascalCase(baseName);
|
|
82
|
+
// Ensure component name starts with uppercase letter
|
|
83
|
+
if (!/^[A-Z]/.test(componentName)) {
|
|
84
|
+
return `Svg${componentName}`;
|
|
85
|
+
}
|
|
86
|
+
return componentName;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generate React component from SVG content
|
|
91
|
+
*/
|
|
92
|
+
async generateComponent(componentName, svgContent, options = {}) {
|
|
93
|
+
try {
|
|
94
|
+
// Clean and optimize SVG content
|
|
95
|
+
const cleanedContent = this.cleanSVGContent(svgContent);
|
|
96
|
+
// Apply plugins (no plugin configs for now, just process directly)
|
|
97
|
+
const processedContent = cleanedContent;
|
|
98
|
+
// Create full options object with required fields
|
|
99
|
+
const fullOptions = {
|
|
100
|
+
componentName,
|
|
101
|
+
svgContent: processedContent,
|
|
102
|
+
framework: options.framework || 'react',
|
|
103
|
+
typescript: options.typescript !== undefined ? options.typescript : true,
|
|
104
|
+
...options,
|
|
105
|
+
};
|
|
106
|
+
// Use framework template engine directly
|
|
107
|
+
const component = frameworkTemplateEngine.generateComponent(fullOptions);
|
|
108
|
+
logger.debug(`Generated component: ${componentName}`);
|
|
109
|
+
return component;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
logger.error(`Failed to generate component ${componentName}:`, error);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Generate framework-agnostic component from SVG content
|
|
118
|
+
*/
|
|
119
|
+
async generateFrameworkComponent(componentName, svgContent, options) {
|
|
120
|
+
try {
|
|
121
|
+
// Optimize SVG content based on framework requirements
|
|
122
|
+
const optimizationLevel = options.framework === 'vanilla' ? 'maximum' : 'balanced';
|
|
123
|
+
const optimizedContent = performanceEngine.optimizeSVGContent(svgContent, optimizationLevel);
|
|
124
|
+
// Generate framework-specific component
|
|
125
|
+
const component = frameworkTemplateEngine.generateComponent({
|
|
126
|
+
...options,
|
|
127
|
+
componentName,
|
|
128
|
+
svgContent: optimizedContent,
|
|
129
|
+
});
|
|
130
|
+
logger.debug(`Generated ${options.framework} component: ${componentName}`);
|
|
131
|
+
return component;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
logger.error(`Failed to generate ${options.framework} component ${componentName}:`, error);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Process multiple SVG files in batch with performance optimization
|
|
140
|
+
*/
|
|
141
|
+
async processBatch(files, config = {}) {
|
|
142
|
+
logger.info(`Starting batch processing of ${files.length} files`);
|
|
143
|
+
try {
|
|
144
|
+
const results = await performanceEngine.processBatch(files, config);
|
|
145
|
+
// Log performance metrics
|
|
146
|
+
const metrics = performanceEngine.getPerformanceMetrics();
|
|
147
|
+
if (metrics.memoryUsage.recommendations.length > 0) {
|
|
148
|
+
logger.warn('Performance recommendations:', metrics.memoryUsage.recommendations);
|
|
149
|
+
}
|
|
150
|
+
return results;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
logger.error('Batch processing failed:', error);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Generate filename from component name using naming convention
|
|
159
|
+
*/
|
|
160
|
+
generateFileName(componentName, extension, namingConvention) {
|
|
161
|
+
let fileName;
|
|
162
|
+
switch (namingConvention) {
|
|
163
|
+
case 'kebab':
|
|
164
|
+
fileName = toKebabCase(componentName);
|
|
165
|
+
break;
|
|
166
|
+
case 'camel':
|
|
167
|
+
fileName = toCamelCase(componentName);
|
|
168
|
+
break;
|
|
169
|
+
case 'pascal':
|
|
170
|
+
default:
|
|
171
|
+
// Default to PascalCase (same as component name)
|
|
172
|
+
fileName = componentName;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
return `${fileName}.${extension}`;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Process a single SVG file
|
|
179
|
+
*/
|
|
180
|
+
async processSVGFile(svgFilePath, outputDir, options = {}) {
|
|
181
|
+
const jobId = `job-${++this.jobCounter}`;
|
|
182
|
+
const job = {
|
|
183
|
+
id: jobId,
|
|
184
|
+
filePath: svgFilePath,
|
|
185
|
+
status: 'processing',
|
|
186
|
+
startTime: Date.now(),
|
|
187
|
+
};
|
|
188
|
+
this.processingQueue.set(jobId, job);
|
|
189
|
+
logger.debug(`Processing SVG file: ${svgFilePath}`);
|
|
190
|
+
try {
|
|
191
|
+
// Read SVG content
|
|
192
|
+
const svgContent = await FileSystem.readFile(svgFilePath, 'utf-8');
|
|
193
|
+
// Generate component name (always PascalCase for component)
|
|
194
|
+
const componentName = this.generateComponentName(path.basename(svgFilePath));
|
|
195
|
+
// Generate component code
|
|
196
|
+
const componentCode = await this.generateComponent(componentName, svgContent, options);
|
|
197
|
+
// Ensure output directory exists
|
|
198
|
+
await FileSystem.ensureDir(outputDir);
|
|
199
|
+
// Get correct file extension based on framework
|
|
200
|
+
const framework = options.framework || 'react';
|
|
201
|
+
const typescript = options.typescript !== undefined ? options.typescript : true;
|
|
202
|
+
const fileExtension = frameworkTemplateEngine.getFileExtension(framework, typescript);
|
|
203
|
+
// Generate filename using naming convention
|
|
204
|
+
const namingConvention = options.namingConvention;
|
|
205
|
+
const fileName = this.generateFileName(componentName, fileExtension, namingConvention);
|
|
206
|
+
// Write component file
|
|
207
|
+
const outputFilePath = path.join(outputDir, fileName);
|
|
208
|
+
await FileSystem.writeFile(outputFilePath, componentCode, 'utf-8');
|
|
209
|
+
// Update job status
|
|
210
|
+
job.status = 'completed';
|
|
211
|
+
job.endTime = Date.now();
|
|
212
|
+
const result = {
|
|
213
|
+
success: true,
|
|
214
|
+
componentName,
|
|
215
|
+
filePath: outputFilePath,
|
|
216
|
+
};
|
|
217
|
+
logger.success(`Generated component: ${fileName}`);
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
job.status = 'failed';
|
|
222
|
+
job.endTime = Date.now();
|
|
223
|
+
job.error = error;
|
|
224
|
+
const result = {
|
|
225
|
+
success: false,
|
|
226
|
+
componentName: '',
|
|
227
|
+
filePath: svgFilePath,
|
|
228
|
+
error: error,
|
|
229
|
+
};
|
|
230
|
+
logger.error(`Failed to process ${svgFilePath}:`, error);
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
// Clean up completed jobs after some time
|
|
235
|
+
setTimeout(() => {
|
|
236
|
+
this.processingQueue.delete(jobId);
|
|
237
|
+
}, 30000); // 30 seconds
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Get processing statistics
|
|
242
|
+
*/
|
|
243
|
+
getProcessingStats() {
|
|
244
|
+
const jobs = Array.from(this.processingQueue.values());
|
|
245
|
+
return {
|
|
246
|
+
total: jobs.length,
|
|
247
|
+
pending: jobs.filter(j => j.status === 'pending').length,
|
|
248
|
+
processing: jobs.filter(j => j.status === 'processing').length,
|
|
249
|
+
completed: jobs.filter(j => j.status === 'completed').length,
|
|
250
|
+
failed: jobs.filter(j => j.status === 'failed').length,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Clear processing queue
|
|
255
|
+
*/
|
|
256
|
+
clearQueue() {
|
|
257
|
+
this.processingQueue.clear();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Export singleton instance
|
|
261
|
+
export const svgProcessor = SVGProcessor.getInstance();
|