From 0e9993253004665fe34bd6e794f763894927e0b4 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 16 Feb 2026 11:27:49 +0100 Subject: [PATCH] Only turn links to current instance into hash links (#36237) Given the following markdown: ``` http://localhost:3500/silverwind/symlink-test/commit/a832c723cd116df44cce6271c4a89afa4d8ec670 http://localhost:3500/silverwind/remap-css/commit/19fe6cdf81f7ec50b8cac2d6c28fe7c42c1ffe14 http://github.com/silverwind/symlink-test/commit/a832c723cd116df44cce6271c4a89afa4d8ec670 ``` Previously, all links would turn into hash link, even ones to external sites: Screenshot 2025-12-23 at 19 19 13 After this change, only links to the current instance, as identified by `setting.AppURL` are turned into hash links: Screenshot 2025-12-23 at 19 18 56 There is still one notable [difference with GitHub](https://github.com/silverwind/symlink-test/issues/20#issuecomment-3687535938) where the second link should render like `user/repo@`, not `` as currently, I would like to fix that here as well. --------- Co-authored-by: Claude Opus 4.6 --- modules/markup/html_commit.go | 12 ++++++++++++ modules/markup/html_internal_test.go | 2 +- modules/markup/html_test.go | 13 ++++++++----- modules/markup/markdown/markdown_test.go | 20 +++++++++++++++++--- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/modules/markup/html_commit.go b/modules/markup/html_commit.go index 0a9b329589e..c319374a38d 100644 --- a/modules/markup/html_commit.go +++ b/modules/markup/html_commit.go @@ -8,6 +8,7 @@ import ( "strings" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/references" "code.gitea.io/gitea/modules/util" @@ -121,6 +122,11 @@ func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) { if ret.QueryHash != "" { text += " (" + ret.QueryHash + ")" } + // only turn commit links to the current instance into hash link + if !httplib.IsCurrentGiteaSiteURL(ctx, ret.FullURL) { + node = node.NextSibling + continue + } replaceContent(node, ret.PosStart, ret.PosEnd, createCodeLink(ret.FullURL, text, "commit")) node = node.NextSibling.NextSibling } @@ -167,6 +173,12 @@ func comparePatternProcessor(ctx *RenderContext, node *html.Node) { } } + // only turn compare links to the current instance into hash link + if !httplib.IsCurrentGiteaSiteURL(ctx, urlFull) { + node = node.NextSibling + continue + } + text := text1 + textDots + text2 if hash != "" { text += " (" + hash + ")" diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index 467cc509d0b..ca2579c8ead 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -299,7 +299,7 @@ func TestRender_AutoLink(t *testing.T) { // render other commit URLs tmp = "https://external-link.gitea.io/go-gitea/gitea/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2" - test(tmp, "d8a994ef24 (diff-2)") + test(tmp, ""+tmp+"") } func TestRender_FullIssueURLs(t *testing.T) { diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index 76013ccd13d..5f873d29852 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -71,6 +71,7 @@ func TestRender_Commits(t *testing.T) { } func TestRender_CrossReferences(t *testing.T) { + defer testModule.MockVariableValue(&setting.AppURL, markup.TestAppURL)() defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() test := func(input, expected string) { rctx := markup.NewTestRenderContext(markup.TestAppURL, localMetas).WithRelativePath("a.md") @@ -98,17 +99,17 @@ func TestRender_CrossReferences(t *testing.T) { util.URLJoin(markup.TestAppURL, "gogitea", "some-repo-name", "issues", "12345"), `

gogitea/some-repo-name#12345

`) - inputURL := "https://host/a/b/commit/0123456789012345678901234567890123456789/foo.txt?a=b#L2-L3" + inputURL := setting.AppURL + "a/b/commit/0123456789012345678901234567890123456789/foo.txt?a=b#L2-L3" test( inputURL, `

0123456789/foo.txt (L2-L3)

`) - inputURL = "https://example.com/repo/owner/archive/0123456789012345678901234567890123456789.tar.gz" + inputURL = setting.AppURL + "repo/owner/archive/0123456789012345678901234567890123456789.tar.gz" test( inputURL, `

0123456789.tar.gz

`) - inputURL = "https://example.com/owner/repo/commit/0123456789012345678901234567890123456789.patch?key=val" + inputURL = setting.AppURL + "owner/repo/commit/0123456789012345678901234567890123456789.patch?key=val" test( inputURL, `

0123456789.patch

`) @@ -575,13 +576,15 @@ func TestFuzz(t *testing.T) { } func TestIssue18471(t *testing.T) { - data := `http://domain/org/repo/compare/783b039...da951ce` + defer testModule.MockVariableValue(&setting.AppURL, markup.TestAppURL)() + + data := markup.TestAppURL + `org/repo/compare/783b039...da951ce` var res strings.Builder err := markup.PostProcessDefault(markup.NewTestRenderContext(localMetas), strings.NewReader(data), &res) assert.NoError(t, err) - assert.Equal(t, `783b039...da951ce`, res.String()) + assert.Equal(t, `783b039...da951ce`, res.String()) } func TestIsFullURL(t *testing.T) { diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go index 47b293e1e9b..8d6b3b3c80e 100644 --- a/modules/markup/markdown/markdown_test.go +++ b/modules/markup/markdown/markdown_test.go @@ -483,6 +483,9 @@ foo: bar } func TestRenderLinks(t *testing.T) { + defer test.MockVariableValue(&setting.AppURL, AppURL)() + defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() + input := ` space @mention-user${SPACE}${SPACE} /just/a/path.bin https://example.com/file.bin @@ -520,9 +523,9 @@ mail@domain.com remote image local image remote link -88fc37a3c0...12fc37a3c0 (hash) +https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare -88fc37a3c0 +https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit 👍 mail@domain.com @@ -530,10 +533,21 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit #123 space

` - defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() result, err := markdown.RenderString(markup.NewTestRenderContext(localMetas), input) assert.NoError(t, err) assert.Equal(t, expected, string(result)) + + t.Run("LocalCommitAndCompare", func(t *testing.T) { + input := `http://localhost:3000/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb +http://localhost:3000/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash` + + expected := `

88fc37a3c0 +88fc37a3c0...12fc37a3c0 (hash)

+` + result, err := markdown.RenderString(markup.NewTestRenderContext(localMetas), input) + assert.NoError(t, err) + assert.Equal(t, expected, string(result)) + }) } func TestMarkdownLink(t *testing.T) {