Skip to content

Commit d9ea3e4

Browse files
authored
Merge branch 'main' into telackey/sort
2 parents 54f6d71 + 8c9d2bd commit d9ea3e4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+835
-497
lines changed

custom/conf/app.example.ini

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,14 +1413,14 @@ LEVEL = Info
14131413
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14141414
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14151415
;;
1416-
;; Render soft line breaks as hard line breaks, which means a single newline character between
1417-
;; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
1418-
;; necessary to force a line break.
1419-
;; Render soft line breaks as hard line breaks for comments
1420-
;ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true
1421-
;;
1422-
;; Render soft line breaks as hard line breaks for markdown documents
1423-
;ENABLE_HARD_LINE_BREAK_IN_DOCUMENTS = false
1416+
;; Customize render options for different contexts. Set to "none" to disable the defaults, or use comma separated list:
1417+
;; * short-issue-pattern: recognized "#123" issue reference and render it as a link to the issue
1418+
;; * new-line-hard-break: render soft line breaks as hard line breaks, which means a single newline character between
1419+
;; paragraphs will cause a line break and adding trailing whitespace to paragraphs is not
1420+
;; necessary to force a line break.
1421+
;RENDER_OPTIONS_COMMENT = short-issue-pattern, new-line-hard-break
1422+
;RENDER_OPTIONS_WIKI = short-issue-pattern
1423+
;RENDER_OPTIONS_REPO_FILE =
14241424
;;
14251425
;; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
14261426
;; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
@@ -1434,6 +1434,12 @@ LEVEL = Info
14341434
;;
14351435
;; Enables math inline and block detection
14361436
;ENABLE_MATH = true
1437+
;;
1438+
;; Enable delimiters for math code block detection. Set to "none" to disable all,
1439+
;; or use comma separated list: inline-dollar, inline-parentheses, block-dollar, block-square-brackets
1440+
;; Defaults to "inline-dollar,block-dollar" to follow GitHub's behavior.
1441+
;MATH_CODE_BLOCK_DETECTION =
1442+
;;
14371443

14381444
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14391445
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

models/renderhelper/repo_comment.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ func NewRenderContextRepoComment(ctx context.Context, repo *repo_model.Repositor
5656
if repo != nil {
5757
helper.repoLink = repo.Link()
5858
helper.commitChecker = newCommitChecker(ctx, repo)
59-
rctx = rctx.WithMetas(repo.ComposeMetas(ctx))
59+
rctx = rctx.WithMetas(repo.ComposeCommentMetas(ctx))
6060
} else {
6161
// this is almost dead code, only to pass the incorrect tests
6262
helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName)
6363
rctx = rctx.WithMetas(map[string]string{
6464
"user": helper.opts.DeprecatedOwnerName,
6565
"repo": helper.opts.DeprecatedRepoName,
6666

67-
"markdownLineBreakStyle": "comment",
67+
"markdownNewLineHardBreak": "true",
6868
"markupAllowShortIssuePattern": "true",
6969
})
7070
}

models/renderhelper/repo_file.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,13 @@ func NewRenderContextRepoFile(ctx context.Context, repo *repo_model.Repository,
6161
if repo != nil {
6262
helper.repoLink = repo.Link()
6363
helper.commitChecker = newCommitChecker(ctx, repo)
64-
rctx = rctx.WithMetas(repo.ComposeDocumentMetas(ctx))
64+
rctx = rctx.WithMetas(repo.ComposeRepoFileMetas(ctx))
6565
} else {
6666
// this is almost dead code, only to pass the incorrect tests
6767
helper.repoLink = fmt.Sprintf("%s/%s", helper.opts.DeprecatedOwnerName, helper.opts.DeprecatedRepoName)
6868
rctx = rctx.WithMetas(map[string]string{
6969
"user": helper.opts.DeprecatedOwnerName,
7070
"repo": helper.opts.DeprecatedRepoName,
71-
72-
"markdownLineBreakStyle": "document",
7371
})
7472
}
7573
rctx = rctx.WithHelper(helper)

models/renderhelper/repo_wiki.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ func NewRenderContextRepoWiki(ctx context.Context, repo *repo_model.Repository,
6868
"user": helper.opts.DeprecatedOwnerName,
6969
"repo": helper.opts.DeprecatedRepoName,
7070

71-
"markdownLineBreakStyle": "document",
7271
"markupAllowShortIssuePattern": "true",
7372
})
7473
}

