]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Add site.Store and hugo.Store and Shortcode.Store
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 13 Nov 2024 10:07:32 +0000 (11:07 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 13 Nov 2024 11:41:16 +0000 (12:41 +0100)
Closes #13021

common/hugo/hugo.go
common/maps/scratch.go
hugolib/page_test.go
hugolib/shortcode.go
hugolib/site.go
resources/page/page.go
resources/page/site.go

index f2110394043203e89a107f740b779618e4f22971..dd43cf7b6687d2c6f95d36c036c468a18447b3b2 100644 (file)
@@ -33,6 +33,7 @@ import (
        "github.com/gohugoio/hugo/common/hcontext"
        "github.com/gohugoio/hugo/common/hexec"
        "github.com/gohugoio/hugo/common/loggers"
+       "github.com/gohugoio/hugo/common/maps"
        "github.com/gohugoio/hugo/hugofs/files"
 
        "github.com/spf13/afero"
@@ -55,6 +56,8 @@ var (
        vendorInfo string
 )
 
+var _ maps.StoreProvider = (*HugoInfo)(nil)
+
 // HugoInfo contains information about the current Hugo environment
 type HugoInfo struct {
        CommitHash string
@@ -72,6 +75,8 @@ type HugoInfo struct {
        conf ConfigProvider
        deps []*Dependency
 
+       store *maps.Scratch
+
        // Context gives access to some of the context scoped variables.
        Context Context
 }
@@ -116,6 +121,10 @@ func (i HugoInfo) Deps() []*Dependency {
        return i.deps
 }
 
+func (i HugoInfo) Store() *maps.Scratch {
+       return i.store
+}
+
 // Deprecated: Use hugo.IsMultihost instead.
 func (i HugoInfo) IsMultiHost() bool {
        Deprecate("hugo.IsMultiHost", "Use hugo.IsMultihost instead.", "v0.124.0")
@@ -185,6 +194,7 @@ func NewInfo(conf ConfigProvider, deps []*Dependency) HugoInfo {
                Environment: conf.Environment(),
                conf:        conf,
                deps:        deps,
+               store:       maps.NewScratch(),
                GoVersion:   goVersion,
        }
 }
index 6383772164a6db39cae6aa477fc82b4f17bad437..cf5231783a3ed7909fba698cd2b50587a66bb942 100644 (file)
@@ -22,7 +22,13 @@ import (
        "github.com/gohugoio/hugo/common/math"
 )
 
-// Scratch is a writable context used for stateful operations in Page/Node rendering.
+type StoreProvider interface {
+       // Store returns a Scratch that can be used to store temporary state.
+       // Store is not reset on server rebuilds.
+       Store() *Scratch
+}
+
+// Scratch is a writable context used for stateful build operations
 type Scratch struct {
        values map[string]any
        mu     sync.RWMutex
index bdd1be6f713073c02858f33f4eee3b181ab739d7..39a16d948bf44c4da632a3e5912399bb4a0a7a65 100644 (file)
@@ -1893,3 +1893,52 @@ func TestRenderWithoutArgument(t *testing.T) {
 
        b.Assert(err, qt.IsNotNil)
 }
+
+// Issue #13021
+func TestAllStores(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ["taxonomy", "term", "page", "section"]
+disableLiveReload = true
+-- content/_index.md --
+---
+title: "Home"
+---
+{{< s >}}
+-- layouts/shortcodes/s.html --
+{{ if not (.Store.Get "Shortcode") }}{{ .Store.Set "Shortcode" (printf "sh-%s" $.Page.Title) }}{{ end }}
+Shortcode: {{ .Store.Get "Shortcode" }}|
+-- layouts/index.html --
+{{ .Content }}
+{{ if not (.Store.Get "Page") }}{{ .Store.Set "Page" (printf "p-%s" $.Title) }}{{ end }}
+{{ if not (hugo.Store.Get "Hugo") }}{{ hugo.Store.Set "Hugo" (printf "h-%s" $.Title) }}{{ end }}
+{{ if not (site.Store.Get "Site") }}{{ site.Store.Set "Site" (printf "s-%s" $.Title) }}{{ end }}
+Page: {{ .Store.Get "Page" }}|
+Hugo: {{ hugo.Store.Get "Hugo" }}|
+Site: {{ site.Store.Get "Site" }}|
+`
+
+       b := TestRunning(t, files)
+
+       b.AssertFileContent("public/index.html",
+               `
+Shortcode: sh-Home|
+Page: p-Home|
+Site: s-Home|
+Hugo: h-Home|
+`,
+       )
+
+       b.EditFileReplaceAll("content/_index.md", "Home", "Homer").Build()
+
+       b.AssertFileContent("public/index.html",
+               `
+Shortcode: sh-Homer|
+Page: p-Homer|
+Site: s-Home|
+Hugo: h-Home|
+`,
+       )
+}
index 8a478c9df8f45ba3a0357924bfc5abde825bfef5..69e891adbf7619fbfc19d68fceb60437acaea080 100644 (file)
@@ -43,9 +43,10 @@ import (
 )
 
 var (
-       _ urls.RefLinker  = (*ShortcodeWithPage)(nil)
-       _ types.Unwrapper = (*ShortcodeWithPage)(nil)
-       _ text.Positioner = (*ShortcodeWithPage)(nil)
+       _ urls.RefLinker     = (*ShortcodeWithPage)(nil)
+       _ types.Unwrapper    = (*ShortcodeWithPage)(nil)
+       _ text.Positioner    = (*ShortcodeWithPage)(nil)
+       _ maps.StoreProvider = (*ShortcodeWithPage)(nil)
 )
 
 // ShortcodeWithPage is the "." context in a shortcode template.
@@ -72,7 +73,7 @@ type ShortcodeWithPage struct {
        posOffset int
        pos       text.Position
 
-       scratch *maps.Scratch
+       store *maps.Scratch
 }
 
 // InnerDeindent returns the (potentially de-indented) inner content of the shortcode.
@@ -124,13 +125,19 @@ func (scp *ShortcodeWithPage) RelRef(args map[string]any) (string, error) {
        return scp.Page.RelRefFrom(args, scp)
 }
 
+// Store returns this shortcode's Store.
+func (scp *ShortcodeWithPage) Store() *maps.Scratch {
+       if scp.store == nil {
+               scp.store = maps.NewScratch()
+       }
+       return scp.store
+}
+
 // Scratch returns a scratch-pad scoped for this shortcode. This can be used
 // as a temporary storage for variables, counters etc.
+// Deprecated: Use Store instead. Note that from the templates this should be considered a "soft deprecation".
 func (scp *ShortcodeWithPage) Scratch() *maps.Scratch {
-       if scp.scratch == nil {
-               scp.scratch = maps.NewScratch()
-       }
-       return scp.scratch
+       return scp.Store()
 }
 
 // Get is a convenience method to look up shortcode parameters by its key.
@@ -399,7 +406,16 @@ func doRenderShortcode(
                hasVariants = hasVariants || more
        }
 
-       data := &ShortcodeWithPage{Ordinal: sc.ordinal, posOffset: sc.pos, indentation: sc.indentation, Params: sc.params, Page: newPageForShortcode(p), Parent: parent, Name: sc.name}
+       data := &ShortcodeWithPage{
+               Ordinal:     sc.ordinal,
+               posOffset:   sc.pos,
+               indentation: sc.indentation,
+               Params:      sc.params,
+               Page:        newPageForShortcode(p),
+               Parent:      parent,
+               Name:        sc.name,
+       }
+
        if sc.params != nil {
                data.IsNamedParams = reflect.TypeOf(sc.params).Kind() == reflect.Map
        }
index c5a4956e228d221cfaccc726f95134fd49144ef7..c434ff2b46d359d23be4f0b6395ecee43071dd6f 100644 (file)
@@ -95,6 +95,7 @@ type Site struct {
        language  *langs.Language
        languagei int
        pageMap   *pageMap
+       store     *maps.Scratch
 
        // The owning container.
        h *HugoSites
@@ -248,6 +249,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
                        language:           language,
                        languagei:          i,
                        frontmatterHandler: frontmatterHandler,
+                       store:              maps.NewScratch(),
                }
 
                if i == 0 {
@@ -614,6 +616,10 @@ func (s *Site) AllRegularPages() page.Pages {
        return s.h.RegularPages()
 }
 
+func (s *Site) Store() *maps.Scratch {
+       return s.store
+}
+
 func (s *Site) CheckReady() {
        if s.state != siteStateReady {
                panic("this method cannot be called before the site is fully initialized")
index ea7f4bf1bd70e21b756f11e38d225753d799fd55..acd4ce31354360c50099f8f2765163fdb2cccb3e 100644 (file)
@@ -331,9 +331,7 @@ type PageWithoutContent interface {
        // 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.
-       Store() *maps.Scratch
+       maps.StoreProvider
 
        RelatedKeywordsProvider
 
index 9f7871a020bedf818f4ac85adc18dd5cbe56ba1f..4a99982fdb88375c67a797d2a3740687008f4319 100644 (file)
@@ -135,6 +135,8 @@ type Site interface {
        // Deprecated: Use .Site.Home.OutputFormats.Get "rss" instead.
        RSSLink() template.URL
 
+       maps.StoreProvider
+
        // For internal use only.
        // This will panic if the site is not fully initialized.
        // This is typically used to inform the user in the content adapter templates,
@@ -327,6 +329,10 @@ func (s *siteWrapper) RSSLink() template.URL {
        return s.s.RSSLink()
 }
 
+func (s *siteWrapper) Store() *maps.Scratch {
+       return s.s.Store()
+}
+
 // For internal use only.
 func (s *siteWrapper) ForEeachIdentityByName(name string, f func(identity.Identity) bool) {
        s.s.(identity.ForEeachIdentityByNameProvider).ForEeachIdentityByName(name, f)
@@ -491,6 +497,10 @@ func (s testSite) RSSLink() template.URL {
        return ""
 }
 
+func (s testSite) Store() *maps.Scratch {
+       return maps.NewScratch()
+}
+
 func (s testSite) CheckReady() {
 }