Only turn links to current instance into hash links (#36237)
Given the following markdown: ```a832c723cd19fe6cdf81a832c723cd``` Previously, all links would turn into hash link, even ones to external sites: <img width="849" height="89" alt="Screenshot 2025-12-23 at 19 19 13" src="https://github.com/user-attachments/assets/2ad35a18-4542-40a4-a838-7ab8ac8bc047" /> After this change, only links to the current instance, as identified by `setting.AppURL` are turned into hash links: <img width="850" height="87" alt="Screenshot 2025-12-23 at 19 18 56" src="https://github.com/user-attachments/assets/2c49a5b2-426c-4a82-a610-9b9da8dcfff9" /> 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@<hash>`, not `<hash>` as currently, I would like to fix that here as well. --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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 + ")"
|
||||
|
||||
@@ -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, "<a href=\""+tmp+"\" class=\"commit\"><code>d8a994ef24 (diff-2)</code></a>")
|
||||
test(tmp, "<a href=\""+tmp+"\">"+tmp+"</a>")
|
||||
}
|
||||
|
||||
func TestRender_FullIssueURLs(t *testing.T) {
|
||||
|
||||
@@ -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"),
|
||||
`<p><a href="`+util.URLJoin(markup.TestAppURL, "gogitea", "some-repo-name", "issues", "12345")+`" class="ref-issue" rel="nofollow">gogitea/some-repo-name#12345</a></p>`)
|
||||
|
||||
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,
|
||||
`<p><a href="`+inputURL+`" rel="nofollow"><code>0123456789/foo.txt (L2-L3)</code></a></p>`)
|
||||
|
||||
inputURL = "https://example.com/repo/owner/archive/0123456789012345678901234567890123456789.tar.gz"
|
||||
inputURL = setting.AppURL + "repo/owner/archive/0123456789012345678901234567890123456789.tar.gz"
|
||||
test(
|
||||
inputURL,
|
||||
`<p><a href="`+inputURL+`" rel="nofollow"><code>0123456789.tar.gz</code></a></p>`)
|
||||
|
||||
inputURL = "https://example.com/owner/repo/commit/0123456789012345678901234567890123456789.patch?key=val"
|
||||
inputURL = setting.AppURL + "owner/repo/commit/0123456789012345678901234567890123456789.patch?key=val"
|
||||
test(
|
||||
inputURL,
|
||||
`<p><a href="`+inputURL+`" rel="nofollow"><code>0123456789.patch</code></a></p>`)
|
||||
@@ -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, `<a href="http://domain/org/repo/compare/783b039...da951ce" class="compare"><code>783b039...da951ce</code></a>`, res.String())
|
||||
assert.Equal(t, `<a href="`+markup.TestAppURL+`org/repo/compare/783b039...da951ce" class="compare"><code>783b039...da951ce</code></a>`, res.String())
|
||||
}
|
||||
|
||||
func TestIsFullURL(t *testing.T) {
|
||||
|
||||
@@ -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
|
||||
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a>
|
||||
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a>
|
||||
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow"><code>88fc37a3c0...12fc37a3c0 (hash)</code></a>
|
||||
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow"><code>88fc37a3c0</code></a>
|
||||
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a>
|
||||
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
|
||||
<span class="emoji" aria-label="thumbs up">👍</span>
|
||||
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a>
|
||||
@@ -530,10 +533,21 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
|
||||
#123
|
||||
space</p>
|
||||
`
|
||||
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 := `<p><a href="http://localhost:3000/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow"><code>88fc37a3c0</code></a>
|
||||
<a href="http://localhost:3000/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow"><code>88fc37a3c0...12fc37a3c0 (hash)</code></a></p>
|
||||
`
|
||||
result, err := markdown.RenderString(markup.NewTestRenderContext(localMetas), input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, string(result))
|
||||
})
|
||||
}
|
||||
|
||||
func TestMarkdownLink(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user