Preserve HTML Text for link render hooks

The context now have two text methods:

* Text - rendered
* PlainText

Fixes #6629
This commit is contained in:
Bjørn Erik Pedersen 2019-12-18 17:23:09 +01:00
parent 1b785a7a6d
commit 00954c5d1f
5 changed files with 79 additions and 12 deletions

View file

@ -117,7 +117,10 @@ Title
: The title attribute. : The title attribute.
Text Text
: The link text. : The rendered (HTML) link text.
PlainText
: The plain variant of the above.
A Markdown example for a inline-style link with title: A Markdown example for a inline-style link with title:

View file

@ -213,6 +213,37 @@ P3: <p>P3. xml-link: https://www.example.org|</p>
} }
// https://github.com/gohugoio/hugo/issues/6629
func TestRenderLinkWithMarkupInText(t *testing.T) {
b := newTestSitesBuilder(t)
b.WithTemplates("index.html", `
{{ $p := site.GetPage "p1.md" }}
P1: {{ $p.Content }}
`,
"_default/_markup/render-link.html", `html-link: {{ .Destination | safeURL }}|Text: {{ .Text | safeHTML }}|Plain: {{ .PlainText | safeHTML }}`,
)
b.WithContent("p1.md", `---
title: "p1"
---
START: [**should be bold**](https://gohugo.io)END
Some regular **markup**.
`)
b.Build(BuildCfg{})
b.AssertFileContent("public/index.html", `
P1: <p>START: html-link: https://gohugo.io|Text: <strong>should be bold</strong>|Plain: should be boldEND</p>
<p>Some regular <strong>markup</strong>.</p>
`)
}
func TestRenderString(t *testing.T) { func TestRenderString(t *testing.T) {
b := newTestSitesBuilder(t) b := newTestSitesBuilder(t)

View file

@ -24,6 +24,7 @@ type LinkContext interface {
Destination() string Destination() string
Title() string Title() string
Text() string Text() string
PlainText() string
} }
type Render struct { type Render struct {

View file

@ -15,9 +15,9 @@
package goldmark package goldmark
import ( import (
"bufio"
"bytes" "bytes"
"fmt" "fmt"
"math/bits"
"path/filepath" "path/filepath"
"runtime/debug" "runtime/debug"
@ -162,8 +162,27 @@ func (c converterResult) GetIdentities() identity.Identities {
return c.ids return c.ids
} }
type bufWriter struct {
*bytes.Buffer
}
const maxInt = 1<<(bits.UintSize-1) - 1
func (b *bufWriter) Available() int {
return maxInt
}
func (b *bufWriter) Buffered() int {
return b.Len()
}
func (b *bufWriter) Flush() error {
return nil
}
type renderContext struct { type renderContext struct {
util.BufWriter *bufWriter
pos int
renderContextData renderContextData
} }
@ -205,7 +224,7 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
} }
}() }()
buf := &bytes.Buffer{} buf := &bufWriter{Buffer: &bytes.Buffer{}}
result = buf result = buf
pctx := newParserContext(ctx) pctx := newParserContext(ctx)
reader := text.NewReader(ctx.Src) reader := text.NewReader(ctx.Src)
@ -221,8 +240,8 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
ids: identity.NewManager(converterIdentity), ids: identity.NewManager(converterIdentity),
} }
w := renderContext{ w := &renderContext{
BufWriter: bufio.NewWriter(buf), bufWriter: buf,
renderContextData: rcx, renderContextData: rcx,
} }

View file

@ -43,6 +43,7 @@ type linkContext struct {
destination string destination string
title string title string
text string text string
plainText string
} }
func (ctx linkContext) Destination() string { func (ctx linkContext) Destination() string {
@ -61,6 +62,10 @@ func (ctx linkContext) Text() string {
return ctx.text return ctx.text
} }
func (ctx linkContext) PlainText() string {
return ctx.plainText
}
func (ctx linkContext) Title() string { func (ctx linkContext) Title() string {
return ctx.title return ctx.title
} }
@ -146,13 +151,16 @@ func (r *linkRenderer) renderImage(w util.BufWriter, source []byte, node ast.Nod
return ast.WalkContinue, nil return ast.WalkContinue, nil
} }
text := string(n.Text(source))
err := h.ImageRenderer.Render( err := h.ImageRenderer.Render(
w, w,
linkContext{ linkContext{
page: ctx.DocumentContext().Document, page: ctx.DocumentContext().Document,
destination: string(n.Destination), destination: string(n.Destination),
title: string(n.Title), title: string(n.Title),
text: string(n.Text(source)), text: text,
plainText: text,
}, },
) )
@ -166,7 +174,7 @@ func (r *linkRenderer) renderLink(w util.BufWriter, source []byte, node ast.Node
n := node.(*ast.Link) n := node.(*ast.Link)
var h *hooks.Render var h *hooks.Render
ctx, ok := w.(renderContextData) ctx, ok := w.(*renderContext)
if ok { if ok {
h = ctx.RenderContext().RenderHooks h = ctx.RenderContext().RenderHooks
ok = h != nil && h.LinkRenderer != nil ok = h != nil && h.LinkRenderer != nil
@ -176,24 +184,29 @@ func (r *linkRenderer) renderLink(w util.BufWriter, source []byte, node ast.Node
return r.renderDefaultLink(w, source, node, entering) return r.renderDefaultLink(w, source, node, entering)
} }
if !entering { if entering {
// Store the current pos so we can capture the rendered text.
ctx.pos = ctx.Buffer.Len()
return ast.WalkContinue, nil return ast.WalkContinue, nil
} }
text := ctx.Buffer.Bytes()[ctx.pos:]
ctx.Buffer.Truncate(ctx.pos)
err := h.LinkRenderer.Render( err := h.LinkRenderer.Render(
w, w,
linkContext{ linkContext{
page: ctx.DocumentContext().Document, page: ctx.DocumentContext().Document,
destination: string(n.Destination), destination: string(n.Destination),
title: string(n.Title), title: string(n.Title),
text: string(n.Text(source)), text: string(text),
plainText: string(n.Text(source)),
}, },
) )
ctx.AddIdentity(h.LinkRenderer.GetIdentity()) ctx.AddIdentity(h.LinkRenderer.GetIdentity())
// Do not render the inner text. return ast.WalkContinue, err
return ast.WalkSkipChildren, err
} }