How to dump a collection using eleventy and nunjucks

Leipzig

How to dump a collection using eleventy and nunjucks

Nunjucks offers some builtin filters out of the box.
Most of them are ported from jinja's filters, in addition nunjucks has a few of its own.

Examples

{% set items = [1, 2, 3] %}
{{ items | first }}
> 1

{{ items | dump }}
> [1,2,3]
{% set foods = { ketchup: '5 tbsp', mustard: '1 tbsp', pickle: '0 tbsp', salt: '1 tbsp' } %}
{{ foods | length }}
> 3

{{ foods | dump }}
> {"ketchup":"5 tbsp","mustard":"1 tbsp","pickle":"0 tbsp"}

Dumping a collection

However, dumping a collection leads to the following error:

TypeError: Converting circular structure to JSON (Template render error)

There are several solutions to dump a circular structure anyway:

  • in node.js use util.inspect(object) to replace circular links with "[Circular]"
  • use JSON.stringify with a custom replacer function (the second parameter of stringify) to exclude already serialized objects**
  • use a module/plugin like Circular JSON

Example using util

Add a filter function in .eleventy.js.
Util is a built-in module, you do not have to install it.

.eleventy.js

const util = require('util')

eleventyConfig.addFilter('dump', obj => {
  return util.inspect(obj)
});

You can pass an options as second parameter:
util.inspect(obj, { depth: 5, ... })

Usage

<pre>{{ foods | dump }}</pre>

Output

{ ketchup: '5 tbsp',
  mustard: '1 tbsp',
  pickle: '0 tbsp',
  salt: '1 tbsp' }

Example using JSON.stringify

Solution from MDN.
This solution removes all repeating values, not just the circular ones.

Add a filter function in .eleventy.js.

.eleventy.js

eleventyConfig.addFilter('dump', obj => {
  const getCircularReplacer = () => {
    const seen = new WeakSet();
    return (key, value) => {
      if (typeof value === "object" && value !== null) {
        if (seen.has(value)) {
          return;
        }
        seen.add(value);
      }
      return value;
    };
  };

  return JSON.stringify(obj, getCircularReplacer(), 4);
});

Usage

<pre>{{ foods | dump }}</pre>

Output

{
    "ketchup": "5 tbsp",
    "mustard": "1 tbsp",
    "pickle": "0 tbsp",
    "salt": "1 tbsp"
}