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.
Files changed (91) hide show
  1. package/.svgerconfig.example.json +38 -0
  2. package/CHANGELOG.md +64 -0
  3. package/DEVELOPMENT.md +353 -0
  4. package/README.md +24 -5
  5. package/SECURITY.md +69 -0
  6. package/dist/builder.js +16 -16
  7. package/dist/clean.js +2 -2
  8. package/dist/cli.js +38 -38
  9. package/dist/config.js +11 -11
  10. package/dist/core/error-handler.d.ts +63 -0
  11. package/dist/core/error-handler.js +227 -0
  12. package/dist/core/framework-templates.d.ts +17 -0
  13. package/{src/core/framework-templates.ts → dist/core/framework-templates.js} +104 -139
  14. package/dist/core/logger.d.ts +22 -0
  15. package/dist/core/logger.js +85 -0
  16. package/dist/core/performance-engine.d.ts +67 -0
  17. package/dist/core/performance-engine.js +252 -0
  18. package/dist/core/plugin-manager.d.ts +56 -0
  19. package/dist/core/plugin-manager.js +191 -0
  20. package/dist/core/style-compiler.d.ts +88 -0
  21. package/dist/core/style-compiler.js +468 -0
  22. package/dist/core/template-manager.d.ts +64 -0
  23. package/{src/core/template-manager.ts → dist/core/template-manager.js} +172 -255
  24. package/dist/index.d.ts +153 -0
  25. package/{src/index.ts → dist/index.js} +32 -110
  26. package/dist/lock.js +7 -7
  27. package/dist/processors/svg-processor.d.ts +73 -0
  28. package/dist/processors/svg-processor.js +261 -0
  29. package/dist/services/config.d.ts +55 -0
  30. package/dist/services/config.js +211 -0
  31. package/dist/services/file-watcher.d.ts +54 -0
  32. package/dist/services/file-watcher.js +180 -0
  33. package/dist/services/svg-service.d.ts +81 -0
  34. package/dist/services/svg-service.js +395 -0
  35. package/dist/templates/ComponentTemplate.js +25 -25
  36. package/dist/types/index.d.ts +146 -0
  37. package/dist/types/index.js +4 -0
  38. package/dist/utils/native.d.ts +104 -0
  39. package/dist/utils/native.js +340 -0
  40. package/dist/watch.d.ts +1 -1
  41. package/dist/watch.js +14 -14
  42. package/package.json +154 -14
  43. package/.svgconfig.json +0 -3
  44. package/CODE_OF_CONDUCT.md +0 -79
  45. package/CONTRIBUTING.md +0 -146
  46. package/TESTING.md +0 -143
  47. package/cli-framework.test.js +0 -16
  48. package/cli-test-angular/Arrowbenddownleft.component.ts +0 -27
  49. package/cli-test-angular/Vite.component.ts +0 -27
  50. package/cli-test-angular/index.ts +0 -25
  51. package/cli-test-output/Arrowbenddownleft.vue +0 -33
  52. package/cli-test-output/Vite.vue +0 -33
  53. package/cli-test-output/index.ts +0 -25
  54. package/cli-test-react/Arrowbenddownleft.tsx +0 -39
  55. package/cli-test-react/Vite.tsx +0 -39
  56. package/cli-test-react/index.ts +0 -25
  57. package/cli-test-svelte/Arrowbenddownleft.svelte +0 -22
  58. package/cli-test-svelte/Vite.svelte +0 -22
  59. package/cli-test-svelte/index.ts +0 -25
  60. package/frameworks.test.js +0 -170
  61. package/my-svgs/ArrowBendDownLeft.svg +0 -6
  62. package/my-svgs/vite.svg +0 -1
  63. package/src/builder.ts +0 -104
  64. package/src/clean.ts +0 -21
  65. package/src/cli.ts +0 -221
  66. package/src/config.ts +0 -81
  67. package/src/core/error-handler.ts +0 -303
  68. package/src/core/logger.ts +0 -104
  69. package/src/core/performance-engine.ts +0 -327
  70. package/src/core/plugin-manager.ts +0 -228
  71. package/src/core/style-compiler.ts +0 -605
  72. package/src/lock.ts +0 -74
  73. package/src/processors/svg-processor.ts +0 -288
  74. package/src/services/config.ts +0 -241
  75. package/src/services/file-watcher.ts +0 -218
  76. package/src/services/svg-service.ts +0 -468
  77. package/src/templates/ComponentTemplate.ts +0 -57
  78. package/src/types/index.ts +0 -169
  79. package/src/utils/native.ts +0 -352
  80. package/src/watch.ts +0 -88
  81. package/test-output-mulit/TestIcon-angular-module.component.ts +0 -26
  82. package/test-output-mulit/TestIcon-angular-standalone.component.ts +0 -27
  83. package/test-output-mulit/TestIcon-lit.ts +0 -35
  84. package/test-output-mulit/TestIcon-preact.tsx +0 -38
  85. package/test-output-mulit/TestIcon-react.tsx +0 -35
  86. package/test-output-mulit/TestIcon-solid.tsx +0 -27
  87. package/test-output-mulit/TestIcon-svelte.svelte +0 -22
  88. package/test-output-mulit/TestIcon-vanilla.ts +0 -37
  89. package/test-output-mulit/TestIcon-vue-composition.vue +0 -33
  90. package/test-output-mulit/TestIcon-vue-options.vue +0 -31
  91. package/tsconfig.json +0 -18
