Building your own blog article site and rendering Markdown content with Next.JS isn't difficult - there are a lot of different ways to get the job done. For Serverless DNA we opted to use the react-markdown package which utilises a combination of remark and rehype to process and render the Markdown content into HTML. This provides a good outcome and also provides some control over how particular aspects of Markdown can be rendered. In our builder journey, we found the documentation and examples of customisation for react-markdown to be a little "Hacky".
One of the customisations we made is in the rendering of code blocks, we wanted to add in the Prism SyntaxHighligher which provides themed rendering of code blocks. Integrating the Prism SyntaxHighlighter component is described in the main github page of the npm package, here. As you can see from the in-line sample the customisation for rendering Markdown is handled in the components attribute, which works when applying a single customisation, but when one or more customisations are needed or planned, the code becomes un-maintainable very quickly.
We decided to create our own custom Markdown wrapper component so we could customise markdown rendering and not have to expose that to the main blog pages housing our content. Our custom markdown component is shown below. As you can see the outcome of applying customisations is identical to the react-markdown example, except we are not in-lining our code. Instead we have imported our own rendering functions which enable customisation of Markdown rendering. We have applied custom rendering to code, a, img and blockquote. Image and Links we decided to customise so we could render them using the Next.JS components instead of the existing vanilla HTML tags and blockquote we wanted to provide our own look and feel. For the remainder fo this article we will focus on the CodeHighlight component and how we integrated it.
Rendering Code with Syntax Highlighting
Customising redering of the code markdown block you must provide an function implementation to be called by the Markdown component. In this case you can create a function containing the in-line code and needed to hunt down the Type declaration for the function type. To be able to access the properties for the code block we needed to hunt down the CodeProps that are passed to the rendering function, being new to Typescript this took a little trial and error and detective work. We needed to make sure we found the types passed into the render function and not the return type of the function. To find the actual Property type we needed to explore up the type tree using VS Code through clicking on types and exploring up the hierarchy. We started with Our markdown component whiuch took us to the component return type:
From here you can explore to CodeComponent
and finally we get to CodeProps - this is the one you need!
With this type we are now able to create the rendering function to provide a clean rendering function that also satisfies the strict es-lint rules setup by the default Next.JS project. To keep things clean create a markdown sub-folder in your components folder and place all custom markdown render functions in this folder. In this way we end up with a clean set of files that are easy to find. Each cusomt function is in it's own file and we can import and use these render customisations quickly and easily.
This is how we managed to provide a clean framework to customise rendering of Markdown for Serverless DNA, we hope you find it useful in your Markdown rendering journey. In the following sections is the code for each of our Markdown customisations which you may find useful in your Next.JS project.