Dynamic Footnotes in Markdown With Jekyll Without Plugins
June 12, 2020 | Jameson ZimmerI 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">↩</a></p>
</li>
<li id="fn:2">
<p>here is another footnote. <a href="#fnref:2" class="reversefootnote">↩</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.