テンプレートで変数の出力について詳しく解説

こんにちはnasustです。

Hugoのテンプレートで変数を出力する{{ $variable }}について詳しく解説します。

HTMLの出力

一番使用されるHTMLの変数出力です。 変数の内容は、HTMLエスケープされます。

{{ $variable := "abc&def" }}
{{ $variable }}
<!-- 結果: abc&amp;def -->
html

HTMLのエスケープされたく無い場合

{{ $variable := "abc&def" }}
{{ $variable | safeHTML }}
<!-- 結果: abc&def -->
html

HTMLタグの属性

HTMLタグの属性に変数を出力する場合は同じ様に記述します。 属性用にエスケープしてくれます。

{{ $variable := "https://nasust.com" }}
<a href="{{ $variable }}">alert link</a>
<!-- 結果: <a href="https://nasust.com">alert link</a> -->
html

属性の値がセキュリティの問題になりそうな場合

HTMLの変数出力と同じ様にしてもエラーになります。

{{ $variable := "javascript:alert('Hello');" }}
<a href="{{ $variable }}">alert link</a>
<!-- 結果: <a href="#ZgotmplZ">alert link</a> -->
html

これはHugoを実装しているGo言語のtemplateの機能で、問題になる箇所は#ZgotmplZと出力されます。 以下の文章はGoのドキュメントの引用です。

"ZgotmplZ" is a special value that indicates that unsafe content reached a
CSS or URL context at runtime. The output of the example will be
  <img src="#ZgotmplZ">
If the data comes from a trusted source, use content types to exempt it
from filtering: URL(javascript:...)
template - The Go Programming Language

これを解決するにはsafeHTMLAttrを使用します。

{{ $variable := "javascript:alert('Hello');" }}
<a {{ printf "href=%q" $variable | safeHTMLAttr }}>alert link</a>
<!-- 結果: <a href="javascript:alert('Hello');">alert link</a> -->
html

JavaScript / JSON

HTML内のJavaScriptやJSONに変数を出力する場合は同じ様に記述します。 JavaScriptやJSON用にエスケープしてくれます。

{{ $variable := "abc&def" }}
<script>
    const var = {{ $variable }}
</script>
/* 結果: 
<script>
    const value = "abc\u0026def"
</script>
*/
js

変数名に出力したい場合は、safeJSを使用します。

{{ $variable := "Abcdef" }}
<script>
    const value{{ $variable | safeJS }} = "hoge"
</script>
/*  結果: 
<script>
    const valueAbcdef = "hoge"
</script>
*/
js

まとめ

書く箇所によって、変数の出力のエスケープが変化します。 Hugoのドキュメントで明記されていないので注意が必要です。

prevnext