以前、Hugo で目次を最初の見出しのすぐ前に差し込むカスタマイズについて書いた。
上のリンク先に記した方法でこのブログにも目次を表示させているが、長い投稿を読み返していると、途中で目次に戻りたいなと思うことが多々あった。
そこで、目次に戻るリンクを各見出しの前に挿入することにした。
JavaScript を使う方法もあるが、せっかく Hugo を使っているので独自タグだけで実装する方法を考えた。
※Hugo v0.151.2 を用いた方法です。Hugo のバージョンによってはこの投稿の方法が使えない場合がありますのでご了承ください。
この記事の目次
目次に戻るリンクを各見出しの前に挿入する
既に .TableOfContents で投稿ページに目次を導入しているものとする。
以下のコードを、 single.html などの投稿用テンプレートの記事本文を表示させたい箇所に記述する。
{{ $h2s := findRE `(?s)<h2.*?>.*?</h2>` .Content }}
{{ if ge (len $h2s) 2 }}
{{ $content := .Content }}
{{ $back := `<div class="back-to-toc"><a href="#TableOfContents">↑ 目次に戻る</a></div>` }}
{{ range after 1 $h2s }}
{{ $content = replace $content . (printf "%s%s" $back .) }}
{{ end }}
{{ $content | safeHTML }}
{{ else }}
{{ .Content }}
{{ end }}
本文中の h2 タグをすべて取得し、見出しが2つ以上ある場合は次の処理へ移行、それ以外はそのまま本文を表示させる。
このコードにより、最初の見出しの直前には何もせず、2番目以降の見出しの直前には目次に戻るリンクが挿入される。
リンクの戻り先である #TableOfContents は、 .TableOfContents で生成される div 要素の ID に準じている。
実際にこの段落のすぐ下にも目次に戻るリンクが表示されているはずだ。
目次と目次に戻るリンクを見出しの前に挿入する
以下のコードを、 single.html などの投稿用テンプレートの記事本文を表示させたい箇所に記述する。
{{ $h2s := findRE `(?s)<h2.*?>.*?</h2>` .Content }}
{{ if ge (len $h2s) 2 }}
{{ $content := .Content }}
{{ $toc := printf `<details class="toc"><summary>この記事の目次</summary>%s</details>` .TableOfContents }}
{{ $back := `<div class="back-to-toc"><a href="#TableOfContents">↑ 目次に戻る</a></div>` }}
{{ range $i, $h2 := $h2s }}
{{ if eq $i 0 }}
{{ $content = replace $content $h2 (printf "%s%s" $toc $h2) }}
{{ else }}
{{ $content = replace $content $h2 (printf "%s%s" $back $h2) }}
{{ end }}
{{ end }}
{{ $content | safeHTML }}
{{ else }}
{{ .Content }}
{{ end }}
本文中の h2 タグをすべて取得し、見出しが2つ以上ある場合は次の処理へ移行、それ以外はそのまま本文を表示させる。
このコードにより、最初の見出しの直前には折りたたみ式の目次が、2番目以降の見出しの直前には目次に戻るリンクが挿入される。
リンクの戻り先である #TableOfContents が details の中にあるため、目次が閉じた状態であっても、戻るリンクをクリックすればブラウザが自動で目次を開いてスクロールしてくれる。
ただし、このまま #TableOfContents に飛ぶと上の summary のタイトル部分が見切れてしまうので、以下のように scroll-margin-top でスクロール位置を上部にずらす調整を入れておくといい感じになる。
#TableOfContents {
scroll-margin-top: 64px;
}
あとがき
Hugo で目次に戻るリンクを各見出しの前に挿入する方法について書いた。1つのコードで、目次と目次に戻るリンクを見出しの前に挿入する方法もあわせて紹介した。
このブログを Blogger で運営していたときは、同じことをするのに JavaScript を使うほかなかった。改めて Hugo ってすごいな〜〜〜(小並感)と思った。
このカスタマイズが誰かの助けになれば幸いです。あけましておめでとうございます!!!