Compare commits

...

10 Commits

Author SHA1 Message Date
silverwind f566eb6bdf
Merge 50e995277f into 2f6b1c46a1 2024-04-23 20:55:41 +02:00
sillyguodong 2f6b1c46a1
Interpolate runs-on with variables when scheduling tasks (#30640)
Follow #29468
1. Interpolate runs-on with variables when scheduling tasks.
2. The `GetVariablesOfRun` function will check if the `Repo` of the run
is nil.

---------

Co-authored-by: Giteabot <teabot@gitea.io>
2024-04-23 20:55:25 +02:00
silverwind 50e995277f
move to tools 2024-04-23 19:24:25 +02:00
wxiaoguang b79e3db264
Initial support for colorblindness-friendly themes (#30625)
Initial support for #25680

This PR only adds some simple styles from GitHub, it is big enough and
it focuses on adding the necessary framework-level supports. More styles
could be fine-tuned later.
2024-04-24 00:18:41 +08:00
silverwind 7292423323
Merge branch 'main' into misspell050 2024-04-21 22:28:12 +02:00
silverwind a849f1421d
fmt 2024-04-21 22:26:12 +02:00
silverwind 415a19d8ea
reviewNotifers -> reviewNotifiers 2024-04-21 22:25:46 +02:00
silverwind 0911041761
revert the api change and remove comiter from word list 2024-04-21 22:22:51 +02:00
silverwind e44fccf006
update to 0.5.1 and run fix again 2024-04-21 22:19:09 +02:00
silverwind 13b9aed475
Update misspell to 0.5.0 and add typos.csv 2024-04-18 19:58:21 +02:00
58 changed files with 285 additions and 181 deletions

View File

@ -30,7 +30,7 @@ EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-che
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
@ -397,11 +397,11 @@ lint-md: node_modules
.PHONY: lint-spell
lint-spell:
@go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES)
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -error $(SPELLCHECK_FILES)
.PHONY: lint-spell-fix
lint-spell-fix:
@go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES)
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -w $(SPELLCHECK_FILES)
.PHONY: lint-go
lint-go:

View File

@ -1231,7 +1231,8 @@ LEVEL = Info
;DEFAULT_THEME = gitea-auto
;;
;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
;THEMES = gitea-auto,gitea-light,gitea-dark
;; Leave it empty to allow users to select any theme from "{CustomPath}/public/assets/css/theme-*.css"
;THEMES =
;;
;; All available reactions users can choose on issues/prs and comments.
;; Values can be emoji alias (:smile:) or a unicode emoji.

View File

