Dan Stroot

Parsing MDX files

Compile and bundler MDX files with mdx-bundler

Date:


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 -

1

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
2

Create a directory with MDX files

\posts
  \file-1.mdx
  \file-2.mdx
  \file-3.mdx
3

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
 
4

Parse all MDX files

mdx.js
import { readdirSync, readFileSync } from 'fs'
import { join } from 'path'
import matter from 'gray-matter'
import { bundleMDX } from 'mdx-bundler'
import readingTime from 'reading-time'
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
import rehypeCodeTitles from 'rehype-code-titles'
import rehypePrism from 'rehype-prism-plus'
/* Rehype Plugins */
import rehypeSlug from 'rehype-slug'
 
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,
    ]
  }, [])
}

Resources

Sharing is Caring

Edit this page