UNPKG

@svgx/core

Version:

Transform SVG inputs into many outputs, especially "HAST" "JSX" and "JS".

233 lines (232 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toEstreeComponent = exports.toJsComponent = exports.toJsxComponent = exports.toJs = exports.toJsx = exports.toEstree = exports.toHast = void 0; const svgo_1 = require("svgo"); const astring_1 = require("astring"); const estraverse_1 = require("estraverse"); // transform an svg string to HAST (Hypertext Abstract Syntax Tree) const toHast = async (svg, options = {}) => { const defaultOptions = { optimize: true, svgoConfig: {}, }; const mergedOptions = Object.assign({}, defaultOptions, options); let optimized = svg; if (mergedOptions.optimize) { optimized = (0, svgo_1.optimize)(svg, mergedOptions.svgoConfig).data; } const { fromHtml } = await eval(`import('hast-util-from-html')`); return fromHtml(optimized, { space: "svg", fragment: true, }); }; exports.toHast = toHast; // transform an svg into an estree const toEstree = async (svg, options) => { const hast = await (0, exports.toHast)(svg, options); const { toEstree: getEstree } = await eval(`import('hast-util-to-estree')`); return getEstree(hast, { space: "svg" }); }; exports.toEstree = toEstree; // transform an svg into raw jsx syntax (just jsx, not a component) const toJsx = async (svg, options) => { const esTree = await (0, exports.toEstree)(svg, options); const { toJs: getJs, jsx } = await eval(`import('estree-util-to-js')`); const { value } = getJs(esTree, { handlers: jsx }); return value; }; exports.toJsx = toJsx; // transform an svg into javascript function calls (using pragmas) const toJs = async (svg, options) => { const defaultOptions = { optimize: true, svgoConfig: {}, runtime: "automatic", importSource: "react", pragma: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "createElement" : undefined, pragmaFrag: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "Fragment" : undefined, }; const mergedOptions = Object.assign({}, defaultOptions, options); const esTree = await (0, exports.toEstree)(svg, mergedOptions); const { buildJsx } = await eval(`import('estree-util-build-jsx')`); const esAst = buildJsx(esTree, mergedOptions); return (0, astring_1.generate)(esAst); }; exports.toJs = toJs; // transform an svg into a component with raw jsx return value const toJsxComponent = async (svg, options) => { const esTreeComponent = await (0, exports.toEstreeComponent)(svg, options); const { toJs: getJs, jsx } = await eval(`import('estree-util-to-js')`); const { value } = getJs(esTreeComponent, { handlers: jsx }); return value; }; exports.toJsxComponent = toJsxComponent; // transform an svg into a component with jsx runtime function calls return value const toJsComponent = async (svg, options) => { const defaultOptions = { optimize: true, svgoConfig: {}, componentName: "Component", passProps: true, defaultExport: true, importSource: "react", runtime: "automatic", pragma: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "createElement" : undefined, pragmaFrag: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "Fragment" : undefined, }; const mergedOptions = Object.assign({}, defaultOptions, options); const esTreeComponent = await (0, exports.toEstreeComponent)(svg, mergedOptions); const { buildJsx } = await eval(`import('estree-util-build-jsx')`); const esAst = buildJsx(esTreeComponent, mergedOptions); return (0, astring_1.generate)(esAst); }; exports.toJsComponent = toJsComponent; // transform an svg into a component in estree format const toEstreeComponent = async (svg, options = {}) => { const defaultOptions = { optimize: true, svgoConfig: {}, componentName: "Component", passProps: true, defaultExport: true, runtime: "automatic", pragma: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "createElement" : undefined, pragmaFrag: (options === null || options === void 0 ? void 0 : options.runtime) === "classic" ? "Fragment" : undefined, importSource: "react", }; const mergedOptions = Object.assign({}, defaultOptions, options); const esTree = await (0, exports.toEstree)(svg, mergedOptions); (0, estraverse_1.traverse)(esTree, { enter: function (node) { if (node.type === "Program" && node.body) { const previousNodeBody = node.body[0]; // this is for importing pragma and pragmaFrag when using classic runtime const importDeclaration = (mergedOptions === null || mergedOptions === void 0 ? void 0 : mergedOptions.runtime) === "classic" ? { type: "ImportDeclaration", specifiers: [ { type: "ImportSpecifier", imported: { type: "Identifier", name: mergedOptions.pragma || "createElement", }, local: { type: "Identifier", name: mergedOptions.pragma || "createElement", }, }, { type: "ImportSpecifier", imported: { type: "Identifier", name: mergedOptions.pragmaFrag || "Fragment", }, local: { type: "Identifier", name: mergedOptions.pragmaFrag || "Fragment", }, }, ], source: { type: "Literal", value: mergedOptions.importSource || "react", raw: `"${mergedOptions.importSource}"` || '"react"', }, } : null; const componentNode = { type: "VariableDeclaration", kind: "const", declarations: [ { type: "VariableDeclarator", id: { type: "Identifier", name: mergedOptions.componentName, }, init: { type: "ArrowFunctionExpression", expression: false, generator: false, async: false, params: mergedOptions.passProps ? [ { type: "Identifier", name: "props", }, ] : [], body: { type: "BlockStatement", body: [ { type: "ReturnStatement", argument: previousNodeBody.expression, }, ], }, }, }, ], }; const componentWithNamedExport = [ { type: "ExportNamedDeclaration", declaration: componentNode, specifiers: [], source: null, }, ]; const componentWithDefaultExport = [ componentNode, { type: "ExportDefaultDeclaration", declaration: { type: "Identifier", name: mergedOptions.componentName, }, }, ]; if (importDeclaration) { node.body = mergedOptions.defaultExport ? [importDeclaration, ...componentWithDefaultExport] : [importDeclaration, ...componentWithNamedExport]; } else { node.body = mergedOptions.defaultExport ? componentWithDefaultExport : componentWithNamedExport; } } if (mergedOptions.passProps && node.type === "JSXOpeningElement" && node.name.type === "JSXIdentifier" && node.name.name === "svg") { node.attributes.push({ type: "JSXSpreadAttribute", argument: { type: "Identifier", name: "props" }, }); } }, fallback: function (node) { if (node.type === "JSXFragment") return ["children"]; if (node.type === "JSXElement") return ["openingElement"]; if (node.type === "JSXOpeningElement") return ["attributes", "name", "selfClosing"]; if (node.type === "JSXAttribute") return ["name", "value"]; if (node.type === "JSXIdentifier") return ["name"]; if (node.type === "JSXSpreadAttribute") return ["argument"]; throw new Error("unknown node: " + node.type); }, }); return esTree; }; exports.toEstreeComponent = toEstreeComponent;