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.
Put another way, Fluid starts on the left-most segment and gets some value from it, then successively passes this value “down the line” to the right, which gets progressively modified until it reaches the end, at which point it is output.
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.