From 6d97ee711e834ad4a0d2aca44fafb042008a8429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 31 Aug 2024 17:25:15 +0200 Subject: [PATCH] Make all renderhook Text methods return template.HTML --- common/types/hstring/stringtypes.go | 18 ++++++++++++++++-- common/types/hstring/stringtypes_test.go | 4 ++-- hugolib/content_render_hooks_test.go | 4 ++-- hugolib/page__content.go | 2 +- markup/converter/hooks/hooks.go | 8 ++++---- markup/goldmark/blockquotes/blockquotes.go | 6 +++--- .../blockquotes_integration_test.go | 4 ++-- markup/goldmark/goldmark_integration_test.go | 12 ++++++------ markup/goldmark/render_hooks.go | 16 ++++++++-------- markup/goldmark/tables/tables.go | 2 +- .../goldmark/tables/tables_integration_test.go | 4 ++-- .../_default/_markup/render-link.html | 2 +- .../_default/_markup/render-table.html | 4 ++-- 13 files changed, 50 insertions(+), 36 deletions(-) diff --git a/common/types/hstring/stringtypes.go b/common/types/hstring/stringtypes.go index 5e8e3a23dbf..05977ddceeb 100644 --- a/common/types/hstring/stringtypes.go +++ b/common/types/hstring/stringtypes.go @@ -13,8 +13,22 @@ package hstring -type RenderedString string +import ( + "html/template" -func (s RenderedString) String() string { + "github.com/gohugoio/hugo/common/types" +) + +var _ types.PrintableValueProvider = RenderedHTML("") + +// RenderedHTML is a string that represents rendered HTML. +// When printed in templates it will be rendered as template.HTML and considered safe. +type RenderedHTML string + +func (s RenderedHTML) String() string { return string(s) } + +func (s RenderedHTML) PrintableValue() any { + return template.HTML(s) +} diff --git a/common/types/hstring/stringtypes_test.go b/common/types/hstring/stringtypes_test.go index 2f1f865c8b5..75b7af13c25 100644 --- a/common/types/hstring/stringtypes_test.go +++ b/common/types/hstring/stringtypes_test.go @@ -25,6 +25,6 @@ func TestRenderedString(t *testing.T) { c := qt.New(t) // Validate that it will behave like a string in Hugo settings. - c.Assert(cast.ToString(RenderedString("Hugo")), qt.Equals, "Hugo") - c.Assert(template.HTML(RenderedString("Hugo")), qt.Equals, template.HTML("Hugo")) + c.Assert(cast.ToString(RenderedHTML("Hugo")), qt.Equals, "Hugo") + c.Assert(template.HTML(RenderedHTML("Hugo")), qt.Equals, template.HTML("Hugo")) } diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go index abe30576259..593d01da891 100644 --- a/hugolib/content_render_hooks_test.go +++ b/hugolib/content_render_hooks_test.go @@ -98,8 +98,8 @@ baseURL="https://example.org" P1: {{ $p.Content }} `, - "_default/_markup/render-link.html", `html-link: {{ .Destination | safeURL }}|Text: {{ .Text | safeHTML }}|Plain: {{ .PlainText | safeHTML }}`, - "_default/_markup/render-image.html", `html-image: {{ .Destination | safeURL }}|Text: {{ .Text | safeHTML }}|Plain: {{ .PlainText | safeHTML }}`, + "_default/_markup/render-link.html", `html-link: {{ .Destination | safeURL }}|Text: {{ .Text }}|Plain: {{ .PlainText | safeHTML }}`, + "_default/_markup/render-image.html", `html-image: {{ .Destination | safeURL }}|Text: {{ .Text }}|Plain: {{ .PlainText | safeHTML }}`, ) b.WithContent("p1.md", `--- diff --git a/hugolib/page__content.go b/hugolib/page__content.go index 30caebed0d9..31080b929ae 100644 --- a/hugolib/page__content.go +++ b/hugolib/page__content.go @@ -928,7 +928,7 @@ func (c *cachedContentScope) RenderString(ctx context.Context, args ...any) (tem contentToRenderv := args[sidx] - if _, ok := contentToRenderv.(hstring.RenderedString); ok { + if _, ok := contentToRenderv.(hstring.RenderedHTML); ok { // This content is already rendered, this is potentially // a infinite recursion. return "", errors.New("text is already rendered, repeating it may cause infinite recursion") diff --git a/markup/converter/hooks/hooks.go b/markup/converter/hooks/hooks.go index 9487fd0a710..0232b619f97 100644 --- a/markup/converter/hooks/hooks.go +++ b/markup/converter/hooks/hooks.go @@ -41,7 +41,7 @@ type LinkContext interface { Title() string // The rendered (HTML) text. - Text() hstring.RenderedString + Text() hstring.RenderedHTML // The plain variant of Text. PlainText() string @@ -100,7 +100,7 @@ type BlockquoteContext interface { // The blockquote text. // If type is "alert", this will be the alert text. - Text() hstring.RenderedString + Text() hstring.RenderedHTML /// Returns the blockquote type, one of "regular" and "alert". // Type "alert" indicates that this is a GitHub type alert. @@ -166,7 +166,7 @@ type HeadingContext interface { // Anchor is the HTML id assigned to the heading. Anchor() string // Text is the rendered (HTML) heading text, excluding the heading marker. - Text() hstring.RenderedString + Text() hstring.RenderedHTML // PlainText is the unrendered version of Text. PlainText() string @@ -213,7 +213,7 @@ const ( type GetRendererFunc func(t RendererType, id any) any type TableCell struct { - Text hstring.RenderedString + Text hstring.RenderedHTML Alignment string // left, center, or right } diff --git a/markup/goldmark/blockquotes/blockquotes.go b/markup/goldmark/blockquotes/blockquotes.go index a261ec4fe39..f68cccd06e7 100644 --- a/markup/goldmark/blockquotes/blockquotes.go +++ b/markup/goldmark/blockquotes/blockquotes.go @@ -95,7 +95,7 @@ func (r *htmlRenderer) renderBlockquote(w util.BufWriter, src []byte, node ast.N BaseContext: render.NewBaseContext(ctx, renderer, n, src, nil, ordinal), typ: typ, alertType: alertType, - text: hstring.RenderedString(text), + text: hstring.RenderedHTML(text), AttributesHolder: attributes.New(n.Attributes(), attributes.AttributesOwnerGeneral), } @@ -134,7 +134,7 @@ func (r *htmlRenderer) renderBlockquoteDefault( type blockquoteContext struct { hooks.BaseContext - text hstring.RenderedString + text hstring.RenderedHTML alertType string typ string @@ -149,7 +149,7 @@ func (c *blockquoteContext) AlertType() string { return c.alertType } -func (c *blockquoteContext) Text() hstring.RenderedString { +func (c *blockquoteContext) Text() hstring.RenderedHTML { return c.text } diff --git a/markup/goldmark/blockquotes/blockquotes_integration_test.go b/markup/goldmark/blockquotes/blockquotes_integration_test.go index e4447e5e9b4..f12600b4207 100644 --- a/markup/goldmark/blockquotes/blockquotes_integration_test.go +++ b/markup/goldmark/blockquotes/blockquotes_integration_test.go @@ -32,9 +32,9 @@ func TestBlockquoteHook(t *testing.T) { block = true title = true -- layouts/_default/_markup/render-blockquote.html -- -Blockquote: |{{ .Text | safeHTML }}|{{ .Type }}| +Blockquote: |{{ .Text }}|{{ .Type }}| -- layouts/_default/_markup/render-blockquote-alert.html -- -{{ $text := .Text | safeHTML }} +{{ $text := .Text }} Blockquote Alert: |{{ $text }}|{{ .Type }}| Blockquote Alert Attributes: |{{ $text }}|{{ .Attributes }}| Blockquote Alert Page: |{{ $text }}|{{ .Page.Title }}|{{ .PageInner.Title }}| diff --git a/markup/goldmark/goldmark_integration_test.go b/markup/goldmark/goldmark_integration_test.go index 19338310c02..c691435eee7 100644 --- a/markup/goldmark/goldmark_integration_test.go +++ b/markup/goldmark/goldmark_integration_test.go @@ -76,7 +76,7 @@ title: "p1" {{- range $k, $v := .Attributes -}} {{- printf " %s=%q" $k $v | safeHTMLAttr -}} {{- end -}} ->{{ .Text | safeHTML }} +>{{ .Text }} ` b := hugolib.Test(t, files) @@ -146,11 +146,11 @@ title: "p1" {{ .Content }} -- layouts/_default/_markup/render-heading.html -- - {{ .Text | safeHTML }} + {{ .Text }} # -- layouts/_default/_markup/render-link.html -- -{{ .Text | safeHTML }} +{{ .Text }} ` @@ -236,11 +236,11 @@ func BenchmarkRenderHooks(b *testing.B) { -- config.toml -- -- layouts/_default/_markup/render-heading.html -- - {{ .Text | safeHTML }} + {{ .Text }} # -- layouts/_default/_markup/render-link.html -- -{{ .Text | safeHTML }} +{{ .Text }} -- layouts/_default/single.html -- {{ .Content }} ` @@ -452,7 +452,7 @@ Link https procol: https://www.example.org if withHook { files += `-- layouts/_default/_markup/render-link.html -- -{{ .Text | safeHTML }}` +{{ .Text }}` } return hugolib.NewIntegrationTestBuilder( diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go index 790b2f4caa7..d72300434d9 100644 --- a/markup/goldmark/render_hooks.go +++ b/markup/goldmark/render_hooks.go @@ -52,7 +52,7 @@ type linkContext struct { pageInner any destination string title string - text hstring.RenderedString + text hstring.RenderedHTML plainText string *attributes.AttributesHolder } @@ -69,7 +69,7 @@ func (ctx linkContext) PageInner() any { return ctx.pageInner } -func (ctx linkContext) Text() hstring.RenderedString { +func (ctx linkContext) Text() hstring.RenderedHTML { return ctx.text } @@ -100,7 +100,7 @@ type headingContext struct { pageInner any level int anchor string - text hstring.RenderedString + text hstring.RenderedHTML plainText string *attributes.AttributesHolder } @@ -121,7 +121,7 @@ func (ctx headingContext) Anchor() string { return ctx.anchor } -func (ctx headingContext) Text() hstring.RenderedString { +func (ctx headingContext) Text() hstring.RenderedHTML { return ctx.text } @@ -199,7 +199,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N pageInner: pageInner, destination: string(n.Destination), title: string(n.Title), - text: hstring.RenderedString(text), + text: hstring.RenderedHTML(text), plainText: string(n.Text(source)), AttributesHolder: attributes.New(attrs, attributes.AttributesOwnerGeneral), }, @@ -288,7 +288,7 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No pageInner: pageInner, destination: string(n.Destination), title: string(n.Title), - text: hstring.RenderedString(text), + text: hstring.RenderedHTML(text), plainText: string(n.Text(source)), AttributesHolder: attributes.Empty, }, @@ -355,7 +355,7 @@ func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node as page: page, pageInner: pageInner, destination: url, - text: hstring.RenderedString(label), + text: hstring.RenderedHTML(label), plainText: label, AttributesHolder: attributes.Empty, }, @@ -442,7 +442,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast pageInner: pageInner, level: n.Level, anchor: string(anchor), - text: hstring.RenderedString(text), + text: hstring.RenderedHTML(text), plainText: string(n.Text(source)), AttributesHolder: attributes.New(n.Attributes(), attributes.AttributesOwnerGeneral), }, diff --git a/markup/goldmark/tables/tables.go b/markup/goldmark/tables/tables.go index 61c9b893f5e..943da974ea1 100644 --- a/markup/goldmark/tables/tables.go +++ b/markup/goldmark/tables/tables.go @@ -132,7 +132,7 @@ func (r *htmlRenderer) renderCell(w util.BufWriter, source []byte, node ast.Node alignment = "left" } - cell := hooks.TableCell{Text: hstring.RenderedString(text), Alignment: alignment} + cell := hooks.TableCell{Text: hstring.RenderedHTML(text), Alignment: alignment} if node.Parent().Kind() == gast.KindTableHeader { table.THead[len(table.THead)-1] = append(table.THead[len(table.THead)-1], cell) diff --git a/markup/goldmark/tables/tables_integration_test.go b/markup/goldmark/tables/tables_integration_test.go index 8055265c855..dadce5c81fe 100644 --- a/markup/goldmark/tables/tables_integration_test.go +++ b/markup/goldmark/tables/tables_integration_test.go @@ -32,7 +32,7 @@ title = true | Item | In Stock | Price | | :---------------- | :------: | ----: | | Python Hat | True | 23.99 | -| SQL Hat | True | 23.99 | +| SQL **Hat** | True | 23.99 | | Codecademy Tee | False | 19.99 | | Codecademy Hoodie | False | 42.99 | {.foo foo="bar"} @@ -61,7 +61,7 @@ Attributes: {{ .Attributes }}| b.AssertFileContent("public/p1/index.html", "Attributes: map[class:foo foo:bar]|", "table-0-thead: 0: 0: left: Item| 1: center: In Stock| 2: right: Price|$", - "table-0-tbody: 0: 0: left: Python Hat| 1: center: True| 2: right: 23.99| 1: 0: left: SQL Hat| 1: center: True| 2: right: 23.99| 2: 0: left: Codecademy Tee| 1: center: False| 2: right: 19.99| 3: 0: left: Codecademy Hoodie| 1: center: False| 2: right: 42.99|$", + "table-0-tbody: 0: 0: left: Python Hat| 1: center: True| 2: right: 23.99| 1: 0: left: SQL Hat| 1: center: True| 2: right: 23.99| 2: 0: left: Codecademy Tee| 1: center: False| 2: right: 19.99| 3: 0: left: Codecademy Hoodie| 1: center: False| 2: right: 42.99|$", ) b.AssertFileContent("public/p1/index.html", diff --git a/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html b/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html index daf3f11e1a7..f82158a2d5c 100644 --- a/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html +++ b/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html @@ -25,5 +25,5 @@ {{- printf " %s=%q" $k $v | safeHTMLAttr -}} {{- end -}} {{- end -}} - >{{ .Text | safeHTML }} + >{{ .Text }} {{- /**/ -}} diff --git a/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html b/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html index 307f0a5a350..a0b0cc34d4c 100644 --- a/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html +++ b/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html @@ -9,7 +9,7 @@ {{- range . }} - {{- .Text | safeHTML -}} + {{- .Text -}} {{- end }} @@ -20,7 +20,7 @@ {{- range . }} - {{- .Text | safeHTML -}} + {{- .Text -}} {{- end }}