ページ変数の .NextInSection
や .PrevInSection
を使用すると、同じセクション内の次のページ、前のページを参照することができます。
同じ階層にある「前のページ」「次のページ」へのリンクを表示する
下記のテンプレートコードは、前のページへのリンクと、次のページへのリンクを表示するシンプルな例です。
{{ with .PrevInSection }}
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
{{ with .NextInSection }}
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ end }}
Page 変数の .PrevInSection
や .NextInSection
には、同じセクション内にある通常ページ (regular page) の内、前のエントリと次のエントリにあたるページ が格納されています。
これらの変数は、通常ページ (regular page) でしか有効でないことに注意してください(つまり、シングルページレイアウトで使用します)。
セクションページなどで参照すると、nil
が返されます。
.Title
ではなく .LinkTitle
を参照していることに注意してください。
こうしておくと、ページのフロントマターで linkTitle
プロパティが設定されている場合に、title
プロパティよりも優先的に参照されるようになります。体裁を整えるのであれば、前のページへのリンクは左寄せ、次のページへのリンクは右寄せで表示するとよいでしょう。 表示イメージとしては次のような感じです。
さらに、コードは prev-next
パーシャルテンプレートとして、使い回しがきくようにしておきましょう。
下記は完成版のパーシャルテンプレートです。
<div class="xPrevNextLink">
{{ with .PrevInSection }}
<div class="xPrevNextLink_prev">
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
</div>
{{ end }}
{{ with .NextInSection }}
<div class="xPrevNextLink_next">
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
</div>
{{ end }}
</div>
左寄せ、右寄せ用のスタイルも定義しておきます。 リンクタイトルの前後に表示される ≪ 記号や ≫ 記号も、CSS で表示するように設定します。
/* 前ページ、次ページへのリンク */
.xPrevNextLink {
display: flex;
justify-content: space-between;
}
.xPrevNextLink_prev::before {
content: "≪";
}
.xPrevNextLink_next::after {
content: "≫";
}
prev-next
パーシャルテンプレートを使用するには、任意のテンプレートファイル内で次のように呼び出します。
<body>
<main>
...
{{ partial "prev-next" . }}
...
</main>
</body>
セクションページも含めて「前のページ」「次のページ」へのリンクを表示する
上記の .PrevInSection
や .NextInSection
は、通常ページ (regular page) のみを対象 として、「前のページ」や「次のページ」へのリンクを実現するための機能でした。
例えば、content ディレクトリ内に次のような構成で記事を作成したとすると、
- section-0/_index.md
- section-1/_index.md
- section-2/_index.md
- section-3/_index.md
- page-1.md
- page-2.md
- page-3.md
page-1、page-2、page-3 の 3 つの通常ページを前後に移動するためのリンクとして働きます。 セクションページは対象にならないため、page-1 から section-3 へのリンク(およびその逆のリンク)は張られません。
section-1、section-2、section-3 などのセクションページも含めて、前後に移動できるようにするには、.PrevInSection
や .NextInSection
を使用せず、自力で前後のページへの参照を求める必要があります。
下記のサンプルコードは、セクションページを含めた「前のページ」「次のページ」へのリンクを出力する例です。
{{ if .Parent }}
{{- /* まずは同じ階層のセクションとページから prev と next を決める */}}
{{- range .Parent.Pages }}
{{ if eq . $ }}
{{ $.Scratch.Set "found" true }}
{{ else }}
{{ if $.Scratch.Get "found" }}
{{ if not ($.Scratch.Get "next") }}
{{/* Set "next" entry as just after the current page. */}}
{{ $.Scratch.Set "next" . }}
{{ end }}
{{ else }}
{{/* Update "prev" entry until the current page is found. */}}
{{ $.Scratch.Set "prev" . }}
{{ end }}
{{ end }}
{{ end }}
{{/* 見つかった prev と next のリンクを表示 */}}
<div class="xPrevNextLink">
{{- with ($.Scratch.Get "prev") -}}
<div class="xPrevNextLink_prev">
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
</div>
{{- end -}}
{{- with ($.Scratch.Get "next") -}}
<div class="xPrevNextLink_next">
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
</div>
{{- end -}}
</div>
{{ end }}
ちょっと長いですが、大まかには次のようなことを行っています。
- 同一階層にある通常ページおよびセクションページをループ処理(前から順番に見ていく)
- カレントページにたどり着いた時点で、その前後のページが判明する(
"prev"
と"next"
) "prev"
と"next"
のページへのリンクを出力
range
ループの break
をサポートしていなかったため、前後のページを発見した後も最後までループ処理が継続してしまいます。
Hugo(が使用している Go テンプレート)が break
に対応すれば、もう少し効率的な処理が可能になります。
とはいえ、そのままでも十分速いですが。上記の prev-next-siblings
パーシャルテンプレートは、通常ページ (regular page) 専用の Page 変数である .PrevInSection
や .NextInSection
を使用せずに実装されているため、下記のようにセクションテンプレートなどからも使用することができます。
このセクションテンプレートは、ベーステンプレートと組み合わせて使用する ことを想定しています。
{{ define "article" }}
<article class="xArticle">
{{ partial "prev-next-siblings" . }}
{{ .Render "inc-article" }}
</article>
{{ end }}
Hugo がネイティブでこのようなリンク出力用の Page
変数を用意してくれれば楽なんですけどね(^^;