From dd136858f1ea40ad3c94191d647487fa4f31926c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 18 Oct 2024 20:33:49 +0200 Subject: Adding upstream version 9.0.0. Signed-off-by: Daniel Baumann --- modules/markup/markdown/markdown_test.go | 1359 ++++++++++++++++++++++++++++++ 1 file changed, 1359 insertions(+) create mode 100644 modules/markup/markdown/markdown_test.go (limited to 'modules/markup/markdown/markdown_test.go') diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go new file mode 100644 index 0000000..e3dc6c9 --- /dev/null +++ b/modules/markup/markdown/markdown_test.go @@ -0,0 +1,1359 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package markdown_test + +import ( + "context" + "html/template" + "os" + "strings" + "testing" + + "code.gitea.io/gitea/models/unittest" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/markup" + "code.gitea.io/gitea/modules/markup/markdown" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/util" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +const ( + AppURL = "http://localhost:3000/" + FullURL = AppURL + "gogits/gogs/" +) + +// these values should match the const above +var localMetas = map[string]string{ + "user": "gogits", + "repo": "gogs", + "repoPath": "../../../tests/gitea-repositories-meta/user13/repo11.git/", +} + +func TestMain(m *testing.M) { + unittest.InitSettings() + if err := git.InitSimple(context.Background()); err != nil { + log.Fatal("git init failed, err: %v", err) + } + markup.Init(&markup.ProcessorHelper{ + IsUsernameMentionable: func(ctx context.Context, username string) bool { + return username == "r-lyeh" + }, + }) + os.Exit(m.Run()) +} + +func TestRender_StandardLinks(t *testing.T) { + setting.AppURL = AppURL + + test := func(input, expected, expectedWiki string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + + buffer, err = markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + IsWiki: true, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer))) + } + + googleRendered := `

https://google.com/

` + test("", googleRendered, googleRendered) + + lnk := util.URLJoin(FullURL, "WikiPage") + lnkWiki := util.URLJoin(FullURL, "wiki", "WikiPage") + test("[WikiPage](WikiPage)", + `

WikiPage

`, + `

WikiPage

`) +} + +func TestRender_Images(t *testing.T) { + setting.AppURL = AppURL + + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + url := "../../.images/src/02/train.jpg" + title := "Train" + href := "https://gitea.io" + result := util.URLJoin(FullURL, url) + // hint: With Markdown v2.5.2, there is a new syntax: [link](URL){:target="_blank"} , but we do not support it now + + test( + "!["+title+"]("+url+")", + `

`+title+`

`) + + test( + "[["+title+"|"+url+"]]", + `

`+title+`

`) + test( + "[!["+title+"]("+url+")]("+href+")", + `

`+title+`

`) + + test( + "!["+title+"]("+url+")", + `

`+title+`

`) + + test( + "[["+title+"|"+url+"]]", + `

`+title+`

`) + test( + "[!["+title+"]("+url+")]("+href+")", + `

`+title+`

`) +} + +func testAnswers(baseURLContent, baseURLImages string) []string { + return []string{ + `

Wiki! Enjoy :)

+ +

See commit 65f1bf27bc

+

Ideas and codes

+ +`, + `

What is Wine Staging?

+

Wine Staging on website wine-staging.com.

+ +

Here are some links to the most important topics. You can find the full list of pages at the sidebar.

+ + + + + + + + + + + + + +
images/icon-install.pngInstallation
images/icon-usage.pngUsage
+`, + `

Excelsior JET allows you to create native executables for Windows, Linux and Mac OS X.

+
    +
  1. Package your libGDX application
    +images/1.png
  2. +
  3. Perform a test run by hitting the Run! button.
    +images/2.png
  4. +
+

More tests

+

