Repository: gohugoio/hugo (language: go)

Issue:
Alias Page.Scratch to Page.Store 
This was prompted by:
<https://discourse.gohugo.io/t/strange-behavior-with-scratch-variable/52288>

That topic is not unique. I estimate this comes up every couple of months.

Deprecating `Page.Scratch` would generate a lot of noise given the number of templates that still use a `Page.Scratch` instead of a variable. This is a hangover from [v0.48.0](https://gohugo.io/news/0.48-relnotes/) and earlier where you could not assign a new value to a variable once it had been initialized. So aliasing one to the other seems like a kinder approach.

We would also update the `Page.Scratch` documentation, noting that you should use `Page.Store` instead and that `Page.Scratch` will probably be removed at some point in the future... sort of a soft deprecation.


The shortcode-scoped Scratch would remain as-is.


Discussion / hints:
Yea, the original motivation of adding a new method and not change the old one was to prevent breaking change, but I guess it will fix 99 issues for every breakage, so yea.

I'll assign it to myself, as there is some code cleaning/deletion to do as well.

Fix patch:
diff --git a/common/maps/scratch.go b/common/maps/scratch.go
index e9f412540b2..6383772164a 100644
--- a/common/maps/scratch.go
+++ b/common/maps/scratch.go
@@ -28,25 +28,6 @@ type Scratch struct {
 	mu     sync.RWMutex
 }
 
-// Scratcher provides a scratching service.
-type Scratcher interface {
-	// Scratch returns a "scratch pad" that can be used to store state.
-	Scratch() *Scratch
-}
-
-type scratcher struct {
-	s *Scratch
-}
-
-func (s scratcher) Scratch() *Scratch {
-	return s.s
-}
-
-// NewScratcher creates a new Scratcher.
-func NewScratcher() Scratcher {
-	return scratcher{s: NewScratch()}
-}
-
 // Add will, for single values, add (using the + operator) the addend to the existing addend (if found).
 // Supports numeric values and strings.
 //
diff --git a/hugolib/page.go b/hugolib/page.go
index 2bc1da044b4..e4c841966b2 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -38,7 +38,6 @@ import (
 	"github.com/gohugoio/hugo/tpl"
 
 	"github.com/gohugoio/hugo/common/herrors"
-	"github.com/gohugoio/hugo/common/maps"
 	"github.com/gohugoio/hugo/common/types"
 
 	"github.com/gohugoio/hugo/source"
@@ -149,7 +148,7 @@ func (p *pageState) Key() string {
 }
 
 func (p *pageState) resetBuildState() {
-	p.Scratcher = maps.NewScratcher()
+	// Nothing to do for now.
 }
 
 func (p *pageState) reusePageOutputContent() bool {
diff --git a/hugolib/page__common.go b/hugolib/page__common.go
index d3b0bd112dd..55465e214ec 100644
--- a/hugolib/page__common.go
+++ b/hugolib/page__common.go
@@ -56,7 +56,6 @@ type pageCommon struct {
 	store *maps.Scratch
 
 	// All of these represents the common parts of a page.Page
-	maps.Scratcher
 	navigation.PageMenusProvider
 	page.AuthorProvider
 	page.AlternativeOutputFormatsProvider
@@ -113,3 +112,8 @@ type pageCommon struct {
 func (p *pageCommon) Store() *maps.Scratch {
 	return p.store
 }
+
+// See issue 13016.
+func (p *pageCommon) Scratch() *maps.Scratch {
+	return p.Store()
+}
diff --git a/hugolib/page__new.go b/hugolib/page__new.go
index 9a4972d07fd..9a11fa8892b 100644
--- a/hugolib/page__new.go
+++ b/hugolib/page__new.go
@@ -184,7 +184,6 @@ func (h *HugoSites) doNewPage(m *pageMeta) (*pageState, *paths.Path, error) {
 			pageCommon: &pageCommon{
 				FileProvider:              m,
 				AuthorProvider:            m,
-				Scratcher:                 maps.NewScratcher(),
 				store:                     maps.NewScratch(),
 				Positioner:                page.NopPage,
 				InSectionPositioner:       page.NopPage,
diff --git a/resources/page/page.go b/resources/page/page.go
index 20525669c1e..ea7f4bf1bd7 100644
--- a/resources/page/page.go
+++ b/resources/page/page.go
@@ -327,7 +327,9 @@ type PageWithoutContent interface {
 
 	// Scratch returns a Scratch that can be used to store temporary state.
 	// Note that this Scratch gets reset on server rebuilds. See Store() for a variant that survives.
-	maps.Scratcher
+	// Scratch returns a "scratch pad" that can be used to store state.
+	// Deprecated: From Hugo v0.138.0 this is just an alias for Store.
+	Scratch() *maps.Scratch
 
 	// Store returns a Scratch that can be used to store temporary state.
 	// In contrast to Scratch(), this Scratch is not reset on server rebuilds.


Test patch:
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index 429ab26599a..bdd1be6f713 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -1688,6 +1688,32 @@ title: Scratch Me!
 	b.AssertFileContent("public/scratchme/index.html", "C: cv")
 }
 
+// Issue 13016.
+func TestScratchAliasToStore(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+disableKinds = ["taxonomy", "term", "page", "section"]
+disableLiveReload = true
+-- layouts/index.html --
+{{ .Scratch.Set "a" "b" }}
+{{ .Store.Set "c" "d" }}
+.Scratch eq .Store: {{ eq .Scratch .Store }}
+a: {{ .Store.Get "a" }}
+c: {{ .Scratch.Get "c" }}
+
+`
+
+	b := Test(t, files)
+
+	b.AssertFileContent("public/index.html",
+		".Scratch eq .Store: true",
+		"a: b",
+		"c: d",
+	)
+}
+
 func TestPageParam(t *testing.T) {
 	t.Parallel()