From f0b612dcb1ce62addac0daa876a91b422c668640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 18 Dec 2019 17:23:09 +0100 Subject: [PATCH] Preserve HTML Text for link render hooks The context now have two text methods: * Text - rendered * PlainText Fixes #6629 --- .../getting-started/configuration-markup.md | 5 ++- hugolib/content_render_hooks_test.go | 31 +++++++++++++++++++ markup/converter/hooks/hooks.go | 1 + markup/goldmark/convert.go | 29 ++++++++++++++--- markup/goldmark/render_link.go | 25 +++++++++++---- 5 files changed, 79 insertions(+), 12 deletions(-) diff --git a/docs/content/en/getting-started/configuration-markup.md b/docs/content/en/getting-started/configuration-markup.md index b853af474ec..8c3633ce6eb 100644 --- a/docs/content/en/getting-started/configuration-markup.md +++ b/docs/content/en/getting-started/configuration-markup.md @@ -117,7 +117,10 @@ Title : The title attribute. 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: diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go index aa697220d1b..deccbff48f4 100644 --- a/hugolib/content_render_hooks_test.go +++ b/hugolib/content_render_hooks_test.go @@ -213,6 +213,37 @@ P3:

P3. xml-link: https://www.example.org|

} +// 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:

START: html-link: https://gohugo.io|Text: should be bold|Plain: should be boldEND

+

Some regular markup.

+`) + +} + func TestRenderString(t *testing.T) { b := newTestSitesBuilder(t) diff --git a/markup/converter/hooks/hooks.go b/markup/converter/hooks/hooks.go index 63beacc377e..5dfb09e2d40 100644 --- a/markup/converter/hooks/hooks.go +++ b/markup/converter/hooks/hooks.go @@ -24,6 +24,7 @@ type LinkContext interface { Destination() string Title() string Text() string + PlainText() string } type Render struct { diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go index 130f02a2fb7..af204125f03 100644 --- a/markup/goldmark/convert.go +++ b/markup/goldmark/convert.go @@ -15,9 +15,9 @@ package goldmark import ( - "bufio" "bytes" "fmt" + "math/bits" "path/filepath" "runtime/debug" @@ -162,8 +162,27 @@ func (c converterResult) GetIdentities() identity.Identities { 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 { - util.BufWriter + *bufWriter + pos int renderContextData } @@ -205,7 +224,7 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert } }() - buf := &bytes.Buffer{} + buf := &bufWriter{Buffer: &bytes.Buffer{}} result = buf pctx := newParserContext(ctx) reader := text.NewReader(ctx.Src) @@ -221,8 +240,8 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert ids: identity.NewManager(converterIdentity), } - w := renderContext{ - BufWriter: bufio.NewWriter(buf), + w := &renderContext{ + bufWriter: buf, renderContextData: rcx, } diff --git a/markup/goldmark/render_link.go b/markup/goldmark/render_link.go index 17ba5badacc..cefb786a69b 100644 --- a/markup/goldmark/render_link.go +++ b/markup/goldmark/render_link.go @@ -43,6 +43,7 @@ type linkContext struct { destination string title string text string + plainText string } func (ctx linkContext) Destination() string { @@ -61,6 +62,10 @@ func (ctx linkContext) Text() string { return ctx.text } +func (ctx linkContext) PlainText() string { + return ctx.plainText +} + func (ctx linkContext) Title() string { return ctx.title } @@ -146,13 +151,16 @@ func (r *linkRenderer) renderImage(w util.BufWriter, source []byte, node ast.Nod return ast.WalkContinue, nil } + text := string(n.Text(source)) + err := h.ImageRenderer.Render( w, linkContext{ page: ctx.DocumentContext().Document, destination: string(n.Destination), 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) var h *hooks.Render - ctx, ok := w.(renderContextData) + ctx, ok := w.(*renderContext) if ok { h = ctx.RenderContext().RenderHooks 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) } - if !entering { + if entering { + // Store the current pos so we can capture the rendered text. + ctx.pos = ctx.Buffer.Len() return ast.WalkContinue, nil } + text := ctx.Buffer.Bytes()[ctx.pos:] + ctx.Buffer.Truncate(ctx.pos) + err := h.LinkRenderer.Render( w, linkContext{ page: ctx.DocumentContext().Document, destination: string(n.Destination), title: string(n.Title), - text: string(n.Text(source)), + text: string(text), + plainText: string(n.Text(source)), }, ) ctx.AddIdentity(h.LinkRenderer.GetIdentity()) - // Do not render the inner text. - return ast.WalkSkipChildren, err + return ast.WalkContinue, err }