I'm posting this question asking both to Jinja2 and Nunjucks users as the latter is largely inspired by the former and their templates syntax is mostly the same.
I'm having some troubles finding which is the best approach to write templates files when indentation and whitespaces matter (e.g. when generating markdown files).
Suppose that the following context is passed to my template
{
functions = [
{
name: "myFunc",
description: "This is a jsDoc description for a function",
params: [
{name: "label", type: "string"},
{name: "size", type: "number"},
]
returns: "void", // <- optional, may not be present
since: "API level 2.0" // <- optional, may not be present
deprecated: true // <- optional, may not be present
},
...
]
}
I want to obtain this output (with this precise indentation level):
/**
* This is a jsDoc description for a function
*
* @name myFunc
* @param {string} label
* @param {number} size
* @returns {void}
* @since API level 2.0
* @deprecated
*/
My troubles arise when I need to handle the whitespaces around template tags (i.e., {% ... %}
) as I struggle to mantain a nicely indented template file and a nicely indented output at the same time.
So far I managed to obtain either the former or the latter, but not both.
When writing the template file I would like to write code that cleanly shows which block is the child/parent with respect to the others (note that the first tag starts at the right indentation level):
{% for function in functions %}
/**
* {{ function.description }}
*
{% for param in function.params %}
* @param {% raw %}{{% endraw %} {{ param.type }} {% raw %}}{% endraw %} {{ param.name }}
{% endfor %}
{% if function.returns %}
* @return {% raw %}{{% endraw %} {{ function.returns }} {% raw %}}{% endraw %}
{% endif %}
{% if function.since %}
* @since {{ function.since }}
{% endif %}
{% if function.deprecated %}
* @deprecated
{% endif %}
*/
{% endfor %}
but this does not generate the desired output at all!
On the other hand to obtain the desidered output I have to write this template:
{% for function in functions %}/**
* {{ function.description }}
*
{% for param in function.params -%}
* @param {% raw %}{{% endraw %} {{ param.type }} {% raw %}}{% endraw %} {{ param.name }}
{% endfor -%}
{%- if function.returns -%}
* @return {% raw %}{{% endraw %} {{ function.returns }} {% raw %}}{% endraw %}
{% endif -%}
{% if function.since -%}
* @since {{ function.since }}
{% endif -%}
{%- if function.deprecated -%}
* @deprecated
{% endif -%}
*/
{% endfor -%}
which is not as clean as the previous version, plus I don't see a general rule of thumb that tells me when to place or expect a -
at the beginning or end of a tag, so each time I have to stop, look closely what's the behaviour of what comes before and what comes after it and hope to make the right choice.
To sum up, my question is: is there a secret "combo" or pattern to achieve both nicely indented templated and complete control on the whitespaces that are printed in the output? (maybe something involving the trim_blocks
or lstrip_blocks
)