I’m developing a team-based website using a custom Hugo theme, and am making use of a taxonomy for “authors” following this blog post and demo repo. I want “authors” to show up in my “articles” list and single pages (articles = blog/post-like content) with a link to their bio if they are a member of our team, and to just show up as the typed name if not a team member. I currently have this code in both my list and single partial layout files working:
{{ $authors := (union .Params.author .Params.authors) }}
{{ with $authors }}
{{ $author_count := (len .) }}
<strong>Author{{ if gt $author_count 1 }}s{{ end }}:</strong>
{{ range $index, $val := . }}
{{ $author := $val | title }}
{{- with $.Site.GetPage "taxonomyTerm" (printf "authors/%s" (urlize .)) }}
<a href="{{ .Permalink }}">{{ .Params.name }}</a>{{ if eq (add $index 1) $author_count }}{{ else }}, {{ end }}
{{ else }}
{{ $author }}{{ if eq (add $index 1) $author_count }}{{ else }}, {{ end }}
{{ end }}
{{ end }}
{{ end }}
But it is not robust. This only works if the page frontmatter YAML looks like this:
author: [Alison, Mara Averick, mine] # first and last are in taxonomy
or this:
author:
- Alison
- Mara Averick
- mine
My partials do not work if the names are not in brackets, as in if a single author did this:
author: Mara Averick
Or multiple authors are just separated by commas:
author: Mara Averick, Alison
Is there any way on the Hugo side that I can preserve the taxonomy links but allow users to possibly forget to add the brackets? I feel like this is going to be a frequent issue for users, and currently (I’m using the blogdown package in R), the brackets in my archetypes get stripped out when I create a new post. I tried slice but that lost my taxonomy links.
A semi-related question is that I also foresee users using either author or authors interchangeably in the YAML- my current code seems to work for this situation (using union) but I’m curious if others have better solutions to this.
A few notes, working on the assumption of latest Hugo and that you configured
[taxonomies]
author = "authors"
A semi-related question is that I also foresee users using either author or authors interchangeably in the YAML- my current code seems to work for this situation (using union ) but I’m curious if others have better solutions to this.
When defining your taxonomies, you would in your config define the "singular key" = "plural value", and then use the plural when defining the terms in your content [docs]. So if you defined your author taxonomy to be as above, you need to use the authors key in your content frontmatter to tell Hugo that the values assigned to it belong to a taxonomy, and not just a ‘regular’ front matter param.
You will get a list of strings from both/either the .Params.authors and .Params.author, yes, but .Params.author will just be a list of strings, not taxonomy values.
TLDR#1: you need to be consistent in your front matter taxonomy.
You can simplify this to $.Site.GetPage (printf "authors/%s" (urlize .)) > Hugo 0.45 [docs].
Yaml syntax needs the brackets to define a list. Without the brackets, it is interpreted as a string. You could use split to split a string with a delimiter, but the associated taxonomy would still be at the un-split string value. Also, consider the case where author: LastName, FirstName.
You could try to modify your code something like this:
{{ $authors := slice }}
{{ with .Params.authors }}
{{ if in (printf "%T" . ) "[]" }}
<!-- checks if the value is list type -->
{{ $authors = . }}
{{ else }}
<!-- else single value -->
{{ $authors = $authors | append . }}
{{ end }}
{{ with $authors ...
Thank you so much for your pointers! They got me pretty far to establishing some logic around determining if the author input was in a nice list or not. Here is what I came up with that works, but if it can be simplified I’m all ears!
I changed my taxonomy name so I would get less confused as I work- I may change it back but this helped to make sense of things:
[taxonomies]
member = "members"
tag = "tags"
category = "categories"
So content/members/ has folders in it named by the team member, and an _index.md file inside for each with bio information. Then I made this partial to print the author names, and it is called from a few different places
<!-- based on author field being used in YAML frontmatter -->
<!-- this sequence takes the author field and smartly deals with it! -->
{{ $authors := slice }}
{{ $authors_list := slice }}
{{ with .Params.author }}
{{ if in (printf "%T" . ) "[]" }}
<!-- checks if the value is list type -->
{{ $authors_list = . }}
{{ else }}
<!-- else single value -->
{{ $authors = $authors | append . }}
{{ end }}
<!-- if nice list to start with, now create nicer list -->
{{ with $authors_list }}
{{ $author_count := (len .) }}
{{ range $index, $val := . }}
{{ $author := $val | title }}
<!-- this pulls matching taxonomyTerm -->
{{- with $.Site.GetPage (printf "members/%s" (urlize .)) }}
<a href="{{ .Permalink }}">{{ .Params.name }}</a>{{ if eq (add $index 1) $author_count }}{{ else if eq 2 $author_count }} & {{ else if and (eq (add $index 2) $author_count) }}, & {{ else }}, {{ end }}
{{ else }}
{{ $author }}{{ if eq (add $index 1) $author_count }}{{ else if eq 2 $author_count }} & {{ else if eq (add $index 2) $author_count }}, & {{ else }}, {{ end }}
{{ end }}
{{ end }}
{{ end }}
<!-- if not nice list to start with, now create nice list -->
{{ with $authors }}
{{ range $index, $val := . }}
{{ $split_authors := (split . ",") }}
{{ with $split_authors }}
{{ $author_count := len . }}
{{ if eq 1 $author_count }}{{ . }}
{{ else if eq 2 $author_count }}{{ delimit . ", " " & " }}
{{ else }}{{ delimit . ", " ", & " }}{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
Now author can look like any of these:
author: [mine, mara Averick, Alison]
...
author:
- carl
- Garrett
...
author: Lionel Henry, Jenny Bryan, Hadley Wickham, Greg
And all the links work to link to individual team member bios.
As long as it works for your purposes, all is well. Just to point out one more thing though. In your current setup, you are now using members taxonomy, but setting author in the front matter of your content.
One side effect of this is that (unless you are also setting members in your content frontmatter) you won’t be able to use this nice feature of taxonomies, which is that you can get the content associated with the term, ie get a list of all the articles one author wrote on the author’s page. (Well, you could still, but not as a three-liner code.)