From 45c15387b292c25b5d0572b2eb3f85414156372a Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Fri, 16 Feb 2024 23:18:30 +0800
Subject: [PATCH 01/28] Refactor JWT secret generating & decoding code (#29172)
Old code is not consistent for generating & decoding the JWT secrets.
Now, the callers only need to use 2 consistent functions:
NewJwtSecretWithBase64 and DecodeJwtSecretBase64
And remove a non-common function Base64FixedDecode from util.go
---
cmd/generate.go | 2 +-
modules/generate/generate.go | 24 ++++++++------
modules/generate/generate_test.go | 34 ++++++++++++++++++++
modules/setting/lfs.go | 6 ++--
modules/setting/oauth2.go | 7 ++--
modules/util/util.go | 11 -------
modules/util/util_test.go | 14 --------
routers/install/install.go | 2 +-
services/auth/source/oauth2/jwtsigningkey.go | 3 +-
9 files changed, 57 insertions(+), 46 deletions(-)
create mode 100644 modules/generate/generate_test.go
diff --git a/cmd/generate.go b/cmd/generate.go
index 4ab10da22afaf..90b32ecaf0e1c 100644
--- a/cmd/generate.go
+++ b/cmd/generate.go
@@ -70,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
}
func runGenerateLfsJwtSecret(c *cli.Context) error {
- _, jwtSecretBase64, err := generate.NewJwtSecretBase64()
+ _, jwtSecretBase64, err := generate.NewJwtSecretWithBase64()
if err != nil {
return err
}
diff --git a/modules/generate/generate.go b/modules/generate/generate.go
index ee3c76059bc89..2d9a3dd902245 100644
--- a/modules/generate/generate.go
+++ b/modules/generate/generate.go
@@ -7,6 +7,7 @@ package generate
import (
"crypto/rand"
"encoding/base64"
+ "fmt"
"io"
"time"
@@ -38,19 +39,24 @@ func NewInternalToken() (string, error) {
return internalToken, nil
}
-// NewJwtSecret generates a new value intended to be used for JWT secrets.
-func NewJwtSecret() ([]byte, error) {
- bytes := make([]byte, 32)
- _, err := io.ReadFull(rand.Reader, bytes)
- if err != nil {
+const defaultJwtSecretLen = 32
+
+// DecodeJwtSecretBase64 decodes a base64 encoded jwt secret into bytes, and check its length
+func DecodeJwtSecretBase64(src string) ([]byte, error) {
+ encoding := base64.RawURLEncoding
+ decoded := make([]byte, encoding.DecodedLen(len(src))+3)
+ if n, err := encoding.Decode(decoded, []byte(src)); err != nil {
return nil, err
+ } else if n != defaultJwtSecretLen {
+ return nil, fmt.Errorf("invalid base64 decoded length: %d, expects: %d", n, defaultJwtSecretLen)
}
- return bytes, nil
+ return decoded[:defaultJwtSecretLen], nil
}
-// NewJwtSecretBase64 generates a new base64 encoded value intended to be used for JWT secrets.
-func NewJwtSecretBase64() ([]byte, string, error) {
- bytes, err := NewJwtSecret()
+// NewJwtSecretWithBase64 generates a jwt secret with its base64 encoded value intended to be used for saving into config file
+func NewJwtSecretWithBase64() ([]byte, string, error) {
+ bytes := make([]byte, defaultJwtSecretLen)
+ _, err := io.ReadFull(rand.Reader, bytes)
if err != nil {
return nil, "", err
}
diff --git a/modules/generate/generate_test.go b/modules/generate/generate_test.go
new file mode 100644
index 0000000000000..af640a60c1e34
--- /dev/null
+++ b/modules/generate/generate_test.go
@@ -0,0 +1,34 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package generate
+
+import (
+ "encoding/base64"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestDecodeJwtSecretBase64(t *testing.T) {
+ _, err := DecodeJwtSecretBase64("abcd")
+ assert.ErrorContains(t, err, "invalid base64 decoded length")
+ _, err = DecodeJwtSecretBase64(strings.Repeat("a", 64))
+ assert.ErrorContains(t, err, "invalid base64 decoded length")
+
+ str32 := strings.Repeat("x", 32)
+ encoded32 := base64.RawURLEncoding.EncodeToString([]byte(str32))
+ decoded32, err := DecodeJwtSecretBase64(encoded32)
+ assert.NoError(t, err)
+ assert.Equal(t, str32, string(decoded32))
+}
+
+func TestNewJwtSecretWithBase64(t *testing.T) {
+ secret, encoded, err := NewJwtSecretWithBase64()
+ assert.NoError(t, err)
+ assert.Len(t, secret, 32)
+ decoded, err := DecodeJwtSecretBase64(encoded)
+ assert.NoError(t, err)
+ assert.Equal(t, secret, decoded)
+}
diff --git a/modules/setting/lfs.go b/modules/setting/lfs.go
index a5ea537cef50d..22a75f60084f5 100644
--- a/modules/setting/lfs.go
+++ b/modules/setting/lfs.go
@@ -4,12 +4,10 @@
package setting
import (
- "encoding/base64"
"fmt"
"time"
"code.gitea.io/gitea/modules/generate"
- "code.gitea.io/gitea/modules/util"
)
// LFS represents the configuration for Git LFS
@@ -62,9 +60,9 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
}
LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
- LFS.JWTSecretBytes, err = util.Base64FixedDecode(base64.RawURLEncoding, []byte(LFS.JWTSecretBase64), 32)
+ LFS.JWTSecretBytes, err = generate.DecodeJwtSecretBase64(LFS.JWTSecretBase64)
if err != nil {
- LFS.JWTSecretBytes, LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
+ LFS.JWTSecretBytes, LFS.JWTSecretBase64, err = generate.NewJwtSecretWithBase64()
if err != nil {
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)
}
diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go
index 0d15e91ef0d6c..e16e1670249ca 100644
--- a/modules/setting/oauth2.go
+++ b/modules/setting/oauth2.go
@@ -4,13 +4,11 @@
package setting
import (
- "encoding/base64"
"math"
"path/filepath"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/util"
)
// OAuth2UsernameType is enum describing the way gitea 'name' should be generated from oauth2 data
@@ -137,13 +135,12 @@ func loadOAuth2From(rootCfg ConfigProvider) {
}
if InstallLock {
- if _, err := util.Base64FixedDecode(base64.RawURLEncoding, []byte(OAuth2.JWTSecretBase64), 32); err != nil {
- key, err := generate.NewJwtSecret()
+ if _, err := generate.DecodeJwtSecretBase64(OAuth2.JWTSecretBase64); err != nil {
+ _, OAuth2.JWTSecretBase64, err = generate.NewJwtSecretWithBase64()
if err != nil {
log.Fatal("error generating JWT secret: %v", err)
}
- OAuth2.JWTSecretBase64 = base64.RawURLEncoding.EncodeToString(key)
saveCfg, err := rootCfg.PrepareSaving()
if err != nil {
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
diff --git a/modules/util/util.go b/modules/util/util.go
index c47931f6c95e9..0e5c6a4e64c50 100644
--- a/modules/util/util.go
+++ b/modules/util/util.go
@@ -6,7 +6,6 @@ package util
import (
"bytes"
"crypto/rand"
- "encoding/base64"
"fmt"
"math/big"
"strconv"
@@ -246,13 +245,3 @@ func ToFloat64(number any) (float64, error) {
func ToPointer[T any](val T) *T {
return &val
}
-
-func Base64FixedDecode(encoding *base64.Encoding, src []byte, length int) ([]byte, error) {
- decoded := make([]byte, encoding.DecodedLen(len(src))+3)
- if n, err := encoding.Decode(decoded, src); err != nil {
- return nil, err
- } else if n != length {
- return nil, fmt.Errorf("invalid base64 decoded length: %d, expects: %d", n, length)
- }
- return decoded[:length], nil
-}
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index 8509d8acedc68..c5830ce01cb22 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -4,7 +4,6 @@
package util
import (
- "encoding/base64"
"regexp"
"strings"
"testing"
@@ -234,16 +233,3 @@ func TestToPointer(t *testing.T) {
val123 := 123
assert.False(t, &val123 == ToPointer(val123))
}
-
-func TestBase64FixedDecode(t *testing.T) {
- _, err := Base64FixedDecode(base64.RawURLEncoding, []byte("abcd"), 32)
- assert.ErrorContains(t, err, "invalid base64 decoded length")
- _, err = Base64FixedDecode(base64.RawURLEncoding, []byte(strings.Repeat("a", 64)), 32)
- assert.ErrorContains(t, err, "invalid base64 decoded length")
-
- str32 := strings.Repeat("x", 32)
- encoded32 := base64.RawURLEncoding.EncodeToString([]byte(str32))
- decoded32, err := Base64FixedDecode(base64.RawURLEncoding, []byte(encoded32), 32)
- assert.NoError(t, err)
- assert.Equal(t, str32, string(decoded32))
-}
diff --git a/routers/install/install.go b/routers/install/install.go
index 5c0290d2cccb5..064575d34c578 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -409,7 +409,7 @@ func SubmitInstall(ctx *context.Context) {
cfg.Section("server").Key("LFS_START_SERVER").SetValue("true")
cfg.Section("lfs").Key("PATH").SetValue(form.LFSRootPath)
var lfsJwtSecret string
- if _, lfsJwtSecret, err = generate.NewJwtSecretBase64(); err != nil {
+ if _, lfsJwtSecret, err = generate.NewJwtSecretWithBase64(); err != nil {
ctx.RenderWithErr(ctx.Tr("install.lfs_jwt_secret_failed", err), tplInstall, &form)
return
}
diff --git a/services/auth/source/oauth2/jwtsigningkey.go b/services/auth/source/oauth2/jwtsigningkey.go
index eca0b8b7e1205..2afe557b0d623 100644
--- a/services/auth/source/oauth2/jwtsigningkey.go
+++ b/services/auth/source/oauth2/jwtsigningkey.go
@@ -18,6 +18,7 @@ import (
"path/filepath"
"strings"
+ "code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@@ -336,7 +337,7 @@ func InitSigningKey() error {
// loadSymmetricKey checks if the configured secret is valid.
// If it is not valid, it will return an error.
func loadSymmetricKey() (any, error) {
- return util.Base64FixedDecode(base64.RawURLEncoding, []byte(setting.OAuth2.JWTSecretBase64), 32)
+ return generate.DecodeJwtSecretBase64(setting.OAuth2.JWTSecretBase64)
}
// loadOrCreateAsymmetricKey checks if the configured private key exists.
From 5902372e63db2d3f31150251dfffdb305fa9aaee Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Fri, 16 Feb 2024 17:48:01 +0200
Subject: [PATCH 02/28] Remove jQuery from organization rename prompt toggle
(#29195)
- Switched to plain JavaScript
- Tested the organization rename prompt toggling functionality and it
works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/e6f641b0-aa46-4b85-9693-0d608cca855e)
---------
Signed-off-by: Yarden Shoham
Co-authored-by: silverwind
---
web_src/js/features/common-organization.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/web_src/js/features/common-organization.js b/web_src/js/features/common-organization.js
index 352e824b05be4..a950af3adf0c8 100644
--- a/web_src/js/features/common-organization.js
+++ b/web_src/js/features/common-organization.js
@@ -1,14 +1,15 @@
-import $ from 'jquery';
import {initCompLabelEdit} from './comp/LabelEdit.js';
import {toggleElem} from '../utils/dom.js';
export function initCommonOrganization() {
- if ($('.organization').length === 0) {
+ if (!document.querySelectorAll('.organization').length) {
return;
}
- $('.organization.settings.options #org_name').on('input', function () {
- const nameChanged = $(this).val().toLowerCase() !== $(this).attr('data-org-name').toLowerCase();
+ const orgNameInput = document.querySelector('.organization.settings.options #org_name');
+ if (!orgNameInput) return;
+ orgNameInput.addEventListener('input', function () {
+ const nameChanged = this.value.toLowerCase() !== this.getAttribute('data-org-name').toLowerCase();
toggleElem('#org-name-change-prompt', nameChanged);
});
From 0768842ef56758b3290406656c5ebbd605358f6e Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Fri, 16 Feb 2024 17:52:50 +0200
Subject: [PATCH 03/28] Remove jQuery from username change prompt and fix its
detection (#29197)
- Switched to plain JavaScript
- Tested the user rename prompt toggling functionality and it works as
before
- Fixed bug that allowed pasting with the mouse to avoid the prompt
# Before
![before](https://github.com/go-gitea/gitea/assets/20454870/aa300ad7-612b-461e-bbb2-3f74b3b83ede)
# After
![after](https://github.com/go-gitea/gitea/assets/20454870/f2b5a51b-7b39-43c7-8a4a-62f1f77acae4)
---------
Signed-off-by: Yarden Shoham
Co-authored-by: silverwind
---
web_src/js/features/user-settings.js | 29 ++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/web_src/js/features/user-settings.js b/web_src/js/features/user-settings.js
index d49bf3927548c..0dd908f34a971 100644
--- a/web_src/js/features/user-settings.js
+++ b/web_src/js/features/user-settings.js
@@ -1,18 +1,19 @@
-import $ from 'jquery';
import {hideElem, showElem} from '../utils/dom.js';
export function initUserSettings() {
- if ($('.user.settings.profile').length > 0) {
- $('#username').on('keyup', function () {
- const $prompt = $('#name-change-prompt');
- const $prompt_redirect = $('#name-change-redirect-prompt');
- if ($(this).val().toString().toLowerCase() !== $(this).data('name').toString().toLowerCase()) {
- showElem($prompt);
- showElem($prompt_redirect);
- } else {
- hideElem($prompt);
- hideElem($prompt_redirect);
- }
- });
- }
+ if (document.querySelectorAll('.user.settings.profile').length === 0) return;
+
+ const usernameInput = document.getElementById('username');
+ if (!usernameInput) return;
+ usernameInput.addEventListener('input', function () {
+ const prompt = document.getElementById('name-change-prompt');
+ const promptRedirect = document.getElementById('name-change-redirect-prompt');
+ if (this.value.toLowerCase() !== this.getAttribute('data-name').toLowerCase()) {
+ showElem(prompt);
+ showElem(promptRedirect);
+ } else {
+ hideElem(prompt);
+ hideElem(promptRedirect);
+ }
+ });
}
From 2d8756a9607ee6029ad7a44985e9751988d5fdaa Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Fri, 16 Feb 2024 18:03:52 +0200
Subject: [PATCH 04/28] Fix `initCompLabelEdit` not being called (#29198)
Fix broken `if` from https://github.com/go-gitea/gitea/pull/29195
Signed-off-by: Yarden Shoham
---
web_src/js/features/common-organization.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/web_src/js/features/common-organization.js b/web_src/js/features/common-organization.js
index a950af3adf0c8..442714a3d676a 100644
--- a/web_src/js/features/common-organization.js
+++ b/web_src/js/features/common-organization.js
@@ -6,9 +6,7 @@ export function initCommonOrganization() {
return;
}
- const orgNameInput = document.querySelector('.organization.settings.options #org_name');
- if (!orgNameInput) return;
- orgNameInput.addEventListener('input', function () {
+ document.querySelector('.organization.settings.options #org_name')?.addEventListener('input', function () {
const nameChanged = this.value.toLowerCase() !== this.getAttribute('data-org-name').toLowerCase();
toggleElem('#org-name-change-prompt', nameChanged);
});
From d8d4b33b31d959e4b600cc90a7fa1779b69cadf5 Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Fri, 16 Feb 2024 22:03:50 +0200
Subject: [PATCH 05/28] Remove jQuery from the "quick submit" handler (#29200)
- Switched to plain JavaScript
- Tested the quick submit functionality and it works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/abbd6c49-ad0f-4f95-b4ba-e969b85a46e8)
---------
Signed-off-by: Yarden Shoham
---
web_src/js/features/comp/QuickSubmit.js | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/web_src/js/features/comp/QuickSubmit.js b/web_src/js/features/comp/QuickSubmit.js
index 2587375a717d6..e6d7080bcf1a6 100644
--- a/web_src/js/features/comp/QuickSubmit.js
+++ b/web_src/js/features/comp/QuickSubmit.js
@@ -1,5 +1,3 @@
-import $ from 'jquery';
-
export function handleGlobalEnterQuickSubmit(target) {
const form = target.closest('form');
if (form) {
@@ -8,14 +6,9 @@ export function handleGlobalEnterQuickSubmit(target) {
return;
}
- if (form.classList.contains('form-fetch-action')) {
- form.dispatchEvent(new SubmitEvent('submit', {bubbles: true, cancelable: true}));
- return;
- }
-
// here use the event to trigger the submit event (instead of calling `submit()` method directly)
// otherwise the `areYouSure` handler won't be executed, then there will be an annoying "confirm to leave" dialog
- $(form).trigger('submit');
+ form.dispatchEvent(new SubmitEvent('submit', {bubbles: true, cancelable: true}));
} else {
// if no form, then the editor is for an AJAX request, dispatch an event to the target, let the target's event handler to do the AJAX request.
// the 'ce-' prefix means this is a CustomEvent
From 26b17537e651fe93ef9b64f961633cb4c0b8c2c3 Mon Sep 17 00:00:00 2001
From: silverwind
Date: Fri, 16 Feb 2024 22:41:23 +0100
Subject: [PATCH 06/28] Add `eslint-plugin-github` and fix issues (#29201)
This plugin has a few useful rules. The only thing I dislike about it is
that it pulls in a rather big number of dependencies for react-related
rules we don't use, but it can't really be avoided.
Rule docs:
https://github.com/github/eslint-plugin-github?tab=readme-ov-file#rules
---
.eslintrc.yaml | 24 +
build/generate-images.js | 6 +-
build/generate-svg.js | 6 +-
package-lock.json | 958 ++++++++++++++++++++++++-
package.json | 1 +
web_src/js/features/repo-code.js | 4 +-
web_src/js/features/repo-issue-list.js | 14 +-
web_src/js/features/repo-issue.js | 10 +-
web_src/js/features/repo-legacy.js | 45 +-
9 files changed, 1028 insertions(+), 40 deletions(-)
diff --git a/.eslintrc.yaml b/.eslintrc.yaml
index ed0309dbea3c2..ab9c218849db1 100644
--- a/.eslintrc.yaml
+++ b/.eslintrc.yaml
@@ -12,6 +12,7 @@ plugins:
- "@eslint-community/eslint-plugin-eslint-comments"
- "@stylistic/eslint-plugin-js"
- eslint-plugin-array-func
+ - eslint-plugin-github
- eslint-plugin-i
- eslint-plugin-jquery
- eslint-plugin-no-jquery
@@ -209,6 +210,29 @@ rules:
func-names: [0]
func-style: [0]
getter-return: [2]
+ github/a11y-aria-label-is-well-formatted: [0]
+ github/a11y-no-title-attribute: [0]
+ github/a11y-no-visually-hidden-interactive-element: [0]
+ github/a11y-role-supports-aria-props: [0]
+ github/a11y-svg-has-accessible-name: [0]
+ github/array-foreach: [0]
+ github/async-currenttarget: [2]
+ github/async-preventdefault: [2]
+ github/authenticity-token: [0]
+ github/get-attribute: [0]
+ github/js-class-name: [0]
+ github/no-blur: [0]
+ github/no-d-none: [0]
+ github/no-dataset: [2]
+ github/no-dynamic-script-tag: [2]
+ github/no-implicit-buggy-globals: [2]
+ github/no-inner-html: [0]
+ github/no-innerText: [2]
+ github/no-then: [2]
+ github/no-useless-passive: [2]
+ github/prefer-observers: [2]
+ github/require-passive-events: [2]
+ github/unescaped-html-literal: [0]
grouped-accessor-pairs: [2]
guard-for-in: [0]
id-blacklist: [0]
diff --git a/build/generate-images.js b/build/generate-images.js
index a3a0f8d8f398f..09e3e068afdaa 100755
--- a/build/generate-images.js
+++ b/build/generate-images.js
@@ -79,4 +79,8 @@ async function main() {
]);
}
-main().then(exit).catch(exit);
+try {
+ exit(await main());
+} catch (err) {
+ exit(err);
+}
diff --git a/build/generate-svg.js b/build/generate-svg.js
index b845da9367cf5..2c0a5e37ba811 100755
--- a/build/generate-svg.js
+++ b/build/generate-svg.js
@@ -63,4 +63,8 @@ async function main() {
]);
}
-main().then(exit).catch(exit);
+try {
+ exit(await main());
+} catch (err) {
+ exit(err);
+}
diff --git a/package-lock.json b/package-lock.json
index 13f03b8d2825f..f1f8cc4705731 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -68,6 +68,7 @@
"@vitejs/plugin-vue": "5.0.4",
"eslint": "8.56.0",
"eslint-plugin-array-func": "4.0.0",
+ "eslint-plugin-github": "4.10.1",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
@@ -1022,6 +1023,12 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@github/browserslist-config": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@github/browserslist-config/-/browserslist-config-1.0.0.tgz",
+ "integrity": "sha512-gIhjdJp/c2beaIWWIlsXdqXVRUz3r2BxBCpfz/F3JXHvSAQ1paMYjLH+maEATtENg+k5eLV7gA+9yPp762ieuw==",
+ "dev": true
+ },
"node_modules/@github/combobox-nav": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@github/combobox-nav/-/combobox-nav-2.3.1.tgz",
@@ -1380,6 +1387,18 @@
"node": ">=14"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@playwright/test": {
"version": "1.41.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.41.2.tgz",
@@ -2208,6 +2227,12 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
},
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
"node_modules/@types/marked": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz",
@@ -2271,6 +2296,69 @@
"integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==",
"dev": true
},
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
+ "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@typescript-eslint/scope-manager": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
@@ -2288,6 +2376,33 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
+ "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@typescript-eslint/types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
@@ -2976,6 +3091,15 @@
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"node_modules/array-buffer-byte-length": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
@@ -3000,6 +3124,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/array-includes": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
+ "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "get-intrinsic": "^1.2.1",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -3009,6 +3152,80 @@
"node": ">=8"
}
},
+ "node_modules/array.prototype.filter": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz",
+ "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz",
+ "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/arraybuffer.prototype.slice": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
@@ -3070,6 +3287,12 @@
"node": ">=4"
}
},
+ "node_modules/ast-types-flow": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
+ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
+ "dev": true
+ },
"node_modules/astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
@@ -3088,6 +3311,15 @@
"astring": "bin/astring"
}
},
+ "node_modules/asynciterator.prototype": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
+ "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -3118,6 +3350,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axe-core": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
+ "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/axobject-query": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
+ "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -4243,6 +4493,12 @@
"lodash-es": "^4.17.21"
}
},
+ "node_modules/damerau-levenshtein": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
+ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
+ "dev": true
+ },
"node_modules/data-uri-to-buffer": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
@@ -4685,6 +4941,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-array-method-boxes-properly": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "dev": true
+ },
"node_modules/es-define-property": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
@@ -4706,6 +4968,32 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-iterator-helpers": {
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz",
+ "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==",
+ "dev": true,
+ "dependencies": {
+ "asynciterator.prototype": "^1.0.0",
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.4",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.2",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "globalthis": "^1.0.3",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.7",
+ "iterator.prototype": "^1.1.2",
+ "safe-array-concat": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-module-lexer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
@@ -4725,6 +5013,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
"node_modules/es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
@@ -4897,6 +5194,18 @@
"eslint": ">=6.0.0"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -4955,6 +5264,92 @@
"eslint": ">=8.40.0"
}
},
+ "node_modules/eslint-plugin-escompat": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-escompat/-/eslint-plugin-escompat-3.4.0.tgz",
+ "integrity": "sha512-ufTPv8cwCxTNoLnTZBFTQ5SxU2w7E7wiMIS7PSxsgP1eAxFjtSaoZ80LRn64hI8iYziE6kJG6gX/ZCJVxh48Bg==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.14.1"
+ }
+ },
+ "node_modules/eslint-plugin-eslint-comments": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz",
+ "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5",
+ "ignore": "^5.0.5"
+ },
+ "engines": {
+ "node": ">=6.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=4.19.1"
+ }
+ },
+ "node_modules/eslint-plugin-eslint-comments/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint-plugin-filenames": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz",
+ "integrity": "sha512-tqxJTiEM5a0JmRCUYQmxw23vtTxrb2+a3Q2mMOPhFxvt7ZQQJmdiuMby9B/vUAuVMghyP7oET+nIf6EO6CBd/w==",
+ "dev": true,
+ "dependencies": {
+ "lodash.camelcase": "4.3.0",
+ "lodash.kebabcase": "4.1.1",
+ "lodash.snakecase": "4.1.1",
+ "lodash.upperfirst": "4.3.1"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/eslint-plugin-github": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.10.1.tgz",
+ "integrity": "sha512-1AqQBockOM+m0ZUpwfjWtX0lWdX5cRi/hwJnSNvXoOmz/Hh+ULH6QFz6ENWueTWjoWpgPv0af3bj+snps6o4og==",
+ "dev": true,
+ "dependencies": {
+ "@github/browserslist-config": "^1.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "@typescript-eslint/parser": "^6.0.0",
+ "aria-query": "^5.3.0",
+ "eslint-config-prettier": ">=8.0.0",
+ "eslint-plugin-escompat": "^3.3.3",
+ "eslint-plugin-eslint-comments": "^3.2.0",
+ "eslint-plugin-filenames": "^1.3.2",
+ "eslint-plugin-i18n-text": "^1.0.1",
+ "eslint-plugin-import": "^2.25.2",
+ "eslint-plugin-jsx-a11y": "^6.7.1",
+ "eslint-plugin-no-only-tests": "^3.0.0",
+ "eslint-plugin-prettier": "^5.0.0",
+ "eslint-rule-documentation": ">=1.0.0",
+ "jsx-ast-utils": "^3.3.2",
+ "prettier": "^3.0.0",
+ "svg-element-attributes": "^1.3.1"
+ },
+ "bin": {
+ "eslint-ignore-errors": "bin/eslint-ignore-errors.js"
+ },
+ "peerDependencies": {
+ "eslint": "^8.0.1"
+ }
+ },
"node_modules/eslint-plugin-i": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-i/-/eslint-plugin-i-2.29.1.tgz",
@@ -5002,6 +5397,98 @@
"node": "*"
}
},
+ "node_modules/eslint-plugin-i18n-text": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz",
+ "integrity": "sha512-3G3UetST6rdqhqW9SfcfzNYMpQXS7wNkJvp6dsXnjzGiku6Iu5hl3B0kmk6lIcFPwYjhQIY+tXVRtK9TlGT7RA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=5.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.29.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz",
+ "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.7",
+ "array.prototype.findlastindex": "^1.2.3",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.8.0",
+ "hasown": "^2.0.0",
+ "is-core-module": "^2.13.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.7",
+ "object.groupby": "^1.0.1",
+ "object.values": "^1.1.7",
+ "semver": "^6.3.1",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/eslint-plugin-jquery": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jquery/-/eslint-plugin-jquery-1.5.1.tgz",
@@ -5011,13 +5498,80 @@
"eslint": ">=5.4.0"
}
},
+ "node_modules/eslint-plugin-jsx-a11y": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
+ "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.23.2",
+ "aria-query": "^5.3.0",
+ "array-includes": "^3.1.7",
+ "array.prototype.flatmap": "^1.3.2",
+ "ast-types-flow": "^0.0.8",
+ "axe-core": "=4.7.0",
+ "axobject-query": "^3.2.1",
+ "damerau-levenshtein": "^1.0.8",
+ "emoji-regex": "^9.2.2",
+ "es-iterator-helpers": "^1.0.15",
+ "hasown": "^2.0.0",
+ "jsx-ast-utils": "^3.3.5",
+ "language-tags": "^1.0.9",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.7",
+ "object.fromentries": "^2.0.7"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/eslint-plugin-no-jquery": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.7.0.tgz",
"integrity": "sha512-Aeg7dA6GTH1AcWLlBtWNzOU9efK5KpNi7b0EhBO0o0M+awyzguUUo8gF6hXGjQ9n5h8/uRtYv9zOqQkeC5CG0w==",
"dev": true,
- "peerDependencies": {
- "eslint": ">=2.3.0"
+ "peerDependencies": {
+ "eslint": ">=2.3.0"
+ }
+ },
+ "node_modules/eslint-plugin-no-only-tests": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz",
+ "integrity": "sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==",
+ "dev": true,
+ "engines": {
+ "node": ">=5.0.0"
}
},
"node_modules/eslint-plugin-no-use-extend-native": {
@@ -5035,6 +5589,36 @@
"node": ">=6.0.0"
}
},
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-regexp": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.2.0.tgz",
@@ -5191,6 +5775,15 @@
"eslint": ">=5"
}
},
+ "node_modules/eslint-rule-documentation": {
+ "version": "1.0.23",
+ "resolved": "https://registry.npmjs.org/eslint-rule-documentation/-/eslint-rule-documentation-1.0.23.tgz",
+ "integrity": "sha512-pWReu3fkohwyvztx/oQWWgld2iad25TfUdi6wvhhaDPIQjHU/pyvlKgXFw1kX31SQK2Nq9MH+vRDWB0ZLy8fYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
@@ -6345,6 +6938,21 @@
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true
},
+ "node_modules/is-async-function": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
+ "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -6434,6 +7042,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-finalizationregistry": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
+ "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -6442,6 +7062,21 @@
"node": ">=8"
}
},
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-get-set-prop": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz",
@@ -6472,6 +7107,15 @@
"js-types": "^1.0.0"
}
},
+ "node_modules/is-map": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+ "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -6576,6 +7220,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-set": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -6654,6 +7307,15 @@
"is-potential-custom-element-name": "^1.0.0"
}
},
+ "node_modules/is-weakmap": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+ "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -6666,6 +7328,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-weakset": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -6685,6 +7360,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.4",
+ "set-function-name": "^2.0.1"
+ }
+ },
"node_modules/jackspeak": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
@@ -6915,6 +7603,21 @@
"node": ">=0.10.0"
}
},
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/just-extend": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-5.1.1.tgz",
@@ -6971,6 +7674,24 @@
"integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==",
"dev": true
},
+ "node_modules/language-subtag-registry": {
+ "version": "0.3.22",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
+ "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
+ "dev": true
+ },
+ "node_modules/language-tags": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
+ "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
+ "dev": true,
+ "dependencies": {
+ "language-subtag-registry": "^0.3.20"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/layout-base": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
@@ -7140,12 +7861,30 @@
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA=="
},
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "dev": true
+ },
+ "node_modules/lodash.kebabcase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+ "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+ "dev": true
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
+ "node_modules/lodash.snakecase": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+ "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+ "dev": true
+ },
"node_modules/lodash.sortedlastindex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/lodash.sortedlastindex/-/lodash.sortedlastindex-4.1.0.tgz",
@@ -7181,6 +7920,12 @@
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
"dev": true
},
+ "node_modules/lodash.upperfirst": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+ "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+ "dev": true
+ },
"node_modules/loupe": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
@@ -8260,6 +9005,67 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.entries": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
+ "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
+ "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz",
+ "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.filter": "^1.0.3",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.0.0"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
+ "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -8804,6 +9610,33 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -9046,6 +9879,27 @@
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.5.tgz",
+ "integrity": "sha512-62wgfC8dJWrmxv44CA36pLDnP6KKl3Vhxb7PL+8+qrrFMMoJij4vgiMP8zV4O8+CBMXY1mHxI5fITGHXFHVmQQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.0.0",
+ "get-intrinsic": "^1.2.3",
+ "globalthis": "^1.0.3",
+ "which-builtin-type": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
@@ -9834,6 +10688,15 @@
"node": ">=8"
}
},
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -10176,6 +11039,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svg-element-attributes": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/svg-element-attributes/-/svg-element-attributes-1.3.1.tgz",
+ "integrity": "sha512-Bh05dSOnJBf3miNMqpsormfNtfidA/GxQVakhtn0T4DECWKeXQRQUceYjJ+OxYiiLdGe4Jo9iFV8wICFapFeIA==",
+ "dev": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
@@ -10239,6 +11112,22 @@
"node": ">=14"
}
},
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/table": {
"version": "6.8.1",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
@@ -10491,6 +11380,30 @@
"node": ">=6.10"
}
},
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
@@ -11416,6 +12329,47 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/which-builtin-type": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
+ "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "dev": true,
+ "dependencies": {
+ "function.prototype.name": "^1.1.5",
+ "has-tostringtag": "^1.0.0",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.0.5",
+ "is-finalizationregistry": "^1.0.2",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.1.4",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.0.2",
+ "which-collection": "^1.0.1",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+ "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "dev": true,
+ "dependencies": {
+ "is-map": "^2.0.1",
+ "is-set": "^2.0.1",
+ "is-weakmap": "^2.0.1",
+ "is-weakset": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/which-typed-array": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz",
diff --git a/package.json b/package.json
index 3d753a567c1b8..fdea78ca299b7 100644
--- a/package.json
+++ b/package.json
@@ -67,6 +67,7 @@
"@vitejs/plugin-vue": "5.0.4",
"eslint": "8.56.0",
"eslint-plugin-array-func": "4.0.0",
+ "eslint-plugin-github": "4.10.1",
"eslint-plugin-i": "2.29.1",
"eslint-plugin-jquery": "1.5.1",
"eslint-plugin-no-jquery": "2.7.0",
diff --git a/web_src/js/features/repo-code.js b/web_src/js/features/repo-code.js
index 306f38829fad2..a142313211e8b 100644
--- a/web_src/js/features/repo-code.js
+++ b/web_src/js/features/repo-code.js
@@ -194,7 +194,7 @@ export function initRepoCodeView() {
const blob = await $.get(`${url}?${query}&anchor=${anchor}`);
currentTarget.closest('tr').outerHTML = blob;
});
- $(document).on('click', '.copy-line-permalink', async (e) => {
- await clippie(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
+ $(document).on('click', '.copy-line-permalink', async ({currentTarget}) => {
+ await clippie(toAbsoluteUrl(currentTarget.getAttribute('data-url')));
});
}
diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js
index ca20cfbe387d4..efc7671204828 100644
--- a/web_src/js/features/repo-issue-list.js
+++ b/web_src/js/features/repo-issue-list.js
@@ -69,16 +69,12 @@ function initRepoIssueListCheckboxes() {
}
}
- updateIssuesMeta(
- url,
- action,
- issueIDs,
- elementId,
- ).then(() => {
+ try {
+ await updateIssuesMeta(url, action, issueIDs, elementId);
window.location.reload();
- }).catch((reason) => {
- showErrorToast(reason.responseJSON.error);
- });
+ } catch (err) {
+ showErrorToast(err.responseJSON?.error ?? err.message);
+ }
});
}
diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js
index 6908e0c912342..3437565c804ae 100644
--- a/web_src/js/features/repo-issue.js
+++ b/web_src/js/features/repo-issue.js
@@ -344,19 +344,15 @@ export async function updateIssuesMeta(url, action, issueIds, elementId) {
export function initRepoIssueComments() {
if ($('.repository.view.issue .timeline').length === 0) return;
- $('.re-request-review').on('click', function (e) {
+ $('.re-request-review').on('click', async function (e) {
e.preventDefault();
const url = $(this).data('update-url');
const issueId = $(this).data('issue-id');
const id = $(this).data('id');
const isChecked = $(this).hasClass('checked');
- updateIssuesMeta(
- url,
- isChecked ? 'detach' : 'attach',
- issueId,
- id,
- ).then(() => window.location.reload());
+ await updateIssuesMeta(url, isChecked ? 'detach' : 'attach', issueId, id);
+ window.location.reload();
});
$(document).on('click', (event) => {
diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js
index 08fe21190ac8a..ce1bff11a2f5c 100644
--- a/web_src/js/features/repo-legacy.js
+++ b/web_src/js/features/repo-legacy.js
@@ -205,12 +205,15 @@ export function initRepoCommentForm() {
$listMenu.find('.no-select.item').on('click', function (e) {
e.preventDefault();
if (hasUpdateAction) {
- updateIssuesMeta(
- $listMenu.data('update-url'),
- 'clear',
- $listMenu.data('issue-id'),
- '',
- ).then(reloadConfirmDraftComment);
+ (async () => {
+ await updateIssuesMeta(
+ $listMenu.data('update-url'),
+ 'clear',
+ $listMenu.data('issue-id'),
+ '',
+ );
+ reloadConfirmDraftComment();
+ })();
}
$(this).parent().find('.item').each(function () {
@@ -248,12 +251,15 @@ export function initRepoCommentForm() {
$(this).addClass('selected active');
if (hasUpdateAction) {
- updateIssuesMeta(
- $menu.data('update-url'),
- '',
- $menu.data('issue-id'),
- $(this).data('id'),
- ).then(reloadConfirmDraftComment);
+ (async () => {
+ await updateIssuesMeta(
+ $menu.data('update-url'),
+ '',
+ $menu.data('issue-id'),
+ $(this).data('id'),
+ );
+ reloadConfirmDraftComment();
+ })();
}
let icon = '';
@@ -281,12 +287,15 @@ export function initRepoCommentForm() {
});
if (hasUpdateAction) {
- updateIssuesMeta(
- $menu.data('update-url'),
- '',
- $menu.data('issue-id'),
- $(this).data('id'),
- ).then(reloadConfirmDraftComment);
+ (async () => {
+ await updateIssuesMeta(
+ $menu.data('update-url'),
+ '',
+ $menu.data('issue-id'),
+ $(this).data('id'),
+ );
+ reloadConfirmDraftComment();
+ })();
}
$list.find('.selected').html('');
From e936d2b338859c527482d1569c92d1f8f97f4d51 Mon Sep 17 00:00:00 2001
From: GiteaBot
Date: Sat, 17 Feb 2024 00:23:24 +0000
Subject: [PATCH 07/28] [skip ci] Updated translations via Crowdin
---
options/locale/locale_el-GR.ini | 50 +++++++++++++++++++++++
options/locale/locale_tr-TR.ini | 71 +++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini
index 5164217616fc6..749a2ae4031f1 100644
--- a/options/locale/locale_el-GR.ini
+++ b/options/locale/locale_el-GR.ini
@@ -381,6 +381,7 @@ email_not_associate=Η διεύθυνση ηλεκτρονικού ταχυδρ
send_reset_mail=Αποστολή Email Ανάκτησης Λογαριασμού
reset_password=Ανάκτηση Λογαριασμού
invalid_code=Ο κωδικός επιβεβαίωσης δεν είναι έγκυρος ή έχει λήξει.
+invalid_code_forgot_password=Ο κωδικός επιβεβαίωσης δεν είναι έγκυρος ή έληξε. Πατήστε εδώ για να ξεκινήσετε νέα συνεδρία.
invalid_password=Ο κωδικός πρόσβασης σας δεν ταιριάζει με τον κωδικό που χρησιμοποιήθηκε για τη δημιουργία του λογαριασμού.
reset_password_helper=Ανάκτηση Λογαριασμού
reset_password_wrong_user=Έχετε συνδεθεί ως %s, αλλά ο σύνδεσμος ανάκτησης λογαριασμού προορίζεται για το %s
@@ -864,10 +865,12 @@ revoke_oauth2_grant_description=Η ανάκληση πρόσβασης για α
revoke_oauth2_grant_success=Η πρόσβαση ανακλήθηκε επιτυχώς.
twofa_desc=Ο έλεγχος ταυτότητας δύο παραγόντων ενισχύει την ασφάλεια του λογαριασμού σας.
+twofa_recovery_tip=Αν χάσετε τη συσκευή σας, θα είστε σε θέση να χρησιμοποιήσετε ένα κλειδί ανάκτησης μιας χρήσης για να ανακτήσετε την πρόσβαση στο λογαριασμό σας.
twofa_is_enrolled=Ο λογαριασμός σας είναι εγγεγραμμένος σε έλεγχο ταυτότητας δύο παραγόντων.
twofa_not_enrolled=Ο λογαριασμός σας δεν είναι εγγεγραμμένος σε έλεγχο ταυτότητας δύο παραγόντων.
twofa_disable=Απενεργοποίηση Ταυτοποίησης Δύο Παραμέτρων
twofa_scratch_token_regenerate=Αναδημιουργία Διακριτικού Μίας Χρήσης
+twofa_scratch_token_regenerated=Το κλειδί ανάκτησης μιας χρήσης είναι τώρα %s. Αποθηκεύστε το σε ασφαλές μέρος, καθώς δε θα εμφανιστεί ξανά.
twofa_enroll=Εγγραφή στην ταυτοποίηση δύο παραγόντων
twofa_disable_note=Μπορείτε να απενεργοποιήσετε την ταυτοποίηση δύο παραγόντων αν χρειαστεί.
twofa_disable_desc=Η απενεργοποίηση της ταυτοποίησης δύο παραγόντων θα καταστήσει τον λογαριασμό σας λιγότερο ασφαλή. Συνέχεια;
@@ -885,6 +888,8 @@ webauthn_register_key=Προσθήκη Κλειδιού Ασφαλείας
webauthn_nickname=Ψευδώνυμο
webauthn_delete_key=Αφαίρεση Κλειδιού Ασφαλείας
webauthn_delete_key_desc=Αν αφαιρέσετε ένα κλειδί ασφαλείας δεν μπορείτε πλέον να συνδεθείτε με αυτό. Συνέχεια;
+webauthn_key_loss_warning=Αν χάσετε τα κλειδιά ασφαλείας σας, θα χάσετε την πρόσβαση στο λογαριασμό σας.
+webauthn_alternative_tip=Μπορεί να θέλετε να ρυθμίσετε μια πρόσθετη μέθοδο ταυτοποίησης.
manage_account_links=Διαχείριση Συνδεδεμένων Λογαριασμών
manage_account_links_desc=Αυτοί οι εξωτερικοί λογαριασμοί είναι συνδεδεμένοι στον Gitea λογαριασμό σας.
@@ -894,6 +899,7 @@ remove_account_link=Αφαίρεση Συνδεδεμένου Λογαριασμ
remove_account_link_desc=Η κατάργηση ενός συνδεδεμένου λογαριασμού θα ανακαλέσει την πρόσβασή του στο λογαριασμό σας στο Gitea. Συνέχεια;
remove_account_link_success=Ο συνδεδεμένος λογαριασμός έχει αφαιρεθεί.
+hooks.desc=Προσθήκη webhooks που θα ενεργοποιούνται για όλα τα αποθετήρια που σας ανήκουν.
orgs_none=Δεν είστε μέλος σε κάποιο οργανισμό.
repos_none=Δεν κατέχετε κάποιο αποθετήριο.
@@ -915,9 +921,12 @@ visibility=Ορατότητα χρήστη
visibility.public=Δημόσια
visibility.public_tooltip=Ορατό σε όλους
visibility.limited=Περιορισμένη
+visibility.limited_tooltip=Ορατό μόνο στους ταυτοποιημένους χρήστες
visibility.private=Ιδιωτική
+visibility.private_tooltip=Ορατό μόνο στα μέλη των οργανισμών που συμμετέχετε
[repo]
+new_repo_helper=Ένα αποθετήριο περιέχει όλα τα αρχεία έργου, συμπεριλαμβανομένου του ιστορικού εκδόσεων. Ήδη φιλοξενείται αλλού; Μετεγκατάσταση αποθετηρίου.
owner=Ιδιοκτήτης
owner_helper=Ορισμένοι οργανισμοί ενδέχεται να μην εμφανίζονται στο αναπτυσσόμενο μενού λόγω του μέγιστου αριθμού αποθετηρίων.
repo_name=Όνομα αποθετηρίου
@@ -940,6 +949,7 @@ fork_to_different_account=Fork σε διαφορετικό λογαριασμό
fork_visibility_helper=Η ορατότητα ενός fork αποθετηρίου δεν μπορεί να αλλάξει.
fork_branch=Κλάδος που θα κλωνοποιηθεί στο fork
all_branches=Όλοι οι κλάδοι
+fork_no_valid_owners=Αυτό το αποθετήριο δεν μπορεί να γίνει fork επειδή δεν υπάρχουν έγκυροι ιδιοκτήτες.
use_template=Χρήση αυτού του πρότυπου
clone_in_vsc=Κλωνοποίηση στο VS Code
download_zip=Λήψη ZIP
@@ -1004,13 +1014,20 @@ delete_preexisting=Διαγραφή αρχείων που προϋπήρχαν
delete_preexisting_content=Διαγραφή αρχείων στο %s
delete_preexisting_success=Διαγράφηκαν τα μη υιοθετημένα αρχεία στο %s
blame_prior=Προβολή ευθύνης πριν από αυτή την αλλαγή
+blame.ignore_revs=Αγνόηση των αναθεωρήσεων στο .git-blame-ignore-revs . Πατήστε εδώ για να το παρακάμψετε και να δείτε την κανονική προβολή ευθυνών.
+blame.ignore_revs.failed=Αποτυχία αγνόησης των αναθεωρήσεων στο .git-blame-ignore-revs .
author_search_tooltip=Εμφάνιση το πολύ 30 χρηστών
+tree_path_not_found_commit=Η διαδρομή %[1]s δεν υπάρχει στην υποβολή %[2]s
+tree_path_not_found_branch=Η διαδρομή %[1]s δεν υπάρχει στον κλάδο %[2]s
+tree_path_not_found_tag=Η διαδρομή %[1]s δεν υπάρχει στην ετικέτα %[2]s
transfer.accept=Αποδοχή Μεταφοράς
transfer.accept_desc=`Μεταφορά στο "%s"`
transfer.reject=Απόρριψη Μεταφοράς
transfer.reject_desc=`Ακύρωση μεταφοράς σε "%s"`
+transfer.no_permission_to_accept=Δεν έχετε άδεια να αποδεχτείτε αυτή τη μεταφορά.
+transfer.no_permission_to_reject=Δεν έχετε άδεια να απορρίψετε αυτή τη μεταφορά.
desc.private=Ιδιωτικό
desc.public=Δημόσιο
@@ -1029,6 +1046,8 @@ template.issue_labels=Σήματα Ζητήματος
template.one_item=Πρέπει να επιλέξετε τουλάχιστον ένα αντικείμενο στο πρότυπο
template.invalid=Πρέπει να επιλέξετε ένα πρότυπο αποθετήριο
+archive.title=Αυτό το αποθετήρειο αρχειοθετήθηκε. Μπορείτε να προβάλετε αρχεία και να τα κλωνοποιήσετε, αλλά δεν μπορείτε να ωθήσετε ή να ανοίξετε ζητήματα ή pull requests.
+archive.title_date=Αυτό το αποθετήριο έχει αρχειοθετηθεί στο %s. Μπορείτε να προβάλετε αρχεία και να κλωνοποιήσετε, αλλά δεν μπορείτε να ωθήσετε ή να ανοίξετε ζητήματα ή pull requests.
archive.issue.nocomment=Αυτό το αποθετήριο αρχειοθετήθηκε. Δεν μπορείτε να σχολιάσετε σε ζητήματα.
archive.pull.nocomment=Αυτό το repo αρχειοθετήθηκε. Δεν μπορείτε να σχολιάσετε στα pull requests.
@@ -1045,6 +1064,7 @@ migrate_options_lfs=Μεταφορά αρχείων LFS
migrate_options_lfs_endpoint.label=Άκρο LFS
migrate_options_lfs_endpoint.description=Η μεταφορά θα προσπαθήσει να χρησιμοποιήσει το Git remote για να καθορίσει τον διακομιστή LFS . Μπορείτε επίσης να καθορίσετε ένα δικό σας endpoint αν τα δεδομένα LFS του αποθετηρίου αποθηκεύονται κάπου αλλού.
migrate_options_lfs_endpoint.description.local=Μια διαδρομή στο τοπικό διακομιστή επίσης υποστηρίζεται.
+migrate_options_lfs_endpoint.placeholder=Αν αφεθεί κενό, το άκρο θα προκύψει από το URL του κλώνου
migrate_items=Στοιχεία Μεταφοράς
migrate_items_wiki=Wiki
migrate_items_milestones=Ορόσημα
@@ -1147,6 +1167,7 @@ file_view_rendered=Προβολή Απόδοσης
file_view_raw=Προβολή Ακατέργαστου
file_permalink=Permalink
file_too_large=Το αρχείο είναι πολύ μεγάλο για να εμφανιστεί.
+invisible_runes_header=`Αυτό το αρχείο περιέχει αόρατους χαρακτήρες Unicode `
invisible_runes_description=`Αυτό το αρχείο περιέχει αόρατους χαρακτήρες Unicode που δεν διακρίνονται από ανθρώπους, αλλά μπορεί να επεξεργάζονται διαφορετικά από έναν υπολογιστή. Αν νομίζετε ότι αυτό είναι σκόπιμο, μπορείτε να αγνοήσετε με ασφάλεια αυτή την προειδοποίηση. Χρησιμοποιήστε το κουμπί Escape για να τους αποκαλύψετε.`
ambiguous_runes_header=`Αυτό το αρχείο περιέχει ασαφείς χαρακτήρες Unicode `
ambiguous_runes_description=`Αυτό το αρχείο περιέχει χαρακτήρες Unicode που μπορεί να συγχέονται με άλλους χαρακτήρες. Αν νομίζετε ότι αυτό είναι σκόπιμο, μπορείτε να αγνοήσετε με ασφάλεια αυτή την προειδοποίηση. Χρησιμοποιήστε το κουμπί Escape για να τους αποκαλύψετε.`
@@ -1425,6 +1446,7 @@ issues.filter_sort.moststars=Περισσότερα αστέρια
issues.filter_sort.feweststars=Λιγότερα αστέρια
issues.filter_sort.mostforks=Περισσότερα forks
issues.filter_sort.fewestforks=Λιγότερα forks
+issues.keyword_search_unavailable=Η αναζήτηση μέσω λέξεων κλειδιών δεν είναι διαθέσιμη. Παρακαλώ επικοινωνήστε με το διαχειριστή.
issues.action_open=Άνοιγμα
issues.action_close=Κλείσιμο
issues.action_label=Σήμα
@@ -1715,8 +1737,12 @@ pulls.is_empty=Οι αλλαγές σε αυτόν τον κλάδο είναι
pulls.required_status_check_failed=Ορισμένοι απαιτούμενοι έλεγχοι δεν ήταν επιτυχείς.
pulls.required_status_check_missing=Λείπουν ορισμένοι απαιτούμενοι έλεγχοι.
pulls.required_status_check_administrator=Ως διαχειριστής, μπορείτε ακόμα να συγχωνεύσετε αυτό το pull request.
+pulls.blocked_by_approvals=Το pull request δεν έχει ακόμα αρκετές εγκρίσεις. Δόθηκαν %d από %d εγκρίσεις.
pulls.blocked_by_rejection=Αυτό το Pull Request έχει αλλαγές που ζητούνται από έναν επίσημο εξεταστή.
pulls.blocked_by_official_review_requests=Αυτό το Pull Request έχει επίσημες αιτήσεις αξιολόγησης.
+pulls.blocked_by_outdated_branch=Αυτό το pull request έχει αποκλειστεί επειδή είναι παρωχημένο.
+pulls.blocked_by_changed_protected_files_1=Αυτό το pull request έχει αποκλειστεί επειδή αλλάζει ένα προστατευμένο αρχείο:
+pulls.blocked_by_changed_protected_files_n=Αυτό το pull request έχει αποκλειστεί επειδή αλλάζει προστατευμένα αρχεία:
pulls.can_auto_merge_desc=Αυτό το Pull Request μπορεί να συγχωνευθεί αυτόματα.
pulls.cannot_auto_merge_desc=Αυτό το pull request δεν μπορεί να συγχωνευθεί αυτόματα λόγω συγκρούσεων.
pulls.cannot_auto_merge_helper=Χειροκίνητη Συγχώνευση για την επίλυση των συγκρούσεων.
@@ -1832,11 +1858,16 @@ milestones.filter_sort.least_issues=Λιγότερα ζητήματα
signing.will_sign=Αυτή η υποβολή θα υπογραφεί με το κλειδί "%s".
signing.wont_sign.error=Παρουσιάστηκε σφάλμα κατά τον έλεγχο για το αν η υποβολή μπορεί να υπογραφεί.
+signing.wont_sign.nokey=Δεν υπάρχει διαθέσιμο κλειδί για να υπογραφεί αυτή η υποβολή.
signing.wont_sign.never=Οι υποβολές δεν υπογράφονται ποτέ.
signing.wont_sign.always=Οι υποβολές υπογράφονται πάντα.
+signing.wont_sign.pubkey=Η υποβολή δε θα υπογραφεί επειδή δεν υπάρχει δημόσιο κλειδί που να συνδέεται με το λογαριασμό σας.
+signing.wont_sign.twofa=Πρέπει να έχετε ενεργοποιημένη την ταυτοποίηση δύο παραγόντων για να υπογράφεται υποβολές.
signing.wont_sign.parentsigned=Η υποβολή δε θα υπογραφεί καθώς η γονική υποβολή δεν έχει υπογραφεί.
signing.wont_sign.basesigned=Η συγχώνευση δε θα υπογραφεί καθώς η βασική υποβολή δεν έχει υπογραφή της βάσης.
signing.wont_sign.headsigned=Η συγχώνευση δε θα υπογραφεί καθώς δεν έχει υπογραφή η υποβολή της κεφαλής.
+signing.wont_sign.commitssigned=Η συγχώνευση δε θα υπογραφεί καθώς όλες οι σχετικές υποβολές δεν έχουν υπογραφεί.
+signing.wont_sign.approved=Η συγχώνευση δε θα υπογραφεί καθώς το PR δεν έχει εγκριθεί.
signing.wont_sign.not_signed_in=Δεν είστε συνδεδεμένοι.
ext_wiki=Πρόσβαση στο Εξωτερικό Wiki
@@ -1967,7 +1998,9 @@ settings.mirror_settings.docs.disabled_push_mirror.info=Τα είδωλα ώθη
settings.mirror_settings.docs.no_new_mirrors=Το αποθετήριο σας αντιγράφει τις αλλαγές προς ή από ένα άλλο αποθετήριο. Λάβετε υπόψη ότι δεν μπορείτε να δημιουργήσετε νέα είδωλα αυτή τη στιγμή.
settings.mirror_settings.docs.can_still_use=Αν και δεν μπορείτε να τροποποιήσετε τα υπάρχοντα είδωλα ή να δημιουργήσετε νέα, μπορείτε να χρησιμοποιείται ακόμα το υπάρχων είδωλο.
settings.mirror_settings.docs.pull_mirror_instructions=Για να ορίσετε έναν είδωλο έλξης, παρακαλούμε συμβουλευθείτε:
+settings.mirror_settings.docs.more_information_if_disabled=Μπορείτε να μάθετε περισσότερα για τα είδωλα ώθησης και έλξης εδώ:
settings.mirror_settings.docs.doc_link_title=Πώς μπορώ να αντιγράψω αποθετήρια;
+settings.mirror_settings.docs.doc_link_pull_section=το κεφάλαιο "Pulling from a remote repository" της τεκμηρίωσης.
settings.mirror_settings.docs.pulling_remote_title=Έλξη από ένα απομακρυσμένο αποθετήριο
settings.mirror_settings.mirrored_repository=Είδωλο αποθετηρίου
settings.mirror_settings.direction=Κατεύθυνση
@@ -1980,6 +2013,8 @@ settings.mirror_settings.push_mirror.add=Προσθήκη Είδωλου Push
settings.mirror_settings.push_mirror.edit_sync_time=Επεξεργασία διαστήματος συγχρονισμού ειδώλου
settings.sync_mirror=Συγχρονισμός Τώρα
+settings.pull_mirror_sync_in_progress=Έλκονται αλλαγές από το απομακρυσμένο %s αυτή τη στιγμή.
+settings.push_mirror_sync_in_progress=Ώθηση αλλαγών στο απομακρυσμένο %s αυτή τη στιγμή.
settings.site=Ιστοσελίδα
settings.update_settings=Ενημέρωση Ρυθμίσεων
settings.update_mirror_settings=Ενημέρωση Ρυθμίσεων Ειδώλου
@@ -2046,6 +2081,7 @@ settings.transfer.rejected=Η μεταβίβαση του αποθετηρίου
settings.transfer.success=Η μεταβίβαση του αποθετηρίου ήταν επιτυχής.
settings.transfer_abort=Ακύρωση μεταβίβασης
settings.transfer_abort_invalid=Δεν μπορείτε να ακυρώσετε μια ανύπαρκτη μεταβίβαση αποθετηρίου.
+settings.transfer_abort_success=Η μεταφορά αποθετηρίου στο %s ακυρώθηκε με επιτυχία.
settings.transfer_desc=Μεταβιβάστε αυτό το αποθετήριο σε έναν χρήστη ή σε έναν οργανισμό για τον οποίο έχετε δικαιώματα διαχειριστή.
settings.transfer_form_title=Εισάγετε το όνομα του αποθετηρίου ως επιβεβαίωση:
settings.transfer_in_progress=Αυτή τη στιγμή υπάρχει μια εν εξελίξει μεταβίβαση. Παρακαλούμε ακυρώστε την αν θέλετε να μεταβιβάσετε αυτό το αποθετήριο σε άλλο χρήστη.
@@ -2335,6 +2371,7 @@ settings.unarchive.button=Απο-Αρχειοθέτηση αποθετηρίου
settings.unarchive.header=Απο-Αρχειοθέτηση του αποθετηρίου
settings.unarchive.text=Η απο-αρχειοθέτηση του αποθετηρίου θα αποκαταστήσει την ικανότητά του να λαμβάνει υποβολές και ωθήσεις, καθώς και νέα ζητήματα και pull-requests.
settings.unarchive.success=Το αποθετήριο απο-αρχειοθετήθηκε με επιτυχία.
+settings.unarchive.error=Παρουσιάστηκε σφάλμα κατά την προσπάθεια απο-αρχειοθέτησης του αποθετηρίου. Δείτε τις καταγραφές για περισσότερες λεπτομέρειες.
settings.update_avatar_success=Η εικόνα του αποθετηρίου έχει ενημερωθεί.
settings.lfs=LFS
settings.lfs_filelist=Αρχεία LFS σε αυτό το αποθετήριο
@@ -2458,6 +2495,7 @@ release.edit_release=Ενημέρωση Κυκλοφορίας
release.delete_release=Διαγραφή Κυκλοφορίας
release.delete_tag=Διαγραφή Ετικέτας
release.deletion=Διαγραφή Κυκλοφορίας
+release.deletion_desc=Διαγράφοντας μια κυκλοφορία, αυτή αφαιρείται μόνο από το Gitea. Δε θα επηρεάσει την ετικέτα Git, τα περιεχόμενα του αποθετηρίου σας ή το ιστορικό της. Συνέχεια;
release.deletion_success=Η κυκλοφορία έχει διαγραφεί.
release.deletion_tag_desc=Θα διαγράψει αυτή την ετικέτα από το αποθετήριο. Τα περιεχόμενα του αποθετηρίου και το ιστορικό παραμένουν αμετάβλητα. Συνέχεια;
release.deletion_tag_success=Η ετικέτα έχει διαγραφεί.
@@ -2477,6 +2515,7 @@ branch.already_exists=Ήδη υπάρχει ένας κλάδος με το όν
branch.delete_head=Διαγραφή
branch.delete=`Διαγραφή του Κλάδου "%s"`
branch.delete_html=Διαγραφή Κλάδου
+branch.delete_desc=Η διαγραφή ενός κλάδου είναι μόνιμη. Αν και ο διαγραμμένος κλάδος μπορεί να συνεχίσει να υπάρχει για σύντομο χρονικό διάστημα πριν να αφαιρεθεί, ΔΕΝ ΜΠΟΡΕΙ να αναιρεθεί στις περισσότερες περιπτώσεις. Συνέχεια;
branch.deletion_success=Ο κλάδος "%s" διαγράφηκε.
branch.deletion_failed=Αποτυχία διαγραφής του κλάδου "%s".
branch.delete_branch_has_new_commits=Ο κλάδος "%s" δεν μπορεί να διαγραφεί επειδή προστέθηκαν νέες υποβολές μετά τη συγχώνευση.
@@ -2711,6 +2750,7 @@ dashboard.reinit_missing_repos=Επανεκκινήστε όλα τα αποθε
dashboard.sync_external_users=Συγχρονισμός δεδομένων εξωτερικών χρηστών
dashboard.cleanup_hook_task_table=Εκκαθάριση πίνακα hook_task
dashboard.cleanup_packages=Εκκαθάριση ληγμένων πακέτων
+dashboard.cleanup_actions=Οι ενέργειες καθαρισμού καταγραφές και αντικείμενα
dashboard.server_uptime=Διάρκεια Διακομιστή
dashboard.current_goroutine=Τρέχουσες Goroutines
dashboard.current_memory_usage=Τρέχουσα Χρήση Μνήμης
@@ -2821,6 +2861,7 @@ emails.updated=Το email ενημερώθηκε
emails.not_updated=Αποτυχία ενημέρωσης της ζητούμενης διεύθυνσης email: %v
emails.duplicate_active=Αυτή η διεύθυνση email είναι ήδη ενεργή σε διαφορετικό χρήστη.
emails.change_email_header=Ενημέρωση Ιδιοτήτων Email
+emails.change_email_text=Είστε βέβαιοι ότι θέλετε να ενημερώσετε αυτή τη διεύθυνση email;
orgs.org_manage_panel=Διαχείριση Οργανισμού
orgs.name=Όνομα
@@ -2845,6 +2886,7 @@ packages.package_manage_panel=Διαχείριση Πακέτων
packages.total_size=Συνολικό Μέγεθος: %s
packages.unreferenced_size=Μέγεθος Χωρίς Αναφορά: %s
packages.cleanup=Εκκαθάριση ληγμένων δεδομένων
+packages.cleanup.success=Επιτυχής εκκαθάριση δεδομένων που έχουν λήξει
packages.owner=Ιδιοκτήτης
packages.creator=Δημιουργός
packages.name=Όνομα
@@ -2855,10 +2897,12 @@ packages.size=Μέγεθος
packages.published=Δημοσιευμένα
defaulthooks=Προεπιλεγμένα Webhooks
+defaulthooks.desc=Τα Webhooks κάνουν αυτόματα αιτήσεις HTTP POST σε ένα διακομιστή όταν ενεργοποιούν ορισμένα γεγονότα στο Gitea. Τα Webhooks που ορίζονται εδώ είναι προκαθορισμένα και θα αντιγραφούν σε όλα τα νέα αποθετήρια. Διαβάστε περισσότερα στον οδηγό webhooks .
defaulthooks.add_webhook=Προσθήκη Προεπιλεγμένου Webhook
defaulthooks.update_webhook=Ενημέρωση Προεπιλεγμένου Webhook
systemhooks=Webhooks Συστήματος
+systemhooks.desc=Τα Webhooks κάνουν αυτόματα αιτήσεις HTTP POST σε ένα διακομιστή όταν ενεργοποιούνται ορισμένα γεγονότα στο Gitea. Τα Webhooks που ορίζονται εδώ θα ενεργούν σε όλα τα αποθετήρια του συστήματος, γι 'αυτό παρακαλώ εξετάστε τυχόν επιπτώσεις απόδοσης που μπορεί να έχει. Διαβάστε περισσότερα στον οδηγό webhooks .
systemhooks.add_webhook=Προσθήκη Webhook Συστήματος
systemhooks.update_webhook=Ενημέρωση Webhook Συστήματος
@@ -2951,6 +2995,7 @@ auths.sspi_default_language=Προεπιλεγμένη γλώσσα χρήστη
auths.sspi_default_language_helper=Προεπιλεγμένη γλώσσα για τους χρήστες που δημιουργούνται αυτόματα με τη μέθοδο ταυτοποίησης SSPI. Αφήστε κενό αν προτιμάτε η γλώσσα να εντοπιστεί αυτόματα.
auths.tips=Συμβουλές
auths.tips.oauth2.general=Ταυτοποίηση OAuth2
+auths.tips.oauth2.general.tip=Κατά την εγγραφή μιας νέας ταυτοποίησης OAuth2, το URL κλήσης/ανακατεύθυνσης πρέπει να είναι:
auths.tip.oauth2_provider=Πάροχος OAuth2
auths.tip.bitbucket=Καταχωρήστε ένα νέο καταναλωτή OAuth στο https://bitbucket.org/account/user//oauth-consumers/new και προσθέστε το δικαίωμα 'Account' - 'Read'
auths.tip.nextcloud=`Καταχωρήστε ένα νέο καταναλωτή OAuth στην υπηρεσία σας χρησιμοποιώντας το παρακάτω μενού "Settings -> Security -> OAuth 2.0 client"`
@@ -2962,6 +3007,7 @@ auths.tip.google_plus=Αποκτήστε τα διαπιστευτήρια πε
auths.tip.openid_connect=Χρησιμοποιήστε το OpenID Connect Discovery URL (/.well known/openid-configuration) για να καθορίσετε τα τελικά σημεία
auths.tip.twitter=Πηγαίνετε στο https://dev.twitter.com/apps, δημιουργήστε μια εφαρμογή και βεβαιωθείτε ότι η επιλογή “Allow this application to be used to Sign in with Twitter” είναι ενεργοποιημένη
auths.tip.discord=Καταχωρήστε μια νέα εφαρμογή στο https://discordapp.com/developers/applications/me
+auths.tip.gitea=Καταχωρήστε μια νέα εφαρμογή OAuth2. Μπορείτε να βρείτε τον οδηγό στο https://docs.gitea.com/development/oauth2-provider
auths.tip.yandex=`Δημιουργήστε μια νέα εφαρμογή στο https://oauth.yandex.com/client/new. Επιλέξτε τα ακόλουθα δικαιώματα από την ενότητα "Yandex.Passport API": "Access to email address", "Access to user avatar" και "Access to username, first name and surname, gender"`
auths.tip.mastodon=Εισαγάγετε ένα προσαρμομένο URL για την υπηρεσία mastodon με την οποία θέλετε να πιστοποιήσετε (ή να χρησιμοποιήσετε την προεπιλεγμένη)
auths.edit=Επεξεργασία Πηγής Ταυτοποίησης
@@ -3265,6 +3311,7 @@ desc=Διαχείριση πακέτων μητρώου.
empty=Δεν υπάρχουν πακέτα ακόμα.
empty.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο πακέτων, ανατρέξτε στην τεκμηρίωση .
empty.repo=Μήπως ανεβάσατε ένα πακέτο, αλλά δεν εμφανίζεται εδώ; Πηγαίνετε στις ρυθμίσεις πακέτων και συνδέστε το σε αυτό το αποθετήριο.
+registry.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο %s, ανατρέξτε στη τεκμηρίωση .
filter.type=Τύπος
filter.type.all=Όλα
filter.no_result=Το φίλτρο δεν παρήγαγε αποτελέσματα.
@@ -3376,9 +3423,11 @@ settings.delete.success=Το πακέτο έχει διαγραφεί.
settings.delete.error=Αποτυχία διαγραφής του πακέτου.
owner.settings.cargo.title=Ευρετήριο Μητρώου Cargo
owner.settings.cargo.initialize=Αρχικοποίηση Ευρετηρίου
+owner.settings.cargo.initialize.description=Απαιτείται ένα ειδικό αποθετήριο ευρετηρίου Git για τη χρήση του μητρώου Cargo. Χρησιμοποιώντας αυτή την επιλογή θα δημιουργηθεί ξανά το αποθετήριο και θα ρυθμιστεί αυτόματα.
owner.settings.cargo.initialize.error=Αποτυχία αρχικοποίησης ευρετηρίου Cargo: %v
owner.settings.cargo.initialize.success=Ο ευρετήριο Cargo δημιουργήθηκε με επιτυχία.
owner.settings.cargo.rebuild=Αναδημιουργία Ευρετηρίου
+owner.settings.cargo.rebuild.description=Η ανοικοδόμηση μπορεί να είναι χρήσιμη εάν ο δείκτης δεν είναι συγχρονισμένος με τα αποθηκευμένα πακέτα Cargo.
owner.settings.cargo.rebuild.error=Αποτυχία αναδόμησης του ευρετηρίου Cargo: %v
owner.settings.cargo.rebuild.success=Το ευρετήριο Cargo αναδομήθηκε με επιτυχία.
owner.settings.cleanuprules.title=Διαχείριση Κανόνων Εκκαθάρισης
@@ -3403,6 +3452,7 @@ owner.settings.cleanuprules.success.update=Ο κανόνας καθαρισμο
owner.settings.cleanuprules.success.delete=Ο κανόνας καθαρισμού διαγράφηκε.
owner.settings.chef.title=Μητρώο Chef
owner.settings.chef.keypair=Δημιουργία ζεύγους κλειδιών
+owner.settings.chef.keypair.description=Ένα ζεύγος κλειδιών είναι απαραίτητο για ταυτοποίηση στο μητρώο Chef. Αν έχετε δημιουργήσει ένα ζεύγος κλειδιών πριν, η δημιουργία ενός νέου ζεύγους κλειδιών θα απορρίψει το παλιό ζεύγος κλειδιών.
[secrets]
secrets=Μυστικά
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index dd7d1b066e8b7..ea028657db9c4 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -17,6 +17,7 @@ template=Şablon
language=Dil
notifications=Bildirimler
active_stopwatch=Etkin Zaman Takibi
+tracked_time_summary=Konu listesi süzgeçlerine dayanan takip edilen zamanın özeti
create_new=Oluştur…
user_profile_and_more=Profil ve Ayarlar…
signed_in_as=Giriş yapan:
@@ -90,6 +91,7 @@ remove=Kaldır
remove_all=Tümünü Kaldır
remove_label_str=`"%s" öğesini kaldır`
edit=Düzenle
+view=Görüntüle
enabled=Aktifleştirilmiş
disabled=Devre Dışı
@@ -97,6 +99,7 @@ locked=Kilitli
copy=Kopyala
copy_url=URL'yi kopyala
+copy_hash=Hash'i kopyala
copy_content=İçeriği kopyala
copy_branch=Dal adını kopyala
copy_success=Kopyalandı!
@@ -109,6 +112,7 @@ loading=Yükleniyor…
error=Hata
error404=Ulaşmaya çalıştığınız sayfa mevcut değil veya görüntüleme yetkiniz yok .
+go_back=Geri Git
never=Asla
unknown=Bilinmiyor
@@ -180,6 +184,7 @@ network_error=Ağ hatası
[startpage]
app_desc=Zahmetsiz, kendi sunucunuzda barındırabileceğiniz Git servisi
install=Kurulumu kolay
+install_desc=Platformunuz için ikili dosyayı çalıştırın , Docker ile yükleyin veya paket olarak edinin.
platform=Farklı platformlarda çalışablir
platform_desc=Gitea Go ile derleme yapılabilecek her yerde çalışmaktadır: Windows, macOS, Linux, ARM, vb. Hangisini seviyorsanız onu seçin!
lightweight=Hafif
@@ -356,6 +361,7 @@ disable_register_prompt=Kayıt işlemi devre dışıdır. Lütfen site yönetici
disable_register_mail=Kayıt için e-posta doğrulama devre dışıdır.
manual_activation_only=Etkinleştirmeyi tamamlamak için site yöneticinizle bağlantıya geçin.
remember_me=Bu Aygıtı hatırla
+remember_me.compromised=Oturum açma tokeni artık geçerli değil, bu ele geçirilmiş bir hesaba işaret ediyor olabilir. Lütfen hesabınızda olağandışı faaliyet olup olmadığını denetleyin.
forgot_password_title=Şifremi unuttum
forgot_password=Şifrenizi mi unuttunuz?
sign_up_now=Bir hesaba mı ihtiyacınız var? Hemen kaydolun.
@@ -375,6 +381,7 @@ email_not_associate=Bu e-posta adresi hiçbir hesap ile ilişkilendirilmemiştir
send_reset_mail=Hesap Kurtarma E-postası Gönder
reset_password=Hesap Kurtarma
invalid_code=Doğrulama kodunuz geçersiz veya süresi dolmuş.
+invalid_code_forgot_password=Onay kodunuz hatalı veya süresi geçmiş. Yeni bir oturum başlatmak için buraya tıklayın.
invalid_password=Parolanız hesap oluşturulurken kullanılan parolayla eşleşmiyor.
reset_password_helper=Hesabı Kurtar
reset_password_wrong_user=%s olarak oturum açmışsınız, ancak hesap kurtarma bağlantısı %s için
@@ -676,6 +683,7 @@ choose_new_avatar=Yeni Avatar Seç
update_avatar=Profil Resmini Güncelle
delete_current_avatar=Güncel Avatarı Sil
uploaded_avatar_not_a_image=Yüklenen dosya bir resim dosyası değil.
+uploaded_avatar_is_too_big=Yüklenen dosyanın boyutu (%d KiB), azami boyutu (%d KiB) aşıyor.
update_avatar_success=Profil resminiz değiştirildi.
update_user_avatar_success=Kullanıcının avatarı güncellendi.
@@ -857,6 +865,7 @@ revoke_oauth2_grant_description=Bu üçüncü taraf uygulamasına erişimin ipta
revoke_oauth2_grant_success=Erişim başarıyla kaldırıldı.
twofa_desc=İki faktörlü kimlik doğrulama, hesabınızın güvenliğini artırır.
+twofa_recovery_tip=Aygıtınızı kaybetmeniz durumunda, hesabınıza tekrar erişmek için tek kullanımlık kurtarma anahtarını kullanabileceksiniz.
twofa_is_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde kaydedilmiş .
twofa_not_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içinde kaydedilmemiş.
twofa_disable=İki Aşamalı Doğrulamayı Devre Dışı Bırak
@@ -879,6 +888,8 @@ webauthn_register_key=Güvenlik Anahtarı Ekle
webauthn_nickname=Takma Ad
webauthn_delete_key=Güvenlik Anahtarını Kaldır
webauthn_delete_key_desc=Bir güvenlik anahtarını kaldırırsanız, onunla artık giriş yapamazsınız. Devam edilsin mi?
+webauthn_key_loss_warning=Güvenlik anahtarlarınızı kaybederseniz, hesabınıza erişimi kaybedersiniz.
+webauthn_alternative_tip=Ek bir kimlik doğrulama yöntemi ayarlamak isteyebilirsiniz.
manage_account_links=Bağlı Hesapları Yönet
manage_account_links_desc=Bu harici hesaplar Gitea hesabınızla bağlantılı.
@@ -915,6 +926,7 @@ visibility.private=Özel
visibility.private_tooltip=Sadece katıldığınız organizasyonların üyeleri tarafından görünür
[repo]
+new_repo_helper=Bir depo, sürüm geçmişi dahil tüm proje dosyalarını içerir. Zaten başka bir yerde mi barındırıyorsunuz? Depoyu taşıyın.
owner=Sahibi
owner_helper=Bazı organizasyonlar, en çok depo sayısı sınırı nedeniyle açılır menüde görünmeyebilir.
repo_name=Depo İsmi
@@ -935,6 +947,8 @@ fork_from=Buradan Çatalla
already_forked=%s deposunu zaten çatalladınız
fork_to_different_account=Başka bir hesaba çatalla
fork_visibility_helper=Çatallanmış bir deponun görünürlüğü değiştirilemez.
+fork_branch=Çatala klonlanacak dal
+all_branches=Tüm dallar
fork_no_valid_owners=Geçerli bir sahibi olmadığı için bu depo çatallanamaz.
use_template=Bu şablonu kullan
clone_in_vsc=VS Code'ta klonla
@@ -964,6 +978,7 @@ trust_model_helper_collaborator_committer=Ortak çalışan+İşleyen: İşleyenl
trust_model_helper_default=Varsayılan: Bu kurulum için varsayılan güven modelini kullan
create_repo=Depo Oluştur
default_branch=Varsayılan Dal
+default_branch_label=varsayılan
default_branch_helper=Varsayılan dal, değişiklik istekleri ve kod işlemeleri için temel daldır.
mirror_prune=Buda
mirror_prune_desc=Kullanılmayan uzak depoları izleyen referansları kaldır
@@ -999,8 +1014,13 @@ delete_preexisting=Önceden var olan dosyaları sil
delete_preexisting_content=%s içindeki dosyaları sil
delete_preexisting_success=%s içindeki kabul edilmeyen dosyalar silindi
blame_prior=Bu değişiklikten önceki suçu görüntüle
+blame.ignore_revs=.git-blame-ignore-revs dosyasındaki sürümler yok sayılıyor. Bunun yerine normal sorumlu görüntüsü için buraya tıklayın .
+blame.ignore_revs.failed=.git-blame-ignore-revs dosyasındaki sürümler yok sayılamadı.
author_search_tooltip=En fazla 30 kullanıcı görüntüler
+tree_path_not_found_commit=%[1] yolu, %[2]s işlemesinde mevcut değil
+tree_path_not_found_branch=%[1] yolu, %[2]s dalında mevcut değil
+tree_path_not_found_tag=%[1] yolu, %[2]s etiketinde mevcut değil
transfer.accept=Aktarımı Kabul Et
transfer.accept_desc=`"%s" tarafına aktar`
@@ -1264,6 +1284,7 @@ commits.signed_by_untrusted_user=Güvenilmeyen kullanıcı tarafından imzaland
commits.signed_by_untrusted_user_unmatched=İşleyici ile eşleşmeyen güvenilmeyen kullanıcı tarafından imzalanmış
commits.gpg_key_id=GPG Anahtar Kimliği
commits.ssh_key_fingerprint=SSH Anahtar Parmak İzi
+commits.view_path=Geçmişte bu noktayı görüntüle
commit.operations=İşlemler
commit.revert=Geri Al
@@ -1474,8 +1495,17 @@ issues.ref_closed_from=`bu konuyu kapat%[4]s konuyu yeniden aç%[4]s %[2]s `
issues.ref_from=`%[1]s'den`
issues.author=Yazar
+issues.author_helper=Bu kullanıcı yazardır.
issues.role.owner=Sahibi
+issues.role.owner_helper=Bu kullanıcı bu deponun sahibidir.
issues.role.member=Üye
+issues.role.member_helper=Bu kullanıcı bu deponun sahibi olan organizasyonun üyesidir.
+issues.role.collaborator=Katkıcı
+issues.role.collaborator_helper=Kullanıcı bu depoya işbirliği için davet edildi.
+issues.role.first_time_contributor=İlk defa katkıcı
+issues.role.first_time_contributor_helper=Bu, bu kullanıcının bu depoya ilk katkısı.
+issues.role.contributor=Katılımcı
+issues.role.contributor_helper=Bu kullanıcı bu depoya daha önce işleme gönderdi.
issues.re_request_review=İncelemeyi yeniden iste
issues.is_stale=Bu incelemeden bu yana bu istekte değişiklikler oldu
issues.remove_request_review=İnceleme isteğini kaldır
@@ -1491,6 +1521,8 @@ issues.label_description=Etiket açıklaması
issues.label_color=Etiket rengi
issues.label_exclusive=Özel
issues.label_archive=Etiketi Arşivle
+issues.label_archived_filter=Arşivlenmiş etiketleri göster
+issues.label_archive_tooltip=Arşivlenmiş etiketler, etiket araması yapılırken varsayılan olarak önerilerin dışında tutuluyor.
issues.label_exclusive_desc=Kapsam/öğe
etiketini, diğer kapsam/
etiketleriyle ayrışık olacak şekilde adlandırın.
issues.label_exclusive_warning=Çakışan kapsamlı etiketler, bir konu veya değişiklik isteği etiketleri düzenlenirken kaldırılacaktır.
issues.label_count=%d etiket
@@ -1745,6 +1777,7 @@ pulls.rebase_conflict_summary=Hata Mesajı
pulls.unrelated_histories=Birleştirme Başarısız: Birleştirme başlığı ve tabanı ortak bir geçmişi paylaşmıyor. İpucu: Farklı bir strateji deneyin
pulls.merge_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, taban güncellendi. İpucu: Tekrar deneyin.
pulls.head_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, ana güncellendi. İpucu: Tekrar deneyin.
+pulls.has_merged=Başarısız: Değişiklik isteği birleştirildi, yeniden birleştiremez veya hedef dalı değiştiremezsiniz.
pulls.push_rejected=Birleştirme Başarısız Oldu: Gönderme reddedildi. Bu depo için Git İstemcilerini inceleyin.
pulls.push_rejected_summary=Tam Red Mesajı
pulls.push_rejected_no_message=Birleştirme başarısız oldu: Gönderme reddedildi, ancak uzak bir mesaj yoktu. Bu depo için Git İstemcilerini inceleyin
@@ -1756,6 +1789,8 @@ pulls.status_checks_failure=Bazı kontroller başarısız oldu
pulls.status_checks_error=Bazı kontroller hatalar bildirdi
pulls.status_checks_requested=Gerekli
pulls.status_checks_details=Ayrıntılar
+pulls.status_checks_hide_all=Tüm denetlemeleri gizle
+pulls.status_checks_show_all=Tüm denetlemeleri göster
pulls.update_branch=Dalı birleştirmeyle güncelle
pulls.update_branch_rebase=Dalı yeniden yapılandırmayla güncelle
pulls.update_branch_success=Dal güncellemesi başarıyla gerçekleştirildi
@@ -1764,6 +1799,11 @@ pulls.outdated_with_base_branch=Bu dal, temel dal ile güncel değil
pulls.close=Değişiklik İsteğini Kapat
pulls.closed_at=`%[2]s değişiklik isteğini kapattı`
pulls.reopened_at=`%[2]s değişiklik isteğini yeniden açtı`
+pulls.cmd_instruction_hint=`Komut satırı talimatlarını görüntüleyin.`
+pulls.cmd_instruction_checkout_title=Çekme
+pulls.cmd_instruction_checkout_desc=Proje deponuzdan yeni bir dalı çekin ve değişiklikleri test edin.
+pulls.cmd_instruction_merge_title=Birleştir
+pulls.cmd_instruction_merge_desc=Değişiklikleri birleştirin ve Gitea'da güncelleyin.
pulls.clear_merge_message=Birleştirme iletilerini temizle
pulls.clear_merge_message_hint=Birleştirme iletisini temizlemek sadece işleme ileti içeriğini kaldırır ama üretilmiş "Co-Authored-By …" gibi git fragmanlarını korur.
@@ -1809,6 +1849,8 @@ milestones.edit_success=`"%s" dönüm noktası güncellendi.`
milestones.deletion=Kilometre Taşını Sil
milestones.deletion_desc=Bir kilometre taşını silmek, onu ilgili tüm sorunlardan kaldırır. Devam edilsin mi?
milestones.deletion_success=Kilometre taşı silindi.
+milestones.filter_sort.earliest_due_data=En erken bitiş tarihi
+milestones.filter_sort.latest_due_date=En uzak bitiş tarihi
milestones.filter_sort.least_complete=En az tamamlama
milestones.filter_sort.most_complete=En çok tamamlama
milestones.filter_sort.most_issues=En çok konu
@@ -1971,6 +2013,8 @@ settings.mirror_settings.push_mirror.add=Yansı Gönderimi Ekle
settings.mirror_settings.push_mirror.edit_sync_time=Yansı eşzamanlama aralığını düzenle
settings.sync_mirror=Şimdi Eşitle
+settings.pull_mirror_sync_in_progress=Şu an %s uzak sunucusundan değişiklikler çekiliyor.
+settings.push_mirror_sync_in_progress=Şu an %s uzak sunucusuna değişiklikler itiliyor.
settings.site=Web Sitesi
settings.update_settings=Ayarları Güncelle
settings.update_mirror_settings=Yansı Ayarları Güncelle
@@ -2104,12 +2148,14 @@ settings.webhook_deletion_desc=Bir web isteğini kaldırmak, ayarlarını ve tes
settings.webhook_deletion_success=Web isteği silindi.
settings.webhook.test_delivery=Test Dağıtımı
settings.webhook.test_delivery_desc=Bu web isteğini sahte bir olayla test edin.
+settings.webhook.test_delivery_desc_disabled=Bu web istemcisini sahte bir olayla denemek için etkinleştirin.
settings.webhook.request=İstekler
settings.webhook.response=Cevaplar
settings.webhook.headers=Başlıklar
settings.webhook.payload=İçerik
settings.webhook.body=Gövde
settings.webhook.replay.description=Bu web kancasını tekrar çalıştır.
+settings.webhook.replay.description_disabled=Bu web istemcisini yeniden oynatmak için etkinleştirin.
settings.webhook.delivery.success=Teslim kuyruğuna bir olay eklendi. Teslim geçmişinde görünmesi birkaç saniye alabilir.
settings.githooks_desc=Git İstemcileri Git'in kendisi tarafından desteklenmektedir. Özel işlemler ayarlamak için aşağıdaki istemci dosyalarını düzenleyebilirsiniz.
settings.githook_edit_desc=İstek aktif değilse örnek içerik sunulacaktır. İçeriği boş bırakmak, isteği devre dışı bırakmayı beraberinde getirecektir.
@@ -2269,6 +2315,7 @@ settings.dismiss_stale_approvals_desc=Değişiklik isteğinin içeriğini deği
settings.require_signed_commits=İmzalı İşleme Gerekli
settings.require_signed_commits_desc=Reddetme, onlar imzasızsa veya doğrulanamazsa bu dala gönderir.
settings.protect_branch_name_pattern=Korunmuş Dal Adı Deseni
+settings.protect_branch_name_pattern_desc=Korunmuş dal isim desenleri. Desen sözdizimi için belgelere bakabilirsiniz. Örnekler: main, release/**
settings.protect_patterns=Desenler
settings.protect_protected_file_patterns=Korumalı dosya kalıpları (noktalı virgülle ayrılmış ';'):
settings.protect_protected_file_patterns_desc=Kullanıcının bu dalda dosya ekleme, düzenleme veya silme hakları olsa bile doğrudan değiştirilmesine izin verilmeyen korumalı dosyalar. Birden çok desen noktalı virgül (';') kullanılarak ayrılabilir. Desen sözdizimi için github.com/gobwas/glob belgelerine bakın. Örnekler: .drone.yml
, /docs/**/*.txt
.
@@ -2305,6 +2352,7 @@ settings.tags.protection.allowed.teams=İzin verilen takımlar
settings.tags.protection.allowed.noone=Hiç kimse
settings.tags.protection.create=Etiketi Koru
settings.tags.protection.none=Korumalı etiket yok.
+settings.tags.protection.pattern.description=Birden çok etiketi eşleştirmek için tek bir ad, glob deseni veya normal ifade kullanabilirsiniz. Daha fazlası için korumalı etiketler rehberini okuyun.
settings.bot_token=Bot Jetonu
settings.chat_id=Sohbet Kimliği
settings.thread_id=İş Parçacığı ID
@@ -2485,6 +2533,7 @@ branch.default_deletion_failed=`"%s" dalı varsayılan daldır. Silinemez.`
branch.restore=`"%s" Dalını Geri Yükle`
branch.download=`"%s" Dalını İndir`
branch.rename=`"%s" Dalının Adını Değiştir`
+branch.search=Dal Ara
branch.included_desc=Bu dal varsayılan dalın bir parçasıdır
branch.included=Dahil
branch.create_new_branch=Şu daldan dal oluştur:
@@ -2701,6 +2750,7 @@ dashboard.reinit_missing_repos=Kayıtları bulunanlar için tüm eksik Git depol
dashboard.sync_external_users=Harici kullanıcı verisini senkronize et
dashboard.cleanup_hook_task_table=Hook_task tablosunu temizleme
dashboard.cleanup_packages=Süresi dolmuş paketleri temizleme
+dashboard.cleanup_actions=Eylemlerin süresi geçmiş günlük ve yapılarını temizle
dashboard.server_uptime=Sunucunun Ayakta Kalma Süresi
dashboard.current_goroutine=Güncel Goroutine'ler
dashboard.current_memory_usage=Güncel Bellek Kullanımı
@@ -2738,7 +2788,9 @@ dashboard.gc_lfs=LFS üst nesnelerin atıklarını temizle
dashboard.stop_zombie_tasks=Zombi görevleri durdur
dashboard.stop_endless_tasks=Daimi görevleri durdur
dashboard.cancel_abandoned_jobs=Terkedilmiş görevleri iptal et
+dashboard.start_schedule_tasks=Zamanlanmış görevleri başlat
dashboard.sync_branch.started=Dal Eşzamanlaması başladı
+dashboard.rebuild_issue_indexer=Konu indeksini yeniden oluştur
users.user_manage_panel=Kullanıcı Hesap Yönetimi
users.new_account=Yeni Kullanıcı Hesabı
@@ -2747,6 +2799,9 @@ users.full_name=Tam İsim
users.activated=Aktifleştirilmiş
users.admin=Yönetici
users.restricted=Kısıtlanmış
+users.reserved=Rezerve
+users.bot=Bot
+users.remote=Uzak
users.2fa=2FD
users.repos=Depolar
users.created=Oluşturuldu
@@ -2793,6 +2848,7 @@ users.list_status_filter.is_prohibit_login=Oturum Açmayı Önle
users.list_status_filter.not_prohibit_login=Oturum Açmaya İzin Ver
users.list_status_filter.is_2fa_enabled=2FA Etkin
users.list_status_filter.not_2fa_enabled=2FA Devre Dışı
+users.details=Kullanıcı Ayrıntıları
emails.email_manage_panel=Kullanıcı E-posta Yönetimi
emails.primary=Birincil
@@ -2805,6 +2861,7 @@ emails.updated=E-posta güncellendi
emails.not_updated=İstenen e-posta adresi güncellenemedi: %v
emails.duplicate_active=Bu e-posta adresi farklı bir kullanıcı için zaten aktif.
emails.change_email_header=E-posta Özelliklerini Güncelle
+emails.change_email_text=Bu e-posta adresini güncellemek istediğinizden emin misiniz?
orgs.org_manage_panel=Organizasyon Yönetimi
orgs.name=İsim
@@ -2829,6 +2886,7 @@ packages.package_manage_panel=Paket Yönetimi
packages.total_size=Toplam Boyut: %s
packages.unreferenced_size=Referanssız Boyut: %s
packages.cleanup=Süresi dolmuş veriyi temizle
+packages.cleanup.success=Süresi dolmuş veri başarıyla temizlendi
packages.owner=Sahibi
packages.creator=Oluşturan
packages.name=İsim
@@ -2839,10 +2897,12 @@ packages.size=Boyut
packages.published=Yayınlandı
defaulthooks=Varsayılan Web İstemcileri
+defaulthooks.desc=Web İstemcileri, belirli Gitea olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web İstemcileri varsayılandır ve tüm yeni depolara kopyalanır. web istemcileri kılavuzunda daha fazla bilgi edinin.
defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle
defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle
systemhooks=Sistem Web İstemcileri
+systemhooks.desc=Belirli Gitea olayları tetiklendiğinde Web istemcileri otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web istemcileri sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. web istemcileri kılavuzunda daha fazla bilgi edinin.
systemhooks.add_webhook=Sistem Web İstemcisi Ekle
systemhooks.update_webhook=Sistem Web İstemcisi Güncelle
@@ -2947,6 +3007,7 @@ auths.tip.google_plus=OAuth2 istemci kimlik bilgilerini https://console.develope
auths.tip.openid_connect=Bitiş noktalarını belirlemek için OpenID Connect Discovery URL'sini kullanın (/.well-known/openid-configuration)
auths.tip.twitter=https://dev.twitter.com/apps adresine gidin, bir uygulama oluşturun ve “Bu uygulamanın Twitter ile oturum açmak için kullanılmasına izin ver” seçeneğinin etkin olduğundan emin olun
auths.tip.discord=https://discordapp.com/developers/applications/me adresinde yeni bir uygulama kaydedin
+auths.tip.gitea=Yeni bir OAuth2 uygulaması kaydedin. Rehber https://docs.gitea.com/development/oauth2-provider adresinde bulunabilir
auths.tip.yandex=`https://oauth.yandex.com/client/new adresinde yeni bir uygulama oluşturun. "Yandex.Passport API'sı" bölümünden aşağıdaki izinleri seçin: "E-posta adresine erişim", "Kullanıcı avatarına erişim" ve "Kullanıcı adına, ad ve soyadına, cinsiyete erişim"`
auths.tip.mastodon=Kimlik doğrulaması yapmak istediğiniz mastodon örneği için özel bir örnek URL girin (veya varsayılan olanı kullanın)
auths.edit=Kimlik Doğrulama Kaynağı Düzenle
@@ -3126,8 +3187,10 @@ monitor.queue.name=İsim
monitor.queue.type=Tür
monitor.queue.exemplar=Örnek Türü
monitor.queue.numberworkers=Çalışan Sayısı
+monitor.queue.activeworkers=Etkin Çalışanlar
monitor.queue.maxnumberworkers=En Fazla Çalışan Sayısı
monitor.queue.numberinqueue=Kuyruktaki Sayı
+monitor.queue.review_add=Çalışanları İncele / Ekle
monitor.queue.settings.title=Havuz Ayarları
monitor.queue.settings.desc=Havuzlar, çalışan kuyruğu tıkanmasına bir yanıt olarak dinamik olarak büyürler.
monitor.queue.settings.maxnumberworkers=En fazla çalışan Sayısı
@@ -3454,23 +3517,31 @@ runners.status.idle=Boşta
runners.status.active=Etkin
runners.status.offline=Çevrimdışı
runners.version=Sürüm
+runners.reset_registration_token=Kayıt tokenini sıfırla
runners.reset_registration_token_success=Çalıştırıcı kayıt belirteci başarıyla sıfırlandı
runs.all_workflows=Tüm İş Akışları
runs.commit=İşle
+runs.scheduled=Zamanlanmış
runs.pushed_by=iten
runs.invalid_workflow_helper=İş akışı yapılandırma dosyası geçersiz. Lütfen yapılandırma dosyanızı denetleyin: %s
+runs.no_matching_online_runner_helper=Şu etiket ile eşleşen çevrimiçi çalıştırıcı bulunamadı: %s
runs.actor=Aktör
runs.status=Durum
runs.actors_no_select=Tüm aktörler
runs.status_no_select=Tüm durumlar
runs.no_results=Eşleşen sonuç yok.
+runs.no_workflows=Henüz hiç bir iş akışı yok.
+runs.no_workflows.quick_start=Gitea İşlem'i nasıl başlatacağınızı bilmiyor musunuz? Hızlı başlangıç rehberine bakabilirsiniz.
+runs.no_workflows.documentation=Gitea İşlem'i hakkında daha fazla bilgi için, belgeye bakabilirsiniz.
runs.no_runs=İş akışı henüz hiç çalıştırılmadı.
+runs.empty_commit_message=(boş işleme iletisi)
workflow.disable=İş Akışını Devre Dışı Bırak
workflow.disable_success='%s' iş akışı başarıyla devre dışı bırakıldı.
workflow.enable=İş Akışını Etkinleştir
workflow.enable_success='%s' iş akışı başarıyla etkinleştirildi.
+workflow.disabled=İş akışı devre dışı.
need_approval_desc=Değişiklik isteği çatalında iş akışı çalıştırmak için onay gerekiyor.
From 68227996a7a84a240b36c304d04c5c8d82948df8 Mon Sep 17 00:00:00 2001
From: yp05327 <576951401@qq.com>
Date: Sat, 17 Feb 2024 14:13:37 +0900
Subject: [PATCH 08/28] Fix broken following organization (#29005)
- following organization is broken from #28908
- add login check for the follow button in organization profile page
---
routers/web/user/profile.go | 14 ++++++++++++--
templates/org/home.tmpl | 16 +++++++++-------
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index 73ab93caed5a5..e7f133e98161e 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -29,6 +29,7 @@ import (
const (
tplProfileBigAvatar base.TplName = "shared/user/profile_big_avatar"
+ tplFollowUnfollow base.TplName = "shared/user/follow_unfollow"
)
// OwnerProfile render profile page for a user or a organization (aka, repo owner)
@@ -318,6 +319,15 @@ func Action(ctx *context.Context) {
return
}
- shared_user.PrepareContextForProfileBigAvatar(ctx)
- ctx.HTML(http.StatusOK, tplProfileBigAvatar)
+ if ctx.ContextUser.IsIndividual() {
+ shared_user.PrepareContextForProfileBigAvatar(ctx)
+ ctx.HTML(http.StatusOK, tplProfileBigAvatar)
+ return
+ } else if ctx.ContextUser.IsOrganization() {
+ ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
+ ctx.HTML(http.StatusOK, tplFollowUnfollow)
+ return
+ }
+ log.Error("Failed to apply action %q: unsupport context user type: %s", ctx.FormString("action"), ctx.ContextUser.Type)
+ ctx.Error(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action")))
}
diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl
index fc65d4691cbe7..322be3271d3e4 100644
--- a/templates/org/home.tmpl
+++ b/templates/org/home.tmpl
@@ -25,13 +25,15 @@
{{svg "octicon-rss" 24}}
{{end}}
-
- {{if $.IsFollowing}}
- {{ctx.Locale.Tr "user.unfollow"}}
- {{else}}
- {{ctx.Locale.Tr "user.follow"}}
- {{end}}
-
+ {{if .IsSigned}}
+
+ {{if $.IsFollowing}}
+ {{ctx.Locale.Tr "user.unfollow"}}
+ {{else}}
+ {{ctx.Locale.Tr "user.follow"}}
+ {{end}}
+
+ {{end}}
From 33400a02d4eb35a0656fd6d20fc56801de09b959 Mon Sep 17 00:00:00 2001
From: Robin Schoonover
Date: Fri, 16 Feb 2024 22:40:13 -0700
Subject: [PATCH 09/28] Fix debian InRelease Acquire-By-Hash newline (#29204)
There is a missing newline when generating the debian apt repo InRelease
file, which results in output like:
```
[...]
Date: Wed, 14 Feb 2024 05:03:01 UTC
Acquire-By-Hash: yesMD5Sum:
51a518dbddcd569ac3e0cebf330c800a 3018 main-dev/binary-amd64/Packages
[...]
```
It appears this would probably result in apt ignoring the
Acquire-By-Hash setting and not using the by-hash functionality,
although I'm not sure how to confirm it.
---
services/packages/debian/repository.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/services/packages/debian/repository.go b/services/packages/debian/repository.go
index 86c54e40c840e..611faa6adea6a 100644
--- a/services/packages/debian/repository.go
+++ b/services/packages/debian/repository.go
@@ -342,7 +342,7 @@ func buildReleaseFiles(ctx context.Context, ownerID int64, repoVersion *packages
fmt.Fprintf(w, "Components: %s\n", strings.Join(components, " "))
fmt.Fprintf(w, "Architectures: %s\n", strings.Join(architectures, " "))
fmt.Fprintf(w, "Date: %s\n", time.Now().UTC().Format(time.RFC1123))
- fmt.Fprint(w, "Acquire-By-Hash: yes")
+ fmt.Fprint(w, "Acquire-By-Hash: yes\n")
pfds, err := packages_model.GetPackageFileDescriptors(ctx, pfs)
if err != nil {
From cb85ebc3ef9bdbe473f90181966243d89edf3440 Mon Sep 17 00:00:00 2001
From: xkcdstickfigure <97917457+xkcdstickfigure@users.noreply.github.com>
Date: Sat, 17 Feb 2024 11:01:54 +0000
Subject: [PATCH 10/28] fix typo (#29212)
---
docs/content/administration/https-support.en-us.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/content/administration/https-support.en-us.md b/docs/content/administration/https-support.en-us.md
index 4e18722ddf140..981a29bd85267 100644
--- a/docs/content/administration/https-support.en-us.md
+++ b/docs/content/administration/https-support.en-us.md
@@ -35,7 +35,7 @@ CERT_FILE = cert.pem
KEY_FILE = key.pem
```
-Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to estalbish the trust relationship.
+Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to establish the trust relationship.
To learn more about the config values, please checkout the [Config Cheat Sheet](administration/config-cheat-sheet.md#server-server).
For the `CERT_FILE` or `KEY_FILE` field, the file path is relative to the `GITEA_CUSTOM` environment variable when it is a relative path. It can be an absolute path as well.
From c282d378bd1f2f11ffc884cd6d7c073b7b5745f8 Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 15:11:56 +0200
Subject: [PATCH 11/28] Remove jQuery from issue reference context popup attach
(#29216)
- Switched to plain JavaScript
- Tested the context popup functionality and it works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/1d2f173e-e626-4f7d-82c8-d1539d38d247)
Signed-off-by: Yarden Shoham
---
web_src/js/features/contextpopup.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/web_src/js/features/contextpopup.js b/web_src/js/features/contextpopup.js
index 23a620b8a23cb..51363b810a0b3 100644
--- a/web_src/js/features/contextpopup.js
+++ b/web_src/js/features/contextpopup.js
@@ -1,11 +1,10 @@
-import $ from 'jquery';
import {createApp} from 'vue';
import ContextPopup from '../components/ContextPopup.vue';
import {parseIssueHref} from '../utils.js';
import {createTippy} from '../modules/tippy.js';
export function initContextPopups() {
- const refIssues = $('.ref-issue');
+ const refIssues = document.querySelectorAll('.ref-issue');
attachRefIssueContextPopup(refIssues);
}
From 27192bc321161a4e648547bd7b071065a7b18326 Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 15:17:04 +0200
Subject: [PATCH 12/28] Remove jQuery from the webhook editor (#29211)
- Switched to plain JavaScript
- Tested the webhook editing functionality and it works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/b24c264d-d5e5-4954-8789-e72564a99027)
---------
Signed-off-by: Yarden Shoham
Co-authored-by: wxiaoguang
---
web_src/js/features/comp/WebHookEditor.js | 56 +++++++++++------------
1 file changed, 27 insertions(+), 29 deletions(-)
diff --git a/web_src/js/features/comp/WebHookEditor.js b/web_src/js/features/comp/WebHookEditor.js
index f4c82898fda49..86d21dc8152b1 100644
--- a/web_src/js/features/comp/WebHookEditor.js
+++ b/web_src/js/features/comp/WebHookEditor.js
@@ -1,43 +1,41 @@
-import $ from 'jquery';
+import {POST} from '../../modules/fetch.js';
import {hideElem, showElem, toggleElem} from '../../utils/dom.js';
-const {csrfToken} = window.config;
-
export function initCompWebHookEditor() {
- if ($('.new.webhook').length === 0) {
+ if (!document.querySelectorAll('.new.webhook').length) {
return;
}
- $('.events.checkbox input').on('change', function () {
- if ($(this).is(':checked')) {
- showElem($('.events.fields'));
- }
- });
- $('.non-events.checkbox input').on('change', function () {
- if ($(this).is(':checked')) {
- hideElem($('.events.fields'));
- }
- });
+ for (const input of document.querySelectorAll('.events.checkbox input')) {
+ input.addEventListener('change', function () {
+ if (this.checked) {
+ showElem('.events.fields');
+ }
+ });
+ }
+
+ for (const input of document.querySelectorAll('.non-events.checkbox input')) {
+ input.addEventListener('change', function () {
+ if (this.checked) {
+ hideElem('.events.fields');
+ }
+ });
+ }
const updateContentType = function () {
- const visible = $('#http_method').val() === 'POST';
- toggleElem($('#content_type').parent().parent(), visible);
+ const visible = document.getElementById('http_method').value === 'POST';
+ toggleElem(document.getElementById('content_type').parentNode.parentNode, visible);
};
updateContentType();
- $('#http_method').on('change', () => {
- updateContentType();
- });
+
+ document.getElementById('http_method').addEventListener('change', updateContentType);
// Test delivery
- $('#test-delivery').on('click', function () {
- const $this = $(this);
- $this.addClass('loading disabled');
- $.post($this.data('link'), {
- _csrf: csrfToken
- }).done(
- setTimeout(() => {
- window.location.href = $this.data('redirect');
- }, 5000)
- );
+ document.getElementById('test-delivery')?.addEventListener('click', async function () {
+ this.classList.add('loading', 'disabled');
+ await POST(this.getAttribute('data-link'));
+ setTimeout(() => {
+ window.location.href = this.getAttribute('data-redirect');
+ }, 5000);
});
}
From b96fbb567c67b2e1580396cd5326003a0a8da799 Mon Sep 17 00:00:00 2001
From: silverwind
Date: Sat, 17 Feb 2024 14:18:05 +0100
Subject: [PATCH 13/28] Enable markdownlint `no-trailing-punctuation` and
`no-blanks-blockquote` (#29214)
Enable these two and fix issues.
---
.markdownlint.yaml | 2 --
docs/content/administration/customizing-gitea.en-us.md | 2 +-
docs/content/administration/mail-templates.en-us.md | 4 ++--
docs/content/administration/mail-templates.zh-cn.md | 2 +-
docs/content/contributing/guidelines-frontend.en-us.md | 2 +-
docs/content/contributing/guidelines-frontend.zh-cn.md | 2 +-
docs/content/development/api-usage.zh-cn.md | 2 +-
7 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
index f740d1a4d69b3..b251ff796cbab 100644
--- a/.markdownlint.yaml
+++ b/.markdownlint.yaml
@@ -5,13 +5,11 @@ heading-increment: false
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1}
no-alt-text: false
no-bare-urls: false
-no-blanks-blockquote: false
no-emphasis-as-heading: false
no-empty-links: false
no-hard-tabs: {code_blocks: false}
no-inline-html: false
no-space-in-code: false
no-space-in-emphasis: false
-no-trailing-punctuation: false
no-trailing-spaces: {br_spaces: 0}
single-h1: false
diff --git a/docs/content/administration/customizing-gitea.en-us.md b/docs/content/administration/customizing-gitea.en-us.md
index d122fb4bfaac0..7efddb2824e1d 100644
--- a/docs/content/administration/customizing-gitea.en-us.md
+++ b/docs/content/administration/customizing-gitea.en-us.md
@@ -284,7 +284,7 @@ syntax and shouldn't be touched without fully understanding these components.
Google Analytics, Matomo (previously Piwik), and other analytics services can be added to Gitea. To add the tracking code, refer to the `Other additions to the page` section of this document, and add the JavaScript to the `$GITEA_CUSTOM/templates/custom/header.tmpl` file.
-## Customizing gitignores, labels, licenses, locales, and readmes.
+## Customizing gitignores, labels, licenses, locales, and readmes
Place custom files in corresponding sub-folder under `custom/options`.
diff --git a/docs/content/administration/mail-templates.en-us.md b/docs/content/administration/mail-templates.en-us.md
index 32b352da4b457..05c41a6a02f04 100644
--- a/docs/content/administration/mail-templates.en-us.md
+++ b/docs/content/administration/mail-templates.en-us.md
@@ -222,7 +222,7 @@ Please check [Gitea's logs](administration/logging-config.md) for error messages
{{.Repo}}#{{.Issue.Index}} .
{{if not (eq .Body "")}}
- Message content:
+ Message content
{{.Body | Str2html}}
{{end}}
@@ -245,7 +245,7 @@ This template produces something along these lines:
> [@rhonda](#) (Rhonda Myers) updated [mike/stuff#38](#).
>
-> #### Message content:
+> #### Message content
>
> \_********************************\_********************************
>
diff --git a/docs/content/administration/mail-templates.zh-cn.md b/docs/content/administration/mail-templates.zh-cn.md
index 588f0b2ccbad1..4846f6f398b22 100644
--- a/docs/content/administration/mail-templates.zh-cn.md
+++ b/docs/content/administration/mail-templates.zh-cn.md
@@ -228,7 +228,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
> [@rhonda](#)(Rhonda Myers)更新了 [mike/stuff#38](#)。
>
-> #### 消息内容:
+> #### 消息内容
>
> \_********************************\_********************************
>
diff --git a/docs/content/contributing/guidelines-frontend.en-us.md b/docs/content/contributing/guidelines-frontend.en-us.md
index edd89e1231d16..a33a38a6f92b4 100644
--- a/docs/content/contributing/guidelines-frontend.en-us.md
+++ b/docs/content/contributing/guidelines-frontend.en-us.md
@@ -34,7 +34,7 @@ The source files can be found in the following directories:
We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html) and [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)
-### Gitea specific guidelines:
+### Gitea specific guidelines
1. Every feature (Fomantic-UI/jQuery module) should be put in separate files/directories.
2. HTML ids and classes should use kebab-case, it's preferred to contain 2-3 feature related keywords.
diff --git a/docs/content/contributing/guidelines-frontend.zh-cn.md b/docs/content/contributing/guidelines-frontend.zh-cn.md
index 365144ee7c407..43f72b48083a0 100644
--- a/docs/content/contributing/guidelines-frontend.zh-cn.md
+++ b/docs/content/contributing/guidelines-frontend.zh-cn.md
@@ -34,7 +34,7 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。
我们推荐使用[Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html)和[Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)。
-## Gitea 特定准则:
+## Gitea 特定准则
1. 每个功能(Fomantic-UI/jQuery 模块)应放在单独的文件/目录中。
2. HTML 的 id 和 class 应使用 kebab-case,最好包含2-3个与功能相关的关键词。
diff --git a/docs/content/development/api-usage.zh-cn.md b/docs/content/development/api-usage.zh-cn.md
index 96c19972940cc..d7aca16f7f7be 100644
--- a/docs/content/development/api-usage.zh-cn.md
+++ b/docs/content/development/api-usage.zh-cn.md
@@ -60,7 +60,7 @@ curl "http://localhost:4000/api/v1/repos/test1/test1/issues" \
`/users/:name/tokens` 是一个特殊的接口,需要您使用 basic authentication 进行认证,具体原因在 issue 中
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346) 有所提及,使用方法如下所示:
-### 使用 Basic authentication 认证:
+### 使用 Basic authentication 认证
```
$ curl --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
From aa6f88638fb827d5c5ed7506e5fc06dad92beea7 Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 15:42:52 +0200
Subject: [PATCH 14/28] Fix missing template for follow button in organization
(#29215)
Leftover from https://github.com/go-gitea/gitea/pull/29005
# Before
![before](https://github.com/go-gitea/gitea/assets/20454870/24c74278-ccac-4dc6-bf26-713e90c07239)
# After
![after](https://github.com/go-gitea/gitea/assets/20454870/f91d503b-87d4-4c17-a56c-9c0a81fd9082)
---------
Signed-off-by: Yarden Shoham
---
routers/web/user/profile.go | 2 +-
templates/org/follow_unfollow.tmpl | 7 +++++++
templates/org/home.tmpl | 8 +-------
3 files changed, 9 insertions(+), 8 deletions(-)
create mode 100644 templates/org/follow_unfollow.tmpl
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index e7f133e98161e..37ce450530452 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -29,7 +29,7 @@ import (
const (
tplProfileBigAvatar base.TplName = "shared/user/profile_big_avatar"
- tplFollowUnfollow base.TplName = "shared/user/follow_unfollow"
+ tplFollowUnfollow base.TplName = "org/follow_unfollow"
)
// OwnerProfile render profile page for a user or a organization (aka, repo owner)
diff --git a/templates/org/follow_unfollow.tmpl b/templates/org/follow_unfollow.tmpl
new file mode 100644
index 0000000000000..b9a3bb77fea30
--- /dev/null
+++ b/templates/org/follow_unfollow.tmpl
@@ -0,0 +1,7 @@
+
+ {{if $.IsFollowing}}
+ {{ctx.Locale.Tr "user.unfollow"}}
+ {{else}}
+ {{ctx.Locale.Tr "user.follow"}}
+ {{end}}
+
diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl
index 322be3271d3e4..81a76d3b4d451 100644
--- a/templates/org/home.tmpl
+++ b/templates/org/home.tmpl
@@ -26,13 +26,7 @@
{{end}}
{{if .IsSigned}}
-
- {{if $.IsFollowing}}
- {{ctx.Locale.Tr "user.unfollow"}}
- {{else}}
- {{ctx.Locale.Tr "user.follow"}}
- {{end}}
-
+ {{template "org/follow_unfollow" .}}
{{end}}
From 22b9c2c95c30e77ec444c629eb323325d2c04676 Mon Sep 17 00:00:00 2001
From: Jimmy Praet
Date: Sat, 17 Feb 2024 15:07:56 +0100
Subject: [PATCH 15/28] Load outdated comments when (un)resolving conversation
on PR timeline (#29203)
Relates to #28654, #29039 and #29050.
The "show outdated comments" flag should only apply to the file diff
view.
On the PR timeline, outdated comments are always shown.
So they should also be loaded when (un)resolving a conversation on the
timeline page.
---
routers/web/repo/pull_review.go | 3 ++-
routers/web/repo/pull_review_test.go | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index 217f2dea6d07c..f84510b39d85d 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -156,7 +156,8 @@ func UpdateResolveConversation(ctx *context.Context) {
func renderConversation(ctx *context.Context, comment *issues_model.Comment, origin string) {
ctx.Data["PageIsPullFiles"] = origin == "diff"
- comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, ctx.Data["ShowOutdatedComments"].(bool))
+ showOutdatedComments := origin == "timeline" || ctx.Data["ShowOutdatedComments"].(bool)
+ comments, err := issues_model.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line, showOutdatedComments)
if err != nil {
ctx.ServerError("FetchCodeCommentsByLine", err)
return
diff --git a/routers/web/repo/pull_review_test.go b/routers/web/repo/pull_review_test.go
index 65019af40b168..7e6594774a848 100644
--- a/routers/web/repo/pull_review_test.go
+++ b/routers/web/repo/pull_review_test.go
@@ -68,9 +68,9 @@ func TestRenderConversation(t *testing.T) {
renderConversation(ctx, preparedComment, "timeline")
assert.Contains(t, resp.Body.String(), `
From 1d275c1748a75a01c270f5c306c5248808016aba Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 17:01:25 +0200
Subject: [PATCH 17/28] Fix labels referencing the wrong ID in the user profile
settings (#29199)
2 instances of `for` with a wrong value and 1 `for` that had a reference
to a `name` instead of `id`.
---------
Signed-off-by: Yarden Shoham
---
templates/user/settings/profile.tmpl | 12 ++++++------
tests/integration/auth_ldap_test.go | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl
index 1f32aed0e88ac..d1c68656b6d8f 100644
--- a/templates/user/settings/profile.tmpl
+++ b/templates/user/settings/profile.tmpl
@@ -22,8 +22,8 @@
-
{{ctx.Locale.Tr "email"}}
-
{{.SignedUser.Email}}
+
{{ctx.Locale.Tr "email"}}
+
{{.SignedUser.Email}}
{{ctx.Locale.Tr "user.user_bio"}}
@@ -42,11 +42,11 @@
- {{ctx.Locale.Tr "settings.privacy"}}
+ {{ctx.Locale.Tr "settings.privacy"}}
-
{{ctx.Locale.Tr "settings.visibility"}}
+
{{ctx.Locale.Tr "settings.visibility"}}
{{if .SignedUser.Visibility.IsPublic}} {{end}}
{{if .SignedUser.Visibility.IsLimited}} {{end}}
@@ -120,8 +120,8 @@
- {{ctx.Locale.Tr "settings.choose_new_avatar"}}
-
+ {{ctx.Locale.Tr "settings.choose_new_avatar"}}
+
diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go
index 2d69dfcfd7358..3a5fdb97a6bb8 100644
--- a/tests/integration/auth_ldap_test.go
+++ b/tests/integration/auth_ldap_test.go
@@ -179,7 +179,7 @@ func TestLDAPUserSignin(t *testing.T) {
assert.Equal(t, u.UserName, htmlDoc.GetInputValueByName("name"))
assert.Equal(t, u.FullName, htmlDoc.GetInputValueByName("full_name"))
- assert.Equal(t, u.Email, htmlDoc.Find(`label[for="email"]`).Siblings().First().Text())
+ assert.Equal(t, u.Email, htmlDoc.Find("#signed-user-email").Text())
}
func TestLDAPAuthChange(t *testing.T) {
From 3da2c63354eb3804c7aec3c688b066b044f2c30e Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 19:51:35 +0200
Subject: [PATCH 18/28] Remove unneccesary `initUserAuthLinkAccountView` from
"link account" page (#29217)
Signed-off-by: Yarden Shoham
Co-authored-by: wxiaoguang
---
web_src/js/features/user-auth.js | 28 ----------------------------
web_src/js/index.js | 3 +--
2 files changed, 1 insertion(+), 30 deletions(-)
diff --git a/web_src/js/features/user-auth.js b/web_src/js/features/user-auth.js
index af380dcfc7c86..60d186e699798 100644
--- a/web_src/js/features/user-auth.js
+++ b/web_src/js/features/user-auth.js
@@ -1,4 +1,3 @@
-import $ from 'jquery';
import {checkAppUrl} from './common-global.js';
export function initUserAuthOauth2() {
@@ -21,30 +20,3 @@ export function initUserAuthOauth2() {
});
}
}
-
-export function initUserAuthLinkAccountView() {
- const $lnkUserPage = $('.page-content.user.link-account');
- if ($lnkUserPage.length === 0) {
- return false;
- }
-
- const $signinTab = $lnkUserPage.find('.item[data-tab="auth-link-signin-tab"]');
- const $signUpTab = $lnkUserPage.find('.item[data-tab="auth-link-signup-tab"]');
- const $signInView = $lnkUserPage.find('.tab[data-tab="auth-link-signin-tab"]');
- const $signUpView = $lnkUserPage.find('.tab[data-tab="auth-link-signup-tab"]');
-
- $signUpTab.on('click', () => {
- $signinTab.removeClass('active');
- $signInView.removeClass('active');
- $signUpTab.addClass('active');
- $signUpView.addClass('active');
- return false;
- });
-
- $signinTab.on('click', () => {
- $signUpTab.removeClass('active');
- $signUpView.removeClass('active');
- $signinTab.addClass('active');
- $signInView.addClass('active');
- });
-}
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 078f9fc9df415..117279c3c4a82 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -23,7 +23,7 @@ import {initFindFileInRepo} from './features/repo-findfile.js';
import {initCommentContent, initMarkupContent} from './markup/content.js';
import {initPdfViewer} from './render/pdf.js';
-import {initUserAuthLinkAccountView, initUserAuthOauth2} from './features/user-auth.js';
+import {initUserAuthOauth2} from './features/user-auth.js';
import {
initRepoIssueDue,
initRepoIssueReferenceRepositorySearch,
@@ -178,7 +178,6 @@ onDomReady(() => {
initCommitStatuses();
initCaptcha();
- initUserAuthLinkAccountView();
initUserAuthOauth2();
initUserAuthWebAuthn();
initUserAuthWebAuthnRegister();
From 5e1bf3efe2ad3ba6cd30db187ca59b94c3fcdafa Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sat, 17 Feb 2024 22:07:47 +0200
Subject: [PATCH 19/28] Remove jQuery from repo migrate page (#29219)
- Switched to plain JavaScript
- Tested the repo migrate functionality and it works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/44ad134b-832e-44b8-8e77-7cc8603d95fe)
---------
Signed-off-by: Yarden Shoham
Co-authored-by: silverwind
---
web_src/js/features/repo-migrate.js | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/web_src/js/features/repo-migrate.js b/web_src/js/features/repo-migrate.js
index cae28fdd1b1fc..490e7df0e43ad 100644
--- a/web_src/js/features/repo-migrate.js
+++ b/web_src/js/features/repo-migrate.js
@@ -1,18 +1,17 @@
-import $ from 'jquery';
import {hideElem, showElem} from '../utils/dom.js';
import {GET, POST} from '../modules/fetch.js';
const {appSubUrl} = window.config;
export function initRepoMigrationStatusChecker() {
- const $repoMigrating = $('#repo_migrating');
- if (!$repoMigrating.length) return;
+ const repoMigrating = document.getElementById('repo_migrating');
+ if (!repoMigrating) return;
- $('#repo_migrating_retry').on('click', doMigrationRetry);
+ document.getElementById('repo_migrating_retry').addEventListener('click', doMigrationRetry);
- const task = $repoMigrating.attr('data-migrating-task-id');
+ const task = repoMigrating.getAttribute('data-migrating-task-id');
- // returns true if the refresh still need to be called after a while
+ // returns true if the refresh still needs to be called after a while
const refresh = async () => {
const res = await GET(`${appSubUrl}/user/task/${task}`);
if (res.status !== 200) return true; // continue to refresh if network error occurs
@@ -21,7 +20,7 @@ export function initRepoMigrationStatusChecker() {
// for all status
if (data.message) {
- $('#repo_migrating_progress_message').text(data.message);
+ document.getElementById('repo_migrating_progress_message').textContent = data.message;
}
// TaskStatusFinished
@@ -37,7 +36,7 @@ export function initRepoMigrationStatusChecker() {
showElem('#repo_migrating_retry');
showElem('#repo_migrating_failed');
showElem('#repo_migrating_failed_image');
- $('#repo_migrating_failed_error').text(data.message);
+ document.getElementById('repo_migrating_failed_error').textContent = data.message;
return false;
}
@@ -59,6 +58,6 @@ export function initRepoMigrationStatusChecker() {
}
async function doMigrationRetry(e) {
- await POST($(e.target).attr('data-migrating-task-retry-url'));
+ await POST(e.target.getAttribute('data-migrating-task-retry-url'));
window.location.reload();
}
From 658cbddbfbe219d5988fcbf308e0d8180176725f Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sun, 18 Feb 2024 04:48:10 +0800
Subject: [PATCH 20/28] Make submit event code work with both jQuery event and
native event (#29223)
Partially related to #29200 and fix other potential bugs.
Co-authored-by: Giteabot
---
web_src/js/features/common-issue-list.js | 2 +-
web_src/js/features/repo-diff.js | 2 +-
web_src/js/utils/dom.js | 1 +
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/web_src/js/features/common-issue-list.js b/web_src/js/features/common-issue-list.js
index 317c11219bd27..8182f99f29159 100644
--- a/web_src/js/features/common-issue-list.js
+++ b/web_src/js/features/common-issue-list.js
@@ -40,7 +40,7 @@ export function initCommonIssueListQuickGoto() {
$form.on('submit', (e) => {
// if there is no goto button, or the form is submitted by non-quick-goto elements, submit the form directly
let doQuickGoto = !isElemHidden($goto);
- const submitter = submitEventSubmitter(e.originalEvent);
+ const submitter = submitEventSubmitter(e);
if (submitter !== $form[0] && submitter !== $input[0] && submitter !== $goto[0]) doQuickGoto = false;
if (!doQuickGoto) return;
diff --git a/web_src/js/features/repo-diff.js b/web_src/js/features/repo-diff.js
index eeb80e91b2cc5..6d6f382613d38 100644
--- a/web_src/js/features/repo-diff.js
+++ b/web_src/js/features/repo-diff.js
@@ -58,7 +58,7 @@ function initRepoDiffConversationForm() {
const formData = new FormData($form[0]);
// if the form is submitted by a button, append the button's name and value to the form data
- const submitter = submitEventSubmitter(e.originalEvent);
+ const submitter = submitEventSubmitter(e);
const isSubmittedByButton = (submitter?.nodeName === 'BUTTON') || (submitter?.nodeName === 'INPUT' && submitter.type === 'submit');
if (isSubmittedByButton && submitter.name) {
formData.append(submitter.name, submitter.value);
diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js
index 4dc55a518a605..fb6b751140307 100644
--- a/web_src/js/utils/dom.js
+++ b/web_src/js/utils/dom.js
@@ -211,6 +211,7 @@ export function loadElem(el, src) {
const needSubmitEventPolyfill = typeof SubmitEvent === 'undefined';
export function submitEventSubmitter(e) {
+ e = e.originalEvent ?? e; // if the event is wrapped by jQuery, use "originalEvent", otherwise, use the event itself
return needSubmitEventPolyfill ? (e.target._submitter || null) : e.submitter;
}
From d73223bfc6fcabdfb4ca284729ccead5ba228728 Mon Sep 17 00:00:00 2001
From: Yarden Shoham
Date: Sun, 18 Feb 2024 03:22:09 +0200
Subject: [PATCH 21/28] Remove jQuery from the repo release form (#29225)
- Switched to plain JavaScript
- Tested the repo release form functionality and it works as before
# Demo using JavaScript without jQuery
![action](https://github.com/go-gitea/gitea/assets/20454870/ede2072a-823d-418f-9890-a5a7445a1cc6)
---------
Signed-off-by: Yarden Shoham
Co-authored-by: wxiaoguang
---
web_src/js/features/repo-release.js | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/web_src/js/features/repo-release.js b/web_src/js/features/repo-release.js
index 3338c2874b2ba..2db80790094f3 100644
--- a/web_src/js/features/repo-release.js
+++ b/web_src/js/features/repo-release.js
@@ -1,19 +1,19 @@
-import $ from 'jquery';
import {hideElem, showElem} from '../utils/dom.js';
import {initComboMarkdownEditor} from './comp/ComboMarkdownEditor.js';
export function initRepoRelease() {
- $(document).on('click', '.remove-rel-attach', function() {
- const uuid = $(this).data('uuid');
- const id = $(this).data('id');
- $(`input[name='attachment-del-${uuid}']`).attr('value', true);
- hideElem($(`#attachment-${id}`));
+ document.addEventListener('click', (e) => {
+ if (e.target.matches('.remove-rel-attach')) {
+ const uuid = e.target.getAttribute('data-uuid');
+ const id = e.target.getAttribute('data-id');
+ document.querySelector(`input[name='attachment-del-${uuid}']`).value = 'true';
+ hideElem(`#attachment-${id}`);
+ }
});
}
export function initRepoReleaseNew() {
- const $repoReleaseNew = $('.repository.new.release');
- if (!$repoReleaseNew.length) return;
+ if (!document.querySelector('.repository.new.release')) return;
initTagNameEditor();
initRepoReleaseEditor();
@@ -45,9 +45,9 @@ function initTagNameEditor() {
}
function initRepoReleaseEditor() {
- const $editor = $('.repository.new.release .combo-markdown-editor');
- if ($editor.length === 0) {
+ const editor = document.querySelector('.repository.new.release .combo-markdown-editor');
+ if (!editor) {
return;
}
- const _promise = initComboMarkdownEditor($editor);
+ initComboMarkdownEditor(editor);
}
From a784ed3d6c6946fd9bf95f2e910f52f549326fe2 Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sun, 18 Feb 2024 09:48:59 +0800
Subject: [PATCH 22/28] Use "Safe" modifier for manually constructed safe HTML
strings in templates (#29227)
Follow #29165. These HTML strings are safe to be rendered directly, to
avoid double-escaping.
---
templates/admin/packages/list.tmpl | 2 +-
templates/admin/repo/list.tmpl | 2 +-
templates/admin/stacktrace.tmpl | 2 +-
templates/org/member/members.tmpl | 4 ++--
templates/org/team/members.tmpl | 2 +-
templates/org/team/sidebar.tmpl | 2 +-
templates/org/team/teams.tmpl | 2 +-
templates/repo/commit_page.tmpl | 4 ++--
templates/repo/issue/view_content/comments.tmpl | 4 ++--
templates/repo/issue/view_content/pull.tmpl | 2 +-
templates/repo/settings/webhook/settings.tmpl | 2 +-
templates/user/settings/organization.tmpl | 2 +-
12 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl
index 5cfd9ddefa63e..04f76748d081f 100644
--- a/templates/admin/packages/list.tmpl
+++ b/templates/admin/packages/list.tmpl
@@ -88,7 +88,7 @@
{{ctx.Locale.Tr "packages.settings.delete"}}
- {{ctx.Locale.Tr "packages.settings.delete.notice" ` ` ` ` | Safe}}
+ {{ctx.Locale.Tr "packages.settings.delete.notice" (` `|Safe) (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl
index fdba0734a2abc..c7a6ec7e4e9f8 100644
--- a/templates/admin/repo/list.tmpl
+++ b/templates/admin/repo/list.tmpl
@@ -101,7 +101,7 @@
{{ctx.Locale.Tr "repo.settings.delete_desc"}}
- {{ctx.Locale.Tr "repo.settings.delete_notices_2" `
` | Safe}}
+ {{ctx.Locale.Tr "repo.settings.delete_notices_2" (`
`|Safe)}}
{{ctx.Locale.Tr "repo.settings.delete_notices_fork_1"}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/admin/stacktrace.tmpl b/templates/admin/stacktrace.tmpl
index 894e41f8d7e51..aa5e810cd780d 100644
--- a/templates/admin/stacktrace.tmpl
+++ b/templates/admin/stacktrace.tmpl
@@ -39,7 +39,7 @@
{{ctx.Locale.Tr "admin.monitor.process.cancel"}}
-
{{ctx.Locale.Tr "admin.monitor.process.cancel_notices" ` ` | Safe}}
+
{{ctx.Locale.Tr "admin.monitor.process.cancel_notices" (` `|Safe)}}
{{ctx.Locale.Tr "admin.monitor.process.cancel_desc"}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl
index e4ddb69805b8d..03509ec93e384 100644
--- a/templates/org/member/members.tmpl
+++ b/templates/org/member/members.tmpl
@@ -73,7 +73,7 @@
{{ctx.Locale.Tr "org.members.leave"}}
-
{{ctx.Locale.Tr "org.members.leave.detail" ` ` | Safe}}
+
{{ctx.Locale.Tr "org.members.leave.detail" (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
@@ -82,7 +82,7 @@
{{ctx.Locale.Tr "org.members.remove"}}
-
{{ctx.Locale.Tr "org.members.remove.detail" ` ` ` ` | Safe}}
+
{{ctx.Locale.Tr "org.members.remove.detail" (` `|Safe) (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/org/team/members.tmpl b/templates/org/team/members.tmpl
index da63d82967a20..dd4ece14335a1 100644
--- a/templates/org/team/members.tmpl
+++ b/templates/org/team/members.tmpl
@@ -81,7 +81,7 @@
{{ctx.Locale.Tr "org.members.remove"}}
-
{{ctx.Locale.Tr "org.members.remove.detail" ` ` ` ` | Safe}}
+
{{ctx.Locale.Tr "org.members.remove.detail" (` `|Safe) (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/org/team/sidebar.tmpl b/templates/org/team/sidebar.tmpl
index 29e7cf7cdd90d..37550ab71fae1 100644
--- a/templates/org/team/sidebar.tmpl
+++ b/templates/org/team/sidebar.tmpl
@@ -88,7 +88,7 @@
{{ctx.Locale.Tr "org.teams.leave"}}
-
{{ctx.Locale.Tr "org.teams.leave.detail" ` ` | Safe}}
+
{{ctx.Locale.Tr "org.teams.leave.detail" (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/org/team/teams.tmpl b/templates/org/team/teams.tmpl
index f4ceada2a7458..b518d7d9d738d 100644
--- a/templates/org/team/teams.tmpl
+++ b/templates/org/team/teams.tmpl
@@ -49,7 +49,7 @@
{{ctx.Locale.Tr "org.teams.leave"}}
-
{{ctx.Locale.Tr "org.teams.leave.detail" ` ` | Safe}}
+
{{ctx.Locale.Tr "org.teams.leave.detail" (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl
index 01fa45babe66c..ce9fcecd8b8ad 100644
--- a/templates/repo/commit_page.tmpl
+++ b/templates/repo/commit_page.tmpl
@@ -88,7 +88,7 @@
{{.CsrfTokenHtml}}
- {{ctx.Locale.Tr "repo.branch.new_branch_from" ` ` | Safe}}
+ {{ctx.Locale.Tr "repo.branch.new_branch_from" (` `|Safe)}}
@@ -113,7 +113,7 @@
- {{ctx.Locale.Tr "repo.tag.create_tag_from" ` ` | Safe}}
+ {{ctx.Locale.Tr "repo.tag.create_tag_from" (` `|Safe)}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl
index c1797ba77d5c0..ed83377f5a22d 100644
--- a/templates/repo/issue/view_content/comments.tmpl
+++ b/templates/repo/issue/view_content/comments.tmpl
@@ -112,9 +112,9 @@
{{template "shared/user/authorlink" .Poster}}
{{$link := printf "%s/commit/%s" $.Repository.Link ($.Issue.PullRequest.MergedCommitID|PathEscape)}}
{{if eq $.Issue.PullRequest.Status 3}}
- {{ctx.Locale.Tr "repo.issues.comment_manually_pull_merged_at" (printf `
%[2]s ` ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID)) (printf "
%[1]s " ($.BaseTarget|Escape)) $createdStr | Safe}}
+ {{ctx.Locale.Tr "repo.issues.comment_manually_pull_merged_at" (printf `
%[2]s ` ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) | Safe) (printf "
%[1]s " ($.BaseTarget|Escape) | Safe) $createdStr}}
{{else}}
- {{ctx.Locale.Tr "repo.issues.comment_pull_merged_at" (printf `
%[2]s ` ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID)) (printf "
%[1]s " ($.BaseTarget|Escape)) $createdStr | Safe}}
+ {{ctx.Locale.Tr "repo.issues.comment_pull_merged_at" (printf `
%[2]s ` ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) | Safe) (printf "
%[1]s " ($.BaseTarget|Escape) | Safe) $createdStr}}
{{end}}
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index f1ab53eb677c4..a28b849f98909 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -38,7 +38,7 @@
{{ctx.Locale.Tr "repo.pulls.merged_success"}}
- {{ctx.Locale.Tr "repo.pulls.merged_info_text" (printf "%s
" (.HeadTarget | Escape)) | Str2html}}
+ {{ctx.Locale.Tr "repo.pulls.merged_info_text" (printf "%s
" (.HeadTarget | Escape) | Safe)}}
diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl
index 3dfa094cf5ac6..8e2387067e31f 100644
--- a/templates/repo/settings/webhook/settings.tmpl
+++ b/templates/repo/settings/webhook/settings.tmpl
@@ -263,7 +263,7 @@
{{ctx.Locale.Tr "repo.settings.authorization_header"}}
{{if ne .HookType "matrix"}}{{/* Matrix doesn't make the authorization optional but it is implied by the help string, should be changed.*/}}
- {{ctx.Locale.Tr "repo.settings.authorization_header_desc" "Bearer token123456
, Basic YWxhZGRpbjpvcGVuc2VzYW1l
" | Str2html}}
+ {{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("Bearer token123456
, Basic YWxhZGRpbjpvcGVuc2VzYW1l
" | Safe)}}
{{end}}
diff --git a/templates/user/settings/organization.tmpl b/templates/user/settings/organization.tmpl
index 8079521984068..102ff2e95bcc9 100644
--- a/templates/user/settings/organization.tmpl
+++ b/templates/user/settings/organization.tmpl
@@ -47,7 +47,7 @@
{{ctx.Locale.Tr "org.members.leave"}}
-
{{ctx.Locale.Tr "org.members.leave.detail" ` ` | Safe}}
+
{{ctx.Locale.Tr "org.members.leave.detail" (` `|Safe)}}
{{template "base/modal_actions_confirm" .}}
From 31bb9f3247388b993c61a10190cfd512408ce57e Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sun, 18 Feb 2024 17:52:02 +0800
Subject: [PATCH 23/28] Refactor more code in templates (#29236)
Follow #29165.
* Introduce JSONTemplate to help to render JSON templates
* Introduce JSEscapeSafe for templates. Now only use `{{ ... |
JSEscape}}` instead of `{{ ... | JSEscape | Safe}}`
* Simplify "UserLocationMapURL" useage
---
Makefile | 4 ++--
modules/context/context_response.go | 14 ++++++++++++++
modules/templates/helper.go | 6 +++++-
modules/templates/helper_test.go | 4 ++++
routers/api/v1/api.go | 4 ++--
routers/web/auth/oauth.go | 10 +---------
routers/web/shared/user/header.go | 4 +++-
routers/web/swagger_json.go | 14 +-------------
templates/shared/user/profile_big_avatar.tmpl | 5 ++---
templates/swagger/v1_json.tmpl | 8 ++++----
templates/user/auth/oidc_wellknown.tmpl | 14 +++++++-------
11 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/Makefile b/Makefile
index 3065d9e683bf2..925fdcb946b69 100644
--- a/Makefile
+++ b/Makefile
@@ -164,8 +164,8 @@ ifdef DEPS_PLAYWRIGHT
endif
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
-SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
-SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
+SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g
+SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g
SWAGGER_EXCLUDE := code.gitea.io/sdk
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
diff --git a/modules/context/context_response.go b/modules/context/context_response.go
index d9102b77bdb5e..829bca1f59209 100644
--- a/modules/context/context_response.go
+++ b/modules/context/context_response.go
@@ -90,6 +90,20 @@ func (ctx *Context) HTML(status int, name base.TplName) {
}
}
+// JSONTemplate renders the template as JSON response
+// keep in mind that the template is processed in HTML context, so JSON-things should be handled carefully, eg: by JSEscape
+func (ctx *Context) JSONTemplate(tmpl base.TplName) {
+ t, err := ctx.Render.TemplateLookup(string(tmpl), nil)
+ if err != nil {
+ ctx.ServerError("unable to find template", err)
+ return
+ }
+ ctx.Resp.Header().Set("Content-Type", "application/json")
+ if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
+ ctx.ServerError("unable to execute template", err)
+ }
+}
+
// RenderToString renders the template content to a string
func (ctx *Context) RenderToString(name base.TplName, data map[string]any) (string, error) {
var buf strings.Builder
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 9ff5d8927f3f9..6e42594b0b7d7 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -38,7 +38,7 @@ func NewFuncMap() template.FuncMap {
"Safe": Safe,
"Escape": Escape,
"QueryEscape": url.QueryEscape,
- "JSEscape": template.JSEscapeString,
+ "JSEscape": JSEscapeSafe,
"Str2html": Str2html, // TODO: rename it to SanitizeHTML
"URLJoin": util.URLJoin,
"DotEscape": DotEscape,
@@ -211,6 +211,10 @@ func Escape(s any) template.HTML {
panic(fmt.Sprintf("unexpected type %T", s))
}
+func JSEscapeSafe(s string) template.HTML {
+ return template.HTML(template.JSEscapeString(s))
+}
+
func RenderEmojiPlain(s any) any {
switch v := s.(type) {
case string:
diff --git a/modules/templates/helper_test.go b/modules/templates/helper_test.go
index ec83e9ac33138..739a92f34f93a 100644
--- a/modules/templates/helper_test.go
+++ b/modules/templates/helper_test.go
@@ -52,3 +52,7 @@ func TestSubjectBodySeparator(t *testing.T) {
"",
"Insuficient\n--\nSeparators")
}
+
+func TestJSEscapeSafe(t *testing.T) {
+ assert.EqualValues(t, `\u0026\u003C\u003E\'\"`, JSEscapeSafe(`&<>'"`))
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index f3082e4fa0e89..3fafb96b8ed82 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -6,9 +6,9 @@
//
// This documentation describes the Gitea API.
//
-// Schemes: http, https
+// Schemes: https, http
// BasePath: /api/v1
-// Version: {{AppVer | JSEscape | Safe}}
+// Version: {{AppVer | JSEscape}}
// License: MIT http://opensource.org/licenses/MIT
//
// Consumes:
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 07140b667433c..660fa8fe4e51f 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -579,16 +579,8 @@ func GrantApplicationOAuth(ctx *context.Context) {
// OIDCWellKnown generates JSON so OIDC clients know Gitea's capabilities
func OIDCWellKnown(ctx *context.Context) {
- t, err := ctx.Render.TemplateLookup("user/auth/oidc_wellknown", nil)
- if err != nil {
- ctx.ServerError("unable to find template", err)
- return
- }
- ctx.Resp.Header().Set("Content-Type", "application/json")
ctx.Data["SigningKey"] = oauth2.DefaultSigningKey
- if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
- ctx.ServerError("unable to execute template", err)
- }
+ ctx.JSONTemplate("user/auth/oidc_wellknown")
}
// OIDCKeys generates the JSON Web Key Set
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
index a2c0abb47e4a1..a6c66a2c709fa 100644
--- a/routers/web/shared/user/header.go
+++ b/routers/web/shared/user/header.go
@@ -4,6 +4,8 @@
package user
import (
+ "net/url"
+
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
access_model "code.gitea.io/gitea/models/perm/access"
@@ -36,7 +38,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) {
ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
- ctx.Data["UserLocationMapURL"] = setting.Service.UserLocationMapURL
+ ctx.Data["ContextUserLocationMapURL"] = setting.Service.UserLocationMapURL + url.QueryEscape(ctx.ContextUser.Location)
// Show OpenID URIs
openIDs, err := user_model.GetUserOpenIDs(ctx, ctx.ContextUser.ID)
diff --git a/routers/web/swagger_json.go b/routers/web/swagger_json.go
index 493c97aa67ae9..42e9dbe96708c 100644
--- a/routers/web/swagger_json.go
+++ b/routers/web/swagger_json.go
@@ -4,22 +4,10 @@
package web
import (
- "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
)
-// tplSwaggerV1Json swagger v1 json template
-const tplSwaggerV1Json base.TplName = "swagger/v1_json"
-
// SwaggerV1Json render swagger v1 json
func SwaggerV1Json(ctx *context.Context) {
- t, err := ctx.Render.TemplateLookup(string(tplSwaggerV1Json), nil)
- if err != nil {
- ctx.ServerError("unable to find template", err)
- return
- }
- ctx.Resp.Header().Set("Content-Type", "application/json")
- if err = t.Execute(ctx.Resp, ctx.Data); err != nil {
- ctx.ServerError("unable to execute template", err)
- }
+ ctx.JSONTemplate("swagger/v1_json")
}
diff --git a/templates/shared/user/profile_big_avatar.tmpl b/templates/shared/user/profile_big_avatar.tmpl
index 4fbc43f541071..9ea8334881c85 100644
--- a/templates/shared/user/profile_big_avatar.tmpl
+++ b/templates/shared/user/profile_big_avatar.tmpl
@@ -31,9 +31,8 @@
{{svg "octicon-location"}}
{{.ContextUser.Location}}
- {{if .UserLocationMapURL}}
- {{/* We presume that the UserLocationMapURL is safe, as it is provided by the site administrator. */}}
-
+ {{if .ContextUserLocationMapURL}}
+
{{svg "octicon-link-external"}}
{{end}}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index a881afaf0ec63..d26bed53aaee7 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -8,8 +8,8 @@
"text/html"
],
"schemes": [
- "http",
- "https"
+ "https",
+ "http"
],
"swagger": "2.0",
"info": {
@@ -19,9 +19,9 @@
"name": "MIT",
"url": "http://opensource.org/licenses/MIT"
},
- "version": "{{AppVer | JSEscape | Safe}}"
+ "version": "{{AppVer | JSEscape}}"
},
- "basePath": "{{AppSubUrl | JSEscape | Safe}}/api/v1",
+ "basePath": "{{AppSubUrl | JSEscape}}/api/v1",
"paths": {
"/activitypub/user-id/{user-id}": {
"get": {
diff --git a/templates/user/auth/oidc_wellknown.tmpl b/templates/user/auth/oidc_wellknown.tmpl
index 38e6900c387a3..54bb4a763d307 100644
--- a/templates/user/auth/oidc_wellknown.tmpl
+++ b/templates/user/auth/oidc_wellknown.tmpl
@@ -1,16 +1,16 @@
{
- "issuer": "{{AppUrl | JSEscape | Safe}}",
- "authorization_endpoint": "{{AppUrl | JSEscape | Safe}}login/oauth/authorize",
- "token_endpoint": "{{AppUrl | JSEscape | Safe}}login/oauth/access_token",
- "jwks_uri": "{{AppUrl | JSEscape | Safe}}login/oauth/keys",
- "userinfo_endpoint": "{{AppUrl | JSEscape | Safe}}login/oauth/userinfo",
- "introspection_endpoint": "{{AppUrl | JSEscape | Safe}}login/oauth/introspect",
+ "issuer": "{{AppUrl | JSEscape}}",
+ "authorization_endpoint": "{{AppUrl | JSEscape}}login/oauth/authorize",
+ "token_endpoint": "{{AppUrl | JSEscape}}login/oauth/access_token",
+ "jwks_uri": "{{AppUrl | JSEscape}}login/oauth/keys",
+ "userinfo_endpoint": "{{AppUrl | JSEscape}}login/oauth/userinfo",
+ "introspection_endpoint": "{{AppUrl | JSEscape}}login/oauth/introspect",
"response_types_supported": [
"code",
"id_token"
],
"id_token_signing_alg_values_supported": [
- "{{.SigningKey.SigningMethod.Alg | JSEscape | Safe}}"
+ "{{.SigningKey.SigningMethod.Alg | JSEscape}}"
],
"subject_types_supported": [
"public"
From 7430eb9e7f04a2923cee1f144947cf5fcce39ef8 Mon Sep 17 00:00:00 2001
From: zhangnew <9146834+zhangnew@users.noreply.github.com>
Date: Sun, 18 Feb 2024 18:04:58 +0800
Subject: [PATCH 24/28] Update docs for actions variables (#29239)
the variables is supported, see
https://github.com/go-gitea/gitea/blob/a784ed3d6c6946fd9bf95f2e910f52f549326fe2/docs/content/usage/actions/act-runner.zh-cn.md?plain=1#L262-L289
---
docs/content/usage/actions/comparison.zh-cn.md | 6 ------
1 file changed, 6 deletions(-)
diff --git a/docs/content/usage/actions/comparison.zh-cn.md b/docs/content/usage/actions/comparison.zh-cn.md
index dbe9ca007d235..16b2181ba28ee 100644
--- a/docs/content/usage/actions/comparison.zh-cn.md
+++ b/docs/content/usage/actions/comparison.zh-cn.md
@@ -95,12 +95,6 @@ Gitea Actions目前不支持此功能,如果使用它,结果将始终为空
## 缺失的功能
-### 变量
-
-请参阅[变量](https://docs.github.com/zh/actions/learn-github-actions/variables)。
-
-目前变量功能正在开发中。
-
### 问题匹配器
问题匹配器是一种扫描Actions输出以查找指定正则表达式模式并在用户界面中突出显示该信息的方法。
From 67adc5c1dc3470dab96053c2e77351f3a3f8062b Mon Sep 17 00:00:00 2001
From: FuXiaoHei
Date: Sun, 18 Feb 2024 18:33:50 +0800
Subject: [PATCH 25/28] Artifact deletion in actions ui (#27172)
Add deletion link in runs view page.
Fix #26315
![image](https://github.com/go-gitea/gitea/assets/2142787/aa65a4ab-f434-4deb-b953-21e63c212033)
When click deletion button. It marks this artifact `need-delete`.
This artifact would be deleted when actions cleanup cron task.
---
models/actions/artifact.go | 22 ++++++++++
options/locale/locale_en-US.ini | 1 +
routers/web/repo/actions/view.go | 51 +++++++++++++++++++-----
routers/web/web.go | 1 +
services/actions/cleanup.go | 38 +++++++++++++++++-
templates/repo/actions/view.tmpl | 1 +
web_src/js/components/RepoActionView.vue | 15 ++++++-
web_src/js/svg.js | 2 +
8 files changed, 120 insertions(+), 11 deletions(-)
diff --git a/models/actions/artifact.go b/models/actions/artifact.go
index 5390f6288f124..3d0a288e6287e 100644
--- a/models/actions/artifact.go
+++ b/models/actions/artifact.go
@@ -26,6 +26,8 @@ const (
ArtifactStatusUploadConfirmed // 2, ArtifactStatusUploadConfirmed is the status of an artifact upload that is confirmed
ArtifactStatusUploadError // 3, ArtifactStatusUploadError is the status of an artifact upload that is errored
ArtifactStatusExpired // 4, ArtifactStatusExpired is the status of an artifact that is expired
+ ArtifactStatusPendingDeletion // 5, ArtifactStatusPendingDeletion is the status of an artifact that is pending deletion
+ ArtifactStatusDeleted // 6, ArtifactStatusDeleted is the status of an artifact that is deleted
)
func init() {
@@ -147,8 +149,28 @@ func ListNeedExpiredArtifacts(ctx context.Context) ([]*ActionArtifact, error) {
Where("expired_unix < ? AND status = ?", timeutil.TimeStamp(time.Now().Unix()), ArtifactStatusUploadConfirmed).Find(&arts)
}
+// ListPendingDeleteArtifacts returns all artifacts in pending-delete status.
+// limit is the max number of artifacts to return.
+func ListPendingDeleteArtifacts(ctx context.Context, limit int) ([]*ActionArtifact, error) {
+ arts := make([]*ActionArtifact, 0, limit)
+ return arts, db.GetEngine(ctx).
+ Where("status = ?", ArtifactStatusPendingDeletion).Limit(limit).Find(&arts)
+}
+
// SetArtifactExpired sets an artifact to expired
func SetArtifactExpired(ctx context.Context, artifactID int64) error {
_, err := db.GetEngine(ctx).Where("id=? AND status = ?", artifactID, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusExpired)})
return err
}
+
+// SetArtifactNeedDelete sets an artifact to need-delete, cron job will delete it
+func SetArtifactNeedDelete(ctx context.Context, runID int64, name string) error {
+ _, err := db.GetEngine(ctx).Where("run_id=? AND artifact_name=? AND status = ?", runID, name, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusPendingDeletion)})
+ return err
+}
+
+// SetArtifactDeleted sets an artifact to deleted
+func SetArtifactDeleted(ctx context.Context, artifactID int64) error {
+ _, err := db.GetEngine(ctx).ID(artifactID).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusDeleted)})
+ return err
+}
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index 5f34bc4c1d745..e46d6f38c0b2c 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -123,6 +123,7 @@ pin = Pin
unpin = Unpin
artifacts = Artifacts
+confirm_delete_artifact = Are you sure you want to delete the artifact '%s' ?
archived = Archived
diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go
index 59fb25b68012b..49387362b3537 100644
--- a/routers/web/repo/actions/view.go
+++ b/routers/web/repo/actions/view.go
@@ -57,15 +57,16 @@ type ViewRequest struct {
type ViewResponse struct {
State struct {
Run struct {
- Link string `json:"link"`
- Title string `json:"title"`
- Status string `json:"status"`
- CanCancel bool `json:"canCancel"`
- CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
- CanRerun bool `json:"canRerun"`
- Done bool `json:"done"`
- Jobs []*ViewJob `json:"jobs"`
- Commit ViewCommit `json:"commit"`
+ Link string `json:"link"`
+ Title string `json:"title"`
+ Status string `json:"status"`
+ CanCancel bool `json:"canCancel"`
+ CanApprove bool `json:"canApprove"` // the run needs an approval and the doer has permission to approve
+ CanRerun bool `json:"canRerun"`
+ CanDeleteArtifact bool `json:"canDeleteArtifact"`
+ Done bool `json:"done"`
+ Jobs []*ViewJob `json:"jobs"`
+ Commit ViewCommit `json:"commit"`
} `json:"run"`
CurrentJob struct {
Title string `json:"title"`
@@ -146,6 +147,7 @@ func ViewPost(ctx *context_module.Context) {
resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.CanRerun = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
+ resp.State.Run.CanDeleteArtifact = run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions)
resp.State.Run.Done = run.Status.IsDone()
resp.State.Run.Jobs = make([]*ViewJob, 0, len(jobs)) // marshal to '[]' instead fo 'null' in json
resp.State.Run.Status = run.Status.String()
@@ -535,6 +537,29 @@ func ArtifactsView(ctx *context_module.Context) {
ctx.JSON(http.StatusOK, artifactsResponse)
}
+func ArtifactsDeleteView(ctx *context_module.Context) {
+ if !ctx.Repo.CanWrite(unit.TypeActions) {
+ ctx.Error(http.StatusForbidden, "no permission")
+ return
+ }
+
+ runIndex := ctx.ParamsInt64("run")
+ artifactName := ctx.Params("artifact_name")
+
+ run, err := actions_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
+ if err != nil {
+ ctx.NotFoundOrServerError("GetRunByIndex", func(err error) bool {
+ return errors.Is(err, util.ErrNotExist)
+ }, err)
+ return
+ }
+ if err = actions_model.SetArtifactNeedDelete(ctx, run.ID, artifactName); err != nil {
+ ctx.Error(http.StatusInternalServerError, err.Error())
+ return
+ }
+ ctx.JSON(http.StatusOK, struct{}{})
+}
+
func ArtifactsDownloadView(ctx *context_module.Context) {
runIndex := ctx.ParamsInt64("run")
artifactName := ctx.Params("artifact_name")
@@ -562,6 +587,14 @@ func ArtifactsDownloadView(ctx *context_module.Context) {
return
}
+ // if artifacts status is not uploaded-confirmed, treat it as not found
+ for _, art := range artifacts {
+ if art.Status != int64(actions_model.ArtifactStatusUploadConfirmed) {
+ ctx.Error(http.StatusNotFound, "artifact not found")
+ return
+ }
+ }
+
ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s.zip; filename*=UTF-8''%s.zip", url.PathEscape(artifactName), artifactName))
writer := zip.NewWriter(ctx.Resp)
diff --git a/routers/web/web.go b/routers/web/web.go
index 0528b20328eb8..864164972e0a6 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -1368,6 +1368,7 @@ func registerRoutes(m *web.Route) {
m.Post("/approve", reqRepoActionsWriter, actions.Approve)
m.Post("/artifacts", actions.ArtifactsView)
m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView)
+ m.Delete("/artifacts/{artifact_name}", actions.ArtifactsDeleteView)
m.Post("/rerun", reqRepoActionsWriter, actions.Rerun)
})
}, reqRepoActionsReader, actions.MustEnableActions)
diff --git a/services/actions/cleanup.go b/services/actions/cleanup.go
index 785eeb5838ea9..59e2cc85de4a3 100644
--- a/services/actions/cleanup.go
+++ b/services/actions/cleanup.go
@@ -20,8 +20,15 @@ func Cleanup(taskCtx context.Context, olderThan time.Duration) error {
return CleanupArtifacts(taskCtx)
}
-// CleanupArtifacts removes expired artifacts and set records expired status
+// CleanupArtifacts removes expired add need-deleted artifacts and set records expired status
func CleanupArtifacts(taskCtx context.Context) error {
+ if err := cleanExpiredArtifacts(taskCtx); err != nil {
+ return err
+ }
+ return cleanNeedDeleteArtifacts(taskCtx)
+}
+
+func cleanExpiredArtifacts(taskCtx context.Context) error {
artifacts, err := actions.ListNeedExpiredArtifacts(taskCtx)
if err != nil {
return err
@@ -40,3 +47,32 @@ func CleanupArtifacts(taskCtx context.Context) error {
}
return nil
}
+
+// deleteArtifactBatchSize is the batch size of deleting artifacts
+const deleteArtifactBatchSize = 100
+
+func cleanNeedDeleteArtifacts(taskCtx context.Context) error {
+ for {
+ artifacts, err := actions.ListPendingDeleteArtifacts(taskCtx, deleteArtifactBatchSize)
+ if err != nil {
+ return err
+ }
+ log.Info("Found %d artifacts pending deletion", len(artifacts))
+ for _, artifact := range artifacts {
+ if err := storage.ActionsArtifacts.Delete(artifact.StoragePath); err != nil {
+ log.Error("Cannot delete artifact %d: %v", artifact.ID, err)
+ continue
+ }
+ if err := actions.SetArtifactDeleted(taskCtx, artifact.ID); err != nil {
+ log.Error("Cannot set artifact %d deleted: %v", artifact.ID, err)
+ continue
+ }
+ log.Info("Artifact %d set deleted", artifact.ID)
+ }
+ if len(artifacts) < deleteArtifactBatchSize {
+ log.Debug("No more artifacts pending deletion")
+ break
+ }
+ }
+ return nil
+}
diff --git a/templates/repo/actions/view.tmpl b/templates/repo/actions/view.tmpl
index 6b07e7000afac..f8b106147bb6f 100644
--- a/templates/repo/actions/view.tmpl
+++ b/templates/repo/actions/view.tmpl
@@ -19,6 +19,7 @@
data-locale-status-skipped="{{ctx.Locale.Tr "actions.status.skipped"}}"
data-locale-status-blocked="{{ctx.Locale.Tr "actions.status.blocked"}}"
data-locale-artifacts-title="{{ctx.Locale.Tr "artifacts"}}"
+ data-locale-confirm-delete-artifact="{{ctx.Locale.Tr "confirm_delete_artifact"}}"
data-locale-show-timestamps="{{ctx.Locale.Tr "show_timestamps"}}"
data-locale-show-log-seconds="{{ctx.Locale.Tr "show_log_seconds"}}"
data-locale-show-full-screen="{{ctx.Locale.Tr "show_full_screen"}}"
diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue
index 797869b78cead..c4a7389bc553a 100644
--- a/web_src/js/components/RepoActionView.vue
+++ b/web_src/js/components/RepoActionView.vue
@@ -5,7 +5,7 @@ import {createApp} from 'vue';
import {toggleElem} from '../utils/dom.js';
import {getCurrentLocale} from '../utils.js';
import {renderAnsi} from '../render/ansi.js';
-import {POST} from '../modules/fetch.js';
+import {POST, DELETE} from '../modules/fetch.js';
const sfc = {
name: 'RepoActionView',
@@ -200,6 +200,12 @@ const sfc = {
return await resp.json();
},
+ async deleteArtifact(name) {
+ if (!window.confirm(this.locale.confirmDeleteArtifact.replace('%s', name))) return;
+ await DELETE(`${this.run.link}/artifacts/${name}`);
+ await this.loadJob();
+ },
+
async fetchJob() {
const logCursors = this.currentJobStepsStates.map((it, idx) => {
// cursor is used to indicate the last position of the logs
@@ -329,6 +335,8 @@ export function initRepositoryActionView() {
cancel: el.getAttribute('data-locale-cancel'),
rerun: el.getAttribute('data-locale-rerun'),
artifactsTitle: el.getAttribute('data-locale-artifacts-title'),
+ areYouSure: el.getAttribute('data-locale-are-you-sure'),
+ confirmDeleteArtifact: el.getAttribute('data-locale-confirm-delete-artifact'),
rerun_all: el.getAttribute('data-locale-rerun-all'),
showTimeStamps: el.getAttribute('data-locale-show-timestamps'),
showLogSeconds: el.getAttribute('data-locale-show-log-seconds'),
@@ -404,6 +412,9 @@ export function initRepositoryActionView() {
{{ artifact.name }}
+
+
+
@@ -528,6 +539,8 @@ export function initRepositoryActionView() {
.job-artifacts-item {
margin: 5px 0;
padding: 6px;
+ display: flex;
+ justify-content: space-between;
}
.job-artifacts-list {
diff --git a/web_src/js/svg.js b/web_src/js/svg.js
index 084256587c518..471b5136bd34c 100644
--- a/web_src/js/svg.js
+++ b/web_src/js/svg.js
@@ -67,6 +67,7 @@ import octiconStrikethrough from '../../public/assets/img/svg/octicon-strikethro
import octiconSync from '../../public/assets/img/svg/octicon-sync.svg';
import octiconTable from '../../public/assets/img/svg/octicon-table.svg';
import octiconTag from '../../public/assets/img/svg/octicon-tag.svg';
+import octiconTrash from '../../public/assets/img/svg/octicon-trash.svg';
import octiconTriangleDown from '../../public/assets/img/svg/octicon-triangle-down.svg';
import octiconX from '../../public/assets/img/svg/octicon-x.svg';
import octiconXCircleFill from '../../public/assets/img/svg/octicon-x-circle-fill.svg';
@@ -139,6 +140,7 @@ const svgs = {
'octicon-sync': octiconSync,
'octicon-table': octiconTable,
'octicon-tag': octiconTag,
+ 'octicon-trash': octiconTrash,
'octicon-triangle-down': octiconTriangleDown,
'octicon-x': octiconX,
'octicon-x-circle-fill': octiconXCircleFill,
From 1a6e1cbada27db1e3327b0d7d331492c95e24759 Mon Sep 17 00:00:00 2001
From: yp05327 <576951401@qq.com>
Date: Sun, 18 Feb 2024 19:58:46 +0900
Subject: [PATCH 26/28] Implement some action notifier functions (#29173)
Fix #29166
Add support for the following activity types of `pull_request`
- assigned
- unassigned
- review_requested
- review_request_removed
- milestoned
- demilestoned
---
modules/actions/github.go | 4 +-
modules/actions/workflows.go | 8 ++--
services/actions/notifier.go | 76 +++++++++++++++++++++++++++++++-----
3 files changed, 75 insertions(+), 13 deletions(-)
diff --git a/modules/actions/github.go b/modules/actions/github.go
index fafea4e11a805..18917c5118d66 100644
--- a/modules/actions/github.go
+++ b/modules/actions/github.go
@@ -52,7 +52,9 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
case webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
webhook_module.HookEventPullRequestAssign,
- webhook_module.HookEventPullRequestLabel:
+ webhook_module.HookEventPullRequestLabel,
+ webhook_module.HookEventPullRequestReviewRequest,
+ webhook_module.HookEventPullRequestMilestone:
return true
default:
diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go
index a883f4181b2c8..2db4a9296f0e8 100644
--- a/modules/actions/workflows.go
+++ b/modules/actions/workflows.go
@@ -221,7 +221,9 @@ func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent web
webhook_module.HookEventPullRequest,
webhook_module.HookEventPullRequestSync,
webhook_module.HookEventPullRequestAssign,
- webhook_module.HookEventPullRequestLabel:
+ webhook_module.HookEventPullRequestLabel,
+ webhook_module.HookEventPullRequestReviewRequest,
+ webhook_module.HookEventPullRequestMilestone:
return matchPullRequestEvent(gitRepo, commit, payload.(*api.PullRequestPayload), evt)
case // pull_request_review
@@ -397,13 +399,13 @@ func matchPullRequestEvent(gitRepo *git.Repository, commit *git.Commit, prPayloa
} else {
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
// Actions with the same name:
- // opened, edited, closed, reopened, assigned, unassigned
+ // opened, edited, closed, reopened, assigned, unassigned, review_requested, review_request_removed, milestoned, demilestoned
// Actions need to be converted:
// synchronized -> synchronize
// label_updated -> labeled
// label_cleared -> unlabeled
// Unsupported activity types:
- // converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
+ // converted_to_draft, ready_for_review, locked, unlocked, auto_merge_enabled, auto_merge_disabled, enqueued, dequeued
action := prPayload.Action
switch action {
diff --git a/services/actions/notifier.go b/services/actions/notifier.go
index 0b4fed5db1282..093607f05cc58 100644
--- a/services/actions/notifier.go
+++ b/services/actions/notifier.go
@@ -101,11 +101,40 @@ func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
Notify(ctx)
}
+// IssueChangeAssignee notifies assigned or unassigned to notifiers
+func (n *actionsNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) {
+ ctx = withMethod(ctx, "IssueChangeAssignee")
+
+ var action api.HookIssueAction
+ if removed {
+ action = api.HookIssueUnassigned
+ } else {
+ action = api.HookIssueAssigned
+ }
+ notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestAssign, action)
+}
+
+// IssueChangeMilestone notifies assignee to notifiers
+func (n *actionsNotifier) IssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) {
+ ctx = withMethod(ctx, "IssueChangeMilestone")
+
+ var action api.HookIssueAction
+ if issue.MilestoneID > 0 {
+ action = api.HookIssueMilestoned
+ } else {
+ action = api.HookIssueDemilestoned
+ }
+ notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestMilestone, action)
+}
+
func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue,
_, _ []*issues_model.Label,
) {
ctx = withMethod(ctx, "IssueChangeLabels")
+ notifyIssueChange(ctx, doer, issue, webhook_module.HookEventPullRequestLabel, api.HookIssueLabelUpdated)
+}
+func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, event webhook_module.HookEventType, action api.HookIssueAction) {
var err error
if err = issue.LoadRepo(ctx); err != nil {
log.Error("LoadRepo: %v", err)
@@ -117,20 +146,15 @@ func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
return
}
- permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
if issue.IsPull {
if err = issue.LoadPullRequest(ctx); err != nil {
log.Error("loadPullRequest: %v", err)
return
}
- if err = issue.PullRequest.LoadIssue(ctx); err != nil {
- log.Error("LoadIssue: %v", err)
- return
- }
- newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequestLabel).
+ newNotifyInputFromIssue(issue, event).
WithDoer(doer).
WithPayload(&api.PullRequestPayload{
- Action: api.HookIssueLabelUpdated,
+ Action: action,
Index: issue.Index,
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
Repository: convert.ToRepo(ctx, issue.Repo, access_model.Permission{AccessMode: perm_model.AccessModeNone}),
@@ -140,10 +164,11 @@ func (n *actionsNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
Notify(ctx)
return
}
- newNotifyInputFromIssue(issue, webhook_module.HookEventIssueLabel).
+ permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, issue.Poster)
+ newNotifyInputFromIssue(issue, event).
WithDoer(doer).
WithPayload(&api.IssuePayload{
- Action: api.HookIssueLabelUpdated,
+ Action: action,
Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission),
@@ -305,6 +330,39 @@ func (n *actionsNotifier) PullRequestReview(ctx context.Context, pr *issues_mode
}).Notify(ctx)
}
+func (n *actionsNotifier) PullRequestReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) {
+ if !issue.IsPull {
+ log.Warn("PullRequestReviewRequest: issue is not a pull request: %v", issue.ID)
+ return
+ }
+
+ ctx = withMethod(ctx, "PullRequestReviewRequest")
+
+ permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
+ if err := issue.LoadPullRequest(ctx); err != nil {
+ log.Error("LoadPullRequest failed: %v", err)
+ return
+ }
+ var action api.HookIssueAction
+ if isRequest {
+ action = api.HookIssueReviewRequested
+ } else {
+ action = api.HookIssueReviewRequestRemoved
+ }
+ newNotifyInputFromIssue(issue, webhook_module.HookEventPullRequestReviewRequest).
+ WithDoer(doer).
+ WithPayload(&api.PullRequestPayload{
+ Action: action,
+ Index: issue.Index,
+ PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
+ RequestedReviewer: convert.ToUser(ctx, reviewer, nil),
+ Repository: convert.ToRepo(ctx, issue.Repo, permission),
+ Sender: convert.ToUser(ctx, doer, nil),
+ }).
+ WithPullRequest(issue.PullRequest).
+ Notify(ctx)
+}
+
func (*actionsNotifier) MergePullRequest(ctx context.Context, doer *user_model.User, pr *issues_model.PullRequest) {
ctx = withMethod(ctx, "MergePullRequest")
From 6093f507fe6f2d4802de8ec1ff5b04820e81571c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tim-Nicas=20Oelschl=C3=A4ger?=
<72873130+zokkis@users.noreply.github.com>
Date: Sun, 18 Feb 2024 12:47:50 +0100
Subject: [PATCH 27/28] Convert visibility to number (#29226)
Don't throw error while creating user (Fixes #29218)
---
templates/admin/user/new.tmpl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl
index 81f70511d0e29..bcb53d81314cb 100644
--- a/templates/admin/user/new.tmpl
+++ b/templates/admin/user/new.tmpl
@@ -26,7 +26,7 @@
{{ctx.Locale.Tr "settings.visibility"}}
-
+
{{if .DefaultUserVisibilityMode.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}}
{{if .DefaultUserVisibilityMode.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}}
From 4345cac52971c13debfe5e6f311aef3930fe2eed Mon Sep 17 00:00:00 2001
From: wxiaoguang
Date: Sun, 18 Feb 2024 20:15:24 +0800
Subject: [PATCH 28/28] Improve TrHTML and add more tests (#29228)
Follow #29165.
Co-authored-by: KN4CK3R
---
modules/translation/i18n/i18n_test.go | 66 +++++++++++++++++++++++++
modules/translation/i18n/localestore.go | 8 +--
2 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go
index ffe69a74dfd02..b364992dfe39e 100644
--- a/modules/translation/i18n/i18n_test.go
+++ b/modules/translation/i18n/i18n_test.go
@@ -4,6 +4,7 @@
package i18n
import (
+ "html/template"
"strings"
"testing"
@@ -82,6 +83,71 @@ c=22
assert.Equal(t, "22", lang1.TrString("c"))
}
+type stringerPointerReceiver struct {
+ s string
+}
+
+func (s *stringerPointerReceiver) String() string {
+ return s.s
+}
+
+type stringerStructReceiver struct {
+ s string
+}
+
+func (s stringerStructReceiver) String() string {
+ return s.s
+}
+
+type errorStructReceiver struct {
+ s string
+}
+
+func (e errorStructReceiver) Error() string {
+ return e.s
+}
+
+type errorPointerReceiver struct {
+ s string
+}
+
+func (e *errorPointerReceiver) Error() string {
+ return e.s
+}
+
+func TestLocaleWithTemplate(t *testing.T) {
+ ls := NewLocaleStore()
+ assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", []byte(`key=%s `), nil))
+ lang1, _ := ls.Locale("lang1")
+
+ tmpl := template.New("test").Funcs(template.FuncMap{"tr": lang1.TrHTML})
+ tmpl = template.Must(tmpl.Parse(`{{tr "key" .var}}`))
+
+ cases := []struct {
+ in any
+ want string
+ }{
+ {"", "<str> "},
+ {[]byte(""), "[60 98 121 116 101 115 62] "},
+ {template.HTML(""), " "},
+ {stringerPointerReceiver{""}, "{<stringerPointerReceiver>} "},
+ {&stringerPointerReceiver{""}, "<stringerPointerReceiver ptr> "},
+ {stringerStructReceiver{""}, "<stringerStructReceiver> "},
+ {&stringerStructReceiver{""}, "<stringerStructReceiver ptr> "},
+ {errorStructReceiver{""}, "<errorStructReceiver> "},
+ {&errorStructReceiver{""}, "<errorStructReceiver ptr> "},
+ {errorPointerReceiver{""}, "{<errorPointerReceiver>} "},
+ {&errorPointerReceiver{""}, "<errorPointerReceiver ptr> "},
+ }
+
+ buf := &strings.Builder{}
+ for _, c := range cases {
+ buf.Reset()
+ assert.NoError(t, tmpl.Execute(buf, map[string]any{"var": c.in}))
+ assert.Equal(t, c.want, buf.String())
+ }
+}
+
func TestLocaleStoreQuirks(t *testing.T) {
const nl = "\n"
q := func(q1, s string, q2 ...string) string {
diff --git a/modules/translation/i18n/localestore.go b/modules/translation/i18n/localestore.go
index 69cc9fd91da7e..b422996984503 100644
--- a/modules/translation/i18n/localestore.go
+++ b/modules/translation/i18n/localestore.go
@@ -133,12 +133,14 @@ func (l *locale) TrHTML(trKey string, trArgs ...any) template.HTML {
args := slices.Clone(trArgs)
for i, v := range args {
switch v := v.(type) {
+ case nil, bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, template.HTML:
+ // for most basic types (including template.HTML which is safe), just do nothing and use it
case string:
- args[i] = template.HTML(template.HTMLEscapeString(v))
+ args[i] = template.HTMLEscapeString(v)
case fmt.Stringer:
args[i] = template.HTMLEscapeString(v.String())
- default: // int, float, include template.HTML
- // do nothing, just use it
+ default:
+ args[i] = template.HTMLEscapeString(fmt.Sprint(v))
}
}
return template.HTML(l.TrString(trKey, args...))