|, and chain
left to right:
UnknownFilter error.
Two more rules:
- An unknown value filter records the diagnostic AND passes the value through
unfiltered, so the render itself continues. On the CLI the diagnostic is an error,
so
slurp buildfails and emits no file. - A loop-filter error EMPTIES the collection, which then renders the
{empty}branch. A brokenlimit()looks like missing data, not like an error.
slurp validate reports nothing for ${ x | wat }, and slurp build reports
error[UnknownFilter]: Unknown filter: wat. The same is true of
InvalidFilterArgs and MissingImageSrc.
Value filters
Usable anywhere an expression is.currency
currency(code = "USD")
Formats a number as money. The symbol always PREFIXES, for every code.
USDD 10.00
rather than a diagnostic. A negative puts the sign outside the symbol. Rounding
happens once in minor units, so the fraction carries into the integer part.
null, an array, an object and a non-numeric string all become 0, so the filter
renders the zero amount rather than blank. A non-literal argument leaves the symbol
as a single space.
Crypto amounts do not belong here: they are asset-denominated and high precision,
and 2-decimal rounding destroys them.
date
date(format = "MMM DD, YYYY")
Formats an ISO date string. The complete token set:
There are no time tokens at all. No hours, minutes, seconds, timezone or
day-of-week.
T or space and splits it on
-. If that yields fewer than three parts, the input is returned unchanged.
Epoch milliseconds have no -, so they render verbatim as a long number with no
diagnostic:
YYYY-MM-DD strings, never epoch numbers.
There is also no escaping in the format string, so a literal D or M in
surrounding text is substituted:
default
default(fallback?)
Substitutes the fallback when the value is empty. “Empty” means null, the empty
string, the empty array or the empty object. With no argument it yields the empty
string.
default(user.name) works and currency(user.code) does not.
Because there are no array literals, default([]) is a parse error.
fixed
fixed(n = 2)
Formats a number with exactly n decimal places. Returns a STRING.
null, an array, an object and a non-numeric string all become 0. A
requested precision above 100 is silently clamped to 100. There is no grouping;
for money use currency.
float
float
Coerces to a floating-point number. Returns a NUMBER.
"1.5x"
is 0 rather than 1.5. null, arrays and objects become 0.
int
int
Coerces to a whole number, truncating floats toward zero. Returns a NUMBER.
float: "12abc" is 0, not 12.
A numeric string with a fraction does parse, and truncates: "42.7" is 42.
js
js
Escapes a value for placement INSIDE a JavaScript string literal you wrote
yourself. It escapes the backslash, both quote characters, the backtick, $,
newlines, U+2028, U+2029, < and /. It does NOT add the surrounding quotes.
user.name = "Bo", | js renders Bo and you supply the quotes.
js is rarely needed for its escaping alone: in a JS-evaluated attribute the same
escaper is applied automatically to an undeclared slot inside a string literal.
Writing it silences the development-mode advisory and states the intent.
json
json
Serialises the value as a complete JSON literal, script-safely. Every < is
rewritten as a unicode escape so the value cannot form </script> or <!--, and
U+2028 / U+2029 go the same way. All three are legal JSON string escapes, so the
output is still valid JSON.
name = "Bo" and obj = { a: 1, b: "x" }:
Caveats. Because it is self-delimiting, this is the right choice in JavaScript
statement or expression position, where
| js is refused. Do not wrap it in your
own quotes as well. null serialises as the JSON literal null.
lower
lower
Lowercases the stringified value, with full Unicode case mapping.
null renders as the empty string. An array or object is first
serialised to JSON and then lowercased, which lowercases its KEYS too.
plural
plural(one = "item", many = one + "s")
Picks a singular or plural word based on a count.
null or non-numeric value counts as 0, so the plural word is used.
truncate
truncate(n = 50, suffix = "...")
Shortens a string to n CHARACTERS, not bytes, so it is Unicode-safe. The suffix is
appended only when it actually truncated.
null becomes the empty string, which is length 0 and never
truncates.
If truncation lands inside an unterminated HTML tag, everything from that <
onward is dropped before the suffix is added. That prevents half a tag from
swallowing the rest of the page, but it means truncating markup can produce almost
nothing:
unsafe_js
unsafe_js
No escaping at all. It declares that a value IS JavaScript the theme itself wrote,
rather than data.
upper
upper
Uppercases the stringified value, with full Unicode case mapping.
Loop filters
Usable ONLY in an{each} header, where they transform the collection before
iteration. Chained left to right.
filter
filter(key, value)
Keeps items whose item[key] equals value. Both arguments must be literals.
filter("id", "1") never matches a numeric 1 and
the loop falls to its {empty} branch.
Passing a variable as the key makes the key the empty string, so every item is
dropped and the loop renders {empty}. Nothing is reported.
limit
limit(n)
Truncates the collection to the first n items.
Filter 'limit' requires at least 1 argument(s); a variable reports
Filter 'limit' argument 0 must be a number. Both are InvalidFilterArgs, both
are render-time, and both empty the collection.
reverse
reverse
Reverses the collection.
sort
sort(key?, dir?)
Sorts ascending by default. With a key, sorts by that field on each item, falling
back to the whole item when the key is absent. The sort is stable.