Proper line numbers with Jekyll
By default, Jekyll uses the (excellent) Pygments syntax highlighter for code blocks. While this works well, the line numbers it produces are less than satisfactory.
Here’s the default lineno
option, inline
:
This works, but has two main visual and practical problems: 1. There is no visual separation between the line numbers and the code, causing them to visually become indistinct, and 2. When trying to copy code from the codeblocks, the line numbers are included, annoyingly.
So what’s the alternative?
Well, Pygments has inbuilt the table
option, which separates the code from the linenumbers, ostensibly fixing both of these problems. Let’s take a look:
Well, as you can see, this doesn’t really look good either. The main problems are: 1. The size of the line number table is inconsistent between codeblocks, and 2. The line numbers don’t align with the actual lines of code
So let’s get rid of the lineno
option altogether, and get our beautiful but functional line numbers through CSS counters, as described in an article by Alex Peattie.
CSS File
Alex’s CSS is as follows:
Here’s what it produces after adding it to your syntax.css
:
Note those important lines at the end of pre a::before
:
This tell the browser to ignore the line numbers when copying, solving one of our initial problems.
In addition, the background grey of #eee
gives the visual distinction between line numbers and code that we were lacking from lineno=inline
. And, of course, they align properly with the actual lines of code, unlike lineno=table
.
On top of this, the padding
gives the line numbers a consistent spacing and the solid border given by border: solid 1px #d9d9d9;
gives the code a clear separation from the main text.
Lineanchors
It’s not quite that simple, though. These CSS counters need the lineanchors
option to be given for each codeblock, or it ends up looking like this:
To solve this, you can either just put lineanchors
in every highlight
Liquid tag, which is a bit annoying and can easily be forgotten, or you can use a global plugin to allow you to specify global Pygments options in your _config.yml
. Such a plugin is available here, thanks to Dana Silver.
Using this plugin, you can simply specify as follows in your _config.yml
:
Then you don’t need to put it in each codeblock tag and can forget about it!
Unfortuantely, GitHub Pages doesn’t allow for custom Jekyll plugins for security reasons, so unless you want to build the site locally and push the resulting html, you’re gonna have to stick to putting lineanchors
in each tag. Up to you which you want to do.
Scroll bar
Another problem I had, although I am unsure whether this problem is universal/reproducible, is that an annoying y-scroll bar appeared, even when there was no need for it. This is what it looked like:
Now, I haven’t come all this way just to be bested by an annoying y-scroll bar, so I added in this bit of CSS to Alex’s code to get rid of it:
This is placed in pre { .. }
, just after overflow-x: auto;
.
After this, I finally had the beautiful line numbers that Pygments natively lacks.
Update: 5-8-14
Dana’s global configs Jekyll plugin is incompatible with the new Jekyll 2.2.0 release which both I and GitHub Pages are now using. So it looks like until I get round to sorting out why the plugin is incompatible, you’ll need to actually type highlight lang lineanchors
for each individual code block. Annoying.
I always forget to do this, and could not be bothered to go through each codeblock in each blog post I’ve written, so here’s a simple bash script to replace all instances of the highlight lang
Liquid tag with its lineanchors
equivalent:
Change $posts
to correspond to the location of your blog posts, the contents of which you wish to replace. If you’re using more lexers, just add them into the languages array.