Definitions
Before we go any further, let’s baseline some definitions –
Output braces are two consecutive braces: {{
and }}
. The result of this will be text output in place of whatever what is between the braces (and the braces themselves).
Logic braces are a brace appended/prepended by a percent sign: {%
and %}
. This will not result in output, but will be evaluated by the engine and may affect future statements/flow.
An identifier is a text token inside output braces that maps to a value in a TemplateContext
.
{{ name }}
The engine will attempt to find a corresponding value for name
by searching the context and its contained model or scopes.
An identifier might be modified by a member, which is one or more tokens appended to an identifier using a dot (.
).
{{ name.first }}
In the above code, first
is a member appended to the identifier name
.
Theoretically, an identifier can have an unlimited number of members:
{{ person.parent.name.full.first.size }}
A member invokes some behavior on the output from whatever is to the left of it – it might invoke several different behaviors depending on what the identifier represents.
The member might be interpreted as:
- The name of a property on an underlying object
- The name of a key in an underlying dictionary
- A key which executes code to return a calculated value
See Virtual Members for a deep dive into how this works.
A tag is a template statement in logic braces which has no closing tag:
{% continue %}
There is no endcontinue
tag. Therefore, it encloses nothing.
A block also uses logic braces, but it encloses something – text, or other Liquid tags, blocks, or identifiers. The opening tag is followed by a tag of the same name prefaced by end
.
{% comment %}
This is a comment.
{% endcomment %}
Blocks are enforced by the parser. If a block doesn’t have a corresponding end tag, the parser will throw an exception.
You can define your own tags and blocks, either from a set of three pre-defined patterns, or you can extend the parser to define your own patterns.
A filter is a text value appended to an identifier/member token by a “pipe” (|
).
{{ name | reverse }}
A filter might have one or more arguments. These arguments are usually positional.
{{ amount | format_number:"N0" }}
{{ name | replace:"a","b" }}
Some filters might take named arguments. This is rare, but is sometimes done when the number of arguments is variable.
{{ 'Vehicle: {0}, Wheels: {1}' | format_string:'Bicycle', 2, culture:'en' }}
In that example, there are two positional arguments – Bicycle
and 2
– and a named argument of culture
with a value of en
.
There are dozens of built-in filters, and you can write your own.