I am rather new to building static content using Jekyll, and am blown away by how simple the whole process from writing text, to having it show up on my github.io page has become. Along my path, I wanted a simple way to enable plugin-less (keep reading to find out why) custom highlighting in my blog.

Something like this:

The quick brown fox jumps over the lazy dog

Or this:

Why, man, he doth bestride the narrow world
Like a Colossus, and we petty men
Walk under his huge legs and peep about
To find ourselves dishonourable graves.

The following post curates my exploits in seeking out the above functionality, without boiling the ocean.

Code Highlighting in Jekyll

“Code” Highlighting with Jekyll is pretty awesome and is as simple as wrapping your text with the respective highlight liquid tags as shown below:

{% highlight python %}
# This is a comment
odyssey = space % 2001
{% endhighlight %}

Which produces the following output:

# This is a comment
odyssey = space % 2001

Looking at the generated HTML, we see something like:

<div class="highlight">
  <pre>
    <code class="language-python" data-lang="python">
      <span class="c"># This is a comment</span>
      <span class="n">odyssey</span> <span class="o">=</span> <span class="n">space</span> <span class="o">%</span> <span class="mi">2001</span>
    </code>
  </pre>
</div>

Basically, Jekyll scans the code / text within the {% highlight %} tag, and post processes it. Neat, so to add custom styling for quotes - we should be able to define a custom language and style it as we see fit (we can style the container as well as the content).

However, Jekyll only works with a preset list of languages as supported by pygments or rouge. Certainly one option here, is to pick a language you never plan on highlighting with, and use that anytime you wanted a quote. This sounds icky. Perhaps we can do our quote styling with a plugin instead.

Plugins in Jekyll

From scratching the surface, it was clear that Jekyll could be easily extended by means of simple plugins. However, the large note on said page also cautions the reader that the github pages version of the generated site, will use the --safe option when baking the static site. This means custom plugins are excluded when the static site is built! Clearly, we could set-up Jekyll locally on our dev boxes and push the generated site to github, but where is the fun in that?

So… no plugins, now what?

One other option, would be to write raw HTML in your markdown document. We could do something like this:

<div class="blog-quote">
The quick <b>brown</b> fox jumps over the lazy dog
</div>

and style the blog-quote class like so (excuse my sass):

.blog-quote {
    position:     relative;
    margin:       15px 10px;
    padding-left: 12px;
    overflow-x:   auto;

    font-size:    1rem;
    font-style:   italic;
    color:        #9B9B9B;
    line-height:  1.25;

    border-color: #039BE5;
    border-left:  10px solid #039BE5;

    // Fix <b> tag inside a quote
    & b {
        color:    #424242;
    }
}

This totally works, but is rather ugly. Putting a bunch of divs in the blog seems like a step backwards.

The Unlikely Savior(?) - Front Matter

Each Jekyll page can contain a header section which defines a bunch of Front Matter. This is used to choose page specific layouts, set page attributes and what not in the Jekyll world. Here is an overview on Liquid Variables.

For instance, if we had the following Front Matter on the top of our current post like so:

---
layout: "post"
title: "Post about stuff"
openQuote: "<div class='blog-quote'>"
closeQuote: "</div>"
---
# Some stuff!

Then, anytime we wanted a “quote”, we can “emit” the openQuote and closeQuote values using the {{ var_name }} liquid syntax.

So if we wanted to inject a quote into a post, it would now look something like this:

{{ page.openQuote }}
The quick <b>brown</b> fox jumps over the lazy dog
{{ page.closeQuote }}

This will produce the desired effect (using the same css from above), which is seen here:

The quick brown fox jumps over the lazy dog

Making things a little easier

Lets say we end up quoting things a whole bunch. We would have to add the openQuote and closeQuote variables to each and every post’s Front Matter. This is not very sane, but fortunately Jekyll allows us to specify page wide defaults.

This would allow us to define the blocks of HTML we wish to inject, up-front in the config file. For example, to apply the openQuote and closeQuote variables to all “posts”, your _config.yml file would resemble:

... other settings
defaults:
  -
    scope:
        path: ""
        type: "posts"
    values:
        openQuote: "<div class='blog-quote'>"
        closeQuote: "</div>"

Woot! From now on, any “posts” related page will auto-magically have access to the openQuote and closeQuote variables. The usage still remains the same, use {{ page.openQuote }} and {{ page.closeQuote }} to inject them.