WEBTODESIGN

Hugoで記事にタグをつけて、記事内やサイドバーに表示する

Hugoで各記事にタグを設定し、その記事内にタグを表示、そのタグをクリックすると同じタグの記事一覧に飛べて、サイドバーにはタグの一覧が表示されている、という状態までもっていくことができましたので、共有します!

使用したHugoのバージョンは「v0.75.1」です。

Hugoではタクソノミーとターム

Hugoではタグのような機能を「taxonomy(タクソノミー)」という機能で実装することができます。タクソノミーは、ただタグをつけるだけでなくタグをグループ分けして管理できる機能です。Hugoではタグ自体のことは「term(ターム)」と言います。さらに、タームに紐付けられたコンテンツのことを「value(バリュー)」といいますが今回は割愛します。

標準では「tags」と「categories」というタクソノミーが使えるようになっています。このネーミングが頭の混乱のもとなのですが…(汗)ここでの「tags」や「categories」はグループ分けの際のグループ名にすぎません。私達のイメージするカテゴリー(どこか一つだけに所属する)はまた別の機能があるみたいです。

Hugoでは「タグのグループ=タクソノミー」「タグ=ターム」を意味しているんだな、という認識でいいと思います。

タクソノミー、タームというと私は頭がこんがらがって理解に時間がかかったので、厳密には意味が違うとは思いますが、この記事においてはタクソノミーはグループ、タームはタグと呼ばせてください。

※タクソノミーについての詳しい説明は、公式ドキュメントの「Taxonomies」をご確認ください

記事にタグを設定する

今回は標準で使える「tags」というグループを使います!

//content/post/xx.md
---
title: ~
date: ~
tags: ["タグ名", "タグ名"]
---

記事の最初の設定に追記します。タグの列挙全体は「[ ](ブラケット)」で囲み、それぞれのタグは「" "(ダブルクォーテーション)」で囲みましょう。「,(コンマ)」で区切ることで、複数のタグが設定できます。

たったこれだけで、タグの設定ができました!簡単!

オリジナルのグループを追加したい場合は、config.tomlに以下のように追加します。

//config.toml
[taxonomies]
  trip = "trip"

最後の行のように記述することで、この場合は「trip」という新しいグループを追加することができました。また、新しいグループを追加すると標準で定義されている「tags」と「categories」は作成されなくなります。独自のグループを追加した場合に「tags」と「categories」を引き続き使いたい場合はそれぞれcategory = "categories"tag = "tags"を同じように追記してください。

記事内にタグを表示する

タグをつけただけでは、ユーザーからは何も見えません。記事内やサイドバーにタグを出力する必要があります。例えば、記事タイトルの下にその記事のタグを並べたり、サイドバーにタグ一覧を設置するなどです。

まずは、記事内にその記事に設定されているタグを表示してみましょう!

実際のコード

記事のテンプレートファイルの中でタグを表示したい箇所に、以下のコードを設置します。(例えば、layouts/_default/single.html)

{{ if .Params.tags }}
<ul>
  {{ range (.GetTerms "tags") }}
    <li><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
{{ end }}

コードの解説

ひとつずつ見ていきましょう!まずはHTMLの基本型です。

<ul>
  <li>~</li>
</ul>

リスト形式に使うulとliを使っています。タグの数だけliが繰り返される設定にしていきます。その繰り返す設定はrange関数で行うことができます。range関数は以下のような形で使います。

{{ range 条件 }}内容{{ end }}

条件を満たしている場合内容を出力し、条件が尽きるまでその処理を繰り返します。

グループ「tags」に設定されているタグを取得する、が条件です。タグは(.GetTerms "tags")で取得できるので以下のようになります。

{{ range (.GetTerms "tags") }}
  ~
{{ end }}

rangeの処理の中身に、繰り返したい内容を記述します。今回は、リンク付きのタグの名前が記されたliタグを繰り返したいので以下のように記述します。

<li><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></li>

{{ .Permalink }}(.GetTerms "tags")で取得したタグのリンク、{{ .LinkTitle }}(.GetTerms "tags")で取得したタグ名を出力します。

これで、タグの数だけrangeが繰り返され、タグがリストアップされるようになりました!

ただ、これだとタグが設定されていない場合でもrangeの外側のulタグは出力されてしまいます。記事の見た目は変わらない場合が多いですがソースコードが綺麗ではないので、タグが設定されていない場合は要素ごと非表示になるようにしてみましょう。その場合はif関数で場合分けします。

{{ if 条件 }}内容{{ end }}

if関数の形式はrange関数と同じです。条件を満たしている場合は内容が出力されます。今回は「パラメーターにtagsが設定されていた場合」にしたいです。パラメーターにtagsが設定されているかどうかは「.Params.tags」で判定できるので、以下のように記述します。

{{ if .Params.tags }}
  ~
{{ end }}

以上を組み合わせると、以下のようになります。

{{ if .Params.tags }}
<ul>
  {{ range (.GetTerms "tags") }}
    <li><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></li>
  {{ end }}
</ul>
{{ end }}

「パラメーター(Params)にグループ「tags」の中身が設定されている場合のみ、そのタグを羅列する」ようにできました!

あとは、ulやliにクラスを付与して、CSSで見た目を整えれば完了です。

