Highlight code blocks in Markdown files with React-Markdown and React-Syntax-Highlighter libraries

December 20th, 2021

react markdown

In this post, lets cover how to highlight code blocks which we save in Markdown files. Markdown files are typically used to type out content for blog posts and articles - like this very article here! And in a technology blog - it is kind of necessary otherwise you end up with a rather drab set of lines inside a pre block on the page which doesn't follow any of the styling people familiar with a particular language are used to.

const CheckOutMyCodeBlock = () => { return( <> <p> This styled block of jsx is rendered on this page from a Markdown file with React-Markdown and React-Syntax-Highlighter. </p> </> ); }

If you are interested in learning how to build your own Markdown Blog in Nextjs - check out this link.

Alright, first a few words on the background and then lets dive into the code...which will of course be highlighted!

Markdown, Code Blocks and how they are normally rendered into HTML

Markdown is a format that allows for writing content that can naturally be rendered into HTML supporting various "marks" and such that will get translated into appropriate styles - like adding text between two stars **will bold** text so it appears within <strong> tags when it is rendered in HTML.

There are many libraries available that are capable of doing the rendering for us - typically this involved reading your Markdown files at build time and passing the string to a library to generate HTML that ultimately gets served.

In this post we will use the React-Markdown library to do the rendering.

Code blocks - or code snippets are typically identified in Markdown between these symbols - ```jsx jsx code here``` and get rendered between pre formatted HTML tags - <pre>. This usefully identifies the language of the content - allowing us to style the specific language according to its typical code editor style.

For this, we will be using the React-Syntax-Highlighter library.

These two libraries work great together...but I did struggle to find sufficient documentation on either of their github pages on working together.

This is how I was able to get them to play nice.

Installing dependencies

Lets install the libraries we need.

npm install react-markdown npm install react-syntax-highlighter npm install rehype-raw

We spoke about the first two in the prior section - rehype-raw on the other hand is needed to escape HTML and will allow react-markdown to play nice with react-syntaax-highlighter.

rehype-raw will allow us to work with more than just react-syntax-highlighter and use other React Components - but that is for another discussion.

Passing Markdown content to React Markdown

Check this article for all the details of parsing Markdown files - here will are keeping the "highlight" on the topic and assumes you already have some Markdown content available to pass as a child prop to React Markdown

import ReactMarkdown from 'react-markdown'; import gfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'; ... ... ... //inside the page component... //{markdown} is the content we want to render //{CodeBlock} - we will be discussing this next <article className="prose prose-lg prose-blue max-w-none"> <ReactMarkdown rehypePlugins={[rehypeRaw]} components={CodeBlock} > {markdown} </ReactMarkdown> </article>

We have ReactMarkdown component with rehypeRaw as one of the props. React Markdown allows us to define custom components that we can define to take care of specific sections of the Markdown - here we are going to ask our CodeBlock component to apply styles to code blocks in our markdown.

Lets see how to define that.

Defining a code block handler to highlight styles with React Syntax Highlighter

const CodeBlock = { code({ node, inline, className, children, ...props }) { const match = /language-(\w+)/.exec(className || ''); return !inline && match ? ( <SyntaxHighlighter style={vscDarkPlus} language={match[1]} PreTag="div" {...props} > {String(children).replace(/\n$/, '')} </SyntaxHighlighter> ) : ( <code className={className} {...props}> {children} </code> ); }, };

This is based on the signature in React Markdown for custom component handling. Basically we are looking for sections of the markdown which have the "language-{language-name}" defined in the markdown when we do ```python for example - then we are providing that to React Syntax Highlighter with the language and the style and asking React Syntax Highlighter to style the div.

Conclusion

And now we are good to roll. Give it a whirl with your code blocks - and choose which style works best for your site.