Growing with the Web

Multiple language code snippets have been added to the site

Published
Tags:

I finally got around to implementing multiple programming languages to display on a single post.

Problem

It has been a problem for some time that I’ve had no nice way to include code examples in multiple languages without pushing the length of the page up significantly. The main problem is that since the site is written in Jekyll, the code is within a markdown file, which gives me relatively little control over the content if I want to maintain a nice writing format (I could just dump a bunch of HTML in each post, but that would be ugly and lead to consistency issues).

Jekyll has some features that seem like they could help with this problem initially such as includes, data files and static files, however they all fall short in one way or another. Includes (templates) are great and I use them extensively, however there doesn’t seem to be a way to pass in blocks of content in a good way. I did manage to get it working with data files but I would then have to write all my code within a json file (with double spacing for some reason) away from the related content, which is not at all ideal. And static files unfortunately only expose metadata, not file content.

Solution

My solution to this was to approach the problem in a similar manner to another library I utilise, code-prettify, which searches for all elements of types pre, code and xmp, then extracts the configuration from a comment above the element if it exists.

The way I did it was to wrap my code blocks in the markdown file with ‘marker’ elements with classes .code-block.start and .code-block.end. Then extract all pre elements in between the two marker elements and transform them as I please.

<div class="code-block start"></div>

<!--prettify lang=java-->
    int number = 1;

<!--prettify lang=javascript-->
    var number = 1;

<!--prettify lang=python-->
    number = 1;

<div class="code-block end"></div>

It would have been nice to be able to do this with comments instead of divs, but there is no efficient way to look up comments in the DOM. Iterating over the entire tree would not be as performant as I need.

Accessibility

As with the rest of my site, I wanted to get accessibility right. I know that it’s an all too common problem with tab widgets since the heading element is typically separated from the content so it is read in the incorrect order with a screen reader. I solved this by duplicating the heading, having one for display and one for screen readers. The display element is what the user sees on the tab, this is hidden from assistive technology by using aria-hidden="true", and the screen reader element is directly above the code block and contains css to hide it from display.

Here is the structure I used:

<div class="code-block">
  <div>
    <!-- Hidden from assistive technologies -->
    <a aria-hidden="true" class="header">C#</a>
    <a aria-hidden="true" class="header active">Java</a>
  </div>
  <div>
    <!-- Only visible to assistive technologies -->
    <h6 class="screen-reader">C#</h6>
    <pre class="prettyprint prettyprinted"></pre>
  </div>
  <div>
    <!-- Only visible to assistive technologies -->
    <h6 class="screen-reader">C#</h6>
    <pre class="prettyprint prettyprinted"></pre>
  </div>
</div>
.screen-reader {
  position: absolute;
  left: -9999px;
}

This makes it read just like it’s a normal document with the tab content being laid out one after the other.

Performance

Performance is a feature, delivering content blazingly fast is a great user experience and I strive towards that. The main concern with performance was that there is a bit of DOM manipulation happening pretty early in the page load. Luckily the actions themselves are pretty lightweight when performed scarcely, provided things are done right:

  • Perform a minimal number of DOM manipulations
  • Don’t block HTML parsing with scripts that are not essential to the initial load (ie. use async)

To help with the first point, the manipulation of the <pre> elements needed to be done before code-prettify performs its actions, because moving a single <pre> around the page is a lot different to moving a <pre> with the mounds of children it creates to do syntax highlighting.

Error prevention

With something like this things can always go wrong, the feature depends on several things being in place and could flat out break the page if they are not. I built this feature rather defensively and warn/exit if something doesn’t seem right to try and prevent anything bad getting through to my readers. My writing flow will likely not let anything like this through, but it doesn’t hurt to be careful. I’ll also get a nice warning when I do something wrote.

Wrapping up

See the new feature in action above and in this article, I’ll slowly be rolling this out to all posts that have either multiple languages or where the snippet could do with a language label. This is just one of the improvements I have been working on over the past few days. Keep an eye out for more!

Like this article?
Subscribe for more!