mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-14 03:29:55 +00:00
enhance(markup): improve issue title rendering (#37908)
This commit is contained in:
@@ -69,6 +69,11 @@ func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
|
||||
m[1] += start
|
||||
start = m[1]
|
||||
|
||||
// don't render a shortcode whose ":" directly follows a backtick (an unclosed code span)
|
||||
if m[0] > 0 && node.Data[m[0]-1] == '`' {
|
||||
continue
|
||||
}
|
||||
|
||||
alias := node.Data[m[0]:m[1]]
|
||||
|
||||
var nextChar byte
|
||||
|
||||
@@ -377,6 +377,9 @@ func TestRender_emoji(t *testing.T) {
|
||||
test(":100:200", `<p>:100:200</p>`)
|
||||
test("std::thread::something", `<p>std::thread::something</p>`)
|
||||
test(":not exist:", `<p>:not exist:</p>`)
|
||||
test("foo `:smile:", "<p>foo `:smile:</p>")
|
||||
test("foo `:smile:`", `<p>foo <code>:smile:</code></p>`)
|
||||
test("foo ` :smile:", "<p>foo ` <span class=\"emoji\" aria-label=\"grinning face with smiling eyes\">😄</span></p>")
|
||||
}
|
||||
|
||||
func TestRender_ShortLinks(t *testing.T) {
|
||||
|
||||
@@ -107,19 +107,26 @@ func renderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
|
||||
|
||||
// RenderIssueTitle renders issue/pull title with defined post processors
|
||||
func (ut *RenderUtils) RenderIssueTitle(text string, repo *repo.Repository) template.HTML {
|
||||
renderedText, err := markup.PostProcessIssueTitle(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), template.HTMLEscapeString(text))
|
||||
// wrap "`…`" in <code> before post-processing so code-span content stays literal, like comment bodies
|
||||
htmlWithCode := renderCodeBlock(template.HTML(template.HTMLEscapeString(text)))
|
||||
renderedText, err := markup.PostProcessIssueTitle(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), string(htmlWithCode))
|
||||
if err != nil {
|
||||
log.Error("PostProcessIssueTitle: %v", err)
|
||||
return ""
|
||||
}
|
||||
return renderCodeBlock(template.HTML(renderedText))
|
||||
return template.HTML(renderedText)
|
||||
}
|
||||
|
||||
// RenderIssueSimpleTitle only renders with emoji and inline code block
|
||||
func (ut *RenderUtils) RenderIssueSimpleTitle(text string) template.HTML {
|
||||
ret := ut.RenderEmoji(text)
|
||||
ret = renderCodeBlock(ret)
|
||||
return ret
|
||||
// see RenderIssueTitle: wrap code spans before processing emoji
|
||||
htmlWithCode := renderCodeBlock(template.HTML(template.HTMLEscapeString(text)))
|
||||
renderedText, err := markup.PostProcessEmoji(markup.NewRenderContext(ut.ctx), string(htmlWithCode))
|
||||
if err != nil {
|
||||
log.Error("RenderIssueSimpleTitle: %v", err)
|
||||
return ""
|
||||
}
|
||||
return template.HTML(renderedText)
|
||||
}
|
||||
|
||||
func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
|
||||
|
||||
@@ -180,6 +180,38 @@ mail@domain.com
|
||||
})
|
||||
}
|
||||
|
||||
func TestRenderIssueTitleCodeSpan(t *testing.T) {
|
||||
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
mockRepo := &repo.Repository{
|
||||
ID: 1, OwnerName: "user13", Name: "repo11",
|
||||
Owner: &user_model.User{ID: 13, Name: "user13"},
|
||||
Units: []*repo.RepoUnit{},
|
||||
}
|
||||
ut := newTestRenderUtils(t)
|
||||
|
||||
cases := []struct {
|
||||
input string
|
||||
expected string
|
||||
emojiSafe bool
|
||||
}{
|
||||
{"foo `:100:`", `foo <code class="inline-code-block">:100:</code>`, true},
|
||||
{"`#123`", `<code class="inline-code-block">#123</code>`, false},
|
||||
{"`88fc37a3c0a4dda553bdcfc80c178a58247f42fb`", `<code class="inline-code-block">88fc37a3c0a4dda553bdcfc80c178a58247f42fb</code>`, false},
|
||||
{"foo `:100:", "foo `:100:", true},
|
||||
{"foo ` :100:", `foo ` + "`" + ` <span class="emoji" aria-label="hundred points">💯</span>`, true},
|
||||
{":100:", `<span class="emoji" aria-label="hundred points">💯</span>`, true},
|
||||
{"#123", `<a href="/user13/repo11/issues/123" class="ref-issue">#123</a>`, false},
|
||||
{"`x`:100:", `<code class="inline-code-block">x</code><span class="emoji" aria-label="hundred points">💯</span>`, true},
|
||||
{"a `:100:` b `:+1:` c", `a <code class="inline-code-block">:100:</code> b <code class="inline-code-block">:+1:</code> c`, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, c.expected, string(ut.RenderIssueTitle(c.input, mockRepo)), "input=%q", c.input)
|
||||
if c.emojiSafe {
|
||||
assert.Equal(t, c.expected, string(ut.RenderIssueSimpleTitle(c.input)), "simple input=%q", c.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderMarkdownToHtml(t *testing.T) {
|
||||
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
|
||||
expected := `<p>space <a href="/mention-user" rel="nofollow">@mention-user</a><br/>
|
||||
|
||||
Reference in New Issue
Block a user