Tags
Template Engine Tags
Tags are a set of various built-in constructs and operations over a template. They are declared using code islands and defines the behavior of the template.
Commands#
Command constructs allows one to run specific commands against template. An important aspect common to all commands is that they never produce content, they only produce side effects.
set
#
The set
command allows to specify an assignment operation inside a template, it will assign to the result of an expression to the specified variable:
{% set five = 2 + 3 %}
In previous example we assigned the result of evaluating the expression 2 + 3
to the variable five
.
The set
command also supports compound assignment operators using common binary operators for arithmetic operations (+
, -
, *
, **
, /
, //
) and string concatenation (~
):
{% set value = 2 %}
{% set value += 3 %}
In previous example the resulting value of variable will be 5.
Variable name is an identifier and can only contain alphanumeric (latin) characters and underscores, but cannot start with digits.
Note again that the output of previous example will be empty because, as mentioned before, set
as a command, does not produce content, it just affects the context defining, or redefining a variable.
global
#
The global
command is the same as set
but it will assign the result of evaluating the expression in global context. It means the global variable will be available in macros, following template values of message template and in the action executed by run
. For example, a global variable defined in Message Content Template will be also available in Embed Content Template.
{% global six = 3 + 3 %}
In previous example we assigned the result of evaluating the expression 3 + 3
to the variable six
and will be available globally.
do
#
The do
command just evaluates a given expression.
{% do something.run() %}
There is not a lot to say about this construct, it might be useful to trigger behaviour from the template by running an object function.
require
#
The require
is an extension for return
command:
{% require expression returning 'Some error just happened!' %}
This command will only return an error if result of evaluating the expression is false
according the Type Convert
.
You can pass an Embed instead of string (but keep in mind that you shouldn't send it using its send
function).
use
#
The use
command enables additional template behaviour.
strict#
Enables template evaluation in strict mode. This means that the Template Engine will return a compilation error in the following cases:
- Attempt to output an undefined variable;
- Attempt to access a non-existent property of an object;
- An attempt to call a non-existent object function or with incorrectly passed arguments.
You can enable this behaviour the following way:
{% use 'strict' %}
run
#
The run
command is used to run specified Action and optionally pass there some parameters.
This operation will interrupt current running action.
Warning
This tag is only working in Custom Commands Actions so you can "route" one action to another.
Use action's UUID to run it:
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' %}
Info
You can get this UUID from action form ifself in the command settings (press "i" icon). Both actions must be the part of the same exact command, e.g. you can't run action of command A from the action of command B.
Use this syntax to pass some parameters to child action:
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' with { 'param1': 123 } %}
with
is just a map, so you can use a predefined variable instead.
Those parameters will be available as part of parameters variable in child action:
{{ parameters.param1 }}
123
in child action.
You can also use the parameters itself in the parent action to pass the data to child action. The following example will do the same thing as previous, just in a different way:
{% do parameters.store('param1', 123) %}
{% run 'aebf9ae8-c62a-4348-b153-a7c0a0173da1' %}
Warning
Actions may run each other in chain up to 3 times. Methods quotas will be shared across the whole chain.
Control Flow#
Template Engine implements basic control flow constructs such as if
conditions and for
loops.
Conditions — if/elseif/else
#
If
conditions are the simplest control flow in Template Engine. It supports consecutive elseif
conditions and the common else
construct too.
{% if (expression) %}
... content if expression is evaluated to true ...
{% elseif (anotherExpression) %}
... content if anotherExpression is evaluated to true ...
{% else %}
... content if none of previous conditions are met ...
{% endif %}
Note that if
constructs will only output the content of the first block which condition is evaluated to true
according to Type Convert.
In terms of variable scoping, if
inner content shares the context with the parent context, this means if
conditions can affect variables in the outer scope.
{% set variable = "a" %}
{% if (true) %}
{% set variable = "b" %}
{% endif %}
{{ variable }}
Previous example will output b
which illustrates how scoping works on if conditions by sharing the context with the parent construct.
{% if (1 != 2) %}
{% return '1 is not 2. Oh wow!' %}
{% endif %}
This text will not be printed because the error.
Previous example will conditionally return an error.
Loops — for
#
Template Engine allows iterating over a list or a map.
{# Example with list #}
{% for item in list %}
... content using variable item ...
{% endfor %}
{# Example with map #}
{% for key, value in map %}
... content using variables key and value ...
{% endfor %}
loop
variable#
for
loops come with an extra variable defined in the context, the loop
variable. The loop variable provides a set of useful properties when within a for loop, check below the properties exposed by this variable:
Property | Description |
---|---|
length |
Size of the list or map being iterated |
index |
Current iteration count starting in 1 |
index0 |
Current iteration count starting in 0 |
revindex |
Remaining number of iterations to reach the end of the list or map, ends in 1 |
revindex0 |
Remaining number of iterations to reach the end of the list or map, ends in 0 |
first |
Boolean property only true in the first iteration |
last |
Boolean property only true in the last iteration |
parent |
Accessing the parent context |
{% for item in [1, 2, 3] %}
{% if (loop.first) %}
Start
{% endif %}
{% endfor %}
Previous example will output Start
only once.
This loop
variable is only bound to the for
context, it means this variable will not be visible outside of the for loop scope. If there is a loop
variable in the context, it will not be overriden but to access it one need to get the parent context, for example:
{% set loop = 1 %}
{% for item in [1, 2, 3] %}
{% if (loop.first) %}
{{ loop.parent.loop }}
{% set loop = 2 %}
{% endif %}
{% endfor %}
{{ loop }}
Previous template will print 1 2
. Note that setting loop
inside the for loop will write to the context, but won't override the for loop bound variable. The value loop
variable defined inside the loop is then available outside of the loop scope.
Transformations — transform
#
Transformation is a variant of for
loops used to transform one list to another.
Each transform iteration expects return
tag to return new list element accordingly:
{% transform item in [1, 2, 3] as newList %}
{% return 'element:' ~ item %}
{% endtransform %}
{{ newList }}
Previous example will transform [1, 2, 3]
list to ['element:1', 'element:2', 'element:3']
and saves the result to newList
variable.
In case then return
tag hasn't executed in iteration, corresponding list element will be skipped. Thus, we can use this to filter the list:
{% transform item in [1, 2, 3] as newList %}
{% if (item != 2) %}
{% return item %}
{% endif %}
{% endtransform %}
{{ newList }}
Previous example will transform [1, 2, 3]
list to [1, 3]
, excluding second element from the result according to condition.
Information
Transformations inherits all for
loops behaviour, including loop
variable and parent context.
Warning
Transformations cannot use nested lists/maps, such elements will be excluded from the result. In other words, you can't make list of lists or list of maps.
Also, transformations cannot print anything, output code islands inside transformations will be ignored.
break/continue
#
You can interrupt for loops and transformations iterations using break
and continue
tags.
break
will break current and all next iterations of loop:
{% for item in [1, 2, 3, 4] %}
start:{{item}}
{% if (item > 2) %}
{% break %}
{% endif %}
end:{{item}}
{% endfor %}
Previous example will output start:1 end:1 start:2 end:2 start:3
as third and all next iterations are being interrupted by item > 2
condition.
continue
will only break the current iteration of loop:
{% for item in [1, 2, 3] %}
start:{{item}}
{% if (item == 2) %}
{% continue %}
{% endif %}
end:{{item}}
{% endfor %}
Previous example will output start:1 end:1 start:2 start:3 end:3
. Note that it lacks of end:2
part as second iterations is being interrupted by item == 2
condition.
return
#
The return
command will interrupt template evaluation with an error returned to the user.
{% return 'Some error just happened!' %}
You can pass an Embed instead of string (but keep in mind that you shouldn't send it using its send
function).
This tag is also used in transformations.
Other#
macro
#
Macro constructs allows the user to reduce template code duplication.
This can be achieved by associating pieces of reusable templates to a specific named macro/endmacro
constructs that also allows them to receive arguments.
{% macro macroName(firstArgument, secondArgument, ...) %}
... reusable template content ....
{% endmacro %}
Macro Name#
The macro name is an identifier used to reference the macro. It must be unique inside a template and must be defined only once. Attempt to define one more macro with the same name will lead to template execution error.
Macro Arguments#
Macro arguments is a list of identifiers representing input variables which can then be used inside the macro body definition. All arguments are optional, it's up to the caller to provide such arguments or not. You can have macros without arguments at all.
Scope#
Macros have access to the limited set of variables:
- Arguments passed to macros;
- Global variables defined at the moment of macro execution;
- Default template variables.
Variables defined inside the macro are only available in scope of this macro. Global will be available everywhere.
Execute Macro#
You can execute defined macros just like functions. Think of macros like "user functions".
{% macro fullname(firstName, lastName) %}
{{ firstName ~ ' ' ~ lastName }}
{% endmacro %}
{{ fullname('Elon', 'Mask') }}
This example has a simple macros to get a full name based on two arguments (first name and last name). Result of macro execution is string built by rendering its template with specified arguments.
Also, you can use return tag in case you want to return specific data from macros (like value of variable or expression):
{% macro fullname(firstName, lastName) %}
Blahblahblah
{% return firstName ~ ' ' ~ lastName %}
{% endmacro %}
{{ fullname('Elon', 'Mask') }}
Result of this template is the same as the previous one. Note that "Blahblahblah" text will not be present in result since marco uses return to return specific data.
Warning
Macros can't execute another macros.
filter
#
The filter
construct is the way apply functions to a given content. It uses the provided body as the first argument in the specified function.
{% filter lower | capitalize -%}
HELLO WORLD
{%- endfilter %}
Previous example will produce Hello world
. As we can see, the filter specified results in the composition of two distinct functions, it will first apply the lower
function to the content HELLO WORLD, producing hello world
and then apply the capitalize
function producing Hello world
.
verbatim
#
The verbatim
tag is useful avoiding the specifics around Template Engine syntax, as it will not try to parse the content.
{% verbatim %}
{{ test }}
{% endverbatim %}
The output of previous template will be {{ test }}
.