Recursion in Hugo Templates
Turns out recursion is possible in Hugo templates by define
-ing blocks and then “calling” them with template
. (I had thought define
was only for overriding blocks from parent templates, like Django).
The use case was that I wanted to render a nested file tree, e.g.
- dir/
- file1
- file2
- dir2/
- file3
- dir3/
- file4
- file5
And so here’s a slimmed down version of what I figured out:
{{ define "main" }}
...
<h2>All Pages:</h2>
{{ template "navtree" . }}
...
{{ end }}
{{ define "navtree" }}
<ul>
{{ range .RegularPages }}
<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
{{ end }}
{{ range .Sections }}
<li>
<a href="{{ .RelPermalink}}">{{ .Title }}
{{ template "navtree" . }}
</li>
{{ end }}
</ul>
{{ end }}
This separates out “regular pages” (i.e. individual documents, leaf nodes) from “sections” (directories). If you wanted to intermingle them, you could do something like this instead:
{{ range .Pages }}
<li>
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
{{ if.IsSection }}
{{ template "navtree" . }}
{{ end }}
</li>
{{ end }}
Bonus TIL: if you want to nest content more than one level, e.g. foo/bar/wow.md
, and have that nesting show up in your section hierarchy, you’ll need an _index.md
in every level except the top. That is, foo/_index.md
is optional, but if you’re missing foo/bar/_index.md
, all the content directory will be considered part of the foo
collection, and you won’t have a foo/bar
collection.