Old Sunset Days

トップページにアイキャッチのサムネイル画像を入れる

日付 タグ hugo カテゴリ hugo

目次

Hugoブログでアイキャッチ画像を設定しよう

アイキャッチ画像とは何か?

そもそもアイキャッチ画像とは何か?だが、アイキャッチ画像とは記事一覧とかのページに表示されるサムネイル画像のこと。

アイキャッチ画像があると、パッと見た時に、どんなことが書かれているのか記事一覧のサマリーを読まなくても、イメージしやすいという利点がある。

  • Hugoでアイキャッチのサムネイル画像を表示するには2パターン
    • ブログ記事のMarkdownのmdヘッダー箇所でアイキャッチ画像を指定する
    • 記事中に使われている画像の中で一番最初の画像をアイキャッチ画像にする

既存テーマを利用している場合は、テーマ側でアイキャッチサムネイルの機能が提供されている場合もあるので、その場合は、そのやり方に従ってやれば表示されるはず。一度、自分が使用しているテーマに関する説明などを見返した方がいいだろう。

以下は利用しているテーマにアイキャッチの機能がなかったり、自分でカスタマイズしたい人向けの話。

ブログ記事のMarkdownのmdヘッダー箇所でアイキャッチ画像を指定する

例えば、ブログ記事のアイキャッチ画像をimages/hugo-eyecatch/eyecatch.jpgにおいた記事があるとする。 記事のMarkdownファイルのmd中のヘッダーで

eyecatch: "images/hugo-eyecatch/eyecatch.jpg"

とeyecatch画像のURLを指定しておき、記事をリスト表示しているページ中でこれをサムネイル化して読み込めば良い。 例としてトップページで直近の記事5つをリスト表示している場合、

layouts/index.html中で

{{ $paginator := .Paginate (where .Site.RegularPages.ByDate.Reverse "Section" "blog") 5 }}
{{ range $paginator.Pages }}
  <p>
  <ul style="list-style-type: none;">
  <li>
  <a href="{{ .Permalink }}">{{ .Title }}</a>
  </li>
  {{ if isset .Params "eyecatch" }}
  {{ $eyecatch_image := .Params.eyecatch }}
  {{ with $eyecatch_image }}
    <li><img src="{{ . | safeHTML}}" width="200px"></li>
  {{ end }}
  {{ end }}
  <li>
  {{ .Summary |  plainify }}
  </li>
  </ul>
  <p>
{{ end }}

のような感じでPaginatorでループを回しつつ、そのループ中で各記事に対して、

< 記事タイトル >
< サムネイルのアイキャッチ画像 >
< 記事サマリー >

の順で表示が可能である。

その中でもサムネイルのアイキャッチ画像の部分は以下。

{{ if isset .Params "eyecatch" }}
{{ $eyecatch_image := .Params.eyecatch }}
{{ with $eyecatch_image }}
  <li><img src="{{ . | safeHTML}}" width="200px"></li>
{{ end }}
{{ end }}

if文でパラメータとしてeyecatch指定があるかどうかチェックして、eyecatch指定のヘッダーがある記事のみ、その画像URLをeyecatch_image変数に代入してimgタグで表示している。なお、サムネイル表示のため、画像幅は一律にwidth="200px"で幅を統一している。

eyecatchパラメータ指定がないMarkdownのページは何もアイキャッチのサムネイル画像は表示されない。

結果として表示はこうなる。

ちなみに、ここで再度確認だが、with構文はHugoの公式サイトの説明にあるように

https://gohugo.io/functions/with - with

An alternative way of writing an if statement and then referencing the same value is to use with instead. with rebinds the context (.) within its scope and skips the block if the variable is absent or unset.

if文的な役割もなしているので、eyecatch_image変数がセットできないときは該当処理はスキップされる。つまりMarkdown記事のmdファイル中のヘッダー部分にアイキャッチ画像の定義ない記事ではこの処理はスキップされるということだ。

記事中に使われている画像の中で一番最初の画像をアイキャッチ画像にする

ブログ記事のMarkdownのmdファイル中のヘッダーでいちいち毎記事ごとにアイキャッチ画像を指定するのが面倒という人は、ブログ記事中の最初に出てくる画像タグに指定されているものをアイキャッチ画像に自動的に採用するという方法もある。

Hugoでは記事中の文から特定の文字列を検索するための関数findREが用意されているので、この関数を利用してみよう。

https://gohugo.io/functions/findre/ - findRE

``findRE (パターン) (入力文) (上限数)``

で上限数は省略が可能なパラメータである。この関数を利用して記事中からimgタグ(src指定があるもの)を1つ取ってくるには、このようになる。

findRE `<img.*?src="(.*?)".*?>` .Content 1

注意すべきはHugoのfindRE関数はマッチしたグループを返すのではなく、マッチした部分文字列全体を返すのだ。最初、このことに気づかずにちょっと戸惑った。

例えば、

findRE `<img.*?src="(.*?)".*?>` `<img src="http://example.com" alt="example" width="600px"/>`

の返り値は

[<img src="http://example.com" alt="example" width="600px"/>]

となるのである。Rubyとかで想像するmatchしたグループ http://example.comだけが返ってくる訳ではない。 また返ってくる値はリスト型なので上限数1で指定して返り値に入っているのが1個だとしても、リストのためrangeやindex文で処理する必要がある。

また、src属性だけを取得したい場合は2度findREをかける。これはアイキャッチ画像の幅を200pxに指定したいため、widthまで含めて取得すると、ちょっと面倒なので、一旦imgタグを取ってきて、次にその中で指定されているsrc属性のURLを取ってくる処理をする場合

layouts/index.html中で

{{ $paginator := .Paginate (where .Site.RegularPages.ByDate.Reverse "Section" "blog") 5 }}
{{ range $paginator.Pages }}
  <p>
  <ul style="list-style-type: none;">
  <li>
  <a href="{{ .Permalink }}">{{ .Title }}</a>
  </li>
  {{ $img_tag := findRE `<img.*?src="(.*?)".*?>` .Content 1}}
  {{ range $img_tag }}
    {{ $eyecatch_image := findRE `src="(.*?)"` . }}
    <li>{{ print "<img " (index $eyecatch_image 0) " width=\"200px\">" | safeHTML }}</li>
  {{ end }}
  <li>
  {{ .Summary |  plainify }}
  </li>
  </ul>
  <p>
{{ end }}

その中でもサムネイルのアイキャッチ画像の部分は以下。

{{ $img_tag := findRE `<img.*?src="(.*?)".*?>` .Content 1}}
{{ range $img_tag }}
  {{ $eyecatch_image := findRE `src="(.*?)"` . }}
  <li>{{ print "<img " (index $eyecatch_image 0) " width=\"200px\">" | safeHTML }}</li>
{{ end }}

結果として表示はこうなる。

今回はアイキャッチ画像表示の方法を2パターン示した。どちらの方法でも結果的にはアイキャッチ画像のサムネイルが表示されるので、アイキャッチ画像を個別に指定したいか、自動的に設定したいか、やりやすい方でいいだろう。