After updating Hugo from v0.120.1 to v0.124.1 my custom toc.html partial stopped working. Here is the issue the logs present me:
execute of template failed at <.Fragments.Headings>: nil pointer evaluating *tableofcontents.Fragments.Headings
A did some debug. By checking the .Fragments results, editing the partial to only contain the following line: <pre>{{ .Fragments | jsonify (dict "indent" " ") }}</pre>
But I can easily trigger the error again, by just adding the .Headings portion to that debug line. Meaning that <pre>{{ .Fragments.Headings | jsonify (dict "indent" " ") }}</pre> triggers the same error I get in my regular toc.html partial.
Is the problem that first “empty” level? Could it be due to the fact that I skip the Level 1 heading in my markup because I use the frontmatter title to render that in my final page?
Any pointers would be highly appreciated. I’d be interested in knowing whether something relative to this changed recently, I did browse the changelog, but couldn’t find anything specific.
I wrote a TOC partial a long time ago that walks .Page.Fragments.Headings. I’ve thoroughly tested this with v0.124.1 without error, but perhaps I’m missing a test case.
git clone --single-branch -b hugo-forum-topic-48963 https://github.com/jmooring/hugo-testing hugo-forum-topic-48963
cd hugo-forum-topic-48963
hugo server
That’s right, thanks for mentioning that. This is how I solved, just in case anybody stumbles upon this. Most likely there are better ways to overcome that limitation, but this worked well for my needs so far.
{{- with .Fragments -}}
<nav>
<div>
{{- with . -}}
<div class="toc-title">Contents</div>
{{- range .Headings -}}
<ul class="toc">
{{- with .Headings -}}{{ template "toc-subheading" (dict "headings" . "level" 0) }}{{- end -}}
</ul>
{{- end -}}
{{- end -}}
</div>
</nav>
{{ end -}}
{{- define "toc-subheading" -}}
{{- $headings := .headings -}}
{{- $level := .level -}}
{{- $padding := (mul $level 4) -}}
{{- $class := cond (gt $level 0) (printf "padding-left-%d" (add $padding 2) ) "padding-left-3" -}}
{{- range $headings }}
{{- if .Title }}
<li class="toc-item">
<a class="toc-item-link {{ $class }}" href="#{{ anchorize .ID }}">
{{- .Title | safeHTML | plainify | htmlUnescape -}}
</a>
</li>
{{- end -}}
{{- with .Headings -}}
{{ template "toc-subheading" (dict "headings" . "level" (add $level 1)) }}
{{- end -}}
{{- end -}}
{{- end -}}
Of course the amount of padding is a designer’s decision, but I left it in there as a proof of concept.