CLOVER🍀

That was when it all began.

Mustache.javaのDefaultMustacheFactoryで、テンプレートのデフォルトデリミタをコンパイル時に変更する

最近、Mustache.javaを使っていて気付きまして。

Mustache.javaでは、テンプレートのデリミタの切り替えには、通常テンプレート内に変更前後のデリミタを記述することで実現します。

Mustache.javaのテンプレートのデリミタを切り替える - CLOVER

そして、以下のようなコードを書いてテンプレートをコンパイルしてから実行するわけですが

        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("磯野 カツオ");

この時に使うクラスの型を、MustacheFactoryではなくDefaultMustacheFactoryとして扱うことで、コンパイル時に合わせて変更することができるようです。

            DefaultMustacheFactory mf = new DefaultMustacheFactory();
            Mustache mustache = mf.compile(reader, "template", "{%", "%}");

このように、Readerとテンプレート名、変更後のデリミタを渡すことで、デリミタを変更してからテンプレートをコンパイルすることができます。

テンプレート例。
src/test/resources/template.mustache

デリミタ変更後テンプレート

{% name %}
{%! コメント %}
{%& nonEscape %}

デフォルトのデリミタ(「{{」と「}}」)は、テンプレート中には記載していません。

テストコード。
src/test/java/org/littlewings/mustache/MustacheTest.java

package org.littlewings.mustache;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class MustacheTest {
    @Test
    public void testDefaultMustacheFactoryUsingDelimiter() throws IOException {
        try (InputStreamReader isr =
                     new InputStreamReader(
                             Thread
                                     .currentThread()
                                     .getContextClassLoader()
                                     .getResourceAsStream("template.mustache"), StandardCharsets.UTF_8);
             BufferedReader reader = new BufferedReader(isr)) {
            Map<String, Object> scope = new HashMap<>();
            scope.put("name", "磯野 カツオ");
            scope.put("nonEscape", "<p>HTML</p>");

            DefaultMustacheFactory mf = new DefaultMustacheFactory();
            Mustache mustache = mf.compile(reader, "template", "{%", "%}");

            StringWriter writer = new StringWriter();
            mustache.execute(writer, scope);

            String result = writer.toString();

            assertThat(result)
                    .contains("デリミタ変更後テンプレート")
                    .contains("磯野 カツオ")
                    .contains("<p>HTML</p>\n")
                    .doesNotContain("{%! コメント %}");
        }
    }
}

特にテンプレート中にデリミタの切り替えについて書かずとも、デリミタの変更ができました。

DefaultMustacheFactoryクラスの型で直接扱うことが難点ですが、まあ豆知識的に覚えておきましょう。