Rust のテンプレートエンジン Tera - テンプレート構文チートシート


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 という変数を小文字に変換し、doctorDr. に変換する。

{{ 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 TeraI\'m using Tera
slugify -Hello world!hello-world
title foo barFoo 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: 末尾要素かどうか

breakcontinue も使える。

{% 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 %}
        &copy; 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 指定された名前の環境変数の値を取得