記事一覧のページをつくる

設置できたそれぞれのタグをクリックしてみると、自動的にURLが生成された白紙のページに飛ぶと思います。これは、タグが使われた記事一覧のページのテンプレートが作成されていないからです。

それでは、記事一覧のページのテンプレートを作っていきましょう!

実際のコード

layouts/_defaultにtaxonomy.htmlファイルをつくり、ヘッダーやフッターなど必要な要素を設置したあと一覧を表示したい部分に以下のように記述します。

<ul>
  {{ range .Pages }}
  <li><a href="{{ .Permalink }}">{{ .Title }}<time>{{ .Date.Format "2006.01.02" }}</time></a></li>
  {{ end }}
</ul>

コードの解説

まず、layouts/_defaultフォルダにtaxonomy.htmlというファイルを作ります。

タクソノミー機能の中でタグの部分のことを「ターム(term)」と呼ぶよと最初にお伝えしたことを覚えていらっしゃいますでしょうか。そのtermのことです!

Hugoのテンプレートには優先順位というものがあり、優先順位が高いものがそのページのテンプレートとして適用されます。この優先順位により、グループやタグごとに違うレイアウトにすることもできます。

この優先順位がどこで分かるかと言うと、Hugoの公式ドキュメントの「Hugo’s Lookup Order」に全て掲載されています。タクソノミーに関するテンプレートファイルの優先順位は「Example:Layout Lookup for Taxonomy Pages」の部分です。

このリストより、全てのタグに共通して使われるテンプレートで、なおかつタグ独自のテンプレートはlayouts/_default/taxonomy.htmlなのかなというところです。

というわけで、layouts/_default/taxonomy.htmlを作ったら、ヘッダーやフッターなどの共通のパーツを配置していきましょう。

そして、肝心の記事のリストを並べる部分。先程と同じ用にリストのulとliを使います。

<ul>
  <li>~</li>
</ul>

ページを取得するには「.Pages」という変数で取得できるので、繰り返しのrange関数と組み合わせます。

{{ range .Pages }}
  ~
{{ end }}

これで、記事を全てリストアップするまで処理を繰り返します。処理の中身は以下のように書きます。

<li><a href="{{ .Permalink }}">{{ .Title }}<time>{{ .Date.Format "2006.01.02" }}</time></a></li>

「{{ .Permalink }}」で「.Pages」のリンクを、「{{ .Title }}」で「.Pages」の記事タイトルを、「{{ .Date~ }}」で「.Pages」の投稿日を取得しています。

以上を組み合わせると、以下のようになります。

<ul>
  {{ range .Pages }}
  <li><a href="{{ .Permalink }}">{{ .Title }}<time>{{ .Date.Format "2006.01.02" }}</time></a></li>
  {{ end }}
</ul>

これにヘッダーやフッター、サイドバーをくっつて、CSSで見た目を整えればタグ毎の記事一覧ページの完成です。

サイドバーに一覧を表示する

次は、サイドバーにサイトに使われている全てのタグ一覧を表示してみましょう。

実際のコード

<ul>
{{ range .Site.Taxonomies.tags.ByCount }}
  <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}({{ .Count }})</a></li>
{{ end }}
</ul>
//config.toml
disablePathToLower = true

テンプレート内のサイドバー部分に以上の記述を追加すると、タグがli要素で列挙されます。

コードの解説

ひとつひとつ見ていきましょう!まずは、HTMLの基本の型です。今までと同じくリスト要素のulとliです。

<ul>
  <li>~</li>
</ul>

タグの個数分処理を繰り返すように、繰り返しのrange関数を使います。

{{ range .Site.Taxonomies.tags.ByCount }}
  ~
{{ end }}

「.Site.Taxomies.tags」で、サイト全体のグループの「tags」グループのタームを全て表示するという意味になります。

「.ByCount」は使用数が多い順に並べるという並べ方を意味します。「.Alphabetical」とすればアルファベット順に、「.Reverse」をさらに後ろに付け足せばそれぞれ逆順に並べ替えることができます。

繰り返しの内容は以下のように記述します。

<li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}({{ .Count }})</a></li>

「{{ .Page.Permalink }}」でタグへのリンク、「{{ .Page.Title }}」でタグ名、「{{ .Count }}」はタグが使われている数を取得しています。ここでいう「.Page」は先述のrange関数で指定した「.Site.Taxonomies.tags」で取得したページ(つまりタグ)から情報を取得します。

また、数字の部分を「「()」」で囲っています。例えば「ウェブ」というタグが3記事に使われていた場合は「ウェブ(3)」と出力されます。数が不要な場合は省けばOKです。

また、標準ではタグの全てのアルファベットが小文字に変換されてしまうため、それを防ぐためにconfig.tomlに以下の記述を追加しました。(気にならない方は設定しなくても大丈夫です。)

以上を組み合わせると、以下のようになります。

<ul>
{{ range .Site.Taxonomies.tags.ByCount }}
  <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}({{ .Count }})</a></li>
{{ end }}
</ul>

ulやliにクラスを付与して、見た目を整えれば完成です。

これで、各記事にタグを設定し、その記事内にタグを表示、そのタグをクリックすると同じタグの記事一覧に飛べて、サイドバーにはタグの一覧が表示されている、という状態にできました!