From 12bf0b8e4270956cee1739520d303d9b7527a7f0 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 5 May 2025 23:15:22 +0200 Subject: [PATCH 01/32] Fix only text/* being viewable in web UI (#34374) Regression from #34356, files like SVGs should be editable too (https://github.com/go-gitea/gitea/pull/34356#discussion_r2072766240). --- routers/web/repo/editor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 514eb0ebfe..03e5b830a0 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -165,7 +165,7 @@ func editFile(ctx *context.Context, isNewFile bool) { ctx.Data["FileSize"] = blob.Size() // Only some file types are editable online as text. - if !fInfo.isTextFile || fInfo.isLFSFile { + if !fInfo.st.IsRepresentableAsText() || fInfo.isLFSFile { ctx.NotFound(nil) return } From 6b2c506e0513232b4f111795e27db9b41e8bd8fc Mon Sep 17 00:00:00 2001 From: NorthRealm <155140859+NorthRealm@users.noreply.github.com> Date: Tue, 6 May 2025 04:53:17 +0000 Subject: [PATCH 02/32] Grey out expired artifact on Artifacts list (#34314) Grey out expired artifact on Artifacts list. ![1](https://github.com/user-attachments/assets/79c00e39-29f5-4264-b7b2-7ed638ab71c1) ![2](https://github.com/user-attachments/assets/686b745f-d6d7-4921-8e1b-3472ac8b6c17) --------- Co-authored-by: wxiaoguang --- options/locale/locale_en-US.ini | 1 + routers/web/devtest/mock_actions.go | 10 +++++++ templates/repo/actions/view_component.tmpl | 1 + web_src/js/components/RepoActionView.vue | 31 +++++++++++++--------- web_src/js/features/repo-actions.ts | 1 + 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 4db4964afb..9091b6bc4b 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -130,6 +130,7 @@ pin = Pin unpin = Unpin artifacts = Artifacts +expired = Expired confirm_delete_artifact = Are you sure you want to delete the artifact '%s' ? archived = Archived diff --git a/routers/web/devtest/mock_actions.go b/routers/web/devtest/mock_actions.go index 023909aceb..bc741ecd11 100644 --- a/routers/web/devtest/mock_actions.go +++ b/routers/web/devtest/mock_actions.go @@ -94,6 +94,16 @@ func MockActionsRunsJobs(ctx *context.Context) { Size: 1024 * 1024, Status: "completed", }) + resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{ + Name: "artifact-very-loooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + Size: 100 * 1024, + Status: "expired", + }) + resp.Artifacts = append(resp.Artifacts, &actions.ArtifactsViewItem{ + Name: "artifact-really-loooooooooooooooooooooooooooooooooooooooooooooooooooooooong", + Size: 1024 * 1024, + Status: "completed", + }) resp.State.Run.Jobs = append(resp.State.Run.Jobs, &actions.ViewJob{ ID: runID * 10, diff --git a/templates/repo/actions/view_component.tmpl b/templates/repo/actions/view_component.tmpl index 8d1de41f70..d0741cdc0b 100644 --- a/templates/repo/actions/view_component.tmpl +++ b/templates/repo/actions/view_component.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-artifact-expired="{{ctx.Locale.Tr "expired"}}" 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"}}" diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 447347890b..af300622b4 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -495,14 +495,24 @@ export default defineComponent({ {{ locale.artifactsTitle }} @@ -664,6 +674,7 @@ export default defineComponent({ padding: 6px; display: flex; justify-content: space-between; + align-items: center; } .job-artifacts-list { @@ -671,10 +682,6 @@ export default defineComponent({ list-style: none; } -.job-artifacts-icon { - padding-right: 3px; -} - .job-brief-list { display: flex; flex-direction: column; diff --git a/web_src/js/features/repo-actions.ts b/web_src/js/features/repo-actions.ts index cbd0429c04..8d93fce53f 100644 --- a/web_src/js/features/repo-actions.ts +++ b/web_src/js/features/repo-actions.ts @@ -24,6 +24,7 @@ export function initRepositoryActionView() { pushedBy: el.getAttribute('data-locale-runs-pushed-by'), artifactsTitle: el.getAttribute('data-locale-artifacts-title'), areYouSure: el.getAttribute('data-locale-are-you-sure'), + artifactExpired: el.getAttribute('data-locale-artifact-expired'), confirmDeleteArtifact: el.getAttribute('data-locale-confirm-delete-artifact'), showTimeStamps: el.getAttribute('data-locale-show-timestamps'), showLogSeconds: el.getAttribute('data-locale-show-log-seconds'), From a2024953c5914c5a7d59d236262f9bd94b65b996 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 6 May 2025 09:29:48 +0200 Subject: [PATCH 03/32] gitignore: Visual Studio settings folder (#34375) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 703be8f681..272ea2b5ed 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ _test .vscode __debug_bin* +# Visual Studio +/.vs/ + *.cgo1.go *.cgo2.c _cgo_defun.c From 6bd8fe53537172fb4df976962115f1b928bf2993 Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Tue, 6 May 2025 19:44:25 +0300 Subject: [PATCH 04/32] Bump `@github/relative-time-element` to v4.4.7 (#34384) Tested, it works as before. Changelog: https://github.com/github/relative-time-element/releases/tag/4.4.7 Signed-off-by: Yarden Shoham --- package-lock.json | 18 +++++------------- package.json | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index e374bcdc7c..72e19719ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.6", + "@github/relative-time-element": "4.4.7", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", @@ -1149,18 +1149,10 @@ "license": "MIT" }, "node_modules/@github/relative-time-element": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.6.tgz", - "integrity": "sha512-KgrkxVWb/qcBBSDumGhRzieqtSzGJyyEF4D5to+OVJf/nTExU5sSlPKiNEzN8Nh6Kj0SGlq8UdIJjEgPxZzUhQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "18 || 19" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.7.tgz", + "integrity": "sha512-NZCePEFYtV7qAUI/pHYuqZ8vRhcsfH/dziUZTY9YR5+JwzDCWtEokYSDbDLZjrRl+SAFr02YHUK+UdtP6hPcbQ==", + "license": "MIT" }, "node_modules/@github/text-expander-element": { "version": "2.9.1", diff --git a/package.json b/package.json index bc11e4d398..0d15ecf39d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.6", + "@github/relative-time-element": "4.4.7", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", From 2a660b4a1b6913f80981d8840b3dc129a4eb7f26 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 6 May 2025 20:10:14 -0700 Subject: [PATCH 05/32] Upgrade go-github v61 -> v71 (#34385) There will be a possible bug when migrating from Github https://github.com/google/go-github/issues/3229 This PR upgrades go-github from v61 to v71 to resolve that problem. --- assets/go-licenses.json | 4 ++-- contrib/backport/backport.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- services/migrations/error.go | 2 +- services/migrations/github.go | 42 ++++++++++++++++++++++------------- 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 1693b0a506..3827a092f1 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -625,8 +625,8 @@ "licenseText": "\n Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright [yyyy] [name of copyright owner]\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n" }, { - "name": "github.com/google/go-github/v61/github", - "path": "github.com/google/go-github/v61/github/LICENSE", + "name": "github.com/google/go-github/v71/github", + "path": "github.com/google/go-github/v71/github/LICENSE", "licenseText": "Copyright (c) 2013 The go-github AUTHORS. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, { diff --git a/contrib/backport/backport.go b/contrib/backport/backport.go index 9b30480300..44e4eacf90 100644 --- a/contrib/backport/backport.go +++ b/contrib/backport/backport.go @@ -18,7 +18,7 @@ import ( "strings" "syscall" - "github.com/google/go-github/v61/github" + "github.com/google/go-github/v71/github" "github.com/urfave/cli/v2" "gopkg.in/yaml.v3" ) diff --git a/go.mod b/go.mod index 3f54133a85..a43a0a3111 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v5 v5.2.2 - github.com/google/go-github/v61 v61.0.0 + github.com/google/go-github/v71 v71.0.0 github.com/google/licenseclassifier/v2 v2.0.0 github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416 github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index c9dcc235aa..9b200cc2d9 100644 --- a/go.sum +++ b/go.sum @@ -420,8 +420,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5pNlu1go= -github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY= +github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30= +github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc= diff --git a/services/migrations/error.go b/services/migrations/error.go index c7d912f50b..9b470149bf 100644 --- a/services/migrations/error.go +++ b/services/migrations/error.go @@ -7,7 +7,7 @@ package migrations import ( "errors" - "github.com/google/go-github/v61/github" + "github.com/google/go-github/v71/github" ) // ErrRepoNotCreated returns the error that repository not created diff --git a/services/migrations/github.go b/services/migrations/github.go index ce3e5ced9e..662908756a 100644 --- a/services/migrations/github.go +++ b/services/migrations/github.go @@ -20,7 +20,7 @@ import ( "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/structs" - "github.com/google/go-github/v61/github" + "github.com/google/go-github/v71/github" "golang.org/x/oauth2" ) @@ -441,9 +441,11 @@ func (g *GithubDownloaderV3) GetIssues(ctx context.Context, page, perPage int) ( if !g.SkipReactions { for i := 1; ; i++ { g.waitAndPickClient(ctx) - res, resp, err := g.getClient().Reactions.ListIssueReactions(ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListOptions{ - Page: i, - PerPage: perPage, + res, resp, err := g.getClient().Reactions.ListIssueReactions(ctx, g.repoOwner, g.repoName, issue.GetNumber(), &github.ListReactionOptions{ + ListOptions: github.ListOptions{ + Page: i, + PerPage: perPage, + }, }) if err != nil { return nil, false, err @@ -527,9 +529,11 @@ func (g *GithubDownloaderV3) getComments(ctx context.Context, commentable base.C if !g.SkipReactions { for i := 1; ; i++ { g.waitAndPickClient(ctx) - res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ - Page: i, - PerPage: g.maxPerPage, + res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListReactionOptions{ + ListOptions: github.ListOptions{ + Page: i, + PerPage: g.maxPerPage, + }, }) if err != nil { return nil, err @@ -602,9 +606,11 @@ func (g *GithubDownloaderV3) GetAllComments(ctx context.Context, page, perPage i if !g.SkipReactions { for i := 1; ; i++ { g.waitAndPickClient(ctx) - res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListOptions{ - Page: i, - PerPage: g.maxPerPage, + res, resp, err := g.getClient().Reactions.ListIssueCommentReactions(ctx, g.repoOwner, g.repoName, comment.GetID(), &github.ListReactionOptions{ + ListOptions: github.ListOptions{ + Page: i, + PerPage: g.maxPerPage, + }, }) if err != nil { return nil, false, err @@ -673,9 +679,11 @@ func (g *GithubDownloaderV3) GetPullRequests(ctx context.Context, page, perPage if !g.SkipReactions { for i := 1; ; i++ { g.waitAndPickClient(ctx) - res, resp, err := g.getClient().Reactions.ListIssueReactions(ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListOptions{ - Page: i, - PerPage: perPage, + res, resp, err := g.getClient().Reactions.ListIssueReactions(ctx, g.repoOwner, g.repoName, pr.GetNumber(), &github.ListReactionOptions{ + ListOptions: github.ListOptions{ + Page: i, + PerPage: perPage, + }, }) if err != nil { return nil, false, err @@ -760,9 +768,11 @@ func (g *GithubDownloaderV3) convertGithubReviewComments(ctx context.Context, cs if !g.SkipReactions { for i := 1; ; i++ { g.waitAndPickClient(ctx) - res, resp, err := g.getClient().Reactions.ListPullRequestCommentReactions(ctx, g.repoOwner, g.repoName, c.GetID(), &github.ListOptions{ - Page: i, - PerPage: g.maxPerPage, + res, resp, err := g.getClient().Reactions.ListPullRequestCommentReactions(ctx, g.repoOwner, g.repoName, c.GetID(), &github.ListReactionOptions{ + ListOptions: github.ListOptions{ + Page: i, + PerPage: g.maxPerPage, + }, }) if err != nil { return nil, err From dd886d729f6206ad878aa5e0f0f3d4d20ea9a208 Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 7 May 2025 19:21:38 +0200 Subject: [PATCH 06/32] Update JS and PY dependencies (#34391) Result of `make update-js update-py svg`. Quick test of the UI worked. --- options/fileicon/material-icon-rules.json | 411 +++++-- options/fileicon/material-icon-svgs.json | 52 +- package-lock.json | 1350 +++++++++++---------- package.json | 28 +- poetry.lock | 16 +- pyproject.toml | 2 +- 6 files changed, 1050 insertions(+), 809 deletions(-) diff --git a/options/fileicon/material-icon-rules.json b/options/fileicon/material-icon-rules.json index d097399252..826eb40e87 100644 --- a/options/fileicon/material-icon-rules.json +++ b/options/fileicon/material-icon-rules.json @@ -716,6 +716,14 @@ ".designs": "folder-theme", "_designs": "folder-theme", "__designs__": "folder-theme", + "palette": "folder-theme", + ".palette": "folder-theme", + "_palette": "folder-theme", + "__palette__": "folder-theme", + "palettes": "folder-theme", + ".palettes": "folder-theme", + "_palettes": "folder-theme", + "__palettes__": "folder-theme", "webpack": "folder-webpack", ".webpack": "folder-webpack", "_webpack": "folder-webpack", @@ -884,6 +892,14 @@ ".music": "folder-audio", "_music": "folder-audio", "__music__": "folder-audio", + "song": "folder-audio", + ".song": "folder-audio", + "_song": "folder-audio", + "__song__": "folder-audio", + "songs": "folder-audio", + ".songs": "folder-audio", + "_songs": "folder-audio", + "__songs__": "folder-audio", "sound": "folder-audio", ".sound": "folder-audio", "_sound": "folder-audio", @@ -1136,10 +1152,18 @@ ".benchmarks": "folder-benchmark", "_benchmarks": "folder-benchmark", "__benchmarks__": "folder-benchmark", + "bench": "folder-benchmark", + ".bench": "folder-benchmark", + "_bench": "folder-benchmark", + "__bench__": "folder-benchmark", "performance": "folder-benchmark", ".performance": "folder-benchmark", "_performance": "folder-benchmark", "__performance__": "folder-benchmark", + "perf": "folder-benchmark", + ".perf": "folder-benchmark", + "_perf": "folder-benchmark", + "__perf__": "folder-benchmark", "profiling": "folder-benchmark", ".profiling": "folder-benchmark", "_profiling": "folder-benchmark", @@ -1236,10 +1260,18 @@ ".sandbox": "folder-sandbox", "_sandbox": "folder-sandbox", "__sandbox__": "folder-sandbox", + "sandboxes": "folder-sandbox", + ".sandboxes": "folder-sandbox", + "_sandboxes": "folder-sandbox", + "__sandboxes__": "folder-sandbox", "playground": "folder-sandbox", ".playground": "folder-sandbox", "_playground": "folder-sandbox", "__playground__": "folder-sandbox", + "playgrounds": "folder-sandbox", + ".playgrounds": "folder-sandbox", + "_playgrounds": "folder-sandbox", + "__playgrounds__": "folder-sandbox", "scons": "folder-scons", ".scons": "folder-scons", "_scons": "folder-scons", @@ -1584,46 +1616,46 @@ ".archival": "folder-archive", "_archival": "folder-archive", "__archival__": "folder-archive", - "bkp": "folder-archive", - ".bkp": "folder-archive", - "_bkp": "folder-archive", - "__bkp__": "folder-archive", - "bkps": "folder-archive", - ".bkps": "folder-archive", - "_bkps": "folder-archive", - "__bkps__": "folder-archive", - "bak": "folder-archive", - ".bak": "folder-archive", - "_bak": "folder-archive", - "__bak__": "folder-archive", - "baks": "folder-archive", - ".baks": "folder-archive", - "_baks": "folder-archive", - "__baks__": "folder-archive", - "backup": "folder-archive", - ".backup": "folder-archive", - "_backup": "folder-archive", - "__backup__": "folder-archive", - "backups": "folder-archive", - ".backups": "folder-archive", - "_backups": "folder-archive", - "__backups__": "folder-archive", - "back-up": "folder-archive", - ".back-up": "folder-archive", - "_back-up": "folder-archive", - "__back-up__": "folder-archive", - "back-ups": "folder-archive", - ".back-ups": "folder-archive", - "_back-ups": "folder-archive", - "__back-ups__": "folder-archive", - "history": "folder-archive", - ".history": "folder-archive", - "_history": "folder-archive", - "__history__": "folder-archive", - "histories": "folder-archive", - ".histories": "folder-archive", - "_histories": "folder-archive", - "__histories__": "folder-archive", + "bkp": "folder-backup", + ".bkp": "folder-backup", + "_bkp": "folder-backup", + "__bkp__": "folder-backup", + "bkps": "folder-backup", + ".bkps": "folder-backup", + "_bkps": "folder-backup", + "__bkps__": "folder-backup", + "bak": "folder-backup", + ".bak": "folder-backup", + "_bak": "folder-backup", + "__bak__": "folder-backup", + "baks": "folder-backup", + ".baks": "folder-backup", + "_baks": "folder-backup", + "__baks__": "folder-backup", + "backup": "folder-backup", + ".backup": "folder-backup", + "_backup": "folder-backup", + "__backup__": "folder-backup", + "backups": "folder-backup", + ".backups": "folder-backup", + "_backups": "folder-backup", + "__backups__": "folder-backup", + "back-up": "folder-backup", + ".back-up": "folder-backup", + "_back-up": "folder-backup", + "__back-up__": "folder-backup", + "back-ups": "folder-backup", + ".back-ups": "folder-backup", + "_back-ups": "folder-backup", + "__back-ups__": "folder-backup", + "history": "folder-backup", + ".history": "folder-backup", + "_history": "folder-backup", + "__history__": "folder-backup", + "histories": "folder-backup", + ".histories": "folder-backup", + "_histories": "folder-backup", + "__histories__": "folder-backup", "batch": "folder-batch", ".batch": "folder-batch", "_batch": "folder-batch", @@ -1680,6 +1712,14 @@ ".constants": "folder-constant", "_constants": "folder-constant", "__constants__": "folder-constant", + "const": "folder-constant", + ".const": "folder-constant", + "_const": "folder-constant", + "__const__": "folder-constant", + "consts": "folder-constant", + ".consts": "folder-constant", + "_consts": "folder-constant", + "__consts__": "folder-constant", "container": "folder-container", ".container": "folder-container", "_container": "folder-container", @@ -1868,14 +1908,14 @@ ".hooks": "folder-hook", "_hooks": "folder-hook", "__hooks__": "folder-hook", - "trigger": "folder-hook", - ".trigger": "folder-hook", - "_trigger": "folder-hook", - "__trigger__": "folder-hook", - "triggers": "folder-hook", - ".triggers": "folder-hook", - "_triggers": "folder-hook", - "__triggers__": "folder-hook", + "trigger": "folder-trigger", + ".trigger": "folder-trigger", + "_trigger": "folder-trigger", + "__trigger__": "folder-trigger", + "triggers": "folder-trigger", + ".triggers": "folder-trigger", + "_triggers": "folder-trigger", + "__triggers__": "folder-trigger", "job": "folder-job", ".job": "folder-job", "_job": "folder-job", @@ -3051,6 +3091,46 @@ ".kql": "folder-kusto", "_kql": "folder-kusto", "__kql__": "folder-kusto", + "policy": "folder-policy", + ".policy": "folder-policy", + "_policy": "folder-policy", + "__policy__": "folder-policy", + "policies": "folder-policy", + ".policies": "folder-policy", + "_policies": "folder-policy", + "__policies__": "folder-policy", + "attachment": "folder-attachment", + ".attachment": "folder-attachment", + "_attachment": "folder-attachment", + "__attachment__": "folder-attachment", + "attachments": "folder-attachment", + ".attachments": "folder-attachment", + "_attachments": "folder-attachment", + "__attachments__": "folder-attachment", + "bibliography": "folder-bibliography", + ".bibliography": "folder-bibliography", + "_bibliography": "folder-bibliography", + "__bibliography__": "folder-bibliography", + "bibliographies": "folder-bibliography", + ".bibliographies": "folder-bibliography", + "_bibliographies": "folder-bibliography", + "__bibliographies__": "folder-bibliography", + "book": "folder-bibliography", + ".book": "folder-bibliography", + "_book": "folder-bibliography", + "__book__": "folder-bibliography", + "books": "folder-bibliography", + ".books": "folder-bibliography", + "_books": "folder-bibliography", + "__books__": "folder-bibliography", + "link": "folder-link", + ".link": "folder-link", + "_link": "folder-link", + "__link__": "folder-link", + "links": "folder-link", + ".links": "folder-link", + "_links": "folder-link", + "__links__": "folder-link", "meta-inf": "folder-config", ".meta-inf": "folder-config", "_meta-inf": "folder-config", @@ -3797,6 +3877,14 @@ ".designs": "folder-theme-open", "_designs": "folder-theme-open", "__designs__": "folder-theme-open", + "palette": "folder-theme-open", + ".palette": "folder-theme-open", + "_palette": "folder-theme-open", + "__palette__": "folder-theme-open", + "palettes": "folder-theme-open", + ".palettes": "folder-theme-open", + "_palettes": "folder-theme-open", + "__palettes__": "folder-theme-open", "webpack": "folder-webpack-open", ".webpack": "folder-webpack-open", "_webpack": "folder-webpack-open", @@ -3965,6 +4053,14 @@ ".music": "folder-audio-open", "_music": "folder-audio-open", "__music__": "folder-audio-open", + "song": "folder-audio-open", + ".song": "folder-audio-open", + "_song": "folder-audio-open", + "__song__": "folder-audio-open", + "songs": "folder-audio-open", + ".songs": "folder-audio-open", + "_songs": "folder-audio-open", + "__songs__": "folder-audio-open", "sound": "folder-audio-open", ".sound": "folder-audio-open", "_sound": "folder-audio-open", @@ -4217,10 +4313,18 @@ ".benchmarks": "folder-benchmark-open", "_benchmarks": "folder-benchmark-open", "__benchmarks__": "folder-benchmark-open", + "bench": "folder-benchmark-open", + ".bench": "folder-benchmark-open", + "_bench": "folder-benchmark-open", + "__bench__": "folder-benchmark-open", "performance": "folder-benchmark-open", ".performance": "folder-benchmark-open", "_performance": "folder-benchmark-open", "__performance__": "folder-benchmark-open", + "perf": "folder-benchmark-open", + ".perf": "folder-benchmark-open", + "_perf": "folder-benchmark-open", + "__perf__": "folder-benchmark-open", "profiling": "folder-benchmark-open", ".profiling": "folder-benchmark-open", "_profiling": "folder-benchmark-open", @@ -4317,10 +4421,18 @@ ".sandbox": "folder-sandbox-open", "_sandbox": "folder-sandbox-open", "__sandbox__": "folder-sandbox-open", + "sandboxes": "folder-sandbox-open", + ".sandboxes": "folder-sandbox-open", + "_sandboxes": "folder-sandbox-open", + "__sandboxes__": "folder-sandbox-open", "playground": "folder-sandbox-open", ".playground": "folder-sandbox-open", "_playground": "folder-sandbox-open", "__playground__": "folder-sandbox-open", + "playgrounds": "folder-sandbox-open", + ".playgrounds": "folder-sandbox-open", + "_playgrounds": "folder-sandbox-open", + "__playgrounds__": "folder-sandbox-open", "scons": "folder-scons-open", ".scons": "folder-scons-open", "_scons": "folder-scons-open", @@ -4665,46 +4777,46 @@ ".archival": "folder-archive-open", "_archival": "folder-archive-open", "__archival__": "folder-archive-open", - "bkp": "folder-archive-open", - ".bkp": "folder-archive-open", - "_bkp": "folder-archive-open", - "__bkp__": "folder-archive-open", - "bkps": "folder-archive-open", - ".bkps": "folder-archive-open", - "_bkps": "folder-archive-open", - "__bkps__": "folder-archive-open", - "bak": "folder-archive-open", - ".bak": "folder-archive-open", - "_bak": "folder-archive-open", - "__bak__": "folder-archive-open", - "baks": "folder-archive-open", - ".baks": "folder-archive-open", - "_baks": "folder-archive-open", - "__baks__": "folder-archive-open", - "backup": "folder-archive-open", - ".backup": "folder-archive-open", - "_backup": "folder-archive-open", - "__backup__": "folder-archive-open", - "backups": "folder-archive-open", - ".backups": "folder-archive-open", - "_backups": "folder-archive-open", - "__backups__": "folder-archive-open", - "back-up": "folder-archive-open", - ".back-up": "folder-archive-open", - "_back-up": "folder-archive-open", - "__back-up__": "folder-archive-open", - "back-ups": "folder-archive-open", - ".back-ups": "folder-archive-open", - "_back-ups": "folder-archive-open", - "__back-ups__": "folder-archive-open", - "history": "folder-archive-open", - ".history": "folder-archive-open", - "_history": "folder-archive-open", - "__history__": "folder-archive-open", - "histories": "folder-archive-open", - ".histories": "folder-archive-open", - "_histories": "folder-archive-open", - "__histories__": "folder-archive-open", + "bkp": "folder-backup-open", + ".bkp": "folder-backup-open", + "_bkp": "folder-backup-open", + "__bkp__": "folder-backup-open", + "bkps": "folder-backup-open", + ".bkps": "folder-backup-open", + "_bkps": "folder-backup-open", + "__bkps__": "folder-backup-open", + "bak": "folder-backup-open", + ".bak": "folder-backup-open", + "_bak": "folder-backup-open", + "__bak__": "folder-backup-open", + "baks": "folder-backup-open", + ".baks": "folder-backup-open", + "_baks": "folder-backup-open", + "__baks__": "folder-backup-open", + "backup": "folder-backup-open", + ".backup": "folder-backup-open", + "_backup": "folder-backup-open", + "__backup__": "folder-backup-open", + "backups": "folder-backup-open", + ".backups": "folder-backup-open", + "_backups": "folder-backup-open", + "__backups__": "folder-backup-open", + "back-up": "folder-backup-open", + ".back-up": "folder-backup-open", + "_back-up": "folder-backup-open", + "__back-up__": "folder-backup-open", + "back-ups": "folder-backup-open", + ".back-ups": "folder-backup-open", + "_back-ups": "folder-backup-open", + "__back-ups__": "folder-backup-open", + "history": "folder-backup-open", + ".history": "folder-backup-open", + "_history": "folder-backup-open", + "__history__": "folder-backup-open", + "histories": "folder-backup-open", + ".histories": "folder-backup-open", + "_histories": "folder-backup-open", + "__histories__": "folder-backup-open", "batch": "folder-batch-open", ".batch": "folder-batch-open", "_batch": "folder-batch-open", @@ -4761,6 +4873,14 @@ ".constants": "folder-constant-open", "_constants": "folder-constant-open", "__constants__": "folder-constant-open", + "const": "folder-constant-open", + ".const": "folder-constant-open", + "_const": "folder-constant-open", + "__const__": "folder-constant-open", + "consts": "folder-constant-open", + ".consts": "folder-constant-open", + "_consts": "folder-constant-open", + "__consts__": "folder-constant-open", "container": "folder-container-open", ".container": "folder-container-open", "_container": "folder-container-open", @@ -4949,14 +5069,14 @@ ".hooks": "folder-hook-open", "_hooks": "folder-hook-open", "__hooks__": "folder-hook-open", - "trigger": "folder-hook-open", - ".trigger": "folder-hook-open", - "_trigger": "folder-hook-open", - "__trigger__": "folder-hook-open", - "triggers": "folder-hook-open", - ".triggers": "folder-hook-open", - "_triggers": "folder-hook-open", - "__triggers__": "folder-hook-open", + "trigger": "folder-trigger-open", + ".trigger": "folder-trigger-open", + "_trigger": "folder-trigger-open", + "__trigger__": "folder-trigger-open", + "triggers": "folder-trigger-open", + ".triggers": "folder-trigger-open", + "_triggers": "folder-trigger-open", + "__triggers__": "folder-trigger-open", "job": "folder-job-open", ".job": "folder-job-open", "_job": "folder-job-open", @@ -6131,7 +6251,47 @@ "kql": "folder-kusto-open", ".kql": "folder-kusto-open", "_kql": "folder-kusto-open", - "__kql__": "folder-kusto-open" + "__kql__": "folder-kusto-open", + "policy": "folder-policy-open", + ".policy": "folder-policy-open", + "_policy": "folder-policy-open", + "__policy__": "folder-policy-open", + "policies": "folder-policy-open", + ".policies": "folder-policy-open", + "_policies": "folder-policy-open", + "__policies__": "folder-policy-open", + "attachment": "folder-attachment-open", + ".attachment": "folder-attachment-open", + "_attachment": "folder-attachment-open", + "__attachment__": "folder-attachment-open", + "attachments": "folder-attachment-open", + ".attachments": "folder-attachment-open", + "_attachments": "folder-attachment-open", + "__attachments__": "folder-attachment-open", + "bibliography": "folder-bibliography-open", + ".bibliography": "folder-bibliography-open", + "_bibliography": "folder-bibliography-open", + "__bibliography__": "folder-bibliography-open", + "bibliographies": "folder-bibliography-open", + ".bibliographies": "folder-bibliography-open", + "_bibliographies": "folder-bibliography-open", + "__bibliographies__": "folder-bibliography-open", + "book": "folder-bibliography-open", + ".book": "folder-bibliography-open", + "_book": "folder-bibliography-open", + "__book__": "folder-bibliography-open", + "books": "folder-bibliography-open", + ".books": "folder-bibliography-open", + "_books": "folder-bibliography-open", + "__books__": "folder-bibliography-open", + "link": "folder-link-open", + ".link": "folder-link-open", + "_link": "folder-link-open", + "__link__": "folder-link-open", + "links": "folder-link-open", + ".links": "folder-link-open", + "_links": "folder-link-open", + "__links__": "folder-link-open" }, "rootFolderNames": {}, "rootFolderNamesExpanded": {}, @@ -6316,6 +6476,7 @@ "d.ts": "typescript-def", "d.cts": "typescript-def", "d.mts": "typescript-def", + "d.ets": "typescript-def", "mdoc": "markdoc", "markdoc": "markdoc", "markdoc.md": "markdoc", @@ -6474,6 +6635,9 @@ "ps1xml": "powershell", "psc1": "powershell", "pssc": "powershell", + "excalidraw.json": "excalidraw", + "excalidraw.svg": "excalidraw", + "excalidraw.png": "excalidraw", "gradle": "gradle", "doc": "word", "docx": "word", @@ -6508,8 +6672,9 @@ "ntf": "font", "mrf": "font", "lib": "lib", - "bib": "lib", "a": "lib", + "bib": "bibliography", + "bst": "bibtex-style", "dll": "dll", "ilk": "dll", "so": "dll", @@ -6530,10 +6695,14 @@ "containerfile": "docker", "compose.yaml": "docker", "compose.yml": "docker", + "bbx": "bbx", + "cbx": "cbx", + "lbx": "lbx", "tex": "tex", - "sty": "tex", - "dtx": "tex", - "ltx": "tex", + "sty": "sty", + "cls": "cls", + "ltx": "ltx", + "dtx": "dtx", "pptx": "powerpoint", "ppt": "powerpoint", "pptm": "powerpoint", @@ -7209,6 +7378,8 @@ "epub": "epub", "reg": "regedit", "gnu": "gnuplot", + "smk": "snakemake", + "snakemake": "snakemake", "yaml-tmlanguage": "yaml", "tmlanguage": "xml", "cljx": "clojure", @@ -7275,9 +7446,6 @@ "hintrc": "jsonc", "babelrc": "jsonc", "jmd": "juliamarkdown", - "cls": "tex", - "bbx": "tex", - "cbx": "tex", "ctx": "latex", "mak": "makefile", "mkd": "markdown", @@ -7503,6 +7671,9 @@ "pre-commit": "console", "pre-push": "console", "post-merge": "console", + "excalidraw.json": "excalidraw", + "excalidraw.svg": "excalidraw", + "excalidraw.png": "excalidraw", "gradle.properties": "gradle", "gradlew": "gradle", "gradle-wrapper.properties": "gradle", @@ -7644,6 +7815,8 @@ "compose.ci.yml": "docker", "compose.web.yml": "docker", "compose.worker.yml": "docker", + ".latexmkrc": "latexmk", + "latexmkrc": "latexmk", ".mailmap": "email", ".graphqlrc": "graphql", ".graphqlrc.json": "graphql", @@ -8105,6 +8278,7 @@ ".vars": "tune", ".dev.vars": "tune", "turbo.json": "turborepo", + "turbo.jsonc": "turborepo", ".babelrc": "babel", ".babelrc.json": "babel", ".babelrc.jsonc": "babel", @@ -8873,6 +9047,7 @@ "serverless.js": "serverless", "serverless.ts": "serverless", "supabase.js": "supabase", + "supabase.ts": "supabase", "supabase.py": "supabase", ".ember-cli": "ember", ".ember-cli.js": "ember", @@ -9284,6 +9459,20 @@ "wrangler.json": "wrangler", "wrangler.jsonc": "wrangler", ".clinerules": "cline", + ".packshiprc": "packship", + ".packshiprc.json": "packship", + ".packshiprc.js": "packship", + ".packshiprc.ts": "packship", + "packship.config.js": "packship", + "packship.config.ts": "packship", + "packship.config.mjs": "packship", + "packship.config.mts": "packship", + "packship.config.json": "packship", + "Snakefile": "snakemake", + ".hadolint.yaml": "hadolint", + ".hadolint.yml": "hadolint", + "hadolint.yaml": "hadolint", + "hadolint.yml": "hadolint", ".rhistory": "r", "cname": "http", "sonarqube.analysis.xml": "sonarcloud", @@ -9292,6 +9481,7 @@ "pklproject": "pkl", "pklproject.deps.json": "pkl", ".github/funding.yml": "github-sponsors", + "snakefile": "snakemake", "language-configuration.json": "jsonc", "icon-theme.json": "jsonc", "color-theme.json": "jsonc", @@ -9328,6 +9518,7 @@ "mojo": "mojo", "javascript": "javascript", "typescript": "typescript", + "ets": "typescript", "scala": "scala", "handlebars": "handlebars", "perl": "perl", @@ -9394,13 +9585,14 @@ "reason_lisp": "reason", "sml": "sml", "tex": "tex", - "doctex": "tex", - "latex": "tex", - "latex-expl3": "tex", + "latex": "latex", + "latex-expl3": "latex", + "doctex": "doctex", "apex": "salesforce", "sas": "sas", "dockerfile": "docker", "dockercompose": "docker", + "dockerbake": "docker", "csv": "table", "tsv": "table", "psv": "table", @@ -9427,8 +9619,8 @@ "vue-postcss": "vue", "vue-html": "vue", "lua": "lua", - "bibtex": "lib", - "bibtex-style": "lib", + "bibtex": "bibliography", + "bibtex-style": "bibtex-style", "log": "log", "jupyter": "jupyter", "plaintext": "document", @@ -9539,6 +9731,7 @@ "remix.config.js": "remix_light", "remix.config.ts": "remix_light", "turbo.json": "turborepo_light", + "turbo.jsonc": "turborepo_light", ".autorc": "auto_light", "auto.config.js": "auto_light", "auto.config.ts": "auto_light", diff --git a/options/fileicon/material-icon-svgs.json b/options/fileicon/material-icon-svgs.json index 50bc2d2b8a..cf06555b03 100644 --- a/options/fileicon/material-icon-svgs.json +++ b/options/fileicon/material-icon-svgs.json @@ -50,10 +50,13 @@ "babel": "", "ballerina": "", "bazel": "", + "bbx": "", "beancount": "", "bench-js": "", "bench-jsx": "", "bench-ts": "", + "bibliography": "", + "bibtex-style": "", "bicep": "", "biome": "", "bitbucket": "", @@ -80,6 +83,7 @@ "cake": "", "capacitor": "", "capnp": "", + "cbx": "", "cds": "", "certificate": "", "changelog": "", @@ -88,11 +92,12 @@ "chrome": "", "circleci": "", "circleci_light": "", - "citation": "", + "citation": "", "clangd": "", "cline": "", "clojure": "", "cloudfoundry": "", + "cls.clone": "", "cmake": "", "coala": "", "cobol": "", @@ -122,8 +127,8 @@ "crystal": "", "crystal_light": "", "csharp": "", - "css-map": "", - "css": "", + "css-map": "", + "css": "", "cucumber": "", "cuda": "", "cypress": "", @@ -144,12 +149,14 @@ "django": "", "dll": "", "docker": "", + "doctex.clone": "", "document": "", "dotjs": "", "drawio": "", "drizzle": "", "drone": "", "drone_light": "", + "dtx.clone": "", "duc": "", "dune": "", "edge": "", @@ -163,6 +170,7 @@ "erlang": "", "esbuild": "", "eslint": "", + "excalidraw": "", "exe": "", "fastlane": "", "favicon": "", @@ -187,10 +195,12 @@ "folder-apollo": "", "folder-app-open": "", "folder-app": "", - "folder-archive-open": "", - "folder-archive": "", + "folder-archive-open": "", + "folder-archive": "", "folder-astro-open": "", "folder-astro": "", + "folder-attachment-open": "", + "folder-attachment": "", "folder-audio-open": "", "folder-audio": "", "folder-aurelia-open": "", @@ -199,12 +209,16 @@ "folder-aws": "", "folder-azure-pipelines-open": "", "folder-azure-pipelines": "", + "folder-backup-open": "", + "folder-backup": "", "folder-base-open": "", "folder-base": "", "folder-batch-open": "", "folder-batch": "", "folder-benchmark-open": "", "folder-benchmark": "", + "folder-bibliography-open": "", + "folder-bibliography": "", "folder-bicep-open": "", "folder-bicep": "", "folder-bloc-open": "", @@ -261,8 +275,8 @@ "folder-core": "", "folder-coverage-open": "", "folder-coverage": "", - "folder-css-open": "", - "folder-css": "", + "folder-css-open": "", + "folder-css": "", "folder-custom-open": "", "folder-custom": "", "folder-cypress-open": "", @@ -361,8 +375,8 @@ "folder-helper": "", "folder-home-open": "", "folder-home": "", - "folder-hook-open": "", - "folder-hook": "", + "folder-hook-open": "", + "folder-hook": "", "folder-husky-open": "", "folder-husky": "", "folder-i18n-open": "", @@ -409,6 +423,8 @@ "folder-less": "", "folder-lib-open": "", "folder-lib": "", + "folder-link-open": "", + "folder-link": "", "folder-linux-open": "", "folder-linux": "", "folder-liquibase-open": "", @@ -490,6 +506,8 @@ "folder-plastic": "", "folder-plugin-open": "", "folder-plugin": "", + "folder-policy-open": "", + "folder-policy": "", "folder-powershell-open": "", "folder-powershell": "", "folder-prisma-open": "", @@ -508,8 +526,8 @@ "folder-quasar": "", "folder-queue-open": "", "folder-queue": "", - "folder-react-components-open": "", - "folder-react-components": "", + "folder-react-components-open": "", + "folder-react-components": "", "folder-redux-actions-open.clone": "", "folder-redux-actions.clone": "", "folder-redux-reducer-open": "", @@ -608,6 +626,8 @@ "folder-tools": "", "folder-trash-open": "", "folder-trash": "", + "folder-trigger-open": "", + "folder-trigger": "", "folder-turborepo-open": "", "folder-turborepo": "", "folder-typescript-open": "", @@ -692,6 +712,7 @@ "gulp": "", "h": "", "hack": "", + "hadolint": "", "haml": "", "handlebars": "", "hardhat": "", @@ -751,6 +772,9 @@ "kusto": "", "label": "", "laravel": "", + "latex.clone": "", + "latexmk": "", + "lbx": "", "lefthook": "", "lerna": "", "less": "", @@ -765,6 +789,7 @@ "log": "", "lolcode": "", "lottie": "", + "ltx.clone": "", "lua": "", "luau": "", "lyric": "", @@ -839,6 +864,7 @@ "openapi": "", "openapi_light": "", "otne": "", + "packship": "", "palette": "", "panda": "", "parcel": "", @@ -955,6 +981,7 @@ "slug": "", "smarty": "", "sml": "", + "snakemake": "", "snapcraft": "", "snowpack": "", "snowpack_light": "", @@ -970,6 +997,7 @@ "stitches_light": "", "storybook": "", "stryker": "", + "sty.clone": "", "stylable": "", "stylelint": "", "stylelint_light": "", @@ -1004,7 +1032,7 @@ "test-js": "", "test-jsx": "", "test-ts": "", - "tex": "", + "tex": "", "textlint": "", "tilt": "", "tldraw": "", diff --git a/package-lock.json b/package-lock.json index 72e19719ad..4c5963d0c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,7 @@ "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.99.6", + "webpack": "5.99.8", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, @@ -79,41 +79,41 @@ "@types/swagger-ui-dist": "3.30.5", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@types/toastify-js": "1.12.3", - "@typescript-eslint/eslint-plugin": "8.31.0", - "@typescript-eslint/parser": "8.31.0", + "@types/toastify-js": "1.12.4", + "@typescript-eslint/eslint-plugin": "8.32.0", + "@typescript-eslint/parser": "8.32.0", "@vitejs/plugin-vue": "5.2.3", - "@vitest/eslint-plugin": "1.1.43", + "@vitest/eslint-plugin": "1.1.44", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.3.4", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.10.6", + "eslint-plugin-import-x": "4.11.0", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", "eslint-plugin-regexp": "2.7.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", - "eslint-plugin-vue": "10.0.0", + "eslint-plugin-vue": "10.1.0", "eslint-plugin-vue-scoped-css": "2.9.0", - "eslint-plugin-wc": "3.0.0", - "happy-dom": "17.4.4", + "eslint-plugin-wc": "3.0.1", + "happy-dom": "17.4.6", "markdownlint-cli": "0.44.0", - "material-icon-theme": "5.21.1", + "material-icon-theme": "5.22.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.19.0", + "stylelint": "16.19.1", "stylelint-config-recommended": "16.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", - "stylelint-define-config": "16.18.0", + "stylelint-define-config": "16.19.0", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "3.3.2", - "type-fest": "4.40.0", + "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.1.2", + "vitest": "3.1.3", "vue-tsc": "2.2.10" }, "engines": { @@ -133,13 +133,13 @@ } }, "node_modules/@antfu/install-pkg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.0.0.tgz", - "integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", "license": "MIT", "dependencies": { - "package-manager-detector": "^0.2.8", - "tinyexec": "^0.3.2" + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -165,14 +165,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -185,30 +185,30 @@ "license": "MIT" }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.10" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -218,25 +218,22 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", - "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -555,9 +552,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ "ppc64" ], @@ -571,9 +568,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], @@ -587,9 +584,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], @@ -603,9 +600,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ "x64" ], @@ -619,9 +616,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], @@ -635,9 +632,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ "x64" ], @@ -651,9 +648,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "cpu": [ "arm64" ], @@ -667,9 +664,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], @@ -683,9 +680,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "cpu": [ "arm" ], @@ -699,9 +696,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], @@ -715,9 +712,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ "ia32" ], @@ -731,9 +728,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ "loong64" ], @@ -747,9 +744,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ "mips64el" ], @@ -763,9 +760,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ "ppc64" ], @@ -779,9 +776,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ "riscv64" ], @@ -795,9 +792,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "cpu": [ "s390x" ], @@ -811,9 +808,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "cpu": [ "x64" ], @@ -827,9 +824,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "cpu": [ "arm64" ], @@ -843,9 +840,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], @@ -859,9 +856,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "cpu": [ "arm64" ], @@ -875,9 +872,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], @@ -891,9 +888,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "cpu": [ "x64" ], @@ -907,9 +904,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "cpu": [ "arm64" ], @@ -923,9 +920,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ "ia32" ], @@ -939,9 +936,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ "x64" ], @@ -975,9 +972,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1614,16 +1611,16 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", + "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@playwright/test": { @@ -1709,9 +1706,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz", - "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", + "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", "cpu": [ "arm" ], @@ -1723,9 +1720,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz", - "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", + "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", "cpu": [ "arm64" ], @@ -1737,9 +1734,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz", - "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", + "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", "cpu": [ "arm64" ], @@ -1751,9 +1748,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz", - "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", + "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", "cpu": [ "x64" ], @@ -1765,9 +1762,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz", - "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", + "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", "cpu": [ "arm64" ], @@ -1779,9 +1776,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz", - "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", + "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", "cpu": [ "x64" ], @@ -1793,9 +1790,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz", - "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", + "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", "cpu": [ "arm" ], @@ -1807,9 +1804,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz", - "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", + "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", "cpu": [ "arm" ], @@ -1821,9 +1818,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz", - "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", + "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", "cpu": [ "arm64" ], @@ -1835,9 +1832,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz", - "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", + "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", "cpu": [ "arm64" ], @@ -1849,9 +1846,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz", - "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", + "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", "cpu": [ "loong64" ], @@ -1863,9 +1860,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz", - "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", + "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", "cpu": [ "ppc64" ], @@ -1877,9 +1874,23 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz", - "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", + "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", + "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", "cpu": [ "riscv64" ], @@ -1891,9 +1902,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz", - "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", + "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", "cpu": [ "s390x" ], @@ -1905,9 +1916,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz", - "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", + "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", "cpu": [ "x64" ], @@ -1919,9 +1930,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz", - "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", + "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", "cpu": [ "x64" ], @@ -1933,9 +1944,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz", - "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", + "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", "cpu": [ "arm64" ], @@ -1947,9 +1958,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz", - "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", + "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", "cpu": [ "ia32" ], @@ -1961,9 +1972,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz", - "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", + "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", "cpu": [ "x64" ], @@ -2164,9 +2175,9 @@ } }, "node_modules/@stoplight/spectral-core": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.19.5.tgz", - "integrity": "sha512-i+njdliW7bAHGsHEgDvH0To/9IxiYiBELltkZ7ASVy4i+WXtZ40lQXpeRQRwePrBcSgQl0gcZFuKX10nmSHtbw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-core/-/spectral-core-1.20.0.tgz", + "integrity": "sha512-5hBP81nCC1zn1hJXL/uxPNRKNcB+/pEIHgCjPRpl/w/qy9yC9ver04tw1W0l/PMiv0UeB5dYgozXVQ4j5a6QQQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2251,9 +2262,9 @@ } }, "node_modules/@stoplight/spectral-formatters": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-formatters/-/spectral-formatters-1.4.3.tgz", - "integrity": "sha512-03Nc6nhjMO9aHhJPgBH4zDwMPklKLWEMtvx+PMmzfStCndMjJkf8ki7O/55u3myZ1TwxBzln9z9tXPLSL3KKhw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-formatters/-/spectral-formatters-1.5.0.tgz", + "integrity": "sha512-lR7s41Z00Mf8TdXBBZQ3oi2uR8wqAtR6NO0KA8Ltk4FSpmAy0i6CKUmJG9hZQjanTnGmwpQkT/WP66p1GY3iXA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2276,9 +2287,9 @@ } }, "node_modules/@stoplight/spectral-functions": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.9.4.tgz", - "integrity": "sha512-+dgu7QQ1JIZFsNLhNbQLPA9tniIT3KjOc9ORv0LYSCLvZjkWT2bN7vgmathbXsbmhnmhvl15H9sRqUIqzi+qoQ==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-functions/-/spectral-functions-1.10.1.tgz", + "integrity": "sha512-obu8ZfoHxELOapfGsCJixKZXZcffjg+lSoNuttpmUFuDzVLT3VmH8QkPXfOGOL5Pz80BR35ClNAToDkdnYIURg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2346,9 +2357,9 @@ } }, "node_modules/@stoplight/spectral-ruleset-bundler": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.6.2.tgz", - "integrity": "sha512-Tg7y/0e/6yY4hiebh9YLUGa/fHcgI6RyjfBcRGipYU7QDcJUn2UZYSzeC9hggMwT0UiRzdQlch0aEl7L4VL1GQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-ruleset-bundler/-/spectral-ruleset-bundler-1.6.3.tgz", + "integrity": "sha512-AQFRO6OCKg8SZJUupnr3+OzI1LrMieDTEUHsYgmaRpNiDRPvzImE3bzM1KyQg99q58kTQyZ8kpr7sG8Lp94RRA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2423,9 +2434,9 @@ "license": "Apache-2.0" }, "node_modules/@stoplight/spectral-rulesets": { - "version": "1.21.4", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.21.4.tgz", - "integrity": "sha512-F03Uf+Rb9FnxfjNeIeB0B/dGDJ+NozRkQZtZ/jryoOu+7Qp7rI1e/BkFWEM3y4Fr0zcNEkpS7bjkXnW4frHPcA==", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.22.0.tgz", + "integrity": "sha512-l2EY2jiKKLsvnPfGy+pXC0LeGsbJzcQP5G/AojHgf+cwN//VYxW1Wvv4WKFx/CLmLxc42mJYF2juwWofjWYNIQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2858,13 +2869,6 @@ "@types/ms": "*" } }, - "node_modules/@types/doctrine": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", - "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/dropzone": { "version": "5.7.9", "resolved": "https://registry.npmjs.org/@types/dropzone/-/dropzone-5.7.9.tgz", @@ -2984,12 +2988,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "version": "22.15.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.14.tgz", + "integrity": "sha512-BL1eyu/XWsFGTtDWOYULQEs4KR0qdtYfCxYAUYRoB7JP7h9ETYLgQTww6kH8Sj2C0pFGgrpM0XKv6/kbIzYJ1g==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/normalize-package-data": { @@ -3072,9 +3076,9 @@ "license": "MIT" }, "node_modules/@types/toastify-js": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.3.tgz", - "integrity": "sha512-9RjLlbAHMSaae/KZNHGv19VG4gcLIm3YjvacCXBtfMfYn26h76YP5oxXI8k26q4iKXCB9LNfv18lsoS0JnFPTg==", + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.4.tgz", + "integrity": "sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==", "dev": true, "license": "MIT" }, @@ -3147,21 +3151,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", - "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", + "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.31.0", - "@typescript-eslint/type-utils": "8.31.0", - "@typescript-eslint/utils": "8.31.0", - "@typescript-eslint/visitor-keys": "8.31.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/type-utils": "8.32.0", + "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3177,16 +3181,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.0.tgz", - "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", + "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.31.0", - "@typescript-eslint/types": "8.31.0", - "@typescript-eslint/typescript-estree": "8.31.0", - "@typescript-eslint/visitor-keys": "8.31.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "debug": "^4.3.4" }, "engines": { @@ -3202,14 +3206,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", - "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", + "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.31.0", - "@typescript-eslint/visitor-keys": "8.31.0" + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3220,16 +3224,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", - "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", + "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.31.0", - "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/typescript-estree": "8.32.0", + "@typescript-eslint/utils": "8.32.0", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3244,9 +3248,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.0.tgz", - "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", + "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", "dev": true, "license": "MIT", "engines": { @@ -3258,20 +3262,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", - "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", + "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.31.0", - "@typescript-eslint/visitor-keys": "8.31.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/visitor-keys": "8.32.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3301,16 +3305,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.0.tgz", - "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", + "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.31.0", - "@typescript-eslint/types": "8.31.0", - "@typescript-eslint/typescript-estree": "8.31.0" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.0", + "@typescript-eslint/types": "8.32.0", + "@typescript-eslint/typescript-estree": "8.32.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3325,13 +3329,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.31.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", - "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", + "version": "8.32.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", + "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/types": "8.32.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3350,9 +3354,9 @@ "license": "ISC" }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.0.tgz", - "integrity": "sha512-vIWAU56r2lZAmUsljp6m9+hrTlwNkZH6pqnSPff2WxzofV+jWRSHLmZRUS+g+VE+LlyPByifmGGHpJmhWetatg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz", + "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==", "cpu": [ "arm64" ], @@ -3364,9 +3368,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.0.tgz", - "integrity": "sha512-+bShFLgtdwuNteQbKq3X230754AouNMXSLDZ56EssgDyckDt6Ld7wRaJjZF0pY671HnY2pk9/amO4amAFzfN1A==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz", + "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==", "cpu": [ "x64" ], @@ -3378,9 +3382,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.0.tgz", - "integrity": "sha512-HJjXb3aIptDZQ0saSmk2S4W1pWNVZ2iNpAbNGZOfsUXbi8xwCmHdVjErNS92hRp7djuDLup1OLrzOMtTdw5BmA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz", + "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==", "cpu": [ "x64" ], @@ -3392,9 +3396,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.0.tgz", - "integrity": "sha512-NF3lk7KHulLD97UE+MHjH0mrOjeZG8Hz10h48YcFz2V0rlxBdRSRcMbGer8iH/1mIlLqxtvXJfGLUr4SMj0XZg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz", + "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==", "cpu": [ "arm" ], @@ -3406,9 +3410,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.0.tgz", - "integrity": "sha512-Gn1c/t24irDgU8yYj4vVG6qHplwUM42ti9/zYWgfmFjoXCH6L4Ab9hh6HuO7bfDSvGDRGWQt1IVaBpgbKHdh3Q==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz", + "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==", "cpu": [ "arm" ], @@ -3420,9 +3424,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.0.tgz", - "integrity": "sha512-XRrVXRIUP++qyqAqgiXUpOv0GP3cHx7aA7NrzVFf6Cc8FoYuwtnmT+vctfSo4wRZN71MNU4xq2BEFxI4qvSerg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz", + "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==", "cpu": [ "arm64" ], @@ -3434,9 +3438,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.0.tgz", - "integrity": "sha512-Sligg+vTDAYTXkUtgviPjGEFIh57pkvlfdyRw21i9gkjp/eCNOAi2o5e7qLGTkoYdJHZJs5wVMViPEmAbw2/Tg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz", + "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==", "cpu": [ "arm64" ], @@ -3448,9 +3452,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.0.tgz", - "integrity": "sha512-Apek8/x+7Rg33zUJlQV44Bvq8/t1brfulk0veNJrk9wprF89bCYFMUHF7zQYcpf2u+m1+qs3mYQrBd43fGXhMA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz", + "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==", "cpu": [ "ppc64" ], @@ -3462,9 +3466,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.0.tgz", - "integrity": "sha512-kBale8CFX5clfV9VmI9EwKw2ZACMEx1ecjV92F9SeWTUoxl9d+LGzS6zMSX3kGYqcfJB3NXMwLCTwIDBLG1y4g==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz", + "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==", "cpu": [ "riscv64" ], @@ -3476,9 +3480,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.0.tgz", - "integrity": "sha512-s/Q33xQjeFHSCvGl1sZztFZF6xhv7coMvFz6wa/x/ZlEArjiQoMMwGa/Aieq1Kp/6+S13iU3/IJF0ga6/451ow==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz", + "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==", "cpu": [ "riscv64" ], @@ -3490,9 +3494,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.0.tgz", - "integrity": "sha512-7PuNXAo97ydaxVNrIYJzPipvINJafDpB8pt5CoZHfu8BmqcU6d7kl6/SABTnqNffNkd6Cfhuo70jvGB2P7oJ/Q==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz", + "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==", "cpu": [ "s390x" ], @@ -3504,9 +3508,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.0.tgz", - "integrity": "sha512-fNosEzDMYItA4It+R0tioHwKlEfx/3TkkJdP2x9B5o9R946NDC4ZZj5ZjA+Y4NQD2V/imB3QPAKmeh3vHQGQyA==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz", + "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==", "cpu": [ "x64" ], @@ -3518,9 +3522,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.0.tgz", - "integrity": "sha512-gHIw42dmnVcw7osjNPRybaXhONhggWkkzqiOZzXco1q3OKkn4KsbDylATeemnq3TP+L1BrzSqzl0H9UTJ6ji+w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz", + "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==", "cpu": [ "x64" ], @@ -3532,9 +3536,9 @@ ] }, "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.0.tgz", - "integrity": "sha512-yq7POusv63/yTkNTaNsnXU/SAcBzckHyk1oYrDXqjS1m/goaWAaU9J9HrsovgTHkljxTcDd6PMAsJ5WZVBuGEQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz", + "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==", "cpu": [ "wasm32" ], @@ -3549,9 +3553,9 @@ } }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.0.tgz", - "integrity": "sha512-/IPZPbdri9jglHonwB3F7EpQZvBK3ObH+g4ma/KDrqTEAECwvgE10Unvo0ox3LQFR/iMMAkVY+sGNMrMiIV/QQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz", + "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==", "cpu": [ "arm64" ], @@ -3563,9 +3567,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.0.tgz", - "integrity": "sha512-NGVKbHEdrLuJdpcuGqV5zXO3v8t4CWOs0qeCGjO47RiwwufOi/yYcrtxtCzZAaMPBrffHL7c6tJ1Hxr17cPUGg==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz", + "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==", "cpu": [ "ia32" ], @@ -3577,9 +3581,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.0.tgz", - "integrity": "sha512-Jf14pKofg58DIwcZv4Wt9AyVVe7bSJP8ODz+EP9nG/rho08FQzan0VOJk1g6/BNE1RkoYd+lRTWK+/BgH12qoQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz", + "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==", "cpu": [ "x64" ], @@ -3605,9 +3609,9 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.1.43", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.43.tgz", - "integrity": "sha512-OLoUMO67Yg+kr7E6SjF5+Qvl2f6uNJ7ImQYnXT8WgnPiZE41ZQBsnzn70jehXrhFVadphHs2smk+yl0TFKLV5Q==", + "version": "1.1.44", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.44.tgz", + "integrity": "sha512-m4XeohMT+Dj2RZfxnbiFR+Cv5dEC0H7C6TlxRQT7GK2556solm99kxgzJp/trKrZvanZcOFyw7aABykUTfWyrg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3626,14 +3630,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", - "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.3.tgz", + "integrity": "sha512-7FTQQuuLKmN1Ig/h+h/GO+44Q1IlglPlR2es4ab7Yvfx+Uk5xsv+Ykk+MEt/M2Yn/xGmzaLKxGw2lgy2bwuYqg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.2", - "@vitest/utils": "3.1.2", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3642,13 +3646,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", - "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.3.tgz", + "integrity": "sha512-PJbLjonJK82uCWHjzgBJZuR7zmAOrSvKk1QBxrennDIgtH4uK0TB1PvYmc0XBCigxxtiAVPfWtAdy4lpz8SQGQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.2", + "@vitest/spy": "3.1.3", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3696,9 +3700,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", - "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.3.tgz", + "integrity": "sha512-i6FDiBeJUGLDKADw2Gb01UtUNb12yyXAqC/mmRWuYl+m/U9GS7s8us5ONmGkGpUUo7/iAYzI2ePVfOZTYvUifA==", "dev": true, "license": "MIT", "dependencies": { @@ -3709,13 +3713,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", - "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.3.tgz", + "integrity": "sha512-Tae+ogtlNfFei5DggOsSUvkIaSuVywujMj6HzR97AHK6XK8i3BuVyIifWAm/sE3a15lF5RH9yQIrbXYuo0IFyA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.2", + "@vitest/utils": "3.1.3", "pathe": "^2.0.3" }, "funding": { @@ -3723,13 +3727,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", - "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.3.tgz", + "integrity": "sha512-XVa5OPNTYUsyqG9skuUkFzAeFnEzDp8hQu7kZ0N25B1+6KjGm4hWLtURyBbsIAOekfWQ7Wuz/N/XXzgYO3deWQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.2", + "@vitest/pretty-format": "3.1.3", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3748,9 +3752,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", - "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.3.tgz", + "integrity": "sha512-x6w+ctOEmEXdWaa6TO4ilb7l9DxPR5bwEb6hILKuxfU1NqWT2mpJD9NJN7t3OTfxmVlOMrvtoFJGdgyzZ605lQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3761,13 +3765,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", - "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.3.tgz", + "integrity": "sha512-2Ltrpht4OmHO9+c/nmHtF09HWiyWdworqnHIwjfvDyWjuwKbdkcS9AnhsDn+8E2RM4x++foD1/tNuLPVvWG1Rg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.2", + "@vitest/pretty-format": "3.1.3", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -3776,30 +3780,30 @@ } }, "node_modules/@volar/language-core": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.12.tgz", - "integrity": "sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA==", + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.13.tgz", + "integrity": "sha512-MnQJ7eKchJx5Oz+YdbqyFUk8BN6jasdJv31n/7r6/WwlOOv7qzvot6B66887l2ST3bUW4Mewml54euzpJWA6bg==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "2.4.12" + "@volar/source-map": "2.4.13" } }, "node_modules/@volar/source-map": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.12.tgz", - "integrity": "sha512-bUFIKvn2U0AWojOaqf63ER0N/iHIBYZPpNGogfLPQ68F5Eet6FnLlyho7BS0y2HJ1jFhSif7AcuTx1TqsCzRzw==", + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.13.tgz", + "integrity": "sha512-l/EBcc2FkvHgz2ZxV+OZK3kMSroMr7nN3sZLF2/f6kWW66q8+tEL4giiYyFjt0BcubqJhBt6soYIrAPhg/Yr+Q==", "dev": true, "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "2.4.12", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.12.tgz", - "integrity": "sha512-HJB73OTJDgPc80K30wxi3if4fSsZZAOScbj2fcicMuOPoOkcf9NNAINb33o+DzhBdF9xTKC1gnPmIRDous5S0g==", + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.13.tgz", + "integrity": "sha512-Ukz4xv84swJPupZeoFsQoeJEOm7U9pqsEnaGGgt5ni3SCTa22m8oJP5Nng3Wed7Uw5RBELdLxxORX8YhJPyOgQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "2.4.12", + "@volar/language-core": "2.4.13", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } @@ -4622,9 +4626,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "funding": [ { "type": "opencollective", @@ -4641,10 +4645,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -4724,14 +4728,14 @@ } }, "node_modules/cacheable": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.10.tgz", - "integrity": "sha512-0ZnbicB/N2R6uziva8l6O6BieBklArWyiGx4GkwAhLKhSHyQtRfM9T1nx7HHuHDKkYB/efJQhz3QJ6x/YqoZzA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.9.0.tgz", + "integrity": "sha512-8D5htMCxPDUULux9gFzv30f04Xo3wCnik0oOxKoRTPIBoqA7HtOcJ87uBhQTs3jCfZZTrUBGsYIZOgE0ZRgMAg==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.8.1", - "keyv": "^5.3.2" + "hookified": "^1.8.2", + "keyv": "^5.3.3" } }, "node_modules/cacheable/node_modules/keyv": { @@ -4763,9 +4767,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001705", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001705.tgz", - "integrity": "sha512-S0uyMMiYvA7CxNgomYBwwwPUnWzFD83f3B1ce5jHUfHTH//QL6hHsreI8RVC5606R4ssqravelYO5TU6t8sEyg==", + "version": "1.0.30001717", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", + "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", "funding": [ { "type": "opencollective", @@ -5082,9 +5086,9 @@ } }, "node_modules/codemirror": { - "version": "5.65.18", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.18.tgz", - "integrity": "sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==", + "version": "5.65.19", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.19.tgz", + "integrity": "sha512-+aFkvqhaAVr1gferNMuN8vkTSrWIFvzlMV9I2KBLCWS2WpZ2+UAkZjlMZmEuT+gcXTi6RrGQCkWq1/bDtGqhIA==", "license": "MIT" }, "node_modules/codemirror-spell-checker": { @@ -5160,15 +5164,15 @@ "license": "MIT" }, "node_modules/confbox": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.1.tgz", - "integrity": "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", - "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", + "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5390,9 +5394,9 @@ "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.31.1.tgz", - "integrity": "sha512-Hx5Mtb1+hnmAKaZZ/7zL1Y5HTFYOjdDswZy/jD+1WINRU8KVi1B7+vlHdsTwY+VCFucTreoyu1RDzQJ9u0d2Hw==", + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz", + "integrity": "sha512-5JHBC9n75kz5851jeklCPmZWcg3hUe6sjqJvyk3+hVqFaKcHwHgxsjeN1yLmggoUc6STbtm9/NQyabQehfjvWQ==", "license": "MIT", "engines": { "node": ">=0.10" @@ -6154,9 +6158,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", - "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", + "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -6207,9 +6211,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.119", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.119.tgz", - "integrity": "sha512-Ku4NMzUjz3e3Vweh7PhApPrZSS4fyiCIbcIrG9eKrriYVLmbMepETR/v6SU7xPm98QTqMSYiCwfO89QNjXLkbQ==", + "version": "1.5.150", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.150.tgz", + "integrity": "sha512-rOOkP2ZUMx1yL4fCxXQKDHQ8ZXwisb2OycOQVKHgvB3ZI4CvehOd4y2tfnnLDieJ3Zs1RL1Dlp3cMkyIn7nnXA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -6297,15 +6301,15 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "license": "MIT" }, "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -6315,31 +6319,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, "node_modules/esbuild-loader": { @@ -6452,9 +6456,9 @@ } }, "node_modules/eslint-compat-utils": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz", - "integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.5.tgz", + "integrity": "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6468,9 +6472,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", - "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.3.tgz", + "integrity": "sha512-vDo4d9yQE+cS2tdIT4J02H/16veRvkHgiLDRpej+WL67oCfbOb97itZXn8wMPJ/GsiEBVjrjs//AVNw2Cp1EcA==", "dev": true, "license": "MIT", "bin": { @@ -6713,17 +6717,15 @@ } }, "node_modules/eslint-plugin-import-x": { - "version": "4.10.6", - "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.10.6.tgz", - "integrity": "sha512-sWIaoezWK7kuPA7u29ULsO8WzlYYC8uivaipsazyHiZDykjNsuPtwRsYZIK2luqc5wppwXOop8iFdW7xffo/Xw==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.11.0.tgz", + "integrity": "sha512-NAaYY49342gj09QGvwnFFl5KcD5aLzjAz97Lo+upnN8MzjEGSIlmL5sxCYGqtIeMjw8fSRDFZIp2xjRLT+yl4Q==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.4", - "@types/doctrine": "^0.0.9", - "@typescript-eslint/utils": "^8.30.1", + "@typescript-eslint/utils": "^8.31.0", + "comment-parser": "^1.4.1", "debug": "^4.4.0", - "doctrine": "^3.0.0", "eslint-import-resolver-node": "^0.3.9", "get-tsconfig": "^4.10.0", "is-glob": "^4.0.3", @@ -6731,7 +6733,7 @@ "semver": "^7.7.1", "stable-hash": "^0.0.5", "tslib": "^2.8.1", - "unrs-resolver": "^1.6.0" + "unrs-resolver": "^1.7.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6743,19 +6745,6 @@ "eslint": "^8.57.0 || ^9.0.0" } }, - "node_modules/eslint-plugin-import-x/node_modules/@pkgr/core": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", - "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, "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", @@ -6923,14 +6912,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", - "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.0.tgz", + "integrity": "sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "synckit": "^0.11.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -6941,7 +6930,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -7060,9 +7049,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.0.0.tgz", - "integrity": "sha512-XKckedtajqwmaX6u1VnECmZ6xJt+YvlmMzBPZd+/sI3ub2lpYZyFnsyWo7c3nMOQKJQudeyk1lw/JxdgeKT64w==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.1.0.tgz", + "integrity": "sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA==", "dev": true, "license": "MIT", "dependencies": { @@ -7109,9 +7098,9 @@ } }, "node_modules/eslint-plugin-wc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-3.0.0.tgz", - "integrity": "sha512-TVbwa4ytaKoUGCCAG14+FPDF3v4nGoPcEOd4kjN2MLZ2NTo1lHUs7HsVaiwC0ReKQVivJ7+v6d7u0GYu1c6GJQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-3.0.1.tgz", + "integrity": "sha512-0p1wkSlA2Ue3FA4qW+5LZ+15sy0p1nUyVl1eyBMLq4rtN1LtE9IdI49BXNWMz8N8bM/y7Ulx8SWGAni5f8XO5g==", "dev": true, "license": "MIT", "dependencies": { @@ -7346,9 +7335,9 @@ } }, "node_modules/exsolve": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", - "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", + "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", "license": "MIT" }, "node_modules/fast-deep-equal": { @@ -7857,9 +7846,9 @@ } }, "node_modules/happy-dom": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.4.4.tgz", - "integrity": "sha512-/Pb0ctk3HTZ5xEL3BZ0hK1AqDSAUuRQitOmROPHhfUYEWpmTImwfD8vFDGADmMAX0JYgbcgxWoLFKtsWhcpuVA==", + "version": "17.4.6", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.4.6.tgz", + "integrity": "sha512-OEV1hDe9i2rFr66+WZNiwy1S8rAJy6bRXmXql68YJDjdfHBRbN76om+qVh68vQACf6y5Bcr90e/oK53RQxsDdg==", "dev": true, "license": "MIT", "dependencies": { @@ -7907,9 +7896,9 @@ } }, "node_modules/hookified": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.8.2.tgz", - "integrity": "sha512-5nZbBNP44sFCDjSoB//0N7m508APCgbQ4mGGo1KJGBYyCKNHfry1Pvd0JVHZIxjdnqn8nFRBAN/eFB6Rk/4w5w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.9.0.tgz", + "integrity": "sha512-2yEEGqphImtKIe1NXWEhu6yD3hlFR4Mxk4Mtp3XEyScpSt4pQ4ymmXA1zzxZpj99QkFK+nN0nzjeb2+RUi/6CQ==", "dev": true, "license": "MIT" }, @@ -9132,9 +9121,9 @@ } }, "node_modules/markdownlint-cli/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true, "license": "MIT", "engines": { @@ -9177,9 +9166,9 @@ } }, "node_modules/material-icon-theme": { - "version": "5.21.1", - "resolved": "https://registry.npmjs.org/material-icon-theme/-/material-icon-theme-5.21.1.tgz", - "integrity": "sha512-7gWH20MC3rvf1fBXwTpeMEAJqfuhXaciY2IN/hb74hR0XU/TnicoggblFoWtZvt0HrCzxyqX5P+u60BHWXEEHw==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/material-icon-theme/-/material-icon-theme-5.22.0.tgz", + "integrity": "sha512-hJyUSrb1ak8pJHcgw83ItXyLcj2dRH5lb3H1QWekkqTEQ4xPqUBSHWnBLioT5/sf5GFrut83p9FenC0KoYnjZw==", "dev": true, "license": "MIT", "dependencies": { @@ -9277,9 +9266,9 @@ } }, "node_modules/mermaid/node_modules/marked": { - "version": "15.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz", - "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", + "version": "15.0.11", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.11.tgz", + "integrity": "sha512-1BEXAU2euRCG3xwgLVT1y0xbJEld1XOrmRJpUwRCcy7rxhSCwMrmEu9LXoPhHSCJG41V7YcQ2mjKRr5BA3ITIA==", "license": "MIT", "bin": { "marked": "bin/marked.js" @@ -10001,9 +9990,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", - "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -10019,9 +10008,9 @@ } }, "node_modules/napi-postinstall": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.1.6.tgz", - "integrity": "sha512-w1bClprmjwpybo+7M1Rd0N4QK5Ein8kH/1CQ0Wv8Q9vrLbDMakxc4rZpv8zYc8RVErUELJlFhM8UzOF3IqlYKw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.3.tgz", + "integrity": "sha512-Mi7JISo/4Ij2tDZ2xBE2WH+/KvVlkhA6juEjpEeRAVPNCpN3nxJo/5FhDNKgBcdmcmhaH6JjgST4xY/23ZYK0w==", "dev": true, "license": "MIT", "bin": { @@ -10324,13 +10313,10 @@ "license": "BlueOak-1.0.0" }, "node_modules/package-manager-detector": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", - "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", - "license": "MIT", - "dependencies": { - "quansync": "^0.2.7" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "license": "MIT" }, "node_modules/parent-module": { "version": "1.0.1", @@ -10510,9 +10496,9 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "license": "MIT", "engines": { "node": ">= 6" @@ -10741,41 +10727,6 @@ "postcss": "^8.4.21" } }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, "node_modules/postcss-loader": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", @@ -11168,9 +11119,9 @@ } }, "node_modules/quansync": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.8.tgz", - "integrity": "sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", + "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", "funding": [ { "type": "individual", @@ -11368,12 +11319,6 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, "node_modules/regexp-ast-analysis": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz", @@ -11669,9 +11614,9 @@ "license": "ISC" }, "node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -11724,18 +11669,18 @@ } }, "node_modules/seroval": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.2.1.tgz", - "integrity": "sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.0.tgz", + "integrity": "sha512-4tYQDy3HVM0JjJ1CfDK3K8FhBKIDDri27oc2AyabuuHfQw6/yTDPp2Abt1h2cNtf1R0T+7AQYAzPhUgqXztaXw==", "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/seroval-plugins": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.2.1.tgz", - "integrity": "sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.3.0.tgz", + "integrity": "sha512-FFu/UE3uA8L1vj0CXXZo2Nlh10MtYoOs0G//ptwlQMjfPFSeIVYUNy0zewfV8iM0CrOebAfHEG6J3xA9c+lsaQ==", "license": "MIT", "engines": { "node": ">=10" @@ -11838,9 +11783,9 @@ } }, "node_modules/smol-toml": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.1.tgz", - "integrity": "sha512-tEYNll18pPKHroYSmLLrksq233j021G0giwW7P3D24jC54pQ5W5BXMsQ/Mvw1OJCmEYDgY+lrzT+3nNUtoNfXQ==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.4.tgz", + "integrity": "sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -11851,9 +11796,9 @@ } }, "node_modules/solid-js": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.5.tgz", - "integrity": "sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw==", + "version": "1.9.6", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.6.tgz", + "integrity": "sha512-PoasAJvLk60hRtOTe9ulvALOdLjjqxuxcGZRolBQqxOnXrBXHGzqMT4ijNhGsDAYdOgEa8ZYaAE94PSldrFSkA==", "license": "MIT", "dependencies": { "csstype": "^3.1.0", @@ -12161,9 +12106,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.19.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.19.0.tgz", - "integrity": "sha512-BJzc5mo/ez0H/ZSl3UbxGdkK/s0kFGsF5/k6IGu4z8wJ1qp49WrOS9RxswvcN6HMirt0g/iiJqOwLHTbWv49IQ==", + "version": "16.19.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.19.1.tgz", + "integrity": "sha512-C1SlPZNMKl+d/C867ZdCRthrS+6KuZ3AoGW113RZCOL0M8xOGpgx7G70wq7lFvqvm4dcfdGFVLB/mNaLFChRKw==", "dev": true, "funding": [ { @@ -12273,9 +12218,9 @@ } }, "node_modules/stylelint-define-config": { - "version": "16.18.0", - "resolved": "https://registry.npmjs.org/stylelint-define-config/-/stylelint-define-config-16.18.0.tgz", - "integrity": "sha512-oTwldka07ODNQFcjPFsGSCqBEZPCg5iD85y8gBqXB7Uyv52WNKel+XePzvyaqk6nKEVNxUEbLPqUMx8AnlPY1A==", + "version": "16.19.0", + "resolved": "https://registry.npmjs.org/stylelint-define-config/-/stylelint-define-config-16.19.0.tgz", + "integrity": "sha512-J+VluCron5JwUS/sjtTwzMjpvjqvTe5Rs0SB4mjZDTonPFINEhS9/r0yIA9olfjdf9enV8H/oLMm22SF5yykig==", "dev": true, "license": "MIT", "dependencies": { @@ -12362,31 +12307,31 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.8.tgz", - "integrity": "sha512-FGXHpfmI4XyzbLd3HQ8cbUcsFGohJpZtmQRHr8z8FxxtCe2PcpgIlVLwIgunqjvRmXypBETvwhV4ptJizA+Y1Q==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.0.tgz", + "integrity": "sha512-Et/ex6smi3wOOB+n5mek+Grf7P2AxZR5ueqRUvAAn4qkyatXi3cUC1cuQXVkX0VlzBVsN4BkWJFmY/fYiRTdww==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.8" + "flat-cache": "^6.1.9" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.8", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.8.tgz", - "integrity": "sha512-R6MaD3nrJAtO7C3QOuS79ficm2pEAy++TgEUD8ii1LVlbcgZ9DtASLkt9B+RZSFCzm7QHDMlXPsqqB6W2Pfr1Q==", + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.9.tgz", + "integrity": "sha512-DUqiKkTlAfhtl7g78IuwqYM+YqvT+as0mY+EVk6mfimy19U79pJCzDZQsnqk3Ou/T6hFXWLGbwbADzD/c8Tydg==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^1.8.9", + "cacheable": "^1.9.0", "flatted": "^3.3.3", - "hookified": "^1.8.1" + "hookified": "^1.8.2" } }, "node_modules/stylelint/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true, "license": "MIT", "engines": { @@ -12702,20 +12647,20 @@ } }, "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz", + "integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.3", + "tslib": "^2.8.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/table": { @@ -12772,6 +12717,41 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -12890,9 +12870,9 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", "license": "MIT" }, "node_modules/tinyglobby": { @@ -13010,9 +12990,9 @@ "license": "MIT" }, "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { @@ -13084,9 +13064,9 @@ } }, "node_modules/type-fest": { - "version": "4.40.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.0.tgz", - "integrity": "sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -13123,9 +13103,9 @@ "license": "MIT" }, "node_modules/ufo": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", - "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", "license": "MIT" }, "node_modules/uint8-to-base64": { @@ -13135,9 +13115,9 @@ "license": "ISC" }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, "node_modules/universalify": { @@ -13151,36 +13131,36 @@ } }, "node_modules/unrs-resolver": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.0.tgz", - "integrity": "sha512-b76tVoT9KPniDY1GoYghDUQX20gjzXm/TONfHfgayLaiuo+oGyT9CsQkGCEJs+1/uryVBEOGOt3yYWDXbJhL7g==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz", + "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.1.6" + "napi-postinstall": "^0.2.2" }, "funding": { "url": "https://github.com/sponsors/JounQin" }, "optionalDependencies": { - "@unrs/resolver-binding-darwin-arm64": "1.7.0", - "@unrs/resolver-binding-darwin-x64": "1.7.0", - "@unrs/resolver-binding-freebsd-x64": "1.7.0", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.0", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.0", - "@unrs/resolver-binding-linux-arm64-gnu": "1.7.0", - "@unrs/resolver-binding-linux-arm64-musl": "1.7.0", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.0", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.0", - "@unrs/resolver-binding-linux-riscv64-musl": "1.7.0", - "@unrs/resolver-binding-linux-s390x-gnu": "1.7.0", - "@unrs/resolver-binding-linux-x64-gnu": "1.7.0", - "@unrs/resolver-binding-linux-x64-musl": "1.7.0", - "@unrs/resolver-binding-wasm32-wasi": "1.7.0", - "@unrs/resolver-binding-win32-arm64-msvc": "1.7.0", - "@unrs/resolver-binding-win32-ia32-msvc": "1.7.0", - "@unrs/resolver-binding-win32-x64-msvc": "1.7.0" + "@unrs/resolver-binding-darwin-arm64": "1.7.2", + "@unrs/resolver-binding-darwin-x64": "1.7.2", + "@unrs/resolver-binding-freebsd-x64": "1.7.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.7.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.7.2", + "@unrs/resolver-binding-linux-x64-musl": "1.7.2", + "@unrs/resolver-binding-wasm32-wasi": "1.7.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.7.2" } }, "node_modules/update-browserslist-db": { @@ -13300,15 +13280,18 @@ "license": "MIT" }, "node_modules/vite": { - "version": "6.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.6.tgz", - "integrity": "sha512-9xpjNl3kR4rVDZgPNdTL0/c6ao4km69a/2ihNQbcANz8RuCOK3hQBmLSJf3bRKVQjVMda+YvizNE8AwvogcPbw==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -13372,15 +13355,15 @@ } }, "node_modules/vite-node": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", - "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.3.tgz", + "integrity": "sha512-uHV4plJ2IxCl4u1up1FQRrqclylKAogbtBfOTwcuJ28xFi+89PZ57BRh+naIRvH70HPwxy5QHYzg1OrEaC7AbA==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", + "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0" }, @@ -13402,12 +13385,27 @@ "license": "BSD-2-Clause" }, "node_modules/vite/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true, "license": "MIT" }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/vite/node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -13423,14 +13421,27 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vite/node_modules/rollup": { - "version": "4.35.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz", - "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", + "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -13440,42 +13451,43 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.35.0", - "@rollup/rollup-android-arm64": "4.35.0", - "@rollup/rollup-darwin-arm64": "4.35.0", - "@rollup/rollup-darwin-x64": "4.35.0", - "@rollup/rollup-freebsd-arm64": "4.35.0", - "@rollup/rollup-freebsd-x64": "4.35.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", - "@rollup/rollup-linux-arm-musleabihf": "4.35.0", - "@rollup/rollup-linux-arm64-gnu": "4.35.0", - "@rollup/rollup-linux-arm64-musl": "4.35.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", - "@rollup/rollup-linux-riscv64-gnu": "4.35.0", - "@rollup/rollup-linux-s390x-gnu": "4.35.0", - "@rollup/rollup-linux-x64-gnu": "4.35.0", - "@rollup/rollup-linux-x64-musl": "4.35.0", - "@rollup/rollup-win32-arm64-msvc": "4.35.0", - "@rollup/rollup-win32-ia32-msvc": "4.35.0", - "@rollup/rollup-win32-x64-msvc": "4.35.0", + "@rollup/rollup-android-arm-eabi": "4.40.2", + "@rollup/rollup-android-arm64": "4.40.2", + "@rollup/rollup-darwin-arm64": "4.40.2", + "@rollup/rollup-darwin-x64": "4.40.2", + "@rollup/rollup-freebsd-arm64": "4.40.2", + "@rollup/rollup-freebsd-x64": "4.40.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", + "@rollup/rollup-linux-arm-musleabihf": "4.40.2", + "@rollup/rollup-linux-arm64-gnu": "4.40.2", + "@rollup/rollup-linux-arm64-musl": "4.40.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-musl": "4.40.2", + "@rollup/rollup-linux-s390x-gnu": "4.40.2", + "@rollup/rollup-linux-x64-gnu": "4.40.2", + "@rollup/rollup-linux-x64-musl": "4.40.2", + "@rollup/rollup-win32-arm64-msvc": "4.40.2", + "@rollup/rollup-win32-ia32-msvc": "4.40.2", + "@rollup/rollup-win32-x64-msvc": "4.40.2", "fsevents": "~2.3.2" } }, "node_modules/vitest": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", - "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.3.tgz", + "integrity": "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.2", - "@vitest/mocker": "3.1.2", - "@vitest/pretty-format": "^3.1.2", - "@vitest/runner": "3.1.2", - "@vitest/snapshot": "3.1.2", - "@vitest/spy": "3.1.2", - "@vitest/utils": "3.1.2", + "@vitest/expect": "3.1.3", + "@vitest/mocker": "3.1.3", + "@vitest/pretty-format": "^3.1.3", + "@vitest/runner": "3.1.3", + "@vitest/snapshot": "3.1.3", + "@vitest/spy": "3.1.3", + "@vitest/utils": "3.1.3", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.2.1", @@ -13488,7 +13500,7 @@ "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.2", + "vite-node": "3.1.3", "why-is-node-running": "^2.3.0" }, "bin": { @@ -13504,8 +13516,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.2", - "@vitest/ui": "3.1.2", + "@vitest/browser": "3.1.3", + "@vitest/ui": "3.1.3", "happy-dom": "*", "jsdom": "*" }, @@ -13543,6 +13555,13 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -13633,9 +13652,9 @@ } }, "node_modules/vue-eslint-parser": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.1.tgz", - "integrity": "sha512-bh2Z/Au5slro9QJ3neFYLanZtb1jH+W2bKqGHXAoYD4vZgNG3KeotL7JpPv5xzY4UXUXJl7TrIsnzECH63kd3Q==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.1.3.tgz", + "integrity": "sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==", "dev": true, "license": "MIT", "peer": true, @@ -13739,13 +13758,14 @@ } }, "node_modules/webpack": { - "version": "5.99.6", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.6.tgz", - "integrity": "sha512-TJOLrJ6oeccsGWPl7ujCYuc0pIq2cNsuD6GZDma8i5o5Npvcco/z+NKvZSFsP0/x6SShVb0+X2JK/JHUjKY9dQ==", + "version": "5.99.8", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.8.tgz", + "integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", @@ -13762,7 +13782,7 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", @@ -13860,9 +13880,9 @@ } }, "node_modules/webpack/node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "license": "MIT" }, "node_modules/webpack/node_modules/eslint-scope": { @@ -14129,9 +14149,9 @@ } }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index 0d15ecf39d..0202b92ff4 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.99.6", + "webpack": "5.99.8", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.0" }, @@ -78,41 +78,41 @@ "@types/swagger-ui-dist": "3.30.5", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@types/toastify-js": "1.12.3", - "@typescript-eslint/eslint-plugin": "8.31.0", - "@typescript-eslint/parser": "8.31.0", + "@types/toastify-js": "1.12.4", + "@typescript-eslint/eslint-plugin": "8.32.0", + "@typescript-eslint/parser": "8.32.0", "@vitejs/plugin-vue": "5.2.3", - "@vitest/eslint-plugin": "1.1.43", + "@vitest/eslint-plugin": "1.1.44", "eslint": "8.57.0", "eslint-import-resolver-typescript": "4.3.4", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-github": "5.0.2", - "eslint-plugin-import-x": "4.10.6", + "eslint-plugin-import-x": "4.11.0", "eslint-plugin-no-jquery": "3.1.1", "eslint-plugin-no-use-extend-native": "0.5.0", "eslint-plugin-playwright": "2.2.0", "eslint-plugin-regexp": "2.7.0", "eslint-plugin-sonarjs": "3.0.2", "eslint-plugin-unicorn": "56.0.1", - "eslint-plugin-vue": "10.0.0", + "eslint-plugin-vue": "10.1.0", "eslint-plugin-vue-scoped-css": "2.9.0", - "eslint-plugin-wc": "3.0.0", - "happy-dom": "17.4.4", + "eslint-plugin-wc": "3.0.1", + "happy-dom": "17.4.6", "markdownlint-cli": "0.44.0", - "material-icon-theme": "5.21.1", + "material-icon-theme": "5.22.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", - "stylelint": "16.19.0", + "stylelint": "16.19.1", "stylelint-config-recommended": "16.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", - "stylelint-define-config": "16.18.0", + "stylelint-define-config": "16.19.0", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "3.3.2", - "type-fest": "4.40.0", + "type-fest": "4.41.0", "updates": "16.4.2", "vite-string-plugin": "1.4.4", - "vitest": "3.1.2", + "vitest": "3.1.3", "vue-tsc": "2.2.10" }, "browserslist": [ diff --git a/poetry.lock b/poetry.lock index b532bf0a3a..7c3f690175 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "click" @@ -390,27 +390,27 @@ telegram = ["requests"] [[package]] name = "typing-extensions" -version = "4.13.1" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" groups = ["dev"] markers = "python_version == \"3.10\"" files = [ - {file = "typing_extensions-4.13.1-py3-none-any.whl", hash = "sha256:4b6cf02909eb5495cfbc3f6e8fd49217e6cc7944e145cdda8caa3734777f9e69"}, - {file = "typing_extensions-4.13.1.tar.gz", hash = "sha256:98795af00fb9640edec5b8e31fc647597b4691f099ad75f469a2616be1a76dff"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [[package]] name = "yamllint" -version = "1.37.0" +version = "1.37.1" description = "A linter for YAML files." optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "yamllint-1.37.0-py3-none-any.whl", hash = "sha256:c03ab4e79ab4af964c8eb16ac9746880fc76a3bb0ffb14925b9a55220ae7dda0"}, - {file = "yamllint-1.37.0.tar.gz", hash = "sha256:ead81921d4d87216b2528b7a055664708f9fb8267beb0c427cb706ac6ab93580"}, + {file = "yamllint-1.37.1-py3-none-any.whl", hash = "sha256:364f0d79e81409f591e323725e6a9f4504c8699ddf2d7263d8d2b539cd66a583"}, + {file = "yamllint-1.37.1.tar.gz", hash = "sha256:81f7c0c5559becc8049470d86046b36e96113637bcbe4753ecef06977c00245d"}, ] [package.dependencies] @@ -423,4 +423,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"] [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "d8ed1d7f88ff4be57be2c599b9d906dee25d0f6f6e46fdc9051c892c4e812a1c" +content-hash = "ec65cbc253ccb822e50bb7bdb9a3185a5ab781024175a4d5a339055a06207af6" diff --git a/pyproject.toml b/pyproject.toml index 4eed5f0e74..439b9a6fbd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ python = "^3.10" [tool.poetry.group.dev.dependencies] djlint = "1.36.4" -yamllint = "1.37.0" +yamllint = "1.37.1" [tool.djlint] profile="golang" From 020e774b915512815637aac743ddbe595c5eede5 Mon Sep 17 00:00:00 2001 From: Tobias Balle-Petersen Date: Wed, 7 May 2025 20:00:53 +0200 Subject: [PATCH 07/32] feat: add label 'state' to metric 'gitea_users' (#34326) This PR adds the label _state_ to the metric _gitea_users_. With the change, _gitea_users_ would be reported like this: ``` ... # HELP gitea_users Number of Users # TYPE gitea_users gauge gitea_users{state="active"} 20 gitea_users{state="inactive"} 10 ... ``` The metrics above would be from a Gitea instance with 30 user accounts. 20 of the accounts are active and 10 of the accounts are not active. Resolve #34325 --- models/activities/statistic.go | 18 ++++++++++++++++-- models/user/user.go | 5 +++++ modules/metrics/collector.go | 11 +++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/models/activities/statistic.go b/models/activities/statistic.go index ff81ad78a1..983a124550 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -17,13 +17,15 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" ) // Statistic contains the database statistics type Statistic struct { Counter struct { - User, Org, PublicKey, + UsersActive, UsersNotActive, + Org, PublicKey, Repo, Watch, Star, Access, Issue, IssueClosed, IssueOpen, Comment, Oauth, Follow, @@ -53,7 +55,19 @@ type IssueByRepositoryCount struct { // GetStatistic returns the database statistics func GetStatistic(ctx context.Context) (stats Statistic) { e := db.GetEngine(ctx) - stats.Counter.User = user_model.CountUsers(ctx, nil) + + // Number of active users + usersActiveOpts := user_model.CountUserFilter{ + IsActive: optional.Some(true), + } + stats.Counter.UsersActive = user_model.CountUsers(ctx, &usersActiveOpts) + + // Number of inactive users + usersNotActiveOpts := user_model.CountUserFilter{ + IsActive: optional.Some(false), + } + stats.Counter.UsersNotActive = user_model.CountUsers(ctx, &usersNotActiveOpts) + stats.Counter.Org, _ = db.Count[organization.Organization](ctx, organization.FindOrgOptions{IncludePrivate: true}) stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey)) stats.Counter.Repo, _ = repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{}) diff --git a/models/user/user.go b/models/user/user.go index 100f924cc6..fd420f79c7 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -828,6 +828,7 @@ func IsLastAdminUser(ctx context.Context, user *User) bool { type CountUserFilter struct { LastLoginSince *int64 IsAdmin optional.Option[bool] + IsActive optional.Option[bool] } // CountUsers returns number of users. @@ -848,6 +849,10 @@ func countUsers(ctx context.Context, opts *CountUserFilter) int64 { if opts.IsAdmin.Has() { cond = cond.And(builder.Eq{"is_admin": opts.IsAdmin.Value()}) } + + if opts.IsActive.Has() { + cond = cond.And(builder.Eq{"is_active": opts.IsActive.Value()}) + } } count, err := sess.Where(cond).Count(new(User)) diff --git a/modules/metrics/collector.go b/modules/metrics/collector.go index 230260ff94..4d2ec287a9 100755 --- a/modules/metrics/collector.go +++ b/modules/metrics/collector.go @@ -184,7 +184,7 @@ func NewCollector() Collector { Users: prometheus.NewDesc( namespace+"users", "Number of Users", - nil, nil, + []string{"state"}, nil, ), Watches: prometheus.NewDesc( namespace+"watches", @@ -373,7 +373,14 @@ func (c Collector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( c.Users, prometheus.GaugeValue, - float64(stats.Counter.User), + float64(stats.Counter.UsersActive), + "active", // state label + ) + ch <- prometheus.MustNewConstMetric( + c.Users, + prometheus.GaugeValue, + float64(stats.Counter.UsersNotActive), + "inactive", // state label ) ch <- prometheus.MustNewConstMetric( c.Watches, From bbfc21e74f69a9b1ac83271923210c731edd2873 Mon Sep 17 00:00:00 2001 From: Kerwin Bryant Date: Thu, 8 May 2025 05:33:30 +0800 Subject: [PATCH 08/32] Fix "The sidebar of the repository file list does not have a fixed height #34298" (#34321) There is a known issue where scrolling to the bottom of the page is affected by unknown elements in the footer area: https://github.com/go-gitea/gitea/blob/24145f811069295b9727f25469f1dd3a7c2c5dd7/templates/base/footer.tmpl#L11-L18 ![after](https://github.com/user-attachments/assets/4cdbce32-d22e-4907-a78b-c8e301017fac) --- templates/repo/view.tmpl | 2 +- web_src/css/repo/home.css | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/templates/repo/view.tmpl b/templates/repo/view.tmpl index c3d562003d..85d09d03a1 100644 --- a/templates/repo/view.tmpl +++ b/templates/repo/view.tmpl @@ -17,7 +17,7 @@ {{template "repo/code/recently_pushed_new_branches" .}}
-
+
{{template "repo/view_file_tree" .}}
diff --git a/web_src/css/repo/home.css b/web_src/css/repo/home.css index 69c454d611..61b0a1f962 100644 --- a/web_src/css/repo/home.css +++ b/web_src/css/repo/home.css @@ -58,6 +58,11 @@ flex: 0 0 15%; min-width: 0; max-height: 100vh; + position: sticky; + top: 0; + bottom: 0; + height: 100%; + overflow-y: hidden; } .repo-view-content { From 82071ee7300d478f56519ec30be0213b18a7882c Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Thu, 8 May 2025 00:36:14 +0000 Subject: [PATCH 09/32] [skip ci] Updated translations via Crowdin --- options/locale/locale_ga-IE.ini | 1 + options/locale/locale_pt-PT.ini | 2 ++ 2 files changed, 3 insertions(+) diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index b3a4a43f9d..ca9712b9e1 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -130,6 +130,7 @@ pin=Bioráin unpin=Díphoráil artifacts=Déantáin +expired=Imithe in éag confirm_delete_artifact=An bhfuil tú cinnte gur mhaith leat an déantán '%s' a scriosadh? archived=Cartlann diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 7d00fb81c7..00fa30e2e1 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -130,6 +130,7 @@ pin=Fixar unpin=Desafixar artifacts=Artefactos +expired=Expirado confirm_delete_artifact=Tem a certeza que quer eliminar este artefacto "%s"? archived=Arquivado @@ -1879,6 +1880,7 @@ pulls.add_prefix=Adicione o prefixo %s pulls.remove_prefix=Remover o prefixo %s pulls.data_broken=Este pedido de integração está danificado devido à falta de informação da derivação. pulls.files_conflicted=Este pedido de integração contém modificações que entram em conflito com o ramo de destino. +pulls.is_checking=Verificando se existem conflitos na integração... pulls.is_ancestor=Este ramo já está incluído no ramo de destino. Não há nada a integrar. pulls.is_empty=As modificações feitas neste ramo já existem no ramo de destino. Este cometimento ficará vazio. pulls.required_status_check_failed=Algumas das verificações obrigatórias não foram bem sucedidas. From 2fbc8f9e87fc37f21997bf32d9b29fc16e92780c Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 8 May 2025 07:07:53 +0200 Subject: [PATCH 10/32] Fix LFS file not stored in LFS when uploaded/edited via API or web UI (#34367) Files that should be stored in LFS and are uploaded/edited from the API or web UI aren't stored in LFS. This may be a regression from #34154. --------- Co-authored-by: wxiaoguang --- modules/git/attribute/checker.go | 7 ++++++- modules/git/attribute/checker_test.go | 12 +++++++++++- services/repository/files/upload.go | 7 +++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/modules/git/attribute/checker.go b/modules/git/attribute/checker.go index c17006a154..167b31416e 100644 --- a/modules/git/attribute/checker.go +++ b/modules/git/attribute/checker.go @@ -39,7 +39,12 @@ func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attrib ) cancel = deleteTemporaryFile } - } // else: no treeish, assume it is a not a bare repo, read from working directory + } else { + // Read from existing index, in cases where the repo is bare and has an index, + // or the work tree contains unstaged changes that shouldn't affect the attribute check. + // It is caller's responsibility to add changed ".gitattributes" into the index if they want to respect the new changes. + cmd.AddArguments("--cached") + } cmd.AddDynamicArguments(attributes...) if len(filenames) > 0 { diff --git a/modules/git/attribute/checker_test.go b/modules/git/attribute/checker_test.go index 97db43460b..67fbda8918 100644 --- a/modules/git/attribute/checker_test.go +++ b/modules/git/attribute/checker_test.go @@ -57,8 +57,18 @@ func Test_Checker(t *testing.T) { assert.Equal(t, expectedAttrs(), attrs["i-am-a-python.p"]) }) + t.Run("Run git check-attr in bare repository using index", func(t *testing.T) { + attrs, err := CheckAttributes(t.Context(), gitRepo, "", CheckAttributeOpts{ + Filenames: []string{"i-am-a-python.p"}, + Attributes: LinguistAttributes, + }) + assert.NoError(t, err) + assert.Len(t, attrs, 1) + assert.Equal(t, expectedAttrs(), attrs["i-am-a-python.p"]) + }) + if !git.DefaultFeatures().SupportCheckAttrOnBare { - t.Skip("git version 2.40 is required to support run check-attr on bare repo") + t.Skip("git version 2.40 is required to support run check-attr on bare repo without using index") return } diff --git a/services/repository/files/upload.go b/services/repository/files/upload.go index f348cb68ab..68a071cd28 100644 --- a/services/repository/files/upload.go +++ b/services/repository/files/upload.go @@ -107,6 +107,7 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } var attributesMap map[string]*attribute.Attributes + // when uploading to an empty repo, the old branch doesn't exist, but some "global gitattributes" or "info/attributes" may exist if setting.LFS.StartServer { attributesMap, err = attribute.CheckAttributes(ctx, t.gitRepo, "" /* use temp repo's working dir */, attribute.CheckAttributeOpts{ Attributes: []string{attribute.Filter}, @@ -118,6 +119,12 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } // Copy uploaded files into repository. + // TODO: there is a small problem: when uploading LFS files with ".gitattributes", the "check-attr" runs before this loop, + // so LFS files are not able to be added as LFS objects. Ideally we need to do in 3 steps in the future: + // 1. Add ".gitattributes" to git index + // 2. Run "check-attr" (the previous attribute.CheckAttributes call) + // 3. Add files to git index (this loop) + // This problem is trivial so maybe no need to spend too much time on it at the moment. for i := range infos { if err := copyUploadedLFSFileIntoRepository(ctx, &infos[i], attributesMap, t, opts.TreePath); err != nil { return err From 4c611bf280c501c22c6a58e94d9e3ce6a73214df Mon Sep 17 00:00:00 2001 From: NorthRealm <155140859+NorthRealm@users.noreply.github.com> Date: Thu, 8 May 2025 17:11:43 +0000 Subject: [PATCH 11/32] Add a button editing action secret (#34348) Add a button editing action secret Closes #34190 --------- Co-authored-by: wxiaoguang --- options/locale/locale_en-US.ini | 11 ++++++++--- routers/web/shared/secrets/secrets.go | 4 ++-- templates/shared/secrets/add_list.tmpl | 24 ++++++++++++++++++----- web_src/js/features/common-button.test.ts | 14 +++++++++++++ web_src/js/features/common-button.ts | 23 ++++++++++++++++++---- 5 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 web_src/js/features/common-button.test.ts diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9091b6bc4b..af3b948a88 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3722,13 +3722,18 @@ owner.settings.chef.keypair.description = A key pair is necessary to authenticat secrets = Secrets description = Secrets will be passed to certain actions and cannot be read otherwise. none = There are no secrets yet. -creation = Add Secret + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description = Description creation.name_placeholder = case-insensitive, alphanumeric characters or underscores only, cannot start with GITEA_ or GITHUB_ creation.value_placeholder = Input any content. Whitespace at the start and end will be omitted. creation.description_placeholder = Enter short description (optional). -creation.success = The secret "%s" has been added. -creation.failed = Failed to add secret. + +save_success = The secret "%s" has been saved. +save_failed = Failed to save secret. + +add_secret = Add secret +edit_secret = Edit secret deletion = Remove secret deletion.description = Removing a secret is permanent and cannot be undone. Continue? deletion.success = The secret has been removed. diff --git a/routers/web/shared/secrets/secrets.go b/routers/web/shared/secrets/secrets.go index c8b80ebb26..29f4e9520d 100644 --- a/routers/web/shared/secrets/secrets.go +++ b/routers/web/shared/secrets/secrets.go @@ -32,11 +32,11 @@ func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data), form.Description) if err != nil { log.Error("CreateOrUpdateSecret failed: %v", err) - ctx.JSONError(ctx.Tr("secrets.creation.failed")) + ctx.JSONError(ctx.Tr("secrets.save_failed")) return } - ctx.Flash.Success(ctx.Tr("secrets.creation.success", s.Name)) + ctx.Flash.Success(ctx.Tr("secrets.save_success", s.Name)) ctx.JSONRedirect(redirectURL) } diff --git a/templates/shared/secrets/add_list.tmpl b/templates/shared/secrets/add_list.tmpl index 977f308b71..a4ef2e5384 100644 --- a/templates/shared/secrets/add_list.tmpl +++ b/templates/shared/secrets/add_list.tmpl @@ -4,9 +4,13 @@
@@ -33,6 +37,18 @@ {{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort .CreatedUnix)}} +

