おもこん

おもこんは「思いつくままにコンピュターの話し」の省略形です

Jekyllを勉強中(9)

長くJekyllのことを書いてきましたが、今回で最後です。

今回は、Jekyllでサイトを作る上で中心となるLiquidのポイントを説明します。 Liquidには簡潔なドキュメントがありますので、参考にしてください。

Liquidの基本

Liquidはhtmlの中に埋め込みます。 ちょうどphp、あるいはRailsのeRubyに似ています。 埋めこむ対象が3つあります(オブジェクト、タグ、フィルター)。 また、Liquidが埋め込まれたHTMLをテンプレートと呼んでいます。

オブジェクト

オブジェクトは、何らかの情報を持っているものです。 オブジェクトは変数で参照されます。 例えば、pageという変数はページの情報を持っているオブジェクトを指しています。 その情報はドット記法で参照します。

  • page.title ページのタイトル
  • page.description ページのディスクリプション

オブジェクト「page」につけたドットの後の部分をプロパティといいます。 titleやdescriptionはpageオブジェクトのプロパティです。 ページのフロントマターに記述されたものはプロパティになり、ドット記法で参照することができます。

オブジェクトをHTMLの中に表示するには二重波カッコを使います。

{{ page.title }}
タグ

タグは制御構造(分岐、ループ)、テンプレート(コメント、raw)、変数への代入などです。 他の言語のステートメントにあたるものです。 タグを使うときは、それを出力することは原則としてありません。 タグは波カッコとパーセントで囲みます。

{% if page.title == "サンプル" %}
フィルター

フィルターは縦棒|で左の出力を右に流すものです。 ちょうどシェル・スクリプトのパイプのようなものです。 出力結果はHTMLに表示することが多いので二重波カッコを使うことが多いです。

{{ page.title | escape }}

パイプの右側にフィルターの動作を記述します。 escapeはHTMLで特殊な意味を持つ記号をエスケープします。 例えば<を&lt;と変更します。

フィルターは多くの動作をサポートしています。 他の言語、例えばRubyなどの演算子やメソッドの役割をフィルターが担っています。

Jekyllで使う変数

Jekyllで使える変数はJekyllのドキュメントに書かれています。 変数はLiquidで使います。

グローバル変数は次のとおりです。

  • site => サイトの情報。_config.ymlに書かれた情報をもつオブジェクトを参照する(以下「オブジェクトを参照する」を略す)
  • page => ページの情報。ページのフロントマターに書かれた情報
  • layout => レイアウトの情報。そのフロントマターの情報
  • content => ページのコンテンツ
  • paginator => パジネーター。ブログ記事がたくさんある場合など、それをページに分割するときに使う

siteの情報を見るのに「site.url」(サイトのURL)のようにドット記法が使えます。 詳細はJekyllのドキュメントを参照してください。

Liquidのオペレーター

Liquidのオペレータはコントロールフロー(ifなど)やループ(for)の条件に使えます。

  • ==
  • !=
  • >
  • <
  • >=
  • <=
  • or
  • and
  • contains => 左側の文字列が右側の文字列を含んでいればtrue

オペレータが複数ある場合は右から順に評価されます。 また、かっこ(())で評価順を変更することはできません

Liquidには算術演算子加減乗除)がありません。 その代わりにフィルターを使います。

タグ(Liquidの制御構造)

ここでは項目が多いので極めて簡単な説明だけになっています。 詳しい説明はLiquidのドキュメントを見てください。

コントロール・フロー

コントロール・フローは条件分岐です。 他の言語と同様の条件分岐ができます。 コントロール・フローは次の2種類です。

  • if/unless (条件)〜 elsif/else 〜 endif
  • case(条件)when 〜 [when 〜] else 〜 endcase
イテレーション(ループ)

ループをLiquidではイテレーションと呼んでいます。

  • for (条件)〜 else 〜 endfor。 for文の中のelseは条件が成り立たなかった時に出力される
  • break => ループを中止して外にでる
  • continue => ループの現在の回をスキップして次の回にすすむ
  • forループにはlimit/offset/range/reversedのオプションをつけることができる
  • forの中でcycle (項目のリスト)を使うことができる。 項目は1回目はリストの最初の項目、2回めは2番めの項目・・・と出力される
  • tablerow => ループの中でHTMLの表の行を出力する。 cols/limit/offset/rangeのオプションをつけることができる

tablerowはHTMLの表を作れるので便利です。 HTMLテンプレートらしい機能です。

テンプレート
  • comment 〜 endcomment => コメントとして扱われHTML出力されない
  • raw 〜 endraw => Liquidの解釈をせずにそのまま出力される。 例えば二重波カッコをそのまま出力したい場合に使う。
  • liquid => 複数行にわたりLiquidの構文を書くことができる。 いちいち{% %}で囲まずにすむのがありがたい
  • echo => タグの中で用いられ、echoの次の要素を出力する。 フィルターを使える
  • render => 他のテンプレートファイルを読み込む
変数
  • assign => 変数への代入をする
  • capture => 変数への代入をする
  • increment/ decrement => 引数に変数をとり、0/-1からはじめて変数を1ずつ増加/減少させ、その値をHTMLに出力する。

JekyllのLiquidで良く用いられるフィルター

以下では、JekyllのLiquidで良く用いられる書き方を順不同で説明します。

default

パイプの左側からの入力がnil、false、空文字列のいずれかであるときに引数の値を出力し、それ以外は入力をそのまま出力します。

{{ page.title | default: 無題 }}
  • ページタイトルが設定されていれば、その文字列を出力
  • ページタイトルが設定されていなければ「無題」を出力

