From bcc38eb35fdd2b46fbefea0a52fbba5e934fee3f Mon Sep 17 00:00:00 2001
From: wxiaoguang <wxiaoguang@gmail.com>
Date: Mon, 7 Apr 2025 01:34:59 +0800
Subject: [PATCH] Make markdown render match GitHub's behavior (#34129)

For #2246
---
 modules/markup/html.go      |  3 ++-
 modules/markup/html_test.go | 12 +++++++++---
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/modules/markup/html.go b/modules/markup/html.go
index 05701eebde..0e074cbcfa 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -85,7 +85,8 @@ var globalVars = sync.OnceValue(func() *globalVarsType {
 	// codePreviewPattern matches "http://domain/.../{owner}/{repo}/src/commit/{commit}/{filepath}#L10-L20"
 	v.codePreviewPattern = regexp.MustCompile(`https?://\S+/([^\s/]+)/([^\s/]+)/src/commit/([0-9a-f]{7,64})(/\S+)#(L\d+(-L\d+)?)`)
 
-	v.tagCleaner = regexp.MustCompile(`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL]\b)|(/?[hH][eE][aA][dD]\b))`)
+	// cleans: "<foo/bar", "<any words/", ("<html", "<head", "<script", "<style")
+	v.tagCleaner = regexp.MustCompile(`(?i)<(/?\w+/\w+|/[\w ]+/|/?(html|head|script|style\b))`)
 	v.nulCleaner = strings.NewReplacer("\000", "")
 	return v
 })
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 24dc7c9d3d..aab9fddd91 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -469,7 +469,7 @@ func Test_ParseClusterFuzz(t *testing.T) {
 	assert.NotContains(t, res.String(), "<html")
 }
 
-func TestPostProcess_RenderDocument(t *testing.T) {
+func TestPostProcess(t *testing.T) {
 	setting.StaticURLPrefix = markup.TestAppURL // can't run standalone
 	defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)()
 
@@ -480,7 +480,7 @@ func TestPostProcess_RenderDocument(t *testing.T) {
 		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
 	}
 
-	// Issue index shouldn't be post processing in a document.
+	// Issue index shouldn't be post-processing in a document.
 	test(
 		"#1",
 		"#1")
@@ -490,7 +490,7 @@ func TestPostProcess_RenderDocument(t *testing.T) {
 		"go-gitea/gitea#12345",
 		`<a href="/go-gitea/gitea/issues/12345" class="ref-issue">go-gitea/gitea#12345</a>`)
 
-	// Test that other post processing still works.
+	// Test that other post-processing still works.
 	test(
 		":gitea:",
 		`<span class="emoji" aria-label="gitea"><img alt=":gitea:" src="`+setting.StaticURLPrefix+`/assets/img/emoji/gitea.png"/></span>`)
@@ -499,6 +499,12 @@ func TestPostProcess_RenderDocument(t *testing.T) {
 		`Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span> in the middle`)
 	test("http://localhost:3000/person/repo/issues/4#issuecomment-1234",
 		`<a href="http://localhost:3000/person/repo/issues/4#issuecomment-1234" class="ref-issue">person/repo#4 (comment)</a>`)
+
+	// special tags, GitHub's behavior, and for unclosed tags, output as text content as much as possible
+	test("<script>a", `&lt;script&gt;a`)
+	test("<script>a</script>", `&lt;script&gt;a&lt;/script&gt;`)
+	test("<STYLE>a", `&lt;STYLE&gt;a`)
+	test("<style>a</STYLE>", `&lt;style&gt;a&lt;/STYLE&gt;`)
 }
 
 func TestIssue16020(t *testing.T) {