Language
Expressions
Operators, property access, calls, filters and tests.
Expressions appear inside {{ }} and in tags. They look and behave much like JavaScript.
Literals
null true false
42 3.14 1_000_000
"double" 'single' "with #{ interpolation }"
[1, 2, 3]
{ title: "Home", "data-id": 1, (key): value }
- Hash keys can be names, strings, numbers or any expression in brackets.
{ title }is short for{ title: title }....spreads an array or hash into a new one:[...posts, extra]or{ ...defaults, size: "lg" }.- Trailing commas are allowed.
Operators
| Operators | Meaning |
|---|---|
and or not | Logic. Always return true or false |
== != | Strict equality, like JavaScript's ===. Null and undefined are equal |
< > <= >= | Compare two numbers, two strings or two dates |
+ - * / % ** | Arithmetic. Numbers only |
// | Divide and round down |
~ | Join two values as strings |
in not in | Whether an array or set contains a value, a string contains a substring, or a hash has a key |
starts with ends with | Compare the start or end of two strings |
a..b | An array of whole numbers from a to b, including both |
a ? b : c | If a is true, b, otherwise c. Without : c, null |
a ?: b | a if it is true, otherwise b |
a ?? b | a unless it is null or missing, otherwise b |
{{ "Total: " ~ price * quantity }}
{{ user.role in ["admin", "editor"] ? "Can edit" : "Read only" }}
{{ path starts with "/blog/" }}
{{ user.nickname ?? user.name }}
{{ (1..5)|join(", ") }}
Total: 36
Can edit
true
Ada
1, 2, 3, 4, 5
+ never joins strings, and adding a number to a string is an error. Use ~ to join text. It runs after arithmetic, so "Total: " ~ price * quantity works without brackets.
Reading properties
Use . or [] to read a property. They read the same things, so use whichever fits.
{{ page.title }}
{{ page["title"] }}
{{ page[fieldName] }}
{{ items[0] }}
{{ page?.author?.name }}
?. returns null when the left side is null or missing, and stops there. Method calls work the same way, so post?.summary() is null when there is no post. Nothing after it runs, so keys in brackets and method arguments later in the chain are not evaluated. In strict mode, reading a missing property is an error unless you guard it with ?., ??, default or is defined.
Calling functions
Call a function by name with brackets. Arguments can be positional, named, or both.
{{ range(1, 10, 2)|join(", ") }}
{% set page = document("page", slug: route.path) %}
Named arguments are gathered into one hash at the end. document("page", slug: route.path) passes exactly the same arguments as document("page", { slug: route.path }). Built-in filters and functions also accept their parameter names, such as round(precision: 2).
... spreads an array into positional arguments: max(...prices).
Filters
A filter changes a value. Write it after a |. Filters run left to right, and brackets are optional when there are no arguments.
{{ title|trim|title }}
{{ tags|join(", ", " and ") }}
Kiln Templates
fast, safe and async
Filters bind tighter than a leading minus sign, so -1|abs is -(1|abs). Write (-1)|abs instead. See the filter reference for every built-in filter.
Tests
A test checks a value and returns true or false. Write it after is or is not.
{% if user is defined %}
{% if loop.index is divisible by(3) %}
{% if items is not empty %}
See Tests for every built-in test.
Arrow functions
Filters such as map, filter, sort and reduce take a short function. Write its parameters, then =>, then one expression.
{{ posts|filter(p => p.published)|map(p => p.title)|join(", ") }}
{{ posts|reduce((total, p) => total + p.price, 0) }}
Launch, Update
30
Arrow functions can only be passed to filters and functions. You can't store them with set or print them.