おそらく最も使われているフィルターです。

relative_url

ベースURLを加えたURLにします。

GitHubを例にとって説明します。 GitHub Pagesのサイトはhttps://ユーザ名.github.io/以下に展開されます。 そのスペースを分割していくつかのサイトを構築する場合、ベースURLを個々のサイトにつけます。 例えば、そのサイトのベース名がjekyll-tutorial-for-beginnersであれば、そのサイトはhttps;//ユーザ名.github.io/jekyll-tutorial-for-beginners/をベースとして展開されることになります。

URLの指定には3通りがあります。 例えばサイトのルートにあるabc.htmlは

  • https;//ユーザ名.github.io/jekyll-tutorial-for-beginners/abc.html これを絶対URLといいます
  • /jekyll-tutorial-for-beginners/abc.html これはいろいろの呼び方をされていますが、「The URL Standard」によると絶対URLの一種で、「path-absolute-URL string」(絶対パスURL文字列)というようです。 ですが、https:のついた絶対URLとは振る舞いが違います。
  • 今かりにhttps;//ユーザ名.github.io/jekyll-tutorial-for-beginners/abc.htmlの画面を開いているとします。 そのとき、現在の画面のURLとabc.htmlのURLは最後の部分の違いだけです。 URLを単に「abc.html」と表現することを相対URLといいます。 現在画面のURLと相対URLを組み合わせると絶対URLを求めることができるので、これもURLの表現として可能です。

このうち2番めが問題になります。 /(ルート)がどこに設定されるのかはサーバによります。 GitHubでは/https;//ユーザ名.github.io/と解釈されます。 ですから、サイトのルートhttps;//ユーザ名.github.io/jekyll-tutorial-for-beginners/GitHubのルートとずれがあるわけです。 この差jekyll-tutorial-for-beginnersをJekyllではBase URLといいます。

relative_urlフィルターは流れてきた文字列の先頭にBase URLを付け加えます。 なお、Base URLは_config.ymlの中で定義します。

_config.yml での定義
baseurl: /jekyll-tutorial-for-beginners

{{ "/assets/image/abc.png" | relative_url }}
これにより、出力は次のようになる
=> /jekyll-tutorial-for-beginners/assets/images/abc.png

このことによって、サイトのルートがGitHubのルートに一致するようになります。 なお、baseurlのデフォルト値は空文字列です。

Base URLを定義するかどうかはサーバーサイトのルートの解釈で決まってきます。 また、URL表現の1,3番すなわちhttpsから始まる絶対URLまたは相対URLを使っている限りはこの問題は起きません。 ですから、複雑さを避けるには相対URLのみを使うのが良いと思います。

ただし、Liquidでpage.urlを参照すると/から始まる絶対パスURLが帰ってくるので、relative_urlが必要になります。

absolute_url

文字列の先頭にsite.urlとsite.base_urlを加えます。 前提として_config.ymlにurlを登録することが必要です。

url: https://(ユーザ名).github.io

文字列の最後にスラッシュはつきません。 デフォルト値はhttps://lofalhost:4000です。

escape

escapeはHTMLで特別な意味を持つ文字をエスケープします。

  • < => &lt;
  • > => &gt;
  • & => &amp;

これ以外にもエスケープ文字はあるので、詳細はインターネットで調べてみてください。 とくに<と>が現れるとHTMLタグと解釈されてしまうので、文字そのものを出力するにはエスケープが必要です。 このときescapeフィルターをかけてやります。

例えばpage.titleにはエスケープしなければならない文字が入っているかもしれません。 page.titleはレイアウトの中で使うことが多いと思います。 その場合レイアウトの使用者は自分自身とは限りません。 あらかじめエスケープすべき文字が入っているかどうかわからないので、escapeは必須です。

strip_html

HTMLタグを取り去りたいときに使います。 markdownifyを使う後に使うことが多いと思います。 marakdownifyの説明は後でします。

{{ f.image_caption | markdownify | strip_html }}

「マークダウンをHTMLに変換してタグを取る」ということは、ベタなテキストを手に入れることになります。

replace

文字列置換です。 1番めの引数を2番めの引数に置換します。

{{ "暑いなあ" | replace: "暑い", "寒い" }}
=> 寒いなあ
split

文字列を引数をデリミタとして分割した配列にします。

{% assign ary = "abc, def, ghi, jkl" | split: ", " %}
{% for s in ary %}
  {{ s }}
{% endfor %}
=>
abc
def
ghi
jkl

結果は4行になっていますが、HTMLなのでブラウザ上の表示はつながってしまいます。 このように、コンマ区切りのデータを配列にするときに良くつかいます。

markdownify

これは、Jekyllが拡張したフィルターです。 マークダウンで記述された文字列をHTMLに変換します。 マークダウンで書かれたデータを処理するケースで使います。

date

タイムスタンプを別の形式の時刻表示に切り換えます。 形式の指定は引数の文字列で与えます。 形式にはstrftimeが用いられます。

{{ "2022-8-21" | date: "%Y 年 %m 月 %e 日" }}
=> 2022 年 08 月 21 日
remove

引数の文字列を削除します。

{{ "<p>abcd</p> | remove: <p> | remove </p> }}
=> abcd

シリーズの最後に

はじめてみたら9回も続くことになった「Jekyllを勉強中」は今回で終わります。 自分自身が勉強をしながらの説明だったので、不十分なところが多々ありましたことをお詫びします。

GitHubチュートリアルをあげました。 このチュートリアルはCaymanをテーマに、Jekyllで作られています。 内容はこのブログとほとんど同じですが、構成を変え、説明をより分かりやすくなるように手直ししました。