mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-29 07:05:12 -07:00
Revert 4a7ddc49ca7b5c85bde88dd316d13949f86ec4a5 ... 7c9d9e58e3b2e3e6336c4a803a5a5deee9ea4d6f
@@ -0,0 +1,343 @@
|
|||||||
|
There are two types of markup in Liquid: Output and Tag.
|
||||||
|
|
||||||
|
* Output markup (which may resolve to text) is surrounded by
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{{ matched pairs of curly brackets (ie, braces) }}
|
||||||
|
```
|
||||||
|
|
||||||
|
* Tag markup (which cannot resolve to text) is surrounded by
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% matched pairs of curly brackets and percent signs %}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
Here is a simple example of Output:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
Hello {{name}}
|
||||||
|
Hello {{user.name}}
|
||||||
|
Hello {{ 'tobi' }}
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="filters"></a>
|
||||||
|
|
||||||
|
### Advanced output: Filters
|
||||||
|
|
||||||
|
Output markup takes filters. Filters are simple methods. The first parameter
|
||||||
|
is always the output of the left side of the filter. The return value of the
|
||||||
|
filter will be the new left value when the next filter is run. When there are
|
||||||
|
no more filters, the template will receive the resulting string.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
Hello {{ 'tobi' | upcase }}
|
||||||
|
Hello tobi has {{ 'tobi' | size }} letters!
|
||||||
|
Hello {{ '*tobi*' | textilize | upcase }}
|
||||||
|
Hello {{ 'now' | date: "%Y %h" }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Standard Filters
|
||||||
|
|
||||||
|
* `date` - reformat a date [syntax reference](http://liquid.rubyforge.org/classes/Liquid/StandardFilters.html#M000012)
|
||||||
|
* `capitalize` - capitalize words in the input sentence
|
||||||
|
* `downcase` - convert an input string to lowercase
|
||||||
|
* `upcase` - convert an input string to uppercase
|
||||||
|
* `first` - get the first element of the passed in array
|
||||||
|
* `last` - get the last element of the passed in array
|
||||||
|
* `join` - join elements of the array with certain character between them
|
||||||
|
* `sort` - sort elements of the array
|
||||||
|
* `map` - map/collect an array on a given property
|
||||||
|
* `size` - return the size of an array or string
|
||||||
|
* `escape` - escape a string
|
||||||
|
* `escape_once` - returns an escaped version of html without affecting existing escaped entities
|
||||||
|
* `strip_html` - strip html from string
|
||||||
|
* `strip_newlines` - strip all newlines (\n) from string
|
||||||
|
* `newline_to_br` - replace each newline (\n) with html break
|
||||||
|
* `replace` - replace each occurrence *e.g.* `{{ 'foofoo' | replace:'foo','bar' }} #=> 'barbar'`
|
||||||
|
* `replace_first` - replace the first occurrence *e.g.* `{{ 'barbar' | replace_first:'bar','foo' }} #=> 'foobar'`
|
||||||
|
* `remove` - remove each occurrence *e.g.* `{{ 'foobarfoobar' | remove:'foo' }} #=> 'barbar'`
|
||||||
|
* `remove_first` - remove the first occurrence *e.g.* `{{ 'barbar' | remove_first:'bar' }} #=> 'bar'`
|
||||||
|
* `truncate` - truncate a string down to x characters
|
||||||
|
* `truncatewords` - truncate a string down to x words
|
||||||
|
* `prepend` - prepend a string *e.g.* `{{ 'bar' | prepend:'foo' }} #=> 'foobar'`
|
||||||
|
* `append` - append a string *e.g.* `{{ 'foo' | append:'bar' }} #=> 'foobar'`
|
||||||
|
* `minus` - subtraction *e.g.* `{{ 4 | minus:2 }} #=> 2`
|
||||||
|
* `plus` - addition *e.g.* `{{ '1' | plus:'1' }} #=> '11'`, `{{ 1 | plus:1 }} #=> 2`
|
||||||
|
* `times` - multiplication *e.g* `{{ 5 | times:4 }} #=> 20`
|
||||||
|
* `divided_by` - division *e.g.* `{{ 10 | divided_by:2 }} #=> 5`
|
||||||
|
* `split` - split a string on a matching pattern *e.g.* `{{ "a~b" | split:~ }} #=> ['a','b']`
|
||||||
|
* `modulo` - remainder, *e.g.* `{{ 3 | modulo:2 }} #=> 1`
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
Tags are used for the logic in your template. New tags are very easy to code,
|
||||||
|
so I hope to get many contributions to the standard tag library after releasing
|
||||||
|
this code.
|
||||||
|
|
||||||
|
Here is a list of currently supported tags:
|
||||||
|
|
||||||
|
* **assign** - Assigns some value to a variable
|
||||||
|
* **capture** - Block tag that captures text into a variable
|
||||||
|
* **case** - Block tag, its the standard case...when block
|
||||||
|
* **comment** - Block tag, comments out the text in the block
|
||||||
|
* **cycle** - Cycle is usually used within a loop to alternate between values, like colors or DOM classes.
|
||||||
|
* **for** - For loop
|
||||||
|
* **if** - Standard if/else block
|
||||||
|
* **include** - Includes another template; useful for partials
|
||||||
|
* **raw** - temporarily disable tag processing to avoid syntax conflicts.
|
||||||
|
* **unless** - Mirror of if statement
|
||||||
|
|
||||||
|
### Comments
|
||||||
|
|
||||||
|
Comment is the simplest tag. It just swallows content.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
We made 1 million dollars {% comment %} in losses {% endcomment %} this year
|
||||||
|
```
|
||||||
|
|
||||||
|
### Raw
|
||||||
|
|
||||||
|
Raw temporarily disables tag processing.
|
||||||
|
This is useful for generating content (eg, Mustache, Handlebars) which uses conflicting syntax.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% raw %}
|
||||||
|
In Handlebars, {{ this }} will be HTML-escaped, but {{{ that }}} will not.
|
||||||
|
{% endraw %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### If / Else
|
||||||
|
|
||||||
|
`if / else` should be well-known from any other programming language.
|
||||||
|
Liquid allows you to write simple expressions in the `if` or `unless` (and
|
||||||
|
optionally, `elsif` and `else`) clause:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% if user %}
|
||||||
|
Hello {{ user.name }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.name == 'tobi' %}
|
||||||
|
Hello tobi
|
||||||
|
{% elsif user.name == 'bob' %}
|
||||||
|
Hello bob
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.name == 'tobi' or user.name == 'bob' %}
|
||||||
|
Hello tobi or bob
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.name == 'bob' and user.age > 45 %}
|
||||||
|
Hello old bob
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.name != 'tobi' %}
|
||||||
|
Hello non-tobi
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Same as above
|
||||||
|
{% unless user.name == 'tobi' %}
|
||||||
|
Hello non-tobi
|
||||||
|
{% endunless %}
|
||||||
|
|
||||||
|
# Check if the user has a credit card
|
||||||
|
{% if user.creditcard != null %}
|
||||||
|
poor sob
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Same as above
|
||||||
|
{% if user.creditcard %}
|
||||||
|
poor sob
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Check for an empty array
|
||||||
|
{% if user.payments == empty %}
|
||||||
|
you never paid !
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.age > 18 %}
|
||||||
|
Login here
|
||||||
|
{% else %}
|
||||||
|
Sorry, you are too young
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# array = 1,2,3
|
||||||
|
{% if array contains 2 %}
|
||||||
|
array includes 2
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# string = 'hello world'
|
||||||
|
{% if string contains 'hello' %}
|
||||||
|
string includes 'hello'
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Case Statement
|
||||||
|
|
||||||
|
If you need more conditions, you can use the `case` statement:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% case condition %}
|
||||||
|
{% when 1 %}
|
||||||
|
hit 1
|
||||||
|
{% when 2 or 3 %}
|
||||||
|
hit 2 or 3
|
||||||
|
{% else %}
|
||||||
|
... else ...
|
||||||
|
{% endcase %}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Example:*
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% case template %}
|
||||||
|
|
||||||
|
{% when 'label' %}
|
||||||
|
// {{ label.title }}
|
||||||
|
{% when 'product' %}
|
||||||
|
// {{ product.vendor | link_to_vendor }} / {{ product.title }}
|
||||||
|
{% else %}
|
||||||
|
// {{page_title}}
|
||||||
|
{% endcase %}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cycle
|
||||||
|
|
||||||
|
Often you have to alternate between different colors or similar tasks. Liquid
|
||||||
|
has built-in support for such operations, using the `cycle` tag.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% cycle 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'one', 'two', 'three' %}
|
||||||
|
|
||||||
|
will result in
|
||||||
|
|
||||||
|
one
|
||||||
|
two
|
||||||
|
three
|
||||||
|
one
|
||||||
|
```
|
||||||
|
|
||||||
|
If no name is supplied for the cycle group, then it's assumed that multiple
|
||||||
|
calls with the same parameters are one group.
|
||||||
|
|
||||||
|
If you want to have total control over cycle groups, you can optionally specify
|
||||||
|
the name of the group. This can even be a variable.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% cycle 'group 1': 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'group 1': 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'group 2': 'one', 'two', 'three' %}
|
||||||
|
{% cycle 'group 2': 'one', 'two', 'three' %}
|
||||||
|
|
||||||
|
will result in
|
||||||
|
|
||||||
|
one
|
||||||
|
two
|
||||||
|
one
|
||||||
|
two
|
||||||
|
```
|
||||||
|
|
||||||
|
### For loops
|
||||||
|
|
||||||
|
Liquid allows `for` loops over collections:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% for item in array %}
|
||||||
|
{{ item }}
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
During every `for` loop, the following helper variables are available for extra
|
||||||
|
styling needs:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
forloop.length # => length of the entire for loop
|
||||||
|
forloop.index # => index of the current iteration
|
||||||
|
forloop.index0 # => index of the current iteration (zero based)
|
||||||
|
forloop.rindex # => how many items are still left?
|
||||||
|
forloop.rindex0 # => how many items are still left? (zero based)
|
||||||
|
forloop.first # => is this the first iteration?
|
||||||
|
forloop.last # => is this the last iteration?
|
||||||
|
```
|
||||||
|
|
||||||
|
There are several attributes you can use to influence which items you receive in
|
||||||
|
your loop
|
||||||
|
|
||||||
|
`limit:int` lets you restrict how many items you get.
|
||||||
|
`offset:int` lets you start the collection with the nth item.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
# array = [1,2,3,4,5,6]
|
||||||
|
{% for item in array limit:2 offset:2 %}
|
||||||
|
{{ item }}
|
||||||
|
{% endfor %}
|
||||||
|
# results in 3,4
|
||||||
|
```
|
||||||
|
|
||||||
|
Reversing the loop
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% for item in collection reversed %} {{item}} {% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of looping over an existing collection, you can define a range of
|
||||||
|
numbers to loop through. The range can be defined by both literal and variable
|
||||||
|
numbers:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
# if item.quantity is 4...
|
||||||
|
{% for i in (1..item.quantity) %}
|
||||||
|
{{ i }}
|
||||||
|
{% endfor %}
|
||||||
|
# results in 1,2,3,4
|
||||||
|
```
|
||||||
|
|
||||||
|
### Variable Assignment
|
||||||
|
|
||||||
|
You can store data in your own variables, to be used in output or other tags as
|
||||||
|
desired. The simplest way to create a variable is with the `assign` tag, which
|
||||||
|
has a pretty straightforward syntax:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% assign name = 'freestyle' %}
|
||||||
|
|
||||||
|
{% for t in collections.tags %}{% if t == name %}
|
||||||
|
<p>Freestyle!</p>
|
||||||
|
{% endif %}{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
|
Another way of doing this would be to assign `true / false` values to the
|
||||||
|
variable:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% assign freestyle = false %}
|
||||||
|
|
||||||
|
{% for t in collections.tags %}{% if t == 'freestyle' %}
|
||||||
|
{% assign freestyle = true %}
|
||||||
|
{% endif %}{% endfor %}
|
||||||
|
|
||||||
|
{% if freestyle %}
|
||||||
|
<p>Freestyle!</p>
|
||||||
|
{% endif %}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to combine a number of strings into a single string and save it to
|
||||||
|
a variable, you can do that with the `capture` tag. This tag is a block which
|
||||||
|
"captures" whatever is rendered inside it, then assigns the captured value to
|
||||||
|
the given variable instead of rendering it to the screen.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% capture attribute_name %}{{ item.title | handleize }}-{{ i }}-color{% endcapture %}
|
||||||
|
|
||||||
|
<label for="{{ attribute_name }}">Color:</label>
|
||||||
|
<select name="attributes[{{ attribute_name }}]" id="{{ attribute_name }}">
|
||||||
|
<option value="red">Red</option>
|
||||||
|
<option value="green">Green</option>
|
||||||
|
<option value="blue">Blue</option>
|
||||||
|
</select>
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user