diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go index c3f06a592ba..5e8646b21c4 100644 --- a/hugolib/content_map_page.go +++ b/hugolib/content_map_page.go @@ -37,6 +37,7 @@ import ( "github.com/gohugoio/hugo/hugolib/doctree" "github.com/gohugoio/hugo/hugolib/pagesfromdata" "github.com/gohugoio/hugo/identity" + "github.com/gohugoio/hugo/lazy" "github.com/gohugoio/hugo/media" "github.com/gohugoio/hugo/output" "github.com/gohugoio/hugo/resources" @@ -109,6 +110,11 @@ type pageMap struct { cfg contentMapConfig } +// Invoked on rebuilds. +func (m *pageMap) Reset() { + m.pageReverseIndex.Reset() +} + // pageTrees holds pages and resources in a tree structure for all sites/languages. // Each site gets its own tree set via the Shape method. type pageTrees struct { @@ -958,9 +964,7 @@ type contentTreeReverseIndex struct { } func (c *contentTreeReverseIndex) Reset() { - c.contentTreeReverseIndexMap = &contentTreeReverseIndexMap{ - m: make(map[any]contentNodeI), - } + c.init.ResetWithLock().Unlock() } func (c *contentTreeReverseIndex) Get(key any) contentNodeI { @@ -972,7 +976,7 @@ func (c *contentTreeReverseIndex) Get(key any) contentNodeI { } type contentTreeReverseIndexMap struct { - init sync.Once + init lazy.OnceMore m map[any]contentNodeI } diff --git a/hugolib/rendershortcodes_test.go b/hugolib/rendershortcodes_test.go index 9a31b6536dc..0eebf46eb3e 100644 --- a/hugolib/rendershortcodes_test.go +++ b/hugolib/rendershortcodes_test.go @@ -445,3 +445,38 @@ code_p3 b.AssertNoRenderShortcodesArtifacts() b.AssertFileContentEquals("public/p1/index.html", "
Content p1 id-100.
\ncodep2
Foo.\n
\ncode_p3_edited
\ncode_p1
code_p1_2
code_p1_3
")
}
+
+// Issue 13004.
+func TestRenderShortcodesIncludeShortRefEdit(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+disableLiveReload = true
+disableKinds = ["home", "taxonomy", "term", "section", "rss", "sitemap", "robotsTXT", "404"]
+-- content/first/p1.md --
+---
+title: "p1"
+---
+## p1-h1
+{{% include "p2" %}}
+-- content/second/p2.md --
+---
+title: "p2"
+---
+### p2-h1
+
+This is some **markup**.
+-- layouts/shortcodes/include.html --
+{{ $p := site.GetPage (.Get 0) -}}
+{{ $p.RenderShortcodes -}}
+-- layouts/_default/single.html --
+{{ .Content }}
+`
+ b := TestRunning(t, files)
+ b.AssertNoRenderShortcodesArtifacts()
+ b.AssertFileContentEquals("public/first/p1/index.html", "This is some markup.\n
\n") + b.EditFileReplaceAll("content/second/p2.md", "p2-h1", "p2-h1-edited").Build() + b.AssertNoRenderShortcodesArtifacts() + b.AssertFileContentEquals("public/first/p1/index.html", "This is some markup.\n
\n") +} diff --git a/hugolib/site.go b/hugolib/site.go index 24ee5dcc506..c5a4956e228 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -1351,6 +1351,7 @@ func (s *Site) getLanguagePermalinkLang(alwaysInSubDir bool) string { func (s *Site) resetBuildState(sourceChanged bool) { s.relatedDocsHandler = s.relatedDocsHandler.Clone() s.init.Reset() + s.pageMap.Reset() } func (s *Site) errorCollator(results <-chan error, errs chan<- error) { diff --git a/lazy/init.go b/lazy/init.go index 7b88a53518b..bef3867a9a0 100644 --- a/lazy/init.go +++ b/lazy/init.go @@ -36,7 +36,7 @@ type Init struct { prev *Init children []*Init - init onceMore + init OnceMore out any err error f func(context.Context) (any, error) diff --git a/lazy/once.go b/lazy/once.go index c6abcd88493..dac689df393 100644 --- a/lazy/once.go +++ b/lazy/once.go @@ -18,19 +18,19 @@ import ( "sync/atomic" ) -// onceMore is similar to sync.Once. +// OnceMore is similar to sync.Once. // // Additional features are: // * it can be reset, so the action can be repeated if needed // * it has methods to check if it's done or in progress -type onceMore struct { +type OnceMore struct { mu sync.Mutex lock uint32 done uint32 } -func (t *onceMore) Do(f func()) { +func (t *OnceMore) Do(f func()) { if atomic.LoadUint32(&t.done) == 1 { return } @@ -53,15 +53,15 @@ func (t *onceMore) Do(f func()) { f() } -func (t *onceMore) InProgress() bool { +func (t *OnceMore) InProgress() bool { return atomic.LoadUint32(&t.lock) == 1 } -func (t *onceMore) Done() bool { +func (t *OnceMore) Done() bool { return atomic.LoadUint32(&t.done) == 1 } -func (t *onceMore) ResetWithLock() *sync.Mutex { +func (t *OnceMore) ResetWithLock() *sync.Mutex { t.mu.Lock() defer atomic.StoreUint32(&t.done, 0) return &t.mu