{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{DateUtils.TimeSince .DBBranch.DeletedUnix}}

{{else}}
- {{.DBBranch.Name}} + {{.DBBranch.Name}} {{if .IsProtected}} {{svg "octicon-shield-lock"}} {{end}} diff --git a/tests/integration/change_default_branch_test.go b/tests/integration/change_default_branch_test.go index 729eb1e4ce..9b61cff9fd 100644 --- a/tests/integration/change_default_branch_test.go +++ b/tests/integration/change_default_branch_test.go @@ -6,12 +6,16 @@ package integration import ( "fmt" "net/http" + "strconv" "testing" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" ) func TestChangeDefaultBranch(t *testing.T) { @@ -38,3 +42,96 @@ func TestChangeDefaultBranch(t *testing.T) { }) session.MakeRequest(t, req, http.StatusNotFound) } + +func checkDivergence(t *testing.T, session *TestSession, branchesURL, expectedDefaultBranch string, expectedBranchToDivergence map[string]git.DivergeObject) { + req := NewRequest(t, "GET", branchesURL) + resp := session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + + branchNodes := htmlDoc.doc.Find(".branch-name").Nodes + branchNames := []string{} + for _, node := range branchNodes { + branchNames = append(branchNames, node.FirstChild.Data) + } + + expectBranchCount := len(expectedBranchToDivergence) + + assert.Len(t, branchNames, expectBranchCount+1) + assert.Equal(t, expectedDefaultBranch, branchNames[0]) + + allCountBehindNodes := htmlDoc.doc.Find(".count-behind").Nodes + allCountAheadNodes := htmlDoc.doc.Find(".count-ahead").Nodes + + assert.Len(t, allCountAheadNodes, expectBranchCount) + assert.Len(t, allCountBehindNodes, expectBranchCount) + + for i := range expectBranchCount { + branchName := branchNames[i+1] + assert.Contains(t, expectedBranchToDivergence, branchName) + + expectedCountAhead := expectedBranchToDivergence[branchName].Ahead + expectedCountBehind := expectedBranchToDivergence[branchName].Behind + countAhead, err := strconv.Atoi(allCountAheadNodes[i].FirstChild.Data) + assert.NoError(t, err) + countBehind, err := strconv.Atoi(allCountBehindNodes[i].FirstChild.Data) + assert.NoError(t, err) + + assert.Equal(t, expectedCountAhead, countAhead) + assert.Equal(t, expectedCountBehind, countBehind) + } +} + +func TestChangeDefaultBranchDivergence(t *testing.T) { + defer tests.PrepareTestEnv(t)() + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + session := loginUser(t, owner.Name) + branchesURL := fmt.Sprintf("/%s/%s/branches", owner.Name, repo.Name) + settingsBranchesURL := fmt.Sprintf("/%s/%s/settings/branches", owner.Name, repo.Name) + + // check branch divergence before switching default branch + expectedBranchToDivergenceBefore := map[string]git.DivergeObject{ + "not-signed": { + Ahead: 0, + Behind: 0, + }, + "good-sign-not-yet-validated": { + Ahead: 0, + Behind: 1, + }, + "good-sign": { + Ahead: 1, + Behind: 3, + }, + } + checkDivergence(t, session, branchesURL, "master", expectedBranchToDivergenceBefore) + + // switch default branch + newDefaultBranch := "good-sign-not-yet-validated" + csrf := GetUserCSRFToken(t, session) + req := NewRequestWithValues(t, "POST", settingsBranchesURL, map[string]string{ + "_csrf": csrf, + "action": "default_branch", + "branch": newDefaultBranch, + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + // check branch divergence after switching default branch + expectedBranchToDivergenceAfter := map[string]git.DivergeObject{ + "master": { + Ahead: 1, + Behind: 0, + }, + "not-signed": { + Ahead: 1, + Behind: 0, + }, + "good-sign": { + Ahead: 1, + Behind: 2, + }, + } + checkDivergence(t, session, branchesURL, newDefaultBranch, expectedBranchToDivergenceAfter) +} From f63822fe64b0759dc7e38b467eaa7c41b71d8c5d Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 9 May 2025 02:26:18 +0800 Subject: [PATCH 13/32] Fix autofocus behavior (#34397) The "autofocus" was abused or misbehaved: 1. When users visit a page but they are not going to change a field, then the field shouldn't get "autofocus" * the "auth" / "user" page: in most cases, users do not want to change the names * see also the GitHub's "settings" page behavior. 2. There shouldn't be duplicate "autofocus" inputs in most cases, only the first one focuses 3. When a panel is shown, the "autofocus" should get focus * "add ssh key" panel This PR fixes all these problems and by the way remove duplicate "isElemHidden" function. --- templates/admin/auth/edit.tmpl | 2 +- templates/admin/user/edit.tmpl | 6 +-- templates/org/settings/options.tmpl | 2 +- templates/repo/settings/collaboration.tmpl | 2 +- templates/repo/settings/options.tmpl | 2 +- templates/user/settings/profile.tmpl | 2 +- web_src/js/features/common-button.ts | 11 ++--- web_src/js/features/common-issue-list.ts | 6 +-- web_src/js/features/repo-issue-list.ts | 6 +-- web_src/js/utils/dom.test.ts | 6 ++- web_src/js/utils/dom.ts | 49 +++++++++------------- 11 files changed, 45 insertions(+), 49 deletions(-) diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl index 15683307ed..91b84e13b6 100644 --- a/templates/admin/auth/edit.tmpl +++ b/templates/admin/auth/edit.tmpl @@ -15,7 +15,7 @@
- +
diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index c04d332660..879b5cb550 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -9,7 +9,7 @@ {{.CsrfTokenHtml}}
- +
@@ -55,7 +55,7 @@
- +
@@ -63,7 +63,7 @@
- +
diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index 76315f3eac..f4583bbe36 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -12,7 +12,7 @@
{{ctx.Locale.Tr "org.settings.change_orgname_prompt"}}
{{ctx.Locale.Tr "org.settings.change_orgname_redirect_prompt"}} - +
diff --git a/templates/repo/settings/collaboration.tmpl b/templates/repo/settings/collaboration.tmpl index 4461398258..7064b4c7ba 100644 --- a/templates/repo/settings/collaboration.tmpl +++ b/templates/repo/settings/collaboration.tmpl @@ -90,7 +90,7 @@ {{.CsrfTokenHtml}} diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 4d61604612..fc42056e0a 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -10,7 +10,7 @@
- +
diff --git a/templates/user/settings/profile.tmpl b/templates/user/settings/profile.tmpl index 03c3c18f28..d8e5e27b89 100644 --- a/templates/user/settings/profile.tmpl +++ b/templates/user/settings/profile.tmpl @@ -12,7 +12,7 @@ {{ctx.Locale.Tr "settings.change_username_prompt"}} {{ctx.Locale.Tr "settings.change_username_redirect_prompt"}} - + {{if or (not .SignedUser.IsLocal) ($.UserDisabledFeatures.Contains "change_username") .IsReverseProxy}}

{{ctx.Locale.Tr "settings.password_username_disabled"}}

{{end}} diff --git a/web_src/js/features/common-button.ts b/web_src/js/features/common-button.ts index b8c801ebe9..ae399e48b3 100644 --- a/web_src/js/features/common-button.ts +++ b/web_src/js/features/common-button.ts @@ -1,5 +1,5 @@ import {POST} from '../modules/fetch.ts'; -import {addDelegatedEventListener, hideElem, showElem, toggleElem} from '../utils/dom.ts'; +import {addDelegatedEventListener, hideElem, isElemVisible, showElem, toggleElem} from '../utils/dom.ts'; import {fomanticQuery} from '../modules/fomantic/base.ts'; import {camelize} from 'vue'; @@ -79,10 +79,11 @@ function onShowPanelClick(el: HTMLElement, e: MouseEvent) { // if it has "toggle" class, it toggles the panel e.preventDefault(); const sel = el.getAttribute('data-panel'); - if (el.classList.contains('toggle')) { - toggleElem(sel); - } else { - showElem(sel); + const elems = el.classList.contains('toggle') ? toggleElem(sel) : showElem(sel); + for (const elem of elems) { + if (isElemVisible(elem as HTMLElement)) { + elem.querySelector('[autofocus]')?.focus(); + } } } diff --git a/web_src/js/features/common-issue-list.ts b/web_src/js/features/common-issue-list.ts index e207364794..037529bd10 100644 --- a/web_src/js/features/common-issue-list.ts +++ b/web_src/js/features/common-issue-list.ts @@ -1,4 +1,4 @@ -import {isElemHidden, onInputDebounce, submitEventSubmitter, toggleElem} from '../utils/dom.ts'; +import {isElemVisible, onInputDebounce, submitEventSubmitter, toggleElem} from '../utils/dom.ts'; import {GET} from '../modules/fetch.ts'; const {appSubUrl} = window.config; @@ -28,7 +28,7 @@ export function parseIssueListQuickGotoLink(repoLink: string, searchText: string } export function initCommonIssueListQuickGoto() { - const goto = document.querySelector('#issue-list-quick-goto'); + const goto = document.querySelector('#issue-list-quick-goto'); if (!goto) return; const form = goto.closest('form'); @@ -37,7 +37,7 @@ export function initCommonIssueListQuickGoto() { form.addEventListener('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); + let doQuickGoto = isElemVisible(goto); const submitter = submitEventSubmitter(e); if (submitter !== form && submitter !== input && submitter !== goto) doQuickGoto = false; if (!doQuickGoto) return; diff --git a/web_src/js/features/repo-issue-list.ts b/web_src/js/features/repo-issue-list.ts index 8cd4483357..3ea5fb70c0 100644 --- a/web_src/js/features/repo-issue-list.ts +++ b/web_src/js/features/repo-issue-list.ts @@ -1,5 +1,5 @@ import {updateIssuesMeta} from './repo-common.ts'; -import {toggleElem, isElemHidden, queryElems} from '../utils/dom.ts'; +import {toggleElem, queryElems, isElemVisible} from '../utils/dom.ts'; import {htmlEscape} from 'escape-goat'; import {confirmModal} from './comp/ConfirmModal.ts'; import {showErrorToast} from '../modules/toast.ts'; @@ -33,8 +33,8 @@ function initRepoIssueListCheckboxes() { toggleElem('#issue-filters', !anyChecked); toggleElem('#issue-actions', anyChecked); // there are two panels but only one select-all checkbox, so move the checkbox to the visible panel - const panels = document.querySelectorAll('#issue-filters, #issue-actions'); - const visiblePanel = Array.from(panels).find((el) => !isElemHidden(el)); + const panels = document.querySelectorAll('#issue-filters, #issue-actions'); + const visiblePanel = Array.from(panels).find((el) => isElemVisible(el)); const toolbarLeft = visiblePanel.querySelector('.issue-list-toolbar-left'); toolbarLeft.prepend(issueSelectAll); }; diff --git a/web_src/js/utils/dom.test.ts b/web_src/js/utils/dom.test.ts index 6a3af91556..057ea9808c 100644 --- a/web_src/js/utils/dom.test.ts +++ b/web_src/js/utils/dom.test.ts @@ -25,10 +25,14 @@ test('createElementFromAttrs', () => { }); test('querySingleVisibleElem', () => { - let el = createElementFromHTML('
foo
'); + let el = createElementFromHTML('
'); + expect(querySingleVisibleElem(el, 'span')).toBeNull(); + el = createElementFromHTML('
foo
'); expect(querySingleVisibleElem(el, 'span').textContent).toEqual('foo'); el = createElementFromHTML('
foobar
'); expect(querySingleVisibleElem(el, 'span').textContent).toEqual('bar'); + el = createElementFromHTML('
foobar
'); + expect(querySingleVisibleElem(el, 'span').textContent).toEqual('bar'); el = createElementFromHTML('
foobar
'); expect(() => querySingleVisibleElem(el, 'span')).toThrowError('Expected exactly one visible element'); }); diff --git a/web_src/js/utils/dom.ts b/web_src/js/utils/dom.ts index 4386d38632..83a0d9c8df 100644 --- a/web_src/js/utils/dom.ts +++ b/web_src/js/utils/dom.ts @@ -9,24 +9,24 @@ type ElementsCallback = (el: T) => Promisable; type ElementsCallbackWithArgs = (el: Element, ...args: any[]) => Promisable; export type DOMEvent = E & { target: Partial; }; -function elementsCall(el: ElementArg, func: ElementsCallbackWithArgs, ...args: any[]) { +function elementsCall(el: ElementArg, func: ElementsCallbackWithArgs, ...args: any[]): ArrayLikeIterable { if (typeof el === 'string' || el instanceof String) { el = document.querySelectorAll(el as string); } if (el instanceof Node) { func(el, ...args); + return [el]; } else if (el.length !== undefined) { // this works for: NodeList, HTMLCollection, Array, jQuery - for (const e of (el as ArrayLikeIterable)) { - func(e, ...args); - } - } else { - throw new Error('invalid argument to be shown/hidden'); + const elems = el as ArrayLikeIterable; + for (const elem of elems) func(elem, ...args); + return elems; } + throw new Error('invalid argument to be shown/hidden'); } -export function toggleClass(el: ElementArg, className: string, force?: boolean) { - elementsCall(el, (e: Element) => { +export function toggleClass(el: ElementArg, className: string, force?: boolean): ArrayLikeIterable { + return elementsCall(el, (e: Element) => { if (force === true) { e.classList.add(className); } else if (force === false) { @@ -43,23 +43,16 @@ export function toggleClass(el: ElementArg, className: string, force?: boolean) * @param el ElementArg * @param force force=true to show or force=false to hide, undefined to toggle */ -export function toggleElem(el: ElementArg, force?: boolean) { - toggleClass(el, 'tw-hidden', force === undefined ? force : !force); +export function toggleElem(el: ElementArg, force?: boolean): ArrayLikeIterable { + return toggleClass(el, 'tw-hidden', force === undefined ? force : !force); } -export function showElem(el: ElementArg) { - toggleElem(el, true); +export function showElem(el: ElementArg): ArrayLikeIterable { + return toggleElem(el, true); } -export function hideElem(el: ElementArg) { - toggleElem(el, false); -} - -export function isElemHidden(el: ElementArg) { - const res: boolean[] = []; - elementsCall(el, (e) => res.push(e.classList.contains('tw-hidden'))); - if (res.length > 1) throw new Error(`isElemHidden doesn't work for multiple elements`); - return res[0]; +export function hideElem(el: ElementArg): ArrayLikeIterable { + return toggleElem(el, false); } function applyElemsCallback(elems: ArrayLikeIterable, fn?: ElementsCallback): ArrayLikeIterable { @@ -275,14 +268,12 @@ export function initSubmitEventPolyfill() { document.body.addEventListener('focus', submitEventPolyfillListener); } -/** - * Check if an element is visible, equivalent to jQuery's `:visible` pseudo. - * Note: This function doesn't account for all possible visibility scenarios. - */ -export function isElemVisible(element: HTMLElement): boolean { - if (!element) return false; - // checking element.style.display is not necessary for browsers, but it is required by some tests with happy-dom because happy-dom doesn't really do layout - return Boolean((element.offsetWidth || element.offsetHeight || element.getClientRects().length) && element.style.display !== 'none'); +export function isElemVisible(el: HTMLElement): boolean { + // Check if an element is visible, equivalent to jQuery's `:visible` pseudo. + // This function DOESN'T account for all possible visibility scenarios, its behavior is covered by the tests of "querySingleVisibleElem" + if (!el) return false; + // checking el.style.display is not necessary for browsers, but it is required by some tests with happy-dom because happy-dom doesn't really do layout + return !el.classList.contains('tw-hidden') && Boolean((el.offsetWidth || el.offsetHeight || el.getClientRects().length) && el.style.display !== 'none'); } // replace selected text in a textarea while preserving editor history, e.g. CTRL-Z works after this From 44aadc37c9c0810f3a41189929ae21c613b6bc98 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Fri, 9 May 2025 00:36:27 +0000 Subject: [PATCH 14/32] [skip ci] Updated translations via Crowdin --- options/locale/locale_cs-CZ.ini | 7 ++++--- options/locale/locale_de-DE.ini | 7 ++++--- options/locale/locale_el-GR.ini | 7 ++++--- options/locale/locale_es-ES.ini | 7 ++++--- options/locale/locale_fa-IR.ini | 4 ++++ options/locale/locale_fi-FI.ini | 4 ++++ options/locale/locale_fr-FR.ini | 10 +++++++--- options/locale/locale_ga-IE.ini | 7 ++++--- options/locale/locale_hu-HU.ini | 4 ++++ options/locale/locale_id-ID.ini | 4 ++++ options/locale/locale_is-IS.ini | 4 ++++ options/locale/locale_it-IT.ini | 4 ++++ options/locale/locale_ja-JP.ini | 7 ++++--- options/locale/locale_ko-KR.ini | 4 ++++ options/locale/locale_lv-LV.ini | 7 ++++--- options/locale/locale_nl-NL.ini | 4 ++++ options/locale/locale_pl-PL.ini | 4 ++++ options/locale/locale_pt-BR.ini | 7 ++++--- options/locale/locale_pt-PT.ini | 7 ++++--- options/locale/locale_ru-RU.ini | 7 ++++--- options/locale/locale_si-LK.ini | 4 ++++ options/locale/locale_sk-SK.ini | 4 ++++ options/locale/locale_sv-SE.ini | 4 ++++ options/locale/locale_tr-TR.ini | 7 ++++--- options/locale/locale_uk-UA.ini | 4 ++++ options/locale/locale_zh-CN.ini | 7 ++++--- options/locale/locale_zh-HK.ini | 4 ++++ options/locale/locale_zh-TW.ini | 7 ++++--- 28 files changed, 115 insertions(+), 42 deletions(-) diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 63ab9f9d3a..2a3bd3e743 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -3667,12 +3667,13 @@ owner.settings.chef.keypair.description=Pro autentizaci do registru Chef je zapo secrets=Tajné klíče description=Tejné klíče budou předány určitým akcím a nelze je přečíst jinak. none=Zatím zde nejsou žádné tajné klíče. -creation=Přidat tajný klíč + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Popis creation.name_placeholder=nerozlišovat velká a malá písmena, pouze alfanumerické znaky nebo podtržítka, nemohou začínat na GITEA_ nebo GITHUB_ creation.value_placeholder=Vložte jakýkoliv obsah. Mezery na začátku a konci budou vynechány. -creation.success=Tajný klíč „%s“ byl přidán. -creation.failed=Nepodařilo se přidat tajný klíč. + + deletion=Odstranit tajný klíč deletion.description=Odstranění tajného klíče je trvalé a nelze ho vrátit zpět. Pokračovat? deletion.success=Tajný klíč byl odstraněn. diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 43333f8ac6..f115dee247 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -3659,12 +3659,13 @@ owner.settings.chef.keypair.description=Ein Schlüsselpaar ist notwendig, um mit secrets=Secrets description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden. none=Noch keine Secrets vorhanden. -creation=Secret hinzufügen + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Beschreibung creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen. -creation.success=Das Secret "%s" wurde hinzugefügt. -creation.failed=Secret konnte nicht hinzugefügt werden. + + deletion=Secret entfernen deletion.description=Das Entfernen eines Secrets kann nicht rückgängig gemacht werden. Fortfahren? deletion.success=Das Secret wurde entfernt. diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index c2479bf342..444fbd26c9 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -3329,12 +3329,13 @@ owner.settings.chef.keypair.description=Ένα ζεύγος κλειδιών ε secrets=Μυστικά description=Τα μυστικά θα περάσουν σε ορισμένες δράσεις και δεν μπορούν να αναγνωστούν αλλού. none=Δεν υπάρχουν ακόμα μυστικά. -creation=Προσθήκη Μυστικού + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Περιγραφή creation.name_placeholder=αλφαριθμητικοί χαρακτήρες ή κάτω παύλες μόνο, δεν μπορούν να ξεκινούν με GITEA_ ή GITHUB_ creation.value_placeholder=Εισάγετε οποιοδήποτε περιεχόμενο. Τα κενά στην αρχή παραλείπονται. -creation.success=Το μυστικό "%s" προστέθηκε. -creation.failed=Αποτυχία δημιουργίας μυστικού. + + deletion=Αφαίρεση μυστικού deletion.description=Η αφαίρεση ενός μυστικού είναι μόνιμη και δεν μπορεί να αναιρεθεί. Συνέχεια; deletion.success=Το μυστικό έχει αφαιρεθεί. diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 5f989f6acf..521583395e 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -3309,12 +3309,13 @@ owner.settings.chef.keypair.description=Un par de claves es necesario para auten secrets=Secretos description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo. none=Todavía no hay secretos. -creation=Añadir secreto + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Descripción creation.name_placeholder=sin distinción de mayúsculas, solo carácteres alfanuméricos o guiones bajos, no puede empezar por GITEA_ o GITHUB_ creation.value_placeholder=Introduce cualquier contenido. Se omitirá el espacio en blanco en el inicio y el final. -creation.success=El secreto "%s" ha sido añadido. -creation.failed=Error al añadir secreto. + + deletion=Eliminar secreto deletion.description=Eliminar un secreto es permanente y no se puede deshacer. ¿Continuar? deletion.success=El secreto ha sido eliminado. diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 5d67f03bac..18abc0f401 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -2506,8 +2506,12 @@ conan.details.repository=مخزن owner.settings.cleanuprules.enabled=فعال شده [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=شرح + + [actions] diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index 69cee090fe..b925d6f43a 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -1692,8 +1692,12 @@ conan.details.repository=Repo owner.settings.cleanuprules.enabled=Käytössä [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Kuvaus + + [actions] diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index b9d550eee5..eeb5e31965 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -130,6 +130,7 @@ pin=Épingler unpin=Désépingler artifacts=Artefacts +expired=Expiré confirm_delete_artifact=Êtes-vous sûr de vouloir supprimer l‘artefact « %s » ? archived=Archivé @@ -450,6 +451,7 @@ use_scratch_code=Utiliser un code de secours twofa_scratch_used=Vous avez utilisé votre code de secours. Vous avez été redirigé vers cette page de configuration afin de supprimer l'authentification à deux facteurs de votre appareil ou afin de générer un nouveau code de secours. twofa_passcode_incorrect=Votre code d’accès n’est pas correct. Si vous avez égaré votre appareil, utilisez votre code de secours pour vous connecter. twofa_scratch_token_incorrect=Votre code de secours est incorrect. +twofa_required=Vous devez configurer l’authentification à deux facteurs pour avoir accès aux dépôts, ou essayer de vous reconnecter. login_userpass=Connexion login_openid=OpenID oauth_signup_tab=Créer un compte @@ -1878,6 +1880,7 @@ pulls.add_prefix=Ajouter le préfixe %s pulls.remove_prefix=Enlever le préfixe %s pulls.data_broken=Cette demande d’ajout est impossible par manque d'informations de bifurcation. pulls.files_conflicted=Cette demande d'ajout contient des modifications en conflit avec la branche ciblée. +pulls.is_checking=Recherche de conflits de fusion… pulls.is_ancestor=Cette branche est déjà présente dans la branche ciblée. Il n'y a rien à fusionner. pulls.is_empty=Les changements sur cette branche sont déjà sur la branche cible. Cette révision sera vide. pulls.required_status_check_failed=Certains contrôles requis n'ont pas réussi. @@ -3718,13 +3721,14 @@ owner.settings.chef.keypair.description=Une paire de clés est nécessaire pour secrets=Secrets description=Les secrets seront transmis à certaines actions et ne pourront pas être lus autrement. none=Il n'y a pas encore de secrets. -creation=Ajouter un secret + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Description creation.name_placeholder=Caractères alphanumériques ou tirets bas uniquement, insensibles à la casse, ne peut commencer par GITEA_ ou GITHUB_. creation.value_placeholder=Entrez n’importe quoi. Les blancs cernant seront taillés. creation.description_placeholder=Décrire brièvement votre dépôt (optionnel). -creation.success=Le secret "%s" a été ajouté. -creation.failed=Impossible d'ajouter le secret. + + deletion=Supprimer le secret deletion.description=La suppression d'un secret est permanente et irréversible. Continuer ? deletion.success=Le secret a été supprimé. diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index ca9712b9e1..cdde7e015d 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -3721,13 +3721,14 @@ owner.settings.chef.keypair.description=Tá eochairphéire riachtanach le fíord secrets=Rúin description=Cuirfear rúin ar aghaidh chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt. none=Níl aon rúin ann fós. -creation=Cuir Rúnda leis + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Cur síos creation.name_placeholder=carachtair alfanumair nó íoslaghda amháin nach féidir a thosú le GITEA_ nó GITHUB_ creation.value_placeholder=Ionchur ábhar ar bith. Fágfar spás bán ag tús agus ag deireadh ar lár. creation.description_placeholder=Cuir isteach cur síos gairid (roghnach). -creation.success=Tá an rún "%s" curtha leis. -creation.failed=Theip ar an rún a chur leis. + + deletion=Bain rún deletion.description=Is buan rún a bhaint agus ní féidir é a chealú. Lean ort? deletion.success=Tá an rún bainte. diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini index 0dae5505aa..ebc6d5c801 100644 --- a/options/locale/locale_hu-HU.ini +++ b/options/locale/locale_hu-HU.ini @@ -1592,8 +1592,12 @@ conan.details.repository=Tároló owner.settings.cleanuprules.enabled=Engedélyezett [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Leírás + + [actions] diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 808ebaa9ec..54b0499d96 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -1394,8 +1394,12 @@ conan.details.repository=Repositori owner.settings.cleanuprules.enabled=Aktif [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Deskripsi + + [actions] diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini index 999b21c608..42ecfabe22 100644 --- a/options/locale/locale_is-IS.ini +++ b/options/locale/locale_is-IS.ini @@ -1325,8 +1325,12 @@ npm.details.tag=Merki pypi.requires=Þarfnast Python [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Lýsing + + [actions] diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index f4a6767ea4..569d3f54e1 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -2782,8 +2782,12 @@ settings.delete.error=Impossibile eliminare il pacchetto. owner.settings.cleanuprules.enabled=Attivo [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Descrizione + + [actions] diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index a6366565b2..7790dccd6b 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -3718,13 +3718,14 @@ owner.settings.chef.keypair.description=Chefレジストリの認証にはキー secrets=シークレット description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。 none=シークレットはまだありません。 -creation=シークレットを追加 + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=説明 creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可 creation.value_placeholder=内容を入力してください。前後の空白は除去されます。 creation.description_placeholder=簡単な説明を入力してください。 (オプション) -creation.success=シークレット "%s" を追加しました。 -creation.failed=シークレットの追加に失敗しました。 + + deletion=シークレットの削除 deletion.description=シークレットの削除は恒久的で元に戻すことはできません。 続行しますか? deletion.success=シークレットを削除しました。 diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index 08f6d723de..22bf3e1641 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -1542,8 +1542,12 @@ conan.details.repository=저장소 owner.settings.cleanuprules.enabled=활성화됨 [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=설명 + + [actions] diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 718ca0594e..a746f8738c 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -3332,12 +3332,13 @@ owner.settings.chef.keypair.description=Atslēgu pāris ir nepieciešams, lai au secrets=Noslēpumi description=Noslēpumi tiks padoti atsevišķām darbībām un citādi nevar tikt nolasīti. none=Pagaidām nav neviena noslēpuma. -creation=Pievienot noslēpumu + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Apraksts creation.name_placeholder=reģistr-nejūtīgs, tikai burti, cipari un apakšsvītras, nevar sākties ar GITEA_ vai GITHUB_ creation.value_placeholder=Ievadiet jebkādu saturu. Atstarpes sākumā un beigā tiks noņemtas. -creation.success=Noslēpums "%s" tika pievienots. -creation.failed=Neizdevās pievienot noslēpumu. + + deletion=Dzēst noslēpumu deletion.description=Noslēpuma dzēšana ir neatgriezeniska. Vai turpināt? deletion.success=Noslēpums tika izdzēsts. diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index eff4c1f85f..b6887ee9e0 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -2515,8 +2515,12 @@ settings.link.button=Repository link bijwerken owner.settings.cleanuprules.enabled=Ingeschakeld [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Omschrijving + + [actions] diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index b45f0fc8e0..42a33f9ce4 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -2405,8 +2405,12 @@ conan.details.repository=Repozytorium owner.settings.cleanuprules.enabled=Włączone [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Opis + + [actions] diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 75d425417c..8ee675e6e0 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -3269,12 +3269,13 @@ owner.settings.chef.keypair=Gerar par de chaves secrets=Segredos description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma. none=Não há segredos ainda. -creation=Adicionar Segredo + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Descrição creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), não pode começar com GITEA_ ou GITHUB_ creation.value_placeholder=Insira qualquer conteúdo. Espaços em branco no início e no fim serão omitidos. -creation.success=O segredo "%s" foi adicionado. -creation.failed=Falha ao adicionar segredo. + + deletion=Excluir segredo deletion.description=A exclusão de um segredo é permanente e não pode ser desfeita. Continuar? deletion.success=O segredo foi excluído. diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 00fa30e2e1..2f04452a35 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -3721,13 +3721,14 @@ owner.settings.chef.keypair.description=É necessário um par de chaves para aut secrets=Segredos description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma. none=Ainda não há segredos. -creation=Adicionar segredo + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Descrição creation.name_placeholder=Só sublinhados ou alfanuméricos sem distinguir maiúsculas, sem começar com GITEA_ nem GITHUB_ creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos. creation.description_placeholder=Escreva uma descrição curta (opcional). -creation.success=O segredo "%s" foi adicionado. -creation.failed=Falhou ao adicionar o segredo. + + deletion=Remover segredo deletion.description=Remover um segredo é permanente e não pode ser revertido. Continuar? deletion.success=O segredo foi removido. diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 879d7c6145..c65d08a4cf 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -3266,12 +3266,13 @@ owner.settings.chef.keypair=Создать пару ключей secrets=Секреты description=Секреты будут передаваться определенным действиям и не могут быть прочитаны иначе. none=Секретов пока нет. -creation=Добавить секрет + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Описание creation.name_placeholder=регистр не важен, только алфавитно-цифровые символы и подчёркивания, не может начинаться с GITEA_ или GITHUB_ creation.value_placeholder=Введите любое содержимое. Пробельные символы в начале и конце будут опущены. -creation.success=Секрет «%s» добавлен. -creation.failed=Не удалось добавить секрет. + + deletion=Удалить секрет deletion.description=Удаление секрета необратимо, его нельзя отменить. Продолжить? deletion.success=Секрет удалён. diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini index 042e8ad21b..a209187aff 100644 --- a/options/locale/locale_si-LK.ini +++ b/options/locale/locale_si-LK.ini @@ -2447,8 +2447,12 @@ conan.details.repository=කෝෂ්ඨය owner.settings.cleanuprules.enabled=සබල කර ඇත [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=සවිස්තරය + + [actions] diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini index b1dae7c490..e461075e53 100644 --- a/options/locale/locale_sk-SK.ini +++ b/options/locale/locale_sk-SK.ini @@ -1321,6 +1321,10 @@ owner.settings.cleanuprules.enabled=Povolené [secrets] +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation + + + [actions] diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index 6fb5a9c4cb..04428aeab2 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -1982,8 +1982,12 @@ conan.details.repository=Utvecklingskatalog owner.settings.cleanuprules.enabled=Aktiv [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Beskrivning + + [actions] diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index acd0892eba..d617598057 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -3525,12 +3525,13 @@ owner.settings.chef.keypair.description=Chef kütüğünde kimlik doğrulaması secrets=Gizlilikler description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz. none=Henüz gizlilik yok. -creation=Gizlilik Ekle + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Açıklama creation.name_placeholder=küçük-büyük harfe duyarlı değil, alfanümerik karakterler veya sadece alt tire, GITEA_ veya GITHUB_ ile başlayamaz creation.value_placeholder=Herhangi bir içerik girin. Baştaki ve sondaki boşluklar ihmal edilecektir. -creation.success=Gizlilik "%s" eklendi. -creation.failed=Gizlilik eklenemedi. + + deletion=Gizliliği kaldır deletion.description=Bir gizliliği kaldırma kalıcıdır ve geri alınamaz. Devam edilsin mi? deletion.success=Gizlilik kaldırıldı. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 3a6d1539fa..6aed70491b 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -2517,8 +2517,12 @@ conan.details.repository=Репозиторій owner.settings.cleanuprules.enabled=Увімкнено [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=Опис + + [actions] diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 0e7db6350c..f6d6183e52 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -3717,13 +3717,14 @@ owner.settings.chef.keypair.description=需要密钥对才能向 Chef 注册中 secrets=密钥 description=Secrets 将被传给特定的 Actions,其它情况将不能读取 none=还没有密钥。 -creation=添加密钥 + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=组织描述 creation.name_placeholder=不区分大小写,字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。 creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略 creation.description_placeholder=输入简短描述(可选)。 -creation.success=您的密钥 '%s' 添加成功。 -creation.failed=添加密钥失败。 + + deletion=删除密钥 deletion.description=删除密钥是永久性的,无法撤消。继续吗? deletion.success=此Secret已被删除。 diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini index b157a44c69..2874da3170 100644 --- a/options/locale/locale_zh-HK.ini +++ b/options/locale/locale_zh-HK.ini @@ -959,8 +959,12 @@ conan.details.repository=儲存庫 owner.settings.cleanuprules.enabled=已啟用 [secrets] + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=組織描述 + + [actions] diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 3b25c81be3..a52e147415 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -3635,12 +3635,13 @@ owner.settings.chef.keypair.description=驗證 Chef 註冊中心需要一個密 secrets=Secret description=Secret 會被傳給特定的 Action,其他情況無法讀取。 none=還沒有 Secret。 -creation=加入 Secret + +; These keys are also for "edit secret", the keys are kept as-is to avoid unnecessary re-translation creation.description=描述 creation.name_placeholder=不區分大小寫,只能包含英文字母、數字、底線 ('_'),不能以 GITEA_ 或 GITHUB_ 開頭。 creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。 -creation.success=已新增 Secret「%s」。 -creation.failed=加入 Secret 失敗。 + + deletion=移除 Secret deletion.description=移除 Secret 是永久的且不可還原,是否繼續? deletion.success=已移除此 Secret。 From 179068fddbb463f3a34162730649d82acec522d3 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 9 May 2025 20:42:35 +0800 Subject: [PATCH 15/32] Refactor commit message rendering and fix bugs (#34412) Fix #34398, fix #33308 Remove all `repo.ComposeCommentMetas` from templates, only use `repo` to render commit message. --- models/renderhelper/commit_checker.go | 2 +- modules/templates/util_date_test.go | 2 + modules/templates/util_render.go | 21 ++-- modules/templates/util_render_legacy.go | 16 +-- modules/templates/util_render_test.go | 126 ++++++++++++------------ routers/web/feed/convert.go | 4 +- routers/web/repo/actions/view.go | 6 +- templates/repo/branch/list.tmpl | 4 +- templates/repo/commit_page.tmpl | 4 +- templates/repo/commits_list.tmpl | 4 +- templates/repo/commits_list_small.tmpl | 4 +- templates/repo/diff/compare.tmpl | 2 +- templates/repo/graph/commits.tmpl | 2 +- templates/repo/issue/view_title.tmpl | 2 +- templates/repo/latest_commit.tmpl | 4 +- templates/repo/view_list.tmpl | 2 +- templates/user/dashboard/feeds.tmpl | 2 +- 17 files changed, 101 insertions(+), 106 deletions(-) diff --git a/models/renderhelper/commit_checker.go b/models/renderhelper/commit_checker.go index 4815643e67..407e45fb54 100644 --- a/models/renderhelper/commit_checker.go +++ b/models/renderhelper/commit_checker.go @@ -47,7 +47,7 @@ func (c *commitChecker) IsCommitIDExisting(commitID string) bool { c.gitRepo, c.gitRepoCloser = r, closer } - exist = c.gitRepo.IsReferenceExist(commitID) // Don't use IsObjectExist since it doesn't support short hashs with gogit edition. + exist = c.gitRepo.IsReferenceExist(commitID) // Don't use IsObjectExist since it doesn't support short hashes with gogit edition. c.commitCache[commitID] = exist return exist } diff --git a/modules/templates/util_date_test.go b/modules/templates/util_date_test.go index f3a2409a9f..9015462bbb 100644 --- a/modules/templates/util_date_test.go +++ b/modules/templates/util_date_test.go @@ -17,6 +17,7 @@ import ( func TestDateTime(t *testing.T) { testTz, _ := time.LoadLocation("America/New_York") defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() + defer test.MockVariableValue(&setting.IsProd, true)() defer test.MockVariableValue(&setting.IsInTesting, false)() du := NewDateUtils() @@ -53,6 +54,7 @@ func TestDateTime(t *testing.T) { func TestTimeSince(t *testing.T) { testTz, _ := time.LoadLocation("America/New_York") defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() + defer test.MockVariableValue(&setting.IsProd, true)() defer test.MockVariableValue(&setting.IsInTesting, false)() du := NewDateUtils() diff --git a/modules/templates/util_render.go b/modules/templates/util_render.go index 521233db40..8d9ba1000c 100644 --- a/modules/templates/util_render.go +++ b/modules/templates/util_render.go @@ -14,6 +14,8 @@ import ( "unicode" issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/renderhelper" + "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/htmlutil" "code.gitea.io/gitea/modules/log" @@ -34,11 +36,11 @@ func NewRenderUtils(ctx reqctx.RequestContext) *RenderUtils { } // RenderCommitMessage renders commit message with XSS-safe and special links. -func (ut *RenderUtils) RenderCommitMessage(msg string, metas map[string]string) template.HTML { +func (ut *RenderUtils) RenderCommitMessage(msg string, repo *repo.Repository) template.HTML { cleanMsg := template.HTMLEscapeString(msg) // we can safely assume that it will not return any error, since there // shouldn't be any special HTML. - fullMessage, err := markup.PostProcessCommitMessage(markup.NewRenderContext(ut.ctx).WithMetas(metas), cleanMsg) + fullMessage, err := markup.PostProcessCommitMessage(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), cleanMsg) if err != nil { log.Error("PostProcessCommitMessage: %v", err) return "" @@ -52,7 +54,7 @@ func (ut *RenderUtils) RenderCommitMessage(msg string, metas map[string]string) // RenderCommitMessageLinkSubject renders commit message as a XSS-safe link to // the provided default url, handling for special links without email to links. -func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, metas map[string]string) template.HTML { +func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, repo *repo.Repository) template.HTML { msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace) lineEnd := strings.IndexByte(msgLine, '\n') if lineEnd > 0 { @@ -63,9 +65,8 @@ func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, me return "" } - // we can safely assume that it will not return any error, since there - // shouldn't be any special HTML. - renderedMessage, err := markup.PostProcessCommitMessageSubject(markup.NewRenderContext(ut.ctx).WithMetas(metas), urlDefault, template.HTMLEscapeString(msgLine)) + // we can safely assume that it will not return any error, since there shouldn't be any special HTML. + renderedMessage, err := markup.PostProcessCommitMessageSubject(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), urlDefault, template.HTMLEscapeString(msgLine)) if err != nil { log.Error("PostProcessCommitMessageSubject: %v", err) return "" @@ -74,7 +75,7 @@ func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, me } // RenderCommitBody extracts the body of a commit message without its title. -func (ut *RenderUtils) RenderCommitBody(msg string, metas map[string]string) template.HTML { +func (ut *RenderUtils) RenderCommitBody(msg string, repo *repo.Repository) template.HTML { msgLine := strings.TrimSpace(msg) lineEnd := strings.IndexByte(msgLine, '\n') if lineEnd > 0 { @@ -87,7 +88,7 @@ func (ut *RenderUtils) RenderCommitBody(msg string, metas map[string]string) tem return "" } - renderedMessage, err := markup.PostProcessCommitMessage(markup.NewRenderContext(ut.ctx).WithMetas(metas), template.HTMLEscapeString(msgLine)) + renderedMessage, err := markup.PostProcessCommitMessage(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), template.HTMLEscapeString(msgLine)) if err != nil { log.Error("PostProcessCommitMessage: %v", err) return "" @@ -105,8 +106,8 @@ func renderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML { } // RenderIssueTitle renders issue/pull title with defined post processors -func (ut *RenderUtils) RenderIssueTitle(text string, metas map[string]string) template.HTML { - renderedText, err := markup.PostProcessIssueTitle(markup.NewRenderContext(ut.ctx).WithMetas(metas), template.HTMLEscapeString(text)) +func (ut *RenderUtils) RenderIssueTitle(text string, repo *repo.Repository) template.HTML { + renderedText, err := markup.PostProcessIssueTitle(renderhelper.NewRenderContextRepoComment(ut.ctx, repo), template.HTMLEscapeString(text)) if err != nil { log.Error("PostProcessIssueTitle: %v", err) return "" diff --git a/modules/templates/util_render_legacy.go b/modules/templates/util_render_legacy.go index 8f7b84c83d..df8f5e64de 100644 --- a/modules/templates/util_render_legacy.go +++ b/modules/templates/util_render_legacy.go @@ -32,22 +32,22 @@ func renderMarkdownToHtmlLegacy(ctx context.Context, input string) template.HTML return NewRenderUtils(reqctx.FromContext(ctx)).MarkdownToHtml(input) } -func renderCommitMessageLegacy(ctx context.Context, msg string, metas map[string]string) template.HTML { +func renderCommitMessageLegacy(ctx context.Context, msg string, _ map[string]string) template.HTML { panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessage(msg, metas) + return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessage(msg, nil) } -func renderCommitMessageLinkSubjectLegacy(ctx context.Context, msg, urlDefault string, metas map[string]string) template.HTML { +func renderCommitMessageLinkSubjectLegacy(ctx context.Context, msg, urlDefault string, _ map[string]string) template.HTML { panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessageLinkSubject(msg, urlDefault, metas) + return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessageLinkSubject(msg, urlDefault, nil) } -func renderIssueTitleLegacy(ctx context.Context, text string, metas map[string]string) template.HTML { +func renderIssueTitleLegacy(ctx context.Context, text string, _ map[string]string) template.HTML { panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderIssueTitle(text, metas) + return NewRenderUtils(reqctx.FromContext(ctx)).RenderIssueTitle(text, nil) } -func renderCommitBodyLegacy(ctx context.Context, msg string, metas map[string]string) template.HTML { +func renderCommitBodyLegacy(ctx context.Context, msg string, _ map[string]string) template.HTML { panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitBody(msg, metas) + return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitBody(msg, nil) } diff --git a/modules/templates/util_render_test.go b/modules/templates/util_render_test.go index 460b9dc190..9b51d0cd57 100644 --- a/modules/templates/util_render_test.go +++ b/modules/templates/util_render_test.go @@ -11,11 +11,11 @@ import ( "testing" "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/reqctx" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/translation" @@ -47,19 +47,8 @@ mail@domain.com return strings.ReplaceAll(s, "", " ") } -var testMetas = map[string]string{ - "user": "user13", - "repo": "repo11", - "repoPath": "../../tests/gitea-repositories-meta/user13/repo11.git/", - "markdownNewLineHardBreak": "true", - "markupAllowShortIssuePattern": "true", -} - func TestMain(m *testing.M) { - unittest.InitSettingsForTesting() - if err := git.InitSimple(context.Background()); err != nil { - log.Fatal("git init failed, err: %v", err) - } + setting.Markdown.RenderOptionsComment.ShortIssuePattern = true markup.Init(&markup.RenderHelperFuncs{ IsUsernameMentionable: func(ctx context.Context, username string) bool { return username == "mention-user" @@ -74,46 +63,52 @@ func newTestRenderUtils(t *testing.T) *RenderUtils { return NewRenderUtils(ctx) } -func TestRenderCommitBody(t *testing.T) { - defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() - type args struct { - msg string +func TestRenderRepoComment(t *testing.T) { + mockRepo := &repo.Repository{ + ID: 1, OwnerName: "user13", Name: "repo11", + Owner: &user_model.User{ID: 13, Name: "user13"}, + Units: []*repo.RepoUnit{}, } - tests := []struct { - name string - args args - want template.HTML - }{ - { - name: "multiple lines", - args: args{ - msg: "first line\nsecond line", + t.Run("RenderCommitBody", func(t *testing.T) { + defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() + type args struct { + msg string + } + tests := []struct { + name string + args args + want template.HTML + }{ + { + name: "multiple lines", + args: args{ + msg: "first line\nsecond line", + }, + want: "second line", }, - want: "second line", - }, - { - name: "multiple lines with leading newlines", - args: args{ - msg: "\n\n\n\nfirst line\nsecond line", + { + name: "multiple lines with leading newlines", + args: args{ + msg: "\n\n\n\nfirst line\nsecond line", + }, + want: "second line", }, - want: "second line", - }, - { - name: "multiple lines with trailing newlines", - args: args{ - msg: "first line\nsecond line\n\n\n", + { + name: "multiple lines with trailing newlines", + args: args{ + msg: "first line\nsecond line\n\n\n", + }, + want: "second line", }, - want: "second line", - }, - } - ut := newTestRenderUtils(t) - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, nil), "RenderCommitBody(%v, %v)", tt.args.msg, nil) - }) - } + } + ut := newTestRenderUtils(t) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, mockRepo), "RenderCommitBody(%v, %v)", tt.args.msg, nil) + }) + } - expected := `/just/a/path.bin + expected := `/just/a/path.bin https://example.com/file.bin [local link](file.bin) [remote link](https://example.com) @@ -132,22 +127,22 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit @mention-user test #123 space` - assert.Equal(t, expected, string(newTestRenderUtils(t).RenderCommitBody(testInput(), testMetas))) -} + assert.Equal(t, expected, string(newTestRenderUtils(t).RenderCommitBody(testInput(), mockRepo))) + }) -func TestRenderCommitMessage(t *testing.T) { - expected := `space @mention-user ` - assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessage(testInput(), testMetas)) -} + t.Run("RenderCommitMessage", func(t *testing.T) { + expected := `space @mention-user ` + assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessage(testInput(), mockRepo)) + }) -func TestRenderCommitMessageLinkSubject(t *testing.T) { - expected := `space @mention-user` - assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessageLinkSubject(testInput(), "https://example.com/link", testMetas)) -} + t.Run("RenderCommitMessageLinkSubject", func(t *testing.T) { + expected := `space @mention-user` + assert.EqualValues(t, expected, newTestRenderUtils(t).RenderCommitMessageLinkSubject(testInput(), "https://example.com/link", mockRepo)) + }) -func TestRenderIssueTitle(t *testing.T) { - defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() - expected := ` space @mention-user + t.Run("RenderIssueTitle", func(t *testing.T) { + defer test.MockVariableValue(&markup.RenderBehaviorForTesting.DisableAdditionalAttributes, true)() + expected := ` space @mention-user /just/a/path.bin https://example.com/file.bin [local link](file.bin) @@ -168,8 +163,9 @@ mail@domain.com #123 space ` - expected = strings.ReplaceAll(expected, "", " ") - assert.Equal(t, expected, string(newTestRenderUtils(t).RenderIssueTitle(testInput(), testMetas))) + expected = strings.ReplaceAll(expected, "", " ") + assert.Equal(t, expected, string(newTestRenderUtils(t).RenderIssueTitle(testInput(), mockRepo))) + }) } func TestRenderMarkdownToHtml(t *testing.T) { diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index b04855fa6a..7c59132841 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -201,7 +201,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio switch act.OpType { case activities_model.ActionCommitRepo, activities_model.ActionMirrorSyncPush: push := templates.ActionContent2Commits(act) - + _ = act.LoadRepo(ctx) for _, commit := range push.Commits { if len(desc) != 0 { desc += "\n\n" @@ -209,7 +209,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio desc += fmt.Sprintf("%s\n%s", html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(ctx), commit.Sha1)), commit.Sha1, - renderUtils.RenderCommitMessage(commit.Message, nil), + renderUtils.RenderCommitMessage(commit.Message, act.Repo), ) } diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 2ec6389263..dd18c8380d 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -200,13 +200,9 @@ func ViewPost(ctx *context_module.Context) { } } - // TODO: "ComposeCommentMetas" (usually for comment) is not quite right, but it is still the same as what template "RenderCommitMessage" does. - // need to be refactored together in the future - metas := ctx.Repo.Repository.ComposeCommentMetas(ctx) - // the title for the "run" is from the commit message resp.State.Run.Title = run.Title - resp.State.Run.TitleHTML = templates.NewRenderUtils(ctx).RenderCommitMessage(run.Title, metas) + resp.State.Run.TitleHTML = templates.NewRenderUtils(ctx).RenderCommitMessage(run.Title, ctx.Repo.Repository) resp.State.Run.Link = run.Link() resp.State.Run.CanCancel = !run.Status.IsDone() && ctx.Repo.CanWrite(unit.TypeActions) resp.State.Run.CanApprove = run.NeedApproval && ctx.Repo.CanWrite(unit.TypeActions) diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index aa38413ad7..fffe3a08cc 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -27,7 +27,7 @@ {{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}}
-

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · {{ctx.RenderUtils.RenderCommitMessage .DefaultBranchBranch.DBBranch.CommitMessage (.Repository.ComposeCommentMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime}}{{if .DefaultBranchBranch.DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}

+

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · {{ctx.RenderUtils.RenderCommitMessage .DefaultBranchBranch.DBBranch.CommitMessage .Repository}} · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime}}{{if .DefaultBranchBranch.DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}

{{/* FIXME: here and below, the tw-overflow-visible is not quite right but it is still needed the moment: to show the important buttons when the width is narrow */}} @@ -103,7 +103,7 @@ {{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DBBranch.CommitID)}}
-

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · {{ctx.RenderUtils.RenderCommitMessage .DBBranch.CommitMessage ($.Repository.ComposeCommentMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DBBranch.CommitTime}}{{if .DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}}  {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}

+

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · {{ctx.RenderUtils.RenderCommitMessage .DBBranch.CommitMessage $.Repository}} · {{ctx.Locale.Tr "org.repo_updated"}} {{DateUtils.TimeSince .DBBranch.CommitTime}}{{if .DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}}  {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}

{{end}} diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index 5639c87a82..7abd377108 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -5,7 +5,7 @@
-

{{ctx.RenderUtils.RenderCommitMessage .Commit.Message ($.Repository.ComposeCommentMetas ctx)}}{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses}}

+

{{ctx.RenderUtils.RenderCommitMessage .Commit.Message $.Repository}}{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses}}