@@ -0,0 +1,468 @@
1
+ /**
2
+ * Comprehensive styling system for SVG components
3
+ * Supports all CSS properties, responsive design, theming, and dynamic styling
4
+ */
5
+ export class SVGStyleCompiler {
6
+ static instance;
7
+ themes = new Map();
8
+ globalCSS = [];
9
+ constructor() {
10
+ this.loadDefaultThemes();
11
+ }
12
+ static getInstance() {
13
+ if (!SVGStyleCompiler.instance) {
14
+ SVGStyleCompiler.instance = new SVGStyleCompiler();
15
+ }
16
+ return SVGStyleCompiler.instance;
17
+ }
18
+ /**
19
+ * Compile SVG styling options into CSS
20
+ */
21
+ compileStyles(options, componentName) {
22
+ const compiled = {
23
+ inline: {},
24
+ classes: [],
25
+ cssRules: [],
26
+ mediaQueries: [],
27
+ };
28
+ // Get theme if specified
29
+ const theme = this.resolveTheme(options.theme);
30
+ // Compile base styles
31
+ this.compileBaseStyles(options, compiled, theme);
32
+ // Compile responsive styles
33
+ if (options.responsive) {
34
+ this.compileResponsiveStyles(options, compiled, theme, componentName);
35
+ }
36
+ // Compile interaction states
37
+ this.compileInteractionStates(options, compiled, componentName);
38
+ // Add custom CSS
39
+ if (options.css) {
40
+ Object.assign(compiled.inline, options.css);
41
+ }
42
+ // Add class names
43
+ if (options.className) {
44
+ compiled.classes.push(options.className);
45
+ }
46
+ return compiled;
47
+ }
48
+ /**
49
+ * Register a custom theme
50
+ */
51
+ registerTheme(theme) {
52
+ this.themes.set(theme.name, theme);
53
+ }
54
+ /**
55
+ * Generate CSS for a component with all styling options
56
+ */
57
+ generateComponentCSS(componentName, options) {
58
+ const compiled = this.compileStyles(options, componentName);
59
+ let css = '';
60
+ // Add CSS rules
61
+ if (compiled.cssRules.length > 0) {
62
+ css += compiled.cssRules.join('\n') + '\n';
63
+ }
64
+ // Add media queries
65
+ if (compiled.mediaQueries.length > 0) {
66
+ css += compiled.mediaQueries.join('\n') + '\n';
67
+ }
68
+ return css;
69
+ }
70
+ /**
71
+ * Generate enhanced React component template with full styling support
72
+ */
73
+ generateStyledComponent(componentName, svgContent, options = {}) {
74
+ const compiled = this.compileStyles(options, componentName);
75
+ const hasCustomStyles = compiled.cssRules.length > 0 || compiled.mediaQueries.length > 0;
76
+ const imports = hasCustomStyles
77
+ ? `import React from 'react';\nimport type { SVGProps } from "react";`
78
+ : `import type { SVGProps } from "react";`;
79
+ const styledCSS = hasCustomStyles
80
+ ? `
81
+ const ${componentName}Styles = \`
82
+ ${compiled.cssRules.join('\n')}
83
+ ${compiled.mediaQueries.join('\n')}
84
+ \`;
85
+
86
+ // Inject styles
87
+ if (typeof document !== 'undefined') {
88
+ const styleId = '${componentName.toLowerCase()}-styles';
89
+ if (!document.getElementById(styleId)) {
90
+ const style = document.createElement('style');
91
+ style.id = styleId;
92
+ style.textContent = ${componentName}Styles;
93
+ document.head.appendChild(style);
94
+ }
95
+ }
96
+ `
97
+ : '';
98
+ const inlineStyleObject = Object.keys(compiled.inline).length > 0
99
+ ? `const defaultStyles = ${JSON.stringify(compiled.inline, null, 2)};`
100
+ : '';
101
+ const classNames = compiled.classes.length > 0
102
+ ? `'${compiled.classes.join(' ')} ' + (props.className || '')`
103
+ : 'props.className';
104
+ return `${imports}
105
+
106
+ /**
107
+ * ${componentName} SVG Component with Enhanced Styling
108
+ * Generated by svger-cli with comprehensive styling support
109
+ */
110
+
111
+ ${styledCSS}${inlineStyleObject}
112
+
113
+ export interface ${componentName}Props extends SVGProps<SVGSVGElement> {
114
+ // Enhanced styling props
115
+ size?: number | string;
116
+ variant?: 'primary' | 'secondary' | 'accent' | 'muted';
117
+ responsive?: boolean;
118
+
119
+ // Animation props
120
+ animate?: boolean;
121
+ animationType?: 'spin' | 'pulse' | 'bounce' | 'fade';
122
+
123
+ // Theme props
124
+ theme?: 'light' | 'dark' | 'auto';
125
+ }
126
+
127
+ const ${componentName} = React.forwardRef<SVGSVGElement, ${componentName}Props>(
128
+ ({
129
+ size,
130
+ variant = 'primary',
131
+ responsive = false,
132
+ animate = false,
133
+ animationType = 'spin',
134
+ theme = 'auto',
135
+ style,
136
+ className,
137
+ ...props
138
+ }, ref) => {
139
+
140
+ // Calculate dimensions
141
+ const dimensions = React.useMemo(() => {
142
+ if (size) {
143
+ return { width: size, height: size };
144
+ }
145
+ return {
146
+ width: props.width || ${options.width || 24},
147
+ height: props.height || ${options.height || 24}
148
+ };
149
+ }, [size, props.width, props.height]);
150
+
151
+ // Combine styles
152
+ const combinedStyles = React.useMemo(() => {
153
+ const baseStyles = ${inlineStyleObject ? 'defaultStyles' : '{}'};
154
+ const variantStyles = getVariantStyles(variant);
155
+ const animationStyles = animate ? getAnimationStyles(animationType) : {};
156
+ const themeStyles = getThemeStyles(theme);
157
+
158
+ return {
159
+ ...baseStyles,
160
+ ...variantStyles,
161
+ ...animationStyles,
162
+ ...themeStyles,
163
+ ...style
164
+ };
165
+ }, [variant, animate, animationType, theme, style]);
166
+
167
+ // Combine class names
168
+ const combinedClassName = React.useMemo(() => {
169
+ const classes = [];
170
+ ${compiled.classes.length > 0 ? `classes.push('${compiled.classes.join(' ')}');` : ''}
171
+ if (responsive) classes.push(\`\${componentName.toLowerCase()}-responsive\`);
172
+ if (animate) classes.push(\`\${componentName.toLowerCase()}-animate-\${animationType}\`);
173
+ classes.push(\`\${componentName.toLowerCase()}-variant-\${variant}\`);
174
+ classes.push(\`\${componentName.toLowerCase()}-theme-\${theme}\`);
175
+ if (className) classes.push(className);
176
+ return classes.join(' ');
177
+ }, [responsive, animate, animationType, variant, theme, className]);
178
+
179
+ return (
180
+ <svg
181
+ ref={ref}
182
+ viewBox="0 0 24 24"
183
+ xmlns="http://www.w3.org/2000/svg"
184
+ width={dimensions.width}
185
+ height={dimensions.height}
186
+ fill={props.fill || "${options.fill || 'currentColor'}"}
187
+ className={combinedClassName}
188
+ style={combinedStyles}
189
+ aria-hidden={props['aria-hidden']}
190
+ aria-label={props['aria-label']}
191
+ role={props.role || 'img'}
192
+ {...props}
193
+ >
194
+ ${options.title ? `<title>${options.title}</title>` : ''}
195
+ ${svgContent}
196
+ </svg>
197
+ );
198
+ }
199
+ );
200
+
201
+ // Utility functions for styling
202
+ function getVariantStyles(variant: string): React.CSSProperties {
203
+ const variants = {
204
+ primary: { color: 'var(--color-primary, #007bff)' },
205
+ secondary: { color: 'var(--color-secondary, #6c757d)' },
206
+ accent: { color: 'var(--color-accent, #28a745)' },
207
+ muted: { color: 'var(--color-muted, #6c757d)', opacity: 0.7 }
208
+ };
209
+ return variants[variant as keyof typeof variants] || variants.primary;
210
+ }
211
+
212
+ function getAnimationStyles(animationType: string): React.CSSProperties {
213
+ const animations = {
214
+ spin: { animation: 'svger-spin 1s linear infinite' },
215
+ pulse: { animation: 'svger-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite' },
216
+ bounce: { animation: 'svger-bounce 1s infinite' },
217
+ fade: { animation: 'svger-fade 2s ease-in-out infinite alternate' }
218
+ };
219
+ return animations[animationType as keyof typeof animations] || {};
220
+ }
221
+
222
+ function getThemeStyles(theme: string): React.CSSProperties {
223
+ if (theme === 'dark') {
224
+ return { filter: 'invert(1) hue-rotate(180deg)' };
225
+ }
226
+ if (theme === 'auto') {
227
+ return { filter: 'var(--svger-theme-filter, none)' };
228
+ }
229
+ return {};
230
+ }
231
+
232
+ ${componentName}.displayName = "${componentName}";
233
+
234
+ export default ${componentName};
235
+
236
+ // CSS Animations (injected globally)
237
+ if (typeof document !== 'undefined') {
238
+ const animationCSS = \`
239
+ @keyframes svger-spin {
240
+ from { transform: rotate(0deg); }
241
+ to { transform: rotate(360deg); }
242
+ }
243
+
244
+ @keyframes svger-pulse {
245
+ 0%, 100% { opacity: 1; }
246
+ 50% { opacity: 0.5; }
247
+ }
248
+
249
+ @keyframes svger-bounce {
250
+ 0%, 20%, 53%, 80%, 100% { transform: translate3d(0,0,0); }
251
+ 40%, 43% { transform: translate3d(0,-30px,0); }
252
+ 70% { transform: translate3d(0,-15px,0); }
253
+ 90% { transform: translate3d(0,-4px,0); }
254
+ }
255
+
256
+ @keyframes svger-fade {
257
+ from { opacity: 0.4; }
258
+ to { opacity: 1; }
259
+ }
260
+
261
+ /* CSS Custom Properties for theming */
262
+ :root {
263
+ --color-primary: #007bff;
264
+ --color-secondary: #6c757d;
265
+ --color-accent: #28a745;
266
+ --color-muted: #6c757d;
267
+ --svger-theme-filter: none;
268
+ }
269
+
270
+ @media (prefers-color-scheme: dark) {
271
+ :root {
272
+ --svger-theme-filter: invert(1) hue-rotate(180deg);
273
+ }
274
+ }
275
+ \`;
276
+
277
+ const globalStyleId = 'svger-global-animations';
278
+ if (!document.getElementById(globalStyleId)) {
279
+ const style = document.createElement('style');
280
+ style.id = globalStyleId;
281
+ style.textContent = animationCSS;
282
+ document.head.appendChild(style);
283
+ }
284
+ }
285
+ `;
286
+ }
287
+ // Private helper methods
288
+ loadDefaultThemes() {
289
+ // Light theme
290
+ this.registerTheme({
291
+ name: 'light',
292
+ colors: {
293
+ primary: '#007bff',
294
+ secondary: '#6c757d',
295
+ success: '#28a745',
296
+ warning: '#ffc107',
297
+ danger: '#dc3545',
298
+ info: '#17a2b8',
299
+ light: '#f8f9fa',
300
+ dark: '#343a40',
301
+ },
302
+ sizes: {
303
+ xs: 12,
304
+ sm: 16,
305
+ md: 24,
306
+ lg: 32,
307
+ xl: 48,
308
+ },
309
+ spacing: {
310
+ 1: '0.25rem',
311
+ 2: '0.5rem',
312
+ 3: '0.75rem',
313
+ 4: '1rem',
314
+ 5: '1.5rem',
315
+ },
316
+ breakpoints: {
317
+ sm: '576px',
318
+ md: '768px',
319
+ lg: '992px',
320
+ xl: '1200px',
321
+ },
322
+ });
323
+ // Dark theme
324
+ this.registerTheme({
325
+ name: 'dark',
326
+ colors: {
327
+ primary: '#0d6efd',
328
+ secondary: '#6c757d',
329
+ success: '#198754',
330
+ warning: '#ffc107',
331
+ danger: '#dc3545',
332
+ info: '#0dcaf0',
333
+ light: '#212529',
334
+ dark: '#f8f9fa',
335
+ },
336
+ sizes: {
337
+ xs: 12,
338
+ sm: 16,
339
+ md: 24,
340
+ lg: 32,
341
+ xl: 48,
342
+ },
343
+ spacing: {
344
+ 1: '0.25rem',
345
+ 2: '0.5rem',
346
+ 3: '0.75rem',
347
+ 4: '1rem',
348
+ 5: '1.5rem',
349
+ },
350
+ breakpoints: {
351
+ sm: '576px',
352
+ md: '768px',
353
+ lg: '992px',
354
+ xl: '1200px',
355
+ },
356
+ });
357
+ }
358
+ resolveTheme(theme) {
359
+ if (!theme)
360
+ return null;
361
+ if (typeof theme === 'string') {
362
+ return this.themes.get(theme) || null;
363
+ }
364
+ return theme;
365
+ }
366
+ compileBaseStyles(options, compiled, theme) {
367
+ // Handle basic properties
368
+ const styleMap = {
369
+ fill: 'fill',
370
+ stroke: 'stroke',
371
+ strokeWidth: 'strokeWidth',
372
+ opacity: 'opacity',
373
+ transform: 'transform',
374
+ filter: 'filter',
375
+ clipPath: 'clipPath',
376
+ mask: 'mask',
377
+ animation: 'animation',
378
+ transition: 'transition',
379
+ };
380
+ for (const [cssProp, optionKey] of Object.entries(styleMap)) {
381
+ const value = options[optionKey];
382
+ if (value !== undefined) {
383
+ if (this.isResponsiveValue(value)) {
384
+ compiled.inline[cssProp] = value.base;
385
+ }
386
+ else {
387
+ compiled.inline[cssProp] = value;
388
+ }
389
+ }
390
+ }
391
+ // Handle size shorthand
392
+ if (options.size !== undefined) {
393
+ const sizeValue = this.isResponsiveValue(options.size)
394
+ ? options.size.base
395
+ : options.size;
396
+ compiled.inline.width = sizeValue;
397
+ compiled.inline.height = sizeValue;
398
+ }
399
+ // Handle transform shortcuts
400
+ const transforms = [];
401
+ if (options.rotate)
402
+ transforms.push(`rotate(${options.rotate}deg)`);
403
+ if (options.scale)
404
+ transforms.push(`scale(${options.scale})`);
405
+ if (options.translateX)
406
+ transforms.push(`translateX(${options.translateX})`);
407
+ if (options.translateY)
408
+ transforms.push(`translateY(${options.translateY})`);
409
+ if (transforms.length > 0) {
410
+ const existingTransform = compiled.inline.transform;
411
+ compiled.inline.transform = existingTransform
412
+ ? `${existingTransform} ${transforms.join(' ')}`
413
+ : transforms.join(' ');
414
+ }
415
+ }
416
+ compileResponsiveStyles(options, compiled, theme, componentName) {
417
+ const breakpoints = theme?.breakpoints || {
418
+ sm: '576px',
419
+ md: '768px',
420
+ lg: '992px',
421
+ xl: '1200px',
422
+ };
423
+ for (const [prop, value] of Object.entries(options)) {
424
+ if (this.isResponsiveValue(value)) {
425
+ const responsiveValue = value;
426
+ for (const [breakpoint, breakpointValue] of Object.entries(responsiveValue)) {
427
+ if (breakpoint === 'base')
428
+ continue;
429
+ const mediaQuery = breakpoints[breakpoint];
430
+ if (mediaQuery && breakpointValue !== undefined) {
431
+ const rule = `@media (min-width: ${mediaQuery}) {
432
+ .${componentName.toLowerCase()}-responsive {
433
+ ${this.camelToKebab(prop)}: ${breakpointValue};
434
+ }
435
+ }`;
436
+ compiled.mediaQueries.push(rule);
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+ compileInteractionStates(options, compiled, componentName) {
443
+ const states = ['hover', 'focus', 'active', 'disabled'];
444
+ for (const state of states) {
445
+ const stateStyles = options[state];
446
+ if (stateStyles) {
447
+ const selector = state === 'disabled'
448
+ ? `.${componentName.toLowerCase()}[disabled], .${componentName.toLowerCase()}[aria-disabled="true"]`
449
+ : `.${componentName.toLowerCase()}:${state}`;
450
+ const rules = [];
451
+ for (const [prop, value] of Object.entries(stateStyles)) {
452
+ rules.push(` ${this.camelToKebab(prop)}: ${value};`);
453
+ }
454
+ if (rules.length > 0) {
455
+ compiled.cssRules.push(`${selector} {\n${rules.join('\n')}\n}`);
456
+ }
457
+ }
458
+ }
459
+ }
460
+ isResponsiveValue(value) {
461
+ return value && typeof value === 'object' && 'base' in value;
462
+ }
463
+ camelToKebab(str) {
464
+ return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase();
465
+ }
466
+ }
467
+ // Export singleton instance
468
+ export const styleCompiler = SVGStyleCompiler.getInstance();
@@ -0,0 +1,64 @@
1
+ import { Template, ComponentGenerationOptions } from '../types/index.js';
2
+ /**
3
+ * Template management system for customizable component generation
4
+ */
5
+ export declare class TemplateManager {
6
+ private static instance;
7
+ private templates;
8
+ private defaultTemplate;
9
+ private constructor();
10
+ static getInstance(): TemplateManager;
11
+ /**
12
+ * Load built-in templates
13
+ */
14
+ private loadBuiltinTemplates;
15
+ /**
16
+ * Register a new template
17
+ */
18
+ registerTemplate(template: Template): void;
19
+ /**
20
+ * Generate component using specified template
21
+ */
22
+ generateComponent(templateName: string, options: ComponentGenerationOptions): string;
23
+ /**
24
+ * Load custom template from file
25
+ */
26
+ loadCustomTemplate(templatePath: string): Promise<void>;
27
+ /**
28
+ * Get list of available templates
29
+ */
30
+ getAvailableTemplates(): string[];
31
+ /**
32
+ * Set default template
33
+ */
34
+ setDefaultTemplate(templateName: string): void;
35
+ /**
36
+ * Standard React Functional Component
37
+ */
38
+ private generateReactFunctional;
39
+ /**
40
+ * React Functional Component with forwardRef
41
+ */
42
+ private generateReactForwardRef;
43
+ /**
44
+ * React Class Component (legacy)
45
+ */
46
+ private generateReactClass;
47
+ /**
48
+ * Styled Components Template
49
+ */
50
+ private generateStyledComponents;
51
+ /**
52
+ * TypeScript Native (no React dependencies)
53
+ */
54
+ private generateTypeScriptNative;
55
+ /**
56
+ * Process string template with variable substitution
57
+ */
58
+ private processStringTemplate;
59
+ /**
60
+ * Enhanced Styled Template with comprehensive styling support
61
+ */
62
+ private generateEnhancedStyled;
63
+ }
64
+ export declare const templateManager: TemplateManager;