From b907b9fb1a1a792b9bc25112fa3eb3f8d2fb4397 Mon Sep 17 00:00:00 2001 From: silverwind Date: Wed, 1 Oct 2025 06:43:41 +0200 Subject: [PATCH 01/74] Enable a few more tsconfig options (#35553) Enable a few more useful options in tsconfig. `noImplicitReturns` had two cases which I've fixed. Also, partially sort the file. --- tsconfig.json | 24 ++++++++++++++---------- web_src/js/features/tablesort.ts | 2 +- web_src/js/modules/toast.ts | 10 +++++----- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 0a9e080a51..3bc6065647 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "include": [ - "${configDir}/.*", "${configDir}/*", + "${configDir}/.*", "${configDir}/tests/e2e/**/*", "${configDir}/tests/e2e/**/.*", "${configDir}/tools/**/*", @@ -17,27 +17,31 @@ "allowImportingTsExtensions": true, "allowJs": true, "allowSyntheticDefaultImports": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, "alwaysStrict": true, "erasableSyntaxOnly": true, "esModuleInterop": true, + "exactOptionalPropertyTypes": false, "isolatedModules": true, "libReplacement": false, "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noPropertyAccessFromIndexSignature": false, + "noUnusedLocals": true, + "noUnusedParameters": true, "resolveJsonModule": true, "skipLibCheck": true, - "verbatimModuleSyntax": true, - "stripInternal": true, + "sourceMap": true, "strict": false, "strictBindCallApply": true, "strictBuiltinIteratorReturn": true, "strictFunctionTypes": true, - "noImplicitAny": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noPropertyAccessFromIndexSignature": false, - "exactOptionalPropertyTypes": false, - "sourceMap": true, + "stripInternal": true, + "verbatimModuleSyntax": true, "types": [ "vitest/globals", "./web_src/js/globals.d.ts", diff --git a/web_src/js/features/tablesort.ts b/web_src/js/features/tablesort.ts index 0648ffd067..cd77eb971c 100644 --- a/web_src/js/features/tablesort.ts +++ b/web_src/js/features/tablesort.ts @@ -10,7 +10,7 @@ export function initTableSort() { } function tableSort(normSort: string, revSort: string, isDefault: string) { - if (!normSort) return false; + if (!normSort) return; if (!revSort) revSort = ''; const url = new URL(window.location.href); diff --git a/web_src/js/modules/toast.ts b/web_src/js/modules/toast.ts index 71a7fab8b2..395f31bc82 100644 --- a/web_src/js/modules/toast.ts +++ b/web_src/js/modules/toast.ts @@ -43,7 +43,7 @@ type ToastOpts = { type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast}; /** See https://github.com/apvarun/toastify-js#api for options */ -function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast { +function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast | null { const body = useHtmlBody ? message : htmlEscape(message); const parent = document.querySelector('.ui.dimmer.active') ?? document.body; const duplicateKey = preventDuplicates ? (preventDuplicates === true ? `${level}-${body}` : preventDuplicates) : ''; @@ -56,7 +56,7 @@ function showToast(message: string, level: Intent, {gravity, position, duration, showElem(toastDupNumEl); toastDupNumEl.textContent = String(Number(toastDupNumEl.textContent) + 1); animateOnce(toastDupNumEl, 'pulse-1p5-200'); - return; + return null; } } @@ -83,15 +83,15 @@ function showToast(message: string, level: Intent, {gravity, position, duration, return toast; } -export function showInfoToast(message: string, opts?: ToastOpts): Toast { +export function showInfoToast(message: string, opts?: ToastOpts): Toast | null { return showToast(message, 'info', opts); } -export function showWarningToast(message: string, opts?: ToastOpts): Toast { +export function showWarningToast(message: string, opts?: ToastOpts): Toast | null { return showToast(message, 'warning', opts); } -export function showErrorToast(message: string, opts?: ToastOpts): Toast { +export function showErrorToast(message: string, opts?: ToastOpts): Toast | null { return showToast(message, 'error', opts); } From 340aed39825a8226934fdccbc27fa812b67f6cbd Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 2 Oct 2025 08:45:56 +0200 Subject: [PATCH 02/74] Update JS and PY deps (#35565) Updated all dependencies and did a quick test of the UI. --- package.json | 38 +- pnpm-lock.yaml | 1638 +++++++++++++++++++++++++----------------------- uv.lock | 276 ++++---- 3 files changed, 1022 insertions(+), 930 deletions(-) diff --git a/package.json b/package.json index 0b2ce03354..b88d99cc80 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "chart.js": "4.5.0", "chartjs-adapter-dayjs-4": "1.0.4", "chartjs-plugin-zoom": "2.2.0", - "clippie": "4.1.7", + "clippie": "4.1.8", "cropperjs": "1.6.2", "css-loader": "7.1.2", "dayjs": "1.11.18", @@ -33,10 +33,10 @@ "easymde": "2.20.0", "esbuild-loader": "4.3.0", "htmx.org": "2.0.7", - "idiomorph": "0.7.3", + "idiomorph": "0.7.4", "jquery": "3.7.1", "katex": "0.16.22", - "mermaid": "11.11.0", + "mermaid": "11.12.0", "mini-css-extract-plugin": "2.9.4", "monaco-editor": "0.53.0", "monaco-editor-webpack-plugin": "7.1.0", @@ -46,29 +46,29 @@ "postcss": "8.5.6", "postcss-loader": "8.2.0", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.29.0", + "swagger-ui-dist": "5.29.1", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", "tippy.js": "6.3.7", "toastify-js": "1.12.0", "tributejs": "5.1.3", - "typescript": "5.9.2", + "typescript": "5.9.3", "uint8-to-base64": "0.2.1", "vanilla-colorful": "0.7.2", - "vue": "3.5.21", + "vue": "3.5.22", "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.101.3", + "webpack": "5.102.0", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.2" }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.55.0", + "@playwright/test": "1.55.1", "@stoplight/spectral-cli": "6.15.0", - "@stylistic/eslint-plugin": "5.3.1", + "@stylistic/eslint-plugin": "5.4.0", "@stylistic/stylelint-plugin": "4.0.0", "@types/codemirror": "5.60.16", "@types/dropzone": "5.7.9", @@ -80,12 +80,12 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/parser": "8.43.0", + "@typescript-eslint/parser": "8.45.0", "@vitejs/plugin-vue": "6.0.1", - "@vitest/eslint-plugin": "1.3.9", - "eslint": "9.35.0", + "@vitest/eslint-plugin": "1.3.13", + "eslint": "9.36.0", "eslint-import-resolver-typescript": "4.4.4", - "eslint-plugin-array-func": "5.0.2", + "eslint-plugin-array-func": "5.1.0", "eslint-plugin-github": "6.0.0", "eslint-plugin-import-x": "4.16.1", "eslint-plugin-no-use-extend-native": "0.7.2", @@ -93,11 +93,11 @@ "eslint-plugin-regexp": "2.10.0", "eslint-plugin-sonarjs": "3.0.5", "eslint-plugin-unicorn": "61.0.2", - "eslint-plugin-vue": "10.4.0", + "eslint-plugin-vue": "10.5.0", "eslint-plugin-vue-scoped-css": "2.12.0", - "eslint-plugin-wc": "3.0.1", + "eslint-plugin-wc": "3.0.2", "globals": "16.4.0", - "happy-dom": "18.0.1", + "happy-dom": "19.0.2", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.27.0", "nolyfill": "1.0.44", @@ -108,11 +108,11 @@ "stylelint-declaration-strict-value": "1.10.11", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "4.0.0", - "typescript-eslint": "8.43.0", - "updates": "16.7.0", + "typescript-eslint": "8.45.0", + "updates": "16.7.4", "vite-string-plugin": "1.4.6", "vitest": "3.2.4", - "vue-tsc": "3.0.6" + "vue-tsc": "3.1.0" }, "browserslist": [ "defaults" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d40acd101..deb1db6867 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -61,13 +61,13 @@ importers: version: 2.6.2 '@silverwind/vue3-calendar-heatmap': specifier: 2.0.6 - version: 2.0.6(tippy.js@6.3.7)(vue@3.5.21(typescript@5.9.2)) + version: 2.0.6(tippy.js@6.3.7)(vue@3.5.22(typescript@5.9.3)) '@techknowlogick/license-checker-webpack-plugin': specifier: 0.3.0 - version: 0.3.0(webpack@5.101.3) + version: 0.3.0(webpack@5.102.0) add-asset-webpack-plugin: specifier: 3.1.1 - version: 3.1.1(webpack@5.101.3) + version: 3.1.1(webpack@5.102.0) ansi_up: specifier: 6.0.6 version: 6.0.6 @@ -84,14 +84,14 @@ importers: specifier: 2.2.0 version: 2.2.0(chart.js@4.5.0) clippie: - specifier: 4.1.7 - version: 4.1.7 + specifier: 4.1.8 + version: 4.1.8 cropperjs: specifier: 1.6.2 version: 1.6.2 css-loader: specifier: 7.1.2 - version: 7.1.2(webpack@5.101.3) + version: 7.1.2(webpack@5.102.0) dayjs: specifier: 1.11.18 version: 1.11.18 @@ -103,13 +103,13 @@ importers: version: 2.20.0 esbuild-loader: specifier: 4.3.0 - version: 4.3.0(webpack@5.101.3) + version: 4.3.0(webpack@5.102.0) htmx.org: specifier: 2.0.7 version: 2.0.7 idiomorph: - specifier: 0.7.3 - version: 0.7.3 + specifier: 0.7.4 + version: 0.7.4 jquery: specifier: 3.7.1 version: 3.7.1 @@ -117,17 +117,17 @@ importers: specifier: 0.16.22 version: 0.16.22 mermaid: - specifier: 11.11.0 - version: 11.11.0 + specifier: 11.12.0 + version: 11.12.0 mini-css-extract-plugin: specifier: 2.9.4 - version: 2.9.4(webpack@5.101.3) + version: 2.9.4(webpack@5.102.0) monaco-editor: specifier: 0.53.0 version: 0.53.0 monaco-editor-webpack-plugin: specifier: 7.1.0 - version: 7.1.0(monaco-editor@0.53.0)(webpack@5.101.3) + version: 7.1.0(monaco-editor@0.53.0)(webpack@5.102.0) online-3d-viewer: specifier: 0.16.0 version: 0.16.0 @@ -142,13 +142,13 @@ importers: version: 8.5.6 postcss-loader: specifier: 8.2.0 - version: 8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.101.3) + version: 8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0) sortablejs: specifier: 1.15.6 version: 1.15.6 swagger-ui-dist: - specifier: 5.29.0 - version: 5.29.0 + specifier: 5.29.1 + version: 5.29.1 tailwindcss: specifier: 3.4.17 version: 3.4.17 @@ -168,8 +168,8 @@ importers: specifier: 5.1.3 version: 5.1.3 typescript: - specifier: 5.9.2 - version: 5.9.2 + specifier: 5.9.3 + version: 5.9.3 uint8-to-base64: specifier: 0.2.1 version: 0.2.1 @@ -177,42 +177,42 @@ importers: specifier: 0.7.2 version: 0.7.2 vue: - specifier: 3.5.21 - version: 3.5.21(typescript@5.9.2) + specifier: 3.5.22 + version: 3.5.22(typescript@5.9.3) vue-bar-graph: specifier: 2.2.0 - version: 2.2.0(typescript@5.9.2) + version: 2.2.0(typescript@5.9.3) vue-chartjs: specifier: 5.3.2 - version: 5.3.2(chart.js@4.5.0)(vue@3.5.21(typescript@5.9.2)) + version: 5.3.2(chart.js@4.5.0)(vue@3.5.22(typescript@5.9.3)) vue-loader: specifier: 17.4.2 - version: 17.4.2(vue@3.5.21(typescript@5.9.2))(webpack@5.101.3) + version: 17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0) webpack: - specifier: 5.101.3 - version: 5.101.3(webpack-cli@6.0.1) + specifier: 5.102.0 + version: 5.102.0(webpack-cli@6.0.1) webpack-cli: specifier: 6.0.1 - version: 6.0.1(webpack@5.101.3) + version: 6.0.1(webpack@5.102.0) wrap-ansi: specifier: 9.0.2 version: 9.0.2 devDependencies: '@eslint-community/eslint-plugin-eslint-comments': specifier: 4.5.0 - version: 4.5.0(eslint@9.35.0(jiti@2.5.1)) + version: 4.5.0(eslint@9.36.0(jiti@2.6.1)) '@playwright/test': - specifier: 1.55.0 - version: 1.55.0 + specifier: 1.55.1 + version: 1.55.1 '@stoplight/spectral-cli': specifier: 6.15.0 version: 6.15.0 '@stylistic/eslint-plugin': - specifier: 5.3.1 - version: 5.3.1(eslint@9.35.0(jiti@2.5.1)) + specifier: 5.4.0 + version: 5.4.0(eslint@9.36.0(jiti@2.6.1)) '@stylistic/stylelint-plugin': specifier: 4.0.0 - version: 4.0.0(stylelint@16.24.0(typescript@5.9.2)) + version: 4.0.0(stylelint@16.24.0(typescript@5.9.3)) '@types/codemirror': specifier: 5.60.16 version: 5.60.16 @@ -244,59 +244,59 @@ importers: specifier: 1.12.4 version: 1.12.4 '@typescript-eslint/parser': - specifier: 8.43.0 - version: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + specifier: 8.45.0 + version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) '@vitejs/plugin-vue': specifier: 6.0.1 - version: 6.0.1(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.21(typescript@5.9.2)) + version: 6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) '@vitest/eslint-plugin': - specifier: 1.3.9 - version: 1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + specifier: 1.3.13 + version: 1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) eslint: - specifier: 9.35.0 - version: 9.35.0(jiti@2.5.1) + specifier: 9.36.0 + version: 9.36.0(jiti@2.6.1) eslint-import-resolver-typescript: specifier: 4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-array-func: - specifier: 5.0.2 - version: 5.0.2(eslint@9.35.0(jiti@2.5.1)) + specifier: 5.1.0 + version: 5.1.0(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-github: specifier: 6.0.0 - version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) + version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-import-x: specifier: 4.16.1 - version: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)) + version: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-no-use-extend-native: specifier: 0.7.2 - version: 0.7.2(eslint@9.35.0(jiti@2.5.1)) + version: 0.7.2(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-playwright: specifier: 2.2.2 - version: 2.2.2(eslint@9.35.0(jiti@2.5.1)) + version: 2.2.2(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-regexp: specifier: 2.10.0 - version: 2.10.0(eslint@9.35.0(jiti@2.5.1)) + version: 2.10.0(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-sonarjs: specifier: 3.0.5 - version: 3.0.5(eslint@9.35.0(jiti@2.5.1)) + version: 3.0.5(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-unicorn: specifier: 61.0.2 - version: 61.0.2(eslint@9.35.0(jiti@2.5.1)) + version: 61.0.2(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-vue: - specifier: 10.4.0 - version: 10.4.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))) + specifier: 10.5.0 + version: 10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))) eslint-plugin-vue-scoped-css: specifier: 2.12.0 - version: 2.12.0(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))) + version: 2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))) eslint-plugin-wc: - specifier: 3.0.1 - version: 3.0.1(eslint@9.35.0(jiti@2.5.1)) + specifier: 3.0.2 + version: 3.0.2(eslint@9.36.0(jiti@2.6.1)) globals: specifier: 16.4.0 version: 16.4.0 happy-dom: - specifier: 18.0.1 - version: 18.0.1 + specifier: 19.0.2 + version: 19.0.2 markdownlint-cli: specifier: 0.45.0 version: 0.45.0 @@ -311,37 +311,37 @@ importers: version: 1.8.0 stylelint: specifier: 16.24.0 - version: 16.24.0(typescript@5.9.2) + version: 16.24.0(typescript@5.9.3) stylelint-config-recommended: specifier: 17.0.0 - version: 17.0.0(stylelint@16.24.0(typescript@5.9.2)) + version: 17.0.0(stylelint@16.24.0(typescript@5.9.3)) stylelint-declaration-block-no-ignored-properties: specifier: 2.8.0 - version: 2.8.0(stylelint@16.24.0(typescript@5.9.2)) + version: 2.8.0(stylelint@16.24.0(typescript@5.9.3)) stylelint-declaration-strict-value: specifier: 1.10.11 - version: 1.10.11(stylelint@16.24.0(typescript@5.9.2)) + version: 1.10.11(stylelint@16.24.0(typescript@5.9.3)) stylelint-value-no-unknown-custom-properties: specifier: 6.0.1 - version: 6.0.1(stylelint@16.24.0(typescript@5.9.2)) + version: 6.0.1(stylelint@16.24.0(typescript@5.9.3)) svgo: specifier: 4.0.0 version: 4.0.0 typescript-eslint: - specifier: 8.43.0 - version: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + specifier: 8.45.0 + version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) updates: - specifier: 16.7.0 - version: 16.7.0 + specifier: 16.7.4 + version: 16.7.4 vite-string-plugin: specifier: 1.4.6 version: 1.4.6 vitest: specifier: 3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue-tsc: - specifier: 3.0.6 - version: 3.0.6(typescript@5.9.2) + specifier: 3.1.0 + version: 3.1.0(typescript@5.9.3) packages: @@ -352,8 +352,8 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@antfu/utils@9.2.0': - resolution: {integrity: sha512-Oq1d9BGZakE/FyoEtcNeSwM7MpDO2vUBi11RWBZXf75zPsbUVWmUs03EqkRFrcgbXyKTas0BdZWC1wcuSoqSAw==} + '@antfu/utils@9.2.1': + resolution: {integrity: sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg==} '@asyncapi/specs@6.10.0': resolution: {integrity: sha512-vB5oKLsdrLUORIZ5BXortZTlVyGWWMC1Nud/0LtgxQ3Yn2738HigAD6EVqScvpPsDUI/bcLVsYEXN4dtXQHVng==} @@ -386,6 +386,15 @@ packages: '@braintree/sanitize-url@7.1.1': resolution: {integrity: sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==} + '@cacheable/memoize@2.0.3': + resolution: {integrity: sha512-hl9wfQgpiydhQEIv7fkjEzTGE+tcosCXLKFDO707wYJ/78FVOlowb36djex5GdbSyeHnG62pomYLMuV/OT8Pbw==} + + '@cacheable/memory@2.0.3': + resolution: {integrity: sha512-R3UKy/CKOyb1LZG/VRCTMcpiMDyLH7SH3JrraRdK6kf3GweWCOU3sgvE13W3TiDRbxnDKylzKJvhUAvWl9LQOA==} + + '@cacheable/utils@2.0.3': + resolution: {integrity: sha512-m7Rce68cMHlAUjvWBy9Ru1Nmw5gU0SjGGtQDdhpe6E0xnbcvrIY0Epy//JU1VYYBUTzrG9jvgmTauULGKzOkWA==} + '@chevrotain/cst-dts-gen@11.0.3': resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} @@ -488,158 +497,158 @@ packages: '@emnapi/wasi-threads@1.1.0': resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.25.9': - resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==} + '@esbuild/aix-ppc64@0.25.10': + resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.9': - resolution: {integrity: sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==} + '@esbuild/android-arm64@0.25.10': + resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.9': - resolution: {integrity: sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==} + '@esbuild/android-arm@0.25.10': + resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.9': - resolution: {integrity: sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==} + '@esbuild/android-x64@0.25.10': + resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.9': - resolution: {integrity: sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==} + '@esbuild/darwin-arm64@0.25.10': + resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.9': - resolution: {integrity: sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==} + '@esbuild/darwin-x64@0.25.10': + resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.9': - resolution: {integrity: sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==} + '@esbuild/freebsd-arm64@0.25.10': + resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.9': - resolution: {integrity: sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==} + '@esbuild/freebsd-x64@0.25.10': + resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.9': - resolution: {integrity: sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==} + '@esbuild/linux-arm64@0.25.10': + resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.9': - resolution: {integrity: sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==} + '@esbuild/linux-arm@0.25.10': + resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.9': - resolution: {integrity: sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==} + '@esbuild/linux-ia32@0.25.10': + resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.9': - resolution: {integrity: sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==} + '@esbuild/linux-loong64@0.25.10': + resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.9': - resolution: {integrity: sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==} + '@esbuild/linux-mips64el@0.25.10': + resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.9': - resolution: {integrity: sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==} + '@esbuild/linux-ppc64@0.25.10': + resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.9': - resolution: {integrity: sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==} + '@esbuild/linux-riscv64@0.25.10': + resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.9': - resolution: {integrity: sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==} + '@esbuild/linux-s390x@0.25.10': + resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.9': - resolution: {integrity: sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==} + '@esbuild/linux-x64@0.25.10': + resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.9': - resolution: {integrity: sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==} + '@esbuild/netbsd-arm64@0.25.10': + resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.9': - resolution: {integrity: sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==} + '@esbuild/netbsd-x64@0.25.10': + resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.9': - resolution: {integrity: sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==} + '@esbuild/openbsd-arm64@0.25.10': + resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.9': - resolution: {integrity: sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==} + '@esbuild/openbsd-x64@0.25.10': + resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.9': - resolution: {integrity: sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==} + '@esbuild/openharmony-arm64@0.25.10': + resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.9': - resolution: {integrity: sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==} + '@esbuild/sunos-x64@0.25.10': + resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.9': - resolution: {integrity: sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==} + '@esbuild/win32-arm64@0.25.10': + resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.9': - resolution: {integrity: sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==} + '@esbuild/win32-ia32@0.25.10': + resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.9': - resolution: {integrity: sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==} + '@esbuild/win32-x64@0.25.10': + resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -660,8 +669,8 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/compat@1.3.2': - resolution: {integrity: sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA==} + '@eslint/compat@1.4.0': + resolution: {integrity: sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.40 || 9 @@ -681,12 +690,16 @@ packages: resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.16.0': + resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.35.0': - resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==} + '@eslint/js@9.36.0': + resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -734,8 +747,8 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.0.1': - resolution: {integrity: sha512-A78CUEnFGX8I/WlILxJCuIJXloL0j/OJ9PSchPAfCargEIKmUBWvvEMmKWB5oONwiUqlNt+5eRufdkLxeHIWYw==} + '@iconify/utils@3.0.2': + resolution: {integrity: sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==} '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} @@ -762,8 +775,8 @@ packages: '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.30': - resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@jsep-plugin/assignment@1.3.0': resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} @@ -783,8 +796,12 @@ packages: peerDependencies: jsep: ^0.4.0||^1.0.0 - '@keyv/serialize@1.1.0': - resolution: {integrity: sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==} + '@keyv/bigmap@1.0.2': + resolution: {integrity: sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA==} + engines: {node: '>= 18'} + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} '@kurkle/color@0.3.4': resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==} @@ -888,8 +905,8 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.55.0': - resolution: {integrity: sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==} + '@playwright/test@1.55.1': + resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==} engines: {node: '>=18'} hasBin: true @@ -918,108 +935,113 @@ packages: peerDependencies: rollup: ^1.20.0||^2.0.0 - '@rollup/rollup-android-arm-eabi@4.50.1': - resolution: {integrity: sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==} + '@rollup/rollup-android-arm-eabi@4.52.3': + resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.50.1': - resolution: {integrity: sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==} + '@rollup/rollup-android-arm64@4.52.3': + resolution: {integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.50.1': - resolution: {integrity: sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==} + '@rollup/rollup-darwin-arm64@4.52.3': + resolution: {integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.50.1': - resolution: {integrity: sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==} + '@rollup/rollup-darwin-x64@4.52.3': + resolution: {integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.50.1': - resolution: {integrity: sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==} + '@rollup/rollup-freebsd-arm64@4.52.3': + resolution: {integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.50.1': - resolution: {integrity: sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==} + '@rollup/rollup-freebsd-x64@4.52.3': + resolution: {integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.50.1': - resolution: {integrity: sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.3': + resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.50.1': - resolution: {integrity: sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==} + '@rollup/rollup-linux-arm-musleabihf@4.52.3': + resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.50.1': - resolution: {integrity: sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==} + '@rollup/rollup-linux-arm64-gnu@4.52.3': + resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.50.1': - resolution: {integrity: sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==} + '@rollup/rollup-linux-arm64-musl@4.52.3': + resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.50.1': - resolution: {integrity: sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==} + '@rollup/rollup-linux-loong64-gnu@4.52.3': + resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.50.1': - resolution: {integrity: sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==} + '@rollup/rollup-linux-ppc64-gnu@4.52.3': + resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.50.1': - resolution: {integrity: sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==} + '@rollup/rollup-linux-riscv64-gnu@4.52.3': + resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.50.1': - resolution: {integrity: sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==} + '@rollup/rollup-linux-riscv64-musl@4.52.3': + resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.50.1': - resolution: {integrity: sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==} + '@rollup/rollup-linux-s390x-gnu@4.52.3': + resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.50.1': - resolution: {integrity: sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==} + '@rollup/rollup-linux-x64-gnu@4.52.3': + resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.50.1': - resolution: {integrity: sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==} + '@rollup/rollup-linux-x64-musl@4.52.3': + resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.50.1': - resolution: {integrity: sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==} + '@rollup/rollup-openharmony-arm64@4.52.3': + resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.50.1': - resolution: {integrity: sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==} + '@rollup/rollup-win32-arm64-msvc@4.52.3': + resolution: {integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.50.1': - resolution: {integrity: sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==} + '@rollup/rollup-win32-ia32-msvc@4.52.3': + resolution: {integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.50.1': - resolution: {integrity: sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==} + '@rollup/rollup-win32-x64-gnu@4.52.3': + resolution: {integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.52.3': + resolution: {integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==} cpu: [x64] os: [win32] @@ -1136,8 +1158,8 @@ packages: resolution: {integrity: sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w==} engines: {node: '>=10.8'} - '@stylistic/eslint-plugin@5.3.1': - resolution: {integrity: sha512-Ykums1VYonM0TgkD0VteVq9mrlO2FhF48MDJnPyv3MktIB2ydtuhlO0AfWm7xnW1kyf5bjOqA6xc7JjviuVTxg==} + '@stylistic/eslint-plugin@5.4.0': + resolution: {integrity: sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=9.0.0' @@ -1156,8 +1178,8 @@ packages: peerDependencies: webpack: ^4.4.0 || ^5.4.0 - '@tybys/wasm-util@0.10.0': - resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -1165,8 +1187,8 @@ packages: '@types/codemirror@5.60.16': resolution: {integrity: sha512-V/yHdamffSS075jit+fDxaOAmdP2liok8NSNJnAZfDJErzOheuygHZEhAJrfmk5TEyM32MhkZjwo/idX791yxw==} - '@types/d3-array@3.2.1': - resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + '@types/d3-array@3.2.2': + resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} '@types/d3-axis@3.0.6': resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} @@ -1309,11 +1331,11 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@20.19.13': - resolution: {integrity: sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==} + '@types/node@20.19.19': + resolution: {integrity: sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==} - '@types/node@24.3.1': - resolution: {integrity: sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==} + '@types/node@24.6.2': + resolution: {integrity: sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==} '@types/pdfobject@2.2.5': resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==} @@ -1357,63 +1379,63 @@ packages: '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} - '@typescript-eslint/eslint-plugin@8.43.0': - resolution: {integrity: sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==} + '@typescript-eslint/eslint-plugin@8.45.0': + resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.43.0 + '@typescript-eslint/parser': ^8.45.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.43.0': - resolution: {integrity: sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==} + '@typescript-eslint/parser@8.45.0': + resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.43.0': - resolution: {integrity: sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==} + '@typescript-eslint/project-service@8.45.0': + resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.43.0': - resolution: {integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==} + '@typescript-eslint/scope-manager@8.45.0': + resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.43.0': - resolution: {integrity: sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==} + '@typescript-eslint/tsconfig-utils@8.45.0': + resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.43.0': - resolution: {integrity: sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==} + '@typescript-eslint/type-utils@8.45.0': + resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.43.0': - resolution: {integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==} + '@typescript-eslint/types@8.45.0': + resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.43.0': - resolution: {integrity: sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==} + '@typescript-eslint/typescript-estree@8.45.0': + resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.43.0': - resolution: {integrity: sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==} + '@typescript-eslint/utils@8.45.0': + resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.43.0': - resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} + '@typescript-eslint/visitor-keys@8.45.0': + resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -1518,8 +1540,8 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 vue: ^3.2.25 - '@vitest/eslint-plugin@1.3.9': - resolution: {integrity: sha512-wsNe7xy44ovm/h9ISDkDNcv0aOnUsaOYDqan2y6qCFAUQ0odFr6df/+FdGKHZN+mCM+SvIDWoXuvm5T5V3Kh6w==} + '@vitest/eslint-plugin@1.3.13': + resolution: {integrity: sha512-QfzXd1+lCY3dIqPHOZlagA2bJYoWC5yAU3adv8Gks0rHAL6FpyXKYBiyMCuU6mRrbKUMphGqwDQobinOvYgJig==} peerDependencies: eslint: '>= 8.57.0' typescript: '>= 5.0.0' @@ -1568,45 +1590,42 @@ packages: '@volar/typescript@2.4.23': resolution: {integrity: sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==} - '@vue/compiler-core@3.5.21': - resolution: {integrity: sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==} + '@vue/compiler-core@3.5.22': + resolution: {integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==} - '@vue/compiler-dom@3.5.21': - resolution: {integrity: sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==} + '@vue/compiler-dom@3.5.22': + resolution: {integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==} - '@vue/compiler-sfc@3.5.21': - resolution: {integrity: sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==} + '@vue/compiler-sfc@3.5.22': + resolution: {integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==} - '@vue/compiler-ssr@3.5.21': - resolution: {integrity: sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==} + '@vue/compiler-ssr@3.5.22': + resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==} - '@vue/compiler-vue2@2.7.16': - resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} - - '@vue/language-core@3.0.6': - resolution: {integrity: sha512-e2RRzYWm+qGm8apUHW1wA5RQxzNhkqbbKdbKhiDUcmMrNAZGyM8aTiL3UrTqkaFI5s7wJRGGrp4u3jgusuBp2A==} + '@vue/language-core@3.1.0': + resolution: {integrity: sha512-a7ns+X9vTbdmk7QLrvnZs8s4E1wwtxG/sELzr6F2j4pU+r/OoAv6jJGSz+5tVTU6e4+3rjepGhSP8jDmBBcb3w==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@vue/reactivity@3.5.21': - resolution: {integrity: sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==} + '@vue/reactivity@3.5.22': + resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==} - '@vue/runtime-core@3.5.21': - resolution: {integrity: sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==} + '@vue/runtime-core@3.5.22': + resolution: {integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==} - '@vue/runtime-dom@3.5.21': - resolution: {integrity: sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==} + '@vue/runtime-dom@3.5.22': + resolution: {integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==} - '@vue/server-renderer@3.5.21': - resolution: {integrity: sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==} + '@vue/server-renderer@3.5.22': + resolution: {integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==} peerDependencies: - vue: 3.5.21 + vue: 3.5.22 - '@vue/shared@3.5.21': - resolution: {integrity: sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==} + '@vue/shared@3.5.22': + resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==} '@webassemblyjs/ast@1.14.1': resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} @@ -1745,8 +1764,8 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - alien-signals@2.0.7: - resolution: {integrity: sha512-wE7y3jmYeb0+h6mr5BOovuqhFv22O/MV9j5p0ndJsa7z1zJNPGQ4ph5pQk/kTTCWRC3xsA4SmtwmkzQO+7NCNg==} + alien-signals@3.0.0: + resolution: {integrity: sha512-JHoRJf18Y6HN4/KZALr3iU+0vW9LKG+8FMThQlbn4+gv8utsLIkwpomjElGPccGeNwh0FI2HN6BLnyFLo6OyLQ==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -1839,6 +1858,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + baseline-browser-mapping@2.8.10: + resolution: {integrity: sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==} + hasBin: true + big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} @@ -1859,8 +1882,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.25.4: - resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1889,8 +1912,8 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cacheable@1.10.4: - resolution: {integrity: sha512-Gd7ccIUkZ9TE2odLQVS+PDjIvQCdJKUlLdJRVvZu0aipj07Qfx+XIej7hhDrKGGoIxV5m5fT/kOJNJPQhQneRg==} + cacheable@2.0.3: + resolution: {integrity: sha512-nZF80J3d8RMrroMSYm1E9pBllVDXWPuECZgEZxH+vusCY4MAXAJVrY0jutcHSgh3xYX3G2EUNnmtWGZVVjWCXw==} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -1900,8 +1923,8 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001741: - resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==} + caniuse-lite@1.0.30001746: + resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} @@ -1973,8 +1996,8 @@ packages: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - clippie@4.1.7: - resolution: {integrity: sha512-l8BmUmWqOt4mpxeSflcfODJJOU+DsE5atWj82k1zsxd2X82haz2+g12PJPMOt6e1Cs4/ZnOWdRAV+nY9n2o1Rg==} + clippie@4.1.8: + resolution: {integrity: sha512-GCDd4xnYPqohYPgPN/vbljc3QHD3P2Wsos6RO68ab3Ja6a7IDocXzbsIKXqwrNnK3cR31nog3A5Cyf+8GYc/Dg==} cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} @@ -2288,9 +2311,6 @@ packages: dayjs@1.11.18: resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} - de-indent@1.0.2: - resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} - debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -2299,8 +2319,8 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -2371,8 +2391,8 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.2.6: - resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==} + dompurify@3.2.7: + resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -2386,8 +2406,8 @@ packages: easymde@2.20.0: resolution: {integrity: sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==} - electron-to-chromium@1.5.215: - resolution: {integrity: sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==} + electron-to-chromium@1.5.228: + resolution: {integrity: sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==} emoji-regex@10.5.0: resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==} @@ -2414,13 +2434,13 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - envinfo@7.14.0: - resolution: {integrity: sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==} + envinfo@7.15.0: + resolution: {integrity: sha512-chR+t7exF6y59kelhXw5I3849nTy7KIRO+ePdLMhCD+JRP/JvmkenDWP7QSFGlsHX+kxGxdDutOPrmj5j1HR6g==} engines: {node: '>=4'} hasBin: true - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -2430,8 +2450,8 @@ packages: peerDependencies: webpack: ^4.40.0 || ^5.0.0 - esbuild@0.25.9: - resolution: {integrity: sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==} + esbuild@0.25.10: + resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} engines: {node: '>=18'} hasBin: true @@ -2505,8 +2525,8 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-plugin-array-func@5.0.2: - resolution: {integrity: sha512-iyLex2+pTcxHZ6OLL80oMy+CtffpJ9j6A/57VQi1VN5bK1IS/0o+mWvezDHeAlwXjn6ksRO9L5SGU329BBuY8A==} + eslint-plugin-array-func@5.1.0: + resolution: {integrity: sha512-+OULB0IQdENBmBf8pHMPPObgV6QyfeXFin483jPonOaiurI9UFmc8UydWriK5f5Gel8xBhQLA6NzMwbck1BUJw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=8.51.0' @@ -2621,19 +2641,22 @@ packages: eslint: '>=5.0.0' vue-eslint-parser: '>=7.1.0' - eslint-plugin-vue@10.4.0: - resolution: {integrity: sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw==} + eslint-plugin-vue@10.5.0: + resolution: {integrity: sha512-7BZHsG3kC2vei8F2W8hnfDi9RK+cv5eKPMvzBdrl8Vuc0hR5odGQRli8VVzUkrmUHkxFEm4Iio1r5HOKslO0Aw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: + '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 '@typescript-eslint/parser': ^7.0.0 || ^8.0.0 eslint: ^8.57.0 || ^9.0.0 vue-eslint-parser: ^10.0.0 peerDependenciesMeta: + '@stylistic/eslint-plugin': + optional: true '@typescript-eslint/parser': optional: true - eslint-plugin-wc@3.0.1: - resolution: {integrity: sha512-0p1wkSlA2Ue3FA4qW+5LZ+15sy0p1nUyVl1eyBMLq4rtN1LtE9IdI49BXNWMz8N8bM/y7Ulx8SWGAni5f8XO5g==} + eslint-plugin-wc@3.0.2: + resolution: {integrity: sha512-siwTrxPTw6GU2JmP3faInw8nhi0ZCnKsiSRM3j7EAkZmBTGYdDAToeseLYsvPrc5Urp/vPz+g7Ewh7XcICLxww==} peerDependencies: eslint: '>=8.40.0' @@ -2657,8 +2680,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.35.0: - resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==} + eslint@9.36.0: + resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -2793,8 +2816,8 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flat-cache@6.1.13: - resolution: {integrity: sha512-gmtS2PaUjSPa4zjObEIn4WWliKyZzYljgxODBfxugpK6q6HU9ClXzgCJ+nlcPKY9Bt090ypTOLIFWkV0jbKFjw==} + flat-cache@6.1.17: + resolution: {integrity: sha512-Jzse4YoiUJBVYTwz5Bwl4h/2VQM7e2KK3MVAMlXzX9uamIHAH/TXUlRKU1AQGQOryQhN0EsmufiiF40G057YXA==} flat@5.0.2: resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} @@ -2913,8 +2936,8 @@ packages: resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} engines: {node: '>=0.8.0'} - happy-dom@18.0.1: - resolution: {integrity: sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==} + happy-dom@19.0.2: + resolution: {integrity: sha512-831CLbgDyjRbd2lApHZFsBDe56onuFcjsCBPodzWpzedTpeDr8CGZjs7iEIdNW1DVwSFRecfwzLpVyGBPamwGA==} engines: {node: '>=20.0.0'} has-flag@4.0.0: @@ -2924,12 +2947,8 @@ packages: hash-sum@2.0.0: resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==} - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - - hookified@1.12.0: - resolution: {integrity: sha512-hMr1Y9TCLshScrBbV2QxJ9BROddxZ12MX9KsCtuGGy/3SmmN5H1PllKerrVlSotur9dlE8hmUKAOSa3WDzsZmQ==} + hookified@1.12.1: + resolution: {integrity: sha512-xnKGl+iMIlhrZmGHB729MqlmPoWBznctSQTYCpFKqNsCgimJQmithcW0xSQMMFzYnV2iKUh25alswn6epgxS0Q==} hpagent@1.2.0: resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} @@ -2955,8 +2974,8 @@ packages: peerDependencies: postcss: ^8.1.0 - idiomorph@0.7.3: - resolution: {integrity: sha512-YI/L1QQkBRDtiaGZN+/KolIkNoZuIsCgus1ciueosiqdyWz/weeP+ghFgDQpk2vzA3BkX6/M/kY5SCM03LBDkA==} + idiomorph@0.7.4: + resolution: {integrity: sha512-uCdSpLo3uMfqOmrwXTpR1k/sq4sSmKC7l4o/LdJOEU+MMMq+wkevRqOQYn3lP7vfz9Mv+USBEqPvi0XhdL9ENw==} ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3114,8 +3133,8 @@ packages: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true - jiti@2.5.1: - resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true jquery@3.7.1: @@ -3216,8 +3235,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - keyv@5.5.0: - resolution: {integrity: sha512-QG7qR2tijh1ftOvClut4YKKg1iW6cx3GZsKoGyJPxHkGWK9oJhG9P3j5deP0QQOGDowBMVQFaP+Vm4NpGYvmIQ==} + keyv@5.5.3: + resolution: {integrity: sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==} khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} @@ -3331,8 +3350,8 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.2.1: - resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} magic-string@0.25.9: @@ -3357,9 +3376,9 @@ packages: resolution: {integrity: sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==} engines: {node: '>=20'} - marked@15.0.12: - resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} - engines: {node: '>= 18'} + marked@16.3.0: + resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==} + engines: {node: '>= 20'} hasBin: true marked@4.3.0: @@ -3394,8 +3413,8 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - mermaid@11.11.0: - resolution: {integrity: sha512-9lb/VNkZqWTRjVgCV+l1N+t4kyi94y+l5xrmBmbbxZYkfRl5hEDaTPMOcaWKCl1McG8nBEaMlWwkcAEEgjhBgg==} + mermaid@11.12.0: + resolution: {integrity: sha512-ZudVx73BwrMJfCFmSSJT84y6u5brEoV8DOItdHomNLz32uBjNrelm7mg95X7g+C6UoQH/W6mBLGDEDv73JdxBg==} micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -3573,8 +3592,8 @@ packages: encoding: optional: true - node-releases@2.0.20: - resolution: {integrity: sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==} + node-releases@2.0.21: + resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} node-sarif-builder@2.0.3: resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==} @@ -3726,13 +3745,13 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - playwright-core@1.55.0: - resolution: {integrity: sha512-GvZs4vU3U5ro2nZpeiwyb0zuFaqb9sUiAJuyrWpcGouD8y9/HLgGbNRjIph7zU9D3hnPaisMl9zG9CgFi/biIg==} + playwright-core@1.55.1: + resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==} engines: {node: '>=18'} hasBin: true - playwright@1.55.0: - resolution: {integrity: sha512-sdCWStblvV1YU909Xqx0DhOjPZE4/5lJsIS84IfN9dAZfcl/CIZ5O8l3o0j7hPMjDvqoTF8ZUcc+i/GL5erstA==} + playwright@1.55.1: + resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==} engines: {node: '>=18'} hasBin: true @@ -3760,8 +3779,8 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-js@4.0.1: - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + postcss-js@4.1.0: + resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 @@ -3973,8 +3992,8 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - rollup@4.50.1: - resolution: {integrity: sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==} + rollup@4.52.3: + resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4163,8 +4182,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.0.0: - resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} style-search@0.1.0: resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} @@ -4243,8 +4262,8 @@ packages: svgson@5.3.1: resolution: {integrity: sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==} - swagger-ui-dist@5.29.0: - resolution: {integrity: sha512-gqs7Md3AxP4mbpXAq31o5QW+wGUZsUzVatg70yXpUR245dfIis5jAzufBd+UQM/w2xSfrhvA1eqsrgnl2PbezQ==} + swagger-ui-dist@5.29.1: + resolution: {integrity: sha512-qyjpz0qgcomRr41a5Aye42o69TKwCeHM9F8htLGVeUMKekNS6qAqz9oS7CtSvgGJSppSNAYAIh7vrfrSdHj9zw==} sync-fetch@0.4.5: resolution: {integrity: sha512-esiWJ7ixSKGpd9DJPBTC4ckChqdOjIwJfYhVHkcQ2Gnm41323p1TRmEI+esTQ9ppD+b5opps2OTEGTCGX5kF+g==} @@ -4329,8 +4348,8 @@ packages: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.3: - resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} tippy.js@6.3.7: @@ -4379,15 +4398,15 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - typescript-eslint@8.43.0: - resolution: {integrity: sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w==} + typescript-eslint@8.45.0: + resolution: {integrity: sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - typescript@5.9.2: - resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true @@ -4406,8 +4425,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.10.0: - resolution: {integrity: sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==} + undici-types@7.13.0: + resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==} universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -4422,8 +4441,8 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - updates@16.7.0: - resolution: {integrity: sha512-GOqKdZREAlOR90YBBY8FpkmJOPjjxntYcuAKZRWXK5Pvt2CAcPREk+KeqClG3yqqk+NGWkqAsIxa1ORzQB1iQA==} + updates@16.7.4: + resolution: {integrity: sha512-w8nMoQRFKL7iVTUBUF9pP9lxqe/vqQfxljKcCmY0pKwofXqGEUr3OUQznsGa62V6pvFvg097pm4jT4eDdPq6ow==} engines: {node: '>=20'} hasBin: true @@ -4458,8 +4477,8 @@ packages: vite-string-plugin@1.4.6: resolution: {integrity: sha512-Csjtny8/uVIynzlaRRj4RpHrPAakNwlH9jw6kgQ8tQhc2f0zzA6bCbAgWD0y84EgB8aLNrz7pZFUqSt3LOtk+w==} - vite@7.1.5: - resolution: {integrity: sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==} + vite@7.1.7: + resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -4576,14 +4595,14 @@ packages: vue: optional: true - vue-tsc@3.0.6: - resolution: {integrity: sha512-Tbs8Whd43R2e2nxez4WXPvvdjGbW24rOSgRhLOHXzWiT4pcP4G7KeWh0YCn18rF4bVwv7tggLLZ6MJnO6jXPBg==} + vue-tsc@3.1.0: + resolution: {integrity: sha512-fbMynMG7kXSnqZTRBSCh9ROYaVpXfCZbEO0gY3lqOjLbp361uuS88n6BDajiUriDIF+SGLWoinjvf6stS2J3Gg==} hasBin: true peerDependencies: typescript: '>=5.0.0' - vue@3.5.21: - resolution: {integrity: sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==} + vue@3.5.22: + resolution: {integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -4622,8 +4641,8 @@ packages: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} - webpack@5.101.3: - resolution: {integrity: sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==} + webpack@5.102.0: + resolution: {integrity: sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -4723,7 +4742,7 @@ snapshots: package-manager-detector: 1.3.0 tinyexec: 1.0.1 - '@antfu/utils@9.2.0': {} + '@antfu/utils@9.2.1': {} '@asyncapi/specs@6.10.0': dependencies: @@ -4752,6 +4771,20 @@ snapshots: '@braintree/sanitize-url@7.1.1': {} + '@cacheable/memoize@2.0.3': + dependencies: + '@cacheable/utils': 2.0.3 + + '@cacheable/memory@2.0.3': + dependencies: + '@cacheable/memoize': 2.0.3 + '@cacheable/utils': 2.0.3 + '@keyv/bigmap': 1.0.2 + hookified: 1.12.1 + keyv: 5.5.3 + + '@cacheable/utils@2.0.3': {} + '@chevrotain/cst-dts-gen@11.0.3': dependencies: '@chevrotain/gast': 11.0.3 @@ -4862,105 +4895,107 @@ snapshots: tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.9': + '@esbuild/aix-ppc64@0.25.10': optional: true - '@esbuild/android-arm64@0.25.9': + '@esbuild/android-arm64@0.25.10': optional: true - '@esbuild/android-arm@0.25.9': + '@esbuild/android-arm@0.25.10': optional: true - '@esbuild/android-x64@0.25.9': + '@esbuild/android-x64@0.25.10': optional: true - '@esbuild/darwin-arm64@0.25.9': + '@esbuild/darwin-arm64@0.25.10': optional: true - '@esbuild/darwin-x64@0.25.9': + '@esbuild/darwin-x64@0.25.10': optional: true - '@esbuild/freebsd-arm64@0.25.9': + '@esbuild/freebsd-arm64@0.25.10': optional: true - '@esbuild/freebsd-x64@0.25.9': + '@esbuild/freebsd-x64@0.25.10': optional: true - '@esbuild/linux-arm64@0.25.9': + '@esbuild/linux-arm64@0.25.10': optional: true - '@esbuild/linux-arm@0.25.9': + '@esbuild/linux-arm@0.25.10': optional: true - '@esbuild/linux-ia32@0.25.9': + '@esbuild/linux-ia32@0.25.10': optional: true - '@esbuild/linux-loong64@0.25.9': + '@esbuild/linux-loong64@0.25.10': optional: true - '@esbuild/linux-mips64el@0.25.9': + '@esbuild/linux-mips64el@0.25.10': optional: true - '@esbuild/linux-ppc64@0.25.9': + '@esbuild/linux-ppc64@0.25.10': optional: true - '@esbuild/linux-riscv64@0.25.9': + '@esbuild/linux-riscv64@0.25.10': optional: true - '@esbuild/linux-s390x@0.25.9': + '@esbuild/linux-s390x@0.25.10': optional: true - '@esbuild/linux-x64@0.25.9': + '@esbuild/linux-x64@0.25.10': optional: true - '@esbuild/netbsd-arm64@0.25.9': + '@esbuild/netbsd-arm64@0.25.10': optional: true - '@esbuild/netbsd-x64@0.25.9': + '@esbuild/netbsd-x64@0.25.10': optional: true - '@esbuild/openbsd-arm64@0.25.9': + '@esbuild/openbsd-arm64@0.25.10': optional: true - '@esbuild/openbsd-x64@0.25.9': + '@esbuild/openbsd-x64@0.25.10': optional: true - '@esbuild/openharmony-arm64@0.25.9': + '@esbuild/openharmony-arm64@0.25.10': optional: true - '@esbuild/sunos-x64@0.25.9': + '@esbuild/sunos-x64@0.25.10': optional: true - '@esbuild/win32-arm64@0.25.9': + '@esbuild/win32-arm64@0.25.10': optional: true - '@esbuild/win32-ia32@0.25.9': + '@esbuild/win32-ia32@0.25.10': optional: true - '@esbuild/win32-x64@0.25.9': + '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.35.0(jiti@2.5.1))': + '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.36.0(jiti@2.6.1))': dependencies: escape-string-regexp: 4.0.0 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) ignore: 5.3.2 - '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0(jiti@2.5.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.1))': dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.3.2(eslint@9.35.0(jiti@2.5.1))': + '@eslint/compat@1.4.0(eslint@9.36.0(jiti@2.6.1))': + dependencies: + '@eslint/core': 0.16.0 optionalDependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.1 + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -4971,10 +5006,14 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@0.16.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.1 + debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -4985,7 +5024,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.35.0': {} + '@eslint/js@9.36.0': {} '@eslint/object-schema@2.1.6': {} @@ -5022,12 +5061,12 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.0.1': + '@iconify/utils@3.0.2': dependencies: '@antfu/install-pkg': 1.1.0 - '@antfu/utils': 9.2.0 + '@antfu/utils': 9.2.1 '@iconify/types': 2.0.0 - debug: 4.4.1 + debug: 4.4.3 globals: 15.15.0 kolorist: 1.8.0 local-pkg: 1.1.2 @@ -5053,18 +5092,18 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/source-map@0.3.11': dependencies: '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.30': + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 @@ -5081,7 +5120,11 @@ snapshots: dependencies: jsep: 1.4.0 - '@keyv/serialize@1.1.0': {} + '@keyv/bigmap@1.0.2': + dependencies: + hookified: 1.12.1 + + '@keyv/serialize@1.1.1': {} '@kurkle/color@0.3.4': {} @@ -5099,7 +5142,7 @@ snapshots: dependencies: '@emnapi/core': 1.5.0 '@emnapi/runtime': 1.5.0 - '@tybys/wasm-util': 0.10.0 + '@tybys/wasm-util': 0.10.1 optional: true '@nodelib/fs.scandir@2.1.5': @@ -5175,9 +5218,9 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.55.0': + '@playwright/test@1.55.1': dependencies: - playwright: 1.55.0 + playwright: 1.55.1 '@popperjs/core@2.11.8': {} @@ -5207,77 +5250,80 @@ snapshots: picomatch: 2.3.1 rollup: 2.79.2 - '@rollup/rollup-android-arm-eabi@4.50.1': + '@rollup/rollup-android-arm-eabi@4.52.3': optional: true - '@rollup/rollup-android-arm64@4.50.1': + '@rollup/rollup-android-arm64@4.52.3': optional: true - '@rollup/rollup-darwin-arm64@4.50.1': + '@rollup/rollup-darwin-arm64@4.52.3': optional: true - '@rollup/rollup-darwin-x64@4.50.1': + '@rollup/rollup-darwin-x64@4.52.3': optional: true - '@rollup/rollup-freebsd-arm64@4.50.1': + '@rollup/rollup-freebsd-arm64@4.52.3': optional: true - '@rollup/rollup-freebsd-x64@4.50.1': + '@rollup/rollup-freebsd-x64@4.52.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.50.1': + '@rollup/rollup-linux-arm-gnueabihf@4.52.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.50.1': + '@rollup/rollup-linux-arm-musleabihf@4.52.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.50.1': + '@rollup/rollup-linux-arm64-gnu@4.52.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.50.1': + '@rollup/rollup-linux-arm64-musl@4.52.3': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.50.1': + '@rollup/rollup-linux-loong64-gnu@4.52.3': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.50.1': + '@rollup/rollup-linux-ppc64-gnu@4.52.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.50.1': + '@rollup/rollup-linux-riscv64-gnu@4.52.3': optional: true - '@rollup/rollup-linux-riscv64-musl@4.50.1': + '@rollup/rollup-linux-riscv64-musl@4.52.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.50.1': + '@rollup/rollup-linux-s390x-gnu@4.52.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.50.1': + '@rollup/rollup-linux-x64-gnu@4.52.3': optional: true - '@rollup/rollup-linux-x64-musl@4.50.1': + '@rollup/rollup-linux-x64-musl@4.52.3': optional: true - '@rollup/rollup-openharmony-arm64@4.50.1': + '@rollup/rollup-openharmony-arm64@4.52.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.50.1': + '@rollup/rollup-win32-arm64-msvc@4.52.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.50.1': + '@rollup/rollup-win32-ia32-msvc@4.52.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.50.1': + '@rollup/rollup-win32-x64-gnu@4.52.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.52.3': optional: true '@rtsao/scc@1.1.0': {} '@scarf/scarf@1.4.0': {} - '@silverwind/vue3-calendar-heatmap@2.0.6(tippy.js@6.3.7)(vue@3.5.21(typescript@5.9.2))': + '@silverwind/vue3-calendar-heatmap@2.0.6(tippy.js@6.3.7)(vue@3.5.22(typescript@5.9.3))': dependencies: tippy.js: 6.3.7 - vue: 3.5.21(typescript@5.9.2) + vue: 3.5.22(typescript@5.9.3) '@simonwep/pickr@1.9.0': dependencies: @@ -5446,7 +5492,7 @@ snapshots: '@stoplight/spectral-rulesets': 1.22.0 '@stoplight/spectral-runtime': 1.1.4 '@stoplight/types': 13.20.0 - '@types/node': 24.3.1 + '@types/node': 24.6.2 pony-cause: 1.1.1 rollup: 2.79.2 tslib: 2.8.1 @@ -5463,7 +5509,7 @@ snapshots: '@stoplight/spectral-runtime': 1.1.4 '@stoplight/types': 13.20.0 '@stoplight/yaml': 4.2.3 - '@types/node': 24.3.1 + '@types/node': 24.6.2 ajv: 8.17.1 ast-types: 0.14.2 astring: 1.9.0 @@ -5538,17 +5584,17 @@ snapshots: '@stoplight/yaml-ast-parser': 0.0.50 tslib: 2.8.1 - '@stylistic/eslint-plugin@5.3.1(eslint@9.35.0(jiti@2.5.1))': + '@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1))': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) - '@typescript-eslint/types': 8.43.0 - eslint: 9.35.0(jiti@2.5.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@typescript-eslint/types': 8.45.0 + eslint: 9.36.0(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 picomatch: 4.0.3 - '@stylistic/stylelint-plugin@4.0.0(stylelint@16.24.0(typescript@5.9.2))': + '@stylistic/stylelint-plugin@4.0.0(stylelint@16.24.0(typescript@5.9.3))': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -5557,11 +5603,11 @@ snapshots: postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 style-search: 0.1.0 - stylelint: 16.24.0(typescript@5.9.2) + stylelint: 16.24.0(typescript@5.9.3) '@swc/helpers@0.2.14': {} - '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.101.3)': + '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.102.0)': dependencies: glob: 7.2.3 lodash: 4.17.21 @@ -5570,11 +5616,11 @@ snapshots: spdx-expression-validate: 2.0.0 spdx-satisfies: 5.0.1 superstruct: 0.10.13 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) webpack-sources: 1.4.3 wrap-ansi: 6.2.0 - '@tybys/wasm-util@0.10.0': + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true @@ -5587,7 +5633,7 @@ snapshots: dependencies: '@types/tern': 0.23.9 - '@types/d3-array@3.2.1': {} + '@types/d3-array@3.2.2': {} '@types/d3-axis@3.0.6': dependencies: @@ -5603,7 +5649,7 @@ snapshots: '@types/d3-contour@3.0.6': dependencies: - '@types/d3-array': 3.2.1 + '@types/d3-array': 3.2.2 '@types/geojson': 7946.0.16 '@types/d3-delaunay@6.0.4': {} @@ -5673,7 +5719,7 @@ snapshots: '@types/d3@7.4.3': dependencies: - '@types/d3-array': 3.2.1 + '@types/d3-array': 3.2.2 '@types/d3-axis': 3.0.6 '@types/d3-brush': 3.0.6 '@types/d3-chord': 3.0.6 @@ -5716,7 +5762,7 @@ snapshots: '@types/es-aggregate-error@1.0.6': dependencies: - '@types/node': 24.3.1 + '@types/node': 24.6.2 '@types/eslint-scope@3.7.7': dependencies: @@ -5752,13 +5798,13 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@20.19.13': + '@types/node@20.19.19': dependencies: undici-types: 6.21.0 - '@types/node@24.3.1': + '@types/node@24.6.2': dependencies: - undici-types: 7.10.0 + undici-types: 7.13.0 '@types/pdfobject@2.2.5': {} @@ -5791,97 +5837,97 @@ snapshots: '@types/whatwg-mimetype@3.0.2': {} - '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/type-utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.43.0 - eslint: 9.35.0(jiti@2.5.1) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.45.0 + eslint: 9.36.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.43.0 - debug: 4.4.1 - eslint: 9.35.0(jiti@2.5.1) - typescript: 5.9.2 + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.45.0 + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.43.0(typescript@5.9.2)': + '@typescript-eslint/project-service@8.45.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2) - '@typescript-eslint/types': 8.43.0 - debug: 4.4.1 - typescript: 5.9.2 + '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) + '@typescript-eslint/types': 8.45.0 + debug: 4.4.3 + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.43.0': + '@typescript-eslint/scope-manager@8.45.0': dependencies: - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/visitor-keys': 8.43.0 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/visitor-keys': 8.45.0 - '@typescript-eslint/tsconfig-utils@8.43.0(typescript@5.9.2)': + '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.3)': dependencies: - typescript: 5.9.2 + typescript: 5.9.3 - '@typescript-eslint/type-utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - debug: 4.4.1 - eslint: 9.35.0(jiti@2.5.1) - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.43.0': {} + '@typescript-eslint/types@8.45.0': {} - '@typescript-eslint/typescript-estree@8.43.0(typescript@5.9.2)': + '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.43.0(typescript@5.9.2) - '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2) - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/visitor-keys': 8.43.0 - debug: 4.4.1 + '@typescript-eslint/project-service': 8.45.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/visitor-keys': 8.45.0 + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.9.2) - typescript: 5.9.2 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) - '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/types': 8.43.0 - '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - eslint: 9.35.0(jiti@2.5.1) - typescript: 5.9.2 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.43.0': + '@typescript-eslint/visitor-keys@8.45.0': dependencies: - '@typescript-eslint/types': 8.43.0 + '@typescript-eslint/types': 8.45.0 eslint-visitor-keys: 4.2.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -5943,20 +5989,20 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-vue@6.0.1(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.21(typescript@5.9.2))': + '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.29 - vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) - vue: 3.5.21(typescript@5.9.2) + vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vue: 3.5.22(typescript@5.9.3) - '@vitest/eslint-plugin@1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: - '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - eslint: 9.35.0(jiti@2.5.1) + '@typescript-eslint/scope-manager': 8.45.0 + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) optionalDependencies: - typescript: 5.9.2 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + typescript: 5.9.3 + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -5968,13 +6014,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -5984,7 +6030,7 @@ snapshots: dependencies: '@vitest/utils': 3.2.4 pathe: 2.0.3 - strip-literal: 3.0.0 + strip-literal: 3.1.0 '@vitest/snapshot@3.2.4': dependencies: @@ -5994,7 +6040,7 @@ snapshots: '@vitest/spy@3.2.4': dependencies: - tinyspy: 4.0.3 + tinyspy: 4.0.4 '@vitest/utils@3.2.4': dependencies: @@ -6014,77 +6060,71 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.21': + '@vue/compiler-core@3.5.22': dependencies: '@babel/parser': 7.28.4 - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.22 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.21': + '@vue/compiler-dom@3.5.22': dependencies: - '@vue/compiler-core': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/compiler-core': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/compiler-sfc@3.5.21': + '@vue/compiler-sfc@3.5.22': dependencies: '@babel/parser': 7.28.4 - '@vue/compiler-core': 3.5.21 - '@vue/compiler-dom': 3.5.21 - '@vue/compiler-ssr': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/compiler-core': 3.5.22 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 estree-walker: 2.0.2 magic-string: 0.30.19 postcss: 8.5.6 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.21': + '@vue/compiler-ssr@3.5.22': dependencies: - '@vue/compiler-dom': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/compiler-dom': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/compiler-vue2@2.7.16': - dependencies: - de-indent: 1.0.2 - he: 1.2.0 - - '@vue/language-core@3.0.6(typescript@5.9.2)': + '@vue/language-core@3.1.0(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.23 - '@vue/compiler-dom': 3.5.21 - '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.21 - alien-signals: 2.0.7 + '@vue/compiler-dom': 3.5.22 + '@vue/shared': 3.5.22 + alien-signals: 3.0.0 muggle-string: 0.4.1 path-browserify: 1.0.1 picomatch: 4.0.3 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 - '@vue/reactivity@3.5.21': + '@vue/reactivity@3.5.22': dependencies: - '@vue/shared': 3.5.21 + '@vue/shared': 3.5.22 - '@vue/runtime-core@3.5.21': + '@vue/runtime-core@3.5.22': dependencies: - '@vue/reactivity': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/reactivity': 3.5.22 + '@vue/shared': 3.5.22 - '@vue/runtime-dom@3.5.21': + '@vue/runtime-dom@3.5.22': dependencies: - '@vue/reactivity': 3.5.21 - '@vue/runtime-core': 3.5.21 - '@vue/shared': 3.5.21 + '@vue/reactivity': 3.5.22 + '@vue/runtime-core': 3.5.22 + '@vue/shared': 3.5.22 csstype: 3.1.3 - '@vue/server-renderer@3.5.21(vue@3.5.21(typescript@5.9.2))': + '@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.9.3))': dependencies: - '@vue/compiler-ssr': 3.5.21 - '@vue/shared': 3.5.21 - vue: 3.5.21(typescript@5.9.2) + '@vue/compiler-ssr': 3.5.22 + '@vue/shared': 3.5.22 + vue: 3.5.22(typescript@5.9.3) - '@vue/shared@3.5.21': {} + '@vue/shared@3.5.22': {} '@webassemblyjs/ast@1.14.1': dependencies: @@ -6162,20 +6202,20 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': dependencies: - webpack: 5.101.3(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.101.3) + webpack: 5.102.0(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.0) - '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': dependencies: - webpack: 5.101.3(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.101.3) + webpack: 5.102.0(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.0) - '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.101.3)': + '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': dependencies: - webpack: 5.101.3(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.101.3) + webpack: 5.102.0(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.0) '@xtuc/ieee754@1.2.0': {} @@ -6195,9 +6235,9 @@ snapshots: acorn@8.15.0: {} - add-asset-webpack-plugin@3.1.1(webpack@5.101.3): + add-asset-webpack-plugin@3.1.1(webpack@5.102.0): optionalDependencies: - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) ajv-draft-04@1.0.0(ajv@8.17.1): optionalDependencies: @@ -6230,7 +6270,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - alien-signals@2.0.7: {} + alien-signals@3.0.0: {} ansi-regex@5.0.1: {} @@ -6294,6 +6334,8 @@ snapshots: base64-js@1.5.1: {} + baseline-browser-mapping@2.8.10: {} + big.js@5.2.2: {} binary-extensions@2.3.0: {} @@ -6313,12 +6355,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.25.4: + browserslist@4.26.3: dependencies: - caniuse-lite: 1.0.30001741 - electron-to-chromium: 1.5.215 - node-releases: 2.0.20 - update-browserslist-db: 1.1.3(browserslist@4.25.4) + baseline-browser-mapping: 2.8.10 + caniuse-lite: 1.0.30001746 + electron-to-chromium: 1.5.228 + node-releases: 2.0.21 + update-browserslist-db: 1.1.3(browserslist@4.26.3) buffer-from@1.1.2: {} @@ -6337,16 +6380,19 @@ snapshots: cac@6.7.14: {} - cacheable@1.10.4: + cacheable@2.0.3: dependencies: - hookified: 1.12.0 - keyv: 5.5.0 + '@cacheable/memoize': 2.0.3 + '@cacheable/memory': 2.0.3 + '@cacheable/utils': 2.0.3 + hookified: 1.12.1 + keyv: 5.5.3 callsites@3.1.0: {} camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001741: {} + caniuse-lite@1.0.30001746: {} chai@5.3.3: dependencies: @@ -6424,7 +6470,7 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - clippie@4.1.7: {} + clippie@4.1.8: {} cliui@7.0.4: dependencies: @@ -6486,7 +6532,7 @@ snapshots: core-js-compat@3.45.1: dependencies: - browserslist: 4.25.4 + browserslist: 4.26.3 core-js@3.32.2: {} @@ -6498,14 +6544,14 @@ snapshots: dependencies: layout-base: 2.0.1 - cosmiconfig@9.0.0(typescript@5.9.2): + cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.1 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 cropperjs@1.6.2: {} @@ -6517,7 +6563,7 @@ snapshots: css-functions-list@3.2.3: {} - css-loader@7.1.2(webpack@5.101.3): + css-loader@7.1.2(webpack@5.102.0): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -6528,7 +6574,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.2 optionalDependencies: - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) css-select@5.2.2: dependencies: @@ -6754,13 +6800,11 @@ snapshots: dayjs@1.11.18: {} - de-indent@1.0.2: {} - debug@3.2.7: dependencies: ms: 2.1.3 - debug@4.4.1: + debug@4.4.3: dependencies: ms: 2.1.3 @@ -6819,7 +6863,7 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.2.6: + dompurify@3.2.7: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -6844,7 +6888,7 @@ snapshots: codemirror-spell-checker: 1.1.2 marked: 4.3.0 - electron-to-chromium@1.5.215: {} + electron-to-chromium@1.5.228: {} emoji-regex@10.5.0: {} @@ -6863,50 +6907,50 @@ snapshots: env-paths@2.2.1: {} - envinfo@7.14.0: {} + envinfo@7.15.0: {} - error-ex@1.3.2: + error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 es-module-lexer@1.7.0: {} - esbuild-loader@4.3.0(webpack@5.101.3): + esbuild-loader@4.3.0(webpack@5.102.0): dependencies: - esbuild: 0.25.9 + esbuild: 0.25.10 get-tsconfig: 4.10.1 loader-utils: 2.0.4 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) webpack-sources: 1.4.3 - esbuild@0.25.9: + esbuild@0.25.10: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.9 - '@esbuild/android-arm': 0.25.9 - '@esbuild/android-arm64': 0.25.9 - '@esbuild/android-x64': 0.25.9 - '@esbuild/darwin-arm64': 0.25.9 - '@esbuild/darwin-x64': 0.25.9 - '@esbuild/freebsd-arm64': 0.25.9 - '@esbuild/freebsd-x64': 0.25.9 - '@esbuild/linux-arm': 0.25.9 - '@esbuild/linux-arm64': 0.25.9 - '@esbuild/linux-ia32': 0.25.9 - '@esbuild/linux-loong64': 0.25.9 - '@esbuild/linux-mips64el': 0.25.9 - '@esbuild/linux-ppc64': 0.25.9 - '@esbuild/linux-riscv64': 0.25.9 - '@esbuild/linux-s390x': 0.25.9 - '@esbuild/linux-x64': 0.25.9 - '@esbuild/netbsd-arm64': 0.25.9 - '@esbuild/netbsd-x64': 0.25.9 - '@esbuild/openbsd-arm64': 0.25.9 - '@esbuild/openbsd-x64': 0.25.9 - '@esbuild/openharmony-arm64': 0.25.9 - '@esbuild/sunos-x64': 0.25.9 - '@esbuild/win32-arm64': 0.25.9 - '@esbuild/win32-ia32': 0.25.9 - '@esbuild/win32-x64': 0.25.9 + '@esbuild/aix-ppc64': 0.25.10 + '@esbuild/android-arm': 0.25.10 + '@esbuild/android-arm64': 0.25.10 + '@esbuild/android-x64': 0.25.10 + '@esbuild/darwin-arm64': 0.25.10 + '@esbuild/darwin-x64': 0.25.10 + '@esbuild/freebsd-arm64': 0.25.10 + '@esbuild/freebsd-x64': 0.25.10 + '@esbuild/linux-arm': 0.25.10 + '@esbuild/linux-arm64': 0.25.10 + '@esbuild/linux-ia32': 0.25.10 + '@esbuild/linux-loong64': 0.25.10 + '@esbuild/linux-mips64el': 0.25.10 + '@esbuild/linux-ppc64': 0.25.10 + '@esbuild/linux-riscv64': 0.25.10 + '@esbuild/linux-s390x': 0.25.10 + '@esbuild/linux-x64': 0.25.10 + '@esbuild/netbsd-arm64': 0.25.10 + '@esbuild/netbsd-x64': 0.25.10 + '@esbuild/openbsd-arm64': 0.25.10 + '@esbuild/openbsd-x64': 0.25.10 + '@esbuild/openharmony-arm64': 0.25.10 + '@esbuild/sunos-x64': 0.25.10 + '@esbuild/win32-arm64': 0.25.10 + '@esbuild/win32-ia32': 0.25.10 + '@esbuild/win32-x64': 0.25.10 escalade@3.2.0: {} @@ -6914,14 +6958,14 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.6.5(eslint@9.35.0(jiti@2.5.1)): + eslint-compat-utils@0.6.5(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) semver: 7.7.2 - eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)): + eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) eslint-import-context@0.1.9(unrs-resolver@1.11.1): dependencies: @@ -6938,10 +6982,10 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)): dependencies: - debug: 4.4.1 - eslint: 9.35.0(jiti@2.5.1) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 @@ -6949,87 +6993,87 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - eslint: 9.35.0(jiti@2.5.1) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-array-func@5.0.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-array-func@5.1.0(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) - eslint-plugin-escompat@3.11.4(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-escompat@3.11.4(eslint@9.36.0(jiti@2.6.1)): dependencies: - browserslist: 4.25.4 - eslint: 9.35.0(jiti@2.5.1) + browserslist: 4.26.3 + eslint: 9.36.0(jiti@2.6.1) - eslint-plugin-eslint-comments@3.2.0(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-eslint-comments@3.2.0(eslint@9.36.0(jiti@2.6.1)): dependencies: escape-string-regexp: 1.0.5 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) ignore: 5.3.2 - eslint-plugin-filenames@1.3.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-filenames@1.3.2(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 lodash.upperfirst: 4.3.1 - eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): dependencies: - '@eslint/compat': 1.3.2(eslint@9.35.0(jiti@2.5.1)) + '@eslint/compat': 1.4.0(eslint@9.36.0(jiti@2.6.1)) '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.35.0 + '@eslint/js': 9.36.0 '@github/browserslist-config': 1.0.0 - '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) aria-query: 5.3.2 - eslint: 9.35.0(jiti@2.5.1) - eslint-config-prettier: 10.1.8(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-escompat: 3.11.4(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-eslint-comments: 3.2.0(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-filenames: 1.3.2(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-i18n-text: 1.0.1(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.35.0(jiti@2.5.1)) + eslint: 9.36.0(jiti@2.6.1) + eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-escompat: 3.11.4(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-eslint-comments: 3.2.0(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-filenames: 1.3.2(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-i18n-text: 1.0.1(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.36.0(jiti@2.6.1)) eslint-plugin-no-only-tests: 3.3.0 - eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(prettier@3.6.2) + eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2) eslint-rule-documentation: 1.0.23 globals: 16.4.0 jsx-ast-utils: 3.3.5 prettier: 3.6.2 svg-element-attributes: 1.3.1 - typescript: 5.9.2 - typescript-eslint: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + typescript: 5.9.3 + typescript-eslint: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - '@types/eslint' - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-i18n-text@1.0.1(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-i18n-text@1.0.1(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)): dependencies: - '@typescript-eslint/types': 8.43.0 + '@typescript-eslint/types': 8.45.0 comment-parser: 1.4.1 - debug: 4.4.1 - eslint: 9.35.0(jiti@2.5.1) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.0.3 @@ -7037,12 +7081,12 @@ snapshots: stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: '@nolyfill/array-includes@1.0.44' @@ -7051,9 +7095,9 @@ snapshots: array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44' debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) hasown: '@nolyfill/hasown@1.0.44' is-core-module: '@nolyfill/is-core-module@1.0.39' is-glob: 4.0.3 @@ -7065,13 +7109,13 @@ snapshots: string.prototype.trimend: '@nolyfill/string.prototype.trimend@1.0.44' tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.36.0(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: '@nolyfill/array-includes@1.0.44' @@ -7081,7 +7125,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) hasown: '@nolyfill/hasown@1.0.44' jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -7092,64 +7136,64 @@ snapshots: eslint-plugin-no-only-tests@3.3.0: {} - eslint-plugin-no-use-extend-native@0.7.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-no-use-extend-native@0.7.2(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) is-get-set-prop: 2.0.0 is-js-type: 3.0.0 is-obj-prop: 2.0.0 is-proto-prop: 3.0.1 - eslint-plugin-playwright@2.2.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-playwright@2.2.2(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) globals: 13.24.0 - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@9.35.0(jiti@2.5.1)) + eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-regexp@2.10.0(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-regexp@2.10.0(eslint@9.36.0(jiti@2.6.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 comment-parser: 1.4.1 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) jsdoc-type-pratt-parser: 4.8.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-sonarjs@3.0.5(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-sonarjs@3.0.5(eslint@9.36.0(jiti@2.6.1)): dependencies: '@eslint-community/regexpp': 4.12.1 builtin-modules: 3.3.0 bytes: 3.1.2 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) functional-red-black-tree: 1.0.1 jsx-ast-utils-x: 0.1.0 lodash.merge: 4.6.2 minimatch: 9.0.5 scslre: 0.3.0 semver: 7.7.2 - typescript: 5.9.2 + typescript: 5.9.3 - eslint-plugin-unicorn@61.0.2(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-unicorn@61.0.2(eslint@9.36.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.27.1 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) '@eslint/plugin-kit': 0.3.5 change-case: 5.4.4 ci-info: 4.3.0 clean-regexp: 1.0.0 core-js-compat: 3.45.1 - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) esquery: 1.6.0 find-up-simple: 1.0.1 globals: 16.4.0 @@ -7162,37 +7206,38 @@ snapshots: semver: 7.7.2 strip-indent: 4.1.0 - eslint-plugin-vue-scoped-css@2.12.0(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))): + eslint-plugin-vue-scoped-css@2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) - eslint: 9.35.0(jiti@2.5.1) - eslint-compat-utils: 0.6.5(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + eslint: 9.36.0(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.1)) lodash: 4.17.21 postcss: 8.5.6 postcss-safe-parser: 6.0.0(postcss@8.5.6) postcss-scss: 4.0.9(postcss@8.5.6) postcss-selector-parser: 7.1.0 postcss-styl: 0.12.3 - vue-eslint-parser: 10.2.0(eslint@9.35.0(jiti@2.5.1)) + vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))): + eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) - eslint: 9.35.0(jiti@2.5.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + eslint: 9.36.0(jiti@2.6.1) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 semver: 7.7.2 - vue-eslint-parser: 10.2.0(eslint@9.35.0(jiti@2.5.1)) + vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1)) xml-name-validator: 4.0.0 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@stylistic/eslint-plugin': 5.4.0(eslint@9.36.0(jiti@2.6.1)) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-wc@3.0.1(eslint@9.35.0(jiti@2.5.1)): + eslint-plugin-wc@3.0.2(eslint@9.36.0(jiti@2.6.1)): dependencies: - eslint: 9.35.0(jiti@2.5.1) + eslint: 9.36.0(jiti@2.6.1) is-valid-element-name: 1.0.0 js-levenshtein-esm: 2.0.0 @@ -7212,15 +7257,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.35.0(jiti@2.5.1): + eslint@9.36.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.1 '@eslint/core': 0.15.2 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.35.0 + '@eslint/js': 9.36.0 '@eslint/plugin-kit': 0.3.5 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 @@ -7230,7 +7275,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -7250,7 +7295,7 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.5.1 + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -7340,7 +7385,7 @@ snapshots: file-entry-cache@10.1.4: dependencies: - flat-cache: 6.1.13 + flat-cache: 6.1.17 file-entry-cache@8.0.0: dependencies: @@ -7367,11 +7412,11 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 - flat-cache@6.1.13: + flat-cache@6.1.17: dependencies: - cacheable: 1.10.4 + cacheable: 2.0.3 flatted: 3.3.3 - hookified: 1.12.0 + hookified: 1.12.1 flat@5.0.2: {} @@ -7489,9 +7534,9 @@ snapshots: hammerjs@2.0.8: {} - happy-dom@18.0.1: + happy-dom@19.0.2: dependencies: - '@types/node': 20.19.13 + '@types/node': 20.19.19 '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 @@ -7499,9 +7544,7 @@ snapshots: hash-sum@2.0.0: {} - he@1.2.0: {} - - hookified@1.12.0: {} + hookified@1.12.1: {} hpagent@1.2.0: {} @@ -7524,7 +7567,7 @@ snapshots: dependencies: postcss: 8.5.6 - idiomorph@0.7.3: {} + idiomorph@0.7.4: {} ieee754@1.2.1: {} @@ -7653,13 +7696,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.3.1 + '@types/node': 24.6.2 merge-stream: 2.0.0 supports-color: 8.1.1 jiti@1.21.7: {} - jiti@2.5.1: {} + jiti@2.6.1: {} jquery@3.7.1: {} @@ -7736,9 +7779,9 @@ snapshots: dependencies: json-buffer: 3.0.1 - keyv@5.5.0: + keyv@5.5.3: dependencies: - '@keyv/serialize': 1.1.0 + '@keyv/serialize': 1.1.1 khroma@2.1.0: {} @@ -7833,7 +7876,7 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.2.1: {} + lru-cache@11.2.2: {} magic-string@0.25.9: dependencies: @@ -7883,7 +7926,7 @@ snapshots: transitivePeerDependencies: - supports-color - marked@15.0.12: {} + marked@16.3.0: {} marked@4.3.0: {} @@ -7908,10 +7951,10 @@ snapshots: merge2@1.4.1: {} - mermaid@11.11.0: + mermaid@11.12.0: dependencies: '@braintree/sanitize-url': 7.1.1 - '@iconify/utils': 3.0.1 + '@iconify/utils': 3.0.2 '@mermaid-js/parser': 0.6.2 '@types/d3': 7.4.3 cytoscape: 3.33.1 @@ -7921,11 +7964,11 @@ snapshots: d3-sankey: 0.12.3 dagre-d3-es: 7.0.11 dayjs: 1.11.18 - dompurify: 3.2.6 + dompurify: 3.2.7 katex: 0.16.22 khroma: 2.1.0 lodash-es: 4.17.21 - marked: 15.0.12 + marked: 16.3.0 roughjs: 4.6.6 stylis: 4.3.6 ts-dedent: 2.2.0 @@ -8086,7 +8129,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.1 + debug: 4.4.3 decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -8116,11 +8159,11 @@ snapshots: dependencies: mime-db: 1.52.0 - mini-css-extract-plugin@2.9.4(webpack@5.101.3): + mini-css-extract-plugin@2.9.4(webpack@5.102.0): dependencies: schema-utils: 4.3.2 tapable: 2.2.3 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) minimatch@10.0.3: dependencies: @@ -8145,11 +8188,11 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.1 - monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.53.0)(webpack@5.101.3): + monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.53.0)(webpack@5.102.0): dependencies: loader-utils: 2.0.4 monaco-editor: 0.53.0 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) monaco-editor@0.53.0: dependencies: @@ -8195,7 +8238,7 @@ snapshots: dependencies: whatwg-url: 5.0.0 - node-releases@2.0.20: {} + node-releases@2.0.21: {} node-sarif-builder@2.0.3: dependencies: @@ -8274,7 +8317,7 @@ snapshots: parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 - error-ex: 1.3.2 + error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -8297,7 +8340,7 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.2.1 + lru-cache: 11.2.2 minipass: 7.1.2 path-type@4.0.0: {} @@ -8336,11 +8379,11 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 - playwright-core@1.55.0: {} + playwright-core@1.55.1: {} - playwright@1.55.0: + playwright@1.55.1: dependencies: - playwright-core: 1.55.0 + playwright-core: 1.55.1 optionalDependencies: fsevents: 2.3.2 @@ -8369,7 +8412,7 @@ snapshots: read-cache: 1.0.0 resolve: 1.22.10 - postcss-js@4.0.1(postcss@8.5.6): + postcss-js@4.1.0(postcss@8.5.6): dependencies: camelcase-css: 2.0.1 postcss: 8.5.6 @@ -8381,14 +8424,14 @@ snapshots: optionalDependencies: postcss: 8.5.6 - postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.101.3): + postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0): dependencies: - cosmiconfig: 9.0.0(typescript@5.9.2) - jiti: 2.5.1 + cosmiconfig: 9.0.0(typescript@5.9.3) + jiti: 2.6.1 postcss: 8.5.6 semver: 7.7.2 optionalDependencies: - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) transitivePeerDependencies: - typescript @@ -8444,7 +8487,7 @@ snapshots: postcss-styl@0.12.3: dependencies: - debug: 4.4.1 + debug: 4.4.3 fast-diff: 1.3.0 lodash.sortedlastindex: 4.1.0 postcss: 8.5.6 @@ -8543,31 +8586,32 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - rollup@4.50.1: + rollup@4.52.3: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.50.1 - '@rollup/rollup-android-arm64': 4.50.1 - '@rollup/rollup-darwin-arm64': 4.50.1 - '@rollup/rollup-darwin-x64': 4.50.1 - '@rollup/rollup-freebsd-arm64': 4.50.1 - '@rollup/rollup-freebsd-x64': 4.50.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.50.1 - '@rollup/rollup-linux-arm-musleabihf': 4.50.1 - '@rollup/rollup-linux-arm64-gnu': 4.50.1 - '@rollup/rollup-linux-arm64-musl': 4.50.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.50.1 - '@rollup/rollup-linux-ppc64-gnu': 4.50.1 - '@rollup/rollup-linux-riscv64-gnu': 4.50.1 - '@rollup/rollup-linux-riscv64-musl': 4.50.1 - '@rollup/rollup-linux-s390x-gnu': 4.50.1 - '@rollup/rollup-linux-x64-gnu': 4.50.1 - '@rollup/rollup-linux-x64-musl': 4.50.1 - '@rollup/rollup-openharmony-arm64': 4.50.1 - '@rollup/rollup-win32-arm64-msvc': 4.50.1 - '@rollup/rollup-win32-ia32-msvc': 4.50.1 - '@rollup/rollup-win32-x64-msvc': 4.50.1 + '@rollup/rollup-android-arm-eabi': 4.52.3 + '@rollup/rollup-android-arm64': 4.52.3 + '@rollup/rollup-darwin-arm64': 4.52.3 + '@rollup/rollup-darwin-x64': 4.52.3 + '@rollup/rollup-freebsd-arm64': 4.52.3 + '@rollup/rollup-freebsd-x64': 4.52.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.3 + '@rollup/rollup-linux-arm-musleabihf': 4.52.3 + '@rollup/rollup-linux-arm64-gnu': 4.52.3 + '@rollup/rollup-linux-arm64-musl': 4.52.3 + '@rollup/rollup-linux-loong64-gnu': 4.52.3 + '@rollup/rollup-linux-ppc64-gnu': 4.52.3 + '@rollup/rollup-linux-riscv64-gnu': 4.52.3 + '@rollup/rollup-linux-riscv64-musl': 4.52.3 + '@rollup/rollup-linux-s390x-gnu': 4.52.3 + '@rollup/rollup-linux-x64-gnu': 4.52.3 + '@rollup/rollup-linux-x64-musl': 4.52.3 + '@rollup/rollup-openharmony-arm64': 4.52.3 + '@rollup/rollup-win32-arm64-msvc': 4.52.3 + '@rollup/rollup-win32-ia32-msvc': 4.52.3 + '@rollup/rollup-win32-x64-gnu': 4.52.3 + '@rollup/rollup-win32-x64-msvc': 4.52.3 fsevents: 2.3.3 roughjs@4.6.6: @@ -8749,31 +8793,31 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.0.0: + strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 style-search@0.1.0: {} - stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.9.2)): + stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.2) + stylelint: 16.24.0(typescript@5.9.3) - stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.24.0(typescript@5.9.2)): + stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.24.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.2) + stylelint: 16.24.0(typescript@5.9.3) - stylelint-declaration-strict-value@1.10.11(stylelint@16.24.0(typescript@5.9.2)): + stylelint-declaration-strict-value@1.10.11(stylelint@16.24.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.2) + stylelint: 16.24.0(typescript@5.9.3) - stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.24.0(typescript@5.9.2)): + stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.24.0(typescript@5.9.3)): dependencies: postcss-value-parser: 4.2.0 resolve: 1.22.10 - stylelint: 16.24.0(typescript@5.9.2) + stylelint: 16.24.0(typescript@5.9.3) - stylelint@16.24.0(typescript@5.9.2): + stylelint@16.24.0(typescript@5.9.3): dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -8782,10 +8826,10 @@ snapshots: '@dual-bundle/import-meta-resolve': 4.2.1 balanced-match: 2.0.0 colord: 2.9.3 - cosmiconfig: 9.0.0(typescript@5.9.2) + cosmiconfig: 9.0.0(typescript@5.9.3) css-functions-list: 3.2.3 css-tree: 3.1.0 - debug: 4.4.1 + debug: 4.4.3 fast-glob: 3.3.3 fastest-levenshtein: 1.0.16 file-entry-cache: 10.1.4 @@ -8822,7 +8866,7 @@ snapshots: stylus@0.57.0: dependencies: css: 3.0.0 - debug: 4.4.1 + debug: 4.4.3 glob: 7.2.3 safer-buffer: '@nolyfill/safer-buffer@1.0.44' sax: 1.2.4 @@ -8876,7 +8920,7 @@ snapshots: deep-rename-keys: 0.2.1 xml-reader: 2.4.3 - swagger-ui-dist@5.29.0: + swagger-ui-dist@5.29.1: dependencies: '@scarf/scarf': 1.4.0 @@ -8917,7 +8961,7 @@ snapshots: picocolors: 1.1.1 postcss: 8.5.6 postcss-import: 15.1.0(postcss@8.5.6) - postcss-js: 4.0.1(postcss@8.5.6) + postcss-js: 4.1.0(postcss@8.5.6) postcss-load-config: 4.0.2(postcss@8.5.6) postcss-nested: 6.2.0(postcss@8.5.6) postcss-selector-parser: 6.1.2 @@ -8928,14 +8972,14 @@ snapshots: tapable@2.2.3: {} - terser-webpack-plugin@5.3.14(webpack@5.101.3): + terser-webpack-plugin@5.3.14(webpack@5.102.0): dependencies: - '@jridgewell/trace-mapping': 0.3.30 + '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.2 serialize-javascript: 6.0.2 terser: 5.44.0 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) terser@5.44.0: dependencies: @@ -8975,7 +9019,7 @@ snapshots: tinyrainbow@2.0.0: {} - tinyspy@4.0.3: {} + tinyspy@4.0.4: {} tippy.js@6.3.7: dependencies: @@ -8991,9 +9035,9 @@ snapshots: tributejs@5.1.3: {} - ts-api-utils@2.1.0(typescript@5.9.2): + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: - typescript: 5.9.2 + typescript: 5.9.3 ts-dedent@2.2.0: {} @@ -9016,18 +9060,18 @@ snapshots: type-fest@0.20.2: {} - typescript-eslint@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): + typescript-eslint@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - eslint: 9.35.0(jiti@2.5.1) - typescript: 5.9.2 + '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.36.0(jiti@2.6.1) + typescript: 5.9.3 transitivePeerDependencies: - supports-color - typescript@5.9.2: {} + typescript@5.9.3: {} typo-js@1.3.1: {} @@ -9039,7 +9083,7 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.10.0: {} + undici-types@7.13.0: {} universalify@2.0.1: {} @@ -9067,13 +9111,13 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - update-browserslist-db@1.1.3(browserslist@4.25.4): + update-browserslist-db@1.1.3(browserslist@4.26.3): dependencies: - browserslist: 4.25.4 + browserslist: 4.26.3 escalade: 3.2.0 picocolors: 1.1.1 - updates@16.7.0: {} + updates@16.7.4: {} uri-js@4.4.1: dependencies: @@ -9093,13 +9137,13 @@ snapshots: vanilla-colorful@0.7.2: {} - vite-node@3.2.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.1 + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -9116,34 +9160,34 @@ snapshots: vite-string-plugin@1.4.6: {} - vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: - esbuild: 0.25.9 + esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.50.1 + rollup: 4.52.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.3.1 + '@types/node': 24.6.2 fsevents: 2.3.3 - jiti: 2.5.1 + jiti: 2.6.1 stylus: 0.57.0 terser: 5.44.0 yaml: 2.8.1 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 chai: 5.3.3 - debug: 4.4.1 + debug: 4.4.3 expect-type: 1.2.2 magic-string: 0.30.19 pathe: 2.0.3 @@ -9154,13 +9198,13 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.3.1 - happy-dom: 18.0.1 + '@types/node': 24.6.2 + happy-dom: 19.0.2 transitivePeerDependencies: - jiti - less @@ -9194,21 +9238,21 @@ snapshots: vscode-uri@3.1.0: {} - vue-bar-graph@2.2.0(typescript@5.9.2): + vue-bar-graph@2.2.0(typescript@5.9.3): dependencies: - vue: 3.5.21(typescript@5.9.2) + vue: 3.5.22(typescript@5.9.3) transitivePeerDependencies: - typescript - vue-chartjs@5.3.2(chart.js@4.5.0)(vue@3.5.21(typescript@5.9.2)): + vue-chartjs@5.3.2(chart.js@4.5.0)(vue@3.5.22(typescript@5.9.3)): dependencies: chart.js: 4.5.0 - vue: 3.5.21(typescript@5.9.2) + vue: 3.5.22(typescript@5.9.3) - vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1)): + vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1)): dependencies: - debug: 4.4.1 - eslint: 9.35.0(jiti@2.5.1) + debug: 4.4.3 + eslint: 9.36.0(jiti@2.6.1) eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -9217,30 +9261,30 @@ snapshots: transitivePeerDependencies: - supports-color - vue-loader@17.4.2(vue@3.5.21(typescript@5.9.2))(webpack@5.101.3): + vue-loader@17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0): dependencies: chalk: 4.1.2 hash-sum: 2.0.0 watchpack: 2.4.4 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) optionalDependencies: - vue: 3.5.21(typescript@5.9.2) + vue: 3.5.22(typescript@5.9.3) - vue-tsc@3.0.6(typescript@5.9.2): + vue-tsc@3.1.0(typescript@5.9.3): dependencies: '@volar/typescript': 2.4.23 - '@vue/language-core': 3.0.6(typescript@5.9.2) - typescript: 5.9.2 + '@vue/language-core': 3.1.0(typescript@5.9.3) + typescript: 5.9.3 - vue@3.5.21(typescript@5.9.2): + vue@3.5.22(typescript@5.9.3): dependencies: - '@vue/compiler-dom': 3.5.21 - '@vue/compiler-sfc': 3.5.21 - '@vue/runtime-dom': 3.5.21 - '@vue/server-renderer': 3.5.21(vue@3.5.21(typescript@5.9.2)) - '@vue/shared': 3.5.21 + '@vue/compiler-dom': 3.5.22 + '@vue/compiler-sfc': 3.5.22 + '@vue/runtime-dom': 3.5.22 + '@vue/server-renderer': 3.5.22(vue@3.5.22(typescript@5.9.3)) + '@vue/shared': 3.5.22 optionalDependencies: - typescript: 5.9.2 + typescript: 5.9.3 watchpack@2.4.4: dependencies: @@ -9249,21 +9293,21 @@ snapshots: webidl-conversions@3.0.1: {} - webpack-cli@6.0.1(webpack@5.101.3): + webpack-cli@6.0.1(webpack@5.102.0): dependencies: '@discoveryjs/json-ext': 0.6.3 - '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) - '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) - '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.101.3) + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) colorette: 2.0.20 commander: 12.1.0 cross-spawn: 7.0.6 - envinfo: 7.14.0 + envinfo: 7.15.0 fastest-levenshtein: 1.0.16 import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.101.3(webpack-cli@6.0.1) + webpack: 5.102.0(webpack-cli@6.0.1) webpack-merge: 6.0.1 webpack-merge@6.0.1: @@ -9279,7 +9323,7 @@ snapshots: webpack-sources@3.3.3: {} - webpack@5.101.3(webpack-cli@6.0.1): + webpack@5.102.0(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -9289,7 +9333,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.25.4 + browserslist: 4.26.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.3 es-module-lexer: 1.7.0 @@ -9303,11 +9347,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.2 tapable: 2.2.3 - terser-webpack-plugin: 5.3.14(webpack@5.101.3) + terser-webpack-plugin: 5.3.14(webpack@5.102.0) watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: - webpack-cli: 6.0.1(webpack@5.101.3) + webpack-cli: 6.0.1(webpack@5.102.0) transitivePeerDependencies: - '@swc/core' - esbuild diff --git a/uv.lock b/uv.lock index db2fa1212d..15e0faede1 100644 --- a/uv.lock +++ b/uv.lock @@ -4,14 +4,14 @@ requires-python = ">=3.10" [[package]] name = "click" -version = "8.2.1" +version = "8.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, ] [[package]] @@ -136,125 +136,173 @@ wheels = [ [[package]] name = "pyyaml" -version = "6.0.2" +version = "6.0.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, - { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, - { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, - { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, - { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, - { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, - { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, - { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, - { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, - { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, - { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, - { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, - { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, - { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, - { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, - { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] [[package]] name = "regex" -version = "2025.9.1" +version = "2025.9.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/5a/4c63457fbcaf19d138d72b2e9b39405954f98c0349b31c601bfcb151582c/regex-2025.9.1.tar.gz", hash = "sha256:88ac07b38d20b54d79e704e38aa3bd2c0f8027432164226bdee201a1c0c9c9ff", size = 400852, upload-time = "2025-09-01T22:10:10.479Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/d3/eaa0d28aba6ad1827ad1e716d9a93e1ba963ada61887498297d3da715133/regex-2025.9.18.tar.gz", hash = "sha256:c5ba23274c61c6fef447ba6a39333297d0c247f53059dba0bca415cac511edc4", size = 400917, upload-time = "2025-09-19T00:38:35.79Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/c1/ed9ef923156105a78aa004f9390e5dd87eadc29f5ca8840f172cadb638de/regex-2025.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5aa2a6a73bf218515484b36a0d20c6ad9dc63f6339ff6224147b0e2c095ee55", size = 484813, upload-time = "2025-09-01T22:07:45.528Z" }, - { url = "https://files.pythonhosted.org/packages/05/de/97957618a774c67f892609eee2fafe3e30703fbbba66de5e6b79d7196dbc/regex-2025.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c2ff5c01d5e47ad5fc9d31bcd61e78c2fa0068ed00cab86b7320214446da766", size = 288981, upload-time = "2025-09-01T22:07:48.464Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b0/441afadd0a6ffccbd58a9663e5bdd182daa237893e5f8ceec6ff9df4418a/regex-2025.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d49dc84e796b666181de8a9973284cad6616335f01b52bf099643253094920fc", size = 286608, upload-time = "2025-09-01T22:07:50.484Z" }, - { url = "https://files.pythonhosted.org/packages/6e/cf/d89aecaf17e999ab11a3ef73fc9ab8b64f4e156f121250ef84340b35338d/regex-2025.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9914fe1040874f83c15fcea86d94ea54091b0666eab330aaab69e30d106aabe", size = 780459, upload-time = "2025-09-01T22:07:52.34Z" }, - { url = "https://files.pythonhosted.org/packages/f6/05/05884594a9975a29597917bbdd6837f7b97e8ac23faf22d628aa781e58f7/regex-2025.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e71bceb3947362ec5eabd2ca0870bb78eae4edfc60c6c21495133c01b6cd2df4", size = 849276, upload-time = "2025-09-01T22:07:54.591Z" }, - { url = "https://files.pythonhosted.org/packages/8c/8d/2b3067506838d02096bf107beb129b2ce328cdf776d6474b7f542c0a7bfd/regex-2025.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67a74456f410fe5e869239ee7a5423510fe5121549af133809d9591a8075893f", size = 897320, upload-time = "2025-09-01T22:07:56.129Z" }, - { url = "https://files.pythonhosted.org/packages/9e/b3/0f9f7766e980b900df0ba9901b52871a2e4203698fb35cdebd219240d5f7/regex-2025.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5c3b96ed0223b32dbdc53a83149b6de7ca3acd5acd9c8e64b42a166228abe29c", size = 789931, upload-time = "2025-09-01T22:07:57.834Z" }, - { url = "https://files.pythonhosted.org/packages/47/9f/7b2f29c8f8b698eb44be5fc68e8b9c8d32e99635eac5defc98de114e9f35/regex-2025.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:113d5aa950f428faf46fd77d452df62ebb4cc6531cb619f6cc30a369d326bfbd", size = 780764, upload-time = "2025-09-01T22:07:59.413Z" }, - { url = "https://files.pythonhosted.org/packages/ac/ac/56176caa86155c14462531eb0a4ddc450d17ba8875001122b3b7c0cb01bf/regex-2025.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fcdeb38de4f7f3d69d798f4f371189061446792a84e7c92b50054c87aae9c07c", size = 773610, upload-time = "2025-09-01T22:08:01.042Z" }, - { url = "https://files.pythonhosted.org/packages/39/e8/9d6b9bd43998268a9de2f35602077519cacc9cb149f7381758cf8f502ba7/regex-2025.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4bcdff370509164b67a6c8ec23c9fb40797b72a014766fdc159bb809bd74f7d8", size = 844090, upload-time = "2025-09-01T22:08:02.94Z" }, - { url = "https://files.pythonhosted.org/packages/fd/92/d89743b089005cae4cb81cc2fe177e180b7452e60f29de53af34349640f8/regex-2025.9.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7383efdf6e8e8c61d85e00cfb2e2e18da1a621b8bfb4b0f1c2747db57b942b8f", size = 834775, upload-time = "2025-09-01T22:08:04.781Z" }, - { url = "https://files.pythonhosted.org/packages/01/8f/86a3e0aaa89295d2a3445bb238e56369963ef6b02a5b4aa3362f4e687413/regex-2025.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1ec2bd3bdf0f73f7e9f48dca550ba7d973692d5e5e9a90ac42cc5f16c4432d8b", size = 778521, upload-time = "2025-09-01T22:08:06.596Z" }, - { url = "https://files.pythonhosted.org/packages/3e/df/72072acb370ee8577c255717f8a58264f1d0de40aa3c9e6ebd5271cac633/regex-2025.9.1-cp310-cp310-win32.whl", hash = "sha256:9627e887116c4e9c0986d5c3b4f52bcfe3df09850b704f62ec3cbf177a0ae374", size = 264105, upload-time = "2025-09-01T22:08:08.708Z" }, - { url = "https://files.pythonhosted.org/packages/97/73/fb82faaf0375aeaa1bb675008246c79b6779fa5688585a35327610ea0e2e/regex-2025.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:94533e32dc0065eca43912ee6649c90ea0681d59f56d43c45b5bcda9a740b3dd", size = 276131, upload-time = "2025-09-01T22:08:10.156Z" }, - { url = "https://files.pythonhosted.org/packages/d3/3a/77d7718a2493e54725494f44da1a1e55704743dc4b8fabe5b0596f7b8014/regex-2025.9.1-cp310-cp310-win_arm64.whl", hash = "sha256:a874a61bb580d48642ffd338570ee24ab13fa023779190513fcacad104a6e251", size = 268462, upload-time = "2025-09-01T22:08:11.651Z" }, - { url = "https://files.pythonhosted.org/packages/06/4d/f741543c0c59f96c6625bc6c11fea1da2e378b7d293ffff6f318edc0ce14/regex-2025.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e5bcf112b09bfd3646e4db6bf2e598534a17d502b0c01ea6550ba4eca780c5e6", size = 484811, upload-time = "2025-09-01T22:08:12.834Z" }, - { url = "https://files.pythonhosted.org/packages/c2/bd/27e73e92635b6fbd51afc26a414a3133243c662949cd1cda677fe7bb09bd/regex-2025.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:67a0295a3c31d675a9ee0238d20238ff10a9a2fdb7a1323c798fc7029578b15c", size = 288977, upload-time = "2025-09-01T22:08:14.499Z" }, - { url = "https://files.pythonhosted.org/packages/eb/7d/7dc0c6efc8bc93cd6e9b947581f5fde8a5dbaa0af7c4ec818c5729fdc807/regex-2025.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea8267fbadc7d4bd7c1301a50e85c2ff0de293ff9452a1a9f8d82c6cafe38179", size = 286606, upload-time = "2025-09-01T22:08:15.881Z" }, - { url = "https://files.pythonhosted.org/packages/d1/01/9b5c6dd394f97c8f2c12f6e8f96879c9ac27292a718903faf2e27a0c09f6/regex-2025.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6aeff21de7214d15e928fb5ce757f9495214367ba62875100d4c18d293750cc1", size = 792436, upload-time = "2025-09-01T22:08:17.38Z" }, - { url = "https://files.pythonhosted.org/packages/fc/24/b7430cfc6ee34bbb3db6ff933beb5e7692e5cc81e8f6f4da63d353566fb0/regex-2025.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d89f1bbbbbc0885e1c230f7770d5e98f4f00b0ee85688c871d10df8b184a6323", size = 858705, upload-time = "2025-09-01T22:08:19.037Z" }, - { url = "https://files.pythonhosted.org/packages/d6/98/155f914b4ea6ae012663188545c4f5216c11926d09b817127639d618b003/regex-2025.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca3affe8ddea498ba9d294ab05f5f2d3b5ad5d515bc0d4a9016dd592a03afe52", size = 905881, upload-time = "2025-09-01T22:08:20.377Z" }, - { url = "https://files.pythonhosted.org/packages/8a/a7/a470e7bc8259c40429afb6d6a517b40c03f2f3e455c44a01abc483a1c512/regex-2025.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91892a7a9f0a980e4c2c85dd19bc14de2b219a3a8867c4b5664b9f972dcc0c78", size = 798968, upload-time = "2025-09-01T22:08:22.081Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fa/33f6fec4d41449fea5f62fdf5e46d668a1c046730a7f4ed9f478331a8e3a/regex-2025.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e1cb40406f4ae862710615f9f636c1e030fd6e6abe0e0f65f6a695a2721440c6", size = 781884, upload-time = "2025-09-01T22:08:23.832Z" }, - { url = "https://files.pythonhosted.org/packages/42/de/2b45f36ab20da14eedddf5009d370625bc5942d9953fa7e5037a32d66843/regex-2025.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:94f6cff6f7e2149c7e6499a6ecd4695379eeda8ccbccb9726e8149f2fe382e92", size = 852935, upload-time = "2025-09-01T22:08:25.536Z" }, - { url = "https://files.pythonhosted.org/packages/1e/f9/878f4fc92c87e125e27aed0f8ee0d1eced9b541f404b048f66f79914475a/regex-2025.9.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6c0226fb322b82709e78c49cc33484206647f8a39954d7e9de1567f5399becd0", size = 844340, upload-time = "2025-09-01T22:08:27.141Z" }, - { url = "https://files.pythonhosted.org/packages/90/c2/5b6f2bce6ece5f8427c718c085eca0de4bbb4db59f54db77aa6557aef3e9/regex-2025.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a12f59c7c380b4fcf7516e9cbb126f95b7a9518902bcf4a852423ff1dcd03e6a", size = 787238, upload-time = "2025-09-01T22:08:28.75Z" }, - { url = "https://files.pythonhosted.org/packages/47/66/1ef1081c831c5b611f6f55f6302166cfa1bc9574017410ba5595353f846a/regex-2025.9.1-cp311-cp311-win32.whl", hash = "sha256:49865e78d147a7a4f143064488da5d549be6bfc3f2579e5044cac61f5c92edd4", size = 264118, upload-time = "2025-09-01T22:08:30.388Z" }, - { url = "https://files.pythonhosted.org/packages/ad/e0/8adc550d7169df1d6b9be8ff6019cda5291054a0107760c2f30788b6195f/regex-2025.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:d34b901f6f2f02ef60f4ad3855d3a02378c65b094efc4b80388a3aeb700a5de7", size = 276151, upload-time = "2025-09-01T22:08:32.073Z" }, - { url = "https://files.pythonhosted.org/packages/cb/bd/46fef29341396d955066e55384fb93b0be7d64693842bf4a9a398db6e555/regex-2025.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:47d7c2dab7e0b95b95fd580087b6ae196039d62306a592fa4e162e49004b6299", size = 268460, upload-time = "2025-09-01T22:08:33.281Z" }, - { url = "https://files.pythonhosted.org/packages/39/ef/a0372febc5a1d44c1be75f35d7e5aff40c659ecde864d7fa10e138f75e74/regex-2025.9.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:84a25164bd8dcfa9f11c53f561ae9766e506e580b70279d05a7946510bdd6f6a", size = 486317, upload-time = "2025-09-01T22:08:34.529Z" }, - { url = "https://files.pythonhosted.org/packages/b5/25/d64543fb7eb41a1024786d518cc57faf1ce64aa6e9ddba097675a0c2f1d2/regex-2025.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:645e88a73861c64c1af558dd12294fb4e67b5c1eae0096a60d7d8a2143a611c7", size = 289698, upload-time = "2025-09-01T22:08:36.162Z" }, - { url = "https://files.pythonhosted.org/packages/d8/dc/fbf31fc60be317bd9f6f87daa40a8a9669b3b392aa8fe4313df0a39d0722/regex-2025.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10a450cba5cd5409526ee1d4449f42aad38dd83ac6948cbd6d7f71ca7018f7db", size = 287242, upload-time = "2025-09-01T22:08:37.794Z" }, - { url = "https://files.pythonhosted.org/packages/0f/74/f933a607a538f785da5021acf5323961b4620972e2c2f1f39b6af4b71db7/regex-2025.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9dc5991592933a4192c166eeb67b29d9234f9c86344481173d1bc52f73a7104", size = 797441, upload-time = "2025-09-01T22:08:39.108Z" }, - { url = "https://files.pythonhosted.org/packages/89/d0/71fc49b4f20e31e97f199348b8c4d6e613e7b6a54a90eb1b090c2b8496d7/regex-2025.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a32291add816961aab472f4fad344c92871a2ee33c6c219b6598e98c1f0108f2", size = 862654, upload-time = "2025-09-01T22:08:40.586Z" }, - { url = "https://files.pythonhosted.org/packages/59/05/984edce1411a5685ba9abbe10d42cdd9450aab4a022271f9585539788150/regex-2025.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:588c161a68a383478e27442a678e3b197b13c5ba51dbba40c1ccb8c4c7bee9e9", size = 910862, upload-time = "2025-09-01T22:08:42.416Z" }, - { url = "https://files.pythonhosted.org/packages/b2/02/5c891bb5fe0691cc1bad336e3a94b9097fbcf9707ec8ddc1dce9f0397289/regex-2025.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47829ffaf652f30d579534da9085fe30c171fa2a6744a93d52ef7195dc38218b", size = 801991, upload-time = "2025-09-01T22:08:44.072Z" }, - { url = "https://files.pythonhosted.org/packages/f1/ae/fd10d6ad179910f7a1b3e0a7fde1ef8bb65e738e8ac4fd6ecff3f52252e4/regex-2025.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e978e5a35b293ea43f140c92a3269b6ab13fe0a2bf8a881f7ac740f5a6ade85", size = 786651, upload-time = "2025-09-01T22:08:46.079Z" }, - { url = "https://files.pythonhosted.org/packages/30/cf/9d686b07bbc5bf94c879cc168db92542d6bc9fb67088d03479fef09ba9d3/regex-2025.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cf09903e72411f4bf3ac1eddd624ecfd423f14b2e4bf1c8b547b72f248b7bf7", size = 856556, upload-time = "2025-09-01T22:08:48.376Z" }, - { url = "https://files.pythonhosted.org/packages/91/9d/302f8a29bb8a49528abbab2d357a793e2a59b645c54deae0050f8474785b/regex-2025.9.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d016b0f77be63e49613c9e26aaf4a242f196cd3d7a4f15898f5f0ab55c9b24d2", size = 849001, upload-time = "2025-09-01T22:08:50.067Z" }, - { url = "https://files.pythonhosted.org/packages/93/fa/b4c6dbdedc85ef4caec54c817cd5f4418dbfa2453214119f2538082bf666/regex-2025.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:656563e620de6908cd1c9d4f7b9e0777e3341ca7db9d4383bcaa44709c90281e", size = 788138, upload-time = "2025-09-01T22:08:51.933Z" }, - { url = "https://files.pythonhosted.org/packages/4a/1b/91ee17a3cbf87f81e8c110399279d0e57f33405468f6e70809100f2ff7d8/regex-2025.9.1-cp312-cp312-win32.whl", hash = "sha256:df33f4ef07b68f7ab637b1dbd70accbf42ef0021c201660656601e8a9835de45", size = 264524, upload-time = "2025-09-01T22:08:53.75Z" }, - { url = "https://files.pythonhosted.org/packages/92/28/6ba31cce05b0f1ec6b787921903f83bd0acf8efde55219435572af83c350/regex-2025.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:5aba22dfbc60cda7c0853516104724dc904caa2db55f2c3e6e984eb858d3edf3", size = 275489, upload-time = "2025-09-01T22:08:55.037Z" }, - { url = "https://files.pythonhosted.org/packages/bd/ed/ea49f324db00196e9ef7fe00dd13c6164d5173dd0f1bbe495e61bb1fb09d/regex-2025.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:ec1efb4c25e1849c2685fa95da44bfde1b28c62d356f9c8d861d4dad89ed56e9", size = 268589, upload-time = "2025-09-01T22:08:56.369Z" }, - { url = "https://files.pythonhosted.org/packages/98/25/b2959ce90c6138c5142fe5264ee1f9b71a0c502ca4c7959302a749407c79/regex-2025.9.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bc6834727d1b98d710a63e6c823edf6ffbf5792eba35d3fa119531349d4142ef", size = 485932, upload-time = "2025-09-01T22:08:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/49/2e/6507a2a85f3f2be6643438b7bd976e67ad73223692d6988eb1ff444106d3/regex-2025.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c3dc05b6d579875719bccc5f3037b4dc80433d64e94681a0061845bd8863c025", size = 289568, upload-time = "2025-09-01T22:08:59.258Z" }, - { url = "https://files.pythonhosted.org/packages/c7/d8/de4a4b57215d99868f1640e062a7907e185ec7476b4b689e2345487c1ff4/regex-2025.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22213527df4c985ec4a729b055a8306272d41d2f45908d7bacb79be0fa7a75ad", size = 286984, upload-time = "2025-09-01T22:09:00.835Z" }, - { url = "https://files.pythonhosted.org/packages/03/15/e8cb403403a57ed316e80661db0e54d7aa2efcd85cb6156f33cc18746922/regex-2025.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8e3f6e3c5a5a1adc3f7ea1b5aec89abfc2f4fbfba55dafb4343cd1d084f715b2", size = 797514, upload-time = "2025-09-01T22:09:02.538Z" }, - { url = "https://files.pythonhosted.org/packages/e4/26/2446f2b9585fed61faaa7e2bbce3aca7dd8df6554c32addee4c4caecf24a/regex-2025.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcb89c02a0d6c2bec9b0bb2d8c78782699afe8434493bfa6b4021cc51503f249", size = 862586, upload-time = "2025-09-01T22:09:04.322Z" }, - { url = "https://files.pythonhosted.org/packages/fd/b8/82ffbe9c0992c31bbe6ae1c4b4e21269a5df2559102b90543c9b56724c3c/regex-2025.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b0e2f95413eb0c651cd1516a670036315b91b71767af83bc8525350d4375ccba", size = 910815, upload-time = "2025-09-01T22:09:05.978Z" }, - { url = "https://files.pythonhosted.org/packages/2f/d8/7303ea38911759c1ee30cc5bc623ee85d3196b733c51fd6703c34290a8d9/regex-2025.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a41dc039e1c97d3c2ed3e26523f748e58c4de3ea7a31f95e1cf9ff973fff5a", size = 802042, upload-time = "2025-09-01T22:09:07.865Z" }, - { url = "https://files.pythonhosted.org/packages/fc/0e/6ad51a55ed4b5af512bb3299a05d33309bda1c1d1e1808fa869a0bed31bc/regex-2025.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f0b4258b161094f66857a26ee938d3fe7b8a5063861e44571215c44fbf0e5df", size = 786764, upload-time = "2025-09-01T22:09:09.362Z" }, - { url = "https://files.pythonhosted.org/packages/8d/d5/394e3ffae6baa5a9217bbd14d96e0e5da47bb069d0dbb8278e2681a2b938/regex-2025.9.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bf70e18ac390e6977ea7e56f921768002cb0fa359c4199606c7219854ae332e0", size = 856557, upload-time = "2025-09-01T22:09:11.129Z" }, - { url = "https://files.pythonhosted.org/packages/cd/80/b288d3910c41194ad081b9fb4b371b76b0bbfdce93e7709fc98df27b37dc/regex-2025.9.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b84036511e1d2bb0a4ff1aec26951caa2dea8772b223c9e8a19ed8885b32dbac", size = 849108, upload-time = "2025-09-01T22:09:12.877Z" }, - { url = "https://files.pythonhosted.org/packages/d1/cd/5ec76bf626d0d5abdc277b7a1734696f5f3d14fbb4a3e2540665bc305d85/regex-2025.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c2e05dcdfe224047f2a59e70408274c325d019aad96227ab959403ba7d58d2d7", size = 788201, upload-time = "2025-09-01T22:09:14.561Z" }, - { url = "https://files.pythonhosted.org/packages/b5/36/674672f3fdead107565a2499f3007788b878188acec6d42bc141c5366c2c/regex-2025.9.1-cp313-cp313-win32.whl", hash = "sha256:3b9a62107a7441b81ca98261808fed30ae36ba06c8b7ee435308806bd53c1ed8", size = 264508, upload-time = "2025-09-01T22:09:16.193Z" }, - { url = "https://files.pythonhosted.org/packages/83/ad/931134539515eb64ce36c24457a98b83c1b2e2d45adf3254b94df3735a76/regex-2025.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:b38afecc10c177eb34cfae68d669d5161880849ba70c05cbfbe409f08cc939d7", size = 275469, upload-time = "2025-09-01T22:09:17.462Z" }, - { url = "https://files.pythonhosted.org/packages/24/8c/96d34e61c0e4e9248836bf86d69cb224fd222f270fa9045b24e218b65604/regex-2025.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:ec329890ad5e7ed9fc292858554d28d58d56bf62cf964faf0aa57964b21155a0", size = 268586, upload-time = "2025-09-01T22:09:18.948Z" }, - { url = "https://files.pythonhosted.org/packages/21/b1/453cbea5323b049181ec6344a803777914074b9726c9c5dc76749966d12d/regex-2025.9.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:72fb7a016467d364546f22b5ae86c45680a4e0de6b2a6f67441d22172ff641f1", size = 486111, upload-time = "2025-09-01T22:09:20.734Z" }, - { url = "https://files.pythonhosted.org/packages/f6/0e/92577f197bd2f7652c5e2857f399936c1876978474ecc5b068c6d8a79c86/regex-2025.9.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c9527fa74eba53f98ad86be2ba003b3ebe97e94b6eb2b916b31b5f055622ef03", size = 289520, upload-time = "2025-09-01T22:09:22.249Z" }, - { url = "https://files.pythonhosted.org/packages/af/c6/b472398116cca7ea5a6c4d5ccd0fc543f7fd2492cb0c48d2852a11972f73/regex-2025.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c905d925d194c83a63f92422af7544ec188301451b292c8b487f0543726107ca", size = 287215, upload-time = "2025-09-01T22:09:23.657Z" }, - { url = "https://files.pythonhosted.org/packages/cf/11/f12ecb0cf9ca792a32bb92f758589a84149017467a544f2f6bfb45c0356d/regex-2025.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74df7c74a63adcad314426b1f4ea6054a5ab25d05b0244f0c07ff9ce640fa597", size = 797855, upload-time = "2025-09-01T22:09:25.197Z" }, - { url = "https://files.pythonhosted.org/packages/46/88/bbb848f719a540fb5997e71310f16f0b33a92c5d4b4d72d4311487fff2a3/regex-2025.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4f6e935e98ea48c7a2e8be44494de337b57a204470e7f9c9c42f912c414cd6f5", size = 863363, upload-time = "2025-09-01T22:09:26.705Z" }, - { url = "https://files.pythonhosted.org/packages/54/a9/2321eb3e2838f575a78d48e03c1e83ea61bd08b74b7ebbdeca8abc50fc25/regex-2025.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4a62d033cd9ebefc7c5e466731a508dfabee827d80b13f455de68a50d3c2543d", size = 910202, upload-time = "2025-09-01T22:09:28.906Z" }, - { url = "https://files.pythonhosted.org/packages/33/07/d1d70835d7d11b7e126181f316f7213c4572ecf5c5c97bdbb969fb1f38a2/regex-2025.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef971ebf2b93bdc88d8337238be4dfb851cc97ed6808eb04870ef67589415171", size = 801808, upload-time = "2025-09-01T22:09:30.733Z" }, - { url = "https://files.pythonhosted.org/packages/13/d1/29e4d1bed514ef2bf3a4ead3cb8bb88ca8af94130239a4e68aa765c35b1c/regex-2025.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d936a1db208bdca0eca1f2bb2c1ba1d8370b226785c1e6db76e32a228ffd0ad5", size = 786824, upload-time = "2025-09-01T22:09:32.61Z" }, - { url = "https://files.pythonhosted.org/packages/33/27/20d8ccb1bee460faaa851e6e7cc4cfe852a42b70caa1dca22721ba19f02f/regex-2025.9.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:7e786d9e4469698fc63815b8de08a89165a0aa851720eb99f5e0ea9d51dd2b6a", size = 857406, upload-time = "2025-09-01T22:09:34.117Z" }, - { url = "https://files.pythonhosted.org/packages/74/fe/60c6132262dc36430d51e0c46c49927d113d3a38c1aba6a26c7744c84cf3/regex-2025.9.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6b81d7dbc5466ad2c57ce3a0ddb717858fe1a29535c8866f8514d785fdb9fc5b", size = 848593, upload-time = "2025-09-01T22:09:35.598Z" }, - { url = "https://files.pythonhosted.org/packages/cc/ae/2d4ff915622fabbef1af28387bf71e7f2f4944a348b8460d061e85e29bf0/regex-2025.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cd4890e184a6feb0ef195338a6ce68906a8903a0f2eb7e0ab727dbc0a3156273", size = 787951, upload-time = "2025-09-01T22:09:37.139Z" }, - { url = "https://files.pythonhosted.org/packages/85/37/dc127703a9e715a284cc2f7dbdd8a9776fd813c85c126eddbcbdd1ca5fec/regex-2025.9.1-cp314-cp314-win32.whl", hash = "sha256:34679a86230e46164c9e0396b56cab13c0505972343880b9e705083cc5b8ec86", size = 269833, upload-time = "2025-09-01T22:09:39.245Z" }, - { url = "https://files.pythonhosted.org/packages/83/bf/4bed4d3d0570e16771defd5f8f15f7ea2311edcbe91077436d6908956c4a/regex-2025.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:a1196e530a6bfa5f4bde029ac5b0295a6ecfaaffbfffede4bbaf4061d9455b70", size = 278742, upload-time = "2025-09-01T22:09:40.651Z" }, - { url = "https://files.pythonhosted.org/packages/cf/3e/7d7ac6fd085023312421e0d69dfabdfb28e116e513fadbe9afe710c01893/regex-2025.9.1-cp314-cp314-win_arm64.whl", hash = "sha256:f46d525934871ea772930e997d577d48c6983e50f206ff7b66d4ac5f8941e993", size = 271860, upload-time = "2025-09-01T22:09:42.413Z" }, + { url = "https://files.pythonhosted.org/packages/7e/d8/7e06171db8e55f917c5b8e89319cea2d86982e3fc46b677f40358223dece/regex-2025.9.18-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:12296202480c201c98a84aecc4d210592b2f55e200a1d193235c4db92b9f6788", size = 484829, upload-time = "2025-09-19T00:35:05.215Z" }, + { url = "https://files.pythonhosted.org/packages/8d/70/bf91bb39e5bedf75ce730ffbaa82ca585584d13335306d637458946b8b9f/regex-2025.9.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:220381f1464a581f2ea988f2220cf2a67927adcef107d47d6897ba5a2f6d51a4", size = 288993, upload-time = "2025-09-19T00:35:08.154Z" }, + { url = "https://files.pythonhosted.org/packages/fe/89/69f79b28365eda2c46e64c39d617d5f65a2aa451a4c94de7d9b34c2dc80f/regex-2025.9.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87f681bfca84ebd265278b5daa1dcb57f4db315da3b5d044add7c30c10442e61", size = 286624, upload-time = "2025-09-19T00:35:09.717Z" }, + { url = "https://files.pythonhosted.org/packages/44/31/81e62955726c3a14fcc1049a80bc716765af6c055706869de5e880ddc783/regex-2025.9.18-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34d674cbba70c9398074c8a1fcc1a79739d65d1105de2a3c695e2b05ea728251", size = 780473, upload-time = "2025-09-19T00:35:11.013Z" }, + { url = "https://files.pythonhosted.org/packages/fb/23/07072b7e191fbb6e213dc03b2f5b96f06d3c12d7deaded84679482926fc7/regex-2025.9.18-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:385c9b769655cb65ea40b6eea6ff763cbb6d69b3ffef0b0db8208e1833d4e746", size = 849290, upload-time = "2025-09-19T00:35:12.348Z" }, + { url = "https://files.pythonhosted.org/packages/b3/f0/aec7f6a01f2a112210424d77c6401b9015675fb887ced7e18926df4ae51e/regex-2025.9.18-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8900b3208e022570ae34328712bef6696de0804c122933414014bae791437ab2", size = 897335, upload-time = "2025-09-19T00:35:14.058Z" }, + { url = "https://files.pythonhosted.org/packages/cc/90/2e5f9da89d260de7d0417ead91a1bc897f19f0af05f4f9323313b76c47f2/regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c204e93bf32cd7a77151d44b05eb36f469d0898e3fba141c026a26b79d9914a0", size = 789946, upload-time = "2025-09-19T00:35:15.403Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d5/1c712c7362f2563d389be66bae131c8bab121a3fabfa04b0b5bfc9e73c51/regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3acc471d1dd7e5ff82e6cacb3b286750decd949ecd4ae258696d04f019817ef8", size = 780787, upload-time = "2025-09-19T00:35:17.061Z" }, + { url = "https://files.pythonhosted.org/packages/4f/92/c54cdb4aa41009632e69817a5aa452673507f07e341076735a2f6c46a37c/regex-2025.9.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6479d5555122433728760e5f29edb4c2b79655a8deb681a141beb5c8a025baea", size = 773632, upload-time = "2025-09-19T00:35:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/db/99/75c996dc6a2231a8652d7ad0bfbeaf8a8c77612d335580f520f3ec40e30b/regex-2025.9.18-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:431bd2a8726b000eb6f12429c9b438a24062a535d06783a93d2bcbad3698f8a8", size = 844104, upload-time = "2025-09-19T00:35:20.259Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f7/25aba34cc130cb6844047dbfe9716c9b8f9629fee8b8bec331aa9241b97b/regex-2025.9.18-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0cc3521060162d02bd36927e20690129200e5ac9d2c6d32b70368870b122db25", size = 834794, upload-time = "2025-09-19T00:35:22.002Z" }, + { url = "https://files.pythonhosted.org/packages/51/eb/64e671beafa0ae29712268421597596d781704973551312b2425831d4037/regex-2025.9.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a021217b01be2d51632ce056d7a837d3fa37c543ede36e39d14063176a26ae29", size = 778535, upload-time = "2025-09-19T00:35:23.298Z" }, + { url = "https://files.pythonhosted.org/packages/26/33/c0ebc0b07bd0bf88f716cca240546b26235a07710ea58e271cfe390ae273/regex-2025.9.18-cp310-cp310-win32.whl", hash = "sha256:4a12a06c268a629cb67cc1d009b7bb0be43e289d00d5111f86a2efd3b1949444", size = 264115, upload-time = "2025-09-19T00:35:25.206Z" }, + { url = "https://files.pythonhosted.org/packages/59/39/aeb11a4ae68faaec2498512cadae09f2d8a91f1f65730fe62b9bffeea150/regex-2025.9.18-cp310-cp310-win_amd64.whl", hash = "sha256:47acd811589301298c49db2c56bde4f9308d6396da92daf99cba781fa74aa450", size = 276143, upload-time = "2025-09-19T00:35:26.785Z" }, + { url = "https://files.pythonhosted.org/packages/29/04/37f2d3fc334a1031fc2767c9d89cec13c2e72207c7e7f6feae8a47f4e149/regex-2025.9.18-cp310-cp310-win_arm64.whl", hash = "sha256:16bd2944e77522275e5ee36f867e19995bcaa533dcb516753a26726ac7285442", size = 268473, upload-time = "2025-09-19T00:35:28.39Z" }, + { url = "https://files.pythonhosted.org/packages/58/61/80eda662fc4eb32bfedc331f42390974c9e89c7eac1b79cd9eea4d7c458c/regex-2025.9.18-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:51076980cd08cd13c88eb7365427ae27f0d94e7cebe9ceb2bb9ffdae8fc4d82a", size = 484832, upload-time = "2025-09-19T00:35:30.011Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d9/33833d9abddf3f07ad48504ddb53fe3b22f353214bbb878a72eee1e3ddbf/regex-2025.9.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:828446870bd7dee4e0cbeed767f07961aa07f0ea3129f38b3ccecebc9742e0b8", size = 288994, upload-time = "2025-09-19T00:35:31.733Z" }, + { url = "https://files.pythonhosted.org/packages/2a/b3/526ee96b0d70ea81980cbc20c3496fa582f775a52e001e2743cc33b2fa75/regex-2025.9.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28821d5637866479ec4cc23b8c990f5bc6dd24e5e4384ba4a11d38a526e1414", size = 286619, upload-time = "2025-09-19T00:35:33.221Z" }, + { url = "https://files.pythonhosted.org/packages/65/4f/c2c096b02a351b33442aed5895cdd8bf87d372498d2100927c5a053d7ba3/regex-2025.9.18-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:726177ade8e481db669e76bf99de0b278783be8acd11cef71165327abd1f170a", size = 792454, upload-time = "2025-09-19T00:35:35.361Z" }, + { url = "https://files.pythonhosted.org/packages/24/15/b562c9d6e47c403c4b5deb744f8b4bf6e40684cf866c7b077960a925bdff/regex-2025.9.18-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5cca697da89b9f8ea44115ce3130f6c54c22f541943ac8e9900461edc2b8bd4", size = 858723, upload-time = "2025-09-19T00:35:36.949Z" }, + { url = "https://files.pythonhosted.org/packages/f2/01/dba305409849e85b8a1a681eac4c03ed327d8de37895ddf9dc137f59c140/regex-2025.9.18-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dfbde38f38004703c35666a1e1c088b778e35d55348da2b7b278914491698d6a", size = 905899, upload-time = "2025-09-19T00:35:38.723Z" }, + { url = "https://files.pythonhosted.org/packages/fe/d0/c51d1e6a80eab11ef96a4cbad17fc0310cf68994fb01a7283276b7e5bbd6/regex-2025.9.18-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f2f422214a03fab16bfa495cfec72bee4aaa5731843b771860a471282f1bf74f", size = 798981, upload-time = "2025-09-19T00:35:40.416Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5e/72db90970887bbe02296612bd61b0fa31e6d88aa24f6a4853db3e96c575e/regex-2025.9.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a295916890f4df0902e4286bc7223ee7f9e925daa6dcdec4192364255b70561a", size = 781900, upload-time = "2025-09-19T00:35:42.077Z" }, + { url = "https://files.pythonhosted.org/packages/50/ff/596be45eea8e9bc31677fde243fa2904d00aad1b32c31bce26c3dbba0b9e/regex-2025.9.18-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5db95ff632dbabc8c38c4e82bf545ab78d902e81160e6e455598014f0abe66b9", size = 852952, upload-time = "2025-09-19T00:35:43.751Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1b/2dfa348fa551e900ed3f5f63f74185b6a08e8a76bc62bc9c106f4f92668b/regex-2025.9.18-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb967eb441b0f15ae610b7069bdb760b929f267efbf522e814bbbfffdf125ce2", size = 844355, upload-time = "2025-09-19T00:35:45.309Z" }, + { url = "https://files.pythonhosted.org/packages/f4/bf/aefb1def27fe33b8cbbb19c75c13aefccfbef1c6686f8e7f7095705969c7/regex-2025.9.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f04d2f20da4053d96c08f7fde6e1419b7ec9dbcee89c96e3d731fca77f411b95", size = 787254, upload-time = "2025-09-19T00:35:46.904Z" }, + { url = "https://files.pythonhosted.org/packages/e3/4e/8ef042e7cf0dbbb401e784e896acfc1b367b95dfbfc9ada94c2ed55a081f/regex-2025.9.18-cp311-cp311-win32.whl", hash = "sha256:895197241fccf18c0cea7550c80e75f185b8bd55b6924fcae269a1a92c614a07", size = 264129, upload-time = "2025-09-19T00:35:48.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7d/c4fcabf80dcdd6821c0578ad9b451f8640b9110fb3dcb74793dd077069ff/regex-2025.9.18-cp311-cp311-win_amd64.whl", hash = "sha256:7e2b414deae99166e22c005e154a5513ac31493db178d8aec92b3269c9cce8c9", size = 276160, upload-time = "2025-09-19T00:36:00.45Z" }, + { url = "https://files.pythonhosted.org/packages/64/f8/0e13c8ae4d6df9d128afaba138342d532283d53a4c1e7a8c93d6756c8f4a/regex-2025.9.18-cp311-cp311-win_arm64.whl", hash = "sha256:fb137ec7c5c54f34a25ff9b31f6b7b0c2757be80176435bf367111e3f71d72df", size = 268471, upload-time = "2025-09-19T00:36:02.149Z" }, + { url = "https://files.pythonhosted.org/packages/b0/99/05859d87a66ae7098222d65748f11ef7f2dff51bfd7482a4e2256c90d72b/regex-2025.9.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:436e1b31d7efd4dcd52091d076482031c611dde58bf9c46ca6d0a26e33053a7e", size = 486335, upload-time = "2025-09-19T00:36:03.661Z" }, + { url = "https://files.pythonhosted.org/packages/97/7e/d43d4e8b978890932cf7b0957fce58c5b08c66f32698f695b0c2c24a48bf/regex-2025.9.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c190af81e5576b9c5fdc708f781a52ff20f8b96386c6e2e0557a78402b029f4a", size = 289720, upload-time = "2025-09-19T00:36:05.471Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3b/ff80886089eb5dcf7e0d2040d9aaed539e25a94300403814bb24cc775058/regex-2025.9.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e4121f1ce2b2b5eec4b397cc1b277686e577e658d8f5870b7eb2d726bd2300ab", size = 287257, upload-time = "2025-09-19T00:36:07.072Z" }, + { url = "https://files.pythonhosted.org/packages/ee/66/243edf49dd8720cba8d5245dd4d6adcb03a1defab7238598c0c97cf549b8/regex-2025.9.18-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:300e25dbbf8299d87205e821a201057f2ef9aa3deb29caa01cd2cac669e508d5", size = 797463, upload-time = "2025-09-19T00:36:08.399Z" }, + { url = "https://files.pythonhosted.org/packages/df/71/c9d25a1142c70432e68bb03211d4a82299cd1c1fbc41db9409a394374ef5/regex-2025.9.18-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b47fcf9f5316c0bdaf449e879407e1b9937a23c3b369135ca94ebc8d74b1742", size = 862670, upload-time = "2025-09-19T00:36:10.101Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8f/329b1efc3a64375a294e3a92d43372bf1a351aa418e83c21f2f01cf6ec41/regex-2025.9.18-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:57a161bd3acaa4b513220b49949b07e252165e6b6dc910ee7617a37ff4f5b425", size = 910881, upload-time = "2025-09-19T00:36:12.223Z" }, + { url = "https://files.pythonhosted.org/packages/35/9e/a91b50332a9750519320ed30ec378b74c996f6befe282cfa6bb6cea7e9fd/regex-2025.9.18-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f130c3a7845ba42de42f380fff3c8aebe89a810747d91bcf56d40a069f15352", size = 802011, upload-time = "2025-09-19T00:36:13.901Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1d/6be3b8d7856b6e0d7ee7f942f437d0a76e0d5622983abbb6d21e21ab9a17/regex-2025.9.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f96fa342b6f54dcba928dd452e8d8cb9f0d63e711d1721cd765bb9f73bb048d", size = 786668, upload-time = "2025-09-19T00:36:15.391Z" }, + { url = "https://files.pythonhosted.org/packages/cb/ce/4a60e53df58bd157c5156a1736d3636f9910bdcc271d067b32b7fcd0c3a8/regex-2025.9.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f0d676522d68c207828dcd01fb6f214f63f238c283d9f01d85fc664c7c85b56", size = 856578, upload-time = "2025-09-19T00:36:16.845Z" }, + { url = "https://files.pythonhosted.org/packages/86/e8/162c91bfe7217253afccde112868afb239f94703de6580fb235058d506a6/regex-2025.9.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:40532bff8a1a0621e7903ae57fce88feb2e8a9a9116d341701302c9302aef06e", size = 849017, upload-time = "2025-09-19T00:36:18.597Z" }, + { url = "https://files.pythonhosted.org/packages/35/34/42b165bc45289646ea0959a1bc7531733e90b47c56a72067adfe6b3251f6/regex-2025.9.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:039f11b618ce8d71a1c364fdee37da1012f5a3e79b1b2819a9f389cd82fd6282", size = 788150, upload-time = "2025-09-19T00:36:20.464Z" }, + { url = "https://files.pythonhosted.org/packages/79/5d/cdd13b1f3c53afa7191593a7ad2ee24092a5a46417725ffff7f64be8342d/regex-2025.9.18-cp312-cp312-win32.whl", hash = "sha256:e1dd06f981eb226edf87c55d523131ade7285137fbde837c34dc9d1bf309f459", size = 264536, upload-time = "2025-09-19T00:36:21.922Z" }, + { url = "https://files.pythonhosted.org/packages/e0/f5/4a7770c9a522e7d2dc1fa3ffc83ab2ab33b0b22b447e62cffef186805302/regex-2025.9.18-cp312-cp312-win_amd64.whl", hash = "sha256:3d86b5247bf25fa3715e385aa9ff272c307e0636ce0c9595f64568b41f0a9c77", size = 275501, upload-time = "2025-09-19T00:36:23.4Z" }, + { url = "https://files.pythonhosted.org/packages/df/05/9ce3e110e70d225ecbed455b966003a3afda5e58e8aec2964042363a18f4/regex-2025.9.18-cp312-cp312-win_arm64.whl", hash = "sha256:032720248cbeeae6444c269b78cb15664458b7bb9ed02401d3da59fe4d68c3a5", size = 268601, upload-time = "2025-09-19T00:36:25.092Z" }, + { url = "https://files.pythonhosted.org/packages/d2/c7/5c48206a60ce33711cf7dcaeaed10dd737733a3569dc7e1dce324dd48f30/regex-2025.9.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a40f929cd907c7e8ac7566ac76225a77701a6221bca937bdb70d56cb61f57b2", size = 485955, upload-time = "2025-09-19T00:36:26.822Z" }, + { url = "https://files.pythonhosted.org/packages/e9/be/74fc6bb19a3c491ec1ace943e622b5a8539068771e8705e469b2da2306a7/regex-2025.9.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c90471671c2cdf914e58b6af62420ea9ecd06d1554d7474d50133ff26ae88feb", size = 289583, upload-time = "2025-09-19T00:36:28.577Z" }, + { url = "https://files.pythonhosted.org/packages/25/c4/9ceaa433cb5dc515765560f22a19578b95b92ff12526e5a259321c4fc1a0/regex-2025.9.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a351aff9e07a2dabb5022ead6380cff17a4f10e4feb15f9100ee56c4d6d06af", size = 287000, upload-time = "2025-09-19T00:36:30.161Z" }, + { url = "https://files.pythonhosted.org/packages/7d/e6/68bc9393cb4dc68018456568c048ac035854b042bc7c33cb9b99b0680afa/regex-2025.9.18-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc4b8e9d16e20ddfe16430c23468a8707ccad3365b06d4536142e71823f3ca29", size = 797535, upload-time = "2025-09-19T00:36:31.876Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/ebae9032d34b78ecfe9bd4b5e6575b55351dc8513485bb92326613732b8c/regex-2025.9.18-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b8cdbddf2db1c5e80338ba2daa3cfa3dec73a46fff2a7dda087c8efbf12d62f", size = 862603, upload-time = "2025-09-19T00:36:33.344Z" }, + { url = "https://files.pythonhosted.org/packages/3b/74/12332c54b3882557a4bcd2b99f8be581f5c6a43cf1660a85b460dd8ff468/regex-2025.9.18-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a276937d9d75085b2c91fb48244349c6954f05ee97bba0963ce24a9d915b8b68", size = 910829, upload-time = "2025-09-19T00:36:34.826Z" }, + { url = "https://files.pythonhosted.org/packages/86/70/ba42d5ed606ee275f2465bfc0e2208755b06cdabd0f4c7c4b614d51b57ab/regex-2025.9.18-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92a8e375ccdc1256401c90e9dc02b8642894443d549ff5e25e36d7cf8a80c783", size = 802059, upload-time = "2025-09-19T00:36:36.664Z" }, + { url = "https://files.pythonhosted.org/packages/da/c5/fcb017e56396a7f2f8357412638d7e2963440b131a3ca549be25774b3641/regex-2025.9.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0dc6893b1f502d73037cf807a321cdc9be29ef3d6219f7970f842475873712ac", size = 786781, upload-time = "2025-09-19T00:36:38.168Z" }, + { url = "https://files.pythonhosted.org/packages/c6/ee/21c4278b973f630adfb3bcb23d09d83625f3ab1ca6e40ebdffe69901c7a1/regex-2025.9.18-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a61e85bfc63d232ac14b015af1261f826260c8deb19401c0597dbb87a864361e", size = 856578, upload-time = "2025-09-19T00:36:40.129Z" }, + { url = "https://files.pythonhosted.org/packages/87/0b/de51550dc7274324435c8f1539373ac63019b0525ad720132866fff4a16a/regex-2025.9.18-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1ef86a9ebc53f379d921fb9a7e42b92059ad3ee800fcd9e0fe6181090e9f6c23", size = 849119, upload-time = "2025-09-19T00:36:41.651Z" }, + { url = "https://files.pythonhosted.org/packages/60/52/383d3044fc5154d9ffe4321696ee5b2ee4833a28c29b137c22c33f41885b/regex-2025.9.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d3bc882119764ba3a119fbf2bd4f1b47bc56c1da5d42df4ed54ae1e8e66fdf8f", size = 788219, upload-time = "2025-09-19T00:36:43.575Z" }, + { url = "https://files.pythonhosted.org/packages/20/bd/2614fc302671b7359972ea212f0e3a92df4414aaeacab054a8ce80a86073/regex-2025.9.18-cp313-cp313-win32.whl", hash = "sha256:3810a65675845c3bdfa58c3c7d88624356dd6ee2fc186628295e0969005f928d", size = 264517, upload-time = "2025-09-19T00:36:45.503Z" }, + { url = "https://files.pythonhosted.org/packages/07/0f/ab5c1581e6563a7bffdc1974fb2d25f05689b88e2d416525271f232b1946/regex-2025.9.18-cp313-cp313-win_amd64.whl", hash = "sha256:16eaf74b3c4180ede88f620f299e474913ab6924d5c4b89b3833bc2345d83b3d", size = 275481, upload-time = "2025-09-19T00:36:46.965Z" }, + { url = "https://files.pythonhosted.org/packages/49/22/ee47672bc7958f8c5667a587c2600a4fba8b6bab6e86bd6d3e2b5f7cac42/regex-2025.9.18-cp313-cp313-win_arm64.whl", hash = "sha256:4dc98ba7dd66bd1261927a9f49bd5ee2bcb3660f7962f1ec02617280fc00f5eb", size = 268598, upload-time = "2025-09-19T00:36:48.314Z" }, + { url = "https://files.pythonhosted.org/packages/e8/83/6887e16a187c6226cb85d8301e47d3b73ecc4505a3a13d8da2096b44fd76/regex-2025.9.18-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:fe5d50572bc885a0a799410a717c42b1a6b50e2f45872e2b40f4f288f9bce8a2", size = 489765, upload-time = "2025-09-19T00:36:49.996Z" }, + { url = "https://files.pythonhosted.org/packages/51/c5/e2f7325301ea2916ff301c8d963ba66b1b2c1b06694191df80a9c4fea5d0/regex-2025.9.18-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b9d9a2d6cda6621551ca8cf7a06f103adf72831153f3c0d982386110870c4d3", size = 291228, upload-time = "2025-09-19T00:36:51.654Z" }, + { url = "https://files.pythonhosted.org/packages/91/60/7d229d2bc6961289e864a3a3cfebf7d0d250e2e65323a8952cbb7e22d824/regex-2025.9.18-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:13202e4c4ac0ef9a317fff817674b293c8f7e8c68d3190377d8d8b749f566e12", size = 289270, upload-time = "2025-09-19T00:36:53.118Z" }, + { url = "https://files.pythonhosted.org/packages/3c/d7/b4f06868ee2958ff6430df89857fbf3d43014bbf35538b6ec96c2704e15d/regex-2025.9.18-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874ff523b0fecffb090f80ae53dc93538f8db954c8bb5505f05b7787ab3402a0", size = 806326, upload-time = "2025-09-19T00:36:54.631Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e4/bca99034a8f1b9b62ccf337402a8e5b959dd5ba0e5e5b2ead70273df3277/regex-2025.9.18-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d13ab0490128f2bb45d596f754148cd750411afc97e813e4b3a61cf278a23bb6", size = 871556, upload-time = "2025-09-19T00:36:56.208Z" }, + { url = "https://files.pythonhosted.org/packages/6d/df/e06ffaf078a162f6dd6b101a5ea9b44696dca860a48136b3ae4a9caf25e2/regex-2025.9.18-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05440bc172bc4b4b37fb9667e796597419404dbba62e171e1f826d7d2a9ebcef", size = 913817, upload-time = "2025-09-19T00:36:57.807Z" }, + { url = "https://files.pythonhosted.org/packages/9e/05/25b05480b63292fd8e84800b1648e160ca778127b8d2367a0a258fa2e225/regex-2025.9.18-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5514b8e4031fdfaa3d27e92c75719cbe7f379e28cacd939807289bce76d0e35a", size = 811055, upload-time = "2025-09-19T00:36:59.762Z" }, + { url = "https://files.pythonhosted.org/packages/70/97/7bc7574655eb651ba3a916ed4b1be6798ae97af30104f655d8efd0cab24b/regex-2025.9.18-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:65d3c38c39efce73e0d9dc019697b39903ba25b1ad45ebbd730d2cf32741f40d", size = 794534, upload-time = "2025-09-19T00:37:01.405Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c2/d5da49166a52dda879855ecdba0117f073583db2b39bb47ce9a3378a8e9e/regex-2025.9.18-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ae77e447ebc144d5a26d50055c6ddba1d6ad4a865a560ec7200b8b06bc529368", size = 866684, upload-time = "2025-09-19T00:37:03.441Z" }, + { url = "https://files.pythonhosted.org/packages/bd/2d/0a5c4e6ec417de56b89ff4418ecc72f7e3feca806824c75ad0bbdae0516b/regex-2025.9.18-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3ef8cf53dc8df49d7e28a356cf824e3623764e9833348b655cfed4524ab8a90", size = 853282, upload-time = "2025-09-19T00:37:04.985Z" }, + { url = "https://files.pythonhosted.org/packages/f4/8e/d656af63e31a86572ec829665d6fa06eae7e144771e0330650a8bb865635/regex-2025.9.18-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9feb29817df349c976da9a0debf775c5c33fc1c8ad7b9f025825da99374770b7", size = 797830, upload-time = "2025-09-19T00:37:06.697Z" }, + { url = "https://files.pythonhosted.org/packages/db/ce/06edc89df8f7b83ffd321b6071be4c54dc7332c0f77860edc40ce57d757b/regex-2025.9.18-cp313-cp313t-win32.whl", hash = "sha256:168be0d2f9b9d13076940b1ed774f98595b4e3c7fc54584bba81b3cc4181742e", size = 267281, upload-time = "2025-09-19T00:37:08.568Z" }, + { url = "https://files.pythonhosted.org/packages/83/9a/2b5d9c8b307a451fd17068719d971d3634ca29864b89ed5c18e499446d4a/regex-2025.9.18-cp313-cp313t-win_amd64.whl", hash = "sha256:d59ecf3bb549e491c8104fea7313f3563c7b048e01287db0a90485734a70a730", size = 278724, upload-time = "2025-09-19T00:37:10.023Z" }, + { url = "https://files.pythonhosted.org/packages/3d/70/177d31e8089a278a764f8ec9a3faac8d14a312d622a47385d4b43905806f/regex-2025.9.18-cp313-cp313t-win_arm64.whl", hash = "sha256:dbef80defe9fb21310948a2595420b36c6d641d9bea4c991175829b2cc4bc06a", size = 269771, upload-time = "2025-09-19T00:37:13.041Z" }, + { url = "https://files.pythonhosted.org/packages/44/b7/3b4663aa3b4af16819f2ab6a78c4111c7e9b066725d8107753c2257448a5/regex-2025.9.18-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c6db75b51acf277997f3adcd0ad89045d856190d13359f15ab5dda21581d9129", size = 486130, upload-time = "2025-09-19T00:37:14.527Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/4533f5d7ac9c6a02a4725fe8883de2aebc713e67e842c04cf02626afb747/regex-2025.9.18-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8f9698b6f6895d6db810e0bda5364f9ceb9e5b11328700a90cae573574f61eea", size = 289539, upload-time = "2025-09-19T00:37:16.356Z" }, + { url = "https://files.pythonhosted.org/packages/b8/8d/5ab6797c2750985f79e9995fad3254caa4520846580f266ae3b56d1cae58/regex-2025.9.18-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29cd86aa7cb13a37d0f0d7c21d8d949fe402ffa0ea697e635afedd97ab4b69f1", size = 287233, upload-time = "2025-09-19T00:37:18.025Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/95afcb02ba8d3a64e6ffeb801718ce73471ad6440c55d993f65a4a5e7a92/regex-2025.9.18-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c9f285a071ee55cd9583ba24dde006e53e17780bb309baa8e4289cd472bcc47", size = 797876, upload-time = "2025-09-19T00:37:19.609Z" }, + { url = "https://files.pythonhosted.org/packages/c8/fb/720b1f49cec1f3b5a9fea5b34cd22b88b5ebccc8c1b5de9cc6f65eed165a/regex-2025.9.18-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5adf266f730431e3be9021d3e5b8d5ee65e563fec2883ea8093944d21863b379", size = 863385, upload-time = "2025-09-19T00:37:21.65Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ca/e0d07ecf701e1616f015a720dc13b84c582024cbfbb3fc5394ae204adbd7/regex-2025.9.18-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1137cabc0f38807de79e28d3f6e3e3f2cc8cfb26bead754d02e6d1de5f679203", size = 910220, upload-time = "2025-09-19T00:37:23.723Z" }, + { url = "https://files.pythonhosted.org/packages/b6/45/bba86413b910b708eca705a5af62163d5d396d5f647ed9485580c7025209/regex-2025.9.18-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cc9e5525cada99699ca9223cce2d52e88c52a3d2a0e842bd53de5497c604164", size = 801827, upload-time = "2025-09-19T00:37:25.684Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a6/740fbd9fcac31a1305a8eed30b44bf0f7f1e042342be0a4722c0365ecfca/regex-2025.9.18-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bbb9246568f72dce29bcd433517c2be22c7791784b223a810225af3b50d1aafb", size = 786843, upload-time = "2025-09-19T00:37:27.62Z" }, + { url = "https://files.pythonhosted.org/packages/80/a7/0579e8560682645906da640c9055506465d809cb0f5415d9976f417209a6/regex-2025.9.18-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6a52219a93dd3d92c675383efff6ae18c982e2d7651c792b1e6d121055808743", size = 857430, upload-time = "2025-09-19T00:37:29.362Z" }, + { url = "https://files.pythonhosted.org/packages/8d/9b/4dc96b6c17b38900cc9fee254fc9271d0dde044e82c78c0811b58754fde5/regex-2025.9.18-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:ae9b3840c5bd456780e3ddf2f737ab55a79b790f6409182012718a35c6d43282", size = 848612, upload-time = "2025-09-19T00:37:31.42Z" }, + { url = "https://files.pythonhosted.org/packages/b3/6a/6f659f99bebb1775e5ac81a3fb837b85897c1a4ef5acffd0ff8ffe7e67fb/regex-2025.9.18-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d488c236ac497c46a5ac2005a952c1a0e22a07be9f10c3e735bc7d1209a34773", size = 787967, upload-time = "2025-09-19T00:37:34.019Z" }, + { url = "https://files.pythonhosted.org/packages/61/35/9e35665f097c07cf384a6b90a1ac11b0b1693084a0b7a675b06f760496c6/regex-2025.9.18-cp314-cp314-win32.whl", hash = "sha256:0c3506682ea19beefe627a38872d8da65cc01ffa25ed3f2e422dffa1474f0788", size = 269847, upload-time = "2025-09-19T00:37:35.759Z" }, + { url = "https://files.pythonhosted.org/packages/af/64/27594dbe0f1590b82de2821ebfe9a359b44dcb9b65524876cd12fabc447b/regex-2025.9.18-cp314-cp314-win_amd64.whl", hash = "sha256:57929d0f92bebb2d1a83af372cd0ffba2263f13f376e19b1e4fa32aec4efddc3", size = 278755, upload-time = "2025-09-19T00:37:37.367Z" }, + { url = "https://files.pythonhosted.org/packages/30/a3/0cd8d0d342886bd7d7f252d701b20ae1a3c72dc7f34ef4b2d17790280a09/regex-2025.9.18-cp314-cp314-win_arm64.whl", hash = "sha256:6a4b44df31d34fa51aa5c995d3aa3c999cec4d69b9bd414a8be51984d859f06d", size = 271873, upload-time = "2025-09-19T00:37:39.125Z" }, + { url = "https://files.pythonhosted.org/packages/99/cb/8a1ab05ecf404e18b54348e293d9b7a60ec2bd7aa59e637020c5eea852e8/regex-2025.9.18-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b176326bcd544b5e9b17d6943f807697c0cb7351f6cfb45bf5637c95ff7e6306", size = 489773, upload-time = "2025-09-19T00:37:40.968Z" }, + { url = "https://files.pythonhosted.org/packages/93/3b/6543c9b7f7e734d2404fa2863d0d710c907bef99d4598760ed4563d634c3/regex-2025.9.18-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0ffd9e230b826b15b369391bec167baed57c7ce39efc35835448618860995946", size = 291221, upload-time = "2025-09-19T00:37:42.901Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/e9fdee6ad6bf708d98c5d17fded423dcb0661795a49cba1b4ffb8358377a/regex-2025.9.18-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec46332c41add73f2b57e2f5b642f991f6b15e50e9f86285e08ffe3a512ac39f", size = 289268, upload-time = "2025-09-19T00:37:44.823Z" }, + { url = "https://files.pythonhosted.org/packages/94/a6/bc3e8a918abe4741dadeaeb6c508e3a4ea847ff36030d820d89858f96a6c/regex-2025.9.18-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b80fa342ed1ea095168a3f116637bd1030d39c9ff38dc04e54ef7c521e01fc95", size = 806659, upload-time = "2025-09-19T00:37:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/2b/71/ea62dbeb55d9e6905c7b5a49f75615ea1373afcad95830047e4e310db979/regex-2025.9.18-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4d97071c0ba40f0cf2a93ed76e660654c399a0a04ab7d85472239460f3da84b", size = 871701, upload-time = "2025-09-19T00:37:48.882Z" }, + { url = "https://files.pythonhosted.org/packages/6a/90/fbe9dedb7dad24a3a4399c0bae64bfa932ec8922a0a9acf7bc88db30b161/regex-2025.9.18-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0ac936537ad87cef9e0e66c5144484206c1354224ee811ab1519a32373e411f3", size = 913742, upload-time = "2025-09-19T00:37:51.015Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1c/47e4a8c0e73d41eb9eb9fdeba3b1b810110a5139a2526e82fd29c2d9f867/regex-2025.9.18-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dec57f96d4def58c422d212d414efe28218d58537b5445cf0c33afb1b4768571", size = 811117, upload-time = "2025-09-19T00:37:52.686Z" }, + { url = "https://files.pythonhosted.org/packages/2a/da/435f29fddfd015111523671e36d30af3342e8136a889159b05c1d9110480/regex-2025.9.18-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48317233294648bf7cd068857f248e3a57222259a5304d32c7552e2284a1b2ad", size = 794647, upload-time = "2025-09-19T00:37:54.626Z" }, + { url = "https://files.pythonhosted.org/packages/23/66/df5e6dcca25c8bc57ce404eebc7342310a0d218db739d7882c9a2b5974a3/regex-2025.9.18-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:274687e62ea3cf54846a9b25fc48a04459de50af30a7bd0b61a9e38015983494", size = 866747, upload-time = "2025-09-19T00:37:56.367Z" }, + { url = "https://files.pythonhosted.org/packages/82/42/94392b39b531f2e469b2daa40acf454863733b674481fda17462a5ffadac/regex-2025.9.18-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a78722c86a3e7e6aadf9579e3b0ad78d955f2d1f1a8ca4f67d7ca258e8719d4b", size = 853434, upload-time = "2025-09-19T00:37:58.39Z" }, + { url = "https://files.pythonhosted.org/packages/a8/f8/dcc64c7f7bbe58842a8f89622b50c58c3598fbbf4aad0a488d6df2c699f1/regex-2025.9.18-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:06104cd203cdef3ade989a1c45b6215bf42f8b9dd705ecc220c173233f7cba41", size = 798024, upload-time = "2025-09-19T00:38:00.397Z" }, + { url = "https://files.pythonhosted.org/packages/20/8d/edf1c5d5aa98f99a692313db813ec487732946784f8f93145e0153d910e5/regex-2025.9.18-cp314-cp314t-win32.whl", hash = "sha256:2e1eddc06eeaffd249c0adb6fafc19e2118e6308c60df9db27919e96b5656096", size = 273029, upload-time = "2025-09-19T00:38:02.383Z" }, + { url = "https://files.pythonhosted.org/packages/a7/24/02d4e4f88466f17b145f7ea2b2c11af3a942db6222429c2c146accf16054/regex-2025.9.18-cp314-cp314t-win_amd64.whl", hash = "sha256:8620d247fb8c0683ade51217b459cb4a1081c0405a3072235ba43a40d355c09a", size = 282680, upload-time = "2025-09-19T00:38:04.102Z" }, + { url = "https://files.pythonhosted.org/packages/1f/a3/c64894858aaaa454caa7cc47e2f225b04d3ed08ad649eacf58d45817fad2/regex-2025.9.18-cp314-cp314t-win_arm64.whl", hash = "sha256:b7531a8ef61de2c647cdf68b3229b071e46ec326b3138b2180acb4275f470b01", size = 273034, upload-time = "2025-09-19T00:38:05.807Z" }, ] [[package]] From efc48c36ff565d6333cc6894bd75b8be2259754e Mon Sep 17 00:00:00 2001 From: Aleksandr Denisovich <66480963+saneks222@users.noreply.github.com> Date: Thu, 2 Oct 2025 23:08:11 +0500 Subject: [PATCH 03/74] Added button to copy file name in PR files (#35509) The merge request file viewer has a button for copying the file path, but it is not always convenient. Often, you only want to copy the file name, which is currently not possible. This change request adds this capability. --------- Signed-off-by: wxiaoguang Co-authored-by: a.kiselev Co-authored-by: wxiaoguang --- options/locale/locale_en-US.ini | 1 + services/gitdiff/gitdiff.go | 9 +++++++++ templates/repo/diff/box.tmpl | 1 + 3 files changed, 11 insertions(+) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index b3eb7b1f4a..64bc3b1871 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -109,6 +109,7 @@ copy_path = Copy path copy_success = Copied! copy_error = Copy failed copy_type_unsupported = This file type cannot be copied +copy_filename = Copy filename write = Write preview = Preview diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 1cc5ce66f8..2de87f9979 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -13,6 +13,7 @@ import ( "html/template" "io" "net/url" + "path" "sort" "strings" "time" @@ -403,6 +404,14 @@ func (diffFile *DiffFile) GetDiffFileName() string { return diffFile.Name } +// GetDiffFileBaseName returns the short name of the diff file, or its short old name in case it was deleted +func (diffFile *DiffFile) GetDiffFileBaseName() string { + if diffFile.Name == "" { + return path.Base(diffFile.OldName) + } + return path.Base(diffFile.Name) +} + func (diffFile *DiffFile) ShouldBeHidden() bool { return diffFile.IsGenerated || diffFile.IsViewed } diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index e4d1efac57..7eb96e1ddc 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -143,6 +143,7 @@ {{end}} + {{if not $.PageIsWiki}} {{if $file.IsDeleted}} {{ctx.Locale.Tr "repo.diff.view_file"}} From c4532101a47a423d5f055f14c8097fc168413f9c Mon Sep 17 00:00:00 2001 From: Kausthubh J Rao <105716675+Exgene@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:21:57 +0530 Subject: [PATCH 04/74] fix(webhook): prevent tag events from bypassing branch filters targets #35449 (#35567) Tag creation/deletion was triggering push webhooks even when branch filters were configured, causing unintended pipeline executions. This change modifies the branch filter logic to check the full ref name directly instead of first determining if it's a "branch" event. Fixes: Tag events now properly respect branch filters - Add getPayloadRef() function to extract full ref names - Update PrepareWebhook() to use direct ref matching - Prevents refs/tags/* from matching refs/heads/* filters Closes #35449 --------- Co-authored-by: wxiaoguang Co-authored-by: silverwind --- options/locale/locale_en-US.ini | 4 +- services/webhook/webhook.go | 45 ++++++++++--------- services/webhook/webhook_test.go | 28 ++++++++++++ templates/repo/settings/webhook/settings.tmpl | 11 ++++- web_src/css/base.css | 17 ++++--- web_src/css/form.css | 5 +++ web_src/css/repo/issue-list.css | 7 --- 7 files changed, 83 insertions(+), 34 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 64bc3b1871..03017ce674 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2434,7 +2434,9 @@ settings.event_workflow_job_desc = Gitea Actions Workflow job queued, waiting, i settings.event_package = Package settings.event_package_desc = Package created or deleted in a repository. settings.branch_filter = Branch filter -settings.branch_filter_desc = Branch whitelist for push, branch creation and branch deletion events, specified as glob pattern. If empty or *, events for all branches are reported. See %[2]s documentation for syntax. Examples: master, {master,release*}. +settings.branch_filter_desc_1 = Branch (and ref name) allowlist for push, branch creation and branch deletion events, specified as glob pattern. If empty or *, events for all branches and tags are reported. +settings.branch_filter_desc_2 = Use refs/heads/ or refs/tags/ prefix to match full ref names. +settings.branch_filter_desc_doc = See %[2]s documentation for syntax. settings.authorization_header = Authorization Header settings.authorization_header_desc = Will be included as authorization header for requests when present. Examples: %s. settings.active = Active diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 2b276207a1..a35997dda0 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "net/http" - "strings" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" @@ -46,21 +45,25 @@ func IsValidHookTaskType(name string) bool { // hookQueue is a global queue of web hooks var hookQueue *queue.WorkerPoolQueue[int64] -// getPayloadBranch returns branch for hook event, if applicable. -func getPayloadBranch(p api.Payloader) string { +// getPayloadRef returns the full ref name for hook event, if applicable. +func getPayloadRef(p api.Payloader) git.RefName { switch pp := p.(type) { case *api.CreatePayload: - if pp.RefType == "branch" { - return pp.Ref + switch pp.RefType { + case "branch": + return git.RefNameFromBranch(pp.Ref) + case "tag": + return git.RefNameFromTag(pp.Ref) } case *api.DeletePayload: - if pp.RefType == "branch" { - return pp.Ref + switch pp.RefType { + case "branch": + return git.RefNameFromBranch(pp.Ref) + case "tag": + return git.RefNameFromTag(pp.Ref) } case *api.PushPayload: - if strings.HasPrefix(pp.Ref, git.BranchPrefix) { - return pp.Ref[len(git.BranchPrefix):] - } + return git.RefName(pp.Ref) } return "" } @@ -108,19 +111,22 @@ func enqueueHookTask(taskID int64) error { return nil } -func checkBranch(w *webhook_model.Webhook, branch string) bool { - if w.BranchFilter == "" || w.BranchFilter == "*" { +func checkBranchFilter(branchFilter string, ref git.RefName) bool { + if branchFilter == "" || branchFilter == "*" || branchFilter == "**" { return true } - g, err := glob.Compile(w.BranchFilter) + g, err := glob.Compile(branchFilter) if err != nil { // should not really happen as BranchFilter is validated - log.Error("CheckBranch failed: %s", err) + log.Debug("checkBranchFilter failed to compile filer %q, err: %s", branchFilter, err) return false } - return g.Match(branch) + if ref.IsBranch() && g.Match(ref.BranchName()) { + return true + } + return g.Match(ref.String()) } // PrepareWebhook creates a hook task and enqueues it for processing. @@ -144,11 +150,10 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook return nil } - // If payload has no associated branch (e.g. it's a new tag, issue, etc.), - // branch filter has no effect. - if branch := getPayloadBranch(p); branch != "" { - if !checkBranch(w, branch) { - log.Info("Branch %q doesn't match branch filter %q, skipping", branch, w.BranchFilter) + // If payload has no associated branch (e.g. it's a new tag, issue, etc.), branch filter has no effect. + if ref := getPayloadRef(p); ref != "" { + // Check the payload's git ref against the webhook's branch filter. + if !checkBranchFilter(w.BranchFilter, ref) { return nil } } diff --git a/services/webhook/webhook_test.go b/services/webhook/webhook_test.go index 34bcfd3df9..f4432cc3f1 100644 --- a/services/webhook/webhook_test.go +++ b/services/webhook/webhook_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" webhook_model "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" @@ -90,3 +91,30 @@ func TestWebhookUserMail(t *testing.T) { assert.Equal(t, user.GetPlaceholderEmail(), convert.ToUser(t.Context(), user, nil).Email) assert.Equal(t, user.Email, convert.ToUser(t.Context(), user, user).Email) } + +func TestCheckBranchFilter(t *testing.T) { + cases := []struct { + filter string + ref git.RefName + match bool + }{ + {"", "any-ref", true}, + {"*", "any-ref", true}, + {"**", "any-ref", true}, + + {"main", git.RefNameFromBranch("main"), true}, + {"main", git.RefNameFromTag("main"), false}, + + {"feature/*", git.RefNameFromBranch("feature"), false}, + {"feature/*", git.RefNameFromBranch("feature/foo"), true}, + {"feature/*", git.RefNameFromTag("feature/foo"), false}, + + {"{refs/heads/feature/*,refs/tags/release/*}", git.RefNameFromBranch("feature/foo"), true}, + {"{refs/heads/feature/*,refs/tags/release/*}", git.RefNameFromBranch("main"), false}, + {"{refs/heads/feature/*,refs/tags/release/*}", git.RefNameFromTag("release/bar"), true}, + {"{refs/heads/feature/*,refs/tags/release/*}", git.RefNameFromTag("dev"), false}, + } + for _, v := range cases { + assert.Equal(t, v.match, checkBranchFilter(v.filter, v.ref), "filter: %q ref: %q", v.filter, v.ref) + } +} diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl index a8ad1d6c9e..1f71b9cfab 100644 --- a/templates/repo/settings/webhook/settings.tmpl +++ b/templates/repo/settings/webhook/settings.tmpl @@ -44,7 +44,16 @@
- {{ctx.Locale.Tr "repo.settings.branch_filter_desc" "https://pkg.go.dev/github.com/gobwas/glob#Compile" "github.com/gobwas/glob"}} + + {{ctx.Locale.Tr "repo.settings.branch_filter_desc_1"}} + {{ctx.Locale.Tr "repo.settings.branch_filter_desc_2"}} + {{ctx.Locale.Tr "repo.settings.branch_filter_desc_doc" "https://pkg.go.dev/github.com/gobwas/glob#Compile" "github.com/gobwas/glob"}} +
    +
  • main
  • +
  • {main,feature/*}
  • +
  • {refs/heads/feature/*,refs/tags/release/*}
  • +
+
diff --git a/web_src/css/base.css b/web_src/css/base.css index 6ff060f1f9..9cef92019d 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -101,6 +101,13 @@ samp, font-size: 0.95em; /* compensate for monospace fonts being usually slightly larger */ } +code { + padding: 1px 4px; + border-radius: var(--border-radius); + background-color: var(--color-label-bg); + color: var(--color-label-text); +} + b, strong, h1, @@ -177,6 +184,11 @@ table { border-collapse: collapse; } +ul { + margin: 0.5em 0; + padding: 0 0 0 1.5em; +} + button { cursor: pointer; } @@ -603,11 +615,6 @@ img.ui.avatar, text-align: center; } -.ui .message > ul { - margin: 0; - padding: 0 1em; -} - .ui .header > i + .content { padding-left: 0.75rem; vertical-align: middle; diff --git a/web_src/css/form.css b/web_src/css/form.css index c51eba1bc9..757edf7297 100644 --- a/web_src/css/form.css +++ b/web_src/css/form.css @@ -218,11 +218,16 @@ textarea:focus, .form .help { color: var(--color-secondary-dark-5); + margin-top: 0.25em; padding-bottom: 0.6em; display: inline-block; text-wrap: balance; } +.form .help code { + color: var(--color-text-light-1); +} + .m-captcha-style { width: 100%; height: 5em; diff --git a/web_src/css/repo/issue-list.css b/web_src/css/repo/issue-list.css index bf8ff00b7e..33888101b6 100644 --- a/web_src/css/repo/issue-list.css +++ b/web_src/css/repo/issue-list.css @@ -84,10 +84,3 @@ margin-right: 8px; text-align: left; } - -.label-filter-exclude-info code { - border: 1px solid var(--color-secondary); - border-radius: var(--border-radius); - padding: 1px 2px; - font-size: 11px; -} From 71360a94cb410402484cf1ceda8bdb2290d03d7f Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Sat, 4 Oct 2025 01:21:26 +0800 Subject: [PATCH 05/74] Address some CodeQL security concerns (#35572) Although there is no real security problem --- cmd/admin_user_create.go | 1 + cmd/admin_user_must_change_password.go | 1 + cmd/generate.go | 1 + cmd/hook.go | 4 +-- models/repo/repo.go | 2 +- models/user/user.go | 2 +- modules/auth/password/hash/argon2.go | 16 ++++------ modules/auth/password/hash/common.go | 8 +++-- modules/auth/password/pwn/pwn.go | 4 +-- modules/auth/password/pwn/pwn_test.go | 12 ++++---- modules/git/hook.go | 2 +- modules/log/logger_global.go | 1 + modules/log/misc.go | 1 + modules/setting/config_env.go | 2 +- modules/tempdir/tempdir.go | 2 +- modules/translation/i18n/i18n_test.go | 3 ++ modules/translation/i18n/localestore.go | 8 +++-- modules/util/color.go | 9 +++--- routers/api/v1/repo/issue_pin.go | 2 +- routers/web/explore/repo.go | 2 +- routers/web/explore/user.go | 2 +- routers/web/repo/activity.go | 27 +++++++---------- routers/web/repo/githttp.go | 30 +++++++++++-------- routers/web/repo/view_home.go | 2 +- routers/web/user/avatar.go | 2 +- services/context/access_log.go | 14 +++++++++ services/context/access_log_test.go | 5 ++++ services/context/base_path.go | 5 ++++ web_src/fomantic/build/components/api.js | 4 +-- web_src/fomantic/build/components/dropdown.js | 2 +- web_src/fomantic/build/components/modal.js | 2 +- .../js/features/comp/EditorMarkdown.test.ts | 4 +-- web_src/js/features/repo-issue.ts | 2 +- web_src/js/modules/fomantic/base.ts | 5 +++- web_src/js/utils.ts | 7 ++++- 35 files changed, 118 insertions(+), 78 deletions(-) diff --git a/cmd/admin_user_create.go b/cmd/admin_user_create.go index cbdb5f90e2..7e5675cf58 100644 --- a/cmd/admin_user_create.go +++ b/cmd/admin_user_create.go @@ -151,6 +151,7 @@ func runCreateUser(ctx context.Context, c *cli.Command) error { if err != nil { return err } + // codeql[disable-next-line=go/clear-text-logging] fmt.Printf("generated random password is '%s'\n", password) } else if userType == user_model.UserTypeIndividual { return errors.New("must set either password or random-password flag") diff --git a/cmd/admin_user_must_change_password.go b/cmd/admin_user_must_change_password.go index 8521853dc1..468d462b74 100644 --- a/cmd/admin_user_must_change_password.go +++ b/cmd/admin_user_must_change_password.go @@ -58,6 +58,7 @@ func runMustChangePassword(ctx context.Context, c *cli.Command) error { return err } + // codeql[disable-next-line=go/clear-text-logging] fmt.Printf("Updated %d users setting MustChangePassword to %t\n", n, mustChangePassword) return nil } diff --git a/cmd/generate.go b/cmd/generate.go index cf491604ef..9cb4cf3917 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -91,6 +91,7 @@ func runGenerateSecretKey(_ context.Context, c *cli.Command) error { return err } + // codeql[disable-next-line=go/clear-text-logging] fmt.Printf("%s", secretKey) if isatty.IsTerminal(os.Stdout.Fd()) { diff --git a/cmd/hook.go b/cmd/hook.go index 2f866dd396..ceadb09f63 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -186,7 +186,7 @@ Gitea or set your environment appropriately.`, "") userID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64) prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64) deployKeyID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvDeployKeyID), 10, 64) - actionPerm, _ := strconv.ParseInt(os.Getenv(repo_module.EnvActionPerm), 10, 64) + actionPerm, _ := strconv.Atoi(os.Getenv(repo_module.EnvActionPerm)) hookOptions := private.HookOptions{ UserID: userID, @@ -196,7 +196,7 @@ Gitea or set your environment appropriately.`, "") GitPushOptions: pushOptions(), PullRequestID: prID, DeployKeyID: deployKeyID, - ActionPerm: int(actionPerm), + ActionPerm: actionPerm, } scanner := bufio.NewScanner(os.Stdin) diff --git a/models/repo/repo.go b/models/repo/repo.go index 8237a429e5..401775047b 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -605,7 +605,7 @@ func (repo *Repository) IsGenerated() bool { // RepoPath returns repository path by given user and repository name. func RepoPath(userName, repoName string) string { //revive:disable-line:exported - return filepath.Join(user_model.UserPath(userName), strings.ToLower(repoName)+".git") + return filepath.Join(setting.RepoRootPath, filepath.Clean(strings.ToLower(userName)), filepath.Clean(strings.ToLower(repoName)+".git")) } // RepoPath returns the repository path diff --git a/models/user/user.go b/models/user/user.go index 6143992a25..80d5eb5ec4 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -980,7 +980,7 @@ func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, er // UserPath returns the path absolute path of user repositories. func UserPath(userName string) string { //revive:disable-line:exported - return filepath.Join(setting.RepoRootPath, strings.ToLower(userName)) + return filepath.Join(setting.RepoRootPath, filepath.Clean(strings.ToLower(userName))) } // GetUserByID returns the user object by given ID if exists. diff --git a/modules/auth/password/hash/argon2.go b/modules/auth/password/hash/argon2.go index 0cd6472fa1..f4a7497df6 100644 --- a/modules/auth/password/hash/argon2.go +++ b/modules/auth/password/hash/argon2.go @@ -61,17 +61,11 @@ func NewArgon2Hasher(config string) *Argon2Hasher { return nil } - parsed, err := parseUIntParam(vals[0], "time", "argon2", config, nil) - hasher.time = uint32(parsed) - - parsed, err = parseUIntParam(vals[1], "memory", "argon2", config, err) - hasher.memory = uint32(parsed) - - parsed, err = parseUIntParam(vals[2], "threads", "argon2", config, err) - hasher.threads = uint8(parsed) - - parsed, err = parseUIntParam(vals[3], "keyLen", "argon2", config, err) - hasher.keyLen = uint32(parsed) + var err error + hasher.time, err = parseUintParam[uint32](vals[0], "time", "argon2", config, nil) + hasher.memory, err = parseUintParam[uint32](vals[1], "memory", "argon2", config, err) + hasher.threads, err = parseUintParam[uint8](vals[2], "threads", "argon2", config, err) + hasher.keyLen, err = parseUintParam[uint32](vals[3], "keyLen", "argon2", config, err) if err != nil { return nil } diff --git a/modules/auth/password/hash/common.go b/modules/auth/password/hash/common.go index d5e2c34314..1fafc289ed 100644 --- a/modules/auth/password/hash/common.go +++ b/modules/auth/password/hash/common.go @@ -7,6 +7,7 @@ import ( "strconv" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/util" ) func parseIntParam(value, param, algorithmName, config string, previousErr error) (int, error) { @@ -18,11 +19,12 @@ func parseIntParam(value, param, algorithmName, config string, previousErr error return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed } -func parseUIntParam(value, param, algorithmName, config string, previousErr error) (uint64, error) { //nolint:unparam // algorithmName is always argon2 - parsed, err := strconv.ParseUint(value, 10, 64) +func parseUintParam[T uint32 | uint8](value, param, algorithmName, config string, previousErr error) (ret T, _ error) { + _, isUint32 := any(ret).(uint32) + parsed, err := strconv.ParseUint(value, 10, util.Iif(isUint32, 32, 8)) if err != nil { log.Error("invalid integer for %s representation in %s hash spec %s", param, algorithmName, config) return 0, err } - return parsed, previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed + return T(parsed), previousErr // <- Keep the previous error as this function should still return an error once everything has been checked if any call failed } diff --git a/modules/auth/password/pwn/pwn.go b/modules/auth/password/pwn/pwn.go index 99a6ca6cea..d5ea96c4af 100644 --- a/modules/auth/password/pwn/pwn.go +++ b/modules/auth/password/pwn/pwn.go @@ -72,7 +72,7 @@ func newRequest(ctx context.Context, method, url string, body io.ReadCloser) (*h // Adding padding will make requests more secure, however is also slower // because artificial responses will be added to the response // For more information, see https://www.troyhunt.com/enhancing-pwned-passwords-privacy-with-padding/ -func (c *Client) CheckPassword(pw string, padding bool) (int, error) { +func (c *Client) CheckPassword(pw string, padding bool) (int64, error) { if pw == "" { return -1, ErrEmptyPassword } @@ -111,7 +111,7 @@ func (c *Client) CheckPassword(pw string, padding bool) (int, error) { if err != nil { return -1, err } - return int(count), nil + return count, nil } } return 0, nil diff --git a/modules/auth/password/pwn/pwn_test.go b/modules/auth/password/pwn/pwn_test.go index ae03fabc57..4b760fdf32 100644 --- a/modules/auth/password/pwn/pwn_test.go +++ b/modules/auth/password/pwn/pwn_test.go @@ -37,25 +37,25 @@ func TestPassword(t *testing.T) { count, err := client.CheckPassword("", false) assert.ErrorIs(t, err, ErrEmptyPassword, "blank input should return ErrEmptyPassword") - assert.Equal(t, -1, count) + assert.EqualValues(t, -1, count) count, err = client.CheckPassword("pwned", false) assert.NoError(t, err) - assert.Equal(t, 1, count) + assert.EqualValues(t, 1, count) count, err = client.CheckPassword("notpwned", false) assert.NoError(t, err) - assert.Equal(t, 0, count) + assert.EqualValues(t, 0, count) count, err = client.CheckPassword("paddedpwned", true) assert.NoError(t, err) - assert.Equal(t, 1, count) + assert.EqualValues(t, 1, count) count, err = client.CheckPassword("paddednotpwned", true) assert.NoError(t, err) - assert.Equal(t, 0, count) + assert.EqualValues(t, 0, count) count, err = client.CheckPassword("paddednotpwnedzero", true) assert.NoError(t, err) - assert.Equal(t, 0, count) + assert.EqualValues(t, 0, count) } diff --git a/modules/git/hook.go b/modules/git/hook.go index 548a59971d..361aa53100 100644 --- a/modules/git/hook.go +++ b/modules/git/hook.go @@ -45,7 +45,7 @@ func GetHook(repoPath, name string) (*Hook, error) { } h := &Hook{ name: name, - path: filepath.Join(repoPath, "hooks", name+".d", name), + path: filepath.Join(repoPath, filepath.Join("hooks", name+".d", name)), } isFile, err := util.IsFile(h.path) if err != nil { diff --git a/modules/log/logger_global.go b/modules/log/logger_global.go index 07c25cd62f..2bc8c4f449 100644 --- a/modules/log/logger_global.go +++ b/modules/log/logger_global.go @@ -18,6 +18,7 @@ func GetLevel() Level { } func Log(skip int, level Level, format string, v ...any) { + // codeql[disable-next-line=go/clear-text-logging] GetLogger(DEFAULT).Log(skip+1, &Event{Level: level}, format, v...) } diff --git a/modules/log/misc.go b/modules/log/misc.go index c9d230e4ac..a58b3757da 100644 --- a/modules/log/misc.go +++ b/modules/log/misc.go @@ -20,6 +20,7 @@ func BaseLoggerToGeneralLogger(b BaseLogger) Logger { var _ Logger = (*baseToLogger)(nil) func (s *baseToLogger) Log(skip int, event *Event, format string, v ...any) { + // codeql[disable-next-line=go/clear-text-logging] s.base.Log(skip+1, event, format, v...) } diff --git a/modules/setting/config_env.go b/modules/setting/config_env.go index 409588dc44..8b204e5c7c 100644 --- a/modules/setting/config_env.go +++ b/modules/setting/config_env.go @@ -65,7 +65,7 @@ func decodeEnvSectionKey(encoded string) (ok bool, section, key string) { decodedBytes := make([]byte, len(toDecode)/2) for i := 0; i < len(toDecode)/2; i++ { // Can ignore error here as we know these should be hexadecimal from the regexp - byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 0) + byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 8) decodedBytes[i] = byte(byteInt) } if inKey { diff --git a/modules/tempdir/tempdir.go b/modules/tempdir/tempdir.go index 22c2e4ea16..e5e928e449 100644 --- a/modules/tempdir/tempdir.go +++ b/modules/tempdir/tempdir.go @@ -19,7 +19,7 @@ type TempDir struct { } func (td *TempDir) JoinPath(elems ...string) string { - return filepath.Join(append([]string{td.base, td.sub}, elems...)...) + return filepath.Join(append([]string{td.base, td.sub}, filepath.Join(elems...))...) } // MkdirAllSub works like os.MkdirAll, but the base directory must exist diff --git a/modules/translation/i18n/i18n_test.go b/modules/translation/i18n/i18n_test.go index b364992dfe..3cf3f71294 100644 --- a/modules/translation/i18n/i18n_test.go +++ b/modules/translation/i18n/i18n_test.go @@ -62,6 +62,9 @@ sub = Changed Sub String found := lang1.HasKey("no-such") assert.False(t, found) assert.NoError(t, ls.Close()) + + res := lang1.TrHTML("") + assert.Equal(t, "<no-such>", string(res)) } func TestLocaleStoreMoreSource(t *testing.T) { diff --git a/modules/translation/i18n/localestore.go b/modules/translation/i18n/localestore.go index 4f1ae7e13d..c540b5bf47 100644 --- a/modules/translation/i18n/localestore.go +++ b/modules/translation/i18n/localestore.go @@ -6,6 +6,7 @@ package i18n import ( "errors" "fmt" + "html" "html/template" "slices" @@ -109,8 +110,7 @@ func (store *localeStore) Close() error { } func (l *locale) TrString(trKey string, trArgs ...any) string { - format := trKey - + var format string idx, ok := l.store.trKeyToIdxMap[trKey] if ok { if msg, ok := l.idxToMsgMap[idx]; ok { @@ -122,7 +122,9 @@ func (l *locale) TrString(trKey string, trArgs ...any) string { } } } - + if format == "" { + format = html.EscapeString(trKey) + } msg, err := Format(format, trArgs...) if err != nil { log.Error("Error whilst formatting %q in %s: %v", trKey, l.langName, err) diff --git a/modules/util/color.go b/modules/util/color.go index 8fffc91ac4..4d2c251726 100644 --- a/modules/util/color.go +++ b/modules/util/color.go @@ -26,13 +26,14 @@ func HexToRBGColor(colorString string) (float64, float64, float64) { if len(hexString) == 8 { hexString = hexString[0:6] } - color, err := strconv.ParseUint(hexString, 16, 64) + color, err := strconv.ParseUint(hexString, 16, 32) + color32 := uint32(color) if err != nil { return 0, 0, 0 } - r := float64(uint8(0xFF & (uint32(color) >> 16))) - g := float64(uint8(0xFF & (uint32(color) >> 8))) - b := float64(uint8(0xFF & uint32(color))) + r := float64(uint8(0xFF & (color32 >> 16))) + g := float64(uint8(0xFF & (color32 >> 8))) + b := float64(uint8(0xFF & color32)) return r, g, b } diff --git a/routers/api/v1/repo/issue_pin.go b/routers/api/v1/repo/issue_pin.go index 71985ac765..45bdd875d2 100644 --- a/routers/api/v1/repo/issue_pin.go +++ b/routers/api/v1/repo/issue_pin.go @@ -169,7 +169,7 @@ func MoveIssuePin(ctx *context.APIContext) { return } - err = issues_model.MovePin(ctx, issue, int(ctx.PathParamInt64("position"))) + err = issues_model.MovePin(ctx, issue, ctx.PathParamInt("position")) if err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go index f0d7d0ce7d..1b269deb98 100644 --- a/routers/web/explore/repo.go +++ b/routers/web/explore/repo.go @@ -35,7 +35,7 @@ type RepoSearchOptions struct { // This function is also used to render the Admin Repository Management page. func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) { // Sitemap index for sitemap paths - page := int(ctx.PathParamInt64("idx")) + page := ctx.PathParamInt("idx") isSitemap := ctx.PathParam("idx") != "" if page <= 1 { page = ctx.FormInt("page") diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go index 3774be033d..40d3e2a060 100644 --- a/routers/web/explore/user.go +++ b/routers/web/explore/user.go @@ -34,7 +34,7 @@ func isKeywordValid(keyword string) bool { // RenderUserSearch render user search page func RenderUserSearch(ctx *context.Context, opts user_model.SearchUserOptions, tplName templates.TplName) { // Sitemap index for sitemap paths - opts.Page = int(ctx.PathParamInt64("idx")) + opts.Page = ctx.PathParamInt("idx") isSitemap := ctx.PathParam("idx") != "" if opts.Page <= 1 { opts.Page = ctx.FormInt("page") diff --git a/routers/web/repo/activity.go b/routers/web/repo/activity.go index fcede1822a..4cfe879032 100644 --- a/routers/web/repo/activity.go +++ b/routers/web/repo/activity.go @@ -25,33 +25,28 @@ func Activity(ctx *context.Context) { ctx.Data["PageIsPulse"] = true - ctx.Data["Period"] = ctx.PathParam("period") - timeUntil := time.Now() - var timeFrom time.Time - - switch ctx.Data["Period"] { + period, timeFrom := "weekly", timeUntil.Add(-time.Hour*168) + switch ctx.PathParam("period") { case "daily": - timeFrom = timeUntil.Add(-time.Hour * 24) + period, timeFrom = "daily", timeUntil.Add(-time.Hour*24) case "halfweekly": - timeFrom = timeUntil.Add(-time.Hour * 72) + period, timeFrom = "halfweekly", timeUntil.Add(-time.Hour*72) case "weekly": - timeFrom = timeUntil.Add(-time.Hour * 168) + period, timeFrom = "weekly", timeUntil.Add(-time.Hour*168) case "monthly": - timeFrom = timeUntil.AddDate(0, -1, 0) + period, timeFrom = "monthly", timeUntil.AddDate(0, -1, 0) case "quarterly": - timeFrom = timeUntil.AddDate(0, -3, 0) + period, timeFrom = "quarterly", timeUntil.AddDate(0, -3, 0) case "semiyearly": - timeFrom = timeUntil.AddDate(0, -6, 0) + period, timeFrom = "semiyearly", timeUntil.AddDate(0, -6, 0) case "yearly": - timeFrom = timeUntil.AddDate(-1, 0, 0) - default: - ctx.Data["Period"] = "weekly" - timeFrom = timeUntil.Add(-time.Hour * 168) + period, timeFrom = "yearly", timeUntil.AddDate(-1, 0, 0) } ctx.Data["DateFrom"] = timeFrom ctx.Data["DateUntil"] = timeUntil - ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + ctx.Data["Period"].(string)) + ctx.Data["Period"] = period + ctx.Data["PeriodText"] = ctx.Tr("repo.activity.period." + period) canReadCode := ctx.Repo.CanRead(unit.TypeCode) if canReadCode { diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index ab649b6f15..829e6a5fc3 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -376,7 +376,7 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string ctx.Resp.WriteHeader(http.StatusBadRequest) return } - reqFile := filepath.Join(h.getRepoDir(), file) + reqFile := filepath.Join(h.getRepoDir(), filepath.Clean(file)) fi, err := os.Stat(reqFile) if os.IsNotExist(err) { @@ -395,13 +395,12 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`) func prepareGitCmdWithAllowedService(service string) (*gitcmd.Command, error) { - if service == "receive-pack" { - return gitcmd.NewCommand("receive-pack"), nil + if service == ServiceTypeReceivePack { + return gitcmd.NewCommand(ServiceTypeReceivePack), nil } - if service == "upload-pack" { - return gitcmd.NewCommand("upload-pack"), nil + if service == ServiceTypeUploadPack { + return gitcmd.NewCommand(ServiceTypeUploadPack), nil } - return nil, fmt.Errorf("service %q is not allowed", service) } @@ -464,11 +463,16 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { } } +const ( + ServiceTypeUploadPack = "upload-pack" + ServiceTypeReceivePack = "receive-pack" +) + // ServiceUploadPack implements Git Smart HTTP protocol func ServiceUploadPack(ctx *context.Context) { h := httpBase(ctx) if h != nil { - serviceRPC(ctx, h, "upload-pack") + serviceRPC(ctx, h, ServiceTypeUploadPack) } } @@ -476,16 +480,18 @@ func ServiceUploadPack(ctx *context.Context) { func ServiceReceivePack(ctx *context.Context) { h := httpBase(ctx) if h != nil { - serviceRPC(ctx, h, "receive-pack") + serviceRPC(ctx, h, ServiceTypeReceivePack) } } func getServiceType(ctx *context.Context) string { - serviceType := ctx.Req.FormValue("service") - if !strings.HasPrefix(serviceType, "git-") { - return "" + switch ctx.Req.FormValue("service") { + case "git-" + ServiceTypeUploadPack: + return ServiceTypeUploadPack + case "git-" + ServiceTypeReceivePack: + return ServiceTypeReceivePack } - return strings.TrimPrefix(serviceType, "git-") + return "" } func updateServerInfo(ctx gocontext.Context, dir string) []byte { diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index f475e93f60..88d9fd8fe2 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -279,7 +279,7 @@ func handleRepoViewSubmodule(ctx *context.Context, commitSubmoduleFile *git.Comm ctx.Data["NotFoundPrompt"] = redirectLink ctx.NotFound(nil) } else { - ctx.Redirect(submoduleWebLink.CommitWebLink) + ctx.RedirectToCurrentSite(redirectLink) } } diff --git a/routers/web/user/avatar.go b/routers/web/user/avatar.go index 6d3179bc48..2eca669194 100644 --- a/routers/web/user/avatar.go +++ b/routers/web/user/avatar.go @@ -31,7 +31,7 @@ func AvatarByUsernameSize(ctx *context.Context) { return } } - cacheableRedirect(ctx, user.AvatarLinkWithSize(ctx, int(ctx.PathParamInt64("size")))) + cacheableRedirect(ctx, user.AvatarLinkWithSize(ctx, ctx.PathParamInt("size"))) } // AvatarByEmailHash redirects the browser to the email avatar link diff --git a/services/context/access_log.go b/services/context/access_log.go index caade113a7..9419106a07 100644 --- a/services/context/access_log.go +++ b/services/context/access_log.go @@ -10,6 +10,7 @@ import ( "strings" "text/template" "time" + "unicode" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -37,6 +38,16 @@ const keyOfRequestIDInTemplate = ".RequestID" // So, we accept a Request ID with a maximum character length of 40 const maxRequestIDByteLength = 40 +func isSafeRequestID(id string) bool { + for _, r := range id { + safe := unicode.IsPrint(r) + if !safe { + return false + } + } + return true +} + func parseRequestIDFromRequestHeader(req *http.Request) string { requestID := "-" for _, key := range setting.Log.RequestIDHeaders { @@ -45,6 +56,9 @@ func parseRequestIDFromRequestHeader(req *http.Request) string { break } } + if !isSafeRequestID(requestID) { + return "-" + } if len(requestID) > maxRequestIDByteLength { requestID = requestID[:maxRequestIDByteLength] + "..." } diff --git a/services/context/access_log_test.go b/services/context/access_log_test.go index 139a6eb217..89ec90fd4f 100644 --- a/services/context/access_log_test.go +++ b/services/context/access_log_test.go @@ -69,3 +69,8 @@ func TestAccessLogger(t *testing.T) { recorder.record(time.Date(2000, 1, 2, 3, 4, 5, 0, time.UTC), &testAccessLoggerResponseWriterMock{}, req) assert.Equal(t, []string{`remote-addr - - [02/Jan/2000:03:04:05 +0000] "GET /path https" 200 123123 "referer" "user-agent"`}, mockLogger.logs) } + +func TestAccessLoggerRequestID(t *testing.T) { + assert.False(t, isSafeRequestID("\x00")) + assert.True(t, isSafeRequestID("a b-c")) +} diff --git a/services/context/base_path.go b/services/context/base_path.go index 3678deaff9..63e60c8654 100644 --- a/services/context/base_path.go +++ b/services/context/base_path.go @@ -37,6 +37,11 @@ func (b *Base) PathParamInt64(p string) int64 { return v } +func (b *Base) PathParamInt(p string) int { + v, _ := strconv.Atoi(b.PathParam(p)) + return v +} + // SetPathParam set request path params into routes func (b *Base) SetPathParam(name, value string) { if strings.HasPrefix(name, ":") { diff --git a/web_src/fomantic/build/components/api.js b/web_src/fomantic/build/components/api.js index a104cfbc1b..3bfe27e13c 100644 --- a/web_src/fomantic/build/components/api.js +++ b/web_src/fomantic/build/components/api.js @@ -1144,8 +1144,8 @@ $.api.settings = { }, regExp : { - required : /\{\$*[A-z0-9]+\}/g, - optional : /\{\/\$*[A-z0-9]+\}/g, + required : /\{\$*[_A-Za-z0-9]+\}/g, // GITEA-PATCH: use "_A-Za-z" instead of "A-z" for variable name matching + optional : /\{\/\$*[_A-Za-z0-9]+\}/g, // GITEA-PATCH: use "_A-Za-z" instead of "A-z" for variable name matching }, className: { diff --git a/web_src/fomantic/build/components/dropdown.js b/web_src/fomantic/build/components/dropdown.js index 3ad0984865..f40d77df13 100644 --- a/web_src/fomantic/build/components/dropdown.js +++ b/web_src/fomantic/build/components/dropdown.js @@ -66,7 +66,7 @@ $.fn.dropdown = function(parameters) { moduleNamespace = 'module-' + namespace, $module = $(this), - $context = $(settings.context), + $context = (typeof settings.context === 'string') ? $(document).find(settings.context) : $(settings.context), // GITEA-PATCH: use "jQuery.find(selector)" instead of "jQuery(selector)" $text = $module.find(selector.text), $search = $module.find(selector.search), $sizer = $module.find(selector.sizer), diff --git a/web_src/fomantic/build/components/modal.js b/web_src/fomantic/build/components/modal.js index 3f578ccfcc..0434af3deb 100644 --- a/web_src/fomantic/build/components/modal.js +++ b/web_src/fomantic/build/components/modal.js @@ -64,7 +64,7 @@ $.fn.modal = function(parameters) { moduleNamespace = 'module-' + namespace, $module = $(this), - $context = $(settings.context), + $context = (typeof settings.context === 'string') ? $(document).find(settings.context) : $(settings.context), // GITEA-PATCH: use "jQuery.find(selector)" instead of "jQuery(selector)" $close = $module.find(selector.close), $allModals, diff --git a/web_src/js/features/comp/EditorMarkdown.test.ts b/web_src/js/features/comp/EditorMarkdown.test.ts index 431994c7d3..ae3d0c9f0b 100644 --- a/web_src/js/features/comp/EditorMarkdown.test.ts +++ b/web_src/js/features/comp/EditorMarkdown.test.ts @@ -26,13 +26,13 @@ test('textareaSplitLines', () => { test('markdownHandleIndention', () => { const testInput = (input: string, expected?: string) => { const inputPos = input.indexOf('|'); - input = input.replace('|', ''); + input = input.replaceAll('|', ''); const ret = markdownHandleIndention({value: input, selStart: inputPos, selEnd: inputPos}); if (expected === null) { expect(ret).toEqual({handled: false}); } else { const expectedPos = expected.indexOf('|'); - expected = expected.replace('|', ''); + expected = expected.replaceAll('|', ''); expect(ret).toEqual({ handled: true, valueSelection: {value: expected, selStart: expectedPos, selEnd: expectedPos}, diff --git a/web_src/js/features/repo-issue.ts b/web_src/js/features/repo-issue.ts index ed9aad9adf..58274b95c0 100644 --- a/web_src/js/features/repo-issue.ts +++ b/web_src/js/features/repo-issue.ts @@ -333,7 +333,7 @@ export function initRepoPullRequestReview() { let ntr = tr.nextElementSibling; if (!ntr?.classList.contains('add-comment')) { ntr = createElementFromHTML(` - + ${isSplit ? ` diff --git a/web_src/js/modules/fomantic/base.ts b/web_src/js/modules/fomantic/base.ts index 59996b1156..a227d8123a 100644 --- a/web_src/js/modules/fomantic/base.ts +++ b/web_src/js/modules/fomantic/base.ts @@ -14,4 +14,7 @@ export function linkLabelAndInput(label: Element, input: Element) { } } -export const fomanticQuery = $; +export function fomanticQuery(s: string | Element | NodeListOf): ReturnType { + // intentionally make it only work for query selector, it isn't used for creating HTML elements (for safety) + return typeof s === 'string' ? $(document).find(s) : $(s); +} diff --git a/web_src/js/utils.ts b/web_src/js/utils.ts index 5e2f4d5106..c3db28c0e2 100644 --- a/web_src/js/utils.ts +++ b/web_src/js/utils.ts @@ -35,7 +35,12 @@ export function isDarkTheme(): boolean { /** strip from a string */ export function stripTags(text: string): string { - return text.replace(/<[^>]*>?/g, ''); + let prev = ''; + while (prev !== text) { + prev = text; + text = text.replace(/<[^>]*>?/g, ''); + } + return text; } export function parseIssueHref(href: string): IssuePathInfo { From 17c8aa65875443d1e6096a5f488976ecc25c3b56 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 3 Oct 2025 15:16:17 -0700 Subject: [PATCH 06/74] Add rebase push display wrong comments bug (#35560) Fix #35518 --------- Co-authored-by: wxiaoguang --- models/fixtures/branch.yml | 12 ++ routers/web/repo/pull.go | 19 ++- services/pull/comment.go | 1 + services/pull/pull.go | 11 ++ .../git_helper_for_declarative_test.go | 22 ++-- tests/integration/git_push_test.go | 8 +- tests/integration/pull_comment_test.go | 109 ++++++++++++++++++ tests/integration/pull_create_test.go | 16 +-- 8 files changed, 177 insertions(+), 21 deletions(-) create mode 100644 tests/integration/pull_comment_test.go diff --git a/models/fixtures/branch.yml b/models/fixtures/branch.yml index 03e21d04b4..717230149b 100644 --- a/models/fixtures/branch.yml +++ b/models/fixtures/branch.yml @@ -213,3 +213,15 @@ is_deleted: false deleted_by_id: 0 deleted_unix: 0 + +- + id: 26 + repo_id: 10 + name: 'feature/1' + commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d' + commit_message: 'Initial commit' + commit_time: 1489950479 + pusher_id: 2 + is_deleted: false + deleted_by_id: 0 + deleted_unix: 0 diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 7970c92ebb..22e7cefe4a 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -1583,7 +1583,16 @@ func UpdatePullRequestTarget(ctx *context.Context) { } if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.Doer, targetBranch); err != nil { - if issues_model.IsErrPullRequestAlreadyExists(err) { + switch { + case git_model.IsErrBranchNotExist(err): + errorMessage := ctx.Tr("form.target_branch_not_exist") + + ctx.Flash.Error(errorMessage) + ctx.JSON(http.StatusBadRequest, map[string]any{ + "error": err.Error(), + "user_error": errorMessage, + }) + case issues_model.IsErrPullRequestAlreadyExists(err): err := err.(issues_model.ErrPullRequestAlreadyExists) RepoRelPath := ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name @@ -1594,7 +1603,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { "error": err.Error(), "user_error": errorMessage, }) - } else if issues_model.IsErrIssueIsClosed(err) { + case issues_model.IsErrIssueIsClosed(err): errorMessage := ctx.Tr("repo.pulls.is_closed") ctx.Flash.Error(errorMessage) @@ -1602,7 +1611,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { "error": err.Error(), "user_error": errorMessage, }) - } else if pull_service.IsErrPullRequestHasMerged(err) { + case pull_service.IsErrPullRequestHasMerged(err): errorMessage := ctx.Tr("repo.pulls.has_merged") ctx.Flash.Error(errorMessage) @@ -1610,7 +1619,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { "error": err.Error(), "user_error": errorMessage, }) - } else if git_model.IsErrBranchesEqual(err) { + case git_model.IsErrBranchesEqual(err): errorMessage := ctx.Tr("repo.pulls.nothing_to_compare") ctx.Flash.Error(errorMessage) @@ -1618,7 +1627,7 @@ func UpdatePullRequestTarget(ctx *context.Context) { "error": err.Error(), "user_error": errorMessage, }) - } else { + default: ctx.ServerError("UpdatePullRequestTarget", err) } return diff --git a/services/pull/comment.go b/services/pull/comment.go index f12edaf032..ca156d3d92 100644 --- a/services/pull/comment.go +++ b/services/pull/comment.go @@ -63,6 +63,7 @@ func CreatePushPullComment(ctx context.Context, pusher *user_model.User, pr *iss var data issues_model.PushActionContent if opts.IsForcePush { data.CommitIDs = []string{oldCommitID, newCommitID} + data.IsForcePush = true } else { data.CommitIDs, err = getCommitIDsFromRepo(ctx, pr.BaseRepo, oldCommitID, newCommitID, pr.BaseBranch) if err != nil { diff --git a/services/pull/pull.go b/services/pull/pull.go index 7bf13733b2..17349bb360 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -243,6 +243,17 @@ func ChangeTargetBranch(ctx context.Context, pr *issues_model.PullRequest, doer } } + exist, err := git_model.IsBranchExist(ctx, pr.BaseRepoID, targetBranch) + if err != nil { + return err + } + if !exist { + return git_model.ErrBranchNotExist{ + RepoID: pr.BaseRepoID, + BranchName: targetBranch, + } + } + // Check if branches are equal branchesEqual, err := IsHeadEqualWithBranch(ctx, pr, targetBranch) if err != nil { diff --git a/tests/integration/git_helper_for_declarative_test.go b/tests/integration/git_helper_for_declarative_test.go index 91c30f7278..45c755582e 100644 --- a/tests/integration/git_helper_for_declarative_test.go +++ b/tests/integration/git_helper_for_declarative_test.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func withKeyFile(t *testing.T, keyname string, callback func(string)) { @@ -160,20 +161,27 @@ func doGitPushTestRepositoryFail(dstPath string, args ...string) func(*testing.T } } -func doGitAddSomeCommits(dstPath, branch string) func(*testing.T) { - return func(t *testing.T) { - doGitCheckoutBranch(dstPath, branch)(t) +type localGitAddCommitOptions struct { + LocalRepoPath string + CheckoutBranch string + TreeFilePath string + TreeFileContent string +} - assert.NoError(t, os.WriteFile(filepath.Join(dstPath, fmt.Sprintf("file-%s.txt", branch)), []byte("file "+branch), 0o644)) - assert.NoError(t, git.AddChanges(t.Context(), dstPath, true)) +func doGitCheckoutWriteFileCommit(opts localGitAddCommitOptions) func(*testing.T) { + return func(t *testing.T) { + doGitCheckoutBranch(opts.LocalRepoPath, opts.CheckoutBranch)(t) + localFilePath := filepath.Join(opts.LocalRepoPath, opts.TreeFilePath) + require.NoError(t, os.WriteFile(localFilePath, []byte(opts.TreeFileContent), 0o644)) + require.NoError(t, git.AddChanges(t.Context(), opts.LocalRepoPath, true)) signature := git.Signature{ Email: "test@test.test", Name: "test", } - assert.NoError(t, git.CommitChanges(t.Context(), dstPath, git.CommitChangesOptions{ + require.NoError(t, git.CommitChanges(t.Context(), opts.LocalRepoPath, git.CommitChangesOptions{ Committer: &signature, Author: &signature, - Message: "update " + branch, + Message: fmt.Sprintf("update %s @ %s", opts.TreeFilePath, opts.CheckoutBranch), })) } } diff --git a/tests/integration/git_push_test.go b/tests/integration/git_push_test.go index b02387c3b9..a51bf5730f 100644 --- a/tests/integration/git_push_test.go +++ b/tests/integration/git_push_test.go @@ -58,8 +58,12 @@ func testGitPush(t *testing.T, u *url.URL) { for i := range 5 { branchName := fmt.Sprintf("branch-%d", i) pushed = append(pushed, branchName) - - doGitAddSomeCommits(gitPath, branchName)(t) + doGitCheckoutWriteFileCommit(localGitAddCommitOptions{ + LocalRepoPath: gitPath, + CheckoutBranch: branchName, + TreeFilePath: fmt.Sprintf("file-%s.txt", branchName), + TreeFileContent: "file " + branchName, + })(t) } for i := 5; i < 10; i++ { diff --git a/tests/integration/pull_comment_test.go b/tests/integration/pull_comment_test.go new file mode 100644 index 0000000000..abab65247b --- /dev/null +++ b/tests/integration/pull_comment_test.go @@ -0,0 +1,109 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "fmt" + "net/http" + "net/url" + "os" + "testing" + "time" + + issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/unittest" + issues_service "code.gitea.io/gitea/services/issue" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func testWaitForPullRequestStatus(t *testing.T, prIssue *issues_model.Issue, expectedStatus issues_model.PullRequestStatus) (retIssue *issues_model.Issue) { + require.Eventually(t, func() bool { + prIssueCond := *prIssue + retIssue = unittest.AssertExistsAndLoadBean(t, &prIssueCond) + require.NoError(t, retIssue.LoadPullRequest(t.Context())) + return retIssue.PullRequest.Status == expectedStatus + }, 5*time.Second, 20*time.Millisecond) + return retIssue +} + +func testPullCommentRebase(t *testing.T, u *url.URL, session *TestSession) { + testPRTitle := "Test PR for rebase comment" + // make a change on forked branch + testEditFile(t, session, "user1", "repo1", "test-branch/rebase", "README.md", "Hello, World (Edited)\n") + testPullCreate(t, session, "user1", "repo1", false, "test-branch/rebase", "test-branch/rebase", testPRTitle) + // create a conflict on base repo branch + testEditFile(t, session, "user2", "repo1", "test-branch/rebase", "README.md", "Hello, World (Edited Conflicted)\n") + + // Now the pull request status should be conflicted + testWaitForPullRequestStatus(t, &issues_model.Issue{Title: testPRTitle}, issues_model.PullRequestStatusConflict) + + dstPath := t.TempDir() + u.Path = "/user2/repo1.git" + doGitClone(dstPath, u)(t) + doGitCheckoutBranch(dstPath, "test-branch/rebase")(t) + doGitCreateBranch(dstPath, "local-branch/rebase")(t) + content, _ := os.ReadFile(dstPath + "/README.md") + require.Equal(t, "Hello, World (Edited Conflicted)\n", string(content)) + + doGitCheckoutWriteFileCommit(localGitAddCommitOptions{ + LocalRepoPath: dstPath, + CheckoutBranch: "local-branch/rebase", + TreeFilePath: "README.md", + TreeFileContent: "Hello, World (Edited Conflict Resolved)\n", + })(t) + + // do force push + u.Path = "/user1/repo1.git" + u.User = url.UserPassword("user1", userPassword) + doGitAddRemote(dstPath, "base-repo", u)(t) + doGitPushTestRepositoryFail(dstPath, "base-repo", "local-branch/rebase:test-branch/rebase")(t) + doGitPushTestRepository(dstPath, "--force", "base-repo", "local-branch/rebase:test-branch/rebase")(t) + + // reload the pr + prIssue := testWaitForPullRequestStatus(t, &issues_model.Issue{Title: testPRTitle}, issues_model.PullRequestStatusMergeable) + comments, err := issues_model.FindComments(t.Context(), &issues_model.FindCommentsOptions{ + IssueID: prIssue.ID, + Type: issues_model.CommentTypeUndefined, // get all comments type + }) + require.NoError(t, err) + lastComment := comments[len(comments)-1] + assert.NoError(t, issues_service.LoadCommentPushCommits(t.Context(), lastComment)) + assert.True(t, lastComment.IsForcePush) +} + +func testPullCommentRetarget(t *testing.T, u *url.URL, session *TestSession) { + testPRTitle := "Test PR for retarget comment" + // keep a non-conflict branch + testCreateBranch(t, session, "user2", "repo1", "branch/test-branch/retarget", "test-branch/retarget-no-conflict", http.StatusSeeOther) + // make a change on forked branch + testEditFile(t, session, "user1", "repo1", "test-branch/retarget", "README.md", "Hello, World (Edited)\n") + testPullCreate(t, session, "user1", "repo1", false, "test-branch/retarget", "test-branch/retarget", testPRTitle) + // create a conflict line on user2/repo1 README.md + testEditFile(t, session, "user2", "repo1", "test-branch/retarget", "README.md", "Hello, World (Edited Conflicted)\n") + + // Now the pull request status should be conflicted + prIssue := testWaitForPullRequestStatus(t, &issues_model.Issue{Title: testPRTitle}, issues_model.PullRequestStatusConflict) + + // do retarget + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/user2/repo1/pull/%d/target_branch", prIssue.PullRequest.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "target_branch": "test-branch/retarget-no-conflict", + }) + session.MakeRequest(t, req, http.StatusOK) + testWaitForPullRequestStatus(t, &issues_model.Issue{Title: testPRTitle}, issues_model.PullRequestStatusMergeable) +} + +func TestPullComment(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + session := loginUser(t, "user1") + testCreateBranch(t, session, "user2", "repo1", "branch/master", "test-branch/rebase", http.StatusSeeOther) + testCreateBranch(t, session, "user2", "repo1", "branch/master", "test-branch/retarget", http.StatusSeeOther) + testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "") + + t.Run("RebaseComment", func(t *testing.T) { testPullCommentRebase(t, u, session) }) + t.Run("RetargetComment", func(t *testing.T) { testPullCommentRetarget(t, u, session) }) + }) +} diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go index 18f7e80e82..2eb5e94cf9 100644 --- a/tests/integration/pull_create_test.go +++ b/tests/integration/pull_create_test.go @@ -260,14 +260,16 @@ func TestCreateAgitPullWithReadPermission(t *testing.T) { u.Path = "user2/repo1.git" u.User = url.UserPassword("user4", userPassword) - t.Run("Clone", doGitClone(dstPath, u)) + doGitClone(dstPath, u)(t) + doGitCheckoutWriteFileCommit(localGitAddCommitOptions{ + LocalRepoPath: dstPath, + CheckoutBranch: "master", + TreeFilePath: "new-file-for-agit.txt", + TreeFileContent: "temp content", + })(t) - t.Run("add commit", doGitAddSomeCommits(dstPath, "master")) - - t.Run("do agit pull create", func(t *testing.T) { - err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+"test-topic").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) - assert.NoError(t, err) - }) + err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+"test-topic").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) + assert.NoError(t, err) }) } From 6589326e967cfb0f1898d5ea6c9c95629d1b510f Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 4 Oct 2025 00:25:09 +0200 Subject: [PATCH 07/74] Use bundled version of spectral (#35573) To reduce the risk of npm supply chain attacks and to speed up dependency installation, I've [bundled](https://github.com/silverwind/spectral-cli-bundle) the spectral package into a zero-dependency module. The upstream package is pretty dead currently, so I expect to keep up with their updates. The package [exports](https://github.com/silverwind/spectral-cli-bundle/blob/de05948c53a0a6f9690cdf65d35c3fc3324a583c/package.json#L9) a `spectral` bin script, so `pnpm exec spectral` continues to work as-is. In total, this removes 86 dependencies from the npm dependency tree. --- package.json | 2 +- pnpm-lock.yaml | 827 +------------------------------------------------ 2 files changed, 15 insertions(+), 814 deletions(-) diff --git a/package.json b/package.json index b88d99cc80..e8e6f63eeb 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", "@playwright/test": "1.55.1", - "@stoplight/spectral-cli": "6.15.0", "@stylistic/eslint-plugin": "5.4.0", "@stylistic/stylelint-plugin": "4.0.0", "@types/codemirror": "5.60.16", @@ -102,6 +101,7 @@ "material-icon-theme": "5.27.0", "nolyfill": "1.0.44", "postcss-html": "1.8.0", + "spectral-cli-bundle": "1.0.3", "stylelint": "16.24.0", "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index deb1db6867..376d70c506 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -204,9 +204,6 @@ importers: '@playwright/test': specifier: 1.55.1 version: 1.55.1 - '@stoplight/spectral-cli': - specifier: 6.15.0 - version: 6.15.0 '@stylistic/eslint-plugin': specifier: 5.4.0 version: 5.4.0(eslint@9.36.0(jiti@2.6.1)) @@ -309,6 +306,9 @@ importers: postcss-html: specifier: 1.8.0 version: 1.8.0 + spectral-cli-bundle: + specifier: 1.0.3 + version: 1.0.3 stylelint: specifier: 16.24.0 version: 16.24.0(typescript@5.9.3) @@ -355,9 +355,6 @@ packages: '@antfu/utils@9.2.1': resolution: {integrity: sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg==} - '@asyncapi/specs@6.10.0': - resolution: {integrity: sha512-vB5oKLsdrLUORIZ5BXortZTlVyGWWMC1Nud/0LtgxQ3Yn2738HigAD6EVqScvpPsDUI/bcLVsYEXN4dtXQHVng==} - '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -778,24 +775,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jsep-plugin/assignment@1.3.0': - resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - - '@jsep-plugin/regex@1.0.4': - resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - - '@jsep-plugin/ternary@1.1.4': - resolution: {integrity: sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - '@keyv/bigmap@1.0.2': resolution: {integrity: sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA==} engines: {node: '>= 18'} @@ -846,10 +825,6 @@ packages: resolution: {integrity: sha512-P6OsaEUrpBJ9NdNekFDQVM9LOFHPDKSJzwOWRBaC6LqREX+4lkZT2Q+to78R6aG6atuOQsxBVqPjMGCKjWdvyQ==} engines: {node: '>=12.4.0'} - '@nolyfill/es-aggregate-error@1.0.44': - resolution: {integrity: sha512-NBXDS4gpOiK4csFDGjqAF0WVKAMsqq/2ZU+/z+q+Mmvpr6CIrwKC/X+EbMpalEOZYT8kSTaCMVDUcXTDeMYOLw==} - engines: {node: '>=12.4.0'} - '@nolyfill/hasown@1.0.44': resolution: {integrity: sha512-GA/21lkTr2PAQuT6jGnhLuBD5IFd/AEhBXJ/tf33+/bVxPxg+5ejKx9jGQGnyV/P0eSmdup5E+s8b2HL6lOrwQ==} engines: {node: '>=12.4.0'} @@ -923,18 +898,6 @@ packages: '@rolldown/pluginutils@1.0.0-beta.29': resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} - '@rollup/plugin-commonjs@22.0.2': - resolution: {integrity: sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==} - engines: {node: '>= 12.0.0'} - peerDependencies: - rollup: ^2.68.0 - - '@rollup/pluginutils@3.1.0': - resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} - engines: {node: '>= 8.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0 - '@rollup/rollup-android-arm-eabi@4.52.3': resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==} cpu: [arm] @@ -1061,103 +1024,6 @@ packages: '@simonwep/pickr@1.9.0': resolution: {integrity: sha512-oEYvv15PyfZzjoAzvXYt3UyNGwzsrpFxLaZKzkOSd0WYBVwLd19iJerePDONxC1iF6+DpcswPdLIM2KzCJuYFg==} - '@stoplight/better-ajv-errors@1.0.3': - resolution: {integrity: sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==} - engines: {node: ^12.20 || >= 14.13} - peerDependencies: - ajv: '>=8' - - '@stoplight/json-ref-readers@1.2.2': - resolution: {integrity: sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ==} - engines: {node: '>=8.3.0'} - - '@stoplight/json-ref-resolver@3.1.6': - resolution: {integrity: sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==} - engines: {node: '>=8.3.0'} - - '@stoplight/json@3.21.7': - resolution: {integrity: sha512-xcJXgKFqv/uCEgtGlPxy3tPA+4I+ZI4vAuMJ885+ThkTHFVkC+0Fm58lA9NlsyjnkpxFh4YiQWpH+KefHdbA0A==} - engines: {node: '>=8.3.0'} - - '@stoplight/ordered-object-literal@1.0.5': - resolution: {integrity: sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg==} - engines: {node: '>=8'} - - '@stoplight/path@1.3.2': - resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==} - engines: {node: '>=8'} - - '@stoplight/spectral-cli@6.15.0': - resolution: {integrity: sha512-FVeQIuqQQnnLfa8vy+oatTKUve7uU+3SaaAfdjpX/B+uB1NcfkKRJYhKT9wMEehDRaMPL5AKIRYMCFerdEbIpw==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - hasBin: true - - '@stoplight/spectral-core@1.20.0': - resolution: {integrity: sha512-5hBP81nCC1zn1hJXL/uxPNRKNcB+/pEIHgCjPRpl/w/qy9yC9ver04tw1W0l/PMiv0UeB5dYgozXVQ4j5a6QQQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-formats@1.8.2': - resolution: {integrity: sha512-c06HB+rOKfe7tuxg0IdKDEA5XnjL2vrn/m/OVIIxtINtBzphZrOgtRn7epQ5bQF5SWp84Ue7UJWaGgDwVngMFw==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-formatters@1.5.0': - resolution: {integrity: sha512-lR7s41Z00Mf8TdXBBZQ3oi2uR8wqAtR6NO0KA8Ltk4FSpmAy0i6CKUmJG9hZQjanTnGmwpQkT/WP66p1GY3iXA==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-functions@1.10.1': - resolution: {integrity: sha512-obu8ZfoHxELOapfGsCJixKZXZcffjg+lSoNuttpmUFuDzVLT3VmH8QkPXfOGOL5Pz80BR35ClNAToDkdnYIURg==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-parsers@1.0.5': - resolution: {integrity: sha512-ANDTp2IHWGvsQDAY85/jQi9ZrF4mRrA5bciNHX+PUxPr4DwS6iv4h+FVWJMVwcEYdpyoIdyL+SRmHdJfQEPmwQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-ref-resolver@1.0.5': - resolution: {integrity: sha512-gj3TieX5a9zMW29z3mBlAtDOCgN3GEc1VgZnCVlr5irmR4Qi5LuECuFItAq4pTn5Zu+sW5bqutsCH7D4PkpyAA==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-ruleset-bundler@1.6.3': - resolution: {integrity: sha512-AQFRO6OCKg8SZJUupnr3+OzI1LrMieDTEUHsYgmaRpNiDRPvzImE3bzM1KyQg99q58kTQyZ8kpr7sG8Lp94RRA==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-ruleset-migrator@1.11.2': - resolution: {integrity: sha512-6r5i4hrDmppspSSxdUKKNHc07NGSSIkvwKNk3M5ukCwvSslImvDEimeWAhPBryhmSJ82YAsKr8erZZpKullxWw==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-rulesets@1.22.0': - resolution: {integrity: sha512-l2EY2jiKKLsvnPfGy+pXC0LeGsbJzcQP5G/AojHgf+cwN//VYxW1Wvv4WKFx/CLmLxc42mJYF2juwWofjWYNIQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-runtime@1.1.4': - resolution: {integrity: sha512-YHbhX3dqW0do6DhiPSgSGQzr6yQLlWybhKwWx0cqxjMwxej3TqLv3BXMfIUYFKKUqIwH4Q2mV8rrMM8qD2N0rQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/types@13.20.0': - resolution: {integrity: sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA==} - engines: {node: ^12.20 || >=14.13} - - '@stoplight/types@13.6.0': - resolution: {integrity: sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==} - engines: {node: ^12.20 || >=14.13} - - '@stoplight/types@14.1.1': - resolution: {integrity: sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g==} - engines: {node: ^12.20 || >=14.13} - - '@stoplight/yaml-ast-parser@0.0.48': - resolution: {integrity: sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==} - - '@stoplight/yaml-ast-parser@0.0.50': - resolution: {integrity: sha512-Pb6M8TDO9DtSVla9yXSTAxmo9GVEouq5P40DWXdOie69bXogZTkgvopCq+yEvTMA0F6PEvdJmbtTV3ccIp11VQ==} - - '@stoplight/yaml@4.2.3': - resolution: {integrity: sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==} - engines: {node: '>=10.8'} - - '@stoplight/yaml@4.3.0': - resolution: {integrity: sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w==} - engines: {node: '>=10.8'} - '@stylistic/eslint-plugin@5.4.0': resolution: {integrity: sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1289,18 +1155,12 @@ packages: '@types/dropzone@5.7.9': resolution: {integrity: sha512-c6IlUz+DeQ4gANzJKn8fdP5rO6UyDNOyWLjfPbDRUHCNsXaAVKQOpuOv6LWEyvaK7pLqmoIpvSIlvBgGsk1vGw==} - '@types/es-aggregate-error@1.0.6': - resolution: {integrity: sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg==} - '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} '@types/eslint@9.6.1': resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - '@types/estree@0.0.39': - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -1322,9 +1182,6 @@ packages: '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} - '@types/markdown-escape@1.1.3': - resolution: {integrity: sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw==} - '@types/marked@4.3.2': resolution: {integrity: sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==} @@ -1340,9 +1197,6 @@ packages: '@types/pdfobject@2.2.5': resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==} - '@types/sarif@2.1.7': - resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} - '@types/sizzle@2.3.10': resolution: {integrity: sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww==} @@ -1373,9 +1227,6 @@ packages: '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/urijs@1.19.25': - resolution: {integrity: sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==} - '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -1703,10 +1554,6 @@ packages: '@xtuc/long@4.2.2': resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - acorn-import-phases@1.0.4: resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} engines: {node: '>=10.13.0'} @@ -1732,19 +1579,6 @@ packages: webpack: optional: true - ajv-draft-04@1.0.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv-errors@3.0.0: - resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==} - peerDependencies: - ajv: ^8.0.1 - ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -1811,9 +1645,6 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - as-table@1.0.55: - resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} - asciinema-player@3.10.0: resolution: {integrity: sha512-shoOK6F606nDKZxDVM7JuGSCAyWLePoGRFNlV+FqiP5Sqvyn0BlE7wlbjZyd2X4P1iRhv/HKfVNtnQIxmgphRA==} @@ -1824,18 +1655,10 @@ packages: ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} - ast-types@0.14.2: - resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} - engines: {node: '>=4'} - astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} - astring@1.9.0: - resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} - hasBin: true - atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -1901,9 +1724,6 @@ packages: resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} engines: {node: '>=18.20'} - builtins@1.0.3: - resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} - bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1999,13 +1819,6 @@ packages: clippie@4.1.8: resolution: {integrity: sha512-GCDd4xnYPqohYPgPN/vbljc3QHD3P2Wsos6RO68ab3Ja6a7IDocXzbsIKXqwrNnK3cR31nog3A5Cyf+8GYc/Dg==} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} engines: {node: '>=6'} @@ -2060,9 +1873,6 @@ packages: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -2305,9 +2115,6 @@ packages: damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - data-uri-to-buffer@2.0.2: - resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} - dayjs@1.11.18: resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} @@ -2353,10 +2160,6 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} - dependency-graph@0.11.0: - resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} - engines: {node: '>= 0.6.0'} - dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2710,9 +2513,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-walker@1.0.1: - resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -2723,10 +2523,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - eventemitter3@2.0.3: resolution: {integrity: sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==} @@ -2747,10 +2543,6 @@ packages: fast-diff@1.3.0: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -2761,9 +2553,6 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-memoize@2.5.2: - resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} - fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} @@ -2830,10 +2619,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2850,10 +2635,6 @@ packages: functional-red-black-tree@1.0.1: resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.4.0: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} @@ -2862,9 +2643,6 @@ packages: resolution: {integrity: sha512-YCmOj+4YAeEB5Dd9jfp6ETdejMet4zSxXjNkgaa4npBEKRI9uDOGB5MmAdAgi2OoFGAKshYhCbmLq2DS03CgVA==} engines: {node: '>=18.0.0'} - get-source@2.0.12: - resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} - get-tsconfig@4.10.1: resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} @@ -2950,10 +2728,6 @@ packages: hookified@1.12.1: resolution: {integrity: sha512-xnKGl+iMIlhrZmGHB729MqlmPoWBznctSQTYCpFKqNsCgimJQmithcW0xSQMMFzYnV2iKUh25alswn6epgxS0Q==} - hpagent@1.2.0: - resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} - engines: {node: '>=14'} - html-tags@3.3.1: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} @@ -2988,9 +2762,6 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} - immer@9.0.21: - resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -3105,9 +2876,6 @@ packages: resolution: {integrity: sha512-S8xSxNMGJO4eZD86kO46zrq2gLIhA+rN9443lQEvt8Mz/l8cxk72p/AWFmofY6uL9g9ILD6cXW6j8QQj4F3Hcw==} engines: {node: '>=18.0.0'} - is-reference@1.2.1: - resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - is-valid-element-name@1.0.0: resolution: {integrity: sha512-GZITEJY2LkSjQfaIPBha7eyZv+ge0PhBR7KITeCCWvy7VBQrCUdFkvpI+HrAPQjVtVjy1LvlEkqQTHckoszruw==} @@ -3161,10 +2929,6 @@ packages: resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} engines: {node: '>=12.0.0'} - jsep@1.4.0: - resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} - engines: {node: '>= 10.16.0'} - jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -3199,20 +2963,9 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@2.2.1: - resolution: {integrity: sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==} - jsonc-parser@3.3.1: resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - - jsonpath-plus@10.3.0: - resolution: {integrity: sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==} - engines: {node: '>=18.0.0'} - hasBin: true - jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} @@ -3272,10 +3025,6 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3328,9 +3077,6 @@ packages: lodash.sortedlastindex@4.1.0: resolution: {integrity: sha512-s8xEQdsp2Tu5zUqVdFSe9C0kR8YlnAJYLqMdkh+pIRBRxF6/apWseLdHl3/+jv2I61dhPwtI/Ff+EqvCpc+N8w==} - lodash.topath@4.5.2: - resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} - lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -3354,15 +3100,9 @@ packages: resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} engines: {node: 20 || >=22} - magic-string@0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} - markdown-escape@2.0.0: - resolution: {integrity: sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A==} - markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true @@ -3570,10 +3310,6 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - nimma@0.2.3: - resolution: {integrity: sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA==} - engines: {node: ^12.20 || >=14.13} - node-fetch@2.6.13: resolution: {integrity: sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==} engines: {node: 4.x || >=6.0.0} @@ -3595,10 +3331,6 @@ packages: node-releases@2.0.21: resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} - node-sarif-builder@2.0.3: - resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==} - engines: {node: '>=14'} - nolyfill@1.0.44: resolution: {integrity: sha512-PoggwVLiJUn0MnodpftsiC7EuknW5+6v62ntTOQ6T6l7g2r6aoaOwgk0tQW2BxGLYw9bF298LL8jDFTmEFuzlA==} engines: {node: '>=12.4.0'} @@ -3765,10 +3497,6 @@ packages: points-on-path@0.2.1: resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} - pony-cause@1.1.1: - resolution: {integrity: sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g==} - engines: {node: '>=12.0.0'} - postcss-html@1.8.0: resolution: {integrity: sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ==} engines: {node: ^12 || >=14} @@ -3893,9 +3621,6 @@ packages: engines: {node: '>=14'} hasBin: true - printable-characters@1.0.42: - resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} - prototype-properties@5.0.0: resolution: {integrity: sha512-uCWE2QqnGlwvvJXTwiHTPTyHE62+zORO5hpFWhAwBGDtEtTmNZZleNLJDoFsqHCL4p/CeAP2Q1uMKFUKALuRGQ==} engines: {node: '>=18.20'} @@ -3948,18 +3673,10 @@ packages: resolution: {integrity: sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg==} engines: {node: '>= 0.8.0'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - reserved@0.1.2: - resolution: {integrity: sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g==} - engines: {node: '>=0.8'} - resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -3987,11 +3704,6 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup@2.79.2: - resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} - engines: {node: '>=10.0.0'} - hasBin: true - rollup@4.52.3: resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -4010,9 +3722,6 @@ packages: rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - safe-stable-stringify@1.1.1: - resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} - sax@1.2.4: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} @@ -4068,10 +3777,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-eval@1.0.1: - resolution: {integrity: sha512-LH7FpTAkeD+y5xQC4fzS+tFtaNlvt3Ib1zKzvhjv/Y+cioV4zIuw4IZr2yhRLu67CWL7FR9/6KXKnjRoZTvGGQ==} - engines: {node: '>=12'} - slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -4112,10 +3817,6 @@ packages: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} - sourcemap-codec@1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead - spdx-compare@1.0.0: resolution: {integrity: sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==} @@ -4137,6 +3838,11 @@ packages: spdx-satisfies@5.0.1: resolution: {integrity: sha512-Nwor6W6gzFp8XX4neaKQ7ChV4wmpSh2sSDemMFSzHxpTw460jxFYeOn+jq4ybnSSw/5sc3pjka9MQPouksQNpw==} + spectral-cli-bundle@1.0.3: + resolution: {integrity: sha512-LUsOK0XKl/C2IhlDwBlXz+7qU2rnGbSlu8nqSFB/K+TbPjjmqoCYjG82YFJCmEHurbthvTJ8WRP735vl+3rY2Q==} + engines: {node: '>=20'} + hasBin: true + stable-hash-x@0.2.0: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} @@ -4144,9 +3850,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - stacktracey@2.1.8: - resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} - std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} @@ -4307,9 +4010,6 @@ packages: engines: {node: '>=10'} hasBin: true - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -4384,9 +4084,6 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -4428,10 +4125,6 @@ packages: undici-types@7.13.0: resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} @@ -4449,23 +4142,13 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urijs@1.19.11: - resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - utility-types@3.11.0: - resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} - engines: {node: '>= 4'} - uuid@11.1.0: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true - validate-npm-package-name@3.0.0: - resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} - vanilla-colorful@0.7.2: resolution: {integrity: sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==} @@ -4712,23 +4395,11 @@ packages: xml-reader@2.4.3: resolution: {integrity: sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA==} - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - yaml@2.8.1: resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} engines: {node: '>= 14.6'} hasBin: true - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -4744,10 +4415,6 @@ snapshots: '@antfu/utils@9.2.1': {} - '@asyncapi/specs@6.10.0': - dependencies: - '@types/json-schema': 7.0.15 - '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -5108,18 +4775,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 - - '@jsep-plugin/regex@1.0.4(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 - - '@jsep-plugin/ternary@1.1.4(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 - '@keyv/bigmap@1.0.2': dependencies: hookified: 1.12.1 @@ -5173,10 +4828,6 @@ snapshots: dependencies: '@nolyfill/shared': 1.0.44 - '@nolyfill/es-aggregate-error@1.0.44': - dependencies: - '@nolyfill/shared': 1.0.44 - '@nolyfill/hasown@1.0.44': {} '@nolyfill/is-core-module@1.0.39': {} @@ -5232,24 +4883,6 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.29': {} - '@rollup/plugin-commonjs@22.0.2(rollup@2.79.2)': - dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.2) - commondir: 1.0.1 - estree-walker: 2.0.2 - glob: 7.2.3 - is-reference: 1.2.1 - magic-string: 0.25.9 - resolve: 1.22.10 - rollup: 2.79.2 - - '@rollup/pluginutils@3.1.0(rollup@2.79.2)': - dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 2.79.2 - '@rollup/rollup-android-arm-eabi@4.52.3': optional: true @@ -5330,260 +4963,6 @@ snapshots: core-js: 3.32.2 nanopop: 2.3.0 - '@stoplight/better-ajv-errors@1.0.3(ajv@8.17.1)': - dependencies: - ajv: 8.17.1 - jsonpointer: 5.0.1 - leven: 3.1.0 - - '@stoplight/json-ref-readers@1.2.2': - dependencies: - node-fetch: 2.7.0 - tslib: 1.14.1 - transitivePeerDependencies: - - encoding - - '@stoplight/json-ref-resolver@3.1.6': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.20.0 - '@types/urijs': 1.19.25 - dependency-graph: 0.11.0 - fast-memoize: 2.5.2 - immer: 9.0.21 - lodash: 4.17.21 - tslib: 2.8.1 - urijs: 1.19.11 - - '@stoplight/json@3.21.7': - dependencies: - '@stoplight/ordered-object-literal': 1.0.5 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.20.0 - jsonc-parser: 2.2.1 - lodash: 4.17.21 - safe-stable-stringify: 1.1.1 - - '@stoplight/ordered-object-literal@1.0.5': {} - - '@stoplight/path@1.3.2': {} - - '@stoplight/spectral-cli@6.15.0': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formatters': 1.5.0 - '@stoplight/spectral-parsers': 1.0.5 - '@stoplight/spectral-ref-resolver': 1.0.5 - '@stoplight/spectral-ruleset-bundler': 1.6.3 - '@stoplight/spectral-ruleset-migrator': 1.11.2 - '@stoplight/spectral-rulesets': 1.22.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - chalk: 4.1.2 - fast-glob: 3.2.12 - hpagent: 1.2.0 - lodash: 4.17.21 - pony-cause: 1.1.1 - stacktracey: 2.1.8 - tslib: 2.8.1 - yargs: 17.7.2 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-core@1.20.0': - dependencies: - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-parsers': 1.0.5 - '@stoplight/spectral-ref-resolver': 1.0.5 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.6.0 - '@types/es-aggregate-error': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-errors: 3.0.0(ajv@8.17.1) - ajv-formats: 2.1.1(ajv@8.17.1) - es-aggregate-error: '@nolyfill/es-aggregate-error@1.0.44' - jsonpath-plus: 10.3.0 - lodash: 4.17.21 - lodash.topath: 4.5.2 - minimatch: 3.1.2 - nimma: 0.2.3 - pony-cause: 1.1.1 - simple-eval: 1.0.1 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-formats@1.8.2': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@types/json-schema': 7.0.15 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-formatters@1.5.0': - dependencies: - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/markdown-escape': 1.1.3 - chalk: 4.1.2 - cliui: 7.0.4 - lodash: 4.17.21 - markdown-escape: 2.0.0 - node-sarif-builder: 2.0.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-functions@1.10.1': - dependencies: - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-runtime': 1.1.4 - ajv: 8.17.1 - ajv-draft-04: 1.0.0(ajv@8.17.1) - ajv-errors: 3.0.0(ajv@8.17.1) - ajv-formats: 2.1.1(ajv@8.17.1) - lodash: 4.17.21 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-parsers@1.0.5': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/types': 14.1.1 - '@stoplight/yaml': 4.3.0 - tslib: 2.8.1 - - '@stoplight/spectral-ref-resolver@1.0.5': - dependencies: - '@stoplight/json-ref-readers': 1.2.2 - '@stoplight/json-ref-resolver': 3.1.6 - '@stoplight/spectral-runtime': 1.1.4 - dependency-graph: 0.11.0 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-ruleset-bundler@1.6.3': - dependencies: - '@rollup/plugin-commonjs': 22.0.2(rollup@2.79.2) - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-parsers': 1.0.5 - '@stoplight/spectral-ref-resolver': 1.0.5 - '@stoplight/spectral-ruleset-migrator': 1.11.2 - '@stoplight/spectral-rulesets': 1.22.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/node': 24.6.2 - pony-cause: 1.1.1 - rollup: 2.79.2 - tslib: 2.8.1 - validate-npm-package-name: 3.0.0 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-ruleset-migrator@1.11.2': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/ordered-object-literal': 1.0.5 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@stoplight/yaml': 4.2.3 - '@types/node': 24.6.2 - ajv: 8.17.1 - ast-types: 0.14.2 - astring: 1.9.0 - reserved: 0.1.2 - tslib: 2.8.1 - validate-npm-package-name: 3.0.0 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-rulesets@1.22.0': - dependencies: - '@asyncapi/specs': 6.10.0 - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - json-schema-traverse: 1.0.0 - leven: 3.1.0 - lodash: 4.17.21 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-runtime@1.1.4': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.20.0 - abort-controller: 3.0.0 - lodash: 4.17.21 - node-fetch: 2.7.0 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/types@13.20.0': - dependencies: - '@types/json-schema': 7.0.15 - utility-types: 3.11.0 - - '@stoplight/types@13.6.0': - dependencies: - '@types/json-schema': 7.0.15 - utility-types: 3.11.0 - - '@stoplight/types@14.1.1': - dependencies: - '@types/json-schema': 7.0.15 - utility-types: 3.11.0 - - '@stoplight/yaml-ast-parser@0.0.48': {} - - '@stoplight/yaml-ast-parser@0.0.50': {} - - '@stoplight/yaml@4.2.3': - dependencies: - '@stoplight/ordered-object-literal': 1.0.5 - '@stoplight/types': 13.20.0 - '@stoplight/yaml-ast-parser': 0.0.48 - tslib: 2.8.1 - - '@stoplight/yaml@4.3.0': - dependencies: - '@stoplight/ordered-object-literal': 1.0.5 - '@stoplight/types': 14.1.1 - '@stoplight/yaml-ast-parser': 0.0.50 - tslib: 2.8.1 - '@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1))': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) @@ -5760,10 +5139,6 @@ snapshots: dependencies: '@types/jquery': 3.5.33 - '@types/es-aggregate-error@1.0.6': - dependencies: - '@types/node': 24.6.2 - '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -5774,8 +5149,6 @@ snapshots: '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 - '@types/estree@0.0.39': {} - '@types/estree@1.0.8': {} '@types/geojson@7946.0.16': {} @@ -5792,8 +5165,6 @@ snapshots: '@types/katex@0.16.7': {} - '@types/markdown-escape@1.1.3': {} - '@types/marked@4.3.2': {} '@types/ms@2.1.0': {} @@ -5808,8 +5179,6 @@ snapshots: '@types/pdfobject@2.2.5': {} - '@types/sarif@2.1.7': {} - '@types/sizzle@2.3.10': {} '@types/sortablejs@1.15.8': {} @@ -5833,8 +5202,6 @@ snapshots: '@types/unist@2.0.11': {} - '@types/urijs@1.19.25': {} - '@types/whatwg-mimetype@3.0.2': {} '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': @@ -6221,10 +5588,6 @@ snapshots: '@xtuc/long@4.2.2': {} - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - acorn-import-phases@1.0.4(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -6239,14 +5602,6 @@ snapshots: optionalDependencies: webpack: 5.102.0(webpack-cli@6.0.1) - ajv-draft-04@1.0.0(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv-errors@3.0.0(ajv@8.17.1): - dependencies: - ajv: 8.17.1 - ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -6301,10 +5656,6 @@ snapshots: array-union@2.1.0: {} - as-table@1.0.55: - dependencies: - printable-characters: 1.0.42 - asciinema-player@3.10.0: dependencies: '@babel/runtime': 7.28.4 @@ -6314,14 +5665,8 @@ snapshots: ast-types-flow@0.0.8: {} - ast-types@0.14.2: - dependencies: - tslib: 2.8.1 - astral-regex@2.0.0: {} - astring@1.9.0: {} - atob@2.1.2: {} axe-core@4.10.3: {} @@ -6374,8 +5719,6 @@ snapshots: builtin-modules@5.0.0: {} - builtins@1.0.3: {} - bytes@3.1.2: {} cac@6.7.14: {} @@ -6472,18 +5815,6 @@ snapshots: clippie@4.1.8: {} - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clone-deep@4.0.1: dependencies: is-plain-object: 2.0.4 @@ -6522,8 +5853,6 @@ snapshots: comment-parser@1.4.1: {} - commondir@1.0.1: {} - concat-map@0.0.1: {} confbox@0.1.8: {} @@ -6796,8 +6125,6 @@ snapshots: damerau-levenshtein@1.0.8: {} - data-uri-to-buffer@2.0.2: {} - dayjs@1.11.18: {} debug@3.2.7: @@ -6829,8 +6156,6 @@ snapshots: dependencies: robust-predicates: 3.0.2 - dependency-graph@0.11.0: {} - dequal@2.0.3: {} devlop@1.1.0: @@ -7317,8 +6642,6 @@ snapshots: estraverse@5.3.0: {} - estree-walker@1.0.1: {} - estree-walker@2.0.2: {} estree-walker@3.0.3: @@ -7327,8 +6650,6 @@ snapshots: esutils@2.0.3: {} - event-target-shim@5.0.1: {} - eventemitter3@2.0.3: {} events@3.3.0: {} @@ -7341,14 +6662,6 @@ snapshots: fast-diff@1.3.0: {} - fast-glob@3.2.12: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7361,8 +6674,6 @@ snapshots: fast-levenshtein@2.0.6: {} - fast-memoize@2.5.2: {} - fast-uri@3.1.0: {} fastest-levenshtein@1.0.16: {} @@ -7427,12 +6738,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - fs.realpath@1.0.0: {} fsevents@2.3.2: @@ -7443,17 +6748,10 @@ snapshots: functional-red-black-tree@1.0.1: {} - get-caller-file@2.0.5: {} - get-east-asian-width@1.4.0: {} get-set-props@0.2.0: {} - get-source@2.0.12: - dependencies: - data-uri-to-buffer: 2.0.2 - source-map: 0.6.1 - get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -7546,8 +6844,6 @@ snapshots: hookified@1.12.1: {} - hpagent@1.2.0: {} - html-tags@3.3.1: {} htmlparser2@8.0.2: @@ -7575,8 +6871,6 @@ snapshots: ignore@7.0.5: {} - immer@9.0.21: {} - import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -7672,10 +6966,6 @@ snapshots: lowercase-keys: 3.0.0 prototype-properties: 5.0.0 - is-reference@1.2.1: - dependencies: - '@types/estree': 1.0.8 - is-valid-element-name@1.0.0: dependencies: is-potential-custom-element-name: 1.0.1 @@ -7720,8 +7010,6 @@ snapshots: jsdoc-type-pratt-parser@4.8.0: {} - jsep@1.4.0: {} - jsesc@3.0.2: {} jsesc@3.1.0: {} @@ -7742,22 +7030,8 @@ snapshots: json5@2.2.3: {} - jsonc-parser@2.2.1: {} - jsonc-parser@3.3.1: {} - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsonpath-plus@10.3.0: - dependencies: - '@jsep-plugin/assignment': 1.3.0(jsep@1.4.0) - '@jsep-plugin/regex': 1.0.4(jsep@1.4.0) - jsep: 1.4.0 - jsonpointer@5.0.1: {} jsx-ast-utils-x@0.1.0: {} @@ -7813,8 +7087,6 @@ snapshots: layout-base@2.0.1: {} - leven@3.1.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -7862,8 +7134,6 @@ snapshots: lodash.sortedlastindex@4.1.0: {} - lodash.topath@4.5.2: {} - lodash.truncate@4.4.2: {} lodash.upperfirst@4.3.1: {} @@ -7878,16 +7148,10 @@ snapshots: lru-cache@11.2.2: {} - magic-string@0.25.9: - dependencies: - sourcemap-codec: 1.4.8 - magic-string@0.30.19: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - markdown-escape@2.0.0: {} - markdown-it@14.1.0: dependencies: argparse: 2.0.1 @@ -8220,16 +7484,6 @@ snapshots: neo-async@2.6.2: {} - nimma@0.2.3: - dependencies: - '@jsep-plugin/regex': 1.0.4(jsep@1.4.0) - '@jsep-plugin/ternary': 1.1.4(jsep@1.4.0) - astring: 1.9.0 - jsep: 1.4.0 - optionalDependencies: - jsonpath-plus: 10.3.0 - lodash.topath: 4.5.2 - node-fetch@2.6.13: dependencies: whatwg-url: 5.0.0 @@ -8240,11 +7494,6 @@ snapshots: node-releases@2.0.21: {} - node-sarif-builder@2.0.3: - dependencies: - '@types/sarif': 2.1.7 - fs-extra: 10.1.0 - nolyfill@1.0.44: {} normalize-path@3.0.0: {} @@ -8396,8 +7645,6 @@ snapshots: path-data-parser: 0.1.0 points-on-curve: 0.2.0 - pony-cause@1.1.1: {} - postcss-html@1.8.0: dependencies: htmlparser2: 8.0.2 @@ -8511,8 +7758,6 @@ snapshots: prettier@3.6.2: {} - printable-characters@1.0.42: {} - prototype-properties@5.0.0: {} punycode.js@2.3.1: {} @@ -8556,12 +7801,8 @@ snapshots: rename-keys@1.2.0: {} - require-directory@2.1.1: {} - require-from-string@2.0.2: {} - reserved@0.1.2: {} - resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -8582,10 +7823,6 @@ snapshots: robust-predicates@3.0.2: {} - rollup@2.79.2: - optionalDependencies: - fsevents: 2.3.3 - rollup@4.52.3: dependencies: '@types/estree': 1.0.8 @@ -8634,8 +7871,6 @@ snapshots: rw@1.3.3: {} - safe-stable-stringify@1.1.1: {} - sax@1.2.4: {} sax@1.4.1: {} @@ -8681,10 +7916,6 @@ snapshots: signal-exit@4.1.0: {} - simple-eval@1.0.1: - dependencies: - jsep: 1.4.0 - slash@3.0.0: {} slice-ansi@4.0.0: @@ -8721,8 +7952,6 @@ snapshots: source-map@0.7.6: {} - sourcemap-codec@1.4.8: {} - spdx-compare@1.0.0: dependencies: array-find-index: 1.0.2 @@ -8750,15 +7979,14 @@ snapshots: spdx-expression-parse: 3.0.1 spdx-ranges: 2.1.1 + spectral-cli-bundle@1.0.3: + optionalDependencies: + fsevents: 2.3.3 + stable-hash-x@0.2.0: {} stackback@0.0.2: {} - stacktracey@2.1.8: - dependencies: - as-table: 1.0.55 - get-source: 2.0.12 - std-env@3.9.0: {} string-width@4.2.3: @@ -8988,8 +8216,6 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 - text-table@0.2.0: {} - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -9050,9 +8276,8 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tslib@1.14.1: {} - - tslib@2.8.1: {} + tslib@2.8.1: + optional: true type-check@0.4.0: dependencies: @@ -9085,8 +8310,6 @@ snapshots: undici-types@7.13.0: {} - universalify@2.0.1: {} - unrs-resolver@1.11.1: dependencies: napi-postinstall: 0.3.3 @@ -9123,18 +8346,10 @@ snapshots: dependencies: punycode: 2.3.1 - urijs@1.19.11: {} - util-deprecate@1.0.2: {} - utility-types@3.11.0: {} - uuid@11.1.0: {} - validate-npm-package-name@3.0.0: - dependencies: - builtins: 1.0.3 - vanilla-colorful@0.7.2: {} vite-node@3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): @@ -9423,20 +8638,6 @@ snapshots: eventemitter3: 2.0.3 xml-lexer: 0.2.2 - y18n@5.0.8: {} - yaml@2.8.1: {} - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - yocto-queue@0.1.0: {} From e1c2fef5939a1fc81ba4ed1ce1e1660f7a3aad2a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 3 Oct 2025 15:54:37 -0700 Subject: [PATCH 08/74] Fix creating pull request failure when the target branch name is the same as some tag (#35552) Use full reference name in the git command to avoid ambiguity. Fix #35470 --- services/pull/temp_repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 8750b4288a..09225079f5 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -139,7 +139,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) return nil, nil, fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), err, prCtx.outbuf.String(), prCtx.errbuf.String()) } - if err := gitcmd.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). + if err := gitcmd.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(git.BranchPrefix+pr.BaseBranch+":"+git.BranchPrefix+baseBranch, git.BranchPrefix+pr.BaseBranch+":"+git.BranchPrefix+"original_"+baseBranch). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr, pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() From 4e7a97dea020b6599781bc24ebe4ab5344fc1411 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sat, 4 Oct 2025 00:32:04 +0000 Subject: [PATCH 09/74] [skip ci] Updated translations via Crowdin --- options/locale/locale_cs-CZ.ini | 1 - options/locale/locale_de-DE.ini | 1 - options/locale/locale_fr-FR.ini | 1 - options/locale/locale_ga-IE.ini | 2 +- options/locale/locale_ja-JP.ini | 1 - options/locale/locale_pt-PT.ini | 1 - options/locale/locale_tr-TR.ini | 346 +++++++++++++++++++++++++++++++- options/locale/locale_zh-CN.ini | 1 - options/locale/locale_zh-TW.ini | 1 - 9 files changed, 343 insertions(+), 12 deletions(-) diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index cc92f2e626..26c1131a56 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -2228,7 +2228,6 @@ settings.event_pull_request_merge=Sloučení pull requestu settings.event_package=Balíček settings.event_package_desc=Balíček vytvořen nebo odstraněn v repozitáři. settings.branch_filter=Filtr větví -settings.branch_filter_desc=Povolené větve pro události nahrání, vytvoření větve a smazání větve jsou určeny pomocí zástupného vzoru. Pokud je prázdný nebo *, všechny události jsou ohlášeny. Podívejte se na dokumentaci syntaxe na github.com/gobwas/glob. Příklady: master, {master,release*}. settings.authorization_header=Autorizační hlavička settings.authorization_header_desc=Pokud vyplněno, bude připojeno k požadavkům jako autorizační hlavička. Příklady: %s. settings.active=Aktivní diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index dae7275f82..3613032b2d 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -2269,7 +2269,6 @@ settings.event_workflow_job_desc=Gitea Actions Workflow Job in Warteschlange, wa settings.event_package=Paket settings.event_package_desc=Paket wurde in einem Repository erstellt oder gelöscht. settings.branch_filter=Branch-Filter -settings.branch_filter_desc=Whitelist für Branches für Push-, Erzeugungs- und Löschevents, als Glob-Pattern beschrieben. Es werden Events für alle Branches gemeldet, falls das Pattern * ist, oder falls es leer ist. Siehe die %[2]s Dokumentation für die Syntax (Englisch). Beispiele: master, {master,release*}. settings.authorization_header=Authorization-Header settings.authorization_header_desc=Wird, falls vorhanden, als Authorization-Header mitgesendet. Beispiele: %s. settings.active=Aktiv diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 5814de64ca..ac25444844 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -2433,7 +2433,6 @@ settings.event_workflow_job_desc=Travaux du flux de travail Gitea Actions en fil settings.event_package=Paquet settings.event_package_desc=Paquet créé ou supprimé. settings.branch_filter=Filtre de branche -settings.branch_filter_desc=Liste de branches et motifs globs autorisant la soumission, la création et suppression de branches. Laisser vide ou utiliser * englobent toutes les branches. Voir la %[2]s. Exemples : master, {master,release*}. settings.authorization_header=En-tête « Authorization » settings.authorization_header_desc=Si présent, sera ajouté aux requêtes comme en-tête d’authentification. Exemples : %s. settings.active=Actif diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index b5b05209e5..f9801d7723 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -109,6 +109,7 @@ copy_path=Cóipeáil cosán copy_success=Cóipeáil! copy_error=Theip ar an gcóipeáil copy_type_unsupported=Ní féidir an cineál comhaid seo a chóipeáil +copy_filename=Cóipeáil ainm comhaid write=Scríobh preview=Réamhamharc @@ -2433,7 +2434,6 @@ settings.event_workflow_job_desc=Gitea Actions Sreabhadh oibre post ciúáilte, settings.event_package=Pacáiste settings.event_package_desc=Pacáiste a cruthaíodh nó a scriosadh i stóras. settings.branch_filter=Scagaire brainse -settings.branch_filter_desc=Liosta bán brainse le haghaidh brú, cruthú brainse agus imeachtaí scriosta brainse, sonraithe mar phatrún glob. Má tá sé folamh nó *, tuairiscítear imeachtaí do gach brainse. Féach %[2]s doiciméadú le haghaidh comhréire. Samplaí: máistir, {master,release*}. settings.authorization_header=Ceanntásc Údaraithe settings.authorization_header_desc=Cuirfear san áireamh mar cheanntásc údaraithe d'iarratais nuair a bheidh ann Samplaí: %s. settings.active=Gníomhach diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index f2fbce889e..9144916e45 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -2433,7 +2433,6 @@ settings.event_workflow_job_desc=Gitea Actions のワークフロージョブが settings.event_package=パッケージ settings.event_package_desc=リポジトリにパッケージが作成または削除されたとき。 settings.branch_filter=ブランチ フィルター -settings.branch_filter_desc=プッシュ、ブランチ作成、ブランチ削除のイベントを通知するブランチを、globパターンで指定するホワイトリストです。 空か*のときは、すべてのブランチのイベントを通知します。 文法については %[2]s を参照してください。 例: master{master,release*} settings.authorization_header=Authorizationヘッダー settings.authorization_header_desc=入力した場合、リクエストにAuthorizationヘッダーとして付加します。 例: %s settings.active=有効 diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 9e648b6602..f43fe03958 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -2433,7 +2433,6 @@ settings.event_workflow_job_desc=O trabalho da sequência de trabalho das opera settings.event_package=Pacote settings.event_package_desc=Pacote criado ou eliminado num repositório. settings.branch_filter=Filtro de ramos -settings.branch_filter_desc=Lista dos ramos a serem considerados nos eventos de envio e de criação e eliminação de ramos, especificada como um padrão glob. Se estiver em branco ou for *, serão reportados eventos para todos os ramos. Veja a documentação para ver os detalhes da sintaxe. Exemplos: main, {main,release*}. settings.authorization_header=Cabeçalho de Autorização settings.authorization_header_desc=Será incluído como cabeçalho de autorização para pedidos, quando estiver presente. Exemplos: %s. settings.active=Em funcionamento diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index a3ae736f67..ccc74293f5 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -85,7 +85,7 @@ ok=Tamam cancel=İptal retry=Yeniden Dene rerun=Yeniden çalıştır -rerun_all=Tüm görevleri yeniden çalıştır +rerun_all=Tüm işleri yeniden çalıştır save=Kaydet add=Ekle add_all=Tümünü Ekle @@ -109,6 +109,7 @@ copy_path=Yolu kopyala copy_success=Kopyalandı! copy_error=Kopyalama başarısız oldu copy_type_unsupported=Bu dosya türü kopyalanamaz +copy_filename=Dosya adını kopyala write=Yaz preview=Önizleme @@ -270,11 +271,16 @@ path=Yol sqlite_helper=SQLite3 veritabanı dosya yolu.
Gitea'yı servis olarak çalıştırıyorsanız tam yol adını girin. reinstall_error=Mevcut bir Gitea veritabanına yüklemeye çalışıyorsunuz reinstall_confirm_message=Mevcut bir Gitea veritabanıyla yeniden kurulum yapmak birden çok soruna neden olabilir. Çoğu durumda Gitea'yı çalıştırmak için mevcut "app.ini" dosyanızı kullanmalısınız. Ne yaptığınızı biliyorsanız, aşağıdakileri onaylayın: +reinstall_confirm_check_1=App.ini'de SECRET_KEY tarafından şifrelenen veriler kaybolabilir: kullanıcılar 2FA/OTP ile oturum açamayabilir ve yansılar düzgün çalışmayabilir. Bu kutuyu işaretleyerek mevcut app.ini dosyasının doğru SECRET_KEY içerdiğini onaylıyorsunuz. +reinstall_confirm_check_2=Depoların ve ayarların yeniden eşlenmesi gerekebilir. Bu kutuyu işaretleyerek depolar ve authorized_keys dosyası için istemcileri elle yeniden eşleyeceğinizi onaylamış olursunuz. Depo ve yansı ayarlarının doğru olduğundan emin olacağınızı onaylıyorsunuz. reinstall_confirm_check_3=Bu Gitea'nın doğru app.ini konumuyla çalıştığından kesinlikle emin olduğunuzu ve yeniden yüklemeniz gerektiğinden emin olduğunuzu onaylarsınız. Yukarıdaki riskleri kabul ettiğinizi onaylıyorsunuz. err_empty_db_path=SQLite3 veritabanı dosya yolu boş olamaz. no_admin_and_disable_registration=Bir yönetici hesabı oluşturmadan kullanıcı kaydını kapatamazsınız. err_empty_admin_password=Yönetici parolası boş olamaz. err_empty_admin_email=Yönetici e-postası boş olamaz. +err_admin_name_is_reserved=Yönetici Kullanıcı Adı geçersiz, bu kullanıcı adı rezerv edilen bir kelimedir. +err_admin_name_pattern_not_allowed=Yönetici kullanıcı adı geçersiz, kullanıcı adı ayrılmış bir desenle eşleşiyor. +err_admin_name_is_invalid=Yönetici Kullanıcı Adı geçersiz general_title=Genel Ayarlar app_name=Site Başlığı @@ -290,6 +296,7 @@ domain_helper=Sunucu için alan adı veya ana bilgisayar adresi. ssh_port=SSH Sunucu Portu ssh_port_helper=SSH sunucusunun dinleyeceği port numarası. Etkisizleştimek için boş bırakın. http_port=Gitea HTTP Dinleme Portu +http_port_helper=Gitea'nın web sunucusunun dinleyeceği port numarası. app_url=Gitea Kök URL app_url_helper=HTTP(S) kopyalama URL'leri ve e-posta bildirimleri için temel adres. log_root_path=Günlük Dosyaları Yolu @@ -353,6 +360,7 @@ no_reply_address=Gizlenecek E-Posta Alan Adı no_reply_address_helper=Gizlenmiş e-posta adresine sahip kullanıcılar için alan adı. Örneğin 'ali' kullanıcı adı, gizlenmiş e-postalar için alan adı 'yanityok.ornek.org' olarak ayarlandığında Git günlüğüne 'ali@yanityok.ornek.org' olarak kaydedilecektir. password_algorithm=Parola Hash Algoritması invalid_password_algorithm=Hatalı parola hash algoritması +password_algorithm_helper=Parola hash algoritmasını ayarlayın. Algoritmalar değişen gereksinimlere ve güce sahiptirler. argon2 algoritması iyi özelliklere sahip olmasına rağmen fazla miktarda bellek kullanır ve küçük sistemler için uygun olmayabilir. enable_update_checker=Güncelleme Denetleyicisini Etkinleştir enable_update_checker_helper=Düzenli olarak gitea.io'ya bağlanarak yeni yayınlanan sürümleri denetler. env_config_keys=Ortam Yapılandırma @@ -424,6 +432,8 @@ allow_password_change=Kullanıcıyı parola değiştirmeye zorla (önerilen) reset_password_mail_sent_prompt=%s adresine bir onay e-postası gönderildi. Hesap kurtarma işlemini tamamlamak için lütfen gelen kutunuzu sonraki %s içinde kontrol edin. active_your_account=Hesabınızı Etkinleştirin account_activated=Hesap etkinleştirildi +prohibit_login=Oturum Açma Yasaklanmış +prohibit_login_desc=Hesabınız ile oturum açmanız yasaklanmış, lütfen site yöneticinizle iletişime geçin. resent_limit_prompt=Zaten bir etkinleştirme e-postası talep ettiniz. Lütfen 3 dakika bekleyip tekrar deneyin. has_unconfirmed_mail=Merhaba %s, doğrulanmamış bir e-posta adresin var (%s). Bir doğrulama e-postası almadıysanız ya da yenisine ihtiyacınız varsa lütfen aşağıdaki düğmeye tıklayın. change_unconfirmed_mail_address=Eğer kayıt e-posta adresiniz hatalı ise, burada değiştirebilir ve yeni bir doğrulama e-postası gönderebilirsiniz. @@ -444,6 +454,7 @@ use_scratch_code=Bir çizgi kodu kullanınız twofa_scratch_used=Geçici kodunuzu kullandınız. İki aşamalı ayarlar sayfasına yönlendirildiniz, burada aygıt kaydınızı kaldırabilir veya yeni bir geçici kod oluşturabilirsiniz. twofa_passcode_incorrect=Şifreniz yanlış. Aygıtınızı yanlış yerleştirdiyseniz, oturum açmak için çizgi kodunuzu kullanın. twofa_scratch_token_incorrect=Çizgi kodunuz doğru değildir. +twofa_required=Depolara erişmek için iki aşama doğrulama kullanmanız veya tekrar oturum açmayı denemeniz gereklidir. login_userpass=Oturum Aç login_openid=Açık Kimlik oauth_signup_tab=Yeni Hesap Oluştur @@ -455,19 +466,24 @@ oauth_signin_submit=Hesabı Bağla oauth.signin.error.general=Yetkilendirme isteğini işlerken bir hata oluştu: %s. Eğer hata devam ederse lütfen site yöneticisiyle bağlantıya geçin. oauth.signin.error.access_denied=Yetkilendirme isteği reddedildi. oauth.signin.error.temporarily_unavailable=Yetkilendirme sunucusu geçici olarak erişilemez olduğu için yetkilendirme başarısız oldu. Lütfen daha sonra tekrar deneyin. +oauth_callback_unable_auto_reg=Otomatik kayıt etkin ancak OAuth2 Sağlayıcı %[1] eksik sahalar döndürdü: %[2]s, otomatik olarak hesap oluşturulamıyor, lütfen bir hesap oluşturun veya bağlantı verin, veya site yöneticisiyle iletişim kurun. openid_connect_submit=Bağlan openid_connect_title=Mevcut olan bir hesaba bağlan openid_connect_desc=Seçilen OpenID URI'si bilinmiyor. Burada yeni bir hesapla ilişkilendir. openid_register_title=Yeni hesap oluştur openid_register_desc=Seçilen OpenID URI'si bilinmiyor. Burada yeni bir hesapla ilişkilendir. openid_signin_desc=OpenID URI'nizi girin. Örneğin: alice.openid.example.org veya https://openid.example.org/alice. +disable_forgot_password_mail=E-posta ayarlanmadığından hesap kurtarma devre dışı. Site yöneticinizle iletişime geçin. +disable_forgot_password_mail_admin=Hesap kurtarma sadece e-posta ayarlanmışsa kullanılabilir. Hesap kurtarmayı etkinleştirmek için lütfen e-posta ayarlayın. email_domain_blacklisted=Bu e-posta adresinizle kayıt olamazsınız. authorize_application=Uygulamayı Yetkilendir authorize_redirect_notice=Bu uygulamayı yetkilendirirseniz %s adresine yönlendirileceksiniz. authorize_application_created_by=Bu uygulama %s tarafından oluşturuldu. +authorize_application_description=Erişime izin verirseniz, özel depolar ve organizasyonlar da dahil olmak üzere tüm hesap bilgilerinize erişebilir ve yazabilir. authorize_application_with_scopes=Kapsamlar: %s authorize_title=Hesabınıza erişmesi için "%s" yetkilendirilsin mi? authorization_failed=Yetkilendirme başarısız oldu +authorization_failed_desc=Geçersiz bir istek tespit ettiğimiz için yetkilendirme başarısız oldu. Lütfen izin vermeye çalıştığınız uygulamanın sağlayıcısı ile iletişim kurun. sspi_auth_failed=SSPI kimlik doğrulaması başarısız oldu password_pwned=Seçtiğiniz parola, daha önce herkese açık veri ihlallerinde açığa çıkan bir çalınan parola listesindedir. Lütfen farklı bir parola ile tekrar deneyin ve başka yerlerde de bu parolayı değiştirmeyi düşünün. password_pwned_err=HaveIBeenPwned'e yapılan istek tamamlanamadı @@ -492,6 +508,8 @@ activate_email.text=E posta adresinizi doğrulamak için lütfen %s için register_notify=%s'ya Hoş Geldiniz register_notify.title=%[1]s, %[2]s e hoşgeldiniz +register_notify.text_1=bu %s için kayıt onay e-postanızdır! +register_notify.text_2=Artık %s kullanıcı adı ile oturum açabilirsiniz. register_notify.text_3=Eğer bu hesap sizin için oluşturulduysa, lütfen önce şifrenizi ayarlayın. reset_password=Hesabınızı kurtarın @@ -529,10 +547,18 @@ release.download.targz=Kaynak Kodu (TAR.GZ) repo.transfer.subject_to=%s "%s" aktarımını %s tarafına gerçekleştirmek istiyor repo.transfer.subject_to_you=%s size "%s" aktarmak istiyor repo.transfer.to_you=siz +repo.transfer.body=Kabul veya reddetmek için %s ziyaret edin veya görmezden gelin. repo.collaborator.added.subject=%s sizi %s ekledi repo.collaborator.added.text=Bu depo için katkıcı olarak eklendiniz: +repo.actions.run.failed=Çalıştırma başarısız oldu +repo.actions.run.succeeded=Çalıştırma başarılı oldu +repo.actions.run.cancelled=Çalıştırma iptal edildi +repo.actions.jobs.all_succeeded=Tüm işler başarılı oldu +repo.actions.jobs.all_failed=Tüm işler başarısız oldu +repo.actions.jobs.some_not_successful=Bazı işler başarısız oldu +repo.actions.jobs.all_cancelled=Tüm işler iptal edildi team_invite.subject=%[1]s sizi %[2]s organizasyonuna katılmaya davet etti team_invite.text_1=%[1]s sizi %[3]s organizasyonundaki %[2]s takımına katılmaya davet etti. @@ -581,6 +607,7 @@ url_error=`"%s" geçerli bir URL değil.` include_error=` "%s" içermelidir.` glob_pattern_error=` glob deseni geçersiz: %s.` regex_pattern_error=` regex dizisi geçersiz: %s.` +username_error=` sadece alfanümerik karakterler ('0-9','a-z','A-Z'), tire ('-'), altçizgi ('_') ve nokta ('.') içerebilir. Alfanümerik olmayan karakterle başlayamaz veya bitemez ve alfanümerik olmayan karakterler peşpeşe gelemez.` invalid_group_team_map_error=` eşleme geçersiz: %s` unknown_error=Bilinmeyen hata: captcha_incorrect=CAPTCHA eşleşmedi. @@ -595,14 +622,17 @@ username_has_not_been_changed=Kullanıcı adı değişmedi repo_name_been_taken=Depo adı zaten kullanılıyor. repository_force_private=Gizliyi Zorla devrede: gizli depolar herkese açık yapılamaz. repository_files_already_exist=Bu depo için dosyalar zaten var. Sistem yöneticisine başvurun. +repository_files_already_exist.adopt=Bu depo için dosyalar zaten var ve yalnızca Kabul Edilebilir. repository_files_already_exist.delete=Bu depo için dosyalar zaten var. Onları silmelisiniz. repository_files_already_exist.adopt_or_delete=Bu depo için dosyalar zaten var. Ya kabul edin ya da silin. visit_rate_limit=Uzaktan ziyarette oran sınırlaması ele alındı. +2fa_auth_required=Uzaktan ziyaret için iki faktörlü kimlik doğrulaması gerekli. org_name_been_taken=Organizasyon adı zaten kullanılıyor. team_name_been_taken=Takım adı zaten alınmış. team_no_units_error=En az bir depo bölümüne erişimine izin ver. email_been_used=E-posta adresi zaten kullanılıyor. email_invalid=E-posta adresi geçersiz. +email_domain_is_not_allowed=Kullanıcı e-posta adresi %s alan adı EMAIL_DOMAIN_ALLOWLIST veya EMAIL_DOMAIN_BLOCKLIST ile çelişiyor. Lütfen işleminizin beklendiğinden emin olun. openid_been_used=OpenID adresi "%s" zaten kullanılıyor. username_password_incorrect=Kullanıcı adı veya parola hatalı. password_complexity=Parola, karmaşıklık gereksinimlerini karşılamıyor: @@ -627,8 +657,14 @@ invalid_ssh_key=SSH anahtarınız doğrulanamıyor: %s invalid_gpg_key=GPG anahtarınız doğrulanamıyor: %s invalid_ssh_principal=Geçersiz sorumlu: %s must_use_public_key=Sağladığınız anahtar bir özel anahtardır. Lütfen özel anahtarınızı herhangi bir yere yüklemeyin. Onun yerine açık anahtarınızı kullanın. +unable_verify_ssh_key=SSH anahtarı doğrulanamıyor, hatalar için dikkatle inceleyin. auth_failed=Kimlik doğrulaması başarısız oldu: %v +still_own_repo=Hesabınız bir veya daha fazla depoya sahip, önce depoları silin veya aktarın. +still_has_org=Hesabınız bir veya daha fazla organizasyonun üyesi, önce onlardan ayrılın. +still_own_packages=Hesabınız bir veya daha fazla pakete sahip, önce onları silin. +org_still_own_repo=Bu organizasyon hala bir veya daha fazla depoya sahip, önce depoları silin veya aktarın. +org_still_own_packages=Bu organizasyon hala bir veya daha fazla pakete sahip, önce onları silin. target_branch_not_exist=Hedef dal mevcut değil. target_ref_not_exist=Hedef referans mevcut değil %s @@ -659,9 +695,11 @@ settings=Kullanıcı Ayarları form.name_reserved=`"%s" kullanıcı adı rezerve edilmiş.` form.name_pattern_not_allowed=Kullanıcı adında "%s" deseni kullanılamaz. +form.name_chars_not_allowed=`"%s" kullanıcı adı geçersiz karakterler içeriyor.` block.block=Engelle block.block.user=Kullanıcıyı engelle +block.block.org=Kullanıcıyı organizasyonda engelle block.block.failure=Kullanıcı engellenemedi: %s block.unblock=Engeli kaldır block.unblock.failure=Kullanıcının engeli kaldırılamadı: %s @@ -674,6 +712,7 @@ block.info_3=kullanıcı adınızdan @bahsederek size bildirim göndermek block.info_4=kendi depolarına sizi katkıcı olarak davet etmek block.info_5=depolara yıldız koymak, çatallamak veya izlemek block.info_6=konu veya değişiklik isteği açmak ve yorum eklemek +block.info_7=konularda veya değişiklik isteklerinde yorumlarınıza tepki vermek block.user_to_block=Engellenecek kullanıcı block.note=Not block.note.title=İsteğe bağlı not: @@ -704,6 +743,7 @@ webauthn=İki-Aşamalı Kimlik Doğrulama (Güvenlik Anahtarları) public_profile=Herkese Açık Profil biography_placeholder=Bize kendiniz hakkında birşeyler söyleyin! (Markdown kullanabilirsiniz) location_placeholder=Yaklaşık konumunuzu başkalarıyla paylaşın +profile_desc=Profilinizin başkalarına nasıl gösterildiğini yönetin. Ana e-posta adresiniz bildirimler, parola kurtarma ve web tabanlı Git işlemleri için kullanılacaktır. password_username_disabled=Yerel olmayan kullanıcılara kullanıcı adlarını değiştirme izni verilmemiştir. Daha fazla bilgi edinmek için lütfen site yöneticisi ile iletişime geçiniz. password_full_name_disabled=Tam adınızı değiştirme izniniz yoktur. Daha fazla bilgi edinmek için lütfen site yöneticisi ile iletişime geçiniz. full_name=Ad Soyad @@ -723,6 +763,7 @@ cancel=İptal language=Dil ui=Tema hidden_comment_types=Gizli yorum türleri +hidden_comment_types_description=Burada işaretlenen yorum türleri konu sayfalarında görüntülenmeyecektir. Örneğin "Etiket" seçildiğinde tüm "{user}, {label} ekledi/çıkardı" yorumları kalkacaktır. hidden_comment_types.ref_tooltip=Bu konuya başka konu/işlem tarafından değinilen yorumlar… hidden_comment_types.issue_ref_tooltip=Kullanıcının konuyla ilişkili dalı/etiketi değiştirdiği yorumlar comment_type_group_reference=Referans @@ -770,14 +811,18 @@ manage_themes=Varsayılan temayı seç manage_openid=OpenID Adreslerini Yönet email_desc=Ana e-posta adresiniz bildirimler, parola kurtarma ve gizlenmemişse eğer web tabanlı Git işlemleri için kullanılacaktır. theme_desc=Bu, sitedeki varsayılan temanız olacak. +theme_colorblindness_help=Renk Körlüğü için Tema Desteği +theme_colorblindness_prompt=Gitea temel renk körlüğü desteği olan, yalnızca az sayıda rengin tanımlı olduğu, sadece birkaç temaya sahip. Çalışmalar sürüyor. Tema CSS dosyalarında daha çok renk tanımlanmasıyla daha fazla iyileştirme yapılabilir. primary=Birincil activated=Aktifleştirildi requires_activation=Etkinleştirme gerekiyor primary_email=Birincil Yap activate_email=Etkinleştirme Gönder activations_pending=Bekleyen Etkinleştirmeler +can_not_add_email_activations_pending=Bekleyen etkinleştirme var, yeni bir e-posta adresi eklemek istiyorsanız birkaç dakika içinde tekrar deneyin. delete_email=Kaldır email_deletion=E-posta Adresini Kaldır +email_deletion_desc=E-posta adresi ve ilgili bilgiler hesabınızdan kaldırılacak. Bu e-posta adresi tarafından yapılan işlemeler değişmeden kalacaktır. Devam edilsin mi? email_deletion_success=E-posta adresi kaldırıldı. theme_update_success=Temanız güncellendi. theme_update_error=Seçilen tema mevcut değil. @@ -820,6 +865,7 @@ gpg_key_matched_identities_long=Bu anahtara gömülü kimlikler bu kullanıcı i gpg_key_verified=Doğrulanmış Anahtar gpg_key_verified_long=Bu anahtar doğrulandı ve etkinleştirilmiş herhangi bir e-posta adresi veya eşleşen herhangi bir kimlik ile uyuşan işlemeleri doğrulamaya hazır. gpg_key_verify=Doğrula +gpg_invalid_token_signature=Verilen GPG anahtarı, imza ve erişim anahtarı uyuşmuyor veya erişim anahtarı güncel değil. gpg_token_required=Aşağıdaki anahtar için bir imza sağlamalısınız gpg_token=Anahtar gpg_token_help=Şunu kullanarak bir imza oluşturabilirsiniz: @@ -829,6 +875,7 @@ verify_gpg_key_success=GPG anahtarı "%s" doğrulandı. ssh_key_verified=Doğrulanmış Anahtar ssh_key_verified_long=Bu anahtar bir belirteç ile doğrulandı ve bu kullanıcı için etkinleştirilmiş herhangi bir e-posta adresi ile uyuşan işlemeleri doğrulamak için kullanılabilir. ssh_key_verify=Doğrula +ssh_invalid_token_signature=Verilen SSH anahtarı, imza veya erişim anahtarı uyuşmuyor veya erişim anahtarı güncel değil. ssh_token_required=Aşağıdaki erişim anahtarı için bir imza sağlamalısınız ssh_token=Erişim Anahtarı ssh_token_help=Şunu kullanarak bir imza oluşturabilirsiniz: @@ -849,6 +896,7 @@ gpg_key_deletion=GPG Anahtarını Sil ssh_principal_deletion=SSH Sertifika Sorumlusunu Kaldır ssh_key_deletion_desc=Bir SSH anahtarını kaldırmak, hesabınıza erişimi iptal eder. Devam edilsin mi? gpg_key_deletion_desc=Bir GPG anahtarını kaldırmak, onun tarafından imzalanan işlemelerin doğrulamasını iptal eder. Devam edilsin mi? +ssh_principal_deletion_desc=Bir SSH Sertifika Sorumlusunun kaldırılması, hesabınıza erişimini iptal eder. Devam edilsin mi? ssh_key_deletion_success=SSH anahtarı silindi. gpg_key_deletion_success=GPG anahtarı silindi. ssh_principal_deletion_success=Sorumlu kaldırıldı. @@ -910,6 +958,7 @@ create_oauth2_application_button=Uygulama Oluştur create_oauth2_application_success=Yeni bir OAuth2 uygulamasını başarıyla oluşturdunuz. update_oauth2_application_success=OAuth2 uygulamasını başarıyla güncellediniz. oauth2_application_name=Uygulama Adı +oauth2_confidential_client=Güvenli İstemci. Web uygulamaları gibi sırları güvende tutan uygulamalar için bunu seçin. Masaüstü ve mobil uygulamaları da içeren doğal uygulamalar için seçmeyin. oauth2_skip_secondary_authorization=Herkese açık istemcilerin yetkilendirilmesini bir kere erişim izni verdikten sonra atla. Bu bir güvenlik riski oluşturabilir. oauth2_redirect_uris=Yönlendirme URI'leri. Lütfen her bir URI'yi yeni bir satıra yazın. save_application=Kaydet @@ -924,8 +973,10 @@ oauth2_application_remove_description=Bir OAuth2 uygulamasının kaldırılması oauth2_application_locked=Gitea kimi OAuth2 uygulamalarının başlangıçta ön kaydını, yapılandırmada etkinleştirilmişse yapabilir. Beklenmeyen davranışı önlemek için bunlar ne düzenlenmeli ne de kaldırılmalı. Daha fazla bilgi için OAuth2 belgesine bakın. authorized_oauth2_applications=Yetkili OAuth2 Uygulamaları +authorized_oauth2_applications_description=Kişisel Gitea hesabınıza bu üçüncü parti uygulamalara erişim izni verdiniz. Lütfen artık ihtiyaç duyulmayan uygulamalara erişimi iptal edin. revoke_key=İptal Et revoke_oauth2_grant=Erişimi İptal Et +revoke_oauth2_grant_description=Bu üçüncü taraf uygulamasına erişimin iptal edilmesi bu uygulamanın verilerinize erişmesini önleyecektir. Emin misiniz? revoke_oauth2_grant_success=Erişim başarıyla kaldırıldı. twofa_desc=İki aşamalı kimlik doğrulama, hesabınızın güvenliğini artırır. @@ -935,6 +986,7 @@ twofa_not_enrolled=Hesabınız şu anda iki faktörlü kimlik doğrulaması içi twofa_disable=İki Aşamalı Doğrulamayı Devre Dışı Bırak twofa_scratch_token_regenerate=Geçici Kodu Yeniden Üret twofa_scratch_token_regenerated=Geçici kodunuz şimdi %s. Güvenli bir yerde saklayın, tekrar gösterilmeyecektir. +twofa_enroll=İki Aşamalı Kimlik Doğrulamaya Kaydolun twofa_disable_note=Gerekirse iki faktörlü kimlik doğrulamayı devre dışı bırakabilirsiniz. twofa_disable_desc=İki faktörlü kimlik doğrulamayı devre dışı bırakmak hesabınızı daha az güvenli hale getirir. Devam edilsin mi? regenerate_scratch_token_desc=Geçici kodunuzu kaybettiyseniz veya oturum açmak için kullandıysanız, buradan sıfırlayabilirsiniz. @@ -950,11 +1002,13 @@ webauthn_desc=Güvenlik anahtarları, şifreleme anahtarlarını içeren donanı webauthn_register_key=Güvenlik Anahtarı Ekle webauthn_nickname=Takma Ad webauthn_delete_key=Güvenlik Anahtarını Kaldır +webauthn_delete_key_desc=Bir güvenlik anahtarını kaldırırsanız, artık onunla giriş yapamazsınız. Devam edilsin mi? webauthn_key_loss_warning=Güvenlik anahtarlarınızı kaybederseniz, hesabınıza erişimi kaybedersiniz. webauthn_alternative_tip=Ek bir kimlik doğrulama yöntemi ayarlamak isteyebilirsiniz. manage_account_links=Bağlı Hesapları Yönet manage_account_links_desc=Bu harici hesaplar Gitea hesabınızla bağlantılı. +account_links_not_available=Şu anda Gitea hesabınıza bağlı harici bir hesap yok. link_account=Hesap Bağla remove_account_link=Bağlantılı Hesabı Kaldır remove_account_link_desc=Bağlantılı bir hesabı kaldırmak, onunla Gitea hesabınıza erişimi iptal edecektir. Devam edilsin mi? @@ -977,6 +1031,8 @@ email_notifications.onmention=Sadece Bahsedilen E-posta email_notifications.disable=E-posta Bildirimlerini Devre Dışı Bırak email_notifications.submit=E-posta Tercihlerini Ayarla email_notifications.andyourown=Ve Sizin Bildirimleriniz +email_notifications.actions.desc=Gitea Actions ile ayarlanan depolarda iş akışı çalıştırmaları için bildirimler. +email_notifications.actions.failure_only=Sadece başarısız olan iş akışı çalıştırmalarını bildir visibility=Kullanıcı görünürlüğü visibility.public=Herkese Açık @@ -991,6 +1047,8 @@ new_repo_helper=Bir depo, sürüm geçmişi dahil tüm proje dosyalarını içer owner=Sahibi owner_helper=Bazı organizasyonlar, en çok depo sayısı sınırı nedeniyle açılır menüde görünmeyebilir. repo_name=Depo İsmi +repo_name_profile_public_hint=.profile herkese açık organizasyonunuzun profiline herkesin görüntüleyebileceği bir README.md dosyası eklemek için kullanabileceğiniz özel bir depodur. Başlamak için herkese açık olduğundan ve profile dizininde README ile başladığınızdan emin olun. +repo_name_profile_private_hint=.profile-private organizasyonunuzun üye profiline sadece organizasyon üyelerinin görüntüleyebileceği bir README.md eklemek için kullanabileceğiniz özel bir depodur. Başlamak için özel olduğundan ve profil dizininde README ile başladığınızdan emin olun. repo_name_helper=İyi depo isimleri kısa, akılda kalıcı ve benzersiz anahtar kelimeler kullanır. “.profile” veya ‘.profile-private’ adlı bir depo, kullanıcı/kuruluş profili için bir README.md eklemek için kullanılabilir. repo_size=Depo Boyutu template=Şablon @@ -1012,6 +1070,7 @@ fork_branch=Çatala klonlanacak dal all_branches=Tüm dallar view_all_branches=Tüm dalları görüntüle view_all_tags=Tüm etiketleri görüntüle +fork_no_valid_owners=Geçerli bir sahibi olmadığı için bu depo çatallanamaz. fork.blocked_user=Depo çatallanamıyor, depo sahibi tarafından engellenmişsiniz. use_template=Bu şablonu kullan open_with_editor=%s ile aç @@ -1055,10 +1114,12 @@ mirror_sync=eşitlendi mirror_sync_on_commit=İşlemeler gönderildiğinde senkronize et mirror_address=URL'den Klonla mirror_address_desc=Yetkilendirme bölümüne gerekli tüm kimlik bilgilerini girin. +mirror_address_url_invalid=Sağlanan URL geçersiz. URL'nin tüm bileşenleri doğru olarak girilmelidir. mirror_address_protocol_invalid=Sağlanan URL geçersiz. Yalnızca http(s):// veya git:// konumları yansı olabilir. mirror_lfs=Büyük Dosya Depolama (LFS) mirror_lfs_desc=LFS verisinin yansılamasını etkinleştir. mirror_lfs_endpoint=LFS Uç Noktası +mirror_lfs_endpoint_desc=Senkronizasyon, LFS sunucusunu belirlemek için klonlama URL'sini kullanmaya çalışacak. Eğer LFS veri deposu başka yerdeyse özel bir uç nokta da belirtebilirsiniz. mirror_last_synced=Son Senkronize Edilen mirror_password_placeholder=(Değiştirilmedi) mirror_password_blank_placeholder=(Ayarı kaldır) @@ -1071,6 +1132,7 @@ stars=Yıldızlar reactions_more=ve %d daha fazla unit_disabled=Site yöneticisi bu depo bölümünü devre dışı bıraktı. language_other=Diğer +adopt_search=Kabul edilmeyen depoları aramak için kullanıcı adını girin... (tümünü bulmak için boş bırakın) adopt_preexisting_label=Dosyaları Kabul Et adopt_preexisting=Önceden var olan dosyaları kabul et adopt_preexisting_content=%s konumundan depo oluştur @@ -1112,6 +1174,8 @@ template.issue_labels=Konu Etiketleri template.one_item=En az bir şablon öğesi seçmelisiniz template.invalid=Bir şablon deposu seçmelisiniz +archive.title=Bu depo arşivlendi. Dosyaları görüntüleyebilir ve klonlayabilirsiniz ama işleme gönderemez veya konu veya değişiklik isteği açamazsınız. +archive.title_date=Bu depo %s tarihinde arşivlendi. Dosyaları görüntüleyebilir ve klonlayabilirsiniz ama işleme gönderemez veya konu veya değişiklik isteği açamazsınız. archive.issue.nocomment=Bu depo arşivlendi. Konular bölümünde yorum yapamazsınız. archive.pull.nocomment=Bu depo arşivlendi. Değişiklik istekleri bölümünde yorum yapamazsınız. @@ -1128,6 +1192,7 @@ migrate_options_lfs=LFS dosyalarını taşı migrate_options_lfs_endpoint.label=LFS Uç Noktası migrate_options_lfs_endpoint.description=Taşıma, LFS sunucusunu belirlemek için Git uzak sunucusunu kullanmaya çalışacak. Eğer LFS veri deposu başka yerdeyse özel bir uç nokta da belirtebilirsiniz. migrate_options_lfs_endpoint.description.local=Yerel bir sunucu yolu da destekleniyor. +migrate_options_lfs_endpoint.placeholder=Boş bırakılırsa, uç nokta klon URL'sinden türetilecektir migrate_items=Göç Öğeleri migrate_items_wiki=Wiki migrate_items_milestones=Dönüm noktaları @@ -1139,8 +1204,10 @@ migrate_items_releases=Sürümler migrate_repo=Depoyu Göç Ettir migrate.clone_address=URL'den Taşı / Klonla migrate.clone_address_desc=Varolan bir deponun HTTP(S) veya Git 'klonlama' URL'si +migrate.github_token_desc=GitHub API hız sınırı nedeniyle göçü hızlandırmak için buraya virgülle ayrılmış bir veya daha fazla erişm anahtarı koyabilirsiniz. UYARI: Bu özelliğin kötüye kullanılması, hizmet sağlayıcının politikasını ihlal edebilir ve hesap(ların) engellenmesine yol açabilir. migrate.clone_local_path=veya bir yerel sunucu yolu migrate.permission_denied=Yerel depoları içeri aktarma izniniz yok. +migrate.permission_denied_blocked=İzin verilmeyen sunuculardan içe aktaramazsınız, lütfen yöneticiden ALLOWED_DOMAINS/ALLOW_LOCALNETWORKS/BLOCKED_DOMAINS ayarlarını denetlemesini isteyin. migrate.invalid_local_path=Yerel yol geçersiz. Mevcut değil veya bir dizin değil. migrate.invalid_lfs_endpoint=LFS Uç noktası geçerli değil. migrate.failed=Göç başarısız: %v @@ -1148,6 +1215,7 @@ migrate.migrate_items_options=Ek öğeleri taşımak için Erişim Kodu gereklid migrated_from=%[2]s konumundan göç edildi migrated_from_fake=%[1]s Konumundan Göç Edildi migrate.migrate=%s Konumundan Göç Et +migrate.migrating=%s konumundan taşınıyor… migrate.migrating_failed=%s konumundan taşıma başarısız oldu. migrate.migrating_failed.error=Göç yapılamadı: %s migrate.migrating_failed_no_addr=Göç başarısız oldu. @@ -1196,7 +1264,9 @@ clone_this_repo=Bu depoyu klonla cite_this_repo=Bu depoya atıf ver create_new_repo_command=Komut satırında yeni bir depo oluşturuluyor push_exist_repo=Komut satırından mevcut bir depo itiliyor +empty_message=Bu depoda herhangi bir içerik yok. broken_message=Bu deponun altındaki Git verisi okunamıyor. Bu sunucunun yöneticisiyle bağlantıya geçin veya bu depoyu silin. +no_branch=Bu deponun hiç bir dalı yok. code=Kod code.desc=Kaynak koda, dosyalara, işlemelere ve dallara eriş. @@ -1213,6 +1283,7 @@ projects=Projeler packages=Paketler actions=İşlemler labels=Etiketler +org_labels_desc=Bu organizasyon altındaki tüm depolarla kullanılabilen organizasyon düzeyinde etiketler org_labels_desc_manage=yönet milestone=Dönüm noktası @@ -1224,6 +1295,7 @@ releases=Sürüm tag=Etiket released_this=bu sürümü yayınladı tagged_this=şunu etiketledi +file.title=%s dalındaki/etiketindeki %s file_raw=Ham file_history=Geçmiş file_view_source=Kaynağı Görüntüle @@ -1260,6 +1332,7 @@ commit_graph.color=Renk commit.contained_in=Bu işleme şunda yer alıyor: commit.contained_in_default_branch=Bu işleme varsayılan dalın bir parçasıdır commit.load_referencing_branches_and_tags=Bu işlemeyi kullanan dal ve etiketleri yükle +commit.merged_in_pr=Bu commit, %s pull request’inde birleştirildi. blame=Suçlama download_file=Dosya indir normal_view=Normal Görünüm @@ -1308,13 +1381,17 @@ editor.new_branch_name_desc=Yeni dal ismi… editor.cancel=İptal editor.filename_cannot_be_empty=Dosya adı boş olamaz. editor.filename_is_invalid=Dosya adı geçersiz: "%s". +editor.commit_email=İşleme e-postası +editor.invalid_commit_email=İşleme e-postası hatalı. editor.branch_does_not_exist=Bu depoda "%s" dalı yok. editor.branch_already_exists=Bu depoda "%s" dalı zaten var. editor.directory_is_a_file=Dizin adı "%s" zaten bu depoda bir dosya adı olarak kullanılmaktadır. +editor.file_is_a_symlink=`"%s" sembolik bir bağlantıdır. Sembolik bağlantılar web düzenleyicisinde düzenlenemez` editor.filename_is_a_directory=Dosya adı "%s" zaten bu depoda bir dizin adı olarak kullanılmaktadır. editor.file_modifying_no_longer_exists=Değiştirilmekte olan "%s" dosyası artık bu depoda yer almıyor. editor.file_changed_while_editing=Düzenlemeye başladığınızdan beri dosya içeriği değişti. Görmek için burayı tıklayın veya üzerine yazmak için değişiklikleri yine de işleyin. editor.file_already_exists=Bu depoda "%s" isimli bir dosya zaten var. +editor.commit_id_not_matching=İşleme ID'si, düzenlemeye başladığınız ID ile uyuşmuyor, bir yama dalına işleme yapın ve sonra birleştirin. editor.push_out_of_date=İtme eskimiş. editor.commit_empty_file_header=Boş bir dosya işle editor.commit_empty_file_text=İşlemek üzere olduğunuz dosya boş. Devam edilsin mi? @@ -1336,8 +1413,11 @@ editor.failed_to_commit=Değişikliklerin işlenmesi başarısız oldu. editor.failed_to_commit_summary=Hata Mesajı: editor.fork_create=Değişiklikler Önermek için Depoyu Çatallayın +editor.fork_create_description=Bu depoyu doğrudan düzenleyemezsiniz. Bunun yerine bir çatal oluşturabilir, düzenlemeler yapabilir ve bir değişiklik isteği oluşturabilirsiniz. +editor.fork_edit_description=Bu depoyu doğrudan düzenleyemezsiniz. Değişiklikler %s çatalınıza yazılacak, böylece bir değişiklik isteği oluşturabilirsiniz. editor.fork_not_editable=Bu deponun çatalını oluşturdunuz ancak çatalınız düzenlenemez durumda. editor.fork_failed_to_push_branch=%s dalını deponuza gönderme başarısız oldu. +editor.fork_branch_exists=`"%s" dalı çatalınızda zaten mevcut, lütfen yeni bir dal adı seçin.` commits.desc=Kaynak kodu değişiklik geçmişine göz atın. commits.commits=İşleme @@ -1439,6 +1519,7 @@ issues.new.clear_assignees=Atamaları Temizle issues.new.no_assignees=Atanan Kişi Yok issues.new.no_reviewers=Gözden geçiren yok issues.new.blocked_user=Konu oluşturulamıyor, depo sahibi tarafından engellenmişsiniz. +issues.edit.already_changed=Konuya yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın. issues.edit.blocked_user=İçerik düzenlenemiyor, gönderen veya depo sahibi tarafından engellenmişsiniz. issues.choose.get_started=Başla issues.choose.open_external_link=Aç @@ -1465,6 +1546,7 @@ issues.remove_labels=%s etiketlerini %s sildi issues.add_remove_labels=%s ekleme ve %s kaldırma işlemlerini %s yaptı issues.add_milestone_at=`%[2]s %[1]s kilometre taşına ekledi` issues.add_project_at=`bunu %s projesine %s ekledi` +issues.move_to_column_of_project=`bu %s sütununa, %s tahtasına %s tarihinde taşındı` issues.change_milestone_at=`%s kilometre taşını %s iken %s olarak değiştirdi` issues.change_project_at=%s %s olan projeyi %s olarak değiştirdi issues.remove_milestone_at=`%[2]s %[1]s kilometre taşından kaldırdı` @@ -1509,6 +1591,7 @@ issues.filter_type.reviewed_by_you=Sizin tarafınızdan incelendi issues.filter_sort=Sırala issues.filter_sort.latest=En yeni issues.filter_sort.oldest=En eski +issues.filter_sort.recentupdate=Yakın zamanda güncellenmiş issues.filter_sort.leastupdate=Yakın olmayan zamanda güncellenmiş issues.filter_sort.mostcomment=En çok yorum yapılan issues.filter_sort.leastcomment=En az yorum yapılan @@ -1598,6 +1681,7 @@ issues.label_archived_filter=Arşivlenmiş etiketleri göster issues.label_archive_tooltip=Arşivlenmiş etiketler, etiket araması yapılırken varsayılan olarak önerilerin dışında tutuluyor. issues.label_exclusive_desc=Kapsam/öğe etiketini, diğer kapsam/ etiketleriyle ayrışık olacak şekilde adlandırın. issues.label_exclusive_warning=Çakışan kapsamlı etiketler, bir konu veya değişiklik isteği etiketleri düzenlenirken kaldırılacaktır. +issues.label_exclusive_order=Listeleme Sırası issues.label_exclusive_order_tooltip=Aynı bağlamdaki özel etiketler bu sayısal sıralamaya göre sıralanacaktır. issues.label_count=%d etiket issues.label_open_issues=%d açık konu @@ -1629,6 +1713,7 @@ issues.lock_no_reason=konuşma kilitlendi ve katkıcılar için sınırlandırı issues.unlock_comment=bu konuşmanın kilidini açtı %s issues.lock_confirm=Kilitle issues.unlock_confirm=Kilidi Aç +issues.lock.notice_1=- Diğer kullanıcılar bu konuya yeni yorum ekleyemez. issues.lock.notice_2=- Siz ve bu depoya erişimi olan diğer katkıcılar, başkalarının görebileceği yorumlar bırakabilir. issues.lock.notice_3=- Her zaman bu konunun kilidini açabilirsiniz. issues.unlock.notice_1=- Herkes bu konuda bir kez daha yorum yapabilir. @@ -1652,13 +1737,17 @@ issues.time_estimate_display=Tahmin: %s issues.change_time_estimate_at=zaman tahmini değiştirildi: %[1]s%[2]s issues.remove_time_estimate_at=zaman tahmini %s kaldırıldı issues.time_estimate_invalid=Zaman tahmini biçimi hatalı +issues.start_tracking_history=%s çalışma başlattı issues.tracker_auto_close=Bu konu kapatıldığında zamanlayıcı otomatik olarak durur +issues.stopwatch_already_stopped=Bu konunun zamanlayıcısı zaten durmuş +issues.stopwatch_already_created=Bu konunun zamanlayıcısı zaten var issues.tracking_already_started=`başka bir konuda zaten zaman izleyici başlattınız!` issues.stop_tracking=Zamanlayıcıyı Durdur issues.stop_tracking_history=%[1]s %[2]s için çalıştı issues.cancel_tracking=Yoksay issues.cancel_tracking_history=`%s zaman takibini iptal etti` issues.del_time=Bu zaman kaydını sil +issues.add_time_history=%[1]s %[2]s harcanan zaman eklendi issues.del_time_history=`%s harcanan zaman silindi` issues.add_time_manually=El ile Zaman Ekle issues.add_time_hours=Saat @@ -1679,6 +1768,7 @@ issues.due_date_form=yyyy-aa-gg issues.due_date_form_add=Bitiş tarihi ekle issues.due_date_form_edit=Düzenle issues.due_date_form_remove=Kaldır +issues.due_date_not_writer=Bir konunun bitiş tarihini güncellemek için bu depoda yazma iznine ihtiyacınız var. issues.due_date_not_set=Bitiş tarihi atanmadı. issues.due_date_added=bitiş tarihini %s olarak %s ekledi issues.due_date_modified=bitiş tarihini %[2]s iken %[1]s olarak %[3]s değiştirdi @@ -1701,7 +1791,9 @@ issues.dependency.pr_closing_blockedby=Bu değişiklik isteğinin kapatılması issues.dependency.issue_closing_blockedby=Bu konunun kapatılması aşağıdaki konular tarafından engelleniyor issues.dependency.issue_close_blocks=Bu konu aşağıdaki konuların kapatılmasını engelliyor issues.dependency.pr_close_blocks=Bu değişiklik isteği aşağıdaki sorunların kapatılmasını engelliyor +issues.dependency.issue_close_blocked=Kapatmadan önce bu konuyu engelleyen tüm konuları kapatmanız gerekir. issues.dependency.issue_batch_close_blocked=Seçtiğiniz konular topluca kapatılamıyor, çünkü #%d konusunun açık bağımlılıkları var +issues.dependency.pr_close_blocked=Birleştirme işleminden önce bu değişiklik isteğini engelleyen tüm konuları kapatmanız gerekir. issues.dependency.blocks_short=Engeller issues.dependency.blocked_by_short=Bağımlılıklar issues.dependency.remove_header=Bağımlılığı Kaldır @@ -1712,11 +1804,13 @@ issues.dependency.add_error_same_issue=Bir konuyu kendine bağımlı yapamazsın issues.dependency.add_error_dep_issue_not_exist=Bağımlı konu mevcut değil. issues.dependency.add_error_dep_not_exist=Bağımlılık mevcut değil. issues.dependency.add_error_dep_exists=Bağımlılık zaten var. +issues.dependency.add_error_cannot_create_circular=Birbirini engelleyen iki konu arasında bağımlılık oluşturamazsınız. issues.dependency.add_error_dep_not_same_repo=Her iki konu da aynı depoda olmalıdır. issues.review.self.approval=Kendi değişiklik isteğinizi onaylayamazsınız. issues.review.self.rejection=Kendi değişiklik isteğinizde değişiklik isteyemezsiniz. issues.review.approve=%s bu değişiklikleri onayladı issues.review.comment=%s incelendi +issues.review.dismissed=%s, %s incelemesini reddetti issues.review.dismissed_label=Reddedildi issues.review.left_comment=bir yorum yaptı issues.review.content.empty=İstenen değişiklik(ler)i belirten bir yorum bırakmanız gerekir. @@ -1724,6 +1818,7 @@ issues.review.reject=%s değişiklik istedi issues.review.wait=için %s inceleme isteği issues.review.add_review_request=%s tarafından %s inceleme istedi issues.review.remove_review_request=%s %s için inceleme isteği kaldırıldı +issues.review.remove_review_request_self=%s incelemeyi reddetti issues.review.pending=Beklemede issues.review.pending.tooltip=Bu yorum başkaları tarafından görünmüyor. Bekleyen yorumlarınızı göndermek için, sayfanın üstünde "%s" -> "%s/%s/%s" seçin. issues.review.review=Gözden Geçir @@ -1745,6 +1840,7 @@ issues.review.requested=İnceleme bekliyor issues.review.rejected=Değişiklik istendi issues.review.stale=Onaydan sonra güncellendi issues.review.unofficial=Sayılmamış onay +issues.assignee.error=Beklenmeyen bir hata nedeniyle tüm atananlar eklenemedi. issues.reference_issue.body=Gövde issues.content_history.deleted=silindi issues.content_history.edited=düzenlendi @@ -1761,6 +1857,7 @@ pulls.desc=Değişiklik isteklerini ve kod incelemelerini etkinleştir. pulls.new=Yeni Değişiklik İsteği pulls.new.blocked_user=Değişiklik isteği oluşturulamıyor, depo sahibi tarafından engellenmişsiniz. pulls.new.must_collaborator=Değişiklik isteği oluşturmak için bir katkıcı olmalısınız. +pulls.edit.already_changed=Değişiklik isteğine yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın. pulls.view=Değişiklik İsteği Görüntüle pulls.compare_changes=Yeni Değişiklik İsteği pulls.allow_edits_from_maintainers=Bakımcıların düzenlemelerine izin ver @@ -1781,9 +1878,11 @@ pulls.show_all_commits=Tüm işlemeleri göster pulls.show_changes_since_your_last_review=Son incelemenizden sonraki değişiklikleri göster pulls.showing_only_single_commit=Sadece %[1]s işlemesindeki değişiklikler gösteriliyor pulls.showing_specified_commit_range=%[1]s..%[2]s arasındaki değişiklikler gösteriliyor +pulls.select_commit_hold_shift_for_range=İşleme seç. Bir aralık seçmek için Shift'e basılı tutup tıklayın. pulls.review_only_possible_for_full_diff=İnceleme sadece tam fark görüntülemede mümkündür pulls.filter_changes_by_commit=İşleme ile süz pulls.nothing_to_compare=Bu dallar eşit. Değişiklik isteği oluşturmaya gerek yok. +pulls.nothing_to_compare_have_tag=Seçili dal/etiket aynı. pulls.nothing_to_compare_and_allow_empty_pr=Bu dallar eşittir. Bu Dİ boş olacak. pulls.has_pull_request=`Bu dallar arasında zaten bir değişiklik isteği var: %[2]s#%[3]d` pulls.create=Değişiklik İsteği Oluştur @@ -1808,6 +1907,7 @@ pulls.add_prefix=%s ön ekini ekle pulls.remove_prefix=%s ön ekini kaldır pulls.data_broken=Bu değişiklik isteği, çatallama bilgilerinin eksik olması nedeniyle bozuldu. pulls.files_conflicted=Bu değişiklik isteğinde, hedef dalla çakışan değişiklikler var. +pulls.is_checking=Birleştirme çakışması denetleniyor… pulls.is_ancestor=Bu dal zaten hedef dalda mevcut. Birleştirilecek bir şey yok. pulls.is_empty=Bu daldaki değişiklikler zaten hedef dalda mevcut. Bu boş bir işleme olacaktır. pulls.required_status_check_failed=Bazı gerekli denetimler başarılı olmadı. @@ -1831,12 +1931,16 @@ pulls.reject_count_1=%d değişiklik isteği pulls.reject_count_n=%d değişiklik isteği pulls.waiting_count_1=%d bekleyen inceleme pulls.waiting_count_n=%d bekleyen inceleme +pulls.wrong_commit_id=işleme kimliği, hedef daldaki bir işleme kimliği olmalıdır pulls.no_merge_desc=Tüm depo birleştirme seçenekleri devre dışı bırakıldığından, bu değişiklik isteği birleştirilemez. pulls.no_merge_helper=Depo ayarlarındaki birleştirme seçeneklerini etkinleştirin veya değişiklik isteğini el ile birleştirin. pulls.no_merge_wip=Bu değişiklik isteği birleştirilemez çünkü devam eden bir çalışma olarak işaretlendi. +pulls.no_merge_not_ready=Bu değişiklik isteği birleştirilmeye hazır değil, inceleme durumunu ve durum kontrollerini kontrol edin. pulls.no_merge_access=Bu değişiklik isteğini birleştirme yetkiniz yok. pulls.merge_pull_request=Birleştirme işlemi oluştur +pulls.rebase_merge_pull_request=Yeniden yapılandır ve ileri sar +pulls.rebase_merge_commit_pull_request=Yeniden yapılandır ve birleştirme işlemi oluştur pulls.squash_merge_pull_request=Ezme işlemi oluştur pulls.fast_forward_only_merge_pull_request=Sadece ileri sarma pulls.merge_manually=Elle birleştirildi @@ -1844,10 +1948,17 @@ pulls.merge_commit_id=Birleştirme işlemesi kimliği pulls.require_signed_wont_sign=Dal imzalı işlemeler gerektiriyor, ancak bu birleştirme imzalanmayacak pulls.invalid_merge_option=Bu değişiklik isteği için bu birleştirme seçeneğini kullanamazsınız. +pulls.merge_conflict=Birleştirme Başarısız Oldu: Birleştirme sırasında bir çakışma oldu. İpucu: Farklı bir strateji deneyin. pulls.merge_conflict_summary=Hata Mesajı +pulls.rebase_conflict=Birleştirme Başarısız: Yeniden yapılandırma işlemesi sırasında bir çakışma oldu: %[1]s. İpucu: Farklı bir strateji deneyin. pulls.rebase_conflict_summary=Hata Mesajı +pulls.unrelated_histories=Birleştirme Başarısız: Birleştirmenin ana ve tabanı ortak bir geçmişi paylaşmıyor. İpucu: Farklı bir strateji deneyin. +pulls.merge_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, taban güncellendi. İpucu: Tekrar deneyin. +pulls.head_out_of_date=Birleştirme Başarısız: Birleştirme oluşturulurken, ana güncellendi. İpucu: Tekrar deneyin. +pulls.has_merged=Başarısız: Değişiklik isteği birleştirildi, yeniden birleştiremez veya hedef dalı değiştiremezsiniz. pulls.push_rejected=Gönderme Başarısız Oldu: Gönderme reddedildi. Bu depo için Git İstemcilerini inceleyin. pulls.push_rejected_summary=Tam Red Mesajı +pulls.push_rejected_no_message=Gönderme Başarısız Oldu: Gönderme reddedildi, ancak uzak bir mesaj yoktu. Bu depo için Git İstemcilerini inceleyin pulls.open_unmerged_pull_exists=`Aynı özelliklere sahip bekleyen bir değişiklik isteği (#%d) olduğundan yeniden açma işlemini gerçekleştiremezsiniz.` pulls.status_checking=Bazı denetlemeler beklemede pulls.status_checks_success=Tüm denetlemeler başarılı oldu @@ -1866,11 +1977,14 @@ pulls.outdated_with_base_branch=Bu dal, temel dal ile güncel değil pulls.close=Değişiklik İsteğini Kapat pulls.closed_at=`%[2]s değişiklik isteğini kapattı` pulls.reopened_at=`%[2]s değişiklik isteğini yeniden açtı` +pulls.cmd_instruction_hint=Komut satırı talimatlarını görüntüleyin pulls.cmd_instruction_checkout_title=Çekme pulls.cmd_instruction_checkout_desc=Proje deponuzdan yeni bir dalı çekin ve değişiklikleri test edin. pulls.cmd_instruction_merge_title=Birleştir pulls.cmd_instruction_merge_desc=Değişiklikleri birleştirin ve Gitea'da güncelleyin. +pulls.cmd_instruction_merge_warning=Uyarı: Bu işlem değişiklik isteğini birleştiremez, çünkü "kendiliğinden algılamalı elle birleştirme " etkin değil pulls.clear_merge_message=Birleştirme iletilerini temizle +pulls.clear_merge_message_hint=Birleştirme iletisini temizlemek sadece işleme ileti içeriğini kaldırır ama üretilmiş "Co-Authored-By…" gibi git fragmanlarını korur. pulls.auto_merge_button_when_succeed=(Denetlemeler başarılı olduğunda) pulls.auto_merge_when_succeed=Tüm denetlemeler başarılı olduğundan otomatik olarak birleştir @@ -1888,8 +2002,14 @@ pulls.delete.title=Bu değişiklik isteği silinsin mi? pulls.delete.text=Bu değişiklik isteğini gerçekten silmek istiyor musunuz? (Bu işlem tüm içeriği kalıcı olarak silecektir. Arşivde tutma niyetiniz varsa silmek yerine kapatmayı düşünün) pulls.recently_pushed_new_branches=%[1]s dalına ittiniz %[2]s +pulls.upstream_diverging_prompt_behind_1=Bu dal, %[2]s dalının %[1]d işlem gerisinde +pulls.upstream_diverging_prompt_behind_n=Bu dal, %[2]s dalının %[1]d işleme gerisinde +pulls.upstream_diverging_prompt_base_newer=Temel dal %s yeni değişikliğe sahip +pulls.upstream_diverging_merge=Çatalı eşle +pulls.upstream_diverging_merge_confirm=`"%[1]s" dalını "%[2]s" dalına birleştirmek ister misiniz?` pull.deleted_branch=(silindi): %s +pull.agit_documentation=AGit hakkındaki belgeleri gözden geçirin comments.edit.already_changed=Yoruma yapılan değişiklikler kaydedilemiyor. İçerik başka kullanıcı tarafından değiştirilmiş gözüküyor. Diğerlerinin değişikliklerinin üzerine yazmamak için lütfen sayfayı yenileyin ve tekrar düzenlemeye çalışın @@ -1900,6 +2020,7 @@ milestones.no_due_date=Bitiş tarihi yok milestones.open=Aç milestones.close=Kapat milestones.new_subheader=Kilometre taşları konuları yönetmenize ve gelişmelerini takip etmenize yardımcı olur. +milestones.completeness=%d%% Tamamlandı milestones.create=Kilometre Taşı Oluştur milestones.title=Başlık milestones.desc=Açıklama @@ -1924,10 +2045,12 @@ milestones.filter_sort.most_issues=En çok konu milestones.filter_sort.least_issues=En az konu signing.will_sign=Bu işleme "%s" anahtarıyla imzalanacak. +signing.wont_sign.error=İşlemenin imzalanıp imzalanamayacağını kontrol ederken bir hata oluştu. signing.wont_sign.nokey=Bu işlemeyi imzalamak için anahtar yok. signing.wont_sign.never=İşlemeler asla imzalanmaz. signing.wont_sign.always=İşlemeler her zaman imzalanır. signing.wont_sign.pubkey=Hesabınızla ilişkilendirilmiş bir ortak anahtarınız olmadığı için işleme imzalanmayacak. +signing.wont_sign.twofa=İşlemelerin imzalanması için iki aşamalı kimlik doğrulamayı etkinleştirmelisiniz. signing.wont_sign.parentsigned=Üst işleme imzalanmadığı için bu işleme imzalanmayacak. signing.wont_sign.basesigned=Temel işleme imzalanmadığı için birleştirme imzalanmayacak. signing.wont_sign.headsigned=Ana işleme imzalanmadığı için birleştirme imzalanmayacak. @@ -2013,6 +2136,7 @@ activity.title.releases_1=%d Sürüm activity.title.releases_n=%d Sürüm activity.title.releases_published_by=%s %s tarafından yayınlandı activity.published_release_label=Yayınlandı +activity.no_git_activity=Bu dönemde herhangi bir işleme yapılmamıştır. activity.git_stats_exclude_merges=Birleştirmeler hariç, activity.git_stats_author_1=%d yazar activity.git_stats_author_n=%d yazar @@ -2040,14 +2164,21 @@ contributors.contribution_type.additions=Eklemeler contributors.contribution_type.deletions=Silmeler settings=Ayarlar +settings.desc=Ayarlar, deponun ayarlarını yönetebileceğiniz yerdir. settings.options=Depo settings.public_access=Herkese Açık Erişim +settings.public_access_desc=Bu depodaki varsayılanları değiştirmek için dışarıdan gelen ziyaretçilerin erişim izinlerini yapılandırın. +settings.public_access.docs.not_set=Ayarlanmazsa: ek bir herkese açık erişim izni yok. Ziyaretçinin izni deponun görünürlük ve üye izinlerini kullanır. +settings.public_access.docs.anonymous_read=Anonim Okuma: oturum açmamış kullanıcılar birime okuma izniyle erişebilir. +settings.public_access.docs.everyone_read=Herkes Okuyabilir: tüm oturum açmış kullanıcılar birime okuma izniyle erişebilir. Konu/değişiklik istekleri için okuma izni ayrıca kullanıcıların yeni konu/değişiklik isteği oluşturabileceği anlamına gelir. +settings.public_access.docs.everyone_write=Herkes Yazabilir: tüm oturum açmış kullanıcılar birimde yazma iznine sahiptir. Sadece Viki birimi bu izni destekliyor. settings.collaboration=Katkıcılar settings.collaboration.admin=Yönetici settings.collaboration.write=Yazma settings.collaboration.read=Okunmuş settings.collaboration.owner=Sahibi settings.collaboration.undefined=Tanımsız +settings.collaboration.per_unit=Birim İzinleri settings.hooks=Web İstemcileri settings.githooks=Git İstemcileri settings.basic_settings=Temel Ayarlar @@ -2057,6 +2188,7 @@ settings.mirror_settings.docs.disabled_pull_mirror.instructions=Projenizi işlem settings.mirror_settings.docs.disabled_push_mirror.instructions=Projenizi işlemeleri, etiketleri ve dalları başka bir depodan otomatik olarak çekecek şekilde kurun. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=Şu an bu sadece "Yeni Göç" menüsüyle yapılabilir. Daha fazla bilgi için, lütfen şuraya danışın: settings.mirror_settings.docs.disabled_push_mirror.info=Gönderme yansıları site yöneticiniz tarafından devre dışı bırakılmıştır. +settings.mirror_settings.docs.no_new_mirrors=Deponuz değişiklikleri başka bir depoyla yansılıyor. Şu an başka bir yansı oluşturamayacağınızı unutmayın. settings.mirror_settings.docs.can_still_use=Her ne kadar mevcut yansıları değiştiremiyor veya yeni yansı oluşturamıyor olsanız da, hala mevcut yansıyı kullanabilirsiniz. settings.mirror_settings.docs.pull_mirror_instructions=Çekme yansıyı kurmak için, lütfen şuraya danışın: settings.mirror_settings.docs.more_information_if_disabled=İtme ve çekme yansıları hakkında daha fazla bilgiye şuradan ulaşabilirsiniz: @@ -2117,6 +2249,7 @@ settings.pulls.default_delete_branch_after_merge=Varsayılan olarak birleştirme settings.pulls.default_allow_edits_from_maintainers=Bakımcıların düzenlemelerine izin ver settings.releases_desc=Depo Sürümlerini Etkinleştir settings.packages_desc=Depo Paket Kütüğünü Etkinleştir +settings.projects_desc=Projeleri Etkinleştir settings.projects_mode_desc=Proje Modu (ne tür projeler görüntülensin) settings.projects_mode_repo=Sadece depo projeleri settings.projects_mode_owner=Sadece kullanıcı veya organizasyon projeleri @@ -2130,6 +2263,7 @@ settings.admin_indexer_commit_sha=Son Dizinlenen SHA settings.admin_indexer_unindexed=Dizinlenmemiş settings.reindex_button=Yeniden Dizinleme Kuyruğuna Ekle settings.reindex_requested=Yeniden Dizinleme İstendi +settings.admin_enable_close_issues_via_commit_in_any_branch=Varsayılan olmayan bir dalda yapılan bir işlemeyle bir konuyu kapat settings.danger_zone=Tehlike Alanı settings.new_owner_has_same_repo=Yeni sahibin aynı isimde başka bir deposu var. Lütfen farklı bir isim seçin. settings.convert=Düzenli Depoya Dönüştür @@ -2151,9 +2285,11 @@ settings.transfer_abort_invalid=Var olmayan bir depo aktarımını iptal edemezs settings.transfer_abort_success=%s tarafına yapılan depo aktarımı başarıyla iptal edildi. settings.transfer_desc=Bu depoyu bir kullanıcıya veya yönetici haklarına sahip olduğunuz bir organizasyona aktarın. settings.transfer_form_title=Onaylamak için depo adını girin: +settings.transfer_in_progress=Şu anda devam etmekte olan bir aktarım mevcut. Eğer bu depoyu başka bir kullanıcıya aktarmak istiyorsanız mevcut aktarımı iptal edin. settings.transfer_notices_1=- Bireysel bir kullanıcıya aktarırsanız depoya erişiminizi kaybedersiniz. settings.transfer_notices_2=- Sahip (-yardımcı) olduğunuz bir organizasyona devrederseniz, depoya erişmeye devam edersiniz. settings.transfer_notices_3=- Depo özelse ve bireysel bir kullanıcıya aktarılmışsa, bu eylem kullanıcının en azından okuma iznine sahip olmasını sağlar (ve gerekirse izinleri değiştirir). +settings.transfer_notices_4=- Eğer depo bir organizasyona aitse ve onu başka bir organizasyon veya kişiye aktarırsanız, deponun konuları ve organizasyonun proje panosu arasındaki bağlantıları yitireceksiniz. settings.transfer_owner=Yeni Sahip settings.transfer_perform=Aktarımı Gerçekleştir settings.transfer_started=Bu depo aktarılmak üzere işaretlendi ve "%s" tarafından onay bekliyor @@ -2164,9 +2300,13 @@ settings.trust_model.default=Varsayılan Güven Modeli settings.trust_model.default.desc=Bu kurulum için varsayılan depo güven modelini kullanın. settings.trust_model.collaborator=Katkıcı settings.trust_model.collaborator.long=Katkıcı: Katkıcıların imzalarına güvenin +settings.trust_model.collaborator.desc=Bu deponun katkıcılarının geçerli imzaları, işleyici ile eşleşse de eşleşmese de, "güvenilir" olarak işaretlenecektir. Aksi takdirde, imzanın işleyiciyle eşleşmesi durumunda geçerli imzalar "güvenilmez", eşleşmiyorsa "eşleşmemiş" olarak işaretlenir. settings.trust_model.committer=İşleyici +settings.trust_model.committer.long=İşleyici: İşleyicilerle eşleşen imzalara güvenin. Bu GitHub'ın davranışına uygundur ve Gitea imzalı işlemeleri işleyen olarak Gitea'ya sahip olmaya zorlar. +settings.trust_model.committer.desc=Geçerli imzalar yalnızca işleyiciyle eşleşiyorsa "güvenilir" olarak işaretlenir, aksi takdirde "eşleşmemiş" olarak işaretlenir. Bu, Gitea'yı işlemede Ortak Yazan: ve Ortak İşlenen: fragmanı olarak işaretlenen gerçek kaydediciyle imzalanan işlemelerde işleyici olmayı zorlayacaktır. Varsayılan Gitea anahtarı, veritabanındaki bir Kullanıcıyla eşleşmelidir. settings.trust_model.collaboratorcommitter=Katkıcı+İşleyici settings.trust_model.collaboratorcommitter.long=Katkıcı+İşleyen: İşleyenle eşleşen katkıcıların imzalarına güvenin +settings.trust_model.collaboratorcommitter.desc=Bu deponun katkıcılarının geçerli imzaları, işleyici ile eşleşiyorlarsa "güvenilir" olarak işaretlenecektir. Aksi takdirde, imza işleyiciyle eşleşiyorsa geçerli imzalar "güvenilmez", aksi takdirde "eşleşmiyor" olarak işaretlenir. Bu, Gitea'yı işlemede Ortak Yazan: ve Ortak İşlenen: fragmanı olarak işaretlenmiş gerçek işleyici ile imzalı işlemelerde işleyici olarak işaretlenmeye zorlayacaktır. Varsayılan Gitea anahtarı, veritabanındaki bir Kullanıcıyla eşleşmelidir. settings.wiki_delete=Wiki Verisini Sil settings.wiki_delete_desc=Depo wiki verilerini silmek kalıcıdır ve geri alınamaz. settings.wiki_delete_notices_1=- Bu işlem, %s için depo wiki'sini kalıcı olarak siler ve devre dışı bırakır. @@ -2175,6 +2315,7 @@ settings.wiki_deletion_success=Depo wiki verisi silindi. settings.delete=Bu Depoyu Sil settings.delete_desc=Bir depoyu silmek kalıcıdır ve geri alınamaz. settings.delete_notices_1=- Bu işlem geri ALINAMAZ. +settings.delete_notices_2=- Bu işlem, kod, sorunlar, yorumlar, wiki verileri ve katkıcı ayarları dahil olmak üzere %s deposunu kalıcı olarak siler. settings.delete_notices_fork_1=- Silme işleminden sonra bu deponun çatalları bağımsız hale gelecektir. settings.deletion_success=Depo silindi. settings.update_settings_success=Depo ayarları güncellendi. @@ -2196,6 +2337,8 @@ settings.team_not_in_organization=Takım, depo ile aynı organizasyonda değil settings.teams=Takımlar settings.add_team=Takım Ekle settings.add_team_duplicate=Takım zaten bu depoya sahip +settings.add_team_success=Takım artık bu depoya erişebilir. +settings.change_team_permission_tip=Takımın izni takım ayarı sayfasında ayarlanır ve depo başına değiştirilemez settings.delete_team_tip=Bu takımın tüm depolara erişimi var ve kaldırılamıyor settings.remove_team_success=Takımın depoya erişimi kaldırıldı. settings.add_webhook=Web İsteği Ekle @@ -2204,6 +2347,8 @@ settings.hooks_desc=Web istemcileri, belirli Gitea olayları tetiklendiğinde ot settings.webhook_deletion=Web İsteğini Sil settings.webhook_deletion_desc=Bir web isteğini kaldırmak, ayarlarını ve teslimat geçmişini siler. Devam edilsin mi? settings.webhook_deletion_success=Web isteği silindi. +settings.webhook.test_delivery=İtme Olayını Sına +settings.webhook.test_delivery_desc=Bu web istemcisini sahte bir itme olayıyla sınayın. settings.webhook.test_delivery_desc_disabled=Bu web istemcisini sahte bir olayla denemek için etkinleştirin. settings.webhook.request=İstekler settings.webhook.response=Cevaplar @@ -2223,6 +2368,7 @@ settings.payload_url=Hedef URL settings.http_method=HTTP Yöntemi settings.content_type=POST İçerik Türü settings.secret=Gizli +settings.webhook_secret_desc=Eğer web isteği sunucusu gizli anahtar kullanımını destekliyorsa, web isteği kılavuzunu takip ederek buraya gizli anahtarı girebilirsiniz. settings.slack_username=Kullanıcı Adı settings.slack_icon_url=Simge Bağlantısı settings.slack_color=Renk @@ -2241,6 +2387,8 @@ settings.event_fork=Çatalla settings.event_fork_desc=Depo çatallandı. settings.event_wiki=Viki settings.event_wiki_desc=Viki sayfası oluşturuldu, adı değiştirildi, düzenlendi veya silindi. +settings.event_statuses=Durumlar +settings.event_statuses_desc=İşleme Durumu API aracılığıyla güncellendi. settings.event_release=Sürüm settings.event_release_desc=Sürüm yayınlandığında, güncellendiğinde veya silindiğinde. settings.event_push=Çek @@ -2250,6 +2398,7 @@ settings.event_repository=Depo settings.event_repository_desc=Depo oluşturuldu veya silindi. settings.event_header_issue=Konu Olayları settings.event_issues=Konular +settings.event_issues_desc=Konu açıldı, kapatıldı, yeniden açıldı veya düzenlendi. settings.event_issue_assign=Konu Atandı settings.event_issue_assign_desc=Konu atandı veya atanmadı. settings.event_issue_label=Konu Etiketlendi @@ -2260,6 +2409,7 @@ settings.event_issue_comment=Konu Yorumu settings.event_issue_comment_desc=Konu yorumu eklendiğinde, düzenlendiğinde veya silindiğinde. settings.event_header_pull_request=Değişiklik İsteği Olayları settings.event_pull_request=İstek Çek +settings.event_pull_request_desc=Değişiklik isteği açıldı, kapatıldı, yeniden açıldı veya düzenlendi. settings.event_pull_request_assign=Değişiklik İsteği Atandı settings.event_pull_request_assign_desc=Değişiklik isteği atanmış veya atanmamış. settings.event_pull_request_label=Değişiklik İsteği Etiketlendi @@ -2276,10 +2426,14 @@ settings.event_pull_request_review_request=Değişiklik İsteği İncelemesi İs settings.event_pull_request_review_request_desc=Değişiklik isteği incelemesi istendi veya inceleme isteği kaldırıldı. settings.event_pull_request_approvals=Değişiklik İsteği Onayları settings.event_pull_request_merge=Değişiklik İsteği Birleştirme +settings.event_header_workflow=İş Akışı Olayları +settings.event_workflow_run=İş Akışı Çalışması +settings.event_workflow_run_desc=Gitea Eylemleri İş Akışı çalışması kuyruğa alındı, bekliyor, sürüyor veya tamamlandı. +settings.event_workflow_job=İş Akışı İşleri +settings.event_workflow_job_desc=Gitea Eylemleri İş Akışı işi kuyruğa alındı, bekliyor, çalışıyor veya tamamlandı. settings.event_package=Paket settings.event_package_desc=Bir depoda paket oluşturuldu veya silindi. settings.branch_filter=Dal filtresi -settings.branch_filter_desc=Gönderme, dal oluşturma ve dal silme olayları için glob deseni olarak belirtilen dal beyaz listesi. Boşsa veya * ise, tüm dallar için olaylar raporlanır. Sözdizimi için %[2]s belgelerine bakın. Örnekler: master, {master,release*}. settings.authorization_header=Yetkilendirme Başlığı settings.authorization_header_desc=Mevcutsa isteklere yetkilendirme başlığı olarak eklenecektir. Örnekler: %s. settings.active=Etkin @@ -2328,6 +2482,10 @@ settings.branches=Dallar settings.protected_branch=Dal Koruması settings.protected_branch.save_rule=Kuralı Kaydet settings.protected_branch.delete_rule=Kural sil +settings.protected_branch_can_push=İtmeye izin verilsin mi? +settings.protected_branch_can_push_yes=İtebilirsiniz +settings.protected_branch_can_push_no=İtemezsiniz +settings.branch_protection=%s dalı için Dal Koruması settings.protect_this_branch=Dal Korumayı Etkinleştir settings.protect_this_branch_desc=Silmeyi önler ve dala Git gönderimini ve birleştirmesini kısıtlar. settings.protect_disable_push=İtmeyi Devre Dışı Bırak @@ -2357,11 +2515,13 @@ settings.protect_merge_whitelist_teams=Birleştirme için izin listesindeki tak settings.protect_check_status_contexts=Durum Denetimini Etkinleştir settings.protect_status_check_patterns=Durum denetleme desenleri: settings.protect_status_check_patterns_desc=Bu kurala uyan dala diğer dallar birleştirilmeden önce başarılı olması gereken durum denetlemelerini belirten desenleri girin. Her bir satır bir desen tanımlıyor. Desenler boş olamaz. +settings.protect_check_status_contexts_desc=Birleştirmeden önce durum denetimlerinin geçmesini zorunlu kılın. Dalların bu kurala uyan bir dalda birleştirilebilmesi için hangi durum denetimlerinin geçmesi gerektiğini seçin. Etkinleştirildiğinde, işlemeler önce başka bir dala gönderilmeli, ardından durum denetimleri geçtikten sonra bu kuralla eşleşen bir dala birleştirilmeli veya doğrudan gönderilmelidir. Hiçbir bağlam seçilmezse, bağlamdan bağımsız olarak son işleme başarılı olmalıdır. settings.protect_check_status_contexts_list=Bu depo için geçen haftadaki durum denetimleri settings.protect_status_check_matched=Eşleşen settings.protect_invalid_status_check_pattern=Hatalı durum denetleme deseni: "%s". settings.protect_no_valid_status_check_patterns=Geçerli durum denetleme deseni yok. settings.protect_required_approvals=Gerekli onaylar: +settings.protect_required_approvals_desc=Değişiklik isteğini yalnızca yeterince olumlu yorumla birleştirmeye izin ver. settings.protect_approvals_whitelist_enabled=Onayları izin listesine giren kullanıcılar veya takımlar için kısıtla settings.protect_approvals_whitelist_enabled_desc=Yalnızca izin listesindeki kullanıcıların veya takımların gözden geçirmeleri gerekli onaylar için dikkate alınır. Onaylı izin listesi olmadan, yazma erişimi olan herkesin gözden geçirmeleri gerekli onaylar için dikkate alınır. settings.protect_approvals_whitelist_users=İzin listesindeki gözden geçirenler: @@ -2373,12 +2533,18 @@ settings.ignore_stale_approvals_desc=Daha eski işlemelere (eski incelemelere) y settings.require_signed_commits=İmzalı İşleme Gerekli settings.require_signed_commits_desc=Reddetme, onlar imzasızsa veya doğrulanamazsa bu dala gönderir. settings.protect_branch_name_pattern=Korunmuş Dal Adı Deseni +settings.protect_branch_name_pattern_desc=Korunmuş dal isim desenleri. Desen sözdizimi için belgelere bakabilirsiniz. Örnekler: main, release/** settings.protect_patterns=Desenler settings.protect_protected_file_patterns=Korumalı dosya kalıpları (noktalı virgülle ayrılmış ';'): +settings.protect_protected_file_patterns_desc=Kullanıcının bu dalda dosya ekleme, düzenleme veya silme hakları olsa bile doğrudan değiştirilmesine izin verilmeyen korumalı dosyalar. Birden çok desen noktalı virgül (';') kullanılarak ayrılabilir. Desen sözdizimi için github.com/gobwas/glob belgelerine bakın. Örnekler: .drone.yml, /docs/**/*.txt. settings.protect_unprotected_file_patterns=Korunmasız dosya desenleri (noktalı virgülle ayrılmış ';'): +settings.protect_unprotected_file_patterns_desc=Kullanıcının yazma erişimi, itme kısıtlamasını atlama hakkı olduğunda doğrudan değiştirmesine izin verilen korunmasız dosyalar. Birden çok desen noktalı virgül (';') kullanılarak ayrılabilir. Desen söz dizimi için github.com/gobwas/glob belgelerine bakın. Örnekler: .drone.yml, /docs/**/*.txt. +settings.add_protected_branch=Korumayı etkinleştir +settings.delete_protected_branch=Korumayı devre dışı bırak settings.update_protect_branch_success=Dal koruma kuralı "%s" güncellendi. settings.remove_protected_branch_success=Dal koruma kuralı "%s" kaldırıldı. settings.remove_protected_branch_failed=Dal koruma kuralı "%s" kaldırılamadı. +settings.protected_branch_deletion=Dal Korumasını Sil settings.protected_branch_deletion_desc=Dal korumasını devre dışı bırakmak, kullanıcıların dalı itmek için yazma izni olmasını sağlar. Devam edilsin mi? settings.block_rejected_reviews=Reddedilen incelemelerde birleştirmeyi engelle settings.block_rejected_reviews_desc=Yeterli onay olsa bile resmi gözden geçirenler tarafından değişiklik istendiğinde birleşme mümkün olmayacaktır. @@ -2386,8 +2552,11 @@ settings.block_on_official_review_requests=Resmi inceleme isteklerinde birleşti settings.block_on_official_review_requests_desc=Yeterli onay olsa bile, resmi inceleme istekleri olduğunda birleştirme mümkün olmayacaktır. settings.block_outdated_branch=Değişiklik isteği güncel değilse birleştirmeyi engelle settings.block_outdated_branch_desc=Baş dal taban dalın arkasındayken birleştirme mümkün olmayacaktır. +settings.block_admin_merge_override=Yöneticiler dal koruma kurallarına uymalıdır +settings.block_admin_merge_override_desc=Yöneticiler dal koruma kurallarına uymalıdır ve kurallardan kaçınamazlar. settings.default_branch_desc=Değişiklik istekleri ve kod işlemeleri için varsayılan bir depo dalı seçin: settings.merge_style_desc=Biçimleri Birleştir +settings.default_merge_style_desc=Değişiklik istekleri için varsayılan birleştirme tarzı settings.choose_branch=Bir dal seç… settings.no_protected_branch=Korumalı dal yok. settings.edit_protected_branch=Düzenle @@ -2403,12 +2572,25 @@ settings.tags.protection.allowed.teams=İzin verilen takımlar settings.tags.protection.allowed.noone=Hiç kimse settings.tags.protection.create=Etiketi Koru settings.tags.protection.none=Korumalı etiket yok. +settings.tags.protection.pattern.description=Birden çok etiketi eşleştirmek için tek bir ad, glob deseni veya normal ifade kullanabilirsiniz. Daha fazlası için korunan etiketler rehberini okuyun. settings.bot_token=Bot Jetonu settings.chat_id=Sohbet Kimliği settings.thread_id=İş Parçacığı ID settings.matrix.homeserver_url=Ev sunucusu URL'si settings.matrix.room_id=Oda Kimliği settings.matrix.message_type=Mesaj Türü +settings.visibility.private.button=Özel Yap +settings.visibility.private.text=Görünürlüğü özele çevirmek depoyu sadece izin verilen üyeler görecek ancak kendisiyle çatalları, izleyenler ve yıldızlar arasındaki ilişkiyi ortadan kaldırabilir. +settings.visibility.private.bullet_title=Görünürlüğü özele çevirmek: +settings.visibility.private.bullet_one=Depoyu sadece izin verilen kullanıcılar görecek. +settings.visibility.private.bullet_two=Kendisiyle çatalları, izleyenler, ve yıldızlar arasındaki ilişkiyi ortadan kaldırabilir. +settings.visibility.public.button=Açık Yap +settings.visibility.public.text=Görünürlüğü açık yaptığınızda depo herkes tarafından görünecektir. +settings.visibility.public.bullet_title=Görünürlüğü açığa çevirmek: +settings.visibility.public.bullet_one=Depo herkes tarafından görünecektir. +settings.visibility.success=Depo görünürlüğü değiştirildi. +settings.visibility.error=Depo görünürlüğünü değiştirmeye çalışırken bir hata oluştu. +settings.visibility.fork_error=Çatallanmış bir deponun görünürlüğü değiştirilemez. settings.archive.button=Depoyu Arşivle settings.archive.header=Bu Depoyu Arşivle settings.archive.text=Depoyu arşivlemek onu tamamen salt okunur yapacaktır. Panoda gizlenecektir. Hiç kimse (siz bile) yeni işleme yapamayacak veya yeni konu veya değişiklik isteği açamayacak. @@ -2420,6 +2602,7 @@ settings.archive.tagsettings_unavailable=Depo arşivlenmişse etiket ayarları k settings.archive.mirrors_unavailable=Depo arşivlenmişse yansılar kullanılamaz. settings.unarchive.button=Depoyu Arşivden Çıkar settings.unarchive.header=Bu Depoyu Arşivden Çıkar +settings.unarchive.text=Depoyu arşivden çıkarmak, yeni sorunların ve değişiklik isteklerinin yanı sıra işleme ve itme yeteneğini de geri kazandıracaktır. settings.unarchive.success=Depo başarıyla arşivden çıkarıldı. settings.unarchive.error=Depoyu arşivden çıkarmaya çalışırken bir hata oluştu. Daha fazla ayrıntı için günlüğe bakın. settings.update_avatar_success=Depo resmi güncellendi. @@ -2437,9 +2620,11 @@ settings.lfs_invalid_locking_path=Geçersiz yol: %s settings.lfs_invalid_lock_directory=Dizin kilitlenemiyor: %s settings.lfs_lock_already_exists=Kilit zaten var: %s settings.lfs_lock=Kilitle +settings.lfs_lock_path=Kilitlenecek dosya yolu… settings.lfs_locks_no_locks=Kilit yok settings.lfs_lock_file_no_exist=Kilitli dosya varsayılan dalda mevcut değil settings.lfs_force_unlock=Kilidi Açmaya Zorla +settings.lfs_pointers.found=Bulunan %d blob işaretçi(leri) - %d ilişkili, %d ilişkilendirilmemiş (%d mağazadan eksik) settings.lfs_pointers.sha=Blob SHA settings.lfs_pointers.oid=OID settings.lfs_pointers.inRepo=Depoda @@ -2507,6 +2692,9 @@ diff.image.overlay=Arayüz diff.has_escaped=Bu satırda gizli evrensel kod karakterler var diff.show_file_tree=Dosya ağacını göster diff.hide_file_tree=Dosya ağacını gizle +diff.submodule_added=%[1]s alt modülü eklendi: %[2]s +diff.submodule_deleted=%[1]s alt modülü silindi: %[2]s +diff.submodule_updated=%[1]s alt modülü güncellendi: %[2]s releases.desc=Proje sürümlerini ve indirmeleri takip edin. release.releases=Sürümler @@ -2516,6 +2704,7 @@ release.new_release=Yeni Sürüm release.draft=Taslak release.prerelease=Ön Sürüm release.stable=Kararlı +release.latest=En son release.compare=Karşılaştır release.edit=düzenle release.ahead.commits=%d işleme @@ -2576,6 +2765,7 @@ branch.restore_success=`"%s" dalı geri yüklendi.` branch.restore_failed=`"%s" dalı geri yüklenemedi.` branch.protected_deletion_failed=`"%s" dalı korunuyor. Silinemez.` branch.default_deletion_failed=`"%s" dalı varsayılan daldır. Silinemez.` +branch.default_branch_not_exist=Varsayılan dal "%s" mevcut değil. branch.restore=`"%s" Dalını Geri Yükle` branch.download=`"%s" Dalını İndir` branch.rename=`"%s" Dalının Adını Değiştir` @@ -2590,6 +2780,10 @@ branch.create_branch_operation=Dal oluştur branch.new_branch=Yeni dal oluştur branch.new_branch_from=`"%s" dalından yeni dal oluştur` branch.renamed=%s dalının adı %s olarak değiştirildi. +branch.rename_default_or_protected_branch_error=Varsayılan veya korunan dalların adını sadece yöneticiler değiştirebilir. +branch.rename_protected_branch_failed=Bu dal glob tabanlı koruma kurallarıyla korunuyor. +branch.commits_divergence_from=İşleme farklılığı: %[3]s dalının %[1]d işleme gerisinde ve %[2]d işleme ilerisinde +branch.commits_no_divergence=%[1]s dalı ile aynı tag.create_tag=%s etiketi oluştur tag.create_tag_operation=Etiket oluştur @@ -2600,8 +2794,10 @@ tag.create_success=`"%s" etiketi oluşturuldu.` topic.manage_topics=Konuları Yönet topic.done=Bitti +topic.count_prompt=25'ten fazla konu seçemezsiniz topic.format_prompt=Konular bir harf veya rakamla başlamalı, kısa çizgi ('-') ve nokta ('.') içerebilir ve en fazla 35 karakter uzunluğunda olabilir. Harfler küçük harf olmalıdır. +find_file.follow_symlink=Bu sembolik bağlantıyı, işaret ettiği yere kadar takip edin find_file.go_to_file=Dosyaya git find_file.no_matching=Eşleşen dosya bulunamadı @@ -2611,6 +2807,7 @@ error.csv.invalid_field_count=%d satırında yanlış sayıda alan olduğundan b error.broken_git_hook=Bu deponun Git İstemcileri bozuk gibi gözüküyor. Onarmak için lütfen belgelere bakın, daha sonra durumu yenilemek için bazı işlemeler itin. [graphs] +component_loading=%s yükleniyor… component_loading_failed=%s yüklenemedi component_loading_info=Bu biraz sürebilir… component_failed_to_load=Beklenmedik bir hata oluştu. @@ -2641,6 +2838,7 @@ team_permission_desc=İzin team_unit_desc=Depo Bölümlerine Erişime İzin Ver team_unit_disabled=(Devre dışı) +form.name_been_taken=Organizasyon adı "%s" zaten kullanılıyor. form.name_reserved=`"%s" organizasyon adı rezerve edilmiştir.` form.name_pattern_not_allowed=Organizasyon adında "%s" desenine izin verilmiyor. form.create_org_not_allowed=Organizasyon oluşturmanıza izin verilmiyor. @@ -2648,11 +2846,17 @@ form.create_org_not_allowed=Organizasyon oluşturmanıza izin verilmiyor. settings=Ayarlar settings.options=Organizasyon settings.full_name=Tam İsim +settings.email=İletişim E-posta Adresi settings.website=Web Sitesi settings.location=Lokasyon settings.permission=İzinler settings.repoadminchangeteam=Depo yöneticisi takımlar için erişim ekleyebilir ve kaldırabilir settings.visibility=Görünürlük +settings.change_visibility=Görünürlüğü değiştir +settings.change_visibility_notices_1=Organizasyon özel hale getirilirse, depo yıldızları kaldırılacak ve geri alınamayacaktır. +settings.change_visibility_notices_2=Görünürlük özel olarak değiştirildiğinde, üyeler dışındakiler organizasyonun depolarına erişemez. +settings.change_visibility_success=%s organizasyonunun görünürlüğü başarıyla değiştirildi. +settings.visibility_desc=Organizasyonu ve depolarını kimlerin görüntüleyebileceğini değiştirin. settings.visibility.public=Genel settings.visibility.limited=Sınırlı (Sadece giriş yapmış kullanıcılar görebilir) settings.visibility.limited_shortname=Sınırlı @@ -2662,12 +2866,27 @@ settings.visibility.private_shortname=Özel settings.update_settings=Ayarları Güncelle settings.update_setting_success=Organizasyon ayarları güncellendi. +settings.rename=Organizasyonu Yeniden Adlandır +settings.rename_desc=Organizasyon adını değiştirmek organizasyonunuzun URL'sini de değiştirecek ve eski ismi serbest bıracaktır. +settings.rename_success=Organizasyon %[1]s, %[2]s olarak başarıyla yeniden adlandırıldı. +settings.rename_no_change=Organizasyon ismi değişmedi. +settings.rename_new_org_name=Yeni Organizasyon Adı +settings.rename_failed=İçsel bir hata nedeniyle organizasyon ad değişikliği başarısız oldu +settings.rename_notices_1=Bu işlem geri ALINAMAZ. +settings.rename_notices_2=Eski ad, başkası tarafından alınana kadar buraya yönlendirilecektir. settings.update_avatar_success=Organizasyonun resmi güncellendi. settings.delete=Organizasyonu Sil settings.delete_account=Bu Organizasyonu Sil settings.delete_prompt=Organizasyon kalıcı olarak kaldırılacaktır. Bu işlem GERİ ALINAMAZ! +settings.name_confirm=Onaylamak için organizasyon adını girin: +settings.delete_notices_1=Bu işlem geri ALINAMAZ. +settings.delete_notices_2=Bu işlem kod, sorunlar, yorumlar, viki verileri ve katkıcı ayarları dahil olmak üzere %s organizasyonunun tüm depolarını kalıcı olarak siler. +settings.delete_notices_3=Bu işlem %s organizasyonunun tüm paketlerini kalıcı olarak siler. +settings.delete_notices_4=Bu işlem %s organizasyonunun tüm projelerini kalıcı olarak siler. settings.confirm_delete_account=Silmeyi Onaylıyorum +settings.delete_failed=İçsel bir hata nedeniyle organizasyon silme başarısız oldu +settings.delete_successful=%s organizasyonu başarıyla silindi. settings.hooks_desc=Bu organizasyon altındaki tüm depolar için tetiklenecek webhook'lar ekle. settings.labels_desc=Bu organizasyonun altındaki tüm depolar ile ilgili konularda kullanılabilecek etiketler ekleyin. @@ -2693,6 +2912,7 @@ teams.leave.detail=%s bırakılsın mı? teams.can_create_org_repo=Depoları oluştur teams.can_create_org_repo_helper=Üyeler organizasyonda yeni depolar oluşturabilirler. Oluşturan yeni depoya yönetici erişimi sağlayacak. teams.none_access=Erişim Yok +teams.none_access_helper=Üyeler bu birimi görüntüleyemez veya üzerinde başka bir işlem yapamaz. teams.general_access=Genel Erişim teams.general_access_helper=Üyelerin izinleri aşağıdaki izin tablosuna göre kararlaştırılacaktır. teams.read_access=Okuma @@ -2722,6 +2942,7 @@ teams.remove_all_repos_title=Tüm takım depolarını kaldır teams.remove_all_repos_desc=Bu, tüm depoları takımdan kaldıracaktır. teams.add_all_repos_title=Tüm depoları ekle teams.add_all_repos_desc=Bu, organizasyonun tüm depolarını takıma ekleyecektir. +teams.add_nonexistent_repo=Eklemeye çalıştığınız depo mevcut değil. Lütfen önce oluşturun. teams.add_duplicate_users=Kullanıcı zaten takımın üyesi. teams.repos.none=Bu takım tarafından hiçbir depoya erişilemedi. teams.members.none=Bu takımda üye yok. @@ -2737,7 +2958,18 @@ teams.invite.title=%s takımına (Organizasyon: %sblog'a bakabilirsiniz. dashboard.statistic=Özet dashboard.maintenance_operations=Bakım İşlemleri dashboard.system_status=Sistem Durumu @@ -2781,8 +3015,11 @@ dashboard.cron.cancelled=Cron: %[1]s iptal edildi: %[3]s dashboard.cron.error=Cron Hatası: %s: %[3]s dashboard.cron.finished=Cron: %[1]s bitti dashboard.delete_inactive_accounts=Etkinleştirilmemiş tüm hesapları sil +dashboard.delete_inactive_accounts.started=Etkinleştirilmemiş tüm hesapları silme görevi başladı dashboard.delete_repo_archives=Tüm depoların arşivlerini (ZIP, TAR.GZ, vb.) sil +dashboard.delete_repo_archives.started=Tüm depo arşivlerini silme görevi başladı dashboard.delete_missing_repos=Git dosyaları eksik olan tüm depoları sil +dashboard.delete_missing_repos.started=Git dosyaları eksik olan tüm depoları silme görevi başladı dashboard.delete_generated_repository_avatars=Oluşturulan depo resimlerini sil dashboard.sync_repo_branches=Eşzamanlama git verisinden veritabanlarına dalları kaçırdı dashboard.sync_repo_tags=Etiketleri git verisinden veritabanına eşitle @@ -2790,9 +3027,17 @@ dashboard.update_mirrors=Yansıları Güncelle dashboard.repo_health_check=Tüm depoların sağlığını denetle dashboard.check_repo_stats=Tüm depo istatistiklerini denetle dashboard.archive_cleanup=Eski depo arşivlerini sil +dashboard.deleted_branches_cleanup=Silinen dalları temizle dashboard.update_migration_poster_id=Taşıma poster kimliklerini güncelle +dashboard.git_gc_repos=Tüm depolardaki atıkları temizle +dashboard.resync_all_sshkeys='.ssh/authority_keys' dosyasını Gitea SSH anahtarlarıyla güncelle +dashboard.resync_all_sshprincipals='.ssh/authorized_principals' dosyasını Gitea SSH sorumlularıyla güncelleyin +dashboard.resync_all_hooks=Tüm depoların alma öncesi, güncelleme ve alma sonrası kancalarını yeniden senkronize edin dashboard.reinit_missing_repos=Kayıtları bulunanlar için tüm eksik Git depolarını yeniden başlat dashboard.sync_external_users=Harici kullanıcı verisini senkronize et +dashboard.cleanup_hook_task_table=Hook_task tablosunu temizle +dashboard.cleanup_packages=Süresi dolmuş paketleri temizle +dashboard.cleanup_actions=Eylemlerin süresi geçmiş günlük ve yapılarını temizle dashboard.server_uptime=Sunucunun Ayakta Kalma Süresi dashboard.current_goroutine=Güncel Goroutine'ler dashboard.current_memory_usage=Güncel Bellek Kullanımı @@ -2823,8 +3068,10 @@ dashboard.total_gc_pause=Toplam GC Durması dashboard.last_gc_pause=Son GC Durması dashboard.gc_times=GC Zamanları dashboard.delete_old_actions=Veritabanından tüm eski faaliyetleri sil +dashboard.delete_old_actions.started=Veritabanından başlatılan tüm eski faaliyetleri silme dashboard.update_checker=Denetleyiciyi güncelle dashboard.delete_old_system_notices=Veritabanından tüm eski sistem bildirimlerini sil +dashboard.gc_lfs=LFS üst nesnelerin atıklarını temizle dashboard.stop_zombie_tasks=Zombi görevlerin durdurma eylemleri dashboard.stop_endless_tasks=Daimi görevlerin durdurma eylemleri dashboard.cancel_abandoned_jobs=Terkedilmiş görevlerin iptal eylemleri @@ -2832,6 +3079,7 @@ dashboard.start_schedule_tasks=Zamanlanmış görevlerin başlatma eylemleri dashboard.sync_branch.started=Dal Eşzamanlaması başladı dashboard.sync_tag.started=Etiket eşitlemesi başladı dashboard.rebuild_issue_indexer=Konu indeksini yeniden oluştur +dashboard.sync_repo_licenses=Depo lisanslarını eşle users.user_manage_panel=Kullanıcı Hesap Yönetimi users.new_account=Yeni Kullanıcı Hesabı @@ -2847,6 +3095,7 @@ users.2fa=2FD users.repos=Depolar users.created=Oluşturuldu users.last_login=Son Oturum Açma +users.never_login=Hiç Oturum Açılmadı users.send_register_notify=Kullanıcı Kayıt Bildirimi Gönder users.new_success=`"%s" kullanıcı hesabı oluşturuldu.` users.edit=Düzenle @@ -2873,6 +3122,7 @@ users.still_own_repo=Bu kullanıcı hala bir veya daha fazla depoya sahip. Önce users.still_has_org=Bu kullanıcı bir organizasyonun üyesidir. Önce kullanıcıyı tüm organizasyonlardan çıkarın. users.purge=Kullanıcıyı Temizle users.purge_help=Kullanıcıyı ve sahip olduğu herhangi bir depoyu, organizasyonu ve paketleri zorla sil. Tüm yorumlar da silinecektir. +users.still_own_packages=Kullanıcının bir veya daha fazla paketi var, önce bu paketleri silin. users.deletion_success=Kullanıcı hesabı silindi. users.reset_2fa=2FD'yi sıfırla users.list_status_filter.menu_text=Filtre @@ -2892,7 +3142,11 @@ users.details=Kullanıcı Ayrıntıları emails.email_manage_panel=Kullanıcı E-posta Yönetimi emails.primary=Birincil emails.activated=Aktifleştirildi +emails.filter_sort.email=E-Posta adresi +emails.filter_sort.email_reverse=E-posta (ters) emails.filter_sort.name=Kullanıcı Adı +emails.filter_sort.name_reverse=Kullanıcı Adı (ters) +emails.updated=E-posta güncellendi emails.not_updated=İstenen e-posta adresi güncellenemedi: %v emails.duplicate_active=Bu e-posta adresi farklı bir kullanıcı için zaten aktif. emails.change_email_header=E-posta Özelliklerini Güncelle @@ -2900,6 +3154,7 @@ emails.change_email_text=Bu e-posta adresini güncellemek istediğinizden emin m emails.delete=E-postayı Sil emails.delete_desc=Bu e-posta adresini silmek istediğinizden emin misiniz? emails.deletion_success=E-posta adresi silindi. +emails.delete_primary_email_error=Ana e-posta adresini silemezsiniz. orgs.org_manage_panel=Organizasyon Yönetimi orgs.name=İsim @@ -2932,10 +3187,12 @@ packages.size=Boyut packages.published=Yayınlandı defaulthooks=Varsayılan Web İstemcileri +defaulthooks.desc=Web İstemcileri, belirli Gitea olayları tetiklendiğinde otomatik olarak HTTP POST isteklerini sunucuya yapar. Burada tanımlanan Web İstemcileri varsayılandır ve tüm yeni depolara kopyalanır. web istemcileri kılavuzunda daha fazla bilgi edinin. defaulthooks.add_webhook=Varsayılan Web İstemcisi Ekle defaulthooks.update_webhook=Varsayılan Web İstemcisini Güncelle systemhooks=Sistem Web İstemcileri +systemhooks.desc=Belirli Gitea olayları tetiklendiğinde Web istemcileri otomatik olarak bir sunucuya HTTP POST istekleri yapar. Burada tanımlanan web istemcileri sistemdeki tüm depolar üzerinde çalışır, bu yüzden lütfen bunun olabilecek tüm performans sonuçlarını göz önünde bulundurun. web istemcileri kılavuzunda daha fazla bilgi edinin. systemhooks.add_webhook=Sistem Web İstemcisi Ekle systemhooks.update_webhook=Sistem Web İstemcisi Güncelle @@ -3011,19 +3268,39 @@ auths.oauth2_required_claim_name_helper=Bu ismi, bu kaynağa oturum açmayı bu auths.oauth2_required_claim_value=Gerekli Talep Değeri auths.oauth2_required_claim_value_helper=Bu değeri, bu kaynağa oturum açmayı bu isimdeki ve değerdeki talebe sahip kullanıcıların girişiyle sınırlamak için ayarlayın auths.oauth2_group_claim_name=Talep ismi bu kaynak için grup isimlerini sağlıyor. (İsteğe bağlı) +auths.oauth2_full_name_claim_name=Tam Adı Talep Adı. (İsteğe bağlı, ayarlanırsa, kullanıcının tam adı her zaman bu iddia ile senkronize edilir) +auths.oauth2_ssh_public_key_claim_name=SSH Açık Anahtar Talep Adı +auths.oauth2_admin_group=Yönetici kullanıcıları için Grup Talep değeri. (İsteğe bağlı, yukarıda talep ismine gerek duyar) +auths.oauth2_restricted_group=Kısıtlı kullanıcılar için Grup Talep değeri. (İsteğe bağlı, yukarıda talep ismine gerek duyar) +auths.oauth2_map_group_to_team=Talep edilen grupları Organizasyon takımlarına eşle. (İsteğe bağlıdır - yukarıdaki talep adına gerek duyar) auths.oauth2_map_group_to_team_removal=Eğer kullanıcı ilişkili gruba ait değilse, kullanıcıları eşleşmiş takımlardan çıkarın. auths.enable_auto_register=Otomatik Kaydolmayı Etkinleştir auths.sspi_auto_create_users=Kullanıcıları otomatik olarak oluştur +auths.sspi_auto_create_users_helper=SSPI kimlik doğrulama yönteminin ilk kez oturum açan kullanıcılar için otomatik olarak yeni hesaplar oluşturmasına izin ver auths.sspi_auto_activate_users=Kullanıcıları otomatik olarak etkinleştir auths.sspi_auto_activate_users_helper=SSPI kimlik doğrulama yönteminin yeni kullanıcıları otomatik olarak etkinleştirmesine izin ver auths.sspi_strip_domain_names=Alan adlarını kullanıcı adlarından kaldır +auths.sspi_strip_domain_names_helper=İşaretlenirse, etki alanı adları oturum açma adlarından kaldırılacaktır (örn. "ETKİALANI\kullanıcı" ve " kullanıcı@örnek.org "her ikisi de sadece "kullanıcı" olacak). auths.sspi_separator_replacement=\, / ve @ yerine kullanılacak ayırıcı +auths.sspi_separator_replacement_helper=Alt seviye oturum açma adlarının (örneğin, "ETKİALANI\kullanıcı" içindeki \) ve kullanıcı asıl adlarının (örneğin, "kullanıcı@örnek.org" daki @) ayırıcılarını değiştirmek için kullanılacak karakter. auths.sspi_default_language=Varsayılan kullanıcı dili +auths.sspi_default_language_helper=SSPI kimlik doğrulama yöntemi tarafından otomatik olarak oluşturulan kullanıcılar için varsayılan dil. Dili otomatik olarak algılamayı tercih ederseniz boş bırakın. auths.tips=İpuçları auths.tips.oauth2.general=OAuth2 Kimlik Doğrulama auths.tips.oauth2.general.tip=Yeni bir OAuth2 kimlik doğrulama kaydederken, geri çağırma/yönlendirme URL'si şu olmalıdır: auths.tip.oauth2_provider=OAuth2 Sağlayıcısı +auths.tip.bitbucket=%s sayfasında yeni bir OAuth tüketicisi kaydedin ve 'Hesap' - 'Oku' iznini ekleyin +auths.tip.nextcloud=Aşağıdaki "Ayarlar -> Güvenlik -> OAuth 2.0 istemcisi" menüsünü kullanarak örneğinize yeni bir OAuth tüketicisi kaydedin +auths.tip.dropbox=%s adresinde yeni bir uygulama oluştur +auths.tip.facebook=%s adresinde yeni bir uygulama kaydedin ve "Facebook Giriş" ürününü ekleyin. +auths.tip.github=%s adresinde yeni bir OAuth uygulaması kaydedin +auths.tip.gitlab_new=%s adresinde yeni bir uygulama kaydedin +auths.tip.google_plus=OAuth2 istemci kimlik bilgilerini %s adresindeki Google API konsolundan alın auths.tip.openid_connect=Bitiş noktalarını belirlemek için OpenID Connect Discovery URL'sini (https://{server}/.well-known/openid-configuration) kullanın +auths.tip.twitter=%s adresine gidin, bir uygulama oluşturun ve “Bu uygulamanın Twitter ile oturum açmak için kullanılmasına izin ver” seçeneğinin etkin olduğundan emin olun +auths.tip.discord=%s adresinde yeni bir uygulama kaydedin +auths.tip.gitea=Yeni bir OAuth2 uygulaması kaydedin. Rehber %s adresinde bulunabilir +auths.tip.yandex=`%s adresinde yeni bir uygulama oluşturun. "Yandex.Passport API'sı" bölümünden aşağıdaki izinleri seçin: "E-posta adresine erişim", "Kullanıcı avatarına erişim" ve "Kullanıcı adına, ad ve soyadına, cinsiyete erişim"` auths.tip.mastodon=Kimlik doğrulaması yapmak istediğiniz mastodon örneği için özel bir örnek URL girin (veya varsayılan olanı kullanın) auths.edit=Kimlik Doğrulama Kaynağı Düzenle auths.activated=Bu Kimlik Doğrulama Kaynağı Etkinleştirildi @@ -3123,6 +3400,7 @@ config.mailer_sendmail_path=Sendmail Yolu config.mailer_sendmail_args=Sendmail İçin İlave Değişkenler config.mailer_sendmail_timeout=Sendmail Zaman Aşımı config.mailer_use_dummy=Sahte +config.test_email_placeholder=E-posta Adresi (ör. test@example.com) config.send_test_mail=Test E-postası Gönder config.send_test_mail_submit=Gönder config.test_mail_failed=`"%s" adresine deneme e-postası gönderilemedi: %v` @@ -3155,6 +3433,7 @@ config.picture_service=Resim Servisi config.disable_gravatar=Gravatar Hizmet Dışı config.enable_federated_avatar=Birleştirilmiş Avatarları Etkinleştir config.open_with_editor_app_help=Klon menüsü için "Birlikte aç" düzenleyicileri. Boş bırakılırsa, varsayılan kullanılacaktır. Varsayılanı görmek için genişletin. +config.git_guide_remote_name=Kılavuzdaki git komutları için deponun uzak adı config.git_config=Git Yapılandırması config.git_disable_diff_highlight=Değişiklik Sözdizimi Vurgusunu Devre Dışı Bırak @@ -3186,6 +3465,9 @@ monitor.next=Sonraki Zaman monitor.previous=Önceki Zaman monitor.execute_times=Çalıştırma monitor.process=Çalışan Süreçler +monitor.stacktrace=Yığın raporu +monitor.trace=İzle +monitor.performance_logs=Performans Günlükleri monitor.processes_count=%d İşlem monitor.download_diagnosis_report=Tanı raporunu indir monitor.desc=Açıklama @@ -3193,6 +3475,7 @@ monitor.start=Başlangıç Zamanı monitor.execute_time=Çalıştırma Zamanı monitor.last_execution_result=Sonuç monitor.process.cancel=İşlemi iptal et +monitor.process.cancel_desc=Bir işlemi iptal etmek veri kaybına neden olabilir monitor.process.children=Çocuklar monitor.queues=Kuyruklar @@ -3207,6 +3490,7 @@ monitor.queue.numberinqueue=Kuyruktaki Sayı monitor.queue.review_add=Çalışanları İncele / Ekle monitor.queue.settings.title=Havuz Ayarları monitor.queue.settings.desc=Havuzlar, çalışan kuyruğu tıkanmasına bir yanıt olarak dinamik olarak büyürler. +monitor.queue.settings.maxnumberworkers=En fazla çalışan sayısı monitor.queue.settings.maxnumberworkers.placeholder=Şu anda %[1]d monitor.queue.settings.maxnumberworkers.error=En fazla çalışan sayısı bir sayı olmalıdır monitor.queue.settings.submit=Ayarları Güncelle @@ -3232,6 +3516,10 @@ notices.delete_success=Sistem bildirimleri silindi. self_check.no_problem_found=Henüz bir sorun bulunmadı. self_check.startup_warnings=Başlangıç uyarıları: self_check.database_collation_mismatch=Veritabanının şu harmanlamayı kullanmasını bekle: %s +self_check.database_collation_case_insensitive=Veritabanı %s harmanlamasını kullanıyor, bu duyarsız bir harmanlamadır. Her ne kadar Gitea bununla çalışabilse de, beklendiği gibi çalışmadığı nadir durumlar ortaya çıkabilir. +self_check.database_inconsistent_collation_columns=Veritabanı %s harmanlamasını kullanıyor, ancak bu sütunlar uyumsuz harmanlamalar kullanıyor. Bu beklenmedik sorunlar oluşturabilir. +self_check.database_fix_mysql=MySQL/MariaDB kullanıcıları "gitea doctor convert" komutunu harmanlama sorunlarını çözmek için kullanabilir veya "ALTER ... COLLATE ..." SQL'lerini şahsen çalıştırarak sorunu çözebilirler. +self_check.database_fix_mssql=MSSQL kullanıcıları sorunu şu an sadece "ALTER ... COLLATE ..." SQL'lerini şahsen çalıştırarak çözebilirler. self_check.location_origin_mismatch=Mevcut URL (%[1]s) Gitea tarafından görülen URL (%[2]s) ile eşleşmiyor. Eğer bir vekil sunucu kullanıyorsanız, lütfen "Host" ve "X-Forwarded-Proto" başlıklarının doğru ayarlandığından emin olunuz. [action] @@ -3289,6 +3577,7 @@ raw_minutes=dakikalar [dropzone] default_message=Dosyaları buraya bırakın veya yüklemek için tıklayın. +invalid_input_type=Bu tür dosyaları yükleyemezsiniz. file_too_big=Dosya boyutu ({{filesize}} MB) maksimum boyutu ({{maxFilesize}} MB) aşıyor. remove_file=Dosya Kaldır @@ -3314,6 +3603,8 @@ error.no_committer_account=İşleyicinin e-posta adresine bağlı hesap yok error.no_gpg_keys_found=Veri tabanında bu imza için bilinen anahtar bulunamadı error.not_signed_commit=İmzalı bir işleme değil error.failed_retrieval_gpg_keys=İşleyicin hesabına bağlı herhangi bir anahtar alınamadı +error.probable_bad_signature=UYARI! Veritabanında bu kimliğe sahip bir anahtar olmasına rağmen, bu işlemeyi doğrulamaz! Bu işleme ŞÜPHELİDİR. +error.probable_bad_default_signature=UYARI! Varsayılan anahtarın bu kimliği olmasına rağmen, bu işlemeyi doğrulamaz! Bu işleme ŞÜPHELİDİR. [units] unit=Birim @@ -3351,6 +3642,8 @@ versions=Sürümler versions.view_all=Tümünü görüntüle dependency.id=Kimlik dependency.version=Sürüm +search_in_external_registry=%s içinde ara +alpine.registry=Bu kütüğü, /etc/apk/repositories dosyanıza url'yi ekleyerek kurun: alpine.registry.key=Kütüğün açık RSA anahtarını, indeks imzasını doğrulamak için /etc/apk/keys/ dizinine indirin: alpine.registry.info=Aşağıdaki listeden $branch ve $repository seçin. alpine.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: @@ -3358,26 +3651,37 @@ alpine.repository=Depo Bilgisi alpine.repository.branches=Dallar alpine.repository.repositories=Depolar alpine.repository.architectures=Mimariler +arch.registry=Sunucuyu ilişkili depo ve mimariyle /etc/pacman.conf dosyasına ekle: +arch.install=Paketi pacman ile eşzamanla: arch.repository=Depo Bilgisi arch.repository.repositories=Depolar arch.repository.architectures=Mimariler +cargo.registry=Bu kütüğü Cargo yapılandırma dosyasına (örneğin ~/.cargo/config.toml) ayarlayın: cargo.install=Paketi Cargo kullanarak kurmak için, şu komutu çalıştırın: +chef.registry=Bu kütüğü ~/.chef/config.rb dosyasında ayarlayın: chef.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: +composer.registry=Bu kütüğü ~/.composer/config.json dosyasında ayarlayın: composer.install=Paketi Composer ile kurmak için, şu komutu çalıştırın: composer.dependencies=Bağımlılıklar composer.dependencies.development=Geliştirme Bağımlılıkları conan.details.repository=Depo +conan.registry=Bu kütüğü komut satırını kullanarak kurun: conan.install=Conan ile paket kurmak için aşağıdaki komutu çalıştırın: +conda.registry=Bu kütüğü .condarc dosyasında bir Conda deposu olarak ayarlayın: conda.install=Conda ile paket kurmak için aşağıdaki komutu çalıştırın: container.details.type=Görüntü Türü container.details.platform=Platform container.pull=Görüntüyü komut satırını kullanarak çekin: +container.images=Görüntüler +container.digest=Özet container.multi_arch=İşletim Sistemi / Mimari container.layers=Görüntü Katmanları container.labels=Etiketler container.labels.key=Anahtar container.labels.value=Değer +cran.registry=Bu kütüğü Rprofile.site dosyasında ayarlayın: cran.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: +debian.registry=Bu kütüğü komut satırını kullanarak kurun: debian.registry.info=Aşağıdaki listeden $distribution ve $component seçin. debian.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: debian.repository=Depo Bilgisi @@ -3386,11 +3690,16 @@ debian.repository.components=Bileşenler debian.repository.architectures=Mimariler generic.download=Paketi komut satırında indirin: go.install=Paketi komut satırını kullanarak yükleyin: +helm.registry=Bu kütüğü komut satırını kullanarak kurun: helm.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: +maven.registry=Bu kütüğü projenizdeki pom.xml dosyasında ayarlayın: +maven.install=Paketi kullanmak için aşağıdaki dependencies parçasını pom.xml dosyasınıza ekleyin: maven.install2=Komut satırında çalıştırın: maven.download=Bağımlılığı indirmek için, komut satırında çalıştırın: +nuget.registry=Bu kütüğü komut satırını kullanarak kurun: nuget.install=Paketi NuGet ile kurmak için, şu komutu çalıştırın: nuget.dependency.framework=Hedef Çerçeve +npm.registry=Bu kütüğü projenizdeki .npmrc dosyasında ayarlayın: npm.install=Paketi npm ile kurmak için, şu komutu çalıştırın: npm.install2=veya paketi package.json dosyasına ekleyin: npm.dependencies=Bağımlılıklar @@ -3402,6 +3711,7 @@ npm.details.tag=Etiket pub.install=Paketi Dart ile kurmak için, şu komutu çalıştırın: pypi.requires=Gereken Python pypi.install=Paketi pip ile kurmak için, şu komutu çalıştırın: +rpm.registry=Bu kütüğü komut satırını kullanarak kurun: rpm.distros.redhat=RedHat tabanlı dağıtımlarda rpm.distros.suse=SUSE tabanlı dağıtımlarda rpm.install=Paketi kurmak için, aşağıdaki komutu çalıştırın: @@ -3414,14 +3724,19 @@ rubygems.dependencies.runtime=Çalışma Zamanı Bağımlılıkları rubygems.dependencies.development=Geliştirme Bağımlılıkları rubygems.required.ruby=Gereken Ruby sürümü rubygems.required.rubygems=Gereken RubyGem sürümü +swift.registry=Bu kütüğü komut satırını kullanarak kurun: swift.install=Paketi Package.swift dosyanıza ekleyin: swift.install2=ve şu komutu çalıştırın: vagrant.install=Vagrant paketi eklemek için aşağıdaki komutu çalıştırın: settings.link=Bu paketi bir depoya bağlayın +settings.link.description=Eğer bir paketi bir depoya bağlarsanız, paket deponun paket listesinde listelenecektir. settings.link.select=Depo Seç settings.link.button=Depo Bağlantısını Güncelle settings.link.success=Depo bağlantısı başarıyla güncellendi. settings.link.error=Depo bağlantısı güncellenemedi. +settings.link.repo_not_found=%s deposu bulunamadı. +settings.unlink.error=Depo bağlantısı kaldırılamadı. +settings.unlink.success=Depo bağlantısı başarıyla kaldırıldı. settings.delete=Paket Sil settings.delete.description=Bir paketi silmek kalıcıdır ve geri alınamaz. settings.delete.notice=%s (%s) paketini silmek üzeresiniz. Bu işlem geri alınamaz, emin misiniz? @@ -3435,6 +3750,7 @@ owner.settings.cargo.initialize.success=Cargo dizini başarıyla oluşturuldu. owner.settings.cargo.rebuild=Dizini yeniden oluştur owner.settings.cargo.rebuild.description=İndeks, depolanmış Cargo paketleriyle eşzamanlanmamışsa yeniden oluşturma yararlı olabilir. owner.settings.cargo.rebuild.error=Cargo dizinini yeniden oluşturma başarısız oldu: %v +owner.settings.cargo.rebuild.success=Cargo dizini başarıyla yeniden oluşturuldu. owner.settings.cleanuprules.title=Temizleme Kurallarını Yönet owner.settings.cleanuprules.add=Temizleme Kuralı Ekle owner.settings.cleanuprules.edit=Temizleme Kuralı Düzenle @@ -3468,8 +3784,13 @@ none=Henüz gizlilik yok. 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.description_placeholder=Kısa açıklama girin (isteğe bağlı). +save_success=Gizlilik "%s" kaydedildi. +save_failed=Gizlilik kaydedilemedi. +add_secret=Gizlilik ekle +edit_secret=Gizlilik düzenle 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ı. @@ -3517,6 +3838,7 @@ runners.delete_runner=Bu çalıştırıcıyı sil runners.delete_runner_success=Çalıştırıcı başarıyla silindi runners.delete_runner_failed=Çalıştırıcı silinemedi runners.delete_runner_header=Çalıştırıcıyı silmeyi onaylayın +runners.delete_runner_notice=Eğer bu çalıştırıcıda bir görev çalışıyorsa, sonlandırılacak ve başarısız olarak işaretlenecek. Yapım iş akışını bozabilir. runners.none=Hiç çalıştırıcı yok runners.status.unspecified=Bilinmiyor runners.status.idle=Boşta @@ -3524,6 +3846,7 @@ runners.status.active=Etkin runners.status.offline=Çevrimdışı runners.version=Sürüm runners.reset_registration_token=Kayıt tokenini sıfırla +runners.reset_registration_token_confirm=Mevcut tokeni geçersiz kılmak ve yeni bir tane oluşturmak ister misiniz? runners.reset_registration_token_success=Çalıştırıcı kayıt belirteci başarıyla sıfırlandı runs.all_workflows=Tüm İş Akışları @@ -3532,8 +3855,8 @@ runs.scheduled=Zamanlanmış runs.pushed_by=iten runs.invalid_workflow_helper=İş akışı yapılandırma dosyası geçersiz. Lütfen yapılandırma dosyanızı denetleyin: %s runs.no_matching_online_runner_helper=Şu etiket ile eşleşen çevrimiçi çalıştırıcı bulunamadı: %s -runs.no_job_without_needs=İş akışı en azından bağımlılığı olmayan bir görev içermelidir. -runs.no_job=İş akışı en azından bir görev içermelidir +runs.no_job_without_needs=İş akışı en azından bağımlılığı olmayan bir iş içermelidir. +runs.no_job=İş akışı en azından bir iş içermelidir runs.actor=Aktör runs.status=Durum runs.actors_no_select=Tüm aktörler @@ -3545,12 +3868,23 @@ runs.no_workflows.documentation=Gitea İşlemleri hakkında daha fazla bilgi iç runs.no_runs=İş akışı henüz hiç çalıştırılmadı. runs.empty_commit_message=(boş işleme iletisi) runs.expire_log_message=Günlükler, çok eski oldukları için temizlendiler. +runs.delete=İş akışı çalışmasını sil +runs.cancel=İş akışı çalışmasını iptal et +runs.delete.description=Bu iş akışı çalışmasını kalıcı olarak silmek istediğinizden emin misiniz? Bu eylem geri alınamaz. +runs.not_done=Bu iş akışı tamamlanmadı. +runs.view_workflow_file=İş akışı dosyasını görüntüle workflow.disable=İş Akışını Devre Dışı Bırak workflow.disable_success='%s' iş akışı başarıyla devre dışı bırakıldı. workflow.enable=İş Akışını Etkinleştir workflow.enable_success='%s' iş akışı başarıyla etkinleştirildi. workflow.disabled=İş akışı devre dışı. +workflow.run=İş Akışını Çalıştır +workflow.not_found='%s' iş akışı bulunamadı. +workflow.run_success='%s' iş akışı başarıyla çalıştırıldı. +workflow.from_ref=İş akışını şuradan kullan +workflow.has_workflow_dispatch=Bu iş akışının workflow_dispatch olay tetikleyicisi var. +workflow.has_no_workflow_dispatch='%s' iş akışının workflow_dispatch olay tetikleyicisi yok. need_approval_desc=Değişiklik isteği çatalında iş akışı çalıştırmak için onay gerekiyor. @@ -3570,12 +3904,16 @@ variables.creation.success=`"%s" değişkeni eklendi.` variables.update.failed=Değişken düzenlenemedi. variables.update.success=Değişken düzenlendi. +logs.always_auto_scroll=Günlükleri her zaman otomatik kaydır +logs.always_expand_running=Çalıştırma günlüklerini her zaman genişlet [projects] deleted.display_name=Silinmiş Proje type-1.display_name=Kişisel Proje type-2.display_name=Depo Projesi type-3.display_name=Organizasyon Projesi +enter_fullscreen=Tam Ekran +exit_fullscreen=Tam Ekrandan Çık [git.filemode] changed_filemode=%[1]s → %[2]s diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 93444fb0da..9d353faa64 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -2434,7 +2434,6 @@ settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在 settings.event_package=软件包 settings.event_package_desc=软件包在仓库中已创建或删除。 settings.branch_filter=分支过滤 -settings.branch_filter_desc=推送、创建,删除分支事件的分支白名单,使用 glob 表达式匹配指定。若为空或 *,则会报告所有分支的事件。语法文档见 %[2]s。示例:master{master,release*}。 settings.authorization_header=授权标头 settings.authorization_header_desc=当存在时将被作为授权标头包含在内。例如: %s。 settings.active=激活 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index c1879203f7..c7166bbd6c 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -2213,7 +2213,6 @@ settings.event_pull_request_merge=合併請求合併 settings.event_package=套件 settings.event_package_desc=套件已在儲存庫中建立或刪除。 settings.branch_filter=分支篩選 -settings.branch_filter_desc=推送、建立分支、刪除分支事件的白名單,請使用 glob 比對模式。如果留白或輸入*,所有分支的事件都會被回報。語法參見 github.com/gobwas/glob。範例:master, {master,release*}。 settings.authorization_header=Authorization 標頭 settings.authorization_header_desc=存在時將將包含此 Authorization 標頭在請求中。例: %s。 settings.active=啟用 From 851d8f9f7cc1e6ff2736b4ddcfc5748a532b2345 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sun, 5 Oct 2025 00:38:21 +0000 Subject: [PATCH 10/74] [skip ci] Updated translations via Crowdin --- options/locale/locale_fr-FR.ini | 4 ++++ options/locale/locale_ga-IE.ini | 3 +++ options/locale/locale_pt-PT.ini | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index ac25444844..7fc8ba3b11 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -109,6 +109,7 @@ copy_path=Copier le chemin copy_success=Copié ! copy_error=Échec de la copie copy_type_unsupported=Ce type de fichier ne peut pas être copié +copy_filename=Copier le nom du fichier write=Écrire preview=Aperçu @@ -3732,6 +3733,9 @@ settings.link.select=Sélectionner un dépôt settings.link.button=Actualiser le lien du dépôt settings.link.success=Le lien du dépôt a été mis à jour avec succès. settings.link.error=Impossible de mettre à jour le lien du dépôt. +settings.link.repo_not_found=Dépôt %s non trouvé. +settings.unlink.error=Impossible de supprimer le lien du dépôt. +settings.unlink.success=Le lien du dépôt a été supprimé. settings.delete=Supprimer le paquet settings.delete.description=Supprimer un paquet est permanent et irréversible. settings.delete.notice=Vous êtes sur le point de supprimer %s (%s). Cette opération est irréversible, êtes-vous sûr ? diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index f9801d7723..776340db42 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -2434,6 +2434,9 @@ settings.event_workflow_job_desc=Gitea Actions Sreabhadh oibre post ciúáilte, settings.event_package=Pacáiste settings.event_package_desc=Pacáiste a cruthaíodh nó a scriosadh i stóras. settings.branch_filter=Scagaire brainse +settings.branch_filter_desc_1=Liosta ceadanna brainse (agus ainm tagartha) le haghaidh imeachtaí brú, cruthaithe brainse agus scriosadh brainse, sonraithe mar phatrún glob. Más folamh nó * é, tuairiscítear imeachtaí do na brainsí agus na clibeanna uile. +settings.branch_filter_desc_2=Úsáid réimír refs/heads/refs/tags/ chun ainmneacha tagartha iomlána a mheaitseáil. +settings.branch_filter_desc_doc=Féach ar dhoiciméadú %[2]s le haghaidh comhréir. settings.authorization_header=Ceanntásc Údaraithe settings.authorization_header_desc=Cuirfear san áireamh mar cheanntásc údaraithe d'iarratais nuair a bheidh ann Samplaí: %s. settings.active=Gníomhach diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index f43fe03958..eefe32a515 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -109,6 +109,7 @@ copy_path=Copiar caminho copy_success=Copiado! copy_error=Falha ao copiar copy_type_unsupported=Este tipo de ficheiro não pode ser copiado +copy_filename=Copiar o nome do ficheiro write=Escrever preview=Pré-visualizar @@ -2433,6 +2434,9 @@ settings.event_workflow_job_desc=O trabalho da sequência de trabalho das opera settings.event_package=Pacote settings.event_package_desc=Pacote criado ou eliminado num repositório. settings.branch_filter=Filtro de ramos +settings.branch_filter_desc_1=A lista de permissão do ramo (e nome de referência) para eventos de envio, criação de ramos e eliminação de ramos, especificada como padrão glob. Se estiver em branco ou for *, serão reportados eventos para todos os ramos e etiquetas. +settings.branch_filter_desc_2=Use um prefixo refs/heads/ ou refs/tags/ para corresponder aos nomes completos de referência. +settings.branch_filter_desc_doc=Consulte a documentação %[2]s para ver a sintaxe. settings.authorization_header=Cabeçalho de Autorização settings.authorization_header_desc=Será incluído como cabeçalho de autorização para pedidos, quando estiver presente. Exemplos: %s. settings.active=Em funcionamento From 0a0baeb3b020bb4ca89af205cc9660ef3585fc37 Mon Sep 17 00:00:00 2001 From: Shafi Ahmed <98274448+ita004@users.noreply.github.com> Date: Sun, 5 Oct 2025 08:01:06 +0530 Subject: [PATCH 11/74] fix: auto-expand and auto-scroll for actions logs (#35570) (#35583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements reliable auto-expand and auto-scroll behavior for the Actions logs view. * Expands running or unfinished steps automatically. * Smoothly scrolls to the latest log line during execution. * Controlled via existing “Always auto-scroll” and “Expand running steps” options. Fixes #35570. --------- Co-authored-by: wxiaoguang --- routers/web/devtest/mock_actions.go | 42 +++++++++++------ web_src/js/components/RepoActionView.vue | 59 +++++++++++++++++++----- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/routers/web/devtest/mock_actions.go b/routers/web/devtest/mock_actions.go index bc741ecd11..90c6f99d5e 100644 --- a/routers/web/devtest/mock_actions.go +++ b/routers/web/devtest/mock_actions.go @@ -6,6 +6,7 @@ package devtest import ( mathRand "math/rand/v2" "net/http" + "slices" "strconv" "strings" "time" @@ -17,25 +18,29 @@ import ( "code.gitea.io/gitea/services/context" ) -func generateMockStepsLog(logCur actions.LogCursor) (stepsLog []*actions.ViewStepLog) { - mockedLogs := []string{ - "::group::test group for: step={step}, cursor={cursor}", - "in group msg for: step={step}, cursor={cursor}", - "in group msg for: step={step}, cursor={cursor}", - "in group msg for: step={step}, cursor={cursor}", - "::endgroup::", +type generateMockStepsLogOptions struct { + mockCountFirst int + mockCountGeneral int + groupRepeat int +} + +func generateMockStepsLog(logCur actions.LogCursor, opts generateMockStepsLogOptions) (stepsLog []*actions.ViewStepLog) { + var mockedLogs []string + mockedLogs = append(mockedLogs, "::group::test group for: step={step}, cursor={cursor}") + mockedLogs = append(mockedLogs, slices.Repeat([]string{"in group msg for: step={step}, cursor={cursor}"}, opts.groupRepeat)...) + mockedLogs = append(mockedLogs, "::endgroup::") + mockedLogs = append(mockedLogs, "message for: step={step}, cursor={cursor}", "message for: step={step}, cursor={cursor}", "##[group]test group for: step={step}, cursor={cursor}", "in group msg for: step={step}, cursor={cursor}", "##[endgroup]", - } - cur := logCur.Cursor // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally - mockCount := util.Iif(logCur.Step == 0, 3, 1) - if logCur.Step == 1 && logCur.Cursor == 0 { - mockCount = 30 // for the first batch, return as many as possible to test the auto-expand and auto-scroll - } - for i := 0; i < mockCount; i++ { + ) + // usually the cursor is the "file offset", but here we abuse it as "line number" to make the mock easier, intentionally + cur := logCur.Cursor + // for the first batch, return as many as possible to test the auto-expand and auto-scroll + mockCount := util.Iif(logCur.Cursor == 0, opts.mockCountFirst, opts.mockCountGeneral) + for range mockCount { logStr := mockedLogs[int(cur)%len(mockedLogs)] cur++ logStr = strings.ReplaceAll(logStr, "{step}", strconv.Itoa(logCur.Step)) @@ -127,21 +132,28 @@ func MockActionsRunsJobs(ctx *context.Context) { Duration: "3h", }) + var mockLogOptions []generateMockStepsLogOptions resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{ Summary: "step 0 (mock slow)", Duration: time.Hour.String(), Status: actions_model.StatusRunning.String(), }) + mockLogOptions = append(mockLogOptions, generateMockStepsLogOptions{mockCountFirst: 30, mockCountGeneral: 1, groupRepeat: 3}) + resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{ Summary: "step 1 (mock fast)", Duration: time.Hour.String(), Status: actions_model.StatusRunning.String(), }) + mockLogOptions = append(mockLogOptions, generateMockStepsLogOptions{mockCountFirst: 30, mockCountGeneral: 3, groupRepeat: 20}) + resp.State.CurrentJob.Steps = append(resp.State.CurrentJob.Steps, &actions.ViewJobStep{ Summary: "step 2 (mock error)", Duration: time.Hour.String(), Status: actions_model.StatusRunning.String(), }) + mockLogOptions = append(mockLogOptions, generateMockStepsLogOptions{mockCountFirst: 30, mockCountGeneral: 3, groupRepeat: 3}) + if len(req.LogCursors) == 0 { ctx.JSON(http.StatusOK, resp) return @@ -156,7 +168,7 @@ func MockActionsRunsJobs(ctx *context.Context) { } doSlowResponse = doSlowResponse || logCur.Step == 0 doErrorResponse = doErrorResponse || logCur.Step == 2 - resp.Logs.StepsLog = append(resp.Logs.StepsLog, generateMockStepsLog(logCur)...) + resp.Logs.StepsLog = append(resp.Logs.StepsLog, generateMockStepsLog(logCur, mockLogOptions[logCur.Step])...) } if doErrorResponse { if mathRand.Float64() > 0.5 { diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 2eb2211269..b90aef7411 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -2,7 +2,7 @@ import {SvgIcon} from '../svg.ts'; import ActionRunStatus from './ActionRunStatus.vue'; import {defineComponent, type PropType} from 'vue'; -import {createElementFromAttrs, toggleElem} from '../utils/dom.ts'; +import {addDelegatedEventListener, createElementFromAttrs, toggleElem} from '../utils/dom.ts'; import {formatDatetime} from '../utils/time.ts'; import {renderAnsi} from '../render/ansi.ts'; import {POST, DELETE} from '../modules/fetch.ts'; @@ -40,6 +40,12 @@ type Step = { status: RunStatus, } +type JobStepState = { + cursor: string|null, + expanded: boolean, + manuallyCollapsed: boolean, // whether the user manually collapsed the step, used to avoid auto-expanding it again +} + function parseLineCommand(line: LogLine): LogLineCommand | null { for (const prefix of LogLinePrefixesGroup) { if (line.message.startsWith(prefix)) { @@ -54,9 +60,10 @@ function parseLineCommand(line: LogLine): LogLineCommand | null { return null; } -function isLogElementInViewport(el: Element): boolean { +function isLogElementInViewport(el: Element, {extraViewPortHeight}={extraViewPortHeight: 0}): boolean { const rect = el.getBoundingClientRect(); - return rect.top >= 0 && rect.bottom <= window.innerHeight; // only check height but not width + // only check whether bottom is in viewport, because the log element can be a log group which is usually tall + return 0 <= rect.bottom && rect.bottom <= window.innerHeight + extraViewPortHeight; } type LocaleStorageOptions = { @@ -104,7 +111,7 @@ export default defineComponent({ // internal state loadingAbortController: null as AbortController | null, intervalID: null as IntervalId | null, - currentJobStepsStates: [] as Array>, + currentJobStepsStates: [] as Array, artifacts: [] as Array>, menuVisible: false, isFullScreen: false, @@ -181,6 +188,19 @@ export default defineComponent({ // load job data and then auto-reload periodically // need to await first loadJob so this.currentJobStepsStates is initialized and can be used in hashChangeListener await this.loadJob(); + + // auto-scroll to the bottom of the log group when it is opened + // "toggle" event doesn't bubble, so we need to use 'click' event delegation to handle it + addDelegatedEventListener(this.elStepsContainer(), 'click', 'summary.job-log-group-summary', (el, _) => { + if (!this.optionAlwaysAutoScroll) return; + const elJobLogGroup = el.closest('details.job-log-group') as HTMLDetailsElement; + setTimeout(() => { + if (elJobLogGroup.open && !isLogElementInViewport(elJobLogGroup)) { + elJobLogGroup.scrollIntoView({behavior: 'smooth', block: 'end'}); + } + }, 0); + }); + this.intervalID = setInterval(() => this.loadJob(), 1000); document.body.addEventListener('click', this.closeDropdown); this.hashChangeListener(); @@ -252,6 +272,8 @@ export default defineComponent({ this.currentJobStepsStates[idx].expanded = !this.currentJobStepsStates[idx].expanded; if (this.currentJobStepsStates[idx].expanded) { this.loadJobForce(); // try to load the data immediately instead of waiting for next timer interval + } else if (this.currentJob.steps[idx].status === 'running') { + this.currentJobStepsStates[idx].manuallyCollapsed = true; } }, // cancel a run @@ -293,7 +315,8 @@ export default defineComponent({ const el = this.getJobStepLogsContainer(stepIndex); // if the logs container is empty, then auto-scroll if the step is expanded if (!el.lastChild) return this.currentJobStepsStates[stepIndex].expanded; - return isLogElementInViewport(el.lastChild as Element); + // use extraViewPortHeight to tolerate some extra "virtual view port" height (for example: the last line is partially visible) + return isLogElementInViewport(el.lastChild as Element, {extraViewPortHeight: 5}); }, appendLogs(stepIndex: number, startTime: number, logLines: LogLine[]) { @@ -343,7 +366,6 @@ export default defineComponent({ const abortController = new AbortController(); this.loadingAbortController = abortController; try { - const isFirstLoad = !this.run.status; const job = await this.fetchJobData(abortController); if (this.loadingAbortController !== abortController) return; @@ -353,10 +375,15 @@ export default defineComponent({ // sync the currentJobStepsStates to store the job step states for (let i = 0; i < this.currentJob.steps.length; i++) { - const expanded = isFirstLoad && this.optionAlwaysExpandRunning && this.currentJob.steps[i].status === 'running'; + const autoExpand = this.optionAlwaysExpandRunning && this.currentJob.steps[i].status === 'running'; if (!this.currentJobStepsStates[i]) { // initial states for job steps - this.currentJobStepsStates[i] = {cursor: null, expanded}; + this.currentJobStepsStates[i] = {cursor: null, expanded: autoExpand, manuallyCollapsed: false}; + } else { + // if the step is not manually collapsed by user, then auto-expand it if option is enabled + if (autoExpand && !this.currentJobStepsStates[i].manuallyCollapsed) { + this.currentJobStepsStates[i].expanded = true; + } } } @@ -380,7 +407,10 @@ export default defineComponent({ if (!autoScrollStepIndexes.get(stepIndex)) continue; autoScrollJobStepElement = this.getJobStepLogsContainer(stepIndex); } - autoScrollJobStepElement?.lastElementChild.scrollIntoView({behavior: 'smooth', block: 'nearest'}); + const lastLogElem = autoScrollJobStepElement?.lastElementChild; + if (lastLogElem && !isLogElementInViewport(lastLogElem)) { + lastLogElem.scrollIntoView({behavior: 'smooth', block: 'end'}); + } // clear the interval timer if the job is done if (this.run.done && this.intervalID) { @@ -408,9 +438,13 @@ export default defineComponent({ if (this.menuVisible) this.menuVisible = false; }, + elStepsContainer(): HTMLElement { + return this.$refs.stepsContainer as HTMLElement; + }, + toggleTimeDisplay(type: 'seconds' | 'stamp') { this.timeVisible[`log-time-${type}`] = !this.timeVisible[`log-time-${type}`]; - for (const el of (this.$refs.steps as HTMLElement).querySelectorAll(`.log-time-${type}`)) { + for (const el of this.elStepsContainer().querySelectorAll(`.log-time-${type}`)) { toggleElem(el, this.timeVisible[`log-time-${type}`]); } }, @@ -419,6 +453,7 @@ export default defineComponent({ this.isFullScreen = !this.isFullScreen; toggleFullScreen('.action-view-right', this.isFullScreen, '.action-view-body'); }, + async hashChangeListener() { const selectedLogStep = window.location.hash; if (!selectedLogStep) return; @@ -431,7 +466,7 @@ export default defineComponent({ // so logline can be selected by querySelector await this.loadJob(); } - const logLine = (this.$refs.steps as HTMLElement).querySelector(selectedLogStep); + const logLine = this.elStepsContainer().querySelector(selectedLogStep); if (!logLine) return; logLine.querySelector('.line-num').click(); }, @@ -566,7 +601,7 @@ export default defineComponent({
-
+
diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts index d3da9ca053..2ad9bffd51 100644 --- a/web_src/js/svg.ts +++ b/web_src/js/svg.ts @@ -5,6 +5,7 @@ import giteaDoubleChevronLeft from '../../public/assets/img/svg/gitea-double-che import giteaDoubleChevronRight from '../../public/assets/img/svg/gitea-double-chevron-right.svg'; import giteaEmptyCheckbox from '../../public/assets/img/svg/gitea-empty-checkbox.svg'; import giteaExclamation from '../../public/assets/img/svg/gitea-exclamation.svg'; +import giteaRunning from '../../public/assets/img/svg/gitea-running.svg'; import octiconArchive from '../../public/assets/img/svg/octicon-archive.svg'; import octiconArrowSwitch from '../../public/assets/img/svg/octicon-arrow-switch.svg'; import octiconBlocked from '../../public/assets/img/svg/octicon-blocked.svg'; @@ -15,6 +16,7 @@ import octiconCheckCircleFill from '../../public/assets/img/svg/octicon-check-ci import octiconChevronDown from '../../public/assets/img/svg/octicon-chevron-down.svg'; import octiconChevronLeft from '../../public/assets/img/svg/octicon-chevron-left.svg'; import octiconChevronRight from '../../public/assets/img/svg/octicon-chevron-right.svg'; +import octiconCircle from '../../public/assets/img/svg/octicon-circle.svg'; import octiconClock from '../../public/assets/img/svg/octicon-clock.svg'; import octiconCode from '../../public/assets/img/svg/octicon-code.svg'; import octiconColumns from '../../public/assets/img/svg/octicon-columns.svg'; @@ -84,6 +86,7 @@ const svgs = { 'gitea-double-chevron-right': giteaDoubleChevronRight, 'gitea-empty-checkbox': giteaEmptyCheckbox, 'gitea-exclamation': giteaExclamation, + 'gitea-running': giteaRunning, 'octicon-archive': octiconArchive, 'octicon-arrow-switch': octiconArrowSwitch, 'octicon-blocked': octiconBlocked, @@ -94,6 +97,7 @@ const svgs = { 'octicon-chevron-down': octiconChevronDown, 'octicon-chevron-left': octiconChevronLeft, 'octicon-chevron-right': octiconChevronRight, + 'octicon-circle': octiconCircle, 'octicon-clock': octiconClock, 'octicon-code': octiconCode, 'octicon-columns': octiconColumns, diff --git a/web_src/svg/gitea-running.svg b/web_src/svg/gitea-running.svg new file mode 100644 index 0000000000..6eccaddeed --- /dev/null +++ b/web_src/svg/gitea-running.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From 40f71bcd4cc9ad38e3a8205747901440371ffb80 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Fri, 10 Oct 2025 12:58:55 -0600 Subject: [PATCH 23/74] Support Actions `concurrency` syntax (#32751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #24769 Fix #32662 Fix #33260 Depends on https://gitea.com/gitea/act/pulls/124 - https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency ## ⚠️ BREAKING ⚠️ This PR removes the auto-cancellation feature added by #25716. Users need to manually add `concurrency` to workflows to control concurrent workflows or jobs. --------- Signed-off-by: Zettat123 Co-authored-by: Christopher Homberger Co-authored-by: wxiaoguang --- models/actions/run.go | 203 +- models/actions/run_job.go | 75 +- models/actions/run_job_list.go | 19 +- models/actions/run_list.go | 25 +- models/migrations/migrations.go | 1 + models/migrations/v1_25/v323.go | 43 + routers/api/actions/runner/runner.go | 5 +- routers/web/repo/actions/view.go | 141 +- services/actions/clear_tasks.go | 76 +- services/actions/concurrency.go | 121 ++ services/actions/job_emitter.go | 296 ++- services/actions/job_emitter_test.go | 4 +- services/actions/notifier_helper.go | 29 +- services/actions/run.go | 127 ++ services/actions/schedule_tasks.go | 26 +- services/actions/workflow.go | 27 +- tests/integration/actions_concurrency_test.go | 1709 +++++++++++++++++ 17 files changed, 2649 insertions(+), 278 deletions(-) create mode 100644 models/migrations/v1_25/v323.go create mode 100644 services/actions/concurrency.go create mode 100644 services/actions/run.go create mode 100644 tests/integration/actions_concurrency_test.go diff --git a/models/actions/run.go b/models/actions/run.go index f1d85bbcd9..4da6958e2d 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -16,13 +16,13 @@ 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/log" "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" webhook_module "code.gitea.io/gitea/modules/webhook" - "github.com/nektos/act/pkg/jobparser" "xorm.io/builder" ) @@ -30,7 +30,7 @@ import ( type ActionRun struct { ID int64 Title string - RepoID int64 `xorm:"index unique(repo_index)"` + RepoID int64 `xorm:"unique(repo_index) index(repo_concurrency)"` Repo *repo_model.Repository `xorm:"-"` OwnerID int64 `xorm:"index"` WorkflowID string `xorm:"index"` // the name of workflow file @@ -49,6 +49,9 @@ type ActionRun struct { TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow Status Status `xorm:"index"` Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed + RawConcurrency string // raw concurrency + ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` + ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` // Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0 Started timeutil.TimeStamp Stopped timeutil.TimeStamp @@ -190,7 +193,7 @@ func (run *ActionRun) IsSchedule() bool { return run.ScheduleID > 0 } -func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { +func UpdateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { _, err := db.GetEngine(ctx).ID(repo.ID). NoAutoTime(). SetExpr("num_action_runs", @@ -247,116 +250,62 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin return cancelledJobs, err } - // Iterate over each job and attempt to cancel it. - for _, job := range jobs { - // Skip jobs that are already in a terminal state (completed, cancelled, etc.). - status := job.Status - if status.IsDone() { - continue - } - - // If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it. - if job.TaskID == 0 { - job.Status = StatusCancelled - job.Stopped = timeutil.TimeStampNow() - - // Update the job's status and stopped time in the database. - n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped") - if err != nil { - return cancelledJobs, err - } - - // If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again. - if n == 0 { - return cancelledJobs, errors.New("job has changed, try again") - } - - cancelledJobs = append(cancelledJobs, job) - // Continue with the next job. - continue - } - - // If the job has an associated task, try to stop the task, effectively cancelling the job. - if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil { - return cancelledJobs, err - } - cancelledJobs = append(cancelledJobs, job) + cjs, err := CancelJobs(ctx, jobs) + if err != nil { + return cancelledJobs, err } + cancelledJobs = append(cancelledJobs, cjs...) } // Return nil to indicate successful cancellation of all running and waiting jobs. return cancelledJobs, nil } -// InsertRun inserts a run -// The title will be cut off at 255 characters if it's longer than 255 characters. -func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error { - return db.WithTx(ctx, func(ctx context.Context) error { - index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID) - if err != nil { - return err - } - run.Index = index - run.Title = util.EllipsisDisplayString(run.Title, 255) - - if err := db.Insert(ctx, run); err != nil { - return err +func CancelJobs(ctx context.Context, jobs []*ActionRunJob) ([]*ActionRunJob, error) { + cancelledJobs := make([]*ActionRunJob, 0, len(jobs)) + // Iterate over each job and attempt to cancel it. + for _, job := range jobs { + // Skip jobs that are already in a terminal state (completed, cancelled, etc.). + status := job.Status + if status.IsDone() { + continue } - if run.Repo == nil { - repo, err := repo_model.GetRepositoryByID(ctx, run.RepoID) + // If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it. + if job.TaskID == 0 { + job.Status = StatusCancelled + job.Stopped = timeutil.TimeStampNow() + + // Update the job's status and stopped time in the database. + n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped") if err != nil { - return err + return cancelledJobs, err } - run.Repo = repo + + // If the update affected 0 rows, it means the job has changed in the meantime + if n == 0 { + log.Error("Failed to cancel job %d because it has changed", job.ID) + continue + } + + cancelledJobs = append(cancelledJobs, job) + // Continue with the next job. + continue } - if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil { - return err + // If the job has an associated task, try to stop the task, effectively cancelling the job. + if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil { + return cancelledJobs, err } + updatedJob, err := GetRunJobByID(ctx, job.ID) + if err != nil { + return cancelledJobs, fmt.Errorf("get job: %w", err) + } + cancelledJobs = append(cancelledJobs, updatedJob) + } - runJobs := make([]*ActionRunJob, 0, len(jobs)) - var hasWaiting bool - for _, v := range jobs { - id, job := v.Job() - needs := job.Needs() - if err := v.SetJob(id, job.EraseNeeds()); err != nil { - return err - } - payload, _ := v.Marshal() - status := StatusWaiting - if len(needs) > 0 || run.NeedApproval { - status = StatusBlocked - } else { - hasWaiting = true - } - job.Name = util.EllipsisDisplayString(job.Name, 255) - runJobs = append(runJobs, &ActionRunJob{ - RunID: run.ID, - RepoID: run.RepoID, - OwnerID: run.OwnerID, - CommitSHA: run.CommitSHA, - IsForkPullRequest: run.IsForkPullRequest, - Name: job.Name, - WorkflowPayload: payload, - JobID: id, - Needs: needs, - RunsOn: job.RunsOn(), - Status: status, - }) - } - if err := db.Insert(ctx, runJobs); err != nil { - return err - } - - // if there is a job in the waiting status, increase tasks version. - if hasWaiting { - if err := IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil { - return err - } - } - return nil - }) + // Return nil to indicate successful cancellation of all running and waiting jobs. + return cancelledJobs, nil } func GetRunByRepoAndID(ctx context.Context, repoID, runID int64) (*ActionRun, error) { @@ -441,7 +390,7 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error { if err = run.LoadRepo(ctx); err != nil { return err } - if err := updateRepoRunsNumbers(ctx, run.Repo); err != nil { + if err := UpdateRepoRunsNumbers(ctx, run.Repo); err != nil { return err } } @@ -450,3 +399,59 @@ func UpdateRun(ctx context.Context, run *ActionRun, cols ...string) error { } type ActionRunIndex db.ResourceIndex + +func GetConcurrentRunsAndJobs(ctx context.Context, repoID int64, concurrencyGroup string, status []Status) ([]*ActionRun, []*ActionRunJob, error) { + runs, err := db.Find[ActionRun](ctx, &FindRunOptions{ + RepoID: repoID, + ConcurrencyGroup: concurrencyGroup, + Status: status, + }) + if err != nil { + return nil, nil, fmt.Errorf("find runs: %w", err) + } + + jobs, err := db.Find[ActionRunJob](ctx, &FindRunJobOptions{ + RepoID: repoID, + ConcurrencyGroup: concurrencyGroup, + Statuses: status, + }) + if err != nil { + return nil, nil, fmt.Errorf("find jobs: %w", err) + } + + return runs, jobs, nil +} + +func CancelPreviousJobsByRunConcurrency(ctx context.Context, actionRun *ActionRun) ([]*ActionRunJob, error) { + if actionRun.ConcurrencyGroup == "" { + return nil, nil + } + + var jobsToCancel []*ActionRunJob + + statusFindOption := []Status{StatusWaiting, StatusBlocked} + if actionRun.ConcurrencyCancel { + statusFindOption = append(statusFindOption, StatusRunning) + } + runs, jobs, err := GetConcurrentRunsAndJobs(ctx, actionRun.RepoID, actionRun.ConcurrencyGroup, statusFindOption) + if err != nil { + return nil, fmt.Errorf("find concurrent runs and jobs: %w", err) + } + jobsToCancel = append(jobsToCancel, jobs...) + + // cancel runs in the same concurrency group + for _, run := range runs { + if run.ID == actionRun.ID { + continue + } + jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{ + RunID: run.ID, + }) + if err != nil { + return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err) + } + jobsToCancel = append(jobsToCancel, jobs...) + } + + return CancelJobs(ctx, jobsToCancel) +} diff --git a/models/actions/run_job.go b/models/actions/run_job.go index e7fa21270c..9c7c3658d7 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -22,23 +22,38 @@ type ActionRunJob struct { ID int64 RunID int64 `xorm:"index"` Run *ActionRun `xorm:"-"` - RepoID int64 `xorm:"index"` + RepoID int64 `xorm:"index(repo_concurrency)"` Repo *repo_model.Repository `xorm:"-"` OwnerID int64 `xorm:"index"` CommitSHA string `xorm:"index"` IsForkPullRequest bool Name string `xorm:"VARCHAR(255)"` Attempt int64 - WorkflowPayload []byte - JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id - Needs []string `xorm:"JSON TEXT"` - RunsOn []string `xorm:"JSON TEXT"` - TaskID int64 // the latest task of the job - Status Status `xorm:"index"` - Started timeutil.TimeStamp - Stopped timeutil.TimeStamp - Created timeutil.TimeStamp `xorm:"created"` - Updated timeutil.TimeStamp `xorm:"updated index"` + + // WorkflowPayload is act/jobparser.SingleWorkflow for act/jobparser.Parse + // it should contain exactly one job with global workflow fields for this model + WorkflowPayload []byte + + JobID string `xorm:"VARCHAR(255)"` // job id in workflow, not job's id + Needs []string `xorm:"JSON TEXT"` + RunsOn []string `xorm:"JSON TEXT"` + TaskID int64 // the latest task of the job + Status Status `xorm:"index"` + + RawConcurrency string // raw concurrency from job YAML's "concurrency" section + + // IsConcurrencyEvaluated is only valid/needed when this job's RawConcurrency is not empty. + // If RawConcurrency can't be evaluated (e.g. depend on other job's outputs or have errors), this field will be false. + // If RawConcurrency has been successfully evaluated, this field will be true, ConcurrencyGroup and ConcurrencyCancel are also set. + IsConcurrencyEvaluated bool + + ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` // evaluated concurrency.group + ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` // evaluated concurrency.cancel-in-progress + + Started timeutil.TimeStamp + Stopped timeutil.TimeStamp + Created timeutil.TimeStamp `xorm:"created"` + Updated timeutil.TimeStamp `xorm:"updated index"` } func init() { @@ -125,7 +140,7 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col return affected, nil } - if affected != 0 && slices.Contains(cols, "status") && job.Status.IsWaiting() { + if slices.Contains(cols, "status") && job.Status.IsWaiting() { // if the status of job changes to waiting again, increase tasks version. if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil { return 0, err @@ -197,3 +212,39 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status { return StatusUnknown // it shouldn't happen } } + +func CancelPreviousJobsByJobConcurrency(ctx context.Context, job *ActionRunJob) (jobsToCancel []*ActionRunJob, _ error) { + if job.RawConcurrency == "" { + return nil, nil + } + if !job.IsConcurrencyEvaluated { + return nil, nil + } + if job.ConcurrencyGroup == "" { + return nil, nil + } + + statusFindOption := []Status{StatusWaiting, StatusBlocked} + if job.ConcurrencyCancel { + statusFindOption = append(statusFindOption, StatusRunning) + } + runs, jobs, err := GetConcurrentRunsAndJobs(ctx, job.RepoID, job.ConcurrencyGroup, statusFindOption) + if err != nil { + return nil, fmt.Errorf("find concurrent runs and jobs: %w", err) + } + jobs = slices.DeleteFunc(jobs, func(j *ActionRunJob) bool { return j.ID == job.ID }) + jobsToCancel = append(jobsToCancel, jobs...) + + // cancel runs in the same concurrency group + for _, run := range runs { + jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{ + RunID: run.ID, + }) + if err != nil { + return nil, fmt.Errorf("find run %d jobs: %w", run.ID, err) + } + jobsToCancel = append(jobsToCancel, jobs...) + } + + return CancelJobs(ctx, jobsToCancel) +} diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index 5f7bb62878..10f76d3641 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -69,12 +69,13 @@ func (jobs ActionJobList) LoadAttributes(ctx context.Context, withRepo bool) err type FindRunJobOptions struct { db.ListOptions - RunID int64 - RepoID int64 - OwnerID int64 - CommitSHA string - Statuses []Status - UpdatedBefore timeutil.TimeStamp + RunID int64 + RepoID int64 + OwnerID int64 + CommitSHA string + Statuses []Status + UpdatedBefore timeutil.TimeStamp + ConcurrencyGroup string } func (opts FindRunJobOptions) ToConds() builder.Cond { @@ -94,6 +95,12 @@ func (opts FindRunJobOptions) ToConds() builder.Cond { if opts.UpdatedBefore > 0 { cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore}) } + if opts.ConcurrencyGroup != "" { + if opts.RepoID == 0 { + panic("Invalid FindRunJobOptions: repo_id is required") + } + cond = cond.And(builder.Eq{"`action_run_job`.concurrency_group": opts.ConcurrencyGroup}) + } return cond } diff --git a/models/actions/run_list.go b/models/actions/run_list.go index 12c55e538e..2628c4712f 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -64,15 +64,16 @@ func (runs RunList) LoadRepos(ctx context.Context) error { type FindRunOptions struct { db.ListOptions - RepoID int64 - OwnerID int64 - WorkflowID string - Ref string // the commit/tag/… that caused this workflow - TriggerUserID int64 - TriggerEvent webhook_module.HookEventType - Approved bool // not util.OptionalBool, it works only when it's true - Status []Status - CommitSHA string + RepoID int64 + OwnerID int64 + WorkflowID string + Ref string // the commit/tag/… that caused this workflow + TriggerUserID int64 + TriggerEvent webhook_module.HookEventType + Approved bool // not util.OptionalBool, it works only when it's true + Status []Status + ConcurrencyGroup string + CommitSHA string } func (opts FindRunOptions) ToConds() builder.Cond { @@ -101,6 +102,12 @@ func (opts FindRunOptions) ToConds() builder.Cond { if opts.CommitSHA != "" { cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA}) } + if len(opts.ConcurrencyGroup) > 0 { + if opts.RepoID == 0 { + panic("Invalid FindRunOptions: repo_id is required") + } + cond = cond.And(builder.Eq{"`action_run`.concurrency_group": opts.ConcurrencyGroup}) + } return cond } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 1b1558f39d..8fb10e84cf 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -394,6 +394,7 @@ func prepareMigrationTasks() []*migration { // Gitea 1.24.0 ends at database version 321 newMigration(321, "Use LONGTEXT for some columns and fix review_state.updated_files column", v1_25.UseLongTextInSomeColumnsAndFixBugs), newMigration(322, "Extend comment tree_path length limit", v1_25.ExtendCommentTreePathLength), + newMigration(323, "Add support for actions concurrency", v1_25.AddActionsConcurrency), } return preparedMigrations } diff --git a/models/migrations/v1_25/v323.go b/models/migrations/v1_25/v323.go new file mode 100644 index 0000000000..5f38ea8545 --- /dev/null +++ b/models/migrations/v1_25/v323.go @@ -0,0 +1,43 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_25 + +import ( + "xorm.io/xorm" +) + +func AddActionsConcurrency(x *xorm.Engine) error { + type ActionRun struct { + RepoID int64 `xorm:"index(repo_concurrency)"` + RawConcurrency string + ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` + ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` + } + + if _, err := x.SyncWithOptions(xorm.SyncOptions{ + IgnoreDropIndices: true, + }, new(ActionRun)); err != nil { + return err + } + + if err := x.Sync(new(ActionRun)); err != nil { + return err + } + + type ActionRunJob struct { + RepoID int64 `xorm:"index(repo_concurrency)"` + RawConcurrency string + IsConcurrencyEvaluated bool + ConcurrencyGroup string `xorm:"index(repo_concurrency) NOT NULL DEFAULT ''"` + ConcurrencyCancel bool `xorm:"NOT NULL DEFAULT FALSE"` + } + + if _, err := x.SyncWithOptions(xorm.SyncOptions{ + IgnoreDropIndices: true, + }, new(ActionRunJob)); err != nil { + return err + } + + return nil +} diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index 55ba7862a9..46c5147d99 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -227,9 +227,12 @@ func (s *Service) UpdateTask( } if req.Msg.State.Result != runnerv1.Result_RESULT_UNSPECIFIED { - if err := actions_service.EmitJobsIfReady(task.Job.RunID); err != nil { + if err := actions_service.EmitJobsIfReadyByRun(task.Job.RunID); err != nil { log.Error("Emit ready jobs of run %d: %v", task.Job.RunID, err) } + if task.Job.Run.Status.IsDone() { + actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, task.Job) + } } return connect.NewResponse(&runnerv1.UpdateTaskResponse{ diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 3422128026..232c627709 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -27,7 +27,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/templates" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/common" @@ -36,6 +35,7 @@ import ( notify_service "code.gitea.io/gitea/services/notify" "github.com/nektos/act/pkg/model" + "gopkg.in/yaml.v3" "xorm.io/builder" ) @@ -420,12 +420,45 @@ func Rerun(ctx *context_module.Context) { return } + // check run (workflow-level) concurrency + + job, jobs := getRunJobs(ctx, runIndex, jobIndex) + if ctx.Written() { + return + } + // reset run's start and stop time when it is done if run.Status.IsDone() { run.PreviousDuration = run.Duration() run.Started = 0 run.Stopped = 0 - if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration"); err != nil { + + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + ctx.ServerError("GetVariablesOfRun", fmt.Errorf("get run %d variables: %w", run.ID, err)) + return + } + + if run.RawConcurrency != "" { + var rawConcurrency model.RawConcurrency + if err := yaml.Unmarshal([]byte(run.RawConcurrency), &rawConcurrency); err != nil { + ctx.ServerError("UnmarshalRawConcurrency", fmt.Errorf("unmarshal raw concurrency: %w", err)) + return + } + + err = actions_service.EvaluateRunConcurrencyFillModel(ctx, run, &rawConcurrency, vars) + if err != nil { + ctx.ServerError("EvaluateRunConcurrencyFillModel", err) + return + } + + run.Status, err = actions_service.PrepareToStartRunWithConcurrency(ctx, run) + if err != nil { + ctx.ServerError("PrepareToStartRunWithConcurrency", err) + return + } + } + if err := actions_model.UpdateRun(ctx, run, "started", "stopped", "previous_duration", "status", "concurrency_group", "concurrency_cancel"); err != nil { ctx.ServerError("UpdateRun", err) return } @@ -437,16 +470,12 @@ func Rerun(ctx *context_module.Context) { notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run) } - job, jobs := getRunJobs(ctx, runIndex, jobIndex) - if ctx.Written() { - return - } - + isRunBlocked := run.Status == actions_model.StatusBlocked if jobIndexStr == "" { // rerun all jobs for _, j := range jobs { // if the job has needs, it should be set to "blocked" status to wait for other jobs - shouldBlock := len(j.Needs) > 0 - if err := rerunJob(ctx, j, shouldBlock); err != nil { + shouldBlockJob := len(j.Needs) > 0 || isRunBlocked + if err := rerunJob(ctx, j, shouldBlockJob); err != nil { ctx.ServerError("RerunJob", err) return } @@ -459,8 +488,8 @@ func Rerun(ctx *context_module.Context) { for _, j := range rerunJobs { // jobs other than the specified one should be set to "blocked" status - shouldBlock := j.JobID != job.JobID - if err := rerunJob(ctx, j, shouldBlock); err != nil { + shouldBlockJob := j.JobID != job.JobID || isRunBlocked + if err := rerunJob(ctx, j, shouldBlockJob); err != nil { ctx.ServerError("RerunJob", err) return } @@ -476,15 +505,37 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou } job.TaskID = 0 - job.Status = actions_model.StatusWaiting - if shouldBlock { - job.Status = actions_model.StatusBlocked - } + job.Status = util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting) job.Started = 0 job.Stopped = 0 + job.ConcurrencyGroup = "" + job.ConcurrencyCancel = false + job.IsConcurrencyEvaluated = false + if err := job.LoadRun(ctx); err != nil { + return err + } + + vars, err := actions_model.GetVariablesOfRun(ctx, job.Run) + if err != nil { + return fmt.Errorf("get run %d variables: %w", job.Run.ID, err) + } + + if job.RawConcurrency != "" && !shouldBlock { + err = actions_service.EvaluateJobConcurrencyFillModel(ctx, job.Run, job, vars) + if err != nil { + return fmt.Errorf("evaluate job concurrency: %w", err) + } + + job.Status, err = actions_service.PrepareToStartJobWithConcurrency(ctx, job) + if err != nil { + return err + } + } + if err := db.WithTx(ctx, func(ctx context.Context) error { - _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped") + updateCols := []string{"task_id", "status", "started", "stopped", "concurrency_group", "concurrency_cancel", "is_concurrency_evaluated"} + _, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, updateCols...) return err }); err != nil { return err @@ -523,33 +574,14 @@ func Cancel(ctx *context_module.Context) { return } - var updatedjobs []*actions_model.ActionRunJob + var updatedJobs []*actions_model.ActionRunJob if err := db.WithTx(ctx, func(ctx context.Context) error { - for _, job := range jobs { - status := job.Status - if status.IsDone() { - continue - } - if job.TaskID == 0 { - job.Status = actions_model.StatusCancelled - job.Stopped = timeutil.TimeStampNow() - n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped") - if err != nil { - return err - } - if n == 0 { - return errors.New("job has changed, try again") - } - if n > 0 { - updatedjobs = append(updatedjobs, job) - } - continue - } - if err := actions_model.StopTask(ctx, job.TaskID, actions_model.StatusCancelled); err != nil { - return err - } + cancelledJobs, err := actions_model.CancelJobs(ctx, jobs) + if err != nil { + return fmt.Errorf("cancel jobs: %w", err) } + updatedJobs = append(updatedJobs, cancelledJobs...) return nil }); err != nil { ctx.ServerError("StopTask", err) @@ -557,13 +589,14 @@ func Cancel(ctx *context_module.Context) { } actions_service.CreateCommitStatus(ctx, jobs...) + actions_service.EmitJobsIfReadyByJobs(updatedJobs) - for _, job := range updatedjobs { + for _, job := range updatedJobs { _ = job.LoadAttributes(ctx) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } - if len(updatedjobs) > 0 { - job := updatedjobs[0] + if len(updatedJobs) > 0 { + job := updatedJobs[0] actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job) } ctx.JSONOK() @@ -579,40 +612,44 @@ func Approve(ctx *context_module.Context) { run := current.Run doer := ctx.Doer - var updatedjobs []*actions_model.ActionRunJob + var updatedJobs []*actions_model.ActionRunJob - if err := db.WithTx(ctx, func(ctx context.Context) error { + err := db.WithTx(ctx, func(ctx context.Context) (err error) { run.NeedApproval = false run.ApprovedBy = doer.ID if err := actions_model.UpdateRun(ctx, run, "need_approval", "approved_by"); err != nil { return err } for _, job := range jobs { - if len(job.Needs) == 0 && job.Status.IsBlocked() { - job.Status = actions_model.StatusWaiting + job.Status, err = actions_service.PrepareToStartJobWithConcurrency(ctx, job) + if err != nil { + return err + } + if job.Status == actions_model.StatusWaiting { n, err := actions_model.UpdateRunJob(ctx, job, nil, "status") if err != nil { return err } if n > 0 { - updatedjobs = append(updatedjobs, job) + updatedJobs = append(updatedJobs, job) } } } return nil - }); err != nil { + }) + if err != nil { ctx.ServerError("UpdateRunJob", err) return } actions_service.CreateCommitStatus(ctx, jobs...) - if len(updatedjobs) > 0 { - job := updatedjobs[0] + if len(updatedJobs) > 0 { + job := updatedJobs[0] actions_service.NotifyWorkflowRunStatusUpdateWithReload(ctx, job) } - for _, job := range updatedjobs { + for _, job := range updatedJobs { _ = job.LoadAttributes(ctx) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index 3c7aa0b1a5..727a18443d 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" notify_service "code.gitea.io/gitea/services/notify" ) @@ -50,15 +51,84 @@ func notifyWorkflowJobStatusUpdate(ctx context.Context, jobs []*actions_model.Ac func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { jobs, err := actions_model.CancelPreviousJobs(ctx, repoID, ref, workflowID, event) notifyWorkflowJobStatusUpdate(ctx, jobs) + EmitJobsIfReadyByJobs(jobs) return err } func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error { jobs, err := actions_model.CleanRepoScheduleTasks(ctx, repo) notifyWorkflowJobStatusUpdate(ctx, jobs) + EmitJobsIfReadyByJobs(jobs) return err } +func shouldBlockJobByConcurrency(ctx context.Context, job *actions_model.ActionRunJob) (bool, error) { + if job.RawConcurrency != "" && !job.IsConcurrencyEvaluated { + // when the job depends on other jobs, we cannot evaluate its concurrency, so it should be blocked and will be evaluated again when its dependencies are done + return true, nil + } + + if job.ConcurrencyGroup == "" || job.ConcurrencyCancel { + return false, nil + } + + runs, jobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, job.RepoID, job.ConcurrencyGroup, []actions_model.Status{actions_model.StatusRunning}) + if err != nil { + return false, fmt.Errorf("GetConcurrentRunsAndJobs: %w", err) + } + + return len(runs) > 0 || len(jobs) > 0, nil +} + +// PrepareToStartJobWithConcurrency prepares a job to start by its evaluated concurrency group and cancelling previous jobs if necessary. +// It returns the new status of the job (either StatusBlocked or StatusWaiting) and any error encountered during the process. +func PrepareToStartJobWithConcurrency(ctx context.Context, job *actions_model.ActionRunJob) (actions_model.Status, error) { + shouldBlock, err := shouldBlockJobByConcurrency(ctx, job) + if err != nil { + return actions_model.StatusBlocked, err + } + + // even if the current job is blocked, we still need to cancel previous "waiting/blocked" jobs in the same concurrency group + jobs, err := actions_model.CancelPreviousJobsByJobConcurrency(ctx, job) + if err != nil { + return actions_model.StatusBlocked, fmt.Errorf("CancelPreviousJobsByJobConcurrency: %w", err) + } + notifyWorkflowJobStatusUpdate(ctx, jobs) + + return util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting), nil +} + +func shouldBlockRunByConcurrency(ctx context.Context, actionRun *actions_model.ActionRun) (bool, error) { + if actionRun.ConcurrencyGroup == "" || actionRun.ConcurrencyCancel { + return false, nil + } + + runs, jobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, actionRun.RepoID, actionRun.ConcurrencyGroup, []actions_model.Status{actions_model.StatusRunning}) + if err != nil { + return false, fmt.Errorf("find concurrent runs and jobs: %w", err) + } + + return len(runs) > 0 || len(jobs) > 0, nil +} + +// PrepareToStartRunWithConcurrency prepares a run to start by its evaluated concurrency group and cancelling previous jobs if necessary. +// It returns the new status of the run (either StatusBlocked or StatusWaiting) and any error encountered during the process. +func PrepareToStartRunWithConcurrency(ctx context.Context, run *actions_model.ActionRun) (actions_model.Status, error) { + shouldBlock, err := shouldBlockRunByConcurrency(ctx, run) + if err != nil { + return actions_model.StatusBlocked, err + } + + // even if the current run is blocked, we still need to cancel previous "waiting/blocked" jobs in the same concurrency group + jobs, err := actions_model.CancelPreviousJobsByRunConcurrency(ctx, run) + if err != nil { + return actions_model.StatusBlocked, fmt.Errorf("CancelPreviousJobsByRunConcurrency: %w", err) + } + notifyWorkflowJobStatusUpdate(ctx, jobs) + + return util.Iif(shouldBlock, actions_model.StatusBlocked, actions_model.StatusWaiting), nil +} + func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { tasks, err := db.Find[actions_model.ActionTask](ctx, opts) if err != nil { @@ -95,6 +165,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { } notifyWorkflowJobStatusUpdate(ctx, jobs) + EmitJobsIfReadyByJobs(jobs) return nil } @@ -103,7 +174,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { func CancelAbandonedJobs(ctx context.Context) error { jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, - UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), + UpdatedBefore: timeutil.TimeStampNow().AddDuration(-setting.Actions.AbandonedJobTimeout), }) if err != nil { log.Warn("find abandoned tasks: %v", err) @@ -114,6 +185,7 @@ func CancelAbandonedJobs(ctx context.Context) error { // Collect one job per run to send workflow run status update updatedRuns := map[int64]*actions_model.ActionRunJob{} + updatedJobs := []*actions_model.ActionRunJob{} for _, job := range jobs { job.Status = actions_model.StatusCancelled @@ -138,6 +210,7 @@ func CancelAbandonedJobs(ctx context.Context) error { } CreateCommitStatus(ctx, job) if updated { + updatedJobs = append(updatedJobs, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } } @@ -145,6 +218,7 @@ func CancelAbandonedJobs(ctx context.Context) error { for _, job := range updatedRuns { notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) } + EmitJobsIfReadyByJobs(updatedJobs) return nil } diff --git a/services/actions/concurrency.go b/services/actions/concurrency.go new file mode 100644 index 0000000000..2910e47739 --- /dev/null +++ b/services/actions/concurrency.go @@ -0,0 +1,121 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + "context" + "errors" + "fmt" + + actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/modules/json" + api "code.gitea.io/gitea/modules/structs" + + "github.com/nektos/act/pkg/jobparser" + act_model "github.com/nektos/act/pkg/model" + "gopkg.in/yaml.v3" +) + +// EvaluateRunConcurrencyFillModel evaluates the expressions in a run-level (workflow) concurrency, +// and fills the run's model fields with `concurrency.group` and `concurrency.cancel-in-progress`. +// Workflow-level concurrency doesn't depend on the job outputs, so it can always be evaluated if there is no syntax error. +// See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#concurrency +func EvaluateRunConcurrencyFillModel(ctx context.Context, run *actions_model.ActionRun, wfRawConcurrency *act_model.RawConcurrency, vars map[string]string) error { + if err := run.LoadAttributes(ctx); err != nil { + return fmt.Errorf("run LoadAttributes: %w", err) + } + + actionsRunCtx := GenerateGiteaContext(run, nil) + jobResults := map[string]*jobparser.JobResult{"": {}} + inputs, err := getInputsFromRun(run) + if err != nil { + return fmt.Errorf("get inputs: %w", err) + } + + rawConcurrency, err := yaml.Marshal(wfRawConcurrency) + if err != nil { + return fmt.Errorf("marshal raw concurrency: %w", err) + } + run.RawConcurrency = string(rawConcurrency) + run.ConcurrencyGroup, run.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(wfRawConcurrency, "", nil, actionsRunCtx, jobResults, vars, inputs) + if err != nil { + return fmt.Errorf("evaluate concurrency: %w", err) + } + return nil +} + +func findJobNeedsAndFillJobResults(ctx context.Context, job *actions_model.ActionRunJob) (map[string]*jobparser.JobResult, error) { + taskNeeds, err := FindTaskNeeds(ctx, job) + if err != nil { + return nil, fmt.Errorf("find task needs: %w", err) + } + jobResults := make(map[string]*jobparser.JobResult, len(taskNeeds)) + for jobID, taskNeed := range taskNeeds { + jobResult := &jobparser.JobResult{ + Result: taskNeed.Result.String(), + Outputs: taskNeed.Outputs, + } + jobResults[jobID] = jobResult + } + jobResults[job.JobID] = &jobparser.JobResult{ + Needs: job.Needs, + } + return jobResults, nil +} + +// EvaluateJobConcurrencyFillModel evaluates the expressions in a job-level concurrency, +// and fills the job's model fields with `concurrency.group` and `concurrency.cancel-in-progress`. +// Job-level concurrency may depend on other job's outputs (via `needs`): `concurrency.group: my-group-${{ needs.job1.outputs.out1 }}` +// If the needed jobs haven't been executed yet, this evaluation will also fail. +// See https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idconcurrency +func EvaluateJobConcurrencyFillModel(ctx context.Context, run *actions_model.ActionRun, actionRunJob *actions_model.ActionRunJob, vars map[string]string) error { + if err := actionRunJob.LoadAttributes(ctx); err != nil { + return fmt.Errorf("job LoadAttributes: %w", err) + } + + var rawConcurrency act_model.RawConcurrency + if err := yaml.Unmarshal([]byte(actionRunJob.RawConcurrency), &rawConcurrency); err != nil { + return fmt.Errorf("unmarshal raw concurrency: %w", err) + } + + actionsJobCtx := GenerateGiteaContext(run, actionRunJob) + + jobResults, err := findJobNeedsAndFillJobResults(ctx, actionRunJob) + if err != nil { + return fmt.Errorf("find job needs and fill job results: %w", err) + } + + inputs, err := getInputsFromRun(run) + if err != nil { + return fmt.Errorf("get inputs: %w", err) + } + + // singleWorkflows is created from an ActionJob, which always contains exactly a single job's YAML definition. + // Ideally it shouldn't be called "Workflow", it is just a job with global workflow fields + trigger + singleWorkflows, err := jobparser.Parse(actionRunJob.WorkflowPayload) + if err != nil { + return fmt.Errorf("parse single workflow: %w", err) + } else if len(singleWorkflows) != 1 { + return errors.New("not single workflow") + } + _, singleWorkflowJob := singleWorkflows[0].Job() + + actionRunJob.ConcurrencyGroup, actionRunJob.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(&rawConcurrency, actionRunJob.JobID, singleWorkflowJob, actionsJobCtx, jobResults, vars, inputs) + if err != nil { + return fmt.Errorf("evaluate concurrency: %w", err) + } + actionRunJob.IsConcurrencyEvaluated = true + return nil +} + +func getInputsFromRun(run *actions_model.ActionRun) (map[string]any, error) { + if run.Event != "workflow_dispatch" { + return map[string]any{}, nil + } + var payload api.WorkflowDispatchPayload + if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil { + return nil, err + } + return payload.Inputs, nil +} diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index 47c9f59094..c6578eae65 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -10,9 +10,12 @@ import ( actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/queue" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" notify_service "code.gitea.io/gitea/services/notify" "github.com/nektos/act/pkg/jobparser" @@ -25,7 +28,7 @@ type jobUpdate struct { RunID int64 } -func EmitJobsIfReady(runID int64) error { +func EmitJobsIfReadyByRun(runID int64) error { err := jobEmitterQueue.Push(&jobUpdate{ RunID: runID, }) @@ -35,53 +38,77 @@ func EmitJobsIfReady(runID int64) error { return err } +func EmitJobsIfReadyByJobs(jobs []*actions_model.ActionRunJob) { + checkedRuns := make(container.Set[int64]) + for _, job := range jobs { + if !job.Status.IsDone() || checkedRuns.Contains(job.RunID) { + continue + } + if err := EmitJobsIfReadyByRun(job.RunID); err != nil { + log.Error("Check jobs of run %d: %v", job.RunID, err) + } + checkedRuns.Add(job.RunID) + } +} + func jobEmitterQueueHandler(items ...*jobUpdate) []*jobUpdate { ctx := graceful.GetManager().ShutdownContext() var ret []*jobUpdate for _, update := range items { - if err := checkJobsOfRun(ctx, update.RunID); err != nil { + if err := checkJobsByRunID(ctx, update.RunID); err != nil { + log.Error("check run %d: %v", update.RunID, err) ret = append(ret, update) } } return ret } -func checkJobsOfRun(ctx context.Context, runID int64) error { - jobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: runID}) - if err != nil { - return err +func checkJobsByRunID(ctx context.Context, runID int64) error { + run, exist, err := db.GetByID[actions_model.ActionRun](ctx, runID) + if !exist { + return fmt.Errorf("run %d does not exist", runID) } - var updatedjobs []*actions_model.ActionRunJob + if err != nil { + return fmt.Errorf("get action run: %w", err) + } + var jobs, updatedJobs []*actions_model.ActionRunJob if err := db.WithTx(ctx, func(ctx context.Context) error { - idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs)) - for _, job := range jobs { - idToJobs[job.JobID] = append(idToJobs[job.JobID], job) + // check jobs of the current run + if js, ujs, err := checkJobsOfRun(ctx, run); err != nil { + return err + } else { + jobs = append(jobs, js...) + updatedJobs = append(updatedJobs, ujs...) } - - updates := newJobStatusResolver(jobs).Resolve() - for _, job := range jobs { - if status, ok := updates[job.ID]; ok { - job.Status = status - if n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": actions_model.StatusBlocked}, "status"); err != nil { - return err - } else if n != 1 { - return fmt.Errorf("no affected for updating blocked job %v", job.ID) - } - updatedjobs = append(updatedjobs, job) - } + if js, ujs, err := checkRunConcurrency(ctx, run); err != nil { + return err + } else { + jobs = append(jobs, js...) + updatedJobs = append(updatedJobs, ujs...) } return nil }); err != nil { return err } CreateCommitStatus(ctx, jobs...) - for _, job := range updatedjobs { + for _, job := range updatedJobs { _ = job.LoadAttributes(ctx) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) } - if len(jobs) > 0 { + runJobs := make(map[int64][]*actions_model.ActionRunJob) + for _, job := range jobs { + runJobs[job.RunID] = append(runJobs[job.RunID], job) + } + runUpdatedJobs := make(map[int64][]*actions_model.ActionRunJob) + for _, uj := range updatedJobs { + runUpdatedJobs[uj.RunID] = append(runUpdatedJobs[uj.RunID], uj) + } + for runID, js := range runJobs { + if len(runUpdatedJobs[runID]) == 0 { + continue + } runUpdated := true - for _, job := range jobs { + for _, job := range js { if !job.Status.IsDone() { runUpdated = false break @@ -94,6 +121,118 @@ func checkJobsOfRun(ctx context.Context, runID int64) error { return nil } +// findBlockedRunByConcurrency finds the blocked concurrent run in a repo and returns `nil, nil` when there is no blocked run. +func findBlockedRunByConcurrency(ctx context.Context, repoID int64, concurrencyGroup string) (*actions_model.ActionRun, error) { + if concurrencyGroup == "" { + return nil, nil + } + cRuns, cJobs, err := actions_model.GetConcurrentRunsAndJobs(ctx, repoID, concurrencyGroup, []actions_model.Status{actions_model.StatusBlocked}) + if err != nil { + return nil, fmt.Errorf("find concurrent runs and jobs: %w", err) + } + + // There can be at most one blocked run or job + var concurrentRun *actions_model.ActionRun + if len(cRuns) > 0 { + concurrentRun = cRuns[0] + } else if len(cJobs) > 0 { + jobRun, exist, err := db.GetByID[actions_model.ActionRun](ctx, cJobs[0].RunID) + if !exist { + return nil, fmt.Errorf("run %d does not exist", cJobs[0].RunID) + } + if err != nil { + return nil, fmt.Errorf("get run by job %d: %w", cJobs[0].ID, err) + } + concurrentRun = jobRun + } + + return concurrentRun, nil +} + +func checkRunConcurrency(ctx context.Context, run *actions_model.ActionRun) (jobs, updatedJobs []*actions_model.ActionRunJob, err error) { + checkedConcurrencyGroup := make(container.Set[string]) + + // check run (workflow-level) concurrency + if run.ConcurrencyGroup != "" { + concurrentRun, err := findBlockedRunByConcurrency(ctx, run.RepoID, run.ConcurrencyGroup) + if err != nil { + return nil, nil, fmt.Errorf("find blocked run by concurrency: %w", err) + } + if concurrentRun != nil && !concurrentRun.NeedApproval { + js, ujs, err := checkJobsOfRun(ctx, concurrentRun) + if err != nil { + return nil, nil, err + } + jobs = append(jobs, js...) + updatedJobs = append(updatedJobs, ujs...) + } + checkedConcurrencyGroup.Add(run.ConcurrencyGroup) + } + + // check job concurrency + runJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + if err != nil { + return nil, nil, fmt.Errorf("find run %d jobs: %w", run.ID, err) + } + for _, job := range runJobs { + if !job.Status.IsDone() { + continue + } + if job.ConcurrencyGroup == "" && checkedConcurrencyGroup.Contains(job.ConcurrencyGroup) { + continue + } + concurrentRun, err := findBlockedRunByConcurrency(ctx, job.RepoID, job.ConcurrencyGroup) + if err != nil { + return nil, nil, fmt.Errorf("find blocked run by concurrency: %w", err) + } + if concurrentRun != nil && !concurrentRun.NeedApproval { + js, ujs, err := checkJobsOfRun(ctx, concurrentRun) + if err != nil { + return nil, nil, err + } + jobs = append(jobs, js...) + updatedJobs = append(updatedJobs, ujs...) + } + checkedConcurrencyGroup.Add(job.ConcurrencyGroup) + } + return jobs, updatedJobs, nil +} + +func checkJobsOfRun(ctx context.Context, run *actions_model.ActionRun) (jobs, updatedJobs []*actions_model.ActionRunJob, err error) { + jobs, err = db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + if err != nil { + return nil, nil, err + } + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + return nil, nil, err + } + + if err = db.WithTx(ctx, func(ctx context.Context) error { + for _, job := range jobs { + job.Run = run + } + + updates := newJobStatusResolver(jobs, vars).Resolve(ctx) + for _, job := range jobs { + if status, ok := updates[job.ID]; ok { + job.Status = status + if n, err := actions_model.UpdateRunJob(ctx, job, builder.Eq{"status": actions_model.StatusBlocked}, "status"); err != nil { + return err + } else if n != 1 { + return fmt.Errorf("no affected for updating blocked job %v", job.ID) + } + updatedJobs = append(updatedJobs, job) + } + } + return nil + }); err != nil { + return nil, nil, err + } + + return jobs, updatedJobs, nil +} + func NotifyWorkflowRunStatusUpdateWithReload(ctx context.Context, job *actions_model.ActionRunJob) { job.Run = nil if err := job.LoadAttributes(ctx); err != nil { @@ -107,9 +246,10 @@ type jobStatusResolver struct { statuses map[int64]actions_model.Status needs map[int64][]int64 jobMap map[int64]*actions_model.ActionRunJob + vars map[string]string } -func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver { +func newJobStatusResolver(jobs actions_model.ActionJobList, vars map[string]string) *jobStatusResolver { idToJobs := make(map[string][]*actions_model.ActionRunJob, len(jobs)) jobMap := make(map[int64]*actions_model.ActionRunJob) for _, job := range jobs { @@ -131,13 +271,14 @@ func newJobStatusResolver(jobs actions_model.ActionJobList) *jobStatusResolver { statuses: statuses, needs: needs, jobMap: jobMap, + vars: vars, } } -func (r *jobStatusResolver) Resolve() map[int64]actions_model.Status { +func (r *jobStatusResolver) Resolve(ctx context.Context) map[int64]actions_model.Status { ret := map[int64]actions_model.Status{} for i := 0; i < len(r.statuses); i++ { - updated := r.resolve() + updated := r.resolve(ctx) if len(updated) == 0 { return ret } @@ -149,43 +290,86 @@ func (r *jobStatusResolver) Resolve() map[int64]actions_model.Status { return ret } -func (r *jobStatusResolver) resolve() map[int64]actions_model.Status { +func (r *jobStatusResolver) resolveCheckNeeds(id int64) (allDone, allSucceed bool) { + allDone, allSucceed = true, true + for _, need := range r.needs[id] { + needStatus := r.statuses[need] + if !needStatus.IsDone() { + allDone = false + } + if needStatus.In(actions_model.StatusFailure, actions_model.StatusCancelled, actions_model.StatusSkipped) { + allSucceed = false + } + } + return allDone, allSucceed +} + +func (r *jobStatusResolver) resolveJobHasIfCondition(actionRunJob *actions_model.ActionRunJob) (hasIf bool) { + if wfJobs, _ := jobparser.Parse(actionRunJob.WorkflowPayload); len(wfJobs) == 1 { + _, wfJob := wfJobs[0].Job() + hasIf = len(wfJob.If.Value) > 0 + } + return hasIf +} + +func (r *jobStatusResolver) resolve(ctx context.Context) map[int64]actions_model.Status { ret := map[int64]actions_model.Status{} for id, status := range r.statuses { + actionRunJob := r.jobMap[id] if status != actions_model.StatusBlocked { continue } - allDone, allSucceed := true, true - for _, need := range r.needs[id] { - needStatus := r.statuses[need] - if !needStatus.IsDone() { - allDone = false - } - if needStatus.In(actions_model.StatusFailure, actions_model.StatusCancelled, actions_model.StatusSkipped) { - allSucceed = false + allDone, allSucceed := r.resolveCheckNeeds(id) + if !allDone { + continue + } + + // update concurrency and check whether the job can run now + err := updateConcurrencyEvaluationForJobWithNeeds(ctx, actionRunJob, r.vars) + if err != nil { + // The err can be caused by different cases: database error, or syntax error, or the needed jobs haven't completed + // At the moment there is no way to distinguish them. + // Actually, for most cases, the error is caused by "syntax error" / "the needed jobs haven't completed (skipped?)" + // TODO: if workflow or concurrency expression has syntax error, there should be a user error message, need to show it to end users + log.Debug("updateConcurrencyEvaluationForJobWithNeeds failed, this job will stay blocked: job: %d, err: %v", id, err) + continue + } + + shouldStartJob := true + if !allSucceed { + // Not all dependent jobs completed successfully: + // * if the job has "if" condition, it can be started, then the act_runner will evaluate the "if" condition. + // * otherwise, the job should be skipped. + shouldStartJob = r.resolveJobHasIfCondition(actionRunJob) + } + + newStatus := util.Iif(shouldStartJob, actions_model.StatusWaiting, actions_model.StatusSkipped) + if newStatus == actions_model.StatusWaiting { + newStatus, err = PrepareToStartJobWithConcurrency(ctx, actionRunJob) + if err != nil { + log.Error("ShouldBlockJobByConcurrency failed, this job will stay blocked: job: %d, err: %v", id, err) } } - if allDone { - if allSucceed { - ret[id] = actions_model.StatusWaiting - } else { - // Check if the job has an "if" condition - hasIf := false - if wfJobs, _ := jobparser.Parse(r.jobMap[id].WorkflowPayload); len(wfJobs) == 1 { - _, wfJob := wfJobs[0].Job() - hasIf = len(wfJob.If.Value) > 0 - } - if hasIf { - // act_runner will check the "if" condition - ret[id] = actions_model.StatusWaiting - } else { - // If the "if" condition is empty and not all dependent jobs completed successfully, - // the job should be skipped. - ret[id] = actions_model.StatusSkipped - } - } + if newStatus != actions_model.StatusBlocked { + ret[id] = newStatus } } return ret } + +func updateConcurrencyEvaluationForJobWithNeeds(ctx context.Context, actionRunJob *actions_model.ActionRunJob, vars map[string]string) error { + if setting.IsInTesting && actionRunJob.RepoID == 0 { + return nil // for testing purpose only, no repo, no evaluation + } + + err := EvaluateJobConcurrencyFillModel(ctx, actionRunJob.Run, actionRunJob, vars) + if err != nil { + return fmt.Errorf("evaluate job concurrency: %w", err) + } + + if _, err := actions_model.UpdateRunJob(ctx, actionRunJob, nil, "concurrency_group", "concurrency_cancel", "is_concurrency_evaluated"); err != nil { + return fmt.Errorf("update run job: %w", err) + } + return nil +} diff --git a/services/actions/job_emitter_test.go b/services/actions/job_emitter_test.go index 58c2dc3b24..a2152fb270 100644 --- a/services/actions/job_emitter_test.go +++ b/services/actions/job_emitter_test.go @@ -129,8 +129,8 @@ jobs: } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := newJobStatusResolver(tt.jobs) - assert.Equal(t, tt.want, r.Resolve()) + r := newJobStatusResolver(tt.jobs, nil) + assert.Equal(t, tt.want, r.Resolve(t.Context())) }) } } diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index d0d2572b0b..fc1894c5d8 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -357,6 +357,19 @@ func handleWorkflows( continue } + wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(dwf.Content) + if err != nil { + log.Error("ReadWorkflowRawConcurrency: %v", err) + continue + } + if wfRawConcurrency != nil { + err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) + if err != nil { + log.Error("EvaluateRunConcurrencyFillModel: %v", err) + continue + } + } + giteaCtx := GenerateGiteaContext(run, nil) jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext())) @@ -369,21 +382,7 @@ func handleWorkflows( run.Title = jobs[0].RunName } - // cancel running jobs if the event is push or pull_request_sync - if run.Event == webhook_module.HookEventPush || - run.Event == webhook_module.HookEventPullRequestSync { - if err := CancelPreviousJobs( - ctx, - run.RepoID, - run.Ref, - run.WorkflowID, - run.Event, - ); err != nil { - log.Error("CancelPreviousJobs: %v", err) - } - } - - if err := actions_model.InsertRun(ctx, run, jobs); err != nil { + if err := InsertRun(ctx, run, jobs); err != nil { log.Error("InsertRun: %v", err) continue } diff --git a/services/actions/run.go b/services/actions/run.go new file mode 100644 index 0000000000..a3356d71c1 --- /dev/null +++ b/services/actions/run.go @@ -0,0 +1,127 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + "context" + "fmt" + + actions_model "code.gitea.io/gitea/models/actions" + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/util" + + "github.com/nektos/act/pkg/jobparser" + "gopkg.in/yaml.v3" +) + +// InsertRun inserts a run +// The title will be cut off at 255 characters if it's longer than 255 characters. +func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobparser.SingleWorkflow) error { + return db.WithTx(ctx, func(ctx context.Context) error { + index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID) + if err != nil { + return err + } + run.Index = index + run.Title = util.EllipsisDisplayString(run.Title, 255) + + // check run (workflow-level) concurrency + run.Status, err = PrepareToStartRunWithConcurrency(ctx, run) + if err != nil { + return err + } + + if err := db.Insert(ctx, run); err != nil { + return err + } + + if err := run.LoadRepo(ctx); err != nil { + return err + } + + if err := actions_model.UpdateRepoRunsNumbers(ctx, run.Repo); err != nil { + return err + } + + // query vars for evaluating job concurrency groups + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + return fmt.Errorf("get run %d variables: %w", run.ID, err) + } + + runJobs := make([]*actions_model.ActionRunJob, 0, len(jobs)) + var hasWaitingJobs bool + for _, v := range jobs { + id, job := v.Job() + needs := job.Needs() + if err := v.SetJob(id, job.EraseNeeds()); err != nil { + return err + } + payload, _ := v.Marshal() + + shouldBlockJob := len(needs) > 0 || run.NeedApproval || run.Status == actions_model.StatusBlocked + + job.Name = util.EllipsisDisplayString(job.Name, 255) + runJob := &actions_model.ActionRunJob{ + RunID: run.ID, + RepoID: run.RepoID, + OwnerID: run.OwnerID, + CommitSHA: run.CommitSHA, + IsForkPullRequest: run.IsForkPullRequest, + Name: job.Name, + WorkflowPayload: payload, + JobID: id, + Needs: needs, + RunsOn: job.RunsOn(), + Status: util.Iif(shouldBlockJob, actions_model.StatusBlocked, actions_model.StatusWaiting), + } + // check job concurrency + if job.RawConcurrency != nil { + rawConcurrency, err := yaml.Marshal(job.RawConcurrency) + if err != nil { + return fmt.Errorf("marshal raw concurrency: %w", err) + } + runJob.RawConcurrency = string(rawConcurrency) + + // do not evaluate job concurrency when it requires `needs`, the jobs with `needs` will be evaluated later by job emitter + if len(needs) == 0 { + err = EvaluateJobConcurrencyFillModel(ctx, run, runJob, vars) + if err != nil { + return fmt.Errorf("evaluate job concurrency: %w", err) + } + } + + // If a job needs other jobs ("needs" is not empty), its status is set to StatusBlocked at the entry of the loop + // No need to check job concurrency for a blocked job (it will be checked by job emitter later) + if runJob.Status == actions_model.StatusWaiting { + runJob.Status, err = PrepareToStartJobWithConcurrency(ctx, runJob) + if err != nil { + return fmt.Errorf("prepare to start job with concurrency: %w", err) + } + } + } + + hasWaitingJobs = hasWaitingJobs || runJob.Status == actions_model.StatusWaiting + if err := db.Insert(ctx, runJob); err != nil { + return err + } + + runJobs = append(runJobs, runJob) + } + + run.Status = actions_model.AggregateJobStatus(runJobs) + if err := actions_model.UpdateRun(ctx, run, "status"); err != nil { + return err + } + + // if there is a job in the waiting status, increase tasks version. + if hasWaitingJobs { + if err := actions_model.IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil { + return err + } + } + + return nil + }) +} diff --git a/services/actions/schedule_tasks.go b/services/actions/schedule_tasks.go index c029c5a1a2..3b37b44ac4 100644 --- a/services/actions/schedule_tasks.go +++ b/services/actions/schedule_tasks.go @@ -53,20 +53,6 @@ func startTasks(ctx context.Context) error { // Loop through each spec and create a schedule task for it for _, row := range specs { - // cancel running jobs if the event is push - if row.Schedule.Event == webhook_module.HookEventPush { - // cancel running jobs of the same workflow - if err := CancelPreviousJobs( - ctx, - row.RepoID, - row.Schedule.Ref, - row.Schedule.WorkflowID, - webhook_module.HookEventSchedule, - ); err != nil { - log.Error("CancelPreviousJobs: %v", err) - } - } - if row.Repo.IsArchived { // Skip if the repo is archived continue @@ -144,9 +130,19 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule) if err != nil { return err } + wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(cron.Content) + if err != nil { + return err + } + if wfRawConcurrency != nil { + err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) + if err != nil { + return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err) + } + } // Insert the action run and its associated jobs into the database - if err := actions_model.InsertRun(ctx, run, workflows); err != nil { + if err := InsertRun(ctx, run, workflows); err != nil { return err } allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) diff --git a/services/actions/workflow.go b/services/actions/workflow.go index 40b34194e9..e3e60d4967 100644 --- a/services/actions/workflow.go +++ b/services/actions/workflow.go @@ -100,6 +100,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re // find workflow from commit var workflows []*jobparser.SingleWorkflow var entry *git.TreeEntry + var wfRawConcurrency *model.RawConcurrency run := &actions_model.ActionRun{ Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0], @@ -170,6 +171,11 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re ) } + wfRawConcurrency, err = jobparser.ReadWorkflowRawConcurrency(content) + if err != nil { + return err + } + // ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event // https://docs.github.com/en/actions/learn-github-actions/contexts#github-context // https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch @@ -187,19 +193,20 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re } run.EventPayload = string(eventPayload) - // cancel running jobs of the same workflow - if err := CancelPreviousJobs( - ctx, - run.RepoID, - run.Ref, - run.WorkflowID, - run.Event, - ); err != nil { - log.Error("CancelRunningJobs: %v", err) + // cancel running jobs of the same concurrency group + if wfRawConcurrency != nil { + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + return fmt.Errorf("GetVariablesOfRun: %w", err) + } + err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) + if err != nil { + return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err) + } } // Insert the action run and its associated jobs into the database - if err := actions_model.InsertRun(ctx, run, workflows); err != nil { + if err := InsertRun(ctx, run, workflows); err != nil { return fmt.Errorf("InsertRun: %w", err) } diff --git a/tests/integration/actions_concurrency_test.go b/tests/integration/actions_concurrency_test.go new file mode 100644 index 0000000000..cc61368260 --- /dev/null +++ b/tests/integration/actions_concurrency_test.go @@ -0,0 +1,1709 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "encoding/base64" + "fmt" + "net/http" + "net/url" + "testing" + "time" + + actions_model "code.gitea.io/gitea/models/actions" + auth_model "code.gitea.io/gitea/models/auth" + 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/setting" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" + webhook_module "code.gitea.io/gitea/modules/webhook" + actions_service "code.gitea.io/gitea/services/actions" + + runnerv1 "code.gitea.io/actions-proto-go/runner/v1" + "github.com/stretchr/testify/assert" +) + +func TestWorkflowConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + // add a variable for test + req := NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/myvar", user2.Name, repo.Name), &api.CreateVariableOption{ + Value: "abc123", + }). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +concurrency: + group: workflow-main-abc123-user2 +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow1' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +concurrency: + group: workflow-${{ gitea.ref_name }}-${{ vars.myvar }}-${{ gitea.event.pusher.username }} +jobs: + wf2-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow2' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +concurrency: + group: workflow-main-abc${{ 123 }}-${{ gitea.event.pusher.username }} +jobs: + wf3-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow3' +` + // push workflow1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + // fetch and exec workflow1 + task := runner.fetchTask(t) + _, _, run := getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-1.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // push workflow2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + // fetch workflow2 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-2.yml", run.WorkflowID) + + // push workflow3 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + runner.fetchNoTask(t) + + // exec workflow2 + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch and exec workflow3 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-3.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + }) +} + +func TestWorkflowConcurrencyShort(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + // add a variable for test + req := NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/myvar", user2.Name, repo.Name), &api.CreateVariableOption{ + Value: "abc123", + }). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +concurrency: workflow-main-abc123-user2 +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow1' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +concurrency: workflow-${{ gitea.ref_name }}-${{ vars.myvar }}-${{ gitea.event.pusher.username }} +jobs: + wf2-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow2' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +concurrency: workflow-main-abc${{ 123 }}-${{ gitea.event.pusher.username }} +jobs: + wf3-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow3' +` + // push workflow1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + // fetch and exec workflow1 + task := runner.fetchTask(t) + _, _, run := getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-1.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // push workflow2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + // fetch workflow2 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-2.yml", run.WorkflowID) + + // push workflow3 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + runner.fetchNoTask(t) + + // exec workflow2 + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch and exec workflow3 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-3.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + }) +} + +func TestWorkflowConcurrencyShortJson(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + // add a variable for test + req := NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/myvar", user2.Name, repo.Name), &api.CreateVariableOption{ + Value: "abc123", + }). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +concurrency: |- + ${{ fromjson('{ + "group": "workflow-main-abc123-user2", + "cancel-in-progress": false + }') }} +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow1' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +concurrency: |- + ${{ fromjson('{ + "group": "workflow-main-abc123-user2", + "cancel-in-progress": false + }') }} +jobs: + wf2-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow2' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +concurrency: |- + ${{ fromjson('{ + "group": "workflow-main-abc123-user2", + "cancel-in-progress": false + }') }} +jobs: + wf3-job: + runs-on: ubuntu-latest + steps: + - run: echo 'job from workflow3' +` + // push workflow1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + // fetch and exec workflow1 + task := runner.fetchTask(t) + _, _, run := getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-1.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // push workflow2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + // fetch workflow2 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-2.yml", run.WorkflowID) + + // push workflow3 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + runner.fetchNoTask(t) + + // exec workflow2 + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch and exec workflow3 + task = runner.fetchTask(t) + _, _, run = getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "workflow-main-abc123-user2", run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-3.yml", run.WorkflowID) + runner.fetchNoTask(t) + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + }) +} + +func TestPullRequestWorkflowConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + // user2 is the owner of the base repo + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + user2Session := loginUser(t, user2.Name) + user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + // user4 is the owner of the forked repo + user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) + user4Token := getTokenForLoggedInUser(t, loginUser(t, user4.Name), auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiBaseRepo := createActionsTestRepo(t, user2Token, "actions-concurrency", false) + baseRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiBaseRepo.ID}) + user2APICtx := NewAPITestContext(t, baseRepo.OwnerName, baseRepo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(user2APICtx)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, baseRepo.OwnerName, baseRepo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + // init the workflow + wfTreePath := ".gitea/workflows/pull.yml" + wfFileContent := `name: Pull Request +on: pull_request +concurrency: + group: pull-request-test + cancel-in-progress: ${{ !startsWith(gitea.head_ref, 'do-not-cancel/') }} +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'test the pull' +` + opts1 := getWorkflowCreateFileOptions(user2, baseRepo.DefaultBranch, "create %s"+wfTreePath, wfFileContent) + createWorkflowFile(t, user2Token, baseRepo.OwnerName, baseRepo.Name, wfTreePath, opts1) + // user2 creates a pull request + doAPICreateFile(user2APICtx, "user2-fix.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + NewBranchName: "bugfix/aaa", + Message: "create user2-fix.txt", + Author: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Committer: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("user2-fix")), + })(t) + doAPICreatePullRequest(user2APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, "bugfix/aaa")(t) + pr1Task1 := runner.fetchTask(t) + _, _, pr1Run1 := getTaskAndJobAndRunByTaskID(t, pr1Task1.Id) + assert.Equal(t, "pull-request-test", pr1Run1.ConcurrencyGroup) + assert.True(t, pr1Run1.ConcurrencyCancel) + assert.Equal(t, actions_model.StatusRunning, pr1Run1.Status) + + // user4 forks the repo + req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/forks", baseRepo.OwnerName, baseRepo.Name), + &api.CreateForkOption{ + Name: util.ToPointer("actions-concurrency-fork"), + }).AddTokenAuth(user4Token) + resp := MakeRequest(t, req, http.StatusAccepted) + var apiForkRepo api.Repository + DecodeJSON(t, resp, &apiForkRepo) + forkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiForkRepo.ID}) + user4APICtx := NewAPITestContext(t, user4.Name, forkRepo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(user4APICtx)(t) + + // user4 creates a pull request from branch "bugfix/bbb" + doAPICreateFile(user4APICtx, "user4-fix.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + NewBranchName: "bugfix/bbb", + Message: "create user4-fix.txt", + Author: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Committer: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("user4-fix")), + })(t) + doAPICreatePullRequest(user4APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, user4.Name+":bugfix/bbb")(t) + // cannot fetch the task because an approval is required + runner.fetchNoTask(t) + // user2 approves the run + pr2Run1 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID, TriggerUserID: user4.ID}) + req = NewRequestWithValues(t, "POST", + fmt.Sprintf("/%s/%s/actions/runs/%d/approve", baseRepo.OwnerName, baseRepo.Name, pr2Run1.Index), + map[string]string{ + "_csrf": GetUserCSRFToken(t, user2Session), + }) + user2Session.MakeRequest(t, req, http.StatusOK) + // fetch the task and the previous task has been cancelled + pr2Task1 := runner.fetchTask(t) + _, _, pr2Run1 = getTaskAndJobAndRunByTaskID(t, pr2Task1.Id) + assert.Equal(t, "pull-request-test", pr2Run1.ConcurrencyGroup) + assert.True(t, pr2Run1.ConcurrencyCancel) + assert.Equal(t, actions_model.StatusRunning, pr2Run1.Status) + pr1Run1 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: pr1Run1.ID}) + assert.Equal(t, actions_model.StatusCancelled, pr1Run1.Status) + + // user4 creates another pull request from branch "do-not-cancel/ccc" + doAPICreateFile(user4APICtx, "user4-fix2.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + NewBranchName: "do-not-cancel/ccc", + Message: "create user4-fix2.txt", + Author: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Committer: api.Identity{ + Name: user4.Name, + Email: user4.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("user4-fix2")), + })(t) + doAPICreatePullRequest(user4APICtx, baseRepo.OwnerName, baseRepo.Name, baseRepo.DefaultBranch, user4.Name+":do-not-cancel/ccc")(t) + // cannot fetch the task because cancel-in-progress is false + runner.fetchNoTask(t) + runner.execTask(t, pr2Task1, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + pr2Run1 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: pr2Run1.ID}) + assert.Equal(t, actions_model.StatusSuccess, pr2Run1.Status) + // fetch the task + pr3Task1 := runner.fetchTask(t) + _, _, pr3Run1 := getTaskAndJobAndRunByTaskID(t, pr3Task1.Id) + assert.Equal(t, "pull-request-test", pr3Run1.ConcurrencyGroup) + assert.False(t, pr3Run1.ConcurrencyCancel) + assert.Equal(t, actions_model.StatusRunning, pr3Run1.Status) + }) +} + +func TestJobConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner1 := newMockRunner() + runner1.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner-1", []string{"runner1"}, false) + runner2 := newMockRunner() + runner2.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner-2", []string{"runner2"}, false) + + // add a variable for test + req := NewRequestWithJSON(t, "POST", + fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/version_var", user2.Name, repo.Name), &api.CreateVariableOption{ + Value: "v1.23.0", + }). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +jobs: + wf1-job1: + runs-on: runner1 + concurrency: + group: job-main-${{ vars.version_var }} + steps: + - run: echo 'wf1-job1' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +jobs: + wf2-job1: + runs-on: runner2 + outputs: + version: ${{ steps.version_step.outputs.app_version }} + steps: + - id: version_step + run: echo "app_version=v1.23.0" >> "$GITHUB_OUTPUT" + wf2-job2: + runs-on: runner1 + needs: [wf2-job1] + concurrency: + group: job-main-${{ needs.wf2-job1.outputs.version }} + steps: + - run: echo 'wf2-job2' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +jobs: + wf3-job1: + runs-on: runner1 + concurrency: + group: job-main-${{ vars.version_var }} + cancel-in-progress: ${{ vars.version_var == 'v1.23.0' }} + steps: + - run: echo 'wf3-job1' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + + // fetch wf1-job1 + wf1Job1Task := runner1.fetchTask(t) + _, wf1Job1ActionJob, _ := getTaskAndJobAndRunByTaskID(t, wf1Job1Task.Id) + assert.Equal(t, "job-main-v1.23.0", wf1Job1ActionJob.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, wf1Job1ActionJob.Status) + // fetch and exec wf2-job1 + wf2Job1Task := runner2.fetchTask(t) + runner2.execTask(t, wf2Job1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + outputs: map[string]string{ + "version": "v1.23.0", + }, + }) + // cannot fetch wf2-job2 because wf1-job1 is running + runner1.fetchNoTask(t) + // exec wf1-job1 + runner1.execTask(t, wf1Job1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + // fetch wf2-job2 + wf2Job2Task := runner1.fetchTask(t) + _, wf2Job2ActionJob, wf2Run := getTaskAndJobAndRunByTaskID(t, wf2Job2Task.Id) + assert.Equal(t, "job-main-v1.23.0", wf2Job2ActionJob.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, wf2Job2ActionJob.Status) + // push workflow3 to trigger wf3-job1 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + // fetch wf3-job1 + wf3Job1Task := runner1.fetchTask(t) + _, wf3Job1ActionJob, _ := getTaskAndJobAndRunByTaskID(t, wf3Job1Task.Id) + assert.Equal(t, "job-main-v1.23.0", wf3Job1ActionJob.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, wf3Job1ActionJob.Status) + // wf2-job2 has been cancelled + _, wf2Job2ActionJob, _ = getTaskAndJobAndRunByTaskID(t, wf2Job2Task.Id) + assert.Equal(t, actions_model.StatusCancelled, wf2Job2ActionJob.Status) + + // rerun wf2 + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/rerun", user2.Name, repo.Name, wf2Run.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + // (rerun1) cannot fetch wf2-job2 + runner1.fetchNoTask(t) + // (rerun1) fetch and exec wf2-job1 + wf2Job1Rerun1Task := runner2.fetchTask(t) + _, _, wf2Rerun1Run := getTaskAndJobAndRunByTaskID(t, wf2Job1Rerun1Task.Id) + assert.Equal(t, wf2Rerun1Run.ID, wf2Run.ID) + runner2.execTask(t, wf2Job1Rerun1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + outputs: map[string]string{ + "version": "v1.24.0", + }, + }) + // (rerun1) fetch and exec wf2-job2 + wf2Job2Rerun1Task := runner1.fetchTask(t) + runner1.execTask(t, wf2Job2Rerun1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + _, wf2Job2Rerun1Job, _ := getTaskAndJobAndRunByTaskID(t, wf2Job2Rerun1Task.Id) + assert.Equal(t, "job-main-v1.24.0", wf2Job2Rerun1Job.ConcurrencyGroup) + + // rerun wf2-job2 + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/jobs/%d/rerun", user2.Name, repo.Name, wf2Run.Index, 1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + // (rerun2) fetch and exec wf2-job2 + wf2Job2Rerun2Task := runner1.fetchTask(t) + runner1.execTask(t, wf2Job2Rerun2Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + _, wf2Job2Rerun2Job, _ := getTaskAndJobAndRunByTaskID(t, wf2Job2Rerun2Task.Id) + assert.Equal(t, "job-main-v1.24.0", wf2Job2Rerun2Job.ConcurrencyGroup) + }) +} + +func TestMatrixConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + linuxRunner := newMockRunner() + linuxRunner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-linux-runner", []string{"linux-runner"}, false) + windowsRunner := newMockRunner() + windowsRunner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-windows-runner", []string{"windows-runner"}, false) + darwinRunner := newMockRunner() + darwinRunner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-darwin-runner", []string{"darwin-runner"}, false) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +jobs: + wf1-job: + runs-on: ${{ matrix.os }}-runner + strategy: + matrix: + os: [windows, linux] + concurrency: + group: job-os-${{ matrix.os }} + steps: + - run: echo 'wf1' +` + + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +jobs: + wf2-job: + runs-on: ${{ matrix.os }}-runner + strategy: + matrix: + os: [darwin, windows, linux] + concurrency: + group: job-os-${{ matrix.os }} + steps: + - run: echo 'wf2' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + job1WinTask := windowsRunner.fetchTask(t) + job1LinuxTask := linuxRunner.fetchTask(t) + windowsRunner.fetchNoTask(t) + linuxRunner.fetchNoTask(t) + _, job1WinJob, _ := getTaskAndJobAndRunByTaskID(t, job1WinTask.Id) + assert.Equal(t, "wf1-job (windows)", job1WinJob.Name) + assert.Equal(t, "job-os-windows", job1WinJob.ConcurrencyGroup) + _, job1LinuxJob, _ := getTaskAndJobAndRunByTaskID(t, job1LinuxTask.Id) + assert.Equal(t, "wf1-job (linux)", job1LinuxJob.Name) + assert.Equal(t, "job-os-linux", job1LinuxJob.ConcurrencyGroup) + + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + job2DarwinTask := darwinRunner.fetchTask(t) + _, job2DarwinJob, _ := getTaskAndJobAndRunByTaskID(t, job2DarwinTask.Id) + assert.Equal(t, "wf2-job (darwin)", job2DarwinJob.Name) + assert.Equal(t, "job-os-darwin", job2DarwinJob.ConcurrencyGroup) + + windowsRunner.execTask(t, job1WinTask, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + linuxRunner.execTask(t, job1LinuxTask, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + job2WinTask := windowsRunner.fetchTask(t) + job2LinuxTask := linuxRunner.fetchTask(t) + _, job2WinJob, _ := getTaskAndJobAndRunByTaskID(t, job2WinTask.Id) + assert.Equal(t, "wf2-job (windows)", job2WinJob.Name) + assert.Equal(t, "job-os-windows", job2WinJob.ConcurrencyGroup) + _, job2LinuxJob, _ := getTaskAndJobAndRunByTaskID(t, job2LinuxTask.Id) + assert.Equal(t, "wf2-job (linux)", job2LinuxJob.Name) + assert.Equal(t, "job-os-linux", job2LinuxJob.ConcurrencyGroup) + }) +} + +func TestWorkflowDispatchConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/workflow-dispatch-concurrency.yml" + wf1FileContent := `name: workflow-dispatch-concurrency +on: + workflow_dispatch: + inputs: + appVersion: + description: 'APP version' + required: true + default: 'v1.23' + type: choice + options: + - v1.21 + - v1.22 + - v1.23 + cancel: + description: 'Cancel running workflows' + required: false + type: boolean + default: false +concurrency: + group: workflow-dispatch-${{ inputs.appVersion }} + cancel-in-progress: ${{ inputs.cancel }} +jobs: + job: + runs-on: ubuntu-latest + steps: + - run: echo 'workflow dispatch job' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + // run the workflow with appVersion=v1.21 and cancel=false + urlStr := fmt.Sprintf("/%s/%s/actions/run?workflow=%s", user2.Name, repo.Name, "workflow-dispatch-concurrency.yml") + req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.21", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task1 := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, "workflow-dispatch-v1.21", run1.ConcurrencyGroup) + + // run the workflow with appVersion=v1.22 and cancel=false + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task2 := runner.fetchTask(t) + _, _, run2 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run2.ConcurrencyGroup) + + // run the workflow with appVersion=v1.22 and cancel=false again + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + runner.fetchNoTask(t) // cannot fetch task because task2 is not completed + + // run the workflow with appVersion=v1.22 and cancel=true + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + "cancel": "on", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task4 := runner.fetchTask(t) + _, _, run4 := getTaskAndJobAndRunByTaskID(t, task4.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run4.ConcurrencyGroup) + _, _, run2 = getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusCancelled, run2.Status) + }) +} + +func TestWorkflowDispatchRerunAllJobsConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/workflow-dispatch-concurrency.yml" + wf1FileContent := `name: workflow-dispatch-concurrency +on: + workflow_dispatch: + inputs: + appVersion: + description: 'APP version' + required: true + default: 'v1.23' + type: choice + options: + - v1.21 + - v1.22 + - v1.23 + cancel: + description: 'Cancel running workflows' + required: false + type: boolean + default: false +concurrency: + group: workflow-dispatch-${{ inputs.appVersion }} + cancel-in-progress: ${{ inputs.cancel }} +jobs: + job: + runs-on: ubuntu-latest + steps: + - run: echo 'workflow dispatch job' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + // run the workflow with appVersion=v1.21 and cancel=false + urlStr := fmt.Sprintf("/%s/%s/actions/run?workflow=%s", user2.Name, repo.Name, "workflow-dispatch-concurrency.yml") + req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.21", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task1 := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, "workflow-dispatch-v1.21", run1.ConcurrencyGroup) + + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task2 := runner.fetchTask(t) + _, _, run2 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run2.ConcurrencyGroup) + + // run the workflow with appVersion=v1.22 and cancel=false again + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + runner.fetchNoTask(t) // cannot fetch task because task2 is not completed + + // run the workflow with appVersion=v1.22 and cancel=true + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + "cancel": "on", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task4 := runner.fetchTask(t) + _, _, run4 := getTaskAndJobAndRunByTaskID(t, task4.Id) + assert.Equal(t, actions_model.StatusRunning, run4.Status) + assert.Equal(t, "workflow-dispatch-v1.22", run4.ConcurrencyGroup) + _, _, run2 = getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusCancelled, run2.Status) + + runner.execTask(t, task4, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // rerun cancel true scenario + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/rerun", user2.Name, apiRepo.Name, run2.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/rerun", user2.Name, apiRepo.Name, run4.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + task5 := runner.fetchTask(t) + _, _, run4_1 := getTaskAndJobAndRunByTaskID(t, task5.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run4_1.ConcurrencyGroup) + assert.Equal(t, run4.ID, run4_1.ID) + _, _, run2_1 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusCancelled, run2_1.Status) + + runner.execTask(t, task5, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_CANCELLED, + }) + + // rerun cancel false scenario + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/rerun", user2.Name, apiRepo.Name, run2.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + run2_2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run2.ID}) + assert.Equal(t, actions_model.StatusWaiting, run2_2.Status) + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/rerun", user2.Name, apiRepo.Name, run2.Index+1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + task6 := runner.fetchTask(t) + _, _, run3 := getTaskAndJobAndRunByTaskID(t, task6.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run3.ConcurrencyGroup) + + run2_2 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run2_2.ID}) + assert.Equal(t, actions_model.StatusCancelled, run2_2.Status) // cancelled by run3 + }) +} + +func TestWorkflowDispatchRerunSingleJobConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/workflow-dispatch-concurrency.yml" + wf1FileContent := `name: workflow-dispatch-concurrency +on: + workflow_dispatch: + inputs: + appVersion: + description: 'APP version' + required: true + default: 'v1.23' + type: choice + options: + - v1.21 + - v1.22 + - v1.23 + cancel: + description: 'Cancel running workflows' + required: false + type: boolean + default: false +concurrency: + group: workflow-dispatch-${{ inputs.appVersion }} + cancel-in-progress: ${{ inputs.cancel }} +jobs: + job: + runs-on: ubuntu-latest + steps: + - run: echo 'workflow dispatch job' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + // run the workflow with appVersion=v1.21 and cancel=false + urlStr := fmt.Sprintf("/%s/%s/actions/run?workflow=%s", user2.Name, repo.Name, "workflow-dispatch-concurrency.yml") + req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.21", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task1 := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, "workflow-dispatch-v1.21", run1.ConcurrencyGroup) + + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task2 := runner.fetchTask(t) + _, _, run2 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run2.ConcurrencyGroup) + + // run the workflow with appVersion=v1.22 and cancel=false again + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + + runner.fetchNoTask(t) // cannot fetch task because task2 is not completed + + // run the workflow with appVersion=v1.22 and cancel=true + req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + "ref": "refs/heads/main", + "appVersion": "v1.22", + "cancel": "on", + }) + session.MakeRequest(t, req, http.StatusSeeOther) + task4 := runner.fetchTask(t) + _, _, run4 := getTaskAndJobAndRunByTaskID(t, task4.Id) + assert.Equal(t, actions_model.StatusRunning, run4.Status) + assert.Equal(t, "workflow-dispatch-v1.22", run4.ConcurrencyGroup) + _, _, run2 = getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusCancelled, run2.Status) + + runner.execTask(t, task4, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // rerun cancel true scenario + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/jobs/%d/rerun", user2.Name, apiRepo.Name, run2.Index, 1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/jobs/%d/rerun", user2.Name, apiRepo.Name, run4.Index, 1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + task5 := runner.fetchTask(t) + _, _, run4_1 := getTaskAndJobAndRunByTaskID(t, task5.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run4_1.ConcurrencyGroup) + assert.Equal(t, run4.ID, run4_1.ID) + _, _, run2_1 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusCancelled, run2_1.Status) + + runner.execTask(t, task5, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_CANCELLED, + }) + + // rerun cancel false scenario + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/jobs/%d/rerun", user2.Name, apiRepo.Name, run2.Index, 1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + run2_2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run2.ID}) + assert.Equal(t, actions_model.StatusWaiting, run2_2.Status) + + req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/jobs/%d/rerun", user2.Name, apiRepo.Name, run2.Index+1, 1), map[string]string{ + "_csrf": GetUserCSRFToken(t, session), + }) + _ = session.MakeRequest(t, req, http.StatusOK) + + task6 := runner.fetchTask(t) + _, _, run3 := getTaskAndJobAndRunByTaskID(t, task6.Id) + assert.Equal(t, "workflow-dispatch-v1.22", run3.ConcurrencyGroup) + + run2_2 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run2_2.ID}) + assert.Equal(t, actions_model.StatusCancelled, run2_2.Status) // cancelled by run3 + }) +} + +func TestScheduleConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/schedule-concurrency.yml" + wf1FileContent := `name: schedule-concurrency +on: + push: + schedule: + - cron: '@every 1m' +concurrency: + group: schedule-concurrency + cancel-in-progress: ${{ gitea.event_name == 'push' }} +jobs: + job: + runs-on: ubuntu-latest + steps: + - run: echo 'schedule workflow' +` + + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + // fetch the task triggered by push + task1 := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, "schedule-concurrency", run1.ConcurrencyGroup) + assert.True(t, run1.ConcurrencyCancel) + assert.Equal(t, string(webhook_module.HookEventPush), run1.TriggerEvent) + assert.Equal(t, actions_model.StatusRunning, run1.Status) + + // trigger the task by schedule + spec := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: repo.ID}) + spec.Next = timeutil.TimeStampNow() // manually update "Next" + assert.NoError(t, actions_model.UpdateScheduleSpec(t.Context(), spec, "next")) + assert.NoError(t, actions_service.StartScheduleTasks(t.Context())) + runner.fetchNoTask(t) // cannot fetch because task1 is not completed + runner.execTask(t, task1, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + _, _, run1 = getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, actions_model.StatusSuccess, run1.Status) + task2 := runner.fetchTask(t) + _, _, run2 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, "schedule-concurrency", run2.ConcurrencyGroup) + assert.False(t, run2.ConcurrencyCancel) + assert.Equal(t, string(webhook_module.HookEventSchedule), run2.TriggerEvent) + assert.Equal(t, actions_model.StatusRunning, run2.Status) + + // trigger the task by schedule again + spec = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionScheduleSpec{RepoID: repo.ID}) + spec.Next = timeutil.TimeStampNow() // manually update "Next" + assert.NoError(t, actions_model.UpdateScheduleSpec(t.Context(), spec, "next")) + assert.NoError(t, actions_service.StartScheduleTasks(t.Context())) + runner.fetchNoTask(t) // cannot fetch because task2 is not completed + run3 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, Status: actions_model.StatusBlocked}) + assert.Equal(t, "schedule-concurrency", run3.ConcurrencyGroup) + assert.False(t, run3.ConcurrencyCancel) + assert.Equal(t, string(webhook_module.HookEventSchedule), run3.TriggerEvent) + + // trigger the task by push + doAPICreateFile(httpContext, "doc.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + NewBranchName: "main", + Message: "create doc.txt", + Author: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Committer: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("doc")), + })(t) + + task4 := runner.fetchTask(t) + _, _, run4 := getTaskAndJobAndRunByTaskID(t, task4.Id) + assert.Equal(t, "schedule-concurrency", run4.ConcurrencyGroup) + assert.True(t, run4.ConcurrencyCancel) + assert.Equal(t, string(webhook_module.HookEventPush), run4.TriggerEvent) + run3 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run3.ID}) + assert.Equal(t, actions_model.StatusCancelled, run3.Status) + }) +} + +func TestWorkflowAndJobConcurrency(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner1 := newMockRunner() + runner1.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner-1", []string{"runner1"}, false) + runner2 := newMockRunner() + runner2.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner-2", []string{"runner2"}, false) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +concurrency: + group: workflow-group-1 +jobs: + wf1-job1: + runs-on: runner1 + concurrency: + group: job-group-1 + steps: + - run: echo 'wf1-job1' + wf1-job2: + runs-on: runner2 + concurrency: + group: job-group-2 + steps: + - run: echo 'wf1-job2' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +concurrency: + group: workflow-group-1 +jobs: + wf2-job1: + runs-on: runner1 + concurrency: + group: job-group-1 + steps: + - run: echo 'wf2-job1' + wf2-job2: + runs-on: runner2 + concurrency: + group: job-group-2 + steps: + - run: echo 'wf2-job2' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +concurrency: + group: workflow-group-2 +jobs: + wf3-job1: + runs-on: runner1 + concurrency: + group: job-group-1 + steps: + - run: echo 'wf3-job1' +` + + wf4TreePath := ".gitea/workflows/concurrent-workflow-4.yml" + wf4FileContent := `name: concurrent-workflow-4 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-4.yml' +concurrency: + group: workflow-group-2 +jobs: + wf4-job1: + runs-on: runner2 + concurrency: + group: job-group-2 + cancel-in-progress: true + steps: + - run: echo 'wf4-job1' +` + + // push workflow 1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + + // fetch wf1-job1 and wf1-job2 + w1j1Task := runner1.fetchTask(t) + w1j2Task := runner2.fetchTask(t) + _, w1j1Job, w1Run := getTaskAndJobAndRunByTaskID(t, w1j1Task.Id) + assert.Equal(t, "job-group-1", w1j1Job.ConcurrencyGroup) + assert.Equal(t, "workflow-group-1", w1Run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-1.yml", w1Run.WorkflowID) + assert.Equal(t, actions_model.StatusRunning, w1j1Job.Status) + _, w1j2Job, _ := getTaskAndJobAndRunByTaskID(t, w1j2Task.Id) + assert.Equal(t, "job-group-2", w1j2Job.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, w1j2Job.Status) + + // push workflow 2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + // cannot fetch wf2-job1 and wf2-job2 because workflow-2 is blocked by workflow-1's concurrency group "workflow-group-1" + runner1.fetchNoTask(t) + runner2.fetchNoTask(t) + // query wf2-job1 from db and check its status + w2Run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, WorkflowID: "concurrent-workflow-2.yml"}) + w2j1Job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{RunID: w2Run.ID, JobID: "wf2-job1"}) + assert.Equal(t, actions_model.StatusBlocked, w2j1Job.Status) + + // push workflow 3 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + // cannot fetch wf3-job1 because it is blocked by wf1-job1's concurrency group "job-group-1" + runner1.fetchNoTask(t) + // query wf3-job1 from db and check its status + w3Run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, WorkflowID: "concurrent-workflow-3.yml"}) + w3j1Job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{RunID: w3Run.ID, JobID: "wf3-job1"}) + assert.Equal(t, actions_model.StatusBlocked, w3j1Job.Status) + // wf2-job1 is cancelled by wf3-job1 + w2j1Job = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: w2j1Job.ID}) + assert.Equal(t, actions_model.StatusCancelled, w2j1Job.Status) + + // exec wf1-job1 + runner1.execTask(t, w1j1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch wf3-job1 + assert.Equal(t, actions_model.StatusBlocked, w3j1Job.Status) + w3j1Task := runner1.fetchTask(t) + _, w3j1Job, w3Run = getTaskAndJobAndRunByTaskID(t, w3j1Task.Id) + assert.Equal(t, "job-group-1", w3j1Job.ConcurrencyGroup) + assert.Equal(t, "workflow-group-2", w3Run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-3.yml", w3Run.WorkflowID) + + // exec wf1-job2 + runner2.execTask(t, w1j2Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch wf2-job2 + w2j2Task := runner2.fetchTask(t) + _, w2j2Job, w2Run := getTaskAndJobAndRunByTaskID(t, w2j2Task.Id) + assert.Equal(t, "job-group-2", w2j2Job.ConcurrencyGroup) + assert.Equal(t, "workflow-group-1", w2Run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-2.yml", w2Run.WorkflowID) + assert.Equal(t, actions_model.StatusRunning, w2j2Job.Status) + + // push workflow-4 + opts4 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf4TreePath, wf4FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf4TreePath, opts4) + // cannot fetch wf4-job1 because it is blocked by workflow-3's concurrency group "workflow-group-2" + runner2.fetchNoTask(t) + + // exec wf3-job1 + runner1.execTask(t, w3j1Task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch wf4-job1 + w4j1Task := runner2.fetchTask(t) + // all tasks have been fetched + runner1.fetchNoTask(t) + runner2.fetchNoTask(t) + + _, w2j2Job, w2Run = getTaskAndJobAndRunByTaskID(t, w2j2Task.Id) + // wf2-job2 is cancelled because wf4-job1's cancel-in-progress is true + assert.Equal(t, actions_model.StatusCancelled, w2j2Job.Status) + assert.Equal(t, actions_model.StatusCancelled, w2Run.Status) + _, w4j1Job, w4Run := getTaskAndJobAndRunByTaskID(t, w4j1Task.Id) + assert.Equal(t, "job-group-2", w4j1Job.ConcurrencyGroup) + assert.Equal(t, "workflow-group-2", w4Run.ConcurrencyGroup) + assert.Equal(t, "concurrent-workflow-4.yml", w4Run.WorkflowID) + }) +} + +func TestCancelConcurrentRun(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + user2Session := loginUser(t, user2.Name) + user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, user2Token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + user2APICtx := NewAPITestContext(t, repo.OwnerName, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(user2APICtx)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, repo.OwnerName, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + // init the workflow + wfTreePath := ".gitea/workflows/run.yml" + wfFileContent := `name: Cancel Run +on: push +concurrency: + group: cancel-run-group + cancel-in-progress: false +jobs: + wf1-job: + runs-on: ubuntu-latest + steps: + - run: echo 'test' +` + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wfTreePath, wfFileContent) + createWorkflowFile(t, user2Token, repo.OwnerName, repo.Name, wfTreePath, opts1) + + // fetch and check the first task + task1 := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, task1.Id) + assert.Equal(t, "cancel-run-group", run1.ConcurrencyGroup) + assert.False(t, run1.ConcurrencyCancel) + assert.Equal(t, actions_model.StatusRunning, run1.Status) + + // push another file to trigger the workflow again + doAPICreateFile(user2APICtx, "file1.txt", &api.CreateFileOptions{ + FileOptions: api.FileOptions{ + Message: "create file1.txt", + Author: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Committer: api.Identity{ + Name: user2.Name, + Email: user2.Email, + }, + Dates: api.CommitDateOptions{ + Author: time.Now(), + Committer: time.Now(), + }, + }, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("file1")), + })(t) + + // cannot fetch the second task because the first task is not completed + runner.fetchNoTask(t) + + // cancel the first run + req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/actions/runs/%d/cancel", user2.Name, repo.Name, run1.Index), map[string]string{ + "_csrf": GetUserCSRFToken(t, user2Session), + }) + user2Session.MakeRequest(t, req, http.StatusOK) + + // the first run has been cancelled + run1 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run1.ID}) + assert.Equal(t, actions_model.StatusCancelled, run1.Status) + + // fetch and check the second task + task2 := runner.fetchTask(t) + _, _, run2 := getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, "cancel-run-group", run2.ConcurrencyGroup) + assert.False(t, run2.ConcurrencyCancel) + assert.Equal(t, actions_model.StatusRunning, run2.Status) + }) +} + +func TestAbandonConcurrentRun(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + user2Session := loginUser(t, user2.Name) + user2Token := getTokenForLoggedInUser(t, user2Session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, user2Token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + user2APICtx := NewAPITestContext(t, repo.OwnerName, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(user2APICtx)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, repo.OwnerName, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/workflow-1.yml" + wf1FileContent := `name: Workflow-1 +on: + push: + paths: + - '.gitea/workflows/workflow-1.yml' +concurrency: + group: test-group +jobs: + wf1-job1: + runs-on: ubuntu-latest + steps: + - run: echo 'wf1-job1' + wf1-job2: + runs-on: customized-runner + steps: + - run: echo 'wf1-job1' +` + + wf2TreePath := ".gitea/workflows/workflow-2.yml" + wf2FileContent := `name: Workflow-2 +on: + push: + paths: + - '.gitea/workflows/workflow-2.yml' +concurrency: + group: test-group +jobs: + wf2-job1: + runs-on: ubuntu-latest + steps: + - run: echo 'wf2-job1' +` + // push workflow1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf1TreePath, wf1FileContent) + createWorkflowFile(t, user2Token, repo.OwnerName, repo.Name, wf1TreePath, opts1) + + // fetch wf1-job1 + w1j1Task := runner.fetchTask(t) + _, _, run1 := getTaskAndJobAndRunByTaskID(t, w1j1Task.Id) + assert.Equal(t, "test-group", run1.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, run1.Status) + // query wf1-job2 from db and check its status + w1j2Job := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{RunID: run1.ID, JobID: "wf1-job2"}) + // wf1-job2 is waiting but no runner will run it + assert.Equal(t, actions_model.StatusWaiting, w1j2Job.Status) + + time.Sleep(time.Second) + now := time.Now() + time.Sleep(time.Second) + + // push workflow2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create %s"+wf2TreePath, wf2FileContent) + createWorkflowFile(t, user2Token, repo.OwnerName, repo.Name, wf2TreePath, opts2) + + // query run2 from db and check its status + run2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, WorkflowID: "workflow-2.yml"}) + // run2 is blocked because it is blocked by workflow1's concurrency group "test-group" + assert.Equal(t, actions_model.StatusBlocked, run2.Status) + + // mock time + fakeNow := now.Add(setting.Actions.AbandonedJobTimeout) + timeutil.MockSet(fakeNow) + defer timeutil.MockUnset() + + // call CancelAbandonedJobs manually + assert.NoError(t, actions_service.CancelAbandonedJobs(t.Context())) + + // check the status of wf1-job2 + w1j2Job = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunJob{ID: w1j2Job.ID}) + assert.Equal(t, actions_model.StatusCancelled, w1j2Job.Status) + // check the status of run1 + run1 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run1.ID}) + assert.Equal(t, actions_model.StatusCancelled, run1.Status) + + // fetch wf2-job1 and check + w2j1Task := runner.fetchTask(t) + _, w2j1Job, run2 := getTaskAndJobAndRunByTaskID(t, w2j1Task.Id) + assert.Equal(t, "test-group", run2.ConcurrencyGroup) + assert.Equal(t, "wf2-job1", w2j1Job.JobID) + assert.Equal(t, actions_model.StatusRunning, run2.Status) + assert.Equal(t, actions_model.StatusRunning, w2j1Job.Status) + }) +} + +func TestRunAndJobWithSameConcurrencyGroup(t *testing.T) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + session := loginUser(t, user2.Name) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) + + apiRepo := createActionsTestRepo(t, token, "actions-concurrency", false) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: apiRepo.ID}) + httpContext := NewAPITestContext(t, user2.Name, repo.Name, auth_model.AccessTokenScopeWriteRepository) + defer doAPIDeleteRepository(httpContext)(t) + + runner := newMockRunner() + runner.registerAsRepoRunner(t, user2.Name, repo.Name, "mock-runner", []string{"ubuntu-latest"}, false) + + wf1TreePath := ".gitea/workflows/concurrent-workflow-1.yml" + wf1FileContent := `name: concurrent-workflow-1 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-1.yml' +jobs: + wf1-job: + runs-on: ubuntu-latest + concurrency: + group: test-group + steps: + - run: echo 'wf1-job' +` + wf2TreePath := ".gitea/workflows/concurrent-workflow-2.yml" + wf2FileContent := `name: concurrent-workflow-2 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-2.yml' +concurrency: + group: test-group +jobs: + wf2-job: + runs-on: ubuntu-latest + steps: + - run: echo 'wf2-job' +` + wf3TreePath := ".gitea/workflows/concurrent-workflow-3.yml" + wf3FileContent := `name: concurrent-workflow-3 +on: + push: + paths: + - '.gitea/workflows/concurrent-workflow-3.yml' +jobs: + wf3-job: + runs-on: ubuntu-latest + concurrency: + group: test-group + cancel-in-progress: true + steps: + - run: echo 'wf3-job' +` + // push workflow1 + opts1 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf1TreePath, wf1FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf1TreePath, opts1) + // fetch run1 + task := runner.fetchTask(t) + _, job1, run1 := getTaskAndJobAndRunByTaskID(t, task.Id) + assert.Equal(t, "test-group", job1.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, run1.Status) + + // push workflow2 + opts2 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf2TreePath, wf2FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf2TreePath, opts2) + // cannot fetch run2 because run1 is still running + runner.fetchNoTask(t) + run2 := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: repo.ID, WorkflowID: "concurrent-workflow-2.yml"}) + assert.Equal(t, "test-group", run2.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusBlocked, run2.Status) + + // exec run1 + runner.execTask(t, task, &mockTaskOutcome{ + result: runnerv1.Result_RESULT_SUCCESS, + }) + + // fetch run2 + task2 := runner.fetchTask(t) + _, _, run2 = getTaskAndJobAndRunByTaskID(t, task2.Id) + assert.Equal(t, actions_model.StatusRunning, run2.Status) + + // push workflow3 + opts3 := getWorkflowCreateFileOptions(user2, repo.DefaultBranch, "create "+wf3TreePath, wf3FileContent) + createWorkflowFile(t, token, user2.Name, repo.Name, wf3TreePath, opts3) + // fetch run3 + task3 := runner.fetchTask(t) + _, job3, run3 := getTaskAndJobAndRunByTaskID(t, task3.Id) + assert.Equal(t, "test-group", job3.ConcurrencyGroup) + assert.Equal(t, actions_model.StatusRunning, run3.Status) + + // run2 should be cancelled by run3 + run2 = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run2.ID}) + assert.Equal(t, actions_model.StatusCancelled, run2.Status) + }) +} From b029ad431ba5a9c2ef4923a7fa7f804a06995eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=B2=81=E6=B1=80?= <131967983+lutinglt@users.noreply.github.com> Date: Sun, 12 Oct 2025 02:38:42 +0800 Subject: [PATCH 24/74] Fix code tag style problem and LFS view bug (#35628) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #35567 --------- Signed-off-by: 鲁汀 <131967983+lutinglt@users.noreply.github.com> Co-authored-by: wxiaoguang --- routers/web/repo/setting/lfs.go | 3 +-- templates/admin/config.tmpl | 10 +++++----- templates/admin/stacktrace-row.tmpl | 4 ++-- templates/base/alert_details.tmpl | 2 +- templates/projects/view.tmpl | 4 +++- templates/repo/settings/lfs_file.tmpl | 2 +- templates/repo/settings/webhook/history.tmpl | 4 ++-- templates/user/settings/keys_gpg.tmpl | 8 ++++---- templates/user/settings/keys_ssh.tmpl | 9 ++++----- web_src/css/base.css | 6 ++++-- web_src/css/form.css | 6 ++++++ 11 files changed, 33 insertions(+), 25 deletions(-) diff --git a/routers/web/repo/setting/lfs.go b/routers/web/repo/setting/lfs.go index af6708e841..a558231df1 100644 --- a/routers/web/repo/setting/lfs.go +++ b/routers/web/repo/setting/lfs.go @@ -270,8 +270,7 @@ func LFSFileGet(ctx *context.Context) { // FIXME: there is no IsPlainText set, but template uses it ctx.Data["IsTextFile"] = st.IsText() ctx.Data["FileSize"] = meta.Size - // FIXME: the last field is the URL-base64-encoded filename, it should not be "direct" - ctx.Data["RawFileLink"] = fmt.Sprintf("%s%s/%s.git/info/lfs/objects/%s/%s", setting.AppURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid), "direct") + ctx.Data["RawFileLink"] = fmt.Sprintf("%s/%s/%s.git/info/lfs/objects/%s", setting.AppSubURL, url.PathEscape(ctx.Repo.Repository.OwnerName), url.PathEscape(ctx.Repo.Repository.Name), url.PathEscape(meta.Oid)) switch { case st.IsRepresentableAsText(): if meta.Size >= setting.UI.MaxDisplayFileSize { diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 806347c720..080b2cd3d6 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -252,9 +252,9 @@ {{end}} {{if .CacheConn}}
{{ctx.Locale.Tr "admin.config.cache_conn"}}
-
{{.CacheConn}}
+
{{.CacheConn}}
{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}
-
{{.CacheItemTTL}}
+
{{.CacheItemTTL}}
{{end}}
{{ctx.Locale.Tr "admin.config.cache_test"}}
@@ -275,7 +275,7 @@
{{ctx.Locale.Tr "admin.config.session_provider"}}
{{.SessionConfig.Provider}}
{{ctx.Locale.Tr "admin.config.provider_config"}}
-
{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}
+
{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}
{{ctx.Locale.Tr "admin.config.cookie_name"}}
{{.SessionConfig.CookieName}}
{{ctx.Locale.Tr "admin.config.gc_interval_time"}}
@@ -301,7 +301,7 @@
{{ctx.Locale.Tr "admin.config.git_max_diff_files"}}
{{.Git.MaxGitDiffFiles}}
{{ctx.Locale.Tr "admin.config.git_gc_args"}}
-
{{.Git.GCArgs}}
+
{{.Git.GCArgs}}
@@ -330,7 +330,7 @@ {{if .Loggers.access.IsEnabled}}
{{ctx.Locale.Tr "admin.config.access_log_template"}}
-
{{$.AccessLogTemplate}}
+
{{$.AccessLogTemplate}}
{{end}} {{range $loggerName, $loggerDetail := .Loggers}} diff --git a/templates/admin/stacktrace-row.tmpl b/templates/admin/stacktrace-row.tmpl index db7ed81c79..356c517935 100644 --- a/templates/admin/stacktrace-row.tmpl +++ b/templates/admin/stacktrace-row.tmpl @@ -46,8 +46,8 @@
{{svg "octicon-dot-fill" 16}}
-
{{.Function}}
-
{{.File}}:{{.Line}}
+
{{.Function}}
+
{{.File}}:{{.Line}}
{{end}} diff --git a/templates/base/alert_details.tmpl b/templates/base/alert_details.tmpl index 6d4c1fb2db..6380a72498 100644 --- a/templates/base/alert_details.tmpl +++ b/templates/base/alert_details.tmpl @@ -2,7 +2,7 @@ {{if .Details}}
{{.Summary}} - {{.Details | SanitizeHTML}} + {{.Details | SanitizeHTML}}
{{else}}
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 692808a32d..21bc287643 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -65,7 +65,9 @@
- {{$.Project.RenderedContent}} +
+ {{$.Project.RenderedContent}} +
diff --git a/templates/repo/settings/lfs_file.tmpl b/templates/repo/settings/lfs_file.tmpl index cd1b168401..e9f4afda26 100644 --- a/templates/repo/settings/lfs_file.tmpl +++ b/templates/repo/settings/lfs_file.tmpl @@ -39,7 +39,7 @@ {{.LineNums}} -
    {{.FileContent}}
+
{{.FileContent}}
diff --git a/templates/repo/settings/webhook/history.tmpl b/templates/repo/settings/webhook/history.tmpl index 953ba69670..d27c1fb8b1 100644 --- a/templates/repo/settings/webhook/history.tmpl +++ b/templates/repo/settings/webhook/history.tmpl @@ -68,7 +68,7 @@ {{range $key, $val := .RequestInfo.Headers}}{{$key}}: {{$val}} {{end}}
{{ctx.Locale.Tr "repo.settings.webhook.payload"}}
-
{{or .RequestInfo.Body .PayloadContent}}
+
{{or .RequestInfo.Body .PayloadContent}}
{{else}} - {{end}} @@ -79,7 +79,7 @@
{{range $key, $val := .ResponseInfo.Headers}}{{$key}}: {{$val}}
 {{end}}
{{ctx.Locale.Tr "repo.settings.webhook.body"}}
-
{{.ResponseInfo.Body}}
+
{{.ResponseInfo.Body}}
{{else}} - {{end}} diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl index e44a838b25..bb45ea58c5 100644 --- a/templates/user/settings/keys_gpg.tmpl +++ b/templates/user/settings/keys_gpg.tmpl @@ -21,8 +21,8 @@
-

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

-

{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}

+ {{ctx.Locale.Tr "settings.gpg_token_help"}} +
{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` .TokenToSign .PaddedKeyID}}
@@ -89,8 +89,8 @@
-

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

-

{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}

+ {{ctx.Locale.Tr "settings.gpg_token_help"}} +
{{printf `echo "%s" | gpg -a --default-key %s --detach-sig` $.TokenToSign .PaddedKeyID}}

diff --git a/templates/user/settings/keys_ssh.tmpl b/templates/user/settings/keys_ssh.tmpl index 9d62d4ab08..02bcc937ff 100644 --- a/templates/user/settings/keys_ssh.tmpl +++ b/templates/user/settings/keys_ssh.tmpl @@ -77,16 +77,15 @@
-

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

-

echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey

+ {{ctx.Locale.Tr "settings.ssh_token_help"}} +
echo -n '{{$.TokenToSign}}' | ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey
Windows PowerShell -

cmd /c "<NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"

+
cmd /c "<NUL set /p=`"{{$.TokenToSign}}`"| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey"
-
Windows CMD -

set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey

+
set /p={{$.TokenToSign}}| ssh-keygen -Y sign -n gitea -f /path_to_PrivateKey_or_RelatedPublicKey

diff --git a/web_src/css/base.css b/web_src/css/base.css index 9cef92019d..8b77e55fa3 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -101,11 +101,13 @@ samp, font-size: 0.95em; /* compensate for monospace fonts being usually slightly larger */ } -code { +/* there are many blocks in non-markup(.markup code) / non-code-diff(code.code-inner) containers (for example: translation strings, etc), +so we need to make have default global styles, ".markup code" has its own styles and doesn't conflict, but `.code-inner` is special. +TODO: in the future, we should use `div` instead of `code` for `.code-inner` because it is a container for highlighted code line */ +code:not(.code-inner) { padding: 1px 4px; border-radius: var(--border-radius); background-color: var(--color-label-bg); - color: var(--color-label-text); } b, diff --git a/web_src/css/form.css b/web_src/css/form.css index 757edf7297..197c0f5af2 100644 --- a/web_src/css/form.css +++ b/web_src/css/form.css @@ -228,6 +228,12 @@ textarea:focus, color: var(--color-text-light-1); } +.form .help pre.command-block { + white-space: pre-wrap; + overflow-wrap: anywhere; + margin: 0.25em 0 0.25em 1em; +} + .m-captcha-style { width: 100%; height: 5em; From 25c4eb16593a839ea1a4313885cf36ebfe9da928 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Sat, 11 Oct 2025 21:58:36 +0200 Subject: [PATCH 25/74] Refactor ActionRunJob parsing into a reusable function (#35623) Use a helper method around the jobparser for parsing a single job structure from an ActionRunJob --------- Co-authored-by: wxiaoguang --- models/actions/run_job.go | 19 +++++++++++++++++++ models/actions/task.go | 8 ++------ services/actions/concurrency.go | 12 +++--------- services/actions/job_emitter.go | 7 +++---- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/models/actions/run_job.go b/models/actions/run_job.go index 9c7c3658d7..f72a7040e3 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "github.com/nektos/act/pkg/jobparser" "xorm.io/builder" ) @@ -99,6 +100,24 @@ func (job *ActionRunJob) LoadAttributes(ctx context.Context) error { return job.Run.LoadAttributes(ctx) } +// ParseJob parses the job structure from the ActionRunJob.WorkflowPayload +func (job *ActionRunJob) ParseJob() (*jobparser.Job, error) { + // job.WorkflowPayload is a SingleWorkflow created from an ActionRun's workflow, which exactly contains this job's YAML definition. + // Ideally it shouldn't be called "Workflow", it is just a job with global workflow fields + trigger + parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload) + if err != nil { + return nil, fmt.Errorf("job %d single workflow: unable to parse: %w", job.ID, err) + } else if len(parsedWorkflows) != 1 { + return nil, fmt.Errorf("job %d single workflow: not single workflow", job.ID) + } + _, workflowJob := parsedWorkflows[0].Job() + if workflowJob == nil { + // it shouldn't happen, and since the callers don't check nil, so return an error instead of nil + return nil, util.ErrorWrap(util.ErrNotExist, "job %d single workflow: payload doesn't contain a job", job.ID) + } + return workflowJob, nil +} + func GetRunJobByID(ctx context.Context, id int64) (*ActionRunJob, error) { var job ActionRunJob has, err := db.GetEngine(ctx).Where("id=?", id).Get(&job) diff --git a/models/actions/task.go b/models/actions/task.go index c1306a8418..7417af8b45 100644 --- a/models/actions/task.go +++ b/models/actions/task.go @@ -21,7 +21,6 @@ import ( runnerv1 "code.gitea.io/actions-proto-go/runner/v1" lru "github.com/hashicorp/golang-lru/v2" - "github.com/nektos/act/pkg/jobparser" "google.golang.org/protobuf/types/known/timestamppb" "xorm.io/builder" ) @@ -278,13 +277,10 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask return nil, false, err } - parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload) + workflowJob, err := job.ParseJob() if err != nil { - return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err) - } else if len(parsedWorkflows) != 1 { - return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID) + return nil, false, fmt.Errorf("load job %d: %w", job.ID, err) } - _, workflowJob := parsedWorkflows[0].Job() if _, err := e.Insert(task); err != nil { return nil, false, err diff --git a/services/actions/concurrency.go b/services/actions/concurrency.go index 2910e47739..0908302709 100644 --- a/services/actions/concurrency.go +++ b/services/actions/concurrency.go @@ -5,7 +5,6 @@ package actions import ( "context" - "errors" "fmt" actions_model "code.gitea.io/gitea/models/actions" @@ -91,17 +90,12 @@ func EvaluateJobConcurrencyFillModel(ctx context.Context, run *actions_model.Act return fmt.Errorf("get inputs: %w", err) } - // singleWorkflows is created from an ActionJob, which always contains exactly a single job's YAML definition. - // Ideally it shouldn't be called "Workflow", it is just a job with global workflow fields + trigger - singleWorkflows, err := jobparser.Parse(actionRunJob.WorkflowPayload) + workflowJob, err := actionRunJob.ParseJob() if err != nil { - return fmt.Errorf("parse single workflow: %w", err) - } else if len(singleWorkflows) != 1 { - return errors.New("not single workflow") + return fmt.Errorf("load job %d: %w", actionRunJob.ID, err) } - _, singleWorkflowJob := singleWorkflows[0].Job() - actionRunJob.ConcurrencyGroup, actionRunJob.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(&rawConcurrency, actionRunJob.JobID, singleWorkflowJob, actionsJobCtx, jobResults, vars, inputs) + actionRunJob.ConcurrencyGroup, actionRunJob.ConcurrencyCancel, err = jobparser.EvaluateConcurrency(&rawConcurrency, actionRunJob.JobID, workflowJob, actionsJobCtx, jobResults, vars, inputs) if err != nil { return fmt.Errorf("evaluate concurrency: %w", err) } diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index c6578eae65..762d28e9cc 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -18,7 +18,6 @@ import ( "code.gitea.io/gitea/modules/util" notify_service "code.gitea.io/gitea/services/notify" - "github.com/nektos/act/pkg/jobparser" "xorm.io/builder" ) @@ -305,9 +304,9 @@ func (r *jobStatusResolver) resolveCheckNeeds(id int64) (allDone, allSucceed boo } func (r *jobStatusResolver) resolveJobHasIfCondition(actionRunJob *actions_model.ActionRunJob) (hasIf bool) { - if wfJobs, _ := jobparser.Parse(actionRunJob.WorkflowPayload); len(wfJobs) == 1 { - _, wfJob := wfJobs[0].Job() - hasIf = len(wfJob.If.Value) > 0 + // FIXME evaluate this on the server side + if job, err := actionRunJob.ParseJob(); err == nil { + return len(job.If.Value) > 0 } return hasIf } From 24a595c3fc7ea0f6f02ab185b2728151f9ee9e1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Oct 2025 01:52:03 +0000 Subject: [PATCH 26/74] Bump happy-dom from 19.0.2 to 20.0.0 (#35625) --- package.json | 2 +- pnpm-lock.yaml | 81 +++++++++++++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index e8e6f63eeb..68ea60ffed 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "eslint-plugin-vue-scoped-css": "2.12.0", "eslint-plugin-wc": "3.0.2", "globals": "16.4.0", - "happy-dom": "19.0.2", + "happy-dom": "20.0.0", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.27.0", "nolyfill": "1.0.44", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 376d70c506..e749a71c7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -245,10 +245,10 @@ importers: version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) '@vitejs/plugin-vue': specifier: 6.0.1 - version: 6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) + version: 6.0.1(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) '@vitest/eslint-plugin': specifier: 1.3.13 - version: 1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + version: 1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) eslint: specifier: 9.36.0 version: 9.36.0(jiti@2.6.1) @@ -292,8 +292,8 @@ importers: specifier: 16.4.0 version: 16.4.0 happy-dom: - specifier: 19.0.2 - version: 19.0.2 + specifier: 20.0.0 + version: 20.0.0 markdownlint-cli: specifier: 0.45.0 version: 0.45.0 @@ -338,7 +338,7 @@ importers: version: 1.4.6 vitest: specifier: 3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue-tsc: specifier: 3.1.0 version: 3.1.0(typescript@5.9.3) @@ -1188,11 +1188,11 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@20.19.19': - resolution: {integrity: sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==} + '@types/node@20.19.20': + resolution: {integrity: sha512-2Q7WS25j4pS1cS8yw3d6buNCVJukOTeQ39bAnwR6sOJbaxvyCGebzTMypDFN82CxBLnl+lSWVdCCWbRY6y9yZQ==} - '@types/node@24.6.2': - resolution: {integrity: sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==} + '@types/node@24.7.1': + resolution: {integrity: sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==} '@types/pdfobject@2.2.5': resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==} @@ -2714,8 +2714,8 @@ packages: resolution: {integrity: sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==} engines: {node: '>=0.8.0'} - happy-dom@19.0.2: - resolution: {integrity: sha512-831CLbgDyjRbd2lApHZFsBDe56onuFcjsCBPodzWpzedTpeDr8CGZjs7iEIdNW1DVwSFRecfwzLpVyGBPamwGA==} + happy-dom@20.0.0: + resolution: {integrity: sha512-GkWnwIFxVGCf2raNrxImLo397RdGhLapj5cT3R2PT7FwL62Ze1DROhzmYW7+J3p9105DYMVenEejEbnq5wA37w==} engines: {node: '>=20.0.0'} has-flag@4.0.0: @@ -3745,6 +3745,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} @@ -4122,8 +4127,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.13.0: - resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==} + undici-types@7.14.0: + resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} @@ -5169,13 +5174,13 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@20.19.19': + '@types/node@20.19.20': dependencies: undici-types: 6.21.0 - '@types/node@24.6.2': + '@types/node@24.7.1': dependencies: - undici-types: 7.13.0 + undici-types: 7.14.0 '@types/pdfobject@2.2.5': {} @@ -5356,20 +5361,20 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.29 - vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue: 3.5.22(typescript@5.9.3) - '@vitest/eslint-plugin@1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@typescript-eslint/scope-manager': 8.45.0 '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) eslint: 9.36.0(jiti@2.6.1) optionalDependencies: typescript: 5.9.3 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -5381,13 +5386,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -6832,9 +6837,9 @@ snapshots: hammerjs@2.0.8: {} - happy-dom@19.0.2: + happy-dom@20.0.0: dependencies: - '@types/node': 20.19.19 + '@types/node': 20.19.20 '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 @@ -6986,7 +6991,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.6.2 + '@types/node': 24.7.1 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -7892,6 +7897,8 @@ snapshots: semver@7.7.2: {} + semver@7.7.3: {} + serialize-javascript@6.0.2: dependencies: randombytes: 2.1.0 @@ -8308,7 +8315,7 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.13.0: {} + undici-types@7.14.0: {} unrs-resolver@1.11.1: dependencies: @@ -8352,13 +8359,13 @@ snapshots: vanilla-colorful@0.7.2: {} - vite-node@3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -8375,7 +8382,7 @@ snapshots: vite-string-plugin@1.4.6: {} - vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -8384,18 +8391,18 @@ snapshots: rollup: 4.52.3 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.6.2 + '@types/node': 24.7.1 fsevents: 2.3.3 jiti: 2.6.1 stylus: 0.57.0 terser: 5.44.0 yaml: 2.8.1 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.6.2)(happy-dom@19.0.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -8413,13 +8420,13 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.6.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.6.2 - happy-dom: 19.0.2 + '@types/node': 24.7.1 + happy-dom: 20.0.0 transitivePeerDependencies: - jiti - less @@ -8472,7 +8479,7 @@ snapshots: eslint-visitor-keys: 4.2.1 espree: 10.4.0 esquery: 1.6.0 - semver: 7.7.2 + semver: 7.7.3 transitivePeerDependencies: - supports-color From 662a44d9246b0bef7914bd540e1ae68522f971a7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 11 Oct 2025 19:24:00 -0700 Subject: [PATCH 27/74] Fix merge panic (#35606) To prevent potential bugs, the logic in #35543 makes `gitcmd.Command` panic when attempting to override stdout or stderr. Instead of using `PrepareCmd`, this PR now uses the WithXXX methods directly to avoid the panic. Fix #35603 --- services/pull/merge_prepare.go | 9 ++- services/pull/temp_repo.go | 3 + tests/integration/pull_merge_test.go | 100 +++++++++++++++++++++--- tests/integration/pull_review_test.go | 5 +- tests/integration/repo_activity_test.go | 5 +- tests/integration/repo_branch_test.go | 10 ++- 6 files changed, 114 insertions(+), 18 deletions(-) diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 7dedf0d2a0..07935ac16d 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -32,6 +32,9 @@ type mergeContext struct { env []string } +// PrepareGitCmd prepares a git command with the correct directory, environment, and output buffers +// This function can only be called with gitcmd.Run() +// Do NOT use it with gitcmd.RunStd*() functions, otherwise it will panic func (ctx *mergeContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command { ctx.outbuf.Reset() ctx.errbuf.Reset() @@ -73,7 +76,11 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque } if expectedHeadCommitID != "" { - trackingCommitID, _, err := mergeCtx.PrepareGitCmd(gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix + trackingBranch)).RunStdString(ctx) + trackingCommitID, _, err := gitcmd.NewCommand("show-ref", "--hash"). + AddDynamicArguments(git.BranchPrefix + trackingBranch). + WithEnv(mergeCtx.env). + WithDir(mergeCtx.tmpBasePath). + RunStdString(ctx) if err != nil { defer cancel() log.Error("failed to get sha of head branch in %-v: show-ref[%s] --hash refs/heads/tracking: %v", mergeCtx.pr, mergeCtx.tmpBasePath, err) diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 597a4aa48c..4f7a504b11 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -37,6 +37,9 @@ type prTmpRepoContext struct { errbuf *strings.Builder // any use should be preceded by a Reset and preferably after use } +// PrepareGitCmd prepares a git command with the correct directory, environment, and output buffers +// This function can only be called with gitcmd.Run() +// Do NOT use it with gitcmd.RunStd*() functions, otherwise it will panic func (ctx *prTmpRepoContext) PrepareGitCmd(cmd *gitcmd.Command) *gitcmd.Command { ctx.outbuf.Reset() ctx.errbuf.Reset() diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 7670aebab5..3345216838 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -43,7 +43,13 @@ import ( "github.com/stretchr/testify/assert" ) -func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum string, mergeStyle repo_model.MergeStyle, deleteBranch bool) *httptest.ResponseRecorder { +type MergeOptions struct { + Style repo_model.MergeStyle + HeadCommitID string + DeleteBranch bool +} + +func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum string, mergeOptions MergeOptions) *httptest.ResponseRecorder { req := NewRequest(t, "GET", path.Join(user, repo, "pulls", pullnum)) resp := session.MakeRequest(t, req, http.StatusOK) @@ -51,11 +57,12 @@ func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum strin link := path.Join(user, repo, "pulls", pullnum, "merge") options := map[string]string{ - "_csrf": htmlDoc.GetCSRF(), - "do": string(mergeStyle), + "_csrf": htmlDoc.GetCSRF(), + "do": string(mergeOptions.Style), + "head_commit_id": mergeOptions.HeadCommitID, } - if deleteBranch { + if mergeOptions.DeleteBranch { options["delete_branch_after_merge"] = "on" } @@ -69,6 +76,14 @@ func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum strin assert.Equal(t, fmt.Sprintf("/%s/%s/pulls/%s", user, repo, pullnum), respJSON.Redirect) + pullnumInt, err := strconv.ParseInt(pullnum, 10, 64) + assert.NoError(t, err) + repository, err := repo_model.GetRepositoryByOwnerAndName(t.Context(), user, repo) + assert.NoError(t, err) + pull, err := issues_model.GetPullRequestByIndex(t.Context(), repository.ID, pullnumInt) + assert.NoError(t, err) + assert.True(t, pull.HasMerged) + return resp } @@ -102,7 +117,10 @@ func TestPullMerge(t *testing.T) { elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: false, + }) hookTasks, err = webhook.HookTasks(t.Context(), 1, 1) assert.NoError(t, err) @@ -124,7 +142,10 @@ func TestPullRebase(t *testing.T) { elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebase, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleRebase, + DeleteBranch: false, + }) hookTasks, err = webhook.HookTasks(t.Context(), 1, 1) assert.NoError(t, err) @@ -146,7 +167,10 @@ func TestPullRebaseMerge(t *testing.T) { elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebaseMerge, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleRebaseMerge, + DeleteBranch: false, + }) hookTasks, err = webhook.HookTasks(t.Context(), 1, 1) assert.NoError(t, err) @@ -169,7 +193,42 @@ func TestPullSquash(t *testing.T) { elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleSquash, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleSquash, + DeleteBranch: false, + }) + + hookTasks, err = webhook.HookTasks(t.Context(), 1, 1) + assert.NoError(t, err) + assert.Len(t, hookTasks, hookTasksLenBefore+1) + }) +} + +func TestPullSquashWithHeadCommitID(t *testing.T) { + onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + hookTasks, err := webhook.HookTasks(t.Context(), 1, 1) // Retrieve previous hook number + assert.NoError(t, err) + hookTasksLenBefore := len(hookTasks) + + session := loginUser(t, "user1") + testRepoFork(t, session, "user2", "repo1", "user1", "repo1", "") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited!)\n") + + resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title") + + repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: "repo1"}) + headBranch, err := git_model.GetBranch(t.Context(), repo1.ID, "master") + assert.NoError(t, err) + assert.NotNil(t, headBranch) + + elem := strings.Split(test.RedirectURL(resp), "/") + assert.Equal(t, "pulls", elem[3]) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleSquash, + DeleteBranch: false, + HeadCommitID: headBranch.CommitID, + }) hookTasks, err = webhook.HookTasks(t.Context(), 1, 1) assert.NoError(t, err) @@ -187,7 +246,10 @@ func TestPullCleanUpAfterMerge(t *testing.T) { elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: false, + }) // Check PR branch deletion resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4]) @@ -556,7 +618,10 @@ func TestPullRetargetChildOnBranchDelete(t *testing.T) { elemChildPR := strings.Split(test.RedirectURL(respChildPR), "/") assert.Equal(t, "pulls", elemChildPR[3]) - testPullMerge(t, session, elemBasePR[1], elemBasePR[2], elemBasePR[4], repo_model.MergeStyleMerge, true) + testPullMerge(t, session, elemBasePR[1], elemBasePR[2], elemBasePR[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: true, + }) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "repo1"}) branchBasePR := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "base-pr"}) @@ -592,7 +657,10 @@ func TestPullDontRetargetChildOnWrongRepo(t *testing.T) { defer test.MockVariableValue(&setting.Repository.PullRequest.RetargetChildrenOnMerge, false)() - testPullMerge(t, session, elemBasePR[1], elemBasePR[2], elemBasePR[4], repo_model.MergeStyleMerge, true) + testPullMerge(t, session, elemBasePR[1], elemBasePR[2], elemBasePR[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: true, + }) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user1", Name: "repo1"}) branchBasePR := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "base-pr"}) @@ -624,7 +692,10 @@ func TestPullRequestMergedWithNoPermissionDeleteBranch(t *testing.T) { // user2 has no permission to delete branch of repo user1/repo1 session2 := loginUser(t, "user2") - testPullMerge(t, session2, elemBasePR[1], elemBasePR[2], elemBasePR[4], repo_model.MergeStyleMerge, true) + testPullMerge(t, session2, elemBasePR[1], elemBasePR[2], elemBasePR[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: true, + }) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user4", Name: "repo1"}) branchBasePR := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo1.ID, Name: "base-pr"}) @@ -672,7 +743,10 @@ func TestPullMergeIndexerNotifier(t *testing.T) { // merge the pull request elem := strings.Split(test.RedirectURL(createPullResp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: false, + }) // check if the issue is closed issue = unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index 73a40c9440..67dd023a8a 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -212,7 +212,10 @@ func TestPullView_GivenApproveOrRejectReviewOnClosedPR(t *testing.T) { resp := testPullCreate(t, user1Session, "user1", "repo1", false, "master", "master", "This is a pull title") elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, user1Session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + testPullMerge(t, user1Session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: false, + }) // Grab the CSRF token. req := NewRequest(t, "GET", path.Join(elem[1], elem[2], "pulls", elem[4])) diff --git a/tests/integration/repo_activity_test.go b/tests/integration/repo_activity_test.go index d5025decba..7781fd0511 100644 --- a/tests/integration/repo_activity_test.go +++ b/tests/integration/repo_activity_test.go @@ -27,7 +27,10 @@ func TestRepoActivity(t *testing.T) { resp := testPullCreate(t, session, "user1", "repo1", false, "master", "master", "This is a pull title") elem := strings.Split(test.RedirectURL(resp), "/") assert.Equal(t, "pulls", elem[3]) - testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false) + testPullMerge(t, session, elem[1], elem[2], elem[4], MergeOptions{ + Style: repo_model.MergeStyleMerge, + DeleteBranch: false, + }) testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n") testPullCreate(t, session, "user1", "repo1", false, "master", "feat/better_readme", "This is a pull title") diff --git a/tests/integration/repo_branch_test.go b/tests/integration/repo_branch_test.go index 379cf56802..666ae44c08 100644 --- a/tests/integration/repo_branch_test.go +++ b/tests/integration/repo_branch_test.go @@ -218,13 +218,19 @@ func prepareRepoPR(t *testing.T, baseSession, headSession *TestSession, baseRepo testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "merged-pr", http.StatusSeeOther) prID = testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "merged-pr", "merged pr") testAPINewFile(t, headSession, headRepo.OwnerName, headRepo.Name, "merged-pr", fmt.Sprintf("new-commit-%s.txt", headRepo.Name), "new-commit") - testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, repo_model.MergeStyleRebaseMerge, false) + testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, MergeOptions{ + Style: repo_model.MergeStyleRebaseMerge, + DeleteBranch: false, + }) // create merged PR with deleted branch testCreateBranch(t, headSession, headRepo.OwnerName, headRepo.Name, "branch/new-commit", "merged-pr-deleted", http.StatusSeeOther) prID = testCreatePullToDefaultBranch(t, baseSession, baseRepo, headRepo, "merged-pr-deleted", "merged pr with deleted branch") testAPINewFile(t, headSession, headRepo.OwnerName, headRepo.Name, "merged-pr-deleted", fmt.Sprintf("new-commit-%s-2.txt", headRepo.Name), "new-commit") - testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, repo_model.MergeStyleRebaseMerge, true) + testPullMerge(t, baseSession, baseRepo.OwnerName, baseRepo.Name, prID, MergeOptions{ + Style: repo_model.MergeStyleRebaseMerge, + DeleteBranch: true, + }) } func checkRecentlyPushedNewBranches(t *testing.T, session *TestSession, repoPath string, expected []string) { From 3d264ba636bcd165de5f4186cd42253a0dee1de8 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Sat, 11 Oct 2025 23:48:19 -0400 Subject: [PATCH 28/74] bump archives&rar dep (#35637) --- assets/go-licenses.json | 13 +++++++--- go.mod | 25 ++++++++++--------- go.sum | 55 ++++++++++++++++++++++------------------- 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 9c19080e24..b105757683 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -1096,8 +1096,13 @@ }, { "name": "github.com/sorairolake/lzip-go", - "path": "github.com/sorairolake/lzip-go/LICENSE", - "licenseText": " 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\n---\n\nMIT License\n\nCopyright (c) 2024 Shun Sakai\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" + "path": "github.com/sorairolake/lzip-go/LICENSE-APACHE", + "licenseText": " 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/spf13/afero", + "path": "github.com/spf13/afero/LICENSE.txt", + "licenseText": " 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" }, { "name": "github.com/ssor/bom", @@ -1225,8 +1230,8 @@ "licenseText": "Copyright (c) 2016-2024 Uber Technologies, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n" }, { - "name": "go4.org", - "path": "go4.org/LICENSE", + "name": "go4.org/readerutil", + "path": "go4.org/readerutil/LICENSE", "licenseText": " 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\n" }, { diff --git a/go.mod b/go.mod index 64a7dcc708..74e6c4a870 100644 --- a/go.mod +++ b/go.mod @@ -84,7 +84,7 @@ require ( github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-sqlite3 v1.14.32 github.com/meilisearch/meilisearch-go v0.33.2 - github.com/mholt/archives v0.1.3 + github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726 github.com/microcosm-cc/bluemonday v1.0.27 github.com/microsoft/go-mssqldb v1.9.3 github.com/minio/minio-go/v7 v7.0.95 @@ -116,13 +116,13 @@ require ( github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-meta v1.1.0 gitlab.com/gitlab-org/api/client-go v0.142.4 - golang.org/x/crypto v0.41.0 + golang.org/x/crypto v0.42.0 golang.org/x/image v0.30.0 - golang.org/x/net v0.43.0 + golang.org/x/net v0.44.0 golang.org/x/oauth2 v0.30.0 golang.org/x/sync v0.17.0 - golang.org/x/sys v0.35.0 - golang.org/x/text v0.29.0 + golang.org/x/sys v0.36.0 + golang.org/x/text v0.30.0 google.golang.org/grpc v1.75.0 google.golang.org/protobuf v1.36.8 gopkg.in/ini.v1 v1.67.0 @@ -142,7 +142,7 @@ require ( github.com/DataDog/zstd v1.5.7 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/RoaringBitmap/roaring/v2 v2.10.0 // indirect - github.com/STARRY-S/zip v0.2.1 // indirect + github.com/STARRY-S/zip v0.2.3 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect @@ -172,7 +172,7 @@ require ( github.com/blevesearch/zapx/v16 v16.2.4 // indirect github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect github.com/bodgit/plumbing v1.3.0 // indirect - github.com/bodgit/sevenzip v1.6.0 // indirect + github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/boombuler/barcode v1.1.0 // indirect github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf // indirect @@ -233,14 +233,14 @@ require ( github.com/mikelolasagasti/xz v1.0.1 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minlz v1.0.0 // indirect + github.com/minio/minlz v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nwaples/rardecode/v2 v2.1.0 // indirect + github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250817074551-3280053e4e00 // indirect github.com/olekukonko/errors v1.1.0 // indirect github.com/olekukonko/ll v0.1.0 // indirect @@ -259,7 +259,8 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/sorairolake/lzip-go v0.3.5 // indirect + github.com/sorairolake/lzip-go v0.3.8 // indirect + github.com/spf13/afero v1.15.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/tinylib/msgp v1.4.0 // indirect github.com/unknwon/com v1.0.1 // indirect @@ -278,9 +279,9 @@ require ( go.uber.org/zap/exp v0.3.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect - golang.org/x/mod v0.27.0 // indirect + golang.org/x/mod v0.28.0 // indirect golang.org/x/time v0.12.0 // indirect - golang.org/x/tools v0.36.0 // indirect + golang.org/x/tools v0.37.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index 3e9d75c3b8..a1acf535dd 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06 github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I= github.com/RoaringBitmap/roaring/v2 v2.10.0 h1:HbJ8Cs71lfCJyvmSptxeMX2PtvOC8yonlU0GQcy2Ak0= github.com/RoaringBitmap/roaring/v2 v2.10.0/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0= -github.com/STARRY-S/zip v0.2.1 h1:pWBd4tuSGm3wtpoqRZZ2EAwOmcHK6XFf7bU9qcJXyFg= -github.com/STARRY-S/zip v0.2.1/go.mod h1:xNvshLODWtC4EJ702g7cTYn13G53o1+X9BWnPFpcWV4= +github.com/STARRY-S/zip v0.2.3 h1:luE4dMvRPDOWQdeDdUxUoZkzUIpTccdKdhHHsQJ1fm4= +github.com/STARRY-S/zip v0.2.3/go.mod h1:lqJ9JdeRipyOQJrYSOtpNAiaesFO6zVDsE8GIGFaoSk= github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0 h1:tgjwQrDH5m6jIYB7kac5IQZmfUzQNseac/e3H4VoCNE= github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.0/go.mod h1:1HmmMEVsr+0R1QWahSeMJkjSkq6CYAZu1aIbYSpfJ4o= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= @@ -193,8 +193,8 @@ github.com/bmatcuk/doublestar/v4 v4.9.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTS github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q= github.com/bodgit/plumbing v1.3.0 h1:pf9Itz1JOQgn7vEOE7v7nlEfBykYqvUYioC61TwWCFU= github.com/bodgit/plumbing v1.3.0/go.mod h1:JOTb4XiRu5xfnmdnDJo6GmSbSbtSyufrsyZFByMtKEs= -github.com/bodgit/sevenzip v1.6.0 h1:a4R0Wu6/P1o1pP/3VV++aEOcyeBxeO/xE2Y9NSTrr6A= -github.com/bodgit/sevenzip v1.6.0/go.mod h1:zOBh9nJUof7tcrlqJFv1koWRrhz3LbDbUNngkuZxLMc= +github.com/bodgit/sevenzip v1.6.1 h1:kikg2pUMYC9ljU7W9SaqHXhym5HyKm8/M/jd31fYan4= +github.com/bodgit/sevenzip v1.6.1/go.mod h1:GVoYQbEVbOGT8n2pfqCIMRUaRjQ8F9oSqoBEqZh5fQ8= github.com/bodgit/windows v1.0.1 h1:tF7K6KOluPYygXa3Z2594zxlkbKPAOvqr97etrGNIz4= github.com/bodgit/windows v1.0.1/go.mod h1:a6JLwrB4KrTR5hBpp8FI9/9W9jJfeQ2h4XDXU74ZCdM= github.com/bohde/codel v0.2.0 h1:fzF7ibgKmCfQbOzQCblmQcwzDRmV7WO7VMLm/hDvD3E= @@ -572,8 +572,8 @@ github.com/meilisearch/meilisearch-go v0.33.2 h1:YgsQSLYhAkRN2ias6I1KNRTjdYCN5w2 github.com/meilisearch/meilisearch-go v0.33.2/go.mod h1:6eOPcQ+OAuwXvnONlfSgfgvr7TIAWM/6OdhcVHg8cF0= github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ= -github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458= -github.com/mholt/archives v0.1.3/go.mod h1:LUCGp++/IbV/I0Xq4SzcIR6uwgeh2yjnQWamjRQfLTU= +github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726 h1:narluFTg20M5KBwKxedpFiSMkdjQRRNUlpY4uAsKMwk= +github.com/mholt/archives v0.0.0-20251009205813-e30ac6010726/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/microsoft/go-mssqldb v1.9.3 h1:hy4p+LDC8LIGvI3JATnLVmBOLMJbmn5X400mr5j0lPs= @@ -588,8 +588,8 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU= github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo= -github.com/minio/minlz v1.0.0 h1:Kj7aJZ1//LlTP1DM8Jm7lNKvvJS2m74gyyXXn3+uJWQ= -github.com/minio/minlz v1.0.0/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= +github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A= +github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -610,8 +610,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/niklasfasching/go-org v1.9.1 h1:/3s4uTPOF06pImGa2Yvlp24yKXZoTYM+nsIlMzfpg/0= github.com/niklasfasching/go-org v1.9.1/go.mod h1:ZAGFFkWvUQcpazmi/8nHqwvARpr1xpb+Es67oUGX/48= -github.com/nwaples/rardecode/v2 v2.1.0 h1:JQl9ZoBPDy+nIZGb1mx8+anfHp/LV3NE2MjMiv0ct/U= -github.com/nwaples/rardecode/v2 v2.1.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= +github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= +github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -714,9 +714,11 @@ github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYl github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/sorairolake/lzip-go v0.3.5 h1:ms5Xri9o1JBIWvOFAorYtUNik6HI3HgBTkISiqu0Cwg= -github.com/sorairolake/lzip-go v0.3.5/go.mod h1:N0KYq5iWrMXI0ZEXKXaS9hCyOjZUQdBDEIbXfoUwbdk= +github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= +github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -729,6 +731,7 @@ github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -837,8 +840,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -875,8 +878,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= -golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -905,8 +908,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -972,8 +975,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -984,8 +987,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -999,8 +1002,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= @@ -1036,8 +1039,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= -golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 2401812b7600383f9297d556a616a7656034effd Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Sun, 12 Oct 2025 14:23:37 +0200 Subject: [PATCH 29/74] Cleanup ActionRun creation (#35624) Closes #35622 --------- Signed-off-by: ChristopherHX Signed-off-by: wxiaoguang Co-authored-by: delvh Co-authored-by: wxiaoguang --- routers/api/actions/runner/runner.go | 5 +- routers/web/repo/actions/view.go | 8 +-- services/actions/clear_tasks.go | 23 +++++--- services/actions/commit_status.go | 82 +++++++++++++++------------- services/actions/job_emitter.go | 2 +- services/actions/notifier_helper.go | 79 +-------------------------- services/actions/run.go | 65 +++++++++++++++++++--- services/actions/schedule_tasks.go | 41 +------------- services/actions/task.go | 2 +- services/actions/workflow.go | 62 +-------------------- 10 files changed, 133 insertions(+), 236 deletions(-) diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index 46c5147d99..86bab4b340 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -217,10 +217,7 @@ func (s *Service) UpdateTask( return nil, status.Errorf(codes.Internal, "load run: %v", err) } - // don't create commit status for cron job - if task.Job.Run.ScheduleID == 0 { - actions_service.CreateCommitStatus(ctx, task.Job) - } + actions_service.CreateCommitStatusForRunJobs(ctx, task.Job.Run, task.Job) if task.Status.IsDone() { notify_service.WorkflowJobStatusUpdate(ctx, task.Job.Run.Repo, task.Job.Run.TriggerUser, task.Job, task) diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index 232c627709..b409e887be 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -541,7 +541,7 @@ func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shou return err } - actions_service.CreateCommitStatus(ctx, job) + actions_service.CreateCommitStatusForRunJobs(ctx, job.Run, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) return nil @@ -569,7 +569,7 @@ func Logs(ctx *context_module.Context) { func Cancel(ctx *context_module.Context) { runIndex := getRunIndex(ctx) - _, jobs := getRunJobs(ctx, runIndex, -1) + firstJob, jobs := getRunJobs(ctx, runIndex, -1) if ctx.Written() { return } @@ -588,7 +588,7 @@ func Cancel(ctx *context_module.Context) { return } - actions_service.CreateCommitStatus(ctx, jobs...) + actions_service.CreateCommitStatusForRunJobs(ctx, firstJob.Run, jobs...) actions_service.EmitJobsIfReadyByJobs(updatedJobs) for _, job := range updatedJobs { @@ -642,7 +642,7 @@ func Approve(ctx *context_module.Context) { return } - actions_service.CreateCommitStatus(ctx, jobs...) + actions_service.CreateCommitStatusForRunJobs(ctx, current.Run, jobs...) if len(updatedJobs) > 0 { job := updatedJobs[0] diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index 727a18443d..e49bda1b16 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -37,13 +37,19 @@ func StopEndlessTasks(ctx context.Context) error { } func notifyWorkflowJobStatusUpdate(ctx context.Context, jobs []*actions_model.ActionRunJob) { - if len(jobs) > 0 { - CreateCommitStatus(ctx, jobs...) - for _, job := range jobs { - _ = job.LoadAttributes(ctx) - notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) + if len(jobs) == 0 { + return + } + for _, job := range jobs { + if err := job.LoadAttributes(ctx); err != nil { + log.Error("Failed to load job attributes: %v", err) + continue } - job := jobs[0] + CreateCommitStatusForRunJobs(ctx, job.Run, job) + notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) + } + + if job := jobs[0]; job.Run != nil && job.Run.Repo != nil { notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) } } @@ -208,7 +214,10 @@ func CancelAbandonedJobs(ctx context.Context) error { log.Warn("cancel abandoned job %v: %v", job.ID, err) // go on } - CreateCommitStatus(ctx, job) + if job.Run == nil || job.Run.Repo == nil { + continue // error occurs during loading attributes, the following code that depends on "Run.Repo" will fail, so ignore and skip + } + CreateCommitStatusForRunJobs(ctx, job.Run, job) if updated { updatedJobs = append(updatedJobs, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) diff --git a/services/actions/commit_status.go b/services/actions/commit_status.go index ef241e5091..d3f2b0f3cc 100644 --- a/services/actions/commit_status.go +++ b/services/actions/commit_status.go @@ -8,14 +8,15 @@ import ( "errors" "fmt" "path" + "strconv" actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" actions_module "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/commitstatus" - git "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" webhook_module "code.gitea.io/gitea/modules/webhook" commitstatus_service "code.gitea.io/gitea/services/repository/commitstatus" @@ -23,38 +24,46 @@ import ( "github.com/nektos/act/pkg/jobparser" ) -// CreateCommitStatus creates a commit status for the given job. +// CreateCommitStatusForRunJobs creates a commit status for the given job if it has a supported event and related commit. // It won't return an error failed, but will log it, because it's not critical. -func CreateCommitStatus(ctx context.Context, jobs ...*actions_model.ActionRunJob) { +func CreateCommitStatusForRunJobs(ctx context.Context, run *actions_model.ActionRun, jobs ...*actions_model.ActionRunJob) { + // don't create commit status for cron job + if run.ScheduleID != 0 { + return + } + + event, commitID, err := getCommitStatusEventNameAndCommitID(run) + if err != nil { + log.Error("GetCommitStatusEventNameAndSHA: %v", err) + } + if event == "" || commitID == "" { + return // unsupported event, or no commit id, or error occurs, do nothing + } + + if err = run.LoadAttributes(ctx); err != nil { + log.Error("run.LoadAttributes: %v", err) + return + } + for _, job := range jobs { - if err := createCommitStatus(ctx, job); err != nil { + if err = createCommitStatus(ctx, run.Repo, event, commitID, run, job); err != nil { log.Error("Failed to create commit status for job %d: %v", job.ID, err) } } } -func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) error { - if err := job.LoadAttributes(ctx); err != nil { - return fmt.Errorf("load run: %w", err) - } - - run := job.Run - - var ( - sha string - event string - ) +func getCommitStatusEventNameAndCommitID(run *actions_model.ActionRun) (event, commitID string, _ error) { switch run.Event { case webhook_module.HookEventPush: event = "push" payload, err := run.GetPushEventPayload() if err != nil { - return fmt.Errorf("GetPushEventPayload: %w", err) + return "", "", fmt.Errorf("GetPushEventPayload: %w", err) } if payload.HeadCommit == nil { - return errors.New("head commit is missing in event payload") + return "", "", errors.New("head commit is missing in event payload") } - sha = payload.HeadCommit.ID + commitID = payload.HeadCommit.ID case // pull_request webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync, @@ -69,32 +78,33 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er } payload, err := run.GetPullRequestEventPayload() if err != nil { - return fmt.Errorf("GetPullRequestEventPayload: %w", err) + return "", "", fmt.Errorf("GetPullRequestEventPayload: %w", err) } if payload.PullRequest == nil { - return errors.New("pull request is missing in event payload") + return "", "", errors.New("pull request is missing in event payload") } else if payload.PullRequest.Head == nil { - return errors.New("head of pull request is missing in event payload") + return "", "", errors.New("head of pull request is missing in event payload") } - sha = payload.PullRequest.Head.Sha + commitID = payload.PullRequest.Head.Sha case webhook_module.HookEventRelease: event = string(run.Event) - sha = run.CommitSHA - default: - return nil + commitID = run.CommitSHA + default: // do nothing, return empty } + return event, commitID, nil +} - repo := run.Repo +func createCommitStatus(ctx context.Context, repo *repo_model.Repository, event, commitID string, run *actions_model.ActionRun, job *actions_model.ActionRunJob) error { // TODO: store workflow name as a field in ActionRun to avoid parsing runName := path.Base(run.WorkflowID) if wfs, err := jobparser.Parse(job.WorkflowPayload); err == nil && len(wfs) > 0 { runName = wfs[0].Name } - ctxname := fmt.Sprintf("%s / %s (%s)", runName, job.Name, event) + ctxName := fmt.Sprintf("%s / %s (%s)", runName, job.Name, event) state := toCommitStatus(job.Status) - if statuses, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptionsAll); err == nil { + if statuses, err := git_model.GetLatestCommitStatus(ctx, repo.ID, commitID, db.ListOptionsAll); err == nil { for _, v := range statuses { - if v.Context == ctxname { + if v.Context == ctxName { if v.State == state { // no need to update return nil @@ -106,7 +116,7 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er return fmt.Errorf("GetLatestCommitStatus: %w", err) } - description := "" + var description string switch job.Status { // TODO: if we want support description in different languages, we need to support i18n placeholders in it case actions_model.StatusSuccess: @@ -123,6 +133,8 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er description = "Waiting to run" case actions_model.StatusBlocked: description = "Blocked by required conditions" + default: + description = "Unknown status: " + strconv.Itoa(int(job.Status)) } index, err := getIndexOfJob(ctx, job) @@ -131,20 +143,16 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er } creator := user_model.NewActionsUser() - commitID, err := git.NewIDFromString(sha) - if err != nil { - return fmt.Errorf("HashTypeInterfaceFromHashString: %w", err) - } status := git_model.CommitStatus{ - SHA: sha, + SHA: commitID, TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), index), Description: description, - Context: ctxname, + Context: ctxName, CreatorID: creator.ID, State: state, } - return commitstatus_service.CreateCommitStatus(ctx, repo, creator, commitID.String(), &status) + return commitstatus_service.CreateCommitStatus(ctx, repo, creator, commitID, &status) } func toCommitStatus(status actions_model.Status) commitstatus.CommitStatusState { diff --git a/services/actions/job_emitter.go b/services/actions/job_emitter.go index 762d28e9cc..74a8a127ef 100644 --- a/services/actions/job_emitter.go +++ b/services/actions/job_emitter.go @@ -89,7 +89,7 @@ func checkJobsByRunID(ctx context.Context, runID int64) error { }); err != nil { return err } - CreateCommitStatus(ctx, jobs...) + CreateCommitStatusForRunJobs(ctx, run, jobs...) for _, job := range updatedJobs { _ = job.LoadAttributes(ctx) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, nil) diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index fc1894c5d8..d17955b029 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -27,9 +27,7 @@ import ( api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" "code.gitea.io/gitea/services/convert" - notify_service "code.gitea.io/gitea/services/notify" - "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" ) @@ -346,65 +344,10 @@ func handleWorkflows( run.NeedApproval = need - if err := run.LoadAttributes(ctx); err != nil { - log.Error("LoadAttributes: %v", err) + if err := PrepareRunAndInsert(ctx, dwf.Content, run, nil); err != nil { + log.Error("PrepareRunAndInsert: %v", err) continue } - - vars, err := actions_model.GetVariablesOfRun(ctx, run) - if err != nil { - log.Error("GetVariablesOfRun: %v", err) - continue - } - - wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(dwf.Content) - if err != nil { - log.Error("ReadWorkflowRawConcurrency: %v", err) - continue - } - if wfRawConcurrency != nil { - err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) - if err != nil { - log.Error("EvaluateRunConcurrencyFillModel: %v", err) - continue - } - } - - giteaCtx := GenerateGiteaContext(run, nil) - - jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext())) - if err != nil { - log.Error("jobparser.Parse: %v", err) - continue - } - - if len(jobs) > 0 && jobs[0].RunName != "" { - run.Title = jobs[0].RunName - } - - if err := InsertRun(ctx, run, jobs); err != nil { - log.Error("InsertRun: %v", err) - continue - } - - alljobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) - if err != nil { - log.Error("FindRunJobs: %v", err) - continue - } - CreateCommitStatus(ctx, alljobs...) - if len(alljobs) > 0 { - job := alljobs[0] - err := job.LoadRun(ctx) - if err != nil { - log.Error("LoadRun: %v", err) - continue - } - notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) - } - for _, job := range alljobs { - notify_service.WorkflowJobStatusUpdate(ctx, input.Repo, input.Doer, job, nil) - } } return nil } @@ -559,24 +502,6 @@ func handleSchedules( Content: dwf.Content, } - vars, err := actions_model.GetVariablesOfRun(ctx, run.ToActionRun()) - if err != nil { - log.Error("GetVariablesOfRun: %v", err) - continue - } - - giteaCtx := GenerateGiteaContext(run.ToActionRun(), nil) - - jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext())) - if err != nil { - log.Error("jobparser.Parse: %v", err) - continue - } - - if len(jobs) > 0 && jobs[0].RunName != "" { - run.Title = jobs[0].RunName - } - crons = append(crons, run) } diff --git a/services/actions/run.go b/services/actions/run.go index a3356d71c1..90413e9bc2 100644 --- a/services/actions/run.go +++ b/services/actions/run.go @@ -10,14 +10,71 @@ import ( actions_model "code.gitea.io/gitea/models/actions" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/util" + notify_service "code.gitea.io/gitea/services/notify" "github.com/nektos/act/pkg/jobparser" "gopkg.in/yaml.v3" ) +// PrepareRunAndInsert prepares a run and inserts it into the database +// It parses the workflow content, evaluates concurrency if needed, and inserts the run and its jobs into the database. +// The title will be cut off at 255 characters if it's longer than 255 characters. +func PrepareRunAndInsert(ctx context.Context, content []byte, run *actions_model.ActionRun, inputsWithDefaults map[string]any) error { + if err := run.LoadAttributes(ctx); err != nil { + return fmt.Errorf("LoadAttributes: %w", err) + } + + vars, err := actions_model.GetVariablesOfRun(ctx, run) + if err != nil { + return fmt.Errorf("GetVariablesOfRun: %w", err) + } + + wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(content) + if err != nil { + return fmt.Errorf("ReadWorkflowRawConcurrency: %w", err) + } + + if wfRawConcurrency != nil { + err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) + if err != nil { + return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err) + } + } + + giteaCtx := GenerateGiteaContext(run, nil) + + jobs, err := jobparser.Parse(content, jobparser.WithVars(vars), jobparser.WithGitContext(giteaCtx.ToGitHubContext()), jobparser.WithInputs(inputsWithDefaults)) + if err != nil { + return fmt.Errorf("parse workflow: %w", err) + } + + if len(jobs) > 0 && jobs[0].RunName != "" { + run.Title = jobs[0].RunName + } + + if err = InsertRun(ctx, run, jobs, vars); err != nil { + return fmt.Errorf("InsertRun: %w", err) + } + + // Load the newly inserted jobs with all fields from database (the job models in InsertRun are partial, so load again) + allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) + if err != nil { + return fmt.Errorf("FindRunJob: %w", err) + } + + CreateCommitStatusForRunJobs(ctx, run, allJobs...) + + notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run) + for _, job := range allJobs { + notify_service.WorkflowJobStatusUpdate(ctx, run.Repo, run.TriggerUser, job, nil) + } + + return nil +} + // InsertRun inserts a run // The title will be cut off at 255 characters if it's longer than 255 characters. -func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobparser.SingleWorkflow) error { +func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobparser.SingleWorkflow, vars map[string]string) error { return db.WithTx(ctx, func(ctx context.Context) error { index, err := db.GetNextResourceIndex(ctx, "action_run_index", run.RepoID) if err != nil { @@ -44,12 +101,6 @@ func InsertRun(ctx context.Context, run *actions_model.ActionRun, jobs []*jobpar return err } - // query vars for evaluating job concurrency groups - vars, err := actions_model.GetVariablesOfRun(ctx, run) - if err != nil { - return fmt.Errorf("get run %d variables: %w", run.ID, err) - } - runJobs := make([]*actions_model.ActionRunJob, 0, len(jobs)) var hasWaitingJobs bool for _, v := range jobs { diff --git a/services/actions/schedule_tasks.go b/services/actions/schedule_tasks.go index 3b37b44ac4..037bf5cddd 100644 --- a/services/actions/schedule_tasks.go +++ b/services/actions/schedule_tasks.go @@ -15,9 +15,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" webhook_module "code.gitea.io/gitea/modules/webhook" - notify_service "code.gitea.io/gitea/services/notify" - - "github.com/nektos/act/pkg/jobparser" ) // StartScheduleTasks start the task @@ -119,44 +116,12 @@ func CreateScheduleTask(ctx context.Context, cron *actions_model.ActionSchedule) Status: actions_model.StatusWaiting, } - vars, err := actions_model.GetVariablesOfRun(ctx, run) - if err != nil { - log.Error("GetVariablesOfRun: %v", err) - return err - } - - // Parse the workflow specification from the cron schedule - workflows, err := jobparser.Parse(cron.Content, jobparser.WithVars(vars)) - if err != nil { - return err - } - wfRawConcurrency, err := jobparser.ReadWorkflowRawConcurrency(cron.Content) - if err != nil { - return err - } - if wfRawConcurrency != nil { - err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) - if err != nil { - return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err) - } - } - + // FIXME cron.Content might be outdated if the workflow file has been changed. + // Load the latest sha from default branch // Insert the action run and its associated jobs into the database - if err := InsertRun(ctx, run, workflows); err != nil { + if err := PrepareRunAndInsert(ctx, cron.Content, run, nil); err != nil { return err } - allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) - if err != nil { - log.Error("FindRunJobs: %v", err) - } - err = run.LoadAttributes(ctx) - if err != nil { - log.Error("LoadAttributes: %v", err) - } - notify_service.WorkflowRunStatusUpdate(ctx, run.Repo, run.TriggerUser, run) - for _, job := range allJobs { - notify_service.WorkflowJobStatusUpdate(ctx, run.Repo, run.TriggerUser, job, nil) - } // Return nil if no errors occurred return nil diff --git a/services/actions/task.go b/services/actions/task.go index 6a547c1c12..cf2164f456 100644 --- a/services/actions/task.go +++ b/services/actions/task.go @@ -97,7 +97,7 @@ func PickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv return nil, false, nil } - CreateCommitStatus(ctx, job) + CreateCommitStatusForRunJobs(ctx, job.Run, job) notify_service.WorkflowJobStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job, actionTask) return task, true, nil diff --git a/services/actions/workflow.go b/services/actions/workflow.go index e3e60d4967..25801d6fa1 100644 --- a/services/actions/workflow.go +++ b/services/actions/workflow.go @@ -8,7 +8,6 @@ import ( "strings" actions_model "code.gitea.io/gitea/models/actions" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" @@ -16,13 +15,11 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/reqctx" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/convert" - notify_service "code.gitea.io/gitea/services/notify" "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" @@ -98,9 +95,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re } // find workflow from commit - var workflows []*jobparser.SingleWorkflow var entry *git.TreeEntry - var wfRawConcurrency *model.RawConcurrency run := &actions_model.ActionRun{ Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0], @@ -153,29 +148,6 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re } } - giteaCtx := GenerateGiteaContext(run, nil) - - workflows, err = jobparser.Parse(content, jobparser.WithGitContext(giteaCtx.ToGitHubContext()), jobparser.WithInputs(inputsWithDefaults)) - if err != nil { - return err - } - - if len(workflows) > 0 && workflows[0].RunName != "" { - run.Title = workflows[0].RunName - } - - if len(workflows) == 0 { - return util.ErrorWrapLocale( - util.NewNotExistErrorf("workflow %q doesn't exist", workflowID), - "actions.workflow.not_found", workflowID, - ) - } - - wfRawConcurrency, err = jobparser.ReadWorkflowRawConcurrency(content) - if err != nil { - return err - } - // ctx.Req.PostForm -> WorkflowDispatchPayload.Inputs -> ActionRun.EventPayload -> runner: ghc.Event // https://docs.github.com/en/actions/learn-github-actions/contexts#github-context // https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch @@ -193,39 +165,9 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re } run.EventPayload = string(eventPayload) - // cancel running jobs of the same concurrency group - if wfRawConcurrency != nil { - vars, err := actions_model.GetVariablesOfRun(ctx, run) - if err != nil { - return fmt.Errorf("GetVariablesOfRun: %w", err) - } - err = EvaluateRunConcurrencyFillModel(ctx, run, wfRawConcurrency, vars) - if err != nil { - return fmt.Errorf("EvaluateRunConcurrencyFillModel: %w", err) - } - } - // Insert the action run and its associated jobs into the database - if err := InsertRun(ctx, run, workflows); err != nil { - return fmt.Errorf("InsertRun: %w", err) - } - - allJobs, err := db.Find[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{RunID: run.ID}) - if err != nil { - log.Error("FindRunJobs: %v", err) - } - CreateCommitStatus(ctx, allJobs...) - if len(allJobs) > 0 { - job := allJobs[0] - err := job.LoadRun(ctx) - if err != nil { - log.Error("LoadRun: %v", err) - } else { - notify_service.WorkflowRunStatusUpdate(ctx, job.Run.Repo, job.Run.TriggerUser, job.Run) - } - } - for _, job := range allJobs { - notify_service.WorkflowJobStatusUpdate(ctx, repo, doer, job, nil) + if err := PrepareRunAndInsert(ctx, content, run, inputsWithDefaults); err != nil { + return fmt.Errorf("PrepareRun: %w", err) } return nil } From f9a4b2753c7944b95fdb658f0be391f82ffc5025 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Sun, 12 Oct 2025 11:59:00 -0400 Subject: [PATCH 30/74] nix flake update (#35639) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 16a487ba13..5cb95c1aed 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1755186698, - "narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=", + "lastModified": 1760038930, + "narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c", + "rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3", "type": "github" }, "original": { From 912515e63a0ee209b12d98143431d47a04a73124 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 12 Oct 2025 20:01:42 +0200 Subject: [PATCH 31/74] Bump actions/checkout to v5 (#35644) --- .github/workflows/cron-licenses.yml | 2 +- .github/workflows/cron-translations.yml | 2 +- .github/workflows/files-changed.yml | 2 +- .github/workflows/pull-compliance.yml | 24 +++++++++++------------ .github/workflows/pull-db-tests.yml | 10 +++++----- .github/workflows/pull-e2e-tests.yml | 2 +- .github/workflows/release-nightly.yml | 6 +++--- .github/workflows/release-tag-rc.yml | 6 +++--- .github/workflows/release-tag-version.yml | 6 +++--- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/cron-licenses.yml b/.github/workflows/cron-licenses.yml index c34066d318..024c273e79 100644 --- a/.github/workflows/cron-licenses.yml +++ b/.github/workflows/cron-licenses.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'go-gitea/gitea' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod diff --git a/.github/workflows/cron-translations.yml b/.github/workflows/cron-translations.yml index f1b51debf1..ae2238ad2d 100644 --- a/.github/workflows/cron-translations.yml +++ b/.github/workflows/cron-translations.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest if: github.repository == 'go-gitea/gitea' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: crowdin/github-action@v1 with: upload_sources: true diff --git a/.github/workflows/files-changed.yml b/.github/workflows/files-changed.yml index edceef0092..b21341a277 100644 --- a/.github/workflows/files-changed.yml +++ b/.github/workflows/files-changed.yml @@ -34,7 +34,7 @@ jobs: swagger: ${{ steps.changes.outputs.swagger }} yaml: ${{ steps.changes.outputs.yaml }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dorny/paths-filter@v3 id: changes with: diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml index 6f8991ed4e..0561392cf8 100644 --- a/.github/workflows/pull-compliance.yml +++ b/.github/workflows/pull-compliance.yml @@ -16,7 +16,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -31,7 +31,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - run: uv python install 3.12 - uses: pnpm/action-setup@v4 @@ -47,7 +47,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: astral-sh/setup-uv@v6 - run: uv python install 3.12 - run: make deps-py @@ -58,7 +58,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v5 with: @@ -71,7 +71,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -83,7 +83,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -100,7 +100,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -115,7 +115,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -128,7 +128,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v5 with: @@ -144,7 +144,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -176,7 +176,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v5 with: @@ -189,7 +189,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod diff --git a/.github/workflows/pull-db-tests.yml b/.github/workflows/pull-db-tests.yml index a7ad7ed5c3..6ff7d53b75 100644 --- a/.github/workflows/pull-db-tests.yml +++ b/.github/workflows/pull-db-tests.yml @@ -38,7 +38,7 @@ jobs: ports: - "9000:9000" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -66,7 +66,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -124,7 +124,7 @@ jobs: ports: - 10000:10000 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -177,7 +177,7 @@ jobs: - "587:587" - "993:993" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod @@ -217,7 +217,7 @@ jobs: ports: - 10000:10000 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod diff --git a/.github/workflows/pull-e2e-tests.yml b/.github/workflows/pull-e2e-tests.yml index 89b32260ca..27b7a4eabb 100644 --- a/.github/workflows/pull-e2e-tests.yml +++ b/.github/workflows/pull-e2e-tests.yml @@ -18,7 +18,7 @@ jobs: needs: files-changed runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: actions/setup-go@v5 with: go-version-file: go.mod diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index 3d652e4ad8..a521fd9c28 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -12,7 +12,7 @@ jobs: nightly-binary: runs-on: namespace-profile-gitea-release-binary steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -61,7 +61,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -103,7 +103,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force diff --git a/.github/workflows/release-tag-rc.yml b/.github/workflows/release-tag-rc.yml index f4776a9ed8..52731bccf9 100644 --- a/.github/workflows/release-tag-rc.yml +++ b/.github/workflows/release-tag-rc.yml @@ -13,7 +13,7 @@ jobs: binary: runs-on: namespace-profile-gitea-release-binary steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -71,7 +71,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -112,7 +112,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force diff --git a/.github/workflows/release-tag-version.yml b/.github/workflows/release-tag-version.yml index ad0820f31f..238636c8e1 100644 --- a/.github/workflows/release-tag-version.yml +++ b/.github/workflows/release-tag-version.yml @@ -17,7 +17,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -75,7 +75,7 @@ jobs: permissions: packages: write # to publish to ghcr.io steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force @@ -118,7 +118,7 @@ jobs: docker-rootless: runs-on: namespace-profile-gitea-release-docker steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force From 49a0a11f55acd2df40d77c02381ba9db94c5723c Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 12 Oct 2025 23:07:15 +0200 Subject: [PATCH 32/74] Update JS deps, misc tweaks (#35643) - Update all JS dependencies - Enable eslint `no-useless-assignment` and fix 2 discovered issues - Replace `gitea-vscode` svg with new `octicon-vscode` - Remove now-unused `@ts-expect-error` comments - Change Monaco wrapping behaviour to match the wrapping in code view: no wrapping indent and break on any character. --- eslint.config.ts | 8 +- package.json | 32 +- pnpm-lock.yaml | 1163 ++++++++++-------- public/assets/img/svg/gitea-vscode.svg | 1 - public/assets/img/svg/octicon-comment-ai.svg | 1 + public/assets/img/svg/octicon-vscode.svg | 1 + routers/web/repo/view_home.go | 21 +- web_src/js/features/codeeditor.ts | 3 + web_src/js/features/dropzone.ts | 1 - web_src/js/features/repo-migration.ts | 2 +- web_src/svg/gitea-vscode.svg | 1 - 11 files changed, 654 insertions(+), 580 deletions(-) delete mode 100644 public/assets/img/svg/gitea-vscode.svg create mode 100644 public/assets/img/svg/octicon-comment-ai.svg create mode 100644 public/assets/img/svg/octicon-vscode.svg delete mode 100644 web_src/svg/gitea-vscode.svg diff --git a/eslint.config.ts b/eslint.config.ts index 678a49647c..02aacefca2 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -52,21 +52,16 @@ export default defineConfig([ }, plugins: { '@eslint-community/eslint-comments': comments, - // @ts-expect-error '@stylistic': stylistic, '@typescript-eslint': typescriptPlugin.plugin, 'array-func': arrayFunc, // @ts-expect-error -- https://github.com/un-ts/eslint-plugin-import-x/issues/203 'import-x': importPlugin, 'no-use-extend-native': noUseExtendNative, - // @ts-expect-error regexp, - // @ts-expect-error sonarjs, - // @ts-expect-error unicorn, github, - // @ts-expect-error wc, }, settings: { @@ -595,6 +590,7 @@ export default defineConfig([ 'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars 'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define 'no-use-extend-native/no-use-extend-native': [2], + 'no-useless-assignment': [2], 'no-useless-backreference': [2], 'no-useless-call': [2], 'no-useless-catch': [2], @@ -900,7 +896,6 @@ export default defineConfig([ 'yoda': [2, 'never'], }, }, - // @ts-expect-error { ...playwright.configs['flat/recommended'], files: ['tests/e2e/**'], @@ -916,7 +911,6 @@ export default defineConfig([ }, }, extends: [ - // @ts-expect-error vue.configs['flat/recommended'], // @ts-expect-error vueScopedCss.configs['flat/recommended'], diff --git a/package.json b/package.json index 68ea60ffed..61cda2e1e7 100644 --- a/package.json +++ b/package.json @@ -15,13 +15,13 @@ "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.2", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", - "@primer/octicons": "19.18.0", + "@primer/octicons": "19.19.0", "@resvg/resvg-wasm": "2.6.2", "@silverwind/vue3-calendar-heatmap": "2.0.6", "@techknowlogick/license-checker-webpack-plugin": "0.3.0", "add-asset-webpack-plugin": "3.1.1", "ansi_up": "6.0.6", - "asciinema-player": "3.10.0", + "asciinema-player": "3.12.0", "chart.js": "4.5.0", "chartjs-adapter-dayjs-4": "1.0.4", "chartjs-plugin-zoom": "2.2.0", @@ -31,22 +31,22 @@ "dayjs": "1.11.18", "dropzone": "6.0.0-beta.2", "easymde": "2.20.0", - "esbuild-loader": "4.3.0", + "esbuild-loader": "4.4.0", "htmx.org": "2.0.7", "idiomorph": "0.7.4", "jquery": "3.7.1", - "katex": "0.16.22", + "katex": "0.16.23", "mermaid": "11.12.0", "mini-css-extract-plugin": "2.9.4", - "monaco-editor": "0.53.0", - "monaco-editor-webpack-plugin": "7.1.0", + "monaco-editor": "0.54.0", + "monaco-editor-webpack-plugin": "7.1.1", "online-3d-viewer": "0.16.0", "pdfobject": "2.3.1", "perfect-debounce": "2.0.0", "postcss": "8.5.6", "postcss-loader": "8.2.0", "sortablejs": "1.15.6", - "swagger-ui-dist": "5.29.1", + "swagger-ui-dist": "5.29.4", "tailwindcss": "3.4.17", "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", @@ -60,13 +60,13 @@ "vue-bar-graph": "2.2.0", "vue-chartjs": "5.3.2", "vue-loader": "17.4.2", - "webpack": "5.102.0", + "webpack": "5.102.1", "webpack-cli": "6.0.1", "wrap-ansi": "9.0.2" }, "devDependencies": { "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", - "@playwright/test": "1.55.1", + "@playwright/test": "1.56.0", "@stylistic/eslint-plugin": "5.4.0", "@stylistic/stylelint-plugin": "4.0.0", "@types/codemirror": "5.60.16", @@ -79,10 +79,10 @@ "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/parser": "8.45.0", + "@typescript-eslint/parser": "8.46.0", "@vitejs/plugin-vue": "6.0.1", - "@vitest/eslint-plugin": "1.3.13", - "eslint": "9.36.0", + "@vitest/eslint-plugin": "1.3.16", + "eslint": "9.37.0", "eslint-import-resolver-typescript": "4.4.4", "eslint-plugin-array-func": "5.1.0", "eslint-plugin-github": "6.0.0", @@ -102,17 +102,17 @@ "nolyfill": "1.0.44", "postcss-html": "1.8.0", "spectral-cli-bundle": "1.0.3", - "stylelint": "16.24.0", + "stylelint": "16.25.0", "stylelint-config-recommended": "17.0.0", "stylelint-declaration-block-no-ignored-properties": "2.8.0", "stylelint-declaration-strict-value": "1.10.11", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "4.0.0", - "typescript-eslint": "8.45.0", - "updates": "16.7.4", + "typescript-eslint": "8.46.0", + "updates": "16.8.0", "vite-string-plugin": "1.4.6", "vitest": "3.2.4", - "vue-tsc": "3.1.0" + "vue-tsc": "3.1.1" }, "browserslist": [ "defaults" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e749a71c7d..7989a54441 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,8 +54,8 @@ importers: specifier: 0.1.0-alpha-3 version: 0.1.0-alpha-3 '@primer/octicons': - specifier: 19.18.0 - version: 19.18.0 + specifier: 19.19.0 + version: 19.19.0 '@resvg/resvg-wasm': specifier: 2.6.2 version: 2.6.2 @@ -64,16 +64,16 @@ importers: version: 2.0.6(tippy.js@6.3.7)(vue@3.5.22(typescript@5.9.3)) '@techknowlogick/license-checker-webpack-plugin': specifier: 0.3.0 - version: 0.3.0(webpack@5.102.0) + version: 0.3.0(webpack@5.102.1) add-asset-webpack-plugin: specifier: 3.1.1 - version: 3.1.1(webpack@5.102.0) + version: 3.1.1(webpack@5.102.1) ansi_up: specifier: 6.0.6 version: 6.0.6 asciinema-player: - specifier: 3.10.0 - version: 3.10.0 + specifier: 3.12.0 + version: 3.12.0 chart.js: specifier: 4.5.0 version: 4.5.0 @@ -91,7 +91,7 @@ importers: version: 1.6.2 css-loader: specifier: 7.1.2 - version: 7.1.2(webpack@5.102.0) + version: 7.1.2(webpack@5.102.1) dayjs: specifier: 1.11.18 version: 1.11.18 @@ -102,8 +102,8 @@ importers: specifier: 2.20.0 version: 2.20.0 esbuild-loader: - specifier: 4.3.0 - version: 4.3.0(webpack@5.102.0) + specifier: 4.4.0 + version: 4.4.0(webpack@5.102.1) htmx.org: specifier: 2.0.7 version: 2.0.7 @@ -114,20 +114,20 @@ importers: specifier: 3.7.1 version: 3.7.1 katex: - specifier: 0.16.22 - version: 0.16.22 + specifier: 0.16.23 + version: 0.16.23 mermaid: specifier: 11.12.0 version: 11.12.0 mini-css-extract-plugin: specifier: 2.9.4 - version: 2.9.4(webpack@5.102.0) + version: 2.9.4(webpack@5.102.1) monaco-editor: - specifier: 0.53.0 - version: 0.53.0 + specifier: 0.54.0 + version: 0.54.0 monaco-editor-webpack-plugin: - specifier: 7.1.0 - version: 7.1.0(monaco-editor@0.53.0)(webpack@5.102.0) + specifier: 7.1.1 + version: 7.1.1(monaco-editor@0.54.0)(webpack@5.102.1) online-3d-viewer: specifier: 0.16.0 version: 0.16.0 @@ -142,13 +142,13 @@ importers: version: 8.5.6 postcss-loader: specifier: 8.2.0 - version: 8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0) + version: 8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1) sortablejs: specifier: 1.15.6 version: 1.15.6 swagger-ui-dist: - specifier: 5.29.1 - version: 5.29.1 + specifier: 5.29.4 + version: 5.29.4 tailwindcss: specifier: 3.4.17 version: 3.4.17 @@ -187,29 +187,29 @@ importers: version: 5.3.2(chart.js@4.5.0)(vue@3.5.22(typescript@5.9.3)) vue-loader: specifier: 17.4.2 - version: 17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0) + version: 17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.1) webpack: - specifier: 5.102.0 - version: 5.102.0(webpack-cli@6.0.1) + specifier: 5.102.1 + version: 5.102.1(webpack-cli@6.0.1) webpack-cli: specifier: 6.0.1 - version: 6.0.1(webpack@5.102.0) + version: 6.0.1(webpack@5.102.1) wrap-ansi: specifier: 9.0.2 version: 9.0.2 devDependencies: '@eslint-community/eslint-plugin-eslint-comments': specifier: 4.5.0 - version: 4.5.0(eslint@9.36.0(jiti@2.6.1)) + version: 4.5.0(eslint@9.37.0(jiti@2.6.1)) '@playwright/test': - specifier: 1.55.1 - version: 1.55.1 + specifier: 1.56.0 + version: 1.56.0 '@stylistic/eslint-plugin': specifier: 5.4.0 - version: 5.4.0(eslint@9.36.0(jiti@2.6.1)) + version: 5.4.0(eslint@9.37.0(jiti@2.6.1)) '@stylistic/stylelint-plugin': specifier: 4.0.0 - version: 4.0.0(stylelint@16.24.0(typescript@5.9.3)) + version: 4.0.0(stylelint@16.25.0(typescript@5.9.3)) '@types/codemirror': specifier: 5.60.16 version: 5.60.16 @@ -241,53 +241,53 @@ importers: specifier: 1.12.4 version: 1.12.4 '@typescript-eslint/parser': - specifier: 8.45.0 - version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.46.0 + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) '@vitejs/plugin-vue': specifier: 6.0.1 - version: 6.0.1(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) + version: 6.0.1(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) '@vitest/eslint-plugin': - specifier: 1.3.13 - version: 1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + specifier: 1.3.16 + version: 1.3.16(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) eslint: - specifier: 9.36.0 - version: 9.36.0(jiti@2.6.1) + specifier: 9.37.0 + version: 9.37.0(jiti@2.6.1) eslint-import-resolver-typescript: specifier: 4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-array-func: specifier: 5.1.0 - version: 5.1.0(eslint@9.36.0(jiti@2.6.1)) + version: 5.1.0(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-github: specifier: 6.0.0 - version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) + version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-import-x: specifier: 4.16.1 - version: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)) + version: 4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-no-use-extend-native: specifier: 0.7.2 - version: 0.7.2(eslint@9.36.0(jiti@2.6.1)) + version: 0.7.2(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-playwright: specifier: 2.2.2 - version: 2.2.2(eslint@9.36.0(jiti@2.6.1)) + version: 2.2.2(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-regexp: specifier: 2.10.0 - version: 2.10.0(eslint@9.36.0(jiti@2.6.1)) + version: 2.10.0(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-sonarjs: specifier: 3.0.5 - version: 3.0.5(eslint@9.36.0(jiti@2.6.1)) + version: 3.0.5(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-unicorn: specifier: 61.0.2 - version: 61.0.2(eslint@9.36.0(jiti@2.6.1)) + version: 61.0.2(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-vue: specifier: 10.5.0 - version: 10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))) + version: 10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1)))(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))) eslint-plugin-vue-scoped-css: specifier: 2.12.0 - version: 2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))) + version: 2.12.0(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))) eslint-plugin-wc: specifier: 3.0.2 - version: 3.0.2(eslint@9.36.0(jiti@2.6.1)) + version: 3.0.2(eslint@9.37.0(jiti@2.6.1)) globals: specifier: 16.4.0 version: 16.4.0 @@ -310,38 +310,38 @@ importers: specifier: 1.0.3 version: 1.0.3 stylelint: - specifier: 16.24.0 - version: 16.24.0(typescript@5.9.3) + specifier: 16.25.0 + version: 16.25.0(typescript@5.9.3) stylelint-config-recommended: specifier: 17.0.0 - version: 17.0.0(stylelint@16.24.0(typescript@5.9.3)) + version: 17.0.0(stylelint@16.25.0(typescript@5.9.3)) stylelint-declaration-block-no-ignored-properties: specifier: 2.8.0 - version: 2.8.0(stylelint@16.24.0(typescript@5.9.3)) + version: 2.8.0(stylelint@16.25.0(typescript@5.9.3)) stylelint-declaration-strict-value: specifier: 1.10.11 - version: 1.10.11(stylelint@16.24.0(typescript@5.9.3)) + version: 1.10.11(stylelint@16.25.0(typescript@5.9.3)) stylelint-value-no-unknown-custom-properties: specifier: 6.0.1 - version: 6.0.1(stylelint@16.24.0(typescript@5.9.3)) + version: 6.0.1(stylelint@16.25.0(typescript@5.9.3)) svgo: specifier: 4.0.0 version: 4.0.0 typescript-eslint: - specifier: 8.45.0 - version: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.46.0 + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) updates: - specifier: 16.7.4 - version: 16.7.4 + specifier: 16.8.0 + version: 16.8.0 vite-string-plugin: specifier: 1.4.6 version: 1.4.6 vitest: specifier: 3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue-tsc: - specifier: 3.1.0 - version: 3.1.0(typescript@5.9.3) + specifier: 3.1.1 + version: 3.1.1(typescript@5.9.3) packages: @@ -352,8 +352,8 @@ packages: '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - '@antfu/utils@9.2.1': - resolution: {integrity: sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg==} + '@antfu/utils@9.3.0': + resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} @@ -389,8 +389,8 @@ packages: '@cacheable/memory@2.0.3': resolution: {integrity: sha512-R3UKy/CKOyb1LZG/VRCTMcpiMDyLH7SH3JrraRdK6kf3GweWCOU3sgvE13W3TiDRbxnDKylzKJvhUAvWl9LQOA==} - '@cacheable/utils@2.0.3': - resolution: {integrity: sha512-m7Rce68cMHlAUjvWBy9Ru1Nmw5gU0SjGGtQDdhpe6E0xnbcvrIY0Epy//JU1VYYBUTzrG9jvgmTauULGKzOkWA==} + '@cacheable/utils@2.1.0': + resolution: {integrity: sha512-ZdxfOiaarMqMj+H7qwlt5EBKWaeGihSYVHdQv5lUsbn8MJJOTW82OIwirQ39U5tMZkNvy3bQE+ryzC+xTAb9/g==} '@chevrotain/cst-dts-gen@11.0.3': resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} @@ -679,8 +679,8 @@ packages: resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.1': - resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + '@eslint/config-helpers@0.4.0': + resolution: {integrity: sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.15.2': @@ -695,8 +695,8 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.36.0': - resolution: {integrity: sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==} + '@eslint/js@9.37.0': + resolution: {integrity: sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -707,6 +707,10 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.4.0': + resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@github/browserslist-config@1.0.0': resolution: {integrity: sha512-gIhjdJp/c2beaIWWIlsXdqXVRUz3r2BxBCpfz/F3JXHvSAQ1paMYjLH+maEATtENg+k5eLV7gA+9yPp762ieuw==} @@ -775,8 +779,8 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@keyv/bigmap@1.0.2': - resolution: {integrity: sha512-KR03xkEZlAZNF4IxXgVXb+uNIVNvwdh8UwI0cnc7WI6a+aQcDp8GL80qVfeB4E5NpsKJzou5jU0r6yLSSbMOtA==} + '@keyv/bigmap@1.0.3': + resolution: {integrity: sha512-jUEkNlnE9tYzX2AIBeoSe1gVUvSOfIOQ5EFPL5Un8cFHGvjD9L/fxpxlS1tEivRLHgapO2RZJ3D93HYAa049pg==} engines: {node: '>= 18'} '@keyv/serialize@1.1.1': @@ -791,8 +795,8 @@ packages: '@mcaptcha/vanilla-glue@0.1.0-alpha-3': resolution: {integrity: sha512-GT6TJBgmViGXcXiT5VOr+h/6iOnThSlZuCoOWncubyTZU9R3cgU5vWPkF7G6Ob6ee2CBe3yqBxxk24CFVGTVXw==} - '@mermaid-js/parser@0.6.2': - resolution: {integrity: sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==} + '@mermaid-js/parser@0.6.3': + resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -880,16 +884,16 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.55.1': - resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==} + '@playwright/test@1.56.0': + resolution: {integrity: sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==} engines: {node: '>=18'} hasBin: true '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@primer/octicons@19.18.0': - resolution: {integrity: sha512-4P8FS7slUp0vHE7zLtlfOQcgF99r0tdxpriT3ahp6iwwnf1hF3OlDWXEp5n6b6G5eIY1cNr1bCrjRL+DkRjFVw==} + '@primer/octicons@19.19.0': + resolution: {integrity: sha512-LBbL8nOl6FWMDy7riKB5ppHLtffY7loRq+CDGj0D5G1Xdo2mKlSOQy3rWy2RVE8SxxPFL+mj46C1nG+smKBEZA==} '@resvg/resvg-wasm@2.6.2': resolution: {integrity: sha512-FqALmHI8D4o6lk/LRWDnhw95z5eO+eAa6ORjVg09YRR7BkcM6oPHU9uyC0gtQG5vpFLvgpeU4+zEAz2H8APHNw==} @@ -898,113 +902,113 @@ packages: '@rolldown/pluginutils@1.0.0-beta.29': resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} - '@rollup/rollup-android-arm-eabi@4.52.3': - resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==} + '@rollup/rollup-android-arm-eabi@4.52.4': + resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.52.3': - resolution: {integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==} + '@rollup/rollup-android-arm64@4.52.4': + resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.52.3': - resolution: {integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==} + '@rollup/rollup-darwin-arm64@4.52.4': + resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.52.3': - resolution: {integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==} + '@rollup/rollup-darwin-x64@4.52.4': + resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.52.3': - resolution: {integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==} + '@rollup/rollup-freebsd-arm64@4.52.4': + resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.52.3': - resolution: {integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==} + '@rollup/rollup-freebsd-x64@4.52.4': + resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.52.3': - resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==} + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': + resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.52.3': - resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==} + '@rollup/rollup-linux-arm-musleabihf@4.52.4': + resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.52.3': - resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==} + '@rollup/rollup-linux-arm64-gnu@4.52.4': + resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.52.3': - resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==} + '@rollup/rollup-linux-arm64-musl@4.52.4': + resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.52.3': - resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==} + '@rollup/rollup-linux-loong64-gnu@4.52.4': + resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.52.3': - resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==} + '@rollup/rollup-linux-ppc64-gnu@4.52.4': + resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.52.3': - resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==} + '@rollup/rollup-linux-riscv64-gnu@4.52.4': + resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.52.3': - resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==} + '@rollup/rollup-linux-riscv64-musl@4.52.4': + resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.52.3': - resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==} + '@rollup/rollup-linux-s390x-gnu@4.52.4': + resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.52.3': - resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==} + '@rollup/rollup-linux-x64-gnu@4.52.4': + resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.52.3': - resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==} + '@rollup/rollup-linux-x64-musl@4.52.4': + resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.52.3': - resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==} + '@rollup/rollup-openharmony-arm64@4.52.4': + resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.52.3': - resolution: {integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==} + '@rollup/rollup-win32-arm64-msvc@4.52.4': + resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.52.3': - resolution: {integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==} + '@rollup/rollup-win32-ia32-msvc@4.52.4': + resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.52.3': - resolution: {integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==} + '@rollup/rollup-win32-x64-gnu@4.52.4': + resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.52.3': - resolution: {integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==} + '@rollup/rollup-win32-x64-msvc@4.52.4': + resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} cpu: [x64] os: [win32] @@ -1024,6 +1028,21 @@ packages: '@simonwep/pickr@1.9.0': resolution: {integrity: sha512-oEYvv15PyfZzjoAzvXYt3UyNGwzsrpFxLaZKzkOSd0WYBVwLd19iJerePDONxC1iF6+DpcswPdLIM2KzCJuYFg==} + '@solid-primitives/refs@1.1.2': + resolution: {integrity: sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/transition-group@1.1.2': + resolution: {integrity: sha512-gnHS0OmcdjeoHN9n7Khu8KNrOlRc8a2weETDt2YT6o1zeW/XtUC6Db3Q9pkMU/9cCKdEmN4b0a/41MKAHRhzWA==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/utils@6.3.2': + resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==} + peerDependencies: + solid-js: ^1.6.12 + '@stylistic/eslint-plugin@5.4.0': resolution: {integrity: sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1188,11 +1207,11 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@20.19.20': - resolution: {integrity: sha512-2Q7WS25j4pS1cS8yw3d6buNCVJukOTeQ39bAnwR6sOJbaxvyCGebzTMypDFN82CxBLnl+lSWVdCCWbRY6y9yZQ==} + '@types/node@20.19.21': + resolution: {integrity: sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==} - '@types/node@24.7.1': - resolution: {integrity: sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==} + '@types/node@24.7.2': + resolution: {integrity: sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==} '@types/pdfobject@2.2.5': resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==} @@ -1218,9 +1237,6 @@ packages: '@types/toastify-js@1.12.4': resolution: {integrity: sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==} - '@types/trusted-types@1.0.6': - resolution: {integrity: sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==} - '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -1230,63 +1246,63 @@ packages: '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} - '@typescript-eslint/eslint-plugin@8.45.0': - resolution: {integrity: sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==} + '@typescript-eslint/eslint-plugin@8.46.0': + resolution: {integrity: sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.45.0 + '@typescript-eslint/parser': ^8.46.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.45.0': - resolution: {integrity: sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==} + '@typescript-eslint/parser@8.46.0': + resolution: {integrity: sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.45.0': - resolution: {integrity: sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==} + '@typescript-eslint/project-service@8.46.0': + resolution: {integrity: sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.45.0': - resolution: {integrity: sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==} + '@typescript-eslint/scope-manager@8.46.0': + resolution: {integrity: sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.45.0': - resolution: {integrity: sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==} + '@typescript-eslint/tsconfig-utils@8.46.0': + resolution: {integrity: sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.45.0': - resolution: {integrity: sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==} + '@typescript-eslint/type-utils@8.46.0': + resolution: {integrity: sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.45.0': - resolution: {integrity: sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==} + '@typescript-eslint/types@8.46.0': + resolution: {integrity: sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.45.0': - resolution: {integrity: sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==} + '@typescript-eslint/typescript-estree@8.46.0': + resolution: {integrity: sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.45.0': - resolution: {integrity: sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==} + '@typescript-eslint/utils@8.46.0': + resolution: {integrity: sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.45.0': - resolution: {integrity: sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==} + '@typescript-eslint/visitor-keys@8.46.0': + resolution: {integrity: sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -1391,8 +1407,8 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 vue: ^3.2.25 - '@vitest/eslint-plugin@1.3.13': - resolution: {integrity: sha512-QfzXd1+lCY3dIqPHOZlagA2bJYoWC5yAU3adv8Gks0rHAL6FpyXKYBiyMCuU6mRrbKUMphGqwDQobinOvYgJig==} + '@vitest/eslint-plugin@1.3.16': + resolution: {integrity: sha512-EvXGiZpz3L1G/pmebcmMe61UzqgR8LFwmm+QGgQEHcrTCFkMgl+c0mj2jneo38/CkHhofbK3zc3xafV6/SpzNw==} peerDependencies: eslint: '>= 8.57.0' typescript: '>= 5.0.0' @@ -1453,8 +1469,8 @@ packages: '@vue/compiler-ssr@3.5.22': resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==} - '@vue/language-core@3.1.0': - resolution: {integrity: sha512-a7ns+X9vTbdmk7QLrvnZs8s4E1wwtxG/sELzr6F2j4pU+r/OoAv6jJGSz+5tVTU6e4+3rjepGhSP8jDmBBcb3w==} + '@vue/language-core@3.1.1': + resolution: {integrity: sha512-qjMY3Q+hUCjdH+jLrQapqgpsJ0rd/2mAY02lZoHG3VFJZZZKLjAlV+Oo9QmWIT4jh8+Rx8RUGUi++d7T9Wb6Mw==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -1645,8 +1661,8 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - asciinema-player@3.10.0: - resolution: {integrity: sha512-shoOK6F606nDKZxDVM7JuGSCAyWLePoGRFNlV+FqiP5Sqvyn0BlE7wlbjZyd2X4P1iRhv/HKfVNtnQIxmgphRA==} + asciinema-player@3.12.0: + resolution: {integrity: sha512-qKaqcN4gkssF5shAk0SOyREJfMAFmmek0cYUmx+qVDGTUKIEA2oU5mXCRFgszYAJqu2kyGlu20BYhr9mH7mmpQ==} assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} @@ -1664,8 +1680,8 @@ packages: engines: {node: '>= 4.5.0'} hasBin: true - axe-core@4.10.3: - resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} engines: {node: '>=4'} axobject-query@4.1.0: @@ -1681,8 +1697,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.10: - resolution: {integrity: sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==} + baseline-browser-mapping@2.8.16: + resolution: {integrity: sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==} hasBin: true big.js@5.2.2: @@ -1732,8 +1748,8 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - cacheable@2.0.3: - resolution: {integrity: sha512-nZF80J3d8RMrroMSYm1E9pBllVDXWPuECZgEZxH+vusCY4MAXAJVrY0jutcHSgh3xYX3G2EUNnmtWGZVVjWCXw==} + cacheable@2.1.0: + resolution: {integrity: sha512-zzL1BxdnqwD69JRT0dihnawAcLkBMwAH+hZSKjUzeBbPedVhk3qYPjRw9VOMYWwt5xRih5xd8S+3kEdGohZm/g==} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -1743,8 +1759,8 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - caniuse-lite@1.0.30001746: - resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==} + caniuse-lite@1.0.30001750: + resolution: {integrity: sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} @@ -1805,8 +1821,8 @@ packages: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - ci-info@4.3.0: - resolution: {integrity: sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==} + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} engines: {node: '>=8'} citeproc@2.4.63: @@ -1882,8 +1898,8 @@ packages: confbox@0.2.2: resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} - core-js-compat@3.45.1: - resolution: {integrity: sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA==} + core-js-compat@3.46.0: + resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} core-js@3.32.2: resolution: {integrity: sha512-pxXSw1mYZPDGvTQqEc5vgIb83jGQKFGYWY76z4a7weZXUolw3G+OvpZqSRcfYOoOVUQJYEPsWeQK8pKEnUtWxQ==} @@ -2194,6 +2210,9 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dompurify@3.1.7: + resolution: {integrity: sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==} + dompurify@3.2.7: resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} @@ -2209,8 +2228,8 @@ packages: easymde@2.20.0: resolution: {integrity: sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==} - electron-to-chromium@1.5.228: - resolution: {integrity: sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==} + electron-to-chromium@1.5.234: + resolution: {integrity: sha512-RXfEp2x+VRYn8jbKfQlRImzoJU01kyDvVPBmG39eU2iuRVhuS6vQNocB8J0/8GrIMLnPzgz4eW6WiRnJkTuNWg==} emoji-regex@10.5.0: resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==} @@ -2237,8 +2256,8 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - envinfo@7.15.0: - resolution: {integrity: sha512-chR+t7exF6y59kelhXw5I3849nTy7KIRO+ePdLMhCD+JRP/JvmkenDWP7QSFGlsHX+kxGxdDutOPrmj5j1HR6g==} + envinfo@7.17.0: + resolution: {integrity: sha512-GpfViocsFM7viwClFgxK26OtjMlKN67GCR5v6ASFkotxtpBWd9d+vNy+AH7F2E1TUkMDZ8P/dDPZX71/NG8xnQ==} engines: {node: '>=4'} hasBin: true @@ -2248,8 +2267,8 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - esbuild-loader@4.3.0: - resolution: {integrity: sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==} + esbuild-loader@4.4.0: + resolution: {integrity: sha512-4J+hXTpTtEdzUNLoY8ReqDNJx2NoldfiljRCiKbeYUuZmVaiJeDqFgyAzz8uOopaekwRoCcqBFyEroGQLFVZ1g==} peerDependencies: webpack: ^4.40.0 || ^5.0.0 @@ -2483,8 +2502,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.36.0: - resolution: {integrity: sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==} + eslint@9.37.0: + resolution: {integrity: sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -2643,8 +2662,8 @@ packages: resolution: {integrity: sha512-YCmOj+4YAeEB5Dd9jfp6ETdejMet4zSxXjNkgaa4npBEKRI9uDOGB5MmAdAgi2OoFGAKshYhCbmLq2DS03CgVA==} engines: {node: '>=18.0.0'} - get-tsconfig@4.10.1: - resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + get-tsconfig@4.12.0: + resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -2981,8 +3000,8 @@ packages: just-extend@5.1.1: resolution: {integrity: sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==} - katex@0.16.22: - resolution: {integrity: sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==} + katex@0.16.23: + resolution: {integrity: sha512-7VlC1hsEEolL9xNO05v9VjrvWZePkCVBJqj8ruICxYjZfHaHbaU53AlP+PODyFIXEnaEIEWi3wJy7FPZ95JAVg==} hasBin: true keyv@4.5.4: @@ -3039,8 +3058,8 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} - loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} loader-utils@2.0.4: @@ -3116,8 +3135,13 @@ packages: resolution: {integrity: sha512-xaSxkaU7wY/0852zGApM8LdlIfGCW8ETZ0Rr62IQtAnUMlMuifsg09vWJcNYeL4f0anvr8Vo4ZQar8jGpV0btQ==} engines: {node: '>=20'} - marked@16.3.0: - resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==} + marked@14.0.0: + resolution: {integrity: sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==} + engines: {node: '>= 18'} + hasBin: true + + marked@16.4.0: + resolution: {integrity: sha512-CTPAcRBq57cn3R8n3hwc2REddc28hjR7RzDXQ+lXLmMJYqn20BaI2cGw6QjgZGIgVfp2Wdfw4aMzgNteQ6qJgQ==} engines: {node: '>= 20'} hasBin: true @@ -3270,14 +3294,14 @@ packages: mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} - monaco-editor-webpack-plugin@7.1.0: - resolution: {integrity: sha512-ZjnGINHN963JQkFqjjcBtn1XBtUATDZBMgNQhDQwd78w2ukRhFXAPNgWuacaQiDZsUr4h1rWv5Mv6eriKuOSzA==} + monaco-editor-webpack-plugin@7.1.1: + resolution: {integrity: sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==} peerDependencies: monaco-editor: '>= 0.31.0' webpack: ^4.5.0 || 5.x - monaco-editor@0.53.0: - resolution: {integrity: sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==} + monaco-editor@0.54.0: + resolution: {integrity: sha512-hx45SEUoLatgWxHKCmlLJH81xBo0uXP4sRkESUpmDQevfi+e7K1VuiSprK6UpQ8u4zOcKNiH0pMvHvlMWA/4cw==} moo@0.5.2: resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} @@ -3299,8 +3323,8 @@ packages: nanopop@2.3.0: resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==} - napi-postinstall@0.3.3: - resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==} + napi-postinstall@0.3.4: + resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} hasBin: true @@ -3328,8 +3352,8 @@ packages: encoding: optional: true - node-releases@2.0.21: - resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + node-releases@2.0.23: + resolution: {integrity: sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==} nolyfill@1.0.44: resolution: {integrity: sha512-PoggwVLiJUn0MnodpftsiC7EuknW5+6v62ntTOQ6T6l7g2r6aoaOwgk0tQW2BxGLYw9bF298LL8jDFTmEFuzlA==} @@ -3388,8 +3412,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - package-manager-detector@1.3.0: - resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==} + package-manager-detector@1.4.0: + resolution: {integrity: sha512-rRZ+pR1Usc+ND9M2NkmCvE/LYJS+8ORVV9X0KuNSY/gFsp7RBHJM/ADh9LYq4Vvfq6QkKrW6/weuh8SMEtN5gw==} parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -3477,13 +3501,13 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} - playwright-core@1.55.1: - resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==} + playwright-core@1.56.0: + resolution: {integrity: sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==} engines: {node: '>=18'} hasBin: true - playwright@1.55.1: - resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==} + playwright@1.56.0: + resolution: {integrity: sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==} engines: {node: '>=18'} hasBin: true @@ -3633,6 +3657,10 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + qified@0.5.0: + resolution: {integrity: sha512-Zj6Q/Vc/SQ+Fzc87N90jJUzBzxD7MVQ2ZvGyMmYtnl2u1a07CejAhvtk4ZwASos+SiHKCAIylyGHJKIek75QBw==} + engines: {node: '>=20'} + quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} @@ -3704,8 +3732,8 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup@4.52.3: - resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==} + rollup@4.52.4: + resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -3728,8 +3756,8 @@ packages: sax@1.4.1: resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} - schema-utils@4.3.2: - resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} scslre@0.3.0: @@ -3797,6 +3825,12 @@ packages: solid-js@1.9.9: resolution: {integrity: sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA==} + solid-transition-group@0.2.3: + resolution: {integrity: sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==} + engines: {node: '>=18.0.0', pnpm: '>=8.6.0'} + peerDependencies: + solid-js: ^1.6.12 + sortablejs@1.15.6: resolution: {integrity: sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==} @@ -3920,8 +3954,8 @@ packages: peerDependencies: stylelint: '>=16' - stylelint@16.24.0: - resolution: {integrity: sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ==} + stylelint@16.25.0: + resolution: {integrity: sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==} engines: {node: '>=18.12.0'} hasBin: true @@ -3970,8 +4004,8 @@ packages: svgson@5.3.1: resolution: {integrity: sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==} - swagger-ui-dist@5.29.1: - resolution: {integrity: sha512-qyjpz0qgcomRr41a5Aye42o69TKwCeHM9F8htLGVeUMKekNS6qAqz9oS7CtSvgGJSppSNAYAIh7vrfrSdHj9zw==} + swagger-ui-dist@5.29.4: + resolution: {integrity: sha512-gJFDz/gyLOCQtWwAgqs6Rk78z9ONnqTnlW11gimG9nLap8drKa3AJBKpzIQMIjl5PD2Ix+Tn+mc/tfoT2tgsng==} sync-fetch@0.4.5: resolution: {integrity: sha512-esiWJ7ixSKGpd9DJPBTC4ckChqdOjIwJfYhVHkcQ2Gnm41323p1TRmEI+esTQ9ppD+b5opps2OTEGTCGX5kF+g==} @@ -3990,8 +4024,8 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tapable@2.2.3: - resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==} + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} terser-webpack-plugin@5.3.14: @@ -4100,8 +4134,8 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - typescript-eslint@8.45.0: - resolution: {integrity: sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==} + typescript-eslint@8.46.0: + resolution: {integrity: sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -4139,8 +4173,8 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - updates@16.7.4: - resolution: {integrity: sha512-w8nMoQRFKL7iVTUBUF9pP9lxqe/vqQfxljKcCmY0pKwofXqGEUr3OUQznsGa62V6pvFvg097pm4jT4eDdPq6ow==} + updates@16.8.0: + resolution: {integrity: sha512-iKLehaYwcz9sdL/PIYX+V0quBl0hGXXqwLGPy/jlLOrXdFdz15QtE7kxtJATJhH2oPOi7+Y3VcL2rY90IU4L4g==} engines: {node: '>=20'} hasBin: true @@ -4165,8 +4199,8 @@ packages: vite-string-plugin@1.4.6: resolution: {integrity: sha512-Csjtny8/uVIynzlaRRj4RpHrPAakNwlH9jw6kgQ8tQhc2f0zzA6bCbAgWD0y84EgB8aLNrz7pZFUqSt3LOtk+w==} - vite@7.1.7: - resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==} + vite@7.1.9: + resolution: {integrity: sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -4283,8 +4317,8 @@ packages: vue: optional: true - vue-tsc@3.1.0: - resolution: {integrity: sha512-fbMynMG7kXSnqZTRBSCh9ROYaVpXfCZbEO0gY3lqOjLbp361uuS88n6BDajiUriDIF+SGLWoinjvf6stS2J3Gg==} + vue-tsc@3.1.1: + resolution: {integrity: sha512-fyixKxFniOVgn+L/4+g8zCG6dflLLt01Agz9jl3TO45Bgk87NZJRmJVPsiK+ouq3LB91jJCbOV+pDkzYTxbI7A==} hasBin: true peerDependencies: typescript: '>=5.0.0' @@ -4329,8 +4363,8 @@ packages: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} - webpack@5.102.0: - resolution: {integrity: sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==} + webpack@5.102.1: + resolution: {integrity: sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -4415,10 +4449,10 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.3.0 + package-manager-detector: 1.4.0 tinyexec: 1.0.1 - '@antfu/utils@9.2.1': {} + '@antfu/utils@9.3.0': {} '@babel/code-frame@7.27.1': dependencies: @@ -4445,17 +4479,19 @@ snapshots: '@cacheable/memoize@2.0.3': dependencies: - '@cacheable/utils': 2.0.3 + '@cacheable/utils': 2.1.0 '@cacheable/memory@2.0.3': dependencies: '@cacheable/memoize': 2.0.3 - '@cacheable/utils': 2.0.3 - '@keyv/bigmap': 1.0.2 + '@cacheable/utils': 2.1.0 + '@keyv/bigmap': 1.0.3 hookified: 1.12.1 keyv: 5.5.3 - '@cacheable/utils@2.0.3': {} + '@cacheable/utils@2.1.0': + dependencies: + keyv: 5.5.3 '@chevrotain/cst-dts-gen@11.0.3': dependencies: @@ -4645,24 +4681,24 @@ snapshots: '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.36.0(jiti@2.6.1))': + '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.37.0(jiti@2.6.1))': dependencies: escape-string-regexp: 4.0.0 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) ignore: 5.3.2 - '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0(jiti@2.6.1))': dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/compat@1.4.0(eslint@9.36.0(jiti@2.6.1))': + '@eslint/compat@1.4.0(eslint@9.37.0(jiti@2.6.1))': dependencies: '@eslint/core': 0.16.0 optionalDependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) '@eslint/config-array@0.21.0': dependencies: @@ -4672,7 +4708,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.1': {} + '@eslint/config-helpers@0.4.0': + dependencies: + '@eslint/core': 0.16.0 '@eslint/core@0.15.2': dependencies: @@ -4696,7 +4734,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.36.0': {} + '@eslint/js@9.37.0': {} '@eslint/object-schema@2.1.6': {} @@ -4705,6 +4743,11 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 + '@eslint/plugin-kit@0.4.0': + dependencies: + '@eslint/core': 0.16.0 + levn: 0.4.1 + '@github/browserslist-config@1.0.0': {} '@github/combobox-nav@2.3.1': {} @@ -4736,7 +4779,7 @@ snapshots: '@iconify/utils@3.0.2': dependencies: '@antfu/install-pkg': 1.1.0 - '@antfu/utils': 9.2.1 + '@antfu/utils': 9.3.0 '@iconify/types': 2.0.0 debug: 4.4.3 globals: 15.15.0 @@ -4780,7 +4823,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@keyv/bigmap@1.0.2': + '@keyv/bigmap@1.0.3': dependencies: hookified: 1.12.1 @@ -4794,7 +4837,7 @@ snapshots: dependencies: '@mcaptcha/core-glue': 0.1.0-alpha-5 - '@mermaid-js/parser@0.6.2': + '@mermaid-js/parser@0.6.3': dependencies: langium: 3.3.1 @@ -4874,13 +4917,13 @@ snapshots: '@pkgr/core@0.2.9': {} - '@playwright/test@1.55.1': + '@playwright/test@1.56.0': dependencies: - playwright: 1.55.1 + playwright: 1.56.0 '@popperjs/core@2.11.8': {} - '@primer/octicons@19.18.0': + '@primer/octicons@19.19.0': dependencies: object-assign: 4.1.1 @@ -4888,70 +4931,70 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.29': {} - '@rollup/rollup-android-arm-eabi@4.52.3': + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true - '@rollup/rollup-android-arm64@4.52.3': + '@rollup/rollup-android-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-arm64@4.52.3': + '@rollup/rollup-darwin-arm64@4.52.4': optional: true - '@rollup/rollup-darwin-x64@4.52.3': + '@rollup/rollup-darwin-x64@4.52.4': optional: true - '@rollup/rollup-freebsd-arm64@4.52.3': + '@rollup/rollup-freebsd-arm64@4.52.4': optional: true - '@rollup/rollup-freebsd-x64@4.52.3': + '@rollup/rollup-freebsd-x64@4.52.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.52.3': + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.52.3': + '@rollup/rollup-linux-arm-musleabihf@4.52.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.52.3': + '@rollup/rollup-linux-arm64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.52.3': + '@rollup/rollup-linux-arm64-musl@4.52.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.52.3': + '@rollup/rollup-linux-loong64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.52.3': + '@rollup/rollup-linux-ppc64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.52.3': + '@rollup/rollup-linux-riscv64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.52.3': + '@rollup/rollup-linux-riscv64-musl@4.52.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.52.3': + '@rollup/rollup-linux-s390x-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.52.3': + '@rollup/rollup-linux-x64-gnu@4.52.4': optional: true - '@rollup/rollup-linux-x64-musl@4.52.3': + '@rollup/rollup-linux-x64-musl@4.52.4': optional: true - '@rollup/rollup-openharmony-arm64@4.52.3': + '@rollup/rollup-openharmony-arm64@4.52.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.52.3': + '@rollup/rollup-win32-arm64-msvc@4.52.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.52.3': + '@rollup/rollup-win32-ia32-msvc@4.52.4': optional: true - '@rollup/rollup-win32-x64-gnu@4.52.3': + '@rollup/rollup-win32-x64-gnu@4.52.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.52.3': + '@rollup/rollup-win32-x64-msvc@4.52.4': optional: true '@rtsao/scc@1.1.0': {} @@ -4968,17 +5011,30 @@ snapshots: core-js: 3.32.2 nanopop: 2.3.0 - '@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1))': + '@solid-primitives/refs@1.1.2(solid-js@1.9.9)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - '@typescript-eslint/types': 8.45.0 - eslint: 9.36.0(jiti@2.6.1) + '@solid-primitives/utils': 6.3.2(solid-js@1.9.9) + solid-js: 1.9.9 + + '@solid-primitives/transition-group@1.1.2(solid-js@1.9.9)': + dependencies: + solid-js: 1.9.9 + + '@solid-primitives/utils@6.3.2(solid-js@1.9.9)': + dependencies: + solid-js: 1.9.9 + + '@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1))': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + '@typescript-eslint/types': 8.46.0 + eslint: 9.37.0(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 picomatch: 4.0.3 - '@stylistic/stylelint-plugin@4.0.0(stylelint@16.24.0(typescript@5.9.3))': + '@stylistic/stylelint-plugin@4.0.0(stylelint@16.25.0(typescript@5.9.3))': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -4987,11 +5043,11 @@ snapshots: postcss-selector-parser: 7.1.0 postcss-value-parser: 4.2.0 style-search: 0.1.0 - stylelint: 16.24.0(typescript@5.9.3) + stylelint: 16.25.0(typescript@5.9.3) '@swc/helpers@0.2.14': {} - '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.102.0)': + '@techknowlogick/license-checker-webpack-plugin@0.3.0(webpack@5.102.1)': dependencies: glob: 7.2.3 lodash: 4.17.21 @@ -5000,7 +5056,7 @@ snapshots: spdx-expression-validate: 2.0.0 spdx-satisfies: 5.0.1 superstruct: 0.10.13 - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) webpack-sources: 1.4.3 wrap-ansi: 6.2.0 @@ -5174,11 +5230,11 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@20.19.20': + '@types/node@20.19.21': dependencies: undici-types: 6.21.0 - '@types/node@24.7.1': + '@types/node@24.7.2': dependencies: undici-types: 7.14.0 @@ -5200,8 +5256,6 @@ snapshots: '@types/toastify-js@1.12.4': {} - '@types/trusted-types@1.0.6': {} - '@types/trusted-types@2.0.7': optional: true @@ -5209,15 +5263,15 @@ snapshots: '@types/whatwg-mimetype@3.0.2': {} - '@typescript-eslint/eslint-plugin@8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/type-utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.45.0 - eslint: 9.36.0(jiti@2.6.1) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 + eslint: 9.37.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -5226,80 +5280,80 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.46.0 debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.45.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.45.0': + '@typescript-eslint/scope-manager@8.46.0': dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 - '@typescript-eslint/tsconfig-utils@8.45.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.46.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.45.0': {} + '@typescript-eslint/types@8.46.0': {} - '@typescript-eslint/typescript-estree@8.45.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.46.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.45.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.45.0(typescript@5.9.3) - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/visitor-keys': 8.45.0 + '@typescript-eslint/project-service': 8.46.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.46.0(typescript@5.9.3) + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/visitor-keys': 8.46.0 debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 + semver: 7.7.3 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/types': 8.45.0 - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/types': 8.46.0 + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.45.0': + '@typescript-eslint/visitor-keys@8.46.0': dependencies: - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/types': 8.46.0 eslint-visitor-keys: 4.2.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -5361,20 +5415,20 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.1(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.29 - vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue: 3.5.22(typescript@5.9.3) - '@vitest/eslint-plugin@1.3.13(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.3.16(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: - '@typescript-eslint/scope-manager': 8.45.0 - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) + '@typescript-eslint/scope-manager': 8.46.0 + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) optionalDependencies: typescript: 5.9.3 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -5386,13 +5440,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -5462,7 +5516,7 @@ snapshots: '@vue/compiler-dom': 3.5.22 '@vue/shared': 3.5.22 - '@vue/language-core@3.1.0(typescript@5.9.3)': + '@vue/language-core@3.1.1(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.23 '@vue/compiler-dom': 3.5.22 @@ -5574,20 +5628,20 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': + '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.102.0(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.102.0) + webpack: 5.102.1(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.1) - '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': + '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.102.0(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.102.0) + webpack: 5.102.1(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.1) - '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.0)': + '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: - webpack: 5.102.0(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack@5.102.0) + webpack: 5.102.1(webpack-cli@6.0.1) + webpack-cli: 6.0.1(webpack@5.102.1) '@xtuc/ieee754@1.2.0': {} @@ -5603,9 +5657,9 @@ snapshots: acorn@8.15.0: {} - add-asset-webpack-plugin@3.1.1(webpack@5.102.0): + add-asset-webpack-plugin@3.1.1(webpack@5.102.1): optionalDependencies: - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: @@ -5661,10 +5715,11 @@ snapshots: array-union@2.1.0: {} - asciinema-player@3.10.0: + asciinema-player@3.12.0: dependencies: '@babel/runtime': 7.28.4 solid-js: 1.9.9 + solid-transition-group: 0.2.3(solid-js@1.9.9) assertion-error@2.0.1: {} @@ -5674,7 +5729,7 @@ snapshots: atob@2.1.2: {} - axe-core@4.10.3: {} + axe-core@4.11.0: {} axobject-query@4.1.0: {} @@ -5684,7 +5739,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.8.10: {} + baseline-browser-mapping@2.8.16: {} big.js@5.2.2: {} @@ -5707,10 +5762,10 @@ snapshots: browserslist@4.26.3: dependencies: - baseline-browser-mapping: 2.8.10 - caniuse-lite: 1.0.30001746 - electron-to-chromium: 1.5.228 - node-releases: 2.0.21 + baseline-browser-mapping: 2.8.16 + caniuse-lite: 1.0.30001750 + electron-to-chromium: 1.5.234 + node-releases: 2.0.23 update-browserslist-db: 1.1.3(browserslist@4.26.3) buffer-from@1.1.2: {} @@ -5728,19 +5783,20 @@ snapshots: cac@6.7.14: {} - cacheable@2.0.3: + cacheable@2.1.0: dependencies: '@cacheable/memoize': 2.0.3 '@cacheable/memory': 2.0.3 - '@cacheable/utils': 2.0.3 + '@cacheable/utils': 2.1.0 hookified: 1.12.1 keyv: 5.5.3 + qified: 0.5.0 callsites@3.1.0: {} camelcase-css@2.0.1: {} - caniuse-lite@1.0.30001746: {} + caniuse-lite@1.0.30001750: {} chai@5.3.3: dependencies: @@ -5810,7 +5866,7 @@ snapshots: chrome-trace-event@1.0.4: {} - ci-info@4.3.0: {} + ci-info@4.3.1: {} citeproc@2.4.63: {} @@ -5864,7 +5920,7 @@ snapshots: confbox@0.2.2: {} - core-js-compat@3.45.1: + core-js-compat@3.46.0: dependencies: browserslist: 4.26.3 @@ -5897,7 +5953,7 @@ snapshots: css-functions-list@3.2.3: {} - css-loader@7.1.2(webpack@5.102.0): + css-loader@7.1.2(webpack@5.102.1): dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 @@ -5906,9 +5962,9 @@ snapshots: postcss-modules-scope: 3.2.1(postcss@8.5.6) postcss-modules-values: 4.0.0(postcss@8.5.6) postcss-value-parser: 4.2.0 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) css-select@5.2.2: dependencies: @@ -6193,6 +6249,8 @@ snapshots: dependencies: domelementtype: 2.3.0 + dompurify@3.1.7: {} + dompurify@3.2.7: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -6218,7 +6276,7 @@ snapshots: codemirror-spell-checker: 1.1.2 marked: 4.3.0 - electron-to-chromium@1.5.228: {} + electron-to-chromium@1.5.234: {} emoji-regex@10.5.0: {} @@ -6231,13 +6289,13 @@ snapshots: enhanced-resolve@5.18.3: dependencies: graceful-fs: 4.2.11 - tapable: 2.2.3 + tapable: 2.3.0 entities@4.5.0: {} env-paths@2.2.1: {} - envinfo@7.15.0: {} + envinfo@7.17.0: {} error-ex@1.3.4: dependencies: @@ -6245,12 +6303,12 @@ snapshots: es-module-lexer@1.7.0: {} - esbuild-loader@4.3.0(webpack@5.102.0): + esbuild-loader@4.4.0(webpack@5.102.1): dependencies: esbuild: 0.25.10 - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 loader-utils: 2.0.4 - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) webpack-sources: 1.4.3 esbuild@0.25.10: @@ -6288,18 +6346,18 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.6.5(eslint@9.36.0(jiti@2.6.1)): + eslint-compat-utils@0.6.5(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) - semver: 7.7.2 + eslint: 9.37.0(jiti@2.6.1) + semver: 7.7.3 - eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-import-context@0.1.9(unrs-resolver@1.11.1): dependencies: - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 stable-hash-x: 0.2.0 optionalDependencies: unrs-resolver: 1.11.1 @@ -6312,111 +6370,111 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1)): dependencies: debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - get-tsconfig: 4.10.1 + get-tsconfig: 4.12.0 is-bun-module: 2.0.0 stable-hash-x: 0.2.0 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.36.0(jiti@2.6.1)) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)))(eslint-plugin-import@2.32.0)(eslint@9.37.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-array-func@5.1.0(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-array-func@5.1.0(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) - eslint-plugin-escompat@3.11.4(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-escompat@3.11.4(eslint@9.37.0(jiti@2.6.1)): dependencies: browserslist: 4.26.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) - eslint-plugin-eslint-comments@3.2.0(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-eslint-comments@3.2.0(eslint@9.37.0(jiti@2.6.1)): dependencies: escape-string-regexp: 1.0.5 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) ignore: 5.3.2 - eslint-plugin-filenames@1.3.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-filenames@1.3.2(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 lodash.upperfirst: 4.3.1 - eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)): dependencies: - '@eslint/compat': 1.4.0(eslint@9.36.0(jiti@2.6.1)) + '@eslint/compat': 1.4.0(eslint@9.37.0(jiti@2.6.1)) '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.36.0 + '@eslint/js': 9.37.0 '@github/browserslist-config': 1.0.0 - '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) aria-query: 5.3.2 - eslint: 9.36.0(jiti@2.6.1) - eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-escompat: 3.11.4(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-eslint-comments: 3.2.0(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-filenames: 1.3.2(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-i18n-text: 1.0.1(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.36.0(jiti@2.6.1)) + eslint: 9.37.0(jiti@2.6.1) + eslint-config-prettier: 10.1.8(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-escompat: 3.11.4(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-eslint-comments: 3.2.0(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-filenames: 1.3.2(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-i18n-text: 1.0.1(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-no-only-tests: 3.3.0 - eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2) + eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2) eslint-rule-documentation: 1.0.23 globals: 16.4.0 jsx-ast-utils: 3.3.5 prettier: 3.6.2 svg-element-attributes: 1.3.1 typescript: 5.9.3 - typescript-eslint: 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - '@types/eslint' - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-i18n-text@1.0.1(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-i18n-text@1.0.1(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.37.0(jiti@2.6.1)): dependencies: - '@typescript-eslint/types': 8.45.0 + '@typescript-eslint/types': 8.46.0 comment-parser: 1.4.1 debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.0.3 - semver: 7.7.2 + semver: 7.7.3 stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: '@nolyfill/array-includes@1.0.44' @@ -6425,9 +6483,9 @@ snapshots: array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44' debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.36.0(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.37.0(jiti@2.6.1)) hasown: '@nolyfill/hasown@1.0.44' is-core-module: '@nolyfill/is-core-module@1.0.39' is-glob: 4.0.3 @@ -6439,23 +6497,23 @@ snapshots: string.prototype.trimend: '@nolyfill/string.prototype.trimend@1.0.44' tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.37.0(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: '@nolyfill/array-includes@1.0.44' array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44' ast-types-flow: 0.0.8 - axe-core: 4.10.3 + axe-core: 4.11.0 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) hasown: '@nolyfill/hasown@1.0.44' jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -6466,46 +6524,46 @@ snapshots: eslint-plugin-no-only-tests@3.3.0: {} - eslint-plugin-no-use-extend-native@0.7.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-no-use-extend-native@0.7.2(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) is-get-set-prop: 2.0.0 is-js-type: 3.0.0 is-obj-prop: 2.0.0 is-proto-prop: 3.0.1 - eslint-plugin-playwright@2.2.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-playwright@2.2.2(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) globals: 13.24.0 - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.36.0(jiti@2.6.1)))(eslint@9.36.0(jiti@2.6.1))(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.37.0(jiti@2.6.1)))(eslint@9.37.0(jiti@2.6.1))(prettier@3.6.2): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@9.36.0(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@9.37.0(jiti@2.6.1)) - eslint-plugin-regexp@2.10.0(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-regexp@2.10.0(eslint@9.37.0(jiti@2.6.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 comment-parser: 1.4.1 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) jsdoc-type-pratt-parser: 4.8.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-sonarjs@3.0.5(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-sonarjs@3.0.5(eslint@9.37.0(jiti@2.6.1)): dependencies: '@eslint-community/regexpp': 4.12.1 builtin-modules: 3.3.0 bytes: 3.1.2 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) functional-red-black-tree: 1.0.1 jsx-ast-utils-x: 0.1.0 lodash.merge: 4.6.2 @@ -6514,16 +6572,16 @@ snapshots: semver: 7.7.2 typescript: 5.9.3 - eslint-plugin-unicorn@61.0.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-unicorn@61.0.2(eslint@9.37.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.27.1 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint/plugin-kit': 0.3.5 change-case: 5.4.4 - ci-info: 4.3.0 + ci-info: 4.3.1 clean-regexp: 1.0.0 - core-js-compat: 3.45.1 - eslint: 9.36.0(jiti@2.6.1) + core-js-compat: 3.46.0 + eslint: 9.37.0(jiti@2.6.1) esquery: 1.6.0 find-up-simple: 1.0.1 globals: 16.4.0 @@ -6533,41 +6591,41 @@ snapshots: pluralize: 8.0.0 regexp-tree: 0.1.27 regjsparser: 0.12.0 - semver: 7.7.2 + semver: 7.7.3 strip-indent: 4.1.0 - eslint-plugin-vue-scoped-css@2.12.0(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))): + eslint-plugin-vue-scoped-css@2.12.0(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - eslint: 9.36.0(jiti@2.6.1) - eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + eslint: 9.37.0(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@9.37.0(jiti@2.6.1)) lodash: 4.17.21 postcss: 8.5.6 postcss-safe-parser: 6.0.0(postcss@8.5.6) postcss-scss: 4.0.9(postcss@8.5.6) postcss-selector-parser: 7.1.0 postcss-styl: 0.12.3 - vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1)) + vue-eslint-parser: 10.2.0(eslint@9.37.0(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.36.0(jiti@2.6.1)))(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1))): + eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@5.4.0(eslint@9.37.0(jiti@2.6.1)))(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) - eslint: 9.36.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) + eslint: 9.37.0(jiti@2.6.1) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 - semver: 7.7.2 - vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.1)) + semver: 7.7.3 + vue-eslint-parser: 10.2.0(eslint@9.37.0(jiti@2.6.1)) xml-name-validator: 4.0.0 optionalDependencies: - '@stylistic/eslint-plugin': 5.4.0(eslint@9.36.0(jiti@2.6.1)) - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) + '@stylistic/eslint-plugin': 5.4.0(eslint@9.37.0(jiti@2.6.1)) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-wc@3.0.2(eslint@9.36.0(jiti@2.6.1)): + eslint-plugin-wc@3.0.2(eslint@9.37.0(jiti@2.6.1)): dependencies: - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) is-valid-element-name: 1.0.0 js-levenshtein-esm: 2.0.0 @@ -6587,16 +6645,16 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.36.0(jiti@2.6.1): + eslint@9.37.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.1 - '@eslint/core': 0.15.2 + '@eslint/config-helpers': 0.4.0 + '@eslint/core': 0.16.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.36.0 - '@eslint/plugin-kit': 0.3.5 + '@eslint/js': 9.37.0 + '@eslint/plugin-kit': 0.4.0 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -6730,7 +6788,7 @@ snapshots: flat-cache@6.1.17: dependencies: - cacheable: 2.0.3 + cacheable: 2.1.0 flatted: 3.3.3 hookified: 1.12.1 @@ -6757,7 +6815,7 @@ snapshots: get-set-props@0.2.0: {} - get-tsconfig@4.10.1: + get-tsconfig@4.12.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -6839,7 +6897,7 @@ snapshots: happy-dom@20.0.0: dependencies: - '@types/node': 20.19.20 + '@types/node': 20.19.21 '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 @@ -6928,7 +6986,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.7.3 is-decimal@2.0.1: {} @@ -6991,7 +7049,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.7.1 + '@types/node': 24.7.2 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -7050,7 +7108,7 @@ snapshots: just-extend@5.1.1: {} - katex@0.16.22: + katex@0.16.23: dependencies: commander: 8.3.0 @@ -7105,7 +7163,7 @@ snapshots: dependencies: uc.micro: 2.1.0 - loader-runner@4.3.0: {} + loader-runner@4.3.1: {} loader-utils@2.0.4: dependencies: @@ -7195,7 +7253,9 @@ snapshots: transitivePeerDependencies: - supports-color - marked@16.3.0: {} + marked@14.0.0: {} + + marked@16.4.0: {} marked@4.3.0: {} @@ -7224,7 +7284,7 @@ snapshots: dependencies: '@braintree/sanitize-url': 7.1.1 '@iconify/utils': 3.0.2 - '@mermaid-js/parser': 0.6.2 + '@mermaid-js/parser': 0.6.3 '@types/d3': 7.4.3 cytoscape: 3.33.1 cytoscape-cose-bilkent: 4.1.0(cytoscape@3.33.1) @@ -7234,10 +7294,10 @@ snapshots: dagre-d3-es: 7.0.11 dayjs: 1.11.18 dompurify: 3.2.7 - katex: 0.16.22 + katex: 0.16.23 khroma: 2.1.0 lodash-es: 4.17.21 - marked: 16.3.0 + marked: 16.4.0 roughjs: 4.6.6 stylis: 4.3.6 ts-dedent: 2.2.0 @@ -7304,7 +7364,7 @@ snapshots: dependencies: '@types/katex': 0.16.7 devlop: 1.1.0 - katex: 0.16.22 + katex: 0.16.23 micromark-factory-space: 2.0.1 micromark-util-character: 2.1.1 micromark-util-symbol: 2.0.1 @@ -7428,11 +7488,11 @@ snapshots: dependencies: mime-db: 1.52.0 - mini-css-extract-plugin@2.9.4(webpack@5.102.0): + mini-css-extract-plugin@2.9.4(webpack@5.102.1): dependencies: - schema-utils: 4.3.2 - tapable: 2.2.3 - webpack: 5.102.0(webpack-cli@6.0.1) + schema-utils: 4.3.3 + tapable: 2.3.0 + webpack: 5.102.1(webpack-cli@6.0.1) minimatch@10.0.3: dependencies: @@ -7457,15 +7517,16 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.1 - monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.53.0)(webpack@5.102.0): + monaco-editor-webpack-plugin@7.1.1(monaco-editor@0.54.0)(webpack@5.102.1): dependencies: loader-utils: 2.0.4 - monaco-editor: 0.53.0 - webpack: 5.102.0(webpack-cli@6.0.1) + monaco-editor: 0.54.0 + webpack: 5.102.1(webpack-cli@6.0.1) - monaco-editor@0.53.0: + monaco-editor@0.54.0: dependencies: - '@types/trusted-types': 1.0.6 + dompurify: 3.1.7 + marked: 14.0.0 moo@0.5.2: {} @@ -7483,7 +7544,7 @@ snapshots: nanopop@2.3.0: {} - napi-postinstall@0.3.3: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -7497,7 +7558,7 @@ snapshots: dependencies: whatwg-url: 5.0.0 - node-releases@2.0.21: {} + node-releases@2.0.23: {} nolyfill@1.0.44: {} @@ -7552,7 +7613,7 @@ snapshots: package-json-from-dist@1.0.1: {} - package-manager-detector@1.3.0: {} + package-manager-detector@1.4.0: {} parent-module@1.0.1: dependencies: @@ -7633,11 +7694,11 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 - playwright-core@1.55.1: {} + playwright-core@1.56.0: {} - playwright@1.55.1: + playwright@1.56.0: dependencies: - playwright-core: 1.55.1 + playwright-core: 1.56.0 optionalDependencies: fsevents: 2.3.2 @@ -7676,14 +7737,14 @@ snapshots: optionalDependencies: postcss: 8.5.6 - postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.0): + postcss-loader@8.2.0(postcss@8.5.6)(typescript@5.9.3)(webpack@5.102.1): dependencies: cosmiconfig: 9.0.0(typescript@5.9.3) jiti: 2.6.1 postcss: 8.5.6 - semver: 7.7.2 + semver: 7.7.3 optionalDependencies: - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) transitivePeerDependencies: - typescript @@ -7769,6 +7830,10 @@ snapshots: punycode@2.3.1: {} + qified@0.5.0: + dependencies: + hookified: 1.12.1 + quansync@0.2.11: {} queue-microtask@1.2.3: {} @@ -7828,32 +7893,32 @@ snapshots: robust-predicates@3.0.2: {} - rollup@4.52.3: + rollup@4.52.4: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.52.3 - '@rollup/rollup-android-arm64': 4.52.3 - '@rollup/rollup-darwin-arm64': 4.52.3 - '@rollup/rollup-darwin-x64': 4.52.3 - '@rollup/rollup-freebsd-arm64': 4.52.3 - '@rollup/rollup-freebsd-x64': 4.52.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.3 - '@rollup/rollup-linux-arm-musleabihf': 4.52.3 - '@rollup/rollup-linux-arm64-gnu': 4.52.3 - '@rollup/rollup-linux-arm64-musl': 4.52.3 - '@rollup/rollup-linux-loong64-gnu': 4.52.3 - '@rollup/rollup-linux-ppc64-gnu': 4.52.3 - '@rollup/rollup-linux-riscv64-gnu': 4.52.3 - '@rollup/rollup-linux-riscv64-musl': 4.52.3 - '@rollup/rollup-linux-s390x-gnu': 4.52.3 - '@rollup/rollup-linux-x64-gnu': 4.52.3 - '@rollup/rollup-linux-x64-musl': 4.52.3 - '@rollup/rollup-openharmony-arm64': 4.52.3 - '@rollup/rollup-win32-arm64-msvc': 4.52.3 - '@rollup/rollup-win32-ia32-msvc': 4.52.3 - '@rollup/rollup-win32-x64-gnu': 4.52.3 - '@rollup/rollup-win32-x64-msvc': 4.52.3 + '@rollup/rollup-android-arm-eabi': 4.52.4 + '@rollup/rollup-android-arm64': 4.52.4 + '@rollup/rollup-darwin-arm64': 4.52.4 + '@rollup/rollup-darwin-x64': 4.52.4 + '@rollup/rollup-freebsd-arm64': 4.52.4 + '@rollup/rollup-freebsd-x64': 4.52.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.4 + '@rollup/rollup-linux-arm-musleabihf': 4.52.4 + '@rollup/rollup-linux-arm64-gnu': 4.52.4 + '@rollup/rollup-linux-arm64-musl': 4.52.4 + '@rollup/rollup-linux-loong64-gnu': 4.52.4 + '@rollup/rollup-linux-ppc64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-gnu': 4.52.4 + '@rollup/rollup-linux-riscv64-musl': 4.52.4 + '@rollup/rollup-linux-s390x-gnu': 4.52.4 + '@rollup/rollup-linux-x64-gnu': 4.52.4 + '@rollup/rollup-linux-x64-musl': 4.52.4 + '@rollup/rollup-openharmony-arm64': 4.52.4 + '@rollup/rollup-win32-arm64-msvc': 4.52.4 + '@rollup/rollup-win32-ia32-msvc': 4.52.4 + '@rollup/rollup-win32-x64-gnu': 4.52.4 + '@rollup/rollup-win32-x64-msvc': 4.52.4 fsevents: 2.3.3 roughjs@4.6.6: @@ -7880,7 +7945,7 @@ snapshots: sax@1.4.1: {} - schema-utils@4.3.2: + schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 ajv: 8.17.1 @@ -7939,6 +8004,12 @@ snapshots: seroval: 1.3.2 seroval-plugins: 1.3.3(seroval@1.3.2) + solid-transition-group@0.2.3(solid-js@1.9.9): + dependencies: + '@solid-primitives/refs': 1.1.2(solid-js@1.9.9) + '@solid-primitives/transition-group': 1.1.2(solid-js@1.9.9) + solid-js: 1.9.9 + sortablejs@1.15.6: {} source-list-map@2.0.1: {} @@ -8034,25 +8105,25 @@ snapshots: style-search@0.1.0: {} - stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.9.3)): + stylelint-config-recommended@17.0.0(stylelint@16.25.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.3) + stylelint: 16.25.0(typescript@5.9.3) - stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.24.0(typescript@5.9.3)): + stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.25.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.3) + stylelint: 16.25.0(typescript@5.9.3) - stylelint-declaration-strict-value@1.10.11(stylelint@16.24.0(typescript@5.9.3)): + stylelint-declaration-strict-value@1.10.11(stylelint@16.25.0(typescript@5.9.3)): dependencies: - stylelint: 16.24.0(typescript@5.9.3) + stylelint: 16.25.0(typescript@5.9.3) - stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.24.0(typescript@5.9.3)): + stylelint-value-no-unknown-custom-properties@6.0.1(stylelint@16.25.0(typescript@5.9.3)): dependencies: postcss-value-parser: 4.2.0 resolve: 1.22.10 - stylelint: 16.24.0(typescript@5.9.3) + stylelint: 16.25.0(typescript@5.9.3) - stylelint@16.24.0(typescript@5.9.3): + stylelint@16.25.0(typescript@5.9.3): dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 @@ -8155,7 +8226,7 @@ snapshots: deep-rename-keys: 0.2.1 xml-reader: 2.4.3 - swagger-ui-dist@5.29.1: + swagger-ui-dist@5.29.4: dependencies: '@scarf/scarf': 1.4.0 @@ -8205,16 +8276,16 @@ snapshots: transitivePeerDependencies: - ts-node - tapable@2.2.3: {} + tapable@2.3.0: {} - terser-webpack-plugin@5.3.14(webpack@5.102.0): + terser-webpack-plugin@5.3.14(webpack@5.102.1): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 - schema-utils: 4.3.2 + schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.0 - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) terser@5.44.0: dependencies: @@ -8292,13 +8363,13 @@ snapshots: type-fest@0.20.2: {} - typescript-eslint@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.45.0(@typescript-eslint/parser@8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.45.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.45.0(eslint@9.36.0(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.36.0(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -8319,7 +8390,7 @@ snapshots: unrs-resolver@1.11.1: dependencies: - napi-postinstall: 0.3.3 + napi-postinstall: 0.3.4 optionalDependencies: '@unrs/resolver-binding-android-arm-eabi': 1.11.1 '@unrs/resolver-binding-android-arm64': 1.11.1 @@ -8347,7 +8418,7 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - updates@16.7.4: {} + updates@16.8.0: {} uri-js@4.4.1: dependencies: @@ -8359,13 +8430,13 @@ snapshots: vanilla-colorful@0.7.2: {} - vite-node@3.2.4(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -8382,27 +8453,27 @@ snapshots: vite-string-plugin@1.4.6: {} - vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.3 + rollup: 4.52.4 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.7.1 + '@types/node': 24.7.2 fsevents: 2.3.3 jiti: 2.6.1 stylus: 0.57.0 terser: 5.44.0 yaml: 2.8.1 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.1)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(happy-dom@20.0.0)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -8420,12 +8491,12 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.7(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.7.1)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite: 7.1.9(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.7.2)(jiti@2.6.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.7.1 + '@types/node': 24.7.2 happy-dom: 20.0.0 transitivePeerDependencies: - jiti @@ -8471,10 +8542,10 @@ snapshots: chart.js: 4.5.0 vue: 3.5.22(typescript@5.9.3) - vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.1)): + vue-eslint-parser@10.2.0(eslint@9.37.0(jiti@2.6.1)): dependencies: debug: 4.4.3 - eslint: 9.36.0(jiti@2.6.1) + eslint: 9.37.0(jiti@2.6.1) eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -8483,19 +8554,19 @@ snapshots: transitivePeerDependencies: - supports-color - vue-loader@17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.0): + vue-loader@17.4.2(vue@3.5.22(typescript@5.9.3))(webpack@5.102.1): dependencies: chalk: 4.1.2 hash-sum: 2.0.0 watchpack: 2.4.4 - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) optionalDependencies: vue: 3.5.22(typescript@5.9.3) - vue-tsc@3.1.0(typescript@5.9.3): + vue-tsc@3.1.1(typescript@5.9.3): dependencies: '@volar/typescript': 2.4.23 - '@vue/language-core': 3.1.0(typescript@5.9.3) + '@vue/language-core': 3.1.1(typescript@5.9.3) typescript: 5.9.3 vue@3.5.22(typescript@5.9.3): @@ -8515,21 +8586,21 @@ snapshots: webidl-conversions@3.0.1: {} - webpack-cli@6.0.1(webpack@5.102.0): + webpack-cli@6.0.1(webpack@5.102.1): dependencies: '@discoveryjs/json-ext': 0.6.3 - '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) - '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) - '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.0) + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) colorette: 2.0.20 commander: 12.1.0 cross-spawn: 7.0.6 - envinfo: 7.15.0 + envinfo: 7.17.0 fastest-levenshtein: 1.0.16 import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.102.0(webpack-cli@6.0.1) + webpack: 5.102.1(webpack-cli@6.0.1) webpack-merge: 6.0.1 webpack-merge@6.0.1: @@ -8545,7 +8616,7 @@ snapshots: webpack-sources@3.3.3: {} - webpack@5.102.0(webpack-cli@6.0.1): + webpack@5.102.1(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -8564,16 +8635,16 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 + loader-runner: 4.3.1 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 4.3.2 - tapable: 2.2.3 - terser-webpack-plugin: 5.3.14(webpack@5.102.0) + schema-utils: 4.3.3 + tapable: 2.3.0 + terser-webpack-plugin: 5.3.14(webpack@5.102.1) watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: - webpack-cli: 6.0.1(webpack@5.102.0) + webpack-cli: 6.0.1(webpack@5.102.1) transitivePeerDependencies: - '@swc/core' - esbuild diff --git a/public/assets/img/svg/gitea-vscode.svg b/public/assets/img/svg/gitea-vscode.svg deleted file mode 100644 index 453b9befcc..0000000000 --- a/public/assets/img/svg/gitea-vscode.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/assets/img/svg/octicon-comment-ai.svg b/public/assets/img/svg/octicon-comment-ai.svg new file mode 100644 index 0000000000..72aa8715a0 --- /dev/null +++ b/public/assets/img/svg/octicon-comment-ai.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/img/svg/octicon-vscode.svg b/public/assets/img/svg/octicon-vscode.svg new file mode 100644 index 0000000000..d226e3a574 --- /dev/null +++ b/public/assets/img/svg/octicon-vscode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index 88d9fd8fe2..6b161df392 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -6,7 +6,6 @@ package repo import ( "errors" "fmt" - "html/template" "net/http" "path" "strconv" @@ -76,16 +75,24 @@ func prepareOpenWithEditorApps(ctx *context.Context) { } for _, app := range apps { schema, _, _ := strings.Cut(app.OpenURL, ":") - var iconHTML template.HTML - if schema == "vscode" || schema == "vscodium" || schema == "jetbrains" { - iconHTML = svg.RenderHTML("gitea-"+schema, 16) - } else { - iconHTML = svg.RenderHTML("gitea-git", 16) // TODO: it could support user's customized icon in the future + + var iconName string + switch schema { + case "vscode": + iconName = "octicon-vscode" + case "vscodium": + iconName = "gitea-vscodium" + case "jetbrains": + iconName = "gitea-jetbrains" + default: + // TODO: it could support user's customized icon in the future + iconName = "gitea-git" } + tmplApps = append(tmplApps, map[string]any{ "DisplayName": app.DisplayName, "OpenURL": app.OpenURL, - "IconHTML": iconHTML, + "IconHTML": svg.RenderHTML(iconName, 16), }) } ctx.Data["OpenWithEditorApps"] = tmplApps diff --git a/web_src/js/features/codeeditor.ts b/web_src/js/features/codeeditor.ts index a09785f0ab..c1c367c5c2 100644 --- a/web_src/js/features/codeeditor.ts +++ b/web_src/js/features/codeeditor.ts @@ -38,6 +38,9 @@ const baseOptions: MonacoOpts = { scrollbar: {horizontalScrollbarSize: 6, verticalScrollbarSize: 6}, scrollBeyondLastLine: false, automaticLayout: true, + wrappingIndent: 'none', + wordWrapBreakAfterCharacters: '', + wordWrapBreakBeforeCharacters: '', }; function getEditorconfig(input: HTMLInputElement): EditorConfig | null { diff --git a/web_src/js/features/dropzone.ts b/web_src/js/features/dropzone.ts index 20f7ceb6c3..508b7cb606 100644 --- a/web_src/js/features/dropzone.ts +++ b/web_src/js/features/dropzone.ts @@ -28,7 +28,6 @@ async function createDropzone(el: HTMLElement, opts: DropzoneOptions) { export function generateMarkdownLinkForAttachment(file: Partial, {width, dppx}: {width?: number, dppx?: number} = {}) { let fileMarkdown = `[${file.name}](/attachments/${file.uuid})`; if (isImageFile(file)) { - fileMarkdown = `!${fileMarkdown}`; if (width > 0 && dppx > 1) { // Scale down images from HiDPI monitors. This uses the tag because it's the only // method to change image size in Markdown that is supported by all implementations. diff --git a/web_src/js/features/repo-migration.ts b/web_src/js/features/repo-migration.ts index 0b348b45fb..9f086bb9d3 100644 --- a/web_src/js/features/repo-migration.ts +++ b/web_src/js/features/repo-migration.ts @@ -53,7 +53,7 @@ function checkAuth() { } function checkItems(tokenAuth: boolean) { - let enableItems = false; + let enableItems: boolean; if (tokenAuth) { enableItems = token?.value !== ''; } else { diff --git a/web_src/svg/gitea-vscode.svg b/web_src/svg/gitea-vscode.svg deleted file mode 100644 index 62cd1a3b73..0000000000 --- a/web_src/svg/gitea-vscode.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 22b92e30ca04295c30b81eba8ff49a351c0924ee Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 13 Oct 2025 00:37:21 +0000 Subject: [PATCH 33/74] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 1 + options/locale/locale_zh-CN.ini | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 9144916e45..04d8984a0a 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -109,6 +109,7 @@ copy_path=パスをコピー copy_success=コピーされました! copy_error=コピーに失敗しました copy_type_unsupported=このファイルタイプはコピーできません +copy_filename=ファイル名をコピー write=書き込み preview=プレビュー diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 9d353faa64..29eb6be949 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -109,6 +109,7 @@ copy_path=复制路径 copy_success=复制成功! copy_error=复制失败 copy_type_unsupported=无法复制此类型的文件内容 +copy_filename=复制文件名 write=撰写 preview=预览 @@ -2434,6 +2435,9 @@ settings.event_workflow_job_desc=Gitea 工作流队列中、等待中、正在 settings.event_package=软件包 settings.event_package_desc=软件包在仓库中已创建或删除。 settings.branch_filter=分支过滤 +settings.branch_filter_desc_1=推送、分支创建和分支删除事件的分支(和引用名称)白名单,以全局模式指定。如果为空或为 *,则报告所有分支和标签的事件。 +settings.branch_filter_desc_2=使用 refs/heads/refs/tags/ 前缀来匹配完整的引用名称。 +settings.branch_filter_desc_doc=请参阅 %[2]s 文档了解语法。 settings.authorization_header=授权标头 settings.authorization_header_desc=当存在时将被作为授权标头包含在内。例如: %s。 settings.active=激活 From 96102c69e76c70df9b07d4e012f7619a455145bd Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 14 Oct 2025 20:28:05 +0200 Subject: [PATCH 34/74] Bump setup-go to v6 (#35660) --- .github/workflows/cron-licenses.yml | 2 +- .github/workflows/pull-compliance.yml | 14 +++++++------- .github/workflows/pull-db-tests.yml | 10 +++++----- .github/workflows/pull-e2e-tests.yml | 2 +- .github/workflows/release-nightly.yml | 6 +++--- .github/workflows/release-tag-rc.yml | 2 +- .github/workflows/release-tag-version.yml | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/cron-licenses.yml b/.github/workflows/cron-licenses.yml index 024c273e79..12f52289b6 100644 --- a/.github/workflows/cron-licenses.yml +++ b/.github/workflows/cron-licenses.yml @@ -11,7 +11,7 @@ jobs: if: github.repository == 'go-gitea/gitea' steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml index 0561392cf8..f73772e934 100644 --- a/.github/workflows/pull-compliance.yml +++ b/.github/workflows/pull-compliance.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -72,7 +72,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -101,7 +101,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -116,7 +116,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -145,7 +145,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -190,7 +190,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/pull-db-tests.yml b/.github/workflows/pull-db-tests.yml index 6ff7d53b75..21ec76b48e 100644 --- a/.github/workflows/pull-db-tests.yml +++ b/.github/workflows/pull-db-tests.yml @@ -39,7 +39,7 @@ jobs: - "9000:9000" steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -125,7 +125,7 @@ jobs: - 10000:10000 steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -178,7 +178,7 @@ jobs: - "993:993" steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -218,7 +218,7 @@ jobs: - 10000:10000 steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/pull-e2e-tests.yml b/.github/workflows/pull-e2e-tests.yml index 27b7a4eabb..4f806e93bd 100644 --- a/.github/workflows/pull-e2e-tests.yml +++ b/.github/workflows/pull-e2e-tests.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index a521fd9c28..16ce0fd643 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -16,7 +16,7 @@ jobs: # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -65,7 +65,7 @@ jobs: # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true @@ -107,7 +107,7 @@ jobs: # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/release-tag-rc.yml b/.github/workflows/release-tag-rc.yml index 52731bccf9..c239ff392b 100644 --- a/.github/workflows/release-tag-rc.yml +++ b/.github/workflows/release-tag-rc.yml @@ -17,7 +17,7 @@ jobs: # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true diff --git a/.github/workflows/release-tag-version.yml b/.github/workflows/release-tag-version.yml index 238636c8e1..289b0e9d9c 100644 --- a/.github/workflows/release-tag-version.yml +++ b/.github/workflows/release-tag-version.yml @@ -21,7 +21,7 @@ jobs: # fetch all commits instead of only the last as some branches are long lived and could have many between versions # fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567 - run: git fetch --unshallow --quiet --tags --force - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true From 731d803d19d29cd5152a76048b143e6a95723870 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 14 Oct 2025 12:19:27 -0700 Subject: [PATCH 35/74] Creating push comments before invoke pull request checking (#35647) This PR moved the creation of pushing comments before pull request mergeable checking. So that when the pull request status changed, the comments should have been created. --------- Co-authored-by: wxiaoguang --- services/issue/comments.go | 26 +++++++++++++++++--------- services/pull/merge.go | 5 +++++ services/pull/pull.go | 12 +++++++----- services/pull/update.go | 3 +++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/services/issue/comments.go b/services/issue/comments.go index 9442701029..3ce2e2a5e1 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -15,6 +15,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" git_service "code.gitea.io/gitea/services/git" notify_service "code.gitea.io/gitea/services/notify" @@ -151,15 +152,15 @@ func DeleteComment(ctx context.Context, doer *user_model.User, comment *issues_m } // LoadCommentPushCommits Load push commits -func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err error) { +func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) error { if c.Content == "" || c.Commits != nil || c.Type != issues_model.CommentTypePullRequestPush { return nil } var data issues_model.PushActionContent - err = json.Unmarshal([]byte(c.Content), &data) - if err != nil { - return err + if err := json.Unmarshal([]byte(c.Content), &data); err != nil { + log.Debug("Unmarshal: %v", err) // no need to show 500 error to end user when the JSON is broken + return nil } c.IsForcePush = data.IsForcePush @@ -168,9 +169,15 @@ func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err e if len(data.CommitIDs) != 2 { return nil } - c.OldCommit = data.CommitIDs[0] - c.NewCommit = data.CommitIDs[1] + c.OldCommit, c.NewCommit = data.CommitIDs[0], data.CommitIDs[1] } else { + if err := c.LoadIssue(ctx); err != nil { + return err + } + if err := c.Issue.LoadRepo(ctx); err != nil { + return err + } + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, c.Issue.Repo) if err != nil { return err @@ -179,10 +186,11 @@ func LoadCommentPushCommits(ctx context.Context, c *issues_model.Comment) (err e c.Commits, err = git_service.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo) if err != nil { - return err + log.Debug("ConvertFromGitCommit: %v", err) // no need to show 500 error to end user when the commit does not exist + } else { + c.CommitsNum = int64(len(c.Commits)) } - c.CommitsNum = int64(len(c.Commits)) } - return err + return nil } diff --git a/services/pull/merge.go b/services/pull/merge.go index f1ad8fa17d..1e8e9d444b 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -248,6 +248,11 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U } defer releaser() defer func() { + // This is a duplicated call to AddTestPullRequestTask (it will also be called by the post-receive hook, via a push queue). + // This call will do some operations (push to base repo, sync commit divergence, add PR conflict check queue task, etc) + // immediately instead of waiting for the "push queue"'s task. The code is from https://github.com/go-gitea/gitea/pull/7082. + // But it's really questionable whether it's worth to do it ahead without waiting for the "push queue" task to run. + // TODO: DUPLICATE-PR-TASK: maybe can try to remove this in 1.26 to see if there is any issue. go AddTestPullRequestTask(TestPullRequestOptions{ RepoID: pr.BaseRepo.ID, Doer: doer, diff --git a/services/pull/pull.go b/services/pull/pull.go index 619347055b..a519a1032f 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -374,10 +374,8 @@ type TestPullRequestOptions struct { func AddTestPullRequestTask(opts TestPullRequestOptions) { log.Trace("AddTestPullRequestTask [head_repo_id: %d, head_branch: %s]: finding pull requests", opts.RepoID, opts.Branch) graceful.GetManager().RunWithShutdownContext(func(ctx context.Context) { - // There is no sensible way to shut this down ":-(" - // If you don't let it run all the way then you will lose data - // TODO: graceful: AddTestPullRequestTask needs to become a queue! - + // this function does a lot of operations to various models, if the process gets killed in the middle, + // there is no way to recover at the moment. The best workaround is to let end user push again. repo, err := repo_model.GetRepositoryByID(ctx, opts.RepoID) if err != nil { log.Error("GetRepositoryByID: %v", err) @@ -402,11 +400,15 @@ func AddTestPullRequestTask(opts TestPullRequestOptions) { continue } - StartPullRequestCheckImmediately(ctx, pr) + // create push comment before check pull request status, + // then when the status is mergeable, the comment is already in database, to make testing easy and stable comment, err := CreatePushPullComment(ctx, opts.Doer, pr, opts.OldCommitID, opts.NewCommitID, opts.IsForcePush) if err == nil && comment != nil { notify_service.PullRequestPushCommits(ctx, opts.Doer, pr, comment) } + // The caller can be in a goroutine or a "push queue", "conflict check" can be time-consuming, + // and the concurrency should be limited, so the conflict check will be done in another queue + StartPullRequestCheckImmediately(ctx, pr) } if opts.IsSync { diff --git a/services/pull/update.go b/services/pull/update.go index cce3937451..436e3b52a6 100644 --- a/services/pull/update.go +++ b/services/pull/update.go @@ -63,6 +63,9 @@ func Update(ctx context.Context, pr *issues_model.PullRequest, doer *user_model. } defer func() { + // The code is from https://github.com/go-gitea/gitea/pull/9784, + // it seems a simple copy-paste from https://github.com/go-gitea/gitea/pull/7082 without a real reason. + // TODO: DUPLICATE-PR-TASK: search and see another TODO comment for more details go AddTestPullRequestTask(TestPullRequestOptions{ RepoID: pr.BaseRepo.ID, Doer: doer, From 16fc3323b958b0a5a8ebdd424a62e90294abd906 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 14 Oct 2025 20:12:07 -0700 Subject: [PATCH 36/74] Fix a bug missed return (#35655) --- routers/web/auth/oauth2_provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/routers/web/auth/oauth2_provider.go b/routers/web/auth/oauth2_provider.go index 79989d8fbe..1dc40d6a75 100644 --- a/routers/web/auth/oauth2_provider.go +++ b/routers/web/auth/oauth2_provider.go @@ -636,6 +636,7 @@ func handleAuthorizationCode(ctx *context.Context, form forms.AccessTokenForm, s ErrorCode: oauth2_provider.AccessTokenErrorCodeInvalidRequest, ErrorDescription: "cannot proceed your request", }) + return } resp, tokenErr := oauth2_provider.NewAccessTokenResponse(ctx, authorizationCode.Grant, serverKey, clientKey) if tokenErr != nil { From 9ae2e9e76ff8ea73f2071452c4396fdfef1dbd3a Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Wed, 15 Oct 2025 12:07:58 +0800 Subject: [PATCH 37/74] Always create Actions logs stepsContainer (#35654) --- web_src/js/components/RepoActionView.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index b90aef7411..6e6733c7d0 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -601,7 +601,8 @@ export default defineComponent({
-
+ +
-
-
{{ i18nErrorOccurred }}
-
{{ i18nErrorMessage }}
+
+ {{ errorMessage }}
diff --git a/web_src/js/features/contextpopup.ts b/web_src/js/features/contextpopup.ts deleted file mode 100644 index 7477331dbe..0000000000 --- a/web_src/js/features/contextpopup.ts +++ /dev/null @@ -1,43 +0,0 @@ -import {createApp} from 'vue'; -import ContextPopup from '../components/ContextPopup.vue'; -import {parseIssueHref} from '../utils.ts'; -import {createTippy} from '../modules/tippy.ts'; - -export function initContextPopups() { - const refIssues = document.querySelectorAll('.ref-issue'); - attachRefIssueContextPopup(refIssues); -} - -export function attachRefIssueContextPopup(refIssues: NodeListOf) { - for (const refIssue of refIssues) { - if (refIssue.classList.contains('ref-external-issue')) continue; - - const issuePathInfo = parseIssueHref(refIssue.getAttribute('href')); - if (!issuePathInfo.ownerName) continue; - - const el = document.createElement('div'); - el.classList.add('tw-p-3'); - refIssue.parentNode.insertBefore(el, refIssue.nextSibling); - - const view = createApp(ContextPopup); - - try { - view.mount(el); - } catch (err) { - console.error(err); - el.textContent = 'ContextPopup failed to load'; - } - - createTippy(refIssue, { - theme: 'default', - content: el, - placement: 'top-start', - interactive: true, - role: 'dialog', - interactiveBorder: 5, - onShow: () => { - el.firstChild.dispatchEvent(new CustomEvent('ce-load-context-popup', {detail: issuePathInfo})); - }, - }); - } -} diff --git a/web_src/js/features/repo-diff.ts b/web_src/js/features/repo-diff.ts index 24d937a252..20cec2939d 100644 --- a/web_src/js/features/repo-diff.ts +++ b/web_src/js/features/repo-diff.ts @@ -12,8 +12,6 @@ import {invertFileFolding} from './file-fold.ts'; import {parseDom, sleep} from '../utils.ts'; import {registerGlobalSelectorFunc} from '../modules/observer.ts'; -const {i18n} = window.config; - function initRepoDiffFileBox(el: HTMLElement) { // switch between "rendered" and "source", for image and CSV files queryElems(el, '.file-view-toggle', (btn) => btn.addEventListener('click', () => { @@ -86,7 +84,7 @@ function initRepoDiffConversationForm() { } } catch (error) { console.error('Error:', error); - showErrorToast(i18n.network_error); + showErrorToast(`Submit form failed: ${error}`); } finally { form?.classList.remove('is-loading'); } diff --git a/web_src/js/features/repo-editor.ts b/web_src/js/features/repo-editor.ts index f3ca13460c..0825999edc 100644 --- a/web_src/js/features/repo-editor.ts +++ b/web_src/js/features/repo-editor.ts @@ -1,7 +1,6 @@ import {html, htmlRaw} from '../utils/html.ts'; import {createCodeEditor} from './codeeditor.ts'; import {hideElem, queryElems, showElem, createElementFromHTML} from '../utils/dom.ts'; -import {attachRefIssueContextPopup} from './contextpopup.ts'; import {POST} from '../modules/fetch.ts'; import {initDropzone} from './dropzone.ts'; import {confirmModal} from './comp/ConfirmModal.ts'; @@ -199,5 +198,4 @@ export function initRepoEditor() { export function renderPreviewPanelContent(previewPanel: Element, htmlContent: string) { // the content is from the server, so it is safe to use innerHTML previewPanel.innerHTML = html`
${htmlRaw(htmlContent)}
`; - attachRefIssueContextPopup(previewPanel.querySelectorAll('p .ref-issue')); } diff --git a/web_src/js/features/repo-issue-edit.ts b/web_src/js/features/repo-issue-edit.ts index f883ee460b..43aee314e0 100644 --- a/web_src/js/features/repo-issue-edit.ts +++ b/web_src/js/features/repo-issue-edit.ts @@ -3,7 +3,6 @@ import {getComboMarkdownEditor, initComboMarkdownEditor, ComboMarkdownEditor} fr import {POST} from '../modules/fetch.ts'; import {showErrorToast} from '../modules/toast.ts'; import {hideElem, querySingleVisibleElem, showElem, type DOMEvent} from '../utils/dom.ts'; -import {attachRefIssueContextPopup} from './contextpopup.ts'; import {triggerUploadStateChanged} from './comp/EditorUpload.ts'; import {convertHtmlToMarkdown} from '../markup/html2markdown.ts'; import {applyAreYouSure, reinitializeAreYouSure} from '../vendor/jquery.are-you-sure.ts'; @@ -62,8 +61,6 @@ async function tryOnEditContent(e: DOMEvent) { renderContent = newRenderContent; rawContent.textContent = comboMarkdownEditor.value(); - const refIssues = renderContent.querySelectorAll('p .ref-issue'); - attachRefIssueContextPopup(refIssues); if (!commentContent.querySelector('.dropzone-attachments')) { if (data.attachments !== '') { diff --git a/web_src/js/index-domready.ts b/web_src/js/index-domready.ts index cfb6b89ea7..8a3a27fa19 100644 --- a/web_src/js/index-domready.ts +++ b/web_src/js/index-domready.ts @@ -5,7 +5,6 @@ import '../../node_modules/easymde/dist/easymde.min.css'; // TODO: lazy load in import {initHtmx} from './htmx.ts'; import {initDashboardRepoList} from './features/dashboard.ts'; import {initGlobalCopyToClipboardListener} from './features/clipboard.ts'; -import {initContextPopups} from './features/contextpopup.ts'; import {initRepoGraphGit} from './features/repo-graph.ts'; import {initHeatmap} from './features/heatmap.ts'; import {initImageDiff} from './features/imagediff.ts'; @@ -97,7 +96,6 @@ const initPerformanceTracer = callInitFunctions([ initHeadNavbarContentToggle, initFootLanguageMenu, - initContextPopups, initHeatmap, initImageDiff, initMarkupAnchors, diff --git a/web_src/js/markup/content.ts b/web_src/js/markup/content.ts index cf88ed61de..d964c88989 100644 --- a/web_src/js/markup/content.ts +++ b/web_src/js/markup/content.ts @@ -5,6 +5,7 @@ import {initMarkupRenderAsciicast} from './asciicast.ts'; import {initMarkupTasklist} from './tasklist.ts'; import {registerGlobalSelectorFunc} from '../modules/observer.ts'; import {initMarkupRenderIframe} from './render-iframe.ts'; +import {initMarkupRefIssue} from './refissue.ts'; // code that runs for all markup content export function initMarkupContent(): void { @@ -15,5 +16,6 @@ export function initMarkupContent(): void { initMarkupCodeMath(el); initMarkupRenderAsciicast(el); initMarkupRenderIframe(el); + initMarkupRefIssue(el); }); } diff --git a/web_src/js/markup/refissue.ts b/web_src/js/markup/refissue.ts new file mode 100644 index 0000000000..5a05de84fe --- /dev/null +++ b/web_src/js/markup/refissue.ts @@ -0,0 +1,41 @@ +import {queryElems} from '../utils/dom.ts'; +import {parseIssueHref} from '../utils.ts'; +import {createApp} from 'vue'; +import ContextPopup from '../components/ContextPopup.vue'; +import {createTippy, getAttachedTippyInstance} from '../modules/tippy.ts'; + +export function initMarkupRefIssue(el: HTMLElement) { + queryElems(el, '.ref-issue', (el) => { + el.addEventListener('mouseenter', showMarkupRefIssuePopup); + el.addEventListener('focus', showMarkupRefIssuePopup); + }); +} + +export function showMarkupRefIssuePopup(e: MouseEvent | FocusEvent) { + const refIssue = e.currentTarget as HTMLElement; + if (getAttachedTippyInstance(refIssue)) return; + if (refIssue.classList.contains('ref-external-issue')) return; + + const issuePathInfo = parseIssueHref(refIssue.getAttribute('href')); + if (!issuePathInfo.ownerName) return; + + const el = document.createElement('div'); + const tippy = createTippy(refIssue, { + theme: 'default', + content: el, + trigger: 'mouseenter focus', + placement: 'top-start', + interactive: true, + role: 'dialog', + interactiveBorder: 5, + // onHide() { return false }, // help to keep the popup and debug the layout + onShow: () => { + const view = createApp(ContextPopup, { + // backend: GetIssueInfo + loadIssueInfoUrl: `${window.config.appSubUrl}/${issuePathInfo.ownerName}/${issuePathInfo.repoName}/issues/${issuePathInfo.indexString}/info`, + }); + view.mount(el); + }, + }); + tippy.show(); +} diff --git a/web_src/js/modules/tippy.ts b/web_src/js/modules/tippy.ts index 2a1d998d76..6f42a4f987 100644 --- a/web_src/js/modules/tippy.ts +++ b/web_src/js/modules/tippy.ts @@ -209,3 +209,7 @@ export function showTemporaryTooltip(target: Element, content: Content): void { }, }); } + +export function getAttachedTippyInstance(el: Element): Instance | null { + return el._tippy ?? null; +}