From 54398f8d572c689f9785d59e907fd910a23401b0 Mon Sep 17 00:00:00 2001 From: Joe Mooring Date: Wed, 4 Dec 2024 14:01:31 -0800 Subject: [PATCH] tpl/tplimpl: Escape Markdown attributes in render hooks and shortcodes --- hugolib/content_render_hooks_test.go | 10 ++-- .../tables/tables_integration_test.go | 15 ++--- .../_default/_markup/render-image.html | 13 +++-- .../_default/_markup/render-link.html | 17 ++---- .../_default/_markup/render-table.html | 2 +- .../templates/shortcodes/youtube.html | 57 ++++++++----------- tpl/tplimpl/render_hook_integration_test.go | 28 +++++++-- 7 files changed, 74 insertions(+), 68 deletions(-) diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go index 593d01da8..7f2c35032 100644 --- a/hugolib/content_render_hooks_test.go +++ b/hugolib/content_render_hooks_test.go @@ -90,7 +90,7 @@ baseURL="https://example.org" [markup.goldmark] [markup.goldmark.renderer] unsafe = true - + `) b.WithTemplates("index.html", ` @@ -223,16 +223,16 @@ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAA iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg== -- layouts/_default/single.html -- {{ .Title }}|{{ .Content }}|$ - + ` t.Run("Default multilingual", func(t *testing.T) { b := Test(t, files) b.AssertFileContent("public/nn/p1/index.html", - "p1|

P2

", "\"Pixel\"") + "p1|

P2

", "\"Pixel\"") b.AssertFileContent("public/en/p1/index.html", - "p1 en|

P2

", "\"Pixel\"") + "p1 en|

P2

", "\"Pixel\"") }) t.Run("Disabled", func(t *testing.T) { @@ -279,7 +279,7 @@ Image: ![alt-"<>&](/destination-"<> 'title-"<>&') if enabled { b.AssertFileContent("public/index.html", "Link: text-"<>&", - "img alt=\"alt-"<>&\" src=\"/destination-%22%3C%3E\" title=\"title-"<>&\">", + "img src=\"/destination-%22%3C%3E\" alt=\"alt-"<>&\" title=\"title-"<>&\">", "><script>", ) } else { diff --git a/markup/goldmark/tables/tables_integration_test.go b/markup/goldmark/tables/tables_integration_test.go index 85cf81c9d..36cf953ae 100644 --- a/markup/goldmark/tables/tables_integration_test.go +++ b/markup/goldmark/tables/tables_integration_test.go @@ -89,6 +89,12 @@ title = true | Codecademy Hoodie | False | 42.99 | {.foo} +## Table 2 + +a|b +---|--- +1|2 +{id="\">"} -- layouts/_default/single.html -- Summary: {{ .Summary }} @@ -97,7 +103,8 @@ Content: {{ .Content }} ` b := hugolib.Test(t, files) - b.AssertFileContent("public/p1/index.html", "") + b.AssertFileContent("public/p1/index.html", `
`) + b.AssertFileContent("public/p1/index.html", `
`) } // Issue 12811. @@ -166,14 +173,8 @@ title: "Home" | Codecademy Tee | False | 19.99 | | Codecademy Hoodie | False | 42.99 | - - - - -- layouts/index.xml -- Content: {{ .Content }} - - ` b := hugolib.Test(t, files) diff --git a/tpl/tplimpl/embedded/templates/_default/_markup/render-image.html b/tpl/tplimpl/embedded/templates/_default/_markup/render-image.html index 89514cb83..5c0f43835 100644 --- a/tpl/tplimpl/embedded/templates/_default/_markup/render-image.html +++ b/tpl/tplimpl/embedded/templates/_default/_markup/render-image.html @@ -1,7 +1,7 @@ {{- $u := urls.Parse .Destination -}} {{- $src := $u.String -}} {{- if not $u.IsAbs -}} - {{- $path := strings.TrimPrefix "./" $u.Path }} + {{- $path := strings.TrimPrefix "./" $u.Path -}} {{- with or (.PageInner.Resources.Get $path) (resources.Get $path) -}} {{- $src = .RelPermalink -}} {{- with $u.RawQuery -}} @@ -12,11 +12,12 @@ {{- end -}} {{- end -}} {{- end -}} -{{- $attributes := merge .Attributes (dict "alt" .Text "src" $src "title" (.Title | transform.HTMLEscape)) -}} -{{ .Text }} + {{- end -}} +> {{- /**/ -}} diff --git a/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html b/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html index f82158a2d..95e15aba4 100644 --- a/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html +++ b/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html @@ -1,9 +1,9 @@ {{- $u := urls.Parse .Destination -}} {{- $href := $u.String -}} -{{- if strings.HasPrefix $u.String "#" }} - {{- $href = printf "%s#%s" .PageInner.RelPermalink $u.Fragment }} -{{- else if not $u.IsAbs -}} - {{- $path := strings.TrimPrefix "./" $u.Path }} +{{- if strings.HasPrefix $u.String "#" -}} + {{- $href = printf "%s#%s" .PageInner.RelPermalink $u.Fragment -}} +{{- else if and $href (not $u.IsAbs) -}} + {{- $path := strings.TrimPrefix "./" $u.Path -}} {{- with or ($.PageInner.GetPage $path) ($.PageInner.Resources.Get $path) @@ -18,12 +18,5 @@ {{- end -}} {{- end -}} {{- end -}} -{{- $attributes := dict "href" $href "title" (.Title | transform.HTMLEscape) -}} -{{ .Text }} +{{ .Text }} {{- /**/ -}} diff --git a/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html b/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html index 5fdd79ddb..c43a72832 100644 --- a/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html +++ b/tpl/tplimpl/embedded/templates/_default/_markup/render-table.html @@ -1,7 +1,7 @@
diff --git a/tpl/tplimpl/embedded/templates/shortcodes/youtube.html b/tpl/tplimpl/embedded/templates/shortcodes/youtube.html index 93fa18197..441469d0a 100644 --- a/tpl/tplimpl/embedded/templates/shortcodes/youtube.html +++ b/tpl/tplimpl/embedded/templates/shortcodes/youtube.html @@ -26,7 +26,7 @@ Renders an embedded YouTube video. {{- if not $pc.Disable }} {{- with $id := or (.Get "id") (.Get 0) }} - {{/* Set defaults. */}} + {{- /* Set defaults. */}} {{- $allowFullScreen := "allowfullscreen" }} {{- $autoplay := 0 }} {{- $class := "" }} @@ -70,23 +70,8 @@ Renders an embedded YouTube video. {{- $start := or ($.Get "start") $start }} {{- $title := or ($.Get "title") $title }} - {{- /* Determine host. */}} - {{- $host := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" }} - - {{- /* Set styles. */}} - {{- $divStyle := "position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;" }} - {{- $iframeStyle := "position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" }} - {{- if $class }} - {{- $iframeStyle = "" }} - {{- end }} - - {{- /* Set class or style of wrapping div element. */}} - {{- $divClassOrStyle := printf "style=%q" $divStyle }} - {{- with $class }} - {{- $divClassOrStyle = printf "class=%q" $class }} - {{- end }} - {{- /* Define src attribute. */}} + {{- $host := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" }} {{- $src := printf "https://%s/embed/%s" $host $id }} {{- $params := dict "autoplay" $autoplay @@ -108,25 +93,33 @@ Renders an embedded YouTube video. {{- $src = printf "%s?%s" $src . }} {{- end }} + {{- /* Set div attributes. */}} + {{- $divStyle := "position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;" }} + {{- if $class }} + {{- $divStyle = "" }} + {{- end }} + {{- /* Set iframe attributes. */}} - {{- $iframeAttributes := dict - "allow" "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" - "allowfullscreen" $allowFullScreen - "loading" $loading - "referrerpolicy" "strict-origin-when-cross-origin" - "src" $src - "style" $iframeStyle - "title" $title - }} + {{- $iframeStyle := "position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" }} + {{- if $class }} + {{- $iframeStyle = "" }} + {{- end }} + {{- $allow := "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" }} + {{- $referrerpolicy := "strict-origin-when-cross-origin" }} {{- /* Render. */}} -
+
{{- else }} diff --git a/tpl/tplimpl/render_hook_integration_test.go b/tpl/tplimpl/render_hook_integration_test.go index b91358227..9f5f670a8 100644 --- a/tpl/tplimpl/render_hook_integration_test.go +++ b/tpl/tplimpl/render_hook_integration_test.go @@ -91,6 +91,9 @@ title: s1/p3 [430](p2/) [440](/s1/p2/) [450](../s1/p2/) + +// empty +[]() ` b := hugolib.Test(t, files) @@ -122,6 +125,8 @@ title: s1/p3 `430`, `440`, `450`, + + ``, ) b.AssertFileContent("public/s1/p2/index.html", @@ -148,10 +153,17 @@ block = false [markup.goldmark.renderHooks.image] enableDefault = true -- content/p1/index.md -- +![]() + ![alt1](./pixel.png) -![alt2](pixel.png?a=b&c=d#fragment) +![alt2-&<>'](pixel.png "&<>'") + +![alt3](pixel.png?a=b&c=d#fragment) {.foo #bar} + +![alt4](pixel.png) +{id="\">"} -- content/p1/pixel.png -- iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg== -- layouts/_default/single.html -- @@ -160,15 +172,21 @@ iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAA b := hugolib.Test(t, files) b.AssertFileContent("public/p1/index.html", - `alt1`, - `alt2`, + ``, + `alt1`, + `alt2-&<>’`, + `alt3`, + `alt4`, ) files = strings.Replace(files, "block = false", "block = true", -1) b = hugolib.Test(t, files) b.AssertFileContent("public/p1/index.html", - `alt1`, - `alt2`, + ``, + `alt1`, + `alt2-&<>’`, + `alt3`, + `alt4`, ) }