mirror of https://github.com/go-gitea/gitea
Refactor markdown render (#32728)
Follow up recent render system refactoring PRs (split test code), and fine tune the math render (added some new cases)pull/32732/head^2
parent
f7f68e4cc0
commit
0f18046df4
@ -0,0 +1,56 @@ |
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package markdown_test |
||||||
|
|
||||||
|
import ( |
||||||
|
"strings" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/markup" |
||||||
|
"code.gitea.io/gitea/modules/markup/markdown" |
||||||
|
"code.gitea.io/gitea/modules/svg" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert" |
||||||
|
"golang.org/x/text/cases" |
||||||
|
"golang.org/x/text/language" |
||||||
|
) |
||||||
|
|
||||||
|
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.NewTestRenderContext(), 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>") |
||||||
|
|
||||||
|
// escaped by mdformat
|
||||||
|
test(`> \[!NOTE\]`, renderAttention("note", "octicon-info")+"\n</blockquote>") |
||||||
|
|
||||||
|
// legacy GitHub style
|
||||||
|
test(`> **warning**`, renderAttention("warning", "octicon-alert")+"\n</blockquote>") |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package markdown_test |
||||||
|
|
||||||
|
import ( |
||||||
|
"testing" |
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/markup" |
||||||
|
"code.gitea.io/gitea/modules/markup/markdown" |
||||||
|
) |
||||||
|
|
||||||
|
func BenchmarkSpecializedMarkdown(b *testing.B) { |
||||||
|
// 240856 4719 ns/op
|
||||||
|
for i := 0; i < b.N; i++ { |
||||||
|
markdown.SpecializedMarkdown(&markup.RenderContext{}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func BenchmarkMarkdownRender(b *testing.B) { |
||||||
|
// 23202 50840 ns/op
|
||||||
|
for i := 0; i < b.N; i++ { |
||||||
|
_, _ = markdown.RenderString(markup.NewTestRenderContext(), "https://example.com\n- a\n- b\n") |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,163 @@ |
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package markdown |
||||||
|
|
||||||
|
import ( |
||||||
|
"strings" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/markup" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert" |
||||||
|
) |
||||||
|
|
||||||
|
func TestMathRender(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, |
||||||
|
}, |
||||||
|
{ |
||||||
|
`$a$.`, |
||||||
|
`<p><code class="language-math is-loading">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$", |
||||||
|
`<p>a$x$</p>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"$x$a", |
||||||
|
`<p>$x$a</p>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"$a$ ($b$) [$c$] {$d$}", |
||||||
|
`<p><code class="language-math is-loading">a</code> (<code class="language-math is-loading">b</code>) [$c$] {$d$}</p>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"$$a$$", |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display">a</code></pre>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"$$a$$ test", |
||||||
|
`<p><code class="language-math display is-loading">a</code> test</p>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"test $$a$$", |
||||||
|
`<p>test <code class="language-math display is-loading">a</code></p>` + nl, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"foo $x=\\$$ bar", |
||||||
|
`<p>foo <code class="language-math is-loading">x=\$</code> bar</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) { |
||||||
|
testcases := []struct { |
||||||
|
name string |
||||||
|
testcase string |
||||||
|
expected string |
||||||
|
}{ |
||||||
|
{ |
||||||
|
"indent-0", |
||||||
|
` |
||||||
|
\[ |
||||||
|
\alpha |
||||||
|
\] |
||||||
|
`, |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display"> |
||||||
|
\alpha |
||||||
|
</code></pre> |
||||||
|
`, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"indent-1", |
||||||
|
` |
||||||
|
\[ |
||||||
|
\alpha |
||||||
|
\] |
||||||
|
`, |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display"> |
||||||
|
\alpha |
||||||
|
</code></pre> |
||||||
|
`, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"indent-2", |
||||||
|
` |
||||||
|
\[ |
||||||
|
\alpha |
||||||
|
\] |
||||||
|
`, |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display"> |
||||||
|
\alpha |
||||||
|
</code></pre> |
||||||
|
`, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"indent-0-oneline", |
||||||
|
`$$ x $$ |
||||||
|
foo`, |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display"> x </code></pre> |
||||||
|
<p>foo</p> |
||||||
|
`, |
||||||
|
}, |
||||||
|
{ |
||||||
|
"indent-3-oneline", |
||||||
|
` $$ x $$<SPACE> |
||||||
|
foo`, |
||||||
|
`<pre class="code-block is-loading"><code class="chroma language-math display"> x </code></pre> |
||||||
|
<p>foo</p> |
||||||
|
`, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
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) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue