From 8e553dcdefe50ab534f1199c006ae7754e14bee5 Mon Sep 17 00:00:00 2001 From: Helder Pereira Date: Wed, 16 Sep 2020 23:02:35 +0100 Subject: markup/asciidocext: Add preserveTOC option --- markup/asciidocext/asciidocext_config/config.go | 2 + markup/asciidocext/convert.go | 14 +-- markup/asciidocext/convert_test.go | 131 ++++++++++++++++++++---- 3 files changed, 121 insertions(+), 26 deletions(-) (limited to 'markup') diff --git a/markup/asciidocext/asciidocext_config/config.go b/markup/asciidocext/asciidocext_config/config.go index 231946b3c..ac6e0cda4 100644 --- a/markup/asciidocext/asciidocext_config/config.go +++ b/markup/asciidocext/asciidocext_config/config.go @@ -27,6 +27,7 @@ var ( Trace: false, FailureLevel: "fatal", WorkingFolderCurrent: false, + PreserveTOC: false, } // CliDefault holds Asciidoctor CLI defaults (see https://asciidoctor.org/docs/user-manual/) @@ -86,4 +87,5 @@ type Config struct { Trace bool FailureLevel string WorkingFolderCurrent bool + PreserveTOC bool } diff --git a/markup/asciidocext/convert.go b/markup/asciidocext/convert.go index c337131d6..f3e451496 100644 --- a/markup/asciidocext/convert.go +++ b/markup/asciidocext/convert.go @@ -18,7 +18,6 @@ package asciidocext import ( "bytes" - "io" "os/exec" "path/filepath" @@ -64,7 +63,7 @@ type asciidocConverter struct { } func (a *asciidocConverter) Convert(ctx converter.RenderContext) (converter.Result, error) { - content, toc, err := extractTOC(a.getAsciidocContent(ctx.Src, a.ctx)) + content, toc, err := a.extractTOC(a.getAsciidocContent(ctx.Src, a.ctx)) if err != nil { return nil, err } @@ -204,7 +203,7 @@ func getAsciidoctorExecPath() string { // extractTOC extracts the toc from the given src html. // It returns the html without the TOC, and the TOC data -func extractTOC(src []byte) ([]byte, tableofcontents.Root, error) { +func (a *asciidocConverter) extractTOC(src []byte) ([]byte, tableofcontents.Root, error) { var buf bytes.Buffer buf.Write(src) node, err := html.Parse(&buf) @@ -219,7 +218,9 @@ func extractTOC(src []byte) ([]byte, tableofcontents.Root, error) { f = func(n *html.Node) bool { if n.Type == html.ElementNode && n.Data == "div" && attr(n, "id") == "toc" { toc = parseTOC(n) - n.Parent.RemoveChild(n) + if !a.cfg.MarkupConfig.AsciidocExt.PreserveTOC { + n.Parent.RemoveChild(n) + } return true } if n.FirstChild != nil { @@ -285,7 +286,7 @@ func parseTOC(doc *html.Node) tableofcontents.Root { f(n.NextSibling, row, level) } } - f(doc.FirstChild, 0, 0) + f(doc.FirstChild, -1, 0) return toc } @@ -300,9 +301,8 @@ func attr(node *html.Node, key string) string { func nodeContent(node *html.Node) string { var buf bytes.Buffer - w := io.Writer(&buf) for c := node.FirstChild; c != nil; c = c.NextSibling { - html.Render(w, c) + html.Render(&buf, c) } return buf.String() } diff --git a/markup/asciidocext/convert_test.go b/markup/asciidocext/convert_test.go index eb38d2d7b..0e7c93c45 100644 --- a/markup/asciidocext/convert_test.go +++ b/markup/asciidocext/convert_test.go @@ -277,11 +277,17 @@ func TestTableOfContents(t *testing.T) { t.Skip("asciidoctor not installed") } c := qt.New(t) - p, err := Provider.New(converter.ProviderConfig{Logger: loggers.NewErrorLogger()}) + mconf := markup_config.Default + p, err := Provider.New( + converter.ProviderConfig{ + MarkupConfig: mconf, + Logger: loggers.NewErrorLogger(), + }, + ) c.Assert(err, qt.IsNil) conv, err := p.New(converter.DocumentContext{}) c.Assert(err, qt.IsNil) - b, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: macro + r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: macro :toclevels: 4 toc::[] @@ -300,11 +306,52 @@ testContent == Section 2 `)}) c.Assert(err, qt.IsNil) - toc, ok := b.(converter.TableOfContentsProvider) + toc, ok := r.(converter.TableOfContentsProvider) c.Assert(ok, qt.Equals, true) - root := toc.TableOfContents() - c.Assert(root.ToHTML(2, 4, false), qt.Equals, "") - c.Assert(root.ToHTML(2, 3, false), qt.Equals, "") + expected := tableofcontents.Root{ + Headers: tableofcontents.Headers{ + { + ID: "", + Text: "", + Headers: tableofcontents.Headers{ + { + ID: "_introduction", + Text: "Introduction", + Headers: nil, + }, + { + ID: "_section_1", + Text: "Section 1", + Headers: tableofcontents.Headers{ + { + ID: "_section_1_1", + Text: "Section 1.1", + Headers: tableofcontents.Headers{ + { + ID: "_section_1_1_1", + Text: "Section 1.1.1", + Headers: nil, + }, + }, + }, + { + ID: "_section_1_2", + Text: "Section 1.2", + Headers: nil, + }, + }, + }, + { + ID: "_section_2", + Text: "Section 2", + Headers: nil, + }, + }, + }, + }, + } + c.Assert(toc.TableOfContents(), qt.DeepEquals, expected) + c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "
") } func TestTableOfContentsWithCode(t *testing.T) { @@ -322,26 +369,72 @@ func TestTableOfContentsWithCode(t *testing.T) { c.Assert(err, qt.IsNil) conv, err := p.New(converter.DocumentContext{}) c.Assert(err, qt.IsNil) - b, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: auto + r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: auto == Some ` + "`code`" + ` in the title `)}) c.Assert(err, qt.IsNil) - toc, ok := b.(converter.TableOfContentsProvider) + toc, ok := r.(converter.TableOfContentsProvider) + c.Assert(ok, qt.Equals, true) + expected := tableofcontents.Root{ + Headers: tableofcontents.Headers{ + { + ID: "", + Text: "", + Headers: tableofcontents.Headers{ + { + ID: "_some_code_in_the_title", + Text: "Some code in the title", + Headers: nil, + }, + }, + }, + }, + } + c.Assert(toc.TableOfContents(), qt.DeepEquals, expected) + c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "
") +} + +func TestTableOfContentsPreserveTOC(t *testing.T) { + if !Supports() { + t.Skip("asciidoctor not installed") + } + c := qt.New(t) + mconf := markup_config.Default + mconf.AsciidocExt.PreserveTOC = true + p, err := Provider.New( + converter.ProviderConfig{ + MarkupConfig: mconf, + Logger: loggers.NewErrorLogger(), + }, + ) + c.Assert(err, qt.IsNil) + conv, err := p.New(converter.DocumentContext{}) + c.Assert(err, qt.IsNil) + r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: +:idprefix: +:idseparator: - + +== Some title +`)}) + c.Assert(err, qt.IsNil) + toc, ok := r.(converter.TableOfContentsProvider) c.Assert(ok, qt.Equals, true) - expected := tableofcontents.Headers{ - {}, - { - ID: "", - Text: "", - Headers: tableofcontents.Headers{ - { - ID: "_some_code_in_the_title", - Text: "Some code in the title", - Headers: nil, + expected := tableofcontents.Root{ + Headers: tableofcontents.Headers{ + { + ID: "", + Text: "", + Headers: tableofcontents.Headers{ + { + ID: "some-title", + Text: "Some title", + Headers: nil, + }, }, }, }, } - c.Assert(toc.TableOfContents().Headers, qt.DeepEquals, expected) + c.Assert(toc.TableOfContents(), qt.DeepEquals, expected) + c.Assert(string(r.Bytes()), qt.Contains, "
") } -- cgit v1.2.3