mirror of
https://github.com/go-gitea/gitea.git
synced 2024-09-28 03:06:03 -04:00
Merge remote-tracking branch 'origin/main' into zzc/dev/sidebar_board_option
This commit is contained in:
commit
ae9d6292f1
@ -10,7 +10,8 @@
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "3.12"
|
||||
}
|
||||
},
|
||||
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
@ -25,7 +26,7 @@
|
||||
"Vue.volar",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"vitest.explorer",
|
||||
"qwtel.sqlite-viewer",
|
||||
"cweijan.vscode-database-client2",
|
||||
"GitHub.vscode-pull-request-github",
|
||||
"Azurite.azurite"
|
||||
]
|
||||
|
@ -43,7 +43,7 @@ vscode:
|
||||
- Vue.volar
|
||||
- ms-azuretools.vscode-docker
|
||||
- vitest.explorer
|
||||
- qwtel.sqlite-viewer
|
||||
- cweijan.vscode-database-client2
|
||||
- GitHub.vscode-pull-request-github
|
||||
|
||||
ports:
|
||||
|
4
Makefile
4
Makefile
@ -25,10 +25,10 @@ COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.22.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285
|
||||
|
@ -1687,6 +1687,16 @@ LEVEL = Info
|
||||
;; convert \r\n to \n for Sendmail
|
||||
;SENDMAIL_CONVERT_CRLF = true
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[mailer.override_header]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; This is empty by default, use it only if you know what you need it for.
|
||||
;Reply-To = test@example.com, test2@example.com
|
||||
;Content-Type = text/html; charset=utf-8
|
||||
;In-Reply-To =
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[email.incoming]
|
||||
|
@ -724,11 +724,13 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
|
||||
|
||||
## Mailer (`mailer`)
|
||||
|
||||
⚠️ This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
|
||||
:::warning
|
||||
This section is for Gitea 1.18 and later. If you are using Gitea 1.17 or older,
|
||||
please refer to
|
||||
[Gitea 1.17 app.ini example](https://github.com/go-gitea/gitea/blob/release/v1.17/custom/conf/app.example.ini)
|
||||
and
|
||||
[Gitea 1.17 configuration document](https://github.com/go-gitea/gitea/blob/release/v1.17/docs/content/doc/advanced/config-cheat-sheet.en-us.md)
|
||||
:::
|
||||
|
||||
- `ENABLED`: **false**: Enable to use a mail service.
|
||||
- `PROTOCOL`: **_empty_**: Mail server protocol. One of "smtp", "smtps", "smtp+starttls", "smtp+unix", "sendmail", "dummy". _Before 1.18, this was inferred from a combination of `MAILER_TYPE` and `IS_TLS_ENABLED`._
|
||||
@ -761,6 +763,21 @@ and
|
||||
- `SEND_BUFFER_LEN`: **100**: Buffer length of mailing queue. **DEPRECATED** use `LENGTH` in `[queue.mailer]`
|
||||
- `SEND_AS_PLAIN_TEXT`: **false**: Send mails only in plain text, without HTML alternative.
|
||||
|
||||
## Override Email Headers (`mailer.override_header`)
|
||||
|
||||
:::warning
|
||||
This is empty by default, use it only if you know what you need it for.
|
||||
:::
|
||||
|
||||
examples would be:
|
||||
|
||||
```ini
|
||||
[mailer.override_header]
|
||||
Reply-To = test@example.com, test2@example.com
|
||||
Content-Type = text/html; charset=utf-8
|
||||
In-Reply-To =
|
||||
```
|
||||
|
||||
## Incoming Email (`email.incoming`)
|
||||
|
||||
- `ENABLED`: **false**: Enable handling of incoming emails.
|
||||
|
2
go.mod
2
go.mod
@ -20,7 +20,7 @@ require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||
github.com/ProtonMail/go-crypto v1.0.0
|
||||
github.com/PuerkitoBio/goquery v1.9.1
|
||||
github.com/alecthomas/chroma/v2 v2.13.0
|
||||
github.com/alecthomas/chroma/v2 v2.14.0
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.3.10
|
||||
github.com/buildkite/terminal-to-html/v3 v3.11.0
|
||||
|
8
go.sum
8
go.sum
@ -82,11 +82,11 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06
|
||||
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
|
||||
github.com/RoaringBitmap/roaring v1.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE=
|
||||
github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
|
||||
github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
|
||||
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E=
|
||||
github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
|
@ -26,6 +26,7 @@ type Mailer struct {
|
||||
FromEmail string `ini:"-"`
|
||||
SendAsPlainText bool `ini:"SEND_AS_PLAIN_TEXT"`
|
||||
SubjectPrefix string `ini:"SUBJECT_PREFIX"`
|
||||
OverrideHeader map[string][]string `ini:"-"`
|
||||
|
||||
// SMTP sender
|
||||
Protocol string `ini:"PROTOCOL"`
|
||||
@ -151,6 +152,12 @@ func loadMailerFrom(rootCfg ConfigProvider) {
|
||||
log.Fatal("Unable to map [mailer] section on to MailService. Error: %v", err)
|
||||
}
|
||||
|
||||
overrideHeader := rootCfg.Section("mailer.override_header").Keys()
|
||||
MailService.OverrideHeader = make(map[string][]string)
|
||||
for _, key := range overrideHeader {
|
||||
MailService.OverrideHeader[key.Name()] = key.Strings(",")
|
||||
}
|
||||
|
||||
// Infer SMTPPort if not set
|
||||
if MailService.SMTPPort == "" {
|
||||
switch MailService.Protocol {
|
||||
|
@ -8,6 +8,9 @@ import "time"
|
||||
type Activity struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"` // Receiver user
|
||||
// the type of action
|
||||
//
|
||||
// enum: create_repo,rename_repo,star_repo,watch_repo,commit_repo,create_issue,create_pull_request,transfer_repo,push_tag,comment_issue,merge_pull_request,close_issue,reopen_issue,close_pull_request,reopen_pull_request,delete_tag,delete_branch,mirror_sync_push,mirror_sync_create,mirror_sync_delete,approve_pull_request,reject_pull_request,comment_pull,publish_release,pull_review_dismissed,pull_request_ready_for_review,auto_merge_pull_request
|
||||
OpType string `json:"op_type"`
|
||||
ActUserID int64 `json:"act_user_id"`
|
||||
ActUser *User `json:"act_user"`
|
||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"@citation-js/plugin-csl": "0.7.11",
|
||||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/relative-time-element": "4.4.1",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@primer/octicons": "19.9.0",
|
||||
@ -1028,9 +1028,9 @@
|
||||
"integrity": "sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A=="
|
||||
},
|
||||
"node_modules/@github/relative-time-element": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.0.tgz",
|
||||
"integrity": "sha512-CrI6oAecoahG7PF5dsgjdvlF5kCtusVMjg810EULD81TvnDsP+k/FRi/ClFubWLgBo4EGpr2EfvmumtqQFo7ow=="
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.1.tgz",
|
||||
"integrity": "sha512-E2vRcIgDj8AHv/iHpQMLJ/RqKOJ704OXkKw6+Zdhk3X+kVQhOf3Wj8KVz4DfCQ1eOJR8XxY6XVv73yd+pjMfXA=="
|
||||
},
|
||||
"node_modules/@github/text-expander-element": {
|
||||
"version": "2.6.1",
|
||||
|
@ -9,7 +9,7 @@
|
||||
"@citation-js/plugin-csl": "0.7.11",
|
||||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.0",
|
||||
"@github/relative-time-element": "4.4.1",
|
||||
"@github/text-expander-element": "2.6.1",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@primer/octicons": "19.9.0",
|
||||
|
@ -96,20 +96,34 @@ func FeedCapabilityResource(ctx *context.Context) {
|
||||
xmlResponse(ctx, http.StatusOK, Metadata)
|
||||
}
|
||||
|
||||
var searchTermExtract = regexp.MustCompile(`'([^']+)'`)
|
||||
var (
|
||||
searchTermExtract = regexp.MustCompile(`'([^']+)'`)
|
||||
searchTermExact = regexp.MustCompile(`\s+eq\s+'`)
|
||||
)
|
||||
|
||||
func getSearchTerm(ctx *context.Context) string {
|
||||
func getSearchTerm(ctx *context.Context) packages_model.SearchValue {
|
||||
searchTerm := strings.Trim(ctx.FormTrim("searchTerm"), "'")
|
||||
if searchTerm == "" {
|
||||
if searchTerm != "" {
|
||||
return packages_model.SearchValue{
|
||||
Value: searchTerm,
|
||||
ExactMatch: false,
|
||||
}
|
||||
}
|
||||
|
||||
// $filter contains a query like:
|
||||
// (((Id ne null) and substringof('microsoft',tolower(Id)))
|
||||
// https://www.odata.org/documentation/odata-version-2-0/uri-conventions/ section 4.5
|
||||
// We don't support these queries, just extract the search term.
|
||||
match := searchTermExtract.FindStringSubmatch(ctx.FormTrim("$filter"))
|
||||
filter := ctx.FormTrim("$filter")
|
||||
match := searchTermExtract.FindStringSubmatch(filter)
|
||||
if len(match) == 2 {
|
||||
searchTerm = strings.TrimSpace(match[1])
|
||||
return packages_model.SearchValue{
|
||||
Value: strings.TrimSpace(match[1]),
|
||||
ExactMatch: searchTermExact.MatchString(filter),
|
||||
}
|
||||
}
|
||||
return searchTerm
|
||||
|
||||
return packages_model.SearchValue{}
|
||||
}
|
||||
|
||||
// https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Protocol/LegacyFeed/V2FeedQueryBuilder.cs
|
||||
@ -120,9 +134,7 @@ func SearchServiceV2(ctx *context.Context) {
|
||||
pvs, total, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
|
||||
OwnerID: ctx.Package.Owner.ID,
|
||||
Type: packages_model.TypeNuGet,
|
||||
Name: packages_model.SearchValue{
|
||||
Value: getSearchTerm(ctx),
|
||||
},
|
||||
Name: getSearchTerm(ctx),
|
||||
IsInternal: optional.Some(false),
|
||||
Paginator: paginator,
|
||||
})
|
||||
@ -170,9 +182,7 @@ func SearchServiceV2(ctx *context.Context) {
|
||||
func SearchServiceV2Count(ctx *context.Context) {
|
||||
count, err := nuget_model.CountPackages(ctx, &packages_model.PackageSearchOptions{
|
||||
OwnerID: ctx.Package.Owner.ID,
|
||||
Name: packages_model.SearchValue{
|
||||
Value: getSearchTerm(ctx),
|
||||
},
|
||||
Name: getSearchTerm(ctx),
|
||||
IsInternal: optional.Some(false),
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -156,7 +156,7 @@ func GetContentHistoryDetail(ctx *context.Context) {
|
||||
|
||||
// use chroma to render the diff html
|
||||
diffHTMLBuf := bytes.Buffer{}
|
||||
diffHTMLBuf.WriteString("<pre class='chroma' style='tab-size: 4'>")
|
||||
diffHTMLBuf.WriteString("<pre class='chroma'>")
|
||||
for _, it := range diff {
|
||||
if it.Type == diffmatchpatch.DiffInsert {
|
||||
diffHTMLBuf.WriteString("<span class='gi'>")
|
||||
|
@ -1061,7 +1061,7 @@ func readFileName(rd *strings.Reader) (string, bool) {
|
||||
char, _ := rd.ReadByte()
|
||||
_ = rd.UnreadByte()
|
||||
if char == '"' {
|
||||
fmt.Fscanf(rd, "%q ", &name)
|
||||
_, _ = fmt.Fscanf(rd, "%q ", &name)
|
||||
if len(name) == 0 {
|
||||
log.Error("Reader has no file name: reader=%+v", rd)
|
||||
return "", true
|
||||
@ -1073,12 +1073,12 @@ func readFileName(rd *strings.Reader) (string, bool) {
|
||||
} else {
|
||||
// This technique is potentially ambiguous it may not be possible to uniquely identify the filenames from the diff line alone
|
||||
ambiguity = true
|
||||
fmt.Fscanf(rd, "%s ", &name)
|
||||
_, _ = fmt.Fscanf(rd, "%s ", &name)
|
||||
char, _ := rd.ReadByte()
|
||||
_ = rd.UnreadByte()
|
||||
for !(char == 0 || char == '"' || char == 'b') {
|
||||
var suffix string
|
||||
fmt.Fscanf(rd, "%s ", &suffix)
|
||||
_, _ = fmt.Fscanf(rd, "%s ", &suffix)
|
||||
name += " " + suffix
|
||||
char, _ = rd.ReadByte()
|
||||
_ = rd.UnreadByte()
|
||||
|
@ -57,7 +57,7 @@ func (m *Message) ToMessage() *gomail.Message {
|
||||
msg.SetHeader(header, m.Headers[header]...)
|
||||
}
|
||||
|
||||
if len(setting.MailService.SubjectPrefix) > 0 {
|
||||
if setting.MailService.SubjectPrefix != "" {
|
||||
msg.SetHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject)
|
||||
} else {
|
||||
msg.SetHeader("Subject", m.Subject)
|
||||
@ -79,6 +79,14 @@ func (m *Message) ToMessage() *gomail.Message {
|
||||
if len(msg.GetHeader("Message-ID")) == 0 {
|
||||
msg.SetHeader("Message-ID", m.generateAutoMessageID())
|
||||
}
|
||||
|
||||
for k, v := range setting.MailService.OverrideHeader {
|
||||
if len(msg.GetHeader(k)) != 0 {
|
||||
log.Debug("Mailer override header '%s' as per config", k)
|
||||
}
|
||||
msg.SetHeader(k, v...)
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
package mailer
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -36,3 +37,78 @@ func TestGenerateMessageID(t *testing.T) {
|
||||
gm = m.ToMessage()
|
||||
assert.Equal(t, "<msg-d@domain.com>", gm.GetHeader("Message-ID")[0])
|
||||
}
|
||||
|
||||
func TestToMessage(t *testing.T) {
|
||||
oldConf := *setting.MailService
|
||||
defer func() {
|
||||
setting.MailService = &oldConf
|
||||
}()
|
||||
setting.MailService.From = "test@gitea.com"
|
||||
|
||||
m1 := Message{
|
||||
Info: "info",
|
||||
FromAddress: "test@gitea.com",
|
||||
FromDisplayName: "Test Gitea",
|
||||
To: "a@b.com",
|
||||
Subject: "Issue X Closed",
|
||||
Body: "Some Issue got closed by Y-Man",
|
||||
}
|
||||
|
||||
buf := &strings.Builder{}
|
||||
_, err := m1.ToMessage().WriteTo(buf)
|
||||
assert.NoError(t, err)
|
||||
header, _ := extractMailHeaderAndContent(t, buf.String())
|
||||
assert.EqualValues(t, map[string]string{
|
||||
"Content-Type": "multipart/alternative;",
|
||||
"Date": "Mon, 01 Jan 0001 00:00:00 +0000",
|
||||
"From": "\"Test Gitea\" <test@gitea.com>",
|
||||
"Message-ID": "<autogen--6795364578871-69c000786adc60dc@localhost>",
|
||||
"Mime-Version": "1.0",
|
||||
"Subject": "Issue X Closed",
|
||||
"To": "a@b.com",
|
||||
"X-Auto-Response-Suppress": "All",
|
||||
}, header)
|
||||
|
||||
setting.MailService.OverrideHeader = map[string][]string{
|
||||
"Message-ID": {""}, // delete message id
|
||||
"Auto-Submitted": {"auto-generated"}, // suppress auto replay
|
||||
}
|
||||
|
||||
buf = &strings.Builder{}
|
||||
_, err = m1.ToMessage().WriteTo(buf)
|
||||
assert.NoError(t, err)
|
||||
header, _ = extractMailHeaderAndContent(t, buf.String())
|
||||
assert.EqualValues(t, map[string]string{
|
||||
"Content-Type": "multipart/alternative;",
|
||||
"Date": "Mon, 01 Jan 0001 00:00:00 +0000",
|
||||
"From": "\"Test Gitea\" <test@gitea.com>",
|
||||
"Message-ID": "",
|
||||
"Mime-Version": "1.0",
|
||||
"Subject": "Issue X Closed",
|
||||
"To": "a@b.com",
|
||||
"X-Auto-Response-Suppress": "All",
|
||||
"Auto-Submitted": "auto-generated",
|
||||
}, header)
|
||||
}
|
||||
|
||||
func extractMailHeaderAndContent(t *testing.T, mail string) (map[string]string, string) {
|
||||
header := make(map[string]string)
|
||||
|
||||
parts := strings.SplitN(mail, "boundary=", 2)
|
||||
if !assert.Len(t, parts, 2) {
|
||||
return nil, ""
|
||||
}
|
||||
content := strings.TrimSpace("boundary=" + parts[1])
|
||||
|
||||
hParts := strings.Split(parts[0], "\n")
|
||||
|
||||
for _, hPart := range hParts {
|
||||
parts := strings.SplitN(hPart, ":", 2)
|
||||
hk := strings.TrimSpace(parts[0])
|
||||
if hk != "" {
|
||||
header[hk] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
|
||||
return header, content
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {readFileSync} from 'node:fs';
|
||||
import {env} from 'node:process';
|
||||
import {parse} from 'postcss';
|
||||
import plugin from 'tailwindcss/plugin.js';
|
||||
|
||||
const isProduction = env.NODE_ENV !== 'development';
|
||||
|
||||
@ -98,4 +99,26 @@ export default {
|
||||
})),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
plugin(({addUtilities}) => {
|
||||
addUtilities({
|
||||
// tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
|
||||
// do not use:
|
||||
// * "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
|
||||
// * ".hidden" class: it has been polluted by Fomantic UI in many cases
|
||||
// * inline style="display: none": it's difficult to tweak
|
||||
// * jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
|
||||
// only use:
|
||||
// * this ".tw-hidden" class
|
||||
// * showElem/hideElem/toggleElem functions in "utils/dom.js"
|
||||
'.hidden.hidden': {
|
||||
'display': 'none',
|
||||
},
|
||||
// proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128
|
||||
'.break-anywhere': {
|
||||
'overflow-wrap': 'anywhere',
|
||||
},
|
||||
});
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{range .RecentlyPushedNewBranches}}
|
||||
<div class="ui positive message tw-flex tw-items-center">
|
||||
<div class="tw-flex-1">
|
||||
<div class="ui positive message tw-flex tw-items-center tw-gap-2">
|
||||
<div class="tw-flex-1 tw-break-anywhere">
|
||||
{{$timeSince := TimeSince .CommitTime.AsTime ctx.Locale}}
|
||||
{{$branchLink := HTMLFormat `<a href="%s">%s</a>` .BranchLink .BranchDisplayName}}
|
||||
{{ctx.Locale.Tr "repo.pulls.recently_pushed_new_branches" $branchLink $timeSince}}
|
||||
|
30
templates/swagger/v1_json.tmpl
generated
30
templates/swagger/v1_json.tmpl
generated
@ -18178,7 +18178,37 @@
|
||||
"x-go-name": "IsPrivate"
|
||||
},
|
||||
"op_type": {
|
||||
"description": "the type of action",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"create_repo",
|
||||
"rename_repo",
|
||||
"star_repo",
|
||||
"watch_repo",
|
||||
"commit_repo",
|
||||
"create_issue",
|
||||
"create_pull_request",
|
||||
"transfer_repo",
|
||||
"push_tag",
|
||||
"comment_issue",
|
||||
"merge_pull_request",
|
||||
"close_issue",
|
||||
"reopen_issue",
|
||||
"close_pull_request",
|
||||
"reopen_pull_request",
|
||||
"delete_tag",
|
||||
"delete_branch",
|
||||
"mirror_sync_push",
|
||||
"mirror_sync_create",
|
||||
"mirror_sync_delete",
|
||||
"approve_pull_request",
|
||||
"reject_pull_request",
|
||||
"comment_pull",
|
||||
"publish_release",
|
||||
"pull_review_dismissed",
|
||||
"pull_request_ready_for_review",
|
||||
"auto_merge_pull_request"
|
||||
],
|
||||
"x-go-name": "OpType"
|
||||
},
|
||||
"ref_name": {
|
||||
|
@ -44,14 +44,14 @@
|
||||
{{end}}
|
||||
</div>
|
||||
<a class="notifications-link tw-flex tw-flex-1 tw-flex-col silenced" href="{{.Link ctx}}">
|
||||
<div class="notifications-top-row tw-text-13">
|
||||
<div class="notifications-top-row tw-text-13 tw-break-anywhere">
|
||||
{{.Repository.FullName}} {{if .Issue}}<span class="text light-3">#{{.Issue.Index}}</span>{{end}}
|
||||
{{if eq .Status 3}}
|
||||
{{svg "octicon-pin" 13 "text blue tw-mt-0.5 tw-ml-1"}}
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="notifications-bottom-row tw-text-16 tw-py-0.5">
|
||||
<span class="issue-title">
|
||||
<span class="issue-title tw-break-anywhere">
|
||||
{{if .Issue}}
|
||||
{{.Issue.Title | RenderEmoji $.Context | RenderCodeBlock}}
|
||||
{{else}}
|
||||
|
@ -434,17 +434,28 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
|
||||
Take int
|
||||
ExpectedTotal int64
|
||||
ExpectedResults int
|
||||
ExpectedExactMatch bool
|
||||
}{
|
||||
{"", 0, 0, 1, 1},
|
||||
{"", 0, 10, 1, 1},
|
||||
{"gitea", 0, 10, 0, 0},
|
||||
{"test", 0, 10, 1, 1},
|
||||
{"test", 1, 10, 1, 0},
|
||||
{"", 0, 0, 4, 4, false},
|
||||
{"", 0, 10, 4, 4, false},
|
||||
{"gitea", 0, 10, 0, 0, false},
|
||||
{"test", 0, 10, 1, 1, false},
|
||||
{"test", 1, 10, 1, 0, false},
|
||||
{"almost.similar", 0, 0, 3, 3, true},
|
||||
}
|
||||
|
||||
req := NewRequestWithBody(t, "PUT", url, createPackage(packageName, "1.0.99")).
|
||||
fakePackages := []string{
|
||||
packageName,
|
||||
"almost.similar.dependency",
|
||||
"almost.similar",
|
||||
"almost.similar.dependant",
|
||||
}
|
||||
|
||||
for _, fakePackageName := range fakePackages {
|
||||
req := NewRequestWithBody(t, "PUT", url, createPackage(fakePackageName, "1.0.99")).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
}
|
||||
|
||||
t.Run("v2", func(t *testing.T) {
|
||||
t.Run("Search()", func(t *testing.T) {
|
||||
@ -491,6 +502,63 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Packages()", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("substringof", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
for i, c := range cases {
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result FeedResponse
|
||||
decodeXML(t, resp, &result)
|
||||
|
||||
assert.Equal(t, c.ExpectedTotal, result.Count, "case %d: unexpected total hits", i)
|
||||
assert.Len(t, result.Entries, c.ExpectedResults, "case %d: unexpected result count", i)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=substringof('%s',tolower(Id))&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, strconv.FormatInt(c.ExpectedTotal, 10), resp.Body.String(), "case %d: unexpected total hits", i)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IdEq", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
for i, c := range cases {
|
||||
if c.Query == "" {
|
||||
// Ignore the `tolower(Id) eq ''` as it's unlikely to happen
|
||||
continue
|
||||
}
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("%s/Packages()?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result FeedResponse
|
||||
decodeXML(t, resp, &result)
|
||||
|
||||
expectedCount := 0
|
||||
if c.ExpectedExactMatch {
|
||||
expectedCount = 1
|
||||
}
|
||||
|
||||
assert.Equal(t, int64(expectedCount), result.Count, "case %d: unexpected total hits", i)
|
||||
assert.Len(t, result.Entries, expectedCount, "case %d: unexpected result count", i)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("%s/Packages()/$count?$filter=(tolower(Id) eq '%s')&$skip=%d&$top=%d", url, c.Query, c.Skip, c.Take)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, strconv.FormatInt(int64(expectedCount), 10), resp.Body.String(), "case %d: unexpected total hits", i)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Next", func(t *testing.T) {
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("%s/Search()?searchTerm='test'&$skip=0&$top=1", url)).
|
||||
AddBasicAuth(user.Name)
|
||||
@ -548,9 +616,11 @@ AAAjQmxvYgAAAGm7ENm9SGxMtAFVvPUsPJTF6PbtAAAAAFcVogEJAAAAAQAAAA==`)
|
||||
})
|
||||
})
|
||||
|
||||
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, packageName, "1.0.99")).
|
||||
for _, fakePackageName := range fakePackages {
|
||||
req := NewRequest(t, "DELETE", fmt.Sprintf("%s/%s/%s", url, fakePackageName, "1.0.99")).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RegistrationService", func(t *testing.T) {
|
||||
|
@ -35,22 +35,6 @@ Gitea's private styles use `g-` prefix.
|
||||
.interact-bg:hover { background: var(--color-hover) !important; }
|
||||
.interact-bg:active { background: var(--color-active) !important; }
|
||||
|
||||
/*
|
||||
tw-hidden must win all other "display: xxx !important" classes to get the chance to "hide" an element.
|
||||
do not use:
|
||||
* "[hidden]" attribute: it's too weak, can not be applied to an element with "display: flex"
|
||||
* ".hidden" class: it has been polluted by Fomantic UI in many cases
|
||||
* inline style="display: none": it's difficult to tweak
|
||||
* jQuery's show/hide/toggle: it can not show/hide elements with "display: xxx !important"
|
||||
only use:
|
||||
* this ".tw-hidden" class
|
||||
* showElem/hideElem/toggleElem functions in "utils/dom.js"
|
||||
*/
|
||||
.tw-hidden.tw-hidden { display: none !important; }
|
||||
|
||||
/* proposed class from https://github.com/tailwindlabs/tailwindcss/pull/12128 */
|
||||
.tw-break-anywhere { overflow-wrap: anywhere !important; }
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
/* double selector so it wins over .tw-flex (old .gt-df) etc */
|
||||
.not-mobile.not-mobile {
|
||||
|
@ -2322,6 +2322,7 @@ tbody.commit-list {
|
||||
min-height: 12em;
|
||||
max-height: calc(100vh - 10.5rem);
|
||||
overflow-y: auto;
|
||||
tab-size: 4;
|
||||
}
|
||||
|
||||
.comment-diff-data pre {
|
||||
|
Loading…
Reference in New Issue
Block a user