aboutsummaryrefslogtreecommitdiffstats
path: root/modules/markup
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2024-11-22 13:48:09 +0800
committerGitHub <noreply@github.com>2024-11-22 05:48:09 +0000
commitc4e27cb27b99dd9528c999fdc8b1073f28be6313 (patch)
treebbd065423fa48e09553918d23bdc7c5daef6e8bd /modules/markup
parent81ac8d914cf5fdfaad3c206223ad0ace1e8c1dcd (diff)
downloadgitea-c4e27cb27b99dd9528c999fdc8b1073f28be6313.tar.gz
gitea-c4e27cb27b99dd9528c999fdc8b1073f28be6313.zip
Refactor markup render system (#32589)
This PR mainly moves some code and introduces `RenderContext.WithXxx` functions
Diffstat (limited to 'modules/markup')
-rw-r--r--modules/markup/asciicast/asciicast.go8
-rw-r--r--modules/markup/console/console_test.go5
-rw-r--r--modules/markup/csv/csv.go4
-rw-r--r--modules/markup/csv/csv_test.go5
-rw-r--r--modules/markup/external/external.go19
-rw-r--r--modules/markup/html_codepreview.go4
-rw-r--r--modules/markup/html_codepreview_test.go6
-rw-r--r--modules/markup/html_commit.go26
-rw-r--r--modules/markup/html_internal_test.go78
-rw-r--r--modules/markup/html_issue.go32
-rw-r--r--modules/markup/html_link.go10
-rw-r--r--modules/markup/html_mention.go10
-rw-r--r--modules/markup/html_node.go4
-rw-r--r--modules/markup/html_test.go124
-rw-r--r--modules/markup/markdown/goldmark.go2
-rw-r--r--modules/markup/markdown/markdown.go4
-rw-r--r--modules/markup/markdown/markdown_test.go93
-rw-r--r--modules/markup/markdown/transform_image.go2
-rw-r--r--modules/markup/orgmode/orgmode.go10
-rw-r--r--modules/markup/orgmode/orgmode_test.go43
-rw-r--r--modules/markup/render.go157
21 files changed, 299 insertions, 347 deletions
diff --git a/modules/markup/asciicast/asciicast.go b/modules/markup/asciicast/asciicast.go
index e92b78a4bc..1d0d631650 100644
--- a/modules/markup/asciicast/asciicast.go
+++ b/modules/markup/asciicast/asciicast.go
@@ -44,10 +44,10 @@ func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
func (Renderer) Render(ctx *markup.RenderContext, _ io.Reader, output io.Writer) error {
rawURL := fmt.Sprintf("%s/%s/%s/raw/%s/%s",
setting.AppSubURL,
- url.PathEscape(ctx.Metas["user"]),
- url.PathEscape(ctx.Metas["repo"]),
- ctx.Metas["BranchNameSubURL"],
- url.PathEscape(ctx.RelativePath),
+ url.PathEscape(ctx.RenderOptions.Metas["user"]),
+ url.PathEscape(ctx.RenderOptions.Metas["repo"]),
+ ctx.RenderOptions.Metas["BranchNameSubURL"],
+ url.PathEscape(ctx.RenderOptions.RelativePath),
)
return ctx.RenderInternal.FormatWithSafeAttrs(output, `<div class="%s" %s="%s"></div>`, playerClassName, playerSrcAttr, rawURL)
}
diff --git a/modules/markup/console/console_test.go b/modules/markup/console/console_test.go
index 2337d91ac5..e1f0da1f01 100644
--- a/modules/markup/console/console_test.go
+++ b/modules/markup/console/console_test.go
@@ -4,10 +4,10 @@
package console
import (
+ "context"
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"github.com/stretchr/testify/assert"
@@ -24,8 +24,7 @@ func TestRenderConsole(t *testing.T) {
canRender := render.CanRender("test", strings.NewReader(k))
assert.True(t, canRender)
- err := render.Render(&markup.RenderContext{Ctx: git.DefaultContext},
- strings.NewReader(k), &buf)
+ err := render.Render(markup.NewRenderContext(context.Background()), strings.NewReader(k), &buf)
assert.NoError(t, err)
assert.EqualValues(t, v, buf.String())
}
diff --git a/modules/markup/csv/csv.go b/modules/markup/csv/csv.go
index a3e6bbaac6..b7d7a1b35b 100644
--- a/modules/markup/csv/csv.go
+++ b/modules/markup/csv/csv.go
@@ -133,10 +133,10 @@ func (r Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.W
// Check if maxRows or maxSize is reached, and if true, warn.
if (row >= maxRows && maxRows != 0) || (rd.InputOffset() >= maxSize && maxSize != 0) {
warn := `<table class="data-table"><tr><td>`
- rawLink := ` <a href="` + ctx.Links.RawLink() + `/` + util.PathEscapeSegments(ctx.RelativePath) + `">`
+ rawLink := ` <a href="` + ctx.RenderOptions.Links.RawLink() + `/` + util.PathEscapeSegments(ctx.RenderOptions.RelativePath) + `">`
// Try to get the user translation
- if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok {
+ if locale, ok := ctx.Value(translation.ContextKey).(translation.Locale); ok {
warn += locale.TrString("repo.file_too_large")
rawLink += locale.TrString("repo.file_view_raw")
} else {
diff --git a/modules/markup/csv/csv_test.go b/modules/markup/csv/csv_test.go
index 8c07184b21..4c47170c30 100644
--- a/modules/markup/csv/csv_test.go
+++ b/modules/markup/csv/csv_test.go
@@ -4,10 +4,10 @@
package markup
import (
+ "context"
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"github.com/stretchr/testify/assert"
@@ -24,8 +24,7 @@ func TestRenderCSV(t *testing.T) {
for k, v := range kases {
var buf strings.Builder
- err := render.Render(&markup.RenderContext{Ctx: git.DefaultContext},
- strings.NewReader(k), &buf)
+ err := render.Render(markup.NewRenderContext(context.Background()), strings.NewReader(k), &buf)
assert.NoError(t, err)
assert.EqualValues(t, v, buf.String())
}
diff --git a/modules/markup/external/external.go b/modules/markup/external/external.go
index d28dc9fa5d..98708e99b8 100644
--- a/modules/markup/external/external.go
+++ b/modules/markup/external/external.go
@@ -12,7 +12,6 @@ import (
"runtime"
"strings"
- "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/process"
@@ -80,8 +79,8 @@ func envMark(envName string) string {
func (p *Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
var (
command = strings.NewReplacer(
- envMark("GITEA_PREFIX_SRC"), ctx.Links.SrcLink(),
- envMark("GITEA_PREFIX_RAW"), ctx.Links.RawLink(),
+ envMark("GITEA_PREFIX_SRC"), ctx.RenderOptions.Links.SrcLink(),
+ envMark("GITEA_PREFIX_RAW"), ctx.RenderOptions.Links.RawLink(),
).Replace(p.Command)
commands = strings.Fields(command)
args = commands[1:]
@@ -113,22 +112,14 @@ func (p *Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.
args = append(args, f.Name())
}
- if ctx.Ctx == nil {
- if !setting.IsProd || setting.IsInTesting {
- panic("RenderContext did not provide context")
- }
- log.Warn("RenderContext did not provide context, defaulting to Shutdown context")
- ctx.Ctx = graceful.GetManager().ShutdownContext()
- }
-
- processCtx, _, finished := process.GetManager().AddContext(ctx.Ctx, fmt.Sprintf("Render [%s] for %s", commands[0], ctx.Links.SrcLink()))
+ processCtx, _, finished := process.GetManager().AddContext(ctx, fmt.Sprintf("Render [%s] for %s", commands[0], ctx.RenderOptions.Links.SrcLink()))
defer finished()
cmd := exec.CommandContext(processCtx, commands[0], args...)
cmd.Env = append(
os.Environ(),
- "GITEA_PREFIX_SRC="+ctx.Links.SrcLink(),
- "GITEA_PREFIX_RAW="+ctx.Links.RawLink(),
+ "GITEA_PREFIX_SRC="+ctx.RenderOptions.Links.SrcLink(),
+ "GITEA_PREFIX_RAW="+ctx.RenderOptions.Links.RawLink(),
)
if !p.IsInputFile {
cmd.Stdin = input
diff --git a/modules/markup/html_codepreview.go b/modules/markup/html_codepreview.go
index 5c88481d76..68886a3434 100644
--- a/modules/markup/html_codepreview.go
+++ b/modules/markup/html_codepreview.go
@@ -38,7 +38,7 @@ func renderCodeBlock(ctx *RenderContext, node *html.Node) (urlPosStart, urlPosSt
CommitID: node.Data[m[6]:m[7]],
FilePath: node.Data[m[8]:m[9]],
}
- if !httplib.IsCurrentGiteaSiteURL(ctx.Ctx, opts.FullURL) {
+ if !httplib.IsCurrentGiteaSiteURL(ctx, opts.FullURL) {
return 0, 0, "", nil
}
u, err := url.Parse(opts.FilePath)
@@ -51,7 +51,7 @@ func renderCodeBlock(ctx *RenderContext, node *html.Node) (urlPosStart, urlPosSt
lineStart, _ := strconv.Atoi(strings.TrimPrefix(lineStartStr, "L"))
lineStop, _ := strconv.Atoi(strings.TrimPrefix(lineStopStr, "L"))
opts.LineStart, opts.LineStop = lineStart, lineStop
- h, err := DefaultProcessorHelper.RenderRepoFileCodePreview(ctx.Ctx, opts)
+ h, err := DefaultProcessorHelper.RenderRepoFileCodePreview(ctx, opts)
return m[0], m[1], h, err
}
diff --git a/modules/markup/html_codepreview_test.go b/modules/markup/html_codepreview_test.go
index 5054627dde..7c0db59d06 100644
--- a/modules/markup/html_codepreview_test.go
+++ b/modules/markup/html_codepreview_test.go
@@ -9,7 +9,6 @@ import (
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
@@ -23,10 +22,7 @@ func TestRenderCodePreview(t *testing.T) {
},
})
test := func(input, expected string) {
- buffer, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- MarkupType: markdown.MarkupName,
- }, input)
+ buffer, err := markup.RenderString(markup.NewRenderContext(context.Background()).WithMarkupType(markdown.MarkupName), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
diff --git a/modules/markup/html_commit.go b/modules/markup/html_commit.go
index 0e674c83e1..0649f84664 100644
--- a/modules/markup/html_commit.go
+++ b/modules/markup/html_commit.go
@@ -84,7 +84,7 @@ func anyHashPatternExtract(s string) (ret anyHashPatternResult, ok bool) {
// fullHashPatternProcessor renders SHA containing URLs
func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
- if ctx.Metas == nil {
+ if ctx.RenderOptions.Metas == nil {
return
}
nodeStop := node.NextSibling
@@ -111,7 +111,7 @@ func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
}
func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
- if ctx.Metas == nil {
+ if ctx.RenderOptions.Metas == nil {
return
}
nodeStop := node.NextSibling
@@ -163,14 +163,14 @@ func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
// hashCurrentPatternProcessor renders SHA1 strings to corresponding links that
// are assumed to be in the same repository.
func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
- if ctx.Metas == nil || ctx.Metas["user"] == "" || ctx.Metas["repo"] == "" || (ctx.Repo == nil && ctx.GitRepo == nil) {
+ if ctx.RenderOptions.Metas == nil || ctx.RenderOptions.Metas["user"] == "" || ctx.RenderOptions.Metas["repo"] == "" || (ctx.RenderHelper.repoFacade == nil && ctx.RenderHelper.gitRepo == nil) {
return
}
start := 0
next := node.NextSibling
- if ctx.ShaExistCache == nil {
- ctx.ShaExistCache = make(map[string]bool)
+ if ctx.RenderHelper.shaExistCache == nil {
+ ctx.RenderHelper.shaExistCache = make(map[string]bool)
}
for node != nil && node != next && start < len(node.Data) {
m := globalVars().hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
@@ -191,25 +191,25 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
// a commit in the repository before making it a link.
// check cache first
- exist, inCache := ctx.ShaExistCache[hash]
+ exist, inCache := ctx.RenderHelper.shaExistCache[hash]
if !inCache {
- if ctx.GitRepo == nil {
+ if ctx.RenderHelper.gitRepo == nil {
var err error
var closer io.Closer
- ctx.GitRepo, closer, err = gitrepo.RepositoryFromContextOrOpen(ctx.Ctx, ctx.Repo)
+ ctx.RenderHelper.gitRepo, closer, err = gitrepo.RepositoryFromContextOrOpen(ctx, ctx.RenderHelper.repoFacade)
if err != nil {
- log.Error("unable to open repository: %s Error: %v", gitrepo.RepoGitURL(ctx.Repo), err)
+ log.Error("unable to open repository: %s Error: %v", gitrepo.RepoGitURL(ctx.RenderHelper.repoFacade), err)
return
}
ctx.AddCancel(func() {
_ = closer.Close()
- ctx.GitRepo = nil
+ ctx.RenderHelper.gitRepo = nil
})
}
// Don't use IsObjectExist since it doesn't support short hashs with gogit edition.
- exist = ctx.GitRepo.IsReferenceExist(hash)
- ctx.ShaExistCache[hash] = exist
+ exist = ctx.RenderHelper.gitRepo.IsReferenceExist(hash)
+ ctx.RenderHelper.shaExistCache[hash] = exist
}
if !exist {
@@ -217,7 +217,7 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
continue
}
- link := util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], "commit", hash)
+ link := util.URLJoin(ctx.RenderOptions.Links.Prefix(), ctx.RenderOptions.Metas["user"], ctx.RenderOptions.Metas["repo"], "commit", hash)
replaceContent(node, m[2], m[3], createCodeLink(link, base.ShortSha(hash), "commit"))
start = 0
node = node.NextSibling.NextSibling
diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go
index cdcc94d563..7b143664fe 100644
--- a/modules/markup/html_internal_test.go
+++ b/modules/markup/html_internal_test.go
@@ -4,12 +4,12 @@
package markup
import (
+ "context"
"fmt"
"strconv"
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
testModule "code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/modules/util"
@@ -79,11 +79,11 @@ func TestRender_IssueIndexPattern(t *testing.T) {
// numeric: render inputs without valid mentions
test := func(s string) {
testRenderIssueIndexPattern(t, s, s, &RenderContext{
- Ctx: git.DefaultContext,
+ ctx: context.Background(),
})
testRenderIssueIndexPattern(t, s, s, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: numericMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: numericMetas},
})
}
@@ -133,8 +133,8 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
}
expectedNil := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNil, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: localMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: localMetas},
})
class := "ref-issue"
@@ -147,8 +147,8 @@ func TestRender_IssueIndexPattern2(t *testing.T) {
}
expectedNum := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expectedNum, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: numericMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: numericMetas},
})
}
@@ -184,8 +184,8 @@ func TestRender_IssueIndexPattern3(t *testing.T) {
// alphanumeric: render inputs without valid mentions
test := func(s string) {
testRenderIssueIndexPattern(t, s, s, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: alphanumericMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: alphanumericMetas},
})
}
test("")
@@ -217,8 +217,8 @@ func TestRender_IssueIndexPattern4(t *testing.T) {
}
expected := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expected, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: alphanumericMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: alphanumericMetas},
})
}
test("OTT-1234 test", "%s test", "OTT-1234")
@@ -240,8 +240,8 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
expected := fmt.Sprintf(expectedFmt, links...)
testRenderIssueIndexPattern(t, s, expected, &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: metas},
})
}
@@ -264,8 +264,8 @@ func TestRender_IssueIndexPattern5(t *testing.T) {
)
testRenderIssueIndexPattern(t, "will not match", "will not match", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: regexpMetas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: regexpMetas},
})
}
@@ -279,16 +279,16 @@ func TestRender_IssueIndexPattern_NoShortPattern(t *testing.T) {
}
testRenderIssueIndexPattern(t, "#1", "#1", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: metas},
})
testRenderIssueIndexPattern(t, "#1312", "#1312", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: metas},
})
testRenderIssueIndexPattern(t, "!1", "!1", &RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: metas},
})
}
@@ -301,17 +301,17 @@ func TestRender_RenderIssueTitle(t *testing.T) {
"style": IssueNameStyleNumeric,
}
actual, err := RenderIssueTitle(&RenderContext{
- Ctx: git.DefaultContext,
- Metas: metas,
+ ctx: context.Background(),
+ RenderOptions: RenderOptions{Metas: metas},
}, "#1")
assert.NoError(t, err)
assert.Equal(t, "#1", actual)
}
func testRenderIssueIndexPattern(t *testing.T, input, expected string, ctx *RenderContext) {
- ctx.Links.AbsolutePrefix = true
- if ctx.Links.Base == "" {
- ctx.Links.Base = TestRepoURL
+ ctx.RenderOptions.Links.AbsolutePrefix = true
+ if ctx.RenderOptions.Links.Base == "" {
+ ctx.RenderOptions.Links.Base = TestRepoURL
}
var buf strings.Builder
@@ -326,22 +326,18 @@ func TestRender_AutoLink(t *testing.T) {
test := func(input, expected string) {
var buffer strings.Builder
err := PostProcess(&RenderContext{
- Ctx: git.DefaultContext,
- Links: Links{
- Base: TestRepoURL,
- },
- Metas: localMetas,
+ ctx: context.Background(),
+
+ RenderOptions: RenderOptions{Metas: localMetas, Links: Links{Base: TestRepoURL}},
}, strings.NewReader(input), &buffer)
assert.Equal(t, err, nil)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer.String()))
buffer.Reset()
err = PostProcess(&RenderContext{
- Ctx: git.DefaultContext,
- Links: Links{
- Base: TestRepoURL,
- },
- Metas: localWikiMetas,
+ ctx: context.Background(),
+
+ RenderOptions: RenderOptions{Metas: localWikiMetas, Links: Links{Base: TestRepoURL}},
}, strings.NewReader(input), &buffer)
assert.Equal(t, err, nil)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer.String()))
@@ -368,11 +364,9 @@ func TestRender_FullIssueURLs(t *testing.T) {
test := func(input, expected string) {
var result strings.Builder
err := postProcess(&RenderContext{
- Ctx: git.DefaultContext,
- Links: Links{
- Base: TestRepoURL,
- },
- Metas: localMetas,
+ ctx: context.Background(),
+
+ RenderOptions: RenderOptions{Metas: localMetas, Links: Links{Base: TestRepoURL}},
}, []processor{fullIssuePatternProcessor}, strings.NewReader(input), &result)
assert.NoError(t, err)
assert.Equal(t, expected, result.String())
diff --git a/modules/markup/html_issue.go b/modules/markup/html_issue.go
index 7341af7eb6..a75a8b3290 100644
--- a/modules/markup/html_issue.go
+++ b/modules/markup/html_issue.go
@@ -19,7 +19,7 @@ import (
)
func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
- if ctx.Metas == nil {
+ if ctx.RenderOptions.Metas == nil {
return
}
next := node.NextSibling
@@ -36,14 +36,14 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
}
link := node.Data[m[0]:m[1]]
- if !httplib.IsCurrentGiteaSiteURL(ctx.Ctx, link) {
+ if !httplib.IsCurrentGiteaSiteURL(ctx, link) {
return
}
text := "#" + node.Data[m[2]:m[3]]
// if m[4] and m[5] is not -1, then link is to a comment
// indicate that in the text by appending (comment)
if m[4] != -1 && m[5] != -1 {
- if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok {
+ if locale, ok := ctx.Value(translation.ContextKey).(translation.Locale); ok {
text += " " + locale.TrString("repo.from_comment")
} else {
text += " (comment)"
@@ -56,7 +56,7 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
matchOrg := linkParts[len(linkParts)-4]
matchRepo := linkParts[len(linkParts)-3]
- if matchOrg == ctx.Metas["user"] && matchRepo == ctx.Metas["repo"] {
+ if matchOrg == ctx.RenderOptions.Metas["user"] && matchRepo == ctx.RenderOptions.Metas["repo"] {
replaceContent(node, m[0], m[1], createLink(ctx, link, text, "ref-issue"))
} else {
text = matchOrg + "/" + matchRepo + text
@@ -67,14 +67,14 @@ func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
}
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
- if ctx.Metas == nil {
+ if ctx.RenderOptions.Metas == nil {
return
}
// 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["markupAllowShortIssuePattern"] != "true"
+ // old logic: crossLinkOnly := ctx.RenderOptions.Metas["mode"] == "document" && !ctx.IsWiki
+ crossLinkOnly := ctx.RenderOptions.Metas["markupAllowShortIssuePattern"] != "true"
var (
found bool
@@ -84,20 +84,20 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
next := node.NextSibling
for node != nil && node != next {
- _, hasExtTrackFormat := ctx.Metas["format"]
+ _, hasExtTrackFormat := ctx.RenderOptions.Metas["format"]
// Repos with external issue trackers might still need to reference local PRs
// We need to concern with the first one that shows up in the text, whichever it is
- isNumericStyle := ctx.Metas["style"] == "" || ctx.Metas["style"] == IssueNameStyleNumeric
+ isNumericStyle := ctx.RenderOptions.Metas["style"] == "" || ctx.RenderOptions.Metas["style"] == IssueNameStyleNumeric
foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
- switch ctx.Metas["style"] {
+ switch ctx.RenderOptions.Metas["style"] {
case "", IssueNameStyleNumeric:
found, ref = foundNumeric, refNumeric
case IssueNameStyleAlphanumeric:
found, ref = references.FindRenderizableReferenceAlphanumeric(node.Data)
case IssueNameStyleRegexp:
- pattern, err := regexplru.GetCompiled(ctx.Metas["regexp"])
+ pattern, err := regexplru.GetCompiled(ctx.RenderOptions.Metas["regexp"])
if err != nil {
return
}
@@ -121,9 +121,9 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
var link *html.Node
reftext := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
if hasExtTrackFormat && !ref.IsPull {
- ctx.Metas["index"] = ref.Issue
+ ctx.RenderOptions.Metas["index"] = ref.Issue
- res, err := vars.Expand(ctx.Metas["format"], ctx.Metas)
+ res, err := vars.Expand(ctx.RenderOptions.Metas["format"], ctx.RenderOptions.Metas)
if err != nil {
// here we could just log the error and continue the rendering
log.Error("unable to expand template vars for ref %s, err: %v", ref.Issue, err)
@@ -136,9 +136,9 @@ func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
// Gitea will redirect on click as appropriate.
issuePath := util.Iif(ref.IsPull, "pulls", "issues")
if ref.Owner == "" {
- link = createLink(ctx, util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], issuePath, ref.Issue), reftext, "ref-issue")
+ link = createLink(ctx, util.URLJoin(ctx.RenderOptions.Links.Prefix(), ctx.RenderOptions.Metas["user"], ctx.RenderOptions.Metas["repo"], issuePath, ref.Issue), reftext, "ref-issue")
} else {
- link = createLink(ctx, util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, issuePath, ref.Issue), reftext, "ref-issue")
+ link = createLink(ctx, util.URLJoin(ctx.RenderOptions.Links.Prefix(), ref.Owner, ref.Name, issuePath, ref.Issue), reftext, "ref-issue")
}
}
@@ -177,7 +177,7 @@ func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
}
reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha)
- link := createLink(ctx, util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit")
+ link := createLink(ctx, util.URLJoin(ctx.RenderOptions.Links.Prefix(), ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit")
replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
node = node.NextSibling.NextSibling
diff --git a/modules/markup/html_link.go b/modules/markup/html_link.go
index 32aa7dc614..f6700161b5 100644
--- a/modules/markup/html_link.go
+++ b/modules/markup/html_link.go
@@ -19,15 +19,15 @@ import (
func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (result string, resolved bool) {
isAnchorFragment := link != "" && link[0] == '#'
if !isAnchorFragment && !IsFullURLString(link) {
- linkBase := ctx.Links.Base
+ linkBase := ctx.RenderOptions.Links.Base
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()
- } else if ctx.Links.BranchPath != "" || ctx.Links.TreePath != "" {
+ linkBase = ctx.RenderOptions.Links.WikiLink()
+ } else if ctx.RenderOptions.Links.BranchPath != "" || ctx.RenderOptions.Links.TreePath != "" {
// if there is no BranchPath, then the link will be something like "/owner/repo/src/{the-file-path}"
// and then this link will be handled by the "legacy-ref" code and be redirected to the default branch like "/owner/repo/src/branch/main/{the-file-path}"
- linkBase = ctx.Links.SrcLink()
+ linkBase = ctx.RenderOptions.Links.SrcLink()
}
link, resolved = util.URLJoin(linkBase, link), true
}
@@ -147,7 +147,7 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
}
if image {
if !absoluteLink {
- link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), link)
+ link = util.URLJoin(ctx.RenderOptions.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), link)
}
title := props["title"]
if title == "" {
diff --git a/modules/markup/html_mention.go b/modules/markup/html_mention.go
index f7e2ad50f1..4243eeb20f 100644
--- a/modules/markup/html_mention.go
+++ b/modules/markup/html_mention.go
@@ -25,15 +25,15 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) {
loc.Start += start
loc.End += start
mention := node.Data[loc.Start:loc.End]
- teams, ok := ctx.Metas["teams"]
+ teams, ok := ctx.RenderOptions.Metas["teams"]
// FIXME: util.URLJoin may not be necessary here:
// - setting.AppURL is defined to have a terminal '/' so unless mention[1:]
// is an AppSubURL link we can probably fallback to concatenation.
// team mention should follow @orgName/teamName style
if ok && strings.Contains(mention, "/") {
mentionOrgAndTeam := strings.Split(mention, "/")
- if mentionOrgAndTeam[0][1:] == ctx.Metas["org"] && strings.Contains(teams, ","+strings.ToLower(mentionOrgAndTeam[1])+",") {
- replaceContent(node, loc.Start, loc.End, createLink(ctx, util.URLJoin(ctx.Links.Prefix(), "org", ctx.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "" /*mention*/))
+ if mentionOrgAndTeam[0][1:] == ctx.RenderOptions.Metas["org"] && strings.Contains(teams, ","+strings.ToLower(mentionOrgAndTeam[1])+",") {
+ replaceContent(node, loc.Start, loc.End, createLink(ctx, util.URLJoin(ctx.RenderOptions.Links.Prefix(), "org", ctx.RenderOptions.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "" /*mention*/))
node = node.NextSibling.NextSibling
start = 0
continue
@@ -43,8 +43,8 @@ func mentionProcessor(ctx *RenderContext, node *html.Node) {
}
mentionedUsername := mention[1:]
- if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) {
- replaceContent(node, loc.Start, loc.End, createLink(ctx, util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "" /*mention*/))
+ if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx, mentionedUsername) {
+ replaceContent(node, loc.Start, loc.End, createLink(ctx, util.URLJoin(ctx.RenderOptions.Links.Prefix(), mentionedUsername), mention, "" /*mention*/))
node = node.NextSibling.NextSibling
start = 0
} else {
diff --git a/modules/markup/html_node.go b/modules/markup/html_node.go
index 234adba2bf..a7c323fcba 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.IsMarkupContentWiki()), attr.Val)
+ attr.Val = util.URLJoin(ctx.RenderOptions.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()), attr.Val)
// By default, the "<img>" tag should also be clickable,
// because frontend use `<img>` 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.IsMarkupContentWiki()), attr.Val)
+ attr.Val = util.URLJoin(ctx.RenderOptions.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 67ac2758a3..7366965a9d 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -9,7 +9,6 @@ import (
"testing"
"code.gitea.io/gitea/modules/emoji"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
@@ -57,16 +56,10 @@ func newMockRepo(ownerName, repoName string) gitrepo.Repository {
func TestRender_Commits(t *testing.T) {
setting.AppURL = markup.TestAppURL
test := func(input, expected string) {
- buffer, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- RelativePath: ".md",
- Links: markup.Links{
- AbsolutePrefix: true,
- Base: markup.TestRepoURL,
- },
- Repo: newMockRepo(testRepoOwnerName, testRepoName),
- Metas: localMetas,
- }, input)
+ buffer, err := markup.RenderString(markup.NewTestRenderContext("a.md", localMetas, newMockRepo(testRepoOwnerName, testRepoName), markup.Links{
+ AbsolutePrefix: true,
+ Base: markup.TestRepoURL,
+ }), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -112,15 +105,11 @@ func TestRender_CrossReferences(t *testing.T) {
setting.AppURL = markup.TestAppURL
defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
test := func(input, expected string) {
- buffer, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- RelativePath: "a.md",
- Links: markup.Links{
+ buffer, err := markup.RenderString(markup.NewTestRenderContext("a.md", localMetas,
+ markup.Links{
AbsolutePrefix: true,
Base: setting.AppSubURL,
- },
- Metas: localMetas,
- }, input)
+ }), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -154,13 +143,7 @@ func TestRender_links(t *testing.T) {
setting.AppURL = markup.TestAppURL
defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
test := func(input, expected string) {
- buffer, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- RelativePath: "a.md",
- Links: markup.Links{
- Base: markup.TestRepoURL,
- },
- }, input)
+ buffer, err := markup.RenderString(markup.NewTestRenderContext("a.md", markup.Links{Base: markup.TestRepoURL}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -265,13 +248,7 @@ func TestRender_email(t *testing.T) {
setting.AppURL = markup.TestAppURL
defer testModule.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
test := func(input, expected string) {
- res, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- RelativePath: "a.md",
- Links: markup.Links{
- Base: markup.TestRepoURL,
- },
- }, input)
+ res, err := markup.RenderString(markup.NewTestRenderContext("a.md", markup.Links{Base: markup.TestRepoURL}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res))
}
@@ -338,13 +315,7 @@ func TestRender_emoji(t *testing.T) {
test := func(input, expected string) {
expected = strings.ReplaceAll(expected, "&", "&amp;")
- buffer, err := markup.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- RelativePath: "a.md",
- Links: markup.Links{
- Base: markup.TestRepoURL,
- },
- }, input)
+ buffer, err := markup.RenderString(markup.NewTestRenderContext("a.md", markup.Links{Base: markup.TestRepoURL}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -404,22 +375,10 @@ func TestRender_ShortLinks(t *testing.T) {
tree := util.URLJoin(markup.TestRepoURL, "src", "master")
test := func(input, expected, expectedWiki string) {
- buffer, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: markup.TestRepoURL,
- BranchPath: "master",
- },
- }, input)
+ buffer, err := markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: markup.TestRepoURL, BranchPath: "master"}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
- buffer, err = markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: markup.TestRepoURL,
- },
- Metas: localWikiMetas,
- }, input)
+ buffer, err = markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: markup.TestRepoURL}, localWikiMetas), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
}
@@ -529,11 +488,7 @@ 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: util.Iif(isWiki, localWikiMetas, localMetas),
- }, input)
+ buffer, err := markdown.RenderString(markup.NewTestRenderContext(links, util.Iif(isWiki, localWikiMetas, localMetas)), input)
assert.NoError(t, err)
return strings.TrimSpace(string(buffer))
}
@@ -574,26 +529,14 @@ func Test_ParseClusterFuzz(t *testing.T) {
data := "<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
var res strings.Builder
- err := markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: "https://example.com",
- },
- Metas: localMetas,
- }, strings.NewReader(data), &res)
+ err := markup.PostProcess(markup.NewTestRenderContext(markup.Links{Base: "https://example.com"}, localMetas), strings.NewReader(data), &res)
assert.NoError(t, err)
assert.NotContains(t, res.String(), "<html")
data = "<!DOCTYPE html>\n<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
res.Reset()
- err = markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: "https://example.com",
- },
- Metas: localMetas,
- }, strings.NewReader(data), &res)
+ err = markup.PostProcess(markup.NewTestRenderContext(markup.Links{Base: "https://example.com"}, localMetas), strings.NewReader(data), &res)
assert.NoError(t, err)
assert.NotContains(t, res.String(), "<html")
@@ -606,14 +549,13 @@ func TestPostProcess_RenderDocument(t *testing.T) {
test := func(input, expected string) {
var res strings.Builder
- err := markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
+ err := markup.PostProcess(markup.NewTestRenderContext(
+ markup.Links{
AbsolutePrefix: true,
Base: "https://example.com",
},
- Metas: map[string]string{"user": "go-gitea", "repo": "gitea"},
- }, strings.NewReader(input), &res)
+ map[string]string{"user": "go-gitea", "repo": "gitea"},
+ ), strings.NewReader(input), &res)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
}
@@ -650,10 +592,7 @@ func TestIssue16020(t *testing.T) {
data := `<img src="data:image/png;base64,i//V"/>`
var res strings.Builder
- err := markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Metas: localMetas,
- }, strings.NewReader(data), &res)
+ err := markup.PostProcess(markup.NewTestRenderContext(localMetas), strings.NewReader(data), &res)
assert.NoError(t, err)
assert.Equal(t, data, res.String())
}
@@ -666,29 +605,23 @@ func BenchmarkEmojiPostprocess(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var res strings.Builder
- err := markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Metas: localMetas,
- }, strings.NewReader(data), &res)
+ err := markup.PostProcess(markup.NewTestRenderContext(localMetas), strings.NewReader(data), &res)
assert.NoError(b, err)
}
}
func TestFuzz(t *testing.T) {
s := "t/l/issues/8#/../../a"
- renderContext := markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
+ renderContext := markup.NewTestRenderContext(
+ markup.Links{
Base: "https://example.com/go-gitea/gitea",
},
- Metas: map[string]string{
+ map[string]string{
"user": "go-gitea",
"repo": "gitea",
},
- }
-
- err := markup.PostProcess(&renderContext, strings.NewReader(s), io.Discard)
-
+ )
+ err := markup.PostProcess(renderContext, strings.NewReader(s), io.Discard)
assert.NoError(t, err)
}
@@ -696,10 +629,7 @@ func TestIssue18471(t *testing.T) {
data := `http://domain/org/repo/compare/783b039...da951ce`
var res strings.Builder
- err := markup.PostProcess(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Metas: localMetas,
- }, strings.NewReader(data), &res)
+ err := markup.PostProcess(markup.NewTestRenderContext(localMetas), strings.NewReader(data), &res)
assert.NoError(t, err)
assert.Equal(t, `<a href="http://domain/org/repo/compare/783b039...da951ce" class="compare"><code class="nohighlight">783b039...da951ce</code></a>`, res.String())
diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 47dcfa8b5a..45f8c266a2 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -79,7 +79,7 @@ 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"]
+ markdownLineBreakStyle := ctx.RenderOptions.Metas["markdownLineBreakStyle"]
if markup.RenderBehaviorForTesting.ForceHardLineBreak {
v.SetHardLineBreak(true)
} else if markdownLineBreakStyle == "comment" {
diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go
index a3915ad439..f77db9eb38 100644
--- a/modules/markup/markdown/markdown.go
+++ b/modules/markup/markdown/markdown.go
@@ -182,7 +182,7 @@ func render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
bufWithMetadataLength := len(buf)
rc := &RenderConfig{
- Meta: renderMetaModeFromString(string(ctx.RenderMetaAs)),
+ Meta: markup.RenderMetaAsDetails,
Icon: "table",
Lang: "",
}
@@ -241,7 +241,7 @@ func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Wri
// Render renders Markdown to HTML with all specific handling stuff.
func Render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error {
- ctx.MarkupType = MarkupName
+ ctx.RenderOptions.MarkupType = MarkupName
return markup.Render(ctx, input, output)
}
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index e4889a75e5..634ec6301f 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -4,12 +4,10 @@
package markdown_test
import (
- "context"
"html/template"
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
@@ -67,22 +65,11 @@ func TestRender_StandardLinks(t *testing.T) {
setting.AppURL = AppURL
test := func(input, expected, expectedWiki string) {
- buffer, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- }, input)
+ buffer, err := markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: FullURL}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
- buffer, err = markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- Metas: localWikiMetas,
- }, input)
+ buffer, err = markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: FullURL}, localWikiMetas), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expectedWiki), strings.TrimSpace(string(buffer)))
}
@@ -101,12 +88,7 @@ func TestRender_Images(t *testing.T) {
setting.AppURL = AppURL
test := func(input, expected string) {
- buffer, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- }, input)
+ buffer, err := markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: FullURL}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
}
@@ -308,14 +290,11 @@ func TestTotal_RenderWiki(t *testing.T) {
setting.AppURL = AppURL
answers := testAnswers(util.URLJoin(FullURL, "wiki"), util.URLJoin(FullURL, "wiki", "raw"))
for i := 0; i < len(sameCases); i++ {
- line, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- Repo: newMockRepo(testRepoOwnerName, testRepoName),
- Metas: localWikiMetas,
- }, sameCases[i])
+ line, err := markdown.RenderString(markup.NewTestRenderContext(
+ markup.Links{Base: FullURL},
+ newMockRepo(testRepoOwnerName, testRepoName),
+ localWikiMetas,
+ ), sameCases[i])
assert.NoError(t, err)
assert.Equal(t, answers[i], string(line))
}
@@ -334,13 +313,7 @@ func TestTotal_RenderWiki(t *testing.T) {
}
for i := 0; i < len(testCases); i += 2 {
- line, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- Metas: localWikiMetas,
- }, testCases[i])
+ line, err := markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: FullURL}, localWikiMetas), testCases[i])
assert.NoError(t, err)
assert.EqualValues(t, testCases[i+1], string(line))
}
@@ -352,15 +325,14 @@ func TestTotal_RenderString(t *testing.T) {
setting.AppURL = AppURL
answers := testAnswers(util.URLJoin(FullURL, "src", "master"), util.URLJoin(FullURL, "media", "master"))
for i := 0; i < len(sameCases); i++ {
- line, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
+ line, err := markdown.RenderString(markup.NewTestRenderContext(
+ markup.Links{
Base: FullURL,
BranchPath: "master",
},
- Repo: newMockRepo(testRepoOwnerName, testRepoName),
- Metas: localMetas,
- }, sameCases[i])
+ newMockRepo(testRepoOwnerName, testRepoName),
+ localMetas,
+ ), sameCases[i])
assert.NoError(t, err)
assert.Equal(t, answers[i], string(line))
}
@@ -368,12 +340,7 @@ func TestTotal_RenderString(t *testing.T) {
testCases := []string{}
for i := 0; i < len(testCases); i += 2 {
- line, err := markdown.RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: FullURL,
- },
- }, testCases[i])
+ line, err := markdown.RenderString(markup.NewTestRenderContext(markup.Links{Base: FullURL}), testCases[i])
assert.NoError(t, err)
assert.Equal(t, template.HTML(testCases[i+1]), line)
}
@@ -381,17 +348,17 @@ func TestTotal_RenderString(t *testing.T) {
func TestRender_RenderParagraphs(t *testing.T) {
test := func(t *testing.T, str string, cnt int) {
- res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, str)
+ res, err := markdown.RenderRawString(markup.NewTestRenderContext(), str)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for unix should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
mac := strings.ReplaceAll(str, "\n", "\r")
- res, err = markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, mac)
+ res, err = markdown.RenderRawString(markup.NewTestRenderContext(), mac)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for mac should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
dos := strings.ReplaceAll(str, "\n", "\r\n")
- res, err = markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, dos)
+ res, err = markdown.RenderRawString(markup.NewTestRenderContext(), dos)
assert.NoError(t, err)
assert.Equal(t, cnt, strings.Count(res, "<p"), "Rendered result for windows should have %d paragraph(s) but has %d:\n%s\n", cnt, strings.Count(res, "<p"), res)
}
@@ -419,7 +386,7 @@ func TestMarkdownRenderRaw(t *testing.T) {
for _, testcase := range testcases {
log.Info("Test markdown render error with fuzzy data: %x, the following errors can be recovered", testcase)
- _, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, string(testcase))
+ _, err := markdown.RenderRawString(markup.NewTestRenderContext(), string(testcase))
assert.NoError(t, err)
}
}
@@ -432,7 +399,7 @@ func TestRenderSiblingImages_Issue12925(t *testing.T) {
<a href="/image2" target="_blank" rel="nofollow noopener"><img src="/image2" alt="image2"></a></p>
`
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.ForceHardLineBreak, true)()
- res, err := markdown.RenderRawString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
+ res, err := markdown.RenderRawString(markup.NewTestRenderContext(), testcase)
assert.NoError(t, err)
assert.Equal(t, expected, res)
}
@@ -441,7 +408,7 @@ func TestRenderEmojiInLinks_Issue12331(t *testing.T) {
testcase := `[Link with emoji :moon: in text](https://gitea.io)`
expected := `<p><a href="https://gitea.io" rel="nofollow">Link with emoji <span class="emoji" aria-label="waxing gibbous moon">🌔</span> in text</a></p>
`
- res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, testcase)
+ res, err := markdown.RenderString(markup.NewTestRenderContext(), testcase)
assert.NoError(t, err)
assert.Equal(t, template.HTML(expected), res)
}
@@ -479,7 +446,7 @@ func TestColorPreview(t *testing.T) {
}
for _, test := range positiveTests {
- res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
+ res, err := markdown.RenderString(markup.NewTestRenderContext(), test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
@@ -498,7 +465,7 @@ func TestColorPreview(t *testing.T) {
}
for _, test := range negativeTests {
- res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test)
+ res, err := markdown.RenderString(markup.NewTestRenderContext(), test)
assert.NoError(t, err, "Unexpected error in testcase: %q", test)
assert.NotContains(t, res, `<span class="color-preview" style="background-color: `, "Unexpected result in testcase %q", test)
}
@@ -573,7 +540,7 @@ func TestMathBlock(t *testing.T) {
}
for _, test := range testcases {
- res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
+ res, err := markdown.RenderString(markup.NewTestRenderContext(), test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
@@ -610,7 +577,7 @@ foo: bar
}
for _, test := range testcases {
- res, err := markdown.RenderString(&markup.RenderContext{Ctx: git.DefaultContext}, test.testcase)
+ res, err := markdown.RenderString(markup.NewTestRenderContext(), test.testcase)
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
assert.Equal(t, template.HTML(test.expected), res, "Unexpected result in testcase %q", test.testcase)
}
@@ -1003,11 +970,7 @@ space</p>
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.ForceHardLineBreak, true)()
defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableInternalAttributes, true)()
for i, c := range cases {
- result, err := markdown.RenderString(&markup.RenderContext{
- Ctx: context.Background(),
- Links: c.Links,
- Metas: util.Iif(c.IsWiki, map[string]string{"markupContentMode": "wiki"}, map[string]string{}),
- }, input)
+ result, err := markdown.RenderString(markup.NewTestRenderContext(c.Links, 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)
}
@@ -1029,7 +992,7 @@ func TestAttention(t *testing.T) {
}
test := func(input, expected string) {
- result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background()}, input)
+ result, err := markdown.RenderString(markup.NewTestRenderContext(), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(result)))
}
@@ -1062,6 +1025,6 @@ func BenchmarkSpecializedMarkdown(b *testing.B) {
func BenchmarkMarkdownRender(b *testing.B) {
// 23202 50840 ns/op
for i := 0; i < b.N; i++ {
- _, _ = markdown.RenderString(&markup.RenderContext{Ctx: context.Background()}, "https://example.com\n- a\n- b\n")
+ _, _ = markdown.RenderString(markup.NewTestRenderContext(), "https://example.com\n- a\n- b\n")
}
}
diff --git a/modules/markup/markdown/transform_image.go b/modules/markup/markdown/transform_image.go
index b2262c1c78..c2cbffc1c1 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.IsMarkupContentWiki()),
+ ctx.RenderOptions.Links.ResolveMediaLink(ctx.IsMarkupContentWiki()),
strings.TrimLeft(string(v.Destination), "/"),
))
}
diff --git a/modules/markup/orgmode/orgmode.go b/modules/markup/orgmode/orgmode.go
index c587a6ada5..cf719cf4e9 100644
--- a/modules/markup/orgmode/orgmode.go
+++ b/modules/markup/orgmode/orgmode.go
@@ -143,15 +143,15 @@ func (r *Writer) resolveLink(kind, link string) string {
kind = org.RegularLink{URL: link}.Kind()
}
- base := r.Ctx.Links.Base
+ base := r.Ctx.RenderOptions.Links.Base
if r.Ctx.IsMarkupContentWiki() {
- base = r.Ctx.Links.WikiLink()
- } else if r.Ctx.Links.HasBranchInfo() {
- base = r.Ctx.Links.SrcLink()
+ base = r.Ctx.RenderOptions.Links.WikiLink()
+ } else if r.Ctx.RenderOptions.Links.HasBranchInfo() {
+ base = r.Ctx.RenderOptions.Links.SrcLink()
}
if kind == "image" || kind == "video" {
- base = r.Ctx.Links.ResolveMediaLink(r.Ctx.IsMarkupContentWiki())
+ base = r.Ctx.RenderOptions.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 a3eefc3db3..4048ae2475 100644
--- a/modules/markup/orgmode/orgmode_test.go
+++ b/modules/markup/orgmode/orgmode_test.go
@@ -4,10 +4,10 @@
package markup
import (
+ "os"
"strings"
"testing"
- "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -15,20 +15,21 @@ import (
"github.com/stretchr/testify/assert"
)
-const AppURL = "http://localhost:3000/"
+func TestMain(m *testing.M) {
+ setting.AppURL = "http://localhost:3000/"
+ setting.IsInTesting = true
+ os.Exit(m.Run())
+}
func TestRender_StandardLinks(t *testing.T) {
- setting.AppURL = AppURL
-
test := func(input, expected string, isWiki bool) {
- buffer, err := RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
+ buffer, err := RenderString(markup.NewTestRenderContext(
+ markup.Links{
Base: "/relative-path",
BranchPath: "branch/main",
},
- Metas: map[string]string{"markupContentMode": util.Iif(isWiki, "wiki", "")},
- }, input)
+ map[string]string{"markupContentMode": util.Iif(isWiki, "wiki", "")},
+ ), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -42,16 +43,13 @@ func TestRender_StandardLinks(t *testing.T) {
}
func TestRender_InternalLinks(t *testing.T) {
- setting.AppURL = AppURL
-
test := func(input, expected string) {
- buffer, err := RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
+ buffer, err := RenderString(markup.NewTestRenderContext(
+ markup.Links{
Base: "/relative-path",
BranchPath: "branch/main",
},
- }, input)
+ ), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -67,15 +65,8 @@ func TestRender_InternalLinks(t *testing.T) {
}
func TestRender_Media(t *testing.T) {
- setting.AppURL = AppURL
-
test := func(input, expected string) {
- buffer, err := RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- Links: markup.Links{
- Base: "./relative-path",
- },
- }, input)
+ buffer, err := RenderString(markup.NewTestRenderContext(markup.Links{Base: "./relative-path"}), input)
assert.NoError(t, err)
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
}
@@ -113,12 +104,8 @@ func TestRender_Media(t *testing.T) {
}
func TestRender_Source(t *testing.T) {
- setting.AppURL = AppURL
-
test := func(input, expected string) {
- buffer, err := RenderString(&markup.RenderContext{
- Ctx: git.DefaultContext,
- }, input)
+ buffer, err := RenderString(markup.NewTestRenderContext(), 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 f05cb62626..e251f47fc9 100644
--- a/modules/markup/render.go
+++ b/modules/markup/render.go
@@ -9,6 +9,7 @@ import (
"io"
"net/url"
"strings"
+ "time"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@@ -42,16 +43,16 @@ var RenderBehaviorForTesting struct {
DisableInternalAttributes bool
}
-// RenderContext represents a render context
-type RenderContext struct {
- Ctx context.Context
- RelativePath string // relative path from tree root of the branch
+type RenderOptions struct {
+ // relative path from tree root of the branch
+ RelativePath string
// eg: "orgmode", "asciicast", "console"
// for file mode, it could be left as empty, and will be detected by file extension in RelativePath
MarkupType string
- Links Links // special link references for rendering, especially when there is a branch/tree path
+ // special link references for rendering, especially when there is a branch/tree path
+ Links Links
// user&repo, format&style&regexp (for external issue pattern), teams&org (for mention)
// BranchNameSubURL (for iframe&asciicast)
@@ -59,27 +60,95 @@ type RenderContext struct {
// markdownLineBreakStyle (comment, document)
Metas map[string]string
- GitRepo *git.Repository
- Repo gitrepo.Repository
- ShaExistCache map[string]bool
- cancelFn func()
- SidebarTocNode ast.Node
- RenderMetaAs RenderMetaMode
- InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
+ // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
+ InStandalonePage bool
+}
+
+type RenderHelper struct {
+ gitRepo *git.Repository
+ repoFacade gitrepo.Repository
+ shaExistCache map[string]bool
+ cancelFn func()
+}
+
+// RenderContext represents a render context
+type RenderContext struct {
+ ctx context.Context
+ SidebarTocNode ast.Node
+
+ RenderHelper RenderHelper
+ RenderOptions RenderOptions
RenderInternal internal.RenderInternal
}
+func (ctx *RenderContext) Deadline() (deadline time.Time, ok bool) {
+ return ctx.ctx.Deadline()
+}
+
+func (ctx *RenderContext) Done() <-chan struct{} {
+ return ctx.ctx.Done()
+}
+
+func (ctx *RenderContext) Err() error {
+ return ctx.ctx.Err()
+}
+
+func (ctx *RenderContext) Value(key any) any {
+ return ctx.ctx.Value(key)
+}
+
+var _ context.Context = (*RenderContext)(nil)
+
+func NewRenderContext(ctx context.Context) *RenderContext {
+ return &RenderContext{ctx: ctx}
+}
+
+func (ctx *RenderContext) WithMarkupType(typ string) *RenderContext {
+ ctx.RenderOptions.MarkupType = typ
+ return ctx
+}
+
+func (ctx *RenderContext) WithRelativePath(path string) *RenderContext {
+ ctx.RenderOptions.RelativePath = path
+ return ctx
+}
+
+func (ctx *RenderContext) WithLinks(links Links) *RenderContext {
+ ctx.RenderOptions.Links = links
+ return ctx
+}
+
+func (ctx *RenderContext) WithMetas(metas map[string]string) *RenderContext {
+ ctx.RenderOptions.Metas = metas
+ return ctx
+}
+
+func (ctx *RenderContext) WithInStandalonePage(v bool) *RenderContext {
+ ctx.RenderOptions.InStandalonePage = v
+ return ctx
+}
+
+func (ctx *RenderContext) WithGitRepo(r *git.Repository) *RenderContext {
+ ctx.RenderHelper.gitRepo = r
+ return ctx
+}
+
+func (ctx *RenderContext) WithRepoFacade(r gitrepo.Repository) *RenderContext {
+ ctx.RenderHelper.repoFacade = r
+ return ctx
+}
+
// Cancel runs any cleanup functions that have been registered for this Ctx
func (ctx *RenderContext) Cancel() {
if ctx == nil {
return
}
- ctx.ShaExistCache = map[string]bool{}
- if ctx.cancelFn == nil {
+ ctx.RenderHelper.shaExistCache = map[string]bool{}
+ if ctx.RenderHelper.cancelFn == nil {
return
}
- ctx.cancelFn()
+ ctx.RenderHelper.cancelFn()
}
// AddCancel adds the provided fn as a Cleanup for this Ctx
@@ -87,38 +156,38 @@ func (ctx *RenderContext) AddCancel(fn func()) {
if ctx == nil {
return
}
- oldCancelFn := ctx.cancelFn
+ oldCancelFn := ctx.RenderHelper.cancelFn
if oldCancelFn == nil {
- ctx.cancelFn = fn
+ ctx.RenderHelper.cancelFn = fn
return
}
- ctx.cancelFn = func() {
+ ctx.RenderHelper.cancelFn = func() {
defer oldCancelFn()
fn()
}
}
func (ctx *RenderContext) IsMarkupContentWiki() bool {
- return ctx.Metas != nil && ctx.Metas["markupContentMode"] == "wiki"
+ return ctx.RenderOptions.Metas != nil && ctx.RenderOptions.Metas["markupContentMode"] == "wiki"
}
// Render renders markup file to HTML with all specific handling stuff.
func Render(ctx *RenderContext, input io.Reader, output io.Writer) error {
- if ctx.MarkupType == "" && ctx.RelativePath != "" {
- ctx.MarkupType = DetectMarkupTypeByFileName(ctx.RelativePath)
- if ctx.MarkupType == "" {
- return util.NewInvalidArgumentErrorf("unsupported file to render: %q", ctx.RelativePath)
+ if ctx.RenderOptions.MarkupType == "" && ctx.RenderOptions.RelativePath != "" {
+ ctx.RenderOptions.MarkupType = DetectMarkupTypeByFileName(ctx.RenderOptions.RelativePath)
+ if ctx.RenderOptions.MarkupType == "" {
+ return util.NewInvalidArgumentErrorf("unsupported file to render: %q", ctx.RenderOptions.RelativePath)
}
}
- renderer := renderers[ctx.MarkupType]
+ renderer := renderers[ctx.RenderOptions.MarkupType]
if renderer == nil {
- return util.NewInvalidArgumentErrorf("unsupported markup type: %q", ctx.MarkupType)
+ return util.NewInvalidArgumentErrorf("unsupported markup type: %q", ctx.RenderOptions.MarkupType)
}
- if ctx.RelativePath != "" {
+ if ctx.RenderOptions.RelativePath != "" {
if externalRender, ok := renderer.(ExternalRenderer); ok && externalRender.DisplayInIFrame() {
- if !ctx.InStandalonePage {
+ if !ctx.RenderOptions.InStandalonePage {
// for an external "DisplayInIFrame" render, it could only output its content in a standalone page
// otherwise, a <iframe> should be outputted to embed the external rendered page
return renderIFrame(ctx, output)
@@ -151,10 +220,10 @@ width="100%%" height="0" scrolling="no" frameborder="0" style="overflow: hidden"
sandbox="allow-scripts"
></iframe>`,
setting.AppSubURL,
- url.PathEscape(ctx.Metas["user"]),
- url.PathEscape(ctx.Metas["repo"]),
- ctx.Metas["BranchNameSubURL"],
- url.PathEscape(ctx.RelativePath),
+ url.PathEscape(ctx.RenderOptions.Metas["user"]),
+ url.PathEscape(ctx.RenderOptions.Metas["repo"]),
+ ctx.RenderOptions.Metas["BranchNameSubURL"],
+ url.PathEscape(ctx.RenderOptions.RelativePath),
))
return err
}
@@ -176,7 +245,7 @@ func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Wr
pr1, pw1, close1 := pipes()
defer close1()
- eg, _ := errgroup.WithContext(ctx.Ctx)
+ eg, _ := errgroup.WithContext(ctx)
var pw2 io.WriteCloser = util.NopCloser{Writer: finalProcessor}
if r, ok := renderer.(ExternalRenderer); !ok || !r.SanitizerDisabled() {
@@ -230,3 +299,27 @@ func Init(ph *ProcessorHelper) {
func ComposeSimpleDocumentMetas() map[string]string {
return map[string]string{"markdownLineBreakStyle": "document"}
}
+
+// NewTestRenderContext is a helper function to create a RenderContext for testing purpose
+// It accepts string (RelativePath), Links, map[string]string (Metas), gitrepo.Repository
+func NewTestRenderContext(a ...any) *RenderContext {
+ if !setting.IsInTesting {
+ panic("NewTestRenderContext should only be used in testing")
+ }
+ ctx := NewRenderContext(context.Background())
+ for _, v := range a {
+ switch v := v.(type) {
+ case string:
+ ctx = ctx.WithRelativePath(v)
+ case Links:
+ ctx = ctx.WithLinks(v)
+ case map[string]string:
+ ctx = ctx.WithMetas(v)
+ case gitrepo.Repository:
+ ctx = ctx.WithRepoFacade(v)
+ default:
+ panic(fmt.Sprintf("unknown type %T", v))
+ }
+ }
+ return ctx
+}