aboutsummaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2024-11-14 13:02:11 +0800
committerGitHub <noreply@github.com>2024-11-14 05:02:11 +0000
commit3f9c3e7bc394c115ccc4818d6505f1f68de350d2 (patch)
treee07e4a3dc07ce80104f7949af5cb180b7fce449e /routers
parent985e2a8af3d6468bac3ab178148c38bdbd8414f5 (diff)
downloadgitea-3f9c3e7bc394c115ccc4818d6505f1f68de350d2.tar.gz
gitea-3f9c3e7bc394c115ccc4818d6505f1f68de350d2.zip
Refactor render system (#32492)
There were too many patches to the Render system, it's really difficult to make further improvements. This PR clears the legacy problems and fix TODOs. 1. Rename `RenderContext.Type` to `RenderContext.MarkupType` to clarify its usage. 2. Use `ContentMode` to replace `meta["mode"]` and `IsWiki`, to clarify the rendering behaviors. 3. Use "wiki" mode instead of "mode=gfm + wiki=true" 4. Merge `renderByType` and `renderByFile` 5. Add more comments ---- The problem of "mode=document": in many cases it is not set, so many non-comment places use comment's hard line break incorrectly
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/misc/markup.go12
-rw-r--r--routers/api/v1/misc/markup_test.go13
-rw-r--r--routers/common/markup.go70
-rw-r--r--routers/web/feed/convert.go1
-rw-r--r--routers/web/misc/markup.go4
-rw-r--r--routers/web/repo/view.go12
-rw-r--r--routers/web/repo/wiki.go6
-rw-r--r--routers/web/user/profile.go1
8 files changed, 50 insertions, 69 deletions
diff --git a/routers/api/v1/misc/markup.go b/routers/api/v1/misc/markup.go
index 9699c79368..868ed92519 100644
--- a/routers/api/v1/misc/markup.go
+++ b/routers/api/v1/misc/markup.go
@@ -9,6 +9,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
@@ -41,7 +42,8 @@ func Markup(ctx *context.APIContext) {
return
}
- common.RenderMarkup(ctx.Base, ctx.Repo, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki)
+ mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck
+ common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, form.FilePath)
}
// Markdown render markdown document to HTML
@@ -71,12 +73,8 @@ func Markdown(ctx *context.APIContext) {
return
}
- mode := "markdown"
- if form.Mode == "comment" || form.Mode == "gfm" {
- mode = form.Mode
- }
-
- common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "", form.Wiki)
+ mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck
+ common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "")
}
// MarkdownRaw render raw markdown HTML
diff --git a/routers/api/v1/misc/markup_test.go b/routers/api/v1/misc/markup_test.go
index abffdf3516..6b8c09034a 100644
--- a/routers/api/v1/misc/markup_test.go
+++ b/routers/api/v1/misc/markup_test.go
@@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/services/contexttest"
@@ -24,6 +25,7 @@ const AppURL = "http://localhost:3000/"
func testRenderMarkup(t *testing.T, mode string, wiki bool, filePath, text, expectedBody string, expectedCode int) {
setting.AppURL = AppURL
+ defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
context := "/gogits/gogs"
if !wiki {
context += path.Join("/src/branch/main", path.Dir(filePath))
@@ -38,13 +40,13 @@ func testRenderMarkup(t *testing.T, mode string, wiki bool, filePath, text, expe
ctx, resp := contexttest.MockAPIContext(t, "POST /api/v1/markup")
web.SetForm(ctx, &options)
Markup(ctx)
- actual := strings.ReplaceAll(resp.Body.String(), ` data-markdown-generated-content=""`, "")
- assert.Equal(t, expectedBody, actual)
+ assert.Equal(t, expectedBody, resp.Body.String())
assert.Equal(t, expectedCode, resp.Code)
resp.Body.Reset()
}
func testRenderMarkdown(t *testing.T, mode string, wiki bool, text, responseBody string, responseCode int) {
+ defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
setting.AppURL = AppURL
context := "/gogits/gogs"
if !wiki {
@@ -59,8 +61,7 @@ func testRenderMarkdown(t *testing.T, mode string, wiki bool, text, responseBody
ctx, resp := contexttest.MockAPIContext(t, "POST /api/v1/markdown")
web.SetForm(ctx, &options)
Markdown(ctx)
- actual := strings.ReplaceAll(resp.Body.String(), ` data-markdown-generated-content=""`, "")
- assert.Equal(t, responseBody, actual)
+ assert.Equal(t, responseBody, resp.Body.String())
assert.Equal(t, responseCode, resp.Code)
resp.Body.Reset()
}
@@ -158,8 +159,8 @@ Here are some links to the most important topics. You can find the full list of
<a href="http://localhost:3000/gogits/gogs/media/branch/main/path/image.png" target="_blank" rel="nofollow noopener"><img src="http://localhost:3000/gogits/gogs/media/branch/main/path/image.png" alt="Image"/></a></p>
`, http.StatusOK)
- testRenderMarkup(t, "file", true, "path/test.unknown", "## Test", "Unsupported render extension: .unknown\n", http.StatusUnprocessableEntity)
- testRenderMarkup(t, "unknown", true, "", "## Test", "Unknown mode: unknown\n", http.StatusUnprocessableEntity)
+ testRenderMarkup(t, "file", false, "path/test.unknown", "## Test", "unsupported file to render: \"path/test.unknown\"\n", http.StatusUnprocessableEntity)
+ testRenderMarkup(t, "unknown", false, "", "## Test", "Unknown mode: unknown\n", http.StatusUnprocessableEntity)
}
var simpleCases = []string{
diff --git a/routers/common/markup.go b/routers/common/markup.go
index 0a00eac7d4..c8cc1a5ff1 100644
--- a/routers/common/markup.go
+++ b/routers/common/markup.go
@@ -5,21 +5,22 @@
package common
import (
+ "errors"
"fmt"
"net/http"
"path"
"strings"
- repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/context"
)
// RenderMarkup renders markup text for the /markup and /markdown endpoints
-func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPathContext, filePath string, wiki bool) {
+func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPathContext, filePath string) {
// urlPathContext format is "/subpath/{user}/{repo}/src/{branch, commit, tag}/{identifier/path}/{file/dir}"
// filePath is the path of the file to render if the end user is trying to preview a repo file (mode == "file")
// filePath will be used as RenderContext.RelativePath
@@ -27,32 +28,33 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
// for example, when previewing file "/gitea/owner/repo/src/branch/features/feat-123/doc/CHANGE.md", then filePath is "doc/CHANGE.md"
// and the urlPathContext is "/gitea/owner/repo/src/branch/features/feat-123/doc"
- var markupType, relativePath string
-
- links := markup.Links{AbsolutePrefix: true}
+ renderCtx := &markup.RenderContext{
+ Ctx: ctx,
+ Links: markup.Links{AbsolutePrefix: true},
+ MarkupType: markdown.MarkupName,
+ }
if urlPathContext != "" {
- links.Base = fmt.Sprintf("%s%s", httplib.GuessCurrentHostURL(ctx), urlPathContext)
+ renderCtx.Links.Base = fmt.Sprintf("%s%s", httplib.GuessCurrentHostURL(ctx), urlPathContext)
}
- switch mode {
- case "markdown":
- // Raw markdown
- if err := markdown.RenderRaw(&markup.RenderContext{
- Ctx: ctx,
- Links: links,
- }, strings.NewReader(text), ctx.Resp); err != nil {
+ if mode == "" || mode == "markdown" {
+ // raw markdown doesn't need any special handling
+ if err := markdown.RenderRaw(renderCtx, strings.NewReader(text), ctx.Resp); err != nil {
ctx.Error(http.StatusInternalServerError, err.Error())
}
return
+ }
+ switch mode {
+ case "gfm": // legacy mode, do nothing
case "comment":
- // Issue & comment content
- markupType = markdown.MarkupName
- case "gfm":
- // GitHub Flavored Markdown
- markupType = markdown.MarkupName
+ renderCtx.ContentMode = markup.RenderContentAsComment
+ case "wiki":
+ renderCtx.ContentMode = markup.RenderContentAsWiki
case "file":
- markupType = "" // render the repo file content by its extension
- relativePath = filePath
+ // render the repo file content by its extension
+ renderCtx.MarkupType = ""
+ renderCtx.RelativePath = filePath
+ renderCtx.InStandalonePage = true
default:
ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("Unknown mode: %s", mode))
return
@@ -67,33 +69,19 @@ func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPa
refPath := strings.Join(fields[3:], "/") // it is "branch/features/feat-12/doc"
refPath = strings.TrimSuffix(refPath, "/"+fileDir) // now we get the correct branch path: "branch/features/feat-12"
- links = markup.Links{AbsolutePrefix: true, Base: absoluteBasePrefix, BranchPath: refPath, TreePath: fileDir}
+ renderCtx.Links = markup.Links{AbsolutePrefix: true, Base: absoluteBasePrefix, BranchPath: refPath, TreePath: fileDir}
}
- meta := map[string]string{}
- var repoCtx *repo_model.Repository
if repo != nil && repo.Repository != nil {
- repoCtx = repo.Repository
- if mode == "comment" {
- meta = repo.Repository.ComposeMetas(ctx)
+ renderCtx.Repo = repo.Repository
+ if renderCtx.ContentMode == markup.RenderContentAsComment {
+ renderCtx.Metas = repo.Repository.ComposeMetas(ctx)
} else {
- meta = repo.Repository.ComposeDocumentMetas(ctx)
+ renderCtx.Metas = repo.Repository.ComposeDocumentMetas(ctx)
}
}
- if mode != "comment" {
- meta["mode"] = "document"
- }
-
- if err := markup.Render(&markup.RenderContext{
- Ctx: ctx,
- Repo: repoCtx,
- Links: links,
- Metas: meta,
- IsWiki: wiki,
- Type: markupType,
- RelativePath: relativePath,
- }, strings.NewReader(text), ctx.Resp); err != nil {
- if markup.IsErrUnsupportedRenderExtension(err) {
+ if err := markup.Render(renderCtx, strings.NewReader(text), ctx.Resp); err != nil {
+ if errors.Is(err, util.ErrInvalidArgument) {
ctx.Error(http.StatusUnprocessableEntity, err.Error())
} else {
ctx.Error(http.StatusInternalServerError, err.Error())
diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go
index 3f33e9933a..a273515c8a 100644
--- a/routers/web/feed/convert.go
+++ b/routers/web/feed/convert.go
@@ -56,7 +56,6 @@ func renderMarkdown(ctx *context.Context, act *activities_model.Action, content
Links: markup.Links{
Base: act.GetRepoLink(ctx),
},
- Type: markdown.MarkupName,
Metas: map[string]string{
"user": act.GetRepoUserName(ctx),
"repo": act.GetRepoName(ctx),
diff --git a/routers/web/misc/markup.go b/routers/web/misc/markup.go
index 2dbbd6fc09..0c7ec6c2eb 100644
--- a/routers/web/misc/markup.go
+++ b/routers/web/misc/markup.go
@@ -6,6 +6,7 @@ package misc
import (
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
@@ -14,5 +15,6 @@ import (
// Markup render markup document to HTML
func Markup(ctx *context.Context) {
form := web.GetForm(ctx).(*api.MarkupOption)
- common.RenderMarkup(ctx.Base, ctx.Repo, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki)
+ mode := util.Iif(form.Wiki, "wiki", form.Mode) //nolint:staticcheck
+ common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, form.FilePath)
}
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index 7d9281b397..7030f6d8a9 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -312,6 +312,7 @@ func renderReadmeFile(ctx *context.Context, subfolder string, readmeFile *git.Tr
ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{
Ctx: ctx,
+ MarkupType: markupType,
RelativePath: path.Join(ctx.Repo.TreePath, readmeFile.Name()), // ctx.Repo.TreePath is the directory not the Readme so we must append the Readme filename (and path).
Links: markup.Links{
Base: ctx.Repo.RepoLink,
@@ -502,28 +503,20 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
ctx.Data["ReadmeExist"] = readmeExist
markupType := markup.DetectMarkupTypeByFileName(blob.Name())
- // If the markup is detected by custom markup renderer it should not be reset later on
- // to not pass it down to the render context.
- detected := false
if markupType == "" {
- detected = true
markupType = markup.DetectRendererType(blob.Name(), bytes.NewReader(buf))
}
if markupType != "" {
ctx.Data["HasSourceRenderedToggle"] = true
}
-
if markupType != "" && !shouldRenderSource {
ctx.Data["IsMarkup"] = true
ctx.Data["MarkupType"] = markupType
- if !detected {
- markupType = ""
- }
metas := ctx.Repo.Repository.ComposeDocumentMetas(ctx)
metas["BranchNameSubURL"] = ctx.Repo.BranchNameSubURL()
ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{
Ctx: ctx,
- Type: markupType,
+ MarkupType: markupType,
RelativePath: ctx.Repo.TreePath,
Links: markup.Links{
Base: ctx.Repo.RepoLink,
@@ -615,6 +608,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry) {
ctx.Data["MarkupType"] = markupType
ctx.Data["EscapeStatus"], ctx.Data["FileContent"], err = markupRender(ctx, &markup.RenderContext{
Ctx: ctx,
+ MarkupType: markupType,
RelativePath: ctx.Repo.TreePath,
Links: markup.Links{
Base: ctx.Repo.RepoLink,
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index d2056353d8..2b8312f10a 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -289,12 +289,12 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
}
rctx := &markup.RenderContext{
- Ctx: ctx,
- Metas: ctx.Repo.Repository.ComposeDocumentMetas(ctx),
+ Ctx: ctx,
+ ContentMode: markup.RenderContentAsWiki,
+ Metas: ctx.Repo.Repository.ComposeDocumentMetas(ctx),
Links: markup.Links{
Base: ctx.Repo.RepoLink,
},
- IsWiki: true,
}
buf := &strings.Builder{}
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index d0abf603c3..4fbfc2bd17 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -258,7 +258,6 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb
Base: profileDbRepo.Link(),
BranchPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)),
},
- Metas: map[string]string{"mode": "document"},
}, bytes); err != nil {
log.Error("failed to RenderString: %v", err)
} else {