svgfusion 1.0.0-beta.2 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.mts +1 -2
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +91 -2
- package/dist/cli.mjs +89 -1
- package/dist/index.js +51 -362
- package/dist/index.mjs +39 -325
- package/package.json +1 -1
- package/dist/cli.js.map +0 -1
- package/dist/cli.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/cli.d.mts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { }
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { }
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
CHANGED
|
@@ -1,2 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var commander = require('commander');
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var fs = require('fs');
|
|
8
|
+
var core = require('@svgr/core');
|
|
9
|
+
var svgo = require('svgo');
|
|
10
|
+
var url = require('url');
|
|
11
|
+
|
|
12
|
+
var A=()=>typeof document>"u"?new URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href,u=A();async function R(e){try{return await promises.readFile(e,"utf-8")}catch(t){throw new Error(`Failed to read SVG file: ${e}. ${t}`)}}async function T(e,t){try{await H(path.dirname(e)),await promises.writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write component file: ${e}. ${r}`)}}async function x(e,t=!1){try{let r=await promises.readdir(e),n=[];for(let s of r){let i=path.join(e,s),o=await promises.stat(i);if(o.isDirectory()&&t){let p=await x(i,t);n.push(...p);}else o.isFile()&&path.extname(s).toLowerCase()===".svg"&&n.push(i);}return n}catch(r){throw new Error(`Failed to read directory: ${e}. ${r}`)}}async function H(e){fs.existsSync(e)||await promises.mkdir(e,{recursive:!0});}function d(e,t=!0){return e==="react"?t?".tsx":".jsx":".vue"}function w(e,t,r){return `${t}${r}`}var Q={plugins:[{name:"preset-default",params:{overrides:{removeViewBox:!1,removeTitle:!1,removeDesc:!1,removeUselessStrokeAndFill:!1,convertColors:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"removeDimensions","cleanupNumericValues"]};function f(e,t=Q){try{return svgo.optimize(e,t).data}catch(r){throw new Error(`Failed to optimize SVG: ${r}`)}}function C(e){return e.replace(/[^a-zA-Z0-9\s-_]/g," ").split(/[\s-_]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function $(e,t,r){let n=t?C(t):"",s=r?C(r):"",i=C(e);return `${n}${i}${s}`}async function z(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,memo:p=!0,ref:m=!0,titleProp:l=!0,descProp:g=!0}=t;try{let a=e;i&&(a=f(e));let c=$(r||"icon",n,s),v=await core.transform(a,{typescript:o,memo:p,ref:m,titleProp:l,descProp:g,svgProps:{className:"{className}"}},{componentName:c}),h=o?`import { SVGProps } from 'react';
|
|
13
|
+
`:"",y=p?`import { memo } from 'react';
|
|
14
|
+
`:"",S=m?`import { forwardRef } from 'react';
|
|
15
|
+
`:"",D=`
|
|
16
|
+
export default ${c};
|
|
17
|
+
export { ${c} };`,G=o?"SVGProps<SVGSVGElement> & { className?: string; }":"",N=o?`props: ${G}`:"props",k=p?"memo(":"",_=m?`forwardRef<SVGSVGElement, ${G}>(`:"";v=`${h}${y}${S}
|
|
18
|
+
const ${c} = ${k}${_}(${N}) => {
|
|
19
|
+
return ${v};
|
|
20
|
+
}${`${m?")":""}${p?")":""}`};
|
|
21
|
+
|
|
22
|
+
${c}.displayName = "${c}";
|
|
23
|
+
${D}`;let O=d("react",o),j=w("icon.svg",c,O);return {code:v,filename:j,componentName:c}}catch(a){throw new Error(`Failed to convert SVG to React: ${a}`)}}function E(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,compositionApi:p=!0,scriptSetup:m=!0}=t;try{let l=e;i&&(l=f(e));let a=$(r||"icon",n,s),F=l.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"),c=m?Y(o,a):ee(a,o),b=`<template>
|
|
24
|
+
${F}
|
|
25
|
+
</template>`,h=`${c}
|
|
26
|
+
|
|
27
|
+
${b}
|
|
28
|
+
|
|
29
|
+
<style scoped>
|
|
30
|
+
/* Add component-specific styles here */
|
|
31
|
+
</style>`,y=d("vue",o),S=w("icon.svg",a,y);return {code:h,filename:S,componentName:a}}catch(l){throw new Error(`Failed to convert SVG to Vue: ${l}`)}}function Y(e,t){return `<script setup${e?' lang="ts"':""}>${e?`
|
|
32
|
+
interface Props {
|
|
33
|
+
class?: string;
|
|
34
|
+
style?: string | Record<string, any>;
|
|
35
|
+
}`:""}${e?`
|
|
36
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
37
|
+
class: '',
|
|
38
|
+
style: undefined,
|
|
39
|
+
});`:`
|
|
40
|
+
const props = withDefaults(defineProps(), {
|
|
41
|
+
class: '',
|
|
42
|
+
style: undefined,
|
|
43
|
+
});`}
|
|
44
|
+
|
|
45
|
+
// Component name for debugging
|
|
46
|
+
const __name = '${t}';
|
|
47
|
+
</script>`}function ee(e,t){let r=t?' lang="ts"':"",n=t?`
|
|
48
|
+
interface Props {
|
|
49
|
+
class?: string;
|
|
50
|
+
style?: string | Record<string, any>;
|
|
51
|
+
}`:"",s=t?`
|
|
52
|
+
const ${e} = defineComponent({
|
|
53
|
+
name: '${e}',
|
|
54
|
+
props: {
|
|
55
|
+
class: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: '',
|
|
58
|
+
},
|
|
59
|
+
style: {
|
|
60
|
+
type: [String, Object],
|
|
61
|
+
default: undefined,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
setup(props: Props) {
|
|
65
|
+
return {};
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export default ${e};
|
|
70
|
+
export { ${e} };`:`
|
|
71
|
+
const ${e} = defineComponent({
|
|
72
|
+
name: '${e}',
|
|
73
|
+
props: {
|
|
74
|
+
class: {
|
|
75
|
+
type: String,
|
|
76
|
+
default: '',
|
|
77
|
+
},
|
|
78
|
+
style: {
|
|
79
|
+
type: [String, Object],
|
|
80
|
+
default: undefined,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
setup(props) {
|
|
84
|
+
return {};
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export default ${e};
|
|
89
|
+
export { ${e} };`;return `<script${r}>
|
|
90
|
+
import { defineComponent } from 'vue';${n}${s}
|
|
91
|
+
</script>`}var se=url.fileURLToPath(u),ie=path.dirname(se),ae=JSON.parse(fs.readFileSync(path.join(ie,"..","package.json"),"utf-8")),V=new commander.Command;V.name("svgfusion").description("Transform SVG files into production-ready React and Vue 3 components").version(ae.version);V.command("convert").description("Convert SVG files to React or Vue components").argument("<input>","Input SVG file or directory").option("-o, --output <output>","Output directory","./components").option("-f, --framework <framework>","Target framework (react|vue)","react").option("-t, --typescript","Generate TypeScript files",!1).option("--no-optimize","Skip SVG optimization").action(async(e,t)=>{console.log("\u{1F504} Processing SVG files...");try{let{framework:r,output:n,typescript:s,optimize:i}=t;if(r!=="react"&&r!=="vue")throw new Error('Framework must be either "react" or "vue"');let o=await x(e);if(o.length===0)throw new Error("No SVG files found in the input path");console.log(`\u{1F504} Converting ${o.length} SVG file(s)...`);for(let p of o){let m=await R(p),l=i?f(m):m,g=r==="react"?await z(l,{typescript:s}):E(l,{typescript:s}),a=path.join(n,g.filename);await T(a,g.code);}console.log(`\u2705 Successfully converted ${o.length} SVG file(s) to ${r} components`);}catch(r){console.error(`\u274C Error: ${r instanceof Error?r.message:"Unknown error"}`),process.exit(1);}});V.parse();
|
package/dist/cli.mjs
CHANGED
|
@@ -1 +1,89 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { readFile, writeFile, readdir, stat, mkdir } from 'fs/promises';
|
|
4
|
+
import { dirname, join, extname } from 'path';
|
|
5
|
+
import { readFileSync, existsSync } from 'fs';
|
|
6
|
+
import { transform } from '@svgr/core';
|
|
7
|
+
import { optimize } from 'svgo';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
|
|
10
|
+
async function z(e){try{return await readFile(e,"utf-8")}catch(t){throw new Error(`Failed to read SVG file: ${e}. ${t}`)}}async function E(e,t){try{await H(dirname(e)),await writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write component file: ${e}. ${r}`)}}async function C(e,t=!1){try{let r=await readdir(e),n=[];for(let s of r){let i=join(e,s),o=await stat(i);if(o.isDirectory()&&t){let p=await C(i,t);n.push(...p);}else o.isFile()&&extname(s).toLowerCase()===".svg"&&n.push(i);}return n}catch(r){throw new Error(`Failed to read directory: ${e}. ${r}`)}}async function H(e){existsSync(e)||await mkdir(e,{recursive:!0});}function $(e,t=!0){return e==="react"?t?".tsx":".jsx":".vue"}function w(e,t,r){return `${t}${r}`}var Q={plugins:[{name:"preset-default",params:{overrides:{removeViewBox:!1,removeTitle:!1,removeDesc:!1,removeUselessStrokeAndFill:!1,convertColors:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"removeDimensions","cleanupNumericValues"]};function u(e,t=Q){try{return optimize(e,t).data}catch(r){throw new Error(`Failed to optimize SVG: ${r}`)}}function V(e){return e.replace(/[^a-zA-Z0-9\s-_]/g," ").split(/[\s-_]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function h(e,t,r){let n=t?V(t):"",s=r?V(r):"",i=V(e);return `${n}${i}${s}`}async function P(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,memo:p=!0,ref:m=!0,titleProp:l=!0,descProp:f=!0}=t;try{let a=e;i&&(a=u(e));let c=h(r||"icon",n,s),g=await transform(a,{typescript:o,memo:p,ref:m,titleProp:l,descProp:f,svgProps:{className:"{className}"}},{componentName:c}),y=o?`import { SVGProps } from 'react';
|
|
11
|
+
`:"",S=p?`import { memo } from 'react';
|
|
12
|
+
`:"",x=m?`import { forwardRef } from 'react';
|
|
13
|
+
`:"",N=`
|
|
14
|
+
export default ${c};
|
|
15
|
+
export { ${c} };`,T=o?"SVGProps<SVGSVGElement> & { className?: string; }":"",k=o?`props: ${T}`:"props",O=p?"memo(":"",_=m?`forwardRef<SVGSVGElement, ${T}>(`:"";g=`${y}${S}${x}
|
|
16
|
+
const ${c} = ${O}${_}(${k}) => {
|
|
17
|
+
return ${g};
|
|
18
|
+
}${`${m?")":""}${p?")":""}`};
|
|
19
|
+
|
|
20
|
+
${c}.displayName = "${c}";
|
|
21
|
+
${N}`;let A=$("react",o),j=w("icon.svg",c,A);return {code:g,filename:j,componentName:c}}catch(a){throw new Error(`Failed to convert SVG to React: ${a}`)}}function R(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,compositionApi:p=!0,scriptSetup:m=!0}=t;try{let l=e;i&&(l=u(e));let a=h(r||"icon",n,s),b=l.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"),c=m?Y(o,a):ee(a,o),G=`<template>
|
|
22
|
+
${b}
|
|
23
|
+
</template>`,y=`${c}
|
|
24
|
+
|
|
25
|
+
${G}
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
/* Add component-specific styles here */
|
|
29
|
+
</style>`,S=$("vue",o),x=w("icon.svg",a,S);return {code:y,filename:x,componentName:a}}catch(l){throw new Error(`Failed to convert SVG to Vue: ${l}`)}}function Y(e,t){return `<script setup${e?' lang="ts"':""}>${e?`
|
|
30
|
+
interface Props {
|
|
31
|
+
class?: string;
|
|
32
|
+
style?: string | Record<string, any>;
|
|
33
|
+
}`:""}${e?`
|
|
34
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
35
|
+
class: '',
|
|
36
|
+
style: undefined,
|
|
37
|
+
});`:`
|
|
38
|
+
const props = withDefaults(defineProps(), {
|
|
39
|
+
class: '',
|
|
40
|
+
style: undefined,
|
|
41
|
+
});`}
|
|
42
|
+
|
|
43
|
+
// Component name for debugging
|
|
44
|
+
const __name = '${t}';
|
|
45
|
+
</script>`}function ee(e,t){let r=t?' lang="ts"':"",n=t?`
|
|
46
|
+
interface Props {
|
|
47
|
+
class?: string;
|
|
48
|
+
style?: string | Record<string, any>;
|
|
49
|
+
}`:"",s=t?`
|
|
50
|
+
const ${e} = defineComponent({
|
|
51
|
+
name: '${e}',
|
|
52
|
+
props: {
|
|
53
|
+
class: {
|
|
54
|
+
type: String,
|
|
55
|
+
default: '',
|
|
56
|
+
},
|
|
57
|
+
style: {
|
|
58
|
+
type: [String, Object],
|
|
59
|
+
default: undefined,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
setup(props: Props) {
|
|
63
|
+
return {};
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export default ${e};
|
|
68
|
+
export { ${e} };`:`
|
|
69
|
+
const ${e} = defineComponent({
|
|
70
|
+
name: '${e}',
|
|
71
|
+
props: {
|
|
72
|
+
class: {
|
|
73
|
+
type: String,
|
|
74
|
+
default: '',
|
|
75
|
+
},
|
|
76
|
+
style: {
|
|
77
|
+
type: [String, Object],
|
|
78
|
+
default: undefined,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
setup(props) {
|
|
82
|
+
return {};
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export default ${e};
|
|
87
|
+
export { ${e} };`;return `<script${r}>
|
|
88
|
+
import { defineComponent } from 'vue';${n}${s}
|
|
89
|
+
</script>`}var se=fileURLToPath(import.meta.url),ie=dirname(se),ae=JSON.parse(readFileSync(join(ie,"..","package.json"),"utf-8")),F=new Command;F.name("svgfusion").description("Transform SVG files into production-ready React and Vue 3 components").version(ae.version);F.command("convert").description("Convert SVG files to React or Vue components").argument("<input>","Input SVG file or directory").option("-o, --output <output>","Output directory","./components").option("-f, --framework <framework>","Target framework (react|vue)","react").option("-t, --typescript","Generate TypeScript files",!1).option("--no-optimize","Skip SVG optimization").action(async(e,t)=>{console.log("\u{1F504} Processing SVG files...");try{let{framework:r,output:n,typescript:s,optimize:i}=t;if(r!=="react"&&r!=="vue")throw new Error('Framework must be either "react" or "vue"');let o=await C(e);if(o.length===0)throw new Error("No SVG files found in the input path");console.log(`\u{1F504} Converting ${o.length} SVG file(s)...`);for(let p of o){let m=await z(p),l=i?u(m):m,f=r==="react"?await P(l,{typescript:s}):R(l,{typescript:s}),a=join(n,f.filename);await E(a,f.code);}console.log(`\u2705 Successfully converted ${o.length} SVG file(s) to ${r} components`);}catch(r){console.error(`\u274C Error: ${r instanceof Error?r.message:"Unknown error"}`),process.exit(1);}});F.parse();
|
package/dist/index.js
CHANGED
|
@@ -1,359 +1,53 @@
|
|
|
1
|
-
|
|
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);
|
|
1
|
+
'use strict';
|
|
19
2
|
|
|
20
|
-
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
}
|
|
3
|
+
var core = require('@svgr/core');
|
|
4
|
+
var svgo = require('svgo');
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
|
+
var path = require('path');
|
|
7
|
+
var fs = require('fs');
|
|
104
8
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
}
|
|
9
|
+
var j={plugins:[{name:"preset-default",params:{overrides:{removeViewBox:!1,removeTitle:!1,removeDesc:!1,removeUselessStrokeAndFill:!1,convertColors:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"removeDimensions","cleanupNumericValues"]};function g(e,t=j){try{return svgo.optimize(e,t).data}catch(r){throw new Error(`Failed to optimize SVG: ${r}`)}}function B(e){let t=[{name:"preset-default",params:{overrides:{removeViewBox:!e.removeViewBox,removeTitle:!e.removeTitle,removeDesc:!e.removeDesc,removeUselessStrokeAndFill:!e.preserveClasses,convertColors:e.preserveColors?!1:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"cleanupNumericValues"];return e.removeDimensions!==!1&&t.push("removeDimensions"),{plugins:t}}function _(e){let t=e.replace(/\.svg$/i,"");return t=k(t),u(t)}function k(e){let t=e,r=t.match(/^([^,]+),\s*Type=([^,]+)/i);if(r)return t=`${r[1]} ${r[2]}`,t;let n=t.match(/Size=(\w+)/i),s=t.match(/Color=(\w+)/i),i=t.match(/Type=(\w+)/i);if(n||s||i){let o=[];if(i&&o.push(i[1]),s&&o.push(s[1]),n&&o.push(n[1]),o.length>0)return t=o.join(" "),t}return t=t.replace(/\b\w+=\w+\b/g,"").replace(/,\s*/g," ").replace(/[=]/g," ").replace(/\s+/g," ").trim(),(!t||t.length<2)&&(t=e),t}function M(e){return u(e.replace(/[^a-zA-Z0-9]/g," "))}function u(e){return e.replace(/[^a-zA-Z0-9\s-_]/g," ").split(/[\s-_]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function v(e,t,r){let n=t?u(t):"",s=r?u(r):"",i=u(e);return `${n}${i}${s}`}async function J(e){try{return await promises.readFile(e,"utf-8")}catch(t){throw new Error(`Failed to read SVG file: ${e}. ${t}`)}}async function K(e,t){try{await D(path.dirname(e)),await promises.writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write SVG file: ${e}. ${r}`)}}async function Q(e,t){try{await D(path.dirname(e)),await promises.writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write component file: ${e}. ${r}`)}}async function T(e,t=!1){try{let r=await promises.readdir(e),n=[];for(let s of r){let i=path.join(e,s),o=await promises.stat(i);if(o.isDirectory()&&t){let c=await T(i,t);n.push(...c);}else o.isFile()&&path.extname(s).toLowerCase()===".svg"&&n.push(i);}return n}catch(r){throw new Error(`Failed to read directory: ${e}. ${r}`)}}async function D(e){fs.existsSync(e)||await promises.mkdir(e,{recursive:!0});}function C(e,t=!0){return e==="react"?t?".tsx":".jsx":".vue"}function $(e,t,r){return `${t}${r}`}async function Y(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,memo:c=!0,ref:l=!0,titleProp:m=!0,descProp:h=!0}=t;try{let p=e;i&&(p=g(e));let a=v(r||"icon",n,s),d=await core.transform(p,{typescript:o,memo:c,ref:l,titleProp:m,descProp:h,svgProps:{className:"{className}"}},{componentName:a}),x=o?`import { SVGProps } from 'react';
|
|
10
|
+
`:"",w=c?`import { memo } from 'react';
|
|
11
|
+
`:"",y=l?`import { forwardRef } from 'react';
|
|
12
|
+
`:"",N=`
|
|
13
|
+
export default ${a};
|
|
14
|
+
export { ${a} };`,b=o?"SVGProps<SVGSVGElement> & { className?: string; }":"",z=o?`props: ${b}`:"props",E=c?"memo(":"",O=l?`forwardRef<SVGSVGElement, ${b}>(`:"";d=`${x}${w}${y}
|
|
15
|
+
const ${a} = ${E}${O}(${z}) => {
|
|
16
|
+
return ${d};
|
|
17
|
+
}${`${l?")":""}${c?")":""}`};
|
|
152
18
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
}
|
|
19
|
+
${a}.displayName = "${a}";
|
|
20
|
+
${N}`;let P=C("react",o),G=$("icon.svg",a,P);return {code:d,filename:G,componentName:a}}catch(p){throw new Error(`Failed to convert SVG to React: ${p}`)}}function ee(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,compositionApi:c=!0,scriptSetup:l=!0}=t;try{let m=e;i&&(m=g(e));let p=v(r||"icon",n,s),S=m.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"),a=l?te(o,p):re(p,o),F=`<template>
|
|
21
|
+
${S}
|
|
22
|
+
</template>`,x=`${a}
|
|
215
23
|
|
|
216
|
-
|
|
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};
|
|
24
|
+
${F}
|
|
267
25
|
|
|
268
|
-
|
|
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>
|
|
26
|
+
<style scoped>
|
|
307
27
|
/* 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 ? `
|
|
28
|
+
</style>`,w=C("vue",o),y=$("icon.svg",p,w);return {code:x,filename:y,componentName:p}}catch(m){throw new Error(`Failed to convert SVG to Vue: ${m}`)}}function te(e,t){return `<script setup${e?' lang="ts"':""}>${e?`
|
|
328
29
|
interface Props {
|
|
329
30
|
class?: string;
|
|
330
31
|
style?: string | Record<string, any>;
|
|
331
|
-
}
|
|
332
|
-
const propsDefinition = typescript ? `
|
|
32
|
+
}`:""}${e?`
|
|
333
33
|
const props = withDefaults(defineProps<Props>(), {
|
|
334
34
|
class: '',
|
|
335
35
|
style: undefined,
|
|
336
|
-
})
|
|
36
|
+
});`:`
|
|
337
37
|
const props = withDefaults(defineProps(), {
|
|
338
38
|
class: '',
|
|
339
39
|
style: undefined,
|
|
340
|
-
})
|
|
341
|
-
return `<script setup${lang}>${propsType}${propsDefinition}
|
|
40
|
+
});`}
|
|
342
41
|
|
|
343
42
|
// Component name for debugging
|
|
344
|
-
const __name = '${
|
|
345
|
-
</script
|
|
346
|
-
}
|
|
347
|
-
function generateCompositionScript(componentName, typescript) {
|
|
348
|
-
const lang = typescript ? ' lang="ts"' : "";
|
|
349
|
-
const propsType = typescript ? `
|
|
43
|
+
const __name = '${t}';
|
|
44
|
+
</script>`}function re(e,t){let r=t?' lang="ts"':"",n=t?`
|
|
350
45
|
interface Props {
|
|
351
46
|
class?: string;
|
|
352
47
|
style?: string | Record<string, any>;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
name: '${componentName}',
|
|
48
|
+
}`:"",s=t?`
|
|
49
|
+
const ${e} = defineComponent({
|
|
50
|
+
name: '${e}',
|
|
357
51
|
props: {
|
|
358
52
|
class: {
|
|
359
53
|
type: String,
|
|
@@ -369,10 +63,10 @@ const ${componentName} = defineComponent({
|
|
|
369
63
|
},
|
|
370
64
|
});
|
|
371
65
|
|
|
372
|
-
export default ${
|
|
373
|
-
export { ${
|
|
374
|
-
const ${
|
|
375
|
-
name: '${
|
|
66
|
+
export default ${e};
|
|
67
|
+
export { ${e} };`:`
|
|
68
|
+
const ${e} = defineComponent({
|
|
69
|
+
name: '${e}',
|
|
376
70
|
props: {
|
|
377
71
|
class: {
|
|
378
72
|
type: String,
|
|
@@ -388,25 +82,20 @@ const ${componentName} = defineComponent({
|
|
|
388
82
|
},
|
|
389
83
|
});
|
|
390
84
|
|
|
391
|
-
export default ${
|
|
392
|
-
export { ${
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
svgToComponentName,
|
|
409
|
-
writeComponentFile,
|
|
410
|
-
writeSvgFile
|
|
411
|
-
});
|
|
412
|
-
//# sourceMappingURL=index.js.map
|
|
85
|
+
export default ${e};
|
|
86
|
+
export { ${e} };`;return `<script${r}>
|
|
87
|
+
import { defineComponent } from 'vue';${n}${s}
|
|
88
|
+
</script>`}
|
|
89
|
+
|
|
90
|
+
exports.convertToReact = Y;
|
|
91
|
+
exports.convertToVue = ee;
|
|
92
|
+
exports.createSvgoConfig = B;
|
|
93
|
+
exports.formatComponentName = v;
|
|
94
|
+
exports.optimizeSvg = g;
|
|
95
|
+
exports.pascalCase = u;
|
|
96
|
+
exports.readSvgDirectory = T;
|
|
97
|
+
exports.readSvgFile = J;
|
|
98
|
+
exports.sanitizeComponentName = M;
|
|
99
|
+
exports.svgToComponentName = _;
|
|
100
|
+
exports.writeComponentFile = Q;
|
|
101
|
+
exports.writeSvgFile = K;
|
package/dist/index.mjs
CHANGED
|
@@ -1,322 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
import { transform } from '@svgr/core';
|
|
2
|
+
import { optimize } from 'svgo';
|
|
3
|
+
import { readFile, writeFile, readdir, stat, mkdir } from 'fs/promises';
|
|
4
|
+
import { dirname, join, extname } from 'path';
|
|
5
|
+
import { existsSync } from 'fs';
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
removeTitle: false,
|
|
14
|
-
removeDesc: false,
|
|
15
|
-
removeUselessStrokeAndFill: false,
|
|
16
|
-
convertColors: {
|
|
17
|
-
currentColor: true,
|
|
18
|
-
names2hex: true,
|
|
19
|
-
rgb2hex: true,
|
|
20
|
-
shorthex: true,
|
|
21
|
-
// cspell:disable-line
|
|
22
|
-
shortname: true
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"removeDimensions",
|
|
28
|
-
"cleanupNumericValues"
|
|
29
|
-
]
|
|
30
|
-
};
|
|
31
|
-
function optimizeSvg(svgContent, config = defaultConfig) {
|
|
32
|
-
try {
|
|
33
|
-
const result = optimize(svgContent, config);
|
|
34
|
-
return result.data;
|
|
35
|
-
} catch (error) {
|
|
36
|
-
throw new Error(`Failed to optimize SVG: ${error}`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function createSvgoConfig(options) {
|
|
40
|
-
const plugins = [
|
|
41
|
-
{
|
|
42
|
-
name: "preset-default",
|
|
43
|
-
params: {
|
|
44
|
-
overrides: {
|
|
45
|
-
removeViewBox: !options.removeViewBox,
|
|
46
|
-
removeTitle: !options.removeTitle,
|
|
47
|
-
removeDesc: !options.removeDesc,
|
|
48
|
-
removeUselessStrokeAndFill: !options.preserveClasses,
|
|
49
|
-
convertColors: options.preserveColors ? false : {
|
|
50
|
-
currentColor: true,
|
|
51
|
-
names2hex: true,
|
|
52
|
-
rgb2hex: true,
|
|
53
|
-
shorthex: true,
|
|
54
|
-
// cspell:disable-line
|
|
55
|
-
shortname: true
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
"cleanupNumericValues"
|
|
61
|
-
];
|
|
62
|
-
if (options.removeDimensions !== false) {
|
|
63
|
-
plugins.push("removeDimensions");
|
|
64
|
-
}
|
|
65
|
-
return { plugins };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/utils/name.ts
|
|
69
|
-
function svgToComponentName(filename) {
|
|
70
|
-
let baseName = filename.replace(/\.svg$/i, "");
|
|
71
|
-
baseName = processComplexFilename(baseName);
|
|
72
|
-
return pascalCase(baseName);
|
|
73
|
-
}
|
|
74
|
-
function processComplexFilename(filename) {
|
|
75
|
-
let processed = filename;
|
|
76
|
-
const simpleMatch = processed.match(/^([^,]+),\s*Type=([^,]+)/i);
|
|
77
|
-
if (simpleMatch) {
|
|
78
|
-
processed = `${simpleMatch[1]} ${simpleMatch[2]}`;
|
|
79
|
-
return processed;
|
|
80
|
-
}
|
|
81
|
-
const sizeMatch = processed.match(/Size=(\w+)/i);
|
|
82
|
-
const colorMatch = processed.match(/Color=(\w+)/i);
|
|
83
|
-
const typeMatch = processed.match(/Type=(\w+)/i);
|
|
84
|
-
if (sizeMatch || colorMatch || typeMatch) {
|
|
85
|
-
const parts = [];
|
|
86
|
-
if (typeMatch)
|
|
87
|
-
parts.push(typeMatch[1]);
|
|
88
|
-
if (colorMatch)
|
|
89
|
-
parts.push(colorMatch[1]);
|
|
90
|
-
if (sizeMatch)
|
|
91
|
-
parts.push(sizeMatch[1]);
|
|
92
|
-
if (parts.length > 0) {
|
|
93
|
-
processed = parts.join(" ");
|
|
94
|
-
return processed;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
processed = processed.replace(/\b\w+=\w+\b/g, "").replace(/,\s*/g, " ").replace(/[=]/g, " ").replace(/\s+/g, " ").trim();
|
|
98
|
-
if (!processed || processed.length < 2) {
|
|
99
|
-
processed = filename;
|
|
100
|
-
}
|
|
101
|
-
return processed;
|
|
102
|
-
}
|
|
103
|
-
function sanitizeComponentName(name) {
|
|
104
|
-
return pascalCase(name.replace(/[^a-zA-Z0-9]/g, " "));
|
|
105
|
-
}
|
|
106
|
-
function pascalCase(str) {
|
|
107
|
-
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("");
|
|
108
|
-
}
|
|
109
|
-
function formatComponentName(name, prefix, suffix) {
|
|
110
|
-
const prefixPart = prefix ? pascalCase(prefix) : "";
|
|
111
|
-
const suffixPart = suffix ? pascalCase(suffix) : "";
|
|
112
|
-
const baseName = pascalCase(name);
|
|
113
|
-
return `${prefixPart}${baseName}${suffixPart}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/utils/files.ts
|
|
117
|
-
import { readFile, writeFile, readdir, stat, mkdir } from "fs/promises";
|
|
118
|
-
import { join, dirname, extname } from "path";
|
|
119
|
-
import { existsSync } from "fs";
|
|
120
|
-
async function readSvgFile(filePath) {
|
|
121
|
-
try {
|
|
122
|
-
const content = await readFile(filePath, "utf-8");
|
|
123
|
-
return content;
|
|
124
|
-
} catch (error) {
|
|
125
|
-
throw new Error(`Failed to read SVG file: ${filePath}. ${error}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
async function writeSvgFile(filePath, content) {
|
|
129
|
-
try {
|
|
130
|
-
await ensureDirectoryExists(dirname(filePath));
|
|
131
|
-
await writeFile(filePath, content, "utf-8");
|
|
132
|
-
} catch (error) {
|
|
133
|
-
throw new Error(`Failed to write SVG file: ${filePath}. ${error}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async function writeComponentFile(filePath, content) {
|
|
137
|
-
try {
|
|
138
|
-
await ensureDirectoryExists(dirname(filePath));
|
|
139
|
-
await writeFile(filePath, content, "utf-8");
|
|
140
|
-
} catch (error) {
|
|
141
|
-
throw new Error(`Failed to write component file: ${filePath}. ${error}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
async function readSvgDirectory(dirPath, recursive = false) {
|
|
145
|
-
try {
|
|
146
|
-
const files = await readdir(dirPath);
|
|
147
|
-
const svgFiles = [];
|
|
148
|
-
for (const file of files) {
|
|
149
|
-
const filePath = join(dirPath, file);
|
|
150
|
-
const fileStat = await stat(filePath);
|
|
151
|
-
if (fileStat.isDirectory() && recursive) {
|
|
152
|
-
const nestedFiles = await readSvgDirectory(filePath, recursive);
|
|
153
|
-
svgFiles.push(...nestedFiles);
|
|
154
|
-
} else if (fileStat.isFile() && extname(file).toLowerCase() === ".svg") {
|
|
155
|
-
svgFiles.push(filePath);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return svgFiles;
|
|
159
|
-
} catch (error) {
|
|
160
|
-
throw new Error(`Failed to read directory: ${dirPath}. ${error}`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
async function ensureDirectoryExists(dirPath) {
|
|
164
|
-
if (!existsSync(dirPath)) {
|
|
165
|
-
await mkdir(dirPath, { recursive: true });
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
function getFileExtension(framework, typescript = true) {
|
|
169
|
-
if (framework === "react") {
|
|
170
|
-
return typescript ? ".tsx" : ".jsx";
|
|
171
|
-
} else {
|
|
172
|
-
return typescript ? ".vue" : ".vue";
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
function getComponentFilename(_svgFilename, componentName, extension) {
|
|
176
|
-
return `${componentName}${extension}`;
|
|
177
|
-
}
|
|
7
|
+
var B={plugins:[{name:"preset-default",params:{overrides:{removeViewBox:!1,removeTitle:!1,removeDesc:!1,removeUselessStrokeAndFill:!1,convertColors:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"removeDimensions","cleanupNumericValues"]};function v(e,t=B){try{return optimize(e,t).data}catch(r){throw new Error(`Failed to optimize SVG: ${r}`)}}function _(e){let t=[{name:"preset-default",params:{overrides:{removeViewBox:!e.removeViewBox,removeTitle:!e.removeTitle,removeDesc:!e.removeDesc,removeUselessStrokeAndFill:!e.preserveClasses,convertColors:e.preserveColors?!1:{currentColor:!0,names2hex:!0,rgb2hex:!0,shorthex:!0,shortname:!0}}}},"cleanupNumericValues"];return e.removeDimensions!==!1&&t.push("removeDimensions"),{plugins:t}}function k(e){let t=e.replace(/\.svg$/i,"");return t=M(t),u(t)}function M(e){let t=e,r=t.match(/^([^,]+),\s*Type=([^,]+)/i);if(r)return t=`${r[1]} ${r[2]}`,t;let n=t.match(/Size=(\w+)/i),s=t.match(/Color=(\w+)/i),i=t.match(/Type=(\w+)/i);if(n||s||i){let o=[];if(i&&o.push(i[1]),s&&o.push(s[1]),n&&o.push(n[1]),o.length>0)return t=o.join(" "),t}return t=t.replace(/\b\w+=\w+\b/g,"").replace(/,\s*/g," ").replace(/[=]/g," ").replace(/\s+/g," ").trim(),(!t||t.length<2)&&(t=e),t}function I(e){return u(e.replace(/[^a-zA-Z0-9]/g," "))}function u(e){return e.replace(/[^a-zA-Z0-9\s-_]/g," ").split(/[\s-_]+/).filter(t=>t.length>0).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}function d(e,t,r){let n=t?u(t):"",s=r?u(r):"",i=u(e);return `${n}${i}${s}`}async function K(e){try{return await readFile(e,"utf-8")}catch(t){throw new Error(`Failed to read SVG file: ${e}. ${t}`)}}async function Q(e,t){try{await N(dirname(e)),await writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write SVG file: ${e}. ${r}`)}}async function X(e,t){try{await N(dirname(e)),await writeFile(e,t,"utf-8");}catch(r){throw new Error(`Failed to write component file: ${e}. ${r}`)}}async function D(e,t=!1){try{let r=await readdir(e),n=[];for(let s of r){let i=join(e,s),o=await stat(i);if(o.isDirectory()&&t){let c=await D(i,t);n.push(...c);}else o.isFile()&&extname(s).toLowerCase()===".svg"&&n.push(i);}return n}catch(r){throw new Error(`Failed to read directory: ${e}. ${r}`)}}async function N(e){existsSync(e)||await mkdir(e,{recursive:!0});}function $(e,t=!0){return e==="react"?t?".tsx":".jsx":".vue"}function x(e,t,r){return `${t}${r}`}async function ee(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,memo:c=!0,ref:l=!0,titleProp:m=!0,descProp:S=!0}=t;try{let p=e;i&&(p=v(e));let a=d(r||"icon",n,s),C=await transform(p,{typescript:o,memo:c,ref:l,titleProp:m,descProp:S,svgProps:{className:"{className}"}},{componentName:a}),w=o?`import { SVGProps } from 'react';
|
|
8
|
+
`:"",y=c?`import { memo } from 'react';
|
|
9
|
+
`:"",h=l?`import { forwardRef } from 'react';
|
|
10
|
+
`:"",z=`
|
|
11
|
+
export default ${a};
|
|
12
|
+
export { ${a} };`,V=o?"SVGProps<SVGSVGElement> & { className?: string; }":"",E=o?`props: ${V}`:"props",O=c?"memo(":"",P=l?`forwardRef<SVGSVGElement, ${V}>(`:"";C=`${w}${y}${h}
|
|
13
|
+
const ${a} = ${O}${P}(${E}) => {
|
|
14
|
+
return ${C};
|
|
15
|
+
}${`${l?")":""}${c?")":""}`};
|
|
178
16
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
prefix,
|
|
184
|
-
suffix,
|
|
185
|
-
optimize: optimize2 = true,
|
|
186
|
-
typescript = true,
|
|
187
|
-
memo = true,
|
|
188
|
-
ref = true,
|
|
189
|
-
titleProp = true,
|
|
190
|
-
descProp = true
|
|
191
|
-
} = options;
|
|
192
|
-
try {
|
|
193
|
-
let processedSvg = svgContent;
|
|
194
|
-
if (optimize2) {
|
|
195
|
-
processedSvg = optimizeSvg(svgContent);
|
|
196
|
-
}
|
|
197
|
-
const baseName = name || "icon";
|
|
198
|
-
const componentName = formatComponentName(baseName, prefix, suffix);
|
|
199
|
-
const svgrOptions = {
|
|
200
|
-
typescript,
|
|
201
|
-
memo,
|
|
202
|
-
ref,
|
|
203
|
-
titleProp,
|
|
204
|
-
descProp,
|
|
205
|
-
svgProps: {
|
|
206
|
-
className: "{className}"
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
let result = await transform(processedSvg, svgrOptions, {
|
|
210
|
-
componentName
|
|
211
|
-
});
|
|
212
|
-
const typeImports = typescript ? `import { SVGProps } from 'react';
|
|
213
|
-
` : "";
|
|
214
|
-
const memoImport = memo ? `import { memo } from 'react';
|
|
215
|
-
` : "";
|
|
216
|
-
const refImport = ref ? `import { forwardRef } from 'react';
|
|
217
|
-
` : "";
|
|
218
|
-
const exports = `
|
|
219
|
-
export default ${componentName};
|
|
220
|
-
export { ${componentName} };`;
|
|
221
|
-
const propsType = typescript ? `SVGProps<SVGSVGElement> & { className?: string; }` : "";
|
|
222
|
-
const componentProps = typescript ? `props: ${propsType}` : "props";
|
|
223
|
-
const componentFunc = memo ? `memo(` : "";
|
|
224
|
-
const refWrapper = ref ? `forwardRef<SVGSVGElement, ${propsType}>(` : "";
|
|
225
|
-
const closingWrappers = `${ref ? ")" : ""}${memo ? ")" : ""}`;
|
|
226
|
-
result = `${typeImports}${memoImport}${refImport}
|
|
227
|
-
const ${componentName} = ${componentFunc}${refWrapper}(${componentProps}) => {
|
|
228
|
-
return ${result};
|
|
229
|
-
}${closingWrappers};
|
|
17
|
+
${a}.displayName = "${a}";
|
|
18
|
+
${z}`;let G=$("react",o),A=x("icon.svg",a,G);return {code:C,filename:A,componentName:a}}catch(p){throw new Error(`Failed to convert SVG to React: ${p}`)}}function te(e,t={}){let{name:r,prefix:n,suffix:s,optimize:i=!0,typescript:o=!0,compositionApi:c=!0,scriptSetup:l=!0}=t;try{let m=e;i&&(m=v(e));let p=d(r||"icon",n,s),F=m.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"),a=l?re(o,p):oe(p,o),b=`<template>
|
|
19
|
+
${F}
|
|
20
|
+
</template>`,w=`${a}
|
|
230
21
|
|
|
231
|
-
${
|
|
232
|
-
${exports}`;
|
|
233
|
-
const extension = getFileExtension("react", typescript);
|
|
234
|
-
const filename = getComponentFilename("icon.svg", componentName, extension);
|
|
235
|
-
return {
|
|
236
|
-
code: result,
|
|
237
|
-
filename,
|
|
238
|
-
componentName
|
|
239
|
-
};
|
|
240
|
-
} catch (error) {
|
|
241
|
-
throw new Error(`Failed to convert SVG to React: ${error}`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
22
|
+
${b}
|
|
244
23
|
|
|
245
|
-
|
|
246
|
-
function convertToVue(svgContent, options = {}) {
|
|
247
|
-
const {
|
|
248
|
-
name,
|
|
249
|
-
prefix,
|
|
250
|
-
suffix,
|
|
251
|
-
optimize: optimize2 = true,
|
|
252
|
-
typescript = true,
|
|
253
|
-
compositionApi: _compositionApi = true,
|
|
254
|
-
// eslint-disable-line @typescript-eslint/no-unused-vars
|
|
255
|
-
scriptSetup = true
|
|
256
|
-
} = options;
|
|
257
|
-
try {
|
|
258
|
-
let processedSvg = svgContent;
|
|
259
|
-
if (optimize2) {
|
|
260
|
-
processedSvg = optimizeSvg(svgContent);
|
|
261
|
-
}
|
|
262
|
-
const baseName = name || "icon";
|
|
263
|
-
const componentName = formatComponentName(baseName, prefix, suffix);
|
|
264
|
-
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");
|
|
265
|
-
const scriptTag = scriptSetup ? generateScriptSetup(typescript, componentName) : generateCompositionScript(componentName, typescript);
|
|
266
|
-
const template = `<template>
|
|
267
|
-
${cleanedSvg}
|
|
268
|
-
</template>`;
|
|
269
|
-
const style = `<style scoped>
|
|
24
|
+
<style scoped>
|
|
270
25
|
/* Add component-specific styles here */
|
|
271
|
-
</style
|
|
272
|
-
const vueComponent = `${scriptTag}
|
|
273
|
-
|
|
274
|
-
${template}
|
|
275
|
-
|
|
276
|
-
${style}`;
|
|
277
|
-
const extension = getFileExtension("vue", typescript);
|
|
278
|
-
const filename = getComponentFilename("icon.svg", componentName, extension);
|
|
279
|
-
return {
|
|
280
|
-
code: vueComponent,
|
|
281
|
-
filename,
|
|
282
|
-
componentName
|
|
283
|
-
};
|
|
284
|
-
} catch (error) {
|
|
285
|
-
throw new Error(`Failed to convert SVG to Vue: ${error}`);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
function generateScriptSetup(typescript, componentName) {
|
|
289
|
-
const lang = typescript ? ' lang="ts"' : "";
|
|
290
|
-
const propsType = typescript ? `
|
|
26
|
+
</style>`,y=$("vue",o),h=x("icon.svg",p,y);return {code:w,filename:h,componentName:p}}catch(m){throw new Error(`Failed to convert SVG to Vue: ${m}`)}}function re(e,t){return `<script setup${e?' lang="ts"':""}>${e?`
|
|
291
27
|
interface Props {
|
|
292
28
|
class?: string;
|
|
293
29
|
style?: string | Record<string, any>;
|
|
294
|
-
}
|
|
295
|
-
const propsDefinition = typescript ? `
|
|
30
|
+
}`:""}${e?`
|
|
296
31
|
const props = withDefaults(defineProps<Props>(), {
|
|
297
32
|
class: '',
|
|
298
33
|
style: undefined,
|
|
299
|
-
})
|
|
34
|
+
});`:`
|
|
300
35
|
const props = withDefaults(defineProps(), {
|
|
301
36
|
class: '',
|
|
302
37
|
style: undefined,
|
|
303
|
-
})
|
|
304
|
-
return `<script setup${lang}>${propsType}${propsDefinition}
|
|
38
|
+
});`}
|
|
305
39
|
|
|
306
40
|
// Component name for debugging
|
|
307
|
-
const __name = '${
|
|
308
|
-
</script
|
|
309
|
-
}
|
|
310
|
-
function generateCompositionScript(componentName, typescript) {
|
|
311
|
-
const lang = typescript ? ' lang="ts"' : "";
|
|
312
|
-
const propsType = typescript ? `
|
|
41
|
+
const __name = '${t}';
|
|
42
|
+
</script>`}function oe(e,t){let r=t?' lang="ts"':"",n=t?`
|
|
313
43
|
interface Props {
|
|
314
44
|
class?: string;
|
|
315
45
|
style?: string | Record<string, any>;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
name: '${componentName}',
|
|
46
|
+
}`:"",s=t?`
|
|
47
|
+
const ${e} = defineComponent({
|
|
48
|
+
name: '${e}',
|
|
320
49
|
props: {
|
|
321
50
|
class: {
|
|
322
51
|
type: String,
|
|
@@ -332,10 +61,10 @@ const ${componentName} = defineComponent({
|
|
|
332
61
|
},
|
|
333
62
|
});
|
|
334
63
|
|
|
335
|
-
export default ${
|
|
336
|
-
export { ${
|
|
337
|
-
const ${
|
|
338
|
-
name: '${
|
|
64
|
+
export default ${e};
|
|
65
|
+
export { ${e} };`:`
|
|
66
|
+
const ${e} = defineComponent({
|
|
67
|
+
name: '${e}',
|
|
339
68
|
props: {
|
|
340
69
|
class: {
|
|
341
70
|
type: String,
|
|
@@ -351,24 +80,9 @@ const ${componentName} = defineComponent({
|
|
|
351
80
|
},
|
|
352
81
|
});
|
|
353
82
|
|
|
354
|
-
export default ${
|
|
355
|
-
export { ${
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
export {
|
|
361
|
-
convertToReact,
|
|
362
|
-
convertToVue,
|
|
363
|
-
createSvgoConfig,
|
|
364
|
-
formatComponentName,
|
|
365
|
-
optimizeSvg,
|
|
366
|
-
pascalCase,
|
|
367
|
-
readSvgDirectory,
|
|
368
|
-
readSvgFile,
|
|
369
|
-
sanitizeComponentName,
|
|
370
|
-
svgToComponentName,
|
|
371
|
-
writeComponentFile,
|
|
372
|
-
writeSvgFile
|
|
373
|
-
};
|
|
374
|
-
//# sourceMappingURL=index.mjs.map
|
|
83
|
+
export default ${e};
|
|
84
|
+
export { ${e} };`;return `<script${r}>
|
|
85
|
+
import { defineComponent } from 'vue';${n}${s}
|
|
86
|
+
</script>`}
|
|
87
|
+
|
|
88
|
+
export { ee as convertToReact, te as convertToVue, _ as createSvgoConfig, d as formatComponentName, v as optimizeSvg, u as pascalCase, D as readSvgDirectory, K as readSvgFile, I as sanitizeComponentName, k as svgToComponentName, X as writeComponentFile, Q as writeSvgFile };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svgfusion",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"description": "Transform SVG files into production-ready React and Vue 3 components with TypeScript support, automatic optimization, and intelligent naming.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
package/dist/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/cli.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/converters/react.ts","../src/utils/svgo.ts","../src/utils/name.ts","../src/utils/files.ts","../src/converters/vue.ts"],"sourcesContent":["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"]}
|