I’ve submitted a small PR to change Site.Author from map[string]string
to map[string]interface{}
because it will help me with some template work that I’m doing, and I’d like to propose a possible change to how some things work with Hugo and variable resolution. I’ll admit up front that I currently have no idea how this would be implemented, that the change may end up being hugely incompatible with current behaviour, and that it may not be possible within the confines of the templating engine(s) Hugo supports.
I think it would be useful to implement some sort of dynamic resolution so that .Params.foo
looks in <page>.Params
for foo
, and then it looks in <site>.Params
for foo
. This would only work on Node
level objects (that is, nodes and pages), and could potentially be implemented through a new function that does this implicitly. This would work with more than just Params
, but with other values that are either shared (Title
) or pushed down some values from Site
to the Node
or Page
(e.g., Author
).
I’ll give an example of what I mean with a template that I’m adapting from @tom’s Red Lounge for a theme that I’m calling cabaret
. The purpose here is to show social icons for an author if they either have an array map parameter Params.author.social
or if they have a string array parameter Params.author.social-sites
. I’ve also got support for Site.Author.social-sites
(the purpose of PR#600, above), because my Params.social
is a site-wide collection of social sites that I use for other purposes, and I can reuse here by matching each value of social-sites
against the name
value in Params.social
.
<!-- layouts/partials/author/social/list.html -->
{{ if not .Params.noauthor }}
{{ if isset .Params.author "social" }}
{{ range .Params.author.social }}
{{ partial "author/social/site" . }}
{{ end }}
{{ else if isset .Params.author "social-sites" }}
{{ $site := .Site }}
{{ range $name := index .Params.author "social-sites" }}
{{ range $site.Params.social }}
{{ if eq $name .site }}
{{ partial "author/social/site" . }}
{{ end }}
{{ end }}
{{ end }}
{{ else if and (not .Site.Params.noauthor) (isset .Site.Author "social-sites") }}
{{ $site := .Site }}
{{ range $name := index $site.Author "social-sites" }}
{{ range $site.Params.social }}
{{ if eq $name .site }}
{{ partial "author/social/site" . }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
With the sort of change that I’m suggesting here, the template shortens, because Hugo is doing the fallback-to-Site
that I am doing above (and the shortened change also adds the case of having a .Site.Author.social
map, which I don’t support in my code above).
<!-- layouts/partials/author/social/list.html -->
{{ if not .Params.noauthor }}
{{ if isset .Author "social" }}
{{ range .Author.social }}
{{ partial "author/social/site" . }}
{{ end }}
{{ else if isset .Author "social-sites" }}
{{ $site := .Site }}
{{ range $name := index .Author "social-sites" }}
{{ range $site.Params.social }}
{{ if eq $name .site }}
{{ partial "author/social/site" . }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
This is obviously a pretty big change, and I’m definitely not suggesting it for 0.13, but if it sounds like a good change (I’d like to be able to have more overrides and fallbacks pretty much everywhere, including inside Hugo’s internals) I can start trying to figure out how it might work.