Dynamic Footnotes in Markdown With Jekyll Without Plugins

June 12, 2020 | Jameson Zimmer

I recently was working on a project where I needed to produce dynamic footnotes in Jekyll blog posts.

There are some plugins floating around GitHub for this purpose, but I wanted to accomplish it with Liquid templating only if possible. So, this solution is Liquid-only and should work fine with GitHub Pages (which doesn’t allow Jekyll plugins at this time).

Goal: Dynamic Footnotes in Markdown

My goal was to be able to type footnotes and references into my text, but without numbering them, so that I could move or add/remove citations without disrupting the numbering.

Basically, I wanted something like this:

Here is some text in a blog post. [^footnote]  
[^footnote]: Here is the footnote, with citation or commentary. 

Here is another sentence. [^footnote]  
[^footnote]: here is another footnote. 

Rather than the Markdown norm for footnotes, which looks like this:

Here is some text in a blog post. [^1]  
[^1]: Here is the footnote, with citation or commentary. 

Here is another sentence. [^2]  
[^2]: here is another footnote. 

…And have the output HTML still result in numbered footnotes like this:

<p>Here is some text in a blog post.<sup id="fnref:1"><a href="#fn:1" class="footnote">1</a></sup></p>

<p>Here is another sentence.</p><sup id="fnref:2"><a href="#fn:2" class="footnote">2</a></sup></p>

<div class="footnotes">
  <ol>
    <li id="fn:1">
      <p>Here is the footnote, with citation or commentary. <a href="#fnref:1" class="reversefootnote">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>here is another footnote. <a href="#fnref:2" class="reversefootnote">&#8617;</a></p>
    </li>
  </ol>
</div>

Solution: Increment Counter in Liquid

The solution I came up with is to increment a counter in Liquid (template language used by Jekyll):


<!-- Define ref at top of post  -->
{% assign ref = 1 %}

<!-- Include counter with each reference -->
Here is some text in a blog post. [^{{ref}}]  
[^{{ref}}]: Here is the footnote, with citation or commentary.  
{% assign ref = ref | plus:1 %}

Here is another sentence. [^{{ref}}]  
[^{{ref}}]: here is another footnote.  
{% assign ref = ref | plus:1 %}

This solution is a bit clunky, but works for me. I also like that it works for loops on data in my site, which is a regular use case for my project:


<!-- Define ref at top of post  -->
{% assign ref = 1 %}

Some manually written text leading into a listicle based on CSV in the site.data file: 

<!-- Include counter with each for loop -->
{% for item in site.data.my-special-data %}
## {{ item.title }}  
{{ item.text }} {% if item.footnote %}[^{{ref}}]

[^{{ref}}]: {{item.footnote}}
{% assign ref = ref | plus:1 %}
{% endif %}
{% endfor %}

…and the counter just picks up again when you continue with manually written content after the Liquid loop on your data file(s).

Tell me the better way

Anyway, I hope this solution is useful to folks like myself with limited development skills but a stubborn desire to use minimalist tools like Jekyll/GitHub Pages.

If you’re reading this and you think this is a bad solution, please email me and tell me: jameson [at] jamesonzimmer [dot] com. I’ll update the page or just redirect if there is a better solution.