How to share a Partial across Output Formats

Simply create a partial without an extension i.e. partials/example

Before Hugo 0.20 partial extensions didn’t matter.

Since then:

A tpl with a .html suffix will be used by the HTML built in Output Format
A tpl with a .xml suffix will be used by the RSS built in Output Format

and so on…

However there are instances when one needs to share a template across Output Formats.
After much trial and error I found that this can be achieved with Partials without a suffix.
Call them in your templates like so: {{ partial "example" . }}
And within the partial store whatever value you need in a .Scratch
Call the partial from any Output Format template and fetch whatever you need from it with .Scratch.Get

Use case of the above:
I am calculating the sale prices of various products with Hugo’s Math functions and I needed a way to access these values both on the HTML front end and a XML Output Format, that will be used as the Data Feed of a Facebook/Instagram product catalogue.

Due to the seasonal changes of Sales and their percentages I needed one template that I could easily update. Turns out that partials without suffixes are the way to go.

4 Likes

Question: does return not work in this method (extension-less partials)?

By the way, I am always calling my partials without an extension. This solution might be an undocumented “official” way and not a humble “hack”. — bookmarked.

I am storing the values in .Scratch because it is easier for me to access them globally from several places like: homepage editorial, product range list, product permalink.

Actually that was how things worked prior to Custom Output Formats. In the linked topic above people reported breakage when using a partial without an extension but then @bep re-implemented that functionality to make Hugo versions -after 0.22- compatible with prior versions.

Inadvertently he has also made partials without an extension, available across all Output Formats when called through the respective templates.

Perhaps this needs to be documented.

1 Like

One more thing @davidsneighbour regarding return and for future reference.

As I understand this article by @regis return works best for returning one variable.

In my use case I am storing two values, that I have to access from the outside.
The original product price with VAT and the sale price.
Both of these variables need to be declared in the same template for maintenance reasons, because the various conditions to calculate their values are subject to frequent change.

From the outside (i.e. in other templates), return needs to be called with constructs like:

{{ with partial "func/GetEmoji" . }}
  Emoji: {{ . }}
{{ end }}

The above does add an extra layer to the context that will make writing a complex template even more difficult to write (at least for me).

Here is a real example of how I am calling these variables from a template:

    {{- if eq $.Section "handbags" -}}
    {{ with ($.Scratch.Get "prix") }}<del>{{- printf "%v,00" . }} €</del>{{- end -}}
    {{- else -}}
    {{- with $.Page.Params.price -}}<del>{{ printf "%v,00" . }} €</del>{{- end -}}
    {{- end -}}
    {{- end -}}

On the outside of the above there are even more conditions.

.Scratch is simpler, since it works from anywhere (as long as the partial is also accessible from a given template).

<coolvoiceon>I am doing maps and dicts with return<coolvoiceoff>

sample:

{{ $wordsPerMinute := float (site.Data.dnb.functions.readingtime.config.wordsPerMinute | default 220.0) }}
{{ $minsecs := site.Data.dnb.functions.readingtime.config.minutesandseconds | default true }}
{{ $words := countwords .Content }}

{{ $readTime := mul (div $words $wordsPerMinute) 60 }}

{{ $minutes := 0 }}
{{ $seconds := 0 }}

{{ if $minsecs }}

  {{ $minutes = math.Floor (div $readTime 60) }}
  {{ $seconds = mod $readTime 60 }}

{{ else }}

  {{ $minutes = math.Ceil (div $readTime 60) }}
  {{ $seconds = 0 }}

{{ end }}

{{ return (dict "minutes" $minutes "seconds" $seconds "words" $words) }}

I could think of some form of partialCached with dict combo, but I am not saying you should submit to my religion :smiley: It’s already enough you discovered a way to share partials between output formats. I have some cases where I just repeat those things between formats.

1 Like

After 6 long hours of head scratching and the inevitable headache. :upside_down_face:

1 Like

6 hours of 2020 well used :slight_smile:

1 Like