Highlight code blocks in Markdown files with React-Markdown and React-Syntax-Highlighter libraries
December 20th, 2021
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> </> ); }
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.