From 327048c106436160c44faf941ae865ac259a9794 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 24 Jun 2025 01:27:35 +0800 Subject: [PATCH] Refactor template helper (#34819) FIx abuses and remove unused code --------- Signed-off-by: wxiaoguang Co-authored-by: silverwind --- modules/htmlutil/html.go | 4 ++++ .../markup/markdown/math/block_renderer.go | 4 ++-- .../markup/markdown/math/inline_renderer.go | 2 +- modules/templates/helper.go | 24 ------------------- templates/admin/packages/list.tmpl | 2 +- templates/admin/repo/list.tmpl | 2 +- templates/org/member/members.tmpl | 4 ++-- templates/org/team/members.tmpl | 2 +- templates/org/team/sidebar.tmpl | 2 +- templates/org/team/teams.tmpl | 2 +- templates/repo/commit_page.tmpl | 4 ++-- .../repo/issue/view_content/comments.tmpl | 1 + templates/repo/settings/webhook/settings.tmpl | 2 +- templates/user/settings/applications.tmpl | 2 +- templates/user/settings/organization.tmpl | 2 +- 15 files changed, 20 insertions(+), 39 deletions(-) diff --git a/modules/htmlutil/html.go b/modules/htmlutil/html.go index 0ab0e71689..194135ba18 100644 --- a/modules/htmlutil/html.go +++ b/modules/htmlutil/html.go @@ -7,6 +7,7 @@ import ( "fmt" "html/template" "slices" + "strings" ) // ParseSizeAndClass get size and class from string with default values @@ -31,6 +32,9 @@ func ParseSizeAndClass(defaultSize int, defaultClass string, others ...any) (int } func HTMLFormat(s template.HTML, rawArgs ...any) template.HTML { + if !strings.Contains(string(s), "%") || len(rawArgs) == 0 { + panic("HTMLFormat requires one or more arguments") + } args := slices.Clone(rawArgs) for i, v := range args { switch v := v.(type) { diff --git a/modules/markup/markdown/math/block_renderer.go b/modules/markup/markdown/math/block_renderer.go index 427ed842ec..95a336a02c 100644 --- a/modules/markup/markdown/math/block_renderer.go +++ b/modules/markup/markdown/math/block_renderer.go @@ -51,8 +51,8 @@ func (r *BlockRenderer) writeLines(w util.BufWriter, source []byte, n gast.Node) func (r *BlockRenderer) renderBlock(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { n := node.(*Block) if entering { - code := giteaUtil.Iif(n.Inline, "", `
`) + ``
-		_ = r.renderInternal.FormatWithSafeAttrs(w, template.HTML(code))
+		codeHTML := giteaUtil.Iif[template.HTML](n.Inline, "", `
`) + ``
+		_, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(codeHTML)))
 		r.writeLines(w, source, n)
 	} else {
 		_, _ = w.WriteString(`` + giteaUtil.Iif(n.Inline, "", `
`) + "\n") diff --git a/modules/markup/markdown/math/inline_renderer.go b/modules/markup/markdown/math/inline_renderer.go index d000a7b317..eeeb60cc7e 100644 --- a/modules/markup/markdown/math/inline_renderer.go +++ b/modules/markup/markdown/math/inline_renderer.go @@ -28,7 +28,7 @@ func NewInlineRenderer(renderInternal *internal.RenderInternal) renderer.NodeRen func (r *InlineRenderer) renderInline(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { if entering { - _ = r.renderInternal.FormatWithSafeAttrs(w, ``) + _, _ = w.WriteString(string(r.renderInternal.ProtectSafeAttrs(``))) for c := n.FirstChild(); c != nil; c = c.NextSibling() { segment := c.(*ast.Text).Segment value := util.EscapeHTML(segment.Value(source)) diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 052f9c47ab..ff3f7cfda1 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -6,7 +6,6 @@ package templates import ( "fmt" - "html" "html/template" "net/url" "strconv" @@ -38,9 +37,7 @@ func NewFuncMap() template.FuncMap { "dict": dict, // it's lowercase because this name has been widely used. Our other functions should have uppercase names. "Iif": iif, "Eval": evalTokens, - "SafeHTML": safeHTML, "HTMLFormat": htmlFormat, - "HTMLEscape": htmlEscape, "QueryEscape": queryEscape, "QueryBuild": QueryBuild, "JSEscape": jsEscapeSafe, @@ -165,32 +162,11 @@ func NewFuncMap() template.FuncMap { } } -// safeHTML render raw as HTML -func safeHTML(s any) template.HTML { - switch v := s.(type) { - case string: - return template.HTML(v) - case template.HTML: - return v - } - panic(fmt.Sprintf("unexpected type %T", s)) -} - // SanitizeHTML sanitizes the input by default sanitization rules. func SanitizeHTML(s string) template.HTML { return markup.Sanitize(s) } -func htmlEscape(s any) template.HTML { - switch v := s.(type) { - case string: - return template.HTML(html.EscapeString(v)) - case template.HTML: - return v - } - panic(fmt.Sprintf("unexpected type %T", s)) -} - func htmlFormat(s any, args ...any) template.HTML { if len(args) == 0 { // to prevent developers from calling "HTMLFormat $userInput" by mistake which will lead to XSS diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl index 0c6889b599..985caf6bdf 100644 --- a/templates/admin/packages/list.tmpl +++ b/templates/admin/packages/list.tmpl @@ -90,7 +90,7 @@ {{ctx.Locale.Tr "packages.settings.delete"}}
- {{ctx.Locale.Tr "packages.settings.delete.notice" (``|SafeHTML) (``|SafeHTML)}} + {{ctx.Locale.Tr "packages.settings.delete.notice" (HTMLFormat `` "name") (HTMLFormat `` "dataVersion")}}
{{template "base/modal_actions_confirm" .}} diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 762013af47..af80633be0 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -103,7 +103,7 @@

{{ctx.Locale.Tr "repo.settings.delete_desc"}}

- {{ctx.Locale.Tr "repo.settings.delete_notices_2" (``|SafeHTML)}}
+ {{ctx.Locale.Tr "repo.settings.delete_notices_2" (HTMLFormat `` "name")}}
{{ctx.Locale.Tr "repo.settings.delete_notices_fork_1"}}
{{template "base/modal_actions_confirm" .}} diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl index 4388dc9520..2d0f4bc423 100644 --- a/templates/org/member/members.tmpl +++ b/templates/org/member/members.tmpl @@ -73,7 +73,7 @@ {{ctx.Locale.Tr "org.members.leave"}}
-

{{ctx.Locale.Tr "org.members.leave.detail" (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.members.leave.detail" (HTMLFormat `` "dataOrganizationName")}}

{{template "base/modal_actions_confirm" .}} @@ -82,7 +82,7 @@ {{ctx.Locale.Tr "org.members.remove"}}
-

{{ctx.Locale.Tr "org.members.remove.detail" (``|SafeHTML) (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.members.remove.detail" (HTMLFormat `` "name") (HTMLFormat `` "dataOrganizationName")}}

{{template "base/modal_actions_confirm" .}} diff --git a/templates/org/team/members.tmpl b/templates/org/team/members.tmpl index 5433f01530..4bc063f90c 100644 --- a/templates/org/team/members.tmpl +++ b/templates/org/team/members.tmpl @@ -81,7 +81,7 @@ {{ctx.Locale.Tr "org.members.remove"}}
-

{{ctx.Locale.Tr "org.members.remove.detail" (``|SafeHTML) (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.members.remove.detail" (HTMLFormat `` "name") (HTMLFormat `` "dataTeamName")}}

{{template "base/modal_actions_confirm" .}} diff --git a/templates/org/team/sidebar.tmpl b/templates/org/team/sidebar.tmpl index 8390bf0acd..6dd5cb3eeb 100644 --- a/templates/org/team/sidebar.tmpl +++ b/templates/org/team/sidebar.tmpl @@ -90,7 +90,7 @@ {{ctx.Locale.Tr "org.teams.leave"}}
-

{{ctx.Locale.Tr "org.teams.leave.detail" (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.teams.leave.detail" (HTMLFormat `` "name")}}

{{template "base/modal_actions_confirm" .}} diff --git a/templates/org/team/teams.tmpl b/templates/org/team/teams.tmpl index 432df10749..cdd2789128 100644 --- a/templates/org/team/teams.tmpl +++ b/templates/org/team/teams.tmpl @@ -49,7 +49,7 @@ {{ctx.Locale.Tr "org.teams.leave"}}
-

{{ctx.Locale.Tr "org.teams.leave.detail" (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.teams.leave.detail" (HTMLFormat `` "name")}}

{{template "base/modal_actions_confirm" .}} diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index fb0a63eff7..46f641824b 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -75,7 +75,7 @@ {{.CsrfTokenHtml}}
@@ -100,7 +100,7 @@
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index e02111fd8e..6f61d88d3b 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -163,6 +163,7 @@
{{svg "octicon-git-commit"}} + {{/* the content is a link like message title (from CreateRefComment) */}} {{.Content | SanitizeHTML}}
diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl index b8d9609391..a330448c9e 100644 --- a/templates/repo/settings/webhook/settings.tmpl +++ b/templates/repo/settings/webhook/settings.tmpl @@ -298,7 +298,7 @@ {{if ne .HookType "matrix"}}{{/* Matrix doesn't make the authorization optional but it is implied by the help string, should be changed.*/}} - {{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("Bearer token123456, Basic YWxhZGRpbjpvcGVuc2VzYW1l" | SafeHTML)}} + {{ctx.Locale.Tr "repo.settings.authorization_header_desc" (HTMLFormat "%s, %s" "Bearer token123456" "Basic YWxhZGRpbjpvcGVuc2VzYW1l")}} {{end}}
diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl index 501f238c7a..8c24da7fc9 100644 --- a/templates/user/settings/applications.tmpl +++ b/templates/user/settings/applications.tmpl @@ -68,7 +68,7 @@
-
{{ctx.Locale.Tr "settings.access_token_desc" (HTMLFormat `href="%s/api/swagger" target="_blank"` AppSubUrl) (`href="https://docs.gitea.com/development/oauth2-provider#scopes" target="_blank"`|SafeHTML)}}
+
{{ctx.Locale.Tr "settings.access_token_desc" (HTMLFormat `href="%s/api/swagger" target="_blank"` AppSubUrl) (HTMLFormat `href="%s" target="_blank"` "https://docs.gitea.com/development/oauth2-provider#scopes")}}
{{range $category := .TokenCategories}} diff --git a/templates/user/settings/organization.tmpl b/templates/user/settings/organization.tmpl index 16c27b52cd..a48ca9ec9b 100644 --- a/templates/user/settings/organization.tmpl +++ b/templates/user/settings/organization.tmpl @@ -47,7 +47,7 @@ {{ctx.Locale.Tr "org.members.leave"}}
-

{{ctx.Locale.Tr "org.members.leave.detail" (``|SafeHTML)}}

+

{{ctx.Locale.Tr "org.members.leave.detail" (HTMLFormat `` "dataOrganizationName")}}

{{template "base/modal_actions_confirm" .}}