Syntax highlighting

In the previous article about WebP fallback, I wrote my first multiline code snippet on the site. In order to get the lines and spaces to work as expected, I added white-space: pre; to the <code> blocks that was generated from Contentful. It looked fine on desktop, so I hit “publish”, and went about my day. Later on, when showing a friend the site on my phone, I realized that the multiline code blocks caused a horizontal overflow on smaller viewports—how embarrassing!

Foreseeing future articles with multiline code snippets, I figured I should look into syntax highlighting. I didn’t spend too much time researching libraries before landing on Prism.js. I wrote a custom Contentful node renderer to intercept the <code> tag and reformat it using Prism.js. First, I detected if the code snippet is multiline or inline by checking for any newlines. If it’s multiline, I wrap the <code> block with a <pre> tag.

Prism supports about 200 programming languages, so I can highlight pretty much any language by specifying it. By default, I use markup as the language to handle generic code snippets, but I built a simple syntax for specifying the language, which looks like javascript:`const foo = 'bar';`. It’s not entirely standard, but works for now. Here’s an example of a multiline code block, which uses the default markup language:

  <h1 class='title'>Hello world!</h1>
  <p class='body'>This is my code snippet.</p>

And an example using a specified language:

import Foo from 'bar';

const foo = new Foo({ el: document.querySelector('#foo') });

Syntax highlighting is great, but it comes at a cost. Already, my Lighthouse score has dipped, so I’ll be looking at ways to improve it. The main issues involve color contrast for accessibility—an easy fix—and first meaningful paint, which might require some work. I imagine I’ll need to pull syntax highlighting out of the server-side rendering, so it executes asynchronously. I’m not too worried, but I am happy with this progress.