Filters
A filter transforms the value on its left: {{ value | filter: argument }}. See Expressions for how chaining and arguments work.
Filters convert their input as needed: string filters treat a number as its printed text, number filters read a numeric string as a number, and array filters treat nil as an empty array. A filter that cannot work with its arguments fails with an error that names it.
Applications add their own filters. Three built-ins can never be replaced by an application: escape, json and default, because they define how output stays safe.
On this page: Strings · HTML · Numbers · Arrays · Dates · URLs · Fallbacks · JSON
#Strings
#upcase
Converts to upper case.
{{ "Café au lait" | upcase }}CAFÉ AU LAIT#downcase
Converts to lower case.
{{ "Café AU Lait" | downcase }}café au lait#capitalize
Upper-cases the first character and lower-cases the rest.
{{ "éCLAIR WITH CREAM" | capitalize }}Éclair with cream#strip, lstrip, rstrip
Remove whitespace from both ends, the start, or the end.
[{{ " tea " | strip }}] [{{ " tea " | lstrip }}] [{{ " tea " | rstrip }}][tea] [tea ] [ tea]#strip_newlines
Removes every line break.
{{ settings.text | strip_newlines }}{"settings": {"text": "one\ntwo\r\nthree"}}onetwothree#append, prepend
append: text adds text at the end; prepend: text adds it at the start.
{{ "tea" | append: "pot" }} {{ "pot" | prepend: "tea" }}teapot teapot#replace, replace_first
replace: old, new replaces every occurrence; replace_first only the first.
{{ "a-b-c" | replace: "-", "+" }} {{ "a-b-c" | replace_first: "-", "+" }}a+b+c a+b-c#remove, remove_first
remove: text deletes every occurrence; remove_first only the first.
{{ "a-b-c" | remove: "-" }} {{ "a-b-c" | remove_first: "-" }}abc ab-c#truncate
truncate: length, ending shortens text to at most length characters, counting the ending. The default length is 50 and the default ending is .... Text that already fits is unchanged. Characters are never split.
{{ "Vascula templates" | truncate: 10 }} | {{ "Vascula templates" | truncate: 10, "…" }} | {{ "Short" | truncate: 10 }}Vascula... | Vascula t… | Short#truncatewords
truncatewords: count, ending keeps the first count words and adds the ending (default ...) when it removed any. Runs of whitespace become single spaces. The count must be at least 1.
{{ "one two three four" | truncatewords: 2 }} | {{ "one two" | truncatewords: 5 }}one two... | one two#split
split: separator splits text into an array. An empty separator splits into single characters; an empty input gives an empty array.
{{ "a,b,,c" | split: "," | join: "|" }} {{ "abc" | split: "" | join: "." }} {{ "" | split: "," | size }}a|b||c a.b.c 0#slice
slice: offset, length returns part of a string or an array. A negative offset counts from the end. The length defaults to 1.
{{ "Vascula" | slice: 0, 3 }} {{ "Vascula" | slice: -3 }} {{ "Vascula" | slice: -3, 3 }} {{ settings.list | slice: 1, 2 | join: "," }}{"settings": {"list": ["a", "b", "c", "d"]}}Vas u ula b,c#size
The number of characters in a string, items in an array, or keys in a map. Anything else is 0. The .size property gives the same result.
{{ "Café" | size }} {{ settings.list | size }} {{ nil | size }}{"settings": {"list": [1, 2, 3]}}4 3 0#HTML
#escape
Escapes text for HTML. Printing the result does not escape it again, so escape never double-escapes. Output is escaped anyway; use escape when you store markup-safe text in a variable or pass it to an application filter.
{{ "<b>Tea</b> & cake" | escape }}<b>Tea</b> & cake#escape_once
Escapes text that may already contain character references, without escaping them a second time.
{{ "1 < 2 & 3 > 2" | escape_once }}1 < 2 & 3 > 2#strip_html
Removes everything between < and >. The result is text, and is escaped when printed. This is not a sanitizer: use it to make a plain-text summary, not to make markup safe.
{{ "<p>Hello <b>world</b></p>" | strip_html }}Hello world#newline_to_br
Escapes the text and replaces each line break with <br>.
{{ settings.text | newline_to_br }}{"settings": {"text": "line one\n<line two>"}}line one<br><line two>#Numbers
Number filters read numbers and numeric strings. Two integers give an exact integer result (falling back to a decimal on 64-bit overflow); anything with a decimal gives a decimal.
#plus, minus, times
{{ 7 | plus: 3 }} {{ 7 | minus: 10 }} {{ 7 | times: 3 }} {{ 1.5 | times: 2 }} {{ "4" | plus: 1 }}10 -3 21 3 5#divided_by
Divides. Two integers that divide exactly give an integer; otherwise the result is a decimal. Dividing by zero is an error.
{{ 10 | divided_by: 2 }} {{ 7 | divided_by: 2 }} {{ 1 | divided_by: 3 | round: 4 }}5 3.5 0.3333{{ 1 | divided_by: 0 }}divided_by: division by zero#modulo
The remainder of a division, exact for two integers. Its sign follows the input. A zero divisor is an error.
{{ 7 | modulo: 3 }} {{ -7 | modulo: 3 }} {{ 7.5 | modulo: 2 }}1 -1 1.5#round, ceil, floor
Round to the nearest integer, up, or down. An optional argument keeps that many decimal places. Halves round away from zero.
{{ 2.5 | round }} {{ 3.14159 | round: 2 }} {{ 2.1 | ceil }} {{ 2.9 | floor }} {{ -2.5 | round }}3 3.14 3 2 -3#abs
The absolute value.
{{ -7 | abs }} {{ 2.5 | abs }}7 2.5#at_least, at_most
at_least: n returns the larger of the value and n; at_most: n the smaller. Use them to clamp.
{{ 3 | at_least: 5 }} {{ 30 | at_most: 12 }} {{ 8 | at_least: 1 | at_most: 10 }}5 12 8#Arrays
#join
join: separator prints each item and joins them. The separator defaults to no separator.
{{ settings.list | join: ", " }} {{ settings.list | join }}{"settings": {"list": ["a", "b", "c"]}}a, b, c abc#first, last
The first or last item, or nil for an empty array. The .first and .last properties do the same.
{{ settings.list | first }} {{ settings.list | last }}{"settings": {"list": ["a", "b", "c"]}}a c#map
map: field returns an array of one field from each item.
{{ settings.people | map: "name" | join: ", " }}{"settings": {"people": [{"name": "Ada"}, {"name": "Grace"}]}}Ada, Grace#where
where: field keeps the items whose field is truthy. where: field, value keeps the items whose field equals the value.
{{ settings.items | where: "available" | map: "name" | join: "," }} / {{ settings.items | where: "color", "red" | map: "name" | join: "," }}{"settings": {"items": [
{"name": "cup", "available": true, "color": "red"},
{"name": "pot", "available": false, "color": "red"},
{"name": "jug", "available": true, "color": "blue"}
]}}cup,jug / cup,pot#sort, sort_natural
sort orders items ascending; sort: field orders by a field. Numbers sort as numbers and strings in character order (upper case before lower case). sort_natural compares the printed text case-insensitively. Items that cannot be compared keep their original order.
{{ settings.nums | sort | join: "," }} {{ settings.words | sort | join: "," }} {{ settings.words | sort_natural | join: "," }} {{ settings.items | sort: "price" | map: "name" | join: "," }}{"settings": {
"nums": [10, 2, 33],
"words": ["banana", "Cherry", "apple"],
"items": [{"name": "b", "price": 5}, {"name": "a", "price": 2}]
}}2,10,33 Cherry,apple,banana apple,banana,Cherry a,b#reverse
Reverses the order.
{{ (1..4) | reverse | join: "," }}4,3,2,1#uniq
Removes repeated items, keeping the first of each. Items compare with equality, so 1 and 1.0 are the same.
{{ settings.list | uniq | join: "," }}{"settings": {"list": ["a", "b", "a", "c", "b"]}}a,b,c#compact
Removes nil items.
{{ settings.list | compact | join: "," }}{"settings": {"list": ["a", null, "b", null]}}a,b#concat
concat: other joins two arrays.
{{ settings.a | concat: settings.b | join: "," }}{"settings": {"a": [1, 2], "b": [3]}}1,2,3#sum
Adds up the items, or sum: field adds up one field of each item. Items that are not numbers are skipped.
{{ settings.prices | sum }} {{ settings.lines | sum: "qty" }}{"settings": {"prices": [1.5, 2, "x"], "lines": [{"qty": 2}, {"qty": 3}]}}3.5 5#Dates
#date
date: format formats a date. The input is a date string (2026-10-02, 2026-10-02 14:30:00, or RFC 3339 such as 2026-10-02T14:30:00Z), a date value from the application, or "now" or "today" (the current time in UTC). The format uses strftime directives:
| Directive | Meaning | Example |
|---|---|---|
%Y, %y | year, two-digit year | 2026, 26 |
%m, %d, %e | month, day, day padded with a space | 10, 02, 2 |
%B, %b | month name, short month name | October, Oct |
%A, %a | weekday, short weekday | Friday, Fri |
%H, %I, %p | hour (24h), hour (12h), AM/PM | 14, 02, PM |
%M, %S | minute, second | 30, 00 |
%j | day of the year | 275 |
%s | Unix seconds | 1790951400 |
%Z, %z | time zone name, offset | UTC, +0000 |
%% | a percent sign | % |
Other directives are printed as written. A value that is not a date, or a missing format, is an error.
{{ "2026-10-02T14:30:00Z" | date: "%A, %e %B %Y at %H:%M" }} | {{ "2026-10-02" | date: "%d/%m/%y" }}Friday, 2 October 2026 at 14:30 | 02/10/26{{ "next week" | date: "%Y" }}date: cannot parse "next week" as a date#URLs
#url_encode, url_decode
Encode text for use in a URL query, or decode it. Spaces become +.
{{ "tea & cake" | url_encode }} {{ "tea+%26+cake" | url_decode }}tea+%26+cake tea & cake#Fallbacks
#default
default: fallback returns the fallback when the value is nil, false, an empty string or an empty collection. Unlike a condition, it treats "" as missing. 0 is a real value and is kept.
With allow_false: true, an explicit false is kept, which lets a setting that defaults to true still be switched off.
[{{ settings.title | default: "Untitled" }}] [{{ settings.count | default: 10 }}] [{{ settings.missing | default: "none" }}] [{{ settings.flag | default: true }}] [{{ settings.flag | default: true, allow_false: true }}]{"settings": {"title": "", "count": 0, "flag": false}}[Untitled] [0] [none] [true] [false]#JSON
#json
Converts a value to JSON. Inside <script> it is printed as JSON with <, > and & encoded; inside an HTML tag it is also escaped for HTML. See Output: JSON.
<script>const data = {{ settings.data | json }};</script>{"settings": {"data": {"tags": ["a", "<b>"], "count": 2}}}<script>const data = {"count":2,"tags":["a","\u003cb\u003e"]};</script>Map keys are written in sorted order.