From 9e27bce9458fe280d70144e0b3507bc1b6517d12 Mon Sep 17 00:00:00 2001
From: leo <80651389+Hello-Liar@users.noreply.github.com>
Date: Mon, 26 Oct 2026 08:27:42 -0700
Subject: [PATCH] fix(markup): keep commit title emoji inside links (#39986)
Render emoji inside the default commit-title link so the whole title
remains clickable, including emoji-only titles. Explicit links and
mentions keep their own destinations.
Fixes https://github.com/go-gitea/gitea/issues/31873
---
modules/markup/html.go | 5 +++--
modules/templates/util_render_test.go | 17 +++++++++++++++++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 4731ae91e93..abef1cdf287 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -153,8 +153,6 @@ func PostProcessCommitMessageSubject(ctx *RenderContext, defaultLink, content st
issueIndexPatternProcessor,
commitCrossReferencePatternProcessor,
hashCurrentPatternProcessor,
- emojiShortCodeProcessor,
- emojiProcessor,
linkProcessor,
}
@@ -175,6 +173,9 @@ func PostProcessCommitMessageSubject(ctx *RenderContext, defaultLink, content st
node.DataAtom = atom.A
node.Attr = []html.Attribute{{Key: "href", Val: defaultLink}, {Key: "class", Val: "muted title-full-link"}}
node.FirstChild, node.LastChild = ch, ch
+ for n := node.FirstChild; n != nil; {
+ n = visitNode(ctx, emojiProcessors, n)
+ }
})
rendered := postProcessHTML(ctx, procs, htmlutil.EscapeString(content))
return htmlutil.HTMLFormat(`%s`, rendered)
diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go
index b1901b5cf76..8378d2f928d 100644
--- a/modules/templates/util_render_test.go
+++ b/modules/templates/util_render_test.go
@@ -136,6 +136,23 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessageLinkSubject("see https://example.com/x here", "https://example.com/link", mockRepo))
})
+ t.Run("RenderCommitMessageLinkSubjectEmoji", func(t *testing.T) {
+ defer test.MockVariableValue(&setting.UI.CustomEmojisMap, map[string]string{"custom-emoji": ":custom-emoji:"})()
+ for _, tt := range []struct {
+ name, subject, content string
+ }{
+ {"native", "Bug ❌ Feature ✅", `Bug ❌ Feature ✅`},
+ {"shortcode", "Ship :+1: today", `Ship 👍 today`},
+ {"emoji only", "👍", `👍`},
+ {"custom", "Ship :custom-emoji:", `Ship
`},
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ expected := `` + tt.content + ``
+ assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessageLinkSubject(tt.subject, "https://example.com/link", mockRepo))
+ })
+ }
+ })
+
t.Run("RenderIssueTitle", func(t *testing.T) {
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
expected := ` space @mention-user