diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2021-07-15 08:46:54 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2021-07-15 10:14:52 +0200 |
commit | ee3d2bb1d3974584f47cde7c973fbd1ae1f512b6 (patch) | |
tree | 6ce5324b0e5f935cd1834c514495c3eb7cc5dc60 /markup/goldmark/render_hooks.go | |
parent | eb2a500367780b07d67c301ce7c866e6b67aa687 (diff) |
markup/goldmark: Support auto links in render hook
Fixes #8755
Diffstat (limited to 'markup/goldmark/render_hooks.go')
-rw-r--r-- | markup/goldmark/render_hooks.go | 70 |
1 files changed, 70 insertions, 0 deletions
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 { |