(from https://www.markdownguide.org/extended-syntax/)

+

Checkboxes

+
    +
  • unchecked
  • +
  • checked
  • +
  • still unchecked
  • +
+

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.2

+
+
+
    +
  1. +

    This is the first footnote. ↩ī¸Ž

    +
  2. +
  3. +

    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. ↩ī¸Ž

    +
  4. +
+
+`, `
    +
  • If you want to rebase/retry this PR, click this checkbox.
  • +
+
+

This PR has been generated by Renovate Bot.

+`, + } +} + +// 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]] + +See commit 65f1bf27bc + +Ideas and codes + +- Bezier widget (by @r-lyeh) ` + AppURL + `ocornut/imgui/issues/786 +- Bezier widget (by @r-lyeh) ` + AppURL + `gogits/gogs/issues/786 +- 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). + +## 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. +[[images/2.png]] + +## More tests {#custom-id} + +(from https://www.markdownguide.org/extended-syntax/) + +### Checkboxes + +- [ ] unchecked +- [x] checked +- [ ] still unchecked + +### 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. +`, + ` +- [ ] If you want to rebase/retry this PR, click this checkbox. + +--- + +This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). + +`, +} + +func TestTotal_RenderWiki(t *testing.T) { + setting.AppURL = AppURL + + answers := testAnswers(util.URLJoin(FullURL, "wiki"), util.URLJoin(FullURL, "wiki", "raw")) + + for i := 0; i < len(sameCases); i++ { + line, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + Metas: localMetas, + IsWiki: true, + }, sameCases[i]) + require.NoError(t, err) + assert.Equal(t, template.HTML(answers[i]), line) + } + + testCases := []string{ + // Guard wiki sidebar: special syntax + `[[Guardfile-DSL / Configuring-Guard|Guardfile-DSL---Configuring-Guard]]`, + // rendered + `

Guardfile-DSL / Configuring-Guard

+`, + // special syntax + `[[Name|Link]]`, + // rendered + `

Name

+`, + } + + for i := 0; i < len(testCases); i += 2 { + line, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + IsWiki: true, + }, testCases[i]) + require.NoError(t, err) + assert.Equal(t, template.HTML(testCases[i+1]), line) + } +} + +func TestTotal_RenderString(t *testing.T) { + setting.AppURL = AppURL + + answers := testAnswers(util.URLJoin(FullURL, "src", "master"), util.URLJoin(FullURL, "media", "master")) + + for i := 0; i < len(sameCases); i++ { + line, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + BranchPath: "master", + }, + Metas: localMetas, + }, sameCases[i]) + require.NoError(t, err) + assert.Equal(t, template.HTML(answers[i]), line) + } + + testCases := []string{} + + for i := 0; i < len(testCases); i += 2 { + line, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + }, + }, testCases[i]) + require.NoError(t, err) + assert.Equal(t, template.HTML(testCases[i+1]), line) + } +} + +func TestRender_RenderParagraphs(t *testing.T) { + test := func(t *testing.T, str string, cnt int) { + res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, str) + require.NoError(t, err) + assert.Equal(t, cnt, strings.Count(res, "image1
+image2

+` + res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase) + require.NoError(t, err) + assert.Equal(t, expected, res) +} + +func TestRenderEmojiInLinks_Issue12331(t *testing.T) { + testcase := `[Link with emoji :moon: in text](https://gitea.io)` + expected := `

Link with emoji 🌔 in text

+` + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase) + require.NoError(t, err) + assert.Equal(t, template.HTML(expected), res) +} + +func TestColorPreview(t *testing.T) { + const nl = "\n" + positiveTests := []struct { + testcase string + expected string + }{ + { // hex + "`#FF0000`", + `

#FF0000

` + nl, + }, + { // rgb + "`rgb(16, 32, 64)`", + `

rgb(16, 32, 64)

` + nl, + }, + { // short hex + "This is the color white `#000`", + `

This is the color white #000

` + nl, + }, + { // hsl + "HSL stands for hue, saturation, and lightness. An example: `hsl(0, 100%, 50%)`.", + `

HSL stands for hue, saturation, and lightness. An example: hsl(0, 100%, 50%).

` + nl, + }, + { // uppercase hsl + "HSL stands for hue, saturation, and lightness. An example: `HSL(0, 100%, 50%)`.", + `

HSL stands for hue, saturation, and lightness. An example: HSL(0, 100%, 50%).

` + nl, + }, + } + + for _, test := range positiveTests { + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) + require.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) + assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) + } + + 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%)`", // codespell-ignore + // looks like a color but not really + "`hsl(40, 60, 80)`", + } + + for _, test := range negativeTests { + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test) + require.NoError(t, err, "Unexpected error in testcase: %q", test) + assert.NotContains(t, res, `a

` + nl, + }, + { + "$ a $", + `

a

` + nl, + }, + { + "$a$ $b$", + `

a b

` + nl, + }, + { + `\(a\) \(b\)`, + `

a b

` + nl, + }, + { + `$a$.`, + `

a.

` + nl, + }, + { + `.$a$`, + `

.$a$

` + nl, + }, + { + `$a a$b b$`, + `

$a a$b b$

` + nl, + }, + { + `a a$b b`, + `

a a$b b

` + nl, + }, + { + `a$b $a a$b b$`, + `

a$b $a a$b b$

` + nl, + }, + { + "a$x$", + `

a$x$

` + nl, + }, + { + "$x$a", + `

$x$a

` + nl, + }, + { + "$$a$$", + `
a
` + nl, + }, + { + `\[a b\]`, + `
a b
` + nl, + }, + { + `\[a b]`, + `

[a b]

` + nl, + }, + { + `$$a`, + `

$$a

` + nl, + }, + { + "$a$ ($b$) [$c$] {$d$}", + `

a (b) [$c$] {$d$}

` + nl, + }, + { + "$$a$$ test", + `

a test

` + nl, + }, + { + "test $$a$$", + `

test a

` + nl, + }, + } + + for _, test := range testcases { + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) + require.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) + assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) + } +} + +func TestFootnote(t *testing.T) { + testcases := []struct { + testcase string + expected string + }{ + { + `Citation needed[^0]. +[^0]: Source`, + `

Citation needed1.

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed[^0]`, + `

Citation needed[^0]

+`, + }, + { + `Citation needed[^1], Citation needed twice[^3] +[^3]: Source`, + `

Citation needed[^1], Citation needed twice1

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed[^0] +[^1]: Source`, + `

Citation needed[^0]

+`, + }, + { + `Citation needed[^0] +[^0]: Source 1 +[^0]: Source 2`, + `

Citation needed1

+
+
+
    +
  1. +

    Source 1 ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed![^0] +[^0]: Source`, + `

Citation needed1

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Trigger [^`, + `

Trigger [^

+`, + }, + { + `Trigger 2 [^0`, + `

Trigger 2 [^0

+`, + }, + { + `Citation needed[^0] +[^0]: Source with citation needed[^1] +[^1]: Source`, + `

Citation needed1

+
+
+
    +
  1. +

    Source with citation needed2 ↩ī¸Ž

    +
  2. +
  3. +

    Source ↩ī¸Ž

    +
  4. +
+
+`, + }, + { + `Citation needed[^#] +[^#]: Source`, + `

Citation needed1

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed[^0] + [^0]: Source`, + `

Citation needed[^0]
+[^0]: Source

+`, + }, + { + `[^0]: Source + +Citation needed[^0].`, + `

Citation needed1.

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed[^] +[^]: Source`, + `

Citation needed[^]
+[^]: Source

+`, + }, + { + `Citation needed[^0] +[^0] Source`, + `

Citation needed[^0]
+[^0] Source

+`, + }, + { + `Citation needed[^0] +[^0 Source`, + `

Citation needed[^0]
+[^0 Source

+`, + }, + { + `Citation needed[^0] [^0]: Source`, + `

Citation needed[^0] [^0]: Source

+`, + }, + { + `Citation needed[^Source here 0 # 9-3] +[^Source here 0 # 9-3]: Source`, + `

Citation needed1

+
+
+
    +
  1. +

    Source ↩ī¸Ž

    +
  2. +
+
+`, + }, + { + `Citation needed[^0] +[^0]:`, + `

Citation needed1

+
+
+
    +
  1. + ↩ī¸Ž
  2. +
+
+`, + }, + } + for _, test := range testcases { + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) + require.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) + assert.Equal(t, test.expected, string(res), "Unexpected result in testcase %q", test.testcase) + } +} + +func TestTaskList(t *testing.T) { + testcases := []struct { + testcase string + expected string + }{ + { + // data-source-position should take into account YAML frontmatter. + `--- +foo: bar +--- +- [ ] task 1`, + `
+ + + + + + + + + + +
foo
bar
+
    +
  • task 1
  • +
+`, + }, + } + + for _, test := range testcases { + res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase) + require.NoError(t, err, "Unexpected error in testcase: %q", test.testcase) + assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase) + } +} + +func TestRenderLinks(t *testing.T) { + input := ` space @mention-user${SPACE}${SPACE} +/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]] +![local image](image.jpg) +![local image](path/file) +![local image](/path/file) +![remote image](https://example.com/image.jpg) +[[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 + space${SPACE}${SPACE} +` + input = strings.ReplaceAll(input, "${SPACE}", " ") // replace ${SPACE} with " ", to avoid some editor's auto-trimming + cases := []struct { + Links markup.Links + IsWiki bool + Expected string + }{ + { // 0 + Links: markup.Links{}, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 1 + Links: markup.Links{}, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 2 + Links: markup.Links{ + Base: "https://gitea.io/", + }, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 3 + Links: markup.Links{ + Base: "https://gitea.io/", + }, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 4 + Links: markup.Links{ + Base: "/relative/path", + }, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 5 + Links: markup.Links{ + Base: "/relative/path", + }, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 6 + Links: markup.Links{ + Base: "/user/repo", + BranchPath: "branch/main", + }, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 7 + Links: markup.Links{ + Base: "/relative/path", + BranchPath: "branch/main", + }, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 8 + Links: markup.Links{ + Base: "/user/repo", + TreePath: "sub/folder", + }, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 9 + Links: markup.Links{ + Base: "/relative/path", + TreePath: "sub/folder", + }, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 10 + Links: markup.Links{ + Base: "/user/repo", + BranchPath: "branch/main", + TreePath: "sub/folder", + }, + IsWiki: false, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + { // 11 + Links: markup.Links{ + Base: "/relative/path", + BranchPath: "branch/main", + TreePath: "sub/folder", + }, + IsWiki: true, + Expected: `

space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+local link
+remote link
+local link
+remote link
+local image
+local image
+local image
+remote image
+local image
+remote link
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+space

+`, + }, + } + + for i, c := range cases { + result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input) + require.NoError(t, err, "Unexpected error in testcase: %v", i) + assert.Equal(t, template.HTML(c.Expected), result, "Unexpected result in testcase %v", i) + } +} + +func TestCustomMarkdownURL(t *testing.T) { + defer test.MockVariableValue(&setting.Markdown.CustomURLSchemes, []string{"abp"})() + setting.AppURL = AppURL + + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + Links: markup.Links{ + Base: FullURL, + BranchPath: "branch/main", + }, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + test("[test](abp:subscribe?location=https://codeberg.org/filters.txt&title=joy)", + `

test

`) + + // Ensure that the schema itself without `:` is still made absolute. + test("[test](abp)", + `

test

`) +} + +func TestYAMLMeta(t *testing.T) { + setting.AppURL = AppURL + + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + test(`--- +include_toc: true +--- +## Header`, + `
+ + + + + + + + + + +
include_toc
true
+
toc +

Header

`) + + test(`--- +key: value +---`, + `
+ + + + + + + + + + +
key
value
+
`) + + test("---\n---\n", + `
+
`) + + test(`--- +gitea: + details_icon: smiley + include_toc: true +--- +# Another header`, + `
+ + + + + + + + + + +
gitea
+ + + + + + + + + + + + +
details_iconinclude_toc
smileytrue
+
+
toc +

Another header

`) + + test(`--- +gitea: + meta: table +key: value +---`, ` + + + + + + + + + + + + +
giteakey
+ + + + + + + + + + +
meta
table
+
value
`) +} + +func TestCallout(t *testing.T) { + setting.AppURL = AppURL + + test := func(input, expected string) { + buffer, err := markdown.RenderString(&markup.RenderContext{ + Ctx: git.DefaultContext, + }, input) + require.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer))) + } + + test(">\n0", "
\n
\n

0

") +} -- cgit v1.2.3