Modifying Object in Nunjucks

Indirectly by Using 11ty’s Computed Data Feature

Hyunbin
3 min readMar 29, 2021

Limitation of Nunjucks

Templating engine Nunjucks has set tag to create or modify a variable.

{% set username = "joe" %}
{{ username }} // This would print "joe".
// Source: Nunjucks Templating Docs

However, it is not possible to create or modify an existing object with set.

// The Following Does Not Work{% set obj = {} %}
{% set obj.property = 111 %}
// Source: {% set %} doesn't work with objects

Using Static Site Generator 11ty

Nunjucks is used in diverse cases, including in a static site generator.

Diagram static site generator turning assets into a website at build time

If static site generator 11ty(Eleventy) is used, the following is possible.

---
title: My First Blog Post
img:
cover:
extension: avif
color: '#70ACC4'
eleventyComputed:
img:
cover:
alt: '{{title}}'s Cover Image'
src: '{{page.url}}cover.{{img.cover.extension}}'
---

Above front matter(YAML syntax) resolves to the following object that can be accessed by a Nunjucks template. (e.g. {{img.cover.src}})

{
"title": "My First Blog Post",
"img": {
"cover": {
"extension": "avif",
"color": "#70ACC4",
"alt": "My First Blog Post's Cover Image",
"src": "/posts/My First Blog Post/cover.avif"
}
}
}

img object assgining is a result of 11ty’s Data Cascade(Computed Data).

By default, Eleventy does a simple top level merge (Object.assign) from the different data sources. It doesn’t dive any deeper to merge Object literals or Arrays in the data. — Eleventy Documentation

Comparison

With this feature, there is less need to handle data inside a template file.

Without 11ty

---
title: My First Blog Post
img:
cover:
extension: avif
color: '#70ACC4'
---
{% set img_cover_alt = title + 's Cover Image' %}
{# img.cover.alt is not a valid variable name in `set` #}
{% set img_cover_src = page.url + 'cover.' + img.cover.extension %}<img src="{{img_cover_src}}" alt="{{img_cover_alt}}">

With 11ty

---
title: My First Blog Post
img:
cover:
extension: avif
color: '#70ACC4'
eleventyComputed:
img:
cover:
alt: '{{title}}'s Cover Image'
src: '{{page.url}}cover.{{img.cover.extension}}'
---
<img src="{{img.cover.src}}" alt="{{img.cover.alt}}">

Common Result

// page.url = /posts/My First Blog Post/<img
src="My First Blog Post's Cover Image"
alt="/posts/My First Blog Post/cover.avif"
>

Absence of template literals in Nunjucks can be supplemented by this.

const a = 5;
const b = 10;
console.log(`
Fifteen is ${a + b} and // "Fifteen is 15 and
not ${2 * a + b}. // not 20."
`);
// Source: Template literals (Template strings)

Use Case

Javascript functions and Nunjucks macros do not work in front matter of YAML syntax, such as the above. However, 11ty shortcodes do work.

JavaScript functions require either JavaScript front matter or a JavaScript data file (template, directory, or global). YAML and JSON do not support JavaScript functions. — Eleventy Documentation

Find Parent Folder Path

Since a page’s parent folder path is not supplied by 11ty, the following shortcode can be added and can be used in non-javascript front matters.

module.exports = (eleventyConfig) => {
eleventyConfig.addShortcode('parentUrl',
(page) => (page.url).replace(`${page.fileSlug}/`, ''));
};
// FileName: .eleventy.js

The following front matter(YAML syntax) is successfully computed.

---
layout: default.njk
eleventyComputed:
img:
mock:
cover: '{% parentUrl page %}cover.{{img.cover.extension}}'
---

--

--

Hyunbin

Node.js and web developer using TypeScript. Undergraduate in Seoul National University.