The templating engine used by Notifuse is the famous Nunjucks (same syntax as Twig, Jinja2...).
Learning few basics will save you a lot of time, and improve the quality of your messages.
JSON is a cross-platform data format used everywhere on the web, and mostly in APIs.
A JSON object always starts with brackets, and keys are wrapped in double quotes like this:
{"key": "value"}. Values can be a string, a number, an object, an array, true or false and null.
Strings are wrapped in double quotes: {"myString": "I'm a string"}.
Number are not wrapped in double quotes: {"myNumber": 10.5}.
Objects are wrapped in brackets: {"myObject": {"key": "value"}}.
Arrays are wrapped in square brackets, and can contain any kind of values:
{"myArray":["a_string", 3, true]}.
Booleans are true or false: {"winner": true}.
Now we will learn some templating syntax, let's say our JSON data is the following:
{
"firstName": "John",
"basket": {
"banana": 7,
"orange": 8
},
"tags": ["customer", "vip"]
}
To print a variable in your template using the templating syntax, wrap it with double brackets:
Hello {{ firstName }}.
To access a child property of an object, you can either use a dot: {{ basket.orange }}
or square brackets like this: {{ basket["orange"] }}
To access values of an array, we use square brackets with the index number. The first value of an array is at the index 0. Example: {{ tags[0] }} will print customer.
What if you want to print some information in your messages only if a variable exists?
That's where we need the {% if myCondition %} I'm in baby! {% endif %} condition!
The content inside the "if" block will be printed only if the condition is valid. You can use logic and comparisons keywords: and or not == != > >= < <=, and parentheses to group expressions.
You can chain as many conditions as you want with the {% elif condition %} block and end them with {% else %}.
{% if user.isCustomer %} ... {% endif %}
{% if not user.isCustomer %} ... {% endif %}
{% if comments|length > 5 %} ... {% endif %}
{% if order.payment == "creditcard" and order.total > 1000 %}
...
{% elif (x > 5 or y > 5) and not user.isMad %}
...
{% else %}
...
{% endif %}
To customize your messages with a list of new comments, articles, products... you will have to loop over an "array" or "objects". Let's take this JSON data as an example:
{
"products": [
{"name": "Bike", "price": 150},
{"name": "Skateboard", "price": 70}
]
}
To loop over a list, we will use the {% for item in items %} ... {% endfor %} like this:
{% for product in products %}
- {{ product.name }} at {{product.price}} USD!
{% else %}
The "else" can be used to say something if your list is empty
i.e: there is no new products...
{% endfor %}
It's also possible to loop over the properties of an object with:
{% for key, value in myObject %} ... {% endfor %}.
Nunjucks also provides 2 useful functions to improve your loops: range & cycler.
The range([start], stop, [step]) function returns an array with a defined length:
{% for i in range(0, 5) %}
{{ i }} is gonna be: 0, 1, 2, 3, 4
{% endfor %}
The cycler(item1, item2, ...itemN) function is often used
to create invoices with even/odd table rows:
{% set cls = cycler("odd", "even") %}
{% for row in rows %}
<div class="{{ cls.next() }}">{{ row.name }}</div>
{% endfor %}
To put some comments that will be removed at compilation, use {# my beautiful comment... #}
Normally the template engine outputs everything outside of variable and tag blocks verbatim, with all the whitespace as it is in the file. Occasionally you don't want the extra whitespace, but you still want to format the template cleanly, which requires whitespace.
You can tell the engine to strip all leading or trailing whitespace by adding a minus sign (-) to the start or end block tag. Example:
{% for i in [1,2,3,4,5] -%}
{{ i }}
{%- endfor %}
The exact output of the above would be "12345". The -%} strips the whitespace right after the tag, and the {%- strips the whitespace right before the tag.
To help you format your data, Nunjucks has some useful builtin filters.
Example: {{ article.description|truncate(100) }} will truncate a long text and append "..." at the end.
Some filters we like:
batch | Used to batch an array of items. Example: show 3 articles per line in your newsletters. |
---|---|
capitalize | Capitalize a value. The first character will be uppercase, all others lowercase. |
escape | Convert the characters &, <, >, ‘, and ” in string s to HTML-safe sequences. Use this if you need to display text that might contain such characters in HTML. Marks return value as markup string. |
format | Apply python string formatting on an object. |
groupby | Group a sequence of objects by a common attribute. Example: you want to group and display your most recent products by categories |
join | Return a string which is the concatenation of the strings in the sequence. Example: you want to convert an array of tags to: tag1, tag2, tag3... |
length | Return the number of items of an array or object. Example: you want to display the total of new comments... |
random | Return a random item from the sequence. Example: you want each one of your contacts to see a unique newsletter an A/B test which products get the most of clicks... |
round | Round the number to a given precision. Useful to cleanup some numbers after doing some math... |
safe | Mark the value as safe which means that in an environment with automatic escaping enabled this variable will not be escaped. Useful if you want to print some HTML tags... |
title | Return a titlecased version of the value. I.e. words will start with uppercase letters, all remaining characters are lowercase. Useful to display people names properly... |
truncate | Return a truncated copy of the string. The length to truncate and the suffix can be customized. |
upper | Convert a value to uppercase. |
urlencode | Escape strings for use in URLs (uses UTF-8 encoding). It accepts both dictionaries and regular strings as well as pairwise iterables. Useful to inject some Google Analytics parameters in your links... |