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 {