@ -214,10 +214,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a
- `SITEMAP_PAGING_NUM`: **20**: Number of items that are displayed in a single subsitemap.
- `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph.
- `CODE_COMMENT_LINES`: **4**: Number of line of codes shown for a code comment.
- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: Set the default theme for the Gitea installation.
- `DEFAULT_THEME`: **gitea-auto**: Set the default theme for the Gitea installation, custom themes could be provided by "{CustomPath}/public/assets/css/theme-*.css".
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
regardless of the value of `DEFAULT_THEME`.
- `THEMES`: **_empty_**: All available themes by "{CustomPath}/public/assets/css/theme-*.css". Allow users select personalized themes.
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
- `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
@ -1323,7 +1322,7 @@ Defaultly every storage has their default base path like below
| actions_log | actions_log/ |
| actions_artifacts | actions_artifacts/ |
And bucket, basepath or `SERVE_DIRECT` could be special or overrided, if you want to use a different you can:
And bucket, basepath or `SERVE_DIRECT` could be special or overridden, if you want to use a different you can:
```ini
[storage.actions_log]

View File

@ -212,10 +212,9 @@ menu:
- `SITEMAP_PAGING_NUM`: **20**: 在单个子SiteMap中显示的项数。
- `GRAPH_MAX_COMMIT_NUM`: **100**: 提交图中显示的最大commit数量。
- `CODE_COMMENT_LINES`: **4**: 在代码评论中能够显示的最大代码行数。
- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: 在Gitea安装时候设置的默认主题。
- `DEFAULT_THEME`: **gitea-auto**: 在Gitea安装时候设置的默认主题,自定义的主题可以通过 "{CustomPath}/public/assets/css/theme-*.css" 提供
- `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: 所有可用的主题。允许用户选择个性化的主题,
而不受DEFAULT_THEME 值的影响。
- `THEMES`: **_empty_**: 所有可用的主题(由 "{CustomPath}/public/assets/css/theme-*.css" 提供)。允许用户选择个性化的主题,
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小默认为8MiB
- `REACTIONS`: 用户可以在问题Issue、Pull RequestPR以及评论中选择的所有可选的反应。
这些值可以是表情符号别名(例如::smile:或Unicode表情符号。

View File

@ -381,7 +381,7 @@ To make a custom theme available to all users:
1. Add a CSS file to `$GITEA_CUSTOM/public/assets/css/theme-<theme-name>.css`.
The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath".
2. Add `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`
2. Add `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes.
Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes).

View File

@ -178,17 +178,6 @@ At some point, a customer or third party needs access to a specific repo and onl
Use [Fail2Ban](administration/fail2ban-setup.md) to monitor and stop automated login attempts or other malicious behavior based on log patterns
## How to add/use custom themes
Gitea supports three official themes right now, `gitea-light`, `gitea-dark`, and `gitea-auto` (automatically switches between the previous two depending on operating system settings).
To add your own theme, currently the only way is to provide a complete theme (not just color overrides)
As an example, let's say our theme is `arc-blue` (this is a real theme, and can be found [in this issue](https://github.com/go-gitea/gitea/issues/6011))
Name the `.css` file `theme-arc-blue.css` and add it to your custom folder in `custom/public/assets/css`
Allow users to use it by adding `arc-blue` to the list of `THEMES` in your `app.ini`
## SSHD vs built-in SSH
SSHD is the built-in SSH server on most Unix systems.

View File

@ -182,17 +182,6 @@ Gitea不提供内置的Pages服务器。您需要一个专用的域名来提供
使用 [Fail2Ban](administration/fail2ban-setup.md) 监视并阻止基于日志模式的自动登录尝试或其他恶意行为。
## 如何添加/使用自定义主题
Gitea 目前支持三个官方主题,分别是 `gitea-light`、`gitea-dark` 和 `gitea-auto`(根据操作系统设置自动切换前两个主题)。
要添加自己的主题,目前唯一的方法是提供一个完整的主题(不仅仅是颜色覆盖)。
假设我们的主题是 `arc-blue`(这是一个真实的主题,可以在[此问题](https://github.com/go-gitea/gitea/issues/6011)中找到)
将`.css`文件命名为`theme-arc-blue.css`并将其添加到`custom/public/assets/css`文件夹中
通过将`arc-blue`添加到`app.ini`中的`THEMES`列表中,允许用户使用该主题
## SSHD vs 内建SSH
SSHD是大多数Unix系统上内建的SSH服务器。

View File

@ -98,13 +98,10 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
return nil
}
if run.Repo == nil {
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
if err != nil {
return err
}
run.Repo = repo
if err := run.LoadRepo(ctx); err != nil {
return err
}
if err := run.Repo.LoadAttributes(ctx); err != nil {
return err
}
@ -120,6 +117,19 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error {
return nil
}
func (run *ActionRun) LoadRepo(ctx context.Context) error {
if run == nil || run.Repo != nil {
return nil
}
repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID)
if err != nil {
return err
}
run.Repo = repo
return nil
}
func (run *ActionRun) Duration() time.Duration {
return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration
}
@ -241,11 +251,11 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
// InsertRun inserts a run
func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error {
ctx, commiter, err := db.TxContext(ctx)
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer commiter.Close()
defer committer.Close()
index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID)
if err != nil {
@ -310,7 +320,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
}
}
return commiter.Commit()
return committer.Commit()
}
func GetRunByID(ctx context.Context, id int64) (*ActionRun, error) {

View File

@ -216,11 +216,11 @@ func GetRunningTaskByToken(ctx context.Context, token string) (*ActionTask, erro
}
func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask, bool, error) {
ctx, commiter, err := db.TxContext(ctx)
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return nil, false, err
}
defer commiter.Close()
defer committer.Close()
e := db.GetEngine(ctx)
@ -322,7 +322,7 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
task.Job = job
if err := commiter.Commit(); err != nil {
if err := committer.Commit(); err != nil {
return nil, false, err
}
@ -347,11 +347,11 @@ func UpdateTaskByState(ctx context.Context, state *runnerv1.TaskState) (*ActionT
stepStates[v.Id] = v
}
ctx, commiter, err := db.TxContext(ctx)
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return nil, err
}
defer commiter.Close()
defer committer.Close()
e := db.GetEngine(ctx)
@ -412,7 +412,7 @@ func UpdateTaskByState(ctx context.Context, state *runnerv1.TaskState) (*ActionT
}
}
if err := commiter.Commit(); err != nil {
if err := committer.Commit(); err != nil {
return nil, err
}

View File

@ -13,7 +13,7 @@ import (
// ActionTasksVersion
// If both ownerID and repoID is zero, its scope is global.
// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currrently).
// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currently).
// If ownerID is zero and repoID is not zero, its scope is repo.
type ActionTasksVersion struct {
ID int64 `xorm:"pk autoincr"`
@ -73,11 +73,11 @@ func increaseTasksVersionByScope(ctx context.Context, ownerID, repoID int64) err
}
func IncreaseTaskVersion(ctx context.Context, ownerID, repoID int64) error {
ctx, commiter, err := db.TxContext(ctx)
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer commiter.Close()
defer committer.Close()
// 1. increase global
if err := increaseTasksVersionByScope(ctx, 0, 0); err != nil {
@ -101,5 +101,5 @@ func IncreaseTaskVersion(ctx context.Context, ownerID, repoID int64) error {
}
}
return commiter.Commit()
return committer.Commit()
}

View File

@ -92,6 +92,11 @@ func DeleteVariable(ctx context.Context, id int64) error {
func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) {
variables := map[string]string{}
if err := run.LoadRepo(ctx); err != nil {
log.Error("LoadRepo: %v", err)
return nil, err
}
// Global
globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{})
if err != nil {

View File

@ -1,7 +1,7 @@
-
id: 1
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 2
index: 2
head_repo_id: 1
@ -16,7 +16,7 @@
-
id: 2
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 3
index: 3
head_repo_id: 1
@ -29,7 +29,7 @@
-
id: 3
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 8
index: 1
head_repo_id: 11
@ -42,7 +42,7 @@
-
id: 4
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 9
index: 1
head_repo_id: 48
@ -55,7 +55,7 @@
-
id: 5 # this PR is outdated (one commit behind branch1 )
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 11
index: 5
head_repo_id: 1
@ -68,7 +68,7 @@
-
id: 6
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 12
index: 2
head_repo_id: 3
@ -81,7 +81,7 @@
-
id: 7
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 19
index: 1
head_repo_id: 58
@ -94,7 +94,7 @@
-
id: 8
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 20
index: 1
head_repo_id: 23
@ -103,7 +103,7 @@
-
id: 9
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 21
index: 1
head_repo_id: 60
@ -112,7 +112,7 @@
-
id: 10
type: 0 # gitea pull request
status: 2 # mergable
status: 2 # mergeable
issue_id: 22
index: 1
head_repo_id: 61

View File

@ -807,7 +807,7 @@ func UpdateAllowEdits(ctx context.Context, pr *PullRequest) error {
// Mergeable returns if the pullrequest is mergeable.
func (pr *PullRequest) Mergeable(ctx context.Context) bool {
// If a pull request isn't mergable if it's:
// If a pull request isn't mergeable if it's:
// - Being conflict checked.
// - Has a conflict.
// - Received a error while being conflict checked.

View File

@ -187,8 +187,8 @@ func AddTime(ctx context.Context, user *user_model.User, issue *Issue, amount in
Issue: issue,
Repo: issue.Repo,
Doer: user,
// Content before v1.21 did store the formated string instead of seconds,
// so use "|" as delimeter to mark the new format
// Content before v1.21 did store the formatted string instead of seconds,
// so use "|" as delimiter to mark the new format
Content: fmt.Sprintf("|%d", amount),
Type: CommentTypeAddTimeManual,
TimeID: t.ID,
@ -267,8 +267,8 @@ func DeleteIssueUserTimes(ctx context.Context, issue *Issue, user *user_model.Us
Issue: issue,
Repo: issue.Repo,
Doer: user,
// Content before v1.21 did store the formated string instead of seconds,
// so use "|" as delimeter to mark the new format
// Content before v1.21 did store the formatted string instead of seconds,
// so use "|" as delimiter to mark the new format
Content: fmt.Sprintf("|%d", removedTime),
Type: CommentTypeDeleteTimeManual,
}); err != nil {
@ -298,8 +298,8 @@ func DeleteTime(ctx context.Context, t *TrackedTime) error {
Issue: t.Issue,
Repo: t.Issue.Repo,
Doer: t.User,
// Content before v1.21 did store the formated string instead of seconds,
// so use "|" as delimeter to mark the new format
// Content before v1.21 did store the formatted string instead of seconds,
// so use "|" as delimiter to mark the new format
Content: fmt.Sprintf("|%d", t.Time),
Type: CommentTypeDeleteTimeManual,
}); err != nil {

View File

@ -4,4 +4,4 @@
package v1_17 //nolint
// This migration added non-ideal indices to the action table which on larger datasets slowed things down
// it has been superceded by v218.go
// it has been superseded by v218.go

View File

@ -184,7 +184,7 @@ func (ref RefName) RefGroup() string {
}
// RefType returns the simple ref type of the reference, e.g. branch, tag
// It's differrent from RefGroup, which is using the name of the directory under .git/refs
// It's different from RefGroup, which is using the name of the directory under .git/refs
// Here we using branch but not heads, using tag but not tags
func (ref RefName) RefType() string {
var refType string

View File

@ -134,7 +134,7 @@ func (pm *Manager) AddTypedContext(parent context.Context, description, processT
//
// Most processes will not need to use the cancel function but there will be cases whereby you want to cancel the process but not immediately remove it from the
// process table.
func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finshed FinishedFunc) {
func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Duration, description string) (ctx context.Context, cancel context.CancelFunc, finished FinishedFunc) {
if timeout <= 0 {
// it's meaningless to use timeout <= 0, and it must be a bug! so we must panic here to tell developers to make the timeout correct
panic("the timeout must be greater than zero, otherwise the context will be cancelled immediately")
@ -142,9 +142,9 @@ func (pm *Manager) AddContextTimeout(parent context.Context, timeout time.Durati
ctx, cancel = context.WithTimeout(parent, timeout)
ctx, _, finshed = pm.Add(ctx, description, cancel, NormalProcessType, true)
ctx, _, finished = pm.Add(ctx, description, cancel, NormalProcessType, true)
return ctx, cancel, finshed
return ctx, cancel, finished
}
// Add create a new process

View File

@ -318,7 +318,7 @@ func mustMapSetting(rootCfg ConfigProvider, sectionName string, setting any) {
// StartupProblems contains the messages for various startup problems, including: setting option, file/folder, etc
var StartupProblems []string
func logStartupProblem(skip int, level log.Level, format string, args ...any) {
func LogStartupProblem(skip int, level log.Level, format string, args ...any) {
msg := fmt.Sprintf(format, args...)
log.Log(skip+1, level, "%s", msg)
StartupProblems = append(StartupProblems, msg)
@ -326,14 +326,14 @@ func logStartupProblem(skip int, level log.Level, format string, args ...any) {
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) {
if rootCfg.Section(oldSection).HasKey(oldKey) {
logStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
}
}
// deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini
func deprecatedSettingDB(rootCfg ConfigProvider, oldSection, oldKey string) {
if rootCfg.Section(oldSection).HasKey(oldKey) {
logStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey)
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey)
}
}

View File

@ -174,7 +174,7 @@ func GetGeneralTokenSigningSecret() []byte {
}
if generalSigningSecret.CompareAndSwap(old, &jwtSecret) {
// FIXME: in main branch, the signing token should be refactored (eg: one unique for LFS/OAuth2/etc ...)
logStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes")
LogStartupProblem(1, log.WARN, "OAuth2 is not enabled, unable to use a persistent signing secret, a new one is generated, which is not persistent between restarts and cluster nodes")
return jwtSecret
}
return *generalSigningSecret.Load()

View File

@ -235,7 +235,7 @@ var configuredPaths = make(map[string]string)
func checkOverlappedPath(name, path string) {
// TODO: some paths shouldn't overlap (storage.xxx.path), while some could (data path is the base path for storage path)
if targetName, ok := configuredPaths[path]; ok && targetName != name {
logStartupProblem(1, log.ERROR, "Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name)
LogStartupProblem(1, log.ERROR, "Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name)
}
configuredPaths[path] = name
}

View File

@ -82,7 +82,6 @@ var UI = struct {
ReactionMaxUserNum: 10,
MaxDisplayFileSize: 8388608,
DefaultTheme: `gitea-auto`,
Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`},
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},

