Syntax Highlighting
Unfortunately I spoke too soon when I wrote the Building this Site post. I had a plan in place to use hilite
, along with TextMate grammars and themes pulled from Shiki (which in turn gets its grammars and themes from TextMate/VSCode), but it fell through.
The Plan
The plan was to grab lightmode and darkmode themes from Shiki's trove of themes, stripping out any extraneous styles (a lot of text-editor-specific colors are given) to arrive at two sets of colors for pre-determined class names. Shiki works similarly to hilite
: during processing it tags portions of the source code with CSS tags derived from the grammars. All of the TextMate grammars employed by Shiki use a consistent naming scheme, ensuring themes always line up with the grammars, resulting in colored text. With a little adjustment of the theme CSS tags to account for any differences between Hilite's and Shiki's tagging, I'd have ahead-of-time syntax highlighting, with as many supported languages as VSCode.
Speedbumps
hilite tags a captured code block with a language-specific CSS class
By design hilite
prepends the identified language name onto the grammar-specified name for the code block. This blocks my plan by requiring additional CSS class definition for every new language being highlighted. Nothing to fear though, in the short term I can pull in the library source code in order to change that single expression, and long term work with the library maintainer on how to make this configurable.
Success: I use Shiki's more complicated OCaml grammar, since it has CSS class tags that match the highlighting themes, and I get highlighted OCaml code!
Shiki and VSCode are more lenient when interpreting TextMate grammars
I didn't want to stop at only having OCaml highlighted. I expect I'll show some random shell scripts from time to time. So I pull in the grammar for shellscript and receive an exception when highlighting shellscript. It turns out that textmate-language
is either strict with grammar intepretation (good IMO, in keeping with OCaml's spirit), OR Shiki/VSCode have builtins I don't know how to find. The failure comes from an Unknown repository key
.
🤔 In for a penny, in for a pound I guess. I pull in the source code of textmate-language
. I try a couple of uneducated guesses — either barely anything gets highlighted, or the program falls into an infinite loop. I think: maybe it's just this shellscript grammar, the OCaml grammar was fine, let me try out the HTML grammar. It is similarly broken. I give up.
Resolution
Ultimately I had to give up on doing code syntax highlighting as part of my static site build. As this website is mainly for fun, I'm not (right now) interested in learning the ins and outs of the TextMate syntax grammar and how to interpret/execute it, such that my speedbumps would be understandable and fixable. Additionally I am trying to keep down the number of dependencies, so I am not trying to introduce a dependency on NodeJS just to statically highlight code in my blog posts. So I split the difference.
I went with client-side rendering of syntax highlighting, picking a much smaller runtime than Shiki — Prism.js. I include their minified engine and a hand-selected set of languages I expect I'll want highlighted, and a lightly modified CSS file containing their Default and Okaidia themes, switching based on the user's preferred light/dark mode. This is combined with a code
template builtin that attaches the CSS and JS to the page, ensuring highlighting is only loaded for the pages that need it.
Et voilà:
{code(ocaml)/}
let foo = bar + 1
{/code}