Syntax Highlighting with MDX in Next.js

If you write about programming, devops, machine learning, data journalism and lots of other stuff that need any kind of code in the content, I would suggest adding syntax highlighting to your articles to make things a little clearer.

I just re-launched this blog with Next.js and MDX for content and I needed a plugin to highlight syntax in code blocks (because apparently I have those a lot) and I found a post by Colin that really helped to get things going. However, apparently languages like Elixir and nginx configs are not included by default, so I needed a little more config.

Enabling Syntax Highlighting in MDX

The code below is in my [slug].js file, which displays a single post.

<article className="post">
  <PostsMeta thumbnailURL={thumbnailURL} title={title} slug={slug} description={description} />
  <FeaturedImage thumbnailURL={thumbnailURL} />
  <h1>{title}</h1>
  <MDXRemote {...mdxSource} />
</article>

The mdxSource is our main content, which we need to pass to the syntax highlight plugin like rehype-highlight

Add Missing Language to Rehype Highlight

We're both going to import some additional languages and define an alias, because there is a 0 percent change I will ever get right if it's docker or dockerfile when defining a code block, so both '```docker' and '```dockerfile' will both work.

import rehypeHighlight from "rehype-highlight";
import langNginx from 'highlight.js/lib/languages/nginx'
import langElixir from 'highlight.js/lib/languages/elixir'
import langDockerfile from 'highlight.js/lib/languages/dockerfile'

import 'highlight.js/styles/a11y-dark.css'

const languages = {
	nginx: langNginx,
	elixir: langElixir,
	dockerfile: langDockerfile
}

const aliases = { dockerfile: 'docker' }

// ...

const mdxSource = await serialize(content, {
	mdxOptions: {
		rehypePlugins: [[rehypeHighlight, {
			ignoreMissing: true,
			languages,
			aliases 
		}]]
	},
});

lastly we're passing the plugin to rehypePlugins. Note that this is an array and just like with webpack plugins the second index has the options, in this case: { ignoreMissing: true, languages, aliases }. If you don't set ignoreMissing your compilation might fail.

This is what the error message looks like when building with next.js:

Error occurred prerendering page "/p/deploying-a-vue-js-single-page-app-including-router-with-docker". Read more: https://nextjs.org/docs/messages/prerender-error
Error: [next-mdx-remote] error compiling MDX:
Unknown language: `docker` is not registered                                                            
  37 |
  38 | <strong>Dockerfile</strong>
> 39 | ```docker
     | ^
  40 | # Create the container from the alpine linux image 
  41 | FROM alpine:3.7

These errors will also occur if your code should start directly after the backticks. You can see a full list of supported languages here: highlight js languages.

There is some support for jsx in highlight.js at the moment, for full support you can check out rehype-prism

Tagged with: #mdx #rehype #next.js

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!