Syntax Highlighting in Gatsby MDX

calendar icon
27 Jan 2020
clock icon
1 min read
Last Updated
calendar icon
29 Oct 2021
Syntax Highlighting in Gatsby MDX

Photo by Estée Janssens

In this post, we will be looking into how to enable syntax highlighting for Gatsby MDX files using prism-react-renderer

first, we need to install a couple of modules

npm i prism-react-renderer @mdx-js/react

Then, we create the component which we will use in the <MDXProvider/> that is going to provide a wrapper replacement for our application.

gatsby-browser.js
const component = {
  pre: (props) => {
    const className = props.children.props.className || "";
    const matches = className.match(/language-(?<lang>.*)/);
    return (
      <Highlight
        {...defaultProps}
        code={props.children.props.children}
        language={
          matches && matches.groups && matches.groups.lang
            ? matches.groups.lang
            : ""
        }
      >
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre className={className} style={style}>
            {tokens.map((line, i) => (
              <div {...getLineProps({ line, key: i })}>
                {line.map((token, key) => (
                  <span {...getTokenProps({ token, key })} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
    );
  },
};

To render the code block we added in MDX file to show up on the page we will access props of the child component of <pre/> component as markdown code blocks get compiled into a <pre/> component wrapping the code component. We can dive a level deeper to get the code by using props.children.props.children, as you can see from the screenshot below.

code-block

To get the language attribute of the code block rather than hardcoding the value we look into MDX code block as it comes through as a class name that will look like language-className (for example language-javascript).

```javascript
const text = 'World'
console.log(`Hello ${text}`)
```

To get the language defined in the code component in the MDX file, we will drill down at props.children.props.className, if there is no class name then we might have not put a language on our code block in which case we will default to empty strings. Then we use a name capture group in regex with the name lang to get the language of the language-className. if there are matches

const matches = className.match(/language-(?<lang>.*)/);

To enable syntax highlighting in MDX files by adding the following snippet below in gatsby-browser.js

gatsby-browser.js
import React from "react";
import { MDXProvider } from "@mdx-js/react";
import Highlight, { defaultProps } from "prism-react-renderer";

/* eslint-disable */
const component = {
  pre: (props) => {
    const className = props.children.props.className || "";
    const matches = className.match(/language-(?<lang>.*)/);
    return (
      <Highlight
        {...defaultProps}
        code={props.children.props.children}
        language={
          matches && matches.groups && matches.groups.lang
            ? matches.groups.lang
            : ""
        }
      >
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre className={className} style={style}>
            {tokens.map((line, i) => (
              <div {...getLineProps({ line, key: i })}>
                {line.map((token, key) => (
                  <span {...getTokenProps({ token, key })} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
    );
  },
};

export const wrapRootElement = ({ element }) => {
  return <MDXProvider components={component}>{element}</MDXProvider>;
};

Following the post and you can find a starter repo here that shows usage of mdx pages and syntax highlighting

If you found this article helpful

You will enjoy these other articles.

How to create pages dynamically in Gatsby using MDX
tag icon

#javascript

#gatsby

How to create pages dynamically in Gatsby using MDX

In this post, we will be looking into how to create pages dynamically using MDX

Subscribe to the newsletter

subscribe to get my latest content, favourite articles from the web and additional details about my launches, products, and experiments