{{if not $.PageIsWiki}} {{if IsMultilineCommitMessage .Commit.Message}} -
{{ctx.RenderUtils.RenderCommitBody .Commit.Message ($.Repository.ComposeCommentMetas ctx)}}
+
{{ctx.RenderUtils.RenderCommitBody .Commit.Message $.Repository}}
{{end}} {{template "repo/commit_load_branches_and_tags" .}}
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index 17c7240ee4..8a268a5d14 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -44,7 +44,7 @@ {{.Summary | ctx.RenderUtils.RenderEmoji}} {{else}} {{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}} - {{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink ($.Repository.ComposeCommentMetas ctx)}} + {{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.Repository}} {{end}} {{if IsMultilineCommitMessage .Message}} @@ -52,7 +52,7 @@ {{end}} {{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses}} {{if IsMultilineCommitMessage .Message}} -
{{ctx.RenderUtils.RenderCommitBody .Message ($.Repository.ComposeCommentMetas ctx)}}
+
{{ctx.RenderUtils.RenderCommitBody .Message $.Repository}}
{{end}} {{if $.CommitsTagsMap}} {{range (index $.CommitsTagsMap .ID.String)}} diff --git a/templates/repo/commits_list_small.tmpl b/templates/repo/commits_list_small.tmpl index b054ce19a5..ee94ad7e58 100644 --- a/templates/repo/commits_list_small.tmpl +++ b/templates/repo/commits_list_small.tmpl @@ -15,7 +15,7 @@ {{$commitLink:= printf "%s/%s" $commitBaseLink (PathEscape .ID.String)}} - {{- ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink ($.comment.Issue.PullRequest.BaseRepo.ComposeCommentMetas ctx) -}} + {{- ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.comment.Issue.PullRequest.BaseRepo -}} {{if IsMultilineCommitMessage .Message}} @@ -29,7 +29,7 @@
{{if IsMultilineCommitMessage .Message}}
-		{{- ctx.RenderUtils.RenderCommitBody .Message ($.comment.Issue.PullRequest.BaseRepo.ComposeCommentMetas ctx) -}}
+		{{- ctx.RenderUtils.RenderCommitBody .Message $.comment.Issue.PullRequest.BaseRepo -}}
 	
