Skip to content

Feat/svgr transform #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/transforms/svgToSVGR.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
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 + "SVGComponent";


// Change the import source
node.source.value = sourceArray.join("/") + "/" + newImportName;

// Change the import default specifier
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", "");
}

return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You technically don't need these return false. It was left over in a older transform before I made some other changes.

},
visitExportNamedDeclaration(path) {
const { node } = path;

if (node.specifiers && node.specifiers.length > 0) {
node.specifiers.forEach(specifier => {
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;
}
});
}

return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

},
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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here :)

},
};
};

export { transform };