Filters
absattrbatchcapitalizecomposedefaulteqescapeexistsfindflattenfloatfmt_floatfoldforallgegroupbygtintjoinlastlelengthlistlowerltmapmaxmd5minnenthpprintprintfrandomrangerejectreplacereverseroundsafeselectslicesortsplitstriptagsstrlensublistsubstringsumtitletojsontrimtruncateuniqueupperurlizewordcountwordwrapxmlattr

Statements

{%- set script = "<script></script>" -%}
{%- autoescape true -%}
{{ script }}
{% endautoescape -%}
{%- autoescape false -%}
{{ script }}
{% endautoescape -%}
{%- autoescape true -%}
{{ script | safe + '' | safe }}
{% endautoescape -%}
&lt;script&gt;&lt;/script&gt;
<script></script>
<script></script>

Itérer sur chaque élément d'une séquence.

A l'intérieur d'une boucle for, vous pouvez acceder à certaines variables automatiques :

loop.index
L'index courant de la boucle, en commençant à 1.
loop.index0
L'index courant de la boucle, en commençant à 0.
loop.revindex
Le nombre d'itération restantes jusqu'à la fin. Retourne 1 lors de la dernière itération.
loop.revindex0
Le nombre d'itération restantes jusqu'à la fin. Retourne 0 lors de la dernière itération.
loop.first
<code>true</code> lors de la première iteration uniquement.
loop.last
<code>true</code> lors de la dernière iteration uniquement.
loop.length
Le nombre total d'éléments dans la séquence.
loop.cycle
Une fontion pour cycler sur une séquence donnée en paramètre (c.f. l'exemple ci-dessous).
{{ { links: [ [ "http://yahoo.co.jp", "yahoo japan" ],
	      [ "http://google.co.jp", "google japan" ] ],
     links2:[ ("http://yahoo.co.jp", "yahoo japan"),
              ("http://google.co.jp", "google japan") ],
     obj: { name: "alice", age: 42, sex: "F" },
     str1: "abc",
     str2: "日本語"
   } }}
{%- for item in [ 0, 1, 2, 3, 4, 5 ] -%}
  - {{ item }}: {{ loop.cycle (["even","odd"]) }}
{% endfor -%}
{%- for item in links -%}
<a href="{{ item[0] }}">{{ item[1] }}</a>
{% endfor -%}
{%- for (href, title) in links2 -%}
<a href="{{ href }}">{{ title }}</a>
{% endfor -%}
{%- for (key, value) in obj -%}
  - {{ key }}: {{ value }}
{% endfor -%}
{% for s in str1 -%}
  {{ s }}({{ loop.index }})
{% endfor -%}
{% for s in str2 -%}
{{ s }}({{ loop.index }})
{% endfor -%}
- 0: even
- 1: odd
- 2: even
- 3: odd
- 4: even
- 5: odd
<a href="http://yahoo.co.jp">yahoo japan</a>
<a href="http://google.co.jp">google japan</a>
<a href="http://yahoo.co.jp">yahoo japan</a>
<a href="http://google.co.jp">google japan</a>
- name: alice
- age: 42
- sex: F
a(1)
b(2)
c(3)
日(1)
本(2)
語(3)

Macro are useful to put often used idioms into reusable component.

Note that macros are hoisted, and their scope is the toplevel scope. It means that you define two macro with the same name, the second will erase the first, even in the macro invocation occuring before the second definition.

Optionally, you can repeat the name of the macro in the endmacro part.

{% macro li (content) %}<li>{{ content }}</li>{% endmacro -%}
{% macro oli (content) %}{{ li (content) }}{% endmacro oli -%}
{% macro const () %}{{ oli('Item4') }}{% endmacro -%}
<ol>
  {{ oli ('Item1') }}
  {{ oli ('Item2') }}
  {{ oli ('Item3') }}
  {{ const () }}
</ol>
<ol>
  <li>Item1</li>
  <li>Item2</li>
  <li>Item3</li>
  <li>Item4</li>
</ol>

Use call statement to pass a macro to another macro.

{%- macro present (name) -%}
Hello, I am {{ name }}.{{ caller() }}
{%- endmacro -%}
{{ present ("Bob") }}
{% call present ("Alice") %} I'm a programmer.{% endcall %}
Hello, I am Bob.
Hello, I am Alice. I'm a programmer.

Function can be seen as macros that return a value instead of printing it.

{% function incr (i) %}{{i+1}}{% endfunction -%}
incr(1) = {{ incr (1) }}
incr(-1) = {{ incr (-1) }}

{% function lt1 (i) %}{{ i < 1 }}{% endfunction -%}
lt1(1) = {{ lt1 (1) }}
lt1(-1) = {{ lt1 (-1) }}

{% function obj (x, y) %}{{ {a:x,b:y} }}{% endfunction -%}

obj(1,2).a = {{ obj(1,2).a }}
obj(1,2).b = {{ obj(1,2).b }}

obj('a',2.5).a = {{ obj('a',2.5).a }}
obj('a',2.5).b = {{ obj('a',2.5).b }}

{% function inv (reverse=false, x, y) -%}
  {%- if reverse %}{{ {a:y,b:x} }}{% else %}{{ {a:x,b:y} }}{% endif -%}
{%- endfunction -%}

inv('a','b').a = {{ (inv('a','b')).a }}
inv(reverse=true,'a','b').a = {{ (inv(reverse=true,'a','b')).a }}

{% function add_val (val=0, x) -%}
  {{ [ x, (x + val) ] }}
{%- endfunction -%}
{% for x in [-1,0,1,2] | map (add_val, val=-2) -%}
  add_val(val=-2,{{x[0]}}) = {{x[1]}}
{% endfor -%}

{% function const () -%}{{ 4 }}{% endfunction -%}

const() = {{ const () }}
incr(1) = 2
incr(-1) = 0

lt1(1) = false
lt1(-1) = true

obj(1,2).a = 1
obj(1,2).b = 2

obj('a',2.5).a = a
obj('a',2.5).b = 2.5

inv('a','b').a = a
inv(reverse=true,'a','b').a = b

add_val(val=-2,-1) = -3
add_val(val=-2,0) = -2
add_val(val=-2,1) = -1
add_val(val=-2,2) = 0
const() = 4

The if statement allows us to check if an expression is true or false, and execute different code according to the result.

0, null, '', "", [], or {} are considered as false when used in a if/elif test. The rest is true.

{{ { hoge : "baz" } }}
{%- if hoge == "foo" -%}
hoge == "foo"
{%- elseif hoge == "bar" -%}
hoge == "bar"
{%- else if hoge == "hoge" -%}
hoge == "hoge"
{%- elif hoge == "baz" -%}
hoge == "baz"
{%- else -%}
But... What is hoge?
{%- endif %}
hoge == "baz"

The switch statement allows us to use compare a variable with a set of literal values.

{{ { foo : 'foo' } }}
{% switch foo %}
  {%- case 'bar' || 'baz' %}1
  {%- case 'foo' %}2
  {%- default %}3
{%- endswitch %}
2
{% if 1 in [1,2,3] -%}
<p>Yes, it works! <code>1</code> is in <code>[1,2,3]</code></p>
{%- endif %}
<p>Yes, it works! <code>1</code> is in <code>[1,2,3]</code></p>
{% filter upper -%}
must be upper
{%- endfilter %}
MUST BE UPPER
{{ { person : { name : "alice", age: 42 } } }}
- person.name: {{ person.name }}
- person.age: {{ person.age }}
- person["name"]: {{ person["name"] }}
- person["age"]: {{ person["age"] }}
- person.name: alice
- person.age: 42
- person["name"]: alice
- person["age"]: 42
{% raw -%}
Not expanded: {{ hoge }}
Not a for loop: {% for x in long_list %}{{x}}{% endfor %}
{%- endraw %}
Not expanded: {{ hoge }}
Not a for loop: {% for x in long_list %}{{x}}{% endfor %}

Lors de l'assignement d'une variable dans un block, la portée de cette dernière se limite au block dans lequel elle a été défini (et à ses blocks enfants). C'est à dire que vous pouvez accéder aux variables définies dans un block parent, mais pas les redfinir. Une affectation masquera l'ancienne définition de la variable tant que vous ne serez au sein du block courant, mais à l'exterieur du block, la variable sera toujours affectée à l'ancienne valeur.

Seuls les blocks if dérogent à la règle et modifie la variable du scope parent.

Voyez les namespaces pour des utiliser des variables modifiable par les blocks enfants.

{%- set hoge = "ok" -%}
{%- set foo, bar = ("foo", "bar") -%}
hoge: {{ hoge }}
foo: {{ foo }}
bar: {{ bar }}

{% set baz = 0 -%}
{%- set baz += 1 -%}
baz: {{ baz }}
{% set baz += 1 -%}
baz: {{ baz }}
{% set baz -= 1 -%}
baz: {{ baz }}
{% set baz *= 6 -%}
baz: {{ baz }}
{% set baz /= 2 -%}
baz: {{ baz }}
{% set baz %= 2 -%}
baz: {{ baz }}

{% set iterated = false -%}
{%- for item in [ 1, 2, 3 ] -%}
  {% set iterated = true %}
{%- endfor -%}
{%- if not iterated %}Did not iterate!{% endif %}
hoge: ok
foo: foo
bar: bar

baz: 1
baz: 2
baz: 1
baz: 6
baz: 3
baz: 1

Did not iterate!

Les namespaces peuvent être utilisés pour créer des variables modifiables depuis un block enfant.

{%- set ns = namespace (foo=0, bar='bar') -%}
{%- set key_expr_foo = "foo" -%}
{%- set key_expr_bar = "bar" -%}

{%- for i in [1,2,3] -%}
  {%- set ns.foo = ns.foo + i -%}
  {%- set ns.bar = ns.bar + i -%}
{%- endfor -%}

{%- set ns[key_expr_foo] *= 10 -%}
{%- set ns[key_expr_bar] += '!' -%}

{%- if ns.foo == 60 and ns.bar == 'bar123!' -%}
  Namespace works :)
{%- endif %}
Namespace works :)
{%- set list -%}
{%- macro li (content) %}<li>{{ content }}</li>{% endmacro -%}
{%- set item4 = '<Escaping works>' -%}
<ol>
  {{ li ('Item1') }}
  {{ li ('Item2') }}
  {{ li ('Item3') }}
  {{ li (item4) }}
