markup/tableofcontents: Add config option for ordered list

This commit is contained in:
Gavin D. Howard 2019-12-11 23:48:40 -07:00 committed by Bjørn Erik Pedersen
parent 186a5ebfca
commit 4c804319f6
6 changed files with 68 additions and 13 deletions

View file

@ -70,4 +70,7 @@ startLevel
: The heading level, values starting at 1 (`h1`), to start render the table of contents. : The heading level, values starting at 1 (`h1`), to start render the table of contents.
endLevel endLevel
: The heading level, inclusive, to stop render the table of contents. : The heading level, inclusive, to stop render the table of contents.
ordered
: Whether or not to generate an ordered list instead of an unordered list.

View file

@ -1387,7 +1387,8 @@
}, },
"tableOfContents": { "tableOfContents": {
"startLevel": 2, "startLevel": 2,
"endLevel": 3 "endLevel": 3,
"ordered": false
}, },
"goldmark": { "goldmark": {
"renderer": { "renderer": {

View file

@ -292,7 +292,7 @@ func (p *pageContentOutput) TableOfContents() template.HTML {
p.p.s.initInit(p.initMain, p.p) p.p.s.initInit(p.initMain, p.p)
if tocProvider, ok := p.convertedResult.(converter.TableOfContentsProvider); ok { if tocProvider, ok := p.convertedResult.(converter.TableOfContentsProvider); ok {
cfg := p.p.s.ContentSpec.Converters.GetMarkupConfig() cfg := p.p.s.ContentSpec.Converters.GetMarkupConfig()
return template.HTML(tocProvider.TableOfContents().ToHTML(cfg.TableOfContents.StartLevel, cfg.TableOfContents.EndLevel)) return template.HTML(tocProvider.TableOfContents().ToHTML(cfg.TableOfContents.StartLevel, cfg.TableOfContents.EndLevel, cfg.TableOfContents.Ordered))
} }
return p.tableOfContents return p.tableOfContents
} }

View file

@ -58,7 +58,7 @@ And then some.
c.Assert(err, qt.IsNil) c.Assert(err, qt.IsNil)
b, err := conv.Convert(converter.RenderContext{Src: []byte(content), RenderTOC: true}) b, err := conv.Convert(converter.RenderContext{Src: []byte(content), RenderTOC: true})
c.Assert(err, qt.IsNil) c.Assert(err, qt.IsNil)
got := b.(converter.TableOfContentsProvider).TableOfContents().ToHTML(2, 3) got := b.(converter.TableOfContentsProvider).TableOfContents().ToHTML(2, 3, false)
c.Assert(got, qt.Equals, `<nav id="TableOfContents"> c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ul> <ul>
<li><a href="#first-h2---now-with-typography">First h2&mdash;now with typography!</a> <li><a href="#first-h2---now-with-typography">First h2&mdash;now with typography!</a>

View file

@ -62,12 +62,13 @@ func (toc *Root) AddAt(h Header, y, x int) {
} }
// ToHTML renders the ToC as HTML. // ToHTML renders the ToC as HTML.
func (toc Root) ToHTML(startLevel, stopLevel int) string { func (toc Root) ToHTML(startLevel, stopLevel int, ordered bool) string {
b := &tocBuilder{ b := &tocBuilder{
s: strings.Builder{}, s: strings.Builder{},
h: toc.Headers, h: toc.Headers,
startLevel: startLevel, startLevel: startLevel,
stopLevel: stopLevel, stopLevel: stopLevel,
ordered: ordered,
} }
b.Build() b.Build()
return b.s.String() return b.s.String()
@ -79,6 +80,7 @@ type tocBuilder struct {
startLevel int startLevel int
stopLevel int stopLevel int
ordered bool
} }
func (b *tocBuilder) Build() { func (b *tocBuilder) Build() {
@ -108,7 +110,11 @@ func (b *tocBuilder) writeHeaders(level, indent int, h Headers) {
if hasChildren { if hasChildren {
b.s.WriteString("\n") b.s.WriteString("\n")
b.indent(indent + 1) b.indent(indent + 1)
b.s.WriteString("<ul>\n") if b.ordered {
b.s.WriteString("<ol>\n")
} else {
b.s.WriteString("<ul>\n")
}
} }
for _, h := range h { for _, h := range h {
@ -117,7 +123,11 @@ func (b *tocBuilder) writeHeaders(level, indent int, h Headers) {
if hasChildren { if hasChildren {
b.indent(indent + 1) b.indent(indent + 1)
b.s.WriteString("</ul>") if b.ordered {
b.s.WriteString("</ol>")
} else {
b.s.WriteString("</ul>")
}
b.s.WriteString("\n") b.s.WriteString("\n")
b.indent(indent) b.indent(indent)
} }
@ -143,6 +153,7 @@ func (b *tocBuilder) indent(n int) {
var DefaultConfig = Config{ var DefaultConfig = Config{
StartLevel: 2, StartLevel: 2,
EndLevel: 3, EndLevel: 3,
Ordered: false,
} }
type Config struct { type Config struct {
@ -153,4 +164,7 @@ type Config struct {
// Heading end level, inclusive, to include in the table of contents. // Heading end level, inclusive, to include in the table of contents.
// Default is 3, a value of -1 will include everything. // Default is 3, a value of -1 will include everything.
EndLevel int EndLevel int
// Whether to produce a ordered list or not.
Ordered bool
} }

View file

@ -30,7 +30,7 @@ func TestToc(t *testing.T) {
toc.AddAt(Header{Text: "1-H3-1", ID: "1-h2-2"}, 0, 2) toc.AddAt(Header{Text: "1-H3-1", ID: "1-h2-2"}, 0, 2)
toc.AddAt(Header{Text: "Header 2", ID: "h1-2"}, 1, 0) toc.AddAt(Header{Text: "Header 2", ID: "h1-2"}, 1, 0)
got := toc.ToHTML(1, -1) got := toc.ToHTML(1, -1, false)
c.Assert(got, qt.Equals, `<nav id="TableOfContents"> c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ul> <ul>
<li><a href="#h1-1">Header 1</a> <li><a href="#h1-1">Header 1</a>
@ -47,7 +47,7 @@ func TestToc(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(1, 1) got = toc.ToHTML(1, 1, false)
c.Assert(got, qt.Equals, `<nav id="TableOfContents"> c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ul> <ul>
<li><a href="#h1-1">Header 1</a></li> <li><a href="#h1-1">Header 1</a></li>
@ -55,7 +55,7 @@ func TestToc(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(1, 2) got = toc.ToHTML(1, 2, false)
c.Assert(got, qt.Equals, `<nav id="TableOfContents"> c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ul> <ul>
<li><a href="#h1-1">Header 1</a> <li><a href="#h1-1">Header 1</a>
@ -68,7 +68,7 @@ func TestToc(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(2, 2) got = toc.ToHTML(2, 2, false)
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>
@ -76,6 +76,22 @@ func TestToc(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(1, -1, true)
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ol>
<li><a href="#h1-1">Header 1</a>
<ol>
<li><a href="#1-h2-1">1-H2-1</a></li>
<li><a href="#1-h2-2">1-H2-2</a>
<ol>
<li><a href="#1-h2-2">1-H3-1</a></li>
</ol>
</li>
</ol>
</li>
<li><a href="#h1-2">Header 2</a></li>
</ol>
</nav>`, qt.Commentf(got))
} }
func TestTocMissingParent(t *testing.T) { func TestTocMissingParent(t *testing.T) {
@ -87,7 +103,7 @@ func TestTocMissingParent(t *testing.T) {
toc.AddAt(Header{Text: "H3", ID: "h3"}, 1, 2) toc.AddAt(Header{Text: "H3", ID: "h3"}, 1, 2)
toc.AddAt(Header{Text: "H3", ID: "h3"}, 1, 2) toc.AddAt(Header{Text: "H3", ID: "h3"}, 1, 2)
got := toc.ToHTML(1, -1) got := toc.ToHTML(1, -1, false)
c.Assert(got, qt.Equals, `<nav id="TableOfContents"> c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ul> <ul>
<li> <li>
@ -108,7 +124,7 @@ func TestTocMissingParent(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(3, 3) got = toc.ToHTML(3, 3, false)
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>
@ -116,4 +132,25 @@ func TestTocMissingParent(t *testing.T) {
</ul> </ul>
</nav>`, qt.Commentf(got)) </nav>`, qt.Commentf(got))
got = toc.ToHTML(1, -1, true)
c.Assert(got, qt.Equals, `<nav id="TableOfContents">
<ol>
<li>
<ol>
<li><a href="#h2">H2</a></li>
</ol>
</li>
<li>
<ol>
<li>
<ol>
<li><a href="#h3">H3</a></li>
<li><a href="#h3">H3</a></li>
</ol>
</li>
</ol>
</li>
</ol>
</nav>`, qt.Commentf(got))
} }