Date: Sat, 16 Mar 2024 08:09:49 +0100
Subject: [PATCH 007/822] Split filePreviewPatternProcessor into a new type
FilePreview and some functions to make code more maintainable
---
modules/markup/file_preview.go | 269 +++++++++++++++++++++++++++++++++
modules/markup/html.go | 245 +-----------------------------
2 files changed, 276 insertions(+), 238 deletions(-)
create mode 100644 modules/markup/file_preview.go
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
new file mode 100644
index 0000000000..646bf83630
--- /dev/null
+++ b/modules/markup/file_preview.go
@@ -0,0 +1,269 @@
+package markup
+
+import (
+ "bytes"
+ "html/template"
+ "regexp"
+ "slices"
+ "strconv"
+ "strings"
+
+ "code.gitea.io/gitea/modules/charset"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/translation"
+ "golang.org/x/net/html"
+ "golang.org/x/net/html/atom"
+)
+
+var (
+ // filePreviewPattern matches "http://domain/org/repo/src/commit/COMMIT/filepath#L1-L2"
+ filePreviewPattern = regexp.MustCompile(`https?://((?:\S+/){3})src/commit/([0-9a-f]{4,64})/(\S+)#(L\d+(?:-L\d+)?)`)
+)
+
+type FilePreview struct {
+ fileContent []template.HTML
+ subTitle template.HTML
+ lineOffset int
+ urlFull string
+ filePath string
+ start int
+ end int
+}
+
+func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale) *FilePreview {
+ preview := &FilePreview{}
+
+ m := filePreviewPattern.FindStringSubmatchIndex(node.Data)
+ if m == nil {
+ return nil
+ }
+
+ // Ensure that every group has a match
+ if slices.Contains(m, -1) {
+ return nil
+ }
+
+ preview.urlFull = node.Data[m[0]:m[1]]
+
+ // Ensure that we only use links to local repositories
+ if !strings.HasPrefix(preview.urlFull, setting.AppURL+setting.AppSubURL) {
+ return nil
+ }
+
+ projPath := strings.TrimSuffix(node.Data[m[2]:m[3]], "/")
+
+ commitSha := node.Data[m[4]:m[5]]
+ preview.filePath = node.Data[m[6]:m[7]]
+ hash := node.Data[m[8]:m[9]]
+
+ preview.start = m[0]
+ preview.end = m[1]
+
+ // If url ends in '.', it's very likely that it is not part of the
+ // actual url but used to finish a sentence.
+ if strings.HasSuffix(preview.urlFull, ".") {
+ preview.end--
+ preview.urlFull = preview.urlFull[:len(preview.urlFull)-1]
+ hash = hash[:len(hash)-1]
+ }
+
+ projPathSegments := strings.Split(projPath, "/")
+ fileContent, err := DefaultProcessorHelper.GetRepoFileContent(
+ ctx.Ctx,
+ projPathSegments[len(projPathSegments)-2],
+ projPathSegments[len(projPathSegments)-1],
+ commitSha, preview.filePath,
+ )
+ if err != nil {
+ return nil
+ }
+
+ lineSpecs := strings.Split(hash, "-")
+ lineCount := len(fileContent)
+
+ commitLinkBuffer := new(bytes.Buffer)
+ html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
+
+ if len(lineSpecs) == 1 {
+ line, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
+ if line < 1 || line > lineCount {
+ return nil
+ }
+
+ preview.fileContent = fileContent[line-1 : line]
+ preview.subTitle = locale.Tr(
+ "markup.filepreview.line", line,
+ template.HTML(commitLinkBuffer.String()),
+ )
+
+ preview.lineOffset = line - 1
+ } else {
+ startLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
+ endLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[1], "L"))
+
+ if startLine < 1 || endLine < 1 || startLine > lineCount || endLine > lineCount || endLine < startLine {
+ return nil
+ }
+
+ preview.fileContent = fileContent[startLine-1 : endLine]
+ preview.subTitle = locale.Tr(
+ "markup.filepreview.lines", startLine, endLine,
+ template.HTML(commitLinkBuffer.String()),
+ )
+
+ preview.lineOffset = startLine - 1
+ }
+
+ return preview
+}
+
+func (p *FilePreview) CreateHtml(locale translation.Locale) *html.Node {
+ table := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Table.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "file-preview"}},
+ }
+ tbody := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Tbody.String(),
+ }
+
+ status := &charset.EscapeStatus{}
+ statuses := make([]*charset.EscapeStatus, len(p.fileContent))
+ for i, line := range p.fileContent {
+ statuses[i], p.fileContent[i] = charset.EscapeControlHTML(line, locale, charset.FileviewContext)
+ status = status.Or(statuses[i])
+ }
+
+ for idx, code := range p.fileContent {
+ tr := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Tr.String(),
+ }
+
+ lineNum := strconv.Itoa(p.lineOffset + idx + 1)
+
+ tdLinesnum := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Td.String(),
+ Attr: []html.Attribute{
+ {Key: "id", Val: "L" + lineNum},
+ {Key: "class", Val: "lines-num"},
+ },
+ }
+ spanLinesNum := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Span.String(),
+ Attr: []html.Attribute{
+ {Key: "id", Val: "L" + lineNum},
+ {Key: "data-line-number", Val: lineNum},
+ },
+ }
+ tdLinesnum.AppendChild(spanLinesNum)
+ tr.AppendChild(tdLinesnum)
+
+ if status.Escaped {
+ tdLinesEscape := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Td.String(),
+ Attr: []html.Attribute{
+ {Key: "class", Val: "lines-escape"},
+ },
+ }
+
+ if statuses[idx].Escaped {
+ btnTitle := ""
+ if statuses[idx].HasInvisible {
+ btnTitle += locale.TrString("repo.invisible_runes_line") + " "
+ }
+ if statuses[idx].HasAmbiguous {
+ btnTitle += locale.TrString("repo.ambiguous_runes_line")
+ }
+
+ escapeBtn := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Button.String(),
+ Attr: []html.Attribute{
+ {Key: "class", Val: "toggle-escape-button btn interact-bg"},
+ {Key: "title", Val: btnTitle},
+ },
+ }
+ tdLinesEscape.AppendChild(escapeBtn)
+ }
+
+ tr.AppendChild(tdLinesEscape)
+ }
+
+ tdCode := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Td.String(),
+ Attr: []html.Attribute{
+ {Key: "rel", Val: "L" + lineNum},
+ {Key: "class", Val: "lines-code chroma"},
+ },
+ }
+ codeInner := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Code.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "code-inner"}},
+ }
+ codeText := &html.Node{
+ Type: html.RawNode,
+ Data: string(code),
+ }
+ codeInner.AppendChild(codeText)
+ tdCode.AppendChild(codeInner)
+ tr.AppendChild(tdCode)
+
+ tbody.AppendChild(tr)
+ }
+
+ table.AppendChild(tbody)
+
+ twrapper := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Div.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "ui table"}},
+ }
+ twrapper.AppendChild(table)
+
+ header := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Div.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "header"}},
+ }
+ afilepath := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.A.String(),
+ Attr: []html.Attribute{
+ {Key: "href", Val: p.urlFull},
+ {Key: "class", Val: "muted"},
+ },
+ }
+ afilepath.AppendChild(&html.Node{
+ Type: html.TextNode,
+ Data: p.filePath,
+ })
+ header.AppendChild(afilepath)
+
+ psubtitle := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Span.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "text small grey"}},
+ }
+ psubtitle.AppendChild(&html.Node{
+ Type: html.RawNode,
+ Data: string(p.subTitle),
+ })
+ header.AppendChild(psubtitle)
+
+ preview_node := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Div.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "file-preview-box"}},
+ }
+ preview_node.AppendChild(header)
+ preview_node.AppendChild(twrapper)
+
+ return preview_node
+}
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 1e83dad701..2e38c05f58 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -5,19 +5,15 @@ package markup
import (
"bytes"
- "html/template"
"io"
"net/url"
"path"
"path/filepath"
"regexp"
- "slices"
- "strconv"
"strings"
"sync"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
@@ -65,9 +61,6 @@ var (
validLinksPattern = regexp.MustCompile(`^[a-z][\w-]+://`)
- // filePreviewPattern matches "http://domain/org/repo/src/commit/COMMIT/filepath#L1-L2"
- filePreviewPattern = regexp.MustCompile(`https?://((?:\S+/){3})src/commit/([0-9a-f]{4,64})/(\S+)#(L\d+(?:-L\d+)?)`)
-
// While this email regex is definitely not perfect and I'm sure you can come up
// with edge cases, it is still accepted by the CommonMark specification, as
// well as the HTML5 spec:
@@ -1072,252 +1065,28 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) {
next := node.NextSibling
for node != nil && node != next {
- m := filePreviewPattern.FindStringSubmatchIndex(node.Data)
- if m == nil {
- return
- }
-
- // Ensure that every group has a match
- if slices.Contains(m, -1) {
- return
- }
-
- urlFull := node.Data[m[0]:m[1]]
-
- // Ensure that we only use links to local repositories
- if !strings.HasPrefix(urlFull, setting.AppURL+setting.AppSubURL) {
- return
- }
-
- projPath := strings.TrimSuffix(node.Data[m[2]:m[3]], "/")
-
- commitSha := node.Data[m[4]:m[5]]
- filePath := node.Data[m[6]:m[7]]
- hash := node.Data[m[8]:m[9]]
-
- start := m[0]
- end := m[1]
-
- // If url ends in '.', it's very likely that it is not part of the
- // actual url but used to finish a sentence.
- if strings.HasSuffix(urlFull, ".") {
- end--
- urlFull = urlFull[:len(urlFull)-1]
- hash = hash[:len(hash)-1]
- }
-
- projPathSegments := strings.Split(projPath, "/")
- fileContent, err := DefaultProcessorHelper.GetRepoFileContent(
- ctx.Ctx,
- projPathSegments[len(projPathSegments)-2],
- projPathSegments[len(projPathSegments)-1],
- commitSha, filePath,
- )
- if err != nil {
- return
- }
-
- lineSpecs := strings.Split(hash, "-")
- lineCount := len(fileContent)
-
- commitLinkBuffer := new(bytes.Buffer)
- html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
-
- var subTitle template.HTML
- var lineOffset int
-
locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale)
if !ok {
locale = translation.NewLocale("en-US")
}
- if len(lineSpecs) == 1 {
- line, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
- if line < 1 || line > lineCount {
- return
- }
-
- fileContent = fileContent[line-1 : line]
- subTitle = locale.Tr(
- "markup.filepreview.line", line,
- template.HTML(commitLinkBuffer.String()),
- )
-
- lineOffset = line - 1
- } else {
- startLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
- endLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[1], "L"))
-
- if startLine < 1 || endLine < 1 || startLine > lineCount || endLine > lineCount || endLine < startLine {
- return
- }
-
- fileContent = fileContent[startLine-1 : endLine]
- subTitle = locale.Tr(
- "markup.filepreview.lines", startLine, endLine,
- template.HTML(commitLinkBuffer.String()),
- )
-
- lineOffset = startLine - 1
+ preview := NewFilePreview(ctx, node, locale)
+ if preview == nil {
+ return
}
- table := &html.Node{
- Type: html.ElementNode,
- Data: atom.Table.String(),
- Attr: []html.Attribute{{Key: "class", Val: "file-preview"}},
- }
- tbody := &html.Node{
- Type: html.ElementNode,
- Data: atom.Tbody.String(),
- }
-
- status := &charset.EscapeStatus{}
- statuses := make([]*charset.EscapeStatus, len(fileContent))
- for i, line := range fileContent {
- statuses[i], fileContent[i] = charset.EscapeControlHTML(line, locale, charset.FileviewContext)
- status = status.Or(statuses[i])
- }
-
- for idx, code := range fileContent {
- tr := &html.Node{
- Type: html.ElementNode,
- Data: atom.Tr.String(),
- }
-
- lineNum := strconv.Itoa(lineOffset + idx + 1)
-
- tdLinesnum := &html.Node{
- Type: html.ElementNode,
- Data: atom.Td.String(),
- Attr: []html.Attribute{
- {Key: "id", Val: "L" + lineNum},
- {Key: "class", Val: "lines-num"},
- },
- }
- spanLinesNum := &html.Node{
- Type: html.ElementNode,
- Data: atom.Span.String(),
- Attr: []html.Attribute{
- {Key: "id", Val: "L" + lineNum},
- {Key: "data-line-number", Val: lineNum},
- },
- }
- tdLinesnum.AppendChild(spanLinesNum)
- tr.AppendChild(tdLinesnum)
-
- if status.Escaped {
- tdLinesEscape := &html.Node{
- Type: html.ElementNode,
- Data: atom.Td.String(),
- Attr: []html.Attribute{
- {Key: "class", Val: "lines-escape"},
- },
- }
-
- if statuses[idx].Escaped {
- btnTitle := ""
- if statuses[idx].HasInvisible {
- btnTitle += locale.TrString("repo.invisible_runes_line") + " "
- }
- if statuses[idx].HasAmbiguous {
- btnTitle += locale.TrString("repo.ambiguous_runes_line")
- }
-
- escapeBtn := &html.Node{
- Type: html.ElementNode,
- Data: atom.Button.String(),
- Attr: []html.Attribute{
- {Key: "class", Val: "toggle-escape-button btn interact-bg"},
- {Key: "title", Val: btnTitle},
- },
- }
- tdLinesEscape.AppendChild(escapeBtn)
- }
-
- tr.AppendChild(tdLinesEscape)
- }
-
- tdCode := &html.Node{
- Type: html.ElementNode,
- Data: atom.Td.String(),
- Attr: []html.Attribute{
- {Key: "rel", Val: "L" + lineNum},
- {Key: "class", Val: "lines-code chroma"},
- },
- }
- codeInner := &html.Node{
- Type: html.ElementNode,
- Data: atom.Code.String(),
- Attr: []html.Attribute{{Key: "class", Val: "code-inner"}},
- }
- codeText := &html.Node{
- Type: html.RawNode,
- Data: string(code),
- }
- codeInner.AppendChild(codeText)
- tdCode.AppendChild(codeInner)
- tr.AppendChild(tdCode)
-
- tbody.AppendChild(tr)
- }
-
- table.AppendChild(tbody)
-
- twrapper := &html.Node{
- Type: html.ElementNode,
- Data: atom.Div.String(),
- Attr: []html.Attribute{{Key: "class", Val: "ui table"}},
- }
- twrapper.AppendChild(table)
-
- header := &html.Node{
- Type: html.ElementNode,
- Data: atom.Div.String(),
- Attr: []html.Attribute{{Key: "class", Val: "header"}},
- }
- afilepath := &html.Node{
- Type: html.ElementNode,
- Data: atom.A.String(),
- Attr: []html.Attribute{
- {Key: "href", Val: urlFull},
- {Key: "class", Val: "muted"},
- },
- }
- afilepath.AppendChild(&html.Node{
- Type: html.TextNode,
- Data: filePath,
- })
- header.AppendChild(afilepath)
-
- psubtitle := &html.Node{
- Type: html.ElementNode,
- Data: atom.Span.String(),
- Attr: []html.Attribute{{Key: "class", Val: "text small grey"}},
- }
- psubtitle.AppendChild(&html.Node{
- Type: html.RawNode,
- Data: string(subTitle),
- })
- header.AppendChild(psubtitle)
-
- preview := &html.Node{
- Type: html.ElementNode,
- Data: atom.Div.String(),
- Attr: []html.Attribute{{Key: "class", Val: "file-preview-box"}},
- }
- preview.AppendChild(header)
- preview.AppendChild(twrapper)
+ preview_node := preview.CreateHtml(locale)
// Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div
- before := node.Data[:start]
- after := node.Data[end:]
+ before := node.Data[:preview.start]
+ after := node.Data[preview.end:]
node.Data = before
nextSibling := node.NextSibling
node.Parent.InsertBefore(&html.Node{
Type: html.RawNode,
Data: "",
}, nextSibling)
- node.Parent.InsertBefore(preview, nextSibling)
+ node.Parent.InsertBefore(preview_node, nextSibling)
node.Parent.InsertBefore(&html.Node{
Type: html.RawNode,
Data: "" + after,
From 8218e80bfc3a1f9ba02ce60f1acafdc0e57c5ae0 Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Sat, 16 Mar 2024 08:18:47 +0100
Subject: [PATCH 008/822] Fix linting issues
---
modules/markup/file_preview.go | 22 ++++++++++++----------
modules/markup/html.go | 4 ++--
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 646bf83630..be788aae4b 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -9,16 +9,15 @@ import (
"strings"
"code.gitea.io/gitea/modules/charset"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
-var (
- // filePreviewPattern matches "http://domain/org/repo/src/commit/COMMIT/filepath#L1-L2"
- filePreviewPattern = regexp.MustCompile(`https?://((?:\S+/){3})src/commit/([0-9a-f]{4,64})/(\S+)#(L\d+(?:-L\d+)?)`)
-)
+// filePreviewPattern matches "http://domain/org/repo/src/commit/COMMIT/filepath#L1-L2"
+var filePreviewPattern = regexp.MustCompile(`https?://((?:\S+/){3})src/commit/([0-9a-f]{4,64})/(\S+)#(L\d+(?:-L\d+)?)`)
type FilePreview struct {
fileContent []template.HTML
@@ -82,7 +81,10 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
lineCount := len(fileContent)
commitLinkBuffer := new(bytes.Buffer)
- html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
+ err = html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
+ if err != nil {
+ log.Error("failed to render commitLink: %v", err)
+ }
if len(lineSpecs) == 1 {
line, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
@@ -117,7 +119,7 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
return preview
}
-func (p *FilePreview) CreateHtml(locale translation.Locale) *html.Node {
+func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
table := &html.Node{
Type: html.ElementNode,
Data: atom.Table.String(),
@@ -257,13 +259,13 @@ func (p *FilePreview) CreateHtml(locale translation.Locale) *html.Node {
})
header.AppendChild(psubtitle)
- preview_node := &html.Node{
+ node := &html.Node{
Type: html.ElementNode,
Data: atom.Div.String(),
Attr: []html.Attribute{{Key: "class", Val: "file-preview-box"}},
}
- preview_node.AppendChild(header)
- preview_node.AppendChild(twrapper)
+ node.AppendChild(header)
+ node.AppendChild(twrapper)
- return preview_node
+ return node
}
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 2e38c05f58..9a04e02fb8 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -1075,7 +1075,7 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) {
return
}
- preview_node := preview.CreateHtml(locale)
+ previewNode := preview.CreateHTML(locale)
// Specialized version of replaceContent, so the parent paragraph element is not destroyed from our div
before := node.Data[:preview.start]
@@ -1086,7 +1086,7 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) {
Type: html.RawNode,
Data: "
",
}, nextSibling)
- node.Parent.InsertBefore(preview_node, nextSibling)
+ node.Parent.InsertBefore(previewNode, nextSibling)
node.Parent.InsertBefore(&html.Node{
Type: html.RawNode,
Data: "" + after,
From 10bca456a9140519e95559aa7bac2221e1156c5b Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 18 Mar 2024 06:19:27 +0100
Subject: [PATCH 009/822] Remove `rel` and `id` attributes that only add the
linenumber to elements
---
modules/markup/file_preview.go | 3 ---
modules/markup/sanitizer.go | 1 -
2 files changed, 4 deletions(-)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index be788aae4b..167bbd1997 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -149,7 +149,6 @@ func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
Type: html.ElementNode,
Data: atom.Td.String(),
Attr: []html.Attribute{
- {Key: "id", Val: "L" + lineNum},
{Key: "class", Val: "lines-num"},
},
}
@@ -157,7 +156,6 @@ func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
Type: html.ElementNode,
Data: atom.Span.String(),
Attr: []html.Attribute{
- {Key: "id", Val: "L" + lineNum},
{Key: "data-line-number", Val: lineNum},
},
}
@@ -200,7 +198,6 @@ func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
Type: html.ElementNode,
Data: atom.Td.String(),
Attr: []html.Attribute{
- {Key: "rel", Val: "L" + lineNum},
{Key: "class", Val: "lines-code chroma"},
},
}
diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go
index 73e17060a7..c37027b843 100644
--- a/modules/markup/sanitizer.go
+++ b/modules/markup/sanitizer.go
@@ -128,7 +128,6 @@ func createDefaultPolicy() *bluemonday.Policy {
policy.AllowAttrs("class").Matching(regexp.MustCompile("^header$")).OnElements("div")
policy.AllowAttrs("data-line-number").Matching(regexp.MustCompile("^[0-9]+$")).OnElements("span")
policy.AllowAttrs("class").Matching(regexp.MustCompile("^text small grey$")).OnElements("span")
- policy.AllowAttrs("rel").Matching(regexp.MustCompile("^L[0-9]+$")).OnElements("td")
policy.AllowAttrs("class").Matching(regexp.MustCompile("^file-preview*")).OnElements("table")
policy.AllowAttrs("class").Matching(regexp.MustCompile("^lines-escape$")).OnElements("td")
policy.AllowAttrs("class").Matching(regexp.MustCompile("^toggle-escape-button btn interact-bg$")).OnElements("button")
From db6f6281fcf568ae8e35330a4a93c9be1cb46efd Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 18 Mar 2024 06:21:35 +0100
Subject: [PATCH 010/822] Add copyright & license header to file_preview.go
---
modules/markup/file_preview.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 167bbd1997..377809529d 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -1,3 +1,6 @@
+// Copyright The Forgejo Authors.
+// SPDX-License-Identifier: MIT
+
package markup
import (
From ed8e8a792e75b930074cd3cf1bab580a09ff8485 Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 18 Mar 2024 06:23:12 +0100
Subject: [PATCH 011/822] Run make fmt
---
modules/markup/file_preview.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 377809529d..2702cb7ce3 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
+
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
From d6428f92ce7ce67d127cbd5bb4977aa92abf071c Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 25 Mar 2024 14:33:30 +0100
Subject: [PATCH 012/822] Fix typo in language files
---
options/locale/locale_en-US.ini | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index ebc8db24ca..efaf8b72c9 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3709,5 +3709,5 @@ symbolic_link = Symbolic link
submodule = Submodule
[markup]
-filepreview.line = Line %[1]d in %[3]s
+filepreview.line = Line %[1]d in %[2]s
filepreview.lines = Lines %[1]d to %[2]d in %[3]s
From 069d87b80f909e91626249afbb240a1df339a8fd Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 25 Mar 2024 14:33:54 +0100
Subject: [PATCH 013/822] Remove unneeded case for a trailing dot
---
modules/markup/file_preview.go | 8 --------
1 file changed, 8 deletions(-)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 2702cb7ce3..3e76dcb8a4 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -62,14 +62,6 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
preview.start = m[0]
preview.end = m[1]
- // If url ends in '.', it's very likely that it is not part of the
- // actual url but used to finish a sentence.
- if strings.HasSuffix(preview.urlFull, ".") {
- preview.end--
- preview.urlFull = preview.urlFull[:len(preview.urlFull)-1]
- hash = hash[:len(hash)-1]
- }
-
projPathSegments := strings.Split(projPath, "/")
fileContent, err := DefaultProcessorHelper.GetRepoFileContent(
ctx.Ctx,
From 2b6546adc954d450a9c6befccd407ce2ca1636a0 Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Mon, 25 Mar 2024 16:05:01 +0100
Subject: [PATCH 014/822] Add setting to restrict count of lines being
displayed & only highlight those lines
---
custom/conf/app.example.ini | 2 +
modules/markup/file_preview.go | 103 ++++++++++++++++++++++++-----
modules/markup/html.go | 2 +-
modules/markup/renderer.go | 4 +-
modules/markup/sanitizer.go | 1 +
modules/setting/markup.go | 2 +
options/locale/locale_en-US.ini | 1 +
services/markup/processorhelper.go | 24 ++++---
web_src/css/markup/filepreview.css | 6 ++
9 files changed, 117 insertions(+), 28 deletions(-)
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index b3896bc31c..91f86da5f8 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -2338,6 +2338,8 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set the maximum number of characters in a mermaid source. (Set to -1 to disable limits)
;MERMAID_MAX_SOURCE_CHARACTERS = 5000
+;; Set the maximum number of lines allowed for a filepreview. (Set to -1 to disable limits; set to 0 to disable the feature)
+;FILEPREVIEW_MAX_LINES = 50
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 3e76dcb8a4..32683c317c 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -4,6 +4,7 @@
package markup
import (
+ "bufio"
"bytes"
"html/template"
"regexp"
@@ -12,6 +13,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/charset"
+ "code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
@@ -31,9 +33,15 @@ type FilePreview struct {
filePath string
start int
end int
+ isTruncated bool
}
func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale) *FilePreview {
+ if (setting.FilePreviewMaxLines == 0) {
+ // Feature is disabled
+ return nil
+ }
+
preview := &FilePreview{}
m := filePreviewPattern.FindStringSubmatchIndex(node.Data)
@@ -63,18 +71,20 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
preview.end = m[1]
projPathSegments := strings.Split(projPath, "/")
- fileContent, err := DefaultProcessorHelper.GetRepoFileContent(
+ var language string
+ fileBlob, err := DefaultProcessorHelper.GetRepoFileBlob(
ctx.Ctx,
projPathSegments[len(projPathSegments)-2],
projPathSegments[len(projPathSegments)-1],
commitSha, preview.filePath,
+ &language,
)
if err != nil {
return nil
}
lineSpecs := strings.Split(hash, "-")
- lineCount := len(fileContent)
+ // lineCount := len(fileContent)
commitLinkBuffer := new(bytes.Buffer)
err = html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
@@ -82,28 +92,31 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
log.Error("failed to render commitLink: %v", err)
}
- if len(lineSpecs) == 1 {
- line, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
- if line < 1 || line > lineCount {
- return nil
- }
+ var startLine, endLine int
- preview.fileContent = fileContent[line-1 : line]
+ if len(lineSpecs) == 1 {
+ startLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
+ endLine = startLine
+ // if line < 1 || line > lineCount {
+ // return nil
+ // }
+
+ // preview.fileContent = fileContent[line-1 : line]
preview.subTitle = locale.Tr(
- "markup.filepreview.line", line,
+ "markup.filepreview.line", startLine,
template.HTML(commitLinkBuffer.String()),
)
- preview.lineOffset = line - 1
+ preview.lineOffset = startLine - 1
} else {
- startLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
- endLine, _ := strconv.Atoi(strings.TrimPrefix(lineSpecs[1], "L"))
+ startLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
+ endLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[1], "L"))
- if startLine < 1 || endLine < 1 || startLine > lineCount || endLine > lineCount || endLine < startLine {
- return nil
- }
+ // if startLine < 1 || endLine < 1 || startLine > lineCount || endLine > lineCount || endLine < startLine {
+ // return nil
+ // }
- preview.fileContent = fileContent[startLine-1 : endLine]
+ // preview.fileContent = fileContent[startLine-1 : endLine]
preview.subTitle = locale.Tr(
"markup.filepreview.lines", startLine, endLine,
template.HTML(commitLinkBuffer.String()),
@@ -112,6 +125,50 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
preview.lineOffset = startLine - 1
}
+ lineCount := endLine - (startLine-1)
+ if startLine < 1 || endLine < 1 || lineCount < 1 {
+ return nil
+ }
+
+ if setting.FilePreviewMaxLines > 0 && lineCount > setting.FilePreviewMaxLines {
+ preview.isTruncated = true
+ lineCount = setting.FilePreviewMaxLines
+ }
+
+ dataRc, err := fileBlob.DataAsync()
+ if err != nil {
+ return nil
+ }
+ defer dataRc.Close()
+
+ reader := bufio.NewReader(dataRc)
+
+ // skip all lines until we find our startLine
+ for i := 1; i < startLine; i++ {
+ _, err := reader.ReadBytes('\n')
+ if err != nil {
+ return nil
+ }
+ }
+
+ // capture the lines we're interested in
+ lineBuffer := new(bytes.Buffer)
+ for i := 0; i < lineCount; i++ {
+ buf, err := reader.ReadBytes('\n')
+ if err != nil {
+ break;
+ }
+ lineBuffer.Write(buf)
+ }
+
+ // highlight the file...
+ fileContent, _, err := highlight.File(fileBlob.Name(), language, lineBuffer.Bytes())
+ if err != nil {
+ log.Error("highlight.File failed, fallback to plain text: %v", err)
+ fileContent = highlight.PlainText(lineBuffer.Bytes())
+ }
+ preview.fileContent = fileContent
+
return preview
}
@@ -258,6 +315,20 @@ func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
Attr: []html.Attribute{{Key: "class", Val: "file-preview-box"}},
}
node.AppendChild(header)
+
+ if (p.isTruncated) {
+ warning := &html.Node{
+ Type: html.ElementNode,
+ Data: atom.Div.String(),
+ Attr: []html.Attribute{{Key: "class", Val: "ui warning message tw-text-left"}},
+ }
+ warning.AppendChild(&html.Node{
+ Type: html.TextNode,
+ Data: locale.TrString("markup.filepreview.truncated"),
+ })
+ node.AppendChild(warning)
+ }
+
node.AppendChild(twrapper)
return node
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 9a04e02fb8..4c74a81ba7 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -1059,7 +1059,7 @@ func filePreviewPatternProcessor(ctx *RenderContext, node *html.Node) {
if ctx.Metas == nil {
return
}
- if DefaultProcessorHelper.GetRepoFileContent == nil {
+ if DefaultProcessorHelper.GetRepoFileBlob == nil {
return
}
diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go
index b6d742e5ce..b08c9eb230 100644
--- a/modules/markup/renderer.go
+++ b/modules/markup/renderer.go
@@ -8,7 +8,7 @@ import (
"context"
"errors"
"fmt"
- "html/template"
+ // "html/template"
"io"
"net/url"
"path/filepath"
@@ -32,7 +32,7 @@ const (
type ProcessorHelper struct {
IsUsernameMentionable func(ctx context.Context, username string) bool
- GetRepoFileContent func(ctx context.Context, ownerName, repoName, commitSha, filePath string) ([]template.HTML, error)
+ GetRepoFileBlob func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error)
ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute
}
diff --git a/modules/markup/sanitizer.go b/modules/markup/sanitizer.go
index c37027b843..1048f0e374 100644
--- a/modules/markup/sanitizer.go
+++ b/modules/markup/sanitizer.go
@@ -135,6 +135,7 @@ func createDefaultPolicy() *bluemonday.Policy {
policy.AllowAttrs("class").Matching(regexp.MustCompile("^ambiguous-code-point$")).OnElements("span")
policy.AllowAttrs("data-tooltip-content").OnElements("span")
policy.AllowAttrs("class").Matching(regexp.MustCompile("muted|(text black)")).OnElements("a")
+ policy.AllowAttrs("class").Matching(regexp.MustCompile("^ui warning message tw-text-left$")).OnElements("div")
// Allow generally safe attributes
generalSafeAttrs := []string{
diff --git a/modules/setting/markup.go b/modules/setting/markup.go
index 6c2246342b..e893c1c2f1 100644
--- a/modules/setting/markup.go
+++ b/modules/setting/markup.go
@@ -15,6 +15,7 @@ var (
ExternalMarkupRenderers []*MarkupRenderer
ExternalSanitizerRules []MarkupSanitizerRule
MermaidMaxSourceCharacters int
+ FilePreviewMaxLines int
)
const (
@@ -62,6 +63,7 @@ func loadMarkupFrom(rootCfg ConfigProvider) {
mustMapSetting(rootCfg, "markdown", &Markdown)
MermaidMaxSourceCharacters = rootCfg.Section("markup").Key("MERMAID_MAX_SOURCE_CHARACTERS").MustInt(5000)
+ FilePreviewMaxLines = rootCfg.Section("markup").Key("FILEPREVIEW_MAX_LINES").MustInt(50)
ExternalMarkupRenderers = make([]*MarkupRenderer, 0, 10)
ExternalSanitizerRules = make([]MarkupSanitizerRule, 0, 10)
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index efaf8b72c9..8533cf0650 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -3711,3 +3711,4 @@ submodule = Submodule
[markup]
filepreview.line = Line %[1]d in %[2]s
filepreview.lines = Lines %[1]d to %[2]d in %[3]s
+filepreview.truncated = Preview has been truncated
diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go
index df96f25ce9..98a7824a6e 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/processorhelper.go
@@ -6,15 +6,17 @@ package markup
import (
"context"
"fmt"
- "html/template"
- "io"
+
+ // "html/template"
+ // "io"
"code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
- "code.gitea.io/gitea/modules/highlight"
+ // "code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
gitea_context "code.gitea.io/gitea/services/context"
@@ -39,7 +41,7 @@ func ProcessorHelper() *markup.ProcessorHelper {
// when using gitea context (web context), use user's visibility and user's permission to check
return user.IsUserVisibleToViewer(giteaCtx, mentionedUser, giteaCtx.Doer)
},
- GetRepoFileContent: func(ctx context.Context, ownerName, repoName, commitSha, filePath string) ([]template.HTML, error) {
+ GetRepoFileBlob: func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error) {
repo, err := repo.GetRepositoryByOwnerAndName(ctx, ownerName, repoName)
if err != nil {
return nil, err
@@ -70,9 +72,11 @@ func ProcessorHelper() *markup.ProcessorHelper {
return nil, err
}
- language, err := file_service.TryGetContentLanguage(gitRepo, commitSha, filePath)
- if err != nil {
- log.Error("Unable to get file language for %-v:%s. Error: %v", repo, filePath, err)
+ if language != nil {
+ *language, err = file_service.TryGetContentLanguage(gitRepo, commitSha, filePath)
+ if err != nil {
+ log.Error("Unable to get file language for %-v:%s. Error: %v", repo, filePath, err)
+ }
}
blob, err := commit.GetBlobByPath(filePath)
@@ -80,7 +84,9 @@ func ProcessorHelper() *markup.ProcessorHelper {
return nil, err
}
- dataRc, err := blob.DataAsync()
+ return blob, nil
+
+ /*dataRc, err := blob.DataAsync()
if err != nil {
return nil, err
}
@@ -97,7 +103,7 @@ func ProcessorHelper() *markup.ProcessorHelper {
fileContent = highlight.PlainText(buf)
}
- return fileContent, nil
+ return fileContent, nil*/
},
}
}
diff --git a/web_src/css/markup/filepreview.css b/web_src/css/markup/filepreview.css
index 69360e2a70..d2ec16ea8b 100644
--- a/web_src/css/markup/filepreview.css
+++ b/web_src/css/markup/filepreview.css
@@ -25,6 +25,12 @@
background: var(--color-box-header);
}
+.markup .file-preview-box .warning {
+ border-radius: 0;
+ margin: 0;
+ padding: .5rem .5rem .5rem 1rem;
+}
+
.markup .file-preview-box .header > a {
display: block;
}
From 4f43b7338b956e7850927ba452492fe1b4f33238 Mon Sep 17 00:00:00 2001
From: Leo Heitmann Ruiz
Date: Tue, 26 Mar 2024 22:01:53 +0100
Subject: [PATCH 015/822] "Plaintext" => "Text"
---
modules/highlight/highlight.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go
index d7ab3f7afd..8fa2de6daf 100644
--- a/modules/highlight/highlight.go
+++ b/modules/highlight/highlight.go
@@ -217,7 +217,7 @@ func PlainText(code []byte) []template.HTML {
func formatLexerName(name string) string {
if name == "fallback" {
- return "Plaintext"
+ return "Text"
}
return util.ToTitleCaseNoLower(name)
From c340e020786b1451c1693853fc3c42102729a10a Mon Sep 17 00:00:00 2001
From: Leo Heitmann Ruiz
Date: Tue, 26 Mar 2024 22:25:34 +0100
Subject: [PATCH 016/822] "Plaintext" => "Text"
---
modules/highlight/highlight_test.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/highlight/highlight_test.go b/modules/highlight/highlight_test.go
index 659688bd0f..dd15b97847 100644
--- a/modules/highlight/highlight_test.go
+++ b/modules/highlight/highlight_test.go
@@ -58,7 +58,7 @@ func TestFile(t *testing.T) {
name: "tags.txt",
code: "<>",
want: lines("<>"),
- lexerName: "Plaintext",
+ lexerName: "Text",
},
{
name: "tags.py",
From 4c7cb0a5d20e8973b03e35d91119cf917eed125e Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Wed, 27 Mar 2024 18:25:37 +0100
Subject: [PATCH 017/822] Close git.Repository when GetRepoFileBlob returns
---
services/markup/processorhelper.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go
index 98a7824a6e..7466e962d2 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/processorhelper.go
@@ -66,6 +66,7 @@ func ProcessorHelper() *markup.ProcessorHelper {
if err != nil {
return nil, err
}
+ defer gitRepo.Close()
commit, err := gitRepo.GetCommit(commitSha)
if err != nil {
From 7e0014dd1391e123d95f2537c3b2165fef7122ef Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Wed, 27 Mar 2024 18:36:12 +0100
Subject: [PATCH 018/822] Fix formating & remove commented out code
---
modules/markup/file_preview.go | 20 ++++----------------
modules/markup/renderer.go | 2 +-
services/markup/processorhelper.go | 19 -------------------
3 files changed, 5 insertions(+), 36 deletions(-)
diff --git a/modules/markup/file_preview.go b/modules/markup/file_preview.go
index 32683c317c..95c94e0c14 100644
--- a/modules/markup/file_preview.go
+++ b/modules/markup/file_preview.go
@@ -37,7 +37,7 @@ type FilePreview struct {
}
func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Locale) *FilePreview {
- if (setting.FilePreviewMaxLines == 0) {
+ if setting.FilePreviewMaxLines == 0 {
// Feature is disabled
return nil
}
@@ -84,7 +84,6 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
}
lineSpecs := strings.Split(hash, "-")
- // lineCount := len(fileContent)
commitLinkBuffer := new(bytes.Buffer)
err = html.Render(commitLinkBuffer, createLink(node.Data[m[0]:m[5]], commitSha[0:7], "text black"))
@@ -97,11 +96,6 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
if len(lineSpecs) == 1 {
startLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
endLine = startLine
- // if line < 1 || line > lineCount {
- // return nil
- // }
-
- // preview.fileContent = fileContent[line-1 : line]
preview.subTitle = locale.Tr(
"markup.filepreview.line", startLine,
template.HTML(commitLinkBuffer.String()),
@@ -111,12 +105,6 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
} else {
startLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[0], "L"))
endLine, _ = strconv.Atoi(strings.TrimPrefix(lineSpecs[1], "L"))
-
- // if startLine < 1 || endLine < 1 || startLine > lineCount || endLine > lineCount || endLine < startLine {
- // return nil
- // }
-
- // preview.fileContent = fileContent[startLine-1 : endLine]
preview.subTitle = locale.Tr(
"markup.filepreview.lines", startLine, endLine,
template.HTML(commitLinkBuffer.String()),
@@ -125,7 +113,7 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
preview.lineOffset = startLine - 1
}
- lineCount := endLine - (startLine-1)
+ lineCount := endLine - (startLine - 1)
if startLine < 1 || endLine < 1 || lineCount < 1 {
return nil
}
@@ -156,7 +144,7 @@ func NewFilePreview(ctx *RenderContext, node *html.Node, locale translation.Loca
for i := 0; i < lineCount; i++ {
buf, err := reader.ReadBytes('\n')
if err != nil {
- break;
+ break
}
lineBuffer.Write(buf)
}
@@ -316,7 +304,7 @@ func (p *FilePreview) CreateHTML(locale translation.Locale) *html.Node {
}
node.AppendChild(header)
- if (p.isTruncated) {
+ if p.isTruncated {
warning := &html.Node{
Type: html.ElementNode,
Data: atom.Div.String(),
diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go
index b08c9eb230..163cd5d688 100644
--- a/modules/markup/renderer.go
+++ b/modules/markup/renderer.go
@@ -32,7 +32,7 @@ const (
type ProcessorHelper struct {
IsUsernameMentionable func(ctx context.Context, username string) bool
- GetRepoFileBlob func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error)
+ GetRepoFileBlob func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error)
ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute
}
diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go
index 7466e962d2..ac751d0e62 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/processorhelper.go
@@ -86,25 +86,6 @@ func ProcessorHelper() *markup.ProcessorHelper {
}
return blob, nil
-
- /*dataRc, err := blob.DataAsync()
- if err != nil {
- return nil, err
- }
- defer dataRc.Close()
-
- buf, err := io.ReadAll(dataRc)
- if err != nil {
- log.Error("failed to completly read blob for %-v:%s. Error: %v", repo, filePath, err)
- }
-
- fileContent, _, err := highlight.File(blob.Name(), language, buf)
- if err != nil {
- log.Error("highlight.File failed, fallback to plain text: %v", err)
- fileContent = highlight.PlainText(buf)
- }
-
- return fileContent, nil*/
},
}
}
From 5785ae72c75ea66cdadfc260d59084e0bb0bf0bb Mon Sep 17 00:00:00 2001
From: oliverpool
Date: Wed, 27 Mar 2024 22:02:51 +0100
Subject: [PATCH 019/822] [TESTS] prevent overriding testlogger when calling
mainApp
---
modules/testlogger/testlogger.go | 5 +++
tests/integration/cmd_forgejo_actions_test.go | 32 +++++++++-------
tests/integration/cmd_forgejo_test.go | 36 ------------------
tests/integration/cmd_keys_test.go | 27 +++++++------
tests/integration/integration_test.go | 38 +++++++++++++++++++
5 files changed, 75 insertions(+), 63 deletions(-)
delete mode 100644 tests/integration/cmd_forgejo_test.go
diff --git a/modules/testlogger/testlogger.go b/modules/testlogger/testlogger.go
index c5ca906220..43fbaf0afd 100644
--- a/modules/testlogger/testlogger.go
+++ b/modules/testlogger/testlogger.go
@@ -128,6 +128,11 @@ func (w *testLoggerWriterCloser) recordError(msg string) {
err = w.errs[len(w.errs)-1]
}
+ if len(w.t) > 0 {
+ // format error message to easily add it to the ignore list
+ msg = fmt.Sprintf("// %s\n\t`%s`,", w.t[len(w.t)-1].Name(), msg)
+ }
+
err = errors.Join(err, errors.New(msg))
if len(w.errs) > 0 {
diff --git a/tests/integration/cmd_forgejo_actions_test.go b/tests/integration/cmd_forgejo_actions_test.go
index 44211007f5..e45526ac7a 100644
--- a/tests/integration/cmd_forgejo_actions_test.go
+++ b/tests/integration/cmd_forgejo_actions_test.go
@@ -4,8 +4,11 @@ package integration
import (
gocontext "context"
+ "errors"
+ "io"
"net/url"
"os"
+ "os/exec"
"strings"
"testing"
@@ -19,16 +22,18 @@ import (
func Test_CmdForgejo_Actions(t *testing.T) {
onGiteaRun(t, func(*testing.T, *url.URL) {
- token, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-runner-token"})
+ token, err := runMainApp("forgejo-cli", "actions", "generate-runner-token")
assert.NoError(t, err)
assert.EqualValues(t, 40, len(token))
- secret, err := cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "generate-secret"})
+ secret, err := runMainApp("forgejo-cli", "actions", "generate-secret")
assert.NoError(t, err)
assert.EqualValues(t, 40, len(secret))
- _, err = cmdForgejoCaptureOutput(t, []string{"forgejo", "forgejo-cli", "actions", "register"})
- assert.ErrorContains(t, err, "at least one of the --secret")
+ _, err = runMainApp("forgejo-cli", "actions", "register")
+ var exitErr *exec.ExitError
+ assert.True(t, errors.As(err, &exitErr))
+ assert.Contains(t, string(exitErr.Stderr), "at least one of the --secret")
for _, testCase := range []struct {
testName string
@@ -62,10 +67,12 @@ func Test_CmdForgejo_Actions(t *testing.T) {
},
} {
t.Run(testCase.testName, func(t *testing.T) {
- cmd := []string{"forgejo", "forgejo-cli", "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope}
- output, err := cmdForgejoCaptureOutput(t, cmd)
- assert.ErrorContains(t, err, testCase.errorMessage)
+ output, err := runMainApp("forgejo-cli", "actions", "register", "--secret", testCase.secret, "--scope", testCase.scope)
assert.EqualValues(t, "", output)
+
+ var exitErr *exec.ExitError
+ assert.True(t, errors.As(err, &exitErr))
+ assert.Contains(t, string(exitErr.Stderr), testCase.errorMessage)
})
}
@@ -75,7 +82,7 @@ func Test_CmdForgejo_Actions(t *testing.T) {
for _, testCase := range []struct {
testName string
secretOption func() string
- stdin []string
+ stdin io.Reader
}{
{
testName: "secret from argument",
@@ -88,7 +95,7 @@ func Test_CmdForgejo_Actions(t *testing.T) {
secretOption: func() string {
return "--secret-stdin"
},
- stdin: []string{secret},
+ stdin: strings.NewReader(secret),
},
{
testName: "secret from file",
@@ -100,8 +107,7 @@ func Test_CmdForgejo_Actions(t *testing.T) {
},
} {
t.Run(testCase.testName, func(t *testing.T) {
- cmd := []string{"forgejo", "forgejo-cli", "actions", "register", testCase.secretOption(), "--scope=org26"}
- uuid, err := cmdForgejoCaptureOutput(t, cmd, testCase.stdin...)
+ uuid, err := runMainAppWithStdin(testCase.stdin, "forgejo-cli", "actions", "register", testCase.secretOption(), "--scope=org26")
assert.NoError(t, err)
assert.EqualValues(t, expecteduuid, uuid)
})
@@ -161,7 +167,7 @@ func Test_CmdForgejo_Actions(t *testing.T) {
} {
t.Run(testCase.testName, func(t *testing.T) {
cmd := []string{
- "forgejo", "forgejo-cli", "actions", "register",
+ "actions", "register",
"--secret", testCase.secret, "--scope", testCase.scope,
}
if testCase.name != "" {
@@ -177,7 +183,7 @@ func Test_CmdForgejo_Actions(t *testing.T) {
// Run twice to verify it is idempotent
//
for i := 0; i < 2; i++ {
- uuid, err := cmdForgejoCaptureOutput(t, cmd)
+ uuid, err := runMainApp("forgejo-cli", cmd...)
assert.NoError(t, err)
if assert.EqualValues(t, testCase.uuid, uuid) {
ownerName, repoName, found := strings.Cut(testCase.scope, "/")
diff --git a/tests/integration/cmd_forgejo_test.go b/tests/integration/cmd_forgejo_test.go
deleted file mode 100644
index 76f5a6fc08..0000000000
--- a/tests/integration/cmd_forgejo_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: MIT
-
-package integration
-
-import (
- "bytes"
- "context"
- "strings"
- "testing"
-
- "code.gitea.io/gitea/cmd/forgejo"
-
- "github.com/urfave/cli/v2"
-)
-
-func cmdForgejoCaptureOutput(t *testing.T, args []string, stdin ...string) (string, error) {
- buf := new(bytes.Buffer)
-
- app := cli.NewApp()
- app.Writer = buf
- app.ErrWriter = buf
- ctx := context.Background()
- ctx = forgejo.ContextSetNoInit(ctx, true)
- ctx = forgejo.ContextSetNoExit(ctx, true)
- ctx = forgejo.ContextSetStdout(ctx, buf)
- ctx = forgejo.ContextSetStderr(ctx, buf)
- if len(stdin) > 0 {
- ctx = forgejo.ContextSetStdin(ctx, strings.NewReader(strings.Join(stdin, "")))
- }
- app.Commands = []*cli.Command{
- forgejo.CmdForgejo(ctx),
- }
- err := app.Run(args)
-
- return buf.String(), err
-}
diff --git a/tests/integration/cmd_keys_test.go b/tests/integration/cmd_keys_test.go
index 61f11c58b0..a3220c13ce 100644
--- a/tests/integration/cmd_keys_test.go
+++ b/tests/integration/cmd_keys_test.go
@@ -4,16 +4,15 @@
package integration
import (
- "bytes"
+ "errors"
"net/url"
+ "os/exec"
"testing"
- "code.gitea.io/gitea/cmd"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
- "github.com/urfave/cli/v2"
)
func Test_CmdKeys(t *testing.T) {
@@ -24,30 +23,30 @@ func Test_CmdKeys(t *testing.T) {
wantErr bool
expectedOutput string
}{
- {"test_empty_1", []string{"keys", "--username=git", "--type=test", "--content=test"}, true, ""},
- {"test_empty_2", []string{"keys", "-e", "git", "-u", "git", "-t", "test", "-k", "test"}, true, ""},
+ {"test_empty_1", []string{"--username=git", "--type=test", "--content=test"}, true, ""},
+ {"test_empty_2", []string{"-e", "git", "-u", "git", "-t", "test", "-k", "test"}, true, ""},
{
"with_key",
- []string{"keys", "-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="},
+ []string{"-e", "git", "-u", "git", "-t", "ssh-rsa", "-k", "AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM="},
false,
"# gitea public key\ncommand=\"" + setting.AppPath + " --config=" + util.ShellEscape(setting.CustomConf) + " serv key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,no-user-rc,restrict ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDWVj0fQ5N8wNc0LVNA41wDLYJ89ZIbejrPfg/avyj3u/ZohAKsQclxG4Ju0VirduBFF9EOiuxoiFBRr3xRpqzpsZtnMPkWVWb+akZwBFAx8p+jKdy4QXR/SZqbVobrGwip2UjSrri1CtBxpJikojRIZfCnDaMOyd9Jp6KkujvniFzUWdLmCPxUE9zhTaPu0JsEP7MW0m6yx7ZUhHyfss+NtqmFTaDO+QlMR7L2QkDliN2Jl3Xa3PhuWnKJfWhdAq1Cw4oraKUOmIgXLkuiuxVQ6mD3AiFupkmfqdHq6h+uHHmyQqv3gU+/sD8GbGAhf6ftqhTsXjnv1Aj4R8NoDf9BS6KRkzkeun5UisSzgtfQzjOMEiJtmrep2ZQrMGahrXa+q4VKr0aKJfm+KlLfwm/JztfsBcqQWNcTURiCFqz+fgZw0Ey/de0eyMzldYTdXXNRYCKjs9bvBK+6SSXRM7AhftfQ0ZuoW5+gtinPrnmoOaSCEJbAiEiTO/BzOHgowiM= user2@localhost\n",
},
- {"invalid", []string{"keys", "--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"},
+ {"invalid", []string{"--not-a-flag=git"}, true, "Incorrect Usage: flag provided but not defined: -not-a-flag\n\n"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- out := new(bytes.Buffer)
- app := cli.NewApp()
- app.Writer = out
- app.Commands = []*cli.Command{cmd.CmdKeys}
- cmd.CmdKeys.HideHelp = true
- err := app.Run(append([]string{"prog"}, tt.args...))
+ out, err := runMainApp("keys", tt.args...)
+
+ var exitErr *exec.ExitError
+ if errors.As(err, &exitErr) {
+ t.Log(string(exitErr.Stderr))
+ }
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
- assert.Equal(t, tt.expectedOutput, out.String())
+ assert.Equal(t, tt.expectedOutput, out)
})
}
})
diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go
index e8f28105c1..b087281ff4 100644
--- a/tests/integration/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -17,6 +17,7 @@ import (
"net/http/httptest"
"net/url"
"os"
+ "os/exec"
"path/filepath"
"strconv"
"strings"
@@ -24,6 +25,7 @@ import (
"testing"
"time"
+ "code.gitea.io/gitea/cmd"
"code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
@@ -93,7 +95,43 @@ func NewNilResponseHashSumRecorder() *NilResponseHashSumRecorder {
}
}
+// runMainApp runs the subcommand and returns its standard output. Any returned error will usually be of type *ExitError. If c.Stderr was nil, Output populates ExitError.Stderr.
+func runMainApp(subcommand string, args ...string) (string, error) {
+ return runMainAppWithStdin(nil, subcommand, args...)
+}
+
+// runMainAppWithStdin runs the subcommand and returns its standard output. Any returned error will usually be of type *ExitError. If c.Stderr was nil, Output populates ExitError.Stderr.
+func runMainAppWithStdin(stdin io.Reader, subcommand string, args ...string) (string, error) {
+ // running the main app directly will very likely mess with the testing setup (logger & co.)
+ // hence we run it as a subprocess and capture its output
+ args = append([]string{subcommand}, args...)
+ cmd := exec.Command(os.Args[0], args...)
+ cmd.Env = append(os.Environ(),
+ "GITEA_TEST_CLI=true",
+ "GITEA_CONF="+setting.CustomConf,
+ "GITEA_WORK_DIR="+setting.AppWorkPath)
+ cmd.Stdin = stdin
+ out, err := cmd.Output()
+ return string(out), err
+}
+
func TestMain(m *testing.M) {
+ // GITEA_TEST_CLI is set by runMainAppWithStdin
+ // inspired by https://abhinavg.net/2022/05/15/hijack-testmain/
+ if testCLI := os.Getenv("GITEA_TEST_CLI"); testCLI == "true" {
+ app := cmd.NewMainApp("test-version", "integration-test")
+ args := append([]string{
+ "executable-name", // unused, but expected at position 1
+ "--config", os.Getenv("GITEA_CONF"),
+ },
+ os.Args[1:]..., // skip the executable name
+ )
+ if err := cmd.RunMainApp(app, args...); err != nil {
+ panic(err) // should never happen since RunMainApp exits on error
+ }
+ return
+ }
+
defer log.GetManager().Close()
managerCtx, cancel := context.WithCancel(context.Background())
From 16a8658878a2656cb131453b728b65a89271f11f Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Thu, 28 Mar 2024 04:20:13 +0100
Subject: [PATCH 020/822] Update test
---
modules/markup/html_test.go | 40 ++++++++++++------
.../markup/tests/repo/repo1_filepreview/HEAD | 1 +
.../tests/repo/repo1_filepreview/config | 6 +++
.../tests/repo/repo1_filepreview/description | 1 +
.../tests/repo/repo1_filepreview/info/exclude | 6 +++
.../19/0d9492934af498c3f669d6a2431dc5459e5b20 | Bin 0 -> 120 bytes
.../4b/825dc642cb6eb9a060e54bf8d69288fbee4904 | Bin 0 -> 15 bytes
.../83/57a737d04385bb7f2ab59ff184be94756e7972 | Bin 0 -> 44 bytes
.../84/22d40f12717e1ebd5cef2449f6c09d1f775969 | Bin 0 -> 23 bytes
.../d4/490327def9658be036d6a52c4417d84e74dd4c | Bin 0 -> 46 bytes
.../ee/2b1253d9cf407796e2e724926cbe3a974b214d | 1 +
.../repo/repo1_filepreview/refs/heads/master | 1 +
12 files changed, 43 insertions(+), 13 deletions(-)
create mode 100644 modules/markup/tests/repo/repo1_filepreview/HEAD
create mode 100644 modules/markup/tests/repo/repo1_filepreview/config
create mode 100644 modules/markup/tests/repo/repo1_filepreview/description
create mode 100644 modules/markup/tests/repo/repo1_filepreview/info/exclude
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/19/0d9492934af498c3f669d6a2431dc5459e5b20
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/83/57a737d04385bb7f2ab59ff184be94756e7972
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/84/22d40f12717e1ebd5cef2449f6c09d1f775969
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/d4/490327def9658be036d6a52c4417d84e74dd4c
create mode 100644 modules/markup/tests/repo/repo1_filepreview/objects/ee/2b1253d9cf407796e2e724926cbe3a974b214d
create mode 100644 modules/markup/tests/repo/repo1_filepreview/refs/heads/master
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index c43f006266..3583894bae 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -5,7 +5,6 @@ package markup_test
import (
"context"
- "html/template"
"io"
"os"
"strings"
@@ -14,14 +13,15 @@ import (
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/emoji"
"code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
var localMetas = map[string]string{
@@ -677,16 +677,30 @@ func TestIssue18471(t *testing.T) {
}
func TestRender_FilePreview(t *testing.T) {
+ setting.StaticRootPath = "../../"
+ setting.Names = []string{"english"}
+ setting.Langs = []string{"en-US"}
+ translation.InitLocales(context.Background())
+
setting.AppURL = markup.TestAppURL
markup.Init(&markup.ProcessorHelper{
- GetRepoFileContent: func(ctx context.Context, ownerName, repoName, commitSha, filePath string) ([]template.HTML, error) {
- buf := []byte("A\nB\nC\nD\n")
- return highlight.PlainText(buf), nil
+ GetRepoFileBlob: func(ctx context.Context, ownerName, repoName, commitSha, filePath string, language *string) (*git.Blob, error) {
+ gitRepo, err := git.OpenRepository(git.DefaultContext, "./tests/repo/repo1_filepreview")
+ require.NoError(t, err)
+ defer gitRepo.Close()
+
+ commit, err := gitRepo.GetCommit("HEAD")
+ require.NoError(t, err)
+
+ blob, err := commit.GetBlobByPath("path/to/file.go")
+ require.NoError(t, err)
+
+ return blob, nil
},
})
- sha := "b6dd6210eaebc915fd5be5579c58cce4da2e2579"
- commitFilePreview := util.URLJoin(markup.TestRepoURL, "src", "commit", sha, "path", "to", "file.go") + "#L1-L2"
+ sha := "190d9492934af498c3f669d6a2431dc5459e5b20"
+ commitFilePreview := util.URLJoin(markup.TestRepoURL, "src", "commit", sha, "path", "to", "file.go") + "#L2-L3"
test := func(input, expected string) {
buffer, err := markup.RenderString(&markup.RenderContext{
@@ -703,21 +717,21 @@ func TestRender_FilePreview(t *testing.T) {
``+
``+
``+
`
`+
`
`+
``+
``+
- ` | `+
- `A`+"\n"+` | `+
+ ` | `+
+ `B`+"\n"+` | `+
`
`+
``+
- ` | `+
- `B`+"\n"+` | `+
+ ` | `+
+ `C`+"\n"+` | `+
`
`+
``+
`
`+
diff --git a/modules/markup/tests/repo/repo1_filepreview/HEAD b/modules/markup/tests/repo/repo1_filepreview/HEAD
new file mode 100644
index 0000000000..cb089cd89a
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/modules/markup/tests/repo/repo1_filepreview/config b/modules/markup/tests/repo/repo1_filepreview/config
new file mode 100644
index 0000000000..42cc799c8d
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/config
@@ -0,0 +1,6 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
+[remote "origin"]
+ url = /home/mai/projects/codeark/forgejo/forgejo/modules/markup/tests/repo/repo1_filepreview/../../__test_repo
diff --git a/modules/markup/tests/repo/repo1_filepreview/description b/modules/markup/tests/repo/repo1_filepreview/description
new file mode 100644
index 0000000000..498b267a8c
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/modules/markup/tests/repo/repo1_filepreview/info/exclude b/modules/markup/tests/repo/repo1_filepreview/info/exclude
new file mode 100644
index 0000000000..a5196d1be8
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/modules/markup/tests/repo/repo1_filepreview/objects/19/0d9492934af498c3f669d6a2431dc5459e5b20 b/modules/markup/tests/repo/repo1_filepreview/objects/19/0d9492934af498c3f669d6a2431dc5459e5b20
new file mode 100644
index 0000000000000000000000000000000000000000..161d0bafc6731f5fe0b3b3c29ffe5463b056e840
GIT binary patch
literal 120
zcmV-;0Ehp00hNtO4#F@D06FIsz9S(!b&^)95RZTdgxH8kluC)q`&oX#X-+d!)@7*%
z6w=O`DhTt0gHNKjDTeW?I7Ep#_`*y{M%Kh4TwLDlzBagYZ3Of7#i>`*Lw&yTqskE|
a(I?AD9`;CxuKZr6|5@&=-P{|T!ZCX0g*&(a
literal 0
HcmV?d00001
diff --git a/modules/markup/tests/repo/repo1_filepreview/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/modules/markup/tests/repo/repo1_filepreview/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
new file mode 100644
index 0000000000000000000000000000000000000000..adf64119a33d7621aeeaa505d30adb58afaa5559
GIT binary patch
literal 15
Wcmb
)%hIiUR!8gx4luvu~TxC+uKC9{8ioO8p9WH2!R0)>Lak_?9C@a5(goLhI-Yi*tXv1Q+s(!9zd00ff{
EldH%Sg8%>k
literal 0
HcmV?d00001
diff --git a/modules/markup/tests/repo/repo1_filepreview/objects/ee/2b1253d9cf407796e2e724926cbe3a974b214d b/modules/markup/tests/repo/repo1_filepreview/objects/ee/2b1253d9cf407796e2e724926cbe3a974b214d
new file mode 100644
index 0000000000..e13ca647db
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/objects/ee/2b1253d9cf407796e2e724926cbe3a974b214d
@@ -0,0 +1 @@
+x+)JMU06e040031QHหฬIีKฯghQบย/TX'ท7ๆฝ็ทsๅห#3๔
\ No newline at end of file
diff --git a/modules/markup/tests/repo/repo1_filepreview/refs/heads/master b/modules/markup/tests/repo/repo1_filepreview/refs/heads/master
new file mode 100644
index 0000000000..49c348b41c
--- /dev/null
+++ b/modules/markup/tests/repo/repo1_filepreview/refs/heads/master
@@ -0,0 +1 @@
+190d9492934af498c3f669d6a2431dc5459e5b20
From 6e98bacbbd3c089b2ccfa725c58184f4dfe5e7fe Mon Sep 17 00:00:00 2001
From: Mai-Lapyst
Date: Thu, 28 Mar 2024 05:42:25 +0100
Subject: [PATCH 021/822] Format code
---
modules/markup/html_test.go | 2 +-
modules/markup/renderer.go | 1 -
services/markup/processorhelper.go | 4 ----
3 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index 3583894bae..1ecf519f46 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -688,7 +688,7 @@ func TestRender_FilePreview(t *testing.T) {
gitRepo, err := git.OpenRepository(git.DefaultContext, "./tests/repo/repo1_filepreview")
require.NoError(t, err)
defer gitRepo.Close()
-
+
commit, err := gitRepo.GetCommit("HEAD")
require.NoError(t, err)
diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go
index 163cd5d688..6781d2e552 100644
--- a/modules/markup/renderer.go
+++ b/modules/markup/renderer.go
@@ -8,7 +8,6 @@ import (
"context"
"errors"
"fmt"
- // "html/template"
"io"
"net/url"
"path/filepath"
diff --git a/services/markup/processorhelper.go b/services/markup/processorhelper.go
index ac751d0e62..40bf1d65da 100644
--- a/services/markup/processorhelper.go
+++ b/services/markup/processorhelper.go
@@ -7,16 +7,12 @@ import (
"context"
"fmt"
- // "html/template"
- // "io"
-
"code.gitea.io/gitea/models/perm/access"
"code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
- // "code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
gitea_context "code.gitea.io/gitea/services/context"
From cbd067e759b1de054da17c18f92fc934c10eacf8 Mon Sep 17 00:00:00 2001
From: 0ko <0ko@noreply.codeberg.org>
Date: Thu, 28 Mar 2024 19:48:56 +0500
Subject: [PATCH 022/822] Fix accessibility and translatability of repo explore
counters
Progression of: https://codeberg.org/forgejo/forgejo/commit/9e69ef9c51cded6321e4cca39d33a64e9801d910
Regression of: https://codeberg.org/forgejo/forgejo/commit/65e190ae8bd6c72d8701a58d67b256c87b92c189#diff-8d94e33cfe70fa6443d059b9c34e3f8064514816
---
templates/explore/repo_list.tmpl | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/templates/explore/repo_list.tmpl b/templates/explore/repo_list.tmpl
index 9e5042d650..99c9bc1736 100644
--- a/templates/explore/repo_list.tmpl
+++ b/templates/explore/repo_list.tmpl
@@ -38,15 +38,15 @@
{{end}}
{{if not $.DisableStars}}
-
- {{svg "octicon-star" 16}}
- {{CountFmt .NumStars}}
+
+ {{svg "octicon-star" 16}}
+ {{if ge .NumStars 1000}}data-tooltip-content="{{.NumStars}}"{{end}}{{CountFmt .NumStars}}
{{end}}
{{if not $.DisableForks}}
-
- {{svg "octicon-git-branch" 16}}
- {{CountFmt .NumForks}}
+
+ {{svg "octicon-git-branch" 16}}
+ {{if ge .NumForks 1000}}data-tooltip-content="{{.NumForks}}"{{end}}{{CountFmt .NumForks}}
{{end}}
From 869795a530f6a5a4e28687c003300d39fbaee6e2 Mon Sep 17 00:00:00 2001
From: Earl Warren
Date: Thu, 28 Mar 2024 15:45:51 +0100
Subject: [PATCH 023/822] [RELEASE] GITEA_VERSION is a fallback for
FORGEJO_VERSION
Existing Forgejo packages may rely on setting GITEA_VERSION to specify
the version to build if:
* they do not build from the git repository with the proper tag
* they build from a source tarbal that does not have a VERSION file
With 7.0 the logic of setting the version was modified in the
`[RELEASE] Gitea version is for interoperability only` commit and
ignores this variable which creates an unecessary breaking change.
If GITEA_VERSION is set, the versions will be set on 7.0 exactly as
they would have with version before and included 1.21.
* If GITEA_VERSION is not set, all versions are the same
* If GITEA_VERSION is set, there is a distinction between the version
set in the binary are returned by the Gitea API and the
version returned by the Forgejo API which includes metadata.
Before:
$ make GITEA_VERSION=7.0.0 show-version-full
7.0.0-dev-1809-cd6fa771ab+gitea-1.22.0
$ make GITEA_VERSION=7.0.0 show-version-api
7.0.0-dev-1809-cd6fa771ab+gitea-1.22.0
After:
$ make GITEA_VERSION=7.0.0 show-version-full
7.0.0
$ make GITEA_VERSION=7.0.0 show-version-api
7.0.0+gitea-1.22.0
---
Makefile | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
index b1c4864c7a..16d7edb2dd 100644
--- a/Makefile
+++ b/Makefile
@@ -88,8 +88,13 @@ STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null)
ifneq ($(STORED_VERSION),)
FORGEJO_VERSION ?= $(STORED_VERSION)
else
- # drop the "g" prefix prepended by git describe to the commit hash
- FORGEJO_VERSION ?= $(shell git describe --exclude '*-test' --tags --always | sed 's/^v//' | sed 's/\-g/-/')+${GITEA_COMPATIBILITY}
+ ifneq ($(GITEA_VERSION),)
+ FORGEJO_VERSION ?= $(GITEA_VERSION)
+ FORGEJO_VERSION_API ?= $(GITEA_VERSION)+${GITEA_COMPATIBILITY}
+ else
+ # drop the "g" prefix prepended by git describe to the commit hash
+ FORGEJO_VERSION ?= $(shell git describe --exclude '*-test' --tags --always | sed 's/^v//' | sed 's/\-g/-/')+${GITEA_COMPATIBILITY}
+ endif
endif
FORGEJO_VERSION_MAJOR=$(shell echo $(FORGEJO_VERSION) | sed -e 's/\..*//')
FORGEJO_VERSION_MINOR=$(shell echo $(FORGEJO_VERSION) | sed -E -e 's/^([0-9]+\.[0-9]+).*/\1/')
@@ -106,7 +111,12 @@ show-version-minor:
RELEASE_VERSION ?= ${FORGEJO_VERSION}
VERSION ?= ${RELEASE_VERSION}
-LDFLAGS := $(LDFLAGS) -X "main.ReleaseVersion=$(RELEASE_VERSION)" -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(FORGEJO_VERSION)" -X "main.Tags=$(TAGS)" -X "main.ForgejoVersion=$(FORGEJO_VERSION)"
+FORGEJO_VERSION_API ?= ${FORGEJO_VERSION}
+
+show-version-api:
+ @echo ${FORGEJO_VERSION_API}
+
+LDFLAGS := $(LDFLAGS) -X "main.ReleaseVersion=$(RELEASE_VERSION)" -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(FORGEJO_VERSION)" -X "main.Tags=$(TAGS)" -X "main.ForgejoVersion=$(FORGEJO_VERSION_API)"
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
From 79b70893601c33a33d8d44eb0421797dfd846a47 Mon Sep 17 00:00:00 2001
From: Gusted
Date: Thu, 28 Mar 2024 21:41:52 +0100
Subject: [PATCH 024/822] [FEAT] Configure if protected branch rule should
apply to admins
- Currently protected branch rules do not apply to admins, however in
some cases (like in the case of Forgejo project) you might also want to
apply these rules to admins to avoid accidental merges.
- Add new option to configure this on a per-rule basis.
- Adds integration tests.
- Resolves #65
---
models/forgejo_migrations/migrate.go | 2 +
models/forgejo_migrations/v1_22/v9.go | 15 ++++
models/git/protected_branch.go | 1 +
modules/structs/repo_branch.go | 3 +
options/locale/locale_en-US.ini | 3 +
routers/api/v1/repo/branch.go | 5 ++
routers/private/hook_pre_receive.go | 16 ++--
routers/web/repo/setting/protected_branch.go | 1 +
services/convert/convert.go | 1 +
services/forms/repo_form.go | 1 +
services/pull/check.go | 7 +-
services/pull/merge.go | 29 ++++---
templates/repo/issue/view_content/pull.tmpl | 2 +-
templates/repo/settings/protected_branch.tmpl | 8 ++
templates/swagger/v1_json.tmpl | 12 +++
tests/integration/proctected_branch_test.go | 87 +++++++++++++++++++
16 files changed, 167 insertions(+), 26 deletions(-)
create mode 100644 models/forgejo_migrations/v1_22/v9.go
create mode 100644 tests/integration/proctected_branch_test.go
diff --git a/models/forgejo_migrations/migrate.go b/models/forgejo_migrations/migrate.go
index c2ffda5eb7..965b748ac9 100644
--- a/models/forgejo_migrations/migrate.go
+++ b/models/forgejo_migrations/migrate.go
@@ -54,6 +54,8 @@ var migrations = []*Migration{
NewMigration("Add the `enable_repo_unit_hints` column to the `user` table", forgejo_v1_22.AddUserRepoUnitHintsSetting),
// v7 -> v8
NewMigration("Modify the `release`.`note` content to remove SSH signatures", forgejo_v1_22.RemoveSSHSignaturesFromReleaseNotes),
+ // v8 -> v9
+ NewMigration("Add the `apply_to_admins` column to the `protected_branch` table", forgejo_v1_22.AddApplyToAdminsSetting),
}
// GetCurrentDBVersion returns the current Forgejo database version.
diff --git a/models/forgejo_migrations/v1_22/v9.go b/models/forgejo_migrations/v1_22/v9.go
new file mode 100644
index 0000000000..34c2844c39
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v9.go
@@ -0,0 +1,15 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import "xorm.io/xorm"
+
+func AddApplyToAdminsSetting(x *xorm.Engine) error {
+ type ProtectedBranch struct {
+ ID int64 `xorm:"pk autoincr"`
+ ApplyToAdmins bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ return x.Sync(&ProtectedBranch{})
+}
diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go
index e0ff4d1542..a8b8c81bbe 100644
--- a/models/git/protected_branch.go
+++ b/models/git/protected_branch.go
@@ -58,6 +58,7 @@ type ProtectedBranch struct {
RequireSignedCommits bool `xorm:"NOT NULL DEFAULT false"`
ProtectedFilePatterns string `xorm:"TEXT"`
UnprotectedFilePatterns string `xorm:"TEXT"`
+ ApplyToAdmins bool `xorm:"NOT NULL DEFAULT false"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go
index e96d276b29..0b3b0bb030 100644
--- a/modules/structs/repo_branch.go
+++ b/modules/structs/repo_branch.go
@@ -47,6 +47,7 @@ type BranchProtection struct {
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
+ ApplyToAdmins bool `json:"apply_to_admins"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
@@ -80,6 +81,7 @@ type CreateBranchProtectionOption struct {
RequireSignedCommits bool `json:"require_signed_commits"`
ProtectedFilePatterns string `json:"protected_file_patterns"`
UnprotectedFilePatterns string `json:"unprotected_file_patterns"`
+ ApplyToAdmins bool `json:"apply_to_admins"`
}
// EditBranchProtectionOption options for editing a branch protection
@@ -106,4 +108,5 @@ type EditBranchProtectionOption struct {
RequireSignedCommits *bool `json:"require_signed_commits"`
ProtectedFilePatterns *string `json:"protected_file_patterns"`
UnprotectedFilePatterns *string `json:"unprotected_file_patterns"`
+ ApplyToAdmins *bool `json:"apply_to_admins"`
}
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 17a8180ec9..5042e5467e 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2348,6 +2348,7 @@ settings.event_pull_request_review_request = Pull request review requested
settings.event_pull_request_review_request_desc = Pull request review requested or review request removed.
settings.event_pull_request_approvals = Pull request approvals
settings.event_pull_request_merge = Pull request merge
+settings.event_pull_request_enforcement = Enforcement
settings.event_package = Package
settings.event_package_desc = Package created or deleted in a repository.
settings.branch_filter = Branch filter
@@ -2462,6 +2463,8 @@ settings.block_on_official_review_requests = Block merge on official review requ
settings.block_on_official_review_requests_desc = Merging will not be possible when it has official review requests, even if there are enough approvals.
settings.block_outdated_branch = Block merge if pull request is outdated
settings.block_outdated_branch_desc = Merging will not be possible when head branch is behind base branch.
+settings.enforce_on_admins = Enforce this rule for repository admins
+settings.enforce_on_admins_desc = Repository admins cannot bypass this rule.
settings.default_branch_desc = Select a default repository branch for pull requests and code commits:
settings.merge_style_desc = Merge styles
settings.default_merge_style_desc = Default merge style
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 5e6b6a8658..c33beee0ae 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -621,6 +621,7 @@ func CreateBranchProtection(ctx *context.APIContext) {
ProtectedFilePatterns: form.ProtectedFilePatterns,
UnprotectedFilePatterns: form.UnprotectedFilePatterns,
BlockOnOutdatedBranch: form.BlockOnOutdatedBranch,
+ ApplyToAdmins: form.ApplyToAdmins,
}
err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
@@ -808,6 +809,10 @@ func EditBranchProtection(ctx *context.APIContext) {
protectBranch.BlockOnOutdatedBranch = *form.BlockOnOutdatedBranch
}
+ if form.ApplyToAdmins != nil {
+ protectBranch.ApplyToAdmins = *form.ApplyToAdmins
+ }
+
var whitelistUsers []int64
if form.PushWhitelistUsernames != nil {
whitelistUsers, err = user_model.GetUserIDsByNames(ctx, form.PushWhitelistUsernames, false)
diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go
index f45e57b9e3..0613492845 100644
--- a/routers/private/hook_pre_receive.go
+++ b/routers/private/hook_pre_receive.go
@@ -337,13 +337,9 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
return
}
- // If we're an admin for the repository we can ignore status checks, reviews and override protected files
- if ctx.userPerm.IsAdmin() {
- return
- }
-
- // Now if we're not an admin - we can't overwrite protected files so fail now
- if changedProtectedfiles {
+ // It's not allowed t overwrite protected files. Unless if the user is an
+ // admin and the protected branch rule doesn't apply to admins.
+ if changedProtectedfiles && (!ctx.user.IsAdmin || protectBranch.ApplyToAdmins) {
log.Warn("Forbidden: Branch: %s in %-v is protected from changing file %s", branchName, repo, protectedFilePath)
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("branch %s is protected from changing file %s", branchName, protectedFilePath),
@@ -352,8 +348,12 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
}
// Check all status checks and reviews are ok
- if err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil {
+ if pb, err := pull_service.CheckPullBranchProtections(ctx, pr, true); err != nil {
if models.IsErrDisallowedToMerge(err) {
+ // Allow this if the rule doesn't apply to admins and the user is an admin.
+ if ctx.user.IsAdmin && !pb.ApplyToAdmins {
+ return
+ }
log.Warn("Forbidden: User %d is not allowed push to protected branch %s in %-v and pr #%d is not ready to be merged: %s", ctx.opts.UserID, branchName, repo, pr.Index, err.Error())
ctx.JSON(http.StatusForbidden, private.Response{
UserMsg: fmt.Sprintf("Not allowed to push to protected branch %s and pr #%d is not ready to be merged: %s", branchName, ctx.opts.PullRequestID, err.Error()),
diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go
index 7ee67e5925..25146779de 100644
--- a/routers/web/repo/setting/protected_branch.go
+++ b/routers/web/repo/setting/protected_branch.go
@@ -237,6 +237,7 @@ func SettingsProtectedBranchPost(ctx *context.Context) {
protectBranch.ProtectedFilePatterns = f.ProtectedFilePatterns
protectBranch.UnprotectedFilePatterns = f.UnprotectedFilePatterns
protectBranch.BlockOnOutdatedBranch = f.BlockOnOutdatedBranch
+ protectBranch.ApplyToAdmins = f.ApplyToAdmins
err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{
UserIDs: whitelistUsers,
diff --git a/services/convert/convert.go b/services/convert/convert.go
index ca3ec32a40..dd2239458e 100644
--- a/services/convert/convert.go
+++ b/services/convert/convert.go
@@ -162,6 +162,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch) *api
RequireSignedCommits: bp.RequireSignedCommits,
ProtectedFilePatterns: bp.ProtectedFilePatterns,
UnprotectedFilePatterns: bp.UnprotectedFilePatterns,
+ ApplyToAdmins: bp.ApplyToAdmins,
Created: bp.CreatedUnix.AsTime(),
Updated: bp.UpdatedUnix.AsTime(),
}
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index 0f7665804d..b5ff031f4b 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -219,6 +219,7 @@ type ProtectBranchForm struct {
RequireSignedCommits bool
ProtectedFilePatterns string
UnprotectedFilePatterns string
+ ApplyToAdmins bool
}
// Validate validates the fields
diff --git a/services/pull/check.go b/services/pull/check.go
index f4dd332b14..9aab3c94f3 100644
--- a/services/pull/check.go
+++ b/services/pull/check.go
@@ -104,7 +104,7 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
return ErrIsChecking
}
- if err := CheckPullBranchProtections(ctx, pr, false); err != nil {
+ if pb, err := CheckPullBranchProtections(ctx, pr, false); err != nil {
if !models.IsErrDisallowedToMerge(err) {
log.Error("Error whilst checking pull branch protection for %-v: %v", pr, err)
return err
@@ -117,8 +117,9 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
err = nil
}
- // * if the doer is admin, they could skip the branch protection check
- if adminSkipProtectionCheck {
+ // * if the doer is admin, they could skip the branch protection check,
+ // if that's allowed by the protected branch rule.
+ if adminSkipProtectionCheck && !pb.ApplyToAdmins {
if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
return errCheckAdmin
diff --git a/services/pull/merge.go b/services/pull/merge.go
index df8d66e2d4..7f79eca2aa 100644
--- a/services/pull/merge.go
+++ b/services/pull/merge.go
@@ -424,63 +424,64 @@ func IsUserAllowedToMerge(ctx context.Context, pr *issues_model.PullRequest, p a
return false, nil
}
-// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks)
-func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (err error) {
+// CheckPullBranchProtections checks whether the PR is ready to be merged (reviews and status checks).
+// Returns the protected branch rule when `ErrDisallowedToMerge` is returned as error.
+func CheckPullBranchProtections(ctx context.Context, pr *issues_model.PullRequest, skipProtectedFilesCheck bool) (protectedBranchRule *git_model.ProtectedBranch, err error) {
if err = pr.LoadBaseRepo(ctx); err != nil {
- return fmt.Errorf("LoadBaseRepo: %w", err)
+ return nil, fmt.Errorf("LoadBaseRepo: %w", err)
}
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
if err != nil {
- return fmt.Errorf("LoadProtectedBranch: %v", err)
+ return nil, fmt.Errorf("LoadProtectedBranch: %v", err)
}
if pb == nil {
- return nil
+ return nil, nil
}
isPass, err := IsPullCommitStatusPass(ctx, pr)
if err != nil {
- return err
+ return nil, err
}
if !isPass {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "Not all required status checks successful",
}
}
if !issues_model.HasEnoughApprovals(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "Does not have enough approvals",
}
}
if issues_model.MergeBlockedByRejectedReview(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "There are requested changes",
}
}
if issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pr) {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "There are official review requests",
}
}
if issues_model.MergeBlockedByOutdatedBranch(pb, pr) {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "The head branch is behind the base branch",
}
}
if skipProtectedFilesCheck {
- return nil
+ return nil, nil
}
if pb.MergeBlockedByProtectedFiles(pr.ChangedProtectedFiles) {
- return models.ErrDisallowedToMerge{
+ return pb, models.ErrDisallowedToMerge{
Reason: "Changed protected files",
}
}
- return nil
+ return nil, nil
}
// MergedManually mark pr as merged manually
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index 19f1d3f91d..08f666d210 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -158,7 +158,7 @@
{{$notAllOverridableChecksOk := or .IsBlockedByApprovals .IsBlockedByRejection .IsBlockedByOfficialReviewRequests .IsBlockedByOutdatedBranch .IsBlockedByChangedProtectedFiles (and .EnableStatusCheck (not .RequiredStatusCheckState.IsSuccess))}}
{{/* admin can merge without checks, writer can merge when checks succeed */}}
- {{$canMergeNow := and (or $.IsRepoAdmin (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
+ {{$canMergeNow := and (or (and $.IsRepoAdmin (not .ProtectedBranch.ApplyToAdmins)) (not $notAllOverridableChecksOk)) (or (not .AllowMerge) (not .RequireSigned) .WillSign)}}
{{/* admin and writer both can make an auto merge schedule */}}
{{if $canMergeNow}}
diff --git a/templates/repo/settings/protected_branch.tmpl b/templates/repo/settings/protected_branch.tmpl
index e95dd831c9..e1ee7b36f5 100644
--- a/templates/repo/settings/protected_branch.tmpl
+++ b/templates/repo/settings/protected_branch.tmpl
@@ -260,6 +260,14 @@
{{ctx.Locale.Tr "repo.settings.block_outdated_branch_desc"}}
+
+
+
+
+
+
{{ctx.Locale.Tr "repo.settings.enforce_on_admins_desc"}}
+
+
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index 6034a8fbce..ee1ed64eaf 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -17756,6 +17756,10 @@
"description": "BranchProtection represents a branch protection for a repository",
"type": "object",
"properties": {
+ "apply_to_admins": {
+ "type": "boolean",
+ "x-go-name": "ApplyToAdmins"
+ },
"approvals_whitelist_teams": {
"type": "array",
"items": {
@@ -18406,6 +18410,10 @@
"description": "CreateBranchProtectionOption options for creating a branch protection",
"type": "object",
"properties": {
+ "apply_to_admins": {
+ "type": "boolean",
+ "x-go-name": "ApplyToAdmins"
+ },
"approvals_whitelist_teams": {
"type": "array",
"items": {
@@ -19577,6 +19585,10 @@
"description": "EditBranchProtectionOption options for editing a branch protection",
"type": "object",
"properties": {
+ "apply_to_admins": {
+ "type": "boolean",
+ "x-go-name": "ApplyToAdmins"
+ },
"approvals_whitelist_teams": {
"type": "array",
"items": {
diff --git a/tests/integration/proctected_branch_test.go b/tests/integration/proctected_branch_test.go
new file mode 100644
index 0000000000..9c6e5e3cae
--- /dev/null
+++ b/tests/integration/proctected_branch_test.go
@@ -0,0 +1,87 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "testing"
+
+ git_model "code.gitea.io/gitea/models/git"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unittest"
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestProtectedBranch_AdminEnforcement(t *testing.T) {
+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
+ session := loginUser(t, "user1")
+ testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
+ testEditFileToNewBranch(t, session, "user1", "repo1", "master", "add-readme", "README.md", "WIP")
+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 1, Name: "repo1"})
+
+ req := NewRequestWithValues(t, "POST", "user1/repo1/compare/master...add-readme", map[string]string{
+ "_csrf": GetCSRF(t, session, "user1/repo1/compare/master...add-readme"),
+ "title": "pull request",
+ })
+ session.MakeRequest(t, req, http.StatusOK)
+
+ t.Run("No protected branch", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req = NewRequest(t, "GET", "/user1/repo1/pulls/1")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+
+ text := strings.TrimSpace(doc.doc.Find(".merge-section").Text())
+ assert.Contains(t, text, "This pull request can be merged automatically.")
+ assert.Contains(t, text, "'canMergeNow': true")
+ })
+
+ t.Run("Without admin enforcement", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ req := NewRequestWithValues(t, "POST", "/user1/repo1/settings/branches/edit", map[string]string{
+ "_csrf": GetCSRF(t, session, "/user1/repo1/settings/branches/edit"),
+ "rule_name": "master",
+ "required_approvals": "1",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ req = NewRequest(t, "GET", "/user1/repo1/pulls/1")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+
+ text := strings.TrimSpace(doc.doc.Find(".merge-section").Text())
+ assert.Contains(t, text, "This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.")
+ assert.Contains(t, text, "'canMergeNow': true")
+ })
+
+ t.Run("With admin enforcement", func(t *testing.T) {
+ defer tests.PrintCurrentTest(t)()
+
+ protectedBranch := unittest.AssertExistsAndLoadBean(t, &git_model.ProtectedBranch{RuleName: "master", RepoID: repo.ID})
+ req := NewRequestWithValues(t, "POST", "/user1/repo1/settings/branches/edit", map[string]string{
+ "_csrf": GetCSRF(t, session, "/user1/repo1/settings/branches/edit"),
+ "rule_name": "master",
+ "rule_id": strconv.FormatInt(protectedBranch.ID, 10),
+ "required_approvals": "1",
+ "apply_to_admins": "true",
+ })
+ session.MakeRequest(t, req, http.StatusSeeOther)
+
+ req = NewRequest(t, "GET", "/user1/repo1/pulls/1")
+ resp := session.MakeRequest(t, req, http.StatusOK)
+ doc := NewHTMLParser(t, resp.Body)
+
+ text := strings.TrimSpace(doc.doc.Find(".merge-section").Text())
+ assert.Contains(t, text, "This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.")
+ assert.Contains(t, text, "'canMergeNow': false")
+ })
+ })
+}
From 39b53ef56f5d0d0cef6ff5a9a1204b04eb7f05e7 Mon Sep 17 00:00:00 2001
From: 0ko <0ko@noreply.codeberg.org>
Date: Tue, 19 Mar 2024 16:27:01 +0500
Subject: [PATCH 025/822] Provide plural support for issue participants
---
options/locale/locale_ar.ini | 2 +-
options/locale/locale_bg.ini | 2 +-
options/locale/locale_cs-CZ.ini | 2 +-
options/locale/locale_de-DE.ini | 2 +-
options/locale/locale_el-GR.ini | 2 +-
options/locale/locale_en-US.ini | 3 ++-
options/locale/locale_es-ES.ini | 2 +-
options/locale/locale_fa-IR.ini | 2 +-
options/locale/locale_fi-FI.ini | 2 +-
options/locale/locale_fr-FR.ini | 3 ++-
options/locale/locale_hu-HU.ini | 2 +-
options/locale/locale_id-ID.ini | 2 +-
options/locale/locale_it-IT.ini | 2 +-
options/locale/locale_ja-JP.ini | 2 +-
options/locale/locale_ko-KR.ini | 2 +-
options/locale/locale_lv-LV.ini | 2 +-
options/locale/locale_nl-NL.ini | 2 +-
options/locale/locale_pl-PL.ini | 2 +-
options/locale/locale_pt-BR.ini | 2 +-
options/locale/locale_pt-PT.ini | 2 +-
options/locale/locale_ru-RU.ini | 3 ++-
options/locale/locale_si-LK.ini | 2 +-
options/locale/locale_sv-SE.ini | 2 +-
options/locale/locale_tr-TR.ini | 2 +-
options/locale/locale_uk-UA.ini | 2 +-
options/locale/locale_zh-CN.ini | 2 +-
options/locale/locale_zh-HK.ini | 2 +-
options/locale/locale_zh-TW.ini | 2 +-
templates/repo/issue/view_content/sidebar.tmpl | 2 +-
29 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/options/locale/locale_ar.ini b/options/locale/locale_ar.ini
index 38e18bec5a..4e0c617907 100644
--- a/options/locale/locale_ar.ini
+++ b/options/locale/locale_ar.ini
@@ -680,7 +680,7 @@ issues.self_assign_at = `ูููู ููุณู ุจูุง %s`
issues.label_deletion = ุงุญุฐู ุงูุชุตููู
issues.filter_milestone_all = ูู ุงูุฃูุฏุงู
issues.unlock.notice_2 = - ูู
ููู ุฏูู
ุง ุฅููุงู ูุฐู ุงูู
ุณุฃูุฉ ู
ู ุฌุฏูุฏ ูู ุงูู
ุณุชูุจู.
-issues.num_participants = %d ู
ุชุญุงูุฑ
+issues.num_participants_few = %d ู
ุชุญุงูุฑ
release.title = ุนููุงู ุงูุฅุตุฏุงุฑ
issues.closed_at = `ุฃุบูู ูุฐู ุงูู
ุณุฃูุฉ
%[2]s`
issues.lock.title = ุฅููุงู ุงูุชุญุงูุฑ ูู ูุฐู ุงูู
ุณุฃูุฉ.
diff --git a/options/locale/locale_bg.ini b/options/locale/locale_bg.ini
index 5b9bb0715e..cea90012b1 100644
--- a/options/locale/locale_bg.ini
+++ b/options/locale/locale_bg.ini
@@ -629,7 +629,7 @@ issues.filter_milestone_all = ะัะธัะบะธ ะตัะฐะฟะธ
issues.filter_milestone_open = ะัะฒะพัะตะฝะธ ะตัะฐะฟะธ
issues.filter_milestone_none = ะะตะท ะตัะฐะฟะธ
issues.filter_project = ะัะพะตะบั
-issues.num_participants = %d ััะฐััะฒะฐัะธ
+issues.num_participants_few = %d ััะฐััะฒะฐัะธ
issues.filter_assignee = ะะทะฟัะปะฝะธัะตะป
issues.filter_milestone_closed = ะะฐัะฒะพัะตะฝะธ ะตัะฐะฟะธ
issues.filter_assginee_no_select = ะัะธัะบะธ ะธะทะฟัะปะฝะธัะตะปะธ
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 3747ae28c9..03ee22944f 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -1603,7 +1603,7 @@ issues.label.filter_sort.alphabetically=Od zaฤรกtku abecedy
issues.label.filter_sort.reverse_alphabetically=Od konce abecedy
issues.label.filter_sort.by_size=Nejmenลกรญ velikost
issues.label.filter_sort.reverse_by_size=Nejvฤtลกรญ velikost
-issues.num_participants=%d รบฤastnรญkลฏ
+issues.num_participants_few=%d รบฤastnรญkลฏ
issues.attachment.open_tab=`Kliknฤte pro zobrazenรญ โ%sโ v novรฉ zรกloลพce`
issues.attachment.download=`Kliknฤte pro staลพenรญ โ%sโ`
issues.subscribe=Odebรญrat
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index f5aafdf5c9..1bdf6c4d0b 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -1596,7 +1596,7 @@ issues.label.filter_sort.alphabetically=Alphabetisch
issues.label.filter_sort.reverse_alphabetically=Umgekehrt alphabetisch
issues.label.filter_sort.by_size=Kleinste Grรถรe
issues.label.filter_sort.reverse_by_size=Grรถรte Grรถรe
-issues.num_participants=%d Beteiligte
+issues.num_participants_few=%d Beteiligte
issues.attachment.open_tab=`Klicken, um โ%sโ in einem neuen Tab zu รถffnen`
issues.attachment.download=`Klicken, um โ%sโ herunterzuladen`
issues.subscribe=Abonnieren
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 36b7518c62..17362a6036 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -1580,7 +1580,7 @@ issues.label.filter_sort.alphabetically=ฮฮปฯฮฑฮฒฮทฯฮนฮบฮฌ
issues.label.filter_sort.reverse_alphabetically=ฮฮฝฯฮฏฯฯฯฮฟฯฮฑ ฮฑฮปฯฮฑฮฒฮทฯฮนฮบฮฌ
issues.label.filter_sort.by_size=ฮฮนฮบฯฯฯฮตฯฮฟ ฮผฮญฮณฮตฮธฮฟฯ
issues.label.filter_sort.reverse_by_size=ฮฮตฮณฮฑฮปฯฯฮตฯฮฟ ฮผฮญฮณฮตฮธฮฟฯ
-issues.num_participants=%d ฮฃฯ
ฮผฮผฮตฯฮญฯฮฟฮฝฯฮตฯ
+issues.num_participants_few=%d ฮฃฯ
ฮผฮผฮตฯฮญฯฮฟฮฝฯฮตฯ
issues.attachment.open_tab=`ฮ ฮฑฯฮฎฯฯฮต ฮตฮดฯ ฮณฮนฮฑ ฮฝฮฑ ฮฑฮฝฮฟฮฏฮพฮตฯฮต ฯฮฟ ยซ%sยป ฯฮต ฮผฮนฮฑ ฮฝฮญฮฑ ฮบฮฑฯฯฮญฮปฮฑ`
issues.attachment.download=`ฮ ฮฑฯฮฎฯฯฮต ฮตฮดฯ ฮณฮนฮฑ ฮฝฮฑ ฮบฮฑฯฮตฮฒฮฌฯฮตฯฮต ฯฮฟ ยซ%sยป`
issues.subscribe=ฮฮณฮณฯฮฑฯฮฎ
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 17a8180ec9..bb7c716e49 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1636,7 +1636,8 @@ issues.label.filter_sort.alphabetically = Alphabetically
issues.label.filter_sort.reverse_alphabetically = Reverse alphabetically
issues.label.filter_sort.by_size = Smallest size
issues.label.filter_sort.reverse_by_size = Largest size
-issues.num_participants = %d participants
+issues.num_participants_one = %d participant
+issues.num_participants_few = %d participants
issues.attachment.open_tab = `Click to see "%s" in a new tab`
issues.attachment.download = `Click to download "%s"`
issues.subscribe = Subscribe
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index 3dbca87381..78e06b8f09 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -1561,7 +1561,7 @@ issues.label.filter_sort.alphabetically=Alfabรฉticamente
issues.label.filter_sort.reverse_alphabetically=Invertir alfabรฉticamente
issues.label.filter_sort.by_size=Tamaรฑo mรกs pequeรฑo
issues.label.filter_sort.reverse_by_size=Tamaรฑo mรกs grande
-issues.num_participants=%d participantes
+issues.num_participants_few=%d participantes
issues.attachment.open_tab='Haga clic para ver "%s" en una pestaรฑa nueva'
issues.attachment.download=`Haga clic para descargar "%s"`
issues.subscribe=Suscribir
diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini
index 598c1636dc..7f394176d0 100644
--- a/options/locale/locale_fa-IR.ini
+++ b/options/locale/locale_fa-IR.ini
@@ -1189,7 +1189,7 @@ issues.label.filter_sort.alphabetically=ุงููุจุง
issues.label.filter_sort.reverse_alphabetically=ุจุฑุนฺฉุณ ุชุฑุชุจ ุงููุจุง
issues.label.filter_sort.by_size=ฺฉฺฺูฉุชุฑู ุงูุฏุงุฒู
issues.label.filter_sort.reverse_by_size=ุจุฒุฑฺฏุชุฑู ุงูุฏุงุฒู
-issues.num_participants=%d ู
ุดุงุฑฺฉุช ฺฉููุฏู
+issues.num_participants_few=%d ู
ุดุงุฑฺฉุช ฺฉููุฏู
issues.attachment.open_tab=ุจุฑุง ู
ุดุงูุฏู "%s" ุฏุฑ ุฒุจุงูู ุฌุฏุฏุ ฺฉฺูฉ ฺฉูุฏ
issues.attachment.download=`ุจุฑุง ุฏุฑุงูุช "%s" ฺฉฺูฉ ฺฉูุฏ`
issues.subscribe=ู
ุดุชุฑฺฉ ุดุฏู
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index c6c64ad6ce..60b6e93f00 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -920,7 +920,7 @@ issues.label.filter_sort.alphabetically=Aakkosjรคrjestyksessรค
issues.label.filter_sort.reverse_alphabetically=Kรครคnteisessรค aakkosjรคrjestyksessรค
issues.label.filter_sort.by_size=Pienin koko
issues.label.filter_sort.reverse_by_size=Suurin koko
-issues.num_participants=%d osallistujaa
+issues.num_participants_few=%d osallistujaa
issues.subscribe=Tilaa
issues.unsubscribe=Lopeta tilaus
issues.lock=Lukitse keskustelu
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 659615e6ff..fe527fe3d3 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -1599,7 +1599,7 @@ issues.label.filter_sort.alphabetically=Par ordre alphabรฉtique
issues.label.filter_sort.reverse_alphabetically=Par ordre alphabรฉtique inversรฉ
issues.label.filter_sort.by_size=Plus petite taille
issues.label.filter_sort.reverse_by_size=Plus grande taille
-issues.num_participants=%d participants
+issues.num_participants_few=%d participants
issues.attachment.open_tab=`Cliquez ici pour voir ยซย %sย ยป dans un nouvel onglet.`
issues.attachment.download=`Cliquez pour tรฉlรฉcharger ยซย %sย ยป.`
issues.subscribe=Sโabonner
@@ -3754,6 +3754,7 @@ component_failed_to_load = Une erreur inattendue s'est produite.
contributors.what = contributions
component_loading = Chargement %s...
component_loading_failed = รchec de chargement de %s
+
code_frequency.what = fลequence de code
recent_commits.what = commits rรฉcents
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index 3764f6fa61..5be3fa9c6f 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -857,7 +857,7 @@ issues.label.filter_sort.alphabetically=Betลฑrendben
issues.label.filter_sort.reverse_alphabetically=Fordรญtott betลฑrendben
issues.label.filter_sort.by_size=Legkisebb mรฉret
issues.label.filter_sort.reverse_by_size=Legnagyobb mรฉret
-issues.num_participants=%d Rรฉsztvevล
+issues.num_participants_few=%d Rรฉsztvevล
issues.attachment.open_tab=`A(z) "%s" megnyitรกsa รบj fรผlรถn`
issues.attachment.download=`Kattintson a(z) "%s" letรถltรฉsรฉhez`
issues.subscribe=Feliratkozรกs
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index 574063bcaa..3ab9991f4a 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -729,7 +729,7 @@ issues.label_edit=Sunting
issues.label_delete=Hapus
issues.label.filter_sort.alphabetically=Urutan abjad
issues.label.filter_sort.reverse_alphabetically=Membalikkan menurut abjad
-issues.num_participants=%d peserta
+issues.num_participants_few=%d peserta
issues.attachment.open_tab=`Klik untuk melihat "%s" di tab baru`
issues.attachment.download=`Klik untuk mengunduh "%s"`
issues.subscribe=Berlangganan
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index dc6f4c127e..cb30d51e2f 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -1478,7 +1478,7 @@ issues.label.filter_sort.alphabetically=In ordine alfabetico
issues.label.filter_sort.reverse_alphabetically=In ordine alfabetico inverso
issues.label.filter_sort.by_size=Dimensione piรน piccola
issues.label.filter_sort.reverse_by_size=Dimensione piรน grande
-issues.num_participants=%d partecipanti
+issues.num_participants_few=%d partecipanti
issues.attachment.open_tab=`Clicca per vedere "%s" in una nuova scheda`
issues.attachment.download=`Clicca qui per scaricare "%s"`
issues.subscribe=Iscriviti
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 7f3e1ded36..4774ef78cb 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -1587,7 +1587,7 @@ issues.label.filter_sort.alphabetically=ใขใซใใกใใใ้
issues.label.filter_sort.reverse_alphabetically=้ใขใซใใกใใใ้
issues.label.filter_sort.by_size=ใตใคใบใฎๅฐใใ้
issues.label.filter_sort.reverse_by_size=ใตใคใบใฎๅคงใใ้
-issues.num_participants=%d ไบบใฎๅๅ ่
+issues.num_participants_few=%d ไบบใฎๅๅ ่
issues.attachment.open_tab=`ใฏใชใใฏใใฆๆฐใใใฟใใง "%s" ใ่ฆใ`
issues.attachment.download=`ใฏใชใใฏใใฆ "%s" ใใใฆใณใญใผใ`
issues.subscribe=่ณผ่ชญใใ
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index fa6df2d2a1..0903f5eb3e 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -782,7 +782,7 @@ issues.label_deletion_desc=๋ผ๋ฒจ์ ์ญ์ ํ๋ฉด ๋ชจ๋ ์ด์๋ก๋ถํฐ๋ ์ญ
issues.label_deletion_success=๋ผ๋ฒจ์ด ์ญ์ ๋์์ต๋๋ค.
issues.label.filter_sort.alphabetically=์ํ๋ฒณ์
issues.label.filter_sort.reverse_alphabetically=์ด๋ฆ ์ญ์์ผ๋ก ์ ๋ ฌ
-issues.num_participants=์ฐธ์ฌ์ %d๋ช
+issues.num_participants_few=์ฐธ์ฌ์ %d๋ช
issues.attachment.open_tab=`ํด๋ฆญํ์ฌ "%s" ์ํญ์ผ๋ก ๋ณด๊ธฐ`
issues.attachment.download=' "%s"๋ฅผ ๋ค์ด๋ก๋ ํ๋ ค๋ฉด ํด๋ฆญ ํ์ญ์์ค '
issues.subscribe=๊ตฌ๋
ํ๊ธฐ
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index ce8f05e4b5..587143c9c3 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -1540,7 +1540,7 @@ issues.label.filter_sort.alphabetically=Alfabฤtiski
issues.label.filter_sort.reverse_alphabetically=Pretฤji alfabฤtiski
issues.label.filter_sort.by_size=Mazฤkais izmฤrs
issues.label.filter_sort.reverse_by_size=Lielฤkais izmฤrs
-issues.num_participants=%d dalฤซbnieki
+issues.num_participants_few=%d dalฤซbnieki
issues.attachment.open_tab=`Noklikลกฤทiniet, lai apskatฤซtos "%s" jaunฤ logฤ`
issues.attachment.download=`Noklikลกฤทiniet, lai lejupielฤdฤtu "%s"`
issues.subscribe=Abonฤt
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 4358cc1e81..d5071d98bf 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -1482,7 +1482,7 @@ issues.label.filter_sort.alphabetically=Alfabetisch
issues.label.filter_sort.reverse_alphabetically=Omgekeerd alfabetisch
issues.label.filter_sort.by_size=Kleinste grootte
issues.label.filter_sort.reverse_by_size=Grootste grootte
-issues.num_participants=%d deelnemers
+issues.num_participants_few=%d deelnemers
issues.attachment.open_tab=`Klik om "%s" in een nieuw tabblad te bekijken`
issues.attachment.download=`Klik om "%s" te downloaden`
issues.subscribe=Abonneren
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index a254a912bd..f23f68f7c8 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -1179,7 +1179,7 @@ issues.label.filter_sort.alphabetically=Alfabetycznie
issues.label.filter_sort.reverse_alphabetically=Alfabetycznie odwrotnie
issues.label.filter_sort.by_size=Najmniejszy rozmiar
issues.label.filter_sort.reverse_by_size=Najwiฤkszy rozmiar
-issues.num_participants=Uczestnicy %d
+issues.num_participants_few=Uczestnicy %d
issues.attachment.open_tab=`Kliknij, aby zobaczyฤ "%s" w nowej karcie`
issues.attachment.download=`Kliknij, aby pobraฤ "%s"`
issues.subscribe=Subskrybuj
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 086cea74fa..ac30ff3e74 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -1552,7 +1552,7 @@ issues.label.filter_sort.alphabetically=Alfabeticamente
issues.label.filter_sort.reverse_alphabetically=Alfabeticamente inverso
issues.label.filter_sort.by_size=Menor tamanho
issues.label.filter_sort.reverse_by_size=Maior tamanho
-issues.num_participants=%d participante(s)
+issues.num_participants_few=%d participante(s)
issues.attachment.open_tab=`Clique para ver "%s" em uma nova aba`
issues.attachment.download=`Clique para baixar "%s"`
issues.subscribe=Inscrever-se
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 3538ac9460..09b3fc3153 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -1548,7 +1548,7 @@ issues.label.filter_sort.alphabetically=por ordem alfabรฉtica
issues.label.filter_sort.reverse_alphabetically=por ordem alfabรฉtica inversa
issues.label.filter_sort.by_size=Menor tamanho
issues.label.filter_sort.reverse_by_size=Maior tamanho
-issues.num_participants=%d Participantes
+issues.num_participants_few=%d Participantes
issues.attachment.open_tab=`Clique para ver "%s" num separador novo`
issues.attachment.download=`Clique para descarregar "%s"`
issues.subscribe=Subscrever
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index addc2f8110..34321b18f9 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -1581,7 +1581,8 @@ issues.label.filter_sort.alphabetically=ะะพ ะฐะปัะฐะฒะธัั
issues.label.filter_sort.reverse_alphabetically=ะก ะบะพะฝัะฐ ะฐะปัะฐะฒะธัะฐ
issues.label.filter_sort.by_size=ะะตะฝััะธะน ัะฐะทะผะตั
issues.label.filter_sort.reverse_by_size=ะะพะปััะธะน ัะฐะทะผะตั
-issues.num_participants=%d ััะฐััะฒัััะธั
+issues.num_participants_one=%d ััะฐััะฝะธะบ
+issues.num_participants_few=%d ััะฐััะฝะธะบะพะฒ
issues.attachment.open_tab=`ะะฐะถะผะธัะต, ััะพะฑั ัะฒะธะดะตัั ยซ%sยป ะฒ ะฝะพะฒะพะน ะฒะบะปะฐะดะบะต`
issues.attachment.download=`ะะฐะถะผะธัะต, ััะพะฑั ัะบะฐัะฐัั ยซ%sยป`
issues.subscribe=ะะพะดะฟะธัะฐัััั
diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini
index 7cb1768d22..ac837173e4 100644
--- a/options/locale/locale_si-LK.ini
+++ b/options/locale/locale_si-LK.ini
@@ -1132,7 +1132,7 @@ issues.label.filter_sort.alphabetically=เถ
เถเทเถปเทเถฏเท
issues.label.filter_sort.reverse_alphabetically=เถ
เถเทเถปเทเถฏเท เถดเทเถปเถญเทเทเทเถเทเถซเทเถธเท
issues.label.filter_sort.by_size=เถเทเถฉเทเถธ เถดเทโเถปเถธเทเถซเถบ
issues.label.filter_sort.reverse_by_size=เทเทเทเทเถฝเถธ เถดเทโเถปเถธเทเถซเถบ
-issues.num_participants=เทเทเถทเทเถเทเทเถฑเทเถฑเถฑเท %d
+issues.num_participants_few=เทเทเถทเทเถเทเทเถฑเทเถฑเถฑเท %d
issues.attachment.open_tab=`เถฑเท เทเถเทเทเถ "%s" เถถเทเถฝเทเถธเถง เถเทเถฝเทเถเท เถเถปเถฑเทเถฑ`
issues.attachment.download=`"%s" เถถเทเถเทเถฑเทเถธเถง เถเถถเถฑเทเถฑ`
issues.subscribe=เถฏเทเถบเถ เทเถฑเทเถฑ
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index 38382a6f66..e7cb248aaa 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -972,7 +972,7 @@ issues.label.filter_sort.alphabetically=Alfabetiskt A-ร
issues.label.filter_sort.reverse_alphabetically=Alfabetiskt ร-A
issues.label.filter_sort.by_size=Minsta storlek
issues.label.filter_sort.reverse_by_size=Stรถrsta storlek
-issues.num_participants=%d Deltagare
+issues.num_participants_few=%d Deltagare
issues.attachment.open_tab=`Klicka fรถr att se "%s" i en ny flik`
issues.attachment.download=`Klicka fรถr att hรคmta "%s"`
issues.subscribe=Prenumerera
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 74ef77eb19..fa8a1b687f 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -1539,7 +1539,7 @@ issues.label.filter_sort.alphabetically=Alfabetik
issues.label.filter_sort.reverse_alphabetically=Ters alfabetik
issues.label.filter_sort.by_size=En kรผรงรผk boyut
issues.label.filter_sort.reverse_by_size=En bรผyรผk boyut
-issues.num_participants=%d Katฤฑlฤฑmcฤฑ
+issues.num_participants_few=%d Katฤฑlฤฑmcฤฑ
issues.attachment.open_tab=`Yeni bir sekmede "%s" gรถrmek iรงin tฤฑkla`
issues.attachment.download=`"%s" indirmek iรงin tฤฑkla`
issues.subscribe=Abone Ol
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 0a79e54010..d1040ac2b5 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -1248,7 +1248,7 @@ issues.label.filter_sort.alphabetically=ะะฐ ะฐะปัะฐะฒััะพะผ
issues.label.filter_sort.reverse_alphabetically=ะ ะบัะฝัั ะฐะปัะฐะฒััั
issues.label.filter_sort.by_size=ะะฐะนะผะตะฝัะธะน ัะพะทะผัั
issues.label.filter_sort.reverse_by_size=ะะฐะนะฑัะปััะธะน ัะพะทะผัั
-issues.num_participants=%d ััะฐัะฝะธะบัะฒ
+issues.num_participants_few=%d ััะฐัะฝะธะบัะฒ
issues.attachment.open_tab=`ะะฐัะธัะฝััั ัะพะฑ ะฟะพะฑะฐัะธัะธ "%s" ั ะฝะพะฒัะน ะฒะบะปะฐะดัั`
issues.attachment.download=`ะะฐัะธัะฝััั ัะพะฑ ะทะฐะฒะฐะฝัะฐะถะธัะธ "%s"`
issues.subscribe=ะัะดะฟะธัะฐัะธัั
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 4ca2e70f21..b0e3b383b6 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -1597,7 +1597,7 @@ issues.label.filter_sort.alphabetically=ๆๅญๆฏ้กบๅบๆๅบ
issues.label.filter_sort.reverse_alphabetically=ๆๅญๆฏ้ๅบๆๅบ
issues.label.filter_sort.by_size=ๆๅฐๅฐบๅฏธ
issues.label.filter_sort.reverse_by_size=ๆๅคงๅฐบๅฏธ
-issues.num_participants=%d ๅๅไธ่
+issues.num_participants_few=%d ๅๅไธ่
issues.attachment.open_tab=`ๅจๆฐ็ๆ ็ญพ้กตไธญๆฅ็ '%s'`
issues.attachment.download=`็นๅปไธ่ฝฝ '%s'`
issues.subscribe=่ฎข้
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index 5c1e234392..ab0a075d42 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -467,7 +467,7 @@ issues.label_edit=็ทจ่ผฏ
issues.label_delete=ๅช้ค
issues.label.filter_sort.alphabetically=ๆๅญๆฏ้กบๅบๆๅบ
issues.label.filter_sort.reverse_alphabetically=ๆๅญๆฏๅๅๆๅบ
-issues.num_participants=%d ๅ่่
+issues.num_participants_few=%d ๅ่่
issues.attachment.open_tab=`ๅจๆฐ็ๆจ็ฑค้ ไธญๆฅ็ '%s'`
issues.attachment.download=`้ปๆไธ่ผ '%s'`
issues.subscribe=่จ้ฑ
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index 5bfff77fd2..25e98ed025 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -1433,7 +1433,7 @@ issues.label.filter_sort.alphabetically=ๆๅญๆฏ้ ๅบๆๅบ
issues.label.filter_sort.reverse_alphabetically=ๆๅญๆฏๅๅๆๅบ
issues.label.filter_sort.by_size=ๆชๆก็ฑๅฐๅฐๅคง
issues.label.filter_sort.reverse_by_size=ๆชๆก็ฑๅคงๅฐๅฐ
-issues.num_participants=%d ๅ่่
+issues.num_participants_few=%d ๅ่่
issues.attachment.open_tab=`ๅจๆฐๅ้ ไธญๆฅ็ใ%sใ`
issues.attachment.download=`้ปๆไธ่ผใ%sใ`
issues.subscribe=่จ้ฑ
diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl
index 1414ac45ee..badad6ac47 100644
--- a/templates/repo/issue/view_content/sidebar.tmpl
+++ b/templates/repo/issue/view_content/sidebar.tmpl
@@ -263,7 +263,7 @@
{{if .Participants}}
-
{{ctx.Locale.Tr "repo.issues.num_participants" .NumParticipants}}
+
{{ctx.Locale.TrN .NumParticipants "repo.issues.num_participants_one" "repo.issues.num_participants_few" .NumParticipants}}
{{range .Participants}}
From a517e4aeb1146aea392d6e7f5bdfe5ed8513a61d Mon Sep 17 00:00:00 2001
From: Renovate Bot
Date: Sat, 30 Mar 2024 06:05:07 +0000
Subject: [PATCH 026/822] Update module github.com/minio/minio-go/v7 to v7.0.69
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 5c39436eca..db3560d3fb 100644
--- a/go.mod
+++ b/go.mod
@@ -74,7 +74,7 @@ require (
github.com/meilisearch/meilisearch-go v0.26.1
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.26
- github.com/minio/minio-go/v7 v7.0.66
+ github.com/minio/minio-go/v7 v7.0.69
github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52
github.com/niklasfasching/go-org v1.7.0
diff --git a/go.sum b/go.sum
index 5ab9cfc5f9..44d5f1a268 100644
--- a/go.sum
+++ b/go.sum
@@ -614,8 +614,8 @@ github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
-github.com/minio/minio-go/v7 v7.0.66 h1:bnTOXOHjOqv/gcMuiVbN9o2ngRItvqE774dG9nq0Dzw=
-github.com/minio/minio-go/v7 v7.0.66/go.mod h1:DHAgmyQEGdW3Cif0UooKOyrT3Vxs82zNdV6tkKhRtbs=
+github.com/minio/minio-go/v7 v7.0.69 h1:l8AnsQFyY1xiwa/DaQskY4NXSLA2yrGsW5iD9nRPVS0=
+github.com/minio/minio-go/v7 v7.0.69/go.mod h1:XAvOPJQ5Xlzk5o3o/ArO2NMbhSGkimC+bpW/ngRKDmQ=
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
From 02dcd07437c49430e4e858c36c12a954112ff1f1 Mon Sep 17 00:00:00 2001
From: Renovate Bot
Date: Sat, 30 Mar 2024 10:11:45 +0000
Subject: [PATCH 027/822] Update module github.com/felixge/fgprof to v0.9.4
---
go.mod | 4 ++--
go.sum | 24 +++++++++++++++++-------
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/go.mod b/go.mod
index cc3528800d..41acfdcf39 100644
--- a/go.mod
+++ b/go.mod
@@ -31,7 +31,7 @@ require (
github.com/editorconfig/editorconfig-core-go/v2 v2.6.1
github.com/emersion/go-imap v1.2.1
github.com/emirpasic/gods v1.18.1
- github.com/felixge/fgprof v0.9.3
+ github.com/felixge/fgprof v0.9.4
github.com/fsnotify/fsnotify v1.7.0
github.com/gliderlabs/ssh v0.3.7
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
@@ -53,7 +53,7 @@ require (
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/google/go-github/v57 v57.0.0
- github.com/google/pprof v0.0.0-20240117000934-35fc243c5815
+ github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.1.2
github.com/gorilla/sessions v1.2.2
diff --git a/go.sum b/go.sum
index b3fae2a8d8..3bc626042e 100644
--- a/go.sum
+++ b/go.sum
@@ -186,9 +186,15 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chi-middleware/proxy v1.1.1 h1:4HaXUp8o2+bhHr1OhVy+VjN0+L7/07JDcn6v7YrTjrQ=
github.com/chi-middleware/proxy v1.1.1/go.mod h1:jQwMEJct2tz9VmtCELxvnXoMfa+SOdikvbVJVHv/M+0=
+github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
+github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
+github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
@@ -256,8 +262,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
-github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
-github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
+github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88=
+github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
@@ -353,6 +359,9 @@ github.com/go-webauthn/x v0.1.6 h1:QNAX+AWeqRt9loE8mULeWJCqhVG5D/jvdmJ47fIWCkQ=
github.com/go-webauthn/x v0.1.6/go.mod h1:W8dFVZ79o4f+nY1eOUICy/uq5dhrRl7mxQkYhXTo0FA=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
+github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
+github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/goccy/go-json v0.9.5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
@@ -441,9 +450,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
-github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8=
-github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
+github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -494,7 +502,7 @@ github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
+github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
@@ -567,6 +575,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
@@ -670,6 +679,7 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
+github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
@@ -1034,9 +1044,9 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
From ddc24177dd080229ab3b7d80a1231e59d270a064 Mon Sep 17 00:00:00 2001
From: Gusted
Date: Fri, 29 Mar 2024 20:41:13 +0100
Subject: [PATCH 028/822] [BUG] Render emojis in labels in issue info popup
- Currently emojis that are part of the label's name aren't rendered
when shown in the popup that you get when you hover over issue
references.
- This patch fixes that by rendering the emoji.
- Adds CSS to not make the emoji big in the label.
- Resolves #1531
---
package-lock.json | 171 ++++++++++++++++++++-
package.json | 1 +
web_src/css/repo.css | 4 +
web_src/js/components/ContextPopup.test.js | 39 +++++
web_src/js/components/ContextPopup.vue | 18 +--
web_src/js/vitest.setup.js | 1 +
6 files changed, 221 insertions(+), 13 deletions(-)
create mode 100644 web_src/js/components/ContextPopup.test.js
diff --git a/package-lock.json b/package-lock.json
index 5358428509..3b2f868ec8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -70,6 +70,7 @@
"@stylistic/eslint-plugin-js": "1.7.0",
"@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
+ "@vue/test-utils": "2.4.5",
"eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
"eslint-plugin-github": "4.10.2",
@@ -1329,6 +1330,12 @@
"node": ">= 8"
}
},
+ "node_modules/@one-ini/wasm": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
+ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
+ "dev": true
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -2680,6 +2687,16 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g=="
},
+ "node_modules/@vue/test-utils": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.5.tgz",
+ "integrity": "sha512-oo2u7vktOyKUked36R93NB7mg2B+N7Plr8lxp2JBGwr18ch6EggFjixSCdIVVLkT6Qr0z359Xvnafc9dcKyDUg==",
+ "dev": true,
+ "dependencies": {
+ "js-beautify": "^1.14.9",
+ "vue-component-type-helpers": "^2.0.0"
+ }
+ },
"node_modules/@webassemblyjs/ast": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
@@ -2862,6 +2879,15 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
},
+ "node_modules/abbrev": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
+ "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -3799,6 +3825,22 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/config-chain/node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
"node_modules/core-js-compat": {
"version": "3.36.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz",
@@ -4775,6 +4817,48 @@
"marked": "^4.1.0"
}
},
+ "node_modules/editorconfig": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
+ "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+ "dev": true,
+ "dependencies": {
+ "@one-ini/wasm": "0.1.1",
+ "commander": "^10.0.0",
+ "minimatch": "9.0.1",
+ "semver": "^7.5.3"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/minimatch": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
+ "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.716",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.716.tgz",
@@ -7398,6 +7482,58 @@
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
+ "node_modules/js-beautify": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz",
+ "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==",
+ "dev": true,
+ "dependencies": {
+ "config-chain": "^1.1.13",
+ "editorconfig": "^1.0.4",
+ "glob": "^10.3.3",
+ "js-cookie": "^3.0.5",
+ "nopt": "^7.2.0"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/js-beautify/node_modules/glob": {
+ "version": "10.3.12",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
+ "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.6",
+ "minimatch": "^9.0.1",
+ "minipass": "^7.0.4",
+ "path-scurry": "^1.10.2"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+ "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/js-levenshtein-esm": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-1.2.0.tgz",
@@ -8801,6 +8937,21 @@
"resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz",
"integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw=="
},
+ "node_modules/nopt": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz",
+ "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "^2.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -9140,11 +9291,11 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-scurry": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
- "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
+ "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
+ "lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@@ -9727,6 +9878,12 @@
"integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
"dev": true
},
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+ "dev": true
+ },
"node_modules/proto-props": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz",
@@ -12089,6 +12246,12 @@
"vue": "^3.0.0-0 || ^2.7.0"
}
},
+ "node_modules/vue-component-type-helpers": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.0.7.tgz",
+ "integrity": "sha512-7e12Evdll7JcTIocojgnCgwocX4WzIYStGClBQ+QuWPinZo/vQolv2EMq4a3lg16TKfwWafLimG77bxb56UauA==",
+ "dev": true
+ },
"node_modules/vue-eslint-parser": {
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
diff --git a/package.json b/package.json
index b5bfda9dc6..7b40976968 100644
--- a/package.json
+++ b/package.json
@@ -69,6 +69,7 @@
"@stylistic/eslint-plugin-js": "1.7.0",
"@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
+ "@vue/test-utils": "2.4.5",
"eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
"eslint-plugin-github": "4.10.2",
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 0dfd132a73..d28dc4b96d 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -3010,3 +3010,7 @@ tbody.commit-list {
margin-top: -1px;
border-top: 1px solid var(--color-secondary);
}
+#issue-info-popup .emoji {
+ font-size: inherit;
+ line-height: inherit;
+}
diff --git a/web_src/js/components/ContextPopup.test.js b/web_src/js/components/ContextPopup.test.js
new file mode 100644
index 0000000000..1db6c38301
--- /dev/null
+++ b/web_src/js/components/ContextPopup.test.js
@@ -0,0 +1,39 @@
+import {mount, flushPromises} from '@vue/test-utils';
+import ContextPopup from './ContextPopup.vue';
+
+test('renders a issue info popup', async () => {
+ const owner = 'user2';
+ const repo = 'repo1';
+ const index = 1;
+ vi.spyOn(global, 'fetch').mockResolvedValue({
+ json: vi.fn().mockResolvedValue({
+ ok: true,
+ created_at: '2023-09-30T19:00:00Z',
+ repository: {full_name: owner},
+ pull_request: null,
+ state: 'open',
+ title: 'Normal issue',
+ body: 'Lorem ipsum...',
+ number: index,
+ labels: [{color: 'ee0701', name: "Bug :+1: "}],
+ }),
+ ok: true,
+ });
+
+ const wrapper = mount(ContextPopup);
+ wrapper.vm.$el.dispatchEvent(new CustomEvent('ce-load-context-popup', {detail: {owner, repo, index}}));
+ await flushPromises();
+
+ // Header
+ expect(wrapper.get('p:nth-of-type(1)').text()).toEqual('user2 on Sep 30, 2023');
+ // Title
+ expect(wrapper.get('p:nth-of-type(2)').text()).toEqual('Normal issue #1');
+ // Body
+ expect(wrapper.get('p:nth-of-type(3)').text()).toEqual('Lorem ipsum...');
+ // Check that the state is correct.
+ expect(wrapper.get('svg').classes()).toContain('octicon-issue-opened');
+ // Ensure that script is not an element.
+ expect(() => wrapper.get('.evil')).toThrowError();
+ // Check content of label
+ expect(wrapper.get('.ui.label').text()).toContain("Bug ๐ ");
+});
diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue
index d87eb1a180..ac6a8f3bb6 100644
--- a/web_src/js/components/ContextPopup.vue
+++ b/web_src/js/components/ContextPopup.vue
@@ -3,6 +3,8 @@ import {SvgIcon} from '../svg.js';
import {useLightTextOnBackground} from '../utils/color.js';
import tinycolor from 'tinycolor2';
import {GET} from '../modules/fetch.js';
+import {emojiHTML} from '../features/emoji.js';
+import {htmlEscape} from 'escape-goat';
const {appSubUrl, i18n} = window.config;
@@ -67,6 +69,10 @@ export default {
} else {
textColor = '#111111';
}
+ label.name = htmlEscape(label.name);
+ label.name = label.name.replaceAll(/:[-+\w]+:/g, (emoji) => {
+ return emojiHTML(emoji.substring(1, emoji.length - 1));
+ });
return {name: label.name, color: `#${label.color}`, textColor};
});
},
@@ -104,19 +110,13 @@ export default {
-
+
diff --git a/web_src/js/vitest.setup.js b/web_src/js/vitest.setup.js
index 6fb0f5dc8f..5366958fb5 100644
--- a/web_src/js/vitest.setup.js
+++ b/web_src/js/vitest.setup.js
@@ -4,6 +4,7 @@ window.config = {
csrfToken: 'test-csrf-token-123456',
pageData: {},
i18n: {},
+ customEmojis: {},
appSubUrl: '',
mentionValues: [
{key: 'user1 User 1', value: 'user1', name: 'user1', fullname: 'User 1', avatar: 'https://avatar1.com'},
From 05376503ed6c8859c0996b7f295457af0aa7634e Mon Sep 17 00:00:00 2001
From: Renovate Bot
Date: Sat, 30 Mar 2024 11:48:44 +0000
Subject: [PATCH 029/822] Update dependency happy-dom to v14.3.9
---
package-lock.json | 8 ++++----
package.json | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 3b2f868ec8..c4579fbd8a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -86,7 +86,7 @@
"eslint-plugin-vue": "9.24.0",
"eslint-plugin-vue-scoped-css": "2.8.0",
"eslint-plugin-wc": "2.0.4",
- "happy-dom": "14.3.7",
+ "happy-dom": "14.3.9",
"markdownlint-cli": "0.39.0",
"postcss-html": "1.6.0",
"stylelint": "16.3.0",
@@ -6597,9 +6597,9 @@
}
},
"node_modules/happy-dom": {
- "version": "14.3.7",
- "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.3.7.tgz",
- "integrity": "sha512-lUfDRGzjrVJF2pnvh13OL+qEJ9eDpcedVLm77a3aMg8gPGKXfG+xFMNk3cOWetjucU8FveJ4qcSC/EX55nJ4fQ==",
+ "version": "14.3.9",
+ "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-14.3.9.tgz",
+ "integrity": "sha512-0kPQchwthekcYpYN8CvCiq+/z5bqFYDLbTxZ+yDLwT8AFRVJDFadShHRxp3VAZRy7a5isOZ1j/LzsU1dtAIZMQ==",
"dev": true,
"dependencies": {
"entities": "^4.5.0",
diff --git a/package.json b/package.json
index 7b40976968..d823ba4b30 100644
--- a/package.json
+++ b/package.json
@@ -85,7 +85,7 @@
"eslint-plugin-vue": "9.24.0",
"eslint-plugin-vue-scoped-css": "2.8.0",
"eslint-plugin-wc": "2.0.4",
- "happy-dom": "14.3.7",
+ "happy-dom": "14.3.9",
"markdownlint-cli": "0.39.0",
"postcss-html": "1.6.0",
"stylelint": "16.3.0",
From d8ab3648897a647dd09bb7d3b2313b2c3a513763 Mon Sep 17 00:00:00 2001
From: Earl Warren
Date: Sat, 30 Mar 2024 13:35:56 +0100
Subject: [PATCH 030/822] [CI] allow backports to be launched on merged pull
requests
The intention was good initially but the expression was wrong for two
reasons:
* When a pull_request event is received for a labeled action, the
match should be github.event.action == 'label_updated' and not
'labeled'
* The event does not have a github.event.label field and
contains(github.event.label.name, 'backport/v') will always be
false.
Since the expression is only evaluated in the context of a merged pull
request, either because it was just closed or because it was labeled
after the fact, the only verification that is needed is to assert that
there is at least one `backport/v*` label.
---
.forgejo/workflows/backport.yml | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/.forgejo/workflows/backport.yml b/.forgejo/workflows/backport.yml
index 50e8785c12..10da148eab 100644
--- a/.forgejo/workflows/backport.yml
+++ b/.forgejo/workflows/backport.yml
@@ -33,17 +33,8 @@ jobs:
if: >
!startsWith(vars.ROLE, 'forgejo-') && (
github.event.pull_request.merged
- && (
- (
- github.event.action == 'closed' &&
- contains(toJSON(github.event.pull_request.labels), 'backport/v')
- )
- ||
- (
- github.event.action == 'labeled' &&
- contains(github.event.label.name, 'backport/v')
- )
- )
+ &&
+ contains(toJSON(github.event.pull_request.labels), 'backport/v')
)
runs-on: docker
container:
From 19f7eb657b83dc01d032ba220c2e75f87c69de21 Mon Sep 17 00:00:00 2001
From: Earl Warren
Date: Sat, 30 Mar 2024 13:35:56 +0100
Subject: [PATCH 031/822] [CI] allow backports to be launched on merged pull
requests
The intention was good initially but the expression was wrong for two
reasons:
* When a pull_request event is received for a labeled action, the
match should be github.event.action == 'label_updated' and not
'labeled'
* The event does not have a github.event.label field and
contains(github.event.label.name, 'backport/v') will always be
false.
Since the expression is only evaluated in the context of a merged pull
request, either because it was just closed or because it was labeled
after the fact, the only verification that is needed is to assert that
there is at least one `backport/v*` label.
---
.forgejo/workflows/backport.yml | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/.forgejo/workflows/backport.yml b/.forgejo/workflows/backport.yml
index 50e8785c12..10da148eab 100644
--- a/.forgejo/workflows/backport.yml
+++ b/.forgejo/workflows/backport.yml
@@ -33,17 +33,8 @@ jobs:
if: >
!startsWith(vars.ROLE, 'forgejo-') && (
github.event.pull_request.merged
- && (
- (
- github.event.action == 'closed' &&
- contains(toJSON(github.event.pull_request.labels), 'backport/v')
- )
- ||
- (
- github.event.action == 'labeled' &&
- contains(github.event.label.name, 'backport/v')
- )
- )
+ &&
+ contains(toJSON(github.event.pull_request.labels), 'backport/v')
)
runs-on: docker
container:
From 80f22ab0d8ac8aa24fc559eb1b80bee16f1c0b8d Mon Sep 17 00:00:00 2001
From: Gusted
Date: Sat, 30 Mar 2024 14:30:41 +0100
Subject: [PATCH 032/822] [BUG] Don't color dot literal color names
- Colordots are generated for colors in inline code, such as `red`,
`rgb(255, 0, 124)`, `#ffaabb` and `hsl(124, 52%, 50%)`. However this
shouldn't be doon for literal color names as these can be too common
assiocated with non-color related stuff _and matches the behavior of
some other forge_.
- Move the regexes from bluemonday to Forgejo and do the checking
ourselves.
- Adds unit tests.
- Resolves https://codeberg.org/Codeberg/Community/issues/1510
---
modules/markup/markdown/color_util.go | 19 ++++++++
modules/markup/markdown/color_util_test.go | 50 ++++++++++++++++++++++
modules/markup/markdown/goldmark.go | 3 +-
3 files changed, 70 insertions(+), 2 deletions(-)
create mode 100644 modules/markup/markdown/color_util.go
create mode 100644 modules/markup/markdown/color_util_test.go
diff --git a/modules/markup/markdown/color_util.go b/modules/markup/markdown/color_util.go
new file mode 100644
index 0000000000..355fef3fc0
--- /dev/null
+++ b/modules/markup/markdown/color_util.go
@@ -0,0 +1,19 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package markdown
+
+import "regexp"
+
+var (
+ hexRGB = regexp.MustCompile(`^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$`)
+ hsl = regexp.MustCompile(`^hsl\([ ]*([012]?[0-9]{1,2}|3[0-5][0-9]|360),[ ]*([0-9]{0,2}|100)\%,[ ]*([0-9]{0,2}|100)\%\)$`)
+ hsla = regexp.MustCompile(`^hsla\(([ ]*[012]?[0-9]{1,2}|3[0-5][0-9]|360),[ ]*([0-9]{0,2}|100)\%,[ ]*([0-9]{0,2}|100)\%,[ ]*(1|1\.0|0|(0\.[0-9]+))\)$`)
+ rgb = regexp.MustCompile(`^rgb\(([ ]*((([0-9]{1,2}|100)\%)|(([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))),){2}([ ]*((([0-9]{1,2}|100)\%)|(([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))))\)$`)
+ rgba = regexp.MustCompile(`^rgba\(([ ]*((([0-9]{1,2}|100)\%)|(([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))),){3}[ ]*(1(\.0)?|0|(0\.[0-9]+))\)$`)
+)
+
+// matchColor return if color is in the form of hex RGB, HSL(A) or RGB(A).
+func matchColor(color string) bool {
+ return hexRGB.MatchString(color) || rgb.MatchString(color) || rgba.MatchString(color) || hsl.MatchString(color) || hsla.MatchString(color)
+}
diff --git a/modules/markup/markdown/color_util_test.go b/modules/markup/markdown/color_util_test.go
new file mode 100644
index 0000000000..c6e0555a35
--- /dev/null
+++ b/modules/markup/markdown/color_util_test.go
@@ -0,0 +1,50 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package markdown
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestMatchColor(t *testing.T) {
+ testCases := []struct {
+ input string
+ expected bool
+ }{
+ {"#ddeeffa0", true},
+ {"#ddeefe", true},
+ {"#abcdef", true},
+ {"#abcdeg", false},
+ {"#abcdefg0", false},
+ {"black", false},
+ {"violet", false},
+ {"rgb(255, 255, 255)", true},
+ {"rgb(0, 0, 0)", true},
+ {"rgb(256, 0, 0)", false},
+ {"rgb(0, 256, 0)", false},
+ {"rgb(0, 0, 256)", false},
+ {"rgb(0, 0, 0, 1)", false},
+ {"rgba(0, 0, 0)", false},
+ {"rgba(0, 255, 0, 1)", true},
+ {"rgba(32, 255, 12, 0.55)", true},
+ {"rgba(32, 256, 12, 0.55)", false},
+ {"hsl(0, 0%, 0%)", true},
+ {"hsl(360, 100%, 100%)", true},
+ {"hsl(361, 100%, 50%)", false},
+ {"hsl(360, 101%, 50%)", false},
+ {"hsl(360, 100%, 101%)", false},
+ {"hsl(0, 0%, 0%, 0)", false},
+ {"hsla(0, 0%, 0%)", false},
+ {"hsla(0, 0%, 0%, 0)", true},
+ {"hsla(0, 0%, 0%, 1)", true},
+ {"hsla(0, 0%, 0%, 0.5)", true},
+ {"hsla(0, 0%, 0%, 1.5)", false},
+ }
+ for _, testCase := range testCases {
+ actual := matchColor(testCase.input)
+ assert.Equal(t, testCase.expected, actual)
+ }
+}
diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 7ada8b5548..5a481a31fd 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -16,7 +16,6 @@ import (
"code.gitea.io/gitea/modules/setting"
giteautil "code.gitea.io/gitea/modules/util"
- "github.com/microcosm-cc/bluemonday/css"
"github.com/yuin/goldmark/ast"
east "github.com/yuin/goldmark/extension/ast"
"github.com/yuin/goldmark/parser"
@@ -199,7 +198,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
}
case *ast.CodeSpan:
colorContent := n.Text(reader.Source())
- if css.ColorHandler(strings.ToLower(string(colorContent))) {
+ if matchColor(strings.ToLower(string(colorContent))) {
v.AppendChild(v, NewColorPreview(colorContent))
}
}
From afcff0eebdd8ce07434b2a6f4147a7e5a079aa46 Mon Sep 17 00:00:00 2001
From: Leo Heitmann Ruiz
Date: Sat, 30 Mar 2024 15:23:48 +0100
Subject: [PATCH 033/822] Fix
---
modules/highlight/highlight.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go
index 8fa2de6daf..4ee47b7a13 100644
--- a/modules/highlight/highlight.go
+++ b/modules/highlight/highlight.go
@@ -216,7 +216,7 @@ func PlainText(code []byte) []template.HTML {
}
func formatLexerName(name string) string {
- if name == "fallback" {
+ if name == "fallback" || name == "plaintext" {
return "Text"
}
From a1bce73f5cdd1361739bb0a7b99dfcfb11e29f1b Mon Sep 17 00:00:00 2001
From: Gusted
Date: Fri, 29 Mar 2024 20:41:13 +0100
Subject: [PATCH 034/822] [BUG] Render emojis in labels in issue info popup
- Currently emojis that are part of the label's name aren't rendered
when shown in the popup that you get when you hover over issue
references.
- This patch fixes that by rendering the emoji.
- Adds CSS to not make the emoji big in the label.
- Resolves #1531
---
package-lock.json | 171 ++++++++++++++++++++-
package.json | 1 +
web_src/css/repo.css | 4 +
web_src/js/components/ContextPopup.test.js | 39 +++++
web_src/js/components/ContextPopup.vue | 18 +--
web_src/js/vitest.setup.js | 1 +
6 files changed, 221 insertions(+), 13 deletions(-)
create mode 100644 web_src/js/components/ContextPopup.test.js
diff --git a/package-lock.json b/package-lock.json
index 5358428509..3b2f868ec8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -70,6 +70,7 @@
"@stylistic/eslint-plugin-js": "1.7.0",
"@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
+ "@vue/test-utils": "2.4.5",
"eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
"eslint-plugin-github": "4.10.2",
@@ -1329,6 +1330,12 @@
"node": ">= 8"
}
},
+ "node_modules/@one-ini/wasm": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
+ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
+ "dev": true
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -2680,6 +2687,16 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.21.tgz",
"integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g=="
},
+ "node_modules/@vue/test-utils": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.5.tgz",
+ "integrity": "sha512-oo2u7vktOyKUked36R93NB7mg2B+N7Plr8lxp2JBGwr18ch6EggFjixSCdIVVLkT6Qr0z359Xvnafc9dcKyDUg==",
+ "dev": true,
+ "dependencies": {
+ "js-beautify": "^1.14.9",
+ "vue-component-type-helpers": "^2.0.0"
+ }
+ },
"node_modules/@webassemblyjs/ast": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
@@ -2862,6 +2879,15 @@
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
},
+ "node_modules/abbrev": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
+ "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -3799,6 +3825,22 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/config-chain/node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
"node_modules/core-js-compat": {
"version": "3.36.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz",
@@ -4775,6 +4817,48 @@
"marked": "^4.1.0"
}
},
+ "node_modules/editorconfig": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
+ "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+ "dev": true,
+ "dependencies": {
+ "@one-ini/wasm": "0.1.1",
+ "commander": "^10.0.0",
+ "minimatch": "9.0.1",
+ "semver": "^7.5.3"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/minimatch": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
+ "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.4.716",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.716.tgz",
@@ -7398,6 +7482,58 @@
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
+ "node_modules/js-beautify": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz",
+ "integrity": "sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==",
+ "dev": true,
+ "dependencies": {
+ "config-chain": "^1.1.13",
+ "editorconfig": "^1.0.4",
+ "glob": "^10.3.3",
+ "js-cookie": "^3.0.5",
+ "nopt": "^7.2.0"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/js-beautify/node_modules/glob": {
+ "version": "10.3.12",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
+ "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.3.6",
+ "minimatch": "^9.0.1",
+ "minipass": "^7.0.4",
+ "path-scurry": "^1.10.2"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-cookie": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+ "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/js-levenshtein-esm": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-1.2.0.tgz",
@@ -8801,6 +8937,21 @@
"resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz",
"integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw=="
},
+ "node_modules/nopt": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz",
+ "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "^2.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
"node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -9140,11 +9291,11 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/path-scurry": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
- "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
+ "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
+ "lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@@ -9727,6 +9878,12 @@
"integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
"dev": true
},
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+ "dev": true
+ },
"node_modules/proto-props": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz",
@@ -12089,6 +12246,12 @@
"vue": "^3.0.0-0 || ^2.7.0"
}
},
+ "node_modules/vue-component-type-helpers": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.0.7.tgz",
+ "integrity": "sha512-7e12Evdll7JcTIocojgnCgwocX4WzIYStGClBQ+QuWPinZo/vQolv2EMq4a3lg16TKfwWafLimG77bxb56UauA==",
+ "dev": true
+ },
"node_modules/vue-eslint-parser": {
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
diff --git a/package.json b/package.json
index b5bfda9dc6..7b40976968 100644
--- a/package.json
+++ b/package.json
@@ -69,6 +69,7 @@
"@stylistic/eslint-plugin-js": "1.7.0",
"@stylistic/stylelint-plugin": "2.1.0",
"@vitejs/plugin-vue": "5.0.4",
+ "@vue/test-utils": "2.4.5",
"eslint": "8.57.0",
"eslint-plugin-array-func": "4.0.0",
"eslint-plugin-github": "4.10.2",
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 0dfd132a73..d28dc4b96d 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -3010,3 +3010,7 @@ tbody.commit-list {
margin-top: -1px;
border-top: 1px solid var(--color-secondary);
}
+#issue-info-popup .emoji {
+ font-size: inherit;
+ line-height: inherit;
+}
diff --git a/web_src/js/components/ContextPopup.test.js b/web_src/js/components/ContextPopup.test.js
new file mode 100644
index 0000000000..1db6c38301
--- /dev/null
+++ b/web_src/js/components/ContextPopup.test.js
@@ -0,0 +1,39 @@
+import {mount, flushPromises} from '@vue/test-utils';
+import ContextPopup from './ContextPopup.vue';
+
+test('renders a issue info popup', async () => {
+ const owner = 'user2';
+ const repo = 'repo1';
+ const index = 1;
+ vi.spyOn(global, 'fetch').mockResolvedValue({
+ json: vi.fn().mockResolvedValue({
+ ok: true,
+ created_at: '2023-09-30T19:00:00Z',
+ repository: {full_name: owner},
+ pull_request: null,
+ state: 'open',
+ title: 'Normal issue',
+ body: 'Lorem ipsum...',
+ number: index,
+ labels: [{color: 'ee0701', name: "Bug :+1: "}],
+ }),
+ ok: true,
+ });
+
+ const wrapper = mount(ContextPopup);
+ wrapper.vm.$el.dispatchEvent(new CustomEvent('ce-load-context-popup', {detail: {owner, repo, index}}));
+ await flushPromises();
+
+ // Header
+ expect(wrapper.get('p:nth-of-type(1)').text()).toEqual('user2 on Sep 30, 2023');
+ // Title
+ expect(wrapper.get('p:nth-of-type(2)').text()).toEqual('Normal issue #1');
+ // Body
+ expect(wrapper.get('p:nth-of-type(3)').text()).toEqual('Lorem ipsum...');
+ // Check that the state is correct.
+ expect(wrapper.get('svg').classes()).toContain('octicon-issue-opened');
+ // Ensure that script is not an element.
+ expect(() => wrapper.get('.evil')).toThrowError();
+ // Check content of label
+ expect(wrapper.get('.ui.label').text()).toContain("Bug ๐ ");
+});
diff --git a/web_src/js/components/ContextPopup.vue b/web_src/js/components/ContextPopup.vue
index d87eb1a180..ac6a8f3bb6 100644
--- a/web_src/js/components/ContextPopup.vue
+++ b/web_src/js/components/ContextPopup.vue
@@ -3,6 +3,8 @@ import {SvgIcon} from '../svg.js';
import {useLightTextOnBackground} from '../utils/color.js';
import tinycolor from 'tinycolor2';
import {GET} from '../modules/fetch.js';
+import {emojiHTML} from '../features/emoji.js';
+import {htmlEscape} from 'escape-goat';
const {appSubUrl, i18n} = window.config;
@@ -67,6 +69,10 @@ export default {
} else {
textColor = '#111111';
}
+ label.name = htmlEscape(label.name);
+ label.name = label.name.replaceAll(/:[-+\w]+:/g, (emoji) => {
+ return emojiHTML(emoji.substring(1, emoji.length - 1));
+ });
return {name: label.name, color: `#${label.color}`, textColor};
});
},
@@ -104,19 +110,13 @@ export default {
-
+
diff --git a/web_src/js/vitest.setup.js b/web_src/js/vitest.setup.js
index 6fb0f5dc8f..5366958fb5 100644
--- a/web_src/js/vitest.setup.js
+++ b/web_src/js/vitest.setup.js
@@ -4,6 +4,7 @@ window.config = {
csrfToken: 'test-csrf-token-123456',
pageData: {},
i18n: {},
+ customEmojis: {},
appSubUrl: '',
mentionValues: [
{key: 'user1 User 1', value: 'user1', name: 'user1', fullname: 'User 1', avatar: 'https://avatar1.com'},
From 85cbdefaaa08940014cdeb62c8c07452bc227be5 Mon Sep 17 00:00:00 2001
From: Renovate Bot
Date: Sat, 30 Mar 2024 14:46:43 +0000
Subject: [PATCH 035/822] Update module github.com/go-sql-driver/mysql to
v1.8.1
---
go.mod | 2 +-
go.sum | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/go.mod b/go.mod
index 61eb961272..a0b94dcfda 100644
--- a/go.mod
+++ b/go.mod
@@ -44,7 +44,7 @@ require (
github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.11.0
github.com/go-ldap/ldap/v3 v3.4.6
- github.com/go-sql-driver/mysql v1.8.0
+ github.com/go-sql-driver/mysql v1.8.1
github.com/go-swagger/go-swagger v0.30.5
github.com/go-testfixtures/testfixtures/v3 v3.10.0
github.com/go-webauthn/webauthn v0.10.0
diff --git a/go.sum b/go.sum
index b298937b01..b1619b8b67 100644
--- a/go.sum
+++ b/go.sum
@@ -342,8 +342,8 @@ github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wp
github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4=
-github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U=
github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewetCdvEXqgPvbc/Q=
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
From 120fa61a0a720de8d82c4bf9e65e77d8a0bddf87 Mon Sep 17 00:00:00 2001
From: oliverpool
Date: Fri, 22 Mar 2024 16:02:48 +0100
Subject: [PATCH 036/822] [REFACTOR] add Icon to webhook.Interface
---
routers/web/repo/setting/webhook.go | 6 +++++-
services/webhook/default.go | 10 ++++++++++
services/webhook/dingtalk.go | 3 +++
services/webhook/discord.go | 2 ++
services/webhook/feishu.go | 2 ++
services/webhook/general.go | 8 ++++++++
services/webhook/gogs.go | 2 ++
services/webhook/matrix.go | 6 ++++++
services/webhook/msteams.go | 2 ++
services/webhook/packagist.go | 2 ++
services/webhook/slack.go | 2 ++
services/webhook/telegram.go | 2 ++
services/webhook/webhook.go | 2 ++
services/webhook/wechatwork.go | 5 +++++
templates/webhook/new.tmpl | 2 +-
15 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go
index bf7770bfdb..c36ebf5b14 100644
--- a/routers/web/repo/setting/webhook.go
+++ b/routers/web/repo/setting/webhook.go
@@ -132,11 +132,13 @@ func WebhookNew(ctx *context.Context) {
}
hookType := ctx.Params(":type")
- if webhook_service.GetWebhookHandler(hookType) == nil {
+ handler := webhook_service.GetWebhookHandler(hookType)
+ if handler == nil {
ctx.NotFound("GetWebhookHandler", nil)
return
}
ctx.Data["HookType"] = hookType
+ ctx.Data["WebhookHandler"] = handler
ctx.Data["BaseLink"] = orCtx.LinkNew
ctx.Data["BaseLinkNew"] = orCtx.LinkNew
@@ -194,6 +196,7 @@ func WebhookCreate(ctx *context.Context) {
ctx.Data["PageIsSettingsHooksNew"] = true
ctx.Data["Webhook"] = webhook.Webhook{HookEvent: &webhook_module.HookEvent{}}
ctx.Data["HookType"] = hookType
+ ctx.Data["WebhookHandler"] = handler
orCtx, err := getOwnerRepoCtx(ctx)
if err != nil {
@@ -358,6 +361,7 @@ func checkWebhook(ctx *context.Context) (*ownerRepoCtx, *webhook.Webhook) {
if handler := webhook_service.GetWebhookHandler(w.Type); handler != nil {
ctx.Data["HookMetadata"] = handler.Metadata(w)
+ ctx.Data["WebhookHandler"] = handler
}
ctx.Data["History"], err = w.History(ctx, 1)
diff --git a/services/webhook/default.go b/services/webhook/default.go
index f725f8a783..be3b9b3c73 100644
--- a/services/webhook/default.go
+++ b/services/webhook/default.go
@@ -10,6 +10,7 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
+ "html/template"
"io"
"net/http"
"net/url"
@@ -17,6 +18,7 @@ import (
webhook_model "code.gitea.io/gitea/models/webhook"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/svg"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/services/forms"
)
@@ -34,6 +36,14 @@ func (dh defaultHandler) Type() webhook_module.HookType {
return webhook_module.GITEA
}
+func (dh defaultHandler) Icon(size int) template.HTML {
+ if dh.forgejo {
+ // forgejo.svg is not in web_src/svg/, so svg.RenderHTML does not work
+ return imgIcon("forgejo.svg", size)
+ }
+ return svg.RenderHTML("gitea-gitea", size, "img")
+}
+
func (defaultHandler) Metadata(*webhook_model.Webhook) any { return nil }
func (defaultHandler) FormFields(bind func(any)) FormFields {
diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go
index f4bc715e08..0a0160ac46 100644
--- a/services/webhook/dingtalk.go
+++ b/services/webhook/dingtalk.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"net/url"
"strings"
@@ -22,6 +23,8 @@ type dingtalkHandler struct{}
func (dingtalkHandler) Type() webhook_module.HookType { return webhook_module.DINGTALK }
func (dingtalkHandler) Metadata(*webhook_model.Webhook) any { return nil }
+func (dingtalkHandler) Icon(size int) template.HTML { return imgIcon("dingtalk.ico", size) }
+
func (dingtalkHandler) FormFields(bind func(any)) FormFields {
var form struct {
forms.WebhookForm
diff --git a/services/webhook/discord.go b/services/webhook/discord.go
index 3a0a973860..2efb46f5bb 100644
--- a/services/webhook/discord.go
+++ b/services/webhook/discord.go
@@ -7,6 +7,7 @@ import (
"context"
"errors"
"fmt"
+ "html/template"
"net/http"
"net/url"
"strconv"
@@ -26,6 +27,7 @@ import (
type discordHandler struct{}
func (discordHandler) Type() webhook_module.HookType { return webhook_module.DISCORD }
+func (discordHandler) Icon(size int) template.HTML { return imgIcon("discord.png", size) }
func (discordHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/feishu.go b/services/webhook/feishu.go
index b27acc9070..eba54fa09b 100644
--- a/services/webhook/feishu.go
+++ b/services/webhook/feishu.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"strings"
@@ -19,6 +20,7 @@ import (
type feishuHandler struct{}
func (feishuHandler) Type() webhook_module.HookType { return webhook_module.FEISHU }
+func (feishuHandler) Icon(size int) template.HTML { return imgIcon("feishu.png", size) }
func (feishuHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/general.go b/services/webhook/general.go
index c41f58fe8d..454efc6495 100644
--- a/services/webhook/general.go
+++ b/services/webhook/general.go
@@ -6,7 +6,9 @@ package webhook
import (
"fmt"
"html"
+ "html/template"
"net/url"
+ "strconv"
"strings"
webhook_model "code.gitea.io/gitea/models/webhook"
@@ -352,3 +354,9 @@ func ToHook(repoLink string, w *webhook_model.Webhook) (*api.Hook, error) {
Created: w.CreatedUnix.AsTime(),
}, nil
}
+
+func imgIcon(name string, size int) template.HTML {
+ s := strconv.Itoa(size)
+ src := html.EscapeString(setting.StaticURLPrefix + "/assets/img/" + name)
+ return template.HTML(`
`)
+}
diff --git a/services/webhook/gogs.go b/services/webhook/gogs.go
index e23673ed35..f616f5e2f3 100644
--- a/services/webhook/gogs.go
+++ b/services/webhook/gogs.go
@@ -4,6 +4,7 @@
package webhook
import (
+ "html/template"
"net/http"
webhook_model "code.gitea.io/gitea/models/webhook"
@@ -14,6 +15,7 @@ import (
type gogsHandler struct{ defaultHandler }
func (gogsHandler) Type() webhook_module.HookType { return webhook_module.GOGS }
+func (gogsHandler) Icon(size int) template.HTML { return imgIcon("gogs.ico", size) }
func (gogsHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go
index d04f0f367f..322b4d6665 100644
--- a/services/webhook/matrix.go
+++ b/services/webhook/matrix.go
@@ -9,6 +9,7 @@ import (
"crypto/sha1"
"encoding/hex"
"fmt"
+ "html/template"
"net/http"
"net/url"
"regexp"
@@ -20,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
"code.gitea.io/gitea/services/forms"
@@ -29,6 +31,10 @@ type matrixHandler struct{}
func (matrixHandler) Type() webhook_module.HookType { return webhook_module.MATRIX }
+func (matrixHandler) Icon(size int) template.HTML {
+ return svg.RenderHTML("gitea-matrix", size, "img")
+}
+
func (matrixHandler) FormFields(bind func(any)) FormFields {
var form struct {
forms.WebhookForm
diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go
index 849093e9bf..940a6c49aa 100644
--- a/services/webhook/msteams.go
+++ b/services/webhook/msteams.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"net/url"
"strings"
@@ -22,6 +23,7 @@ type msteamsHandler struct{}
func (msteamsHandler) Type() webhook_module.HookType { return webhook_module.MSTEAMS }
func (msteamsHandler) Metadata(*webhook_model.Webhook) any { return nil }
+func (msteamsHandler) Icon(size int) template.HTML { return imgIcon("msteams.png", size) }
func (msteamsHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/packagist.go b/services/webhook/packagist.go
index d8bf9ea23a..f1f3306109 100644
--- a/services/webhook/packagist.go
+++ b/services/webhook/packagist.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"net/url"
@@ -19,6 +20,7 @@ import (
type packagistHandler struct{}
func (packagistHandler) Type() webhook_module.HookType { return webhook_module.PACKAGIST }
+func (packagistHandler) Icon(size int) template.HTML { return imgIcon("packagist.png", size) }
func (packagistHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/slack.go b/services/webhook/slack.go
index 683ef41019..0b4c4b6645 100644
--- a/services/webhook/slack.go
+++ b/services/webhook/slack.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"regexp"
"strings"
@@ -26,6 +27,7 @@ import (
type slackHandler struct{}
func (slackHandler) Type() webhook_module.HookType { return webhook_module.SLACK }
+func (slackHandler) Icon(size int) template.HTML { return imgIcon("slack.png", size) }
type slackForm struct {
forms.WebhookForm
diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go
index 2ede28dbd2..daa986bafb 100644
--- a/services/webhook/telegram.go
+++ b/services/webhook/telegram.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"net/url"
"strings"
@@ -22,6 +23,7 @@ import (
type telegramHandler struct{}
func (telegramHandler) Type() webhook_module.HookType { return webhook_module.TELEGRAM }
+func (telegramHandler) Icon(size int) template.HTML { return imgIcon("telegram.png", size) }
func (telegramHandler) FormFields(bind func(any)) FormFields {
var form struct {
diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go
index a7802d27dc..f27bffc29a 100644
--- a/services/webhook/webhook.go
+++ b/services/webhook/webhook.go
@@ -7,6 +7,7 @@ import (
"context"
"errors"
"fmt"
+ "html/template"
"net/http"
"strings"
@@ -35,6 +36,7 @@ type Handler interface {
// If form implements the [binding.Validator] interface, the Validate method will be called
FormFields(bind func(form any)) FormFields
NewRequest(context.Context, *webhook_model.Webhook, *webhook_model.HookTask) (req *http.Request, body []byte, err error)
+ Icon(size int) template.HTML
}
type FormFields struct {
diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go
index 2ad2acd018..eff5b9b526 100644
--- a/services/webhook/wechatwork.go
+++ b/services/webhook/wechatwork.go
@@ -6,6 +6,7 @@ package webhook
import (
"context"
"fmt"
+ "html/template"
"net/http"
"strings"
@@ -21,6 +22,10 @@ type wechatworkHandler struct{}
func (wechatworkHandler) Type() webhook_module.HookType { return webhook_module.WECHATWORK }
func (wechatworkHandler) Metadata(*webhook_model.Webhook) any { return nil }
+func (wechatworkHandler) Icon(size int) template.HTML {
+ return imgIcon("wechatwork.png", size)
+}
+
func (wechatworkHandler) FormFields(bind func(any)) FormFields {
var form struct {
forms.WebhookForm
diff --git a/templates/webhook/new.tmpl b/templates/webhook/new.tmpl
index 17eb578b0e..8afdb1fa5d 100644
--- a/templates/webhook/new.tmpl
+++ b/templates/webhook/new.tmpl
@@ -2,7 +2,7 @@
{{.CustomHeaderTitle}}
- {{template "shared/webhook/icon" (dict "Size" 20 "HookType" .ctxData.HookType)}}
+ {{.ctxData.WebhookHandler.Icon 20}}
{{ctx.Locale.Tr (print "repo.settings.web_hook_name_" .ctxData.HookType)}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
From 69115baf413636d34686a50baf5b330ecc24362f Mon Sep 17 00:00:00 2001
From: oliverpool
Date: Sat, 23 Mar 2024 21:28:30 +0100
Subject: [PATCH 037/822] [REFACTOR] use Icon from interface in webhook list
---
.deadcode-out | 1 -
options/locale/locale_bg.ini | 6 +--
options/locale/locale_cs-CZ.ini | 6 +--
options/locale/locale_de-DE.ini | 6 +--
options/locale/locale_el-GR.ini | 6 +--
options/locale/locale_en-US.ini | 6 +--
options/locale/locale_es-ES.ini | 6 +--
options/locale/locale_fi-FI.ini | 4 +-
options/locale/locale_fr-FR.ini | 6 +--
options/locale/locale_is-IS.ini | 2 +-
options/locale/locale_it-IT.ini | 6 +--
options/locale/locale_ja-JP.ini | 6 +--
options/locale/locale_lv-LV.ini | 6 +--
options/locale/locale_nl-NL.ini | 6 +--
options/locale/locale_pt-BR.ini | 6 +--
options/locale/locale_pt-PT.ini | 6 +--
options/locale/locale_ru-RU.ini | 6 +--
options/locale/locale_tr-TR.ini | 6 +--
options/locale/locale_zh-CN.ini | 6 +--
options/locale/locale_zh-TW.ini | 6 +--
routers/web/org/setting.go | 2 +
routers/web/repo/setting/webhook.go | 4 ++
routers/web/user/setting/webhooks.go | 2 +
.../repo/settings/webhook/link_menu.tmpl | 54 +++----------------
templates/webhook/new/feishu.tmpl | 4 +-
25 files changed, 70 insertions(+), 105 deletions(-)
diff --git a/.deadcode-out b/.deadcode-out
index c63fd9e0af..1b65e3203d 100644
--- a/.deadcode-out
+++ b/.deadcode-out
@@ -341,5 +341,4 @@ package "code.gitea.io/gitea/services/repository/files"
package "code.gitea.io/gitea/services/webhook"
func NewNotifier
- func List
diff --git a/options/locale/locale_bg.ini b/options/locale/locale_bg.ini
index 5b9bb0715e..6b482d3f2a 100644
--- a/options/locale/locale_bg.ini
+++ b/options/locale/locale_bg.ini
@@ -928,9 +928,9 @@ settings.web_hook_name_discord = Discord
settings.web_hook_name_telegram = Telegram
settings.web_hook_name_matrix = Matrix
settings.web_hook_name_gogs = Gogs
-settings.web_hook_name_feishu_or_larksuite = Feishu / Lark Suite
-settings.web_hook_name_feishu = Feishu
-settings.web_hook_name_larksuite = Lark Suite
+settings.web_hook_name_feishu = Feishu / Lark Suite
+settings.web_hook_name_feishu_only = Feishu
+settings.web_hook_name_larksuite_only = Lark Suite
settings.web_hook_name_wechatwork = WeCom (Wechat Work)
settings.web_hook_name_packagist = Packagist
diff.file_byte_size = ะ ะฐะทะผะตั
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 3747ae28c9..86e7f54d80 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -2306,9 +2306,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Uลพivatelskรฉ jmรฉno pro Packagist
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index f5aafdf5c9..9792692a75 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -2302,9 +2302,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Benutzername fรผr Packagist
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 36b7518c62..b9d2881d8a 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -2293,9 +2293,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=ฮฮฝฮฟฮผฮฑ ฯฯฮฎฯฯฮท Packagist
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index c28ed6c376..67ec3b1960 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -2372,9 +2372,9 @@ settings.web_hook_name_dingtalk = DingTalk
settings.web_hook_name_telegram = Telegram
settings.web_hook_name_matrix = Matrix
settings.web_hook_name_msteams = Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite = Feishu / Lark Suite
-settings.web_hook_name_feishu = Feishu
-settings.web_hook_name_larksuite = Lark Suite
+settings.web_hook_name_feishu = Feishu / Lark Suite
+settings.web_hook_name_feishu_only = Feishu
+settings.web_hook_name_larksuite_only = Lark Suite
settings.web_hook_name_wechatwork = WeCom (Wechat Work)
settings.web_hook_name_packagist = Packagist
settings.packagist_username = Packagist username
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index 3dbca87381..a2794ccd3d 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -2267,9 +2267,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nombre de usuario Packagist
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index c6c64ad6ce..31dca19f33 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -1184,8 +1184,8 @@ settings.web_hook_name_discord=Discord
settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_packagist=Packagist
settings.deploy_keys=Julkaisuavaimet
settings.add_deploy_key=Lisรครค julkaisuavain
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 659615e6ff..d3e015a632 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -2317,9 +2317,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nom d'utilisateur Packagist
diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini
index 27b9a4b17c..e76174cde2 100644
--- a/options/locale/locale_is-IS.ini
+++ b/options/locale/locale_is-IS.ini
@@ -1065,7 +1065,7 @@ settings.web_hook_name_discord=Discord
settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu=Feishu
+settings.web_hook_name_feishu_only =Feishu
settings.title=Heiti
settings.deploy_key_content=Innihald
settings.branches=Greinar
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index dc6f4c127e..d25fc0942d 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -2085,9 +2085,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nome utente Packagist
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 7f3e1ded36..8dbc3e90bf 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -2301,9 +2301,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist ใฆใผใถใผๅ
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index ce8f05e4b5..20ca341ee4 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -2253,9 +2253,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist lietotฤjvฤrds
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 4358cc1e81..41af8e7b03 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -2030,9 +2030,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist gebruikersnaam
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 086cea74fa..f2a72c5c7f 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -2236,9 +2236,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nome de usuรกrio no Packagist
diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini
index 3538ac9460..552695a455 100644
--- a/options/locale/locale_pt-PT.ini
+++ b/options/locale/locale_pt-PT.ini
@@ -2269,9 +2269,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Nome de utilizador no Packagist
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index addc2f8110..b4d246d9f9 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -2276,9 +2276,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu ะธะปะธ Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu ะธะปะธ Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=ะะผั ะฟะพะปัะทะพะฒะฐัะตะปั Packagist
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index 74ef77eb19..b6bb510ab4 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -2252,9 +2252,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist kullanฤฑcฤฑ adฤฑ
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 4ca2e70f21..b4e21c23ee 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -2316,9 +2316,9 @@ settings.web_hook_name_dingtalk=้้
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=้ฃไนฆ / Lark Suite
-settings.web_hook_name_feishu=้ฃไนฆ
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=้ฃไนฆ / Lark Suite
+settings.web_hook_name_feishu_only =้ฃไนฆ
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=ไผไธๅพฎไฟก
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist ็จๆทๅ
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index 5bfff77fd2..a2e3f512ff 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -2071,9 +2071,9 @@ settings.web_hook_name_dingtalk=DingTalk
settings.web_hook_name_telegram=Telegram
settings.web_hook_name_matrix=Matrix
settings.web_hook_name_msteams=Microsoft Teams
-settings.web_hook_name_feishu_or_larksuite=Feishu / Lark Suite
-settings.web_hook_name_feishu=Feishu
-settings.web_hook_name_larksuite=Lark Suite
+settings.web_hook_name_feishu=Feishu / Lark Suite
+settings.web_hook_name_feishu_only =Feishu
+settings.web_hook_name_larksuite_only =Lark Suite
settings.web_hook_name_wechatwork=WeCom (Wechat Work)
settings.web_hook_name_packagist=Packagist
settings.packagist_username=Packagist ๅธณ่
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 494ada4323..0be734abaf 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -26,6 +26,7 @@ import (
org_service "code.gitea.io/gitea/services/org"
repo_service "code.gitea.io/gitea/services/repository"
user_service "code.gitea.io/gitea/services/user"
+ webhook_service "code.gitea.io/gitea/services/webhook"
)
const (
@@ -210,6 +211,7 @@ func Webhooks(ctx *context.Context) {
ctx.Data["PageIsSettingsHooks"] = true
ctx.Data["BaseLink"] = ctx.Org.OrgLink + "/settings/hooks"
ctx.Data["BaseLinkNew"] = ctx.Org.OrgLink + "/settings/hooks"
+ ctx.Data["WebhookList"] = webhook_service.List()
ctx.Data["Description"] = ctx.Tr("org.settings.hooks_desc")
ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Org.Organization.ID})
diff --git a/routers/web/repo/setting/webhook.go b/routers/web/repo/setting/webhook.go
index c36ebf5b14..4469eac9e8 100644
--- a/routers/web/repo/setting/webhook.go
+++ b/routers/web/repo/setting/webhook.go
@@ -45,6 +45,7 @@ func WebhookList(ctx *context.Context) {
ctx.Data["PageIsSettingsHooks"] = true
ctx.Data["BaseLink"] = ctx.Repo.RepoLink + "/settings/hooks"
ctx.Data["BaseLinkNew"] = ctx.Repo.RepoLink + "/settings/hooks"
+ ctx.Data["WebhookList"] = webhook_service.List()
ctx.Data["Description"] = ctx.Tr("repo.settings.hooks_desc", "https://forgejo.org/docs/latest/user/webhooks/")
ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{RepoID: ctx.Repo.Repository.ID})
@@ -141,6 +142,7 @@ func WebhookNew(ctx *context.Context) {
ctx.Data["WebhookHandler"] = handler
ctx.Data["BaseLink"] = orCtx.LinkNew
ctx.Data["BaseLinkNew"] = orCtx.LinkNew
+ ctx.Data["WebhookList"] = webhook_service.List()
ctx.HTML(http.StatusOK, orCtx.NewTemplate)
}
@@ -205,6 +207,7 @@ func WebhookCreate(ctx *context.Context) {
}
ctx.Data["BaseLink"] = orCtx.LinkNew
ctx.Data["BaseLinkNew"] = orCtx.LinkNew
+ ctx.Data["WebhookList"] = webhook_service.List()
if ctx.HasError() {
// pre-fill the form with the submitted data
@@ -339,6 +342,7 @@ func checkWebhook(ctx *context.Context) (*ownerRepoCtx, *webhook.Webhook) {
}
ctx.Data["BaseLink"] = orCtx.Link
ctx.Data["BaseLinkNew"] = orCtx.LinkNew
+ ctx.Data["WebhookList"] = webhook_service.List()
var w *webhook.Webhook
if orCtx.RepoID > 0 {
diff --git a/routers/web/user/setting/webhooks.go b/routers/web/user/setting/webhooks.go
index 4423b62781..3cc67d9def 100644
--- a/routers/web/user/setting/webhooks.go
+++ b/routers/web/user/setting/webhooks.go
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/context"
+ webhook_service "code.gitea.io/gitea/services/webhook"
)
const (
@@ -23,6 +24,7 @@ func Webhooks(ctx *context.Context) {
ctx.Data["PageIsSettingsHooks"] = true
ctx.Data["BaseLink"] = setting.AppSubURL + "/user/settings/hooks"
ctx.Data["BaseLinkNew"] = setting.AppSubURL + "/user/settings/hooks"
+ ctx.Data["WebhookList"] = webhook_service.List()
ctx.Data["Description"] = ctx.Tr("settings.hooks.desc")
ws, err := db.Find[webhook.Webhook](ctx, webhook.ListWebhookOptions{OwnerID: ctx.Doer.ID})
diff --git a/templates/repo/settings/webhook/link_menu.tmpl b/templates/repo/settings/webhook/link_menu.tmpl
index 811e262db6..2edc5af4ac 100644
--- a/templates/repo/settings/webhook/link_menu.tmpl
+++ b/templates/repo/settings/webhook/link_menu.tmpl
@@ -3,52 +3,10 @@
{{$size = .Size}}
{{end}}
diff --git a/templates/webhook/new/feishu.tmpl b/templates/webhook/new/feishu.tmpl
index b691c3f18c..ead11770de 100644
--- a/templates/webhook/new/feishu.tmpl
+++ b/templates/webhook/new/feishu.tmpl
@@ -1,5 +1,5 @@
-{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://feishu.cn" (ctx.Locale.Tr "repo.settings.web_hook_name_feishu")}}
-{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://larksuite.com" (ctx.Locale.Tr "repo.settings.web_hook_name_larksuite")}}
+{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://feishu.cn" (ctx.Locale.Tr "repo.settings.web_hook_name_feishu_only")}}
+{{ctx.Locale.Tr "repo.settings.add_web_hook_desc" "https://larksuite.com" (ctx.Locale.Tr "repo.settings.web_hook_name_larksuite_only")}}