View File

@ -22,6 +22,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/gitdiff"
"code.gitea.io/gitea/services/webtheme"
)
// NewFuncMap returns functions for injecting to templates
@ -137,12 +138,7 @@ func NewFuncMap() template.FuncMap {
"DisableImportLocal": func() bool {
return !setting.ImportLocalPaths
},
"ThemeName": func(user *user_model.User) string {
if user == nil || user.Theme == "" {
return setting.UI.DefaultTheme
}
return user.Theme
},
"UserThemeName": UserThemeName,
"NotificationSettings": func() map[string]any {
return map[string]any{
"MinTimeout": int(setting.UI.Notification.MinTimeout / time.Millisecond),
@ -261,3 +257,13 @@ func Eval(tokens ...any) (any, error) {
n, err := eval.Expr(tokens...)
return n.Value, err
}
func UserThemeName(user *user_model.User) string {
if user == nil || user.Theme == "" {
return setting.UI.DefaultTheme
}
if webtheme.IsThemeAvailable(user.Theme) {
return user.Theme
}
return setting.UI.DefaultTheme
}

View File

@ -49,9 +49,9 @@ func TestSubjectBodySeparator(t *testing.T) {
test("Multiple\n---\n-------\n---\nSeparators",
"Multiple\n",
"\n-------\n---\nSeparators")
test("Insuficient\n--\nSeparators",
test("Insufficient\n--\nSeparators",
"",
"Insuficient\n--\nSeparators")
"Insufficient\n--\nSeparators")
}
func TestJSEscapeSafe(t *testing.T) {

View File

@ -763,6 +763,8 @@ manage_themes = Select default theme
manage_openid = Manage OpenID Addresses
email_desc = Your primary email address will be used for notifications, password recovery and, provided that it is not hidden, web-based Git operations.
theme_desc = This will be your default theme across the site.
theme_colorblindness_help = Colorblindness Theme Support
theme_colorblindness_prompt = Gitea just gets some themes with basic colorblindness support, which only have a few colors defined. The work is still in progress. More improvements could be done by defining more colors in the theme CSS files.
primary = Primary
activated = Activated
requires_activation = Requires activation

View File

@ -301,7 +301,7 @@ func (ar artifactRoutes) uploadArtifact(ctx *ArtifactContext) {
})
}
// comfirmUploadArtifact comfirm upload artifact.
// comfirmUploadArtifact confirm upload artifact.
// if all chunks are uploaded, merge them to one file.
func (ar artifactRoutes) comfirmUploadArtifact(ctx *ArtifactContext) {
_, runID, ok := validateRunID(ctx)

View File

@ -36,7 +36,7 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar
uuid := request.Header().Get(uuidHeaderKey)
token := request.Header().Get(tokenHeaderKey)
// TODO: version will be removed from request header after Gitea 1.20 released.
// And Gitea will not try to read version from reuqest header
// And Gitea will not try to read version from request header
version := request.Header().Get(versionHeaderKey)
runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
@ -53,7 +53,7 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar
cols := []string{"last_online"}
// TODO: version will be removed from request header after Gitea 1.20 released.
// And Gitea will not try to read version from reuqest header
// And Gitea will not try to read version from request header
version, _ = util.SplitStringAtByteN(version, 64)
if !util.IsEmptyString(version) && runner.Version != version {
runner.Version = version

View File

@ -19,7 +19,7 @@ The package registry code is divided into multiple modules to split the function
## Models
Every package registry implementation uses the same underlaying models:
Every package registry implementation uses the same underlying models:
| Model | Description |
| - | - |

View File

@ -12,7 +12,7 @@ import (
"code.gitea.io/gitea/services/context"
)
// RegistrationToken is response related to registeration token
// RegistrationToken is response related to registration token
// swagger:response RegistrationToken
type RegistrationToken struct {
Token string `json:"token"`

View File

@ -359,7 +359,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r
})
return
}
log.Error("Unable to check if mergable: protected branch %s in %-v and pr #%d. Error: %v", ctx.opts.UserID, branchName, repo, pr.Index, err)
log.Error("Unable to check if mergeable: protected branch %s in %-v and pr #%d. Error: %v", ctx.opts.UserID, branchName, repo, pr.Index, err)
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Unable to get status of pull request %d. Error: %v", ctx.opts.PullRequestID, err),
})

