]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
markup/tableofcontents: Cast Fragments.ToHTML args to int
authorJoe Mooring <joe.mooring@veriphor.com>
Wed, 4 Dec 2024 17:21:21 +0000 (09:21 -0800)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 4 Dec 2024 20:37:06 +0000 (21:37 +0100)
Closes #13107

hugolib/page__content.go
markup/goldmark/convert_test.go
markup/tableofcontents/tableofcontents.go
markup/tableofcontents/tableofcontents_integration_test.go
markup/tableofcontents/tableofcontents_test.go

index b5527a281037a7290041ddc99707611842dbbc39..f7579f182f8477732c2117ee0af7e7fc595c7f65 100644 (file)
@@ -730,16 +730,15 @@ func (c *cachedContentScope) contentToC(ctx context.Context) (contentTableOfCont
                isHTML := cp.po.p.m.pageConfig.ContentMediaType.IsHTML()
 
                if !isHTML {
-                       createAndSetToC := func(tocProvider converter.TableOfContentsProvider) {
+                       createAndSetToC := func(tocProvider converter.TableOfContentsProvider) error {
                                cfg := p.s.ContentSpec.Converters.GetMarkupConfig()
                                ct.tableOfContents = tocProvider.TableOfContents()
-                               ct.tableOfContentsHTML = template.HTML(
-                                       ct.tableOfContents.ToHTML(
-                                               cfg.TableOfContents.StartLevel,
-                                               cfg.TableOfContents.EndLevel,
-                                               cfg.TableOfContents.Ordered,
-                                       ),
+                               ct.tableOfContentsHTML, err = ct.tableOfContents.ToHTML(
+                                       cfg.TableOfContents.StartLevel,
+                                       cfg.TableOfContents.EndLevel,
+                                       cfg.TableOfContents.Ordered,
                                )
+                               return err
                        }
 
                        // If the converter supports doing the parsing separately, we do that.
index 6048bce397ac3888b25849aa9f41f7837650a34c..a35441affe1166ff6b1b7263b18ab0bda15969a9 100644 (file)
@@ -208,8 +208,8 @@ unsafe = true
 
        toc, ok := b.(converter.TableOfContentsProvider)
        c.Assert(ok, qt.Equals, true)
-       tocString := string(toc.TableOfContents().ToHTML(1, 2, false))
-       c.Assert(tocString, qt.Contains, "TableOfContents")
+       tocHTML, _ := toc.TableOfContents().ToHTML(1, 2, false)
+       c.Assert(string(tocHTML), qt.Contains, "TableOfContents")
 }
 
 func TestConvertAutoIDAsciiOnly(t *testing.T) {
index 49a9cdeb79c205121349a0e7c8966a7b4cdac58d..560e421b7e837f72343100731fd01579002fba8d 100644 (file)
 package tableofcontents
 
 import (
+       "fmt"
        "html/template"
        "sort"
        "strings"
 
        "github.com/gohugoio/hugo/common/collections"
+       "github.com/spf13/cast"
 )
 
 // Empty is an empty ToC.
@@ -133,19 +135,30 @@ func (toc *Fragments) addAt(h *Heading, row, level int) {
 }
 
 // ToHTML renders the ToC as HTML.
-func (toc *Fragments) ToHTML(startLevel, stopLevel int, ordered bool) template.HTML {
+func (toc *Fragments) ToHTML(startLevel, stopLevel any, ordered bool) (template.HTML, error) {
        if toc == nil {
-               return ""
+               return "", nil
        }
+
+       iStartLevel, err := cast.ToIntE(startLevel)
+       if err != nil {
+               return "", fmt.Errorf("startLevel: %w", err)
+       }
+
+       iStopLevel, err := cast.ToIntE(stopLevel)
+       if err != nil {
+               return "", fmt.Errorf("stopLevel: %w", err)
+       }
+
        b := &tocBuilder{
                s:          strings.Builder{},
                h:          toc.Headings,
-               startLevel: startLevel,
-               stopLevel:  stopLevel,
+               startLevel: iStartLevel,
+               stopLevel:  iStopLevel,
                ordered:    ordered,
        }
        b.Build()
-       return template.HTML(b.s.String())
+       return template.HTML(b.s.String()), nil
 }
 
 func (toc Fragments) walk(fn func(*Heading)) {
index 87a7c010854797a3b6194de839ef4d59d1497889..e6ae03ce2d3d64c3e12f1c2df6f36f2a878811fd 100644 (file)
@@ -14,6 +14,7 @@
 package tableofcontents_test
 
 import (
+       "strings"
        "testing"
 
        "github.com/gohugoio/hugo/hugolib"
@@ -43,3 +44,80 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
                "heading-l5|5|Heading L5",
        )
 }
+
+// Issue #13107
+func TestToHTMLArgTypes(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['home','section','rss','sitemap','taxonomy','term']
+-- layouts/_default/single.html --
+{{ .Fragments.ToHTML .Params.toc.startLevel .Params.toc.endLevel false }}
+-- content/json.md --
+{
+  "title": "json",
+  "params": {
+    "toc": {
+      "startLevel": 2,
+      "endLevel": 4
+    }
+  }
+}
+CONTENT
+-- content/toml.md --
++++
+title = 'toml'
+[params.toc]
+startLevel = 2
+endLevel = 4
++++
+CONTENT
+-- content/yaml.md --
+---
+title: yaml
+params:
+  toc:
+    startLevel: 2
+    endLevel: 4
+---
+CONTENT
+`
+
+       content := `
+# Level One
+## Level Two
+### Level Three
+#### Level Four
+##### Level Five
+###### Level Six
+       `
+
+       want := `
+<nav id="TableOfContents">
+  <ul>
+    <li><a href="#level-two">Level Two</a>
+      <ul>
+        <li><a href="#level-three">Level Three</a>
+          <ul>
+            <li><a href="#level-four">Level Four</a></li>
+          </ul>
+        </li>
+      </ul>
+    </li>
+  </ul>
+</nav>
+`
+
+       files = strings.ReplaceAll(files, "CONTENT", content)
+
+       b := hugolib.Test(t, files)
+       b.AssertFileContentEquals("public/json/index.html", strings.TrimSpace(want))
+       b.AssertFileContentEquals("public/toml/index.html", strings.TrimSpace(want))
+       b.AssertFileContentEquals("public/yaml/index.html", strings.TrimSpace(want))
+
+       files = strings.ReplaceAll(files, `2`, `"x"`)
+
+       b, _ = hugolib.TestE(t, files)
+       b.AssertLogMatches(`error calling ToHTML: startLevel: unable to cast "x" of type string`)
+}
index 3af9c4eb664418a8613419babf8ab822352f185b..9ec7ec293aebfca5330d171163030ce5675b1e72 100644 (file)
@@ -45,7 +45,8 @@ func TestToc(t *testing.T) {
        toc.addAt(&Heading{Title: "1-H3-1", ID: "1-h2-2"}, 0, 2)
        toc.addAt(&Heading{Title: "Heading 2", ID: "h1-2"}, 1, 0)
 
-       got := string(toc.ToHTML(1, -1, false))
+       tocHTML, _ := toc.ToHTML(1, -1, false)
+       got := string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li><a href="#h1-1">Heading 1</a>
@@ -62,7 +63,8 @@ func TestToc(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(1, 1, false))
+       tocHTML, _ = toc.ToHTML(1, 1, false)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li><a href="#h1-1">Heading 1</a></li>
@@ -70,7 +72,8 @@ func TestToc(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(1, 2, false))
+       tocHTML, _ = toc.ToHTML(1, 2, false)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li><a href="#h1-1">Heading 1</a>
@@ -83,7 +86,8 @@ func TestToc(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(2, 2, false))
+       tocHTML, _ = toc.ToHTML(2, 2, false)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li><a href="#1-h2-1">1-H2-1</a></li>
@@ -91,7 +95,8 @@ func TestToc(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(1, -1, true))
+       tocHTML, _ = toc.ToHTML(1, -1, true)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ol>
     <li><a href="#h1-1">Heading 1</a>
@@ -118,7 +123,8 @@ func TestTocMissingParent(t *testing.T) {
        toc.addAt(&Heading{Title: "H3", ID: "h3"}, 1, 2)
        toc.addAt(&Heading{Title: "H3", ID: "h3"}, 1, 2)
 
-       got := string(toc.ToHTML(1, -1, false))
+       tocHTML, _ := toc.ToHTML(1, -1, false)
+       got := string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li>
@@ -139,7 +145,8 @@ func TestTocMissingParent(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(3, 3, false))
+       tocHTML, _ = toc.ToHTML(3, 3, false)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ul>
     <li><a href="#h3">H3</a></li>
@@ -147,7 +154,8 @@ func TestTocMissingParent(t *testing.T) {
   </ul>
 </nav>`, qt.Commentf(got))
 
-       got = string(toc.ToHTML(1, -1, true))
+       tocHTML, _ = toc.ToHTML(1, -1, true)
+       got = string(tocHTML)
        c.Assert(got, qt.Equals, `<nav id="TableOfContents">
   <ol>
     <li>