diff --git a/modules/templates/helper.go b/modules/templates/helper.go index a01aad06a173e..efaa10624bd87 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -73,11 +73,6 @@ func NewFuncMap() template.FuncMap { return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" }, - // for backward compatibility only, do not use them anymore - "TimeSince": timeSinceLegacy, - "TimeSinceUnix": timeSinceLegacy, - "DateTime": dateTimeLegacy, - // ----------------------------------------------------------------- // setting "AppName": func() string { @@ -156,18 +151,8 @@ func NewFuncMap() template.FuncMap { // ----------------------------------------------------------------- // render - "RenderCommitMessage": RenderCommitMessage, - "RenderCommitMessageLinkSubject": renderCommitMessageLinkSubject, - - "RenderCommitBody": renderCommitBody, - "RenderCodeBlock": renderCodeBlock, - "RenderIssueTitle": renderIssueTitle, - "RenderEmoji": renderEmoji, - "ReactionToEmoji": reactionToEmoji, - - "RenderMarkdownToHtml": RenderMarkdownToHtml, - "RenderLabel": renderLabel, - "RenderLabels": RenderLabels, + "RenderCodeBlock": renderCodeBlock, + "ReactionToEmoji": reactionToEmoji, // ----------------------------------------------------------------- // misc @@ -179,6 +164,22 @@ func NewFuncMap() template.FuncMap { "FilenameIsImage": filenameIsImage, "TabSizeClass": tabSizeClass, + + // for backward compatibility only, do not use them anymore + "TimeSince": timeSinceLegacy, + "TimeSinceUnix": timeSinceLegacy, + "DateTime": dateTimeLegacy, + + "RenderEmoji": renderEmojiLegacy, + "RenderLabel": renderLabelLegacy, + "RenderLabels": renderLabelsLegacy, + "RenderIssueTitle": renderIssueTitleLegacy, + + "RenderMarkdownToHtml": renderMarkdownToHtmlLegacy, + + "RenderCommitMessage": renderCommitMessageLegacy, + "RenderCommitMessageLinkSubject": renderCommitMessageLinkSubjectLegacy, + "RenderCommitBody": renderCommitBodyLegacy, } } @@ -296,3 +297,9 @@ func userThemeName(user *user_model.User) string { } return setting.UI.DefaultTheme } + +func panicIfDevOrTesting() { + if !setting.IsProd || setting.IsInTesting { + panic("legacy template functions are for backward compatibility only, do not use them in new code") + } +} diff --git a/modules/templates/util_date.go b/modules/templates/util_date.go index b9e04401f15f5..4a794e6f30c7b 100644 --- a/modules/templates/util_date.go +++ b/modules/templates/util_date.go @@ -12,7 +12,6 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/modules/translation" ) type DateUtils struct{} @@ -54,23 +53,6 @@ func parseLegacy(datetime string) time.Time { return t } -func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML { - if !setting.IsProd || setting.IsInTesting { - panic("dateTimeLegacy is for backward compatibility only, do not use it in new code") - } - if s, ok := datetime.(string); ok { - datetime = parseLegacy(s) - } - return dateTimeFormat(format, datetime) -} - -func timeSinceLegacy(time any, _ translation.Locale) template.HTML { - if !setting.IsProd || setting.IsInTesting { - panic("timeSinceLegacy is for backward compatibility only, do not use it in new code") - } - return TimeSince(time) -} - func anyToTime(any any) (t time.Time, isZero bool) { switch v := any.(type) { case nil: diff --git a/modules/templates/util_date_legacy.go b/modules/templates/util_date_legacy.go new file mode 100644 index 0000000000000..ceefb0044717a --- /dev/null +++ b/modules/templates/util_date_legacy.go @@ -0,0 +1,23 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package templates + +import ( + "html/template" + + "code.gitea.io/gitea/modules/translation" +) + +func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML { + panicIfDevOrTesting() + if s, ok := datetime.(string); ok { + datetime = parseLegacy(s) + } + return dateTimeFormat(format, datetime) +} + +func timeSinceLegacy(time any, _ translation.Locale) template.HTML { + panicIfDevOrTesting() + return TimeSince(time) +} diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go index 6eee007f34683..1201828345715 100644 --- a/modules/templates/util_render.go +++ b/modules/templates/util_render.go @@ -24,13 +24,21 @@ import ( "code.gitea.io/gitea/modules/util" ) +type RenderUtils struct { + ctx context.Context +} + +func NewRenderUtils(ctx context.Context) *RenderUtils { + return &RenderUtils{ctx: ctx} +} + // RenderCommitMessage renders commit message with XSS-safe and special links. -func RenderCommitMessage(ctx context.Context, msg string, metas map[string]string) template.HTML { +func (ut *RenderUtils) RenderCommitMessage(msg string, metas map[string]string) template.HTML { cleanMsg := template.HTMLEscapeString(msg) // we can safely assume that it will not return any error, since there // shouldn't be any special HTML. fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{ - Ctx: ctx, + Ctx: ut.ctx, Metas: metas, }, cleanMsg) if err != nil { @@ -44,9 +52,9 @@ func RenderCommitMessage(ctx context.Context, msg string, metas map[string]strin return renderCodeBlock(template.HTML(msgLines[0])) } -// renderCommitMessageLinkSubject renders commit message as a XSS-safe link to +// RenderCommitMessageLinkSubject renders commit message as a XSS-safe link to // the provided default url, handling for special links without email to links. -func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string, metas map[string]string) template.HTML { +func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, metas map[string]string) template.HTML { msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace) lineEnd := strings.IndexByte(msgLine, '\n') if lineEnd > 0 { @@ -60,7 +68,7 @@ func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string, // we can safely assume that it will not return any error, since there // shouldn't be any special HTML. renderedMessage, err := markup.RenderCommitMessageSubject(&markup.RenderContext{ - Ctx: ctx, + Ctx: ut.ctx, DefaultLink: urlDefault, Metas: metas, }, template.HTMLEscapeString(msgLine)) @@ -71,8 +79,8 @@ func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string, return renderCodeBlock(template.HTML(renderedMessage)) } -// renderCommitBody extracts the body of a commit message without its title. -func renderCommitBody(ctx context.Context, msg string, metas map[string]string) template.HTML { +// RenderCommitBody extracts the body of a commit message without its title. +func (ut *RenderUtils) RenderCommitBody(msg string, metas map[string]string) template.HTML { msgLine := strings.TrimSpace(msg) lineEnd := strings.IndexByte(msgLine, '\n') if lineEnd > 0 { @@ -86,7 +94,7 @@ func renderCommitBody(ctx context.Context, msg string, metas map[string]string) } renderedMessage, err := markup.RenderCommitMessage(&markup.RenderContext{ - Ctx: ctx, + Ctx: ut.ctx, Metas: metas, }, template.HTMLEscapeString(msgLine)) if err != nil { @@ -105,22 +113,22 @@ func renderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML { return template.HTML(htmlWithCodeTags) } -// renderIssueTitle renders issue/pull title with defined post processors -func renderIssueTitle(ctx context.Context, text string, metas map[string]string) template.HTML { +// RenderIssueTitle renders issue/pull title with defined post processors +func (ut *RenderUtils) RenderIssueTitle(text string, metas map[string]string) template.HTML { renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{ - Ctx: ctx, + Ctx: ut.ctx, Metas: metas, }, template.HTMLEscapeString(text)) if err != nil { log.Error("RenderIssueTitle: %v", err) - return template.HTML("") + return "" } return template.HTML(renderedText) } -// renderLabel renders a label -// locale is needed due to an import cycle with our context providing the `Tr` function -func renderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML { +// RenderLabel renders a label +func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML { + locale := ut.ctx.Value(translation.ContextKey).(translation.Locale) var extraCSSClasses string textColor := util.ContrastColor(label.Color) labelScope := label.ExclusiveScope() @@ -134,12 +142,12 @@ func renderLabel(ctx context.Context, locale translation.Locale, label *issues_m if labelScope == "" { // Regular label return HTMLFormat(`
@no-such-user @mention-user @mention-user
`, strings.TrimSpace(string(rendered))) } diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 774644e29ae21..3f33e9933a2ea 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -71,6 +71,7 @@ func renderMarkdown(ctx *context.Context, act *activities_model.Action, content // feedActionsToFeedItems convert gitea's Action feed to feeds Item func feedActionsToFeedItems(ctx *context.Context, actions activities_model.ActionList) (items []*feeds.Item, err error) { + renderUtils := templates.NewRenderUtils(ctx) for _, act := range actions { act.LoadActUser(ctx) @@ -215,7 +216,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio desc += fmt.Sprintf("%s\n%s", html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(ctx), commit.Sha1)), commit.Sha1, - templates.RenderCommitMessage(ctx, commit.Message, nil), + renderUtils.RenderCommitMessage(commit.Message, nil), ) } diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 2a5434b4147f6..6dfefbf68d243 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -103,9 +103,9 @@ func Projects(ctx *context.Context) { } else { ctx.Data["State"] = "open" } - + renderUtils := templates.NewRenderUtils(ctx) for _, project := range projects { - project.RenderedContent = templates.RenderMarkdownToHtml(ctx, project.Description) + project.RenderedContent = renderUtils.MarkdownToHtml(project.Description) } err = shared_user.LoadHeaderCount(ctx) @@ -435,7 +435,7 @@ func ViewProject(ctx *context.Context) { ctx.Data["SelectLabels"] = selectLabels ctx.Data["AssigneeID"] = assigneeID - project.RenderedContent = templates.RenderMarkdownToHtml(ctx, project.Description) + project.RenderedContent = templates.NewRenderUtils(ctx).MarkdownToHtml(project.Description) ctx.Data["LinkedPRs"] = linkedPrsMap ctx.Data["PageIsViewProjects"] = true ctx.Data["CanWriteProjects"] = canWriteProjects(ctx) diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 507b5af9d904a..93e2b5e748662 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2215,7 +2215,7 @@ func GetIssueInfo(ctx *context.Context) { ctx.JSON(http.StatusOK, map[string]any{ "convertedIssue": convert.ToIssue(ctx, ctx.Doer, issue), - "renderedLabels": templates.RenderLabels(ctx, ctx.Locale, issue.Labels, ctx.Repo.RepoLink, issue), + "renderedLabels": templates.NewRenderUtils(ctx).RenderLabels(issue.Labels, ctx.Repo.RepoLink, issue), }) } diff --git a/services/context/context.go b/services/context/context.go index 42f7c3d9d1d8a..6c7128ef6866c 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -100,6 +100,7 @@ func NewTemplateContextForWeb(ctx *Context) TemplateContext { tmplCtx := NewTemplateContext(ctx) tmplCtx["Locale"] = ctx.Base.Locale tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx) + tmplCtx["RenderUtils"] = templates.NewRenderUtils(ctx) tmplCtx["RootData"] = ctx.Data tmplCtx["Consts"] = map[string]any{ "RepoUnitTypeCode": unit.TypeCode, @@ -154,7 +155,9 @@ func Contexter() func(next http.Handler) http.Handler { ctx := NewWebContext(base, rnd, session.GetContextSession(req)) ctx.Data.MergeFrom(middleware.CommonTemplateContextData()) - ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this + if setting.IsProd && !setting.IsInTesting { + ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this + } ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI() ctx.Data["Link"] = ctx.Link diff --git a/templates/base/head_script.tmpl b/templates/base/head_script.tmpl index 22e08e9c8f69c..c0c7235e3b02e 100644 --- a/templates/base/head_script.tmpl +++ b/templates/base/head_script.tmpl @@ -21,10 +21,10 @@ If you introduce mistakes in it, Gitea JavaScript code wouldn't run correctly. {{if or .Participants .Assignees .MentionableTeams}} mentionValues: Array.from(new Map([ {{- range .Participants -}} - ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], + ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink ctx}}'}], {{- end -}} {{- range .Assignees -}} - ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink $.Context}}'}], + ['{{.Name}}', {key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.AvatarLink ctx}}'}], {{- end -}} {{- range .MentionableTeams -}} ['{{$.MentionableTeamsOrg}}/{{.Name}}', {key: '{{$.MentionableTeamsOrg}}/{{.Name}}', value: '{{$.MentionableTeamsOrg}}/{{.Name}}', name: '{{$.MentionableTeamsOrg}}/{{.Name}}', avatar: '{{$.MentionableTeamsOrgAvatar}}'}], diff --git a/templates/explore/repo_list.tmpl b/templates/explore/repo_list.tmpl index 742e83834d06f..219b1255c0a12 100644 --- a/templates/explore/repo_list.tmpl +++ b/templates/explore/repo_list.tmpl @@ -49,7 +49,7 @@ - {{$description := .DescriptionHTML $.Context}} + {{$description := .DescriptionHTML ctx}} {{if $description}}{{.PackageDescriptor.Metadata.Description}}
{{end}} - {{if .PackageDescriptor.Metadata.LongDescription}}{{RenderMarkdownToHtml $.Context .PackageDescriptor.Metadata.LongDescription}}{{end}} + {{if .PackageDescriptor.Metadata.LongDescription}}{{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.LongDescription}}{{end}}{{if .PackageDescriptor.Metadata.Summary}}{{.PackageDescriptor.Metadata.Summary}}{{end}}
{{if .PackageDescriptor.Metadata.LongDescription}} - {{RenderMarkdownToHtml $.Context .PackageDescriptor.Metadata.LongDescription}} + {{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.LongDescription}} {{else if .PackageDescriptor.Metadata.Description}} - {{RenderMarkdownToHtml $.Context .PackageDescriptor.Metadata.Description}} + {{ctx.RenderUtils.MarkdownToHtml .PackageDescriptor.Metadata.Description}} {{end}}{{template "repo/issue/labels/label_archived" .}}
{{end}} diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index 6e2a5570c712a..5484024ff8197 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -27,7 +27,7 @@ {{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}}{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime}}{{if .DefaultBranchBranch.DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}
+{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime}}{{if .DefaultBranchBranch.DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}
{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DBBranch.CommitTime}}{{if .DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}
+{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DBBranch.CommitTime}}{{if .DBBranch.Pusher}} {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}} {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}
{{end}}{{RenderCommitBody $.Context .Commit.Message ($.Repository.ComposeMetas ctx)}}+
{{ctx.RenderUtils.RenderCommitBody .Commit.Message ($.Repository.ComposeMetas ctx)}}{{end}} {{template "repo/commit_load_branches_and_tags" .}}