Interpolation¶
{{ identifier }} (or {{{ identifier }}} for unescaped output) resolves identifier against the
current render context and emits the result. This page covers every identifier form kBars
recognizes and the order in which they're tried.
Identifier forms, in priority order¶
| Form | Resolves to |
|---|---|
this / . |
The entire current top-of-stack context |
this.foo, this/foo |
foo resolved against the current context (dot-notation / RFC 6901) |
./foo |
Same as this/foo |
../foo, ../../foo, … |
foo resolved against an ancestor context, one .. per level up |
@env/name, @env.name |
An environment property — see Environment Properties |
@local/name, @local.name |
A scoped variable bound with {{= }} — see Scoped Variables |
@index, @key, or ../@index, ../@key |
The current (or an ancestor) loop position — see below |
| anything else | Resolved against the current context, as dot-notation or an RFC 6901 pointer |
The last row — "anything else" — is the common case and is dispatched by
kPointer's KPointer.from(identifier):
- Identifiers starting with
/are RFC 6901 JSON Pointers:{{ /user/name }}. - Identifiers starting with
#are RFC 6901 URI fragment identifiers (percent-encoding is decoded before resolution):{{ #/user/name }}. - Everything else is Mustache-style dot notation:
{{ name }},{{ user.city }}. A leading dot is stripped; trailing or consecutive dots throwkbParseExceptionat parse time.
An identifier that resolves to nothing (an absent path, or a null context) renders as the literal
text "null" — see Blocks for how the same absence is treated as falsy inside
{{#if}}/{{#unless}}.
this / . and dotted/pointer suffixes¶
{{ this }} {{! the whole current context }}
{{ . }} {{! same as this }}
{{ this.name }} {{! same as {{ name }} }}
{{ this/name }} {{! same as {{ /name }} — RFC 6901 form }}
{{ ./name }} {{! same as this/name }}
../ — walking up the context stack¶
Every {{#each}} iteration and {{#with}} block pushes a new context frame. ../ walks back up
that stack, one level per repetition, before resolving the remainder:
{{#each posts}}
{{ title }}
{{#each comments}}
by {{ author }}, on {{ ../title }}
{{/each}}
{{/each}}
Inside the inner {{#each}}, ../title steps back out to the enclosing post's context before
reading title. ../../title would step back two levels.
@index / @key — loop position¶
Inside {{#each}}, the current position is available as a special identifier read from the
innermost active loop frame:
- Iterating a list pushes
@index— the zero-based position of the current element. - Iterating a struct (JSON object / map) pushes
@key— the current entry's key, and iterates its entries in insertion order (not sorted, not hash order — this is a normative property of the conformance suite; see Iteration Order).
Prefix with ../ to read an enclosing loop's position from inside a nested loop —
../@index, ../@key — the same ancestor-walking rule as any other ../-prefixed identifier.
Literal values¶
An interpolation expression can also be a literal instead of an identifier:
- Strings:
"…"or'…', with escape sequences\\,\",\',\n,\r,\t,\uXXXX. - Numbers:
-?[0-9]+(\.[0-9]+)?(no scientific notation in source; see Number Rendering for how numbers render). - Booleans and null:
true,false,null.
String primitives render unquoted; other values render in their Kpa form. See
Expressions for how literals combine with binary operators, and
Transforms for piping any of these through |.