models/repo/repo.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,15 @@ func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]strin
512512
"repo": repo.Name,
513513
}
514514

515-
unit, err := repo.GetUnit(ctx, unit.TypeExternalTracker)
515+
unitExternalTracker, err := repo.GetUnit(ctx, unit.TypeExternalTracker)
516516
if err == nil {
517-
metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
518-
switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
517+
metas["format"] = unitExternalTracker.ExternalTrackerConfig().ExternalTrackerFormat
518+
switch unitExternalTracker.ExternalTrackerConfig().ExternalTrackerStyle {
519519
case markup.IssueNameStyleAlphanumeric:
520520
metas["style"] = markup.IssueNameStyleAlphanumeric
521521
case markup.IssueNameStyleRegexp:
522522
metas["style"] = markup.IssueNameStyleRegexp
523-
metas["regexp"] = unit.ExternalTrackerConfig().ExternalTrackerRegexpPattern
523+
metas["regexp"] = unitExternalTracker.ExternalTrackerConfig().ExternalTrackerRegexpPattern
524524
default:
525525
metas["style"] = markup.IssueNameStyleNumeric
526526
}
@@ -544,28 +544,29 @@ func (repo *Repository) composeCommonMetas(ctx context.Context) map[string]strin
544544
return repo.commonRenderingMetas
545545
}
546546

547-
// ComposeMetas composes a map of metas for properly rendering comments or comment-like contents (commit message)
548-
func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
547+
// ComposeCommentMetas composes a map of metas for properly rendering comments or comment-like contents (commit message)
548+
func (repo *Repository) ComposeCommentMetas(ctx context.Context) map[string]string {
549549
metas := maps.Clone(repo.composeCommonMetas(ctx))
550-
metas["markdownLineBreakStyle"] = "comment"
551-
metas["markupAllowShortIssuePattern"] = "true"
550+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsComment.NewLineHardBreak)
551+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsComment.ShortIssuePattern)
552552
return metas
553553
}
554554

555555
// ComposeWikiMetas composes a map of metas for properly rendering wikis
556556
func (repo *Repository) ComposeWikiMetas(ctx context.Context) map[string]string {
557557
// does wiki need the "teams" and "org" from common metas?
558558
metas := maps.Clone(repo.composeCommonMetas(ctx))
559-
metas["markdownLineBreakStyle"] = "document"
560-
metas["markupAllowShortIssuePattern"] = "true"
559+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsWiki.NewLineHardBreak)
560+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsWiki.ShortIssuePattern)
561561
return metas
562562
}
563563

