Vascula v0.1.5

Expressions and operators

An expression is what goes inside {{ }}, after if or elsif, after assign name =, and in a few other tag positions.

#Filters

A filter transforms the value on its left. Chain filters with |; they apply left to right. Arguments follow a colon, separated by commas.

Template
{{ "  hello world  " | strip | capitalize | append: "!" }}
{{ "a,b,c" | split: "," | join: " + " }}
{{ settings.text | truncate: 8, "…" }}
Data
{"settings": {"text": "Vascula templates"}}
Output
Hello world!
a + b + c
Vascula…

Some filters also take named arguments, written name: value after any positional ones:

Template
{{ settings.on | default: true, allow_false: true }}
Data
{"settings": {"on": false}}
Output
false

A filter argument is a single value: a literal, a variable path or a range. To pass the result of another filter, assign it first.

Template
{% assign suffix = settings.unit | upcase %}{{ settings.amount | append: suffix }}
Data
{"settings": {"amount": 3, "unit": "kg"}}
Output
3KG

Every built-in filter is described in Filters. Applications add their own, such as formatting money or building image URLs.

#Comparisons

==, !=, <, >, <=, >= and contains compare two values. The rules for each are in Values: comparing values. Filters bind tighter than comparisons, so each side is filtered first:

Template
{% if settings.name | downcase == "ada" %}hello Ada{% endif %}
Data
{"settings": {"name": "ADA"}}
Output
hello Ada

A comparison takes exactly two sides: a == b == c is a compilation error.

#and, or

and and or combine conditions. They return one of their operands, not a new true or false:

  • a or b is a when a is truthy, otherwise b.
  • a and b is b when a is truthy, otherwise a.

That makes or a convenient fallback:

Template
{{ settings.nickname or settings.name }} / {{ settings.missing or "Guest" }} / {{ settings.name and "has a name" }}
Data
{"settings": {"name": "Ada"}}
Output
Ada / Guest / has a name

The right side is only evaluated when needed, so customer and customer.name never reads a field of nothing.

#Precedence

From tightest to loosest:

  1. A value with its filters: x | upcase
  2. A comparison: a == b
  3. and
  4. or

There are no parentheses for grouping, so a or b and c means a or (b and c). For anything more involved, assign intermediate results to variables. Parentheses are only used for ranges.

Template
{% if false or true and false %}yes{% else %}no{% endif %}
Output
no

#There is no not

Use unless, !=, or == false:

Template
{% unless settings.hidden %}shown{% endunless %} {% if settings.count != 0 %}nonzero{% endif %}
Data
{"settings": {"hidden": false, "count": 2}}
Output
shown nonzero

#Ranges

(from..to) is the list of integers from from to to, inclusive. Each end is a number or a variable. A range whose end is below its start is empty.

Template
{{ (1..4) | join: "," }} | {% for i in (1..settings.n) %}{{ i }}{% endfor %} | [{{ (3..1) | join: "," }}]
Data
{"settings": {"n": 3}}
Output
1,2,3,4 | 123 | []

Next: Conditionals.