svger-cli 2.0.2 → 2.0.4

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/SECURITY.md ADDED
@@ -0,0 +1,69 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ We actively support the following versions of SVGER-CLI with security updates:
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 2.0.x | :white_check_mark: |
10
+ | 1.x.x | :x: |
11
+
12
+ ## Reporting a Vulnerability
13
+
14
+ We take the security of SVGER-CLI seriously. If you discover a security vulnerability, please follow these guidelines:
15
+
16
+ ### How to Report
17
+
18
+ 1. **DO NOT** create a public GitHub issue for security vulnerabilities
19
+ 2. Send an email to **faezemohades@gmail.com** with the subject line: `[SECURITY] SVGER-CLI Vulnerability Report`
20
+ 3. Include the following information:
21
+ - Description of the vulnerability
22
+ - Steps to reproduce the issue
23
+ - Potential impact
24
+ - Suggested fix (if any)
25
+ - Your contact information
26
+
27
+ ### What to Expect
28
+
29
+ - **Acknowledgment**: We will acknowledge receipt of your report within 24 hours
30
+ - **Assessment**: We will assess the vulnerability within 72 hours
31
+ - **Updates**: We will provide regular updates on our progress
32
+ - **Resolution**: Critical vulnerabilities will be patched within 7 days, others within 30 days
33
+
34
+ ### Security Best Practices for Users
35
+
36
+ When using SVGER-CLI in your projects:
37
+
38
+ 1. **Keep Updated**: Always use the latest version
39
+ 2. **Validate Input**: Ensure SVG files come from trusted sources
40
+ 3. **Review Output**: Inspect generated components before deploying
41
+ 4. **File Permissions**: Use appropriate file permissions for generated components
42
+ 5. **CI/CD Security**: Secure your build pipelines that use SVGER-CLI
43
+
44
+ ### Security Features
45
+
46
+ SVGER-CLI includes several security features:
47
+
48
+ - **Zero Dependencies**: Eliminates third-party vulnerability vectors
49
+ - **Input Validation**: Validates SVG content before processing
50
+ - **Sandboxed Processing**: Processes files in isolated contexts
51
+ - **Safe Output Generation**: Generates safe, sanitized component code
52
+ - **File Locking**: Prevents unauthorized modification of protected files
53
+
54
+ ### Disclosure Policy
55
+
56
+ - We believe in responsible disclosure
57
+ - We will credit security researchers who report vulnerabilities responsibly
58
+ - We may create a security advisory for significant vulnerabilities
59
+ - We will notify users through our release notes and GitHub security advisories
60
+
61
+ ## Contact
62
+
63
+ For any security-related questions or concerns:
64
+
65
+ - **Primary Contact**: faezemohades@gmail.com
66
+ - **Alternative Contact**: navidrezadoost07@gmail.com
67
+ - **PGP Key**: Available upon request
68
+
69
+ Thank you for helping keep SVGER-CLI secure!
package/dist/builder.js CHANGED
@@ -1,8 +1,8 @@
1
- import path from "path";
2
- import { toPascalCase, FileSystem } from "./utils/native.js";
3
- import { isLocked } from "./lock.js";
4
- import { readConfig } from "./config.js";
5
- import { reactTemplate } from "./templates/ComponentTemplate.js";
1
+ import path from 'path';
2
+ import { toPascalCase, FileSystem } from './utils/native.js';
3
+ import { isLocked } from './lock.js';
4
+ import { readConfig } from './config.js';
5
+ import { reactTemplate } from './templates/ComponentTemplate.js';
6
6
  /**
7
7
  * Converts all SVG files from a source directory into React components and writes them to an output directory.
8
8
  *
@@ -16,13 +16,13 @@ export async function buildAll(config) {
16
16
  const srcDir = path.resolve(config.src);
17
17
  const outDir = path.resolve(config.out);
18
18
  if (!(await FileSystem.exists(srcDir))) {
19
- console.error("❌ Source folder not found:", srcDir);
19
+ console.error('❌ Source folder not found:', srcDir);
20
20
  process.exit(1);
21
21
  }
22
22
  await FileSystem.ensureDir(outDir);
23
- const files = (await FileSystem.readDir(srcDir)).filter((f) => f.endsWith(".svg"));
23
+ const files = (await FileSystem.readDir(srcDir)).filter((f) => f.endsWith('.svg'));
24
24
  if (!files.length) {
25
- console.log("⚠️ No SVG files found in", srcDir);
25
+ console.log('⚠️ No SVG files found in', srcDir);
26
26
  return;
27
27
  }
28
28
  for (const file of files) {
@@ -31,8 +31,8 @@ export async function buildAll(config) {
31
31
  console.log(`⚠️ Skipped locked file: ${file}`);
32
32
  continue;
33
33
  }
34
- const svgContent = await FileSystem.readFile(svgPath, "utf-8");
35
- const componentName = toPascalCase(file.replace(".svg", ""));
34
+ const svgContent = await FileSystem.readFile(svgPath, 'utf-8');
35
+ const componentName = toPascalCase(file.replace('.svg', ''));
36
36
  const componentCode = reactTemplate({
37
37
  componentName,
38
38
  svgContent,
@@ -41,10 +41,10 @@ export async function buildAll(config) {
41
41
  defaultFill: svgConfig.defaultFill,
42
42
  });
43
43
  const outFile = path.join(outDir, `${componentName}.tsx`);
44
- await FileSystem.writeFile(outFile, componentCode, "utf-8");
44
+ await FileSystem.writeFile(outFile, componentCode, 'utf-8');
45
45
  console.log(`✅ Generated: ${componentName}.tsx`);
46
46
  }
47
- console.log("🎉 All SVGs have been converted successfully!");
47
+ console.log('🎉 All SVGs have been converted successfully!');
48
48
  }
49
49
  /**
50
50
  * Generates a single React component from an SVG file.
@@ -62,11 +62,11 @@ export async function generateSVG({ svgFile, outDir, }) {
62
62
  return;
63
63
  }
64
64
  if (!(await FileSystem.exists(filePath))) {
65
- console.error("❌ SVG file not found:", filePath);
65
+ console.error('❌ SVG file not found:', filePath);
66
66
  process.exit(1);
67
67
  }
68
- const svgContent = await FileSystem.readFile(filePath, "utf-8");
69
- const componentName = toPascalCase(path.basename(svgFile, ".svg"));
68
+ const svgContent = await FileSystem.readFile(filePath, 'utf-8');
69
+ const componentName = toPascalCase(path.basename(svgFile, '.svg'));
70
70
  const componentCode = reactTemplate({
71
71
  componentName,
72
72
  svgContent,
@@ -77,6 +77,6 @@ export async function generateSVG({ svgFile, outDir, }) {
77
77
  const outputFolder = path.resolve(outDir);
78
78
  await FileSystem.ensureDir(outputFolder);
79
79
  const outFile = path.join(outputFolder, `${componentName}.tsx`);
80
- await FileSystem.writeFile(outFile, componentCode, "utf-8");
80
+ await FileSystem.writeFile(outFile, componentCode, 'utf-8');
81
81
  console.log(`✅ Generated: ${componentName}.tsx`);
82
82
  }
package/dist/clean.js CHANGED
@@ -1,5 +1,5 @@
1
- import path from "path";
2
- import { FileSystem } from "./utils/native.js";
1
+ import path from 'path';
2
+ import { FileSystem } from './utils/native.js';
3
3
  /**
4
4
  * Cleans the specified output directory by removing all files and folders inside it.
5
5
  * Typically used to clear previously generated SVG React components before a new build.
package/dist/cli.js CHANGED
@@ -1,30 +1,30 @@
1
1
  #!/usr/bin/env node
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";
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("svger-cli")
13
- .description("Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter")
14
- .version("2.0.0");
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("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")
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("watch <src> <out>")
66
- .description("Watch source folder and rebuild SVGs automatically")
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("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")
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("lock <files...>")
128
- .description("Lock one or more SVG files")
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("unlock <files...>")
143
- .description("Unlock one or more SVG files")
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("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")
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("Invalid format. Use key=value");
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("No option provided. Use --init, --set, or --show");
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("clean <out>")
191
- .description("Remove all generated SVG React components from output folder")
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 "path";
2
- import { FileSystem } from "./utils/native.js";
3
- const CONFIG_FILE = ".svgconfig.json";
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,107 @@ export function writeConfig(config) {
31
31
  */
