From f3d52ecd7371273c0a82dfaf9a6897286e464250 Mon Sep 17 00:00:00 2001 From: Omar Nasr Date: Wed, 3 Jan 2024 10:51:16 -0500 Subject: [PATCH 1/5] initial svgr transform --- src/transforms/svgToSVGR.js | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/transforms/svgToSVGR.js diff --git a/src/transforms/svgToSVGR.js b/src/transforms/svgToSVGR.js new file mode 100644 index 0000000..499011a --- /dev/null +++ b/src/transforms/svgToSVGR.js @@ -0,0 +1,75 @@ +import { namedTypes as n } from "ast-types"; + +/** + * Type definitions for VSCode autocompletion! + * + * @typedef {Object} TransformParams + * @property {*} ast - The resulting AST as parsed by babel + * @property {import("ast-types/gen/builders").builders} builder - Recast builder for transforming the AST + * @property {*} options - Options passed into the transform from the CLI (if any) + */ + +/** + * @param {TransformParams} param0 + * @returns {import("ast-types").Visitor} + */ +const transform = ({ builder }) => { + const importReplacements = {}; + + return { + visitImportDeclaration(path) { + const node = path.node; + const source = node.source.value; + + // Check if the source ends with '.svg' + if (source.endsWith(".svg")) { + const sourceArray = source.split("/"); + const fileName = sourceArray.pop() + + // Generate the new import name + const newImportName = fileName + .replace(".svg", "") + .split("-") + .map(s => s.charAt(0).toUpperCase() + s.slice(1)) + .join(""); + + const oldImportName = node.specifiers[0].local.name; + + // Remember the replacement + importReplacements[oldImportName] = newImportName; + + + // Change the import source + node.source.value = sourceArray.join("/") + "/" + newImportName; + + // Change the import default specifier + node.specifiers[0].local.name = newImportName; + } else if (source.endsWith(".svg?url")) { + // If the source ends with '.svg?url', just remove '?url' + node.source.value = source.replace("?url", ""); + } + + return false; + }, + visitJSXElement(path) { + const { node } = path; + + // If this JSX element's name is one of the old import names + if ( + n.JSXIdentifier.check(node.openingElement.name) && + importReplacements.hasOwnProperty(node.openingElement.name.name) + ) { + // Replace it with the new import name + const newImportName = importReplacements[node.openingElement.name.name]; + node.openingElement.name = builder.jsxIdentifier(newImportName); + if (node.closingElement) { + node.closingElement.name = builder.jsxIdentifier(newImportName); + } + } + + return false; + }, + }; +}; + +export { transform }; From 3b7f1c606eb0074e5e8631c4bcbc95f29eab728d Mon Sep 17 00:00:00 2001 From: Omar Nasr Date: Wed, 3 Jan 2024 11:32:52 -0500 Subject: [PATCH 2/5] initial export transformation --- src/transforms/svgToSVGR.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/transforms/svgToSVGR.js b/src/transforms/svgToSVGR.js index 499011a..6cd3f68 100644 --- a/src/transforms/svgToSVGR.js +++ b/src/transforms/svgToSVGR.js @@ -51,6 +51,20 @@ const transform = ({ builder }) => { return false; }, + visitExportNamedDeclaration(path) { + const { node } = path; + + if (node.specifiers && node.specifiers.length > 0) { + node.specifiers.forEach(specifier => { + if (importReplacements.hasOwnProperty(specifier.exported.name)) { + const newImportName = importReplacements[specifier.exported.name]; + specifier.local = builder.identifier(newImportName); + } + }); + } + + return false; + }, visitJSXElement(path) { const { node } = path; From 1d47cea29aaccf6877d3bd5578e7f85f6ef94b01 Mon Sep 17 00:00:00 2001 From: Omar Nasr Date: Wed, 3 Jan 2024 13:46:21 -0500 Subject: [PATCH 3/5] export transformation --- src/transforms/svgToSVGR.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/transforms/svgToSVGR.js b/src/transforms/svgToSVGR.js index 6cd3f68..6a52ea7 100644 --- a/src/transforms/svgToSVGR.js +++ b/src/transforms/svgToSVGR.js @@ -56,9 +56,21 @@ const transform = ({ builder }) => { if (node.specifiers && node.specifiers.length > 0) { node.specifiers.forEach(specifier => { - if (importReplacements.hasOwnProperty(specifier.exported.name)) { - const newImportName = importReplacements[specifier.exported.name]; - specifier.local = builder.identifier(newImportName); + const oldExportName = specifier.exported.name; + if (importReplacements.hasOwnProperty(oldExportName)) { + const newImportName = importReplacements[oldExportName]; + + // Insert const declaration before the export declaration + const constDeclaration = builder.variableDeclaration("const", [ + builder.variableDeclarator( + builder.identifier(oldExportName), + builder.identifier(newImportName) + ), + ]); + path.insertBefore(constDeclaration); + + // Change the local name to the old export name + specifier.local.name = oldExportName; } }); } From d37f88bd2ab21bf57f5a4016aa04f92e4e82cad7 Mon Sep 17 00:00:00 2001 From: Omar Nasr Date: Wed, 3 Jan 2024 13:51:22 -0500 Subject: [PATCH 4/5] add SVGComponent postfix --- src/transforms/svgToSVGR.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transforms/svgToSVGR.js b/src/transforms/svgToSVGR.js index 6a52ea7..edfdeec 100644 --- a/src/transforms/svgToSVGR.js +++ b/src/transforms/svgToSVGR.js @@ -31,7 +31,7 @@ const transform = ({ builder }) => { .replace(".svg", "") .split("-") .map(s => s.charAt(0).toUpperCase() + s.slice(1)) - .join(""); + .join("") + "SVGComponent"; const oldImportName = node.specifiers[0].local.name; From bc7d90a1c43e8f3cb09542d954f943d782b70c7c Mon Sep 17 00:00:00 2001 From: Omar Nasr Date: Wed, 3 Jan 2024 15:37:18 -0500 Subject: [PATCH 5/5] add SVGComponent postfix --- src/transforms/svgToSVGR.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/transforms/svgToSVGR.js b/src/transforms/svgToSVGR.js index edfdeec..6523102 100644 --- a/src/transforms/svgToSVGR.js +++ b/src/transforms/svgToSVGR.js @@ -31,19 +31,19 @@ const transform = ({ builder }) => { .replace(".svg", "") .split("-") .map(s => s.charAt(0).toUpperCase() + s.slice(1)) - .join("") + "SVGComponent"; + .join(""); const oldImportName = node.specifiers[0].local.name; // Remember the replacement - importReplacements[oldImportName] = newImportName; + importReplacements[oldImportName] = newImportName + "SVGComponent"; // Change the import source node.source.value = sourceArray.join("/") + "/" + newImportName; // Change the import default specifier - node.specifiers[0].local.name = newImportName; + node.specifiers[0].local.name = newImportName + "SVGComponent"; } else if (source.endsWith(".svg?url")) { // If the source ends with '.svg?url', just remove '?url' node.source.value = source.replace("?url", "");