Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A codemod that moves blog metadata to an object.
const transform = (file, api) => {
// Alias the jscodeshift API for ease of use.
const j = api.jscodeshift;
// Convert the entire file source into a collection of nodes paths.
const root = j(file.source);
const LAST_IMPORT = root.find(j.ImportDeclaration).at(-1);
const blogPageProps = [
{ name: "dateTime", type: "Literal", metaName: "publishedAt" },
{ name: "description", type: "Literal", metaName: "summary" },
{ name: "ogImage", type: "Literal", metaName: "image" },
{ name: "title", type: "Literal", metaName: "title" }
];
const metaProps = [];
root
// Find the h1 JSX element...
.findJSXElements("h1")
.replaceWith(() => {
return "<h1>{meta.title}</h1>";
});
const blogPage = root
// Find all JSX elements with the name BlogPage
.findJSXElements("BlogPage");
blogPageProps.forEach(prop => {
blogPage
.find(j.JSXAttribute, {
name: {
type: "JSXIdentifier",
name: prop.name
},
value: {
type: prop.type
}
})
// narrowed down to the string value...
.find(j.Literal)
// and replace the existing node with a new JSX expression with the new definition.
.replaceWith(nodePath => {
const { node } = nodePath;
metaProps.push({ key: prop.metaName, value: node.value });
return j.jsxExpressionContainer(j.identifier(`meta.${prop.metaName}`));
});
});
// Add the meta object after the imports.
const metaPropsStrings = metaProps.map(
prop => `\n ${prop.key}: "${prop.value}"`
);
LAST_IMPORT.insertAfter(`export const meta = {${metaPropsStrings}
};`);
return root.toSource();
};
export default transform;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.