diff options
-rw-r--r-- | hugolib/shortcode_test.go | 2 | ||||
-rw-r--r-- | markup/goldmark/convert.go | 18 | ||||
-rw-r--r-- | markup/goldmark/toc.go | 37 | ||||
-rw-r--r-- | markup/goldmark/toc_test.go | 57 |
4 files changed, 99 insertions, 15 deletions
diff --git a/hugolib/shortcode_test.go b/hugolib/shortcode_test.go index d57a0d663..d60bdd48b 100644 --- a/hugolib/shortcode_test.go +++ b/hugolib/shortcode_test.go @@ -1136,7 +1136,7 @@ TOC: {{ .TableOfContents }} "NEW INLINE: W1: [1 2 3 4 5]", "INLINE IN INNER: Inner: W2: [1 2 3 4]", "REUSED INLINE IN INNER: Inner: W1: [1 2 3]", - `<li><a href="#markdown-delimiter-hugo-rocks">MARKDOWN DELIMITER: Hugo Rocks!</a></li>`, + `<li><a href="#markdown-delimiter-hugo-rocks">MARKDOWN DELIMITER: <strong>Hugo Rocks!</strong></a></li>`, } if enableInlineShortcodes { diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go index d4c353353..ffe9cd45a 100644 --- a/markup/goldmark/convert.go +++ b/markup/goldmark/convert.go @@ -81,15 +81,7 @@ func (c *goldmarkConverter) SanitizeAnchorName(s string) string { func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown { mcfg := pcfg.MarkupConfig cfg := pcfg.MarkupConfig.Goldmark - - var ( - extensions = []goldmark.Extender{ - newLinks(), - newTocExtension(), - } - rendererOptions []renderer.Option - parserOptions []parser.Option - ) + var rendererOptions []renderer.Option if cfg.Renderer.HardWraps { rendererOptions = append(rendererOptions, html.WithHardWraps()) @@ -103,6 +95,14 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown { rendererOptions = append(rendererOptions, html.WithUnsafe()) } + var ( + extensions = []goldmark.Extender{ + newLinks(), + newTocExtension(rendererOptions), + } + parserOptions []parser.Option + ) + if mcfg.Highlight.CodeFences { extensions = append(extensions, newHighlighting(mcfg.Highlight)) } diff --git a/markup/goldmark/toc.go b/markup/goldmark/toc.go index 1753ede1b..4e3e5aec2 100644 --- a/markup/goldmark/toc.go +++ b/markup/goldmark/toc.go @@ -21,6 +21,7 @@ import ( "github.com/yuin/goldmark" "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/parser" + "github.com/yuin/goldmark/renderer" "github.com/yuin/goldmark/text" "github.com/yuin/goldmark/util" ) @@ -31,6 +32,7 @@ var ( ) type tocTransformer struct { + r renderer.Renderer } func (t *tocTransformer) Transform(n *ast.Document, reader text.Reader, pc parser.Context) { @@ -79,8 +81,26 @@ func (t *tocTransformer) Transform(n *ast.Document, reader text.Reader, pc parse if found { header.ID = string(id.([]byte)) } - case ast.KindText, ast.KindString: - headingText.Write(n.Text(reader.Source())) + case + ast.KindCodeSpan, + ast.KindLink, + ast.KindImage, + ast.KindEmphasis: + err := t.r.Render(&headingText, reader.Source(), n) + if err != nil { + return s, err + } + + return ast.WalkSkipChildren, nil + case + ast.KindAutoLink, + ast.KindRawHTML, + ast.KindText, + ast.KindString: + err := t.r.Render(&headingText, reader.Source(), n) + if err != nil { + return s, err + } } return s, nil @@ -90,12 +110,19 @@ func (t *tocTransformer) Transform(n *ast.Document, reader text.Reader, pc parse } type tocExtension struct { + options []renderer.Option } -func newTocExtension() goldmark.Extender { - return &tocExtension{} +func newTocExtension(options []renderer.Option) goldmark.Extender { + return &tocExtension{ + options: options, + } } func (e *tocExtension) Extend(m goldmark.Markdown) { - m.Parser().AddOptions(parser.WithASTTransformers(util.Prioritized(&tocTransformer{}, 10))) + r := goldmark.DefaultRenderer() + r.AddOptions(e.options...) + m.Parser().AddOptions(parser.WithASTTransformers(util.Prioritized(&tocTransformer{ + r: r, + }, 10))) } diff --git a/markup/goldmark/toc_test.go b/markup/goldmark/toc_test.go index 19928dd8e..464441335 100644 --- a/markup/goldmark/toc_test.go +++ b/markup/goldmark/toc_test.go @@ -15,6 +15,7 @@ package goldmark import ( + "strings" "testing" "github.com/gohugoio/hugo/markup/markup_config" @@ -74,3 +75,59 @@ And then some. </ul> </nav>`, qt.Commentf(got)) } + +func TestEscapeToc(t *testing.T) { + c := qt.New(t) + + defaultConfig := markup_config.Default + + safeConfig := defaultConfig + unsafeConfig := defaultConfig + + safeConfig.Goldmark.Renderer.Unsafe = false + unsafeConfig.Goldmark.Renderer.Unsafe = true + + safeP, _ := Provider.New( + converter.ProviderConfig{ + MarkupConfig: safeConfig, + Logger: loggers.NewErrorLogger(), + }) + unsafeP, _ := Provider.New( + converter.ProviderConfig{ + MarkupConfig: unsafeConfig, + Logger: loggers.NewErrorLogger(), + }) + safeConv, _ := safeP.New(converter.DocumentContext{}) + unsafeConv, _ := unsafeP.New(converter.DocumentContext{}) + + content := strings.Join([]string{ + "# A < B & C > D", + "# A < B & C > D <div>foo</div>", + "# *EMPHASIS*", + "# `echo codeblock`", + }, "\n") + // content := "" + b, err := safeConv.Convert(converter.RenderContext{Src: []byte(content), RenderTOC: true}) + c.Assert(err, qt.IsNil) + got := b.(converter.TableOfContentsProvider).TableOfContents().ToHTML(1, 2, false) + c.Assert(got, qt.Equals, `<nav id="TableOfContents"> + <ul> + <li><a href="#a--b--c--d">A < B & C > D</a></li> + <li><a href="#a--b--c--d-divfoodiv">A < B & C > D <!-- raw HTML omitted -->foo<!-- raw HTML omitted --></a></li> + <li><a href="#emphasis"><em>EMPHASIS</em></a></li> + <li><a href="#echo-codeblock"><code>echo codeblock</code></a></li> + </ul> +</nav>`, qt.Commentf(got)) + + b, err = unsafeConv.Convert(converter.RenderContext{Src: []byte(content), RenderTOC: true}) + c.Assert(err, qt.IsNil) + got = b.(converter.TableOfContentsProvider).TableOfContents().ToHTML(1, 2, false) + c.Assert(got, qt.Equals, `<nav id="TableOfContents"> + <ul> + <li><a href="#a--b--c--d">A < B & C > D</a></li> + <li><a href="#a--b--c--d-divfoodiv">A < B & C > D <div>foo</div></a></li> + <li><a href="#emphasis"><em>EMPHASIS</em></a></li> + <li><a href="#echo-codeblock"><code>echo codeblock</code></a></li> + </ul> +</nav>`, qt.Commentf(got)) +} |