{{end}} {{end}} diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl index 6f16ce3bd8..4e8ad1326c 100644 --- a/templates/repo/diff/compare.tmpl +++ b/templates/repo/diff/compare.tmpl @@ -189,7 +189,7 @@
{{template "shared/issueicon" .}}
- {{ctx.RenderUtils.RenderIssueTitle .PullRequest.Issue.Title ($.Repository.ComposeCommentMetas ctx)}} + {{ctx.RenderUtils.RenderIssueTitle .PullRequest.Issue.Title $.Repository}} #{{.PullRequest.Issue.Index}}
diff --git a/templates/repo/graph/commits.tmpl b/templates/repo/graph/commits.tmpl index 630c4579ea..34167cadc0 100644 --- a/templates/repo/graph/commits.tmpl +++ b/templates/repo/graph/commits.tmpl @@ -8,7 +8,7 @@ {{template "repo/commit_sign_badge" dict "Commit" $commit.Commit "CommitBaseLink" (print $.RepoLink "/commit") "CommitSignVerification" $commit.Verification}} - {{ctx.RenderUtils.RenderCommitMessage $commit.Subject ($.Repository.ComposeCommentMetas ctx)}} + {{ctx.RenderUtils.RenderCommitMessage $commit.Subject $.Repository}} diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index a4be598540..b8f28dfd9b 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -13,7 +13,7 @@ {{$canEditIssueTitle := and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}}

