svgfusion 1.0.0-beta.2
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/CONTRIBUTING.md +93 -0
- package/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/cli.d.mts +2 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +1 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +152 -0
- package/dist/index.d.ts +152 -0
- package/dist/index.js +412 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +374 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +102 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Config } from 'svgo';
|
|
2
|
+
|
|
3
|
+
interface ConversionOptions {
|
|
4
|
+
name?: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
suffix?: string;
|
|
7
|
+
optimize?: boolean;
|
|
8
|
+
typescript?: boolean;
|
|
9
|
+
format?: 'esm' | 'cjs';
|
|
10
|
+
}
|
|
11
|
+
interface ReactConversionOptions extends ConversionOptions {
|
|
12
|
+
memo?: boolean;
|
|
13
|
+
ref?: boolean;
|
|
14
|
+
titleProp?: boolean;
|
|
15
|
+
descProp?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface VueConversionOptions extends ConversionOptions {
|
|
18
|
+
compositionApi?: boolean;
|
|
19
|
+
scriptSetup?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface ConversionResult {
|
|
22
|
+
code: string;
|
|
23
|
+
filename: string;
|
|
24
|
+
componentName: string;
|
|
25
|
+
}
|
|
26
|
+
interface BatchConversionOptions extends ConversionOptions {
|
|
27
|
+
inputDir: string;
|
|
28
|
+
outputDir: string;
|
|
29
|
+
recursive?: boolean;
|
|
30
|
+
extensions?: string[];
|
|
31
|
+
}
|
|
32
|
+
interface BatchConversionResult {
|
|
33
|
+
results: ConversionResult[];
|
|
34
|
+
errors: ConversionError[];
|
|
35
|
+
summary: {
|
|
36
|
+
total: number;
|
|
37
|
+
successful: number;
|
|
38
|
+
failed: number;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
interface ConversionError {
|
|
42
|
+
file: string;
|
|
43
|
+
error: string;
|
|
44
|
+
stack?: string;
|
|
45
|
+
}
|
|
46
|
+
type Framework = 'react' | 'vue';
|
|
47
|
+
interface CliOptions {
|
|
48
|
+
framework: Framework;
|
|
49
|
+
input: string;
|
|
50
|
+
output?: string;
|
|
51
|
+
name?: string;
|
|
52
|
+
prefix?: string;
|
|
53
|
+
suffix?: string;
|
|
54
|
+
optimize?: boolean;
|
|
55
|
+
typescript?: boolean;
|
|
56
|
+
format?: 'esm' | 'cjs';
|
|
57
|
+
recursive?: boolean;
|
|
58
|
+
verbose?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Convert SVG to React component
|
|
63
|
+
* @param svgContent - SVG content string
|
|
64
|
+
* @param options - Conversion options
|
|
65
|
+
* @returns Conversion result with React component code
|
|
66
|
+
*/
|
|
67
|
+
declare function convertToReact(svgContent: string, options?: ReactConversionOptions): Promise<ConversionResult>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Convert SVG to Vue 3 component
|
|
71
|
+
* @param svgContent - SVG content string
|
|
72
|
+
* @param options - Conversion options
|
|
73
|
+
* @returns Conversion result with Vue component code
|
|
74
|
+
*/
|
|
75
|
+
declare function convertToVue(svgContent: string, options?: VueConversionOptions): ConversionResult;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Optimize SVG content using SVGO
|
|
79
|
+
* @param svgContent - SVG content to optimize
|
|
80
|
+
* @param config - Optional SVGO configuration
|
|
81
|
+
* @returns Optimized SVG content
|
|
82
|
+
*/
|
|
83
|
+
declare function optimizeSvg(svgContent: string, config?: Config): string;
|
|
84
|
+
/**
|
|
85
|
+
* Create custom SVGO configuration
|
|
86
|
+
* @param options - Configuration options
|
|
87
|
+
* @returns SVGO configuration
|
|
88
|
+
*/
|
|
89
|
+
declare function createSvgoConfig(options: {
|
|
90
|
+
removeViewBox?: boolean;
|
|
91
|
+
removeDimensions?: boolean;
|
|
92
|
+
removeTitle?: boolean;
|
|
93
|
+
removeDesc?: boolean;
|
|
94
|
+
preserveAspectRatio?: boolean;
|
|
95
|
+
preserveColors?: boolean;
|
|
96
|
+
preserveClasses?: boolean;
|
|
97
|
+
}): Config;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Read SVG file content
|
|
101
|
+
* @param filePath - Path to the SVG file
|
|
102
|
+
* @returns SVG content as string
|
|
103
|
+
*/
|
|
104
|
+
declare function readSvgFile(filePath: string): Promise<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Write SVG file content
|
|
107
|
+
* @param filePath - Path to write the SVG file
|
|
108
|
+
* @param content - SVG content
|
|
109
|
+
*/
|
|
110
|
+
declare function writeSvgFile(filePath: string, content: string): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Write component file content
|
|
113
|
+
* @param filePath - Path to write the component file
|
|
114
|
+
* @param content - Component content
|
|
115
|
+
*/
|
|
116
|
+
declare function writeComponentFile(filePath: string, content: string): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Read all SVG files from a directory
|
|
119
|
+
* @param dirPath - Directory path
|
|
120
|
+
* @param recursive - Whether to read recursively
|
|
121
|
+
* @returns Array of SVG file paths
|
|
122
|
+
*/
|
|
123
|
+
declare function readSvgDirectory(dirPath: string, recursive?: boolean): Promise<string[]>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Convert SVG filename to a valid React component name
|
|
127
|
+
* @param filename - The SVG filename
|
|
128
|
+
* @returns PascalCase component name
|
|
129
|
+
*/
|
|
130
|
+
declare function svgToComponentName(filename: string): string;
|
|
131
|
+
/**
|
|
132
|
+
* Sanitize component name to ensure it's valid
|
|
133
|
+
* @param name - The component name to sanitize
|
|
134
|
+
* @returns Sanitized component name
|
|
135
|
+
*/
|
|
136
|
+
declare function sanitizeComponentName(name: string): string;
|
|
137
|
+
/**
|
|
138
|
+
* Convert a string to PascalCase
|
|
139
|
+
* @param str - The string to convert
|
|
140
|
+
* @returns PascalCase string
|
|
141
|
+
*/
|
|
142
|
+
declare function pascalCase(str: string): string;
|
|
143
|
+
/**
|
|
144
|
+
* Add prefix/suffix to component name
|
|
145
|
+
* @param name - Base component name
|
|
146
|
+
* @param prefix - Optional prefix
|
|
147
|
+
* @param suffix - Optional suffix
|
|
148
|
+
* @returns Component name with prefix/suffix
|
|
149
|
+
*/
|
|
150
|
+
declare function formatComponentName(name: string, prefix?: string, suffix?: string): string;
|
|
151
|
+
|
|
152
|
+
export { BatchConversionOptions, BatchConversionResult, CliOptions, ConversionError, ConversionOptions, ConversionResult, Framework, ReactConversionOptions, VueConversionOptions, convertToReact, convertToVue, createSvgoConfig, formatComponentName, optimizeSvg, pascalCase, readSvgDirectory, readSvgFile, sanitizeComponentName, svgToComponentName, writeComponentFile, writeSvgFile };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
convertToReact: () => convertToReact,
|
|
24
|
+
convertToVue: () => convertToVue,
|
|
25
|
+
createSvgoConfig: () => createSvgoConfig,
|
|
26
|
+
formatComponentName: () => formatComponentName,
|
|
27
|
+
optimizeSvg: () => optimizeSvg,
|
|
28
|
+
pascalCase: () => pascalCase,
|
|
29
|
+
readSvgDirectory: () => readSvgDirectory,
|
|
30
|
+
readSvgFile: () => readSvgFile,
|
|
31
|
+
sanitizeComponentName: () => sanitizeComponentName,
|
|
32
|
+
svgToComponentName: () => svgToComponentName,
|
|
33
|
+
writeComponentFile: () => writeComponentFile,
|
|
34
|
+
writeSvgFile: () => writeSvgFile
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
|
|
38
|
+
// src/converters/react.ts
|
|
39
|
+
var import_core = require("@svgr/core");
|
|
40
|
+
|
|
41
|
+
// src/utils/svgo.ts
|
|
42
|
+
var import_svgo = require("svgo");
|
|
43
|
+
var defaultConfig = {
|
|
44
|
+
plugins: [
|
|
45
|
+
{
|
|
46
|
+
name: "preset-default",
|
|
47
|
+
params: {
|
|
48
|
+
overrides: {
|
|
49
|
+
removeViewBox: false,
|
|
50
|
+
removeTitle: false,
|
|
51
|
+
removeDesc: false,
|
|
52
|
+
removeUselessStrokeAndFill: false,
|
|
53
|
+
convertColors: {
|
|
54
|
+
currentColor: true,
|
|
55
|
+
names2hex: true,
|
|
56
|
+
rgb2hex: true,
|
|
57
|
+
shorthex: true,
|
|
58
|
+
// cspell:disable-line
|
|
59
|
+
shortname: true
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"removeDimensions",
|
|
65
|
+
"cleanupNumericValues"
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
function optimizeSvg(svgContent, config = defaultConfig) {
|
|
69
|
+
try {
|
|
70
|
+
const result = (0, import_svgo.optimize)(svgContent, config);
|
|
71
|
+
return result.data;
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new Error(`Failed to optimize SVG: ${error}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function createSvgoConfig(options) {
|
|
77
|
+
const plugins = [
|
|
78
|
+
{
|
|
79
|
+
name: "preset-default",
|
|
80
|
+
params: {
|
|
81
|
+
overrides: {
|
|
82
|
+
removeViewBox: !options.removeViewBox,
|
|
83
|
+
removeTitle: !options.removeTitle,
|
|
84
|
+
removeDesc: !options.removeDesc,
|
|
85
|
+
removeUselessStrokeAndFill: !options.preserveClasses,
|
|
86
|
+
convertColors: options.preserveColors ? false : {
|
|
87
|
+
currentColor: true,
|
|
88
|
+
names2hex: true,
|
|
89
|
+
rgb2hex: true,
|
|
90
|
+
shorthex: true,
|
|
91
|
+
// cspell:disable-line
|
|
92
|
+
shortname: true
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"cleanupNumericValues"
|
|
98
|
+
];
|
|
99
|
+
if (options.removeDimensions !== false) {
|
|
100
|
+
plugins.push("removeDimensions");
|
|
101
|
+
}
|
|
102
|
+
return { plugins };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/utils/name.ts
|
|
106
|
+
function svgToComponentName(filename) {
|
|
107
|
+
let baseName = filename.replace(/\.svg$/i, "");
|
|
108
|
+
baseName = processComplexFilename(baseName);
|
|
109
|
+
return pascalCase(baseName);
|
|
110
|
+
}
|
|
111
|
+
function processComplexFilename(filename) {
|
|
112
|
+
let processed = filename;
|
|
113
|
+
const simpleMatch = processed.match(/^([^,]+),\s*Type=([^,]+)/i);
|
|
114
|
+
if (simpleMatch) {
|
|
115
|
+
processed = `${simpleMatch[1]} ${simpleMatch[2]}`;
|
|
116
|
+
return processed;
|
|
117
|
+
}
|
|
118
|
+
const sizeMatch = processed.match(/Size=(\w+)/i);
|
|
119
|
+
const colorMatch = processed.match(/Color=(\w+)/i);
|
|
120
|
+
const typeMatch = processed.match(/Type=(\w+)/i);
|
|
121
|
+
if (sizeMatch || colorMatch || typeMatch) {
|
|
122
|
+
const parts = [];
|
|
123
|
+
if (typeMatch)
|
|
124
|
+
parts.push(typeMatch[1]);
|
|
125
|
+
if (colorMatch)
|
|
126
|
+
parts.push(colorMatch[1]);
|
|
127
|
+
if (sizeMatch)
|
|
128
|
+
parts.push(sizeMatch[1]);
|
|
129
|
+
if (parts.length > 0) {
|
|
130
|
+
processed = parts.join(" ");
|
|
131
|
+
return processed;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
processed = processed.replace(/\b\w+=\w+\b/g, "").replace(/,\s*/g, " ").replace(/[=]/g, " ").replace(/\s+/g, " ").trim();
|
|
135
|
+
if (!processed || processed.length < 2) {
|
|
136
|
+
processed = filename;
|
|
137
|
+
}
|
|
138
|
+
return processed;
|
|
139
|
+
}
|
|
140
|
+
function sanitizeComponentName(name) {
|
|
141
|
+
return pascalCase(name.replace(/[^a-zA-Z0-9]/g, " "));
|
|
142
|
+
}
|
|
143
|
+
function pascalCase(str) {
|
|
144
|
+
return str.replace(/[^a-zA-Z0-9\s-_]/g, " ").split(/[\s-_]+/).filter((word) => word.length > 0).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
145
|
+
}
|
|
146
|
+
function formatComponentName(name, prefix, suffix) {
|
|
147
|
+
const prefixPart = prefix ? pascalCase(prefix) : "";
|
|
148
|
+
const suffixPart = suffix ? pascalCase(suffix) : "";
|
|
149
|
+
const baseName = pascalCase(name);
|
|
150
|
+
return `${prefixPart}${baseName}${suffixPart}`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/utils/files.ts
|
|
154
|
+
var import_promises = require("fs/promises");
|
|
155
|
+
var import_path = require("path");
|
|
156
|
+
var import_fs = require("fs");
|
|
157
|
+
async function readSvgFile(filePath) {
|
|
158
|
+
try {
|
|
159
|
+
const content = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
160
|
+
return content;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
throw new Error(`Failed to read SVG file: ${filePath}. ${error}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function writeSvgFile(filePath, content) {
|
|
166
|
+
try {
|
|
167
|
+
await ensureDirectoryExists((0, import_path.dirname)(filePath));
|
|
168
|
+
await (0, import_promises.writeFile)(filePath, content, "utf-8");
|
|
169
|
+
} catch (error) {
|
|
170
|
+
throw new Error(`Failed to write SVG file: ${filePath}. ${error}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function writeComponentFile(filePath, content) {
|
|
174
|
+
try {
|
|
175
|
+
await ensureDirectoryExists((0, import_path.dirname)(filePath));
|
|
176
|
+
await (0, import_promises.writeFile)(filePath, content, "utf-8");
|
|
177
|
+
} catch (error) {
|
|
178
|
+
throw new Error(`Failed to write component file: ${filePath}. ${error}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async function readSvgDirectory(dirPath, recursive = false) {
|
|
182
|
+
try {
|
|
183
|
+
const files = await (0, import_promises.readdir)(dirPath);
|
|
184
|
+
const svgFiles = [];
|
|
185
|
+
for (const file of files) {
|
|
186
|
+
const filePath = (0, import_path.join)(dirPath, file);
|
|
187
|
+
const fileStat = await (0, import_promises.stat)(filePath);
|
|
188
|
+
if (fileStat.isDirectory() && recursive) {
|
|
189
|
+
const nestedFiles = await readSvgDirectory(filePath, recursive);
|
|
190
|
+
svgFiles.push(...nestedFiles);
|
|
191
|
+
} else if (fileStat.isFile() && (0, import_path.extname)(file).toLowerCase() === ".svg") {
|
|
192
|
+
svgFiles.push(filePath);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return svgFiles;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw new Error(`Failed to read directory: ${dirPath}. ${error}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function ensureDirectoryExists(dirPath) {
|
|
201
|
+
if (!(0, import_fs.existsSync)(dirPath)) {
|
|
202
|
+
await (0, import_promises.mkdir)(dirPath, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function getFileExtension(framework, typescript = true) {
|
|
206
|
+
if (framework === "react") {
|
|
207
|
+
return typescript ? ".tsx" : ".jsx";
|
|
208
|
+
} else {
|
|
209
|
+
return typescript ? ".vue" : ".vue";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function getComponentFilename(_svgFilename, componentName, extension) {
|
|
213
|
+
return `${componentName}${extension}`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// src/converters/react.ts
|
|
217
|
+
async function convertToReact(svgContent, options = {}) {
|
|
218
|
+
const {
|
|
219
|
+
name,
|
|
220
|
+
prefix,
|
|
221
|
+
suffix,
|
|
222
|
+
optimize: optimize2 = true,
|
|
223
|
+
typescript = true,
|
|
224
|
+
memo = true,
|
|
225
|
+
ref = true,
|
|
226
|
+
titleProp = true,
|
|
227
|
+
descProp = true
|
|
228
|
+
} = options;
|
|
229
|
+
try {
|
|
230
|
+
let processedSvg = svgContent;
|
|
231
|
+
if (optimize2) {
|
|
232
|
+
processedSvg = optimizeSvg(svgContent);
|
|
233
|
+
}
|
|
234
|
+
const baseName = name || "icon";
|
|
235
|
+
const componentName = formatComponentName(baseName, prefix, suffix);
|
|
236
|
+
const svgrOptions = {
|
|
237
|
+
typescript,
|
|
238
|
+
memo,
|
|
239
|
+
ref,
|
|
240
|
+
titleProp,
|
|
241
|
+
descProp,
|
|
242
|
+
svgProps: {
|
|
243
|
+
className: "{className}"
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
let result = await (0, import_core.transform)(processedSvg, svgrOptions, {
|
|
247
|
+
componentName
|
|
248
|
+
});
|
|
249
|
+
const typeImports = typescript ? `import { SVGProps } from 'react';
|
|
250
|
+
` : "";
|
|
251
|
+
const memoImport = memo ? `import { memo } from 'react';
|
|
252
|
+
` : "";
|
|
253
|
+
const refImport = ref ? `import { forwardRef } from 'react';
|
|
254
|
+
` : "";
|
|
255
|
+
const exports = `
|
|
256
|
+
export default ${componentName};
|
|
257
|
+
export { ${componentName} };`;
|
|
258
|
+
const propsType = typescript ? `SVGProps<SVGSVGElement> & { className?: string; }` : "";
|
|
259
|
+
const componentProps = typescript ? `props: ${propsType}` : "props";
|
|
260
|
+
const componentFunc = memo ? `memo(` : "";
|
|
261
|
+
const refWrapper = ref ? `forwardRef<SVGSVGElement, ${propsType}>(` : "";
|
|
262
|
+
const closingWrappers = `${ref ? ")" : ""}${memo ? ")" : ""}`;
|
|
263
|
+
result = `${typeImports}${memoImport}${refImport}
|
|
264
|
+
const ${componentName} = ${componentFunc}${refWrapper}(${componentProps}) => {
|
|
265
|
+
return ${result};
|
|
266
|
+
}${closingWrappers};
|
|
267
|
+
|
|
268
|
+
${componentName}.displayName = "${componentName}";
|
|
269
|
+
${exports}`;
|
|
270
|
+
const extension = getFileExtension("react", typescript);
|
|
271
|
+
const filename = getComponentFilename("icon.svg", componentName, extension);
|
|
272
|
+
return {
|
|
273
|
+
code: result,
|
|
274
|
+
filename,
|
|
275
|
+
componentName
|
|
276
|
+
};
|
|
277
|
+
} catch (error) {
|
|
278
|
+
throw new Error(`Failed to convert SVG to React: ${error}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/converters/vue.ts
|
|
283
|
+
function convertToVue(svgContent, options = {}) {
|
|
284
|
+
const {
|
|
285
|
+
name,
|
|
286
|
+
prefix,
|
|
287
|
+
suffix,
|
|
288
|
+
optimize: optimize2 = true,
|
|
289
|
+
typescript = true,
|
|
290
|
+
compositionApi: _compositionApi = true,
|
|
291
|
+
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
292
|
+
scriptSetup = true
|
|
293
|
+
} = options;
|
|
294
|
+
try {
|
|
295
|
+
let processedSvg = svgContent;
|
|
296
|
+
if (optimize2) {
|
|
297
|
+
processedSvg = optimizeSvg(svgContent);
|
|
298
|
+
}
|
|
299
|
+
const baseName = name || "icon";
|
|
300
|
+
const componentName = formatComponentName(baseName, prefix, suffix);
|
|
301
|
+
const cleanedSvg = processedSvg.replace(/<\?xml[^>]*\?>\s*/, "").replace(/xmlns="[^"]*"/g, "").replace(/width="[^"]*"/g, "").replace(/height="[^"]*"/g, "").replace(/<svg/, '<svg v-bind="$attrs"').replace(/class="([^"]*)"/g, 'class="$1"').replace(/currentColor/g, "currentColor");
|
|
302
|
+
const scriptTag = scriptSetup ? generateScriptSetup(typescript, componentName) : generateCompositionScript(componentName, typescript);
|
|
303
|
+
const template = `<template>
|
|
304
|
+
${cleanedSvg}
|
|
305
|
+
</template>`;
|
|
306
|
+
const style = `<style scoped>
|
|
307
|
+
/* Add component-specific styles here */
|
|
308
|
+
</style>`;
|
|
309
|
+
const vueComponent = `${scriptTag}
|
|
310
|
+
|
|
311
|
+
${template}
|
|
312
|
+
|
|
313
|
+
${style}`;
|
|
314
|
+
const extension = getFileExtension("vue", typescript);
|
|
315
|
+
const filename = getComponentFilename("icon.svg", componentName, extension);
|
|
316
|
+
return {
|
|
317
|
+
code: vueComponent,
|
|
318
|
+
filename,
|
|
319
|
+
componentName
|
|
320
|
+
};
|
|
321
|
+
} catch (error) {
|
|
322
|
+
throw new Error(`Failed to convert SVG to Vue: ${error}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function generateScriptSetup(typescript, componentName) {
|
|
326
|
+
const lang = typescript ? ' lang="ts"' : "";
|
|
327
|
+
const propsType = typescript ? `
|
|
328
|
+
interface Props {
|
|
329
|
+
class?: string;
|
|
330
|
+
style?: string | Record<string, any>;
|
|
331
|
+
}` : "";
|
|
332
|
+
const propsDefinition = typescript ? `
|
|
333
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
334
|
+
class: '',
|
|
335
|
+
style: undefined,
|
|
336
|
+
});` : `
|
|
337
|
+
const props = withDefaults(defineProps(), {
|
|
338
|
+
class: '',
|
|
339
|
+
style: undefined,
|
|
340
|
+
});`;
|
|
341
|
+
return `<script setup${lang}>${propsType}${propsDefinition}
|
|
342
|
+
|
|
343
|
+
// Component name for debugging
|
|
344
|
+
const __name = '${componentName}';
|
|
345
|
+
</script>`;
|
|
346
|
+
}
|
|
347
|
+
function generateCompositionScript(componentName, typescript) {
|
|
348
|
+
const lang = typescript ? ' lang="ts"' : "";
|
|
349
|
+
const propsType = typescript ? `
|
|
350
|
+
interface Props {
|
|
351
|
+
class?: string;
|
|
352
|
+
style?: string | Record<string, any>;
|
|
353
|
+
}` : "";
|
|
354
|
+
const exportStatement = typescript ? `
|
|
355
|
+
const ${componentName} = defineComponent({
|
|
356
|
+
name: '${componentName}',
|
|
357
|
+
props: {
|
|
358
|
+
class: {
|
|
359
|
+
type: String,
|
|
360
|
+
default: '',
|
|
361
|
+
},
|
|
362
|
+
style: {
|
|
363
|
+
type: [String, Object],
|
|
364
|
+
default: undefined,
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
setup(props: Props) {
|
|
368
|
+
return {};
|
|
369
|
+
},
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
export default ${componentName};
|
|
373
|
+
export { ${componentName} };` : `
|
|
374
|
+
const ${componentName} = defineComponent({
|
|
375
|
+
name: '${componentName}',
|
|
376
|
+
props: {
|
|
377
|
+
class: {
|
|
378
|
+
type: String,
|
|
379
|
+
default: '',
|
|
380
|
+
},
|
|
381
|
+
style: {
|
|
382
|
+
type: [String, Object],
|
|
383
|
+
default: undefined,
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
setup(props) {
|
|
387
|
+
return {};
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
export default ${componentName};
|
|
392
|
+
export { ${componentName} };`;
|
|
393
|
+
return `<script${lang}>
|
|
394
|
+
import { defineComponent } from 'vue';${propsType}${exportStatement}
|
|
395
|
+
</script>`;
|
|
396
|
+
}
|
|
397
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
398
|
+
0 && (module.exports = {
|
|
399
|
+
convertToReact,
|
|
400
|
+
convertToVue,
|
|
401
|
+
createSvgoConfig,
|
|
402
|
+
formatComponentName,
|
|
403
|
+
optimizeSvg,
|
|
404
|
+
pascalCase,
|
|
405
|
+
readSvgDirectory,
|
|
406
|
+
readSvgFile,
|
|
407
|
+
sanitizeComponentName,
|
|
408
|
+
svgToComponentName,
|
|
409
|
+
writeComponentFile,
|
|
410
|
+
writeSvgFile
|
|
411
|
+
});
|
|
412
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/converters/react.ts","../src/utils/svgo.ts","../src/utils/name.ts","../src/utils/files.ts","../src/converters/vue.ts"],"sourcesContent":["export type {\n ConversionOptions,\n ReactConversionOptions,\n VueConversionOptions,\n ConversionResult,\n BatchConversionOptions,\n BatchConversionResult,\n ConversionError,\n Framework,\n CliOptions,\n} from './types/index.js';\n\nexport { convertToReact } from './converters/react.js';\nexport { convertToVue } from './converters/vue.js';\nexport { optimizeSvg, createSvgoConfig } from './utils/svgo.js';\nexport {\n readSvgFile,\n writeSvgFile,\n readSvgDirectory,\n writeComponentFile,\n} from './utils/files.js';\nexport {\n svgToComponentName,\n sanitizeComponentName,\n pascalCase,\n formatComponentName,\n} from './utils/name.js';\n","import { transform } from '@svgr/core';\nimport { ReactConversionOptions, ConversionResult } from '../types/index.js';\nimport { optimizeSvg } from '../utils/svgo.js';\nimport { formatComponentName } from '../utils/name.js';\nimport { getFileExtension, getComponentFilename } from '../utils/files.js';\n\n/**\n * Convert SVG to React component\n * @param svgContent - SVG content string\n * @param options - Conversion options\n * @returns Conversion result with React component code\n */\nexport async function convertToReact(\n svgContent: string,\n options: ReactConversionOptions = {}\n): Promise<ConversionResult> {\n const {\n name,\n prefix,\n suffix,\n optimize = true,\n typescript = true,\n memo = true,\n ref = true,\n titleProp = true,\n descProp = true,\n } = options;\n\n try {\n // Optimize SVG if requested\n let processedSvg = svgContent;\n if (optimize) {\n processedSvg = optimizeSvg(svgContent);\n }\n\n // Generate component name\n const baseName = name || 'icon';\n const componentName = formatComponentName(baseName, prefix, suffix);\n\n // SVGR transformation options\n const svgrOptions = {\n typescript,\n memo,\n ref,\n titleProp,\n descProp,\n svgProps: {\n className: '{className}',\n },\n };\n\n // Transform SVG to React component\n let result = await transform(processedSvg, svgrOptions, {\n componentName,\n });\n\n // Add proper exports to the result\n const typeImports = typescript ? `import { SVGProps } from 'react';\\n` : '';\n\n const memoImport = memo ? `import { memo } from 'react';\\n` : '';\n const refImport = ref ? `import { forwardRef } from 'react';\\n` : '';\n\n const exports = `\\nexport default ${componentName};\\nexport { ${componentName} };`;\n\n // Wrap the SVGR result with proper component structure\n const propsType = typescript\n ? `SVGProps<SVGSVGElement> & { className?: string; }`\n : '';\n\n const componentProps = typescript ? `props: ${propsType}` : 'props';\n\n const componentFunc = memo ? `memo(` : '';\n const refWrapper = ref ? `forwardRef<SVGSVGElement, ${propsType}>(` : '';\n const closingWrappers = `${ref ? ')' : ''}${memo ? ')' : ''}`;\n\n result = `${typeImports}${memoImport}${refImport}\nconst ${componentName} = ${componentFunc}${refWrapper}(${componentProps}) => {\n return ${result};\n}${closingWrappers};\n\n${componentName}.displayName = \"${componentName}\";\n${exports}`;\n\n // Generate filename\n const extension = getFileExtension('react', typescript);\n const filename = getComponentFilename('icon.svg', componentName, extension);\n\n return {\n code: result,\n filename,\n componentName,\n };\n } catch (error) {\n throw new Error(`Failed to convert SVG to React: ${error}`);\n }\n}\n","import { optimize, Config } from 'svgo';\n\n/**\n * Default SVGO configuration for optimization\n */\nconst defaultConfig: Config = {\n plugins: [\n {\n name: 'preset-default',\n params: {\n overrides: {\n removeViewBox: false,\n removeTitle: false,\n removeDesc: false,\n removeUselessStrokeAndFill: false,\n convertColors: {\n currentColor: true,\n names2hex: true,\n rgb2hex: true,\n shorthex: true, // cspell:disable-line\n shortname: true,\n },\n },\n },\n },\n 'removeDimensions',\n 'cleanupNumericValues',\n ],\n};\n\n/**\n * Optimize SVG content using SVGO\n * @param svgContent - SVG content to optimize\n * @param config - Optional SVGO configuration\n * @returns Optimized SVG content\n */\nexport function optimizeSvg(\n svgContent: string,\n config: Config = defaultConfig\n): string {\n try {\n const result = optimize(svgContent, config);\n return result.data;\n } catch (error) {\n throw new Error(`Failed to optimize SVG: ${error}`);\n }\n}\n\n/**\n * Create custom SVGO configuration\n * @param options - Configuration options\n * @returns SVGO configuration\n */\nexport function createSvgoConfig(options: {\n removeViewBox?: boolean;\n removeDimensions?: boolean;\n removeTitle?: boolean;\n removeDesc?: boolean;\n preserveAspectRatio?: boolean;\n preserveColors?: boolean;\n preserveClasses?: boolean;\n}): Config {\n const plugins = [\n {\n name: 'preset-default',\n params: {\n overrides: {\n removeViewBox: !options.removeViewBox,\n removeTitle: !options.removeTitle,\n removeDesc: !options.removeDesc,\n removeUselessStrokeAndFill: !options.preserveClasses,\n convertColors: options.preserveColors\n ? false\n : {\n currentColor: true,\n names2hex: true,\n rgb2hex: true,\n shorthex: true, // cspell:disable-line\n shortname: true,\n },\n },\n },\n },\n 'cleanupNumericValues',\n ];\n\n if (options.removeDimensions !== false) {\n plugins.push('removeDimensions');\n }\n\n return { plugins: plugins as Config['plugins'] };\n}\n","/**\n * Convert SVG filename to a valid React component name\n * @param filename - The SVG filename\n * @returns PascalCase component name\n */\nexport function svgToComponentName(filename: string): string {\n // Remove file extension\n let baseName = filename.replace(/\\.svg$/i, '');\n\n // Handle complex filenames with metadata\n baseName = processComplexFilename(baseName);\n\n // Convert to PascalCase\n return pascalCase(baseName);\n}\n\n/**\n * Process complex filenames with metadata and special characters\n * @param filename - The filename to process\n * @returns Cleaned filename\n */\nfunction processComplexFilename(filename: string): string {\n // Handle files with metadata like \"User Profile Avatar, Type=Solid\" or \"Size=xl, Color=Brand, Type=Glass\"\n\n let processed = filename;\n\n // Handle simple patterns like \"User Profile Avatar, Type=Solid\" first\n const simpleMatch = processed.match(/^([^,]+),\\s*Type=([^,]+)/i);\n if (simpleMatch) {\n processed = `${simpleMatch[1]} ${simpleMatch[2]}`;\n return processed;\n }\n\n // Check for metadata patterns\n const sizeMatch = processed.match(/Size=(\\w+)/i);\n const colorMatch = processed.match(/Color=(\\w+)/i);\n const typeMatch = processed.match(/Type=(\\w+)/i);\n\n // If it has metadata, construct a meaningful name\n if (sizeMatch || colorMatch || typeMatch) {\n const parts = [];\n if (typeMatch) parts.push(typeMatch[1]);\n if (colorMatch) parts.push(colorMatch[1]);\n if (sizeMatch) parts.push(sizeMatch[1]);\n\n if (parts.length > 0) {\n processed = parts.join(' ');\n return processed;\n }\n }\n\n // If no metadata patterns found, just clean up the filename\n processed = processed\n .replace(/\\b\\w+=\\w+\\b/g, '') // Remove key=value patterns\n .replace(/,\\s*/g, ' ') // Replace commas with spaces\n .replace(/[=]/g, ' ') // Replace equals with spaces\n .replace(/\\s+/g, ' ') // Normalize multiple spaces\n .trim();\n\n // If the result is empty or too short, use original filename as fallback\n if (!processed || processed.length < 2) {\n processed = filename;\n }\n\n return processed;\n}\n\n/**\n * Sanitize component name to ensure it's valid\n * @param name - The component name to sanitize\n * @returns Sanitized component name\n */\nexport function sanitizeComponentName(name: string): string {\n // Remove invalid characters and convert to PascalCase\n return pascalCase(name.replace(/[^a-zA-Z0-9]/g, ' '));\n}\n\n/**\n * Convert a string to PascalCase\n * @param str - The string to convert\n * @returns PascalCase string\n */\nexport function pascalCase(str: string): string {\n return str\n .replace(/[^a-zA-Z0-9\\s-_]/g, ' ') // Remove any symbols, keep spaces, hyphens, underscores\n .split(/[\\s-_]+/) // Split on spaces, hyphens, underscores\n .filter(word => word.length > 0) // Remove empty strings\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n/**\n * Add prefix/suffix to component name\n * @param name - Base component name\n * @param prefix - Optional prefix\n * @param suffix - Optional suffix\n * @returns Component name with prefix/suffix\n */\nexport function formatComponentName(\n name: string,\n prefix?: string,\n suffix?: string\n): string {\n const prefixPart = prefix ? pascalCase(prefix) : '';\n const suffixPart = suffix ? pascalCase(suffix) : '';\n const baseName = pascalCase(name);\n\n return `${prefixPart}${baseName}${suffixPart}`;\n}\n","import { readFile, writeFile, readdir, stat, mkdir } from 'fs/promises';\nimport { join, dirname, extname } from 'path';\nimport { existsSync } from 'fs';\n\n/**\n * Read SVG file content\n * @param filePath - Path to the SVG file\n * @returns SVG content as string\n */\nexport async function readSvgFile(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf-8');\n return content;\n } catch (error) {\n throw new Error(`Failed to read SVG file: ${filePath}. ${error}`);\n }\n}\n\n/**\n * Write SVG file content\n * @param filePath - Path to write the SVG file\n * @param content - SVG content\n */\nexport async function writeSvgFile(\n filePath: string,\n content: string\n): Promise<void> {\n try {\n await ensureDirectoryExists(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`Failed to write SVG file: ${filePath}. ${error}`);\n }\n}\n\n/**\n * Write component file content\n * @param filePath - Path to write the component file\n * @param content - Component content\n */\nexport async function writeComponentFile(\n filePath: string,\n content: string\n): Promise<void> {\n try {\n await ensureDirectoryExists(dirname(filePath));\n await writeFile(filePath, content, 'utf-8');\n } catch (error) {\n throw new Error(`Failed to write component file: ${filePath}. ${error}`);\n }\n}\n\n/**\n * Read all SVG files from a directory\n * @param dirPath - Directory path\n * @param recursive - Whether to read recursively\n * @returns Array of SVG file paths\n */\nexport async function readSvgDirectory(\n dirPath: string,\n recursive = false\n): Promise<string[]> {\n try {\n const files = await readdir(dirPath);\n const svgFiles: string[] = [];\n\n for (const file of files) {\n const filePath = join(dirPath, file);\n const fileStat = await stat(filePath);\n\n if (fileStat.isDirectory() && recursive) {\n const nestedFiles = await readSvgDirectory(filePath, recursive);\n svgFiles.push(...nestedFiles);\n } else if (fileStat.isFile() && extname(file).toLowerCase() === '.svg') {\n svgFiles.push(filePath);\n }\n }\n\n return svgFiles;\n } catch (error) {\n throw new Error(`Failed to read directory: ${dirPath}. ${error}`);\n }\n}\n\n/**\n * Ensure directory exists, create if not\n * @param dirPath - Directory path\n */\nexport async function ensureDirectoryExists(dirPath: string): Promise<void> {\n if (!existsSync(dirPath)) {\n await mkdir(dirPath, { recursive: true });\n }\n}\n\n/**\n * Get file extension for framework\n * @param framework - Target framework\n * @param typescript - Whether to use TypeScript\n * @returns File extension\n */\nexport function getFileExtension(\n framework: 'react' | 'vue',\n typescript = true\n): string {\n if (framework === 'react') {\n return typescript ? '.tsx' : '.jsx';\n } else {\n return typescript ? '.vue' : '.vue';\n }\n}\n\n/**\n * Get component filename from SVG filename\n * @param svgFilename - SVG filename\n * @param componentName - Component name\n * @param extension - File extension\n * @returns Component filename\n */\nexport function getComponentFilename(\n _svgFilename: string,\n componentName: string,\n extension: string\n): string {\n return `${componentName}${extension}`;\n}\n","import { VueConversionOptions, ConversionResult } from '../types/index.js';\nimport { optimizeSvg } from '../utils/svgo.js';\nimport { formatComponentName } from '../utils/name.js';\nimport { getFileExtension, getComponentFilename } from '../utils/files.js';\n\n/**\n * Convert SVG to Vue 3 component\n * @param svgContent - SVG content string\n * @param options - Conversion options\n * @returns Conversion result with Vue component code\n */\nexport function convertToVue(\n svgContent: string,\n options: VueConversionOptions = {}\n): ConversionResult {\n const {\n name,\n prefix,\n suffix,\n optimize = true,\n typescript = true,\n compositionApi: _compositionApi = true, // eslint-disable-line @typescript-eslint/no-unused-vars\n scriptSetup = true,\n } = options;\n\n try {\n // Optimize SVG if requested\n let processedSvg = svgContent;\n if (optimize) {\n processedSvg = optimizeSvg(svgContent);\n }\n\n // Generate component name\n const baseName = name || 'icon';\n const componentName = formatComponentName(baseName, prefix, suffix);\n\n // Clean up SVG - remove XML declaration and add props binding\n const cleanedSvg = processedSvg\n .replace(/<\\?xml[^>]*\\?>\\s*/, '')\n .replace(/xmlns=\"[^\"]*\"/g, '')\n .replace(/width=\"[^\"]*\"/g, '')\n .replace(/height=\"[^\"]*\"/g, '')\n .replace(/<svg/, '<svg v-bind=\"$attrs\"')\n .replace(/class=\"([^\"]*)\"/g, 'class=\"$1\"') // Keep class as is, don't convert to :class\n .replace(/currentColor/g, 'currentColor');\n\n // Generate Vue SFC\n const scriptTag = scriptSetup\n ? generateScriptSetup(typescript, componentName)\n : generateCompositionScript(componentName, typescript);\n\n const template = `<template>\n ${cleanedSvg}\n</template>`;\n\n const style = `<style scoped>\n/* Add component-specific styles here */\n</style>`;\n\n const vueComponent = `${scriptTag}\n\n${template}\n\n${style}`;\n\n // Generate filename\n const extension = getFileExtension('vue', typescript);\n const filename = getComponentFilename('icon.svg', componentName, extension);\n\n return {\n code: vueComponent,\n filename,\n componentName,\n };\n } catch (error) {\n throw new Error(`Failed to convert SVG to Vue: ${error}`);\n }\n}\n\n/**\n * Generate script setup block for Vue 3\n */\nfunction generateScriptSetup(\n typescript: boolean,\n componentName: string\n): string {\n const lang = typescript ? ' lang=\"ts\"' : '';\n const propsType = typescript\n ? `\ninterface Props {\n class?: string;\n style?: string | Record<string, any>;\n}`\n : '';\n\n const propsDefinition = typescript\n ? `\nconst props = withDefaults(defineProps<Props>(), {\n class: '',\n style: undefined,\n});`\n : `\nconst props = withDefaults(defineProps(), {\n class: '',\n style: undefined,\n});`;\n\n return `<script setup${lang}>${propsType}${propsDefinition}\n\n// Component name for debugging\nconst __name = '${componentName}';\n</script>`;\n}\n\n/**\n * Generate composition API script for Vue 3\n */\nfunction generateCompositionScript(\n componentName: string,\n typescript: boolean\n): string {\n const lang = typescript ? ' lang=\"ts\"' : '';\n const propsType = typescript\n ? `\ninterface Props {\n class?: string;\n style?: string | Record<string, any>;\n}`\n : '';\n\n const exportStatement = typescript\n ? `\nconst ${componentName} = defineComponent({\n name: '${componentName}',\n props: {\n class: {\n type: String,\n default: '',\n },\n style: {\n type: [String, Object],\n default: undefined,\n },\n },\n setup(props: Props) {\n return {};\n },\n});\n\nexport default ${componentName};\nexport { ${componentName} };`\n : `\nconst ${componentName} = defineComponent({\n name: '${componentName}',\n props: {\n class: {\n type: String,\n default: '',\n },\n style: {\n type: [String, Object],\n default: undefined,\n },\n },\n setup(props) {\n return {};\n },\n});\n\nexport default ${componentName};\nexport { ${componentName} };`;\n\n return `<script${lang}>\nimport { defineComponent } from 'vue';${propsType}${exportStatement}\n</script>`;\n}\n"],"mappings":"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","names":["optimize","optimize"]}
|