diff options
Diffstat (limited to 'markup')
-rw-r--r-- | markup/goldmark/convert_test.go | 13 | ||||
-rw-r--r-- | markup/goldmark/render_hooks.go | 70 |
2 files changed, 82 insertions, 1 deletions
diff --git a/markup/goldmark/convert_test.go b/markup/goldmark/convert_test.go index 2b66a1910..6e6b0009f 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://foo.bar/> +https://bar.baz/ +<fake@example.com> +<mailto:fake2@example.com> ## 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, `<a href="https://docuapi.netlify.com/">Live Demo here!</a>`) + c.Assert(got, qt.Contains, `<a href="https://docuapi.netlify.com/">Live Demo here!</a>`) + c.Assert(got, qt.Contains, `<a href="https://foo.bar/">https://foo.bar/</a>`) + c.Assert(got, qt.Contains, `<a href="https://bar.baz/">https://bar.baz/</a>`) + c.Assert(got, qt.Contains, `<a href="mailto:fake@example.com">fake@example.com</a>`) + c.Assert(got, qt.Contains, `<a href="mailto:fake2@example.com">mailto:fake2@example.com</a></p>`) // Header IDs c.Assert(got, qt.Contains, `<h2 id="custom">Custom ID</h2>`, qt.Commentf(got)) diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go index 5e0865a70..9c159f9cf 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(`<a href="`) + url := n.URL(source) + label := n.Label(source) + if n.AutoLinkType == ast.AutoLinkEmail && !bytes.HasPrefix(bytes.ToLower(url), []byte("mailto:")) { + _, _ = w.WriteString("mailto:") + } + _, _ = w.Write(util.EscapeHTML(util.URLEscape(url, false))) + if n.Attributes() != nil { + _ = w.WriteByte('"') + html.RenderAttributes(w, n, html.LinkAttributeFilter) + _ = w.WriteByte('>') + } else { + _, _ = w.WriteString(`">`) + } + _, _ = w.Write(util.EscapeHTML(label)) + _, _ = w.WriteString(`</a>`) + 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 { |