react-markdown with custom renderers

react-markdown with custom renderers

Published on: 2 November 2020

Author: Ramesh Kanjinghat

All the articles I write for https://blogs.dhrutara.com, including the one you are reading now, are stored as markdown files. The front end is built on reactjs and I was looking for an npm package that can render my markdown as html. I tried couple of options and finally decided to use react-markdown[https://github.com/remarkjs/react-markdown]. And I am glad I did so.
react-markdown is a react component so, it is very easy to use.
  • Install react-markdown. I like to add it as dependency in package.json and run npm install --save-dev
  • Import it
1import  ReactMarkdown  from  'react-markdown';
  • Add ReactMarkdown in the jsx like below. In the below code MarkDownText is the markdown you want to render.
1<ReactMarkdown  source={MarkDownText}  escapeHtml={false}  />
With built-in image renderer the images in the markdown are rendered as html img element. Check below screenshot
react-markdown image with built-in renderer
react-markdown image with built-in renderer
react-markdown documentation is very easy to understand and is much easier to use. So, this blog is not about the usage of react-markdown, instead I would like to talk about how you can extend the behavior to suit your requirements. Sometimes you might have specific requirements that react-markdown doesn't support out of box. While writing blogs for https://blogs.dhrutara.com I needed to render images as html figure element with figurecaption but react-markdown renders it as plain html img element.
So, I have defined a custom renderer and registered it with react-markdown.
Step1: First define a custom react component where you can render it as you like it. My ImageRenderer component is as below
1export  default  function  ImageRenderer(props) {
2const  imageSrc = props.src;
3const  altText = props.alt;
4return (
5<figure  className="wp-block-image size-large is-resized">
6<img data-loading="lazy" data-orig-file={imageSrc}
7data-medium-file={imageSrc + "?w=300"}
8data-large-file={imageSrc + "?w=750"}
9src={imageSrc}
10alt={altText}
11srcSet={imageSrc + "?w=1024 1024w, " + imageSrc + "?w=705 705w, " + imageSrc + "?w=150 150w, " + imageSrc + "?w=300 300w, " + imageSrc + "?w=768 768w, " + imageSrc + "?1248w"}
12sizes="(max-width: 707px) 100vw, 707px"  />
13<figcaption  style={{ textAlign:  "center" }}>{altText}</figcaption>
14</figure>
15);
16}
When you define a custom renderer as a react component and register with react-markdown, it passes the required properties as props to the custom renderer component. In the above code you can see that both image source and alternate text are passed as properties of props object. And the names of these properties exactly match the properties of the html component.
Step2: Once the customer renderer is defined, import the component in the code where you want to use ReactMarkdown and let it know that you want to use custom renderer for images. I have given below the code that use ReactMarkdown with my custom image renderer, ImageRenderer. ReactMarkdown has property called renderers which takes collection of custom renderers. This is the property that you use to register your custom image renderer with ReactMarkdown.
To keep it simple I am using ReactMarkdown in app component. The code is given below
1import  './App.css';
2import  ImageRenderer  from  '../src/components/image-renderer';
3import  ReactMarkdown  from  'react-markdown';
4const  MarkDown = `# Sample markdown that will be rendered as html
5## Header2
6### Header3
7### This image will be rendered as html element figure with figurecaption.
8![A sample image](/images/Screenshot.jpg)
9### Complete`;
10function  App() {
11return (
12</div>
13<ReactMarkdown  source={MarkDown}  escapeHtml={false}  renderers={{ "image":  ImageRenderer }}/>
14</div>
15);
16}
17export  default  App;
With custom image renderer the images in markdown will be rendered as figure with figurecaption. Check the screenshot below
react-markdown image with built-in renderer
react-markdown image with built-in renderer
I have a working version of this code in github, [https://github.com/Dhrutara/blogs.dhrutara.com.blogs/tree/main/react-markdown%5D(https://github.com/Dhrutara/blogs.dhrutara.com.blogs/tree/main/react-markdown. I have couple of custom renderers. Please feel free to check and use it in your application).
Happy markdown rendering!!