From ee3d2bb1d3974584f47cde7c973fbd1ae1f512b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Thu, 15 Jul 2021 08:46:54 +0200 Subject: [PATCH] markup/goldmark: Support auto links in render hook Fixes #8755 --- hugolib/content_render_hooks_test.go | 11 ++++- markup/goldmark/convert_test.go | 13 +++++- markup/goldmark/render_hooks.go | 70 ++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go index 1d7a4f8e310..f1c27d51191 100644 --- a/hugolib/content_render_hooks_test.go +++ b/hugolib/content_render_hooks_test.go @@ -56,7 +56,6 @@ title: P1 b.AssertFileContent("public/p1/index.html", `Link First Link|PARTIAL1_EDITED PARTIAL2_EDITEDEND`) } - func TestRenderHooks(t *testing.T) { config := ` baseURL="https://example.org" @@ -110,6 +109,10 @@ title: Cool Page --- [First Link](https://www.google.com "Google's Homepage") + +https://bar.baz/ + + {{< myshortcode3 >}} @@ -209,7 +212,11 @@ title: No Template b.Assert(int(counters.contentRenderCounter), qt.Equals, 45) b.AssertFileContent("public/blog/p1/index.html", ` -

Cool Page|https://www.google.com|Title: Google's Homepage|Text: First Link|END

+Cool Page|https://www.google.com|Title: Google's Homepage|Text: First Link|END +Cool Page|https://foo.bar/|Title: |Text: https://foo.bar/|END +Cool Page|https://bar.baz/|Title: |Text: https://bar.baz/|END +Cool Page|mailto:fake@example.com|Title: |Text: fake@example.com|END +Cool Page|mailto:fake2@example.com|Title: |Text: mailto:fake2@example.com|END Text: Second SHORT3|

IMAGE: Cool Page||/images/Dragster.jpg|Title: image title|Text: Drag Racing|END

diff --git a/markup/goldmark/convert_test.go b/markup/goldmark/convert_test.go index 2b66a191003..6e6b0009f9e 100644 --- a/markup/goldmark/convert_test.go +++ b/markup/goldmark/convert_test.go @@ -14,6 +14,7 @@ package goldmark import ( + "fmt" "strings" "testing" @@ -59,6 +60,10 @@ https://github.com/gohugoio/hugo/issues/6528 [Live Demo here!](https://docuapi.netlify.com/) [I'm an inline-style link with title](https://www.google.com "Google's Homepage") + +https://bar.baz/ + + ## Code Fences @@ -132,8 +137,14 @@ description b := convert(c, mconf, content) got := string(b.Bytes()) + fmt.Println(got) + // Links - // c.Assert(got, qt.Contains, `Live Demo here!`) + c.Assert(got, qt.Contains, `Live Demo here!`) + c.Assert(got, qt.Contains, `https://foo.bar/`) + c.Assert(got, qt.Contains, `https://bar.baz/`) + c.Assert(got, qt.Contains, `fake@example.com`) + c.Assert(got, qt.Contains, `mailto:fake2@example.com

`) // Header IDs c.Assert(got, qt.Contains, `

Custom ID

`, qt.Commentf(got)) diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go index 5e0865a70b6..9c159f9cf35 100644 --- a/markup/goldmark/render_hooks.go +++ b/markup/goldmark/render_hooks.go @@ -15,6 +15,7 @@ package goldmark import ( "bytes" + "strings" "sync" "github.com/spf13/cast" @@ -134,6 +135,7 @@ func (r *hookedRenderer) SetOption(name renderer.OptionName, value interface{}) // RegisterFuncs implements NodeRenderer.RegisterFuncs. func (r *hookedRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) { reg.Register(ast.KindLink, r.renderLink) + reg.Register(ast.KindAutoLink, r.renderAutoLink) reg.Register(ast.KindImage, r.renderImage) reg.Register(ast.KindHeading, r.renderHeading) } @@ -307,6 +309,74 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No return ast.WalkContinue, err } +func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + if !entering { + return ast.WalkContinue, nil + } + + n := node.(*ast.AutoLink) + var h hooks.Renderers + + ctx, ok := w.(*renderContext) + if ok { + h = ctx.RenderContext().RenderHooks + ok = h.LinkRenderer != nil + } + + if !ok { + return r.renderDefaultAutoLink(w, source, node, entering) + } + + url := string(n.URL(source)) + label := string(n.Label(source)) + if n.AutoLinkType == ast.AutoLinkEmail && !strings.HasPrefix(strings.ToLower(url), "mailto:") { + url = "mailto:" + url + } + + err := h.LinkRenderer.RenderLink( + w, + linkContext{ + page: ctx.DocumentContext().Document, + destination: url, + text: label, + plainText: label, + }, + ) + + // TODO(bep) I have a working branch that fixes these rather confusing identity types, + // but for now it's important that it's not .GetIdentity() that's added here, + // to make sure we search the entire chain on changes. + ctx.AddIdentity(h.LinkRenderer) + + return ast.WalkContinue, err +} + +// Fall back to the default Goldmark render funcs. Method below borrowed from: +// https://github.com/yuin/goldmark/blob/5588d92a56fe1642791cf4aa8e9eae8227cfeecd/renderer/html/html.go#L439 +func (r *hookedRenderer) renderDefaultAutoLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { + n := node.(*ast.AutoLink) + if !entering { + return ast.WalkContinue, nil + } + _, _ = w.WriteString(`') + } else { + _, _ = w.WriteString(`">`) + } + _, _ = w.Write(util.EscapeHTML(label)) + _, _ = w.WriteString(``) + return ast.WalkContinue, nil +} + func (r *hookedRenderer) renderDefaultHeading(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { n := node.(*ast.Heading) if entering {