View File

@ -30,7 +30,7 @@ func Organizations(ctx *context.Context) {
explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{
Actor: ctx.Doer,
Type: user_model.UserTypeOrganization,
IncludeReserved: true, // administrator needs to list all acounts include reserved
IncludeReserved: true, // administrator needs to list all accounts include reserved
ListOptions: db.ListOptions{
PageSize: setting.UI.Admin.OrgPagingNum,
},

View File

@ -81,7 +81,7 @@ func Users(ctx *context.Context) {
IsRestricted: util.OptionalBoolParse(statusFilterMap["is_restricted"]),
IsTwoFactorEnabled: util.OptionalBoolParse(statusFilterMap["is_2fa_enabled"]),
IsProhibitLogin: util.OptionalBoolParse(statusFilterMap["is_prohibit_login"]),
IncludeReserved: true, // administrator needs to list all acounts include reserved, bot, remote ones
IncludeReserved: true, // administrator needs to list all accounts include reserved, bot, remote ones
ExtraParamStrings: extraParamStrings,
}, tplUsers)
}

View File

@ -813,7 +813,7 @@ func CompareDiff(ctx *context.Context) {
// applicable if you have one commit to compare and that commit has a message.
// In that case the commit message will be prepend to the template body.
if templateContent, ok := ctx.Data[pullRequestTemplateKey].(string); ok && templateContent != "" {
// Re-use the same key as that's priortized over the "content" key.
// Re-use the same key as that's prioritized over the "content" key.
// Add two new lines between the content to ensure there's always at least
// one empty line between them.
ctx.Data[pullRequestTemplateKey] = content + "\n\n" + templateContent

View File

@ -1760,8 +1760,8 @@ func ViewIssue(ctx *context.Context) {
// drop error since times could be pruned from DB..
_ = comment.LoadTime(ctx)
if comment.Content != "" {
// Content before v1.21 did store the formated string instead of seconds,
// so "|" is used as delimeter to mark the new format
// Content before v1.21 did store the formatted string instead of seconds,
// so "|" is used as delimiter to mark the new format
if comment.Content[0] != '|' {
// handle old time comments that have formatted text stored
comment.RenderedContent = templates.SanitizeHTML(comment.Content)

View File

@ -31,6 +31,7 @@ import (
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
user_service "code.gitea.io/gitea/services/user"
"code.gitea.io/gitea/services/webtheme"
)
const (
@ -319,6 +320,13 @@ func Appearance(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings.appearance")
ctx.Data["PageIsSettingsAppearance"] = true
allThemes := webtheme.GetAvailableThemes()
if webtheme.IsThemeAvailable(setting.UI.DefaultTheme) {
allThemes = util.SliceRemoveAll(allThemes, setting.UI.DefaultTheme)
allThemes = append([]string{setting.UI.DefaultTheme}, allThemes...) // move the default theme to the top
}
ctx.Data["AllThemes"] = allThemes
var hiddenCommentTypes *big.Int
val, err := user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes)
if err != nil {
@ -341,11 +349,12 @@ func UpdateUIThemePost(ctx *context.Context) {
ctx.Data["PageIsSettingsAppearance"] = true
if ctx.HasError() {
ctx.Flash.Error(ctx.GetErrMsg())
ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
return
}
if !form.IsThemeExists() {
if !webtheme.IsThemeAvailable(form.Theme) {
ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
return

View File

@ -652,7 +652,7 @@ func registerRoutes(m *web.Route) {
m.Get("", user_setting.BlockedUsers)
m.Post("", web.Bind(forms.BlockUserForm{}), user_setting.BlockedUsersPost)
})
}, reqSignIn, ctxDataSet("PageIsUserSettings", true, "AllThemes", setting.UI.Themes, "EnablePackages", setting.Packages.Enabled))
}, reqSignIn, ctxDataSet("PageIsUserSettings", true, "EnablePackages", setting.Packages.Enabled))
m.Group("/user", func() {
m.Get("/activate", auth.Activate)

View File

@ -132,8 +132,14 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule)
Status: actions_model.StatusWaiting,
}
vars, err := actions_model.GetVariablesOfRun(ctx, run)
if err != nil {
log.Error("GetVariablesOfRun: %v", err)
return err
}
// Parse the workflow specification from the cron schedule
workflows, err := jobparser.Parse(cron.Content)
workflows, err := jobparser.Parse(cron.Content, jobparser.WithVars(vars))
if err != nil {
return err
}

View File

@ -230,6 +230,7 @@ func Contexter() func(next http.Handler) http.Handler {
// HasError returns true if error occurs in form validation.
// Attention: this function changes ctx.Data and ctx.Flash
// If HasError is called, then before Redirect, the error message should be stored by ctx.Flash.Error(ctx.GetErrMsg()) again.
func (ctx *Context) HasError() bool {
hasErr, ok := ctx.Data["HasError"]
if !ok {

View File

@ -72,8 +72,8 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
c.Type == issues_model.CommentTypeStopTracking ||
c.Type == issues_model.CommentTypeDeleteTimeManual) &&
c.Content[0] == '|' {
// TimeTracking Comments from v1.21 on store the seconds instead of an formated string
// so we check for the "|" delimeter and convert new to legacy format on demand
// TimeTracking Comments from v1.21 on store the seconds instead of an formatted string
// so we check for the "|" delimiter and convert new to legacy format on demand
c.Content = util.SecToTime(c.Content[1:])
}
}

View File

@ -11,7 +11,6 @@ import (
auth_model "code.gitea.io/gitea/models/auth"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/services/context"
@ -273,7 +272,7 @@ func (f *AddEmailForm) Validate(req *http.Request, errs binding.Errors) binding.
// UpdateThemeForm form for updating a users' theme
type UpdateThemeForm struct {
Theme string `binding:"Required;MaxSize(30)"`
Theme string `binding:"Required;MaxSize(255)"`
}
// Validate validates the field
@ -282,20 +281,6 @@ func (f *UpdateThemeForm) Validate(req *http.Request, errs binding.Errors) bindi
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
}
// IsThemeExists checks if the theme is a theme available in the config.
func (f UpdateThemeForm) IsThemeExists() bool {
var exists bool
for _, v := range setting.UI.Themes {
if strings.EqualFold(v, f.Theme) {
exists = true
break
}
}
return exists
}
// ChangePasswordForm form for changing password
type ChangePasswordForm struct {
OldPassword string `form:"old_password" binding:"MaxSize(255)"`

View File

@ -229,12 +229,12 @@ func TeamReviewRequest(ctx context.Context, issue *issues_model.Issue, doer *use
return comment, teamReviewRequestNotify(ctx, issue, doer, reviewer, isAdd, comment)
}
func ReviewRequestNotify(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, reviewNotifers []*ReviewRequestNotifier) {
for _, reviewNotifer := range reviewNotifers {
if reviewNotifer.Reviwer != nil {
notify_service.PullRequestReviewRequest(ctx, issue.Poster, issue, reviewNotifer.Reviwer, reviewNotifer.IsAdd, reviewNotifer.Comment)
} else if reviewNotifer.ReviewTeam != nil {
if err := teamReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifer.ReviewTeam, reviewNotifer.IsAdd, reviewNotifer.Comment); err != nil {
func ReviewRequestNotify(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, reviewNotifiers []*ReviewRequestNotifier) {
for _, reviewNotifier := range reviewNotifiers {
if reviewNotifier.Reviewer != nil {
notify_service.PullRequestReviewRequest(ctx, issue.Poster, issue, reviewNotifier.Reviewer, reviewNotifier.IsAdd, reviewNotifier.Comment)
} else if reviewNotifier.ReviewTeam != nil {
if err := teamReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifier.ReviewTeam, reviewNotifier.IsAdd, reviewNotifier.Comment); err != nil {
log.Error("teamReviewRequestNotify: %v", err)
}
}

View File

@ -90,17 +90,17 @@ func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_mode
return err
}
var reviewNotifers []*ReviewRequestNotifier
var reviewNotifiers []*ReviewRequestNotifier
if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) {
var err error
reviewNotifers, err = PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest)
reviewNotifiers, err = PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest)
if err != nil {
log.Error("PullRequestCodeOwnersReview: %v", err)
}
}
notify_service.IssueChangeTitle(ctx, doer, issue, oldTitle)
ReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifers)
ReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifiers)
return nil
}

View File

@ -36,7 +36,7 @@ func getMergeBase(repo *git.Repository, pr *issues_model.PullRequest, baseBranch
type ReviewRequestNotifier struct {
Comment *issues_model.Comment
IsAdd bool
Reviwer *user_model.User
Reviewer *user_model.User
ReviewTeam *org_model.Team
}
@ -124,9 +124,9 @@ func PullRequestCodeOwnersReview(ctx context.Context, issue *issues_model.Issue,
return nil, err
}
notifiers = append(notifiers, &ReviewRequestNotifier{
Comment: comment,
IsAdd: true,
Reviwer: u,
Comment: comment,
IsAdd: true,
Reviewer: u,
})
}
}

View File

@ -20,11 +20,11 @@ import (
// DeleteOrganization completely and permanently deletes everything of organization.
func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge bool) error {
ctx, commiter, err := db.TxContext(ctx)
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer commiter.Close()
defer committer.Close()
if purge {
err := repo_service.DeleteOwnerRepositoriesDirectly(ctx, org.AsUser())
@ -52,7 +52,7 @@ func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge
return fmt.Errorf("DeleteOrganization: %w", err)
}
if err := commiter.Commit(); err != nil {
if err := committer.Commit(); err != nil {
return err
}

View File

@ -66,7 +66,7 @@ const (
MergeCheckTypeAuto // Auto Merge (Scheduled Merge) After Checks Succeed
)
// CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...)
// CheckPullMergable check if the pull mergeable based on all conditions (branch protection, merge options, ...)
func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error {
return db.WithTx(stdCtx, func(ctx context.Context) error {
if pr.HasMerged {

View File

@ -46,7 +46,7 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC
return commitIDs, isForcePush, err
}
// Find commits between new and old commit exclusing base branch commits
// Find commits between new and old commit excluding base branch commits
commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
if err != nil {
return nil, false, err

View File

@ -77,7 +77,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss
}
defer baseGitRepo.Close()
var reviewNotifers []*issue_service.ReviewRequestNotifier
var reviewNotifiers []*issue_service.ReviewRequestNotifier
if err := db.WithTx(ctx, func(ctx context.Context) error {
if err := issues_model.NewPullRequest(ctx, repo, issue, labelIDs, uuids, pr); err != nil {
return err
@ -137,7 +137,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss
}
if !pr.IsWorkInProgress(ctx) {
reviewNotifers, err = issue_service.PullRequestCodeOwnersReview(ctx, issue, pr)
reviewNotifiers, err = issue_service.PullRequestCodeOwnersReview(ctx, issue, pr)
if err != nil {
return err
}
@ -152,7 +152,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss
}
baseGitRepo.Close() // close immediately to avoid notifications will open the repository again
issue_service.ReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifers)
issue_service.ReviewRequestNotify(ctx, issue, issue.Poster, reviewNotifiers)
mentions, err := issues_model.FindAndUpdateIssueMentions(ctx, issue, issue.Poster, issue.Content)
if err != nil {

View File

@ -0,0 +1,74 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package webtheme
import (
"sort"
"strings"
"sync"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/public"
"code.gitea.io/gitea/modules/setting"
)
var (
availableThemes []string
availableThemesSet container.Set[string]
themeOnce sync.Once
)
func initThemes() {
availableThemes = nil
defer func() {
availableThemesSet = container.SetOf(availableThemes...)
if !availableThemesSet.Contains(setting.UI.DefaultTheme) {
setting.LogStartupProblem(1, log.ERROR, "Default theme %q is not available, please correct the '[ui].DEFAULT_THEME' setting in the config file", setting.UI.DefaultTheme)
}
}()
cssFiles, err := public.AssetFS().ListFiles("/assets/css")
if err != nil {
log.Error("Failed to list themes: %v", err)
availableThemes = []string{setting.UI.DefaultTheme}
return
}
var foundThemes []string
for _, name := range cssFiles {
name, ok := strings.CutPrefix(name, "theme-")
if !ok {
continue
}
name, ok = strings.CutSuffix(name, ".css")
if !ok {
continue
}
foundThemes = append(foundThemes, name)
}
if len(setting.UI.Themes) > 0 {
allowedThemes := container.SetOf(setting.UI.Themes...)
for _, theme := range foundThemes {
if allowedThemes.Contains(theme) {
availableThemes = append(availableThemes, theme)
}
}
} else {
availableThemes = foundThemes
}
sort.Strings(availableThemes)
if len(availableThemes) == 0 {
setting.LogStartupProblem(1, log.ERROR, "No theme candidate in asset files, but Gitea requires there should be at least one usable theme")
availableThemes = []string{setting.UI.DefaultTheme}
}
}
func GetAvailableThemes() []string {
themeOnce.Do(initThemes)
return availableThemes
}
func IsThemeAvailable(name string) bool {
themeOnce.Do(initThemes)
return availableThemesSet.Contains(name)
}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="{{ctx.Locale.Lang}}" data-theme="{{ThemeName .SignedUser}}">
<html lang="{{ctx.Locale.Lang}}" data-theme="{{UserThemeName .SignedUser}}">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{if .Title}}{{.Title}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>

View File

@ -1,2 +1,2 @@
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/index.css?v={{AssetVersion}}">
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{ThemeName .SignedUser | PathEscape}}.css?v={{AssetVersion}}">
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/theme-{{UserThemeName .SignedUser | PathEscape}}.css?v={{AssetVersion}}">

View File

@ -1,12 +1,12 @@
{{/* This page should only depend the minimal template functions/variables, to avoid triggering new panics.
* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, ThemeName
* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, UserThemeName
* ctx.Locale
* .Flash
* .ErrorMsg
* .SignedUser (optional)
*/}}
<!DOCTYPE html>
<html lang="{{ctx.Locale.Lang}}" data-theme="{{ThemeName .SignedUser}}">
<html lang="{{ctx.Locale.Lang}}" data-theme="{{UserThemeName .SignedUser}}">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Internal Server Error - {{AppName}}</title>

View File

@ -25234,7 +25234,7 @@
}
},
"RegistrationToken": {
"description": "RegistrationToken is response related to registeration token",
"description": "RegistrationToken is response related to registration token",
"headers": {
"token": {
"type": "string"

View File

@ -1,4 +1,4 @@
{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings sshkeys")}}
{{template "user/settings/layout_head" (dict "ctxData" . "pageClass" "user settings")}}
<div class="user-setting-content">
<!-- Theme -->
@ -6,39 +6,26 @@
{{ctx.Locale.Tr "settings.manage_themes"}}
</h4>
<div class="ui attached segment">
<div class="ui email list">
<div class="item">
{{ctx.Locale.Tr "settings.theme_desc"}}
</div>
<form class="ui form" action="{{.Link}}/theme" method="post">
{{.CsrfTokenHtml}}
<div class="field">
<label for="ui">{{ctx.Locale.Tr "settings.ui"}}</label>
<div class="ui selection dropdown" id="ui">
<input name="theme" type="hidden" value="{{.SignedUser.Theme}}">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="text">
{{range $i,$a := .AllThemes}}
{{if eq $.SignedUser.Theme $a}}{{$a}}{{end}}
{{end}}
</div>
<div class="menu">
{{range $i,$a := .AllThemes}}
<div class="item{{if eq $.SignedUser.Theme $a}} active selected{{end}}" data-value="{{$a}}">
{{$a}}
</div>
{{end}}
</div>
</div>
</div>
<div class="field">
{{ctx.Locale.Tr "settings.theme_desc"}}
<a class="muted" target="_blank" href="https://github.com/go-gitea/gitea/blob/main/web_src/css/themes/" data-tooltip-content="{{ctx.Locale.Tr "settings.theme_colorblindness_prompt"}}">
{{svg "octicon-question"}} {{ctx.Locale.Tr "settings.theme_colorblindness_help"}}
</a>
</div>
<div class="field">
<label>{{ctx.Locale.Tr "settings.ui"}}</label>
<select name="theme" class="ui dropdown">
{{range $theme := .AllThemes}}
<option value="{{$theme}}" {{Iif (eq $.SignedUser.Theme $theme) "selected"}}>{{$theme}}</option>
{{end}}
</select>
</div>
<div class="field">
<button class="ui primary button">{{ctx.Locale.Tr "settings.update_theme"}}</button>
</div>
</form>
</div>
</div>
<!-- Language -->

View File

@ -119,9 +119,9 @@ func TestAPIRepoIssueConfigPaths(t *testing.T) {
".github/issue_template/config",
}
for _, canidate := range templateConfigCandidates {
for _, candidate := range templateConfigCandidates {
for _, extension := range []string{".yaml", ".yml"} {
fullPath := canidate + extension
fullPath := candidate + extension
t.Run(fullPath, func(t *testing.T) {
configMap := make(map[string]any)
configMap["blank_issues_enabled"] = false

View File

@ -67,7 +67,7 @@ func TestCompareBranches(t *testing.T) {
session := loginUser(t, "user2")
// Inderect compare remove-files-b (head) with add-csv (base) branch
// Indirect compare remove-files-b (head) with add-csv (base) branch
//
// 'link_hi' and 'test.csv' are deleted, 'test.txt' is added
req := NewRequest(t, "GET", "/user2/repo20/compare/add-csv...remove-files-b")
@ -79,7 +79,7 @@ func TestCompareBranches(t *testing.T) {
inspectCompare(t, htmlDoc, diffCount, diffChanges)
// Inderect compare remove-files-b (head) with remove-files-a (base) branch
// Indirect compare remove-files-b (head) with remove-files-a (base) branch
//
// 'link_hi' and 'test.csv' are deleted, 'test.txt' is added
@ -92,7 +92,7 @@ func TestCompareBranches(t *testing.T) {
inspectCompare(t, htmlDoc, diffCount, diffChanges)
// Inderect compare remove-files-a (head) with remove-files-b (base) branch
// Indirect compare remove-files-a (head) with remove-files-b (base) branch
//
// 'link_hi' and 'test.csv' are deleted

21
tools/misspellings.csv Normal file
View File

@ -0,0 +1,21 @@
acounts,accounts
canidate,candidate
comfirm,confirm
converage,coverage
currrently,currently
delimeter,delimiter
differrent,different
exclusing,excluding
finshed,finished
formated,formatted
inderect,indirect
insuficient,insufficient
likly,likely
mergable,mergeable
overrided,overridden
priortized,prioritized
registeration,registration
reuqest,request
reviwer,reviewer
superceded,superseded
underlaying,underlying
1 acounts accounts
2 canidate candidate
3 comfirm confirm
4 converage coverage
5 currrently currently
6 delimeter delimiter
7 differrent different
8 exclusing excluding
9 finshed finished
10 formated formatted
11 inderect indirect
12 insuficient insufficient
13 likly likely
14 mergable mergeable
15 overrided overridden
16 priortized prioritized
17 registeration registration
18 reuqest request
19 reviwer reviewer
20 superceded superseded
21 underlaying underlying

View File

@ -0,0 +1,11 @@
@import "./theme-gitea-dark.css";
/* red/green colorblind-friendly colors */
/* from GitHub: --diffBlob-addition-*, --diffBlob-deletion-*, etc */
:root {
--color-diff-added-word-bg: #388bfd66;
--color-diff-added-row-bg: #388bfd26;
--color-diff-removed-word-bg: #db6d2866;
--color-diff-removed-row-bg: #db6d2826;
}

View File

@ -0,0 +1,11 @@
@import "./theme-gitea-light.css";
/* red/green colorblind-friendly colors */
/* from GitHub: --diffBlob-addition-*, --diffBlob-deletion-*, etc */
:root {
--color-diff-added-word-bg: #54aeff66;
--color-diff-added-row-bg: #ddf4ff80;
--color-diff-removed-word-bg: #ffb77c80;
--color-diff-removed-row-bg: #fff1e580;
}

View File

@ -50,7 +50,7 @@ function processWindowErrorEvent({error, reason, message, type, filename, lineno
const assetBaseUrl = String(new URL(__webpack_public_path__, window.location.origin));
const {runModeIsProd} = window.config ?? {};
// `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likly a
// `error` and `reason` are not guaranteed to be errors. If the value is falsy, it is likely a
// non-critical event from the browser. We log them but don't show them to users. Examples:
// - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
// - https://github.com/mozilla-mobile/firefox-ios/issues/10817