Shortcode param "override" when rendering from list instead of page; how to find correct scope(?)

I have a custom figure shortcode that resembles the built-in img shortcode, but adds a bunch or accessibility params.

Normally, I want my images to load lazy, so there is a param that looks in a bunch of different places before defaulting to lazy:

shortcodes/figure.html

{{- $loading := .Get "imgLoading" | default (.Page.Scratch.Get "imgLoading") | default .Page.Params.imgLoading | default "lazy" -}}

However, I also have a print-view (using paged.js) that essentially consolidates all the sections onto a single page by iterating over a range. (This iteration takes place in a dedicated shortcode.) In this case, I need all the images to load “eager” so that paged.js can calculate pagination.

I’ve tried several methods to communicate this override to my shortcode:

  • set imgLoading: eager in frontmatter of my print_version.html page
---
layout: single-print
title: "Print Publication"
imgLoading: eager
---
  • while iterating over the sections in the shortcode {{ range .Page.Parent.Sections }}, update Scratch: {{.Scratch.Set "imgLoading" "eager"}}
{{ range .Page.Parent.Sections }}
    {{ $sectionOffset = add $sectionOffset 1 }}
    <article id="section{{ $sectionOffset }}">

    {{.Scratch.Set "imgLoading" "eager"}}
    {{ .Render "list-print" }}
    </article>
{{ end }}

Regardless of how I set the value, I always see the default in the rendered print-view.

Is there a better way of doing this? I suspect that the issue might be related to inside-out rendering of shortcodes. They are indirectly nested; .Render will call the code that renders the nested .figure shortcode.

Context is context here :wink:

The dot COULD mean the current page. If you hand it over to the shortcode. Your little snipped does not show how that happens, so you need to cast a wider net for us to find the problem.

I would expect the following to have a proper value for this (inside of the shortcode):

{{ $imgloading := $.Page.Params.imgLoading | default "default value" }}

You would expect that $.Page is the current page, but I am not sure if that is the case. The docs start at $.Page.Params to access the params of the current page. If you need something outside of this then you would have to look into adding parameters to your shortcode.

My understanding is that the . is the current page. But given all the nesting, I’m not entirely sure what “current” means

From the top into the weeds:

print-version.md, the top-level page being rendered

---
noNav: true
layout: single-print
title: "Print Publication"
scrollspy: false
imgLoading: eager             <= attempt to set.Page.Params.imgLoading for shortcode
---

{{< print_version>}}

In print_version.html (shortcode)

{{ $sectionOffset = 0 }}
<div id="sectionContainer">
{{/* hit the main sections */}}
{{ range .Page.Parent.Sections }}
    {{ $curSection = . }}

    {{ $sectionOffset = add $sectionOffset 1 }}
    <article id="section{{ $sectionOffset }}">

    {{.Scratch.Set "imgLoading" "eager"}}  <= attempt to set .Section.Scratch.imgLoading for shortcode

    {{ .Render "list-print" }}                        <= bring in nested section using figure shortcode
    </article>
{{ end }}
</div>

In my section page, it simply content that calls the figure shortcode:

---
title: Filtering the Tables
---
lorem ipsim

<div class="text-center">  
{{<mcd-figure figNum="8" format="png"     <= this is the figure shortcode
alt="some alt text"
details-text="This figure shows....."
>}}  
</div>

And in mcd-figure (shortcode):

{{- $figNum := .Get "figNum" | default "???" -}}
{{- $format := .Get "format" | default "gif" -}}
{{- $loading := .Get "imgLoading" | default (.Page.Scratch.Get "imgLoading") | default .Page.Params.imgLoading | default "lazy" -}}   <= ALWAYS eval to "lazy"
{{- $src := .Get "src" | default (printf "fig%s.%s" $figNum $format) -}}

<figure class="figure">
    <img src="{{$imgPathRes}}" loading="{{$loading}}"
               [other attrs here]
    />
</figure>

The problem is probably here:

{{ range .Page.Parent.Sections }}

The dot here is in a shortcode template and is NOT the page context, but whatever the shortcode gives to you. You need to add the info explicitly:

{{< shortcode param1="value1" param2="value2" >}}

and then access them via .Get "param1" in the shortcode. Or you define a frontmatter parameter, that is accessed via $.Page.Params.VARIABLE and then you get the page somehow from that. I checked my own shortcodes just now and have no sample where I need access to the full page from within the shortcode, so I never came across your issue… If you can solve it via parameters or frontmatter the above would be the way. Maybe someone else has an idea…