11ty quick tip: Nunjucks include in markdown without indentation

Tim Kleyersburg
Tim Kleyersburg on 19 March 2022
3 minutes to read

TL;DR: Scroll to the bottom to see how to use nunjucks whitespace control to correctly render an include within a markdown file.


When I was writing my Create an API proxy with Cloudflare Workers article I wanted to dynamically include the widget for what I last scrobbled so everyone could see what the purpose should be.

I knew I could set a default template engine for markdown files, which is used to parse the files before markdown renders the rest of the file. Since I'm using Nunjucks for the rest of my site I changed the default from liquid to njk in my .eleventy.js configuration file:

module.exports = function (eleventyConfig) {
return {
markdownTemplateEngine: 'njk',
}
}

Next, I tried to simply include the same widget I was including on my homepage by writing:

{% include 'last-tweet.njk' %}

Unfortunately, this wasn't working as expected and looked like this:

Screenshot of the broken Nunjucks include

At first I thought it just included the raw code, but then realized that the outer parts seemed to work as expected but then markdowns Indented code blocks feature kicked in.
This is also mentioned in the 11ty docs as a common pitfall.

The docs pointed me in the right direction but I just couldn't find the real culprit of why it wasn't working as expected.

To understand what the problem was let's take a quick look how I implemented that Last Scrobble widget: Basically, we have two templates. One that provides the structure of the card and one that extends it to provide the individual content. I hate to repeat myself so I reach for this pattern as often as I can.

_last-thing.njk

<div>
<div>
{% block link %}{% endblock %}
</div>
{% block content %}{% endblock %}
</div>

last-scrobble.njk

{% extends '_last-thing.njk' %}
 
{% block link %}
<a href="https://www.last.fm/user/Timmotheus">@timmotheus</a>
{% endblock %}
 
{% block content %}
Dynamic track title and artist
{% endblock %}

Turns out: my problem was my notorious need for correctly indenting everything. When providing the content for the blocks I naturally indented everything between the block statements, therefore adding to much indentation. Changing it to the following solved my problem:

{% extends '_last-thing.njk' %}
{% block link %}
- <a href="https://www.last.fm/user/Timmotheus">@timmotheus</a>
+<a href="https://www.last.fm/user/Timmotheus">@timmotheus</a>
{% endblock %}
{% block content %}
- Dynamic track title and artist
+Dynamic track title and artist
{% endblock %}

But that's ugly. Whitespace control to the rescue! Quoting from the docs:

Occasionally you don't want the extra whitespace, but you still want to format the template cleanly, which requires whitespace.

Yep, that's what I wanted. My first instinct was to use it on the include. But that was wrong, because my extra whitespace was clearly coming from my blocks. So I changed my implementation of last-tweet.njk to this:

{% extends '_last-thing.njk' %}
-{% block link %}
+{%- block link -%}
<a href="https://www.last.fm/user/Timmotheus">@timmotheus</a>
-{% endblock %}
+{%- endblock -%}
-{% block content %}
+{%- block content -%}
Dynamic track title and artist
-{% endblock %}
+{%- endblock -%}

That's it! You should now be able to include a nunjucks template without any code indentation from markdown messing up your HTML.


I hope this post helped you! If you have any questions, hit me up on Twitter 😊.

GitHub
See on GitHub
RSS Feed
Code highlighting provided by torchlight.dev