From b9cd6fb70370b97496e03c61be35e0d3ceedc52d Mon Sep 17 00:00:00 2001
From: Yarden Shoham <hrsi88@gmail.com>
Date: Sat, 15 Oct 2022 21:24:41 +0300
Subject: [PATCH] Add `code` highlighting in issue titles (#21432)

This changes the rendering logic of issue titles. If a substring in an
issue title is enclosed with a pair of backticks, it'll be rendered with
a monospace font (HTML `code` tag).

* Closes #20887

Signed-off-by: Yarden Shoham <hrsi88@gmail.com>
Co-authored-by: Gusted <williamzijl7@hotmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: 6543 <6543@obermui.de>
---
 modules/templates/helper.go          | 11 +++++++++++
 templates/repo/issue/view_title.tmpl |  2 +-
 templates/shared/issuelist.tmpl      |  2 +-
 templates/user/dashboard/feeds.tmpl  |  8 ++++----
 web_src/less/_base.less              |  5 +++++
 web_src/less/_dashboard.less         |  5 ++---
 6 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index a8e4075248..e10beae1d9 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -161,6 +161,7 @@ func NewFuncMap() []template.FuncMap {
 		"RenderCommitMessageLink":        RenderCommitMessageLink,
 		"RenderCommitMessageLinkSubject": RenderCommitMessageLinkSubject,
 		"RenderCommitBody":               RenderCommitBody,
+		"RenderCodeBlock":                RenderCodeBlock,
 		"RenderIssueTitle":               RenderIssueTitle,
 		"RenderEmoji":                    RenderEmoji,
 		"RenderEmojiPlain":               emoji.ReplaceAliases,
@@ -795,6 +796,16 @@ func RenderCommitBody(ctx context.Context, msg, urlPrefix string, metas map[stri
 	return template.HTML(renderedMessage)
 }
 
+// Match text that is between back ticks.
+var codeMatcher = regexp.MustCompile("`([^`]+)`")
+
+// RenderCodeBlock renders "`…`" as highlighted "<code>" block.
+// Intended for issue and PR titles, these containers should have styles for "<code>" elements
+func RenderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
+	htmlWithCodeTags := codeMatcher.ReplaceAllString(string(htmlEscapedTextToRender), "<code>$1</code>") // replace with HTML <code> tags
+	return template.HTML(htmlWithCodeTags)
+}
+
 // RenderIssueTitle renders issue/pull title with defined post processors
 func RenderIssueTitle(ctx context.Context, text, urlPrefix string, metas map[string]string) template.HTML {
 	renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl
index 3141e81808..58f4722e28 100644
--- a/templates/repo/issue/view_title.tmpl
+++ b/templates/repo/issue/view_title.tmpl
@@ -6,7 +6,7 @@
 			</div>
 		{{end}}
 		<h1>
-			<span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas}}</span>
+			<span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}}</span>
 			<span class="index">#{{.Issue.Index}}</span>
 			<div id="edit-title-input" class="ui input" style="display: none">
 				<input value="{{.Issue.Title}}" maxlength="255" autocomplete="off">
diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl
index 0e5879c612..066d34fe33 100644
--- a/templates/shared/issuelist.tmpl
+++ b/templates/shared/issuelist.tmpl
@@ -35,7 +35,7 @@
 			</div>
 			<div class="issue-item-main f1 fc df">
 				<div class="issue-item-top-row">
-					<a class="title tdn" href="{{if .HTMLURL}}{{.HTMLURL}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{RenderEmoji .Title}}</a>
+					<a class="title tdn issue-title" href="{{if .HTMLURL}}{{.HTMLURL}}{{else}}{{$.Link}}/{{.Index}}{{end}}">{{RenderEmoji .Title | RenderCodeBlock}}</a>
 					{{if .IsPull}}
 						{{if (index $.CommitStatuses .PullRequest.ID)}}
 							{{template "repo/commit_statuses" dict "Status" (index $.CommitLastStatus .PullRequest.ID) "Statuses" (index $.CommitStatuses .PullRequest.ID) "root" $}}
diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl
index 1862f32b6b..94bbbc470a 100644
--- a/templates/user/dashboard/feeds.tmpl
+++ b/templates/user/dashboard/feeds.tmpl
@@ -99,17 +99,17 @@
 							</ul>
 						</div>
 					{{else if eq .GetOpType 6}}
-						<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji}}</span>
+						<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji | RenderCodeBlock}}</span>
 					{{else if eq .GetOpType 7}}
-						<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji}}</span>
+						<span class="text truncate issue title">{{index .GetIssueInfos 1 | RenderEmoji | RenderCodeBlock}}</span>
 					{{else if or (eq .GetOpType 10) (eq .GetOpType 21) (eq .GetOpType 22) (eq .GetOpType 23)}}
-						<a href="{{.GetCommentLink}}" class="text truncate issue title">{{.GetIssueTitle | RenderEmoji}}</a>
+						<a href="{{.GetCommentLink}}" class="text truncate issue title">{{.GetIssueTitle | RenderEmoji | RenderCodeBlock}}</a>
 						{{$comment := index .GetIssueInfos 1}}
 						{{if gt (len $comment) 0}}<p class="text light grey">{{$comment | RenderEmoji}}</p>{{end}}
 					{{else if eq .GetOpType 11}}
 						<p class="text light grey">{{index .GetIssueInfos 1}}</p>
 					{{else if or (eq .GetOpType 12) (eq .GetOpType 13) (eq .GetOpType 14) (eq .GetOpType 15)}}
-						<span class="text truncate issue title">{{.GetIssueTitle | RenderEmoji}}</span>
+						<span class="text truncate issue title">{{.GetIssueTitle | RenderEmoji | RenderCodeBlock}}</span>
 					{{else if eq .GetOpType 25}}
 					<p class="text light grey">{{$.locale.Tr "action.review_dismissed_reason"}}</p>
 						<p class="text light grey">{{index .GetIssueInfos 2 | RenderEmoji}}</p>
diff --git a/web_src/less/_base.less b/web_src/less/_base.less
index c66cabd8a1..2abebe5c7d 100644
--- a/web_src/less/_base.less
+++ b/web_src/less/_base.less
@@ -332,6 +332,11 @@ a.commit-statuses-trigger {
   &:extend(.unselectable);
 }
 
+.issue-title code {
+  padding: 2px 4px;
+  border-radius: 6px;
+  background-color: var(--color-markup-code-block);
+}
 /* try to match button with no icons in height */
 .icon-button {
   padding-top: 7.42px !important;
diff --git a/web_src/less/_dashboard.less b/web_src/less/_dashboard.less
index 570d772729..e9a906cbed 100644
--- a/web_src/less/_dashboard.less
+++ b/web_src/less/_dashboard.less
@@ -141,10 +141,9 @@
     }
 
     code {
-      padding: 1px;
-      font-size: 85%;
-      background-color: rgba(0, 0, 0, .04);
+      padding: 2px 4px;
       border-radius: 3px;
+      background-color: var(--color-markup-code-block);
       word-break: break-all;
     }