]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Strip nested page context markers from standalone RenderShortcodes
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 7 Apr 2026 13:59:07 +0000 (15:59 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 7 Apr 2026 17:27:40 +0000 (19:27 +0200)
Fixes #14732

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
hugolib/integrationtest_builder.go
hugolib/page__content.go
hugolib/rendershortcodes_test.go
markup/goldmark/hugocontext/hugocontext.go

index d9f05990306e61baace87f52d2d4c3b546211aac..ee9919a75c4504e3c8995d909970f1f135be8c2e 100644 (file)
@@ -2,7 +2,6 @@ package hugolib
 
 import (
        "bytes"
-       "context"
        "encoding/base64"
        "errors"
        "fmt"
@@ -39,8 +38,8 @@ import (
        "github.com/gohugoio/hugo/hugofs/hglob"
        "github.com/gohugoio/hugo/hugolib/sitesmatrix"
        "github.com/gohugoio/hugo/identity"
+       "github.com/gohugoio/hugo/media"
        "github.com/spf13/afero"
-       "github.com/spf13/cast"
        "golang.org/x/text/unicode/norm"
        "golang.org/x/tools/txtar"
 )
@@ -462,12 +461,20 @@ func (s *IntegrationTestBuilder) AssertFileContentExact(filename string, matches
 
 func (s *IntegrationTestBuilder) AssertNoRenderShortcodesArtifacts() {
        s.Helper()
-       for _, p := range s.H.Pages() {
-               content, err := p.Content(context.Background())
+       afero.Walk(s.fs.PublishDir, "", func(path string, info os.FileInfo, err error) error {
+               if err != nil || info.IsDir() {
+                       return err
+               }
+               ext := strings.TrimPrefix(filepath.Ext(path), ".")
+               if !s.H.Conf.GetConfigSection("mediaTypes").(media.Types).IsTextSuffix(ext) {
+                       return nil
+               }
+               content, err := afero.ReadFile(s.fs.PublishDir, path)
                s.Assert(err, qt.IsNil)
-               comment := qt.Commentf("Page: %s\n%s", p.Path(), content)
-               s.Assert(strings.Contains(cast.ToString(content), "__hugo_ctx"), qt.IsFalse, comment)
-       }
+               comment := qt.Commentf("File: %s\n%s", path, string(content))
+               s.Assert(strings.Contains(string(content), "__hugo_ctx"), qt.IsFalse, comment)
+               return nil
+       })
 }
 
 type IntegrationTestImageHelper struct {
index 7377936f30935c4f8ec4aaae52adbf6ae23053fb..be1f5f396711f425e13ad274762ae99b1a44bbc4 100644 (file)
@@ -1109,6 +1109,10 @@ func (c *cachedContentScope) RenderShortcodes(ctx context.Context) (template.HTM
                return template.HTML(hugocontext.Wrap(cc, pco.po.p.pid)), nil
        }
 
+       // Strip any Hugo context markers from nested RenderShortcodes calls
+       // that won't be processed by Goldmark.
+       cc = hugocontext.Strip(cc)
+
        return helpers.BytesToHTML(cc), nil
 }
 
index e952e258f4a17c0f4fe86d82a291f5a6d52e4d70..6ef7dfdeff9f86c406a42e7b2923d9126e4090e0 100644 (file)
@@ -521,3 +521,34 @@ not emphasized
                "<p>a</p>\n<p><em>emphasized</em></p>\n<p>not emphasized</p>\n<p>b</p>\n",
        )
 }
+
+// Issue 14732.
+func TestRenderShortcodesStandalone(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['section','rss','sitemap','taxonomy','term']
+-- layouts/all.html --
+RenderShortcodes: {{ .RenderShortcodes }}|
+-- layouts/_shortcodes/headings.html --
+## Heading 1
+### Heading 2
+{{ $p := site.GetPage "includeme" }}
+RenderShortcodes2: {{ $p.RenderShortcodes }}|
+-- content/p1.md --
+---
+title: "p1"
+---
+{{% headings "headings" %}}
+-- content/includeme.md --
+---
+title: "includeme"
+---
+## Heading 2
+`
+
+       b := Test(t, files)
+
+       b.AssertNoRenderShortcodesArtifacts()
+}
index 8afe64b7ff869ee7d4316b193381340c8c0217fe..5f6b5eea52135922b4a2802631ddc7c2e67c8292 100644 (file)
@@ -104,6 +104,14 @@ var (
        hugoCtxRe           = regexp.MustCompile(`{{__hugo_ctx( pid=\d+)?/?}}\n?`)
 )
 
+// Strip strips any Hugo context markers from b.
+func Strip(b []byte) []byte {
+       if !bytes.Contains(b, hugoCtxPrefix) {
+               return b
+       }
+       return hugoCtxRe.ReplaceAll(b, nil)
+}
+
 var _ parser.InlineParser = (*hugoContextParser)(nil)
 
 type hugoContextParser struct{}