Random Thoughts

This blog development process

Creating React component with Markdown renderer and code syntax highlight

Saturday, March 17th, 2018

Markdown is pretty nice. As maybe you already know, this blog is based on static markdown files. FrontMatter files to be more precise. Check out the source file of this post. Now let me tell you how I do the render the content of the markdown files.

There are actually many ways to deal with this situation. One for instance, as in this site's storybook docs, it uses Webpack loader to import Markdown files directly to JavaScript. Simple as import Content from 'content.md' and then the imported data can be rendered using something like the dangerouslySetInnerHTML.

But more specifically for the content of this site, the data generator is returning the markdown content into a static JSON file. Not yet parsing it to HTML. In order to use that markdown string to render in the page, first, it needs to be parsed to HTML and then rendered as JSX.

I've used some third-party libraries to help me with the heavy lifting:

There's not much secret, all those libraries have good documentation. Go for it and install the packages:

yarn add marked react-render-html highlight.js

Then create a component to wrap this rendering logic, so this way you can simply reuse the same logic everywhere.

The MarkdownRenderer component

This is how my React component looks like:

// MarkdownRenderer.js
import { PureComponent } from 'react'
import marked from 'marked'
import renderHTML from 'react-render-html'
import hljs from 'highlight.js'
import 'highlight.js/styles/tomorrow-night-eighties.css'

marked.setOptions({
  highlight: (code, language) => language
    ? hljs.highlight(language, code).value
    : hljs.highlightAuto(code).value
})

class MarkdownRenderer extends PureComponent {
  static defaultProps = {
    text: '',
  }

  render() {
    const { text } = this.props
    return text ? renderHTML(marked(text)) : null
  }
}

export default MarkdownRenderer

See it in the source code.

Extra goodies

The highlight.js will try to identify the code language automatically and create styles as better as possible. Even so using it with marked also allows to define the language on code blocks, as in:

// markdown-file.md
```javascript
function() {
  console.log('this is actually a "markdown" code block haha')
}
```

[Edit 2018-03-20]

The highlight option I was using when I wrote this post wasn't correctly identifying the languages in the automatic way, then I improved a little bit the MarkdownRenderer.js code:

marked.setOptions({
-  highlight: (code) => hljs.highlightAuto(code).value
+  highlight: (code, language) => language
+    ? hljs.highlight(language, code).value
+    : hljs.highlightAuto(code).value
})