山カッコ (<>),アンパサンド (&),クォーテーション ("),…HTMLの世界にはエスケープすべき文字があり,Hugoは何も指定がなければ自動的にこれらの文字をエスケープして出力する.エスケープしないことを明示するためにsafeHTML
やsafeURL
といったフィルタが用意されているものの,実際にジェネレータがエスケープするかどうかは文脈から判断する仕様であり,Template埋め込み位置によって記述を変える必要があるので,わかりづらい.そこで,Hugoのエスケープ処理について調べてみた.
safeHTMLは何をしているのか
Go言語は全くわからないが,ここら辺がsafeHTMLの本体なんじゃないかと予想する.この関数を見た限りでは,safeHOGEは入力文字列をHOGEの文法としてパース処理しているようにみえる.ということは,{{ .Params.Hoge | safeURL | safeHTML }}
という記述は.params.Hoge
をURL文法であるという宣言で囲み,それをさらにHTML文法であるという宣言で囲んでいることになる.
具体的にどうすべきか
<meta property="og:title" content="{{ .Title }}">
<!-- or -->
<meta property="og:title" content="{{ .Title | .safeHTML }}">
この場合は前者の方が正しく山カッコ (<>)やアンパサンド (&)を含む文字列を処理できる.
<meta property="og:description" content="{{ .Summary }}">
<!-- or -->
<meta property="og:description" content="{{ .Summary | .safeHTML }}">
だが,こちらの場合は後者でないと山カッコ (<>)やアンパサンド (&)がエスケープされてしまう.
と思っていたが,metaタグのcontent内は&
実体参照で書くらしいので,前者の方が正しく処理できることになる.
まとめると,
- 基本的にはフィルタなしでOK
- URLをパラメータに放り込んで使うなら
safeURL
- HTMLタグを含む文字列をHTMLとして解釈させるなら
safeHTML
- ただしMarkdownファイルで山カッコ (<>)やアンパサンド (&)は
\
でエスケープ
といったところだろうか.
Blackfridayの功罪
HugoのMarkdownパーサであるBlackfridayも,意図しない文字を出力する原因になりうる.
Blackfridayはデフォルトで引用符や二重引用符を左右対応づけた文字に変換するのだが,このExtensionをdisableにする方法がわからなかった1.文章中に'
や"
を表記する必要があるかと言われると微妙だが,わざわざインラインコードにする手間が発生するのも微妙である.
また,3連ドット(...
)も三点リーダ(…)に変えてしまう.深く考えなくとも綺麗に整形してくれるという利点と,入力文字が意図せずに変換されてしまうという欠点がBlackfridayには同居しているように思える.