|
|
@@ -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 { |
|
|
|