</ol>
{%- endset -%}

Stored output:
{{ list }}

Variables defined inside block are not exposed:
{{ item4 }}

Stored output again:
{{ list }}
Stored output:
<ol>
  <li>Item1</li>
  <li>Item2</li>
  <li>Item3</li>
  <li>&lt;Escaping works&gt;</li>
</ol>

Variables defined inside block are not exposed:


Stored output again:
<ol>
  <li>Item1</li>
  <li>Item2</li>
  <li>Item3</li>
  <li>&lt;Escaping works&gt;</li>
</ol>

Use {%- to strip whitespaces before this token.

Use -%} to strip whitespaces after this token.

{%- for i in [1,2,3] -%}
  {{ i }}
{%- endfor %}
123
{% with foo = 10, hoge = 20 -%}
foo: {{ foo }}
hoge: {{ hoge }}
{%- endwith %}
foo: 10
hoge: 20

Tests

Tests are just functions that return a boolean.

Tests can be used with the standard function call syntax, but also with the is keyword in statements or expressions.

- 6 is divisibleby 4: {{ 6 is divisibleby 4 }}
- 6 is divisibleby (4): {{ 6 is divisibleby (4) }}
- divisibleby(3,6): {{ divisibleby(3,6) }}
- 3 is iterable: {{ 3 is iterable }}
- [1,2,3] is iterable: {{ [1,2,3] is iterable }}
- "hoge" is iterable: {{ "hoge" is iterable }}
- null is iterable: {{ null is iterable }}
- 6 is divisibleby 4: false
- 6 is divisibleby (4): false
- divisibleby(3,6): true
- 3 is iterable: false
- [1,2,3] is iterable: true
- "hoge" is iterable: true
- null is iterable: true

Operators

L'évaluation des tests booléens est séquentiel, de gauche à droite.

Dans e1 && e2, e1 est évalué, et si e1 retourne false, e2 n'est pas évalué du tout.

Dans e1 || e2, e1 est évalué, et si e1 retourne true, e2 n'est pas évalué du tout.

Utilisez les opérateurs not et ! pour inverser un booléen.

{{ { foo : "FOO", bar: "BAR" } }}
{% if foo == "BAR" || bar == "BAR" %}{% endif %}
{% if foo == "BAR" or bar == "BAR" %}{% endif %}
{% if foo == "FOO" && bar == "BAR" %}{% endif %}
{% if foo == "FOO" and bar == "BAR" %}{% endif %}
{% if not (foo == "BAR" and bar == "BAR") %}{% endif %}
{% if ! (foo == "BAR" || bar == "FOO") %}{% endif %}
✓
✓
✓
✓
✗
✗
1 + 1 = {{ 1 + 1 }}
1 - 1 = {{ 1 - 1 }}
2 * 3 = {{ 2 * 3 }}
5 / 2 = {{ 5 / 2 }}
2 ** 8 = {{ 2 ** 8 }}
8 % 3 = {{ 8 % 3 }}

"a" + "b" = {{ "a" + "b" }}
{% for i in [1,2] + [3,4] %}{{i}}{% endfor %}
({a:"foo"} + {b:"bar"}).a = {{ ({a:"foo"} + {b:"bar"}).a }}
({a:"foo"} + {b:"bar"}).b = {{ ({a:"foo"} + {b:"bar"}).b }}
({a:"foo"} + {a:"bar"}).a = {{ ({a:"foo"} + {a:"bar"}).a }}
1 + 1 = 2
1 - 1 = 0
2 * 3 = 6
5 / 2 = 2
2 ** 8 = 256.
8 % 3 = 2

"a" + "b" = ab
1234
({a:"foo"} + {b:"bar"}).a = foo
({a:"foo"} + {b:"bar"}).b = bar
({a:"foo"} + {a:"bar"}).a = bar
{{ (1 + 1 == 2) ? 'yes' : 'no' }}
{{ (1 + 1 == 3) ? 'no' : (1 + 1 == 2) ? 'yes' : 'no' }}
{{ null ? 'yes' : 'no' }}
yes
yes
no

The fat arrow operator => is used to define anonymous functions.

It is right associative and have the lowest precedence of all the operators.

((i) => i + 1)(1) = {{ ((i) => i + 1)(1) }}
(i => i + 1)(-1) = {{ (i => i + 1)(-1) }}
((a, b) => a + b)(1, 2) = {{ ((a, b) => a + b)(1, 2) }}
(() => 'foo')() = {{ (() => 'foo')() }}
((i) => i + 1)(1) = 2
(i => i + 1)(-1) = 0
((a, b) => a + b)(1, 2) = 3
(() => 'foo')() = foo

Built-in filters

ocamldoc

abs (num) Return the absolute value of num.

ocamldoc

attr (name, obj)

{{ foo | attr ("bar") }} is {{ foo.bar }}.

{{ foo | attr ("bar.baz") }} is {{ foo.bar.baz }}.

ocamldoc
{{ { list: [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] } }}
Batch of length 4 padded with "X":
{% for row in batch (4, list, fill_with="X") -%}
|{% for x in row %} {{ x }} |{% endfor %}
{% endfor -%}
Batch of length 4 padded with "X":
| 10 | 20 | 30 | 40 |
| 50 | 60 | 70 | 80 |
| 90 | 100 | X | X |
ocamldoc
{{ 'this phrase should be capitalized!' | capitalize }}
This phrase should be capitalized!
ocamldoc

compose (f, g)

The composition function. compose (f, g)) (x) is f (g (x)).

ocamldoc

default (default_value, value)

Return value if it is defined from null, and default otherwise.

ocamldoc
ocamldoc

escape (string). Replaces &, ", < and > with their corresponding HTML entities.

ocamldoc
{% set msg = 'Hello, world!' -%}
{% set src = 'From eval!' -%}

Only the last expression is returned:
- "{{ eval("{{ msg }} {{ src }}") }}"
- "{{ eval("{{ msg + ' ' + src }}") }}"

Be careful with trailing whitespaces:
- "{{ eval("{{ msg + ' ' + src }} ") }}"
Only the last expression is returned:
- "From eval!"
- "Hello, world! From eval!"

Be careful with trailing whitespaces:
- " "
ocamldoc

exists (fn, seq)

{% if exists (eq(0), [0,1,2,3,4]) %}YES{% endif %}
{% if not (exists (eq(5), [0,1,2,3,4])) %}NO{% endif %}
YES
NO
ocamldoc
ocamldoc
ocamldoc
{%- set test = [[1,2],[3],4] | flatten -%}
test[0]: {{ test[0] }}
test[1]: {{ test[1] }}
test[2]: {{ test[2] }}
test[3]: {{ test[3] }}
test[0]: 1
test[1]: 2
test[2]: 3
test[3]: 4
ocamldoc
ocamldoc
ocamldoc
ocamldoc
ocamldoc

groupby (fn, seq)

{{ { persons : [ { name : "alice", age: 42, sex : "F" },
                 { name : "bob", age: 34, sex : "M" },
                 { name : "carol", age: 29, sex : "F" } ] }
}}
{%- for g in persons | groupby (attr('sex')) | sort (attribute='grouper') -%}
- Gender: {{ g.grouper }}
  {%- for p in g.list | sort (attribute='name') %}
  - {{ p.name }}
  {%- endfor %}
{% endfor -%}
- Gender: F
  - alice
  - carol
- Gender: M
  - bob
ocamldoc
ocamldoc

join (sep, seq)

{{ join (", ", [1,2,3,4,5,6,7,8]) }}
1, 2, 3, 4, 5, 6, 7, 8
ocamldoc

last (seq). Return the last element of sequence seq.

ocamldoc
ocamldoc

length (seq). Return the number of elements in sequence seq.

ocamldoc
ocamldoc
ocamldoc
ocamldoc
ocamldoc
{{ max([10, 30, 20]) }}
30
ocamldoc
ocamldoc
{{ min ([10, 20, 5, 30]) }}
5
ocamldoc
ocamldoc
ocamldoc

printf(fmt, a1, a2, ..., aN) Fill fmt with a1 a2 ... aN. Support a subset of OCaml format type: %d %s and %f.

NB: %s would accept any type as long as it can to represented as a string.

{{ printf ("%d %s, %d people, that's %.1f apple per person.", 8, "apples", 4, 0.5) }}
8 apples, 4 people, that&apos;s 0.5 apple per person.
ocamldoc
ocamldoc

range (start, stop)

- range(0,3): {% for x in range(0,3) %}{{x}}{% endfor %}
- range(3,0): {% for x in range(3,0) %}{{x}}{% endfor %}
- range("a","e"): {% for x in range("a","e") %}{{x}}{% endfor %}
- range(0,3): 0123
- range(3,0): 3210
- range("a","e"): abcde
ocamldoc
ocamldoc

replace (src, dst, s) The syntax for regular expressions is the same as in Gnu Emacs.

Return a string identical to s except that all substrings of s that match regexp src have been replaced by dst.

The replacement template dst can contain \1, \2, etc; these sequences will be replaced by the text matched by the corresponding group in the regular expression src. \0 stands for the text matched by the whole regular expression.

Note: in src and dst any backslash character in the regular expression must be doubled to make it past the Jingoo string parser.

In particular, if you want a regular expression that matches a single backslash character, you need to quote it by adding a second backslash. Then you need to quote both backslashes (according to the syntax of string constants in Jingoo) by doubling them again, so you need to write four backslash characters: "\\\\".

{{ replace ("ho", "hi", "hoge") }}
{{ replace ("日本", "英", "日本語") }}
{{ replace ('"\\([^"]*\\)"', '--- \\1 ---', '"FOO"') }}
hige
英語
--- FOO ---
ocamldoc
ocamldoc

round (method, val). method can be "floor" or "ceil".

- 1.5 | round ("floor"): {{ 1.5 | round ("floor") }}
- 1.5 | round ("ceil"): {{ 1.5 | round("ceil") }}
- 1.5 | round ("floor"): 1.
- 1.5 | round ("ceil"): 2.
ocamldoc

Mark a string value as safe: it won't be escaped.

ocamldoc
ocamldoc
{{ { list: [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] } }}
List sliced in 4:
{% for s in slice (4, list) -%}
- [{% for x in s %} {{ x }}{% endfor %} ]
{% endfor -%}
List sliced in 4:
- [ 10 20 30 ]
- [ 40 50 60 ]
- [ 70 80 ]
- [ 90 100 ]
ocamldoc

sort (seq). Support the following optionnal keywords:

reverse
Sort using descending order.
attribute
Compare items using a given attribute. Support dotted notation.
compare
Provide a comparison function to be used instead of built-in.

{{ { data: [ ["A", 0], ["Z", 2], ["b", 1] ] } }}
{%- function ic_fst_cmp (a, b) -%}
  {{ compare (lower (a[0]), lower(b[0])) }}
{%- endfunction -%}

{%- set data = [("A", 0), ("Z", 2), ("b", 1)] -%}

sort(data):
 {% for x in data | sort %} {{ x[0] }}{% endfor %}
sort(data, compare=if_fst_cmp):
 {% for x in data | sort (compare=ic_fst_cmp) %} {{ x[0] }}{% endfor %}
sort(data):
  A Z b
sort(data, compare=if_fst_cmp):
  A b Z
ocamldoc
ocamldoc
ocamldoc

strlen (string). Number of UTF-8 characters.

- strlen("hogehoge"): {{ strlen("hogehoge") }}
- strlen("日本語"): {{ strlen("日本語") }}
- strlen("hogehoge"): 8
- strlen("日本語"): 3
ocamldoc
ocamldoc
- substring (3, 2, "hogehoge"): "{{ substring (3, 2, "hogehoge") }}"
- substring (0, 2, "日本語"): "{{ substring (0, 2, "日本語") }}"
- substring (3, 2, "hogehoge"): "eh"
- substring (0, 2, "日本語"): "日本"
ocamldoc
{{ [ 0, 1, 2, 3, -1 ] | sum }}
5
ocamldoc
{{ 'this phrase should be in title case!' | title }}
This Phrase Should Be In Title Case!
ocamldoc
ocamldoc
ocamldoc
upper test: {{ "must be upper" | upper }}
upper test: MUST BE UPPER
ocamldoc
ocamldoc
Word count for "hoge hage hige" = {{ "hoge hage hige" | wordcount }}
Word count for "hoge hage" = {{ "hoge hage" | wordcount }}
Word count for "hoge hage hige" = 3
Word count for "hoge hage" = 2
ocamldoc
ocamldoc