svger-cli 1.0.1 → 1.0.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/README.md
CHANGED
|
@@ -118,4 +118,4 @@ Cleans output folder at the end if needed.
|
|
|
118
118
|
|
|
119
119
|
Acknowledgements
|
|
120
120
|
|
|
121
|
-
This project was implemented by Faeze
|
|
121
|
+
This project was implemented by Faeze Mohades, following the ADR authored by Navid Rezadoost and based on the TDR prepared by Ehsan Jafari. Their guidance and documentation on SVG integration methods in React were instrumental in shaping the design and functionality of the svger-cli CLI.
|
|
@@ -1,35 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a React functional component string from an SVG file's content
|
|
3
|
-
*
|
|
4
|
-
* This template replaces XML/DOCTYPE declarations, cleans up formatting,
|
|
5
|
-
* and injects React props (`width`, `height`, `fill`, and any others via `...props`)
|
|
6
|
-
* directly into the root `<svg>` tag.
|
|
7
|
-
*
|
|
8
|
-
* @param {Object} params - Template generation parameters.
|
|
9
|
-
* @param {string} params.componentName - The name of the generated React component.
|
|
10
|
-
* @param {string} params.svgContent - The raw SVG markup to transform into a React component.
|
|
11
|
-
* @param {number} [params.defaultWidth=24] - Default width of the SVG (used if none is provided via props).
|
|
12
|
-
* @param {number} [params.defaultHeight=24] - Default height of the SVG (used if none is provided via props).
|
|
13
|
-
* @param {string} [params.defaultFill="currentColor"] - Default fill color of the SVG.
|
|
14
|
-
*
|
|
15
|
-
* @returns {string} The complete TypeScript React component code as a string.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* const svg = '<svg viewBox="0 0 24 24"><path d="M0 0h24v24H0z"/></svg>';
|
|
19
|
-
* const componentCode = reactTemplate({
|
|
20
|
-
* componentName: "MyIcon",
|
|
21
|
-
* svgContent: svg,
|
|
22
|
-
* defaultWidth: 32,
|
|
23
|
-
* defaultHeight: 32,
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* // Result: a ready-to-write .tsx file containing a typed React component
|
|
27
|
-
* console.log(componentCode);
|
|
2
|
+
* Generates a React functional component string from an SVG file's content,
|
|
3
|
+
* safely converting any inline `style="..."` to React-compatible object.
|
|
28
4
|
*/
|
|
29
|
-
export declare function reactTemplate({ componentName, svgContent, defaultWidth, defaultHeight, defaultFill, }: {
|
|
5
|
+
export declare function reactTemplate({ componentName, svgContent, defaultWidth, defaultHeight, defaultFill, defaultStroke, }: {
|
|
30
6
|
componentName: string;
|
|
31
7
|
svgContent: string;
|
|
32
8
|
defaultWidth?: number;
|
|
33
9
|
defaultHeight?: number;
|
|
34
10
|
defaultFill?: string;
|
|
11
|
+
defaultStroke?: string;
|
|
35
12
|
}): string;
|
|
@@ -1,57 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a React functional component string from an SVG file's content
|
|
3
|
-
*
|
|
4
|
-
* This template replaces XML/DOCTYPE declarations, cleans up formatting,
|
|
5
|
-
* and injects React props (`width`, `height`, `fill`, and any others via `...props`)
|
|
6
|
-
* directly into the root `<svg>` tag.
|
|
7
|
-
*
|
|
8
|
-
* @param {Object} params - Template generation parameters.
|
|
9
|
-
* @param {string} params.componentName - The name of the generated React component.
|
|
10
|
-
* @param {string} params.svgContent - The raw SVG markup to transform into a React component.
|
|
11
|
-
* @param {number} [params.defaultWidth=24] - Default width of the SVG (used if none is provided via props).
|
|
12
|
-
* @param {number} [params.defaultHeight=24] - Default height of the SVG (used if none is provided via props).
|
|
13
|
-
* @param {string} [params.defaultFill="currentColor"] - Default fill color of the SVG.
|
|
14
|
-
*
|
|
15
|
-
* @returns {string} The complete TypeScript React component code as a string.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* const svg = '<svg viewBox="0 0 24 24"><path d="M0 0h24v24H0z"/></svg>';
|
|
19
|
-
* const componentCode = reactTemplate({
|
|
20
|
-
* componentName: "MyIcon",
|
|
21
|
-
* svgContent: svg,
|
|
22
|
-
* defaultWidth: 32,
|
|
23
|
-
* defaultHeight: 32,
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* // Result: a ready-to-write .tsx file containing a typed React component
|
|
27
|
-
* console.log(componentCode);
|
|
2
|
+
* Generates a React functional component string from an SVG file's content,
|
|
3
|
+
* safely converting any inline `style="..."` to React-compatible object.
|
|
28
4
|
*/
|
|
29
|
-
export function reactTemplate({ componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = "currentColor", }) {
|
|
30
|
-
//
|
|
5
|
+
export function reactTemplate({ componentName, svgContent, defaultWidth = 24, defaultHeight = 24, defaultFill = "currentColor", defaultStroke = "none", }) {
|
|
6
|
+
// helper: convert inline style string to JS object
|
|
7
|
+
function styleStringToObject(style) {
|
|
8
|
+
const obj = {};
|
|
9
|
+
style.split(";").forEach((pair) => {
|
|
10
|
+
if (!pair.trim())
|
|
11
|
+
return;
|
|
12
|
+
const [key, value] = pair.split(":");
|
|
13
|
+
if (!key || value === undefined)
|
|
14
|
+
return;
|
|
15
|
+
// convert kebab-case to camelCase
|
|
16
|
+
const camelKey = key.trim().replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
17
|
+
let v = value.trim();
|
|
18
|
+
if (!isNaN(Number(v)))
|
|
19
|
+
v = Number(v);
|
|
20
|
+
obj[camelKey] = v;
|
|
21
|
+
});
|
|
22
|
+
return obj;
|
|
23
|
+
}
|
|
24
|
+
// clean SVG content
|
|
31
25
|
let cleaned = svgContent
|
|
32
|
-
.replace(/<\?xml.*?\?>/g, "")
|
|
33
|
-
.replace(/<!DOCTYPE.*?>/g, "")
|
|
34
|
-
.replace(/\r?\n|\r/g, "")
|
|
35
|
-
.replace(/style="[^"]*"/g, "") // حذف style های inline
|
|
36
|
-
.replace(/\s(class|id)=["'][^"']*["']/g, "") // حذف class/id مستقیم
|
|
26
|
+
.replace(/<\?xml.*?\?>/g, "") // remove XML declaration
|
|
27
|
+
.replace(/<!DOCTYPE.*?>/g, "") // remove DOCTYPE
|
|
28
|
+
.replace(/\r?\n|\r/g, "") // remove newlines
|
|
37
29
|
.trim();
|
|
38
|
-
//
|
|
39
|
-
cleaned = cleaned.replace(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
className={props.className}
|
|
45
|
-
{...props}>`);
|
|
30
|
+
// convert all style="..." to React objects
|
|
31
|
+
cleaned = cleaned.replace(/style="([^"]*)"/g, (_, styleContent) => {
|
|
32
|
+
return `{...{style: ${JSON.stringify(styleStringToObject(styleContent))}}}`;
|
|
33
|
+
});
|
|
34
|
+
// inject React props into <svg> tag
|
|
35
|
+
cleaned = cleaned.replace(/<svg([^>]*)>/, `<svg$1 width={props.width || ${defaultWidth}} height={props.height || ${defaultHeight}} fill={props.fill || "${defaultFill}"} stroke={props.stroke || "${defaultStroke}"} {...props}>`);
|
|
46
36
|
return `import * as React from "react";
|
|
47
37
|
import type { SVGProps } from "react";
|
|
48
38
|
|
|
49
|
-
export const ${componentName}: React.FC<SVGProps<SVGSVGElement>> = (
|
|
50
|
-
width = ${defaultWidth},
|
|
51
|
-
height = ${defaultHeight},
|
|
52
|
-
fill = "${defaultFill}",
|
|
53
|
-
...props
|
|
54
|
-
}) => (
|
|
39
|
+
export const ${componentName}: React.FC<SVGProps<SVGSVGElement>> = (props) => (
|
|
55
40
|
${cleaned}
|
|
56
41
|
);
|
|
57
42
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svger-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "CLI and runtime for converting SVGs to React components with watch support",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"cli",
|
|
18
18
|
"components"
|
|
19
19
|
],
|
|
20
|
-
"author": "faeze
|
|
20
|
+
"author": "faeze mohades",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"change-case": "^5.4.4",
|
|
@@ -1,30 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a React functional component string from an SVG file's content
|
|
3
|
-
*
|
|
4
|
-
* This template replaces XML/DOCTYPE declarations, cleans up formatting,
|
|
5
|
-
* and injects React props (`width`, `height`, `fill`, and any others via `...props`)
|
|
6
|
-
* directly into the root `<svg>` tag.
|
|
7
|
-
*
|
|
8
|
-
* @param {Object} params - Template generation parameters.
|
|
9
|
-
* @param {string} params.componentName - The name of the generated React component.
|
|
10
|
-
* @param {string} params.svgContent - The raw SVG markup to transform into a React component.
|
|
11
|
-
* @param {number} [params.defaultWidth=24] - Default width of the SVG (used if none is provided via props).
|
|
12
|
-
* @param {number} [params.defaultHeight=24] - Default height of the SVG (used if none is provided via props).
|
|
13
|
-
* @param {string} [params.defaultFill="currentColor"] - Default fill color of the SVG.
|
|
14
|
-
*
|
|
15
|
-
* @returns {string} The complete TypeScript React component code as a string.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* const svg = '<svg viewBox="0 0 24 24"><path d="M0 0h24v24H0z"/></svg>';
|
|
19
|
-
* const componentCode = reactTemplate({
|
|
20
|
-
* componentName: "MyIcon",
|
|
21
|
-
* svgContent: svg,
|
|
22
|
-
* defaultWidth: 32,
|
|
23
|
-
* defaultHeight: 32,
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* // Result: a ready-to-write .tsx file containing a typed React component
|
|
27
|
-
* console.log(componentCode);
|
|
2
|
+
* Generates a React functional component string from an SVG file's content,
|
|
3
|
+
* safely converting any inline `style="..."` to React-compatible object.
|
|
28
4
|
*/
|
|
29
5
|
export function reactTemplate({
|
|
30
6
|
componentName,
|
|
@@ -32,43 +8,53 @@ export function reactTemplate({
|
|
|
32
8
|
defaultWidth = 24,
|
|
33
9
|
defaultHeight = 24,
|
|
34
10
|
defaultFill = "currentColor",
|
|
11
|
+
defaultStroke = "none",
|
|
35
12
|
}: {
|
|
36
13
|
componentName: string;
|
|
37
14
|
svgContent: string;
|
|
38
15
|
defaultWidth?: number;
|
|
39
16
|
defaultHeight?: number;
|
|
40
17
|
defaultFill?: string;
|
|
18
|
+
defaultStroke?: string;
|
|
41
19
|
}) {
|
|
42
|
-
//
|
|
20
|
+
// helper: convert inline style string to JS object
|
|
21
|
+
function styleStringToObject(style: string) {
|
|
22
|
+
const obj: Record<string, string | number> = {};
|
|
23
|
+
style.split(";").forEach((pair) => {
|
|
24
|
+
if (!pair.trim()) return;
|
|
25
|
+
const [key, value] = pair.split(":");
|
|
26
|
+
if (!key || value === undefined) return;
|
|
27
|
+
// convert kebab-case to camelCase
|
|
28
|
+
const camelKey = key.trim().replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
29
|
+
let v: string | number = value.trim();
|
|
30
|
+
if (!isNaN(Number(v))) v = Number(v);
|
|
31
|
+
obj[camelKey] = v;
|
|
32
|
+
});
|
|
33
|
+
return obj;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// clean SVG content
|
|
43
37
|
let cleaned = svgContent
|
|
44
|
-
.replace(/<\?xml.*?\?>/g, "")
|
|
45
|
-
.replace(/<!DOCTYPE.*?>/g, "")
|
|
46
|
-
.replace(/\r?\n|\r/g, "")
|
|
47
|
-
.replace(/style="[^"]*"/g, "") // حذف style های inline
|
|
48
|
-
.replace(/\s(class|id)=["'][^"']*["']/g, "") // حذف class/id مستقیم
|
|
38
|
+
.replace(/<\?xml.*?\?>/g, "") // remove XML declaration
|
|
39
|
+
.replace(/<!DOCTYPE.*?>/g, "") // remove DOCTYPE
|
|
40
|
+
.replace(/\r?\n|\r/g, "") // remove newlines
|
|
49
41
|
.trim();
|
|
50
42
|
|
|
51
|
-
//
|
|
43
|
+
// convert all style="..." to React objects
|
|
44
|
+
cleaned = cleaned.replace(/style="([^"]*)"/g, (_, styleContent) => {
|
|
45
|
+
return `{...{style: ${JSON.stringify(styleStringToObject(styleContent))}}}`;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// inject React props into <svg> tag
|
|
52
49
|
cleaned = cleaned.replace(
|
|
53
50
|
/<svg([^>]*)>/,
|
|
54
|
-
`<svg$1
|
|
55
|
-
width={width}
|
|
56
|
-
height={height}
|
|
57
|
-
fill={fill}
|
|
58
|
-
stroke={props.stroke || "none"}
|
|
59
|
-
className={props.className}
|
|
60
|
-
{...props}>`
|
|
51
|
+
`<svg$1 width={props.width || ${defaultWidth}} height={props.height || ${defaultHeight}} fill={props.fill || "${defaultFill}"} stroke={props.stroke || "${defaultStroke}"} {...props}>`
|
|
61
52
|
);
|
|
62
53
|
|
|
63
54
|
return `import * as React from "react";
|
|
64
55
|
import type { SVGProps } from "react";
|
|
65
56
|
|
|
66
|
-
export const ${componentName}: React.FC<SVGProps<SVGSVGElement>> = (
|
|
67
|
-
width = ${defaultWidth},
|
|
68
|
-
height = ${defaultHeight},
|
|
69
|
-
fill = "${defaultFill}",
|
|
70
|
-
...props
|
|
71
|
-
}) => (
|
|
57
|
+
export const ${componentName}: React.FC<SVGProps<SVGSVGElement>> = (props) => (
|
|
72
58
|
${cleaned}
|
|
73
59
|
);
|
|
74
60
|
|