Making A Syntax Highlighter Using CodeMirror For ReactJS
I’m developing a Markdown editor called Inkdrop and it provides beautiful syntax highlighting in code blocks. To implement this feature, I…
I’m developing a Markdown editor called Inkdrop and it provides beautiful syntax highlighting in code blocks. To implement this feature, I checked many syntax highlighters out there but I ended up making another one. It works great with React and requires no dangerouslySetInnerHTML
. It supports many languages out of the box. I’d like to introduce it because it’d be a small tip for those who have similar requirements with me.
Two Problems with CodeMirror and highlight.js
Inkdrop’s Markdown editor is based on CodeMirror which is a versatile text editor component built for browsers. It provides built-in syntax highlighter, so users can edit text on the beautiful interface. On the other hand, Inkdrop was using highlight.js for the Markdown preview pane. This composition worked great but had two problems.
The first reason is that highlight.js doesn’t support some languages that CodeMirror supports (and vice versa). Users were sometimes confused by this difference between the editor and the preview, and they thought “Why doesn’t it render Markdown in the same way?”
The second is that highlight.js and other similar libraries require a render function using dangerouslySetInnerHTML
on React or just manually altering the DOM with native javascript. This is not so performant because it needs completely rebuild DOMs every time you change the text. This problem could be solved with lowlight, the fantastic work done by Titus, which outputs virtual DOMs and is compatible with highlight.js. It worked great but the first problem was still existing.
So I decided to make a solution like lowlight but compatible with CodeMirror.
CodeMirror As A Syntax Highlighter
I noticed that CodeMirror provides a mode runner which lets you run it as a syntax highlighter. You can check the demo here. CodeMirror.runMode
is a function that takes the following arguments:
text
(string): The document to run through the highlighter.mode
(mode spec): The mode to use. e.g.,javascript
output
(function or DOM node) : If this is a function, it will be called for each token with two arguments, the token’s text and the token’s style class (may benull
for unstyled tokens). If it is a DOM node, the tokens will be converted tospan
elements as in an editor, and inserted into the node (throughinnerHTML
).
The third argument accepts a function that allows you to generate virtual DOMs from text! That’s a good news. You can make a React component using runMode
like this:
Then, you can use it as following:
That works great. I made a simple library with some features that would make it more comfortable to use in your React applications, like theme
prop. This library is being used in Inkdrop now :D
I hope this article is helpful!
- craftzdog/react-codemirror-runmode — Syntax highlighting for react, utilizing CodeMirror’s parser
- lowlight — Virtual syntax highlighting for virtual DOMs and non-HTML things