Hugo テーマ 3. 最近の更新リスト
2021-10-31 20:25:42
hugo現在作成途中のテーマ cheep をもとに、最近の更新リストを実装する方法を解説します。
最近の更新リストの実物は、このサイトの右にある「LATEST」となります。
今回は、このリストを作成する部分を解説します。
最終形
最近の更新リストをテンプレートとして括り出す構成にします。
まずは、テンプレートをはめ込む側から。
themes/cheep/layouts/_default/baseof.html
1
2
3
4
5
6
7
| <body>
:
<div class="side-area">
{{ partial "profile.html" . }}
{{ partial "latest.html" . }}
{{ partial "tags.html" . }}
</div>
|
partial となっている箇所の2つ目(真ん中)が最近の更新リストが入る部分です。
次に、最近の更新リストの方。
themes/cheep/layouts/partials/latest.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| <div class="latest_list_container">
<ul>
{{ if (default true $.Site.Params.latestOnlyPage) }}
{{ range first 10 (sort (where .Site.Pages "IsPage" true) "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ .Title }}
{{ if $.Site.Params.latestSummaryLength }}
<div class="latest_summary">
{{ substr (replaceRE "<[^>]+>" "" .Summary) 0 $.Site.Params.latestSummaryLength }}
</div>
{{ end }}
</li></a>
{{ end }}
{{ else }}
{{ range first 10 (sort .Site.Pages "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
{{ if .IsPage }}
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ else }}
<span style="display:inline-block; text-decoration:none">{{ default "📂" $.Site.Params.iconLatestList }} </span>
{{ end }}
{{ .Title }}
{{ if $.Site.Params.latestSummaryLength }}
<div class="latest_summary">
{{ substr (replaceRE "<[^>]+>" "" .Summary) 0 $.Site.Params.latestSummaryLength }}
</div>
{{ end }}
</li></a>
{{ end }}
{{ end }}
</ul>
</div>
|
色々とやりすぎているので、簡単なものから徐に機能追加しつつ解説していきます。
シンプルなリスト
1
2
3
4
5
6
7
8
9
10
| <div class="latest_list_container">
<ul>
{{ range first 10 (sort .Site.Pages "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ .Title }}
</li></a>
{{ end }}
</ul>
</div>
|
3行目: Lastmod の降順でループ
カッコの内側から評価されます。
.Site.Pages
でサイトにあるページ(注意: カテゴリーやタグ、セクションも含まれます)を列挙して、
sort
で Lastmod
の降順(desc
)で並び替えます。
その上で、{{range}}
でループしています。
first 10
によって、上記の並び替え結果に対して最初の10件だけをループの対象としています。
4行目, 7行目: ループしている中身の情報を出力
{{ range }}
の内側ではそれぞれのページを参照するようにコンテクストが切り替わるっているで、{{ .Permalink }}
や {{ .Title }}
といった表現でページの内容(Hugo では「変数」と表現しているようです)を参照できます。
変数の一覧は Hugo サイトの Page Variables ☐↗ に列挙されています。
sort
で指定している Lastmod
についてもそのページに記載されています。
ページとその他(カテゴリーやタグ、セクション等)の切り分け
ページだけをリスト表示してみる
シンプルなリストでは、セクションなども混在して列挙されてしまいます。
そうなると、更新したページだけではなく、そのページが属しているセクションも更新されたことになってしまうため、何らか切り分けをして表示したいところです。
(10件の中にページ以外も含まれるため、表示件数が結果的に少なくなってしまうという弊害(?)もあります)
まずは、ページのみをリスト表示するように変えてみます。
更新前
1
| {{ range first 10 (sort .Site.Pages "Lastmod" "desc") }}
|
↓更新後↓
1
| {{ range first 10 (sort (where .Site.Pages "IsPage" true) "Lastmod" "desc") }}
|
sort
の前に、where
つまり (where .Site.Pages "IsPage" true)
を挟むことで、ページの変数が特定の値のものに絞り込んでいます。
ページとそれ以外で表示内容を変えてみる
{{ range }}
の内容は、再度、where
で絞り込みをしないようにして、ループの中で条件分岐をしてみます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <div class="latest_list_container">
<ul>
{{ range first 10 (sort .Site.Pages "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
{{ if .IsPage }}
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ else }}
<span style="display:inline-block; text-decoration:none">{{ default "📂" $.Site.Params.iconLatestList }} </span>
{{ end }}
{{ .Title }}
</div>
{{ end }}
</li></a>
{{ end }}
</ul>
</div>
|
サイト(テーマの利用側)のパラメーターで制御できるようにする
この変更を入れると、ほとんど最終形と同じになります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <div class="latest_list_container">
<ul>
{{ if $.Site.Params.latestOnlyPage }}
{{ range first 10 (sort (where .Site.Pages "IsPage" true) "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ .Title }}
</li></a>
{{ end }}
{{ else }}
{{ range first 10 (sort .Site.Pages "Lastmod" "desc") }}
<a href="{{ .Permalink }}" title={{ .Summary }}><li>
{{ if .IsPage }}
<span style="display:inline-block; text-decoration:none">{{ default "📄" $.Site.Params.iconLatestPage }} </span>
{{ else }}
<span style="display:inline-block; text-decoration:none">{{ default "📂" $.Site.Params.iconLatestList }} </span>
{{ end }}
{{ .Title }}
</li></a>
{{ end }}
{{ end }}
</ul>
</div>
|
サイトのパラメーターとして latestOnlyPage
を使うようにします。
これは、テーマを使う側の config.toml(拡張子はサイトに寄ってはyaml等になっているかもしれません) にパラメーターを記述する必要があります。
1
2
| [params]
latestOnlyPage = true
|
さて、テンプレートの方ですが、3行目と10行目で条件分岐をしています。
それぞれ3行目の方ではページのみを表示、10行目の方ではページもそれ以外も表示しています。
デフォルトの挙動を変更する
config.toml に記述をしていない場合でも、ページのみを表示するように変更してみます。
更新前
1
| {{ if $.Site.Params.latestOnlyPage }}
|
↓更新後↓
1
| {{ if (default true $.Site.Params.latestOnlyPage) }}
|
default
関数を挟むことで、設定をしていない場合のデフォルト値を true
にしています。
(default 関数 ☐↗)
default 関数
default 関数は、第一引数にデフォルト値(今回は true
)を、第二引数に対象の値をとります。
最後の引数が対象の値なので、以下のような書き方も可能です。
1
| {{ if $.Site.Params.latestOnlyPage | default true }}
|
ページのサマリーを表示する
最後です。
ページのタイトルだけでは物足りないので、ページのサマリーも表示してみます。
(-_-) oO( 特にこのサイトは自作ソフトウェアの解説ページが多いので、結果的に無味乾燥なタイトルのページが多いんです )
1
2
3
4
5
6
| {{ .Title }}
{{ if $.Site.Params.latestSummaryLength }}
<div class="latest_summary">
{{ substr (replaceRE "<[^>]+>" "" .Summary) 0 $.Site.Params.latestSummaryLength }}
</div>
{{ end }}
|
サイトのパラメーター $.Site.Params.latestSummaryLength
を参照し、表示する文字数を制限するようにしています。