michimani.net

[Hugo] 記事下に同じカテゴリの記事一覧を表示する

2020-01-31

Hugo で作ったブログの記事下に、その記事と同じカテゴリの記事一覧を表示します。WordPress とか はてなブログ とかだとウィジェットで簡単に設置できるようになってますが、静的サイトの場合は少しだけ工夫が必要です。

目次

前提

やること

各テーマディレクトリ内にある layouts/_default/single.html に修正を加えます。
今回は indigo のテーマで実装するので、対象のファイルは themes/indigo/layouts/_default/single.html となります。

現在の記事のカテゴリ名を取得する

同一カテゴリの記事を表示するために、現在の記事のカテゴリ名を取得する必要があります。
Hugo では下記の記述により、現在の記事のカテゴリ名を取得できます。

{{ .Params.categories }}

ただし、これではカテゴリ名が配列で取得されるので、下記の記述を用いて一番最初のカテゴリ名を取得します。

{{ index .Params.categories 0 }}

また、カテゴリ名は後ほど使用するので、次のようにして変数として保持しておきます。

{{ $c := index .Params.categories 0 }}

対象のカテゴリ内の記事一覧を取得する

続いてカテゴリ内の記事一覧を取得します。

カテゴリ名は先ほど取得して $c という変数に保持しているので、それを利用して下記のような記述で取得できます。

{{ index .Site.Taxonomies.categories (lower $c) }}

.Site.Taxonomies.categories は dict 型になっていて、カテゴリ名をキーとして値に記事の配列を持っています。例えば aws というカテゴリであれば .Site.Taxonomies.categories.aws とすることで aws カテゴリの記事一覧を取得できます。

lower $c としているのは、 .Site.Taxonomies.categories のキーが小文字になっているからです。前項で取得したカテゴリ名は大文字を含んでいる可能性があるため、この記述で小文字に変換しています。

記事一覧についても後ほど複数回使用することになるため、変数に保持しておきます。

{{ $cposts := index .Site.Taxonomies.categories (lower $c) }}

記事一覧を表示させる

最後に、取得した同一カテゴリの記事一覧を表示させます。

Hugo では range 関数を使うことで配列の中身を取り出すことができるので、下記のようにして記事一覧を表示させます。

{{ range $cposts }}
    {{ .Render "li" }}
{{ end }}

{{ .Render "li" }} の部分で各記事の情報を themes/indigo/layouts/_default/li.html に渡しています。この li.html というのはトップページの記事一覧にも使われているテンプレートなので、この一覧表示のためだけに新たにテンプレートを作成すればトップの一覧とは別のデザインで表示することも可能です。

また、上記の表記では同一カテゴリ内の記事が全て一覧で表示されてしまうので、下記のようにして表示件数を制限することも可能です。

{{ range first 5 $cposts }}
  {{ .Render "li" }}
{{ end }}

これで 5 件だけ表示されます。

最終的にどうなったのか

ここまでで同一カテゴリ内の記事一覧表示はできるようになりました。最後に、実際にこのブログで表示させるためにどうしているか、例として載せておきます。

{{ if and (.Params.categories) }}
  {{ $c := index .Params.categories 0 }}
  <div class="same-category-posts-area">
    <h2>Posts in "{{ $c }}" category</h2>
    {{ $cposts := index .Site.Taxonomies.categories (lower $c) }}
    {{ range $cposts }}
      {{ .Render "li" }}
    {{ end }}
    {{ if gt (len $cposts) 5 }}
      <a class="more-btn" href="/categories/{{ lower $c }}/">more ...</a>
    {{ else }}
      <a class="more-btn" href="/categories/">other categories</a>
    {{ end }}
  </div>
{{ end }}

まず最初の if 文 {{ if and (.Params.categories) }} では、そもそも現在の記事にカテゴリが設定されているかを確認してます。設定されていれば表示するし、なければ表示してません。

あとは、 同一カテゴリ内の記事が 5 件以上あればカテゴリ別記事一覧ページへのリンクを、 5 件より少なければカテゴリ一覧ページへのリンクを、それぞれ表示するようにしています。

まとめ

Hugo で作ったブログの記事下に、その記事と同じカテゴリの記事一覧を表示してみた話でした。

こういったウィジェット (のようなもの) は動的に生成しているイメージが強く、静的サイトで実現するのは難しいかなと思っていたのですが、少し工夫することで実現できました。今回紹介したように Hugo には様々な関数が用意されているので、それらを組み合わせることでさらにリッチなコンテンツを表示できるようになるかもしれません。


comments powered by Disqus