2017-09-17 01:17:57 +08:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-28 02:20:29 +08:00
// SPDX-License-Identifier: MIT
2017-09-17 01:17:57 +08:00
package markup_test
import (
2021-08-13 06:22:05 +08:00
"io"
2017-09-17 01:17:57 +08:00
"strings"
"testing"
2020-04-29 02:05:39 +08:00
"code.gitea.io/gitea/modules/emoji"
2022-01-20 07:26:57 +08:00
"code.gitea.io/gitea/modules/git"
2024-05-30 15:04:01 +08:00
"code.gitea.io/gitea/modules/gitrepo"
2023-10-24 10:54:59 +08:00
"code.gitea.io/gitea/modules/markup"
2018-02-27 15:09:18 +08:00
"code.gitea.io/gitea/modules/markup/markdown"
2017-09-17 01:17:57 +08:00
"code.gitea.io/gitea/modules/setting"
2024-11-14 13:02:11 +08:00
testModule "code.gitea.io/gitea/modules/test"
2018-02-20 20:50:42 +08:00
"code.gitea.io/gitea/modules/util"
2017-09-17 01:17:57 +08:00
"github.com/stretchr/testify/assert"
)
2024-05-30 15:04:01 +08:00
var (
testRepoOwnerName = "user13"
testRepoName = "repo11"
localMetas = map [ string ] string {
"user" : testRepoOwnerName ,
"repo" : testRepoName ,
}
)
type mockRepo struct {
OwnerName string
RepoName string
}
func ( m * mockRepo ) GetOwnerName ( ) string {
return m . OwnerName
}
func ( m * mockRepo ) GetName ( ) string {
return m . RepoName
2019-04-16 15:53:57 +08:00
}
2024-05-30 15:04:01 +08:00
func newMockRepo ( ownerName , repoName string ) gitrepo . Repository {
return & mockRepo {
OwnerName : ownerName ,
RepoName : repoName ,
2022-06-16 23:47:44 +08:00
}
}
2017-09-17 01:17:57 +08:00
func TestRender_Commits ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2017-09-17 01:17:57 +08:00
test := func ( input , expected string ) {
2023-10-24 10:54:59 +08:00
buffer , err := markup . RenderString ( & markup . RenderContext {
2022-06-16 11:33:23 +08:00
Ctx : git . DefaultContext ,
RelativePath : ".md" ,
2024-01-15 16:49:24 +08:00
Links : markup . Links {
2024-03-13 18:34:58 +08:00
AbsolutePrefix : true ,
Base : markup . TestRepoURL ,
2024-01-15 16:49:24 +08:00
} ,
2024-05-30 15:04:01 +08:00
Repo : newMockRepo ( testRepoOwnerName , testRepoName ) ,
2024-01-15 16:49:24 +08:00
Metas : localMetas ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2019-07-24 02:50:39 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( buffer ) )
2017-09-17 01:17:57 +08:00
}
2022-01-21 01:46:10 +08:00
sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
2024-05-30 15:04:01 +08:00
repo := markup . TestAppURL + testRepoOwnerName + "/" + testRepoName + "/"
2022-01-21 01:46:10 +08:00
commit := util . URLJoin ( repo , "commit" , sha )
tree := util . URLJoin ( repo , "tree" , sha , "src" )
file := util . URLJoin ( repo , "commit" , sha , "example.txt" )
fileWithExtra := file + ":"
fileWithHash := file + "#L2"
fileWithHasExtra := file + "#L2:"
commitCompare := util . URLJoin ( repo , "compare" , sha + "..." + sha )
commitCompareWithHash := commitCompare + "#L2"
2017-09-17 01:17:57 +08:00
2019-08-14 16:04:55 +08:00
test ( sha , ` <p><a href=" ` + commit + ` " rel="nofollow"><code>65f1bf27bc</code></a></p> ` )
test ( sha [ : 7 ] , ` <p><a href=" ` + commit [ : len ( commit ) - ( 40 - 7 ) ] + ` " rel="nofollow"><code>65f1bf2</code></a></p> ` )
test ( sha [ : 39 ] , ` <p><a href=" ` + commit [ : len ( commit ) - ( 40 - 39 ) ] + ` " rel="nofollow"><code>65f1bf27bc</code></a></p> ` )
test ( commit , ` <p><a href=" ` + commit + ` " rel="nofollow"><code>65f1bf27bc</code></a></p> ` )
test ( tree , ` <p><a href=" ` + tree + ` " rel="nofollow"><code>65f1bf27bc/src</code></a></p> ` )
2021-12-12 01:21:36 +08:00
test ( file , ` <p><a href=" ` + file + ` " rel="nofollow"><code>65f1bf27bc/example.txt</code></a></p> ` )
test ( fileWithExtra , ` <p><a href=" ` + file + ` " rel="nofollow"><code>65f1bf27bc/example.txt</code></a>:</p> ` )
test ( fileWithHash , ` <p><a href=" ` + fileWithHash + ` " rel="nofollow"><code>65f1bf27bc/example.txt (L2)</code></a></p> ` )
test ( fileWithHasExtra , ` <p><a href=" ` + fileWithHash + ` " rel="nofollow"><code>65f1bf27bc/example.txt (L2)</code></a>:</p> ` )
test ( commitCompare , ` <p><a href=" ` + commitCompare + ` " rel="nofollow"><code>65f1bf27bc...65f1bf27bc</code></a></p> ` )
test ( commitCompareWithHash , ` <p><a href=" ` + commitCompareWithHash + ` " rel="nofollow"><code>65f1bf27bc...65f1bf27bc (L2)</code></a></p> ` )
2019-08-14 16:04:55 +08:00
test ( "commit " + sha , ` <p>commit <a href=" ` + commit + ` " rel="nofollow"><code>65f1bf27bc</code></a></p> ` )
2019-04-07 19:18:16 +08:00
test ( "/home/gitea/" + sha , "<p>/home/gitea/" + sha + "</p>" )
2019-08-14 16:04:55 +08:00
test ( "deadbeef" , ` <p>deadbeef</p> ` )
test ( "d27ace93" , ` <p>d27ace93</p> ` )
2021-01-03 23:11:10 +08:00
test ( sha [ : 14 ] + ".x" , ` <p> ` + sha [ : 14 ] + ` .x</p> ` )
expected14 := ` <a href=" ` + commit [ : len ( commit ) - ( 40 - 14 ) ] + ` " rel="nofollow"><code> ` + sha [ : 10 ] + ` </code></a> `
test ( sha [ : 14 ] + "." , ` <p> ` + expected14 + ` .</p> ` )
test ( sha [ : 14 ] + "," , ` <p> ` + expected14 + ` ,</p> ` )
test ( "[" + sha [ : 14 ] + "]" , ` <p>[ ` + expected14 + ` ]</p> ` )
2017-09-17 01:17:57 +08:00
}
func TestRender_CrossReferences ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2024-11-14 13:02:11 +08:00
defer testModule . MockVariableValue ( & markup . RenderBehaviorForTesting . DisableInternalAttributes , true ) ( )
2017-09-17 01:17:57 +08:00
test := func ( input , expected string ) {
2023-10-24 10:54:59 +08:00
buffer , err := markup . RenderString ( & markup . RenderContext {
2023-03-06 05:59:05 +08:00
Ctx : git . DefaultContext ,
2022-06-16 11:33:23 +08:00
RelativePath : "a.md" ,
2024-01-15 16:49:24 +08:00
Links : markup . Links {
2024-03-13 18:34:58 +08:00
AbsolutePrefix : true ,
Base : setting . AppSubURL ,
2024-01-15 16:49:24 +08:00
} ,
Metas : localMetas ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2024-11-14 13:02:11 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( buffer ) )
2017-09-17 01:17:57 +08:00
}
test (
2024-06-04 20:19:41 +08:00
"test-owner/test-repo#12345" ,
` <p><a href=" ` + util . URLJoin ( markup . TestAppURL , "test-owner" , "test-repo" , "issues" , "12345" ) + ` " class="ref-issue" rel="nofollow">test-owner/test-repo#12345</a></p> ` )
2018-01-27 20:33:32 +08:00
test (
"go-gitea/gitea#12345" ,
2023-10-24 10:54:59 +08:00
` <p><a href=" ` + util . URLJoin ( markup . TestAppURL , "go-gitea" , "gitea" , "issues" , "12345" ) + ` " class="ref-issue" rel="nofollow">go-gitea/gitea#12345</a></p> ` )
2019-04-07 19:18:16 +08:00
test (
"/home/gitea/go-gitea/gitea#12345" ,
` <p>/home/gitea/go-gitea/gitea#12345</p> ` )
2022-02-26 07:26:43 +08:00
test (
2023-10-24 10:54:59 +08:00
util . URLJoin ( markup . TestAppURL , "gogitea" , "gitea" , "issues" , "12345" ) ,
` <p><a href=" ` + util . URLJoin ( markup . TestAppURL , "gogitea" , "gitea" , "issues" , "12345" ) + ` " class="ref-issue" rel="nofollow">gogitea/gitea#12345</a></p> ` )
2022-02-26 07:26:43 +08:00
test (
2023-10-24 10:54:59 +08:00
util . URLJoin ( markup . TestAppURL , "go-gitea" , "gitea" , "issues" , "12345" ) ,
` <p><a href=" ` + util . URLJoin ( markup . TestAppURL , "go-gitea" , "gitea" , "issues" , "12345" ) + ` " class="ref-issue" rel="nofollow">go-gitea/gitea#12345</a></p> ` )
2022-02-26 07:26:43 +08:00
test (
2023-10-24 10:54:59 +08:00
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> ` )
2024-05-04 09:48:16 +08:00
inputURL := "https://host/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> ` )
2017-09-17 01:17:57 +08:00
}
2019-02-28 20:31:53 +08:00
func TestRender_links ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2024-11-14 13:02:11 +08:00
defer testModule . MockVariableValue ( & markup . RenderBehaviorForTesting . DisableInternalAttributes , true ) ( )
2019-02-28 20:31:53 +08:00
test := func ( input , expected string ) {
2023-10-24 10:54:59 +08:00
buffer , err := markup . RenderString ( & markup . RenderContext {
2023-03-06 05:59:05 +08:00
Ctx : git . DefaultContext ,
2022-06-16 11:33:23 +08:00
RelativePath : "a.md" ,
2024-01-15 16:49:24 +08:00
Links : markup . Links {
Base : markup . TestRepoURL ,
} ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2024-11-14 13:02:11 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( buffer ) )
2019-02-28 20:31:53 +08:00
}
2024-05-31 21:26:01 +08:00
oldCustomURLSchemes := setting . Markdown . CustomURLSchemes
markup . ResetDefaultSanitizerForTesting ( )
defer func ( ) {
setting . Markdown . CustomURLSchemes = oldCustomURLSchemes
markup . ResetDefaultSanitizerForTesting ( )
markup . CustomLinkURLSchemes ( oldCustomURLSchemes )
} ( )
2019-10-15 09:31:09 +08:00
setting . Markdown . CustomURLSchemes = [ ] string { "ftp" , "magnet" }
2023-10-24 10:54:59 +08:00
markup . CustomLinkURLSchemes ( setting . Markdown . CustomURLSchemes )
2019-10-15 09:31:09 +08:00
2024-05-31 21:26:01 +08:00
// Text that should be turned into URL
2019-02-28 20:31:53 +08:00
test (
"https://www.example.com" ,
` <p><a href="https://www.example.com" rel="nofollow">https://www.example.com</a></p> ` )
test (
"http://www.example.com" ,
` <p><a href="http://www.example.com" rel="nofollow">http://www.example.com</a></p> ` )
test (
"https://example.com" ,
` <p><a href="https://example.com" rel="nofollow">https://example.com</a></p> ` )
test (
"http://example.com" ,
` <p><a href="http://example.com" rel="nofollow">http://example.com</a></p> ` )
test (
"http://foo.com/blah_blah" ,
` <p><a href="http://foo.com/blah_blah" rel="nofollow">http://foo.com/blah_blah</a></p> ` )
test (
"http://foo.com/blah_blah/" ,
` <p><a href="http://foo.com/blah_blah/" rel="nofollow">http://foo.com/blah_blah/</a></p> ` )
test (
"http://www.example.com/wpstyle/?p=364" ,
` <p><a href="http://www.example.com/wpstyle/?p=364" rel="nofollow">http://www.example.com/wpstyle/?p=364</a></p> ` )
test (
"https://www.example.com/foo/?bar=baz&inga=42&quux" ,
2021-07-09 09:30:31 +08:00
` <p><a href="https://www.example.com/foo/?bar=baz&inga=42&quux" rel="nofollow">https://www.example.com/foo/?bar=baz&inga=42&quux</a></p> ` )
2019-02-28 20:31:53 +08:00
test (
"http://142.42.1.1/" ,
` <p><a href="http://142.42.1.1/" rel="nofollow">http://142.42.1.1/</a></p> ` )
2019-03-08 04:12:01 +08:00
test (
"https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd" ,
2021-07-09 09:30:31 +08:00
` <p><a href="https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd" rel="nofollow">https://github.com/go-gitea/gitea/?p=aaa/bbb.html#ccc-ddd</a></p> ` )
2019-03-08 04:12:01 +08:00
test (
"https://en.wikipedia.org/wiki/URL_(disambiguation)" ,
` <p><a href="https://en.wikipedia.org/wiki/URL_(disambiguation)" rel="nofollow">https://en.wikipedia.org/wiki/URL_(disambiguation)</a></p> ` )
test (
"https://foo_bar.example.com/" ,
` <p><a href="https://foo_bar.example.com/" rel="nofollow">https://foo_bar.example.com/</a></p> ` )
2019-03-27 23:37:54 +08:00
test (
"https://stackoverflow.com/questions/2896191/what-is-go-used-fore" ,
` <p><a href="https://stackoverflow.com/questions/2896191/what-is-go-used-fore" rel="nofollow">https://stackoverflow.com/questions/2896191/what-is-go-used-fore</a></p> ` )
test (
"https://username:password@gitea.com" ,
` <p><a href="https://username:password@gitea.com" rel="nofollow">https://username:password@gitea.com</a></p> ` )
2019-10-15 09:31:09 +08:00
test (
"ftp://gitea.com/file.txt" ,
` <p><a href="ftp://gitea.com/file.txt" rel="nofollow">ftp://gitea.com/file.txt</a></p> ` )
test (
"magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" ,
2021-07-09 09:30:31 +08:00
` <p><a href="magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download" rel="nofollow">magnet:?xt=urn:btih:5dee65101db281ac9c46344cd6b175cdcadabcde&dn=download</a></p> ` )
2024-02-21 18:08:08 +08:00
test (
` [link](https://example.com) ` ,
` <p><a href="https://example.com" rel="nofollow">link</a></p> ` )
test (
` [link](mailto:test@example.com) ` ,
` <p><a href="mailto:test@example.com" rel="nofollow">link</a></p> ` )
test (
` [link](javascript:xss) ` ,
` <p>link</p> ` )
2019-02-28 20:31:53 +08:00
// Test that should *not* be turned into URL
test (
"www.example.com" ,
` <p>www.example.com</p> ` )
test (
"example.com" ,
` <p>example.com</p> ` )
test (
"test.example.com" ,
` <p>test.example.com</p> ` )
test (
"http://" ,
` <p>http://</p> ` )
test (
"https://" ,
` <p>https://</p> ` )
test (
"://" ,
` <p>://</p> ` )
test (
"www" ,
` <p>www</p> ` )
2019-10-15 09:31:09 +08:00
test (
"ftps://gitea.com" ,
` <p>ftps://gitea.com</p> ` )
2019-02-28 20:31:53 +08:00
}
2019-04-07 19:18:16 +08:00
func TestRender_email ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2024-11-14 13:02:11 +08:00
defer testModule . MockVariableValue ( & markup . RenderBehaviorForTesting . DisableInternalAttributes , true ) ( )
2019-04-07 19:18:16 +08:00
test := func ( input , expected string ) {
2023-10-24 10:54:59 +08:00
res , err := markup . RenderString ( & markup . RenderContext {
2023-03-06 05:59:05 +08:00
Ctx : git . DefaultContext ,
2022-06-16 11:33:23 +08:00
RelativePath : "a.md" ,
2024-01-15 16:49:24 +08:00
Links : markup . Links {
Base : markup . TestRepoURL ,
} ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2024-11-14 13:02:11 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( res ) )
2019-04-07 19:18:16 +08:00
}
// Text that should be turned into email link
test (
"info@gitea.com" ,
` <p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a></p> ` )
test (
"(info@gitea.com)" ,
` <p>(<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>)</p> ` )
test (
"[info@gitea.com]" ,
` <p>[<a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>]</p> ` )
test (
"info@gitea.com." ,
` <p><a href="mailto:info@gitea.com" rel="nofollow">info@gitea.com</a>.</p> ` )
2019-04-25 09:53:42 +08:00
test (
"firstname+lastname@gitea.com" ,
` <p><a href="mailto:firstname+lastname@gitea.com" rel="nofollow">firstname+lastname@gitea.com</a></p> ` )
2019-04-07 19:18:16 +08:00
test (
"send email to info@gitea.co.uk." ,
` <p>send email to <a href="mailto:info@gitea.co.uk" rel="nofollow">info@gitea.co.uk</a>.</p> ` )
2023-11-11 12:08:19 +08:00
test (
` j . doe @ example . com ,
j . doe @ example . com .
j . doe @ example . com ;
j . doe @ example . com ?
j . doe @ example . com ! ` ,
2024-11-14 13:02:11 +08:00
` < p > < a href = "mailto:j.doe@example.com" rel = "nofollow" > j . doe @ example . com < / a > ,
< a href = "mailto:j.doe@example.com" rel = "nofollow" > j . doe @ example . com < / a > .
< a href = "mailto:j.doe@example.com" rel = "nofollow" > j . doe @ example . com < / a > ;
< a href = "mailto:j.doe@example.com" rel = "nofollow" > j . doe @ example . com < / a > ?
2023-11-11 12:08:19 +08:00
< a href = "mailto:j.doe@example.com" rel = "nofollow" > j . doe @ example . com < / a > ! < / p > ` )
2019-04-07 19:18:16 +08:00
// Test that should *not* be turned into email links
test (
"\"info@gitea.com\"" ,
2020-06-13 14:10:17 +08:00
` <p>"info@gitea.com"</p> ` )
2019-04-07 19:18:16 +08:00
test (
"/home/gitea/mailstore/info@gitea/com" ,
` <p>/home/gitea/mailstore/info@gitea/com</p> ` )
test (
"git@try.gitea.io:go-gitea/gitea.git" ,
` <p>git@try.gitea.io:go-gitea/gitea.git</p> ` )
2019-04-25 09:53:42 +08:00
test (
"gitea@3" ,
` <p>gitea@3</p> ` )
test (
"gitea@gmail.c" ,
` <p>gitea@gmail.c</p> ` )
test (
"email@domain@domain.com" ,
` <p>email@domain@domain.com</p> ` )
test (
"email@domain..com" ,
` <p>email@domain..com</p> ` )
2019-04-07 19:18:16 +08:00
}
2020-04-29 02:05:39 +08:00
func TestRender_emoji ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
setting . StaticURLPrefix = markup . TestAppURL
2020-04-29 02:05:39 +08:00
test := func ( input , expected string ) {
2020-10-12 04:27:20 +08:00
expected = strings . ReplaceAll ( expected , "&" , "&" )
2023-10-24 10:54:59 +08:00
buffer , err := markup . RenderString ( & markup . RenderContext {
2023-03-06 05:59:05 +08:00
Ctx : git . DefaultContext ,
2022-06-16 11:33:23 +08:00
RelativePath : "a.md" ,
2024-01-15 16:49:24 +08:00
Links : markup . Links {
Base : markup . TestRepoURL ,
} ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2020-04-29 02:05:39 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( buffer ) )
}
// Make sure we can successfully match every emoji in our dataset with regex
for i := range emoji . GemojiData {
test (
emoji . GemojiData [ i ] . Emoji ,
` <p><span class="emoji" aria-label=" ` + emoji . GemojiData [ i ] . Description + ` "> ` + emoji . GemojiData [ i ] . Emoji + ` </span></p> ` )
}
for i := range emoji . GemojiData {
test (
":" + emoji . GemojiData [ i ] . Aliases [ 0 ] + ":" ,
` <p><span class="emoji" aria-label=" ` + emoji . GemojiData [ i ] . Description + ` "> ` + emoji . GemojiData [ i ] . Emoji + ` </span></p> ` )
}
2022-01-21 01:46:10 +08:00
// Text that should be turned into or recognized as emoji
2020-04-29 02:05:39 +08:00
test (
":gitea:" ,
2021-05-07 23:34:33 +08:00
` <p><span class="emoji" aria-label="gitea"><img alt=":gitea:" src=" ` + setting . StaticURLPrefix + ` /assets/img/emoji/gitea.png"/></span></p> ` )
2021-06-29 22:28:38 +08:00
test (
":custom-emoji:" ,
` <p>:custom-emoji:</p> ` )
setting . UI . CustomEmojisMap [ "custom-emoji" ] = ":custom-emoji:"
test (
":custom-emoji:" ,
` <p><span class="emoji" aria-label="custom-emoji"><img alt=":custom-emoji:" src=" ` + setting . StaticURLPrefix + ` /assets/img/emoji/custom-emoji.png"/></span></p> ` )
test (
"这是字符:1::+1: some🐊 \U0001f44d:custom-emoji: :gitea:" ,
` <p>这是字符:1:<span class="emoji" aria-label="thumbs up">👍</span> some<span class="emoji" aria-label="crocodile">🐊</span> ` +
` <span class="emoji" aria-label="thumbs up">👍</span><span class="emoji" aria-label="custom-emoji"><img alt=":custom-emoji:" src=" ` + setting . StaticURLPrefix + ` /assets/img/emoji/custom-emoji.png"/></span> ` +
` <span class="emoji" aria-label="gitea"><img alt=":gitea:" src=" ` + setting . StaticURLPrefix + ` /assets/img/emoji/gitea.png"/></span></p> ` )
2020-04-29 02:05:39 +08:00
test (
"Some text with 😄 in the middle" ,
` <p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle</p> ` )
test (
"Some text with :smile: in the middle" ,
` <p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle</p> ` )
2020-05-30 00:08:36 +08:00
test (
"Some text with 😄😄 2 emoji next to each other" ,
` <p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span><span class="emoji" aria-label="grinning face with smiling eyes">😄</span> 2 emoji next to each other</p> ` )
2020-07-25 21:40:04 +08:00
test (
"😎🤪🔐🤑❓" ,
2022-10-06 02:55:36 +08:00
` <p><span class="emoji" aria-label="smiling face with sunglasses">😎</span><span class="emoji" aria-label="zany face">🤪</span><span class="emoji" aria-label="locked with key">🔐</span><span class="emoji" aria-label="money-mouth face">🤑</span><span class="emoji" aria-label="red question mark">❓</span></p> ` )
2020-07-25 21:40:04 +08:00
2020-04-29 02:05:39 +08:00
// should match nothing
test (
"2001:0db8:85a3:0000:0000:8a2e:0370:7334" ,
` <p>2001:0db8:85a3:0000:0000:8a2e:0370:7334</p> ` )
test (
":not exist:" ,
` <p>:not exist:</p> ` )
}
2018-02-27 15:09:18 +08:00
func TestRender_ShortLinks ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
tree := util . URLJoin ( markup . TestRepoURL , "src" , "master" )
2018-02-27 15:09:18 +08:00
test := func ( input , expected , expectedWiki string ) {
2023-10-24 10:54:59 +08:00
buffer , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
Base : markup . TestRepoURL ,
BranchPath : "master" ,
} ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( string ( buffer ) ) )
2023-10-24 10:54:59 +08:00
buffer , err = markdown . RenderString ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
Base : markup . TestRepoURL ,
} ,
2024-11-14 13:02:11 +08:00
Metas : localMetas ,
ContentMode : markup . RenderContentAsWiki ,
2021-04-20 06:25:08 +08:00
} , input )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , strings . TrimSpace ( expectedWiki ) , strings . TrimSpace ( string ( buffer ) ) )
2018-02-27 15:09:18 +08:00
}
2024-01-15 16:49:24 +08:00
mediatree := util . URLJoin ( markup . TestRepoURL , "media" , "master" )
2018-02-27 15:09:18 +08:00
url := util . URLJoin ( tree , "Link" )
2018-03-06 02:39:12 +08:00
otherURL := util . URLJoin ( tree , "Other-Link" )
2018-06-15 20:42:49 +08:00
encodedURL := util . URLJoin ( tree , "Link%3F" )
2024-01-15 16:49:24 +08:00
imgurl := util . URLJoin ( mediatree , "Link.jpg" )
otherImgurl := util . URLJoin ( mediatree , "Link+Other.jpg" )
encodedImgurl := util . URLJoin ( mediatree , "Link+%23.jpg" )
notencodedImgurl := util . URLJoin ( mediatree , "some" , "path" , "Link+#.jpg" )
2023-10-24 10:54:59 +08:00
urlWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "Link" )
otherURLWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "Other-Link" )
encodedURLWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "Link%3F" )
imgurlWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "raw" , "Link.jpg" )
otherImgurlWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "raw" , "Link+Other.jpg" )
encodedImgurlWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "raw" , "Link+%23.jpg" )
notencodedImgurlWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "raw" , "some" , "path" , "Link+#.jpg" )
2024-04-11 01:49:57 +08:00
renderableFileURL := util . URLJoin ( tree , "markdown_file.md" )
renderableFileURLWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "markdown_file.md" )
unrenderableFileURL := util . URLJoin ( tree , "file.zip" )
2024-08-16 20:40:51 +08:00
unrenderableFileURLWiki := util . URLJoin ( markup . TestRepoURL , "wiki" , "file.zip" )
2018-02-27 15:09:18 +08:00
favicon := "http://google.com/favicon.ico"
test (
"[[Link]]" ,
` <p><a href=" ` + url + ` " rel="nofollow">Link</a></p> ` ,
` <p><a href=" ` + urlWiki + ` " rel="nofollow">Link</a></p> ` )
2024-06-18 11:09:20 +08:00
test (
"[[Link.-]]" ,
` <p><a href="http://localhost:3000/test-owner/test-repo/src/master/Link.-" rel="nofollow">Link.-</a></p> ` ,
` <p><a href="http://localhost:3000/test-owner/test-repo/wiki/Link.-" rel="nofollow">Link.-</a></p> ` )
2018-02-27 15:09:18 +08:00
test (
"[[Link.jpg]]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="Link.jpg" alt="Link.jpg"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="Link.jpg" alt="Link.jpg"/></a></p> ` )
test (
"[[" + favicon + "]]" ,
2020-02-29 04:05:12 +08:00
` <p><a href=" ` + favicon + ` " rel="nofollow"><img src=" ` + favicon + ` " title="favicon.ico" alt=" ` + favicon + ` "/></a></p> ` ,
` <p><a href=" ` + favicon + ` " rel="nofollow"><img src=" ` + favicon + ` " title="favicon.ico" alt=" ` + favicon + ` "/></a></p> ` )
2018-02-27 15:09:18 +08:00
test (
"[[Name|Link]]" ,
` <p><a href=" ` + url + ` " rel="nofollow">Name</a></p> ` ,
` <p><a href=" ` + urlWiki + ` " rel="nofollow">Name</a></p> ` )
test (
"[[Name|Link.jpg]]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="Name" alt="Name"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="Name" alt="Name"/></a></p> ` )
test (
"[[Name|Link.jpg|alt=AltName]]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="AltName" alt="AltName"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="AltName" alt="AltName"/></a></p> ` )
test (
"[[Name|Link.jpg|title=Title]]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="Title" alt="Title"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="Title" alt="Title"/></a></p> ` )
test (
"[[Name|Link.jpg|alt=AltName|title=Title]]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="Title" alt="AltName"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="Title" alt="AltName"/></a></p> ` )
test (
"[[Name|Link.jpg|alt=\"AltName\"|title='Title']]" ,
` <p><a href=" ` + imgurl + ` " rel="nofollow"><img src=" ` + imgurl + ` " title="Title" alt="AltName"/></a></p> ` ,
` <p><a href=" ` + imgurlWiki + ` " rel="nofollow"><img src=" ` + imgurlWiki + ` " title="Title" alt="AltName"/></a></p> ` )
test (
2018-03-06 02:39:12 +08:00
"[[Name|Link Other.jpg|alt=\"AltName\"|title='Title']]" ,
` <p><a href=" ` + otherImgurl + ` " rel="nofollow"><img src=" ` + otherImgurl + ` " title="Title" alt="AltName"/></a></p> ` ,
` <p><a href=" ` + otherImgurlWiki + ` " rel="nofollow"><img src=" ` + otherImgurlWiki + ` " title="Title" alt="AltName"/></a></p> ` )
test (
"[[Link]] [[Other Link]]" ,
` <p><a href=" ` + url + ` " rel="nofollow">Link</a> <a href=" ` + otherURL + ` " rel="nofollow">Other Link</a></p> ` ,
` <p><a href=" ` + urlWiki + ` " rel="nofollow">Link</a> <a href=" ` + otherURLWiki + ` " rel="nofollow">Other Link</a></p> ` )
2018-06-15 20:42:49 +08:00
test (
"[[Link?]]" ,
` <p><a href=" ` + encodedURL + ` " rel="nofollow">Link?</a></p> ` ,
` <p><a href=" ` + encodedURLWiki + ` " rel="nofollow">Link?</a></p> ` )
test (
"[[Link]] [[Other Link]] [[Link?]]" ,
` <p><a href=" ` + url + ` " rel="nofollow">Link</a> <a href=" ` + otherURL + ` " rel="nofollow">Other Link</a> <a href=" ` + encodedURL + ` " rel="nofollow">Link?</a></p> ` ,
` <p><a href=" ` + urlWiki + ` " rel="nofollow">Link</a> <a href=" ` + otherURLWiki + ` " rel="nofollow">Other Link</a> <a href=" ` + encodedURLWiki + ` " rel="nofollow">Link?</a></p> ` )
2024-04-11 01:49:57 +08:00
test (
"[[markdown_file.md]]" ,
` <p><a href=" ` + renderableFileURL + ` " rel="nofollow">markdown_file.md</a></p> ` ,
` <p><a href=" ` + renderableFileURLWiki + ` " rel="nofollow">markdown_file.md</a></p> ` )
test (
"[[file.zip]]" ,
` <p><a href=" ` + unrenderableFileURL + ` " rel="nofollow">file.zip</a></p> ` ,
` <p><a href=" ` + unrenderableFileURLWiki + ` " rel="nofollow">file.zip</a></p> ` )
2018-06-15 20:42:49 +08:00
test (
"[[Link #.jpg]]" ,
2020-02-29 04:05:12 +08:00
` <p><a href=" ` + encodedImgurl + ` " rel="nofollow"><img src=" ` + encodedImgurl + ` " title="Link #.jpg" alt="Link #.jpg"/></a></p> ` ,
` <p><a href=" ` + encodedImgurlWiki + ` " rel="nofollow"><img src=" ` + encodedImgurlWiki + ` " title="Link #.jpg" alt="Link #.jpg"/></a></p> ` )
2018-06-15 20:42:49 +08:00
test (
"[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]" ,
` <p><a href=" ` + encodedImgurl + ` " rel="nofollow"><img src=" ` + encodedImgurl + ` " title="Title" alt="AltName"/></a></p> ` ,
` <p><a href=" ` + encodedImgurlWiki + ` " rel="nofollow"><img src=" ` + encodedImgurlWiki + ` " title="Title" alt="AltName"/></a></p> ` )
test (
"[[some/path/Link #.jpg]]" ,
2020-02-29 04:05:12 +08:00
` <p><a href=" ` + notencodedImgurl + ` " rel="nofollow"><img src=" ` + notencodedImgurl + ` " title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p> ` ,
` <p><a href=" ` + notencodedImgurlWiki + ` " rel="nofollow"><img src=" ` + notencodedImgurlWiki + ` " title="Link #.jpg" alt="some/path/Link #.jpg"/></a></p> ` )
2019-03-08 03:13:44 +08:00
test (
"<p><a href=\"https://example.org\">[[foobar]]</a></p>" ,
2019-12-31 09:53:28 +08:00
` <p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p> ` ,
` <p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p> ` )
2018-02-27 15:09:18 +08:00
}
2021-01-20 23:10:50 +08:00
2024-06-22 02:23:54 +08:00
func TestRender_RelativeMedias ( t * testing . T ) {
2024-06-04 20:19:41 +08:00
render := func ( input string , isWiki bool , links markup . Links ) string {
2023-10-24 10:54:59 +08:00
buffer , err := markdown . RenderString ( & markup . RenderContext {
2024-11-14 13:02:11 +08:00
Ctx : git . DefaultContext ,
Links : links ,
Metas : localMetas ,
ContentMode : util . Iif ( isWiki , markup . RenderContentAsWiki , markup . RenderContentAsComment ) ,
2021-07-04 17:26:04 +08:00
} , input )
assert . NoError ( t , err )
2024-06-04 20:19:41 +08:00
return strings . TrimSpace ( string ( buffer ) )
2021-07-04 17:26:04 +08:00
}
2024-06-04 20:19:41 +08:00
out := render ( ` <img src="LINK"> ` , false , markup . Links { Base : "/test-owner/test-repo" } )
assert . Equal ( t , ` <a href="/test-owner/test-repo/LINK" target="_blank" rel="nofollow noopener"><img src="/test-owner/test-repo/LINK"/></a> ` , out )
2021-07-04 17:26:04 +08:00
2024-06-04 20:19:41 +08:00
out = render ( ` <img src="LINK"> ` , true , markup . Links { Base : "/test-owner/test-repo" } )
assert . Equal ( t , ` <a href="/test-owner/test-repo/wiki/raw/LINK" target="_blank" rel="nofollow noopener"><img src="/test-owner/test-repo/wiki/raw/LINK"/></a> ` , out )
2021-07-04 17:26:04 +08:00
2024-06-04 20:19:41 +08:00
out = render ( ` <img src="LINK"> ` , false , markup . Links { Base : "/test-owner/test-repo" , BranchPath : "test-branch" } )
assert . Equal ( t , ` <a href="/test-owner/test-repo/media/test-branch/LINK" target="_blank" rel="nofollow noopener"><img src="/test-owner/test-repo/media/test-branch/LINK"/></a> ` , out )
out = render ( ` <img src="LINK"> ` , true , markup . Links { Base : "/test-owner/test-repo" , BranchPath : "test-branch" } )
assert . Equal ( t , ` <a href="/test-owner/test-repo/wiki/raw/LINK" target="_blank" rel="nofollow noopener"><img src="/test-owner/test-repo/wiki/raw/LINK"/></a> ` , out )
out = render ( ` <img src="/LINK"> ` , true , markup . Links { Base : "/test-owner/test-repo" , BranchPath : "test-branch" } )
assert . Equal ( t , ` <img src="/LINK"/> ` , out )
2024-06-22 02:23:54 +08:00
out = render ( ` <video src="LINK"> ` , false , markup . Links { Base : "/test-owner/test-repo" } )
assert . Equal ( t , ` <video src="/test-owner/test-repo/LINK"></video> ` , out )
out = render ( ` <video src="LINK"> ` , true , markup . Links { Base : "/test-owner/test-repo" } )
assert . Equal ( t , ` <video src="/test-owner/test-repo/wiki/raw/LINK"></video> ` , out )
out = render ( ` <video src="/LINK"> ` , false , markup . Links { Base : "/test-owner/test-repo" } )
assert . Equal ( t , ` <video src="/LINK"></video> ` , out )
2021-07-04 17:26:04 +08:00
}
2021-01-20 23:10:50 +08:00
func Test_ParseClusterFuzz ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2021-01-20 23:10:50 +08:00
2022-01-21 01:46:10 +08:00
localMetas := map [ string ] string {
2021-01-20 23:10:50 +08:00
"user" : "go-gitea" ,
"repo" : "gitea" ,
}
data := "<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
2021-04-20 06:25:08 +08:00
var res strings . Builder
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
Base : "https://example.com" ,
} ,
Metas : localMetas ,
2021-04-20 06:25:08 +08:00
} , strings . NewReader ( data ) , & res )
2021-01-20 23:10:50 +08:00
assert . NoError ( t , err )
2021-04-20 06:25:08 +08:00
assert . NotContains ( t , res . String ( ) , "<html" )
2021-01-20 23:10:50 +08:00
data = "<!DOCTYPE html>\n<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
2021-04-20 06:25:08 +08:00
res . Reset ( )
2023-10-24 10:54:59 +08:00
err = markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
Base : "https://example.com" ,
} ,
Metas : localMetas ,
2021-04-20 06:25:08 +08:00
} , strings . NewReader ( data ) , & res )
2021-01-20 23:10:50 +08:00
assert . NoError ( t , err )
2021-04-20 06:25:08 +08:00
assert . NotContains ( t , res . String ( ) , "<html" )
2021-01-20 23:10:50 +08:00
}
2021-06-08 00:55:26 +08:00
2023-08-07 21:11:25 +08:00
func TestPostProcess_RenderDocument ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2024-01-15 16:49:24 +08:00
setting . StaticURLPrefix = markup . TestAppURL // can't run standalone
2024-11-14 13:02:11 +08:00
defer testModule . MockVariableValue ( & markup . RenderBehaviorForTesting . DisableInternalAttributes , true ) ( )
2023-08-07 21:11:25 +08:00
test := func ( input , expected string ) {
var res strings . Builder
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-03-13 18:34:58 +08:00
AbsolutePrefix : true ,
Base : "https://example.com" ,
2024-01-15 16:49:24 +08:00
} ,
2024-11-14 13:02:11 +08:00
Metas : map [ string ] string { "user" : "go-gitea" , "repo" : "gitea" } ,
2023-08-07 21:11:25 +08:00
} , strings . NewReader ( input ) , & res )
assert . NoError ( t , err )
2024-11-14 13:02:11 +08:00
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( res . String ( ) ) )
2023-08-07 21:11:25 +08:00
}
2024-01-03 14:01:12 +08:00
// Issue index shouldn't be post processing in a document.
2023-08-07 21:11:25 +08:00
test (
"#1" ,
"#1" )
2024-01-03 14:01:12 +08:00
// But cross-referenced issue index should work.
test (
"go-gitea/gitea#12345" ,
` <a href=" ` + util . URLJoin ( markup . TestAppURL , "go-gitea" , "gitea" , "issues" , "12345" ) + ` " class="ref-issue">go-gitea/gitea#12345</a> ` )
2023-08-07 21:11:25 +08:00
// Test that other post processing still works.
test (
":gitea:" ,
` <span class="emoji" aria-label="gitea"><img alt=":gitea:" src=" ` + setting . StaticURLPrefix + ` /assets/img/emoji/gitea.png"/></span> ` )
test (
"Some text with 😄 in the middle" ,
` Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle ` )
test ( "http://localhost:3000/person/repo/issues/4#issuecomment-1234" ,
` <a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4 (comment)</a> ` )
}
2021-06-08 00:55:26 +08:00
func TestIssue16020 ( t * testing . T ) {
2023-10-24 10:54:59 +08:00
setting . AppURL = markup . TestAppURL
2021-06-08 00:55:26 +08:00
2022-01-21 01:46:10 +08:00
localMetas := map [ string ] string {
2021-06-08 00:55:26 +08:00
"user" : "go-gitea" ,
"repo" : "gitea" ,
}
data := ` <img src="data:image/png;base64,i//V"/> `
var res strings . Builder
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Metas : localMetas ,
2021-06-08 00:55:26 +08:00
} , strings . NewReader ( data ) , & res )
assert . NoError ( t , err )
assert . Equal ( t , data , res . String ( ) )
}
2021-06-17 18:35:05 +08:00
func BenchmarkEmojiPostprocess ( b * testing . B ) {
data := "🥰 "
for len ( data ) < 1 << 16 {
data += data
}
b . ResetTimer ( )
for i := 0 ; i < b . N ; i ++ {
var res strings . Builder
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Metas : localMetas ,
2021-06-17 18:35:05 +08:00
} , strings . NewReader ( data ) , & res )
assert . NoError ( b , err )
}
}
2021-08-13 06:22:05 +08:00
func TestFuzz ( t * testing . T ) {
s := "t/l/issues/8#/../../a"
2023-10-24 10:54:59 +08:00
renderContext := markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Links : markup . Links {
Base : "https://example.com/go-gitea/gitea" ,
} ,
2021-08-13 06:22:05 +08:00
Metas : map [ string ] string {
"user" : "go-gitea" ,
"repo" : "gitea" ,
} ,
}
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & renderContext , strings . NewReader ( s ) , io . Discard )
2021-08-13 06:22:05 +08:00
assert . NoError ( t , err )
}
2022-01-31 07:48:47 +08:00
func TestIssue18471 ( t * testing . T ) {
data := ` http://domain/org/repo/compare/783b039...da951ce `
var res strings . Builder
2023-10-24 10:54:59 +08:00
err := markup . PostProcess ( & markup . RenderContext {
2024-01-15 16:49:24 +08:00
Ctx : git . DefaultContext ,
Metas : localMetas ,
2022-01-31 07:48:47 +08:00
} , strings . NewReader ( data ) , & res )
assert . NoError ( t , err )
2024-05-04 09:48:16 +08:00
assert . Equal ( t , ` <a href="http://domain/org/repo/compare/783b039...da951ce" class="compare"><code class="nohighlight">783b039...da951ce</code></a> ` , res . String ( ) )
2022-01-31 07:48:47 +08:00
}
2024-02-21 18:08:08 +08:00
func TestIsFullURL ( t * testing . T ) {
assert . True ( t , markup . IsFullURLString ( "https://example.com" ) )
assert . True ( t , markup . IsFullURLString ( "mailto:test@example.com" ) )
2024-06-04 20:19:41 +08:00
assert . True ( t , markup . IsFullURLString ( "data:image/11111" ) )
2024-02-21 18:08:08 +08:00
assert . False ( t , markup . IsFullURLString ( "/foo:bar" ) )
}