Sharing .Scratch between shortcode outer and .Inner

My goal is to enable responsive image sizes, where the sizes item is context-aware. First, I have a gallery.html shortcode that defines a number of columns for image galleries:

{{ $p := .Page }}
{{ $cols := int (.Get "cols") }}
{{ $p.Scratch.Set "columns" $cols }}

<div class="gallery gallery-cols-{{ $cols }}">
{{- print .Inner | $p.RenderString  -}}
</div>

{{ $p.Scratch.Delete "columns" }}

Then, I overwrite the layout/_default/_markup/render-image.html with:

{{ $image := resources.Get .Destination }}
{{ $cols := .Page.Scratch.Get "columns" | default 0 }}
{{ $sizes := site.Params.Images.sizes }}

{{ if eq $cols 1 }}
  {{ $sizes = "(max-width: 992px) 100vw, (max-width: 1200px) 66.67vw, 50vw" }}
{{ else if eq $cols 2 }}
  {{ $sizes = "(max-width: 140px) 100vw, (max-width: 992px) 50vw, (max-width: 1200px) 33.33vw, 25vw" }}
{{ end }}

<img src={{ $image.RelPermalink }} alt="image"
    decoding="async" loading="lazy"
    sizes="{{ $sizes }}" srcset="..."
    width="{{ $image.Width }}" height="{{ $image.Height }}"
  />

Then in the Markdown page, I call:

{{% gallery cols="2" %}}
![](calibration-after.jpg)
![](calibration-before.jpg)
{{% /gallery %}}

This works properly on one website, not on the other. On the other, the scratch key "columns" seems to be created and deleted in gallery.html shortcode before its .Inner gets evaluated (in any case, its value is empty). The thing is, there can be more than one gallery per page, and the columns value needs to be properly scoped to the relevant gallery. What could be the problem here ?

(Using Hugo 0.124.1)

Your example does not show a nested shortcode. Please clarify.

Also, when testing, are you looking what is rendered by hugo server or are you examing the files rendered after running hugo?

Yes, sorry, this is the gutted example where the upmost {{ .Inner }} is directly Markdown. In some other examples, {{ .Inner }} contains another nested shortcode (like figure). The logic is the same: I want to share a variable inside the context of the upmost shortcode.

I’m rendering using hugo server --disableFastRender on both websites (the working on and the un-working one).

Before I spend any time digging into the details, please change all instances of Page.Scratch to Page.Store then test again.

Changing Page.Scratch to Page.Store doesn’t fix it.

Can you provide a non-gutted example? The goal is to create a minimal reproducible example…

The gutted example is already failing.

So I don’t need to nest shortcodes to make it fail? If yes, please rename this topic.

No. Renamed. Sorry for the confusion.

Here’s an attempt to create a minimal reproducible example based on your description.

git clone --single-branch -b hugo-forum-topic-48968 https://github.com/jmooring/hugo-testing hugo-forum-topic-48968
cd hugo-forum-topic-48968
hugo server
1 Like

And with the above, I’m not seeing what the problem is. Can you clarify?

I don’t either, your example works here. As is my other website.

Somehow, something is messing with my .Page.Scratch or .Page.Store states here, but I have checked and bypassed all calls to these methods and nothing fixes it.

If you can figure out the difference feel free to submit a PR against the hugo-forum-topic-48968 branch of https://github.com/jmooring/hugo-testing.

Note that I’ve also tested this with a 100 page site, spot checked about 30 of them, and everything looks right.

1 Like

Found it. Pull requests · jmooring/hugo-testing · GitHub

It was actually a problem of nesting shortcodes, but since the container.html shortcode took the whole block, I didn’t see it right away.

So what makes gallery break is:

{{% container %}}
{{% gallery cols="2" %}}
![](calibration-after.jpg)
![](calibration-before.jpg)
{{% /gallery %}}
{{% /container %}}

It breaks the same way either with .Page.Scratch or .Page.Store.

Call the inner shortcode using the {{< .. >}} notation.

{{% container %}}

{{< gallery cols="1" >}}
![](calibration-after.jpg)
![](calibration-before.jpg)
{{< /gallery >}}

{{% /container %}}

Thanks ! That works. But I was under the impression that {{% %}} was meant to enable Markdown parsing for .Inner, did I got that wrong ?

Also, what happens for more than one nesting, like:

{{% row %}}
    {{< column >}}
        {{< figure src="calibration-after.jpg" />}}
    {{< /column >}}
{{% /row %}}

(This doesn’t work and I seem to have tested all possible combinations).

You’re already doing that by passing .Inner through .Page.RenderString.

As for deeply nested shortcodes… you’re on your own. Nested shortcodes are, for me, difficult to reason about; I avoid them when possible.

I use deep nesting only on the homepage, to define content blocks that comply with responsive layouts and breaking points. Basically, in that context, shortcodes become reusable HTML macros that prevent from copy-pasting lots of <div class="d-none d-lg-flex flex-none shadow-sm etc...."> in the Markdown content.

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