Skip to content

Instantly share code, notes, and snippets.

@josefaidt
Last active January 25, 2023 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josefaidt/aca65f4a537caaa84ce3419107715c1a to your computer and use it in GitHub Desktop.
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
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;
type RecmaMdxFrontmatterPluginOptions = {
// maybe we'll add something here
name: string = 'frontmatter';
};
/// <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