FreeMarker でデフォルト HTML エスケープ
デフォルト HTML エスケープシリーズ。今回は FreeMarker。
FreeMarker では <#escape> タグで囲った部分を自動でエスケープすることができます。こんな風にファイルの最初と最後にセットしてやればそのファイルではデフォルトでエスケープされます。
<#escape x as x?html> <!DOCTYPE html> <html> ... ${foo.bar} ... </html> </#escape>
いちいち <#escape> で囲むのは面倒ですので TemplateLoader でテンプレートをロードするときに自動でつけるようにします。SpringMVC と組み合わせる場合は以下のようになります。(完全なソースコードはこちら)
FreeMarkerConfigurer c = new FreeMarkerConfigurer(); c.setPreTemplateLoaders( new SpringTemplateLoader( new ServletContextResourceLoader(servletContext), "/WEB-INF/freemarker/") { @Override public Reader getReader(Object templateSource, String encoding) throws IOException { String s = CharStreams.toString( super.getReader(templateSource, encoding)); return new StringReader( "<#escape x as x?html>" + s + "#escape>"); } }); return c;
ちょっと無理矢理な気もしますがこれで <#escape> を付け忘れてしまう心配はありません。
JSP, Velocity の時と同じモデルを使って動作を検証します。
WikiPage wikiPage = new WikiPage( "<strong>Tokyo</strong>", new WikiText("<strong>Tokyo</strong> is the capital of Japan."));
エスケープできていますね。続いて WikiPage の出力。
WikiPage#toString() の結果をエスケープできています。
今度は明示的にエスケープを回避してみます。<#escape> 内で <#noescape> を使うとエスケープなしで出力できます。
JSP や Velocity のようにクラス定義によりエスケープをスキップする方法はわかりませんでした。
<#escape> を自動的にファイルの前後に挿入することによりデフォルト HTML エスケープを実現できました。クラス定義でエスケープを回避できればさらによかったのですがエスケープ漏れはないので優秀ですね。
検証に使ったソースコードは github にあります
こちらのサイトで動作を確認できます (非常に遅いです)