Adding code snippets to static markdown in Next.js using react-syntax-highlighter

IMPORTANT NOTE: The below code and examples have tested and work with react-markdown 6.0.2, these examples do not work with version 5 and below

I recently fully converted my WordPress blog completely to static generated Next.js and it came with some difficulties. One problem was that git gists would not easily work in my static markdown files. I needed way to share formatted pieces of code with my users.

So I used react-syntax-highlighter and you should too for highlighting code snippets in your static markdown files in Next.js. You'll see I am using it for all the code snippets in this post.

Step Zero: (Pre-requisites)

If you are already using the React Markdown npm package to render your markdown into HTML then you can skip this step.

In order to allow for code highlighting, we want to be using the React Markdown package to render our markdown. The reason for this is that we can set the renderers property to use our custom code highlighting component.

Install the React Markdown package and place the ReactMarkdown tag where you want your markdown rendered. The children of this tag should be the raw markdown for your posts.

// Command for installing react-markdown npm install react-markdown
<ReactMarkdown>{postData.markdown}</ReactMarkdown>

If you created your Next.js using the starter tutorial provided by Next.js you may be using remark to convert your markdown to HTML. We don't want that and want to use ReactMarkdown like above. If you have the getPostData(id) method, you will want to refactor it to return the markdown data. You can remove the other data returned if you do not need it.

export async function getPostData(id) { const fullPath = path.join(postsDirectory, `${id}.md`) const fileContents = fs.readFileSync(fullPath, 'utf8') // Use gray-matter to parse the post metadata section const matterResult = matter(fileContents) // Use remark to convert markdown into HTML string const processedContent = await remark() .use(html) .process(matterResult.content) const contentHtml = processedContent.toString() // Combine the data with the id and contentHtml return { id, contentHtml, markdown: matterResult.content, ...matterResult.data } }

You see that in the return statement I have added the markdown data. We are then able to access the markdown data and pass that along to our newly added ReactMarkdown package we added.

Step One: Installing react-syntax-highlighter

First, we will install the react-syntax-highlighter package. In the terminal in the root of your project, run the following command:

npm install react-syntax-highlighter --save

This will add react-syntax-highlighter to our package.json.

Step Two: Creating our custom CodeBlock component

Next we will need to create a custom CodeBlock component. This is where we will set the styles and other properties related to the react-syntax-highlighter.

Create a file name codeblock.js in your components folder and add the following code to it.

// components/codeblock.js import React from "react" import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" import {dracula} from 'react-syntax-highlighter/dist/cjs/styles/prism'; const CodeBlock = { code({node, inline, className, children, ...props}) { const match = /language-(\w+)/.exec(className || '') return !inline && match ? ( <SyntaxHighlighter style={dracula} language={match[1]} PreTag="div" {...props}> {String(children).replace(/\n$/, '')} </SyntaxHighlighter> ) : ( <code className={className} {...props}> {children} </code> ) } } export default CodeBlock

The above code will render our code snippet where the {value} tag is. And we are setting a few properties to our Syntax Highlighter such as style & showLineNumbers. For a full list of properties, check out the GitHub Readme for react-syntax-highlighter.

Note: If you want to have any CSS styling around your code snippets, this is a good place to do it. Wrap the <SyntaxHighlighter> in a div or two and add your styling.

Step Three: Using our custom CodeBlock

Now that we have our custom codeblock.js created we need to tell ReactMarkdown to use this when it sees any code blocks. We can do that with the below code.

// Don't forget to import codeblock at the top of your file import CodeBlock from "../../components/codeblock" <ReactMarkdown components={CodeBlock}>{postData.markdown}</ReactMarkdown>

This tells ReactMarkdown that when it is going to render code from our markdown, it should use the CodeBlock component we created.

Step Four: Add code to our markdown files

Now that we have Next.js all ready to format our beautiful code, we need to put some code into our markdown files. For this we use standard markdown syntax, three back ticks ``` to begin the code and three more ``` at the end of our code. These are on the key to the left of number 1. It often helps to put the ticks on their own line as well.

The three ticks signify to expect code in between. And now that we are telling ReactMarkdown how to render our code, you should get syntax highlighting just like in this blog post!