mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-11 20:40:16 +00:00
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>
318 lines
5.9 KiB
Go
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
|
|
\]
|
|
`)
|
|
}
|