Last active
January 25, 2023 16:26
-
-
Save josefaidt/aca65f4a537caaa84ce3419107715c1a to your computer and use it in GitHub Desktop.
RECMA MDX Frontmatter plugin to transform props generated from remark-mdx-frontmatter and feed into wrapper component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { MDXProvider as StockMDXProvider } from '@mdx-js/react'; | |
import type { PropsWithChildren } from 'react'; | |
const wrapper = ({ children, frontmatter }) => { | |
console.log('mdx page props', { props: { frontmatter } }); | |
return <Page meta={frontmatter}>{children}</Page>; | |
}; | |
const shortcodes = { | |
wrapper | |
}; | |
type MDXProviderProps = PropsWithChildren<{}>; | |
function MDXProvider ({ children }: MDXProviderProps) { | |
return ( | |
<StockMDXProvider components={shortcodes}>{children}</StockMDXProvider> | |
); | |
}; | |
export default MDXProvider; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type RecmaMdxFrontmatterPluginOptions = { | |
// maybe we'll add something here | |
name: string = 'frontmatter'; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <reference path="./plugins.d.ts" /> | |
import { fromJs } from 'esast-util-from-js'; | |
import { visit } from 'estree-util-visit'; | |
/** | |
* Plugin to pass frontmatter to getStaticProps and into MDXProvider's `wrapper` | |
* @returns {import('unified').Plugin<[RecmaMdxFrontmatterPluginOptions], import('estree').Program>} | |
*/ | |
export const recmaMdxFrontmatter = (options) => { | |
const { name = 'frontmatter' } = options || {}; | |
/** | |
* Transformer | |
* @param {import('estree').Program} tree | |
*/ | |
const transformer = (tree) => { | |
const frontmatter = {}; | |
visit(tree, (node) => { | |
// look for `frontmatter` variable created by remark-mdx-frontmatter | |
if (node.type === 'VariableDeclarator' && node.id.name === name) { | |
if (!Array.isArray(node.init.properties)) return; | |
// collect frontmatter props | |
for (const prop of node.init.properties) { | |
frontmatter[prop.key.value] = prop.value.value; | |
} | |
} | |
}); | |
// create `getStaticProps` to feed frontmatter to MDXProvider's `wrapper` | |
const getStaticProps = fromJs( | |
` | |
export const getStaticProps = async () => { | |
return { | |
props: { | |
frontmatter: ${JSON.stringify(frontmatter)} | |
} | |
} | |
} | |
`, | |
{ | |
// sourceType: 'module', | |
module: true | |
} | |
); | |
// push `getStaticProps` to end of tree | |
tree.body.push(...getStaticProps.body); | |
}; | |
return transformer; | |
}; | |
export default recmaMdxFrontmatter; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment