Tera とは
Tera は、Rust のテンプレートエンジン。
Rust 製の Static Site Generator である Zola などで利用されている。
テンプレート構文は Jinja2 と同様。
デリミタ
デリミタは3種類
{% ... %}文{{ ... }}式(テンプレート出力に印字される){# ... #}コメント(テンプレート出力に印字されない)
以下のように使う
{% if price < 10 %}
{# Print when price is less than 10 #}
Price is {{ price }}.
{% endif %}
price が 5 の場合、以下のように出力される。
Price is 5.
空行を出力しないようにするには、- を使い、文の前の空白を全て削除するには {%- とし、文の後の空白を全て削除するには -%} とする。
{{- と -}}、{#- と -#} も同様。
リテラル
- ブール型:
true/false(True/Falseも可) - 整数
- 浮動少数
- 文字列:
",',`のいずれかで括る - 配列: リテラルをカンマ区切りで記載し
[と]で括る
変数
変数の割り当ては set を使う
{% set my_var = "hello" %}
{{ my_var }}
グローバル変数とするには set_global を使う。
{% set_global my_var = "hello" %}
属性へのアクセスは {{ product.name }} のように . を使う
{{ product['name'] }} または {{ product["name"] }} のようにするこもできる(項目が引用符で囲まれていない場合は、変数として扱われる)。
配列へのアクセスは {{ array.1 }} のように添え字を指定できる。
演算
四則演算
+: 加算{{ 1 + 1 }}-: 減算{{ 2 - 1 }}/: 除算{{ 10 / 2 }}*: 乗算{{ 5 * 2 }}%: 剰余{{ 2 % 2 }}
比較演算
==!=>=<=><
論理演算
and: 論理積or: 論理和not: 否定
文字列連結
~ にて文字列連結できる
{{ "hello " ~ 'world' ~!}}
in checking
in 演算子で、左辺が右辺に含まれているかどうかをチェックできる
{{ some_var in [1, 2, 3] }}
{{ 'index' in page.path }}
{{ an_ident not in an_obj }}
フィルタ
| で連結することで、変数をフィルタすることができる。
以下の例では、name という変数を小文字に変換し、doctor を Dr. に変換する。
{{ name | lower | replace(from="doctor", to="Dr.") }}
フィルターは数学演算で使用できるが、優先順位は最も低い。
以下の様にブロックとして適用することもできる。
{% filter upper %}
Hello
{% endfilter %}
ビルトインで以下のフィルタが提供されている。
| フィルタ | 説明 |
|---|---|
lower |
lowercase |
upper |
uppercase |
wordcount |
ワード・カウント |
capitalize |
キャピタライズ |
replace |
置換 replace(from="Robert", to="Bob") |
addslashes |
I'm using Tera → I\'m using Tera |
slugify |
-Hello world! → hello-world |
title |
foo bar → Foo Bar |
trim |
トリム |
trim_start |
開始トリム |
trim_end |
終了トリム |
trim_start_matches |
trim_start_matches(pat="//") //a/b/c// → a/b/c// |
trim_end_matches |
trim_end_matches(pat="//") //a/b/c// → //a/b/c |
truncate |
truncate(length=10) |
linebreaksbr |
\n or \r\n → <br> |
spaceless |
<p>\n<a> </a>\r\n </p> → <p><a></a></p> |
indent |
インデント(デフォルトはスペース4つ) |
striptags |
<b>Joel</b> → Joel |
first |
配列から先頭要素を取得 |
last |
配列から末尾要素を取得 |
nth |
配列からN番目要素を取得 |
join |
文字列結合 |
length |
配列の長さを取得 |
reverse |
文字列や配列を逆順に |
sort |
配列のソート |
unique |
配列のユニーク |
slice |
配列のスライス |
group_by |
配列のグループ化 |
filter |
配列要素のフィルタリング |
map |
配列内の各オブジェクトから属性を取得 |
concat |
配列への値の追加 |
urlencode |
URLエンコード |
urlencode_strict |
URLエンコード |
abs |
絶対値 |
pluralize |
値が±1と等しくない場合は複数形の接尾辞を返し、そうでない場合は単数形の接尾辞を返す |
round |
数値の丸め |
filesizeformat |
整数を 110 MB のような形式へ |
date |
タイムスタンプを YYYY-MM-DD などの文字列化 |
escape |
HTMLエスケープ |
escape_xml |
XMLエスケープ |
safe |
変数を安全としてマークすることで HTML はエスケープされなくなる(式の最後のフィルターである場合にのみ機能する) |
get |
オブジェクトから値にアクセス |
split |
分割 split(pat="/") |
int |
整数化 |
float |
浮動小数化 |
json_encode |
JSON化 |
as_str |
文字列化 |
default |
変数がコンテキスト内に存在しない場合にデフォルト値を返す |
以下のように自身でフィルタを登録できる。
tera.register_filter("upper", string::upper);
if
{% if price < 10 or always_show %}
Price is {{ price }}.
{% elif price > 1000 and not rich %}
That's expensive!
{% else %}
N/A
{% endif %}
odd のようなテスト関数を使うこともできる。
{% if my_number is odd %}
Odd
{% endif %}
{% if my_number is not odd %}
Even
{% endif %}
以下のようなビルトインのテスト関数が提供されている。
| テスト関数 | 説明 |
|---|---|
defined |
引数の変数が定義されている場合 true |
undefined |
引数の変数が定義されていない場合 true |
odd |
指定された変数が奇数の場合 true |
even |
指定された変数が偶数の場合 true |
string |
指定された変数が文字列の場合 true |
number |
指定された変数が数値の場合 true |
divisibleby |
指定された式が指定された引数で割り切れる場合は true |
object |
指定された変数がオブジェクトの場合 true |
starting_with |
指定された変数が文字列で、指定された値で始まる場合 true |
ending_with |
指定された変数が文字列で、指定された値で終わる場合 true |
containing |
指定された変数が指定された値を含む場合 true |
matching |
指定された変数が文字列であり、引数内の正規表現と一致する場合 true |
for
{% for product in products %}
{{loop.index}}. {{product.name}}
{% endfor %}
ループ変数 loop で以下を取得可能。
loop.index: 現在のインデックス(1オリジン)loop.index0: 現在のインデックス(ゼロオリジン)loop.first: 先頭要素かどうかloop.last: 末尾要素かどうか
break と continue も使える。
{% for product in products %}
{% if product.id == target_id %}{% break %}{% endif %}
{{loop.index}}. {{product.name}}
{% endfor %}
{% for product in products %}
{% if loop.index is even %}{% continue %}{% endif %}
{{loop.index}}. {{product.name}}
{% endfor %}
include
他のテンプレートファイルをインクルードできる。
{% include "included.html" %}
以下のようにインクロードすると、存在する最初のものがインクルードされる。
{% include ["custom/header.html", "header.html"] %}
{% include ["special_sidebar.html", "sidebar.html"] ignore missing %}
ignore missing はテンプレートが存在しなかった場合に無視する。
macro
マクロは、呼び出してテキストを返すことができるコンポーネント。
{% macro input(label, type="text") %}
<label>
{{ label }}
<input type="{{type}}" />
</label>
{% endmacro input %}
定義したマクロは、インポートして以下のように使うことができる。
{% import "macros.html" as macros %}
{{ macros::input(label="Name", type="text") }}
extends
テンプレートは継承できる。
以下のような base.html を親テンプレートとして準備し、
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock title %} - My Webpage</title>
{% endblock head %}
</head>
<body>
<div id="content">{% block content %}{% endblock content %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock footer %}
</div>
</body>
</html>
extends にて継承する。
{% extends "base.html" %}
{% block title %}Index{% endblock title %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock head %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock content %}
親テンプレートで定義したブロックの内容を、子テンプレート側でオーバーライドできる。
子テンプレートのブロック内で、{{ super() }} として親テンプレートのブロックを取り込むことができる。
row ブロック
デリミタをそのまま出力するには row ブロック を使う。
{% raw %}
Hello {{ name }}
{% endraw %}
Hello {{ name }} が出力される。
{{ '{{' }} のようにエスケープすることもできる。
ビルトイン関数
以下のビルトイン関数が提供されている。
| 関数 | 説明 |
|---|---|
range |
与えられた引数を使って整数の配列生成 |
now |
ローカルの日時を取得 |
throw |
エラーをスローする |
get_random |
ランダムな整数を取得 |
get_env |
指定された名前の環境変数の値を取得 |