UNPKG

vite-plugin-fast-react-svg

Version:
47 lines (46 loc) 1.44 kB
// src/index.ts import { readFileSync } from "node:fs"; function svgPlugin() { let production = false; return { name: "svg", enforce: "pre", config(_, env) { production = env.command === "build"; }, async load(id) { if (id.endsWith(".svg")) { return svgToJS(readFileSync(id, "utf-8"), production); } } }; } var attributesRE = /\s([a-zA-Z0-9-:]+)=("[^"]*")/gu; var svgToJS = (svg, production) => { const index = svg.indexOf(">"); const content = svg.slice(index + 1, svg.indexOf("</svg>")).trim().replace(/\s+/g, " "); let attributes = ""; for (const match of svg.slice(0, index).matchAll(attributesRE)) { attributes += ` ${transformKey(match[1])}: ${match[2]}, `; } const jsxImport = production ? 'import { jsx } from "react/jsx-runtime";' : 'import { jsxDEV as jsx } from "react/jsx-dev-runtime";'; return `${jsxImport} import { forwardRef } from "react"; export default forwardRef((props, ref) => jsx("svg", { ${attributes} ref, ...props, dangerouslySetInnerHTML: { __html: '${content}' } }) );`; }; var transformKey = (key) => { if (key.startsWith("data-")) return `"${key}"`; const keyWithoutDashes = camelCaseOn(key, "-"); return camelCaseOn(keyWithoutDashes, ":"); }; var camelCaseOn = (string, delimiter) => string.split(delimiter).map((v, i) => i === 0 ? v : v[0].toUpperCase() + v.slice(1)).join(""); export { svgPlugin, svgToJS };