Skip to content

Commit 1260302

Browse files
committed
Add useInnerHTML option [publish]
1 parent 8e0c11b commit 1260302

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 0.3.0
4+
5+
Added `useInnerHTML` option to use `dangerouslySetInnerHTML` for SVG contents which improve bundle size.
6+
37
## 0.2.0
48

59
Breaking: Use named export instead of default export for better esm/cjs interop. Closes #2

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { defineConfig } from "vite";
2121
import { svgPlugin } from "vite-plugin-fast-react-svg";
2222

2323
export default defineConfig({
24-
plugins: [svgPlugin()],
24+
plugins: [svgPlugin({ useInnerHTML: true })],
2525
});
2626
```
2727

@@ -48,3 +48,7 @@ const Example = () => (
4848
</>
4949
);
5050
```
51+
52+
## Options
53+
54+
**useInnerHTML**: Set to true to use `dangerouslySetInnerHTML` for SVG contents, which improve bundle size. Added in 0.3.0.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vite-plugin-fast-react-svg",
33
"description": "Turn SVG into React components, without Babel",
4-
"version": "0.2.0",
4+
"version": "0.3.0",
55
"license": "MIT",
66
"author": "Arnaud Barré (https://github.com/ArnaudBarre)",
77
"main": "dist/index.js",

src/index.ts

+26-11
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { readFileSync } from "fs";
22
import { transform } from "esbuild";
33
import { Plugin } from "vite";
44

5-
export function svgPlugin(): Plugin {
5+
export function svgPlugin(opts?: { useInnerHTML?: boolean }): Plugin {
66
return {
77
name: "svg",
88
enforce: "pre",
99
async load(id) {
1010
if (id.endsWith(".svg")) {
1111
const { code, warnings } = await transform(
12-
svgToJSX(readFileSync(id, "utf-8")),
12+
svgToJSX(readFileSync(id, "utf-8"), opts?.useInnerHTML),
1313
{ loader: "jsx" }
1414
);
1515
for (const warning of warnings) {
@@ -27,15 +27,30 @@ export function svgPlugin(): Plugin {
2727
};
2828
}
2929

30-
export const svgToJSX = (svg: string) =>
31-
`import React from "react";const ReactComponent = (props) => (${svg
32-
.replace(/\s([a-z-:]*)="[^"]*"/gu, (string, key: string) => {
33-
if (key.startsWith("data-")) return string;
34-
const keyWithoutDashes = camelCaseOn(key, "-");
35-
const keyWithoutDots = camelCaseOn(keyWithoutDashes, ":");
36-
return string.replace(key, keyWithoutDots);
37-
})
38-
.replace(">", " {...props}>")});export default ReactComponent`;
30+
export const svgToJSX = (svg: string, useInnerHTML?: boolean) => {
31+
let jsx: string;
32+
if (useInnerHTML) {
33+
const index = svg.indexOf(">");
34+
const content = svg
35+
.slice(index + 1, svg.indexOf("</svg>"))
36+
.trim()
37+
.replace(/\s+/g, " ");
38+
jsx = `${updatePropsCase(
39+
svg.slice(0, index)
40+
)} {...props} dangerouslySetInnerHTML={{ __html: '${content}' }} />`;
41+
} else {
42+
jsx = updatePropsCase(svg).replace(">", " {...props}>");
43+
}
44+
return `import React from "react";const ReactComponent = (props) => (${jsx});export default ReactComponent;`;
45+
};
46+
47+
const updatePropsCase = (svg: string) =>
48+
svg.replace(/\s([a-z-:]*)="[^"]*"/gu, (string, key: string) => {
49+
if (key.startsWith("data-")) return string;
50+
const keyWithoutDashes = camelCaseOn(key, "-");
51+
const keyWithoutDots = camelCaseOn(keyWithoutDashes, ":");
52+
return string.replace(key, keyWithoutDots);
53+
});
3954

4055
const camelCaseOn = (string: string, delimiter: string) =>
4156
string

0 commit comments

Comments
 (0)