Using Hugo .Render
to Save Repetition
Up until recently, my Hugo site's templates were full of snippets like:
{{- if eq .Type "posts" -}}
<meta name="twitter:label1" value="Reading time" />
{{ if eq 1 .ReadingTime }}
<meta name="twitter:data1" value="{{ .ReadingTime }} min" />
{{ else }}
<meta name="twitter:data1" value="{{ .ReadingTime }} mins" />
{{ end }}
{{ end }}
{{- if (eq .Type "events") -}}
{{ if .Params.Start }}
<meta name="twitter:label1" value="Start time" />
<meta name="twitter:data1" value="{{ dateFormat "Mon, 02 Jan 2006 15:04:05 MST" .Params.Start }}" />
{{ end }}
{{ if .Params.Adr }}
<meta name="twitter:label2" value="Address" />
<meta name="twitter:data2" value="{{ .Params.adr.street_address }}, {{ .Params.adr.locality }}, {{ .Params.adr.postal_code }}" />
{{ end }}
{{- end -}}
This wasn't really a very scalable solution, as each time I created a new content type, I'd need to add a new case statement.
But recently I learned about Hugo's .Render
functionality, which means I can update my templates to just call to .Render
:
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="{{ .Title }} · {{ .Site.Title }}" />
<meta name="twitter:description" content="{{ $description }}" />
-
- {{- if eq .Type "posts" -}}
- <meta name="twitter:label1" value="Reading time" />
- {{ if eq 1 .ReadingTime }}
- <meta name="twitter:data1" value="{{ .ReadingTime }} min" />
- {{ else }}
- <meta name="twitter:data1" value="{{ .ReadingTime }} mins" />
- {{ end }}
- {{ end }}
- {{- if (eq .Type "events") -}}
- {{ if .Params.Start }}
- <meta name="twitter:label1" value="Start time" />
- <meta name="twitter:data1" value="{{ dateFormat "Mon, 02 Jan 2006 15:04:05 MST" .Params.Start }}" />
- {{ end }}
- {{ if .Params.Adr }}
- <meta name="twitter:label2" value="Address" />
- <meta name="twitter:data2" value="{{ .Params.adr.street_address }}, {{ .Params.adr.locality }}, {{ .Params.adr.postal_code }}" />
- {{ end }}
- {{- end -}}
<meta name="twitter:image" content="{{ $imageUrl }}" />
+ {{ .Render "sharing-card" }}
And then i.e. in events/sharing-card.html
:
{{ if .Params.Start }}
<meta name="twitter:label1" value="Start time" />
<meta name="twitter:data1" value="{{ dateFormat "Mon, 02 Jan 2006 15:04:05 MST" .Params.Start }}" />
{{ end }}
{{ if .Params.Adr }}
<meta name="twitter:label2" value="Address" />
<meta name="twitter:data2" value="{{ .Params.adr.street_address }}, {{ .Params.adr.locality }}, {{ .Params.adr.postal_code }}" />
{{ end }}
And in posts/sharing-card.html
:
<meta name="twitter:label1" value="Reading time" />
{{ if eq 1 .ReadingTime }}
<meta name="twitter:data1" value="{{ .ReadingTime }} min" />
{{ else }}
<meta name="twitter:data1" value="{{ .ReadingTime }} mins" />
{{ end }}
As well as that, you can set up a _default/sharing-card.html
, which will be used if each content type doesn't override it.
EDIT: However, as found the other day, this actually broke my RSS/JSON Feeds.
.Render
looks up Content Views for the same output format that it's currently rendering. So when I set i.e. my RSS feed to .Render "content"
it was actually looking up content.xml
, which didn't exist, as it's content.html
! The workaround I've now employed is to have a partial that stores the HTML rendering of the page, and can then be called from JSON Feed, HTML or RSS to save on duplication.
Fortunately this didn't break my h-feed - maybe we should be using these instead of JSON Feed/RSS, eh?