var rendered []byte
- if strings.Contains(contentToRender, "{{") {
- // Probably a shortcode.
+ if pageparser.HasShortcode(contentToRender) {
+ // String contains a shortcode.
parsed, err := pageparser.ParseMain(strings.NewReader(contentToRender), pageparser.Config{})
if err != nil {
return "", err
`)
}
+
+func TestRenderStringWithShortcodeIssue10654(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- config.toml --
+timeout = '300ms'
+-- content/p1.md --
+---
+title: "P1"
+---
+{{< toc >}}
+
+## Heading 1
+
+{{< noop >}}
+ {{ not a shortcode
+{{< /noop >}}
+}
+-- layouts/shortcodes/noop.html --
+{{ .Inner | $.Page.RenderString }}
+-- layouts/shortcodes/toc.html --
+{{ .Page.TableOfContents }}
+-- layouts/_default/single.html --
+{{ .Content }}
+`
+
+ b := NewIntegrationTestBuilder(
+ IntegrationTestConfig{
+ T: t,
+ TxtarString: files,
+ },
+ ).Build()
+
+ b.AssertFileContent("public/p1/index.html", `TableOfContents`)
+}
"fmt"
"io"
"io/ioutil"
+ "regexp"
+ "strings"
"github.com/gohugoio/hugo/parser/metadecoders"
)
return true
}
+
+var hasShortcodeRe = regexp.MustCompile(`{{[%,<][^\/]`)
+
+// HasShortcode returns true if the given string contains a shortcode.
+func HasShortcode(s string) bool {
+ // Fast path for the common case.
+ if !strings.Contains(s, "{{") {
+ return false
+ }
+ return hasShortcodeRe.MatchString(s)
+}
c.Assert(IsProbablySourceOfItems([]byte(`{{< foo >}} `), items), qt.IsFalse)
c.Assert(IsProbablySourceOfItems([]byte(``), items), qt.IsFalse)
}
+
+func TestHasShortcode(t *testing.T) {
+ c := qt.New(t)
+
+ c.Assert(HasShortcode("{{< foo >}}"), qt.IsTrue)
+ c.Assert(HasShortcode("aSDasd SDasd aSD\n\nasdfadf{{% foo %}}\nasdf"), qt.IsTrue)
+ c.Assert(HasShortcode("{{</* foo */>}}"), qt.IsFalse)
+ c.Assert(HasShortcode("{{%/* foo */%}}"), qt.IsFalse)
+
+}
+
+func BenchmarkHasShortcode(b *testing.B) {
+ withShortcode := strings.Repeat("this is text", 30) + "{{< myshortcode >}}This is some inner content.{{< /myshortcode >}}" + strings.Repeat("this is text", 30)
+ withoutShortcode := strings.Repeat("this is text", 30) + "This is some inner content." + strings.Repeat("this is text", 30)
+ b.Run("Match", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ HasShortcode(withShortcode)
+ }
+ })
+
+ b.Run("NoMatch", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ HasShortcode(withoutShortcode)
+ }
+ })
+
+}