DEV Community

Cover image for Syntax Highlighting in Gatsby MDX
Malik Gabroun
Malik Gabroun

Posted on • Edited on • Originally published at malikgabroun.com

Syntax Highlighting in Gatsby MDX

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
Enter fullscreen mode Exit fullscreen mode

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

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>
    );
  },
};
Enter fullscreen mode Exit fullscreen mode

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).

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>.*)/);
Enter fullscreen mode Exit fullscreen mode

To enable syntax highlighting in MDX files by adding the following snippet below in 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>;
};
Enter fullscreen mode Exit fullscreen mode

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

Originally posted at malikgabroun.com

Top comments (0)