svger-cli 2.0.8 → 3.1.0

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.
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Official Rollup Plugin for SVGER-CLI
3
+ *
4
+ * Automatically converts SVG files to framework components during Rollup builds
5
+ * with full bundle optimization and tree-shaking support.
6
+ *
7
+ * @example
8
+ * ```js
9
+ * // rollup.config.js
10
+ * import { svgerRollupPlugin } from 'svger-cli/rollup';
11
+ *
12
+ * export default {
13
+ * plugins: [
14
+ * svgerRollupPlugin({
15
+ * source: './src/icons',
16
+ * output: './src/components/icons',
17
+ * framework: 'react',
18
+ * typescript: true
19
+ * })
20
+ * ]
21
+ * };
22
+ * ```
23
+ */
24
+ import path from 'path';
25
+ import { FileSystem } from '../utils/native.js';
26
+ import { svgProcessor } from '../processors/svg-processor.js';
27
+ import { configService } from '../services/config.js';
28
+ import { logger } from '../core/logger.js';
29
+ const PLUGIN_NAME = 'svger-rollup-plugin';
30
+ /**
31
+ * Rollup Plugin for SVGER-CLI
32
+ */
33
+ export function svgerRollupPlugin(options = {}) {
34
+ const config = configService.readConfig();
35
+ const pluginOptions = {
36
+ source: options.source || config.source || './src/icons',
37
+ output: options.output || config.output || './src/components/icons',
38
+ framework: options.framework || config.framework || 'react',
39
+ typescript: options.typescript !== undefined ? options.typescript : config.typescript,
40
+ config: options.config || {},
41
+ include: options.include || ['**/*.svg'],
42
+ exclude: options.exclude || ['node_modules/**'],
43
+ exportType: options.exportType || 'default',
44
+ svgo: options.svgo !== undefined ? options.svgo : false,
45
+ generateIndex: options.generateIndex !== undefined ? options.generateIndex : true,
46
+ sourcemap: options.sourcemap !== undefined ? options.sourcemap : false,
47
+ };
48
+ const processedFiles = new Set();
49
+ return {
50
+ name: PLUGIN_NAME,
51
+ async buildStart() {
52
+ logger.info('SVGER Rollup Plugin: Processing SVG files...');
53
+ await processAllSVGs(pluginOptions, processedFiles);
54
+ },
55
+ resolveId(id) {
56
+ // Handle SVG imports
57
+ if (id.endsWith('.svg')) {
58
+ // Let Rollup handle it naturally, we'll transform it
59
+ return null;
60
+ }
61
+ },
62
+ async load(id) {
63
+ // Load and transform SVG files
64
+ if (id.endsWith('.svg')) {
65
+ if (await FileSystem.exists(id)) {
66
+ const svgContent = await FileSystem.readFile(id, 'utf-8');
67
+ const componentName = svgProcessor.generateComponentName(id, 'pascal');
68
+ const component = await svgProcessor.generateComponent(componentName, svgContent, {
69
+ framework: pluginOptions.framework,
70
+ typescript: pluginOptions.typescript,
71
+ defaultWidth: config.defaultWidth,
72
+ defaultHeight: config.defaultHeight,
73
+ defaultFill: config.defaultFill,
74
+ styleRules: config.styleRules || {},
75
+ });
76
+ if (pluginOptions.exportType === 'named') {
77
+ return {
78
+ code: `${component}\nexport { ${componentName} };`,
79
+ map: pluginOptions.sourcemap ? { mappings: '' } : null,
80
+ };
81
+ }
82
+ return {
83
+ code: component,
84
+ map: pluginOptions.sourcemap ? { mappings: '' } : null,
85
+ };
86
+ }
87
+ }
88
+ },
89
+ async transform(code, id) {
90
+ // Transform SVG content if loaded by another plugin
91
+ if (id.endsWith('.svg')) {
92
+ const componentName = svgProcessor.generateComponentName(id, 'pascal');
93
+ const component = await svgProcessor.generateComponent(componentName, code, {
94
+ framework: pluginOptions.framework,
95
+ typescript: pluginOptions.typescript,
96
+ defaultWidth: config.defaultWidth,
97
+ defaultHeight: config.defaultHeight,
98
+ defaultFill: config.defaultFill,
99
+ styleRules: config.styleRules || {},
100
+ });
101
+ if (pluginOptions.exportType === 'named') {
102
+ return {
103
+ code: `${component}\nexport { ${componentName} };`,
104
+ map: pluginOptions.sourcemap ? { mappings: '' } : null,
105
+ };
106
+ }
107
+ return {
108
+ code: component,
109
+ map: pluginOptions.sourcemap ? { mappings: '' } : null,
110
+ };
111
+ }
112
+ },
113
+ };
114
+ }
115
+ /**
116
+ * Process all SVG files in the source directory
117
+ */
118
+ async function processAllSVGs(options, processedFiles) {
119
+ const sourceDir = path.resolve(options.source);
120
+ const outputDir = path.resolve(options.output);
121
+ if (!(await FileSystem.exists(sourceDir))) {
122
+ logger.warn(`Source directory not found: ${sourceDir}`);
123
+ return;
124
+ }
125
+ await FileSystem.ensureDir(outputDir);
126
+ const files = await FileSystem.readDir(sourceDir);
127
+ const svgFiles = files.filter((file) => file.endsWith('.svg'));
128
+ if (svgFiles.length === 0) {
129
+ logger.warn('No SVG files found in source directory');
130
+ return;
131
+ }
132
+ const results = [];
133
+ for (const file of svgFiles) {
134
+ const svgPath = path.join(sourceDir, file);
135
+ const result = await processSVGFile(svgPath, outputDir, options);
136
+ results.push(result);
137
+ if (result.success && result.outputPath) {
138
+ processedFiles.add(result.outputPath);
139
+ }
140
+ }
141
+ // Generate index file
142
+ if (options.generateIndex) {
143
+ await generateIndexFile(outputDir, results, options);
144
+ }
145
+ const successful = results.filter(r => r.success).length;
146
+ logger.info(`SVGER: Processed ${successful}/${svgFiles.length} SVG files`);
147
+ }
148
+ /**
149
+ * Process a single SVG file
150
+ */
151
+ async function processSVGFile(svgPath, outputDir, options) {
152
+ try {
153
+ const config = configService.readConfig();
154
+ const mergedConfig = {
155
+ ...config,
156
+ ...options.config,
157
+ framework: options.framework,
158
+ typescript: options.typescript,
159
+ };
160
+ const result = await svgProcessor.processSVGFile(svgPath, outputDir, {
161
+ framework: mergedConfig.framework,
162
+ typescript: mergedConfig.typescript,
163
+ defaultWidth: mergedConfig.defaultWidth,
164
+ defaultHeight: mergedConfig.defaultHeight,
165
+ defaultFill: mergedConfig.defaultFill,
166
+ styleRules: mergedConfig.styleRules || {},
167
+ });
168
+ return {
169
+ success: result.success,
170
+ outputPath: result.filePath || undefined,
171
+ componentName: result.componentName,
172
+ error: result.error,
173
+ };
174
+ }
175
+ catch (error) {
176
+ logger.error(`Failed to process ${svgPath}:`, error);
177
+ return {
178
+ success: false,
179
+ error: error,
180
+ };
181
+ }
182
+ }
183
+ /**
184
+ * Generate index file with all exports
185
+ */
186
+ async function generateIndexFile(outputDir, results, options) {
187
+ const extension = options.typescript ? 'ts' : 'js';
188
+ const exports = results
189
+ .filter(r => r.componentName)
190
+ .map(r => `export { default as ${r.componentName} } from './${r.componentName}';`)
191
+ .join('\n');
192
+ const indexPath = path.join(outputDir, `index.${extension}`);
193
+ await FileSystem.writeFile(indexPath, exports, 'utf-8');
194
+ logger.debug(`Generated index file: ${indexPath}`);
195
+ }
196
+ // Default export
197
+ export default svgerRollupPlugin;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Official Vite Plugin for SVGER-CLI
3
+ *
4
+ * Automatically converts SVG files to framework components during Vite builds
5
+ * with full HMR support and virtual module integration.
6
+ *
7
+ * @example
8
+ * ```js
9
+ * // vite.config.js
10
+ * import { svgerVitePlugin } from 'svger-cli/vite';
11
+ *
12
+ * export default {
13
+ * plugins: [
14
+ * svgerVitePlugin({
15
+ * source: './src/icons',
16
+ * output: './src/components/icons',
17
+ * framework: 'react',
18
+ * typescript: true
19
+ * })
20
+ * ]
21
+ * };
22
+ * ```
23
+ */
24
+ import type { VitePluginOptions } from '../types/integrations.js';
25
+ /**
26
+ * Vite Plugin for SVGER-CLI
27
+ */
28
+ export declare function svgerVitePlugin(options?: VitePluginOptions): any;
29
+ export default svgerVitePlugin;
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Official Vite Plugin for SVGER-CLI
3
+ *
4
+ * Automatically converts SVG files to framework components during Vite builds
5
+ * with full HMR support and virtual module integration.
6
+ *
7
+ * @example
8
+ * ```js
9
+ * // vite.config.js
10
+ * import { svgerVitePlugin } from 'svger-cli/vite';
11
+ *
12
+ * export default {
13
+ * plugins: [
14
+ * svgerVitePlugin({
15
+ * source: './src/icons',
16
+ * output: './src/components/icons',
17
+ * framework: 'react',
18
+ * typescript: true
19
+ * })
20
+ * ]
21
+ * };
22
+ * ```
23
+ */
24
+ import path from 'path';
25
+ import { FileSystem } from '../utils/native.js';
26
+ import { svgProcessor } from '../processors/svg-processor.js';
27
+ import { configService } from '../services/config.js';
28
+ import { logger } from '../core/logger.js';
29
+ const PLUGIN_NAME = 'svger-vite-plugin';
30
+ const VIRTUAL_MODULE_PREFIX = 'virtual:svger/';
31
+ /**
32
+ * Vite Plugin for SVGER-CLI
33
+ */
34
+ export function svgerVitePlugin(options = {}) {
35
+ const config = configService.readConfig();
36
+ const pluginOptions = {
37
+ source: options.source || config.source || './src/icons',
38
+ output: options.output || config.output || './src/components/icons',
39
+ framework: options.framework || config.framework || 'react',
40
+ typescript: options.typescript !== undefined ? options.typescript : config.typescript,
41
+ config: options.config || {},
42
+ include: options.include || ['**/*.svg'],
43
+ exclude: options.exclude || ['node_modules/**'],
44
+ hmr: options.hmr !== undefined ? options.hmr : true,
45
+ virtual: options.virtual !== undefined ? options.virtual : false,
46
+ exportType: options.exportType || 'default',
47
+ svgo: options.svgo !== undefined ? options.svgo : false,
48
+ generateIndex: options.generateIndex !== undefined ? options.generateIndex : true,
49
+ };
50
+ let viteConfig;
51
+ const processedFiles = new Set();
52
+ return {
53
+ name: PLUGIN_NAME,
54
+ configResolved(resolvedConfig) {
55
+ viteConfig = resolvedConfig;
56
+ },
57
+ async buildStart() {
58
+ logger.info('SVGER Vite Plugin: Processing SVG files...');
59
+ await processAllSVGs(pluginOptions, processedFiles);
60
+ },
61
+ async handleHotUpdate(ctx) {
62
+ if (!pluginOptions.hmr)
63
+ return;
64
+ const { file, server } = ctx;
65
+ if (file.endsWith('.svg') && file.includes(pluginOptions.source)) {
66
+ logger.info(`SVGER: Hot reloading ${path.basename(file)}`);
67
+ const outputDir = path.resolve(pluginOptions.output);
68
+ const result = await processSVGFile(file, outputDir, pluginOptions);
69
+ if (result.success) {
70
+ // Trigger HMR for the generated component
71
+ const modules = server.moduleGraph.getModulesByFile(file);
72
+ if (modules) {
73
+ return Array.from(modules);
74
+ }
75
+ }
76
+ }
77
+ },
78
+ resolveId(id) {
79
+ // Handle virtual modules
80
+ if (pluginOptions.virtual && id.startsWith(VIRTUAL_MODULE_PREFIX)) {
81
+ return '\0' + id;
82
+ }
83
+ // Handle direct SVG imports
84
+ if (id.endsWith('.svg')) {
85
+ return null; // Let Vite handle it with our transform hook
86
+ }
87
+ },
88
+ async load(id) {
89
+ // Handle virtual modules
90
+ if (pluginOptions.virtual &&
91
+ id.startsWith('\0' + VIRTUAL_MODULE_PREFIX)) {
92
+ const svgName = id.slice(('\0' + VIRTUAL_MODULE_PREFIX).length);
93
+ const sourceDir = path.resolve(pluginOptions.source);
94
+ const svgPath = path.join(sourceDir, svgName + '.svg');
95
+ if (await FileSystem.exists(svgPath)) {
96
+ const svgContent = await FileSystem.readFile(svgPath, 'utf-8');
97
+ const componentName = svgProcessor.generateComponentName(svgPath, 'pascal');
98
+ const component = await svgProcessor.generateComponent(componentName, svgContent, {
99
+ framework: pluginOptions.framework,
100
+ typescript: pluginOptions.typescript,
101
+ defaultWidth: config.defaultWidth,
102
+ defaultHeight: config.defaultHeight,
103
+ defaultFill: config.defaultFill,
104
+ styleRules: config.styleRules || {},
105
+ });
106
+ return {
107
+ code: component,
108
+ map: null,
109
+ };
110
+ }
111
+ }
112
+ },
113
+ async transform(code, id) {
114
+ // Transform direct SVG imports
115
+ if (id.endsWith('.svg')) {
116
+ const componentName = svgProcessor.generateComponentName(id, 'pascal');
117
+ const component = await svgProcessor.generateComponent(componentName, code, {
118
+ framework: pluginOptions.framework,
119
+ typescript: pluginOptions.typescript,
120
+ defaultWidth: config.defaultWidth,
121
+ defaultHeight: config.defaultHeight,
122
+ defaultFill: config.defaultFill,
123
+ styleRules: config.styleRules || {},
124
+ });
125
+ if (pluginOptions.exportType === 'named') {
126
+ return {
127
+ code: `${component}\nexport { ${componentName} };`,
128
+ map: null,
129
+ };
130
+ }
131
+ return {
132
+ code: component,
133
+ map: null,
134
+ };
135
+ }
136
+ },
137
+ };
138
+ }
139
+ /**
140
+ * Process all SVG files in the source directory
141
+ */
142
+ async function processAllSVGs(options, processedFiles) {
143
+ const sourceDir = path.resolve(options.source);
144
+ const outputDir = path.resolve(options.output);
145
+ if (!(await FileSystem.exists(sourceDir))) {
146
+ logger.warn(`Source directory not found: ${sourceDir}`);
147
+ return;
148
+ }
149
+ await FileSystem.ensureDir(outputDir);
150
+ const files = await FileSystem.readDir(sourceDir);
151
+ const svgFiles = files.filter((file) => file.endsWith('.svg'));
152
+ if (svgFiles.length === 0) {
153
+ logger.warn('No SVG files found in source directory');
154
+ return;
155
+ }
156
+ const results = [];
157
+ for (const file of svgFiles) {
158
+ const svgPath = path.join(sourceDir, file);
159
+ const result = await processSVGFile(svgPath, outputDir, options);
160
+ results.push(result);
161
+ if (result.success && result.outputPath) {
162
+ processedFiles.add(result.outputPath);
163
+ }
164
+ }
165
+ // Generate index file
166
+ if (options.generateIndex) {
167
+ await generateIndexFile(outputDir, results, options);
168
+ }
169
+ const successful = results.filter(r => r.success).length;
170
+ logger.info(`SVGER: Processed ${successful}/${svgFiles.length} SVG files`);
171
+ }
172
+ /**
173
+ * Process a single SVG file
174
+ */
175
+ async function processSVGFile(svgPath, outputDir, options) {
176
+ try {
177
+ const config = configService.readConfig();
178
+ const mergedConfig = {
179
+ ...config,
180
+ ...options.config,
181
+ framework: options.framework,
182
+ typescript: options.typescript,
183
+ };
184
+ const result = await svgProcessor.processSVGFile(svgPath, outputDir, {
185
+ framework: mergedConfig.framework,
186
+ typescript: mergedConfig.typescript,
187
+ defaultWidth: mergedConfig.defaultWidth,
188
+ defaultHeight: mergedConfig.defaultHeight,
189
+ defaultFill: mergedConfig.defaultFill,
190
+ styleRules: mergedConfig.styleRules || {},
191
+ });
192
+ return {
193
+ success: result.success,
194
+ outputPath: result.filePath || undefined,
195
+ componentName: result.componentName,
196
+ error: result.error,
197
+ };
198
+ }
199
+ catch (error) {
200
+ logger.error(`Failed to process ${svgPath}:`, error);
201
+ return {
202
+ success: false,
203
+ error: error,
204
+ };
205
+ }
206
+ }
207
+ /**
208
+ * Generate index file with all exports
209
+ */
210
+ async function generateIndexFile(outputDir, results, options) {
211
+ const extension = options.typescript ? 'ts' : 'js';
212
+ const exports = results
213
+ .filter(r => r.componentName)
214
+ .map(r => `export { default as ${r.componentName} } from './${r.componentName}';`)
215
+ .join('\n');
216
+ const indexPath = path.join(outputDir, `index.${extension}`);
217
+ await FileSystem.writeFile(indexPath, exports, 'utf-8');
218
+ logger.debug(`Generated index file: ${indexPath}`);
219
+ }
220
+ // Default export
221
+ export default svgerVitePlugin;
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Official Webpack Plugin for SVGER-CLI
3
+ *
4
+ * Automatically converts SVG files to framework components during webpack builds
5
+ * with full HMR support and optimization.
6
+ *
7
+ * @example
8
+ * ```js
9
+ * // webpack.config.js
10
+ * const { SvgerWebpackPlugin } = require('svger-cli/webpack');
11
+ *
12
+ * module.exports = {
13
+ * plugins: [
14
+ * new SvgerWebpackPlugin({
15
+ * source: './src/icons',
16
+ * output: './src/components/icons',
17
+ * framework: 'react',
18
+ * typescript: true
19
+ * })
20
+ * ]
21
+ * };
22
+ * ```
23
+ */
24
+ import type { WebpackPluginOptions } from '../types/integrations.js';
25
+ /**
26
+ * Webpack Plugin for SVGER-CLI
27
+ */
28
+ export declare class SvgerWebpackPlugin {
29
+ private options;
30
+ private processedFiles;
31
+ private watchDebounceTimer?;
32
+ constructor(options?: WebpackPluginOptions);
33
+ apply(compiler: any): void;
34
+ /**
35
+ * Process all SVG files in the source directory
36
+ */
37
+ private processAllSVGs;
38
+ /**
39
+ * Process changed files in watch mode
40
+ */
41
+ private processChangedFiles;
42
+ /**
43
+ * Process a single SVG file
44
+ */
45
+ private processSVGFile;
46
+ /**
47
+ * Generate index file with all exports
48
+ */
49
+ private generateIndexFile;
50
+ /**
51
+ * Get changed files from webpack
52
+ */
53
+ private getChangedFiles;
54
+ }
55
+ /**
56
+ * Webpack Loader for SVGER-CLI
57
+ *
58
+ * Transforms SVG imports into framework components inline
59
+ *
60
+ * @example
61
+ * ```js
62
+ * // webpack.config.js
63
+ * module.exports = {
64
+ * module: {
65
+ * rules: [
66
+ * {
67
+ * test: /\.svg$/,
68
+ * use: [
69
+ * {
70
+ * loader: 'svger-cli/webpack-loader',
71
+ * options: {
72
+ * framework: 'react',
73
+ * typescript: true
74
+ * }
75
+ * }
76
+ * ]
77
+ * }
78
+ * ]
79
+ * }
80
+ * };
81
+ * ```
82
+ */
83
+ export declare function svgerLoader(this: any, content: string): Promise<string>;
84
+ export default SvgerWebpackPlugin;