From ca68abf0bc2fa003c2052143218f7b2ab195a46e Mon Sep 17 00:00:00 2001 From: satotake Date: Sun, 23 Feb 2020 02:06:30 +0900 Subject: [PATCH] Fix goldmark toc rendering Previously gordmark-based TOC renderes only `KindText` and `KindString` This commit expands target node with Goldmark's renderer I am not sure of what are expected results as TOC contents in some (rare) cases but Blackfriday's behaviours are fundamentally respected. For example, - image `[image text](link)` is rendered as `` tag - GFM AutoLink `gohugo.io` is rendered as text * Render AutoLink as tag as Blackfriday does Fixes #6736 Fixes #6809 --- hugolib/shortcode_test.go | 2 +- markup/goldmark/convert.go | 18 ++++++------ markup/goldmark/toc.go | 37 ++++++++++++++++++++---- 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 d57a0d66..d60bdd48 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]", - `
  • MARKDOWN DELIMITER: Hugo Rocks!
  • `, + `
  • MARKDOWN DELIMITER: Hugo Rocks!
  • `, } if enableInlineShortcodes { diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go index d4c35335..ffe9cd45 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 1753ede1..4e3e5aec 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 19928dd8..46444133 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. `, 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
    foo
    ", + "# *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, ``, 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, ``, qt.Commentf(got)) +} -- 2.30.2