32
32
  export async function initConfig() {
33
33
  if (await FileSystem.exists(getConfigPath())) {
34
- console.log("⚠️ Config file already exists:", getConfigPath());
34
+ console.log('⚠️ Config file already exists:', getConfigPath());
35
35
  return;
36
36
  }
37
37
  const defaultConfig = {
38
- source: "./src/assets/svg",
39
- output: "./src/components/icons",
38
+ // Source & Output
39
+ source: './src/assets/svg',
40
+ output: './src/components/icons',
41
+ // Framework Configuration
42
+ framework: 'react',
43
+ typescript: true,
44
+ componentType: 'functional',
45
+ // Processing Options
40
46
  watch: false,
47
+ parallel: true,
48
+ batchSize: 10,
49
+ maxConcurrency: 4,
50
+ cache: true,
51
+ // Default Properties
41
52
  defaultWidth: 24,
42
53
  defaultHeight: 24,
43
- defaultFill: "currentColor",
44
- exclude: [],
54
+ defaultFill: 'currentColor',
55
+ defaultStroke: 'none',
56
+ defaultStrokeWidth: 1,
57
+ // Styling Configuration
45
58
  styleRules: {
46
- fill: "inherit",
47
- stroke: "none",
59
+ fill: 'inherit',
60
+ stroke: 'none',
61
+ },
62
+ responsive: {
63
+ breakpoints: ['sm', 'md', 'lg', 'xl'],
64
+ values: {
65
+ width: ['16px', '20px', '24px', '32px'],
66
+ height: ['16px', '20px', '24px', '32px'],
67
+ },
68
+ },
69
+ theme: {
70
+ mode: 'auto',
71
+ variables: {
72
+ primary: 'currentColor',
73
+ secondary: '#6b7280',
74
+ accent: '#3b82f6',
75
+ },
76
+ },
77
+ animations: [],
78
+ // Advanced Options
79
+ plugins: [],
80
+ exclude: [],
81
+ include: [],
82
+ // Error Handling
83
+ errorHandling: {
84
+ strategy: 'continue',
85
+ maxRetries: 3,
86
+ timeout: 30000,
87
+ },
88
+ // Performance Settings
89
+ performance: {
90
+ optimization: 'balanced',
91
+ memoryLimit: 512,
92
+ cacheTimeout: 3600000,
93
+ },
94
+ // Output Customization
95
+ outputConfig: {
96
+ naming: 'pascal',
97
+ extension: 'tsx',
98
+ directory: './src/components/icons',
99
+ },
100
+ // Framework-specific configurations
101
+ react: {
102
+ componentType: 'functional',
103
+ forwardRef: true,
104
+ memo: false,
105
+ propsInterface: 'SVGProps',
106
+ styledComponents: false,
107
+ cssModules: false,
108
+ },
109
+ vue: {
110
+ api: 'composition',
111
+ setup: true,
112
+ typescript: true,
113
+ scoped: true,
114
+ cssVariables: true,
115
+ },
116
+ angular: {
117
+ standalone: true,
118
+ signals: true,
119
+ changeDetection: 'OnPush',
120
+ encapsulation: 'Emulated',
121
+ },
122
+ // Legacy support (deprecated)
123
+ template: {
124
+ type: 'default',
125
+ },
126
+ frameworkOptions: {
127
+ forwardRef: true,
128
+ memo: false,
129
+ scriptSetup: true,
130
+ standalone: true,
48
131
  },
49
132
  };
50
133
  writeConfig(defaultConfig);
51
- console.log("✅ Config file created:", getConfigPath());
134
+ console.log('✅ Config file created:', getConfigPath());
52
135
  }
53
136
  /**
54
137
  * Set a specific configuration key to a new value.
@@ -67,6 +150,6 @@ export function setConfig(key, value) {
67
150
  */
68
151
  export function showConfig() {
69
152
  const config = readConfig();
70
- console.log("📄 Current Config:");
153
+ console.log('📄 Current Config:');
71
154
  console.log(JSON.stringify(config, null, 2));
72
155
  }
@@ -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: (error) => error.context?.filePath && error.context?.canSkip === true,
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: (error) => error.context?.svgContent,
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: (error) => error.context?.alternative,
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), { method: propertyName, ...context });
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
- changeDetection: ChangeDetectionStrategy.OnPush` : ''}
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, require('os').cpus().length) } = config;
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((resolve) => {
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 && config?.options && !plugin.validate(config.options)) {
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
  /**