Files
Gitea/modules/markup/markdown/markdown_math_test.go
T
Sergio Benitezandwxiaoguang ab9bcd6a79 fix(markdown): parse escaped alerts by default (#39633)
Previously, recognition of escaped alert markers such as `\[!NOTE\]`
accidentally depended on enabling the optional `inline-parentheses` math
setting, resulting in such escaped alerts not rendering properly.
Goldmark splits the escaped marker differently based on the setting
being enabled or disabled, and only one form was handled. This commit
handles both forms.

For example, in a README or issue:

```
> \[!NOTE\]
> text
```

Before this commit, we'd get an ordinary blockquote displaying literal
`[!NOTE]` followed by `text`. With this commit, we get the styled
admonition.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-10-08 13:47:17 +00:00

318 lines
5.9 KiB
Go

// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package markdown
import (
"strings"
"testing"
"gitea.dev/modules/markup"
"gitea.dev/modules/setting"
"gitea.dev/modules/test"
"github.com/stretchr/testify/assert"
)
const nl = "\n"
func TestMathRender(t *testing.T) {
defer test.MockVariableValue(&setting.Markdown.MathCodeBlockOptions, setting.MarkdownMathCodeBlockOptions{ParseInlineDollar: true, ParseInlineParentheses: true})()
testcases := []struct {
testcase string
expected string
}{
{
"$a$",
`<p><code class="language-math">a</code></p>` + nl,
},
{
"$ a $",
`<p><code class="language-math">a</code></p>` + nl,
},
{
"$a$$b$",
`<p><code class="language-math">a</code><code class="language-math">b</code></p>` + nl,
},
{
"$a$ $b$",
`<p><code class="language-math">a</code> <code class="language-math">b</code></p>` + nl,
},
{
`\(a\) \(b\)`,
`<p><code class="language-math">a</code> <code class="language-math">b</code></p>` + nl,
},
{
`$a$.`,
`<p><code class="language-math">a</code>.</p>` + nl,
},
{
`.$a$`,
`<p>.$a$</p>` + nl,
},
{
`$a a$b b$`,
`<p>$a a$b b$</p>` + nl,
},
{
`a a$b b`,
`<p>a a$b b</p>` + nl,
},
{
`a$b $a a$b b$`,
`<p>a$b $a a$b b$</p>` + nl,
},
{
"a$x$", // Pattern: "word$other$" The real world example is: "Price is between US$1 and US$2.", so don't parse this.
`<p>a$x$</p>` + nl,
},
{
"$x$a",
`<p>$x$a</p>` + nl,
},
{
"$a$ ($b$) [$c$] {$d$}",
`<p><code class="language-math">a</code> (<code class="language-math">b</code>) [$c$] {$d$}</p>` + nl,
},
{
"[$a$](link)",
`<p><a href="/link" rel="nofollow"><code class="language-math">a</code></a></p>` + nl,
},
{
"$$a$$",
`<p><code class="language-math">a</code></p>` + nl,
},
{
"$$a$$ test",
`<p><code class="language-math">a</code> test</p>` + nl,
},
{
"test $$a$$",
`<p>test <code class="language-math">a</code></p>` + nl,
},
{
`foo $x=\$$ bar`,
`<p>foo <code class="language-math">x=\$</code> bar</p>` + nl,
},
{
`$\text{$b$}$`,
`<p><code class="language-math">\text{$b$}</code></p>` + nl,
},
{
"a$`b`$c",
`<p>a<code class="language-math">b</code>c</p>` + nl,
},
{
"a $`b`$ c",
`<p>a <code class="language-math">b</code> c</p>` + nl,
},
{
"a$``b``$c x$```y```$z",
`<p>a<code class="language-math">b</code>c x<code class="language-math">y</code>z</p>` + nl,
},
}
for _, test := range testcases {
t.Run(test.testcase, func(t *testing.T) {
res, err := RenderString(markup.NewTestRenderContext(), test.testcase)
assert.NoError(t, err)
assert.Equal(t, test.expected, string(res))
})
}
}
func TestMathRenderBlockIndent(t *testing.T) {
defer test.MockVariableValue(&setting.Markdown.MathCodeBlockOptions, setting.MarkdownMathCodeBlockOptions{ParseBlockDollar: true, ParseBlockSquareBrackets: true})()
testcases := []struct {
name string
testcase string
expected string
}{
{
"indent-0",
`
\[
\alpha
\]
`,
`<pre class="code-block is-loading"><code class="language-math">
\alpha
</code></pre>
`,
},
{
"indent-1",
`
\[
\alpha
\]
`,
`<pre class="code-block is-loading"><code class="language-math">
\alpha
</code></pre>
`,
},
{
"indent-2-mismatch",
`
\[
a
b
c
d
\]
`,
`<pre class="code-block is-loading"><code class="language-math">
a
b
c
d
</code></pre>
`,
},
{
"indent-2",
`
\[
a
b
c
\]
`,
`<pre class="code-block is-loading"><code class="language-math">
a
b
c
</code></pre>
`,
},
{
"indent-0-oneline",
`$$ x $$
foo`,
`<code class="language-math"> x </code>
<p>foo</p>
`,
},
{
"indent-3-oneline",
` $$ x $$<SPACE>
foo`,
`<code class="language-math"> x </code>
<p>foo</p>
`,
},
{
"quote-block",
`
> \[
> a
> \]
> \[
> b
> \]
`,
`<blockquote>
<pre class="code-block is-loading"><code class="language-math">
a
</code></pre>
<pre class="code-block is-loading"><code class="language-math">
b
</code></pre>
</blockquote>
`,
},
{
"list-block",
`
1. a
\[
x
\]
2. b`,
`<ol>
<li>a
<pre class="code-block is-loading"><code class="language-math">
x
</code></pre>
</li>
<li>b</li>
</ol>
`,
},
{
"inline-non-math",
`\[x]`,
`<p>[x]</p>` + nl,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
res, err := RenderString(markup.NewTestRenderContext(), strings.ReplaceAll(test.testcase, "<SPACE>", " "))
assert.NoError(t, err)
assert.Equal(t, test.expected, string(res), "unexpected result for test case:\n%s", test.testcase)
})
}
}
func TestMathRenderOptions(t *testing.T) {
defer test.MockVariableValue(&setting.Markdown.MathCodeBlockOptions, setting.MarkdownMathCodeBlockOptions{})()
test := func(t *testing.T, expected, input string) {
res, err := RenderString(markup.NewTestRenderContext(), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(res)), "input: %s", input)
}
// default (non-conflict) inline syntax
test(t, `<p><code class="language-math">a</code></p>`, "$`a`$")
// ParseInlineDollar
test(t, `<p>$a$</p>`, `$a$`)
setting.Markdown.MathCodeBlockOptions.ParseInlineDollar = true
test(t, `<p><code class="language-math">a</code></p>`, `$a$`)
// ParseInlineParentheses
test(t, `<p>(a)</p>`, `\(a\)`)
setting.Markdown.MathCodeBlockOptions.ParseInlineParentheses = true
test(t, `<p><code class="language-math">a</code></p>`, `\(a\)`)
// ParseBlockDollar
test(t, `<p>$$
a
$$</p>
`, `
$$
a
$$
`)
setting.Markdown.MathCodeBlockOptions.ParseBlockDollar = true
test(t, `<pre class="code-block is-loading"><code class="language-math">
a
</code></pre>
`, `
$$
a
$$
`)
// ParseBlockSquareBrackets
test(t, `<p>[
a
]</p>
`, `
\[
a
\]
`)
setting.Markdown.MathCodeBlockOptions.ParseBlockSquareBrackets = true
test(t, `<pre class="code-block is-loading"><code class="language-math">
a
</code></pre>
`, `
\[
a
\]
`)
}