CODE HOUSE


Hello, I'm a freelance software engineer.


[Hugo] ページネーションを追加する

ブログ一覧ページの追加

このサイトはhugo-unoというベーステーマを元に作成している。しかし、このテーマはトップページに最新の記事を10個だけ表示するようになっていた。また、index.html#blogというハッシュを付けた場合に一覧を表示するようになっている(カバーページと一覧ページを同一のhtmlで切り替えて表示するようになている)。

これを下記のように変更したいのだが、これがなかなかわかりにくくて、特に下記の★の2つはだいぶ調べるのに時間がかかった。最終的には対応できたのでこれを記事にしておきたいと思う。

  • rootのindex.htmlはカバーページ専用とする。
    • この変更についてはこの記事では説明しない。変更点はmm-git/hugo参照。layouts/index.html, static/js/main.jsあたりを変更している。
  • blogworkといったセクションごとに、記事の一覧を作成する。★
  • blogは5記事毎にページを切り替えるようにする。★
  • workは同一ページに全一覧を載せる。

blog一覧ページの作成

まず最初のハマりポイント。あるセクションごの一覧ページを作成する場合、下記のようにする。(わかれば簡単なのだが・・)

  1. layouts/sectionフォルダにセクション名.htmlというファイルを作成する。
  2. layouts/セクション名フォルダに、summary.htmlというファイルを作成する。
  3. ファイル変更後、hugo serverを起動させて確認する。http://baseurl/セクション名/で一覧が表示される。

blogセクションの場合、layouts/blog/summary.htmllayouts/section/blog.htmlを作成

layouts/section/blog.html

layouts/section/blog.html
 1:
 2<section id="main">
 3    {{ $paginator := .Paginate (where .Data.Pages "Type" "blog") 5 }}
 4    
 5    <div class="article_list">
 6        {{ range $paginator.Pages }}
 7            {{ .Render "summary" }}
 8        {{ end }}
 9        :
10    </div>
11</section>
12:
  • 上記は、blog.htmlの一部。記事一覧とページ機能の部分のみ抜粋。
  • このファイルを元にして、public/blog/index.htmlが作成される。
    • public/blog/index.htmlは一覧の1ページ目のhtmlファイルとなっている。
  • 2つめのハマりポイント。あるセクションごとに、かつ5ページごとにページ一覧作成するには、3行目の.Paginate関数のようにする。
    • .Paginate関数の結果を$paginatorに代入しておくのがポイント。
    • htmlのどこかに.Paginateがあれば、public/blog/page/にページごとのindex.htmlが作成される。
      • public/blog/page/1/index.htmlpublic/blog/page/2/index.html..のようにindex.htmlが作成される。
      • public/blog/page/1/index.htmlについては、public/blog/index.htmlへリダイレクトされるようになっている。
  • 6〜7行目で、各記事のサマリーを作成している。
    • $paginatorには.Paginate関数で絞られた最大5記事のデータが配列で入っている。
    • $paginator.Pagesでループさせることで、各記事のサマリを作成している。
    • .Render "summary"により、layouts/blog/summary.htmlの内容をここに出力する。

layouts/blog/summary.html

layouts/blog/summary.html
 1<article class="summary_post summary_link" onClick="document.location.href = '{{ .Permalink }}'">
 2<header>
 3<h2 class="summary-title">{{ .Title }} {{ if .Draft }}:: DRAFT{{end}} </h2>
 4<div class="post-meta">{{ .Date.Format "2006-01-02" }} - Read in {{ .ReadingTime }} Min </div>
 5</header>
 6<div class="summary">
 7    {{ .Description }}
 8</div>
 9<footer>
10</footer>
11</article>
  • 記事の内容にアクセスするには、.Permalink.Titleなどの変数を用いる。

public フォルダの出力例

public
└──blog
   ├── index.html
   ├── index.xml
   └── page
       ├── 1
       │   └── index.html
       └── 2
           └── index.html

work一覧ページの作成

blogのページ一覧と同様に下記ファイルを作成する。

  • layouts/section/work.html
  • layouts/work/summary.html

layouts/section/work.html

layouts/section/work.html
 1:
 2<section id="main">
 3    <div class="article_list">
 4        {{ range .Data.Pages }}
 5            {{ if eq .Type "work" }}
 6                {{ .Render "summary"}}
 7            {{ end }}
 8        {{ end }}
 9    </div>
10</section>
11:
  • 上記は、work.htmlの一部。記事一覧とページ機能の部分のみ抜粋。
  • このファイルを元にして、public/work/index.htmlが作成される。
  • 4〜6行目で、各記事のサマリーを作成している。
    • .Data.Pagesで全ての記事をループさせ、そのうちタイプがworkのものだけ、各記事のサマリを作成している。
    • .Render "summary"により、layouts/work/summary.htmlの内容をここに出力する。

layouts/work/summary.html

layouts/work/summary.html
 1<article class="summary_post summary_link sumary_work" onClick="document.location.href = '{{ .Permalink }}'">
 2<header>
 3</header>
 4<footer>
 5</footer>
 6<div class="post_image_frame">
 7    {{ if .Params.landscape }}
 8    <img src="{{ .Params.image }}" class="post_image post_image_landscape">
 9    {{ else }}
10    <img src="{{ .Params.image }}" class="post_image">
11    {{ end }}
12</div>
13</article>
  • blog一覧では、記事のタイトル、説明文を表示していたが、workでは画像のみを表示している。
  • 本サイトではwork記事の.mdファイルフロントマターに、imagelandscapeを設定するようにしている。
  • 記事のフロントマターは、.Params.imageのようにすることでアクセスできる。
  • 上記のようにすることで、記事のフロントマターで設定した画像が記事一覧に表示される。

public フォルダの出力例

public
└──work
   ├── index.html
   └── index.xml