67
Rendering a Liquid template with highlight tags in Jekyll
While developing a blog in Jekyll it may happen that you'll have a need for rendering a custom template. I had this situation when trying to build a code snippet block with Contentful that'd eventually be rendered in a Jekyll blog.
Jekyll's docs suggest that you should parse the template like this:
content = "<pre>{{ contentToDisplay }}</pre>"
template = Liquid::Template.parse(content)
Then you can render the template (passing optionally some variables):
template.render('contentToDisplay' => "x = 1")
"<pre>x = 1</pre>"
It works nicely as long as long as you don't want to use a Jekyll Liquid tag, like the highlight tag that I needed.
When you change the content
to:
{% highlight ruby %}
{% endhighlight %}
then rendering such template will raise a following exception:
undefined method `safe' for nil:NilClass
It took me some time to figure out what the problem was, but eventually it turned out that the Jekyll::Tags::HighlightBlock class expects that there's site
in template's context.
So, I ended up having three new problems:
- What should be the type of the
site
variable? - Where do I get the variable from?
- How do I pass it to the
highlight
tag?
After trials & errors I managed to answer all of these questions:
- The tag expects
site
to be aJekyll::Site
- You can get the
site
object by callingJekyll.sites.first
(I suppose that in 99.9% of cases there's just one site so you shouldn't worry too much) - In order to pass the site context when rendering a template the previous call needs to be converted like this:
@template.render!({ 'contentToDisplay' => "x = 1" }, { registers: { site: Jekyll.sites.first } })
That's it! Now my template got rendered correctly and the syntax is nicely highlighted:
<figure class="highlight">
<pre>
<code class="language-ruby" data-lang="ruby">
<span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
</code>
</pre>
</figure>"
Hope you find this post useful and that it'll save you some time :)
67