From 00e9824e1da1e65c27e3bf76116df7853fae3fa1 Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Fri, 15 Nov 2024 18:34:57 +0800
Subject: [PATCH 1/6] fix
---
models/repo/repo.go | 49 ++++++++++++++--------
models/repo/repo_test.go | 2 +-
modules/markup/html.go | 4 +-
modules/markup/html_internal_test.go | 34 +++++++--------
modules/markup/html_issue.go | 6 ++-
modules/markup/html_link.go | 6 +--
modules/markup/html_node.go | 4 +-
modules/markup/html_test.go | 15 ++++---
modules/markup/markdown/goldmark.go | 5 ++-
modules/markup/markdown/markdown_test.go | 21 ++++++----
modules/markup/markdown/transform_image.go | 2 +-
modules/markup/orgmode/orgmode.go | 5 +--
modules/markup/orgmode/orgmode_test.go | 2 +-
modules/markup/render.go | 23 ++++------
modules/markup/render_links.go | 2 +-
modules/templates/util_render.go | 10 ++---
routers/common/markup.go | 22 ++++------
routers/web/repo/wiki.go | 5 +--
18 files changed, 111 insertions(+), 106 deletions(-)
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 4776ff0b9ca25..eba41481aaf41 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -7,6 +7,7 @@ import (
"context"
"fmt"
"html/template"
+ "maps"
"net"
"net/url"
"path/filepath"
@@ -165,10 +166,10 @@ type Repository struct {
Status RepositoryStatus `xorm:"NOT NULL DEFAULT 0"`
- RenderingMetas map[string]string `xorm:"-"`
- DocumentRenderingMetas map[string]string `xorm:"-"`
- Units []*RepoUnit `xorm:"-"`
- PrimaryLanguage *LanguageStat `xorm:"-"`
+ commonRenderingMetas map[string]string `xorm:"-"`
+
+ Units []*RepoUnit `xorm:"-"`
+ PrimaryLanguage *LanguageStat `xorm:"-"`
IsFork bool `xorm:"INDEX NOT NULL DEFAULT false"`
ForkID int64 `xorm:"INDEX"`
@@ -473,9 +474,8 @@ func (repo *Repository) MustOwner(ctx context.Context) *user_model.User {
return repo.Owner
}
-// ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
-func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
- if len(repo.RenderingMetas) == 0 {
+func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]string {
+ if len(repo.commonRenderingMetas) == 0 {
metas := map[string]string{
"user": repo.OwnerName,
"repo": repo.Name,
@@ -508,21 +508,34 @@ func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
metas["org"] = strings.ToLower(repo.OwnerName)
}
- repo.RenderingMetas = metas
+ repo.commonRenderingMetas = metas
}
- return repo.RenderingMetas
+ return repo.commonRenderingMetas
+}
+
+// ComposeMetas composes a map of metas for properly rendering comments or comment-like contents (commit message)
+func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
+ metas := maps.Clone(repo.composeCommonMetas(ctx))
+ metas["markdownLineBreakStyle"] = "comment"
+ metas["markdownAllowShortIssuePattern"] = "true"
+ return metas
}
-// ComposeDocumentMetas composes a map of metas for properly rendering documents
+// ComposeWikiMetas composes a map of metas for properly rendering wikis
+func (repo *Repository) ComposeWikiMetas(ctx context.Context) map[string]string {
+ // does wiki need the "teams" and "org" from common metas?
+ metas := maps.Clone(repo.composeCommonMetas(ctx))
+ metas["markdownLineBreakStyle"] = "document"
+ metas["markdownAllowShortIssuePattern"] = "true"
+ return metas
+}
+
+// ComposeDocumentMetas composes a map of metas for properly rendering documents (repo files)
func (repo *Repository) ComposeDocumentMetas(ctx context.Context) map[string]string {
- if len(repo.DocumentRenderingMetas) == 0 {
- metas := map[string]string{}
- for k, v := range repo.ComposeMetas(ctx) {
- metas[k] = v
- }
- repo.DocumentRenderingMetas = metas
- }
- return repo.DocumentRenderingMetas
+ // does document(file) need the "teams" and "org" from common metas?
+ metas := maps.Clone(repo.composeCommonMetas(ctx))
+ metas["markdownLineBreakStyle"] = "document"
+ return metas
}
// GetBaseRepo populates repo.BaseRepo for a fork repository and
diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go
index c13b698abf148..ab8eb025cba36 100644
--- a/models/repo/repo_test.go
+++ b/models/repo/repo_test.go
@@ -99,7 +99,7 @@ func TestMetas(t *testing.T) {
testSuccess := func(expectedStyle string) {
repo.Units = []*repo_model.RepoUnit{&externalTracker}
- repo.RenderingMetas = nil
+ repo.commonRenderingMetas = nil
metas := repo.ComposeMetas(db.DefaultContext)
assert.Equal(t, expectedStyle, metas["style"])
assert.Equal(t, "testRepo", metas["repo"])
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 54c65c95d2723..6baf7aabef76b 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -249,10 +249,8 @@ func RenderIssueTitle(
ctx *RenderContext,
title string,
) (string, error) {
+ // do not render other issue/commit links in an issue's title - which in most cases is already a link.
return renderProcessString(ctx, []processor{
- issueIndexPatternProcessor,
- commitCrossReferencePatternProcessor,
- hashCurrentPatternProcessor,
emojiShortCodeProcessor,
emojiProcessor,
}, title)
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index 2fb657f56b6ff..b5bcb43e9c26d 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -66,6 +66,12 @@ var localMetas = map[string]string{
"repo": "test-repo",
}
+var localWikiMetas = map[string]string{
+ "user": "test-owner",
+ "repo": "test-repo",
+ "renderContentMode": "wiki",
+}
+
func TestRender_IssueIndexPattern(t *testing.T) {
// numeric: render inputs without valid mentions
test := func(s string) {
@@ -124,9 +130,8 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
}
expectedNil := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNil, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: localMetas,
- ContentMode: RenderContentAsComment,
+ Ctx: git.DefaultContext,
+ Metas: localMetas,
})
class := "ref-issue"
@@ -139,9 +144,8 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
}
expectedNum := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNum, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: numericMetas,
- ContentMode: RenderContentAsComment,
+ Ctx: git.DefaultContext,
+ Metas: numericMetas,
})
}
@@ -270,19 +274,12 @@ func TestRender_IssueIndexPattern_Document(t *testing.T) {
"repo": "someRepo",
"style": IssueNameStyleNumeric,
}
-
- testRenderIssueIndexPattern(t, "#1", "#1", &RenderContext{
+ actual, err := RenderIssueTitle(&RenderContext{
Ctx: git.DefaultContext,
Metas: metas,
- })
- testRenderIssueIndexPattern(t, "#1312", "#1312", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
- })
- testRenderIssueIndexPattern(t, "!1", "!1", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
- })
+ }, "#1")
+ assert.NoError(t, err)
+ assert.Equal(t, "#1", actual)
}
func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *RenderContext) {
@@ -318,8 +315,7 @@ func TestRender_AutoLink(t *testing.T) {
Links: Links{
Base: TestRepoURL,
},
- Metas: localMetas,
- ContentMode: RenderContentAsWiki,
+ Metas: localWikiMetas,
}, strings.NewReader(input), &buffer)
assert.Equal(t, err, nil)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer.String()))
diff --git a/modules/markup/html_issue.go b/modules/markup/html_issue.go
index fa630656cef41..1dc36eed8d3b1 100644
--- a/modules/markup/html_issue.go
+++ b/modules/markup/html_issue.go
@@ -67,8 +67,10 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
return
}
- // crossLinkOnly if not comment and not wiki
- crossLinkOnly := ctx.ContentMode != RenderContentAsTitle && ctx.ContentMode != RenderContentAsComment && ctx.ContentMode != RenderContentAsWiki
+ // crossLinkOnly: do not parse "#123", only parse "owner/repo#123"
+ // if there is no repo in the context, then the "#123" format can't be parsed
+ // old logic: crossLinkOnly := ctx.Metas["mode"] == "document" && !ctx.IsWiki
+ crossLinkOnly := ctx.Metas["markdownAllowShortIssuePattern"] != "true"
var (
found bool
diff --git a/modules/markup/html_link.go b/modules/markup/html_link.go
index 30564da548a66..2916385ad8456 100644
--- a/modules/markup/html_link.go
+++ b/modules/markup/html_link.go
@@ -20,9 +20,9 @@ func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (resu
isAnchorFragment := link != "" && link[0] == '#'
if !isAnchorFragment && !IsFullURLString(link) {
linkBase := ctx.Links.Base
- if ctx.ContentMode == RenderContentAsWiki {
+ if ctx.IsContentModeWiki() {
// no need to check if the link should be resolved as a wiki link or a wiki raw link
- // just use wiki link here and it will be redirected to a wiki raw link if necessary
+ // just use wiki link here, and it will be redirected to a wiki raw link if necessary
linkBase = ctx.Links.WikiLink()
} else if ctx.Links.BranchPath != "" || ctx.Links.TreePath != "" {
// if there is no BranchPath, then the link will be something like "/owner/repo/src/{the-file-path}"
@@ -147,7 +147,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
}
if image {
if !absoluteLink {
- link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.ContentMode == RenderContentAsWiki), link)
+ link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), link)
}
title := props["title"]
if title == "" {
diff --git a/modules/markup/html_node.go b/modules/markup/html_node.go
index c499854053fa2..4bbaee9a447af 100644
--- a/modules/markup/html_node.go
+++ b/modules/markup/html_node.go
@@ -17,7 +17,7 @@ func visitNodeImg(ctx *RenderContext, img *html.Node) (next *html.Node) {
}
if IsNonEmptyRelativePath(attr.Val) {
- attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.ContentMode == RenderContentAsWiki), attr.Val)
+ attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), attr.Val)
// By default, the "
" tag should also be clickable,
// because frontend use `
` to paste the re-scaled image into the markdown,
@@ -53,7 +53,7 @@ func visitNodeVideo(ctx *RenderContext, node *html.Node) (next *html.Node) {
continue
}
if IsNonEmptyRelativePath(attr.Val) {
- attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.ContentMode == RenderContentAsWiki), attr.Val)
+ attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), attr.Val)
}
attr.Val = camoHandleLink(attr.Val)
node.Attr[i] = attr
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 262d0fc4dd5d1..4d97db509d3b7 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -27,6 +27,11 @@ var (
"user": testRepoOwnerName,
"repo": testRepoName,
}
+ localWikiMetas = map[string]string{
+ "user": testRepoOwnerName,
+ "repo": testRepoName,
+ "renderContentMode": "wiki",
+ }
)
type mockRepo struct {
@@ -413,8 +418,7 @@ func TestRender_ShortLinks(t *testing.T) {
Links: markup.Links{
Base: markup.TestRepoURL,
},
- Metas: localMetas,
- ContentMode: markup.RenderContentAsWiki,
+ Metas: localWikiMetas,
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
@@ -526,10 +530,9 @@ func TestRender_ShortLinks(t *testing.T) {
func TestRender_RelativeMedias(t *testing.T) {
render := func(input string, isWiki bool, links markup.Links) string {
buffer, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: links,
- Metas: localMetas,
- ContentMode: util.Iif(isWiki, markup.RenderContentAsWiki, markup.RenderContentAsComment),
+ Ctx: git.DefaultContext,
+ Links: links,
+ Metas: util.Iif(isWiki, localMetas, localWikiMetas),
}, input)
assert.NoError(t, err)
return strings.TrimSpace(string(buffer))
diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index c8488cfb50c37..c837b21e7804c 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -75,11 +75,12 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
// TODO: this was a quite unclear part, old code: `if metas["mode"] != "document" { use comment link break setting }`
// many places render non-comment contents with no mode=document, then these contents also use comment's hard line break setting
// especially in many tests.
+ markdownLineBreakStyle := ctx.Metas["markdownLineBreakStyle"]
if markup.RenderBehaviorForTesting.ForceHardLineBreak {
v.SetHardLineBreak(true)
- } else if ctx.ContentMode == markup.RenderContentAsComment {
+ } else if markdownLineBreakStyle == "comment" {
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInComments)
- } else {
+ } else if markdownLineBreakStyle == "document" {
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
}
}
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 315eed2e62e7c..4e9a3e7e7371b 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -37,6 +37,12 @@ var localMetas = map[string]string{
"repo": testRepoName,
}
+var localWikiMetas = map[string]string{
+ "user": testRepoOwnerName,
+ "repo": testRepoName,
+ "renderContentMode": "wiki",
+}
+
type mockRepo struct {
OwnerName string
RepoName string
@@ -75,7 +81,7 @@ func TestRender_StandardLinks(t *testing.T) {
Links: markup.Links{
Base: FullURL,
},
- ContentMode: markup.RenderContentAsWiki,
+ Metas: localWikiMetas,
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
@@ -307,9 +313,8 @@ func TestTotal_RenderWiki(t *testing.T) {
Links: markup.Links{
Base: FullURL,
},
- Repo: newMockRepo(testRepoOwnerName, testRepoName),
- Metas: localMetas,
- ContentMode: markup.RenderContentAsWiki,
+ Repo: newMockRepo(testRepoOwnerName, testRepoName),
+ Metas: localWikiMetas,
}, sameCases[i])
assert.NoError(t, err)
assert.Equal(t, answers[i], string(line))
@@ -334,7 +339,7 @@ func TestTotal_RenderWiki(t *testing.T) {
Links: markup.Links{
Base: FullURL,
},
- ContentMode: markup.RenderContentAsWiki,
+ Metas: localWikiMetas,
}, testCases[i])
assert.NoError(t, err)
assert.EqualValues(t, testCases[i+1], string(line))
@@ -999,9 +1004,9 @@ space
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
for i, c := range cases {
result, err := markdown.RenderString(&markup.RenderContext{
- Ctx: context.Background(),
- Links: c.Links,
- ContentMode: util.Iif(c.IsWiki, markup.RenderContentAsWiki, markup.RenderContentAsDefault),
+ Ctx: context.Background(),
+ Links: c.Links,
+ Metas: util.Iif(c.IsWiki, localWikiMetas, localMetas),
}, input)
assert.NoError(t, err, "Unexpected error in testcase: %v", i)
assert.Equal(t, c.Expected, string(result), "Unexpected result in testcase %v", i)
diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go
index 4ed4118854386..92e2750fa5925 100644
--- a/modules/markup/markdown/transform_image.go
+++ b/modules/markup/markdown/transform_image.go
@@ -21,7 +21,7 @@ func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image)
// Check if the destination is a real link
if len(v.Destination) > 0 && !markup.IsFullURLBytes(v.Destination) {
v.Destination = []byte(giteautil.URLJoin(
- ctx.Links.ResolveMediaLink(ctx.ContentMode == markup.RenderContentAsWiki),
+ ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()),
strings.TrimLeft(string(v.Destination), "/"),
))
}
diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go
index 6b9c9631575be..e9738a6348186 100644
--- a/modules/markup/orgmode/orgmode.go
+++ b/modules/markup/orgmode/orgmode.go
@@ -144,15 +144,14 @@ func (r *Writer) resolveLink(kind, link string) string {
}
base := r.Ctx.Links.Base
- isWiki := r.Ctx.ContentMode == markup.RenderContentAsWiki
- if isWiki {
+ if r.Ctx.IsContentModeWiki() {
base = r.Ctx.Links.WikiLink()
} else if r.Ctx.Links.HasBranchInfo() {
base = r.Ctx.Links.SrcLink()
}
if kind == "image" || kind == "video" {
- base = r.Ctx.Links.ResolveMediaLink(isWiki)
+ base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsContentModeWiki())
}
link = util.URLJoin(base, link)
diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go
index b882678c7e20e..151f7288888e4 100644
--- a/modules/markup/orgmode/orgmode_test.go
+++ b/modules/markup/orgmode/orgmode_test.go
@@ -27,7 +27,7 @@ func TestRender_StandardLinks(t *testing.T) {
Base: "/relative-path",
BranchPath: "branch/main",
},
- ContentMode: util.Iif(isWiki, markup.RenderContentAsWiki, markup.RenderContentAsDefault),
+ Metas: map[string]string{"renderContentMode": util.Iif(isWiki, "wiki", "")},
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
diff --git a/modules/markup/render.go b/modules/markup/render.go
index add50f438272a..accd8d42ae5c0 100644
--- a/modules/markup/render.go
+++ b/modules/markup/render.go
@@ -27,15 +27,6 @@ const (
RenderMetaAsTable RenderMetaMode = "table"
)
-type RenderContentMode string
-
-const (
- RenderContentAsDefault RenderContentMode = "" // empty means "default", no special handling, maybe just a simple "document"
- RenderContentAsComment RenderContentMode = "comment"
- RenderContentAsTitle RenderContentMode = "title"
- RenderContentAsWiki RenderContentMode = "wiki"
-)
-
var RenderBehaviorForTesting struct {
// Markdown line break rendering has 2 default behaviors:
// * Use hard: replace "\n" with "
" for comments, setting.Markdown.EnableHardLineBreakInComments=true
@@ -59,12 +50,13 @@ type RenderContext struct {
// for file mode, it could be left as empty, and will be detected by file extension in RelativePath
MarkupType string
- // what the content will be used for: eg: for comment or for wiki? or just render a file?
- ContentMode RenderContentMode
+ Links Links // special link references for rendering, especially when there is a branch/tree path
+
+ // user&repo, format&style®exp (for external issue pattern), teams&org (for mention), BranchNameSubURL(for iframe&asciicast)
+ // markdownLineBreakStyle(comment or document)
+ Metas map[string]string
- Links Links // special link references for rendering, especially when there is a branch/tree path
- Metas map[string]string // user&repo, format&style®exp (for external issue pattern), teams&org (for mention), BranchNameSubURL(for iframe&asciicast)
- DefaultLink string // TODO: need to figure out
+ DefaultLink string // TODO: need to figure out
GitRepo *git.Repository
Repo gitrepo.Repository
ShaExistCache map[string]bool
@@ -101,6 +93,9 @@ func (ctx *RenderContext) AddCancel(fn func()) {
fn()
}
}
+func (ctx *RenderContext) IsContentModeWiki() bool {
+ return ctx.Metas != nil && ctx.Metas["renderContentMode"] == "wiki"
+}
// Render renders markup file to HTML with all specific handling stuff.
func Render(ctx *RenderContext, input io.Reader, output io.Writer) error {
diff --git a/modules/markup/render_links.go b/modules/markup/render_links.go
index 3e1aa7ce3a5df..c8339d8f8b3f2 100644
--- a/modules/markup/render_links.go
+++ b/modules/markup/render_links.go
@@ -10,7 +10,7 @@ import (
type Links struct {
AbsolutePrefix bool // add absolute URL prefix to auto-resolved links like "#issue", but not for pre-provided links and medias
- Base string // base prefix for pre-provided links and medias (images, videos)
+ Base string // base prefix for pre-provided links and medias (images, videos), usually it is the path to the repo
BranchPath string // actually it is the ref path, eg: "branch/features/feat-12", "tag/v1.0"
TreePath string // the dir of the file, eg: "doc" if the file "doc/CHANGE.md" is being rendered
}
diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go
index 1db1e4a111919..1201828345715 100644
--- a/modules/templates/util_render.go
+++ b/modules/templates/util_render.go
@@ -94,9 +94,8 @@ func (ut *RenderUtils) RenderCommitBody(msg string, metas map[string]string) tem
}
renderedMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
- Ctx: ut.ctx,
- Metas: metas,
- ContentMode: markup.RenderContentAsComment,
+ Ctx: ut.ctx,
+ Metas: metas,
}, template.HTMLEscapeString(msgLine))
if err != nil {
log.Error("RenderCommitMessage: %v", err)
@@ -117,9 +116,8 @@ func renderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
// RenderIssueTitle renders issue/pull title with defined post processors
func (ut *RenderUtils) RenderIssueTitle(text string, metas map[string]string) template.HTML {
renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
- Ctx: ut.ctx,
- ContentMode: markup.RenderContentAsTitle,
- Metas: metas,
+ Ctx: ut.ctx,
+ Metas: metas,
}, template.HTMLEscapeString(text))
if err != nil {
log.Error("RenderIssueTitle: %v", err)
diff --git a/routers/common/markup.go b/routers/common/markup.go
index c8cc1a5ff1271..03ef5d6172f1c 100644
--- a/routers/common/markup.go
+++ b/routers/common/markup.go
@@ -45,16 +45,7 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
return
}
switch mode {
- case "gfm": // legacy mode, do nothing
- case "comment":
- renderCtx.ContentMode = markup.RenderContentAsComment
- case "wiki":
- renderCtx.ContentMode = markup.RenderContentAsWiki
- case "file":
- // render the repo file content by its extension
- renderCtx.MarkupType = ""
- renderCtx.RelativePath = filePath
- renderCtx.InStandalonePage = true
+ case "gfm", "comment", "wiki", "file":
default:
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Unknown mode: %s", mode))
return
@@ -74,10 +65,15 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
if repo != nil && repo.Repository != nil {
renderCtx.Repo = repo.Repository
- if renderCtx.ContentMode == markup.RenderContentAsComment {
- renderCtx.Metas = repo.Repository.ComposeMetas(ctx)
- } else {
+ if mode == "file" {
+ renderCtx.MarkupType = ""
+ renderCtx.RelativePath = filePath
+ renderCtx.InStandalonePage = true
renderCtx.Metas = repo.Repository.ComposeDocumentMetas(ctx)
+ } else if mode == "wiki" {
+ renderCtx.Metas = repo.Repository.ComposeWikiMetas(ctx)
+ } else if mode == "comment" {
+ renderCtx.Metas = repo.Repository.ComposeMetas(ctx)
}
}
if err := markup.Render(renderCtx, strings.NewReader(text), ctx.Resp); err != nil {
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 2b8312f10acdf..13f6b69493e09 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -289,9 +289,8 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
rctx := &markup.RenderContext{
- Ctx: ctx,
- ContentMode: markup.RenderContentAsWiki,
- Metas: ctx.Repo.Repository.ComposeDocumentMetas(ctx),
+ Ctx: ctx,
+ Metas: ctx.Repo.Repository.ComposeWikiMetas(ctx),
Links: markup.Links{
Base: ctx.Repo.RepoLink,
},
From ecc42444183122dcb6fea4c8cd98e1b0081a940a Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Fri, 15 Nov 2024 20:21:14 +0800
Subject: [PATCH 2/6] fix render metas
---
models/repo/repo.go | 4 +-
models/repo/repo_test.go | 65 +++++++++++-----------
modules/markup/html_internal_test.go | 25 +++++----
modules/markup/html_issue.go | 2 +-
modules/markup/html_link.go | 4 +-
modules/markup/html_node.go | 4 +-
modules/markup/html_test.go | 4 +-
modules/markup/markdown/markdown_test.go | 52 ++++++++---------
modules/markup/markdown/transform_image.go | 2 +-
modules/markup/orgmode/orgmode.go | 4 +-
modules/markup/orgmode/orgmode_test.go | 2 +-
modules/markup/render.go | 15 +++--
modules/templates/util_render.go | 2 +-
modules/templates/util_render_test.go | 18 +++---
routers/common/markup.go | 14 +++--
routers/web/feed/convert.go | 2 +-
routers/web/feed/profile.go | 4 +-
routers/web/org/home.go | 2 +-
routers/web/shared/user/header.go | 2 +-
19 files changed, 120 insertions(+), 107 deletions(-)
diff --git a/models/repo/repo.go b/models/repo/repo.go
index eba41481aaf41..7d78cee2877d4 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -517,7 +517,7 @@ func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]strin
func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
metas := maps.Clone(repo.composeCommonMetas(ctx))
metas["markdownLineBreakStyle"] = "comment"
- metas["markdownAllowShortIssuePattern"] = "true"
+ metas["markupAllowShortIssuePattern"] = "true"
return metas
}
@@ -526,7 +526,7 @@ func (repo *Repository) ComposeWikiMetas(ctx context.Context) map[string]string
// does wiki need the "teams" and "org" from common metas?
metas := maps.Clone(repo.composeCommonMetas(ctx))
metas["markdownLineBreakStyle"] = "document"
- metas["markdownAllowShortIssuePattern"] = "true"
+ metas["markupAllowShortIssuePattern"] = "true"
return metas
}
diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go
index ab8eb025cba36..6468e0f605889 100644
--- a/models/repo/repo_test.go
+++ b/models/repo/repo_test.go
@@ -1,13 +1,12 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
-package repo_test
+package repo
import (
"testing"
"code.gitea.io/gitea/models/db"
- repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
@@ -20,18 +19,18 @@ import (
)
var (
- countRepospts = repo_model.CountRepositoryOptions{OwnerID: 10}
- countReposptsPublic = repo_model.CountRepositoryOptions{OwnerID: 10, Private: optional.Some(false)}
- countReposptsPrivate = repo_model.CountRepositoryOptions{OwnerID: 10, Private: optional.Some(true)}
+ countRepospts = CountRepositoryOptions{OwnerID: 10}
+ countReposptsPublic = CountRepositoryOptions{OwnerID: 10, Private: optional.Some(false)}
+ countReposptsPrivate = CountRepositoryOptions{OwnerID: 10, Private: optional.Some(true)}
)
func TestGetRepositoryCount(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
ctx := db.DefaultContext
- count, err1 := repo_model.CountRepositories(ctx, countRepospts)
- privateCount, err2 := repo_model.CountRepositories(ctx, countReposptsPrivate)
- publicCount, err3 := repo_model.CountRepositories(ctx, countReposptsPublic)
+ count, err1 := CountRepositories(ctx, countRepospts)
+ privateCount, err2 := CountRepositories(ctx, countReposptsPrivate)
+ publicCount, err3 := CountRepositories(ctx, countReposptsPublic)
assert.NoError(t, err1)
assert.NoError(t, err2)
assert.NoError(t, err3)
@@ -42,7 +41,7 @@ func TestGetRepositoryCount(t *testing.T) {
func TestGetPublicRepositoryCount(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- count, err := repo_model.CountRepositories(db.DefaultContext, countReposptsPublic)
+ count, err := CountRepositories(db.DefaultContext, countReposptsPublic)
assert.NoError(t, err)
assert.Equal(t, int64(1), count)
}
@@ -50,14 +49,14 @@ func TestGetPublicRepositoryCount(t *testing.T) {
func TestGetPrivateRepositoryCount(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- count, err := repo_model.CountRepositories(db.DefaultContext, countReposptsPrivate)
+ count, err := CountRepositories(db.DefaultContext, countReposptsPrivate)
assert.NoError(t, err)
assert.Equal(t, int64(2), count)
}
func TestRepoAPIURL(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
+ repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 10})
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user12/repo10", repo.APIURL())
}
@@ -65,22 +64,22 @@ func TestRepoAPIURL(t *testing.T) {
func TestWatchRepo(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
+ repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 3})
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
- assert.NoError(t, repo_model.WatchRepo(db.DefaultContext, user, repo, true))
- unittest.AssertExistsAndLoadBean(t, &repo_model.Watch{RepoID: repo.ID, UserID: user.ID})
- unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
+ assert.NoError(t, WatchRepo(db.DefaultContext, user, repo, true))
+ unittest.AssertExistsAndLoadBean(t, &Watch{RepoID: repo.ID, UserID: user.ID})
+ unittest.CheckConsistencyFor(t, &Repository{ID: repo.ID})
- assert.NoError(t, repo_model.WatchRepo(db.DefaultContext, user, repo, false))
- unittest.AssertNotExistsBean(t, &repo_model.Watch{RepoID: repo.ID, UserID: user.ID})
- unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
+ assert.NoError(t, WatchRepo(db.DefaultContext, user, repo, false))
+ unittest.AssertNotExistsBean(t, &Watch{RepoID: repo.ID, UserID: user.ID})
+ unittest.CheckConsistencyFor(t, &Repository{ID: repo.ID})
}
func TestMetas(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
- repo := &repo_model.Repository{Name: "testRepo"}
+ repo := &Repository{Name: "testRepo"}
repo.Owner = &user_model.User{Name: "testOwner"}
repo.OwnerName = repo.Owner.Name
@@ -90,15 +89,15 @@ func TestMetas(t *testing.T) {
assert.Equal(t, "testRepo", metas["repo"])
assert.Equal(t, "testOwner", metas["user"])
- externalTracker := repo_model.RepoUnit{
+ externalTracker := RepoUnit{
Type: unit.TypeExternalTracker,
- Config: &repo_model.ExternalTrackerConfig{
+ Config: &ExternalTrackerConfig{
ExternalTrackerFormat: "https://someurl.com/{user}/{repo}/{issue}",
},
}
testSuccess := func(expectedStyle string) {
- repo.Units = []*repo_model.RepoUnit{&externalTracker}
+ repo.Units = []*RepoUnit{&externalTracker}
repo.commonRenderingMetas = nil
metas := repo.ComposeMetas(db.DefaultContext)
assert.Equal(t, expectedStyle, metas["style"])
@@ -118,7 +117,7 @@ func TestMetas(t *testing.T) {
externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markup.IssueNameStyleRegexp
testSuccess(markup.IssueNameStyleRegexp)
- repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 3)
+ repo, err := GetRepositoryByID(db.DefaultContext, 3)
assert.NoError(t, err)
metas = repo.ComposeMetas(db.DefaultContext)
@@ -132,7 +131,7 @@ func TestGetRepositoryByURL(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
t.Run("InvalidPath", func(t *testing.T) {
- repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, "something")
+ repo, err := GetRepositoryByURL(db.DefaultContext, "something")
assert.Nil(t, repo)
assert.Error(t, err)
@@ -140,7 +139,7 @@ func TestGetRepositoryByURL(t *testing.T) {
t.Run("ValidHttpURL", func(t *testing.T) {
test := func(t *testing.T, url string) {
- repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
+ repo, err := GetRepositoryByURL(db.DefaultContext, url)
assert.NotNil(t, repo)
assert.NoError(t, err)
@@ -155,7 +154,7 @@ func TestGetRepositoryByURL(t *testing.T) {
t.Run("ValidGitSshURL", func(t *testing.T) {
test := func(t *testing.T, url string) {
- repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
+ repo, err := GetRepositoryByURL(db.DefaultContext, url)
assert.NotNil(t, repo)
assert.NoError(t, err)
@@ -173,7 +172,7 @@ func TestGetRepositoryByURL(t *testing.T) {
t.Run("ValidImplicitSshURL", func(t *testing.T) {
test := func(t *testing.T, url string) {
- repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
+ repo, err := GetRepositoryByURL(db.DefaultContext, url)
assert.NotNil(t, repo)
assert.NoError(t, err)
@@ -200,21 +199,21 @@ func TestComposeSSHCloneURL(t *testing.T) {
setting.SSH.Domain = "domain"
setting.SSH.Port = 22
setting.Repository.UseCompatSSHURI = false
- assert.Equal(t, "git@domain:user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "git@domain:user/repo.git", ComposeSSHCloneURL("user", "repo"))
setting.Repository.UseCompatSSHURI = true
- assert.Equal(t, "ssh://git@domain/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "ssh://git@domain/user/repo.git", ComposeSSHCloneURL("user", "repo"))
// test SSH_DOMAIN while use non-standard SSH port
setting.SSH.Port = 123
setting.Repository.UseCompatSSHURI = false
- assert.Equal(t, "ssh://git@domain:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "ssh://git@domain:123/user/repo.git", ComposeSSHCloneURL("user", "repo"))
setting.Repository.UseCompatSSHURI = true
- assert.Equal(t, "ssh://git@domain:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "ssh://git@domain:123/user/repo.git", ComposeSSHCloneURL("user", "repo"))
// test IPv6 SSH_DOMAIN
setting.Repository.UseCompatSSHURI = false
setting.SSH.Domain = "::1"
setting.SSH.Port = 22
- assert.Equal(t, "git@[::1]:user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "git@[::1]:user/repo.git", ComposeSSHCloneURL("user", "repo"))
setting.SSH.Port = 123
- assert.Equal(t, "ssh://git@[::1]:123/user/repo.git", repo_model.ComposeSSHCloneURL("user", "repo"))
+ assert.Equal(t, "ssh://git@[::1]:123/user/repo.git", ComposeSSHCloneURL("user", "repo"))
}
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index b5bcb43e9c26d..8c44dcf827005 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -40,17 +40,19 @@ func link(href, class, contents string) string {
}
var numericMetas = map[string]string{
- "format": "https://someurl.com/{user}/{repo}/{index}",
- "user": "someUser",
- "repo": "someRepo",
- "style": IssueNameStyleNumeric,
+ "format": "https://someurl.com/{user}/{repo}/{index}",
+ "user": "someUser",
+ "repo": "someRepo",
+ "style": IssueNameStyleNumeric,
+ "markupAllowShortIssuePattern": "true",
}
var alphanumericMetas = map[string]string{
- "format": "https://someurl.com/{user}/{repo}/{index}",
- "user": "someUser",
- "repo": "someRepo",
- "style": IssueNameStyleAlphanumeric,
+ "format": "https://someurl.com/{user}/{repo}/{index}",
+ "user": "someUser",
+ "repo": "someRepo",
+ "style": IssueNameStyleAlphanumeric,
+ "markupAllowShortIssuePattern": "true",
}
var regexpMetas = map[string]string{
@@ -62,14 +64,15 @@ var regexpMetas = map[string]string{
// these values should match the TestOrgRepo const above
var localMetas = map[string]string{
- "user": "test-owner",
- "repo": "test-repo",
+ "user": "test-owner",
+ "repo": "test-repo",
+ "markupAllowShortIssuePattern": "true",
}
var localWikiMetas = map[string]string{
"user": "test-owner",
"repo": "test-repo",
- "renderContentMode": "wiki",
+ "markupContentMode": "wiki",
}
func TestRender_IssueIndexPattern(t *testing.T) {
diff --git a/modules/markup/html_issue.go b/modules/markup/html_issue.go
index 1dc36eed8d3b1..3a315268b6fb9 100644
--- a/modules/markup/html_issue.go
+++ b/modules/markup/html_issue.go
@@ -70,7 +70,7 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
// crossLinkOnly: do not parse "#123", only parse "owner/repo#123"
// if there is no repo in the context, then the "#123" format can't be parsed
// old logic: crossLinkOnly := ctx.Metas["mode"] == "document" && !ctx.IsWiki
- crossLinkOnly := ctx.Metas["markdownAllowShortIssuePattern"] != "true"
+ crossLinkOnly := ctx.Metas["markupAllowShortIssuePattern"] != "true"
var (
found bool
diff --git a/modules/markup/html_link.go b/modules/markup/html_link.go
index 2916385ad8456..1a7c5c8d92c13 100644
--- a/modules/markup/html_link.go
+++ b/modules/markup/html_link.go
@@ -20,7 +20,7 @@ func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (resu
isAnchorFragment := link != "" && link[0] == '#'
if !isAnchorFragment && !IsFullURLString(link) {
linkBase := ctx.Links.Base
- if ctx.IsContentModeWiki() {
+ if ctx.IsMarkupContentWiki() {
// no need to check if the link should be resolved as a wiki link or a wiki raw link
// just use wiki link here, and it will be redirected to a wiki raw link if necessary
linkBase = ctx.Links.WikiLink()
@@ -147,7 +147,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
}
if image {
if !absoluteLink {
- link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), link)
+ link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), link)
}
title := props["title"]
if title == "" {
diff --git a/modules/markup/html_node.go b/modules/markup/html_node.go
index 4bbaee9a447af..234adba2bfa8d 100644
--- a/modules/markup/html_node.go
+++ b/modules/markup/html_node.go
@@ -17,7 +17,7 @@ func visitNodeImg(ctx *RenderContext, img *html.Node) (next *html.Node) {
}
if IsNonEmptyRelativePath(attr.Val) {
- attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), attr.Val)
+ attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), attr.Val)
// By default, the "
" tag should also be clickable,
// because frontend use `
` to paste the re-scaled image into the markdown,
@@ -53,7 +53,7 @@ func visitNodeVideo(ctx *RenderContext, node *html.Node) (next *html.Node) {
continue
}
if IsNonEmptyRelativePath(attr.Val) {
- attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()), attr.Val)
+ attr.Val = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), attr.Val)
}
attr.Val = camoHandleLink(attr.Val)
node.Attr[i] = attr
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 4d97db509d3b7..67ac2758a31fb 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -30,7 +30,7 @@ var (
localWikiMetas = map[string]string{
"user": testRepoOwnerName,
"repo": testRepoName,
- "renderContentMode": "wiki",
+ "markupContentMode": "wiki",
}
)
@@ -532,7 +532,7 @@ func TestRender_RelativeMedias(t *testing.T) {
buffer, err := markdown.RenderString(&markup.RenderContext{
Ctx: git.DefaultContext,
Links: links,
- Metas: util.Iif(isWiki, localMetas, localWikiMetas),
+ Metas: util.Iif(isWiki, localWikiMetas, localMetas),
}, input)
assert.NoError(t, err)
return strings.TrimSpace(string(buffer))
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index 4e9a3e7e7371b..780df8727f0c8 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -40,7 +40,7 @@ var localMetas = map[string]string{
var localWikiMetas = map[string]string{
"user": testRepoOwnerName,
"repo": testRepoName,
- "renderContentMode": "wiki",
+ "markupContentMode": "wiki",
}
type mockRepo struct {
@@ -662,9 +662,9 @@ mail@domain.com



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -689,9 +689,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -718,9 +718,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -747,9 +747,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -776,9 +776,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -805,9 +805,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -835,9 +835,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -865,9 +865,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -895,9 +895,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -925,9 +925,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -956,9 +956,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -987,9 +987,9 @@ space



-https://example.com/user/repo/compare/88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb#hash
+88fc37a3c0...12fc37a3c0 (hash)
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb...12fc37a3c0a4dda553bdcfc80c178a58247f42fb pare
-https://example.com/user/repo/commit/88fc37a3c0a4dda553bdcfc80c178a58247f42fb
+88fc37a3c0
com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@@ -1006,7 +1006,7 @@ space
result, err := markdown.RenderString(&markup.RenderContext{
Ctx: context.Background(),
Links: c.Links,
- Metas: util.Iif(c.IsWiki, localWikiMetas, localMetas),
+ Metas: util.Iif(c.IsWiki, map[string]string{"markupContentMode": "wiki"}, map[string]string{}),
}, input)
assert.NoError(t, err, "Unexpected error in testcase: %v", i)
assert.Equal(t, c.Expected, string(result), "Unexpected result in testcase %v", i)
diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go
index 92e2750fa5925..b2262c1c7885d 100644
--- a/modules/markup/markdown/transform_image.go
+++ b/modules/markup/markdown/transform_image.go
@@ -21,7 +21,7 @@ func (g *ASTTransformer) transformImage(ctx *markup.RenderContext, v *ast.Image)
// Check if the destination is a real link
if len(v.Destination) > 0 && !markup.IsFullURLBytes(v.Destination) {
v.Destination = []byte(giteautil.URLJoin(
- ctx.Links.ResolveMediaLink(ctx.IsContentModeWiki()),
+ ctx.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()),
strings.TrimLeft(string(v.Destination), "/"),
))
}
diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go
index e9738a6348186..c587a6ada5ef0 100644
--- a/modules/markup/orgmode/orgmode.go
+++ b/modules/markup/orgmode/orgmode.go
@@ -144,14 +144,14 @@ func (r *Writer) resolveLink(kind, link string) string {
}
base := r.Ctx.Links.Base
- if r.Ctx.IsContentModeWiki() {
+ if r.Ctx.IsMarkupContentWiki() {
base = r.Ctx.Links.WikiLink()
} else if r.Ctx.Links.HasBranchInfo() {
base = r.Ctx.Links.SrcLink()
}
if kind == "image" || kind == "video" {
- base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsContentModeWiki())
+ base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsMarkupContentWiki())
}
link = util.URLJoin(base, link)
diff --git a/modules/markup/orgmode/orgmode_test.go b/modules/markup/orgmode/orgmode_test.go
index 151f7288888e4..a3eefc3db3df9 100644
--- a/modules/markup/orgmode/orgmode_test.go
+++ b/modules/markup/orgmode/orgmode_test.go
@@ -27,7 +27,7 @@ func TestRender_StandardLinks(t *testing.T) {
Base: "/relative-path",
BranchPath: "branch/main",
},
- Metas: map[string]string{"renderContentMode": util.Iif(isWiki, "wiki", "")},
+ Metas: map[string]string{"markupContentMode": util.Iif(isWiki, "wiki", "")},
}, input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
diff --git a/modules/markup/render.go b/modules/markup/render.go
index accd8d42ae5c0..80023be77a877 100644
--- a/modules/markup/render.go
+++ b/modules/markup/render.go
@@ -52,8 +52,10 @@ type RenderContext struct {
Links Links // special link references for rendering, especially when there is a branch/tree path
- // user&repo, format&style®exp (for external issue pattern), teams&org (for mention), BranchNameSubURL(for iframe&asciicast)
- // markdownLineBreakStyle(comment or document)
+ // user&repo, format&style®exp (for external issue pattern), teams&org (for mention)
+ // BranchNameSubURL (for iframe&asciicast)
+ // markupAllowShortIssuePattern, markupContentMode (wiki)
+ // markdownLineBreakStyle (comment, document)
Metas map[string]string
DefaultLink string // TODO: need to figure out
@@ -93,8 +95,9 @@ func (ctx *RenderContext) AddCancel(fn func()) {
fn()
}
}
-func (ctx *RenderContext) IsContentModeWiki() bool {
- return ctx.Metas != nil && ctx.Metas["renderContentMode"] == "wiki"
+
+func (ctx *RenderContext) IsMarkupContentWiki() bool {
+ return ctx.Metas != nil && ctx.Metas["markupContentMode"] == "wiki"
}
// Render renders markup file to HTML with all specific handling stuff.
@@ -227,3 +230,7 @@ func Init(ph *ProcessorHelper) {
}
}
}
+
+func ComposeSimpleDocumentMetas() map[string]string {
+ return map[string]string{"markdownLineBreakStyle": "document"}
+}
diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go
index 1201828345715..aa7b09a1a23a2 100644
--- a/modules/templates/util_render.go
+++ b/modules/templates/util_render.go
@@ -210,7 +210,7 @@ func reactionToEmoji(reaction string) template.HTML {
func (ut *RenderUtils) MarkdownToHtml(input string) template.HTML { //nolint:revive
output, err := markdown.RenderString(&markup.RenderContext{
Ctx: ut.ctx,
- Metas: map[string]string{"mode": "document"},
+ Metas: markup.ComposeSimpleDocumentMetas(),
}, input)
if err != nil {
log.Error("RenderString: %v", err)
diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go
index 2d331b8317197..498e42f7258da 100644
--- a/modules/templates/util_render_test.go
+++ b/modules/templates/util_render_test.go
@@ -47,10 +47,11 @@ mail@domain.com
}
var testMetas = map[string]string{
- "user": "user13",
- "repo": "repo11",
- "repoPath": "../../tests/gitea-repositories-meta/user13/repo11.git/",
- "mode": "comment",
+ "user": "user13",
+ "repo": "repo11",
+ "repoPath": "../../tests/gitea-repositories-meta/user13/repo11.git/",
+ "markdownLineBreakStyle": "comment",
+ "markupAllowShortIssuePattern": "true",
}
func TestMain(m *testing.M) {
@@ -75,8 +76,7 @@ func newTestRenderUtils() *RenderUtils {
func TestRenderCommitBody(t *testing.T) {
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
type args struct {
- msg string
- metas map[string]string
+ msg string
}
tests := []struct {
name string
@@ -108,7 +108,7 @@ func TestRenderCommitBody(t *testing.T) {
ut := newTestRenderUtils()
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, tt.args.metas), "RenderCommitBody(%v, %v)", tt.args.msg, tt.args.metas)
+ assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, nil), "RenderCommitBody(%v, %v)", tt.args.msg, nil)
})
}
@@ -164,11 +164,11 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
👍
mail@domain.com
@mention-user test
-#123
+#123
space
`
expected = strings.ReplaceAll(expected, "", " ")
- assert.EqualValues(t, expected, string(newTestRenderUtils().RenderIssueTitle(testInput(), testMetas)))
+ assert.EqualValues(t, expected, string(newTestRenderUtils().RenderIssueTitle(testInput(), nil)))
}
func TestRenderMarkdownToHtml(t *testing.T) {
diff --git a/routers/common/markup.go b/routers/common/markup.go
index 03ef5d6172f1c..272c3a643b5fa 100644
--- a/routers/common/markup.go
+++ b/routers/common/markup.go
@@ -45,7 +45,16 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
return
}
switch mode {
- case "gfm", "comment", "wiki", "file":
+ case "gfm": // legacy mode, do nothing
+ case "comment":
+ renderCtx.Metas = map[string]string{"markdownLineBreakStyle": "comment"}
+ case "wiki":
+ renderCtx.Metas = map[string]string{"markdownLineBreakStyle": "document", "markupContentMode": "wiki"}
+ case "file":
+ renderCtx.Metas = map[string]string{"markdownLineBreakStyle": "document"}
+ renderCtx.MarkupType = ""
+ renderCtx.RelativePath = filePath
+ renderCtx.InStandalonePage = true
default:
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Unknown mode: %s", mode))
return
@@ -66,9 +75,6 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
if repo != nil && repo.Repository != nil {
renderCtx.Repo = repo.Repository
if mode == "file" {
- renderCtx.MarkupType = ""
- renderCtx.RelativePath = filePath
- renderCtx.InStandalonePage = true
renderCtx.Metas = repo.Repository.ComposeDocumentMetas(ctx)
} else if mode == "wiki" {
renderCtx.Metas = repo.Repository.ComposeWikiMetas(ctx)
diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go
index a273515c8a3b0..afc2c343a68b3 100644
--- a/routers/web/feed/convert.go
+++ b/routers/web/feed/convert.go
@@ -56,7 +56,7 @@ func renderMarkdown(ctx *context.Context, act *activities_model.Action, content
Links: markup.Links{
Base: act.GetRepoLink(ctx),
},
- Metas: map[string]string{
+ Metas: map[string]string{ // FIXME: not right here, it should use issue to compose the metas
"user": act.GetRepoUserName(ctx),
"repo": act.GetRepoName(ctx),
},
diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go
index 08cbcd9e12bc3..6dd2d14cc6bcf 100644
--- a/routers/web/feed/profile.go
+++ b/routers/web/feed/profile.go
@@ -46,9 +46,7 @@ func showUserFeed(ctx *context.Context, formatType string) {
Links: markup.Links{
Base: ctx.ContextUser.HTMLURL(),
},
- Metas: map[string]string{
- "user": ctx.ContextUser.GetDisplayName(),
- },
+ Metas: markup.ComposeSimpleDocumentMetas(),
}, ctx.ContextUser.Description)
if err != nil {
ctx.ServerError("RenderString", err)
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index 544f5362b897d..18648d33cd79f 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -189,7 +189,7 @@ func prepareOrgProfileReadme(ctx *context.Context, viewRepositories bool) bool {
Base: profileDbRepo.Link(),
BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)),
},
- Metas: map[string]string{"mode": "document"},
+ Metas: markup.ComposeSimpleDocumentMetas(),
}, bytes); err != nil {
log.Error("failed to RenderString: %v", err)
} else {
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index ef111cff806fc..9467b0986b3d5 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -50,7 +50,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) {
ctx.Data["OpenIDs"] = openIDs
if len(ctx.ContextUser.Description) != 0 {
content, err := markdown.RenderString(&markup.RenderContext{
- Metas: map[string]string{"mode": "document"},
+ Metas: markup.ComposeSimpleDocumentMetas(),
Ctx: ctx,
}, ctx.ContextUser.Description)
if err != nil {
From 863170a91a08733c1e101307ba211486357a8f1e Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sat, 16 Nov 2024 09:34:51 +0800
Subject: [PATCH 3/6] take back some tests
---
modules/markup/html_internal_test.go | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index 8c44dcf827005..916d2697b440f 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -269,7 +269,30 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
})
}
-func TestRender_IssueIndexPattern_Document(t *testing.T) {
+func TestRender_IssueIndexPattern_NoShortPattern(t *testing.T) {
+ setting.AppURL = TestAppURL
+ metas := map[string]string{
+ "format": "https://someurl.com/{user}/{repo}/{index}",
+ "user": "someUser",
+ "repo": "someRepo",
+ "style": IssueNameStyleNumeric,
+ }
+
+ testRenderIssueIndexPattern(t, "#1", "#1", &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: metas,
+ })
+ testRenderIssueIndexPattern(t, "#1312", "#1312", &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: metas,
+ })
+ testRenderIssueIndexPattern(t, "!1", "!1", &RenderContext{
+ Ctx: git.DefaultContext,
+ Metas: metas,
+ })
+}
+
+func TestRender_RenderIssueTitle(t *testing.T) {
setting.AppURL = TestAppURL
metas := map[string]string{
"format": "https://someurl.com/{user}/{repo}/{index}",
From 526286bd62bf21481b411fa531058741725612a3 Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sat, 16 Nov 2024 10:09:57 +0800
Subject: [PATCH 4/6] refactor global vars
---
modules/markup/html.go | 96 +++++++++++++---------------
modules/markup/html_commit.go | 6 +-
modules/markup/html_email.go | 2 +-
modules/markup/html_emoji.go | 2 +-
modules/markup/html_internal_test.go | 8 +--
modules/markup/html_issue.go | 4 +-
modules/markup/html_link.go | 2 +-
7 files changed, 57 insertions(+), 63 deletions(-)
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 6baf7aabef76b..7b1d5a4d9c7cd 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -25,7 +25,27 @@ const (
IssueNameStyleRegexp = "regexp"
)
-var (
+// CSS class for action keywords (e.g. "closes: #1")
+const keywordClass = "issue-keyword"
+
+type globalVarsType struct {
+ hashCurrentPattern *regexp.Regexp
+ shortLinkPattern *regexp.Regexp
+ anyHashPattern *regexp.Regexp
+ comparePattern *regexp.Regexp
+ fullURLPattern *regexp.Regexp
+ emailRegex *regexp.Regexp
+ blackfridayExtRegex *regexp.Regexp
+ emojiShortCodeRegex *regexp.Regexp
+ issueFullPattern *regexp.Regexp
+ filesChangedFullPattern *regexp.Regexp
+
+ tagCleaner *regexp.Regexp
+ nulCleaner *strings.Replacer
+}
+
+var globalVars = sync.OnceValue[*globalVarsType](func() *globalVarsType {
+ v := &globalVarsType{}
// NOTE: All below regex matching do not perform any extra validation.
// Thus a link is produced even if the linked entity does not exist.
// While fast, this is also incorrect and lead to false positives.
@@ -36,79 +56,58 @@ var (
// hashCurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae
// Although SHA1 hashes are 40 chars long, SHA256 are 64, the regex matches the hash from 7 to 64 chars in length
// so that abbreviated hash links can be used as well. This matches git and GitHub usability.
- hashCurrentPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-f]{7,64})(?:\s|$|\)|\]|[.,:](\s|$))`)
+ v.hashCurrentPattern = regexp.MustCompile(`(?:\s|^|\(|\[)([0-9a-f]{7,64})(?:\s|$|\)|\]|[.,:](\s|$))`)
// shortLinkPattern matches short but difficult to parse [[name|link|arg=test]] syntax
- shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
+ v.shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
// anyHashPattern splits url containing SHA into parts
- anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~%./\w]+)?(\?[-+~%.\w&=]+)?(#[-+~%.\w]+)?`)
+ v.anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~%./\w]+)?(\?[-+~%.\w&=]+)?(#[-+~%.\w]+)?`)
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
- comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
+ v.comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
// fullURLPattern matches full URL like "mailto:...", "https://..." and "ssh+git://..."
- fullURLPattern = regexp.MustCompile(`^[a-z][-+\w]+:`)
+ v.fullURLPattern = regexp.MustCompile(`^[a-z][-+\w]+:`)
// emailRegex is definitely not perfect with edge cases,
// it is still accepted by the CommonMark specification, as well as the HTML5 spec:
// http://spec.commonmark.org/0.28/#email-address
// https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type%3Demail)
- emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))")
+ v.emailRegex = regexp.MustCompile("(?:\\s|^|\\(|\\[)([a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9]{2,}(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+)(?:\\s|$|\\)|\\]|;|,|\\?|!|\\.(\\s|$))")
// blackfridayExtRegex is for blackfriday extensions create IDs like fn:user-content-footnote
- blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`)
+ v.blackfridayExtRegex = regexp.MustCompile(`[^:]*:user-content-`)
// emojiShortCodeRegex find emoji by alias like :smile:
- emojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
-)
+ v.emojiShortCodeRegex = regexp.MustCompile(`:[-+\w]+:`)
-// CSS class for action keywords (e.g. "closes: #1")
-const keywordClass = "issue-keyword"
+ // example: https://domain/org/repo/pulls/27#hash
+ v.issueFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) +
+ `[\w_.-]+/[\w_.-]+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`)
+
+ // example: https://domain/org/repo/pulls/27/files#hash
+ v.filesChangedFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) +
+ `[\w_.-]+/[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b`)
+
+ v.tagCleaner = regexp.MustCompile(`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL]\b)|(/?[hH][eE][aA][dD]\b))`)
+ v.nulCleaner = strings.NewReplacer("\000", "")
+ return v
+})
// IsFullURLBytes reports whether link fits valid format.
func IsFullURLBytes(link []byte) bool {
- return fullURLPattern.Match(link)
+ return globalVars().fullURLPattern.Match(link)
}
func IsFullURLString(link string) bool {
- return fullURLPattern.MatchString(link)
+ return globalVars().fullURLPattern.MatchString(link)
}
func IsNonEmptyRelativePath(link string) bool {
return link != "" && !IsFullURLString(link) && link[0] != '/' && link[0] != '?' && link[0] != '#'
}
-// regexp for full links to issues/pulls
-var issueFullPattern *regexp.Regexp
-
-// Once for to prevent races
-var issueFullPatternOnce sync.Once
-
-// regexp for full links to hash comment in pull request files changed tab
-var filesChangedFullPattern *regexp.Regexp
-
-// Once for to prevent races
-var filesChangedFullPatternOnce sync.Once
-
-func getIssueFullPattern() *regexp.Regexp {
- issueFullPatternOnce.Do(func() {
- // example: https://domain/org/repo/pulls/27#hash
- issueFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) +
- `[\w_.-]+/[\w_.-]+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#](\S+)?)?\b`)
- })
- return issueFullPattern
-}
-
-func getFilesChangedFullPattern() *regexp.Regexp {
- filesChangedFullPatternOnce.Do(func() {
- // example: https://domain/org/repo/pulls/27/files#hash
- filesChangedFullPattern = regexp.MustCompile(regexp.QuoteMeta(setting.AppURL) +
- `[\w_.-]+/[\w_.-]+/pulls/((?:\w{1,10}-)?[1-9][0-9]*)/files([\?|#](\S+)?)?\b`)
- })
- return filesChangedFullPattern
-}
-
// CustomLinkURLSchemes allows for additional schemes to be detected when parsing links within text
func CustomLinkURLSchemes(schemes []string) {
schemes = append(schemes, "http", "https")
@@ -286,11 +285,6 @@ func RenderEmoji(
return renderProcessString(ctx, emojiProcessors, content)
}
-var (
- tagCleaner = regexp.MustCompile(`<((?:/?\w+/\w+)|(?:/[\w ]+/)|(/?[hH][tT][mM][lL]\b)|(/?[hH][eE][aA][dD]\b))`)
- nulCleaner = strings.NewReplacer("\000", "")
-)
-
func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output io.Writer) error {
defer ctx.Cancel()
// FIXME: don't read all content to memory
@@ -304,7 +298,7 @@ func postProcess(ctx *RenderContext, procs []processor, input io.Reader, output
// prepend ""
strings.NewReader(""),
// Strip out nuls - they're always invalid
- bytes.NewReader(tagCleaner.ReplaceAll([]byte(nulCleaner.Replace(string(rawHTML))), []byte("<$1"))),
+ bytes.NewReader(globalVars().tagCleaner.ReplaceAll([]byte(globalVars().nulCleaner.Replace(string(rawHTML))), []byte("<$1"))),
// close the tags
strings.NewReader(""),
))
@@ -351,7 +345,7 @@ func visitNode(ctx *RenderContext, procs []processor, node *html.Node) *html.Nod
// Add user-content- to IDs and "#" links if they don't already have them
for idx, attr := range node.Attr {
val := strings.TrimPrefix(attr.Val, "#")
- notHasPrefix := !(strings.HasPrefix(val, "user-content-") || blackfridayExtRegex.MatchString(val))
+ notHasPrefix := !(strings.HasPrefix(val, "user-content-") || globalVars().blackfridayExtRegex.MatchString(val))
if attr.Key == "id" && notHasPrefix {
node.Attr[idx].Val = "user-content-" + attr.Val
diff --git a/modules/markup/html_commit.go b/modules/markup/html_commit.go
index 86d70746d470c..0e674c83e1736 100644
--- a/modules/markup/html_commit.go
+++ b/modules/markup/html_commit.go
@@ -54,7 +54,7 @@ func createCodeLink(href, content, class string) *html.Node {
}
func anyHashPatternExtract(s string) (ret anyHashPatternResult, ok bool) {
- m := anyHashPattern.FindStringSubmatchIndex(s)
+ m := globalVars().anyHashPattern.FindStringSubmatchIndex(s)
if m == nil {
return ret, false
}
@@ -120,7 +120,7 @@ func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
node = node.NextSibling
continue
}
- m := comparePattern.FindStringSubmatchIndex(node.Data)
+ m := globalVars().comparePattern.FindStringSubmatchIndex(node.Data)
if m == nil || slices.Contains(m[:8], -1) { // ensure that every group (m[0]...m[7]) has a match
node = node.NextSibling
continue
@@ -173,7 +173,7 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
ctx.ShaExistCache = make(map[string]bool)
}
for node != nil && node != next && start < len(node.Data) {
- m := hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
+ m := globalVars().hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
if m == nil {
return
}
diff --git a/modules/markup/html_email.go b/modules/markup/html_email.go
index a062789b35888..32d0285eb4c46 100644
--- a/modules/markup/html_email.go
+++ b/modules/markup/html_email.go
@@ -9,7 +9,7 @@ import "golang.org/x/net/html"
func emailAddressProcessor(ctx *RenderContext, node *html.Node) {
next := node.NextSibling
for node != nil && node != next {
- m := emailRegex.FindStringSubmatchIndex(node.Data)
+ m := globalVars().emailRegex.FindStringSubmatchIndex(node.Data)
if m == nil {
return
}
diff --git a/modules/markup/html_emoji.go b/modules/markup/html_emoji.go
index c60d06b823223..6eacb2067f028 100644
--- a/modules/markup/html_emoji.go
+++ b/modules/markup/html_emoji.go
@@ -62,7 +62,7 @@ func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
start := 0
next := node.NextSibling
for node != nil && node != next && start < len(node.Data) {
- m := emojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
+ m := globalVars().emojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
if m == nil {
return
}
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index 916d2697b440f..cdcc94d563131 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -413,10 +413,10 @@ func TestRegExp_sha1CurrentPattern(t *testing.T) {
}
for _, testCase := range trueTestCases {
- assert.True(t, hashCurrentPattern.MatchString(testCase))
+ assert.True(t, globalVars().hashCurrentPattern.MatchString(testCase))
}
for _, testCase := range falseTestCases {
- assert.False(t, hashCurrentPattern.MatchString(testCase))
+ assert.False(t, globalVars().hashCurrentPattern.MatchString(testCase))
}
}
@@ -496,9 +496,9 @@ func TestRegExp_shortLinkPattern(t *testing.T) {
}
for _, testCase := range trueTestCases {
- assert.True(t, shortLinkPattern.MatchString(testCase))
+ assert.True(t, globalVars().shortLinkPattern.MatchString(testCase))
}
for _, testCase := range falseTestCases {
- assert.False(t, shortLinkPattern.MatchString(testCase))
+ assert.False(t, globalVars().shortLinkPattern.MatchString(testCase))
}
}
diff --git a/modules/markup/html_issue.go b/modules/markup/html_issue.go
index 3a315268b6fb9..fe883634dcbea 100644
--- a/modules/markup/html_issue.go
+++ b/modules/markup/html_issue.go
@@ -23,12 +23,12 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
}
next := node.NextSibling
for node != nil && node != next {
- m := getIssueFullPattern().FindStringSubmatchIndex(node.Data)
+ m := globalVars().issueFullPattern.FindStringSubmatchIndex(node.Data)
if m == nil {
return
}
- mDiffView := getFilesChangedFullPattern().FindStringSubmatchIndex(node.Data)
+ mDiffView := globalVars().filesChangedFullPattern.FindStringSubmatchIndex(node.Data)
// leave it as it is if the link is from "Files Changed" tab in PR Diff View https://domain/org/repo/pulls/27/files
if mDiffView != nil {
return
diff --git a/modules/markup/html_link.go b/modules/markup/html_link.go
index 1a7c5c8d92c13..023d3e1230ab4 100644
--- a/modules/markup/html_link.go
+++ b/modules/markup/html_link.go
@@ -40,7 +40,7 @@ func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (resu
func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
next := node.NextSibling
for node != nil && node != next {
- m := shortLinkPattern.FindStringSubmatchIndex(node.Data)
+ m := globalVars().shortLinkPattern.FindStringSubmatchIndex(node.Data)
if m == nil {
return
}
From ebd88a535d052207bca761ea3e0a055449158ae0 Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sat, 16 Nov 2024 10:25:40 +0800
Subject: [PATCH 5/6] fix commit subject DefaultLink
---
modules/markup/html.go | 25 ++++++++++---------------
modules/markup/html_link.go | 19 -------------------
modules/markup/render.go | 1 -
modules/templates/util_render.go | 11 +++++------
modules/templates/util_render_test.go | 2 +-
routers/common/markup.go | 1 +
templates/repo/view_file.tmpl | 2 +-
7 files changed, 18 insertions(+), 43 deletions(-)
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 7b1d5a4d9c7cd..1cfc7b1908a82 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -5,6 +5,8 @@ package markup
import (
"bytes"
+ "fmt"
+ "html/template"
"io"
"regexp"
"strings"
@@ -196,13 +198,6 @@ func RenderCommitMessage(
content string,
) (string, error) {
procs := commitMessageProcessors
- if ctx.DefaultLink != "" {
- // we don't have to fear data races, because being
- // commitMessageProcessors of fixed len and cap, every time we append
- // something to it the slice is realloc+copied, so append always
- // generates the slice ex-novo.
- procs = append(procs, genDefaultLinkProcessor(ctx.DefaultLink))
- }
return renderProcessString(ctx, procs, content)
}
@@ -230,17 +225,17 @@ var emojiProcessors = []processor{
// which changes every text node into a link to the passed default link.
func RenderCommitMessageSubject(
ctx *RenderContext,
- content string,
+ defaultLink, content string,
) (string, error) {
procs := commitMessageSubjectProcessors
- if ctx.DefaultLink != "" {
- // we don't have to fear data races, because being
- // commitMessageSubjectProcessors of fixed len and cap, every time we
- // append something to it the slice is realloc+copied, so append always
- // generates the slice ex-novo.
- procs = append(procs, genDefaultLinkProcessor(ctx.DefaultLink))
+ rendered, err := renderProcessString(ctx, procs, content)
+ if err != nil {
+ return "", err
}
- return renderProcessString(ctx, procs, content)
+ if defaultLink != "" {
+ rendered = fmt.Sprintf(`%s`, template.HTMLEscapeString(defaultLink), rendered)
+ }
+ return rendered, nil
}
// RenderIssueTitle to process title on individual issue/pull page
diff --git a/modules/markup/html_link.go b/modules/markup/html_link.go
index 023d3e1230ab4..b7562d0aa6d26 100644
--- a/modules/markup/html_link.go
+++ b/modules/markup/html_link.go
@@ -200,25 +200,6 @@ func linkProcessor(ctx *RenderContext, node *html.Node) {
}
}
-func genDefaultLinkProcessor(defaultLink string) processor {
- return func(ctx *RenderContext, node *html.Node) {
- ch := &html.Node{
- Parent: node,
- Type: html.TextNode,
- Data: node.Data,
- }
-
- node.Type = html.ElementNode
- node.Data = "a"
- node.DataAtom = atom.A
- node.Attr = []html.Attribute{
- {Key: "href", Val: defaultLink},
- {Key: "class", Val: "default-link muted"},
- }
- node.FirstChild, node.LastChild = ch, ch
- }
-}
-
// descriptionLinkProcessor creates links for DescriptionHTML
func descriptionLinkProcessor(ctx *RenderContext, node *html.Node) {
next := node.NextSibling
diff --git a/modules/markup/render.go b/modules/markup/render.go
index 80023be77a877..1977dc73f55ef 100644
--- a/modules/markup/render.go
+++ b/modules/markup/render.go
@@ -58,7 +58,6 @@ type RenderContext struct {
// markdownLineBreakStyle (comment, document)
Metas map[string]string
- DefaultLink string // TODO: need to figure out
GitRepo *git.Repository
Repo gitrepo.Repository
ShaExistCache map[string]bool
diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go
index aa7b09a1a23a2..8e443446bd69c 100644
--- a/modules/templates/util_render.go
+++ b/modules/templates/util_render.go
@@ -62,19 +62,18 @@ func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, me
}
msgLine = strings.TrimRightFunc(msgLine, unicode.IsSpace)
if len(msgLine) == 0 {
- return template.HTML("")
+ return ""
}
// we can safely assume that it will not return any error, since there
// shouldn't be any special HTML.
renderedMessage, err := markup.RenderCommitMessageSubject(&markup.RenderContext{
- Ctx: ut.ctx,
- DefaultLink: urlDefault,
- Metas: metas,
- }, template.HTMLEscapeString(msgLine))
+ Ctx: ut.ctx,
+ Metas: metas,
+ }, urlDefault, template.HTMLEscapeString(msgLine))
if err != nil {
log.Error("RenderCommitMessageSubject: %v", err)
- return template.HTML("")
+ return ""
}
return renderCodeBlock(template.HTML(renderedMessage))
}
diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go
index 498e42f7258da..529507e7eab82 100644
--- a/modules/templates/util_render_test.go
+++ b/modules/templates/util_render_test.go
@@ -140,7 +140,7 @@ func TestRenderCommitMessage(t *testing.T) {
}
func TestRenderCommitMessageLinkSubject(t *testing.T) {
- expected := `space @mention-user`
+ expected := `space @mention-user`
assert.EqualValues(t, expected, newTestRenderUtils().RenderCommitMessageLinkSubject(testInput(), "https://example.com/link", testMetas))
}
diff --git a/routers/common/markup.go b/routers/common/markup.go
index 272c3a643b5fa..dd6b286109f80 100644
--- a/routers/common/markup.go
+++ b/routers/common/markup.go
@@ -51,6 +51,7 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
case "wiki":
renderCtx.Metas = map[string]string{"markdownLineBreakStyle": "document", "markupContentMode": "wiki"}
case "file":
+ // render the repo file content by its extension
renderCtx.Metas = map[string]string{"markdownLineBreakStyle": "document"}
renderCtx.MarkupType = ""
renderCtx.RelativePath = filePath
diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl
index fb5bc14fe2a79..89bb371e7c7cd 100644
--- a/templates/repo/view_file.tmpl
+++ b/templates/repo/view_file.tmpl
@@ -29,7 +29,7 @@