Hugo のコンテンツリスト
サイトのホームページ、セクションページ、タクソノミー リスト、またはタクソノミー用語リストのレンダリングに関して、Hugo ではリストに特定の意味と使用法があります。
リストページ テンプレートとは
リストページ テンプレートは、複数のコンテンツを 1 つの HTML ページで表示するために使用するテンプレートです。ただし、ホームページは例外で、やはりリストではありますが、専用の テンプレート を持ちます。
Hugo では、リスト という用語を本当の意味で使っています。つまり、特にアルファベット順または数字順で、資料を順番に並べます。 Hugo では、出力される HTML ページの中で、伝統的にリスト化されたコンテンツに以下のリストテンプレートを使用します。
テンプレートの検索順序については、「テンプレートの検索順序」 を参照してください。
リストページのアイデアは、Web の階層的メンタルモデル に由来し、以下のように視覚的に示すのが最も効果的です。
リストのデフォルト
デフォルトのテンプレート
セクションリストとタクソノーミリスト (タクソノミー用語リスト
ではないことに注意してください) はどちらもテンプレートに関しては リスト であるため、どちらも _default/list.html
または themes/<THEME>/layouts/_default/list.html
という同じ終了デフォルトが検索順序に設定されています。さらに、セクションリスト
と タクソノミーリスト
は、どちらも _default
に独自のデフォルトのリストテンプレートを持っています。
完全なリファレンスについては、テンプレートの検索順序 を参照してください。
リストページにコンテンツとフロントマターを追加する
v0.18 以降、Hugo にある全てのものは Page
です
。 つまり、リストページとホームページは、ページのメタデータ (つまりフロントマター) とコンテンツを含む関連コンテンツファイル (つまり _index.md
) を持つことができます。
この新しいモデルでは、.Params
を介してリスト固有のフロントマターを含めることができ、また、リストテンプレート (たとえば、layouts/_default/list.html
) がすべての ページ変数
にアクセスできることも意味します。
プロジェクト ディレクトリの例
以下は、典型的な Hugo のプロジェクト ディレクトリのコンテンツの例です。
.
...
├── content
| ├── posts
| | ├── _index.md
| | ├── post-01.md
| | └── post-02.md
| └── quote
| | ├── quote-01.md
| | └── quote-02.md
...
上記の例で、content/posts/_index.md
に以下のように記述しているとします。
---
title: 私の Go の旅
date: 2017-03-23
publishdate: 2017-03-24
---
2017 年 3 月に Go の学習を開始することにしました。
この新しいブログを通して、私の旅にお付き合いください。
上記により、リストテンプレートでこの _index.md
のコンテンツにアクセスできます。
{{ define "main" }}
<main>
<article>
<header>
<h1>{{ .Title }}</h1>
</header>
<!-- "{{.Content}}" は対応する _index.md の Marakdown コンテンツから取得します -->
{{ .Content }}
</article>
<ul>
<!-- content/posts/*.md の範囲指定 -->
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Date.Format "2006-01-02" }} | {{ .Title }}</a>
</li>
{{ end }}
</ul>
</main>
{{ end }}
上記により、以下のような HTML が出力されます。
<!--baseof コードの先頭-->
<main>
<article>
<header>
<h1>私の Go の旅</h1>
</header>
<p>2017 年 3 月に Go の学習を開始することにしました。</p>
<p>この新しいブログを通して、私の旅にお付き合いください。</p>
</article>
<ul>
<li><a href="/posts/post-01/">投稿 1</a></li>
<li><a href="/posts/post-02/">投稿 2</a></li>
</ul>
</main>
<!-- baseof コードの最後 -->
index.md
がないページを一覧表示する
すべてのリストページ (つまり、セクション、タクソノミー、タクソノミー用語など) またはホームページに対して _index.md
ファイルを作成する必要は ありません。 リストテンプレートをレンダリングするときに Hugo がそれぞれのコンテンツセクション内で _index.md
を見つけられない場合、ページは作成されますが、{{ .Content }}
はなく、.Title
などのデフォルト値のみが作成されます。
この同じ layouts/_default/list.html
テンプレートを使用して、上記の quotes
セクションに適用すると、以下の出力がレンダリングされます。 quotes
には、プルする _index.md
ファイルがないことに注意してください。
<!--baseof-->
<main>
<article>
<header>
<!-- Hugo は、.Title がセクションの名前であると仮定します。それは、"title:" フィールドをプルする _index.md コンテンツファイルが存在しないためです -->
<h1>Quotes</h1>
</header>
</article>
<ul>
<li><a href="https://example.com/quote/quotes-01/">Quote 1</a></li>
<li><a href="https://example.com/quote/quotes-02/">Quote 2</a></li>
</ul>
</main>
<!--baseof-->
リストテンプレートの例
セクション テンプレート
このリストテンプレートは、もともと spf13.com
で使われていたテンプレートを少し修正したものです。 ベーステンプレート
を使うのではなく、レンダリングされたページのクロムのために パーシャル
を使っています。以下の例では、コンテンツビュー テンプレート
の li.html
または summary.html
を使っています。
{{ partial "header.html" . }}
{{ partial "subheader.html" . }}
<main>
<div>
<h1>{{ .Title }}</h1>
<ul>
<!-- content/posts/*.md ごとに li.html コンテンツビューをレンダリングします -->
{{ range .Pages }}
{{ .Render "li" }}
{{ end }}
</ul>
</div>
</main>
{{ partial "footer.html" . }}
タクソノミー テンプレート
{{ define "main" }}
<main>
<div>
<h1>{{ .Title }}</h1>
<!-- 特定のタクソノミー用語に関連する各コンテンツファイルを範囲指定し、summary.html コンテンツビューをレンダリングします -->
{{ range .Pages }}
{{ .Render "summary" }}
{{ end }}
</div>
</main>
{{ end }}
コンテンツを並べる
Hugo のリストは、フロントマター で指定したメタデータに基づいてコンテンツをレンダリングします。まともなデフォルトに加えて、Hugo にはリストテンプレート内のコンテンツを素早く並べるための複数のメソッドが同梱されています。
デフォルト: Weight > Date > LinkTitle > FilePath
<ul>
{{ range .Pages }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
重み (Weight) 順で並べる
重み (weight) が小さいほど優先度が高くなります。 そのため、重みの低いコンテンツが最初に表示されます。
<ul>
{{ range .Pages.ByWeight }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
日付 (Date) 順で並べる
<ul>
<!-- フロントマターの "date" フィールドにしたがってコンテンツを並べます -->
{{ range .Pages.ByDate }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
公開日 (Publish Date) 順で並べる
<ul>
<!-- フロントマターの "date" (日付) フィールドにしたがってコンテンツを並べます -->
{{ range .Pages.ByPublishDate }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
有効期限 (Expiration Date) 順で並べる
<ul>
{{ range .Pages.ByExpiryDate }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
最終更新日 (Last Modified Date) 順で並べる
<ul>
<!-- フロントマターの "lastmod" フィールドに従ってコンテンツを並べます -->
{{ range .Pages.ByLastmod }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
長さ (Length) 順で並べる
<ul>
<!-- コンテンツの長さに従ってコンテンツを昇順に並べます (つまり、最も短いコンテンツが最初にリストされます) -->
{{ range .Pages.ByLength }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
タイトル (Title) 順で並べる
<ul>
<!-- フロントマターに設定された "title" フィールドに従って、昇順でコンテンツの範囲を指定します -->
{{ range .Pages.ByTitle }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
リンクタイトル (Link Title) 順で並べる
<ul>
<!-- フロントマターの "linktitle" フィールドに従って、コンテンツを昇順に並べます。 "linktitle" フィールドが設定されていない場合、範囲は "title" フィールドのみを持つコンテンツから始まり、その値を .LinkTitle に使用します -->
{{ range .Pages.ByLinkTitle }}
<li>
<h1><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
ページパラメータ (Page Parameter) 順で並べる
指定されたフロントマター パラメータに基づいて並べます。 指定されたフロントマター フィールドを持たないコンテンツは、サイトの .Site.Params
デフォルトを使用します。 一部のエントリでパラメータがまったく見つからない場合、それらのエントリは順序付けの最後に一緒に表示されます。
<!-- フロントマターに設定された "rating" フィールドにしたがって、コンテンツの範囲を設定します -->
{{ range (.Pages.ByParam "rating") }}
<!-- ... -->
{{ end }}
対象となるフロントマター フィールドが他のフィールドの下にネストされている場合、ドット記法を使ってフィールドにアクセスできます。
{{ range (.Pages.ByParam "author.last_name") }}
<!-- ... -->
{{ end }}
逆順
逆順は、上記のいずれのメソッドにも適用できます。 以下では、例として ByDate
を使用します。
<ul>
{{ range .Pages.ByDate.Reverse }}
<li>
<h1><a href="{{ .Permalink }}">{{ .Title }}</a></h1>
<time>{{ .Date.Format "Mon, Jan 2, 2006" }}</time>
</li>
{{ end }}
</ul>
グループコンテンツ
Hugo には、セクション、タイプ、日付などでページをグループ化する関数があります。
ページフィールド (Page Field) による
<!-- コンテンツセクションに従ってコンテンツをグループ化します。このインスタンスの ".Key" は、セクションのタイトルになります。 -->
{{ range .Pages.GroupBy "Section" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
上記の例では、代わりに _index.md
ファイルに追加した title
フィールドを {{.Title}}
で指定したい場合があります。 以下のように、.GetPage
関数
を使用して、この値にアクセスできます。
<!-- コンテンツ セクションに従ってコンテンツをグループ化します。 -->
{{ range .Pages.GroupBy "Section" }}
<!-- セクションの _index.md があるかどうか確認し、あればフロントマターの "title" から取得します。 -->
{{ with $.Site.GetPage "section" .Key }}
<h3>{{ .Title }}</h3>
{{ else }}
<!-- _index.md がない場合、".Key が デフォルトでセクションのタイトルとなり、タイトルケーシング (タイトルの大文字表記) にフィルタリングされます -->
<h3>{{ .Key | title }}</h3>
{{ end }}
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
日付 (Date) による
<!-- フロントマターの "date" フィールドに従って、月ごとにコンテンツをグループ化します -->
{{ range .Pages.GroupByDate "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
GroupByDate
は time.Format
と同じ時間レイアウトを受け入れ、結果の .Key
は現在の言語にローカライズされます。
公開日 (Publish Date) による
<!-- フロントマターの "publishDate" フィールドに従って、コンテンツを月別にグループ化します -->
{{ range .Pages.GroupByPublishDate "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .PublishDate.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
GroupByDate
は time.Format
と同じ時間レイアウトを受け入れ、結果の .Key
は現在の言語にローカライズされます。
有効期限 (Expiry Date) による
<!-- フロントマターの "expiryDate "フィールドに従って、コンテンツを月別にグループ化します -->
{{ range .Pages.GroupByExpiryDate "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .ExpiryDate.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
GroupByDate
は time.Format
と同じ時間レイアウトを受け入れ、結果の .Key
は現在の言語にローカライズされます。
最終更新日 (Last modified date) による
<!-- フロントマターの "lastMod" フィールドに従って、コンテンツを月別にグループ化します -->
{{ range .Pages.GroupByLastmod "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Lastmod.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
GroupByDate
は time.Format
と同じ時間レイアウトを受け入れ、結果の .Key
は現在の言語にローカライズされます。
ページパラメータによる
<!-- フロントマターの "param_key" フィールドに従って、コンテンツをグループ化します -->
{{ range .Pages.GroupByParam "param_key" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
日付形式のページパラメータによる
以下のテンプレートでは date
によるグループ化をさらに一歩進めて、Go のレイアウト文字列を使用しています。Go のレイアウト文字列を使って、 Hugo で日付をフォーマットする方法については、Format
関数
を参照してください。
<!-- フロントマターの "param_key" フィールドに従って、コンテンツを月別にグループ化します -->
{{ range .Pages.GroupByParamDate "param_key" "2006-01" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
キー順を逆にする
グループの並び順は、キーが英数字順 (A-Z、1-100)、日付は逆の年代順 (つまり、新しいものが最初) になっています。
これらは論理的なデフォルトですが、常に望ましい順序とは限りません。Hugo のグループのデフォルトの並び順を変更するには、2 つの異なる構文があります。
1. リバースメソッドの追加
{{ range (.Pages.GroupBy "Section").Reverse }}
{{ range (.Pages.GroupByDate "2006-01").Reverse }}
2. 代替方向の提供
{{ range .Pages.GroupByDate "2006-01" "asc" }}
{{ range .Pages.GroupBy "Section" "desc" }}
グループ内の順序
グループ化は {{ .Key }}
とページのスライスを返すので、上記のすべての順序付け方法が利用可能です。
ここでは、以下のような順序付けの例を示します。
- コンテンツは、フロントマターの
date
フィールドに従って、月ごとにグループ化されます。 - グループは昇順で表示されます (つまり、最も古いグループが最初になります)。
- 各グループ内のページは、
title
に従ってアルファベット順に並んでいます。
{{ range .Pages.GroupByDate "2006-01" "asc" }}
<h3>{{ .Key }}</h3>
<ul>
{{ range .Pages.ByTitle }}
<li>
<a href="{{ .Permalink }}">{{ .Title }}</a>
<div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div>
</li>
{{ end }}
</ul>
{{ end }}
リストのフィルタリングと制限
時には、利用可能なコンテンツのサブセットのみをリストしたい場合があります。よくあるのは、メインセクション からの投稿のみをブログのホームページに表示することです。
詳細については、where
関数
および first
関数
のドキュメントを参照してください。