§テンプレートエンジンに対するカスタムフォーマットのサポートの追加
組み込みのテンプレートエンジンは一般的なテンプレートフォーマット (HTML、XML、等) をサポートしていますが、必要であれば独自のフォーマットのサポートを簡単に追加する事ができます。このページではカスタムフォーマットをサポートする為に必要なステップをまとめています。
§テンプレートプロセスの概要
テンプレートエンジンはテンプレートの静的および動的な部品を結合する事でビルドします。例えば以下のテンプレートを考えてみて下さい:
foo @bar baz
上記のテンプレートは一つの動的な部品 (bar
) およびその周囲の二つの静的な部品 (foo
および baz
) から構成されています。テンプレートエンジンはこれらの部品を結合する事で結果をビルドします。実際には、クロスサイトスクリプティング攻撃を防ぐ為、他の部品と結合される前に bar
の値をエスケープすることができます。このエスケーププロセスはフォーマット毎に特有となります: 例えば、 HTML の場合は「<」を「<」に変換したくなるでしょう。
テンプレートエンジンはどのようにしてテンプレートファイルに対応するフォーマットを知る事が出来るのでしょうか? 拡張子を見ています: 例えば、 .scala.html
で終わる場合は、HTML フォーマットとファイルを紐付けます。
まとめると、独自のテンプレートフォーマットをサポートするには、以下のステップを行う必要があります:
- フォーマットに対するテキスト統合のプロセスを実装する ;
- ファイル拡張子をフォーマットと関連づける.
§フォーマットを実装する
play.templates.Format<A>
インタフェースを実装しましょう。このインタフェースは A raw(String text)
および A escape(String text)
メソッドがあり、それぞれ静的および動的なテンプレートの部品を統合する為に使われます。
フォーマットの A
型パラメータは、例えば HTML のテンプレートには Html
といったように、テンプレートのレンダリング結果の型を定義します。この型は play.templates.Appendable<A>
のサブタイプである必要があり、各部品をどうやって結合するかを定義します。
利便性のため、 Play は play.api.templates.BufferedContent<A>
抽象クラスを提供します。このクラスは結果をビルドする為に play.templates.Appendable<A>
を StringBuilder
を使って実装していて、また HTTP のレスポンスボディにシリアライズする方法を Play に知らせるために play.mvc.Content
インタフェースを実装しています。
つまり、二つのクラスを書く必要があります: 一つは (play.templates.Appendable<A>
を実装する事で) 結果を定義したクラスで、もう一つは (play.templates.Format<A>
を実装する事で) テキストの統合プロセスを定義したクラスです。例えば、 HTML フォーマットを定義するには以下のようにします:
public class Html extends BufferedContent<Html> {
public Html(StringBuilder buffer) {
super(buffer);
}
String contentType() {
return "text/html";
}
}
public class HtmlFormat implements Format<Html> {
Html raw(String text: String) { … }
Html escape(String text) { … }
public static final HtmlFormat instance = new HtmlFormat(); // ビルドプロセスにおいてフォーマットに対する static な参照が必要となります (次のセクション参照)
}
§ファイル拡張子をフォーマットと関連づける
テンプレートは、ビルドプロセスでアプリケーションのソース全体をコンパイルする直前に .scala
ファイルにコンパイルされます。 sbt.PlayKeys.templatesTypes
キーは Map[String, String]
型の sbt 設定で、ファイル拡張子とテンプレートフォーマットのマッピングを定義しています。例えば、もし独自の HTML 形式の実装を使いたい場合、以下のようにビルドファイルに書く事で .scala.html
を独自の my.HtmlFormat
フォーマットに関連づける必要があります:
templatesTypes += ("html" -> "my.HtmlFormat.instance")
矢印の右側には play.templates.Format<?>
型の静的な値への完全修飾名が含まれている事に注意して下さい。