From 67a62c128ef655da4913186c6b42b3e78d134ec6 Mon Sep 17 00:00:00 2001 From: HappySummer Date: Wed, 15 Apr 2026 01:51:50 +0800 Subject: [PATCH 01/22] =?UTF-8?q?feat(RepositoryCard):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=A4=9A=E8=AF=AD=E8=A8=80=E6=94=AF=E6=8C=81=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为订阅和查看GitHub按钮添加中文标题支持,根据当前语言环境显示相应文本 --- package-lock.json | 669 ++++++++++++++++++------------ src/components/RepositoryCard.tsx | 4 +- 2 files changed, 405 insertions(+), 268 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88f11970..8375a6b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "github-stars-manager", - "version": "0.1.8", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "github-stars-manager", - "version": "0.1.8", + "version": "0.3.0", "dependencies": { "date-fns": "^3.3.1", "lucide-react": "^0.344.0", @@ -60,13 +60,15 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", - "picocolors": "^1.0.0" + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -196,19 +198,21 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -223,40 +227,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", - "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -306,14 +297,15 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -347,14 +339,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", - "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -841,17 +833,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", "dev": true, + "license": "Apache-2.0", "dependencies": { + "@eslint/core": "^0.13.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@humanfs/core": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", @@ -1011,217 +1018,398 @@ } }, "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -1269,10 +1457,11 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -1449,21 +1638,23 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1576,10 +1767,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1603,18 +1795,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -1793,20 +1973,6 @@ } ] }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1957,21 +2123,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2131,10 +2282,11 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2272,15 +2424,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/eslint": { "version": "9.12.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", @@ -2640,10 +2783,11 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" }, "node_modules/foreground-child": { "version": "3.3.0", @@ -2717,10 +2861,12 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -2749,21 +2895,23 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -2790,15 +2938,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2947,10 +3086,11 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3056,9 +3196,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -3119,10 +3259,11 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3157,9 +3298,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -3167,6 +3308,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -3340,10 +3482,11 @@ "dev": true }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3583,12 +3726,12 @@ } }, "node_modules/react-router": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", - "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.0" + "@remix-run/router": "1.23.2" }, "engines": { "node": ">=14.0.0" @@ -3598,13 +3741,13 @@ } }, "node_modules/react-router-dom": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", - "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.0", - "react-router": "6.30.1" + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" }, "engines": { "node": ">=14.0.0" @@ -3682,12 +3825,13 @@ } }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -3697,22 +3841,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" } }, @@ -3964,18 +4117,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -4052,15 +4193,6 @@ "node": ">=0.8" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4211,10 +4343,11 @@ "dev": true }, "node_modules/vite": { - "version": "5.4.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", - "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -4455,15 +4588,19 @@ "dev": true }, "node_modules/yaml": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", - "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, + "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { diff --git a/src/components/RepositoryCard.tsx b/src/components/RepositoryCard.tsx index 0bbc6243..ce840fef 100644 --- a/src/components/RepositoryCard.tsx +++ b/src/components/RepositoryCard.tsx @@ -407,7 +407,7 @@ export const RepositoryCard: React.FC = ({ ? 'bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-400' : 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600' }`} - title={isSubscribed ? 'Unsubscribe from releases' : 'Subscribe to releases'} + title={isSubscribed ? (language === 'zh' ? '取消订阅发布' : 'Unsubscribe from releases') : (language === 'zh' ? '订阅发布' : 'Subscribe to releases')} > {isSubscribed ? : } @@ -436,7 +436,7 @@ export const RepositoryCard: React.FC = ({ target="_blank" rel="noopener noreferrer" className="flex items-center justify-center w-8 h-8 rounded-lg bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors" - title="View on GitHub" + title={language === 'zh' ? '在GitHub上查看' : 'View on GitHub'} > From d439362dc04ea06a6668965e9967c5bc5f812edd Mon Sep 17 00:00:00 2001 From: HappySummer Date: Wed, 15 Apr 2026 03:08:20 +0800 Subject: [PATCH 02/22] =?UTF-8?q?feat(settings):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=A8=A1=E5=9D=97=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增设置模块的多个面板组件,包括通用设置、WebDAV配置、备份恢复、分类管理、后端服务和AI配置。每个面板提供相应的功能界面和交互逻辑,支持多语言切换。 - 通用设置面板支持语言切换和版本检查 - WebDAV面板提供配置管理和测试功能 - 备份面板支持数据备份和恢复操作 - 分类面板管理自定义分类和默认分类显示 - 后端面板处理服务器连接和数据同步 - AI面板配置AI服务参数和测试连接 --- dist/index.html | 9 +- src/components/SettingsPanel.tsx | 1523 +++------------------ src/components/settings/AIConfigPanel.tsx | 472 +++++++ src/components/settings/BackendPanel.tsx | 311 +++++ src/components/settings/BackupPanel.tsx | 327 +++++ src/components/settings/CategoryPanel.tsx | 300 ++++ src/components/settings/GeneralPanel.tsx | 125 ++ src/components/settings/WebDAVPanel.tsx | 293 ++++ src/components/settings/index.ts | 6 + 9 files changed, 2013 insertions(+), 1353 deletions(-) create mode 100644 src/components/settings/AIConfigPanel.tsx create mode 100644 src/components/settings/BackendPanel.tsx create mode 100644 src/components/settings/BackupPanel.tsx create mode 100644 src/components/settings/CategoryPanel.tsx create mode 100644 src/components/settings/GeneralPanel.tsx create mode 100644 src/components/settings/WebDAVPanel.tsx create mode 100644 src/components/settings/index.ts diff --git a/dist/index.html b/dist/index.html index b0f3f514..e8c96d67 100644 --- a/dist/index.html +++ b/dist/index.html @@ -2,7 +2,8 @@ - + + GitHub Stars Manager - AI-Powered Repository Management @@ -10,10 +11,10 @@ - - + +
- \ No newline at end of file + diff --git a/src/components/SettingsPanel.tsx b/src/components/SettingsPanel.tsx index 55eb1ca0..a0941b81 100644 --- a/src/components/SettingsPanel.tsx +++ b/src/components/SettingsPanel.tsx @@ -1,1394 +1,219 @@ -import React, { useState, useEffect } from 'react'; -import { - Bot, - Plus, - Edit3, - Trash2, - Save, - X, - TestTube, - CheckCircle, - AlertCircle, - Cloud, - Download, - Upload, - RefreshCw, +import React, { useState } from 'react'; +import { + Settings, Globe, - MessageSquare, - Package, - ExternalLink, - Mail, - Github, - Twitter, + Bot, + Cloud, + Database, Server, + Package, + X, } from 'lucide-react'; -import { AIConfig, WebDAVConfig, AIApiType, AIReasoningEffort } from '../types'; -import { useAppStore, getAllCategories } from '../store/useAppStore'; -import { AIService } from '../services/aiService'; -import { WebDAVService } from '../services/webdavService'; -import { UpdateChecker } from './UpdateChecker'; -import { backend } from '../services/backendAdapter'; - -export const SettingsPanel: React.FC = () => { - const { - aiConfigs, - activeAIConfig, - webdavConfigs, - activeWebDAVConfig, - lastBackup, - repositories, - releases, - customCategories, - hiddenDefaultCategoryIds, - theme, - language, - addAIConfig, - updateAIConfig, - deleteAIConfig, - setActiveAIConfig, - addWebDAVConfig, - updateWebDAVConfig, - deleteWebDAVConfig, - setActiveWebDAVConfig, - setLastBackup, - setLanguage, - setRepositories, - setReleases, - addCustomCategory, - deleteCustomCategory, - hideDefaultCategory, - showDefaultCategory, - backendApiSecret, - setBackendApiSecret, - setAIConfigs, - setWebDAVConfigs, - } = useAppStore(); - - const [showAIForm, setShowAIForm] = useState(false); - const [showWebDAVForm, setShowWebDAVForm] = useState(false); - const [editingAIId, setEditingAIId] = useState(null); - const [editingWebDAVId, setEditingWebDAVId] = useState(null); - const [testingAIId, setTestingAIId] = useState(null); - const [testingWebDAVId, setTestingWebDAVId] = useState(null); - const [isBackingUp, setIsBackingUp] = useState(false); - const [isRestoring, setIsRestoring] = useState(false); - const [showCustomPrompt, setShowCustomPrompt] = useState(false); - const [backendStatus, setBackendStatus] = useState<'connected' | 'disconnected' | 'checking'>('disconnected'); - const [backendHealth, setBackendHealth] = useState<{ version: string; timestamp: string } | null>(null); - const [isSyncingToBackend, setIsSyncingToBackend] = useState(false); - const [isSyncingFromBackend, setIsSyncingFromBackend] = useState(false); - const [backendSecretInput, setBackendSecretInput] = useState(backendApiSecret || ''); - - // Check backend status on mount - useEffect(() => { - const checkBackend = async () => { - setBackendStatus('checking'); - const health = await backend.checkHealth(); - if (health) { - setBackendStatus('connected'); - setBackendHealth({ version: health.version, timestamp: health.timestamp }); - } else { - setBackendStatus('disconnected'); - setBackendHealth(null); - } - }; - checkBackend(); - }, []); - - type AIFormState = { - name: string; - apiType: AIApiType; - baseUrl: string; - apiKey: string; - model: string; - customPrompt: string; - useCustomPrompt: boolean; - concurrency: number; - reasoningEffort: '' | AIReasoningEffort; - }; - - const [aiForm, setAIForm] = useState({ - name: '', - apiType: 'openai', - baseUrl: '', - apiKey: '', - model: '', - customPrompt: '', - useCustomPrompt: false, - concurrency: 1, - reasoningEffort: '', - }); - - const [webdavForm, setWebDAVForm] = useState({ - name: '', - url: '', - username: '', - password: '', - path: '/', - }); - - const resetAIForm = () => { - setAIForm({ - name: '', - apiType: 'openai', - baseUrl: '', - apiKey: '', - model: '', - customPrompt: '', - useCustomPrompt: false, - concurrency: 1, - reasoningEffort: '', - }); - setShowAIForm(false); - setEditingAIId(null); - setShowCustomPrompt(false); - }; - - const resetWebDAVForm = () => { - setWebDAVForm({ - name: '', - url: '', - username: '', - password: '', - path: '/', - }); - setShowWebDAVForm(false); - setEditingWebDAVId(null); - }; - - const handleSaveAI = () => { - if (!aiForm.name || !aiForm.baseUrl || !aiForm.apiKey || !aiForm.model) { - alert(t('请填写所有必填字段', 'Please fill in all required fields')); - return; - } - - const config: AIConfig = { - id: editingAIId || Date.now().toString(), - name: aiForm.name, - apiType: aiForm.apiType, - baseUrl: aiForm.baseUrl.replace(/\/$/, ''), // Remove trailing slash - apiKey: aiForm.apiKey, - model: aiForm.model, - isActive: false, - customPrompt: aiForm.customPrompt || undefined, - useCustomPrompt: aiForm.useCustomPrompt, - concurrency: aiForm.concurrency, - reasoningEffort: aiForm.reasoningEffort || undefined, - }; - - if (editingAIId) { - updateAIConfig(editingAIId, config); - } else { - addAIConfig(config); - } - - resetAIForm(); - }; - - const handleEditAI = (config: AIConfig) => { - setAIForm({ - name: config.name, - apiType: config.apiType || 'openai', - baseUrl: config.baseUrl, - apiKey: config.apiKey, - model: config.model, - customPrompt: config.customPrompt || '', - useCustomPrompt: config.useCustomPrompt || false, - concurrency: config.concurrency || 1, - reasoningEffort: (config.reasoningEffort === 'minimal' ? 'low' : config.reasoningEffort) || '', - }); - setEditingAIId(config.id); - setShowAIForm(true); - setShowCustomPrompt(config.useCustomPrompt || false); - }; - - const handleTestAI = async (config: AIConfig) => { - setTestingAIId(config.id); - try { - const aiService = new AIService(config, language); - const isConnected = await aiService.testConnection(); - - if (isConnected) { - alert(t('AI服务连接成功!', 'AI service connection successful!')); - } else { - alert(t('AI服务连接失败,请检查配置。', 'AI service connection failed. Please check configuration.')); - } - } catch (error) { - console.error('AI test failed:', error); - alert(t('AI服务测试失败,请检查网络连接和配置。', 'AI service test failed. Please check network connection and configuration.')); - } finally { - setTestingAIId(null); - } - }; - - const handleSaveWebDAV = () => { - const errors = WebDAVService.validateConfig(webdavForm); - if (errors.length > 0) { - alert(errors.join('\n')); - return; - } - - const config: WebDAVConfig = { - id: editingWebDAVId || Date.now().toString(), - name: webdavForm.name, - url: webdavForm.url.replace(/\/$/, ''), // Remove trailing slash - username: webdavForm.username, - password: webdavForm.password, - path: webdavForm.path, - isActive: false, - }; - - if (editingWebDAVId) { - updateWebDAVConfig(editingWebDAVId, config); - } else { - addWebDAVConfig(config); - } - - resetWebDAVForm(); - }; - - const handleEditWebDAV = (config: WebDAVConfig) => { - setWebDAVForm({ - name: config.name, - url: config.url, - username: config.username, - password: config.password, - path: config.path, - }); - setEditingWebDAVId(config.id); - setShowWebDAVForm(true); - }; - - const handleTestWebDAV = async (config: WebDAVConfig) => { - setTestingWebDAVId(config.id); - try { - const webdavService = new WebDAVService(config); - const isConnected = await webdavService.testConnection(); - - if (isConnected) { - alert(t('WebDAV连接成功!', 'WebDAV connection successful!')); - } else { - alert(t('WebDAV连接失败,请检查配置。', 'WebDAV connection failed. Please check configuration.')); - } - } catch (error) { - console.error('WebDAV test failed:', error); - alert(`${t('WebDAV测试失败', 'WebDAV test failed')}: ${error.message}`); - } finally { - setTestingWebDAVId(null); - } - }; - - const handleBackup = async () => { - const activeConfig = webdavConfigs.find(config => config.id === activeWebDAVConfig); - if (!activeConfig) { - alert(t('请先配置并激活WebDAV服务。', 'Please configure and activate WebDAV service first.')); - return; - } - - setIsBackingUp(true); - try { - const webdavService = new WebDAVService(activeConfig); - - const backupData = { - repositories, - releases, - customCategories, - hiddenDefaultCategoryIds, - aiConfigs: aiConfigs.map(config => ({ - ...config, - apiKey: '***' // Don't backup API keys for security - })), - webdavConfigs: webdavConfigs.map(config => ({ - ...config, - password: '***' // Don't backup passwords for security - })), - exportedAt: new Date().toISOString(), - version: '1.0' - }; - - const filename = `github-stars-backup-${new Date().toISOString().split('T')[0]}.json`; - const success = await webdavService.uploadFile(filename, JSON.stringify(backupData, null, 2)); - - if (success) { - setLastBackup(new Date().toISOString()); - alert(t('数据备份成功!', 'Data backup successful!')); - } - } catch (error) { - console.error('Backup failed:', error); - alert(`${t('备份失败', 'Backup failed')}: ${error.message}`); - } finally { - setIsBackingUp(false); - } - }; - - const handleRestore = async () => { - const activeConfig = webdavConfigs.find(config => config.id === activeWebDAVConfig); - if (!activeConfig) { - alert(t('请先配置并激活WebDAV服务。', 'Please configure and activate WebDAV service first.')); - return; - } - - const confirmMessage = t( - '恢复数据将覆盖当前所有数据,是否继续?', - 'Restoring data will overwrite all current data. Continue?' - ); - - if (!confirm(confirmMessage)) return; - - setIsRestoring(true); - try { - const webdavService = new WebDAVService(activeConfig); - const files = await webdavService.listFiles(); - - const backupFiles = files.filter(file => file.startsWith('github-stars-backup-')); - if (backupFiles.length === 0) { - alert(t('未找到备份文件。', 'No backup files found.')); - return; - } - - // Use the most recent backup file - const latestBackup = backupFiles.sort().reverse()[0]; - const backupContent = await webdavService.downloadFile(latestBackup); - - if (backupContent) { - const backupData = JSON.parse(backupContent); - - // 1) 恢复仓库与发布 - if (Array.isArray(backupData.repositories)) { - setRepositories(backupData.repositories); - } - if (Array.isArray(backupData.releases)) { - setReleases(backupData.releases); - } - - // 2) 恢复自定义分类(全部替换) - try { - // 先清空现有自定义分类 - if (Array.isArray(customCategories)) { - for (const cat of customCategories) { - if (cat && cat.id) { - deleteCustomCategory(cat.id); - } - } - } - // 再添加备份中的自定义分类 - if (Array.isArray(backupData.customCategories)) { - for (const cat of backupData.customCategories) { - if (cat && cat.id && cat.name) { - addCustomCategory({ ...cat, isCustom: true }); - } - } - } - if (Array.isArray(hiddenDefaultCategoryIds)) { - for (const categoryId of hiddenDefaultCategoryIds) { - if (typeof categoryId === 'string') { - showDefaultCategory(categoryId); - } - } - } - if (Array.isArray(backupData.hiddenDefaultCategoryIds)) { - for (const categoryId of backupData.hiddenDefaultCategoryIds) { - if (typeof categoryId === 'string') { - hideDefaultCategory(categoryId); - } - } - } - } catch (e) { - console.warn('恢复自定义分类时发生问题:', e); - } - - // 3) 合并 AI 配置(保留现有密钥;备份中密钥为***时不覆盖) - try { - if (Array.isArray(backupData.aiConfigs)) { - const currentMap = new Map(aiConfigs.map((c: AIConfig) => [c.id, c])); - for (const cfg of backupData.aiConfigs as AIConfig[]) { - if (!cfg || !cfg.id) continue; - const existing = currentMap.get(cfg.id); - const isMasked = cfg.apiKey === '***'; - if (existing) { - updateAIConfig(cfg.id, { - name: cfg.name, - baseUrl: cfg.baseUrl, - model: cfg.model, - customPrompt: cfg.customPrompt, - useCustomPrompt: cfg.useCustomPrompt, - concurrency: cfg.concurrency, - reasoningEffort: cfg.reasoningEffort, - // 仅当备份未掩码时才覆盖 apiKey - apiKey: isMasked ? existing.apiKey : cfg.apiKey, - // 保留现有 isActive 状态 - isActive: existing.isActive, - }); - } else { - addAIConfig({ - ...cfg, - apiKey: isMasked ? '' : cfg.apiKey, - isActive: false, - }); - } - } - } - } catch (e) { - console.warn('恢复 AI 配置时发生问题:', e); - } - - // 4) 合并 WebDAV 配置(保留现有密码;备份中密码为***时不覆盖) - try { - if (Array.isArray(backupData.webdavConfigs)) { - const currentMap = new Map(webdavConfigs.map((c: WebDAVConfig) => [c.id, c])); - for (const cfg of backupData.webdavConfigs as WebDAVConfig[]) { - if (!cfg || !cfg.id) continue; - const existing = currentMap.get(cfg.id); - const isMasked = cfg.password === '***'; - if (existing) { - updateWebDAVConfig(cfg.id, { - name: cfg.name, - url: cfg.url, - username: cfg.username, - path: cfg.path, - // 仅当备份未掩码时才覆盖密码 - password: isMasked ? existing.password : cfg.password, - // 保留现有 isActive 状态 - isActive: existing.isActive, - }); - } else { - addWebDAVConfig({ - ...cfg, - password: isMasked ? '' : cfg.password, - isActive: false, - }); - } - } - } - } catch (e) { - console.warn('恢复 WebDAV 配置时发生问题:', e); - } - - alert(t( - `已从备份恢复数据:仓库 ${backupData.repositories?.length ?? 0},发布 ${backupData.releases?.length ?? 0},自定义分类 ${backupData.customCategories?.length ?? 0}。`, - `Data restored from backup: repositories ${backupData.repositories?.length ?? 0}, releases ${backupData.releases?.length ?? 0}, custom categories ${backupData.customCategories?.length ?? 0}.` - )); - } - } catch (error) { - console.error('Restore failed:', error); - alert(`${t('恢复失败', 'Restore failed')}: ${error.message}`); - } finally { - setIsRestoring(false); - } - }; - - const getDefaultPrompt = () => { - if (language === 'zh') { - return `请分析这个GitHub仓库并提供: - -1. 一个简洁的中文概述(不超过50字),说明这个仓库的主要功能和用途 -2. 3-5个相关的应用类型标签(用中文,类似应用商店的分类,如:开发工具、Web应用、移动应用、数据库、AI工具等{CATEGORIES_INFO ? ',请优先从提供的分类中选择' : ''}) -3. 支持的平台类型(从以下选择:mac、windows、linux、ios、android、docker、web、cli) - -重要:请严格使用中文进行分析和回复,无论原始README是什么语言。 - -请以JSON格式回复: -{ - "summary": "你的中文概述", - "tags": ["标签1", "标签2", "标签3", "标签4", "标签5"], - "platforms": ["platform1", "platform2", "platform3"] +import { useAppStore } from '../store/useAppStore'; +import { + GeneralPanel, + AIConfigPanel, + WebDAVPanel, + BackupPanel, + BackendPanel, + CategoryPanel, +} from './settings'; + +type SettingsTab = 'general' | 'ai' | 'webdav' | 'backup' | 'backend' | 'category'; + +interface SettingsPanelProps { + isOpen?: boolean; + onClose?: () => void; + isModal?: boolean; } -仓库信息: -{REPO_INFO}{CATEGORIES_INFO} - -重点关注实用性和准确的分类,帮助用户快速理解仓库的用途和支持的平台。`; - } else { - return `Please analyze this GitHub repository and provide: - -1. A concise English overview (no more than 50 words) explaining the main functionality and purpose of this repository -2. 3-5 relevant application type tags (in English, similar to app store categories, such as: development tools, web apps, mobile apps, database, AI tools, etc.{CATEGORIES_INFO ? ', please prioritize from the provided categories' : ''}) -3. Supported platform types (choose from: mac, windows, linux, ios, android, docker, web, cli) - -Important: Please strictly use English for analysis and response, regardless of the original README language. +export const SettingsPanel: React.FC = ({ + isOpen = true, + onClose, + isModal = false +}) => { + const { language, setCurrentView } = useAppStore(); + const [activeTab, setActiveTab] = useState('general'); -Please reply in JSON format: -{ - "summary": "Your English overview", - "tags": ["tag1", "tag2", "tag3", "tag4", "tag5"], - "platforms": ["platform1", "platform2", "platform3"] -} - -Repository information: -{REPO_INFO}{CATEGORIES_INFO} + const t = (zh: string, en: string) => (language === 'zh' ? zh : en); -Focus on practicality and accurate categorization to help users quickly understand the repository's purpose and supported platforms.`; - } - }; - - const t = (zh: string, en: string) => language === 'zh' ? zh : en; - const hiddenDefaultCategories = getAllCategories([], language, []).filter(category => hiddenDefaultCategoryIds.includes(category.id)); - - - const handleTestBackendConnection = async () => { - setBackendStatus('checking'); - // Save the secret first - setBackendApiSecret(backendSecretInput || null); - // Re-init and check - await backend.init(); - const health = await backend.checkHealth(); - const authOk = backendSecretInput ? await backend.verifyAuth() : true; - if (health && authOk) { - setBackendStatus('connected'); - setBackendHealth({ version: health.version, timestamp: health.timestamp }); - alert(t('后端连接成功!', 'Backend connection successful!')); + const handleClose = () => { + if (onClose) { + onClose(); } else { - setBackendStatus('disconnected'); - setBackendHealth(null); - alert(t( - '后端连接失败,请检查服务器状态或 API Secret 是否正确。', - 'Backend connection failed. Please check the server status or whether the API Secret is correct.' - )); - } - }; - - const handleSyncToBackend = async () => { - if (!backend.isAvailable) { - alert(t('后端不可用', 'Backend not available')); - return; - } - setIsSyncingToBackend(true); - try { - await backend.syncRepositories(repositories); - await backend.syncReleases(releases); - await backend.syncAIConfigs(aiConfigs); - await backend.syncWebDAVConfigs(webdavConfigs); - await backend.syncSettings({ hiddenDefaultCategoryIds }); - alert(t( - `已同步到后端:仓库 ${repositories.length},发布 ${releases.length},AI配置 ${aiConfigs.length},WebDAV配置 ${webdavConfigs.length}`, - `Synced to backend: repos ${repositories.length}, releases ${releases.length}, AI configs ${aiConfigs.length}, WebDAV configs ${webdavConfigs.length}` - )); - } catch (error) { - console.error('Sync to backend failed:', error); - alert(`${t('同步失败', 'Sync failed')}: ${(error as Error).message}`); - } finally { - setIsSyncingToBackend(false); + setCurrentView('repositories'); } }; - const handleSyncFromBackend = async () => { - if (!backend.isAvailable) { - alert(t('后端不可用', 'Backend not available')); - return; - } - - if (!confirm(t( - '从后端同步将覆盖本地数据,是否继续?', - 'Syncing from backend will overwrite local data. Continue?' - ))) return; - - setIsSyncingFromBackend(true); - try { - const repoData = await backend.fetchRepositories(); - const releaseData = await backend.fetchReleases(); - const aiConfigData = await backend.fetchAIConfigs(); - const webdavConfigData = await backend.fetchWebDAVConfigs(); - const settingsData = await backend.fetchSettings(); - - if (repoData.repositories.length > 0) { - setRepositories(repoData.repositories); - } - if (releaseData.releases.length > 0) { - setReleases(releaseData.releases); - } - if (aiConfigData.length > 0) { - setAIConfigs(aiConfigData); - } - if (webdavConfigData.length > 0) { - setWebDAVConfigs(webdavConfigData); - } - if (Array.isArray(hiddenDefaultCategoryIds)) { - for (const categoryId of hiddenDefaultCategoryIds) { - if (typeof categoryId === 'string') showDefaultCategory(categoryId); - } - } - if (Array.isArray(settingsData.hiddenDefaultCategoryIds)) { - for (const categoryId of settingsData.hiddenDefaultCategoryIds) { - if (typeof categoryId === 'string') hideDefaultCategory(categoryId); - } - } - - alert(t( - `已从后端同步:仓库 ${repoData.repositories.length},发布 ${releaseData.releases.length},AI配置 ${aiConfigData.length},WebDAV配置 ${webdavConfigData.length}`, - `Synced from backend: repos ${repoData.repositories.length}, releases ${releaseData.releases.length}, AI configs ${aiConfigData.length}, WebDAV configs ${webdavConfigData.length}` - )); - } catch (error) { - console.error('Sync from backend failed:', error); - alert(`${t('同步失败', 'Sync failed')}: ${(error as Error).message}`); - } finally { - setIsSyncingFromBackend(false); + const tabs: { id: SettingsTab; label: string; icon: React.ReactNode }[] = [ + { + id: 'general', + label: t('通用', 'General'), + icon: , + }, + { + id: 'ai', + label: t('AI配置', 'AI Config'), + icon: , + }, + { + id: 'webdav', + label: t('WebDAV', 'WebDAV'), + icon: , + }, + { + id: 'backup', + label: t('备份恢复', 'Backup'), + icon: , + }, + { + id: 'backend', + label: t('后端同步', 'Backend'), + icon: , + }, + { + id: 'category', + label: t('分类管理', 'Categories'), + icon: , + }, + ]; + + const renderTabContent = () => { + switch (activeTab) { + case 'general': + return ; + case 'ai': + return ; + case 'webdav': + return ; + case 'backup': + return ; + case 'backend': + return ; + case 'category': + return ; + default: + return null; } }; - - return ( -
- {/* Update Check */} -
-
- -

- {t('检查更新', 'Check for Updates')} -

-
- -
-
-

- {t('当前版本: v0.3.0', 'Current Version: v0.3.0')} -

-

- {t('检查是否有新版本可用', 'Check if a new version is available')} -

-
- -
-
- - {/* Language Settings */} -
-
- -

- {t('语言设置', 'Language Settings')} -

-
- -
- - -
-
- - {/* Language Settings */} -
-
- -

- {t('分类显示管理', 'Category Visibility')} -

-
- - {hiddenDefaultCategoryIds.length === 0 ? ( -

- {t('当前没有隐藏的默认分类。', 'No default categories are hidden right now.')} -

- ) : ( -
-

- {t('以下默认分类已被隐藏,你可以在这里恢复显示。', 'The following built-in categories are hidden. You can restore them here.')} -

-
- {hiddenDefaultCategories.map((category) => ( - - ))} + if (!isOpen) return null; + + // 模态框模式 + if (isModal) { + return ( +
+
+
+
+ +

+ {t('设置', 'Settings')} +

-
- )} -
- - {/* Contact Information */} -
-
- -

- {t('联系方式', 'Contact Information')} -

-
- -
-

- {t('如果您在使用过程中遇到任何问题或有建议,欢迎通过以下方式联系我:', 'If you encounter any issues or have suggestions while using the app, feel free to contact me through:')} -

- -
- -
-
-
- - {/* AI Configuration */} -
-
-
- -

- {t('AI服务配置', 'AI Service Configuration')} -

-
- -
- - {/* AI Config Form */} - {showAIForm && ( -
-

- {editingAIId ? t('编辑AI配置', 'Edit AI Configuration') : t('添加AI配置', 'Add AI Configuration')} -

- -
-
- - setAIForm(prev => ({ ...prev, name: e.target.value }))} - className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white" - placeholder={t('例如: OpenAI GPT-4', 'e.g., OpenAI GPT-4')} - /> -
-
- - -
- -
- - setAIForm(prev => ({ ...prev, baseUrl: e.target.value }))} - className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white" - placeholder={ - aiForm.apiType === 'openai' || aiForm.apiType === 'openai-responses' - ? 'https://api.openai.com/v1' - : aiForm.apiType === 'claude' - ? 'https://api.anthropic.com/v1' - : 'https://generativelanguage.googleapis.com/v1beta' - } - /> -

- {t( - '只填到版本号即可(如 .../v1 或 .../v1beta),不要包含 /chat/completions、/responses、/messages 或 :generateContent', - 'Only include the version prefix (e.g. .../v1 or .../v1beta). Do not include /chat/completions, /responses, /messages, or :generateContent.' - )} -

-
- -
- - setAIForm(prev => ({ ...prev, apiKey: e.target.value }))} - className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white" - placeholder={t('输入API密钥', 'Enter API key')} - /> -
- -
- - setAIForm(prev => ({ ...prev, model: e.target.value }))} - className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white" - placeholder="gpt-4" - /> -
- -
- - setAIForm(prev => ({ ...prev, concurrency: Math.max(1, Math.min(10, parseInt(e.target.value) || 1)) }))} - className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white" - placeholder="1" - /> -

- {t('同时进行AI分析的仓库数量 (1-10)', 'Number of repositories to analyze simultaneously (1-10)')} -

-
- -
- - -

- {t( - '仅对 OpenAI 兼容接口生效。留空时保持旧模式兼容,不额外传 reasoning。', - 'Only applies to OpenAI-compatible APIs. Leave empty to preserve legacy behavior and omit reasoning.' - )} -

-
-
- - {/* Custom Prompt Section */} -
-
- - {showCustomPrompt && ( +
+ {/* 侧边栏 - 桌面端 */} +
+
- - {showCustomPrompt && ( -
-