ちょっとMustache.javaで、テンプレートのデリミタを変更できないか見ていまして。
Mustache.java
https://github.com/spullara/mustache.java
通常、Mustacheでは以下のように「{{」と「}}」をデリミタにしてテンプレートを書きますが、
{{name}}
これを変更したい、と。
Mustache.javaではありませんが、調べたらJavaScript版のMustacheについての内容が出てきたので、軽く動作確認してみます。
javascript - How to change the default delimiter of mustache.js? - Stack Overflow
準備
まずは、Maven依存関係。
<dependency> <groupId>com.github.spullara.mustache.java</groupId> <artifactId>compiler</artifactId> <version>0.9.1</version> </dependency>
現時点の最新版は、0.9.1ですと。
その他、テストコード用にJUnitとAssertJを追加。
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.1.0</version> <scope>test</scope> </dependency>
あとは、淡々とコードを書いていきます。
動作確認
まずは、普通に使ってみるところから。
以降では、以下のimport文が定義済みとします。
import java.io.StringReader; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat;
テンプレートをStringで定義して、普通に使ってみたバージョン。
@Test public void testSimpleUsage() { String template = "{{name}}"; Map<String, Object> scope = new HashMap<>(); scope.put("name", "磯野 カツオ"); MustacheFactory mf = new DefaultMustacheFactory(); Mustache mustache = mf.compile(new StringReader(template), "example"); StringWriter writer = new StringWriter(); mustache.execute(writer, scope); writer.flush(); assertThat(writer.toString()) .isEqualTo("磯野 カツオ"); }
これはまあ、いいでしょう。
続いて、デリミタを変更したバージョン。
@Test public void testChangeDelimiter() { String template = "{{=<% %>=}}<%name%><%={{ }}=%>"; Map<String, Object> scope = new HashMap<>(); scope.put("name", "磯野 カツオ"); MustacheFactory mf = new DefaultMustacheFactory(); Mustache mustache = mf.compile(new StringReader(template), "example"); StringWriter writer = new StringWriter(); mustache.execute(writer, scope); writer.flush(); assertThat(writer.toString()) .isEqualTo("磯野 カツオ"); }
というわけで、どうやら「これまでのデリミタ(開始)」「新しいデリミタ(開始)」「新しいデリミタ(終了)」「これまでのデリミタ(終了)」の順番で続ければよいみたいです。
また、もう1度書くことで再度デリミタを変更できるようです。
この例の場合は、「{{」と「}}」から「<%」と「%>」に変更し、最後に「{{」と「}}」に戻しています。
{{=<% %>=}}<%name%><%={{ }}=%>
なるほど。
最後は、テンプレートをファイルで用意。
src/test/resources/template.mustache
{{=<% %>=}} <%name%> <%! ここは、コメントです %> <%={{ }}=%> {{name}} {{! ここは、コメントです }}
テストコード。
@Test public void testChangeDelimiterUsingTemplateFile() { Map<String, Object> scope = new HashMap<>(); scope.put("name", "磯野 カツオ"); MustacheFactory mf = new DefaultMustacheFactory(); Mustache mustache = mf.compile("template.mustache"); StringWriter writer = new StringWriter(); mustache.execute(writer, scope); writer.flush(); assertThat(writer.toString()) .isEqualTo("\n" + "磯野 カツオ\n" + "\n" + "\n" + "磯野 カツオ\n" + "\n" + "\n"); }
コメントに使うデリミタも含めて、変更可能ですね、と。
HTMLエスケープを解除するには?
Mustacheではテンプレートに適用する値は、デフォルトでHTMLエスケープされます。
HTMLエスケープを解除するには、通常のデリミタを使用しているとこんな感じでしたが、
{{{message}}} {{& message}}
デリミタを変更するとどうなるんだろう?ということで。
テストコード。
@Test public void testHtmlEscaped() { Map<String, Object> scope = new HashMap<>(); scope.put("value", "<HTML>"); MustacheFactory mf = new DefaultMustacheFactory(); Mustache mustache = mf.compile("template_html.mustache"); StringWriter writer = new StringWriter(); mustache.execute(writer, scope); writer.flush(); assertThat(writer.toString()) .isEqualTo("\n" + "<HTML>\n" + "<HTML>\n" + "<HTML>\n"); }
で、これをパスするためのテンプレートは、以下となります。もちろん、デリミタの変更を含みます。
src/test/resources/template_html.mustache
{{=<% %>=}} <%value%> <%{value}%> <%& value%>
真ん中のパターンだと、「{」と「}」で囲まないといけないんですね。
※最初のパターンは、HTMLエスケープされる通常のパターンです