mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-23 21:53:09 +02:00
markup/tableofcontents: Cast Fragments.ToHTML args to int
Closes #13107
This commit is contained in:
committed by
Bjørn Erik Pedersen
parent
487bb96474
commit
b529859008
@@ -730,16 +730,15 @@ func (c *cachedContentScope) contentToC(ctx context.Context) (contentTableOfCont
|
|||||||
isHTML := cp.po.p.m.pageConfig.ContentMediaType.IsHTML()
|
isHTML := cp.po.p.m.pageConfig.ContentMediaType.IsHTML()
|
||||||
|
|
||||||
if !isHTML {
|
if !isHTML {
|
||||||
createAndSetToC := func(tocProvider converter.TableOfContentsProvider) {
|
createAndSetToC := func(tocProvider converter.TableOfContentsProvider) error {
|
||||||
cfg := p.s.ContentSpec.Converters.GetMarkupConfig()
|
cfg := p.s.ContentSpec.Converters.GetMarkupConfig()
|
||||||
ct.tableOfContents = tocProvider.TableOfContents()
|
ct.tableOfContents = tocProvider.TableOfContents()
|
||||||
ct.tableOfContentsHTML = template.HTML(
|
ct.tableOfContentsHTML, err = ct.tableOfContents.ToHTML(
|
||||||
ct.tableOfContents.ToHTML(
|
|
||||||
cfg.TableOfContents.StartLevel,
|
cfg.TableOfContents.StartLevel,
|
||||||
cfg.TableOfContents.EndLevel,
|
cfg.TableOfContents.EndLevel,
|
||||||
cfg.TableOfContents.Ordered,
|
cfg.TableOfContents.Ordered,
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the converter supports doing the parsing separately, we do that.
|
// If the converter supports doing the parsing separately, we do that.
|
||||||
|
@@ -208,8 +208,8 @@ unsafe = true
|
|||||||
|
|
||||||
toc, ok := b.(converter.TableOfContentsProvider)
|
toc, ok := b.(converter.TableOfContentsProvider)
|
||||||
c.Assert(ok, qt.Equals, true)
|
c.Assert(ok, qt.Equals, true)
|
||||||
tocString := string(toc.TableOfContents().ToHTML(1, 2, false))
|
tocHTML, _ := toc.TableOfContents().ToHTML(1, 2, false)
|
||||||
c.Assert(tocString, qt.Contains, "TableOfContents")
|
c.Assert(string(tocHTML), qt.Contains, "TableOfContents")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertAutoIDAsciiOnly(t *testing.T) {
|
func TestConvertAutoIDAsciiOnly(t *testing.T) {
|
||||||
|
@@ -14,11 +14,13 @@
|
|||||||
package tableofcontents
|
package tableofcontents
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/collections"
|
"github.com/gohugoio/hugo/common/collections"
|
||||||
|
"github.com/spf13/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Empty is an empty ToC.
|
// Empty is an empty ToC.
|
||||||
@@ -133,19 +135,30 @@ func (toc *Fragments) addAt(h *Heading, row, level int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToHTML renders the ToC as HTML.
|
// 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 {
|
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{
|
b := &tocBuilder{
|
||||||
s: strings.Builder{},
|
s: strings.Builder{},
|
||||||
h: toc.Headings,
|
h: toc.Headings,
|
||||||
startLevel: startLevel,
|
startLevel: iStartLevel,
|
||||||
stopLevel: stopLevel,
|
stopLevel: iStopLevel,
|
||||||
ordered: ordered,
|
ordered: ordered,
|
||||||
}
|
}
|
||||||
b.Build()
|
b.Build()
|
||||||
return template.HTML(b.s.String())
|
return template.HTML(b.s.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (toc Fragments) walk(fn func(*Heading)) {
|
func (toc Fragments) walk(fn func(*Heading)) {
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
package tableofcontents_test
|
package tableofcontents_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/hugolib"
|
"github.com/gohugoio/hugo/hugolib"
|
||||||
@@ -43,3 +44,80 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
|||||||
"heading-l5|5|Heading L5",
|
"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`)
|
||||||
|
}
|
||||||
|
@@ -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: "1-H3-1", ID: "1-h2-2"}, 0, 2)
|
||||||
toc.addAt(&Heading{Title: "Heading 2", ID: "h1-2"}, 1, 0)
|
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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#h1-1">Heading 1</a>
|
<li><a href="#h1-1">Heading 1</a>
|
||||||
@@ -62,7 +63,8 @@ func TestToc(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#h1-1">Heading 1</a></li>
|
<li><a href="#h1-1">Heading 1</a></li>
|
||||||
@@ -70,7 +72,8 @@ func TestToc(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#h1-1">Heading 1</a>
|
<li><a href="#h1-1">Heading 1</a>
|
||||||
@@ -83,7 +86,8 @@ func TestToc(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#1-h2-1">1-H2-1</a></li>
|
<li><a href="#1-h2-1">1-H2-1</a></li>
|
||||||
@@ -91,7 +95,8 @@ func TestToc(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ol>
|
<ol>
|
||||||
<li><a href="#h1-1">Heading 1</a>
|
<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)
|
||||||
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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -139,7 +145,8 @@ func TestTocMissingParent(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#h3">H3</a></li>
|
<li><a href="#h3">H3</a></li>
|
||||||
@@ -147,7 +154,8 @@ func TestTocMissingParent(t *testing.T) {
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>`, qt.Commentf(got))
|
</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">
|
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
|
||||||
<ol>
|
<ol>
|
||||||
<li>
|
<li>
|
||||||
|
Reference in New Issue
Block a user