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