11ty と Liquid を雑に話す
動機
ホームページをリニューアルする際に、React エコシステムから脱却して、11ty に変更しました。11ty は Liquid というマークアップ言語を使って記述することができます。
11ty はその他にも複数のマークアップ言語に対応しているのですが、HTML を素で記述しているような書き味で、尚且つ辛い部分だけ楽したいという自分の要求をミニマムに実現可能なのが Liquid でした。
近い将来 11ty, Liquid のことはほぼほぼ忘れてしまうはずなので、何が実装されているのか、とっかかりを理解する上で必要な知識を書き記しておこうと思います。
11ty
eleventy.config.js このファイルが 11ty プロジェクトの設定を担っています。
return {
dir: {
input: "src",
includes: "_includes",
data: "_data",
output: "_site",
},
};
細かい部分は省きますが、どのフォルダをどう扱うかというのを定義しています。
- input
ここに指定した場所がトップレベルディレクトリとして認識されます。
配下のファイルは HTML への変換対象であるテンプレートファイルとして認識されます。
- includes
テンプレートファイルから参照するファイル (partials, extensions, ...) として認識されます。
ここに置いたファイルは単体ではテンプレートファイルとしては認識されません。
また SSG の慣習として _ が prefix についたフォルダはエンジン側からテンプレートとしては認識されなくなるようです。
- data
各種テンプレートから参照可能なグローバルデータとして認識されます。
includes 同様に、ファイル単体ではテンプレートファイルとしては認識されません。
付加情報を記載しているので、includes の項目を先に見てください。
- output
生成された HTML の出力先として認識されます。
また、今回で言う src つまり、トップレベルディレクトリの外にあるファイルで生成物に含めたいようなもの、例えば public, css なども output に指定したフォルダに配置する必要があります。
eleventyConfig.addPassthroughCopy("public");
API を利用することで、そういったフォルダをビルド時に output へ出力することができます。
上記のように指定した場合は _site/public のように配置されます。
Liquid
Shopify が提供するマークアップ言語です。OSS として提供されています。
雰囲気さえ分かれば書けてしまうぐらいには容易です。
これを開くと、Liquid のマークアップ構文で書かれたテンプレートがどのように HTML に変換されるかが分かります。
覚えることは 2 つぐらいで良くて、
{% %}
ロジックは上記のように記述し、
{{ }}
出力したい場合はこのように記述します。もう少し踏み込んでいきます。
_data フォルダに family.json を配置したとします。
{
"people": [
"alice",
"bob",
"carol"
]
}
そして、下記のように記述する。
<ul>
{%- for person in family.people %}
<li>
<a href="{{person | prepend: "https://example.com/"}}">
{{ person | capitalize }}
</a>
</li>
{%- endfor%}
</ul>
変換後の HTML はこうなる。
<ul>
<li>
<a href="https://example.com/alice">
Alice
</a>
</li>
<li>
<a href="https://example.com/bob">
Bob
</a>
</li>
<li>
<a href="https://example.com/carol">
Carol
</a>
</li>
</ul>
また、prepend や capitalize などをフィルターと言います。
CLI を叩いている時のことを思い出してください。
cat foo.txt | grep bar
これは出力結果を grep に流して bar というテキストの存在する行を出力しますが、Liquid も同様です。
person 変数に格納されたテキストの出力結果を prepend や capitalize に流しているというわけです。
このように、たくさんの built-in filters が存在するので、ロジックを書く前に一度ここを見るのが良いと思います。
また、11ty では独自に filters を記述できるようになっています。
export default function (eleventyConfig) {
// 省略
eleventyConfig.addFilter("formatDate", (dateStr) => {
const date = new Date(dateStr);
return date.toLocaleDateString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
});
});
// 省略
}
例えば、built-in の date filters が使いにくかったので、ブログ記事の日付用に自前で書いたやつです。