2017-04-21 15:01:08 +08:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2017-04-21 15:01:08 +08:00
2016-04-22 17:28:08 -05:00
package markdown_test
import (
2022-06-16 23:47:44 +08:00
"context"
2024-03-01 15:11:51 +08:00
"html/template"
2022-10-05 19:55:36 +01:00
"os"
2017-02-14 08:13:59 +07:00
"strings"
2017-09-17 01:17:57 +08:00
"testing"
2017-02-14 08:13:59 +07:00
2023-06-21 13:50:26 +08:00
"code.gitea.io/gitea/models/unittest"
2022-01-19 23:26:57 +00:00
"code.gitea.io/gitea/modules/git"
2021-10-11 20:12:06 +08:00
"code.gitea.io/gitea/modules/log"
2021-04-20 06:25:08 +08:00
"code.gitea.io/gitea/modules/markup"
2023-10-24 04:54:59 +02:00
"code.gitea.io/gitea/modules/markup/markdown"
2016-11-10 17:24:48 +01:00
"code.gitea.io/gitea/modules/setting"
2024-03-22 20:16:23 +08:00
"code.gitea.io/gitea/modules/svg"
2018-02-20 04:50:42 -08:00
"code.gitea.io/gitea/modules/util"
2017-09-17 01:17:57 +08:00
2017-02-08 01:29:07 -05:00
"github.com/stretchr/testify/assert"
2024-03-22 20:16:23 +08:00
"golang.org/x/text/cases"
"golang.org/x/text/language"
2016-04-22 17:28:08 -05:00
)
2022-01-20 18:46:10 +01:00
const (
2024-02-29 04:39:24 +01:00
AppURL = "http://localhost:3000/"
FullURL = AppURL + "gogits/gogs/"
2022-01-20 18:46:10 +01:00
)
2016-04-22 17:28:08 -05:00
2024-02-29 04:39:24 +01:00
// these values should match the const above
2019-04-12 01:53:34 -04:00
var localMetas = map [ string ] string {
2019-08-14 08:04:55 +00:00
"user" : "gogits" ,
"repo" : "gogs" ,
2022-09-02 15:18:23 -04:00
"repoPath" : "../../../tests/gitea-repositories-meta/user13/repo11.git/" ,
2019-04-12 01:53:34 -04:00
}
2022-06-16 23:47:44 +08:00
func TestMain ( m * testing . M ) {
2023-06-21 13:50:26 +08:00
unittest . InitSettings ( )
2022-06-16 23:47:44 +08:00
if err := git . InitSimple ( context . Background ( ) ) ; err != nil {
log . Fatal ( "git init failed, err: %v" , err )
}
2022-10-22 20:15:52 +03:00
markup . Init ( & markup . ProcessorHelper {
IsUsernameMentionable : func ( ctx context . Context , username string ) bool {
return username == "r-lyeh"
} ,
} )
2022-10-05 19:55:36 +01:00
os . Exit ( m . Run ( ) )
2022-06-16 23:47:44 +08:00
}
2017-02-24 21:59:56 +07:00
func TestRender_StandardLinks ( t * testing . T ) {
2017-02-14 08:13:59 +07:00
setting . AppURL = AppURL
2017-02-24 21:59:56 +07:00
test := func ( input , expected , expectedWiki string ) {
2023-10-24 04:54:59 +02:00
buffer , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
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 ) ) )
2021-04-20 06:25:08 +08:00
2023-10-24 04:54:59 +02:00
buffer , err = markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
IsWiki : true ,
2021-04-20 06:25:08 +08:00
} , input )
2021-07-18 05:09:34 -07:00
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , strings . TrimSpace ( expectedWiki ) , strings . TrimSpace ( string ( buffer ) ) )
2017-02-24 21:59:56 +07:00
}
googleRendered := ` <p><a href="https://google.com/" rel="nofollow">https://google.com/</a></p> `
test ( "<https://google.com/>" , googleRendered , googleRendered )
2024-02-29 04:39:24 +01:00
lnk := util . URLJoin ( FullURL , "WikiPage" )
lnkWiki := util . URLJoin ( FullURL , "wiki" , "WikiPage" )
2017-02-24 21:59:56 +07:00
test ( "[WikiPage](WikiPage)" ,
` <p><a href=" ` + lnk + ` " rel="nofollow">WikiPage</a></p> ` ,
` <p><a href=" ` + lnkWiki + ` " rel="nofollow">WikiPage</a></p> ` )
}
func TestRender_Images ( t * testing . T ) {
setting . AppURL = AppURL
test := func ( input , expected string ) {
2023-10-24 04:54:59 +02:00
buffer , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
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 ) ) )
2017-02-24 21:59:56 +07:00
}
url := "../../.images/src/02/train.jpg"
title := "Train"
2018-10-30 17:26:28 -05:00
href := "https://gitea.io"
2024-02-29 04:39:24 +01:00
result := util . URLJoin ( FullURL , url )
2021-10-11 20:12:06 +08:00
// hint: With Markdown v2.5.2, there is a new syntax: [link](URL){:target="_blank"} , but we do not support it now
2017-02-24 21:59:56 +07:00
test (
"" ,
2021-10-11 20:12:06 +08:00
` <p><a href=" ` + result + ` " target="_blank" rel="nofollow noopener"><img src=" ` + result + ` " alt=" ` + title + ` "/></a></p> ` )
2017-02-24 21:59:56 +07:00
test (
"[[" + title + "|" + url + "]]" ,
2018-02-27 08:09:18 +01:00
` <p><a href=" ` + result + ` " rel="nofollow"><img src=" ` + result + ` " title=" ` + title + ` " alt=" ` + title + ` "/></a></p> ` )
2018-10-30 17:26:28 -05:00
test (
"[](" + href + ")" ,
` <p><a href=" ` + href + ` " rel="nofollow"><img src=" ` + result + ` " alt=" ` + title + ` "/></a></p> ` )
2021-04-10 17:26:28 +01:00
test (
"" ,
2021-10-11 20:12:06 +08:00
` <p><a href=" ` + result + ` " target="_blank" rel="nofollow noopener"><img src=" ` + result + ` " alt=" ` + title + ` "/></a></p> ` )
2021-04-10 17:26:28 +01:00
test (
"[[" + title + "|" + url + "]]" ,
` <p><a href=" ` + result + ` " rel="nofollow"><img src=" ` + result + ` " title=" ` + title + ` " alt=" ` + title + ` "/></a></p> ` )
test (
"[](" + href + ")" ,
` <p><a href=" ` + href + ` " rel="nofollow"><img src=" ` + result + ` " alt=" ` + title + ` "/></a></p> ` )
2017-02-14 08:13:59 +07:00
}
2017-02-24 21:59:56 +07:00
func testAnswers ( baseURLContent , baseURLImages string ) [ ] string {
return [ ] string {
` <p>Wiki! Enjoy :)</p>
<ul>
2017-07-06 12:05:35 -04:00
<li><a href=" ` + baseURLContent + ` /Links" rel="nofollow">Links, Language bindings, Engine bindings</a></li>
<li><a href=" ` + baseURLContent + ` /Tips" rel="nofollow">Tips</a></li>
2017-02-24 21:59:56 +07:00
</ul>
2024-03-13 11:34:58 +01:00
<p>See commit <a href="/gogits/gogs/commit/65f1bf27bc" rel="nofollow"><code>65f1bf27bc</code></a></p>
2017-02-24 21:59:56 +07:00
<p>Ideas and codes</p>
<ul>
2024-03-13 11:34:58 +01:00
<li>Bezier widget (by <a href="/r-lyeh" rel="nofollow">@r-lyeh</a>) <a href="http://localhost:3000/ocornut/imgui/issues/786" class="ref-issue" rel="nofollow">ocornut/imgui#786</a></li>
<li>Bezier widget (by <a href="/r-lyeh" rel="nofollow">@r-lyeh</a>) <a href="http://localhost:3000/gogits/gogs/issues/786" class="ref-issue" rel="nofollow">#786</a></li>
2018-02-27 08:09:18 +01:00
<li>Node graph editors <a href="https://github.com/ocornut/imgui/issues/306" rel="nofollow">https://github.com/ocornut/imgui/issues/306</a></li>
2017-07-06 12:05:35 -04:00
<li><a href=" ` + baseURLContent + ` /memory_editor_example" rel="nofollow">Memory Editor</a></li>
<li><a href=" ` + baseURLContent + ` /plot_var_example" rel="nofollow">Plot var helper</a></li>
2017-02-24 21:59:56 +07:00
</ul>
` ,
2019-12-23 16:38:50 -06:00
` <h2 id="user-content-what-is-wine-staging">What is Wine Staging?</h2>
2017-02-14 08:13:59 +07:00
<p><strong>Wine Staging</strong> on website <a href="http://wine-staging.com" rel="nofollow">wine-staging.com</a>.</p>
2019-12-23 16:38:50 -06:00
<h2 id="user-content-quick-links">Quick Links</h2>
2017-02-14 08:13:59 +07:00
<p>Here are some links to the most important topics. You can find the full list of pages at the sidebar.</p>
<table>
<thead>
<tr>
2018-02-27 08:09:18 +01:00
<th><a href=" ` + baseURLImages + ` /images/icon-install.png" rel="nofollow"><img src=" ` + baseURLImages + ` /images/icon-install.png" title="icon-install.png" alt="images/icon-install.png"/></a></th>
2017-07-06 12:05:35 -04:00
<th><a href=" ` + baseURLContent + ` /Installation" rel="nofollow">Installation</a></th>
2017-02-14 08:13:59 +07:00
</tr>
</thead>
<tbody>
<tr>
2018-02-27 08:09:18 +01:00
<td><a href=" ` + baseURLImages + ` /images/icon-usage.png" rel="nofollow"><img src=" ` + baseURLImages + ` /images/icon-usage.png" title="icon-usage.png" alt="images/icon-usage.png"/></a></td>
2017-07-06 12:05:35 -04:00
<td><a href=" ` + baseURLContent + ` /Usage" rel="nofollow">Usage</a></td>
2017-02-14 08:13:59 +07:00
</tr>
</tbody>
</table>
` ,
2017-02-24 21:59:56 +07:00
` <p><a href="http://www.excelsiorjet.com/" rel="nofollow">Excelsior JET</a> allows you to create native executables for Windows, Linux and Mac OS X.</p>
2017-02-14 08:13:59 +07:00
<ol>
2020-04-22 00:13:56 +02:00
<li><a href="https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop" rel="nofollow">Package your libGDX application</a><br/>
2018-02-27 08:09:18 +01:00
<a href=" ` + baseURLImages + ` /images/1.png" rel="nofollow"><img src=" ` + baseURLImages + ` /images/1.png" title="1.png" alt="images/1.png"/></a></li>
2020-04-22 00:13:56 +02:00
<li>Perform a test run by hitting the Run! button.<br/>
2018-02-27 08:09:18 +01:00
<a href=" ` + baseURLImages + ` /images/2.png" rel="nofollow"><img src=" ` + baseURLImages + ` /images/2.png" title="2.png" alt="images/2.png"/></a></li>
2017-02-14 08:13:59 +07:00
</ol>
2019-12-23 16:38:50 -06:00
<h2 id="user-content-custom-id">More tests</h2>
2019-03-21 14:53:06 +01:00
<p>(from <a href="https://www.markdownguide.org/extended-syntax/" rel="nofollow">https://www.markdownguide.org/extended-syntax/</a>)</p>
2020-05-03 21:17:24 +01:00
<h3 id="user-content-checkboxes">Checkboxes</h3>
2020-05-11 00:14:49 +01:00
<ul>
2021-05-23 16:14:03 +02:00
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="434"/>unchecked</li>
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="450" checked=""/>checked</li>
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="464"/>still unchecked</li>
2020-05-03 21:17:24 +01:00
</ul>
2019-12-23 16:38:50 -06:00
<h3 id="user-content-definition-list">Definition list</h3>
2019-03-21 14:53:06 +01:00
<dl>
<dt>First Term</dt>
<dd>This is the definition of the first term.</dd>
<dt>Second Term</dt>
<dd>This is one definition of the second term.</dd>
<dd>This is another definition of the second term.</dd>
</dl>
2019-12-23 16:38:50 -06:00
<h3 id="user-content-footnotes">Footnotes</h3>
<p>Here is a simple footnote,<sup id="fnref:user-content-1"><a href="#fn:user-content-1" rel="nofollow">1</a></sup> and here is a longer one.<sup id="fnref:user-content-bignote"><a href="#fn:user-content-bignote" rel="nofollow">2</a></sup></p>
2019-03-21 14:53:06 +01:00
<div>
<hr/>
<ol>
2019-12-31 01:53:28 +00:00
<li id="fn:user-content-1">
<p>This is the first footnote. <a href="#fnref:user-content-1" rel="nofollow">↩︎</a></p>
</li>
<li id="fn:user-content-bignote">
<p>Here is one with multiple paragraphs and code.</p>
2019-03-21 14:53:06 +01:00
<p>Indent paragraphs to include them in the footnote.</p>
<p><code> { my code }</code></p>
2019-12-31 01:53:28 +00:00
<p>Add as many paragraphs as you like. <a href="#fnref:user-content-bignote" rel="nofollow">↩︎</a></p>
</li>
2019-03-21 14:53:06 +01:00
</ol>
</div>
2022-03-24 16:47:37 +01:00
` , ` <ul>
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="3"/> If you want to rebase/retry this PR, click this checkbox.</li>
</ul>
<hr/>
<p>This PR has been generated by <a href="https://github.com/renovatebot/renovate" rel="nofollow">Renovate Bot</a>.</p>
2017-02-14 08:13:59 +07:00
` ,
2017-02-24 21:59:56 +07:00
}
2017-02-14 08:13:59 +07:00
}
2017-09-17 01:17:57 +08:00
// Test cases without ambiguous links
var sameCases = [ ] string {
// dear imgui wiki markdown extract: special wiki syntax
` Wiki! Enjoy :)
- [[Links, Language bindings, Engine bindings|Links]]
- [[Tips]]
2017-02-24 21:59:56 +07:00
2019-08-14 08:04:55 +00:00
See commit 65f1bf27bc
2019-04-16 03:53:57 -04:00
2017-09-17 01:17:57 +08:00
Ideas and codes
2017-02-14 08:13:59 +07:00
2017-09-17 01:17:57 +08:00
- Bezier widget (by @r-lyeh) ` + AppURL + ` ocornut/imgui/issues/786
2019-04-12 01:53:34 -04:00
- Bezier widget (by @r-lyeh) ` + AppURL + ` gogits/gogs/issues/786
2017-09-17 01:17:57 +08:00
- Node graph editors https://github.com/ocornut/imgui/issues/306
- [[Memory Editor|memory_editor_example]]
- [[Plot var helper|plot_var_example]] ` ,
// wine-staging wiki home extract: tables, special wiki syntax, images
` ## What is Wine Staging?
**Wine Staging** on website [wine-staging.com](http://wine-staging.com).
2017-02-14 08:13:59 +07:00
2017-09-17 01:17:57 +08:00
## Quick Links
Here are some links to the most important topics. You can find the full list of pages at the sidebar.
| [[images/icon-install.png]] | [[Installation]] |
|--------------------------------|----------------------------------------------------------|
| [[images/icon-usage.png]] | [[Usage]] |
` ,
// libgdx wiki page: inline images with special syntax
` [Excelsior JET](http://www.excelsiorjet.com/) allows you to create native executables for Windows, Linux and Mac OS X.
1. [Package your libGDX application](https://github.com/libgdx/libgdx/wiki/Gradle-on-the-Commandline#packaging-for-the-desktop)
[[images/1.png]]
2. Perform a test run by hitting the Run! button.
2019-03-21 14:53:06 +01:00
[[images/2.png]]
## More tests { #custom-id}
(from https://www.markdownguide.org/extended-syntax/)
2020-05-03 21:17:24 +01:00
### Checkboxes
- [ ] unchecked
- [x] checked
- [ ] still unchecked
2019-03-21 14:53:06 +01:00
### Definition list
First Term
: This is the definition of the first term.
Second Term
: This is one definition of the second term.
: This is another definition of the second term.
### Footnotes
Here is a simple footnote,[^1] and here is a longer one.[^bignote]
[^1]: This is the first footnote.
[^bignote]: Here is one with multiple paragraphs and code.
Indent paragraphs to include them in the footnote.
` + "`{ my code }`" + `
Add as many paragraphs as you like.
` ,
2022-03-24 16:47:37 +01:00
`
- [ ] <!-- rebase-check --> If you want to rebase/retry this PR, click this checkbox.
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!-- test-comment --> ` ,
2017-02-14 08:13:59 +07:00
}
func TestTotal_RenderWiki ( t * testing . T ) {
2021-05-09 15:29:49 +02:00
setting . AppURL = AppURL
2024-02-29 04:39:24 +01:00
answers := testAnswers ( util . URLJoin ( FullURL , "wiki" ) , util . URLJoin ( FullURL , "wiki" , "raw" ) )
2017-02-24 21:59:56 +07:00
for i := 0 ; i < len ( sameCases ) ; i ++ {
2023-10-24 04:54:59 +02:00
line , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
Metas : localMetas ,
IsWiki : true ,
2021-04-20 06:25:08 +08:00
} , sameCases [ i ] )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( answers [ i ] ) , line )
2017-02-14 08:13:59 +07:00
}
testCases := [ ] string {
// Guard wiki sidebar: special syntax
` [[Guardfile-DSL / Configuring-Guard|Guardfile-DSL---Configuring-Guard]] ` ,
// rendered
2024-02-29 04:39:24 +01:00
` <p><a href=" ` + FullURL + ` wiki/Guardfile-DSL---Configuring-Guard" rel="nofollow">Guardfile-DSL / Configuring-Guard</a></p>
2017-02-14 08:13:59 +07:00
` ,
// special syntax
` [[Name|Link]] ` ,
// rendered
2024-02-29 04:39:24 +01:00
` <p><a href=" ` + FullURL + ` wiki/Link" rel="nofollow">Name</a></p>
2017-02-14 08:13:59 +07:00
` ,
}
for i := 0 ; i < len ( testCases ) ; i += 2 {
2023-10-24 04:54:59 +02:00
line , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
IsWiki : true ,
2021-04-20 06:25:08 +08:00
} , testCases [ i ] )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( testCases [ i + 1 ] ) , line )
2017-02-14 08:13:59 +07:00
}
2016-04-22 17:28:08 -05:00
}
2017-09-17 01:17:57 +08:00
func TestTotal_RenderString ( t * testing . T ) {
2021-05-09 15:29:49 +02:00
setting . AppURL = AppURL
2024-02-29 04:39:24 +01:00
answers := testAnswers ( util . URLJoin ( FullURL , "src" , "master" ) , util . URLJoin ( FullURL , "media" , "master" ) )
2017-09-17 01:17:57 +08:00
for i := 0 ; i < len ( sameCases ) ; i ++ {
2023-10-24 04:54:59 +02:00
line , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
BranchPath : "master" ,
} ,
Metas : localMetas ,
2021-04-20 06:25:08 +08:00
} , sameCases [ i ] )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( answers [ i ] ) , line )
2017-09-17 01:17:57 +08:00
}
testCases := [ ] string { }
for i := 0 ; i < len ( testCases ) ; i += 2 {
2023-10-24 04:54:59 +02:00
line , err := markdown . RenderString ( & markup . RenderContext {
2024-01-15 09:49:24 +01:00
Ctx : git . DefaultContext ,
Links : markup . Links {
2024-02-29 04:39:24 +01:00
Base : FullURL ,
2024-01-15 09:49:24 +01:00
} ,
2021-04-20 06:25:08 +08:00
} , testCases [ i ] )
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( testCases [ i + 1 ] ) , line )
2017-09-17 01:17:57 +08:00
}
}
2019-11-12 23:27:11 -03:00
func TestRender_RenderParagraphs ( t * testing . T ) {
test := func ( t * testing . T , str string , cnt int ) {
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderRawString ( & markup . RenderContext { Ctx : git . DefaultContext } , str )
2021-04-20 06:25:08 +08:00
assert . NoError ( t , err )
assert . Equal ( t , cnt , strings . Count ( res , "<p" ) , "Rendered result for unix should have %d paragraph(s) but has %d:\n%s\n" , cnt , strings . Count ( res , "<p" ) , res )
mac := strings . ReplaceAll ( str , "\n" , "\r" )
2023-10-24 04:54:59 +02:00
res , err = markdown . RenderRawString ( & markup . RenderContext { Ctx : git . DefaultContext } , mac )
2021-04-20 06:25:08 +08:00
assert . NoError ( t , err )
assert . Equal ( t , cnt , strings . Count ( res , "<p" ) , "Rendered result for mac should have %d paragraph(s) but has %d:\n%s\n" , cnt , strings . Count ( res , "<p" ) , res )
dos := strings . ReplaceAll ( str , "\n" , "\r\n" )
2023-10-24 04:54:59 +02:00
res , err = markdown . RenderRawString ( & markup . RenderContext { Ctx : git . DefaultContext } , dos )
2021-04-20 06:25:08 +08:00
assert . NoError ( t , err )
assert . Equal ( t , cnt , strings . Count ( res , "<p" ) , "Rendered result for windows should have %d paragraph(s) but has %d:\n%s\n" , cnt , strings . Count ( res , "<p" ) , res )
2019-11-12 23:27:11 -03:00
}
test ( t , "\nOne\nTwo\nThree" , 1 )
test ( t , "\n\nOne\nTwo\nThree" , 1 )
test ( t , "\n\nOne\nTwo\nThree\n\n\n" , 1 )
test ( t , "A\n\nB\nC\n" , 2 )
test ( t , "A\n\n\nB\nC\n" , 2 )
}
2021-03-14 16:36:51 +00:00
2021-03-15 23:20:05 +00:00
func TestMarkdownRenderRaw ( t * testing . T ) {
testcases := [ ] [ ] byte {
{ // clusterfuzz_testcase_minimized_fuzz_markdown_render_raw_6267570554535936
0x2a , 0x20 , 0x2d , 0x0a , 0x09 , 0x20 , 0x60 , 0x5b , 0x0a , 0x09 , 0x20 , 0x60 ,
0x5b ,
} ,
{ // clusterfuzz_testcase_minimized_fuzz_markdown_render_raw_6278827345051648
0x2d , 0x20 , 0x2d , 0x0d , 0x09 , 0x60 , 0x0d , 0x09 , 0x60 ,
} ,
{ // clusterfuzz_testcase_minimized_fuzz_markdown_render_raw_6016973788020736[] = {
0x7b , 0x63 , 0x6c , 0x61 , 0x73 , 0x73 , 0x3d , 0x35 , 0x7d , 0x0a , 0x3d ,
} ,
}
for _ , testcase := range testcases {
2021-10-11 20:12:06 +08:00
log . Info ( "Test markdown render error with fuzzy data: %x, the following errors can be recovered" , testcase )
2023-10-24 04:54:59 +02:00
_ , err := markdown . RenderRawString ( & markup . RenderContext { Ctx : git . DefaultContext } , string ( testcase ) )
2021-04-20 06:25:08 +08:00
assert . NoError ( t , err )
2021-03-15 23:20:05 +00:00
}
}
2021-03-14 16:36:51 +00:00
func TestRenderSiblingImages_Issue12925 ( t * testing . T ) {
testcase := ` 

`
2021-10-11 20:12:06 +08:00
expected := ` <p><a href="/image1" target="_blank" rel="nofollow noopener"><img src="/image1" alt="image1"></a><br>
<a href="/image2" target="_blank" rel="nofollow noopener"><img src="/image2" alt="image2"></a></p>
2021-03-14 16:36:51 +00:00
`
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderRawString ( & markup . RenderContext { Ctx : git . DefaultContext } , testcase )
2021-04-20 06:25:08 +08:00
assert . NoError ( t , err )
2021-03-14 16:36:51 +00:00
assert . Equal ( t , expected , res )
2021-12-16 00:49:12 +01:00
}
2021-03-15 23:20:05 +00:00
2021-12-16 00:49:12 +01:00
func TestRenderEmojiInLinks_Issue12331 ( t * testing . T ) {
testcase := ` [Link with emoji :moon: in text](https://gitea.io) `
expected := ` <p><a href="https://gitea.io" rel="nofollow">Link with emoji <span class="emoji" aria-label="waxing gibbous moon">🌔</span> in text</a></p>
`
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderString ( & markup . RenderContext { Ctx : git . DefaultContext } , testcase )
2021-12-16 00:49:12 +01:00
assert . NoError ( t , err )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( expected ) , res )
2021-03-14 16:36:51 +00:00
}
2022-10-05 19:55:36 +01:00
2022-10-21 15:00:53 +03:00
func TestColorPreview ( t * testing . T ) {
const nl = "\n"
positiveTests := [ ] struct {
testcase string
expected string
} {
2024-03-31 19:17:34 +08:00
{ // do not render color names
"The CSS class `red` is there" ,
"<p>The CSS class <code>red</code> is there</p>\n" ,
} ,
2022-10-21 15:00:53 +03:00
{ // hex
"`#FF0000`" ,
` <p><code>#FF0000<span class="color-preview" style="background-color: #FF0000"></span></code></p> ` + nl ,
} ,
{ // rgb
"`rgb(16, 32, 64)`" ,
` <p><code>rgb(16, 32, 64)<span class="color-preview" style="background-color: rgb(16, 32, 64)"></span></code></p> ` + nl ,
} ,
{ // short hex
2024-03-31 19:17:34 +08:00
"This is the color white `#0a0`" ,
` <p>This is the color white <code>#0a0<span class="color-preview" style="background-color: #0a0"></span></code></p> ` + nl ,
2022-10-21 15:00:53 +03:00
} ,
{ // hsl
"HSL stands for hue, saturation, and lightness. An example: `hsl(0, 100%, 50%)`." ,
` <p>HSL stands for hue, saturation, and lightness. An example: <code>hsl(0, 100%, 50%)<span class="color-preview" style="background-color: hsl(0, 100%, 50%)"></span></code>.</p> ` + nl ,
} ,
{ // uppercase hsl
"HSL stands for hue, saturation, and lightness. An example: `HSL(0, 100%, 50%)`." ,
` <p>HSL stands for hue, saturation, and lightness. An example: <code>HSL(0, 100%, 50%)<span class="color-preview" style="background-color: HSL(0, 100%, 50%)"></span></code>.</p> ` + nl ,
} ,
}
for _ , test := range positiveTests {
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderString ( & markup . RenderContext { Ctx : git . DefaultContext } , test . testcase )
2022-10-21 15:00:53 +03:00
assert . NoError ( t , err , "Unexpected error in testcase: %q" , test . testcase )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( test . expected ) , res , "Unexpected result in testcase %q" , test . testcase )
2022-10-21 15:00:53 +03:00
}
negativeTests := [ ] string {
// not a color code
"`FF0000`" ,
// inside a code block
"```javascript" + nl + ` const red = "#FF0000"; ` + nl + "```" ,
// no backticks
"rgb(166, 32, 64)" ,
// typo
"`hsI(0, 100%, 50%)`" ,
// looks like a color but not really
"`hsl(40, 60, 80)`" ,
}
for _ , test := range negativeTests {
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderString ( & markup . RenderContext { Ctx : git . DefaultContext } , test )
2022-10-21 15:00:53 +03:00
assert . NoError ( t , err , "Unexpected error in testcase: %q" , test )
assert . NotContains ( t , res , ` <span class="color-preview" style="background-color: ` , "Unexpected result in testcase %q" , test )
}
}
2022-10-05 19:55:36 +01:00
func TestMathBlock ( t * testing . T ) {
const nl = "\n"
testcases := [ ] struct {
testcase string
expected string
} {
{
"$a$" ,
` <p><code class="language-math is-loading">a</code></p> ` + nl ,
} ,
{
"$ a $" ,
` <p><code class="language-math is-loading">a</code></p> ` + nl ,
} ,
{
"$a$ $b$" ,
` <p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p> ` + nl ,
} ,
{
` \(a\) \(b\) ` ,
` <p><code class="language-math is-loading">a</code> <code class="language-math is-loading">b</code></p> ` + nl ,
} ,
2024-04-02 19:15:40 +01:00
{
` $a$. ` ,
` <p><code class="language-math is-loading">a</code>.</p> ` + nl ,
} ,
{
` .$a$ ` ,
` <p>.$a$</p> ` + nl ,
} ,
2022-10-05 19:55:36 +01:00
{
` $a a$b b$ ` ,
2024-04-02 19:15:40 +01:00
` <p>$a a$b b$</p> ` + nl ,
2022-10-05 19:55:36 +01:00
} ,
{
` a a$b b ` ,
` <p>a a$b b</p> ` + nl ,
} ,
{
` a$b $a a$b b$ ` ,
2024-04-02 19:15:40 +01:00
` <p>a$b $a a$b b$</p> ` + nl ,
} ,
{
"a$x$" ,
` <p>a$x$</p> ` + nl ,
} ,
{
"$x$a" ,
` <p>$x$a</p> ` + nl ,
2022-10-05 19:55:36 +01:00
} ,
{
"$$a$$" ,
` <pre class="code-block is-loading"><code class="chroma language-math display">a</code></pre> ` + nl ,
} ,
}
for _ , test := range testcases {
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderString ( & markup . RenderContext { Ctx : git . DefaultContext } , test . testcase )
2022-10-05 19:55:36 +01:00
assert . NoError ( t , err , "Unexpected error in testcase: %q" , test . testcase )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( test . expected ) , res , "Unexpected result in testcase %q" , test . testcase )
2022-10-05 19:55:36 +01:00
}
}
2023-06-13 02:44:47 -04:00
func TestTaskList ( t * testing . T ) {
testcases := [ ] struct {
testcase string
expected string
} {
{
// data-source-position should take into account YAML frontmatter.
` ---
foo: bar
---
- [ ] task 1 ` ,
` <details><summary><i class="icon table"></i></summary><table>
<thead>
<tr>
<th>foo</th>
</tr>
</thead>
<tbody>
<tr>
<td>bar</td>
</tr>
</tbody>
</table>
</details><ul>
<li class="task-list-item"><input type="checkbox" disabled="" data-source-position="19"/>task 1</li>
</ul>
` ,
} ,
}
for _ , test := range testcases {
2023-10-24 04:54:59 +02:00
res , err := markdown . RenderString ( & markup . RenderContext { Ctx : git . DefaultContext } , test . testcase )
2023-06-13 02:44:47 -04:00
assert . NoError ( t , err , "Unexpected error in testcase: %q" , test . testcase )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( test . expected ) , res , "Unexpected result in testcase %q" , test . testcase )
2023-06-13 02:44:47 -04:00
}
}
2024-01-15 09:49:24 +01:00
func TestRenderLinks ( t * testing . T ) {
2024-03-01 15:11:51 +08:00
input := ` space @mention-user$ { SPACE}$ { SPACE}
2024-01-15 09:49:24 +01:00
/just/a/path.bin
https://example.com/file.bin
[local link](file.bin)
[remote link](https://example.com)
[[local link|file.bin]]
[[remote link|https://example.com]]

2024-01-27 04:36:01 +01:00


2024-01-15 09:49:24 +01:00

[[local image|image.jpg]]
[[remote link|https://example.com/image.jpg]]
https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
:+1:
mail@domain.com
@mention-user test
#123
2024-03-01 15:11:51 +08:00
space$ { SPACE}$ { SPACE}
2024-01-15 09:49:24 +01:00
`
2024-03-01 15:11:51 +08:00
input = strings . ReplaceAll ( input , "${SPACE}" , " " ) // replace ${SPACE} with " ", to avoid some editor's auto-trimming
2024-01-15 09:49:24 +01:00
cases := [ ] struct {
Links markup . Links
IsWiki bool
Expected string
} {
{ // 0
Links : markup . Links { } ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/src/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/image.jpg" target="_blank" rel="nofollow noopener"><img src="/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
<a href="/path/file" target="_blank" rel="nofollow noopener"><img src="/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/image.jpg" rel="nofollow"><img src="/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 1
Links : markup . Links { } ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/wiki/raw/image.jpg" rel="nofollow"><img src="/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 2
Links : markup . Links {
Base : "https://gitea.io/" ,
} ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="https://gitea.io/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/src/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
<a href="https://gitea.io/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="https://gitea.io/image.jpg" rel="nofollow"><img src="https://gitea.io/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 3
Links : markup . Links {
Base : "https://gitea.io/" ,
} ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="https://gitea.io/wiki/raw/image.jpg" rel="nofollow"><img src="https://gitea.io/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 4
Links : markup . Links {
Base : "/relative/path" ,
} ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/src/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
<a href="/relative/path/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/relative/path/image.jpg" rel="nofollow"><img src="/relative/path/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 5
Links : markup . Links {
Base : "/relative/path" ,
} ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 6
Links : markup . Links {
Base : "/user/repo" ,
BranchPath : "branch/main" ,
} ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-01-25 09:54:44 +01:00
<a href="/user/repo/src/branch/main/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/src/branch/main/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/media/branch/main/image.jpg" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
<a href="/user/repo/media/branch/main/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/user/repo/media/branch/main/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 7
Links : markup . Links {
Base : "/relative/path" ,
BranchPath : "branch/main" ,
} ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 8
Links : markup . Links {
Base : "/user/repo" ,
TreePath : "sub/folder" ,
} ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/user/repo/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/src/sub/folder/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/image.jpg" target="_blank" rel="nofollow noopener"><img src="/user/repo/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
<a href="/user/repo/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/user/repo/image.jpg" rel="nofollow"><img src="/user/repo/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 9
Links : markup . Links {
Base : "/relative/path" ,
TreePath : "sub/folder" ,
} ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 10
Links : markup . Links {
Base : "/user/repo" ,
BranchPath : "branch/main" ,
TreePath : "sub/folder" ,
} ,
IsWiki : false ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-01-25 09:54:44 +01:00
<a href="/user/repo/src/branch/main/sub/folder/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/src/branch/main/sub/folder/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
<a href="/user/repo/media/branch/main/sub/folder/path/file" target="_blank" rel="nofollow noopener"><img src="/user/repo/media/branch/main/sub/folder/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/user/repo/media/branch/main/sub/folder/image.jpg" rel="nofollow"><img src="/user/repo/media/branch/main/sub/folder/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
{ // 11
Links : markup . Links {
Base : "/relative/path" ,
BranchPath : "branch/main" ,
TreePath : "sub/folder" ,
} ,
IsWiki : true ,
Expected : ` <p>space @mention-user<br/>
/just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
2024-04-10 18:49:57 +01:00
<a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
2024-01-27 04:36:01 +01:00
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
2024-01-15 09:49:24 +01:00
<a href="https://example.com/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://example.com/image.jpg" alt="remote image"/></a><br/>
<a href="/relative/path/wiki/raw/image.jpg" rel="nofollow"><img src="/relative/path/wiki/raw/image.jpg" title="local image" alt="local image"/></a><br/>
<a href="https://example.com/image.jpg" rel="nofollow"><img src="https://example.com/image.jpg" title="remote link" alt="remote link"/></a><br/>
<a href="https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash" rel="nofollow">https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare<br/>
<a href="https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb" rel="nofollow">https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb</a><br/>
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit<br/>
<span class="emoji" aria-label="thumbs up">👍</span><br/>
<a href="mailto:mail@domain.com" rel="nofollow">mail@domain.com</a><br/>
@mention-user test<br/>
#123<br/>
space</p>
` ,
} ,
}
for i , c := range cases {
result , err := markdown . RenderString ( & markup . RenderContext { Ctx : context . Background ( ) , Links : c . Links , IsWiki : c . IsWiki } , input )
assert . NoError ( t , err , "Unexpected error in testcase: %v" , i )
2024-03-01 15:11:51 +08:00
assert . Equal ( t , template . HTML ( c . Expected ) , result , "Unexpected result in testcase %v" , i )
2024-01-15 09:49:24 +01:00
}
}
2024-03-22 20:16:23 +08:00
func TestAttention ( t * testing . T ) {
defer svg . MockIcon ( "octicon-info" ) ( )
defer svg . MockIcon ( "octicon-light-bulb" ) ( )
defer svg . MockIcon ( "octicon-report" ) ( )
defer svg . MockIcon ( "octicon-alert" ) ( )
defer svg . MockIcon ( "octicon-stop" ) ( )
renderAttention := func ( attention , icon string ) string {
tmpl := ` <blockquote class="attention-header attention- { attention}"><p><svg class="attention-icon attention- { attention} svg { icon}" width="16" height="16"></svg><strong class="attention- { attention}"> { Attention}</strong></p> `
tmpl = strings . ReplaceAll ( tmpl , "{attention}" , attention )
tmpl = strings . ReplaceAll ( tmpl , "{icon}" , icon )
tmpl = strings . ReplaceAll ( tmpl , "{Attention}" , cases . Title ( language . English ) . String ( attention ) )
return tmpl
}
test := func ( input , expected string ) {
result , err := markdown . RenderString ( & markup . RenderContext { Ctx : context . Background ( ) } , input )
assert . NoError ( t , err )
assert . Equal ( t , strings . TrimSpace ( expected ) , strings . TrimSpace ( string ( result ) ) )
}
test ( `
> [!NOTE]
> text
` , renderAttention ( "note" , "octicon-info" ) + "\n<p>text</p>\n</blockquote>" )
test ( ` > [!note] ` , renderAttention ( "note" , "octicon-info" ) + "\n</blockquote>" )
test ( ` > [!tip] ` , renderAttention ( "tip" , "octicon-light-bulb" ) + "\n</blockquote>" )
test ( ` > [!important] ` , renderAttention ( "important" , "octicon-report" ) + "\n</blockquote>" )
test ( ` > [!warning] ` , renderAttention ( "warning" , "octicon-alert" ) + "\n</blockquote>" )
test ( ` > [!caution] ` , renderAttention ( "caution" , "octicon-stop" ) + "\n</blockquote>" )
}