Strange behavior with Scratch variable

  1. The Scratch variable set empty in baseof.html
  2. use the .Page.Scratch.SetInMap to set the variable in _markup/render-image.html
  3. get the variable in the tail of baseof.html

behavior:

  1. The last single page doesn’t have the field that is set by _markup/render-image.html. The last page has image.
  2. The other page has the field, and the page has image.
  3. After live reload, the last single page has the field.
  4. If with --disableFastRender hasn’t any change after live reload

hugo version: v0.135.0 and v0.137.0

running command

hugo.exe server --noHTTPCache --minify --renderToMemory -v debug

code:
baseof.html

{{- partial "init.html" . -}}
.....
{{- /* Load JavaScript scripts and CSS */ -}}
{{- partial "assets.html" . -}}

init.html

...
{{- .Scratch.Set "this" dict -}}

assets.html

{{- printf "assets this %v" (.Scratch.Get "this") -}}
{{- if $params.lightgallery | and (.Scratch.Get "this").lightgallery -}}

render-image.html

{{- $lightgallery := .Page.Params.lightgallery | default site.Params.Page.lightgallery | default false -}}
{{- .Page.Scratch.SetInMap "this" "lightgallery" $lightgallery -}}
{{- fmt.Warnf "this %v" (.Page.Scratch.Get "this") -}}

Could you try to replace .Scratch with .Store and see if that changes things? I would say that .Store is the correct choice in 99% of the cases.

amazing it works, only replace {{- .Scratch.Set "this" dict -}}{{- .Store.Set "this" dict -}}.
It allows the initial variable by .Store , set and get by .Scratch?

Be consistent.

After testing, it has the same effect as removing this line. why?

I don’t understand your question. For this and your other active topic, I suggest you provide a minimal and complete example. No one wants to scan through tens of lines of code, and snippets aren’t helpful.

1 Like

.Scratch is comparable to a variable in programming and has a definition range. If .Scratch is used in different places, they can be different variables. That is why these effects exist in Hugo.

.Store is a global variable within a page. If possible, define it at the beginning of the page and then use it everywhere.

sorry, I need to set a variable in render-image, and then at the end of the page (in baseof.html), load the JavaScript file on demand based on this variable (load the js file when there is a picture). The loaded static file is in assets.html.

so I ADD the code in render-image.html

{{- $lightgallery := .Page.Params.lightgallery | default site.Params.Page.lightgallery | default false -}}
{{- .Page.Scratch.SetInMap "this" "lightgallery" $lightgallery -}} <--add code here

“init.html” file just initializes the variable

I modified the code here. When the variable set in render-image is true, JavaScript resources are loaded.

--{{- if $params.lightgallery -}}
++{{- if $params.lightgallery | and (.Scratch.Get "this").lightgallery -}}

I modified it as suggested and it worked. Then I also tested removing the code in init.html

mmh, according to the docs we have:

  • ShortCode.Scratch (obsoleted by newScratch and template variables)

    a scratchpad with scope “Shortcode”

  • collections.newScratch

    a locally (i assume block) scoped scratchpad. Called at the beginning of a Shortcode it’ should be the same as the above. simple template variables will do

  • Page.Scratch and Page.Store both are scratchpads with scope “Page”

    the latter one won’t be reset on sever rebuilds.

    and these two scratchpads are different. You cannot use .Scratch.Set and then .Store.Get to retrieve the value

In the next release .Page.Scratch is aliased to .Page.Store, and we’ll update the docs for .Page.Scratch, indicating that it will be removed in a future release and to use .Page.Store instead… sort of a soft deprecation. A hard deprecation would generate too much noise. See https://github.com/gohugoio/hugo/issues/13016 for more info.

@xiao_qing Although I haven’t dug into the details of your issue, let’s start by replacing all instances of page-scoped .Scratch to page-scoped .Store.

1 Like

After more debugging, the key point is a render sequence.
The image render hook executes before baseof.html, so the variable is reset by {{- .Scratch.Set "this" dict -}}. even if I replace Scratch to Store has the same result.

The image render is cached, If page content is rendered on homepage, will not render again. but the single page renders the remaining part, such as baseof.html.

Only the post on the homepage has this issue

I need to force rerender image.