diff --git a/modules/markup/html.go b/modules/markup/html.go
index 9280a67d62..2e65827bf7 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -73,6 +73,8 @@ var (
// EmojiShortCodeRegex find emoji by alias like :smile:
EmojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
+
+ InlineCodeBlockRegex = regexp.MustCompile("`[^`]+`")
)
// CSS class for action keywords (e.g. "closes: #1")
@@ -243,6 +245,7 @@ func RenderIssueTitle(
title string,
) (string, error) {
return renderProcessString(ctx, []processor{
+ inlineCodeBlockProcessor,
issueIndexPatternProcessor,
commitCrossReferencePatternProcessor,
hashCurrentPatternProcessor,
@@ -251,6 +254,19 @@ func RenderIssueTitle(
}, title)
}
+// RenderRefIssueTitle to process title on places where an issue is referenced
+func RenderRefIssueTitle(
+ ctx *RenderContext,
+ title string,
+) (string, error) {
+ return renderProcessString(ctx, []processor{
+ inlineCodeBlockProcessor,
+ issueIndexPatternProcessor,
+ emojiShortCodeProcessor,
+ emojiProcessor,
+ }, title)
+}
+
func renderProcessString(ctx *RenderContext, procs []processor, content string) (string, error) {
var buf strings.Builder
if err := postProcess(ctx, procs, strings.NewReader(content), &buf); err != nil {
@@ -438,6 +454,24 @@ func createKeyword(content string) *html.Node {
return span
}
+func createInlineCode(content string) *html.Node {
+ code := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Code.String(),
+ Attr: []html.Attribute{},
+ }
+
+ code.Attr = append(code.Attr, html.Attribute{Key: "class", Val: "inline-code-block"})
+
+ text := &html.Node{
+ Type: html.TextNode,
+ Data: content,
+ }
+
+ code.AppendChild(text)
+ return code
+}
+
func createEmoji(content, class, name string) *html.Node {
span := &html.Node{
Type: html.ElementNode,
@@ -1070,6 +1104,21 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) {
}
}
+func inlineCodeBlockProcessor(ctx *RenderContext, node *html.Node) {
+ start := 0
+ next := node.NextSibling
+ for node != nil && node != next && start < len(node.Data) {
+ m := InlineCodeBlockRegex.FindStringSubmatchIndex(node.Data[start:])
+ if m == nil {
+ return
+ }
+
+ code := node.Data[m[0]+1 : m[1]-1]
+ replaceContent(node, m[0], m[1], createInlineCode(code))
+ node = node.NextSibling.NextSibling
+ }
+}
+
// emojiShortCodeProcessor for rendering text like :smile: into emoji
func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
start := 0
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index f1ae1c8bb1..aeae8204ad 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -172,11 +172,12 @@ func NewFuncMap() template.FuncMap {
"RenderCommitMessage": RenderCommitMessage,
"RenderCommitMessageLinkSubject": RenderCommitMessageLinkSubject,
- "RenderCommitBody": RenderCommitBody,
- "RenderCodeBlock": RenderCodeBlock,
- "RenderIssueTitle": RenderIssueTitle,
- "RenderEmoji": RenderEmoji,
- "ReactionToEmoji": ReactionToEmoji,
+ "RenderCommitBody": RenderCommitBody,
+ "RenderCodeBlock": RenderCodeBlock,
+ "RenderIssueTitle": RenderIssueTitle,
+ "RenderRefIssueTitle": RenderRefIssueTitle,
+ "RenderEmoji": RenderEmoji,
+ "ReactionToEmoji": ReactionToEmoji,
"RenderMarkdownToHtml": RenderMarkdownToHtml,
"RenderLabel": RenderLabel,
diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go
index 76790b63d5..c53bdd876f 100644
--- a/modules/templates/util_render.go
+++ b/modules/templates/util_render.go
@@ -130,6 +130,17 @@ func RenderIssueTitle(ctx context.Context, text string, metas map[string]string)
return template.HTML(renderedText)
}
+// RenderRefIssueTitle renders referenced issue/pull title with defined post processors
+func RenderRefIssueTitle(ctx context.Context, text string) template.HTML {
+ renderedText, err := markup.RenderRefIssueTitle(&markup.RenderContext{Ctx: ctx}, template.HTMLEscapeString(text))
+ if err != nil {
+ log.Error("RenderRefIssueTitle: %v", err)
+ return ""
+ }
+
+ return template.HTML(renderedText)
+}
+
// RenderLabel renders a label
// locale is needed due to an import cycle with our context providing the `Tr` function
func RenderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML {
diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go
index ea01612ac3..da74298ef7 100644
--- a/modules/templates/util_render_test.go
+++ b/modules/templates/util_render_test.go
@@ -35,8 +35,8 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
mail@domain.com
@mention-user test
#123
- space
-`
+ space
+` + "`code :+1: #123 code`\n"
var testMetas = map[string]string{
"user": "user13",
@@ -115,8 +115,8 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
mail@domain.com
@mention-user test
#123
- space`
-
+ space
+` + "`code 👍 #123 code`"
assert.EqualValues(t, expected, RenderCommitBody(context.Background(), testInput, testMetas))
}
@@ -152,11 +152,38 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
mail@domain.com
@mention-user test
#123
- space
+ space
+code :+1: #123 code
`
assert.EqualValues(t, expected, RenderIssueTitle(context.Background(), testInput, testMetas))
}
+func TestRenderRefIssueTitle(t *testing.T) {
+ expected := ` space @mention-user
+/just/a/path.bin
+https://example.com/file.bin
+[local link](file.bin)
+[remote link](https://example.com)
+[[local link|file.bin]]
+[[remote link|https://example.com]]
+![local image](image.jpg)
+![remote image](https://example.com/image.jpg)
+[[local image|image.jpg]]
+[[remote link|https://example.com/image.jpg]]
+https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
+https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
+👍
+mail@domain.com
+@mention-user test
+#123
+ space
+code :+1: #123 code
+`
+ assert.EqualValues(t, expected, RenderRefIssueTitle(context.Background(), testInput))
+}
+
func TestRenderMarkdownToHtml(t *testing.T) {
expected := `
space @mention-user
/just/a/path.bin
@@ -177,7 +204,8 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
mail@domain.com
@mention-user test
#123
-space
code :+1: #123 code
`
assert.EqualValues(t, expected, RenderMarkdownToHtml(context.Background(), testInput))
}
diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl
index 4c22c28329..0b255d6705 100644
--- a/templates/repo/issue/card.tmpl
+++ b/templates/repo/issue/card.tmpl
@@ -14,7 +14,7 @@
- {{.Title | RenderEmoji ctx | RenderCodeBlock}}
+ {{RenderRefIssueTitle $.Context .Title}}
{{if and $.isPinnedIssueCard $.Page.IsRepoAdmin}}
{{svg "octicon-x" 16}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index 019638bfb0..08c83c07d7 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -149,7 +149,7 @@
{{if eq .RefAction 3}}{{end}}