HUGO

Adding content to block from mutiple partial templates

I have a scripts block in my baseof.html file, where I’d like to add script tags from my shortcodes.

The problem: I can’t find a way to add content to a block from two different places without one overriding the other.

Please provide an example of one of your shortcodes.

Minimal baseof.html:

<head>
{{block "scripts" .}}
{{end}}
</ head>

Shortcode 1

...
{{ define "scripts" }}
<script defer src="/example.js">
{{ end }}
...

Shortcode 2

...
{{ define "scripts" }}
<script defer src="/example2.js">
{{ end }}
...

Only one of those script tags is going to get rendered. My question is: How can I add content to a block from multiple partials / shortcodes? Is that even possible?

You are redefining the block multiple times on the same page. That’s not going to work. How about…

layouts/_default/baseof.html

<head>
  ...
  ...
  {{- $noop := .Content -}}
  {{- range .Scratch.GetSortedMapValues "js" -}}
    {{ . }}
  {{- end -}}
</head>

layouts/shortcodes/a.html

{{- $js := `<script defer src="/example-a.js"></script>` }}
{{- $.Page.Scratch.SetInMap "js" .Name ($js | safeHTML) -}}

layouts/shortcodes/b.html

{{- $js := `<script defer src="/example-b.js"></script>` }}
{{- $.Page.Scratch.SetInMap "js" .Name ($js | safeHTML) -}}

content

{{< b >}}

{{< a >}}

Notes:

  1. If you make any changes to the templates while hugo server is running, you may have to restart the server to see the changes.
  2. The scripts will be added to <head> based on an alphabetical sort of the shortcode names. So in the example above, the scripts will be ordered a,b even though they appear on the page b,a.

You could also use a generic shortcode with this approach.

layouts/shortcodes/js.html

{{- with .Inner -}}
  {{- $.Page.Scratch.SetInMap $.Name (printf "%04d" $.Ordinal) (chomp .) -}}
{{- else -}}
  {{- errorf "The %s shortcode requires 'Inner' content. See %s" .Name .Position -}}
{{- end -}}

content

{{< js >}}
<script defer src="/example-foo.js"></script>
{{< /js >}}

{{< js >}}
<script defer src="/example-bar.js"></script>
{{< /js >}}

The scripts will be added to <head> in the order they appear on the page.

Thanks! This works perfectly.

For anyone trying this, remember to loop over the map after you have rendered your shorcode/partial. I opted to render the scripts before the closing </body> tag.

This should not matter if you preface the range statement with $noop := .Content as shown:

{{- $noop := .Content -}}
{{- range .Scratch.GetSortedMapValues "js" -}}
  {{ . }}
{{- end -}}

Please let me know if you had any problems placing this in the <head> of your page. I tested this thoroughly and did not have any problems.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.