svgfusion-vue 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/index.cjs +29 -0
- package/dist/index.d.cts +91 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.js +29 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# SVGFusion Vue
|
|
2
|
+
|
|
3
|
+
Vue 3 specific utilities and components for SVGFusion.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install svgfusion-vue
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { generateVueComponent, VueOptions } from 'svgfusion-vue';
|
|
15
|
+
|
|
16
|
+
// Generate Vue 3 component from SVG
|
|
17
|
+
const svgContent = '<svg>...</svg>';
|
|
18
|
+
const vueComponent = generateVueComponent(svgContent, options);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- Vue 3 component generation
|
|
24
|
+
- TypeScript support
|
|
25
|
+
- Composition API support
|
|
26
|
+
- Vue-specific optimizations
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
Visit [svgfusion.netlify.app](https://svgfusion.netlify.app) for complete documentation.
|
|
31
|
+
|
|
32
|
+
## License
|
|
33
|
+
|
|
34
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';var svgfusionCore=require('svgfusion-core');var v=Object.defineProperty;var b=(d,l,s)=>l in d?v(d,l,{enumerable:true,configurable:true,writable:true,value:s}):d[l]=s;var y=(d,l,s)=>b(d,l+"",s);var S=class extends svgfusionCore.ComponentGenerator{constructor(s={}){super(s);y(this,"vueOptions");this.vueOptions={...this.options,composition:s.composition??true,scriptSetup:s.scriptSetup??true,sfc:s.sfc??true,defineComponent:s.defineComponent??false,useDefineOptions:s.useDefineOptions??false};}async formatCode(s,n){try{let{format:r}=await import('prettier');return await r(s,{parser:n,semi:!0,singleQuote:!0,trailingComma:"es5",tabWidth:2,printWidth:80,bracketSpacing:!0,arrowParens:"avoid",htmlWhitespaceSensitivity:"ignore",vueIndentScriptAndStyle:!0})}catch(r){return console.warn("Prettier formatting failed or not available, using unformatted code:",r),s}}async generate(s){let n=this.getComponentName(),r;this.vueOptions.sfc?r=this.generateSFC(s):r=this.generateJSComponent(s);let o=this.vueOptions.sfc?"vue":this.vueOptions.typescript?"ts":"js",e=this.generateFilename(n,o),t=this.vueOptions.sfc?"vue":this.vueOptions.typescript?"typescript":"babel";return {code:await this.formatCode(r,t),filename:e,componentName:n,dependencies:this.getDependencies()}}generateSFC(s){let n=this.generateTemplate(s),r=this.generateScript(s),o=this.generateStyle();return `<template>
|
|
2
|
+
${n}
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script${this.vueOptions.scriptSetup?" setup":""}${this.vueOptions.typescript?' lang="ts"':""}>
|
|
6
|
+
${this.vueOptions.scriptSetup&&this.vueOptions.useDefineOptions?`defineOptions({ inheritAttrs: false });
|
|
7
|
+
|
|
8
|
+
`:""}${r}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
${o?`<style scoped>
|
|
12
|
+
${o}
|
|
13
|
+
</style>`:""}`}generateJSComponent(s){return this.vueOptions.composition?this.generateCompositionAPI(s):this.generateOptionsAPI(s)}generateTemplate(s){let{ast:n}=s,r=this.generateSvgAttributes(n),o=n.root.children.map(e=>this.elementToVueTemplate(e,2)).join(`
|
|
14
|
+
`);return ` <svg${r} v-bind="$attrs" :width="computedWidth" :height="computedHeight">
|
|
15
|
+
<title v-if="props.title" :id="props.titleId">{{ props.title }}</title>
|
|
16
|
+
<desc v-if="props.desc" :id="props.descId">{{ props.desc }}</desc>
|
|
17
|
+
${o}
|
|
18
|
+
</svg>`}elementToVueTemplate(s,n=0){let r=" ".repeat(n),{tag:o,attributes:e,children:t,content:i}=s,p=[],a=[],h="class"in e;if(Object.entries(e).forEach(([u,c])=>{if(u==="vector-effect"&&c==="non-scaling-stroke")p.push(`:vector-effect="props.isFixedStrokeWidth ? 'non-scaling-stroke' : 'none'"`);else if(u==="style"){let g=this.parseStyleStringForVue(c);p.push(`:style="${g}"`);let m=this.extractClassVarsFromStyle(c);a.push(...m);}else if(c.startsWith("{")&&c.endsWith("}")){let g=c.slice(1,-1);if(p.push(`:${u}="props.${g}"`),u==="fill"||u==="stroke"||u==="stroke-width"){let m=`${g}Class`;a.push(`props.${m}`);}}else p.push(`${u}="${c}"`);}),a.length>0){let u=e.class;u?p.push(`:class="[${a.join(", ")}, '${u}']"`):p.push(`:class="[${a.join(", ")}]"`);}else if(h){let u=e.class;u&&p.push(`class="${u}"`);}let $=p.length>0?" "+p.join(" "):"";if(t.length===0&&!i)return `${r}<${o}${$} />`;let f=`${r}<${o}${$}>`;return i&&(f+=i),t.length>0&&(f+=`
|
|
19
|
+
`,f+=t.map(u=>this.elementToVueTemplate(u,n+1)).join(`
|
|
20
|
+
`),f+=`
|
|
21
|
+
`+r),f+=`</${o}>`,f}generateScript(s){return this.vueOptions.scriptSetup?this.generateScriptSetup(s):this.vueOptions.composition?this.generateCompositionAPI(s):this.generateOptionsAPI(s)}generateScriptSetup(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=[];if(this.vueOptions.typescript?(e.push('import type { SVGAttributes } from "vue";'),e.push('import { computed } from "vue";'),e.push("")):(e.push('import { computed } from "vue";'),e.push("")),this.vueOptions.typescript){e.push("interface Props extends /* @vue-ignore */ SVGAttributes {"),e.push(" title?: string;"),e.push(" titleId?: string;"),e.push(" desc?: string;"),e.push(" descId?: string;"),e.push(" width?: string | number;"),e.push(" height?: string | number;"),e.push(" size?: string | number;");let t=this.generateColorPropsInterface(n);t&&e.push(t);let i=this.generateStrokeWidthPropsInterface(r);i&&e.push(i),o.features.includes("fixed-stroke-width")&&e.push(" isFixedStrokeWidth?: boolean;"),e.push("}"),e.push(""),e.push("const props = withDefaults(defineProps<Props>(), {");}else e.push("const props = defineProps({"),e.push(" title: { type: String, default: '' },"),e.push(" titleId: { type: String, default: '' },"),e.push(" desc: { type: String, default: '' },"),e.push(" descId: { type: String, default: '' },"),e.push(" class: { type: String, default: '' },"),e.push(" style: { type: Object, default: '' },"),e.push(" width: { type: [String, Number], default: '' },"),e.push(" height: { type: [String, Number], default: '' },"),e.push(' size: { type: [String, Number], default: "24" },');return this.vueOptions.typescript&&e.push(' size: "24",'),n.forEach(t=>{let i=t.variableName,p=t.originalColor,a=`${i}Class`;this.vueOptions.typescript?(e.push(` ${i}: '${p}',`),e.push(` ${a}: "",`)):(e.push(` ${i}: { type: String, default: '${p}' },`),e.push(` ${a}: { type: String, default: "" },`));}),r.forEach(t=>{let i=t.variableName,p=t.originalStrokeWidth,a=`${i}Class`;this.vueOptions.typescript?(e.push(` ${i}: '${p}',`),e.push(` ${a}: "",`)):(e.push(` ${i}: { type: [String, Number], default: '${p}' },`),e.push(` ${a}: { type: String, default: "" },`));}),o.features.includes("fixed-stroke-width")&&(this.vueOptions.typescript?e.push(" isFixedStrokeWidth: true,"):e.push(" isFixedStrokeWidth: { type: Boolean, default: true },")),e.push("});"),e.push(""),e.push("const computedWidth = computed(() => props.width || props.size);"),e.push("const computedHeight = computed(() => props.height || props.size);"),e.join(`
|
|
22
|
+
`)}generateCompositionAPI(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=this.getComponentName(),t=[];return t.push("import { defineComponent, computed } from 'vue';"),t.push(""),t.push("export default defineComponent({"),t.push(` name: '${e}',`),t.push(" props: {"),t.push(" title: { type: String, default: '' },"),t.push(" titleId: { type: String, default: '' },"),t.push(" desc: { type: String, default: '' },"),t.push(" descId: { type: String, default: '' },"),t.push(" class: { type: String, default: '' },"),t.push(" style: { type: Object, default: '' },"),t.push(" width: { type: [String, Number], default: '' },"),t.push(" height: { type: [String, Number], default: '' },"),t.push(' size: { type: [String, Number], default: "24" },'),n.forEach(i=>{let p=i.variableName,a=i.originalColor,h=`${p}Class`;t.push(` ${p}: { type: String, default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),r.forEach(i=>{let p=i.variableName,a=i.originalStrokeWidth,h=`${p}Class`;t.push(` ${p}: { type: [String, Number], default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),o.features.includes("fixed-stroke-width")&&t.push(" isFixedStrokeWidth: { type: Boolean, default: true },"),t.push(" },"),t.push(" setup(props) {"),t.push(" const computedWidth = computed(() => props.width || props.size);"),t.push(" const computedHeight = computed(() => props.height || props.size);"),t.push(" return { computedWidth, computedHeight };"),t.push(" },"),t.push("});"),t.join(`
|
|
23
|
+
`)}generateOptionsAPI(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=this.getComponentName(),t=[];return t.push("export default {"),t.push(` name: '${e}',`),t.push(" props: {"),t.push(" title: { type: String, default: '' },"),t.push(" titleId: { type: String, default: '' },"),t.push(" desc: { type: String, default: '' },"),t.push(" descId: { type: String, default: '' },"),t.push(" class: { type: String, default: '' },"),t.push(" style: { type: Object, default: '' },"),t.push(" width: { type: [String, Number], default: '' },"),t.push(" height: { type: [String, Number], default: '' },"),t.push(' size: { type: [String, Number], default: "24" },'),n.forEach(i=>{let p=i.variableName,a=i.originalColor,h=`${p}Class`;t.push(` ${p}: { type: String, default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),r.forEach(i=>{let p=i.variableName,a=i.originalStrokeWidth,h=`${p}Class`;t.push(` ${p}: { type: [String, Number], default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),o.features.includes("fixed-stroke-width")&&t.push(" isFixedStrokeWidth: { type: Boolean, default: true },"),t.push(" },"),t.push(" computed: {"),t.push(" computedWidth() {"),t.push(" return this.width || this.size;"),t.push(" },"),t.push(" computedHeight() {"),t.push(" return this.height || this.size;"),t.push(" },"),t.push(" },"),t.push("};"),t.join(`
|
|
24
|
+
`)}generateStyle(){return ""}generateColorPropsInterface(s){return s.length===0?"":s.map(n=>{let r=n.variableName,o=`${r}Class`;return ` ${r}?: string;
|
|
25
|
+
${o}?: string;`}).join(`
|
|
26
|
+
`)}generateStrokeWidthPropsInterface(s){return s.length===0?"":s.map(n=>{let r=n.variableName,o=`${r}Class`;return ` ${r}?: string | number;
|
|
27
|
+
${o}?: string;`}).join(`
|
|
28
|
+
`)}parseStyleStringForVue(s){let n=[];return s.split(";").forEach(r=>{let o=r.indexOf(":");if(o>0){let e=r.slice(0,o).trim(),t=r.slice(o+1).trim();if(e&&t)if(t.startsWith("{")&&t.endsWith("}")){let i=t.slice(1,-1);n.push(`'${e}': props.${i}`);}else n.push(`'${e}': '${t}'`);}}),`{ ${n.join(", ")} }`}generateSvgAttributes(s){let n=[],o={...s.root.attributes||{},...s.viewBox&&{viewBox:s.viewBox},...s.namespace&&{xmlns:s.namespace},...s.width&&{width:s.width},...s.height&&{height:s.height}};o.xmlns||(o.xmlns="http://www.w3.org/2000/svg");let e=o.viewBox;return Object.entries(o).forEach(([t,i])=>{if(i!=null){if(e&&(t==="width"||t==="height"))return;if(t==="aria-labelledby"&&typeof i=="string"&&i.includes("{")){let p=i.replace(/\{(\w+)\}/g,"${props.$1}");n.push(` :aria-labelledby="\`${p}\`"`);}else n.push(` ${t}="${i}"`);}}),n.join("")}getDependencies(){return ["vue"]}extractClassVarsFromStyle(s){let n=[];return s.split(";").forEach(r=>{let o=r.indexOf(":");if(o>0){let e=r.slice(0,o).trim(),t=r.slice(o+1).trim();if(e&&t&&t.startsWith("{")&&t.endsWith("}")){let i=t.slice(1,-1);if(e==="fill"||e==="stroke"||e==="stroke-width"){let p=`props.${i}Class`;n.push(p);}}}}),n}};
|
|
29
|
+
exports.VueGenerator=S;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ComponentGenerator, GeneratorOptions, TransformationResult, ComponentResult } from 'svgfusion-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vue component generator
|
|
5
|
+
* Generates production-ready Vue 3 components with TypeScript support
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface VueGeneratorOptions extends GeneratorOptions {
|
|
9
|
+
composition?: boolean;
|
|
10
|
+
scriptSetup?: boolean;
|
|
11
|
+
sfc?: boolean;
|
|
12
|
+
defineComponent?: boolean;
|
|
13
|
+
useDefineOptions?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Vue component generator
|
|
17
|
+
*/
|
|
18
|
+
declare class VueGenerator extends ComponentGenerator {
|
|
19
|
+
private vueOptions;
|
|
20
|
+
constructor(options?: VueGeneratorOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Dynamically load prettier for code formatting
|
|
23
|
+
*/
|
|
24
|
+
private formatCode;
|
|
25
|
+
/**
|
|
26
|
+
* Generate Vue component from transformation result
|
|
27
|
+
*/
|
|
28
|
+
generate(result: TransformationResult): Promise<ComponentResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate Single File Component (.vue)
|
|
31
|
+
*/
|
|
32
|
+
private generateSFC;
|
|
33
|
+
/**
|
|
34
|
+
* Generate separate JS/TS component file
|
|
35
|
+
*/
|
|
36
|
+
private generateJSComponent;
|
|
37
|
+
/**
|
|
38
|
+
* Generate Vue template section
|
|
39
|
+
*/
|
|
40
|
+
private generateTemplate;
|
|
41
|
+
/**
|
|
42
|
+
* Convert SVG element to Vue template syntax
|
|
43
|
+
*/
|
|
44
|
+
private elementToVueTemplate;
|
|
45
|
+
/**
|
|
46
|
+
* Generate script section for SFC
|
|
47
|
+
*/
|
|
48
|
+
private generateScript;
|
|
49
|
+
/**
|
|
50
|
+
* Generate <script setup> content
|
|
51
|
+
*/
|
|
52
|
+
private generateScriptSetup;
|
|
53
|
+
/**
|
|
54
|
+
* Generate Composition API script
|
|
55
|
+
*/
|
|
56
|
+
private generateCompositionAPI;
|
|
57
|
+
/**
|
|
58
|
+
* Generate Options API script
|
|
59
|
+
*/
|
|
60
|
+
private generateOptionsAPI;
|
|
61
|
+
/**
|
|
62
|
+
* Generate style section
|
|
63
|
+
*/
|
|
64
|
+
private generateStyle;
|
|
65
|
+
/**
|
|
66
|
+
* Generate TypeScript interface for color props
|
|
67
|
+
*/
|
|
68
|
+
private generateColorPropsInterface;
|
|
69
|
+
/**
|
|
70
|
+
* Generate TypeScript interface for stroke width props
|
|
71
|
+
*/
|
|
72
|
+
private generateStrokeWidthPropsInterface;
|
|
73
|
+
/**
|
|
74
|
+
* Parse style string for Vue template syntax
|
|
75
|
+
*/
|
|
76
|
+
private parseStyleStringForVue;
|
|
77
|
+
/**
|
|
78
|
+
* Generate SVG root attributes for Vue template
|
|
79
|
+
*/
|
|
80
|
+
private generateSvgAttributes;
|
|
81
|
+
/**
|
|
82
|
+
* Get list of dependencies
|
|
83
|
+
*/
|
|
84
|
+
private getDependencies;
|
|
85
|
+
/**
|
|
86
|
+
* Extract class variables from style attribute value
|
|
87
|
+
*/
|
|
88
|
+
private extractClassVarsFromStyle;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { VueGenerator, type VueGeneratorOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ComponentGenerator, GeneratorOptions, TransformationResult, ComponentResult } from 'svgfusion-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Vue component generator
|
|
5
|
+
* Generates production-ready Vue 3 components with TypeScript support
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface VueGeneratorOptions extends GeneratorOptions {
|
|
9
|
+
composition?: boolean;
|
|
10
|
+
scriptSetup?: boolean;
|
|
11
|
+
sfc?: boolean;
|
|
12
|
+
defineComponent?: boolean;
|
|
13
|
+
useDefineOptions?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Vue component generator
|
|
17
|
+
*/
|
|
18
|
+
declare class VueGenerator extends ComponentGenerator {
|
|
19
|
+
private vueOptions;
|
|
20
|
+
constructor(options?: VueGeneratorOptions);
|
|
21
|
+
/**
|
|
22
|
+
* Dynamically load prettier for code formatting
|
|
23
|
+
*/
|
|
24
|
+
private formatCode;
|
|
25
|
+
/**
|
|
26
|
+
* Generate Vue component from transformation result
|
|
27
|
+
*/
|
|
28
|
+
generate(result: TransformationResult): Promise<ComponentResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Generate Single File Component (.vue)
|
|
31
|
+
*/
|
|
32
|
+
private generateSFC;
|
|
33
|
+
/**
|
|
34
|
+
* Generate separate JS/TS component file
|
|
35
|
+
*/
|
|
36
|
+
private generateJSComponent;
|
|
37
|
+
/**
|
|
38
|
+
* Generate Vue template section
|
|
39
|
+
*/
|
|
40
|
+
private generateTemplate;
|
|
41
|
+
/**
|
|
42
|
+
* Convert SVG element to Vue template syntax
|
|
43
|
+
*/
|
|
44
|
+
private elementToVueTemplate;
|
|
45
|
+
/**
|
|
46
|
+
* Generate script section for SFC
|
|
47
|
+
*/
|
|
48
|
+
private generateScript;
|
|
49
|
+
/**
|
|
50
|
+
* Generate <script setup> content
|
|
51
|
+
*/
|
|
52
|
+
private generateScriptSetup;
|
|
53
|
+
/**
|
|
54
|
+
* Generate Composition API script
|
|
55
|
+
*/
|
|
56
|
+
private generateCompositionAPI;
|
|
57
|
+
/**
|
|
58
|
+
* Generate Options API script
|
|
59
|
+
*/
|
|
60
|
+
private generateOptionsAPI;
|
|
61
|
+
/**
|
|
62
|
+
* Generate style section
|
|
63
|
+
*/
|
|
64
|
+
private generateStyle;
|
|
65
|
+
/**
|
|
66
|
+
* Generate TypeScript interface for color props
|
|
67
|
+
*/
|
|
68
|
+
private generateColorPropsInterface;
|
|
69
|
+
/**
|
|
70
|
+
* Generate TypeScript interface for stroke width props
|
|
71
|
+
*/
|
|
72
|
+
private generateStrokeWidthPropsInterface;
|
|
73
|
+
/**
|
|
74
|
+
* Parse style string for Vue template syntax
|
|
75
|
+
*/
|
|
76
|
+
private parseStyleStringForVue;
|
|
77
|
+
/**
|
|
78
|
+
* Generate SVG root attributes for Vue template
|
|
79
|
+
*/
|
|
80
|
+
private generateSvgAttributes;
|
|
81
|
+
/**
|
|
82
|
+
* Get list of dependencies
|
|
83
|
+
*/
|
|
84
|
+
private getDependencies;
|
|
85
|
+
/**
|
|
86
|
+
* Extract class variables from style attribute value
|
|
87
|
+
*/
|
|
88
|
+
private extractClassVarsFromStyle;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { VueGenerator, type VueGeneratorOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {ComponentGenerator}from'svgfusion-core';var v=Object.defineProperty;var b=(d,l,s)=>l in d?v(d,l,{enumerable:true,configurable:true,writable:true,value:s}):d[l]=s;var y=(d,l,s)=>b(d,l+"",s);var S=class extends ComponentGenerator{constructor(s={}){super(s);y(this,"vueOptions");this.vueOptions={...this.options,composition:s.composition??true,scriptSetup:s.scriptSetup??true,sfc:s.sfc??true,defineComponent:s.defineComponent??false,useDefineOptions:s.useDefineOptions??false};}async formatCode(s,n){try{let{format:r}=await import('prettier');return await r(s,{parser:n,semi:!0,singleQuote:!0,trailingComma:"es5",tabWidth:2,printWidth:80,bracketSpacing:!0,arrowParens:"avoid",htmlWhitespaceSensitivity:"ignore",vueIndentScriptAndStyle:!0})}catch(r){return console.warn("Prettier formatting failed or not available, using unformatted code:",r),s}}async generate(s){let n=this.getComponentName(),r;this.vueOptions.sfc?r=this.generateSFC(s):r=this.generateJSComponent(s);let o=this.vueOptions.sfc?"vue":this.vueOptions.typescript?"ts":"js",e=this.generateFilename(n,o),t=this.vueOptions.sfc?"vue":this.vueOptions.typescript?"typescript":"babel";return {code:await this.formatCode(r,t),filename:e,componentName:n,dependencies:this.getDependencies()}}generateSFC(s){let n=this.generateTemplate(s),r=this.generateScript(s),o=this.generateStyle();return `<template>
|
|
2
|
+
${n}
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script${this.vueOptions.scriptSetup?" setup":""}${this.vueOptions.typescript?' lang="ts"':""}>
|
|
6
|
+
${this.vueOptions.scriptSetup&&this.vueOptions.useDefineOptions?`defineOptions({ inheritAttrs: false });
|
|
7
|
+
|
|
8
|
+
`:""}${r}
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
${o?`<style scoped>
|
|
12
|
+
${o}
|
|
13
|
+
</style>`:""}`}generateJSComponent(s){return this.vueOptions.composition?this.generateCompositionAPI(s):this.generateOptionsAPI(s)}generateTemplate(s){let{ast:n}=s,r=this.generateSvgAttributes(n),o=n.root.children.map(e=>this.elementToVueTemplate(e,2)).join(`
|
|
14
|
+
`);return ` <svg${r} v-bind="$attrs" :width="computedWidth" :height="computedHeight">
|
|
15
|
+
<title v-if="props.title" :id="props.titleId">{{ props.title }}</title>
|
|
16
|
+
<desc v-if="props.desc" :id="props.descId">{{ props.desc }}</desc>
|
|
17
|
+
${o}
|
|
18
|
+
</svg>`}elementToVueTemplate(s,n=0){let r=" ".repeat(n),{tag:o,attributes:e,children:t,content:i}=s,p=[],a=[],h="class"in e;if(Object.entries(e).forEach(([u,c])=>{if(u==="vector-effect"&&c==="non-scaling-stroke")p.push(`:vector-effect="props.isFixedStrokeWidth ? 'non-scaling-stroke' : 'none'"`);else if(u==="style"){let g=this.parseStyleStringForVue(c);p.push(`:style="${g}"`);let m=this.extractClassVarsFromStyle(c);a.push(...m);}else if(c.startsWith("{")&&c.endsWith("}")){let g=c.slice(1,-1);if(p.push(`:${u}="props.${g}"`),u==="fill"||u==="stroke"||u==="stroke-width"){let m=`${g}Class`;a.push(`props.${m}`);}}else p.push(`${u}="${c}"`);}),a.length>0){let u=e.class;u?p.push(`:class="[${a.join(", ")}, '${u}']"`):p.push(`:class="[${a.join(", ")}]"`);}else if(h){let u=e.class;u&&p.push(`class="${u}"`);}let $=p.length>0?" "+p.join(" "):"";if(t.length===0&&!i)return `${r}<${o}${$} />`;let f=`${r}<${o}${$}>`;return i&&(f+=i),t.length>0&&(f+=`
|
|
19
|
+
`,f+=t.map(u=>this.elementToVueTemplate(u,n+1)).join(`
|
|
20
|
+
`),f+=`
|
|
21
|
+
`+r),f+=`</${o}>`,f}generateScript(s){return this.vueOptions.scriptSetup?this.generateScriptSetup(s):this.vueOptions.composition?this.generateCompositionAPI(s):this.generateOptionsAPI(s)}generateScriptSetup(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=[];if(this.vueOptions.typescript?(e.push('import type { SVGAttributes } from "vue";'),e.push('import { computed } from "vue";'),e.push("")):(e.push('import { computed } from "vue";'),e.push("")),this.vueOptions.typescript){e.push("interface Props extends /* @vue-ignore */ SVGAttributes {"),e.push(" title?: string;"),e.push(" titleId?: string;"),e.push(" desc?: string;"),e.push(" descId?: string;"),e.push(" width?: string | number;"),e.push(" height?: string | number;"),e.push(" size?: string | number;");let t=this.generateColorPropsInterface(n);t&&e.push(t);let i=this.generateStrokeWidthPropsInterface(r);i&&e.push(i),o.features.includes("fixed-stroke-width")&&e.push(" isFixedStrokeWidth?: boolean;"),e.push("}"),e.push(""),e.push("const props = withDefaults(defineProps<Props>(), {");}else e.push("const props = defineProps({"),e.push(" title: { type: String, default: '' },"),e.push(" titleId: { type: String, default: '' },"),e.push(" desc: { type: String, default: '' },"),e.push(" descId: { type: String, default: '' },"),e.push(" class: { type: String, default: '' },"),e.push(" style: { type: Object, default: '' },"),e.push(" width: { type: [String, Number], default: '' },"),e.push(" height: { type: [String, Number], default: '' },"),e.push(' size: { type: [String, Number], default: "24" },');return this.vueOptions.typescript&&e.push(' size: "24",'),n.forEach(t=>{let i=t.variableName,p=t.originalColor,a=`${i}Class`;this.vueOptions.typescript?(e.push(` ${i}: '${p}',`),e.push(` ${a}: "",`)):(e.push(` ${i}: { type: String, default: '${p}' },`),e.push(` ${a}: { type: String, default: "" },`));}),r.forEach(t=>{let i=t.variableName,p=t.originalStrokeWidth,a=`${i}Class`;this.vueOptions.typescript?(e.push(` ${i}: '${p}',`),e.push(` ${a}: "",`)):(e.push(` ${i}: { type: [String, Number], default: '${p}' },`),e.push(` ${a}: { type: String, default: "" },`));}),o.features.includes("fixed-stroke-width")&&(this.vueOptions.typescript?e.push(" isFixedStrokeWidth: true,"):e.push(" isFixedStrokeWidth: { type: Boolean, default: true },")),e.push("});"),e.push(""),e.push("const computedWidth = computed(() => props.width || props.size);"),e.push("const computedHeight = computed(() => props.height || props.size);"),e.join(`
|
|
22
|
+
`)}generateCompositionAPI(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=this.getComponentName(),t=[];return t.push("import { defineComponent, computed } from 'vue';"),t.push(""),t.push("export default defineComponent({"),t.push(` name: '${e}',`),t.push(" props: {"),t.push(" title: { type: String, default: '' },"),t.push(" titleId: { type: String, default: '' },"),t.push(" desc: { type: String, default: '' },"),t.push(" descId: { type: String, default: '' },"),t.push(" class: { type: String, default: '' },"),t.push(" style: { type: Object, default: '' },"),t.push(" width: { type: [String, Number], default: '' },"),t.push(" height: { type: [String, Number], default: '' },"),t.push(' size: { type: [String, Number], default: "24" },'),n.forEach(i=>{let p=i.variableName,a=i.originalColor,h=`${p}Class`;t.push(` ${p}: { type: String, default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),r.forEach(i=>{let p=i.variableName,a=i.originalStrokeWidth,h=`${p}Class`;t.push(` ${p}: { type: [String, Number], default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),o.features.includes("fixed-stroke-width")&&t.push(" isFixedStrokeWidth: { type: Boolean, default: true },"),t.push(" },"),t.push(" setup(props) {"),t.push(" const computedWidth = computed(() => props.width || props.size);"),t.push(" const computedHeight = computed(() => props.height || props.size);"),t.push(" return { computedWidth, computedHeight };"),t.push(" },"),t.push("});"),t.join(`
|
|
23
|
+
`)}generateOptionsAPI(s){let{colorMappings:n,strokeWidthMappings:r,metadata:o}=s,e=this.getComponentName(),t=[];return t.push("export default {"),t.push(` name: '${e}',`),t.push(" props: {"),t.push(" title: { type: String, default: '' },"),t.push(" titleId: { type: String, default: '' },"),t.push(" desc: { type: String, default: '' },"),t.push(" descId: { type: String, default: '' },"),t.push(" class: { type: String, default: '' },"),t.push(" style: { type: Object, default: '' },"),t.push(" width: { type: [String, Number], default: '' },"),t.push(" height: { type: [String, Number], default: '' },"),t.push(' size: { type: [String, Number], default: "24" },'),n.forEach(i=>{let p=i.variableName,a=i.originalColor,h=`${p}Class`;t.push(` ${p}: { type: String, default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),r.forEach(i=>{let p=i.variableName,a=i.originalStrokeWidth,h=`${p}Class`;t.push(` ${p}: { type: [String, Number], default: '${a}' },`),t.push(` ${h}: { type: String, default: "" },`);}),o.features.includes("fixed-stroke-width")&&t.push(" isFixedStrokeWidth: { type: Boolean, default: true },"),t.push(" },"),t.push(" computed: {"),t.push(" computedWidth() {"),t.push(" return this.width || this.size;"),t.push(" },"),t.push(" computedHeight() {"),t.push(" return this.height || this.size;"),t.push(" },"),t.push(" },"),t.push("};"),t.join(`
|
|
24
|
+
`)}generateStyle(){return ""}generateColorPropsInterface(s){return s.length===0?"":s.map(n=>{let r=n.variableName,o=`${r}Class`;return ` ${r}?: string;
|
|
25
|
+
${o}?: string;`}).join(`
|
|
26
|
+
`)}generateStrokeWidthPropsInterface(s){return s.length===0?"":s.map(n=>{let r=n.variableName,o=`${r}Class`;return ` ${r}?: string | number;
|
|
27
|
+
${o}?: string;`}).join(`
|
|
28
|
+
`)}parseStyleStringForVue(s){let n=[];return s.split(";").forEach(r=>{let o=r.indexOf(":");if(o>0){let e=r.slice(0,o).trim(),t=r.slice(o+1).trim();if(e&&t)if(t.startsWith("{")&&t.endsWith("}")){let i=t.slice(1,-1);n.push(`'${e}': props.${i}`);}else n.push(`'${e}': '${t}'`);}}),`{ ${n.join(", ")} }`}generateSvgAttributes(s){let n=[],o={...s.root.attributes||{},...s.viewBox&&{viewBox:s.viewBox},...s.namespace&&{xmlns:s.namespace},...s.width&&{width:s.width},...s.height&&{height:s.height}};o.xmlns||(o.xmlns="http://www.w3.org/2000/svg");let e=o.viewBox;return Object.entries(o).forEach(([t,i])=>{if(i!=null){if(e&&(t==="width"||t==="height"))return;if(t==="aria-labelledby"&&typeof i=="string"&&i.includes("{")){let p=i.replace(/\{(\w+)\}/g,"${props.$1}");n.push(` :aria-labelledby="\`${p}\`"`);}else n.push(` ${t}="${i}"`);}}),n.join("")}getDependencies(){return ["vue"]}extractClassVarsFromStyle(s){let n=[];return s.split(";").forEach(r=>{let o=r.indexOf(":");if(o>0){let e=r.slice(0,o).trim(),t=r.slice(o+1).trim();if(e&&t&&t.startsWith("{")&&t.endsWith("}")){let i=t.slice(1,-1);if(e==="fill"||e==="stroke"||e==="stroke-width"){let p=`props.${i}Class`;n.push(p);}}}}),n}};
|
|
29
|
+
export{S as VueGenerator};
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "svgfusion-vue",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Vue component generator for SVGFusion",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "lolvoid",
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup",
|
|
24
|
+
"dev": "tsup --watch",
|
|
25
|
+
"test": "jest",
|
|
26
|
+
"test:coverage": "jest --coverage",
|
|
27
|
+
"test:watch": "jest --watch",
|
|
28
|
+
"lint": "eslint src/**/*.ts",
|
|
29
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
30
|
+
"format": "prettier --write src/**/*.ts",
|
|
31
|
+
"format:check": "prettier --check src/**/*.ts",
|
|
32
|
+
"type-check": "tsc --noEmit",
|
|
33
|
+
"clean": "rm -rf dist",
|
|
34
|
+
"release": "semantic-release"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"svgfusion-core": "workspace:^",
|
|
38
|
+
"svgfusion-utils": "workspace:^"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@eslint/js": "9.31.0",
|
|
42
|
+
"@jest/globals": "^30.0.4",
|
|
43
|
+
"@types/jest": "^30.0.0",
|
|
44
|
+
"@types/node": "^20.0.0",
|
|
45
|
+
"eslint": "^9.31.0",
|
|
46
|
+
"jest": "^30.0.4",
|
|
47
|
+
"semantic-release": "^24.2.5",
|
|
48
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
49
|
+
"@semantic-release/git": "^10.0.1",
|
|
50
|
+
"@semantic-release/github": "^11.0.3",
|
|
51
|
+
"@semantic-release/npm": "^12.0.2",
|
|
52
|
+
"semantic-release-monorepo": "^8.0.2",
|
|
53
|
+
"tsup": "^8.5.0",
|
|
54
|
+
"typescript": "^5.0.0",
|
|
55
|
+
"typescript-eslint": "8.37.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"prettier": "^3.0.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"prettier": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=18.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|