- {{ctx.RenderUtils.RenderIssueTitle .Issue.Title ($.Repository.ComposeCommentMetas ctx)}} + {{ctx.RenderUtils.RenderIssueTitle .Issue.Title $.Repository}} #{{.Issue.Index}}

diff --git a/templates/repo/latest_commit.tmpl b/templates/repo/latest_commit.tmpl index da457e423a..cff338949f 100644 --- a/templates/repo/latest_commit.tmpl +++ b/templates/repo/latest_commit.tmpl @@ -21,10 +21,10 @@ {{template "repo/commit_statuses" dict "Status" .LatestCommitStatus "Statuses" .LatestCommitStatuses}} {{$commitLink:= printf "%s/commit/%s" .RepoLink (PathEscape .LatestCommit.ID.String)}} - {{ctx.RenderUtils.RenderCommitMessageLinkSubject .LatestCommit.Message $commitLink ($.Repository.ComposeCommentMetas ctx)}} + {{ctx.RenderUtils.RenderCommitMessageLinkSubject .LatestCommit.Message $commitLink $.Repository}} {{if IsMultilineCommitMessage .LatestCommit.Message}} -
{{ctx.RenderUtils.RenderCommitBody .LatestCommit.Message ($.Repository.ComposeCommentMetas ctx)}}
+
{{ctx.RenderUtils.RenderCommitBody .LatestCommit.Message $.Repository}}
{{end}}
{{end}} diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl index cd832498b4..c8ee059e89 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -47,7 +47,7 @@
{{end}} From 2ecd73d2e586cd4ff2001246d54c4affe0e1ccec Mon Sep 17 00:00:00 2001 From: Yarden Shoham Date: Fri, 9 May 2025 17:11:13 +0300 Subject: [PATCH 16/32] Bump `@github/relative-time-element` to v4.4.8 (#34413) Tested, it works as before. Changelog: https://github.com/github/relative-time-element/releases/tag/v4.4.8 Signed-off-by: Yarden Shoham --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4c5963d0c8..e61fe3472d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.7", + "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", @@ -1146,9 +1146,9 @@ "license": "MIT" }, "node_modules/@github/relative-time-element": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.7.tgz", - "integrity": "sha512-NZCePEFYtV7qAUI/pHYuqZ8vRhcsfH/dziUZTY9YR5+JwzDCWtEokYSDbDLZjrRl+SAFr02YHUK+UdtP6hPcbQ==", + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/@github/relative-time-element/-/relative-time-element-4.4.8.tgz", + "integrity": "sha512-FSLYm6F3TSQnqHE1EMQUVVgi2XjbCvsESwwXfugHFpBnhyF1uhJOtu0Psp/BB/qqazfdkk7f5fVcu7WuXl3t8Q==", "license": "MIT" }, "node_modules/@github/text-expander-element": { diff --git a/package.json b/package.json index 0202b92ff4..bc2c0c87f3 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", - "@github/relative-time-element": "4.4.7", + "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.1", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@primer/octicons": "19.15.1", From 8b16ab719cab24805beb2189af7ee960ca94d524 Mon Sep 17 00:00:00 2001 From: silverwind Date: Fri, 9 May 2025 17:14:21 +0200 Subject: [PATCH 17/32] Merge and tweak markup editor expander CSS (#34409) - Merge the CSS for the two expanders (text-expander-element and tribute.js) into one file - Fix overflow issues - Remove min-width - Various other tweaks like borders, colors, padding, gaps. text-expander: Screenshot 2025-05-09 at 02 21 24 tribute: Screenshot 2025-05-09 at 02 21 37 --------- Co-authored-by: wxiaoguang --- web_src/css/editor/combomarkdowneditor.css | 64 --------------- web_src/css/features/expander.css | 96 ++++++++++++++++++++++ web_src/css/features/tribute.css | 32 -------- web_src/css/index.css | 2 +- web_src/js/features/comp/TextExpander.ts | 1 + 5 files changed, 98 insertions(+), 97 deletions(-) create mode 100644 web_src/css/features/expander.css delete mode 100644 web_src/css/features/tribute.css diff --git a/web_src/css/editor/combomarkdowneditor.css b/web_src/css/editor/combomarkdowneditor.css index 835286b795..046010c6c8 100644 --- a/web_src/css/editor/combomarkdowneditor.css +++ b/web_src/css/editor/combomarkdowneditor.css @@ -100,67 +100,3 @@ border-bottom: 1px solid var(--color-secondary); padding-bottom: 1rem; } - -text-expander { - display: block; - position: relative; -} - -text-expander .suggestions { - position: absolute; - min-width: 180px; - padding: 0; - margin-top: 24px; - list-style: none; - background: var(--color-box-body); - border-radius: var(--border-radius); - border: 1px solid var(--color-secondary); - box-shadow: 0 .5rem 1rem var(--color-shadow); - z-index: 100; /* needs to be > 20 to be on top of dropzone's .dz-details */ -} - -text-expander .suggestions li { - display: flex; - align-items: center; - cursor: pointer; - padding: 4px 8px; - font-weight: var(--font-weight-medium); -} - -text-expander .suggestions li + li { - border-top: 1px solid var(--color-secondary-alpha-40); -} - -text-expander .suggestions li:first-child { - border-radius: var(--border-radius) var(--border-radius) 0 0; -} - -text-expander .suggestions li:last-child { - border-radius: 0 0 var(--border-radius) var(--border-radius); -} - -text-expander .suggestions li:only-child { - border-radius: var(--border-radius); -} - -text-expander .suggestions li:hover { - background: var(--color-hover); -} - -text-expander .suggestions .fullname { - font-weight: var(--font-weight-normal); - margin-left: 4px; - color: var(--color-text-light-1); -} - -text-expander .suggestions li[aria-selected="true"], -text-expander .suggestions li[aria-selected="true"] span { - background: var(--color-primary); - color: var(--color-primary-contrast); -} - -text-expander .suggestions img { - width: 24px; - height: 24px; - margin-right: 8px; -} diff --git a/web_src/css/features/expander.css b/web_src/css/features/expander.css new file mode 100644 index 0000000000..f560b2a9fd --- /dev/null +++ b/web_src/css/features/expander.css @@ -0,0 +1,96 @@ +text-expander .suggestions, +.tribute-container { + position: absolute; + max-height: min(300px, 95vh); + max-width: min(500px, 95vw); + overflow-x: hidden; + overflow-y: auto; + white-space: nowrap; + background: var(--color-menu); + box-shadow: 0 6px 18px var(--color-shadow); + border-radius: var(--border-radius); + border: 1px solid var(--color-secondary); + z-index: 100; /* needs to be > 20 to be on top of dropzone's .dz-details */ +} + +text-expander { + display: block; + position: relative; +} + +text-expander .suggestions { + padding: 0; + margin-top: 24px; + list-style: none; +} + +text-expander .suggestions li, +.tribute-item { + display: flex; + align-items: center; + cursor: pointer; + gap: 6px; + font-weight: var(--font-weight-medium); +} + +text-expander .suggestions li, +.tribute-container li { + padding: 3px 6px; +} + +text-expander .suggestions li + li, +.tribute-container li + li { + border-top: 1px solid var(--color-secondary); +} + +text-expander .suggestions li:first-child { + border-radius: var(--border-radius) var(--border-radius) 0 0; +} + +text-expander .suggestions li:last-child { + border-radius: 0 0 var(--border-radius) var(--border-radius); +} + +text-expander .suggestions li:only-child { + border-radius: var(--border-radius); +} + +text-expander .suggestions .fullname, +.tribute-container li .fullname { + font-weight: var(--font-weight-normal); + color: var(--color-text-light-1); + overflow: hidden; + text-overflow: ellipsis; +} + +text-expander .suggestions li:hover, +text-expander .suggestions li:hover *, +text-expander .suggestions li[aria-selected="true"], +text-expander .suggestions li[aria-selected="true"] *, +.tribute-container li.highlight, +.tribute-container li.highlight * { + background: var(--color-primary); + color: var(--color-primary-contrast); +} + +text-expander .suggestions img, +.tribute-item img { + width: 21px; + height: 21px; + object-fit: contain; + aspect-ratio: 1; +} + +.tribute-container { + display: block; +} + +.tribute-container ul { + margin: 0; + padding: 0; + list-style: none; +} + +.tribute-container li.no-match { + cursor: default; +} diff --git a/web_src/css/features/tribute.css b/web_src/css/features/tribute.css deleted file mode 100644 index 99a026b9bc..0000000000 --- a/web_src/css/features/tribute.css +++ /dev/null @@ -1,32 +0,0 @@ -@import "tributejs/dist/tribute.css"; - -.tribute-container { - box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.25); - border-radius: var(--border-radius); -} - -.tribute-container ul { - margin-top: 0 !important; - background: var(--color-body) !important; -} - -.tribute-container li { - padding: 3px 0.5rem !important; -} - -.tribute-container li span.fullname { - font-weight: var(--font-weight-normal); - font-size: 0.8rem; -} - -.tribute-container li.highlight, -.tribute-container li:hover { - background: var(--color-primary) !important; - color: var(--color-primary-contrast) !important; -} - -.tribute-item { - display: flex; - align-items: center; - gap: 6px; -} diff --git a/web_src/css/index.css b/web_src/css/index.css index 84795d6d27..c20aa028e4 100644 --- a/web_src/css/index.css +++ b/web_src/css/index.css @@ -39,7 +39,7 @@ @import "./features/imagediff.css"; @import "./features/codeeditor.css"; @import "./features/projects.css"; -@import "./features/tribute.css"; +@import "./features/expander.css"; @import "./features/cropper.css"; @import "./features/console.css"; diff --git a/web_src/js/features/comp/TextExpander.ts b/web_src/js/features/comp/TextExpander.ts index 5be234629d..2d79fe5029 100644 --- a/web_src/js/features/comp/TextExpander.ts +++ b/web_src/js/features/comp/TextExpander.ts @@ -97,6 +97,7 @@ export function initTextExpander(expander: TextExpanderElement) { li.append(img); const nameSpan = document.createElement('span'); + nameSpan.classList.add('name'); nameSpan.textContent = name; li.append(nameSpan); From ad271444e912ddf44591451292b39b0d6b859955 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 9 May 2025 09:17:08 -0700 Subject: [PATCH 18/32] Fix a bug when uploading file via lfs ssh command (#34408) Co-authored-by: wxiaoguang --- cmd/serv.go | 89 ++++++++++----------------- models/repo/repo.go | 27 +++++--- models/repo/repo_test.go | 15 +++++ modules/git/cmdverb.go | 36 +++++++++++ modules/private/serv.go | 10 ++- routers/private/serv.go | 8 ++- tests/integration/git_general_test.go | 40 +++++++++++- 7 files changed, 149 insertions(+), 76 deletions(-) create mode 100644 modules/git/cmdverb.go diff --git a/cmd/serv.go b/cmd/serv.go index b18508459f..26a3af50f3 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -11,7 +11,6 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "strconv" "strings" "time" @@ -20,7 +19,7 @@ import ( asymkey_model "code.gitea.io/gitea/models/asymkey" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/perm" - "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/lfstransfer" @@ -37,14 +36,6 @@ import ( "github.com/urfave/cli/v2" ) -const ( - verbUploadPack = "git-upload-pack" - verbUploadArchive = "git-upload-archive" - verbReceivePack = "git-receive-pack" - verbLfsAuthenticate = "git-lfs-authenticate" - verbLfsTransfer = "git-lfs-transfer" -) - // CmdServ represents the available serv sub-command. var CmdServ = &cli.Command{ Name: "serv", @@ -78,22 +69,6 @@ func setup(ctx context.Context, debug bool) { } } -var ( - // keep getAccessMode() in sync - allowedCommands = container.SetOf( - verbUploadPack, - verbUploadArchive, - verbReceivePack, - verbLfsAuthenticate, - verbLfsTransfer, - ) - allowedCommandsLfs = container.SetOf( - verbLfsAuthenticate, - verbLfsTransfer, - ) - alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`) -) - // fail prints message to stdout, it's mainly used for git serv and git hook commands. // The output will be passed to git client and shown to user. func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error { @@ -139,19 +114,20 @@ func handleCliResponseExtra(extra private.ResponseExtra) error { func getAccessMode(verb, lfsVerb string) perm.AccessMode { switch verb { - case verbUploadPack, verbUploadArchive: + case git.CmdVerbUploadPack, git.CmdVerbUploadArchive: return perm.AccessModeRead - case verbReceivePack: + case git.CmdVerbReceivePack: return perm.AccessModeWrite - case verbLfsAuthenticate, verbLfsTransfer: + case git.CmdVerbLfsAuthenticate, git.CmdVerbLfsTransfer: switch lfsVerb { - case "upload": + case git.CmdSubVerbLfsUpload: return perm.AccessModeWrite - case "download": + case git.CmdSubVerbLfsDownload: return perm.AccessModeRead } } // should be unreachable + setting.PanicInDevOrTesting("unknown verb: %s %s", verb, lfsVerb) return perm.AccessModeNone } @@ -230,12 +206,12 @@ func runServ(c *cli.Context) error { log.Debug("SSH_ORIGINAL_COMMAND: %s", os.Getenv("SSH_ORIGINAL_COMMAND")) } - words, err := shellquote.Split(cmd) + sshCmdArgs, err := shellquote.Split(cmd) if err != nil { return fail(ctx, "Error parsing arguments", "Failed to parse arguments: %v", err) } - if len(words) < 2 { + if len(sshCmdArgs) < 2 { if git.DefaultFeatures().SupportProcReceive { // for AGit Flow if cmd == "ssh_info" { @@ -246,25 +222,21 @@ func runServ(c *cli.Context) error { return fail(ctx, "Too few arguments", "Too few arguments in cmd: %s", cmd) } - verb := words[0] - repoPath := strings.TrimPrefix(words[1], "/") - - var lfsVerb string - - rr := strings.SplitN(repoPath, "/", 2) - if len(rr) != 2 { + repoPath := strings.TrimPrefix(sshCmdArgs[1], "/") + repoPathFields := strings.SplitN(repoPath, "/", 2) + if len(repoPathFields) != 2 { return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath) } - username := rr[0] - reponame := strings.TrimSuffix(rr[1], ".git") + username := repoPathFields[0] + reponame := strings.TrimSuffix(repoPathFields[1], ".git") // “the-repo-name" or "the-repo-name.wiki" // LowerCase and trim the repoPath as that's how they are stored. // This should be done after splitting the repoPath into username and reponame // so that username and reponame are not affected. repoPath = strings.ToLower(strings.TrimSpace(repoPath)) - if alphaDashDotPattern.MatchString(reponame) { + if !repo.IsValidSSHAccessRepoName(reponame) { return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame) } @@ -286,22 +258,23 @@ func runServ(c *cli.Context) error { }() } - if allowedCommands.Contains(verb) { - if allowedCommandsLfs.Contains(verb) { - if !setting.LFS.StartServer { - return fail(ctx, "LFS Server is not enabled", "") - } - if verb == verbLfsTransfer && !setting.LFS.AllowPureSSH { - return fail(ctx, "LFS SSH transfer is not enabled", "") - } - if len(words) > 2 { - lfsVerb = words[2] - } - } - } else { + verb, lfsVerb := sshCmdArgs[0], "" + if !git.IsAllowedVerbForServe(verb) { return fail(ctx, "Unknown git command", "Unknown git command %s", verb) } + if git.IsAllowedVerbForServeLfs(verb) { + if !setting.LFS.StartServer { + return fail(ctx, "LFS Server is not enabled", "") + } + if verb == git.CmdVerbLfsTransfer && !setting.LFS.AllowPureSSH { + return fail(ctx, "LFS SSH transfer is not enabled", "") + } + if len(sshCmdArgs) > 2 { + lfsVerb = sshCmdArgs[2] + } + } + requestedMode := getAccessMode(verb, lfsVerb) results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb) @@ -310,7 +283,7 @@ func runServ(c *cli.Context) error { } // LFS SSH protocol - if verb == verbLfsTransfer { + if verb == git.CmdVerbLfsTransfer { token, err := getLFSAuthToken(ctx, lfsVerb, results) if err != nil { return err @@ -319,7 +292,7 @@ func runServ(c *cli.Context) error { } // LFS token authentication - if verb == verbLfsAuthenticate { + if verb == git.CmdVerbLfsAuthenticate { url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName)) token, err := getLFSAuthToken(ctx, lfsVerb, results) diff --git a/models/repo/repo.go b/models/repo/repo.go index 2977dfb9f1..5aae02c6d8 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -64,18 +64,18 @@ func (err ErrRepoIsArchived) Error() string { } type globalVarsStruct struct { - validRepoNamePattern *regexp.Regexp - invalidRepoNamePattern *regexp.Regexp - reservedRepoNames []string - reservedRepoPatterns []string + validRepoNamePattern *regexp.Regexp + invalidRepoNamePattern *regexp.Regexp + reservedRepoNames []string + reservedRepoNamePatterns []string } var globalVars = sync.OnceValue(func() *globalVarsStruct { return &globalVarsStruct{ - validRepoNamePattern: regexp.MustCompile(`[-.\w]+`), - invalidRepoNamePattern: regexp.MustCompile(`[.]{2,}`), - reservedRepoNames: []string{".", "..", "-"}, - reservedRepoPatterns: []string{"*.git", "*.wiki", "*.rss", "*.atom"}, + validRepoNamePattern: regexp.MustCompile(`^[-.\w]+$`), + invalidRepoNamePattern: regexp.MustCompile(`[.]{2,}`), + reservedRepoNames: []string{".", "..", "-"}, + reservedRepoNamePatterns: []string{"*.wiki", "*.git", "*.rss", "*.atom"}, } }) @@ -86,7 +86,16 @@ func IsUsableRepoName(name string) error { // Note: usually this error is normally caught up earlier in the UI return db.ErrNameCharsNotAllowed{Name: name} } - return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoPatterns, name) + return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoNamePatterns, name) +} + +// IsValidSSHAccessRepoName is like IsUsableRepoName, but it allows "*.wiki" because wiki repo needs to be accessed in SSH code +func IsValidSSHAccessRepoName(name string) bool { + vars := globalVars() + if !vars.validRepoNamePattern.MatchString(name) || vars.invalidRepoNamePattern.MatchString(name) { + return false + } + return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoNamePatterns[1:], name) == nil } // TrustModelType defines the types of trust model for this repository diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go index b2604ab575..66abe864fc 100644 --- a/models/repo/repo_test.go +++ b/models/repo/repo_test.go @@ -216,8 +216,23 @@ func TestIsUsableRepoName(t *testing.T) { assert.Error(t, IsUsableRepoName("-")) assert.Error(t, IsUsableRepoName("🌞")) + assert.Error(t, IsUsableRepoName("the/repo")) assert.Error(t, IsUsableRepoName("the..repo")) assert.Error(t, IsUsableRepoName("foo.wiki")) assert.Error(t, IsUsableRepoName("foo.git")) assert.Error(t, IsUsableRepoName("foo.RSS")) } + +func TestIsValidSSHAccessRepoName(t *testing.T) { + assert.True(t, IsValidSSHAccessRepoName("a")) + assert.True(t, IsValidSSHAccessRepoName("-1_.")) + assert.True(t, IsValidSSHAccessRepoName(".profile")) + assert.True(t, IsValidSSHAccessRepoName("foo.wiki")) + + assert.False(t, IsValidSSHAccessRepoName("-")) + assert.False(t, IsValidSSHAccessRepoName("🌞")) + assert.False(t, IsValidSSHAccessRepoName("the/repo")) + assert.False(t, IsValidSSHAccessRepoName("the..repo")) + assert.False(t, IsValidSSHAccessRepoName("foo.git")) + assert.False(t, IsValidSSHAccessRepoName("foo.RSS")) +} diff --git a/modules/git/cmdverb.go b/modules/git/cmdverb.go new file mode 100644 index 0000000000..3d6f4ae0c6 --- /dev/null +++ b/modules/git/cmdverb.go @@ -0,0 +1,36 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package git + +const ( + CmdVerbUploadPack = "git-upload-pack" + CmdVerbUploadArchive = "git-upload-archive" + CmdVerbReceivePack = "git-receive-pack" + CmdVerbLfsAuthenticate = "git-lfs-authenticate" + CmdVerbLfsTransfer = "git-lfs-transfer" + + CmdSubVerbLfsUpload = "upload" + CmdSubVerbLfsDownload = "download" +) + +func IsAllowedVerbForServe(verb string) bool { + switch verb { + case CmdVerbUploadPack, + CmdVerbUploadArchive, + CmdVerbReceivePack, + CmdVerbLfsAuthenticate, + CmdVerbLfsTransfer: + return true + } + return false +} + +func IsAllowedVerbForServeLfs(verb string) bool { + switch verb { + case CmdVerbLfsAuthenticate, + CmdVerbLfsTransfer: + return true + } + return false +} diff --git a/modules/private/serv.go b/modules/private/serv.go index 10e9f7995c..b1dafbd81b 100644 --- a/modules/private/serv.go +++ b/modules/private/serv.go @@ -46,18 +46,16 @@ type ServCommandResults struct { } // ServCommand preps for a serv call -func ServCommand(ctx context.Context, keyID int64, ownerName, repoName string, mode perm.AccessMode, verbs ...string) (*ServCommandResults, ResponseExtra) { +func ServCommand(ctx context.Context, keyID int64, ownerName, repoName string, mode perm.AccessMode, verb, lfsVerb string) (*ServCommandResults, ResponseExtra) { reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/command/%d/%s/%s?mode=%d", keyID, url.PathEscape(ownerName), url.PathEscape(repoName), mode, ) - for _, verb := range verbs { - if verb != "" { - reqURL += "&verb=" + url.QueryEscape(verb) - } - } + reqURL += "&verb=" + url.QueryEscape(verb) + // reqURL += "&lfs_verb=" + url.QueryEscape(lfsVerb) // TODO: actually there is no use of this parameter. In the future, the URL construction should be more flexible + _ = lfsVerb req := newInternalRequestAPI(ctx, reqURL, "GET") return requestJSONResp(req, &ServCommandResults{}) } diff --git a/routers/private/serv.go b/routers/private/serv.go index 37fbc0730c..b879be0dc2 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -81,6 +81,7 @@ func ServCommand(ctx *context.PrivateContext) { ownerName := ctx.PathParam("owner") repoName := ctx.PathParam("repo") mode := perm.AccessMode(ctx.FormInt("mode")) + verb := ctx.FormString("verb") // Set the basic parts of the results to return results := private.ServCommandResults{ @@ -295,8 +296,11 @@ func ServCommand(ctx *context.PrivateContext) { return } } else { - // Because of the special ref "refs/for" we will need to delay write permission check - if git.DefaultFeatures().SupportProcReceive && unitType == unit.TypeCode { + // Because of the special ref "refs/for" (AGit) we will need to delay write permission check, + // AGit flow needs to write its own ref when the doer has "reader" permission (allowing to create PR). + // The real permission check is done in HookPreReceive (routers/private/hook_pre_receive.go). + // Here it should relax the permission check for "git push (git-receive-pack)", but not for others like LFS operations. + if git.DefaultFeatures().SupportProcReceive && unitType == unit.TypeCode && verb == git.CmdVerbReceivePack { mode = perm.AccessModeRead } diff --git a/tests/integration/git_general_test.go b/tests/integration/git_general_test.go index 34fe212d50..ed60bdb58a 100644 --- a/tests/integration/git_general_test.go +++ b/tests/integration/git_general_test.go @@ -11,8 +11,10 @@ import ( "net/http" "net/url" "os" + "os/exec" "path" "path/filepath" + "slices" "strconv" "testing" "time" @@ -30,6 +32,7 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/tests" + "github.com/kballard/go-shellquote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -105,7 +108,12 @@ func testGitGeneral(t *testing.T, u *url.URL) { // Setup key the user ssh key withKeyFile(t, keyname, func(keyFile string) { - t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile)) + var keyID int64 + t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile, func(t *testing.T, key api.PublicKey) { + keyID = key.ID + })) + assert.NotZero(t, keyID) + t.Run("LFSAccessTest", doSSHLFSAccessTest(sshContext, keyID)) // Setup remote link // TODO: get url from api @@ -136,6 +144,36 @@ func testGitGeneral(t *testing.T, u *url.URL) { }) } +func doSSHLFSAccessTest(_ APITestContext, keyID int64) func(*testing.T) { + return func(t *testing.T) { + sshCommand := os.Getenv("GIT_SSH_COMMAND") // it is set in withKeyFile + sshCmdParts, err := shellquote.Split(sshCommand) // and parse the ssh command to construct some mocked arguments + require.NoError(t, err) + + t.Run("User2AccessOwned", func(t *testing.T) { + sshCmdUser2Self := append(slices.Clone(sshCmdParts), + "-p", strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost, + "git-lfs-authenticate", "user2/repo1.git", "upload", // accessible to own repo + ) + cmd := exec.CommandContext(t.Context(), sshCmdUser2Self[0], sshCmdUser2Self[1:]...) + _, err := cmd.Output() + assert.NoError(t, err) // accessible, no error + }) + + t.Run("User2AccessOther", func(t *testing.T) { + sshCmdUser2Other := append(slices.Clone(sshCmdParts), + "-p", strconv.Itoa(setting.SSH.ListenPort), "git@"+setting.SSH.ListenHost, + "git-lfs-authenticate", "user5/repo4.git", "upload", // inaccessible to other's (user5/repo4) + ) + cmd := exec.CommandContext(t.Context(), sshCmdUser2Other[0], sshCmdUser2Other[1:]...) + _, err := cmd.Output() + var errExit *exec.ExitError + require.ErrorAs(t, err, &errExit) // inaccessible, error + assert.Contains(t, string(errExit.Stderr), fmt.Sprintf("User: 2:user2 with Key: %d:test-key is not authorized to write to user5/repo4.", keyID)) + }) + } +} + func ensureAnonymousClone(t *testing.T, u *url.URL) { dstLocalPath := t.TempDir() t.Run("CloneAnonymous", doGitClone(dstLocalPath, u)) From 0f63a5ef48b23c6ab26a4b13cfd26edbe4efbfa3 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sat, 10 May 2025 00:34:13 +0000 Subject: [PATCH 19/32] [skip ci] Updated translations via Crowdin --- options/locale/locale_pt-PT.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 2f04452a35..b47b61f6bd 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -3728,7 +3728,11 @@ creation.name_placeholder=Só sublinhados ou alfanuméricos sem distinguir maiú creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos. creation.description_placeholder=Escreva uma descrição curta (opcional). +save_success=O segredo "%s" foi guardado. +save_failed=Falhou ao guardar o segredo. +add_secret=Adicionar segredo +edit_secret=Editar segredo deletion=Remover segredo deletion.description=Remover um segredo é permanente e não pode ser revertido. Continuar? deletion.success=O segredo foi removido. From 9b8609e017aef8376eb59d9fd3e428e35f9caeda Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 11 May 2025 02:47:58 +0800 Subject: [PATCH 20/32] Fix GetUsersByEmails (#34423) Fix #34418, fix #34353 --- models/user/user.go | 4 ++- models/user/user_test.go | 24 ++++++++++++----- tests/integration/repo_commits_test.go | 36 +++++++------------------- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/models/user/user.go b/models/user/user.go index fd420f79c7..d7331d79f0 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -1203,7 +1203,8 @@ func GetUsersByEmails(ctx context.Context, emails []string) (map[string]*User, e for _, email := range emailAddresses { user := users[email.UID] if user != nil { - results[user.GetEmail()] = user + results[user.Email] = user + results[user.GetPlaceholderEmail()] = user } } } @@ -1213,6 +1214,7 @@ func GetUsersByEmails(ctx context.Context, emails []string) (map[string]*User, e return nil, err } for _, user := range users { + results[user.Email] = user results[user.GetPlaceholderEmail()] = user } return results, nil diff --git a/models/user/user_test.go b/models/user/user_test.go index 90e8bf13a8..dd232abe2e 100644 --- a/models/user/user_test.go +++ b/models/user/user_test.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIsUsableUsername(t *testing.T) { @@ -48,14 +49,23 @@ func TestOAuth2Application_LoadUser(t *testing.T) { assert.NotNil(t, user) } -func TestGetUserEmailsByNames(t *testing.T) { +func TestUserEmails(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - - // ignore none active user email - assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"})) - assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"})) - - assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"})) + t.Run("GetUserEmailsByNames", func(t *testing.T) { + // ignore none active user email + assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"})) + assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"})) + assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"})) + }) + t.Run("GetUsersByEmails", func(t *testing.T) { + m, err := user_model.GetUsersByEmails(db.DefaultContext, []string{"user1@example.com", "user2@" + setting.Service.NoReplyAddress}) + require.NoError(t, err) + require.Len(t, m, 4) + assert.EqualValues(t, 1, m["user1@example.com"].ID) + assert.EqualValues(t, 1, m["user1@"+setting.Service.NoReplyAddress].ID) + assert.EqualValues(t, 2, m["user2@example.com"].ID) + assert.EqualValues(t, 2, m["user2@"+setting.Service.NoReplyAddress].ID) + }) } func TestCanCreateOrganization(t *testing.T) { diff --git a/tests/integration/repo_commits_test.go b/tests/integration/repo_commits_test.go index dee0aa6176..504d2adacc 100644 --- a/tests/integration/repo_commits_test.go +++ b/tests/integration/repo_commits_test.go @@ -12,8 +12,6 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/unittest" - user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -40,40 +38,24 @@ func TestRepoCommits(t *testing.T) { func Test_ReposGitCommitListNotMaster(t *testing.T) { defer tests.PrepareTestEnv(t)() - user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - // Login as User2. - session := loginUser(t, user.Name) - - // Test getting commits (Page 1) - req := NewRequestf(t, "GET", "/%s/repo16/commits/branch/master", user.Name) + session := loginUser(t, "user2") + req := NewRequest(t, "GET", "/user2/repo16/commits/branch/master") resp := session.MakeRequest(t, req, http.StatusOK) doc := NewHTMLParser(t, resp.Body) - commits := []string{} + var commits []string doc.doc.Find("#commits-table .commit-id-short").Each(func(i int, s *goquery.Selection) { - commitURL, exists := s.Attr("href") - assert.True(t, exists) - assert.NotEmpty(t, commitURL) + commitURL, _ := s.Attr("href") commits = append(commits, path.Base(commitURL)) }) + assert.Equal(t, []string{"69554a64c1e6030f051e5c3f94bfbd773cd6a324", "27566bd5738fc8b4e3fef3c5e72cce608537bd95", "5099b81332712fe655e34e8dd63574f503f61811"}, commits) - assert.Len(t, commits, 3) - assert.Equal(t, "69554a64c1e6030f051e5c3f94bfbd773cd6a324", commits[0]) - assert.Equal(t, "27566bd5738fc8b4e3fef3c5e72cce608537bd95", commits[1]) - assert.Equal(t, "5099b81332712fe655e34e8dd63574f503f61811", commits[2]) - - userNames := []string{} + var userHrefs []string doc.doc.Find("#commits-table .author-wrapper").Each(func(i int, s *goquery.Selection) { - userPath, exists := s.Attr("href") - assert.True(t, exists) - assert.NotEmpty(t, userPath) - userNames = append(userNames, path.Base(userPath)) + userHref, _ := s.Attr("href") + userHrefs = append(userHrefs, userHref) }) - - assert.Len(t, userNames, 3) - assert.Equal(t, "User2", userNames[0]) - assert.Equal(t, "user21", userNames[1]) - assert.Equal(t, "User2", userNames[2]) + assert.Equal(t, []string{"/user2", "/user21", "/user2"}, userHrefs) } func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) { From 4a98ab05403ef1900937487d434bc075812b0303 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sun, 11 May 2025 13:42:21 +0800 Subject: [PATCH 21/32] Remove legacy template helper functions (#34426) These functions have been marked as `panicIfDevOrTesting` since 1.23 (#32422) --- modules/templates/helper.go | 20 ---------- modules/templates/util_date_legacy.go | 23 ----------- modules/templates/util_date_test.go | 14 +------ modules/templates/util_render_legacy.go | 53 ------------------------- 4 files changed, 2 insertions(+), 108 deletions(-) delete mode 100644 modules/templates/util_date_legacy.go delete mode 100644 modules/templates/util_render_legacy.go diff --git a/modules/templates/helper.go b/modules/templates/helper.go index c9d93e089c..d55d4f87c5 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -162,22 +162,6 @@ func NewFuncMap() template.FuncMap { "FilenameIsImage": filenameIsImage, "TabSizeClass": tabSizeClass, - - // for backward compatibility only, do not use them anymore - "TimeSince": timeSinceLegacy, - "TimeSinceUnix": timeSinceLegacy, - "DateTime": dateTimeLegacy, - - "RenderEmoji": renderEmojiLegacy, - "RenderLabel": renderLabelLegacy, - "RenderLabels": renderLabelsLegacy, - "RenderIssueTitle": renderIssueTitleLegacy, - - "RenderMarkdownToHtml": renderMarkdownToHtmlLegacy, - - "RenderCommitMessage": renderCommitMessageLegacy, - "RenderCommitMessageLinkSubject": renderCommitMessageLinkSubjectLegacy, - "RenderCommitBody": renderCommitBodyLegacy, } } @@ -367,7 +351,3 @@ func QueryBuild(a ...any) template.URL { } return template.URL(s) } - -func panicIfDevOrTesting() { - setting.PanicInDevOrTesting("legacy template functions are for backward compatibility only, do not use them in new code") -} diff --git a/modules/templates/util_date_legacy.go b/modules/templates/util_date_legacy.go deleted file mode 100644 index ceefb00447..0000000000 --- a/modules/templates/util_date_legacy.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2024 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package templates - -import ( - "html/template" - - "code.gitea.io/gitea/modules/translation" -) - -func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML { - panicIfDevOrTesting() - if s, ok := datetime.(string); ok { - datetime = parseLegacy(s) - } - return dateTimeFormat(format, datetime) -} - -func timeSinceLegacy(time any, _ translation.Locale) template.HTML { - panicIfDevOrTesting() - return TimeSince(time) -} diff --git a/modules/templates/util_date_test.go b/modules/templates/util_date_test.go index 9015462bbb..2c1f2d242e 100644 --- a/modules/templates/util_date_test.go +++ b/modules/templates/util_date_test.go @@ -23,7 +23,6 @@ func TestDateTime(t *testing.T) { du := NewDateUtils() refTimeStr := "2018-01-01T00:00:00Z" - refDateStr := "2018-01-01" refTime, _ := time.Parse(time.RFC3339, refTimeStr) refTimeStamp := timeutil.TimeStamp(refTime.Unix()) @@ -32,18 +31,9 @@ func TestDateTime(t *testing.T) { assert.EqualValues(t, "-", du.AbsoluteShort(time.Time{})) assert.EqualValues(t, "-", du.AbsoluteShort(timeutil.TimeStamp(0))) - actual := dateTimeLegacy("short", "invalid") - assert.EqualValues(t, `-`, actual) - - actual = dateTimeLegacy("short", refTimeStr) + actual := du.AbsoluteShort(refTime) assert.EqualValues(t, `2018-01-01`, actual) - actual = du.AbsoluteShort(refTime) - assert.EqualValues(t, `2018-01-01`, actual) - - actual = dateTimeLegacy("short", refDateStr) - assert.EqualValues(t, `2018-01-01`, actual) - actual = du.AbsoluteShort(refTimeStamp) assert.EqualValues(t, `2017-12-31`, actual) @@ -69,6 +59,6 @@ func TestTimeSince(t *testing.T) { actual = timeSinceTo(&refTime, time.Time{}) assert.EqualValues(t, `2018-01-01 00:00:00 +00:00`, actual) - actual = timeSinceLegacy(timeutil.TimeStampNano(refTime.UnixNano()), nil) + actual = du.TimeSince(timeutil.TimeStampNano(refTime.UnixNano())) assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) } diff --git a/modules/templates/util_render_legacy.go b/modules/templates/util_render_legacy.go deleted file mode 100644 index df8f5e64de..0000000000 --- a/modules/templates/util_render_legacy.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2024 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package templates - -import ( - "context" - "html/template" - - issues_model "code.gitea.io/gitea/models/issues" - "code.gitea.io/gitea/modules/reqctx" - "code.gitea.io/gitea/modules/translation" -) - -func renderEmojiLegacy(ctx context.Context, text string) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderEmoji(text) -} - -func renderLabelLegacy(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderLabel(label) -} - -func renderLabelsLegacy(ctx context.Context, locale translation.Locale, labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderLabels(labels, repoLink, issue) -} - -func renderMarkdownToHtmlLegacy(ctx context.Context, input string) template.HTML { //nolint:revive - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).MarkdownToHtml(input) -} - -func renderCommitMessageLegacy(ctx context.Context, msg string, _ map[string]string) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessage(msg, nil) -} - -func renderCommitMessageLinkSubjectLegacy(ctx context.Context, msg, urlDefault string, _ map[string]string) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitMessageLinkSubject(msg, urlDefault, nil) -} - -func renderIssueTitleLegacy(ctx context.Context, text string, _ map[string]string) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderIssueTitle(text, nil) -} - -func renderCommitBodyLegacy(ctx context.Context, msg string, _ map[string]string) template.HTML { - panicIfDevOrTesting() - return NewRenderUtils(reqctx.FromContext(ctx)).RenderCommitBody(msg, nil) -} From b07e03956af8f29464067b19cb5cacee358b592f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 11 May 2025 11:53:23 -0700 Subject: [PATCH 22/32] When updating comment, if the content is the same, just return and not update the databse (#34422) Fix #34318 --- routers/api/v1/repo/issue_comment.go | 18 ++++--- routers/web/repo/issue_comment.go | 31 ++++++----- tests/integration/repo_webhook_test.go | 73 +++++++++++++++++++++----- 3 files changed, 90 insertions(+), 32 deletions(-) diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 0c572a06a8..cc342a9313 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -609,15 +609,17 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption) return } - oldContent := comment.Content - comment.Content = form.Body - if err := issue_service.UpdateComment(ctx, comment, comment.ContentVersion, ctx.Doer, oldContent); err != nil { - if errors.Is(err, user_model.ErrBlockedUser) { - ctx.APIError(http.StatusForbidden, err) - } else { - ctx.APIErrorInternal(err) + if form.Body != comment.Content { + oldContent := comment.Content + comment.Content = form.Body + if err := issue_service.UpdateComment(ctx, comment, comment.ContentVersion, ctx.Doer, oldContent); err != nil { + if errors.Is(err, user_model.ErrBlockedUser) { + ctx.APIError(http.StatusForbidden, err) + } else { + ctx.APIErrorInternal(err) + } + return } - return } ctx.JSON(http.StatusOK, convert.ToAPIComment(ctx, ctx.Repo.Repository, comment)) diff --git a/routers/web/repo/issue_comment.go b/routers/web/repo/issue_comment.go index 8adce26ccc..9b51999fbd 100644 --- a/routers/web/repo/issue_comment.go +++ b/routers/web/repo/issue_comment.go @@ -239,23 +239,30 @@ func UpdateCommentContent(ctx *context.Context) { return } - oldContent := comment.Content newContent := ctx.FormString("content") contentVersion := ctx.FormInt("content_version") - - // allow to save empty content - comment.Content = newContent - if err = issue_service.UpdateComment(ctx, comment, contentVersion, ctx.Doer, oldContent); err != nil { - if errors.Is(err, user_model.ErrBlockedUser) { - ctx.JSONError(ctx.Tr("repo.issues.comment.blocked_user")) - } else if errors.Is(err, issues_model.ErrCommentAlreadyChanged) { - ctx.JSONError(ctx.Tr("repo.comments.edit.already_changed")) - } else { - ctx.ServerError("UpdateComment", err) - } + if contentVersion != comment.ContentVersion { + ctx.JSONError(ctx.Tr("repo.comments.edit.already_changed")) return } + if newContent != comment.Content { + // allow to save empty content + oldContent := comment.Content + comment.Content = newContent + + if err = issue_service.UpdateComment(ctx, comment, contentVersion, ctx.Doer, oldContent); err != nil { + if errors.Is(err, user_model.ErrBlockedUser) { + ctx.JSONError(ctx.Tr("repo.issues.comment.blocked_user")) + } else if errors.Is(err, issues_model.ErrCommentAlreadyChanged) { + ctx.JSONError(ctx.Tr("repo.comments.edit.already_changed")) + } else { + ctx.ServerError("UpdateComment", err) + } + return + } + } + if err := comment.LoadAttachments(ctx); err != nil { ctx.ServerError("LoadAttachments", err) return diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index 89df15b8de..34c2090b72 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -241,19 +241,68 @@ func Test_WebhookIssueComment(t *testing.T) { testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issue_comment") - // 2. trigger the webhook - issueURL := testNewIssue(t, session, "user2", "repo1", "Title2", "Description2") - testIssueAddComment(t, session, issueURL, "issue title2 comment1", "") + t.Run("create comment", func(t *testing.T) { + // 2. trigger the webhook + issueURL := testNewIssue(t, session, "user2", "repo1", "Title2", "Description2") + testIssueAddComment(t, session, issueURL, "issue title2 comment1", "") - // 3. validate the webhook is triggered - assert.Equal(t, "issue_comment", triggeredEvent) - assert.Len(t, payloads, 1) - assert.EqualValues(t, "created", payloads[0].Action) - assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name) - assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName) - assert.Equal(t, "Title2", payloads[0].Issue.Title) - assert.Equal(t, "Description2", payloads[0].Issue.Body) - assert.Equal(t, "issue title2 comment1", payloads[0].Comment.Body) + // 3. validate the webhook is triggered + assert.Equal(t, "issue_comment", triggeredEvent) + assert.Len(t, payloads, 1) + assert.EqualValues(t, "created", payloads[0].Action) + assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name) + assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.Equal(t, "Title2", payloads[0].Issue.Title) + assert.Equal(t, "Description2", payloads[0].Issue.Body) + assert.Equal(t, "issue title2 comment1", payloads[0].Comment.Body) + }) + + t.Run("update comment", func(t *testing.T) { + payloads = make([]api.IssueCommentPayload, 0, 2) + triggeredEvent = "" + + // 2. trigger the webhook + issueURL := testNewIssue(t, session, "user2", "repo1", "Title3", "Description3") + commentID := testIssueAddComment(t, session, issueURL, "issue title3 comment1", "") + modifiedContent := "issue title2 comment1 - modified" + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "content": modifiedContent, + }) + session.MakeRequest(t, req, http.StatusOK) + + // 3. validate the webhook is triggered + assert.Equal(t, "issue_comment", triggeredEvent) + assert.Len(t, payloads, 2) + assert.EqualValues(t, "edited", payloads[1].Action) + assert.Equal(t, "repo1", payloads[1].Issue.Repo.Name) + assert.Equal(t, "user2/repo1", payloads[1].Issue.Repo.FullName) + assert.Equal(t, "Title3", payloads[1].Issue.Title) + assert.Equal(t, "Description3", payloads[1].Issue.Body) + assert.Equal(t, modifiedContent, payloads[1].Comment.Body) + }) + + t.Run("Update comment with no content change", func(t *testing.T) { + payloads = make([]api.IssueCommentPayload, 0, 2) + triggeredEvent = "" + commentContent := "issue title3 comment1" + + // 2. trigger the webhook + issueURL := testNewIssue(t, session, "user2", "repo1", "Title3", "Description3") + commentID := testIssueAddComment(t, session, issueURL, commentContent, "") + + payloads = make([]api.IssueCommentPayload, 0, 2) + triggeredEvent = "" + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/comments/%d", "user2", "repo1", commentID), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "content": commentContent, + }) + session.MakeRequest(t, req, http.StatusOK) + + // 3. validate the webhook is not triggered because no content change + assert.Empty(t, triggeredEvent) + assert.Empty(t, payloads) + }) }) } From 780e92ea99646dfefbe11734a4845fbf304be83c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 11 May 2025 12:18:46 -0700 Subject: [PATCH 23/32] Only git operations should update `last changed` of a repository (#34388) Try to fix #32046 --- models/actions/run.go | 1 + models/repo/transfer.go | 2 +- models/repo/update.go | 6 +++--- routers/private/hook_post_receive.go | 2 +- routers/web/repo/editor.go | 8 +------- routers/web/repo/wiki.go | 2 +- routers/web/repo/wiki_test.go | 2 +- services/migrations/gitea_uploader.go | 4 ++-- services/mirror/mirror_pull.go | 4 ++-- services/repository/adopt.go | 2 +- services/repository/avatar.go | 6 +++--- services/repository/create.go | 2 +- services/repository/files/update.go | 2 +- services/repository/fork.go | 2 +- services/repository/push.go | 2 +- services/repository/repository.go | 2 +- services/repository/template.go | 2 +- services/repository/transfer.go | 8 ++++---- services/wiki/wiki.go | 2 +- 19 files changed, 28 insertions(+), 33 deletions(-) diff --git a/models/actions/run.go b/models/actions/run.go index 5f077940c5..c19fce67ae 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -171,6 +171,7 @@ func (run *ActionRun) IsSchedule() bool { func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { _, err := db.GetEngine(ctx).ID(repo.ID). + NoAutoTime(). SetExpr("num_action_runs", builder.Select("count(*)").From("action_run"). Where(builder.Eq{"repo_id": repo.ID}), diff --git a/models/repo/transfer.go b/models/repo/transfer.go index b669145d68..b4a3592cbc 100644 --- a/models/repo/transfer.go +++ b/models/repo/transfer.go @@ -249,7 +249,7 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m } repo.Status = RepositoryPendingTransfer - if err := UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err := UpdateRepositoryColsNoAutoTime(ctx, repo, "status"); err != nil { return err } diff --git a/models/repo/update.go b/models/repo/update.go index 15c8c48d5b..8a15477a80 100644 --- a/models/repo/update.go +++ b/models/repo/update.go @@ -25,7 +25,7 @@ func UpdateRepositoryOwnerNames(ctx context.Context, ownerID int64, ownerName st } defer committer.Close() - if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{ + if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").NoAutoTime().Update(&Repository{ OwnerName: ownerName, }); err != nil { return err @@ -40,8 +40,8 @@ func UpdateRepositoryUpdatedTime(ctx context.Context, repoID int64, updateTime t return err } -// UpdateRepositoryCols updates repository's columns -func UpdateRepositoryCols(ctx context.Context, repo *Repository, cols ...string) error { +// UpdateRepositoryColsWithAutoTime updates repository's columns +func UpdateRepositoryColsWithAutoTime(ctx context.Context, repo *Repository, cols ...string) error { _, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo) return err } diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 8b1e849e7a..a391e572b3 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -220,7 +220,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { } if len(cols) > 0 { - if err := repo_model.UpdateRepositoryCols(ctx, repo, cols...); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, cols...); err != nil { log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err), diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 03e5b830a0..cbcb3a3b21 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -376,12 +376,6 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b } } - if ctx.Repo.Repository.IsEmpty { - if isEmpty, err := ctx.Repo.GitRepo.IsEmpty(); err == nil && !isEmpty { - _ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, IsEmpty: false}, "is_empty") - } - } - redirectForCommitChoice(ctx, form.CommitChoice, branchName, form.TreePath) } @@ -790,7 +784,7 @@ func UploadFilePost(ctx *context.Context) { if ctx.Repo.Repository.IsEmpty { if isEmpty, err := ctx.Repo.GitRepo.IsEmpty(); err == nil && !isEmpty { - _ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, IsEmpty: false}, "is_empty") + _ = repo_model.UpdateRepositoryColsWithAutoTime(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, IsEmpty: false}, "is_empty") } } diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index d70760bc36..41bf9f5adb 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -109,7 +109,7 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err return wikiGitRepo, nil, errBranch } // update the default branch in the database - errDb := repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, DefaultWikiBranch: gitRepoDefaultBranch}, "default_wiki_branch") + errDb := repo_model.UpdateRepositoryColsNoAutoTime(ctx, &repo_model.Repository{ID: ctx.Repo.Repository.ID, DefaultWikiBranch: gitRepoDefaultBranch}, "default_wiki_branch") if errDb != nil { return wikiGitRepo, nil, errDb } diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index b5dfa9f856..d0139f6613 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -245,7 +245,7 @@ func TestDefaultWikiBranch(t *testing.T) { assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repoWithNoWiki, "main")) // repo with wiki - assert.NoError(t, repo_model.UpdateRepositoryCols(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"})) + assert.NoError(t, repo_model.UpdateRepositoryColsNoAutoTime(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"})) ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki") ctx.SetPathParam("*", "Home") diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index b6caa494c6..acb94439fa 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -148,7 +148,7 @@ func (g *GiteaLocalUploader) CreateRepo(ctx context.Context, repo *base.Reposito return err } g.repo.ObjectFormatName = objectFormat.Name() - return repo_model.UpdateRepositoryCols(ctx, g.repo, "object_format_name") + return repo_model.UpdateRepositoryColsNoAutoTime(ctx, g.repo, "object_format_name") } // Close closes this uploader @@ -975,7 +975,7 @@ func (g *GiteaLocalUploader) Finish(ctx context.Context) error { } g.repo.Status = repo_model.RepositoryReady - return repo_model.UpdateRepositoryCols(ctx, g.repo, "status") + return repo_model.UpdateRepositoryColsWithAutoTime(ctx, g.repo, "status") } func (g *GiteaLocalUploader) remapUser(ctx context.Context, source user_model.ExternalUserMigrated, target user_model.ExternalUserRemappable) error { diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index c43a4ef04a..cb90af5894 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -71,7 +71,7 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error // erase authentication before storing in database u.User = nil m.Repo.OriginalURL = u.String() - return repo_model.UpdateRepositoryCols(ctx, m.Repo, "original_url") + return repo_model.UpdateRepositoryColsNoAutoTime(ctx, m.Repo, "original_url") } // mirrorSyncResult contains information of a updated reference. @@ -653,7 +653,7 @@ func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, re } m.Repo.IsEmpty = false // Update the is empty and default_branch columns - if err := repo_model.UpdateRepositoryCols(ctx, m.Repo, "default_branch", "is_empty"); err != nil { + if err := repo_model.UpdateRepositoryColsWithAutoTime(ctx, m.Repo, "default_branch", "is_empty"); err != nil { log.Error("Failed to update default branch of repository %-v. Error: %v", m.Repo, err) desc := fmt.Sprintf("Failed to update default branch of repository '%s': %v", m.Repo.RepoPath(), err) if err = system_model.CreateRepositoryNotice(desc); err != nil { diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 7f1954145c..97ba22ace5 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -100,7 +100,7 @@ func AdoptRepository(ctx context.Context, doer, owner *user_model.User, opts Cre // 4 - update repository status repo.Status = repo_model.RepositoryReady - if err = repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "status"); err != nil { return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) } diff --git a/services/repository/avatar.go b/services/repository/avatar.go index 15e51d4a25..26bf6da465 100644 --- a/services/repository/avatar.go +++ b/services/repository/avatar.go @@ -40,7 +40,7 @@ func UploadAvatar(ctx context.Context, repo *repo_model.Repository, data []byte) // Users can upload the same image to other repo - prefix it with ID // Then repo will be removed - only it avatar file will be removed repo.Avatar = newAvatar - if err := repo_model.UpdateRepositoryCols(ctx, repo, "avatar"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "avatar"); err != nil { return fmt.Errorf("UploadAvatar: Update repository avatar: %w", err) } @@ -77,7 +77,7 @@ func DeleteAvatar(ctx context.Context, repo *repo_model.Repository) error { defer committer.Close() repo.Avatar = "" - if err := repo_model.UpdateRepositoryCols(ctx, repo, "avatar"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "avatar"); err != nil { return fmt.Errorf("DeleteAvatar: Update repository avatar: %w", err) } @@ -112,5 +112,5 @@ func generateAvatar(ctx context.Context, templateRepo, generateRepo *repo_model. return err } - return repo_model.UpdateRepositoryCols(ctx, generateRepo, "avatar") + return repo_model.UpdateRepositoryColsNoAutoTime(ctx, generateRepo, "avatar") } diff --git a/services/repository/create.go b/services/repository/create.go index c4a9dbb1b6..83d7d84c08 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -321,7 +321,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, owner *user_model.User, // 7 - update repository status to be ready if needsUpdateToReady { repo.Status = repo_model.RepositoryReady - if err = repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "status"); err != nil { return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) } } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index fbf59c40ed..712914a27e 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -306,7 +306,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use if repo.IsEmpty { if isEmpty, err := gitRepo.IsEmpty(); err == nil && !isEmpty { - _ = repo_model.UpdateRepositoryCols(ctx, &repo_model.Repository{ID: repo.ID, IsEmpty: false, DefaultBranch: opts.NewBranch}, "is_empty", "default_branch") + _ = repo_model.UpdateRepositoryColsWithAutoTime(ctx, &repo_model.Repository{ID: repo.ID, IsEmpty: false, DefaultBranch: opts.NewBranch}, "is_empty", "default_branch") } } diff --git a/services/repository/fork.go b/services/repository/fork.go index c16c3d598a..bd1554f163 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -198,7 +198,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork // 8 - update repository status to be ready repo.Status = repo_model.RepositoryReady - if err = repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "status"); err != nil { return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) } diff --git a/services/repository/push.go b/services/repository/push.go index ba801ad019..31794034ba 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -283,7 +283,7 @@ func pushNewBranch(ctx context.Context, repo *repo_model.Repository, pusher *use } } // Update the is empty and default_branch columns - if err := repo_model.UpdateRepositoryCols(ctx, repo, "default_branch", "is_empty"); err != nil { + if err := repo_model.UpdateRepositoryColsWithAutoTime(ctx, repo, "default_branch", "is_empty"); err != nil { return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) } } diff --git a/services/repository/repository.go b/services/repository/repository.go index e078a8fc3c..739ef1ec38 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -205,7 +205,7 @@ func updateRepository(ctx context.Context, repo *repo_model.Repository, visibili e := db.GetEngine(ctx) - if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil { + if _, err = e.ID(repo.ID).NoAutoTime().AllCols().Update(repo); err != nil { return fmt.Errorf("update: %w", err) } diff --git a/services/repository/template.go b/services/repository/template.go index 95f585cead..621bd95cb1 100644 --- a/services/repository/template.go +++ b/services/repository/template.go @@ -184,7 +184,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ // 6 - update repository status to be ready generateRepo.Status = repo_model.RepositoryReady - if err = repo_model.UpdateRepositoryCols(ctx, generateRepo, "status"); err != nil { + if err = repo_model.UpdateRepositoryColsWithAutoTime(ctx, generateRepo, "status"); err != nil { return nil, fmt.Errorf("UpdateRepositoryCols: %w", err) } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index 86917ad285..5ad63cca67 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -160,7 +160,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName repo.OwnerName = newOwner.Name // Update repository. - if err := repo_model.UpdateRepositoryCols(ctx, repo, "owner_id", "owner_name"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "owner_id", "owner_name"); err != nil { return fmt.Errorf("update owner: %w", err) } @@ -304,7 +304,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName return fmt.Errorf("deleteRepositoryTransfer: %w", err) } repo.Status = repo_model.RepositoryReady - if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "status"); err != nil { return err } @@ -495,7 +495,7 @@ func RejectRepositoryTransfer(ctx context.Context, repo *repo_model.Repository, } repo.Status = repo_model.RepositoryReady - if err := repo_model.UpdateRepositoryCols(ctx, repo, "status"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "status"); err != nil { return err } @@ -543,7 +543,7 @@ func CancelRepositoryTransfer(ctx context.Context, repoTransfer *repo_model.Repo } repoTransfer.Repo.Status = repo_model.RepositoryReady - if err := repo_model.UpdateRepositoryCols(ctx, repoTransfer.Repo, "status"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repoTransfer.Repo, "status"); err != nil { return err } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 45a08dc5d6..9405f7cfc8 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -365,7 +365,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n } return db.WithTx(ctx, func(ctx context.Context) error { repo.DefaultWikiBranch = newBranch - if err := repo_model.UpdateRepositoryCols(ctx, repo, "default_wiki_branch"); err != nil { + if err := repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "default_wiki_branch"); err != nil { return fmt.Errorf("unable to update database: %w", err) } From 34281bc198a5ad9a1faa5285d4648b05d7218aaa Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 11 May 2025 16:56:24 -0700 Subject: [PATCH 24/32] Fix bug webhook milestone is not right. (#34419) Fix #34400 --------- Co-authored-by: silverwind --- routers/api/v1/repo/issue.go | 9 ++++ routers/api/v1/repo/pull.go | 5 ++ routers/web/repo/issue.go | 10 ++++ tests/integration/issue_test.go | 9 ++++ tests/integration/repo_webhook_test.go | 72 ++++++++++++++++++++++++++ 5 files changed, 105 insertions(+) diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index e678db5262..b9a71982d0 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -895,6 +895,15 @@ func EditIssue(ctx *context.APIContext) { issue.MilestoneID != *form.Milestone { oldMilestoneID := issue.MilestoneID issue.MilestoneID = *form.Milestone + if issue.MilestoneID > 0 { + issue.Milestone, err = issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, *form.Milestone) + if err != nil { + ctx.APIErrorInternal(err) + return + } + } else { + issue.Milestone = nil + } if err = issue_service.ChangeMilestoneAssign(ctx, issue, ctx.Doer, oldMilestoneID); err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index c0ab381bc8..f1ba06dd4a 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -706,6 +706,11 @@ func EditPullRequest(ctx *context.APIContext) { issue.MilestoneID != form.Milestone { oldMilestoneID := issue.MilestoneID issue.MilestoneID = form.Milestone + issue.Milestone, err = issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, form.Milestone) + if err != nil { + ctx.APIErrorInternal(err) + return + } if err = issue_service.ChangeMilestoneAssign(ctx, issue, ctx.Doer, oldMilestoneID); err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 86ee56b467..e70e8fdd7b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -418,6 +418,16 @@ func UpdateIssueMilestone(ctx *context.Context) { continue } issue.MilestoneID = milestoneID + if milestoneID > 0 { + var err error + issue.Milestone, err = issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, milestoneID) + if err != nil { + ctx.ServerError("GetMilestoneByRepoID", err) + return + } + } else { + issue.Milestone = nil + } if err := issue_service.ChangeMilestoneAssign(ctx, issue, ctx.Doer, oldMilestoneID); err != nil { ctx.ServerError("ChangeMilestoneAssign", err) return diff --git a/tests/integration/issue_test.go b/tests/integration/issue_test.go index f0a5e4f519..b403b3cf17 100644 --- a/tests/integration/issue_test.go +++ b/tests/integration/issue_test.go @@ -184,6 +184,15 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content, return int64(id) } +func testIssueChangeMilestone(t *testing.T, session *TestSession, repoLink string, issueID, milestoneID int64) { + req := NewRequestWithValues(t, "POST", fmt.Sprintf(repoLink+"/issues/milestone?issue_ids=%d", issueID), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "id": strconv.FormatInt(milestoneID, 10), + }) + resp := session.MakeRequest(t, req, http.StatusOK) + assert.Equal(t, `{"ok":true}`, strings.TrimSpace(resp.Body.String())) +} + func TestNewIssue(t *testing.T) { defer tests.PrepareTestEnv(t)() session := loginUser(t, "user2") diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index 34c2090b72..6cd58d1592 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -404,6 +404,78 @@ func Test_WebhookIssue(t *testing.T) { }) } +func Test_WebhookIssueMilestone(t *testing.T) { + var payloads []api.IssuePayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.IssuePayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "issues" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + repo1 := unittest.AssertExistsAndLoadBean(t, &repo.Repository{ID: 1}) + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "issue_milestone") + + t.Run("assign a milestone", func(t *testing.T) { + // trigger the webhook + testIssueChangeMilestone(t, session, repo1.Link(), 1, 1) + + // validate the webhook is triggered + assert.Equal(t, "issues", triggeredEvent) + assert.Len(t, payloads, 1) + assert.Equal(t, "milestoned", string(payloads[0].Action)) + assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name) + assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.Equal(t, "issue1", payloads[0].Issue.Title) + assert.Equal(t, "content for the first issue", payloads[0].Issue.Body) + assert.EqualValues(t, 1, payloads[0].Issue.Milestone.ID) + }) + + t.Run("change a milestong", func(t *testing.T) { + // trigger the webhook again + triggeredEvent = "" + payloads = make([]api.IssuePayload, 0, 1) + // change milestone to 2 + testIssueChangeMilestone(t, session, repo1.Link(), 1, 2) + + // validate the webhook is triggered + assert.Equal(t, "issues", triggeredEvent) + assert.Len(t, payloads, 1) + assert.Equal(t, "milestoned", string(payloads[0].Action)) + assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name) + assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.Equal(t, "issue1", payloads[0].Issue.Title) + assert.Equal(t, "content for the first issue", payloads[0].Issue.Body) + assert.EqualValues(t, 2, payloads[0].Issue.Milestone.ID) + }) + + t.Run("remove a milestone", func(t *testing.T) { + // trigger the webhook again + triggeredEvent = "" + payloads = make([]api.IssuePayload, 0, 1) + // change milestone to 0 + testIssueChangeMilestone(t, session, repo1.Link(), 1, 0) + + // validate the webhook is triggered + assert.Equal(t, "issues", triggeredEvent) + assert.Len(t, payloads, 1) + assert.Equal(t, "demilestoned", string(payloads[0].Action)) + assert.Equal(t, "repo1", payloads[0].Issue.Repo.Name) + assert.Equal(t, "user2/repo1", payloads[0].Issue.Repo.FullName) + assert.Equal(t, "issue1", payloads[0].Issue.Title) + assert.Equal(t, "content for the first issue", payloads[0].Issue.Body) + assert.Nil(t, payloads[0].Issue.Milestone) + }) + }) +} + func Test_WebhookPullRequest(t *testing.T) { var payloads []api.PullRequestPayload var triggeredEvent string From 0902d42fc753cd5f266046f003307285fe9507d5 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 12 May 2025 00:38:34 +0000 Subject: [PATCH 25/32] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index f6d6183e52..d91a06d205 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -117,6 +117,7 @@ files=文件 error=错误 error404=您正尝试访问的页面 不存在您尚未被授权 查看该页面。 +error503=服务器无法完成您的请求,请稍后重试。 go_back=返回 invalid_data=无效数据: %v @@ -129,6 +130,7 @@ pin=固定 unpin=取消置顶 artifacts=制品 +expired=已过期 confirm_delete_artifact=您确定要删除制品'%s'吗? archived=已归档 @@ -449,6 +451,7 @@ use_scratch_code=使用验证口令 twofa_scratch_used=你已经使用了你的验证口令。你将会转到两步验证设置页面以便移除你的注册设备或者重新生成新的验证口令。 twofa_passcode_incorrect=你的验证码不正确。如果你丢失了你的设备,请使用你的验证口令。 twofa_scratch_token_incorrect=你的验证口令不正确。 +twofa_required=您必须设置两步验证来访问仓库,或者尝试重新登录。 login_userpass=登录 login_openid=OpenID oauth_signup_tab=注册帐号 @@ -1524,7 +1527,7 @@ issues.move_to_column_of_project=`将此对象移至 %s 的 %s 中在 %s 上` issues.change_milestone_at=`%[3]s 修改了里程碑从 %[1]s%[2]s` issues.change_project_at=于 %[3]s 将此从项目 %[1]s 移到 %[2]s issues.remove_milestone_at=`%[2]s 删除了里程碑 %[1]s` -issues.remove_project_at=`从 %s 项目 %s 中删除` +issues.remove_project_at=`于 %[2]s 将此工单从项目 %[1]s 中删除` issues.deleted_milestone=(已删除) issues.deleted_project=`(已删除)` issues.self_assign_at=`于 %s 指派给自己` @@ -1877,6 +1880,7 @@ pulls.add_prefix=添加 %s 前缀 pulls.remove_prefix=删除 %s 前缀 pulls.data_broken=此合并请求因为派生仓库信息缺失而中断。 pulls.files_conflicted=此合并请求有变更与目标分支冲突。 +pulls.is_checking=正在进行合并冲突检测 ... pulls.is_ancestor=此分支已经包含在目标分支中,没有什么可以合并。 pulls.is_empty=此分支上的更改已经在目标分支上。这将是一个空提交。 pulls.required_status_check_failed=一些必要的检查没有成功 @@ -3724,7 +3728,11 @@ creation.name_placeholder=不区分大小写,字母数字或下划线不能以 creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略 creation.description_placeholder=输入简短描述(可选)。 +save_success=密钥 '%s' 保存成功。 +save_failed=密钥保存失败。 +add_secret=添加密钥 +edit_secret=编辑密钥 deletion=删除密钥 deletion.description=删除密钥是永久性的,无法撤消。继续吗? deletion.success=此Secret已被删除。 @@ -3841,6 +3849,8 @@ deleted.display_name=已删除项目 type-1.display_name=个人项目 type-2.display_name=仓库项目 type-3.display_name=组织项目 +enter_fullscreen=全屏 +exit_fullscreen=退出全屏 [git.filemode] changed_filemode=%[1]s -> %[2]s From 355e9a9d544aa2d3f3a17b06cdb2bf1ceb290fd7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 11 May 2025 18:06:34 -0700 Subject: [PATCH 26/32] Add a webhook push test for dev branch (#34421) --- tests/integration/repo_webhook_test.go | 50 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/tests/integration/repo_webhook_test.go b/tests/integration/repo_webhook_test.go index 6cd58d1592..13e3d198ea 100644 --- a/tests/integration/repo_webhook_test.go +++ b/tests/integration/repo_webhook_test.go @@ -56,16 +56,21 @@ func TestNewWebHookLink(t *testing.T) { } } -func testAPICreateWebhookForRepo(t *testing.T, session *TestSession, userName, repoName, url, event string) { +func testAPICreateWebhookForRepo(t *testing.T, session *TestSession, userName, repoName, url, event string, branchFilter ...string) { token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeAll) + var branchFilterString string + if len(branchFilter) > 0 { + branchFilterString = branchFilter[0] + } req := NewRequestWithJSON(t, "POST", "/api/v1/repos/"+userName+"/"+repoName+"/hooks", api.CreateHookOption{ Type: "gitea", Config: api.CreateHookOptionConfig{ "content_type": "json", "url": url, }, - Events: []string{event}, - Active: true, + Events: []string{event}, + Active: true, + BranchFilter: branchFilterString, }).AddTokenAuth(token) MakeRequest(t, req, http.StatusCreated) } @@ -371,6 +376,45 @@ func Test_WebhookPush(t *testing.T) { }) } +func Test_WebhookPushDevBranch(t *testing.T) { + var payloads []api.PushPayload + var triggeredEvent string + provider := newMockWebhookProvider(func(r *http.Request) { + content, _ := io.ReadAll(r.Body) + var payload api.PushPayload + err := json.Unmarshal(content, &payload) + assert.NoError(t, err) + payloads = append(payloads, payload) + triggeredEvent = "push" + }, http.StatusOK) + defer provider.Close() + + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + // 1. create a new webhook with special webhook for repo1 + session := loginUser(t, "user2") + + // only for dev branch + testAPICreateWebhookForRepo(t, session, "user2", "repo1", provider.URL(), "push", "develop") + + // 2. this should not trigger the webhook + testCreateFile(t, session, "user2", "repo1", "master", "test_webhook_push.md", "# a test file for webhook push") + assert.Empty(t, triggeredEvent) + assert.Empty(t, payloads) + + // 3. trigger the webhook + testCreateFile(t, session, "user2", "repo1", "develop", "test_webhook_push.md", "# a test file for webhook push") + + // 4. validate the webhook is triggered + assert.Equal(t, "push", triggeredEvent) + assert.Len(t, payloads, 1) + assert.Equal(t, "repo1", payloads[0].Repo.Name) + assert.Equal(t, "develop", payloads[0].Branch()) + assert.Equal(t, "user2/repo1", payloads[0].Repo.FullName) + assert.Len(t, payloads[0].Commits, 1) + assert.Equal(t, []string{"test_webhook_push.md"}, payloads[0].Commits[0].Added) + }) +} + func Test_WebhookIssue(t *testing.T) { var payloads []api.IssuePayload var triggeredEvent string From 4011e2245bcd96f53077f73b7a33b1a754f7151f Mon Sep 17 00:00:00 2001 From: badhezi Date: Mon, 12 May 2025 23:10:40 +0300 Subject: [PATCH 27/32] Fix releases sidebar navigation link (#34436) Resolves https://github.com/go-gitea/gitea/issues/34435 --- templates/repo/home_sidebar_bottom.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/home_sidebar_bottom.tmpl b/templates/repo/home_sidebar_bottom.tmpl index f780dc122d..f66faf6d10 100644 --- a/templates/repo/home_sidebar_bottom.tmpl +++ b/templates/repo/home_sidebar_bottom.tmpl @@ -4,7 +4,7 @@
- + {{ctx.Locale.Tr "repo.releases"}} {{.NumReleases}} From b5fd3e7210cfbcb87015f3a5b8c3f25eab2a5715 Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 13 May 2025 08:52:25 +0200 Subject: [PATCH 28/32] Fix comment textarea scroll issue in Firefox (#34438) In the comment editor, there is a bug in Firefox where the scroll position unexpectedly moves up, which is annoying. This is not reproducible in Chrome and Safari. To reproduce here are some steps: - Go into an editable issue - Scroll page to bottom - Focus the textarea and press Return many times, causing the textarea to get a scrollbar - Scroll page to bottom again - Press Return once more - Page should not scroll up. This fixes the bug by adding a temporary margin, and I verified it works in all browsers. Co-authored-by: wxiaoguang --- web_src/js/utils/dom.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web_src/js/utils/dom.ts b/web_src/js/utils/dom.ts index 83a0d9c8df..8f758bf9ac 100644 --- a/web_src/js/utils/dom.ts +++ b/web_src/js/utils/dom.ts @@ -161,6 +161,7 @@ export function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = function resizeToFit() { if (isUserResized) return; if (textarea.offsetWidth <= 0 && textarea.offsetHeight <= 0) return; + const previousMargin = textarea.style.marginBottom; try { const {top, bottom} = overflowOffset(); @@ -176,6 +177,9 @@ export function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = const curHeight = parseFloat(computedStyle.height); const maxHeight = curHeight + bottom - adjustedViewportMarginBottom; + // In Firefox, setting auto height momentarily may cause the page to scroll up + // unexpectedly, prevent this by setting a temporary margin. + textarea.style.marginBottom = `${textarea.clientHeight}px`; textarea.style.height = 'auto'; let newHeight = textarea.scrollHeight + borderAddOn; @@ -196,6 +200,12 @@ export function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = textarea.style.height = `${newHeight}px`; lastStyleHeight = textarea.style.height; } finally { + // restore previous margin + if (previousMargin) { + textarea.style.marginBottom = previousMargin; + } else { + textarea.style.removeProperty('margin-bottom'); + } // ensure that the textarea is fully scrolled to the end, when the cursor // is at the end during an input event if (textarea.selectionStart === textarea.selectionEnd && From 5cb4cbf044e2f0483afc92516bb4b9aff6ea2b9a Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 13 May 2025 16:18:45 +0800 Subject: [PATCH 29/32] Fix repo broken check (#34444) Fix #34424 --- routers/web/repo/view_home.go | 11 ++++++--- services/context/repo.go | 4 ++-- tests/integration/empty_repo_test.go | 36 +++++++++++++++++----------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index 3b053821ee..48fa47d738 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -21,6 +21,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" giturl "code.gitea.io/gitea/modules/git/url" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -261,6 +262,10 @@ func updateContextRepoEmptyAndStatus(ctx *context.Context, empty bool, status re func handleRepoEmptyOrBroken(ctx *context.Context) { showEmpty := true + if ctx.Repo.GitRepo == nil { + // in case the repo really exists and works, but the status was incorrectly marked as "broken", we need to open and check it again + ctx.Repo.GitRepo, _ = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) + } if ctx.Repo.GitRepo != nil { reallyEmpty, err := ctx.Repo.GitRepo.IsEmpty() if err != nil { @@ -396,10 +401,8 @@ func Home(ctx *context.Context) { return } - prepareHomeTreeSideBarSwitch(ctx) - title := ctx.Repo.Repository.Owner.Name + "/" + ctx.Repo.Repository.Name - if len(ctx.Repo.Repository.Description) > 0 { + if ctx.Repo.Repository.Description != "" { title += ": " + ctx.Repo.Repository.Description } ctx.Data["Title"] = title @@ -412,6 +415,8 @@ func Home(ctx *context.Context) { return } + prepareHomeTreeSideBarSwitch(ctx) + // get the current git entry which doer user is currently looking at. entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) if err != nil { diff --git a/services/context/repo.go b/services/context/repo.go index 127d313258..ea772c508d 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -795,8 +795,8 @@ func RepoRefByType(detectRefType git.RefType) func(*Context) { return func(ctx *Context) { var err error refType := detectRefType - if ctx.Repo.Repository.IsBeingCreated() { - return // no git repo, so do nothing, users will see a "migrating" UI provided by "migrate/migrating.tmpl" + if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() { + return // no git repo, so do nothing, users will see a "migrating" UI provided by "migrate/migrating.tmpl", or empty repo guide } // Empty repository does not have reference information. if ctx.Repo.Repository.IsEmpty { diff --git a/tests/integration/empty_repo_test.go b/tests/integration/empty_repo_test.go index f85d883cc7..8cebfaf32a 100644 --- a/tests/integration/empty_repo_test.go +++ b/tests/integration/empty_repo_test.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" @@ -100,22 +101,29 @@ func TestEmptyRepoAddFile(t *testing.T) { assert.Contains(t, resp.Body.String(), "test-file.md") // if the repo is in incorrect state, it should be able to self-heal (recover to correct state) - user30EmptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"}) - user30EmptyRepo.IsEmpty = true - user30EmptyRepo.DefaultBranch = "no-such" - _, err := db.GetEngine(db.DefaultContext).ID(user30EmptyRepo.ID).Cols("is_empty", "default_branch").Update(user30EmptyRepo) - require.NoError(t, err) - user30EmptyRepo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"}) - assert.True(t, user30EmptyRepo.IsEmpty) + testEmptyOrBrokenRecover := func(t *testing.T, isEmpty, isBroken bool) { + user30EmptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"}) + user30EmptyRepo.IsEmpty = isEmpty + user30EmptyRepo.Status = util.Iif(isBroken, repo_model.RepositoryBroken, repo_model.RepositoryReady) + user30EmptyRepo.DefaultBranch = "no-such" + _, err := db.GetEngine(db.DefaultContext).ID(user30EmptyRepo.ID).Cols("is_empty", "status", "default_branch").Update(user30EmptyRepo) + require.NoError(t, err) + user30EmptyRepo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerID: 30, Name: "empty"}) + assert.Equal(t, isEmpty, user30EmptyRepo.IsEmpty) + assert.Equal(t, isBroken, user30EmptyRepo.Status == repo_model.RepositoryBroken) - req = NewRequest(t, "GET", "/user30/empty") - resp = session.MakeRequest(t, req, http.StatusSeeOther) - redirect = test.RedirectURL(resp) - assert.Equal(t, "/user30/empty", redirect) + req = NewRequest(t, "GET", "/user30/empty") + resp = session.MakeRequest(t, req, http.StatusSeeOther) + redirect = test.RedirectURL(resp) + assert.Equal(t, "/user30/empty", redirect) - req = NewRequest(t, "GET", "/user30/empty") - resp = session.MakeRequest(t, req, http.StatusOK) - assert.Contains(t, resp.Body.String(), "test-file.md") + req = NewRequest(t, "GET", "/user30/empty") + resp = session.MakeRequest(t, req, http.StatusOK) + assert.Contains(t, resp.Body.String(), "test-file.md") + } + testEmptyOrBrokenRecover(t, true, false) + testEmptyOrBrokenRecover(t, false, true) + testEmptyOrBrokenRecover(t, true, true) } func TestEmptyRepoUploadFile(t *testing.T) { From a0595add72db4a5fb421579b9c6bb7dae1392c86 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Tue, 13 May 2025 20:33:56 +0200 Subject: [PATCH 30/32] Fix remove org user failure on mssql (#34449) * mssql does not support fetching 0 repositories * remove paging by NumRepos that might be 0 * extend admin api test to purge user 2 Fixes #34448 --------- Co-authored-by: wxiaoguang --- models/activities/action.go | 2 +- models/organization/org_test.go | 21 +-------------- models/repo/org_repo.go | 31 +++------------------ services/org/user.go | 3 ++- tests/integration/admin_user_test.go | 40 +++++++++++++++++++++++----- 5 files changed, 41 insertions(+), 56 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index c89ba3e14e..6f1837d9f6 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -530,7 +530,7 @@ func ActivityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder. if opts.RequestedTeam != nil { env := repo_model.AccessibleTeamReposEnv(organization.OrgFromUser(opts.RequestedUser), opts.RequestedTeam) - teamRepoIDs, err := env.RepoIDs(ctx, 1, opts.RequestedUser.NumRepos) + teamRepoIDs, err := env.RepoIDs(ctx) if err != nil { return nil, fmt.Errorf("GetTeamRepositories: %w", err) } diff --git a/models/organization/org_test.go b/models/organization/org_test.go index 666a6c44d4..234325a8cd 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -334,7 +334,7 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) { testSuccess := func(userID int64, expectedRepoIDs []int64) { env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID) assert.NoError(t, err) - repoIDs, err := env.RepoIDs(db.DefaultContext, 1, 100) + repoIDs, err := env.RepoIDs(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, expectedRepoIDs, repoIDs) } @@ -342,25 +342,6 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) { testSuccess(4, []int64{3, 32}) } -func TestAccessibleReposEnv_Repos(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) - org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - testSuccess := func(userID int64, expectedRepoIDs []int64) { - env, err := repo_model.AccessibleReposEnv(db.DefaultContext, org, userID) - assert.NoError(t, err) - repos, err := env.Repos(db.DefaultContext, 1, 100) - assert.NoError(t, err) - expectedRepos := make(repo_model.RepositoryList, len(expectedRepoIDs)) - for i, repoID := range expectedRepoIDs { - expectedRepos[i] = unittest.AssertExistsAndLoadBean(t, - &repo_model.Repository{ID: repoID}) - } - assert.Equal(t, expectedRepos, repos) - } - testSuccess(2, []int64{3, 5, 32}) - testSuccess(4, []int64{3, 32}) -} - func TestAccessibleReposEnv_MirrorRepos(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) diff --git a/models/repo/org_repo.go b/models/repo/org_repo.go index fa519d25b1..96f21ba2ac 100644 --- a/models/repo/org_repo.go +++ b/models/repo/org_repo.go @@ -48,8 +48,7 @@ func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) (Repo // accessible to a particular user type AccessibleReposEnvironment interface { CountRepos(ctx context.Context) (int64, error) - RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error) - Repos(ctx context.Context, page, pageSize int) (RepositoryList, error) + RepoIDs(ctx context.Context) ([]int64, error) MirrorRepos(ctx context.Context) (RepositoryList, error) AddKeyword(keyword string) SetSort(db.SearchOrderBy) @@ -132,40 +131,18 @@ func (env *accessibleReposEnv) CountRepos(ctx context.Context) (int64, error) { return repoCount, nil } -func (env *accessibleReposEnv) RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error) { - if page <= 0 { - page = 1 - } - - repoIDs := make([]int64, 0, pageSize) +func (env *accessibleReposEnv) RepoIDs(ctx context.Context) ([]int64, error) { + var repoIDs []int64 return repoIDs, db.GetEngine(ctx). Table("repository"). Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id"). Where(env.cond()). - GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]). + GroupBy("`repository`.id,`repository`." + strings.Fields(string(env.orderBy))[0]). OrderBy(string(env.orderBy)). - Limit(pageSize, (page-1)*pageSize). Cols("`repository`.id"). Find(&repoIDs) } -func (env *accessibleReposEnv) Repos(ctx context.Context, page, pageSize int) (RepositoryList, error) { - repoIDs, err := env.RepoIDs(ctx, page, pageSize) - if err != nil { - return nil, fmt.Errorf("GetUserRepositoryIDs: %w", err) - } - - repos := make([]*Repository, 0, len(repoIDs)) - if len(repoIDs) == 0 { - return repos, nil - } - - return repos, db.GetEngine(ctx). - In("`repository`.id", repoIDs). - OrderBy(string(env.orderBy)). - Find(&repos) -} - func (env *accessibleReposEnv) MirrorRepoIDs(ctx context.Context) ([]int64, error) { repoIDs := make([]int64, 0, 10) return repoIDs, db.GetEngine(ctx). diff --git a/services/org/user.go b/services/org/user.go index 3565ecc2fc..26927253d2 100644 --- a/services/org/user.go +++ b/services/org/user.go @@ -64,10 +64,11 @@ func RemoveOrgUser(ctx context.Context, org *organization.Organization, user *us if err != nil { return fmt.Errorf("AccessibleReposEnv: %w", err) } - repoIDs, err := env.RepoIDs(ctx, 1, org.NumRepos) + repoIDs, err := env.RepoIDs(ctx) if err != nil { return fmt.Errorf("GetUserRepositories [%d]: %w", user.ID, err) } + for _, repoID := range repoIDs { repo, err := repo_model.GetRepositoryByID(ctx, repoID) if err != nil { diff --git a/tests/integration/admin_user_test.go b/tests/integration/admin_user_test.go index d5d7e70bc7..95e03ab750 100644 --- a/tests/integration/admin_user_test.go +++ b/tests/integration/admin_user_test.go @@ -4,6 +4,7 @@ package integration import ( + "fmt" "net/http" "strconv" "testing" @@ -72,12 +73,37 @@ func TestAdminDeleteUser(t *testing.T) { session := loginUser(t, "user1") - csrf := GetUserCSRFToken(t, session) - req := NewRequestWithValues(t, "POST", "/-/admin/users/8/delete", map[string]string{ - "_csrf": csrf, - }) - session.MakeRequest(t, req, http.StatusSeeOther) + usersToDelete := []struct { + userID int64 + purge bool + }{ + { + userID: 2, + purge: true, + }, + { + userID: 8, + }, + } - assertUserDeleted(t, 8) - unittest.CheckConsistencyFor(t, &user_model.User{}) + for _, entry := range usersToDelete { + t.Run(fmt.Sprintf("DeleteUser%d", entry.userID), func(t *testing.T) { + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: entry.userID}) + assert.NotNil(t, user) + + var query string + if entry.purge { + query = "?purge=true" + } + + csrf := GetUserCSRFToken(t, session) + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/-/admin/users/%d/delete%s", entry.userID, query), map[string]string{ + "_csrf": csrf, + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + assertUserDeleted(t, entry.userID) + unittest.CheckConsistencyFor(t, &user_model.User{}) + }) + } } From 1e2f3514b9afd903e19a0413e5d925515e13abf8 Mon Sep 17 00:00:00 2001 From: NorthRealm <155140859+NorthRealm@users.noreply.github.com> Date: Wed, 14 May 2025 03:18:13 +0800 Subject: [PATCH 31/32] Add endpoint deleting workflow run (#34337) Add endpoint deleting workflow run Resolves #26219 /claim #26219 --------- Co-authored-by: Lunny Xiao Co-authored-by: wxiaoguang --- models/actions/run.go | 20 +- models/actions/run_job.go | 4 +- models/actions/task_list.go | 4 + models/fixtures/action_artifact.yml | 36 ++++ models/fixtures/action_run.yml | 22 ++- models/fixtures/action_run_job.yml | 30 +++ models/fixtures/action_task.yml | 40 ++++ options/locale/locale_en-US.ini | 3 + routers/api/v1/api.go | 5 +- routers/api/v1/repo/action.go | 52 +++++ routers/web/repo/actions/actions.go | 2 + routers/web/repo/actions/view.go | 27 +++ routers/web/repo/branch.go | 2 +- routers/web/web.go | 1 + services/actions/cleanup.go | 108 ++++++++++- services/context/api.go | 5 +- services/context/context.go | 9 + templates/repo/actions/runs_list.tmpl | 35 ++-- templates/shared/secrets/add_list.tmpl | 4 +- templates/swagger/v1_json.tmpl | 46 +++++ tests/integration/actions_delete_run_test.go | 181 ++++++++++++++++++ .../api_actions_delete_run_test.go | 98 ++++++++++ 22 files changed, 691 insertions(+), 43 deletions(-) create mode 100644 tests/integration/actions_delete_run_test.go create mode 100644 tests/integration/api_actions_delete_run_test.go diff --git a/models/actions/run.go b/models/actions/run.go index c19fce67ae..498a73dc20 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -16,6 +16,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -343,13 +344,13 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork return committer.Commit() } -func GetRunByID(ctx context.Context, id int64) (*ActionRun, error) { +func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) { var run ActionRun - has, err := db.GetEngine(ctx).Where("id=?", id).Get(&run) + has, err := db.GetEngine(ctx).Where("id=? AND repo_id=?", runID, repoID).Get(&run) if err != nil { return nil, err } else if !has { - return nil, fmt.Errorf("run with id %d: %w", id, util.ErrNotExist) + return nil, fmt.Errorf("run with id %d: %w", runID, util.ErrNotExist) } return &run, nil @@ -420,17 +421,10 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error { if run.Status != 0 || slices.Contains(cols, "status") { if run.RepoID == 0 { - run, err = GetRunByID(ctx, run.ID) - if err != nil { - return err - } + setting.PanicInDevOrTesting("RepoID should not be 0") } - if run.Repo == nil { - repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) - if err != nil { - return err - } - run.Repo = repo + if err = run.LoadRepo(ctx); err != nil { + return err } if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil { return err diff --git a/models/actions/run_job.go b/models/actions/run_job.go index d0dfd10db6..c0df19b020 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -51,7 +51,7 @@ func (job *ActionRunJob) Duration() time.Duration { func (job *ActionRunJob) LoadRun(ctx context.Context) error { if job.Run == nil { - run, err := GetRunByID(ctx, job.RunID) + run, err := GetRunByRepoAndID(ctx, job.RepoID, job.RunID) if err != nil { return err } @@ -142,7 +142,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col { // Other goroutines may aggregate the status of the run and update it too. // So we need load the run and its jobs before updating the run. - run, err := GetRunByID(ctx, job.RunID) + run, err := GetRunByRepoAndID(ctx, job.RepoID, job.RunID) if err != nil { return 0, err } diff --git a/models/actions/task_list.go b/models/actions/task_list.go index df4b43c5ef..0c80397899 100644 --- a/models/actions/task_list.go +++ b/models/actions/task_list.go @@ -48,6 +48,7 @@ func (tasks TaskList) LoadAttributes(ctx context.Context) error { type FindTaskOptions struct { db.ListOptions RepoID int64 + JobID int64 OwnerID int64 CommitSHA string Status Status @@ -61,6 +62,9 @@ func (opts FindTaskOptions) ToConds() builder.Cond { if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) } + if opts.JobID > 0 { + cond = cond.And(builder.Eq{"job_id": opts.JobID}) + } if opts.OwnerID > 0 { cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) } diff --git a/models/fixtures/action_artifact.yml b/models/fixtures/action_artifact.yml index 1b00daf198..ee8ef0d5ce 100644 --- a/models/fixtures/action_artifact.yml +++ b/models/fixtures/action_artifact.yml @@ -105,3 +105,39 @@ created_unix: 1730330775 updated_unix: 1730330775 expired_unix: 1738106775 + +- + id: 24 + run_id: 795 + runner_id: 1 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + storage_path: "27/5/1730330775594233150.chunk" + file_size: 1024 + file_compressed_size: 1024 + content_encoding: "application/zip" + artifact_path: "artifact-795-1.zip" + artifact_name: "artifact-795-1" + status: 2 + created_unix: 1730330775 + updated_unix: 1730330775 + expired_unix: 1738106775 + +- + id: 25 + run_id: 795 + runner_id: 1 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + storage_path: "27/5/1730330775594233150.chunk" + file_size: 1024 + file_compressed_size: 1024 + content_encoding: "application/zip" + artifact_path: "artifact-795-2.zip" + artifact_name: "artifact-795-2" + status: 2 + created_unix: 1730330775 + updated_unix: 1730330775 + expired_unix: 1738106775 diff --git a/models/fixtures/action_run.yml b/models/fixtures/action_run.yml index 1db849352f..ae7dc481ec 100644 --- a/models/fixtures/action_run.yml +++ b/models/fixtures/action_run.yml @@ -48,7 +48,7 @@ commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" is_fork_pull_request: 0 - status: 1 + status: 6 # running started: 1683636528 stopped: 1683636626 created: 1683636108 @@ -74,3 +74,23 @@ updated: 1683636626 need_approval: 0 approved_by: 0 + +- + id: 795 + title: "to be deleted (test)" + repo_id: 2 + owner_id: 2 + workflow_id: "test.yaml" + index: 191 + trigger_user_id: 1 + ref: "refs/heads/test" + commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" + event: "push" + is_fork_pull_request: 0 + status: 2 + started: 1683636528 + stopped: 1683636626 + created: 1683636108 + updated: 1683636626 + need_approval: 0 + approved_by: 0 diff --git a/models/fixtures/action_run_job.yml b/models/fixtures/action_run_job.yml index 8837e6ec2d..72f8627224 100644 --- a/models/fixtures/action_run_job.yml +++ b/models/fixtures/action_run_job.yml @@ -69,3 +69,33 @@ status: 5 started: 1683636528 stopped: 1683636626 + +- + id: 198 + run_id: 795 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: 0 + name: job_1 + attempt: 1 + job_id: job_1 + task_id: 53 + status: 1 + started: 1683636528 + stopped: 1683636626 + +- + id: 199 + run_id: 795 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: 0 + name: job_2 + attempt: 1 + job_id: job_2 + task_id: 54 + status: 2 + started: 1683636528 + stopped: 1683636626 diff --git a/models/fixtures/action_task.yml b/models/fixtures/action_task.yml index 506a47d8a0..76fdac343b 100644 --- a/models/fixtures/action_task.yml +++ b/models/fixtures/action_task.yml @@ -117,3 +117,43 @@ log_length: 707 log_size: 90179 log_expired: 0 +- + id: 53 + job_id: 198 + attempt: 1 + runner_id: 1 + status: 1 + started: 1683636528 + stopped: 1683636626 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: 0 + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784223 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: 1 + log_length: 0 + log_size: 0 + log_expired: 0 +- + id: 54 + job_id: 199 + attempt: 1 + runner_id: 1 + status: 2 + started: 1683636528 + stopped: 1683636626 + repo_id: 2 + owner_id: 2 + commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0 + is_fork_pull_request: 0 + token_hash: b8d3962425466b6709b9ac51446f93260c54afe8e7b6d3686e34f991fb8a8953822b0deed86fe41a103f34bc48dbc4784224 + token_salt: ffffffffff + token_last_eight: ffffffff + log_filename: artifact-test2/2f/47.log + log_in_storage: 1 + log_length: 0 + log_size: 0 + log_expired: 0 diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index af3b948a88..b6411f7777 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3811,6 +3811,9 @@ runs.no_workflows.documentation = For more information on Gitea Actions, see 0 || len(runs) > 0 + + ctx.Data["AllowDeleteWorkflowRuns"] = ctx.Repo.CanWrite(unit.TypeActions) } // loadIsRefDeleted loads the IsRefDeleted field for each run in the list. diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index dd18c8380d..9840465bff 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -577,6 +577,33 @@ func Approve(ctx *context_module.Context) { ctx.JSON(http.StatusOK, struct{}{}) } +func Delete(ctx *context_module.Context) { + runIndex := getRunIndex(ctx) + repoID := ctx.Repo.Repository.ID + + run, err := actions_model.GetRunByIndex(ctx, repoID, runIndex) + if err != nil { + if errors.Is(err, util.ErrNotExist) { + ctx.JSONErrorNotFound() + return + } + ctx.ServerError("GetRunByIndex", err) + return + } + + if !run.Status.IsDone() { + ctx.JSONError(ctx.Tr("actions.runs.not_done")) + return + } + + if err := actions_service.DeleteRun(ctx, run); err != nil { + ctx.ServerError("DeleteRun", err) + return + } + + ctx.JSONOK() +} + // getRunJobs gets the jobs of runIndex, and returns jobs[jobIndex], jobs. // Any error will be written to the ctx. // It never returns a nil job of an empty jobs, if the jobIndex is out of range, it will be treated as 0. diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index 5d963eff66..5d382ebd71 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -264,7 +264,7 @@ func MergeUpstream(ctx *context.Context) { _, err := repo_service.MergeUpstream(ctx, ctx.Doer, ctx.Repo.Repository, branchName) if err != nil { if errors.Is(err, util.ErrNotExist) { - ctx.JSONError(ctx.Tr("error.not_found")) + ctx.JSONErrorNotFound() return } else if pull_service.IsErrMergeConflicts(err) { ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict")) diff --git a/routers/web/web.go b/routers/web/web.go index bd850baec0..866401252d 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1447,6 +1447,7 @@ func registerWebRoutes(m *web.Router) { }) m.Post("/cancel", reqRepoActionsWriter, actions.Cancel) m.Post("/approve", reqRepoActionsWriter, actions.Approve) + m.Post("/delete", reqRepoActionsWriter, actions.Delete) m.Get("/artifacts/{artifact_name}", actions.ArtifactsDownloadView) m.Delete("/artifacts/{artifact_name}", reqRepoActionsWriter, actions.ArtifactsDeleteView) m.Post("/rerun", reqRepoActionsWriter, actions.Rerun) diff --git a/services/actions/cleanup.go b/services/actions/cleanup.go index 23d6e3a49d..5595649517 100644 --- a/services/actions/cleanup.go +++ b/services/actions/cleanup.go @@ -5,12 +5,14 @@ package actions import ( "context" + "errors" "fmt" "time" actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" actions_module "code.gitea.io/gitea/modules/actions" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" @@ -27,7 +29,7 @@ func Cleanup(ctx context.Context) error { } // clean up old logs - if err := CleanupLogs(ctx); err != nil { + if err := CleanupExpiredLogs(ctx); err != nil { return fmt.Errorf("cleanup logs: %w", err) } @@ -98,8 +100,15 @@ func cleanNeedDeleteArtifacts(taskCtx context.Context) error { const deleteLogBatchSize = 100 -// CleanupLogs removes logs which are older than the configured retention time -func CleanupLogs(ctx context.Context) error { +func removeTaskLog(ctx context.Context, task *actions_model.ActionTask) { + if err := actions_module.RemoveLogs(ctx, task.LogInStorage, task.LogFilename); err != nil { + log.Error("Failed to remove log %s (in storage %v) of task %v: %v", task.LogFilename, task.LogInStorage, task.ID, err) + // do not return error here, go on + } +} + +// CleanupExpiredLogs removes logs which are older than the configured retention time +func CleanupExpiredLogs(ctx context.Context) error { olderThan := timeutil.TimeStampNow().AddDuration(-time.Duration(setting.Actions.LogRetentionDays) * 24 * time.Hour) count := 0 @@ -109,10 +118,7 @@ func CleanupLogs(ctx context.Context) error { return fmt.Errorf("find old tasks: %w", err) } for _, task := range tasks { - if err := actions_module.RemoveLogs(ctx, task.LogInStorage, task.LogFilename); err != nil { - log.Error("Failed to remove log %s (in storage %v) of task %v: %v", task.LogFilename, task.LogInStorage, task.ID, err) - // do not return error here, go on - } + removeTaskLog(ctx, task) task.LogIndexes = nil // clear log indexes since it's a heavy field task.LogExpired = true if err := actions_model.UpdateTask(ctx, task, "log_indexes", "log_expired"); err != nil { @@ -148,3 +154,91 @@ func CleanupEphemeralRunners(ctx context.Context) error { log.Info("Removed %d runners", affected) return nil } + +// DeleteRun deletes workflow run, including all logs and artifacts. +func DeleteRun(ctx context.Context, run *actions_model.ActionRun) error { + if !run.Status.IsDone() { + return errors.New("run is not done") + } + + repoID := run.RepoID + + jobs, err := actions_model.GetRunJobsByRunID(ctx, run.ID) + if err != nil { + return err + } + jobIDs := container.FilterSlice(jobs, func(j *actions_model.ActionRunJob) (int64, bool) { + return j.ID, true + }) + tasks := make(actions_model.TaskList, 0) + if len(jobIDs) > 0 { + if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).In("job_id", jobIDs).Find(&tasks); err != nil { + return err + } + } + + artifacts, err := db.Find[actions_model.ActionArtifact](ctx, actions_model.FindArtifactsOptions{ + RepoID: repoID, + RunID: run.ID, + }) + if err != nil { + return err + } + + var recordsToDelete []any + + recordsToDelete = append(recordsToDelete, &actions_model.ActionRun{ + RepoID: repoID, + ID: run.ID, + }) + recordsToDelete = append(recordsToDelete, &actions_model.ActionRunJob{ + RepoID: repoID, + RunID: run.ID, + }) + for _, tas := range tasks { + recordsToDelete = append(recordsToDelete, &actions_model.ActionTask{ + RepoID: repoID, + ID: tas.ID, + }) + recordsToDelete = append(recordsToDelete, &actions_model.ActionTaskStep{ + RepoID: repoID, + TaskID: tas.ID, + }) + recordsToDelete = append(recordsToDelete, &actions_model.ActionTaskOutput{ + TaskID: tas.ID, + }) + } + recordsToDelete = append(recordsToDelete, &actions_model.ActionArtifact{ + RepoID: repoID, + RunID: run.ID, + }) + + if err := db.WithTx(ctx, func(ctx context.Context) error { + // TODO: Deleting task records could break current ephemeral runner implementation. This is a temporary workaround suggested by ChristopherHX. + // Since you delete potentially the only task an ephemeral act_runner has ever run, please delete the affected runners first. + // one of + // call cleanup ephemeral runners first + // delete affected ephemeral act_runners + // I would make ephemeral runners fully delete directly before formally finishing the task + // + // See also: https://github.com/go-gitea/gitea/pull/34337#issuecomment-2862222788 + if err := CleanupEphemeralRunners(ctx); err != nil { + return err + } + return db.DeleteBeans(ctx, recordsToDelete...) + }); err != nil { + return err + } + + // Delete files on storage + for _, tas := range tasks { + removeTaskLog(ctx, tas) + } + for _, art := range artifacts { + if err := storage.ActionsArtifacts.Delete(art.StoragePath); err != nil { + log.Error("remove artifact file %q: %v", art.StoragePath, err) + } + } + + return nil +} diff --git a/services/context/api.go b/services/context/api.go index d43e15bf24..28f0e43d88 100644 --- a/services/context/api.go +++ b/services/context/api.go @@ -245,7 +245,7 @@ func APIContexter() func(http.Handler) http.Handler { // APIErrorNotFound handles 404s for APIContext // String will replace message, errors will be added to a slice func (ctx *APIContext) APIErrorNotFound(objs ...any) { - message := ctx.Locale.TrString("error.not_found") + var message string var errs []string for _, obj := range objs { // Ignore nil @@ -259,9 +259,8 @@ func (ctx *APIContext) APIErrorNotFound(objs ...any) { message = obj.(string) } } - ctx.JSON(http.StatusNotFound, map[string]any{ - "message": message, + "message": util.IfZero(message, "not found"), // do not use locale in API "url": setting.API.SwaggerURL, "errors": errs, }) diff --git a/services/context/context.go b/services/context/context.go index 7f623f85bd..32ec260aab 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/middleware" web_types "code.gitea.io/gitea/modules/web/types" @@ -261,3 +262,11 @@ func (ctx *Context) JSONError(msg any) { panic(fmt.Sprintf("unsupported type: %T", msg)) } } + +func (ctx *Context) JSONErrorNotFound(optMsg ...string) { + msg := util.OptionalArg(optMsg) + if msg == "" { + msg = ctx.Locale.TrString("error.not_found") + } + ctx.JSON(http.StatusNotFound, map[string]any{"errorMessage": msg, "renderFormat": "text"}) +} diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl index fa1adb3e3b..4ebedcd73b 100644 --- a/templates/repo/actions/runs_list.tmpl +++ b/templates/repo/actions/runs_list.tmpl @@ -5,37 +5,46 @@

{{if $.IsFiltered}}{{ctx.Locale.Tr "actions.runs.no_results"}}{{else}}{{ctx.Locale.Tr "actions.runs.no_runs"}}{{end}}

{{end}} - {{range .Runs}} + {{range $run := .Runs}}
- {{template "repo/actions/status" (dict "status" .Status.String)}} + {{template "repo/actions/status" (dict "status" $run.Status.String)}}
- - {{if .Title}}{{.Title}}{{else}}{{ctx.Locale.Tr "actions.runs.empty_commit_message"}}{{end}} + + {{or $run.Title (ctx.Locale.Tr "actions.runs.empty_commit_message")}}
- {{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}: - {{- if .ScheduleID -}} + {{if not $.CurWorkflow}}{{$run.WorkflowID}} {{end}}#{{$run.Index}}: + {{- if $run.ScheduleID -}} {{ctx.Locale.Tr "actions.runs.scheduled"}} {{- else -}} {{ctx.Locale.Tr "actions.runs.commit"}} - {{ShortSha .CommitSHA}} + {{ShortSha $run.CommitSHA}} {{ctx.Locale.Tr "actions.runs.pushed_by"}} - {{.TriggerUser.GetDisplayName}} + {{$run.TriggerUser.GetDisplayName}} {{- end -}}
- {{if .IsRefDeleted}} - {{.PrettyRef}} + {{if $run.IsRefDeleted}} + {{$run.PrettyRef}} {{else}} - {{.PrettyRef}} + {{$run.PrettyRef}} {{end}}
-
{{svg "octicon-calendar" 16}}{{DateUtils.TimeSince .Updated}}
-
{{svg "octicon-stopwatch" 16}}{{.Duration}}
+
{{svg "octicon-calendar" 16}}{{DateUtils.TimeSince $run.Updated}}
+
{{svg "octicon-stopwatch" 16}}{{$run.Duration}}
+ {{if and ($.AllowDeleteWorkflowRuns) ($run.Status.IsDone)}} + + {{end}}
{{end}} diff --git a/templates/shared/secrets/add_list.tmpl b/templates/shared/secrets/add_list.tmpl index a4ef2e5384..44305e9502 100644 --- a/templates/shared/secrets/add_list.tmpl +++ b/templates/shared/secrets/add_list.tmpl @@ -37,7 +37,7 @@ {{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort .CreatedUnix)}} - -