564-
// ComposeDocumentMetas composes a map of metas for properly rendering documents (repo files)
565-
func (repo *Repository) ComposeDocumentMetas(ctx context.Context) map[string]string {
564+
// ComposeRepoFileMetas composes a map of metas for properly rendering documents (repo files)
565+
func (repo *Repository) ComposeRepoFileMetas(ctx context.Context) map[string]string {
566566
// does document(file) need the "teams" and "org" from common metas?
567567
metas := maps.Clone(repo.composeCommonMetas(ctx))
568-
metas["markdownLineBreakStyle"] = "document"
568+
metas["markdownNewLineHardBreak"] = strconv.FormatBool(setting.Markdown.RenderOptionsRepoFile.NewLineHardBreak)
569+
metas["markupAllowShortIssuePattern"] = strconv.FormatBool(setting.Markdown.RenderOptionsRepoFile.ShortIssuePattern)
569570
return metas
570571
}
571572

models/repo/repo_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func TestMetas(t *testing.T) {
8686

8787
repo.Units = nil
8888

89-
metas := repo.ComposeMetas(db.DefaultContext)
89+
metas := repo.ComposeCommentMetas(db.DefaultContext)
9090
assert.Equal(t, "testRepo", metas["repo"])
9191
assert.Equal(t, "testOwner", metas["user"])
9292

@@ -100,7 +100,7 @@ func TestMetas(t *testing.T) {
100100
testSuccess := func(expectedStyle string) {
101101
repo.Units = []*RepoUnit{&externalTracker}
102102
repo.commonRenderingMetas = nil
103-
metas := repo.ComposeMetas(db.DefaultContext)
103+
metas := repo.ComposeCommentMetas(db.DefaultContext)
104104
assert.Equal(t, expectedStyle, metas["style"])
105105
assert.Equal(t, "testRepo", metas["repo"])
106106
assert.Equal(t, "testOwner", metas["user"])
@@ -121,7 +121,7 @@ func TestMetas(t *testing.T) {
121121
repo, err := GetRepositoryByID(db.DefaultContext, 3)
122122
assert.NoError(t, err)
123123

124-
metas = repo.ComposeMetas(db.DefaultContext)
124+
metas = repo.ComposeCommentMetas(db.DefaultContext)
125125
assert.Contains(t, metas, "org")
126126
assert.Contains(t, metas, "teams")
127127
assert.Equal(t, "org3", metas["org"])

modules/fileicon/material.go

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"code.gitea.io/gitea/modules/json"
1414
"code.gitea.io/gitea/modules/log"
1515
"code.gitea.io/gitea/modules/options"
16-
"code.gitea.io/gitea/modules/reqctx"
1716
"code.gitea.io/gitea/modules/svg"
1817
)
1918

@@ -62,30 +61,21 @@ func (m *MaterialIconProvider) loadData() {
6261
log.Debug("Loaded material icon rules and SVG images")
6362
}
6463

65-
func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name, svg, extraClass string) template.HTML {
66-
data := ctx.GetData()
67-
renderedSVGs, _ := data["_RenderedSVGs"].(map[string]bool)
68-
if renderedSVGs == nil {
69-
renderedSVGs = make(map[string]bool)
70-
data["_RenderedSVGs"] = renderedSVGs
71-
}
64+
func (m *MaterialIconProvider) renderFileIconSVG(p *RenderedIconPool, name, svg, extraClass string) template.HTML {
7265
// This part is a bit hacky, but it works really well. It should be safe to do so because all SVG icons are generated by us.
7366
// Will try to refactor this in the future.
7467
if !strings.HasPrefix(svg, "<svg") {
7568
panic("Invalid SVG icon")
7669
}
7770
svgID := "svg-mfi-" + name
7871
svgCommonAttrs := `class="svg git-entry-icon ` + extraClass + `" width="16" height="16" aria-hidden="true"`
79-
posOuterBefore := strings.IndexByte(svg, '>')
80-
if renderedSVGs[svgID] && posOuterBefore != -1 {
81-
return template.HTML(`<svg ` + svgCommonAttrs + `><use xlink:href="#` + svgID + `"></use></svg>`)
72+
if p.IconSVGs[svgID] == "" {
73+
p.IconSVGs[svgID] = template.HTML(`<svg id="` + svgID + `" ` + svgCommonAttrs + svg[4:])
8274
}
83-
svg = `<svg id="` + svgID + `" ` + svgCommonAttrs + svg[4:]
84-
renderedSVGs[svgID] = true
85-
return template.HTML(svg)
75+
return template.HTML(`<svg ` + svgCommonAttrs + `><use xlink:href="#` + svgID + `"></use></svg>`)
8676
}
8777

88-
func (m *MaterialIconProvider) FileIcon(ctx reqctx.RequestContext, entry *git.TreeEntry) template.HTML {
78+
func (m *MaterialIconProvider) FileIcon(p *RenderedIconPool, entry *git.TreeEntry) template.HTML {
8979
if m.rules == nil {
9080
return BasicThemeIcon(entry)
9181
}
@@ -110,7 +100,7 @@ func (m *MaterialIconProvider) FileIcon(ctx reqctx.RequestContext, entry *git.Tr
110100
case entry.IsSubModule():
111101
extraClass = "octicon-file-submodule"
112102
}
113-
return m.renderFileIconSVG(ctx, name, iconSVG, extraClass)
103+
return m.renderFileIconSVG(p, name, iconSVG, extraClass)
114104
}
115105
// TODO: use an interface or wrapper for git.Entry to make the code testable.
116106
return BasicThemeIcon(entry)

modules/fileicon/render.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package fileicon
5+
6+
import (
7+
"html/template"
8+
"strings"
9+
10+
"code.gitea.io/gitea/modules/git"
11+
"code.gitea.io/gitea/modules/setting"
12+
)
13+
14+
type RenderedIconPool struct {
15+
IconSVGs map[string]template.HTML
16+
}
17+
18+
func NewRenderedIconPool() *RenderedIconPool {
19+
return &RenderedIconPool{
20+
IconSVGs: make(map[string]template.HTML),
21+
}
22+
}
23+
24+
func (p *RenderedIconPool) RenderToHTML() template.HTML {
25+
if len(p.IconSVGs) == 0 {
26+
return ""
27+
}
28+
sb := &strings.Builder{}
29+
sb.WriteString(`<div class=tw-hidden>`)
30+
for _, icon := range p.IconSVGs {
31+
sb.WriteString(string(icon))
32+
}
33+
sb.WriteString(`</div>`)
34+
return template.HTML(sb.String())
35+
}
36+
37+
// TODO: use an interface or struct to replace "*git.TreeEntry", to decouple the fileicon module from git module
38+
39+
func RenderEntryIcon(renderedIconPool *RenderedIconPool, entry *git.TreeEntry) template.HTML {
40+
if setting.UI.FileIconTheme == "material" {
41+
return DefaultMaterialIconProvider().FileIcon(renderedIconPool, entry)
42+
}
43+
return BasicThemeIcon(entry)
44+
}
45+
46+
func RenderEntryIconOpen(renderedIconPool *RenderedIconPool, entry *git.TreeEntry) template.HTML {
47+
// TODO: add "open icon" support
48+
if setting.UI.FileIconTheme == "material" {
49+
return DefaultMaterialIconProvider().FileIcon(renderedIconPool, entry)
50+
}
51+
return BasicThemeIcon(entry)
52+
}

modules/git/error.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ func (err ErrNotExist) Unwrap() error {
3232
return util.ErrNotExist
3333
}
3434

35-
// ErrBadLink entry.FollowLink error
36-
type ErrBadLink struct {
35+
// ErrSymlinkUnresolved entry.FollowLink error
36+
type ErrSymlinkUnresolved struct {
3737
Name string
3838
Message string
3939
}
4040

41-
func (err ErrBadLink) Error() string {
41+
func (err ErrSymlinkUnresolved) Error() string {
4242
return fmt.Sprintf("%s: %s", err.Name, err.Message)
4343
}
4444

45-
// IsErrBadLink if some error is ErrBadLink
46-
func IsErrBadLink(err error) bool {
47-
_, ok := err.(ErrBadLink)
45+
// IsErrSymlinkUnresolved if some error is ErrSymlinkUnresolved
46+
func IsErrSymlinkUnresolved(err error) bool {
47+
_, ok := err.(ErrSymlinkUnresolved)
4848
return ok
4949
}
5050

modules/git/repo_commit_nogogit.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
8181

8282
_, _ = wr.Write([]byte(id.String() + "\n"))
8383

84-
return repo.getCommitFromBatchReader(rd, id)
84+
return repo.getCommitFromBatchReader(wr, rd, id)
8585
}
8686

87-
func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID) (*Commit, error) {
87+
func (repo *Repository) getCommitFromBatchReader(wr WriteCloserError, rd *bufio.Reader, id ObjectID) (*Commit, error) {
8888
_, typ, size, err := ReadBatchLine(rd)
8989
if err != nil {
9090
if errors.Is(err, io.EOF) || IsErrNotExist(err) {
@@ -112,7 +112,11 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
112112
return nil, err
113113
}
114114

115-
commit, err := tag.Commit(repo)
115+
if _, err := wr.Write([]byte(tag.Object.String() + "\n")); err != nil {
116+
return nil, err
117+
}
118+
119+
commit, err := repo.getCommitFromBatchReader(wr, rd, tag.Object)
116120
if err != nil {
117121
return nil, err
118122
}

0 commit comments

Comments
 (0)