Jekyll Templates Using Django-Like Liquid Blocks/Inheritance

Jekyll inheritance

Includes and layouts are not the same.

While generating a site, Jekyll does a lot of things in a particular order.

  • Read pages's datas
  • Render liquid

    • make necessary includes
    • compute liquid tags and filters
  • Render html in case the document is markdown
  • Render layout

When it renders liquid :

=== page.html
include other.html

print a
assign: a = apple
print a

include other.html
=== end page.html

Becomes a pile of code which is processed like this :

=== page.html
====== other.html
print a ------> nil
assign: a = orange
print a ------> orange
====== end other.html
print a ------> orange
assign: a = apple
print a ------> apple
====== other.html
print a ------> apple
assign: a = orange
print a ------> orange
====== end other.html
=== end page.html

Liquid tags are executed exactly in the order they appear in code, and variables (the local variables assigned in page body, not the one in front matter that are freezed and cannot be changed) are global and can be overridden from page or any child include.

After this, it renders HTML if necessary, and "spits" page's {{ content }} in the layout that knows nothing about page's local variables and can only see page's variables defined in front matter.

Jekyll does not highlight django templates tag

There is another way, but it is equally infuriating: it involves lots of quotes.

Appart from that, you are out of luck; Jekyll can't "escape" liquid.

How to pass {% captured %} variable from a view to the layout in Jekyll/Liquid?

You can't do this with a capture, but you can using an include. Every level of the page hierarchy can override the head key to point to a different include file as required. This example wraps the include with a condition so if no head key is specified the page will still generate.

default.html

{% if page.head %}
{% include {{ page.head }} %}
{% endif %}

{{ content }}

frontpage.html

---
layout: default
head: header1.html
---

{{ content }}

_includes/header1.html

(Frontpage header content)

How to generate files from Liquid blocks in Jekyll?

I've found the proper solution: use the Jekyll::StaticFile class.

When you add one object of this class to the site.static_files array, you are marking this file as pending for copy after the render process is completed. In fact, the copy of such files is done in the site.write process. Take a look at the site_process.rb file in your Jekyll installation.

The usage of this class is easy. When you need to mark a file for future copy, you simply execute a code like this:

site.static_files << Jekyll::StaticFile.new(site, site.source, path, filename)

Where path and filename depends on the location of your file in the src folder.

I had a similar issue developing a LaTeX -> PNG liquid tag. You can take a look at my code at GitHub: https://github.com/fgalindo/jekyll-liquid-latex-plugin

Iterate over hashes in liquid templates

When you iterate over a hash using a variable called hash, hash[0] contains the key and hash[1] contains the value on each iteration.

{% for link_hash in page.links %}
{% for link in link_hash %}
<a href="{{ link[1] }}">{{ link[0] }}</a>
{% endfor %}
{% endfor %}


Related Topics



Leave a reply



Submit