MDX

Using MDX with renoun.

This guide will help you understand how to use MDX with renoun.

What is MDX?

MDX is a format that allows you to write JSX directly within Markdown documents. This lets you embed React components and JSX elements inside your Markdown files, creating interactive and dynamic content. MDX works seamlessly with renoun, making it a powerful tool for your documentation needs.

MDX component

The easiest way to get started using MDX with renoun is with the MDX component:

import { MDX } from 'renoun/components'

const content = `
# Hello, world!

This is an MDX file.
`

export default function Page() {
  return <MDX>{content}</MDX>
}

In this example, the MDX component renders a string of MDX content. It parses the MDX and converts it into React components that can be rendered in your application.

MDX with Next.js

If you’re working with Next.js, configuring MDX with renoun is straightforward. We have a dedicated guide that walks you through the process of setting it up with your Next.js project.

To learn how to configure MDX with Next.js, check out the Next.js Guide.

Pre-configured Plugins

The renoun/mdx import includes pre-configured plugins for both remark and rehype, which are part the MDX process that parses and transforms MDX content.

You can import these respective plugins and add them to your MDX configuration to extend the functionality of your MDX content.

import { remarkPlugins, rehypePlugins } from 'renoun/mdx'

Here’s a list of the plugins and their effects:

Community Plugins

remark-gfm

Adds support for GitHub Flavored Markdown (GFM) to MDX.

  • Enables strikethrough, tables, task lists, and URLs directly in MDX.
  • Enhances the readability and functionality of markdown content.

remark-smartypants

Transforms punctuation in MDX to typographically correct symbols using SmartyPants.

  • Straight quotes ( " and ' ) into “curly” quote HTML entities
  • Dashes ( -- and --- ) into en- (–) and em-dash (—) entities
  • Three consecutive dots ( ... ) into an ellipsis entity …

remark-strip-badges

Strips out badges, which are often used in README files.

remark-squeeze-paragraphs

Cleans up the document by removing unnecessary empty paragraphs which can be caused by packages like remark-strip-badges.

rehype-infer-reading-time-meta

Infers reading time metadata for MDX content.

rehype-unwrap-images

Ensures that images are not wrapped in paragraph tags.

renoun plugins

In addition to the community plugins listed above, renoun adds specific custom plugins to further extend the capabilities of MDX content.

remark add-headings

Adds an id to all headings and exports a headings variable.

remark remove-immediate-paragraphs

Removes paragraph elements added around immediate element and component children.

For example, when using elements like div, this will remove the paragraph element added around the text content:

<div>
  An example of using a longer sentence in an element that when formatted by
  tools like Prettier will be moved to a new line.
</div>

If you’d like MDX to still wrap the text contents in a paragraph element, you can use a line break before and after the content like so:

<div>

By adding a line break before and after the content, MDX will now wrap this text in a paragraph element.

</div>

Reformats all relative links that use ordered numbers and extensions. For example, ./01.introduction.mdx will be transformed to ./introduction.

rehype add-code-block

Parses the meta string from code fences as props and replaces the parent pre element with a CodeBlock element.

To configure the CodeBlock component, either configure the providerImportSource in your MDX configuration which will configure the default CodeBlock component:

next.config.ts
import createMDXPlugin from '@next/mdx'
import addCodeBlock from '@renoun/mdx/rehype/add-code-block'

const withMDX = createMDXPlugin({
  options: {
    providerImportSource: 'renoun/mdx/components',
    rehypePlugins: [addCodeBlock],
  },
})

Or import and pass CodeBlock as a component to the MDX component:

import { CodeBlock } from 'renoun/components'
import GettingStarted from './docs/getting-started.mdx'

export default function Page() {
  return <GettingStarted components={{ CodeBlock }} />
}

rehype add-reading-time

Exports the reading time metadata added by rehype-infer-reading-time-meta as a readingTime variable.

Applying plugins

By default, the MDX component configures both the remark and rehype plugins from renoun/mdx. You can import and apply individual plugins to the MDX component or any other MDX configuration in your application.

We’ll use the example from before and add the renoun/mdx/rehype/add-code-block plugin to the MDX component:

import { MDX } from 'renoun/components'
import addCodeBlock from '@renoun/mdx/rehype/add-code-block'

const content = `
# Hello, world!

This is an MDX file.
`

export default function Page() {
  return <MDX rehypePlugins={[addCodeBlock]}>{content}</MDX>
}

Note, by overriding the rehypePlugins it will remove the default renoun/mdx rehype plugins. If you want to keep the default plugins, you can import and apply them to the MDX component and add your own plugins:

import { MDX } from 'renoun/components'
import { rehypePlugins, remarkPlugins } from 'renoun/mdx'
import remarkFrontmatter from 'remark-frontmatter'
import remarkMdxFrontmatter from 'remark-mdx-frontmatter'

const content = `
---
title: Hello, world!
---

# Hello, world!

This is an MDX file.
`

export default function Page() {
  return (
    <MDX
      remarkPlugins={[
        ...remarkPlugins,
        remarkFrontmatter,
        remarkMdxFrontmatter,
      ]}
      rehypePlugins={rehypePlugins}
    >
      {content}
    </MDX>
  )
}

Conclusion

MDX is a powerful tool that can be used to create interactive and dynamic content in your documentation. By using the MDX component and custom plugins, you can easily render MDX content in your components and extend the functionality of the MDX rendering process.