Parsing MDX files
Compile and bundler MDX files with mdx-bundler
Date: 2021-10-23
MDX is an extension of Markdown that allows you to import and write JSX in your markdown documents.
Markdown can be used for creating web pages, documents or any text that needs to be transformed into other formats like For web applications, Markdown needs to be transformed into HTML. But, Using Markdown you can only use HTML elements.
MDX is an extension of Markdown that allows you to import and write JSX in your markdown documents. So, MDX takes the format a step further and allows us to include our own custom React components!
Today, MDX Bundler is arguably the best option for processing MDX in a Nextjs applicattion. mdx-bundler uses esbuild, so it's VERY fast and supports TypeScript files (for the dependencies of your MDX files). It also uses xdm which is a more modern and powerful MDX compiler with no extra runtime requirements.
Here we go -
Install the dependencies for mdx-bundler
# If you're using npm
npm install mdx-bundler esbuild
# If you're using yarn
yarn add mdx-bundler esbuild
Create a directory with MDX files
\posts
\file-1.mdx
\file-2.mdx
\file-3.mdx
Install necessary Plugins
# If you're using npm
npm install reading-time gray-matter rehype-slug rehype-code-titles rehype-autolink-headings rehype-prism-plus
# If you're using yarn
yarn add reading-time gray-matter rehype-slug rehype-code-titles rehype-autolink-headings rehype-prism-plus
- reading-time Estimate an article's reading time
- gray-matter Extend front-matter metadata
- rehype-slug Plugin to add id's to headings
- rehype-code-titles Plugin to add titles for code blocks
- rehype-prism-plus Plugin to add code highlighting
- rehype-autolink-headings Plugin to automatically add link to headings
Parse all MDX files
import matter from 'gray-matter';
import readingTime from 'reading-time';
import { join } from 'path';
import { bundleMDX } from 'mdx-bundler';
import { readdirSync, readFileSync } from 'fs';
/* Rehype Plugins */
import rehypeSlug from 'rehype-slug';
import rehypeCodeTitles from 'rehype-code-titles';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypePrism from 'rehype-prism-plus';
export async function getFiles() {
return readdirSync(join(process.cwd(), 'posts'));
}
export async function getFileBySlug(slug) {
const source = readFileSync(
join(process.cwd(), 'posts', `${slug}.mdx`),
'utf8'
);
const { code, frontmatter } = await bundleMDX(source, {
xdmOptions(options) {
options.rehypePlugins = [
// some good and popular plugins
...(options?.rehypePlugins ?? []),
rehypeSlug,
rehypeCodeTitles,
rehypePrism,
[
rehypeAutolinkHeadings,
{
properties: {
className: ['heading_title']
}
}
]
];
return options;
}
});
return {
code,
frontMatter: {
wordCount: source.split(/\s+/gu).length,
readingTime: readingTime(source),
slug: slug || null,
...frontmatter
}
};
}
export async function getAllFilesFrontMatter() {
const files = readdirSync(join(process.cwd(), 'posts'));
return files.reduce((allPosts, postSlug) => {
const source = readFileSync(
join(process.cwd(), 'posts', postSlug),
'utf8'
);
const { data } = matter(source);
return [
{
...data,
slug: postSlug.replace('.mdx', ''),
readingTime: readingTime(source)
},
...allPosts
];
}, []);
}