• 作成:

YesodのShakespearean TemplatesのHamletで埋め込み形式を使うのはやめてwfsHamletSettings = (wfsHamletSettings def){hamletNewlines = NoNewlines}しましょう

Yesodの Shakespearean Templates :: Yesod Web Framework Book- Version 1.4 はのHamletはインデントで閉じタグを表現します.

<body>
    <p>Some paragraph.
    <ul>
        <li>Item 1
        <li>Item 2

のように書くわけです.

しかしHamletにはタグを埋め込みで書いて閉じタグを明示的に書く方式も提供されています.

<p>Paragraph <i>italic</i> end.のような感じですね.

インデントで括られていない箇所はプレインテキストとして処理されて, タグやクラスの展開などは行われません.

この形式は一見よくわからない挙動をして, 例えば<img>の後ろに埋め込みで書くと本来閉じタグを書いてはいけない<img>の閉じタグが生じたりします. 本来<img>の中にテキストがあることはありえないので, ありえないことを書くとありえない結果が起きるのは当然なのですが.

これを避けることは簡単で, 単に埋め込み形式を使わないことで避けることができます. 実際Yesodのbookにも

You should almost always start Hamlet tags on their own line instead of embedding start/end tags after an existing tag. The only exception to this is the occasional <i> or <b> tag inside a large block of text.

ほとんどの場合, 常に埋め込み形式を使う代わりに, 1つの行でHamletのタグを使用することをオススメします. 唯一の例外は, 大量の<i><b>がテキストブロックに存在するときです.

と書かれています.

埋め込み形式を使うのをやめましょう.

ところが, 1つ日本語(正確には中国語などもでしょうが…)特有の問題があります. 日本語では単語と単語の間にスペースを入れませんが, HTMLコード上の改行はスペースとして描画されてしまいます. Hamletに埋め込み形式でない独自の行を入れると, HTMLコード上でも改行が入力されます.

というわけでそれを嫌った人が大量に埋め込み形式でマークアップを書いていました.

これの対策はHTMLに改行が出力されなくすることです. ファイル別なら!newline neverが効きますが, 日本語全てのファイルをこうしたいので, フレームワーク全体の設定を弄ったほうが良いでしょう.

私はsrc/Settings.hsに以下のように書きました.

import           Text.Hamlet
import           Yesod.Default.Util

widgetFileSettings :: WidgetFileSettings
widgetFileSettings = def
    { wfsHamletSettings = (wfsHamletSettings def){hamletNewlines = NoNewlines}
    }

これを書いて, Hamletの埋め込み形式を消滅させましょう.