Arguments must be literals
Breaking this rule fails silently.currency falls back to no symbol at all and a
leading space appears where the currency marker should be. The compiler says
nothing.
default is the one exception. Its argument is evaluated in scope, so
default(user.name) works. Every other filter reads its arguments literally.Filters bind loosest
A filter applies to the whole expression to its left, including a ternary.archived, so the ternary chose "live", and upper then
applied to that result rather than to the "draft" it sits next to.
Parenthesise for the other reading:
${ n | int + 1 } is a
parse error; write ${ (n | int) + 1 }.
Text
upper, lower and truncate(n, suffix).
truncate counts characters rather than bytes, so it is safe on non-ASCII
text, and it appends the suffix only when it actually cut something. The
default length is 50 and the default suffix is three dots.
Numbers
int and float coerce, fixed(n) formats.
fixed replaces toFixed, and it returns a string with exactly that many
decimal places.
int and float parse all-or-nothing. "12abc" becomes 0, not 12, and so
does anything else that is not cleanly a number, including null, arrays and
objects.
Comparisons in Slurp do not coerce, so {if product.stock > 0} is false when
stock is the string "10". Write {if (product.stock | int) > 0}. That trap is
explained in full under
displaying data.
Money
- The symbol always prefixes, for every code, so EUR renders as a leading euro sign rather than the trailing one much of Europe writes. Grouping and the decimal separator do follow the code.
- Only JPY uses zero decimals. Everything else uses two, and rounds once, so
19.999renders as$20.00. - An unknown code is not an error. The code plus a space becomes the symbol,
which is how
SEK 12.50comes out.
Money arrives as a string
A server decimal serialises to JSON as a string such as"49.990000", not as
a number. Filters coerce, so this is invisible most of the time:
Number(...) wrapper that is "49.990000".toFixed(2), which
throws at runtime. The compiler does not read emitted JavaScript, so nothing
warns. Format with | currency or | fixed server-side and pass the finished
string where possible.
Dates
YYYY, YY, MMMM, MMM, MM, M, DD and D.
There are no time tokens at all: no hours, minutes, seconds, timezone or
day-of-week. For a time, format it server-side.
There is also no escaping in the format string, so a stray D or M in
surrounding text gets substituted. Keep the format to the date and write the
words outside the filter.
Fallbacks and counts
default substitutes when a value is empty, where empty means null, the empty
string, the empty array or the empty object. 0 and false are not empty and
pass straight through.
plural picks a word from a count:
Collections
Four filters work only in an{each} header, and they run before iteration.
They are a separate set from everything above.
They chain in the order written:
"desc" reverses. "DESC" and "descending"
both silently mean ascending.
And filter compares strictly, exactly like ==. filter("stock", "3") never
matches a numeric 3, and items that are not objects or that lack the key are
dropped rather than kept.
sort is stable, and it orders cross-type pairs by type rank rather than
erratically, so a mixed collection sorts deterministically.
Sending values to JavaScript
js and json put a value safely inside a <script> body or a
JavaScript-evaluated attribute. Every ${ } in a script body must end in one of
them, and which one depends on where the slot sits.
When a filter goes wrong
Filters fail in three ways. An unknown filter fails the build. So does using a loop filter in value position, or a value filter in an{each} header. The two sets are disjoint
and the compiler checks both directions:
limit() argument fails the build, because that
argument is required rather than defaulted:
filter() empties the
collection, which then renders the {empty} branch:
Next
Filter reference
All 17 filters alphabetically, with null behaviour and traps.
Control flow
Where the loop filters go, and the iteration budget.
Scripts and attributes
When
| js applies and when | json does.Common mistakes
The silent failures, collected in one place.