Hugo+MmarkでTOCを表示する
Contents
環境
- Hugo 0.55.3
背景
Hugo で Mmark ファイルをビルドする場合、TOC (table of contents) が仕様上表示されない。
対策
{{ .TableOfContents }}
の代わりに、カスタムテンプレートを作成する。
HTML
{{ $headers := findRE "<h[2-4].*?>(.|\n])+?</h[2-4]>" .Content }}
{{ $numHeaders := len $headers }}
{{ $hasHeaders := ge $numHeaders 1 }}
{{ if $hasHeaders }}
<nav id="TableOfContents">
<ul>
{{ range $i, $header := $headers }}
{{ $anchorId := (replaceRE "[ ]" "-" ($header | htmlUnescape | plainify | htmlEscape)) }}
{{ $listItemTitle := $header | htmlUnescape | plainify | htmlEscape }}
{{ $listItemOpen := safeHTML (printf "<li><a href='#%s'>%s</a></li>" $anchorId $listItemTitle) }}
{{ $currentHeaderLevelString := index (findRE "[2-4]" $header 1) 0 }}
{{ $currentHeaderLevel := len (seq $currentHeaderLevelString) }}
{{ if lt $i 1 }}
{{ $.Scratch.Set "previous" 2 }}
{{ else }}
{{ $previousHeader := index $headers (sub $i 1) }}
{{ $previousHeaderLevelString := index (findRE "[2-4]" $previousHeader 1) 0 }}
{{ $previousHeaderLevel := len (seq $previousHeaderLevelString) }}
{{ $.Scratch.Set "previous" $previousHeaderLevel }}
{{ end }}
{{ $previousHeaderLevel := ($.Scratch.Get "previous") }}
{{ range $j := seq (sub $currentHeaderLevel $previousHeaderLevel) }}
{{ if gt $j 0 }}<ul>{{ else }}</ul>{{ end }}
{{ end }}
{{ $listItemOpen }}
{{ end }}
</ul>
</nav>
{{ end }}