From f418692ad065ae1adf87c991a6ad3aa4cc3b6056 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 3 Sep 2026 17:07:19 +0800 Subject: [PATCH 1/3] =?UTF-8?q?build(lint):=20=E5=BC=95=E5=85=A5=20ESLint?= =?UTF-8?q?=20=E5=B7=A5=E5=85=B7=E9=93=BE=E4=B8=8E=20flat=20config=20?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E8=A7=84=E5=88=99=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - devDependencies: eslint 10 / typescript-eslint 8 / eslint-plugin-react-hooks 7 / globals / @eslint/js(ESLint 10 起 @eslint/js 不再随 eslint 自带,需显式安装) - eslint.config.js:@eslint/js recommended + typescript-eslint recommended(非 type-checked)+ react-hooks recommended(v7 的 React Compiler 语义规则档整体关闭——57 处存量误报,保留经典 rules-of-hooks / exhaustive-deps 双规则) - globals 分域:src/client → browser;src 根 / scripts / 根级 config → node;tests → node+browser - reportUnusedDisableDirectives: error 揪孤儿豁免;no-unused-vars 对齐仓库既有 _ 前缀占位约定 - package.json 增加 lint script(eslint .) --- eslint.config.js | 88 ++++ package.json | 10 +- pnpm-lock.yaml | 1317 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1413 insertions(+), 2 deletions(-) create mode 100644 eslint.config.js diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..cdda766 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,88 @@ +// ESLint flat config(最小规则集): +// - 基础:@eslint/js recommended + typescript-eslint recommended(非 type-checked 档, +// 全量 type-checked 需要项目服务且更慢,当前收益不足以引入); +// - react-hooks recommended:client 侧是 React 重镇,依赖数组豁免注释 +// (react-hooks/exhaustive-deps)由此规则消费; +// - globals 按运行域分治:client bundle → browser,host/脚本 → node,tests → 混合。 +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + // 构建产物 / 工具目录不参与 lint(node_modules 与点开头目录默认也不进)。 + { + ignores: [ + 'lib/', + 'dist/', + 'coverage/', + 'registry/', + 'playwright-report/', + 'test-results/', + 'node_modules/', + '.worktrees/', + ], + }, + + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + + // react-hooks v7 的 recommended 捆绑了 React Compiler 语义规则(purity / + // immutability / refs / set-state-in-effect 等):本仓库对 CodeMirror / xterm + // 等命令式集成大量依赖 render 期读 ref、effect 内同步 setState 的既有模式, + // 57 处存量报错均为噪音级误报,先整体关闭该档,只保留经典双规则 + // (rules-of-hooks / exhaustive-deps——后者消费代码里带理由的豁免注释)。 + { + rules: Object.fromEntries( + [ + 'config', + 'error-boundaries', + 'gating', + 'globals', + 'immutability', + 'incompatible-library', + 'preserve-manual-memoization', + 'purity', + 'refs', + 'set-state-in-effect', + 'static-components', + 'unsupported-syntax', + 'use-memo', + ].map(rule => [`react-hooks/${rule}`, 'off']), + ), + }, + + // 孤儿 eslint-disable 注释(规则未实际触发)直接报错,防止豁免残留。 + { linterOptions: { reportUnusedDisableDirectives: 'error' } }, + + // no-unused-vars 对齐仓库既有约定:下划线前缀 = 刻意不用的占位(mock 桩等)。 + { + rules: { + '@typescript-eslint/no-unused-vars': ['error', { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }], + }, + }, + + // client bundle 运行在浏览器(portal 侧边栏 / 各视图 / 拦截层)。 + { + files: ['src/client/**/*.{js,mjs,cjs,ts,tsx,jsx}'], + languageOptions: { globals: globals.browser }, + }, + + // host 侧插件入口与构建/运维脚本跑在 Node。eslint.config.js 自身不 ignore: + // 它就是一个普通 ESM 脚本,走 js recommended + node globals 正常通过。 + { + files: ['src/*.{js,mjs,cjs,ts}', 'scripts/**/*.{js,mjs,cjs,ts}', '*.config.ts', 'eslint.config.js'], + languageOptions: { globals: globals.node }, + }, + + // tests:Node 里跑(vitest / fs fixtures),jsdom 组件测试又摸浏览器全局。 + { + files: ['tests/**/*.{js,mjs,cjs,ts,tsx,jsx}'], + languageOptions: { globals: { ...globals.node, ...globals.browser } }, + }, +) diff --git a/package.json b/package.json index 4d9de77..07b3b2a 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,8 @@ "test:mount": "bash scripts/e2e-mount.sh", "test:mount:aggregate": "bash scripts/e2e-aggregate-mount.sh", "clean": "node -e \"require('node:fs').rmSync('lib',{recursive:true,force:true})\"", - "check:consumer-types": "bash scripts/check-consumer-types.sh" + "check:consumer-types": "bash scripts/check-consumer-types.sh", + "lint": "eslint ." }, "license": "MIT", "peerDependencies": { @@ -179,6 +180,11 @@ "tsdown": "^0.22.2", "typescript": "^5.6.0", "unrun": "^0.2.39", - "vitest": "^4.1.8" + "vitest": "^4.1.8", + "@eslint/js": "^10.0.1", + "eslint": "^10.9.1", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^17.12.0", + "typescript-eslint": "^8.69.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9222a4..f44d498 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -165,6 +165,9 @@ importers: '@deepseek-ai/dsh-util-time': specifier: 0.1.2-rc.1 version: 0.1.2-rc.1(@deepseek-ai/cordis@4.0.2) + '@eslint/js': + specifier: ^10.0.1 + version: 10.0.1(eslint@10.9.1) '@huanlin/dsh-plugin-better-locale': specifier: ^0.1.0 version: 0.1.0(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-client-locale@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-primitives@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-settings@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-slots@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -192,6 +195,15 @@ importers: cordis: specifier: ^4.0.0-rc.8 version: 4.0.0-rc.8(@cordisjs/plugin-loader@1.0.0-rc.5) + eslint: + specifier: ^10.9.1 + version: 10.9.1 + eslint-plugin-react-hooks: + specifier: ^7.1.1 + version: 7.1.1(eslint@10.9.1) + globals: + specifier: ^17.12.0 + version: 17.12.0 jsdom: specifier: ^29.1.1 version: 29.1.1 @@ -210,6 +222,9 @@ importers: typescript: specifier: ^5.6.0 version: 5.6.2 + typescript-eslint: + specifier: ^8.69.0 + version: 8.69.0(eslint@10.9.1)(typescript@5.6.2) unrun: specifier: ^0.2.39 version: 0.2.39 @@ -237,6 +252,73 @@ packages: '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@braintree/sanitize-url@7.1.2': resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} @@ -584,6 +666,45 @@ packages: '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/js@10.0.1': + resolution: {integrity: sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@exodus/bytes@1.15.1': resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -624,15 +745,63 @@ packages: react-dom: optional: true + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} '@iconify/utils@3.1.4': resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.12': + resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@lexical/clipboard@0.49.0': resolution: {integrity: sha512-AVKj21xH1qU7JAFA/v0hCoafa+Yti1I7cHG+JQIgc/EqCtP8ePeJyIfTPNN/tXskoCdq++HewQoiSXRwwlocVg==} peerDependencies: @@ -788,6 +957,10 @@ packages: '@oxc-project/types@0.146.0': resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@playwright/test@1.62.1': resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==} engines: {node: '>=20'} @@ -1135,6 +1308,9 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} @@ -1144,6 +1320,9 @@ packages: '@types/hast@3.0.5': resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/katex@0.16.8': resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==} @@ -1174,6 +1353,65 @@ packages: '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript-eslint/eslint-plugin@8.69.0': + resolution: {integrity: sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.69.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.69.0': + resolution: {integrity: sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.69.0': + resolution: {integrity: sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.69.0': + resolution: {integrity: sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.69.0': + resolution: {integrity: sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.69.0': + resolution: {integrity: sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.69.0': + resolution: {integrity: sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.69.0': + resolution: {integrity: sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.69.0': + resolution: {integrity: sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.69.0': + resolution: {integrity: sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.3': resolution: {integrity: sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==} @@ -1350,9 +1588,38 @@ packages: '@yuku-toolchain/types@0.8.7': resolution: {integrity: sha512-2Z53dNxAJL6UvFoIrDZvYf3zlO8s4VJK4O2hhaB4mXVwwpX/7ajtss3cmfqKvamlNLWyt9FSWs4eoYdlbxpnHA==} + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + anser@2.3.5: resolution: {integrity: sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ==} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} + engines: {node: '>=12'} + + ansi-styles@4.0.0: + resolution: {integrity: sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA==} + engines: {node: '>=8'} + + ansi-styles@6.1.0: + resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==} + engines: {node: '>=12'} + ansis@4.3.1: resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==} engines: {node: '>=14'} @@ -1361,9 +1628,33 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + balanced-match@1.0.0: + resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.11.20: + resolution: {integrity: sha512-H0ulySigv6icDJ1F7SjtdCD6PrhTpdYCmP0CactWy1+ekh0AFd0o1Wn5T8b+hnTmdBx19u9yhL6wvCylXMY7zw==} + engines: {node: '>=6.0.0'} + hasBin: true + bidi-js@1.0.3: resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} + + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + + browserslist@4.28.8: + resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1372,6 +1663,9 @@ packages: resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} engines: {node: '>=20.19.0'} + caniuse-lite@1.0.30001810: + resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1392,6 +1686,13 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -1442,6 +1743,10 @@ packages: crelt@1.0.7: resolution: {integrity: sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} @@ -1635,6 +1940,9 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + defu@6.1.7: resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} @@ -1664,6 +1972,18 @@ packages: oxc-resolver: optional: true + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.420: + resolution: {integrity: sha512-2yD6XreGusOfNV+dUcvipJEXc3n/n7fgr7996aszTG+YY5E4mqM4tOq/3uhP129cazL9YHbVWSpc79ePotWtPA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@2.0.1: resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} engines: {node: '>=14'} @@ -1678,17 +1998,82 @@ packages: es-toolkit@1.51.0: resolution: {integrity: sha512-zC2lQGkM7QX+Gm6iM3+WIdZJzthsEd14LvRNJneSO2hzyz/zNBENR8+YXWo1cKxgPBtV6ksPYHELbcwBRzmdCw==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.9.1: + resolution: {integrity: sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fastdom@1.0.12: resolution: {integrity: sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==} @@ -1701,6 +2086,25 @@ packages: picomatch: optional: true + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.0: + resolution: {integrity: sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==} + engines: {node: '>=16'} + + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} + + foreground-child@3.1.0: + resolution: {integrity: sha512-lXeSPRCndWPaipZbtI4CkvTZpF6OPsy19dkvf7+5AHeJD+w+iAKPc9Q78xWBmX4SdR+8xrtY9jTXs/YDv8q+Ug==} + engines: {node: '>=14'} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1711,10 +2115,27 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-tsconfig@5.0.0-beta.5: resolution: {integrity: sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==} engines: {node: '>=20.20.0'} + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.5.0: + resolution: {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 + hasBin: true + + globals@17.12.0: + resolution: {integrity: sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==} + engines: {node: '>=18'} + hachure-fill@0.5.2: resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} @@ -1724,6 +2145,12 @@ packages: hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + hookable@6.1.1: resolution: {integrity: sha512-U9LYDy1CwhMCnprUfeAZWZGByVbhd54hwepegYTK7Pi5NvqEj63ifz5z+xukznehT7i6NIZRu89Ay1AZmRsLEQ==} @@ -1738,6 +2165,14 @@ packages: resolution: {integrity: sha512-43ZpGYZ9QtuutX5l6WC1DSO8ane9N+Ct5qPLF2OV7vM9abM69gnAbVkh66ibaZd3aOGkoP1ZmringlKhLBkw2Q==} engines: {node: '>=0.10.0'} + ignore@5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + engines: {node: '>= 4'} + + ignore@7.0.8: + resolution: {integrity: sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==} + engines: {node: '>= 4'} + import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} @@ -1745,6 +2180,10 @@ packages: resolution: {integrity: sha512-NkJQA7oZ4YHQhd2+H3BoRFKF3d/XNsiKpHZCQEMH9pDX27hQQLsTyOocyRgaIVtf8gHX3Nt3LPkR4e5EdtPAGQ==} engines: {node: ^22.18.0 || >=24.0.0} + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + internmap@1.0.1: resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} @@ -1752,12 +2191,34 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.1.2: + resolution: {integrity: sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==} + engines: {node: '>=14'} + js-tokens@3.0.0: resolution: {integrity: sha512-poXEQHPMmTrYZuJgNRll2sbc3kJsSU1m/g1Q93IE6txNj3p6xOOOmdj1G/zCVGawYSPzTkSoWGg1otqbeqKJeg==} + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + jsdom@29.1.1: resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} @@ -1767,10 +2228,32 @@ packages: canvas: optional: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + katex@0.16.47: resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} hasBin: true + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} @@ -1780,6 +2263,10 @@ packages: layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + lexical@0.49.0: resolution: {integrity: sha512-9V1ZIzGpJEd8rIN+nN7veL4fW4fFWbS66Un4JNqSZB4D5t9euzN9+3+jEXy83FjNjNy0MiiUI3+DQaGCLYko0w==} peerDependencies: @@ -1862,6 +2349,10 @@ packages: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} @@ -1872,10 +2363,17 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + lru-cache@11.5.2: resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -2026,6 +2524,18 @@ packages: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -2037,6 +2547,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.4: resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} engines: {node: '>= 0.6'} @@ -2052,6 +2565,10 @@ packages: node-pty@1.1.0: resolution: {integrity: sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==} + node-releases@2.0.54: + resolution: {integrity: sha512-YHs7BmmcsdAI5Ozuf8JZo6PT0mv2GIWC9vMfvUC3dp65M8hn7Ux8CPL+2oBI7juNuj9d0ndhTcznq2ODBps9cQ==} + engines: {node: '>=18'} + obug@2.1.4: resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} engines: {node: '>=12.20.0'} @@ -2066,6 +2583,25 @@ packages: oniguruma-to-es@4.3.6: resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.0.2: + resolution: {integrity: sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@1.8.0: resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} @@ -2075,6 +2611,18 @@ packages: path-data-parser@0.1.0: resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -2105,6 +2653,10 @@ packages: resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} engines: {node: ^10 || ^12 || >=14} + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + property-information@7.2.0: resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} @@ -2145,6 +2697,11 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} + engines: {node: '>=14'} + hasBin: true + robust-predicates@3.0.3: resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} @@ -2202,6 +2759,23 @@ packages: schemastery@3.18.0: resolution: {integrity: sha512-Jw2uxjoyyqc/yeurmChUEc/jbi8GsrdXV/KmqRUDZXJAXAmrJiPsz8vKa17l/VckyzljHZ9oGaul443CQiXxtA==} + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + shiki@4.4.3: resolution: {integrity: sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==} engines: {node: '>=20'} @@ -2209,6 +2783,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2225,9 +2803,25 @@ packages: strictdom@1.0.1: resolution: {integrity: sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==} + string-width@4.2.0: + resolution: {integrity: sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + style-mod@4.1.3: resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} @@ -2274,6 +2868,12 @@ packages: trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-dedent@2.3.0: resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==} engines: {node: '>=6.10'} @@ -2315,6 +2915,17 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript-eslint@8.69.0: + resolution: {integrity: sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + typescript@5.6.2: resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} @@ -2358,6 +2969,15 @@ packages: synckit: optional: true + update-browserslist-db@1.3.2: + resolution: {integrity: sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uuid@14.0.2: resolution: {integrity: sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==} hasBin: true @@ -2479,11 +3099,28 @@ packages: resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + which@2.0.1: + resolution: {integrity: sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==} + engines: {node: '>= 8'} + hasBin: true + why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + ws@8.21.3: resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} engines: {node: '>=10.0.0'} @@ -2503,6 +3140,9 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yuku-ast@0.8.7: resolution: {integrity: sha512-h6+4bDfyootiMB9vckk5uKo5r5j0GHrkr17FQTDNfEsFT3DWlN9uu1HJwQwc64pgmLCI945fWM3lbTIqxjT3GQ==} @@ -2512,6 +3152,12 @@ packages: yuku-parser@0.8.7: resolution: {integrity: sha512-vRD9nwt4L3aYpxNqeSC4WqLv58xrXef0Ong1Mc45CTXTIpvLafx7JO05sczmQZwdLEZvywrLOGdNC5+Rp5N1BQ==} + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + zod@4.4.3: resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} @@ -2545,6 +3191,106 @@ snapshots: '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.12 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.8 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@braintree/sanitize-url@7.1.2': {} '@bramus/specificity@2.4.2': @@ -2985,6 +3731,40 @@ snapshots: tslib: 2.8.1 optional: true + '@eslint-community/eslint-utils@4.10.1(eslint@10.9.1)': + dependencies: + eslint: 10.9.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.6 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.7.0': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/core@1.2.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/js@10.0.1(eslint@10.9.1)': + optionalDependencies: + eslint: 10.9.1 + + '@eslint/object-schema@3.0.5': {} + + '@eslint/plugin-kit@0.7.2': + dependencies: + '@eslint/core': 1.2.1 + levn: 0.4.1 + '@exodus/bytes@1.15.1': {} '@huanlin/dsh-plugin-better-locale@0.1.0(@deepseek-ai/cordis@4.0.2)(@deepseek-ai/dsh-client-locale@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-primitives@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-settings@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-client-ui-slots@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(@deepseek-ai/dsh-invariants@0.1.2-rc.1(@deepseek-ai/cordis@4.0.2))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': @@ -2999,6 +3779,22 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + '@iconify/types@2.0.0': {} '@iconify/utils@3.1.4': @@ -3007,8 +3803,44 @@ snapshots: '@iconify/types': 2.0.0 import-meta-resolve: 4.2.0 + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.0 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.12': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + '@lexical/clipboard@0.49.0(typescript@5.6.2)': dependencies: '@lexical/extension': 0.49.0(typescript@5.6.2) @@ -3207,6 +4039,9 @@ snapshots: '@oxc-project/types@0.146.0': {} + '@pkgjs/parseargs@0.11.0': + optional: true + '@playwright/test@1.62.1': dependencies: playwright: 1.62.1 @@ -3490,6 +4325,8 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/esrecurse@4.3.1': {} + '@types/estree@1.0.9': {} '@types/geojson@7946.0.16': {} @@ -3498,6 +4335,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/json-schema@7.0.15': {} + '@types/katex@0.16.8': {} '@types/mdast@4.0.4': @@ -3529,6 +4368,97 @@ snapshots: dependencies: '@types/node': 24.13.3 + '@typescript-eslint/eslint-plugin@8.69.0(@typescript-eslint/parser@8.69.0(eslint@10.9.1)(typescript@5.6.2))(eslint@10.9.1)(typescript@5.6.2)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + '@typescript-eslint/scope-manager': 8.69.0 + '@typescript-eslint/type-utils': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + '@typescript-eslint/utils': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.69.0 + eslint: 10.9.1 + ignore: 7.0.8 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.6.2) + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.69.0(eslint@10.9.1)(typescript@5.6.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.69.0 + '@typescript-eslint/types': 8.69.0 + '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.6.2) + '@typescript-eslint/visitor-keys': 8.69.0 + debug: 4.4.3 + eslint: 10.9.1 + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.69.0(typescript@5.6.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.69.0(typescript@5.6.2) + '@typescript-eslint/types': 8.69.0 + debug: 4.4.3 + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.69.0': + dependencies: + '@typescript-eslint/types': 8.69.0 + '@typescript-eslint/visitor-keys': 8.69.0 + + '@typescript-eslint/tsconfig-utils@8.69.0(typescript@5.6.2)': + dependencies: + typescript: 5.6.2 + + '@typescript-eslint/type-utils@8.69.0(eslint@10.9.1)(typescript@5.6.2)': + dependencies: + '@typescript-eslint/types': 8.69.0 + '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + debug: 4.4.3 + eslint: 10.9.1 + ts-api-utils: 2.5.0(typescript@5.6.2) + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.69.0': {} + + '@typescript-eslint/typescript-estree@8.69.0(typescript@5.6.2)': + dependencies: + '@typescript-eslint/project-service': 8.69.0(typescript@5.6.2) + '@typescript-eslint/tsconfig-utils': 8.69.0(typescript@5.6.2) + '@typescript-eslint/types': 8.69.0 + '@typescript-eslint/visitor-keys': 8.69.0 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@5.6.2) + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.69.0(eslint@10.9.1)(typescript@5.6.2)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1) + '@typescript-eslint/scope-manager': 8.69.0 + '@typescript-eslint/types': 8.69.0 + '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.6.2) + eslint: 10.9.1 + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.69.0': + dependencies: + '@typescript-eslint/types': 8.69.0 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.3': {} '@upsetjs/venn.js@2.0.0': @@ -3655,20 +4585,67 @@ snapshots: '@yuku-toolchain/types@0.8.7': {} + acorn-jsx@5.3.2(acorn@8.18.0): + dependencies: + acorn: 8.18.0 + + acorn@8.18.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + anser@2.3.5: {} + ansi-regex@5.0.1: {} + + ansi-regex@6.3.0: {} + + ansi-styles@4.0.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.1.0: {} + ansis@4.3.1: {} assertion-error@2.0.1: {} + balanced-match@1.0.0: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.11.20: {} + bidi-js@1.0.3: dependencies: require-from-string: 2.0.2 + brace-expansion@2.1.4: + dependencies: + balanced-match: 1.0.0 + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.28.8: + dependencies: + baseline-browser-mapping: 2.11.20 + caniuse-lite: 1.0.30001810 + electron-to-chromium: 1.5.420 + node-releases: 2.0.54 + update-browserslist-db: 1.3.2(browserslist@4.28.8) + bytes@3.1.2: {} cac@7.0.0: {} + caniuse-lite@1.0.30001810: {} + ccount@2.0.1: {} chai@6.2.2: {} @@ -3681,6 +4658,12 @@ snapshots: clsx@2.1.1: {} + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + comma-separated-tokens@2.0.3: {} commander@7.0.0: {} @@ -3726,6 +4709,12 @@ snapshots: crelt@1.0.7: {} + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.1 + css-tree@3.2.1: dependencies: mdn-data: 2.27.1 @@ -3940,6 +4929,8 @@ snapshots: dependencies: character-entities: 2.0.2 + deep-is@0.1.4: {} + defu@6.1.7: {} delaunator@5.1.0: @@ -3960,6 +4951,14 @@ snapshots: dts-resolver@3.0.0: {} + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.420: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + empathic@2.0.1: {} entities@8.0.0: {} @@ -3968,14 +4967,99 @@ snapshots: es-toolkit@1.51.0: {} + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + escape-string-regexp@5.0.0: {} + eslint-plugin-react-hooks@7.1.1(eslint@10.9.1): + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.8 + eslint: 10.9.1 + hermes-parser: 0.25.1 + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@10.9.1: + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.9.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.7.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.2 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.2.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + minimatch: 10.2.6 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@11.2.0: + dependencies: + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) + eslint-visitor-keys: 5.0.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 + esutils@2.0.3: {} + expect-type@1.4.0: {} + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + fastdom@1.0.12: dependencies: strictdom: 1.0.1 @@ -3984,16 +5068,55 @@ snapshots: optionalDependencies: picomatch: 4.0.5 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.0: + dependencies: + flatted: 3.4.4 + keyv: 4.5.4 + rimraf: 5.0.5 + + flatted@3.4.4: {} + + foreground-child@3.1.0: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + fsevents@2.3.2: optional: true fsevents@2.3.3: optional: true + gensync@1.0.0-beta.2: {} + get-tsconfig@5.0.0-beta.5: dependencies: resolve-pkg-maps: 1.0.0 + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.5.0: + dependencies: + foreground-child: 3.1.0 + jackspeak: 3.1.2 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globals@17.12.0: {} + hachure-fill@0.5.2: {} hast-util-to-html@9.0.5: @@ -4014,6 +5137,12 @@ snapshots: dependencies: '@types/hast': 3.0.5 + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + hookable@6.1.1: {} html-encoding-sniffer@6.0.0: @@ -4028,18 +5157,42 @@ snapshots: dependencies: safer-buffer: 2.1.2 + ignore@5.2.0: {} + + ignore@7.0.8: {} + import-meta-resolve@4.2.0: {} import-without-cache@0.4.0: {} + imurmurhash@0.1.4: {} + internmap@1.0.1: {} internmap@2.0.3: {} + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + is-potential-custom-element-name@1.0.1: {} + isexe@2.0.0: {} + + jackspeak@3.1.2: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + js-tokens@3.0.0: {} + js-tokens@4.0.0: {} + jsdom@29.1.1: dependencies: '@asamuzakjp/css-color': 5.1.11 @@ -4066,16 +5219,35 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + katex@0.16.47: dependencies: commander: 8.3.0 + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + khroma@2.1.0: {} layout-base@1.0.2: {} layout-base@2.0.1: {} + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + lexical@0.49.0(typescript@5.6.2): dependencies: '@lexical/internal': 0.49.0(typescript@5.6.2) @@ -4131,6 +5303,10 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + lodash-es@4.18.1: {} longest-streak@3.1.0: {} @@ -4139,8 +5315,14 @@ snapshots: dependencies: js-tokens: 3.0.0 + lru-cache@10.2.0: {} + lru-cache@11.5.2: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4515,12 +5697,24 @@ snapshots: mime-db@1.54.0: {} + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.4 + + minipass@7.1.3: {} + ms@2.0.0: {} ms@2.1.3: {} nanoid@3.3.18: {} + natural-compare@1.4.0: {} + negotiator@0.6.4: {} negotiator@1.1.0: @@ -4533,6 +5727,8 @@ snapshots: dependencies: node-addon-api: 7.1.0 + node-releases@2.0.54: {} + obug@2.1.4: {} on-headers@1.1.0: {} @@ -4545,6 +5741,27 @@ snapshots: regex: 6.1.0 regex-recursion: 6.0.2 + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.0.2: + dependencies: + p-try: 2.2.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.0.2 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + package-manager-detector@1.8.0: {} parse5@8.0.1: @@ -4553,6 +5770,15 @@ snapshots: path-data-parser@0.1.0: {} + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.2.0 + minipass: 7.1.3 + pathe@2.0.3: {} picocolors@1.1.1: {} @@ -4580,6 +5806,8 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + prelude-ls@1.2.1: {} + property-information@7.2.0: {} punycode@2.3.1: {} @@ -4614,6 +5842,10 @@ snapshots: resolve-pkg-maps@1.0.0: {} + rimraf@5.0.5: + dependencies: + glob: 10.5.0 + robust-predicates@3.0.3: {} rolldown-plugin-dts@0.27.14(rolldown@1.2.5)(typescript@5.6.2): @@ -4702,6 +5934,16 @@ snapshots: '@standard-schema/spec': 1.1.0 cosmokit: 1.8.1 + semver@6.3.1: {} + + semver@7.8.5: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + shiki@4.4.3: dependencies: '@shikijs/core': 4.4.3 @@ -4715,6 +5957,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@4.1.0: {} + source-map-js@1.2.1: {} space-separated-tokens@2.0.2: {} @@ -4725,11 +5969,31 @@ snapshots: strictdom@1.0.1: {} + string-width@4.2.0: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.3.0 + style-mod@4.1.3: {} stylis@4.4.0: {} @@ -4765,6 +6029,10 @@ snapshots: trim-lines@3.0.1: {} + ts-api-utils@2.5.0(typescript@5.6.2): + dependencies: + typescript: 5.6.2 + ts-dedent@2.3.0: {} tsdown@0.22.14(typescript@5.6.2)(unrun@0.2.39): @@ -4795,6 +6063,21 @@ snapshots: tslib@2.8.1: {} + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript-eslint@8.69.0(eslint@10.9.1)(typescript@5.6.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.69.0(@typescript-eslint/parser@8.69.0(eslint@10.9.1)(typescript@5.6.2))(eslint@10.9.1)(typescript@5.6.2) + '@typescript-eslint/parser': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + '@typescript-eslint/typescript-estree': 8.69.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.69.0(eslint@10.9.1)(typescript@5.6.2) + eslint: 10.9.1 + typescript: 5.6.2 + transitivePeerDependencies: + - supports-color + typescript@5.6.2: {} unconfig-core@7.5.0: @@ -4838,6 +6121,16 @@ snapshots: dependencies: rolldown: 1.0.0-rc.17 + update-browserslist-db@1.3.2(browserslist@4.28.8): + dependencies: + browserslist: 4.28.8 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + uuid@14.0.2: {} vary@1.1.2: {} @@ -4911,17 +6204,37 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + which@2.0.1: + dependencies: + isexe: 2.0.0 + why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 stackback: 0.0.2 + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.0.0 + string-width: 4.2.0 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.1.0 + string-width: 5.1.2 + strip-ansi: 7.2.0 + ws@8.21.3: {} xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} + yallist@3.1.1: {} + yuku-ast@0.8.7: dependencies: '@yuku-toolchain/types': 0.8.7 @@ -4961,6 +6274,10 @@ snapshots: '@yuku-parser/binding-win32-arm64': 0.8.7 '@yuku-parser/binding-win32-x64': 0.8.7 + zod-validation-error@4.0.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + zod@4.4.3: {} zwitch@2.0.4: {} From 5a1e75e46b1cc3842a6cd4ad6489d8cdd222cef5 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 3 Sep 2026 17:07:32 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(lint):=20=E6=B8=85=E9=9B=B6=E5=AD=98?= =?UTF-8?q?=E9=87=8F=20lint=20=E5=91=8A=E8=AD=A6=E5=B9=B6=E6=8E=A5?= =?UTF-8?q?=E5=85=A5=20CI=20/=20Makefile=20=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 存量清理(首跑 141 errors / 21 warnings → 0 / 0): - 删除孤儿 disable:SideChatView / Sidebar / selection-popup 三处 exhaustive-deps 豁免与 chunk-artifact 的 no-new-func 豁免(多行理由注释把 disable-next-line 顶离了实报行;selection-popup 改为提取 popupOpen 标志真修复) - 死代码:未用导入(Sidebar×7、TextEditor、SideCardSection、config、fs-operations 及 6 个 spec)、sidechat-core 死累加器 total、chunk-loader.spec 死助手 registry、sidechat-seed-validation 死助手 toolResultMessage - 真实小修:agent-opens 三处 throw 补 cause;lazy-chunk any → ComponentType

(P extends object);service.ts claimed 初值改定值赋值;chunk-loader task / spec 内 etag / pendingLoad / snapshot 改 const;terminal-links 去掉字符类内多余转义;SubagentView catalogs 空兜底 useMemo 稳定标识;editor-host.spec 组件提出大写 FakeViewer(rules-of-hooks);pty-helpers.spec 内联 require 提升为静态导入;panel-host-css 注释里的零宽空格改为可见写法 - 依赖数组豁免(均带理由):granular scope 字段(EditorHost / PdfView / ChangesTab / GitLens×2)、job.status 粒度(SubagentView×2)、清理期读 ref、mount-only 注册等;ctx(挂载期恒定)直接入 deps(Sidebar×3)、TextEditor previewScroll 补 scope(幂等) - 刻意控制字符正则(conversation-draft / markdown-images)与宿主槽位 any 签名(context-types)以带理由豁免保留 接入: - Makefile:lint 目标(typecheck 旁),check 聚合补 lint 保持「对齐 CI」语义 - ci.yml ci / ci-windows 两 job 与 release.yml 在 Typecheck 后加 Lint 步骤(release 注释同步顺序) --- .github/workflows/ci.yml | 4 ++++ .github/workflows/release.yml | 8 +++++-- Makefile | 10 ++++---- src/agent-opens.ts | 6 ++--- src/client/EditorHost.tsx | 3 +++ src/client/PdfView.tsx | 3 +++ src/client/SideCardSection.tsx | 1 - src/client/SideChatView.tsx | 3 +-- src/client/Sidebar.tsx | 21 +++++++++-------- src/client/SubagentView.tsx | 12 +++++++++- src/client/TextEditor.tsx | 10 ++++++-- src/client/add-plugin-modal.tsx | 2 +- src/client/builtins/tabs.tsx | 2 +- src/client/changes/ChangesTab.tsx | 3 +++ src/client/changes/GitLens.tsx | 6 +++++ src/client/chunk-loader.ts | 3 +-- src/client/conversation-draft.ts | 1 + src/client/index.tsx | 2 +- src/client/lazy-chunk.tsx | 4 ++-- src/client/markdown-images.ts | 1 + src/client/selection-popup.ts | 11 ++++----- src/client/service.ts | 2 +- src/client/terminal-links.ts | 2 +- src/config.ts | 2 -- src/context-types.ts | 1 + src/fs-operations.ts | 1 - src/sidechat-core.ts | 3 --- tests/add-plugin-modal.spec.tsx | 3 +-- tests/agent-pty.spec.ts | 1 - tests/chunk-artifact.spec.ts | 1 - tests/chunk-loader.spec.ts | 10 ++------ tests/consumer-types.ts | 4 ++-- tests/editor-host.spec.tsx | 32 +++++++++++++++----------- tests/fs-operations.spec.ts | 2 +- tests/markdown-manual-refresh.spec.tsx | 2 ++ tests/panel-host-css.spec.ts | 2 +- tests/pty-helpers.spec.ts | 6 ++--- tests/sidechat-core.spec.ts | 1 - tests/sidechat-seed-validation.spec.ts | 9 -------- tests/sidechat-view.spec.tsx | 2 +- 40 files changed, 112 insertions(+), 90 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da30813..bcb900a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,8 @@ jobs: run: pnpm install --frozen-lockfile - name: Typecheck run: pnpm typecheck + - name: Lint + run: pnpm lint - name: Test run: pnpm test - name: Build @@ -88,6 +90,8 @@ jobs: run: pnpm install --frozen-lockfile - name: Typecheck run: pnpm typecheck + - name: Lint + run: pnpm lint - name: Test run: pnpm test - name: Build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 670dfa7..be1389c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,6 +88,9 @@ jobs: - name: Typecheck run: pnpm typecheck + - name: Lint + run: pnpm lint + - name: Test run: pnpm test @@ -95,8 +98,9 @@ jobs: run: pnpm build # The consumer-facing declaration surface guard — mirrors the ci.yml - # verification order (typecheck → test → build → check:consumer-types) - # so a release is gated on the same checks a PR runs. + # verification order (typecheck → lint → test → build → + # check:consumer-types) so a release is gated on the same checks a PR + # runs. - name: Check consumer type surface run: pnpm check:consumer-types diff --git a/Makefile b/Makefile index f703433..9bd14bd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,6 @@ # dsh-better-sidebar 命令面薄封装:目标仅转发 package.json scripts(唯一事实源), # 新增/改名 script 不需要动这里;本文件只补目标发现(help)与 CI 门禁聚合 # (check / mount / mount-aggregate / registry)。 -# 注:lint 目标留给引入 ESLint 的后续 PR。 .DEFAULT_GOAL := help @@ -17,11 +16,14 @@ build: ## 构建(清 lib/ → tsc → tsdown) typecheck: ## 类型检查(tsc --noEmit) pnpm typecheck +lint: ## 代码检查(eslint .,flat config 最小规则集) + pnpm lint + test: ## 单元测试(vitest run) pnpm test -check: ## 聚合校验门禁:typecheck → build → test → check:consumer-types(对齐 CI) - pnpm typecheck && pnpm build && pnpm test && pnpm check:consumer-types +check: ## 聚合校验门禁:typecheck → lint → build → test → check:consumer-types(对齐 CI) + pnpm typecheck && pnpm lint && pnpm build && pnpm test && pnpm check:consumer-types clean: ## 清理构建产物与测试报告(lib/、*.tgz、playwright-report/、test-results/) rm -rf lib playwright-report test-results @@ -39,4 +41,4 @@ mount-aggregate: ## 聚合双挂载回归:build + pack → pnpm test:mount:agg registry: ## 组装 plugin-registry 暂存(registry/,不入库):build → node scripts/package-registry.mjs pnpm build && node scripts/package-registry.mjs -.PHONY: help install build typecheck test check clean pack mount mount-aggregate registry +.PHONY: help install build typecheck lint test check clean pack mount mount-aggregate registry diff --git a/src/agent-opens.ts b/src/agent-opens.ts index f0af56d..d102920 100644 --- a/src/agent-opens.ts +++ b/src/agent-opens.ts @@ -158,9 +158,9 @@ async function classifyTarget(raw: string, cwd: string): Promise<{ kind: AgentOp info = await stat(target) } catch (error) { const code = (error as NodeJS.ErrnoException).code - if (code === 'ENOENT') throw new Error(`"${raw}" does not exist (resolved to "${target}")`) - if (code === 'EACCES' || code === 'EPERM') throw new Error(`"${target}" is not readable`) - throw new Error(`cannot open "${target}": ${error instanceof Error ? error.message : String(error)}`) + if (code === 'ENOENT') throw new Error(`"${raw}" does not exist (resolved to "${target}")`, { cause: error }) + if (code === 'EACCES' || code === 'EPERM') throw new Error(`"${target}" is not readable`, { cause: error }) + throw new Error(`cannot open "${target}": ${error instanceof Error ? error.message : String(error)}`, { cause: error }) } const title = basenameOf(target) return { kind: info.isDirectory() ? 'folder' : 'file', target, title: title === '' ? raw : title } diff --git a/src/client/EditorHost.tsx b/src/client/EditorHost.tsx index e1459a9..4411f58 100644 --- a/src/client/EditorHost.tsx +++ b/src/client/EditorHost.tsx @@ -338,6 +338,9 @@ export function EditorHost(props: { } apply(planFirstMatch(ctx.get('betterSidebar')?.matchFileViewer(path), mediaUrlOf)) return () => { cancelled = true; controller.abort() } + // The deps are deliberately granular: the scope object's identity churns, + // only its sessionId / cwd fields gate the (re)fetch. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [scope.sessionId, scope.cwd, path, ctx, showEmpty, isDir, reloadSeq]) // Save-then-refresh in preview mode (issue #167 part C): the edge into diff --git a/src/client/PdfView.tsx b/src/client/PdfView.tsx index c59ccb9..8cb7ab3 100644 --- a/src/client/PdfView.tsx +++ b/src/client/PdfView.tsx @@ -40,6 +40,9 @@ export function PdfView(props: { scope: SessionScope; path: string; title: strin controller.abort() if (objectUrl !== undefined) URL.revokeObjectURL(objectUrl) } + // Granular scope fields: the scope object's identity churns, only its + // sessionId / cwd fields gate the fetch. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [scope.sessionId, scope.cwd, path]) useEffect(() => { diff --git a/src/client/SideCardSection.tsx b/src/client/SideCardSection.tsx index 5a6e0a2..f0596f8 100644 --- a/src/client/SideCardSection.tsx +++ b/src/client/SideCardSection.tsx @@ -60,7 +60,6 @@ import { WIDTH_PERCENT_MAX, WIDTH_PERCENT_MIN, type SidebarPrefs, - type TitleBarScheme, } from '../prefs-shared.ts' import { api } from './api.ts' import { parsePrefs } from './prefs.ts' diff --git a/src/client/SideChatView.tsx b/src/client/SideChatView.tsx index f6ed825..e80abbd 100644 --- a/src/client/SideChatView.tsx +++ b/src/client/SideChatView.tsx @@ -574,7 +574,6 @@ export function SideChatView(props: { } } return items - // eslint-disable-next-line react-hooks/exhaustive-deps }, [threads]) const growComposer = (): void => { @@ -688,7 +687,7 @@ export function SideChatView(props: { )} items={menuItems} selectedId={threadId} - onSelect={(id) => { id === '$new' ? openNewThread() : openExistingThread(id) }} + onSelect={(id) => { if (id === '$new') openNewThread(); else openExistingThread(id) }} onClose={() => { setMenuOpen(false) }} align="end" portal diff --git a/src/client/Sidebar.tsx b/src/client/Sidebar.tsx index 264591e..e2fbe0a 100644 --- a/src/client/Sidebar.tsx +++ b/src/client/Sidebar.tsx @@ -35,14 +35,13 @@ import { IconCloseFill14, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives' import type { Context, SidebarSessionList } from '../context-types.ts' import { appendToDraft, insertFileReference } from './conversation-draft.ts' import { - BOTTOM_MIN, PANEL_MIN, activateTab, agentUuidOf, allLeaves, closeFloatByTab, closeTab, dockFloat, firstLeaf, floatTab, - floatWithTab, isAgentTabId, leafWithTab, migrateBottomTabs, - moveFloat, moveTab, moveTabToEdge, openDiffTab, openTabInActivePane, raiseFloat, reconcileAgentTerminals, + BOTTOM_MIN, PANEL_MIN, agentUuidOf, closeFloatByTab, closeTab, dockFloat, firstLeaf, floatTab, + isAgentTabId, leafWithTab, migrateBottomTabs, + moveFloat, moveTab, moveTabToEdge, openDiffTab, raiseFloat, reconcileAgentTerminals, resizeFloat, resizeSplitIn, setBottomHeight, setTabPin, setWidth, toggleBottomPanel, toggleExpanded, togglePanel, - type DropZone, type SidebarState, type SidebarStore, type SidebarTab, type SplitNode, + type DropZone, type SidebarState, type SidebarStore, type SidebarTab, } from './state.ts' -import { collectPinnedTabs, createPinnedVirtualTab, getPinnedHomeScope, injectPinnedIntoTree, isPinnedVirtualId, isPinnedVirtualTab, parsePinnedVirtualId, type PinnedTabEntry } from './pinned.ts' -import { IconPinOutline16 } from './icons.tsx' +import { collectPinnedTabs, createPinnedVirtualTab, getPinnedHomeScope, injectPinnedIntoTree, isPinnedVirtualId, parsePinnedVirtualId, type PinnedTabEntry } from './pinned.ts' import { IconPanelBottomOutline16, IconPanelRightOutline16 } from './icons.tsx' import { Workbench, type WorkbenchActions } from './split-pane.tsx' import { isNarrowWidth, useViewportSize } from './breakpoints.ts' @@ -418,7 +417,6 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { // for the descriptors' available() callbacks. (The render's own guard // sits below every hook; this memo must handle the no-session case // itself.) - // eslint-disable-next-line react-hooks/exhaustive-deps [state, ctx, sessionId, cwd], ) @@ -476,7 +474,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { window.clearTimeout(retry) socket?.close() } - }, [sessionId, store]) + }, [sessionId, ctx, store]) /** * Agent opens push: subscribe to the host's `sidebar_open` requests for @@ -548,7 +546,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { window.clearTimeout(retry) socket?.close() } - }, [sessionId, store]) + }, [sessionId, ctx, store]) /** * Subagent auto-activation: the moment the current conversation spawns its @@ -679,6 +677,9 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { const pinnedEntries: readonly PinnedTabEntry[] = useMemo(() => { if (sessionId === undefined) return [] return collectPinnedTabs(store.getSessionStates(), { sessionId, cwd }) + // snapshot / pinnedRevision are deliberate cache-busters (see the comment + // above): they recompute this memo for changes that carry no dep of their own. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [store, sessionId, cwd, snapshot, pinnedRevision]) /** Virtual SidebarTab objects for the pinned entries (stable references @@ -1297,7 +1298,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { pinTab: (tabId, scope) => { store.reduce(s => setTabPin(s, tabId, scope === null ? null : { scope, homeCwd: cwd })) }, - }), [store, sessionId, cwd]) + }), [store, sessionId, cwd, ctx]) /** * Wrap the base actions to intercept pinned VIRTUAL tab ids (injected from diff --git a/src/client/SubagentView.tsx b/src/client/SubagentView.tsx index 3f28979..739844f 100644 --- a/src/client/SubagentView.tsx +++ b/src/client/SubagentView.tsx @@ -415,6 +415,9 @@ function JobOutputPane(props: { if (!active || !isJobLive(job)) return const timer = window.setInterval(() => { void load() }, JOB_POLL_MS) return () => { window.clearInterval(timer) } + // isJobLive reads only job.status; whole-job identity churns on every + // catalog refresh and must not restart the poll interval. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [load, active, job.status]) useEffect(() => () => { controllerRef.current?.abort() }, []) @@ -425,6 +428,8 @@ function JobOutputPane(props: { if (!isJobLive(job) || typeof state !== 'object' || state.text.length === 0) return const pre = preRef.current if (pre !== null) pre.scrollTop = pre.scrollHeight + // Same as the poll effect above: only the status transition matters. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [state, job.status]) return ( @@ -656,7 +661,9 @@ export function SubagentView(props: { useCallback(() => sessions.list.getSnapshot(), [sessions]), ) const byId = list.byId - const catalogs = list.subagentsByParent ?? {} + // Memoized so the empty-catalog fallback keeps a stable identity — a fresh + // `{}` per render would invalidate every catalog-dependent memo/effect. + const catalogs = useMemo(() => list.subagentsByParent ?? {}, [list.subagentsByParent]) // The topology root: the main agent of the current session's tree. const rootId = useMemo(() => rootAncestor(byId, sessionId), [byId, sessionId]) @@ -680,6 +687,9 @@ export function SubagentView(props: { if (rootId === undefined || !active) return observe(rootId, true) return () => { + // The cleanup must release everything observed AT cleanup time (the set + // mutates as branches open), so reading the ref here is the point. + // eslint-disable-next-line react-hooks/exhaustive-deps for (const parentSessionId of observedRef.current) { sessions.setSubagentCatalogOpen?.(parentSessionId, false) } diff --git a/src/client/TextEditor.tsx b/src/client/TextEditor.tsx index 4ce8318..459eaf0 100644 --- a/src/client/TextEditor.tsx +++ b/src/client/TextEditor.tsx @@ -31,7 +31,6 @@ import { SandboxStatusBar } from './SandboxStatusBar.tsx' import { appendToDraft } from './conversation-draft.ts' import { useSelectionPopup } from './selection-popup.ts' import { buildSelectionInsert, linesOfSelection } from './selection-payload.ts' -import { lazyChunkComponent } from './lazy-chunk.tsx' import { analyzeMarkdownHtml } from './markdown-html.ts' import { LazyMermaidMarkdown, MarkdownDocument, type MarkdownHtmlMedia } from './MarkdownHtml.tsx' import { MdToc } from './md-toc.tsx' @@ -117,13 +116,16 @@ export function TextEditor(props: FileViewerProps) { setDirty(false) setSaveState('idle') selectionPopup.hide() + // hide() reads a live ref; the reset must fire only on a content (file) + // swap, and the hook object's identity churns on every render. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [content]) // A different file switches the remembered preview scroll position to that // file's own entry (first open: none, so the preview starts at the top). useEffect(() => { previewScrollRef.current = previewScrollMemory.get(previewScrollKey(scope, path)) ?? 0 - }, [path]) + }, [scope, path]) // Create the CodeMirror editor once the content is loaded. The view owns // the document; React only tracks dirty state through the update listener @@ -220,6 +222,7 @@ export function TextEditor(props: FileViewerProps) { // The keymap's save() reads live refs; scope/path are stable for a // tab's lifetime, and the dark flip is handled by the reconfigure // effect below (recreating the view here would drop the draft). + // eslint-disable-next-line react-hooks/exhaustive-deps }, [content, path]) // Scheme flip: re-theme in place (the compartment holds only the @@ -276,6 +279,9 @@ export function TextEditor(props: FileViewerProps) { view.requestMeasure() }) }) + // The reveal reads the live document/view refs; only the flip into + // preview triggers it. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [mode]) // Snapshot the live document into the draft whenever the preview needs diff --git a/src/client/add-plugin-modal.tsx b/src/client/add-plugin-modal.tsx index fa6351a..8abb146 100644 --- a/src/client/add-plugin-modal.tsx +++ b/src/client/add-plugin-modal.tsx @@ -43,7 +43,7 @@ const COPIED_FEEDBACK_MS = 1500 /** The modal body: the GitHub topic button + the recommended plugin list * with per-entry jump/copy buttons (extracted for direct testing). */ export function PluginListBody(props: { service: BetterSidebarService; kind: PluginKind }) { - const { service, kind } = props + const { kind } = props // Which entry's copy button currently shows the "已复制" feedback. const [copiedId, setCopiedId] = useState(null) // Live catalog filter (name / id / description). A free-text search keeps diff --git a/src/client/builtins/tabs.tsx b/src/client/builtins/tabs.tsx index a4a131c..1a73d66 100644 --- a/src/client/builtins/tabs.tsx +++ b/src/client/builtins/tabs.tsx @@ -180,7 +180,7 @@ export function builtinTabs(ctx: Context, options: BuiltinTabOptions = {}): read ], }], }, - component: ({ ctx, store, scope, tab, visible, onOpenFile, onOpenDiff }) => ( + component: ({ ctx, store, scope, tab, visible, onOpenDiff }) => ( { pollGen.current += 1 diff --git a/src/client/changes/GitLens.tsx b/src/client/changes/GitLens.tsx index 106d06e..f3be2b1 100644 --- a/src/client/changes/GitLens.tsx +++ b/src/client/changes/GitLens.tsx @@ -168,6 +168,9 @@ export function GitLens(props: GitLensProps) { } finally { if (options.loading && options.generation === refreshGeneration.current) setLoading(false) } + // Granular scope fields: the scope object's identity churns, only its + // sessionId / cwd fields gate the git target. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [scope.sessionId, scope.cwd, repoRoot]) const refresh = useCallback(async (silent = false): Promise => { @@ -231,6 +234,9 @@ export function GitLens(props: GitLensProps) { } finally { refreshInFlight.current = false } + // Granular scope fields: the scope object's identity churns, only its + // sessionId / cwd fields gate the refresh target. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [scope.sessionId, scope.cwd, refreshTarget]) useEffect(() => { diff --git a/src/client/chunk-loader.ts b/src/client/chunk-loader.ts index 169da7c..0a9e87a 100644 --- a/src/client/chunk-loader.ts +++ b/src/client/chunk-loader.ts @@ -244,8 +244,7 @@ export async function loadChunk(name: ChunkName): Promise { if (revalidation !== null) await revalidation const cached = cache.get(name) if (cached !== undefined) return cached - let task: Promise - task = (async (): Promise => { + const task: Promise = (async (): Promise => { const test = testLoaders.get(name) if (test !== undefined) return test() const modules = moduleSystem() diff --git a/src/client/conversation-draft.ts b/src/client/conversation-draft.ts index 3432523..9235059 100644 --- a/src/client/conversation-draft.ts +++ b/src/client/conversation-draft.ts @@ -203,6 +203,7 @@ export function appendToDraft(ctx: Context, sessionId: string, text: string): bo */ export function fileMention(relativePath: string): { mention: string; label: string } | undefined { const path = relativePath.replace(/[\\/]+$/, '') + // eslint-disable-next-line no-control-regex -- rejecting control characters is the point of this guard if (/[\u0000-\u001f\u007f-\u009f"]/u.test(path)) return undefined const mention = /\s/u.test(path) ? `@"${path}"` : `@${path}` const at = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')) diff --git a/src/client/index.tsx b/src/client/index.tsx index 2915d42..32be1e3 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -297,7 +297,7 @@ export function apply(ctx: Context): void { // rides the same fetch, so one round trip covers both decisions). const decision = await Promise.race([ loadBootDecision(api), - new Promise(resolve => { const timer = window.setTimeout(() => resolve(null), 2000) }), + new Promise(resolve => { window.setTimeout(() => resolve(null), 2000) }), ]) if (disposed) return if (decision !== null) { diff --git a/src/client/lazy-chunk.tsx b/src/client/lazy-chunk.tsx index b8ce62a..a6aee3a 100644 --- a/src/client/lazy-chunk.tsx +++ b/src/client/lazy-chunk.tsx @@ -22,12 +22,12 @@ interface LazyChunkViewProps

{ props: P } -function LazyChunkView

({ chunk, pick, props }: LazyChunkViewProps

): ReactNode { +function LazyChunkView

({ chunk, pick, props }: LazyChunkViewProps

): ReactNode { const [attempt, setAttempt] = useState(0) const [state, setState] = useState< | { status: 'loading' } | { status: 'error'; message: string } - | { status: 'ready'; Comp: ComponentType } + | { status: 'ready'; Comp: ComponentType

} >({ status: 'loading' }) useEffect(() => { diff --git a/src/client/markdown-images.ts b/src/client/markdown-images.ts index cb223c9..c246b19 100644 --- a/src/client/markdown-images.ts +++ b/src/client/markdown-images.ts @@ -133,5 +133,6 @@ export function rewriteLocalImageUrls( return `${head}${resolve(dest.replace(/^<|>$/g, ''))}` }) + // eslint-disable-next-line no-control-regex -- NUL is the deliberate mask sentinel (cannot appear in source markdown) return refsRewritten.replace(/\u0000(\d+)\u0000/g, (_m, index: string) => masks[Number(index)] ?? '') } diff --git a/src/client/selection-popup.ts b/src/client/selection-popup.ts index 5386d9c..ae84427 100644 --- a/src/client/selection-popup.ts +++ b/src/client/selection-popup.ts @@ -133,9 +133,11 @@ export function useSelectionPopup(options: SelectionPopupOptions): SelectionPopu // Re-target the visibility observer whenever a popup opens: the surface // refs may have been null at mount (content loads async, mode flips swap // the preview container for the CodeMirror host), so the surface is only - // trustworthy at open time. + // trustworthy at open time. The boolean flip is the only thing that must + // re-run this; an anchor move while open keeps the same surface. + const popupOpen = popup !== null useEffect(() => { - if (popup === null) return + if (!popupOpen) return observerRef.current?.disconnect() observerRef.current = null if (typeof IntersectionObserver === 'undefined') return @@ -148,10 +150,7 @@ export function useSelectionPopup(options: SelectionPopupOptions): SelectionPopu }, { threshold: 0 }) observerRef.current = observer observer.observe(surface) - // eslint-disable-next-line react-hooks/exhaustive-deps -- the boolean - // flip is the only thing that must re-run this; an anchor move while - // open keeps the same surface. - }, [popup !== null]) + }, [popupOpen]) return { popup, buttonRef, show, hide, commit } } \ No newline at end of file diff --git a/src/client/service.ts b/src/client/service.ts index 9663ac9..12fe6aa 100644 --- a/src/client/service.ts +++ b/src/client/service.ts @@ -449,7 +449,7 @@ function baseNameOf(path: string): string { export function matchUrlTarget(tabs: readonly TabDescriptor[], url: URL): TabDescriptor | undefined { for (const tab of tabs) { if (tab.urlTarget === undefined) continue - let claimed = false + let claimed: boolean try { claimed = tab.urlTarget(url) === true } catch (error) { diff --git a/src/client/terminal-links.ts b/src/client/terminal-links.ts index 37834b9..7e68a91 100644 --- a/src/client/terminal-links.ts +++ b/src/client/terminal-links.ts @@ -38,7 +38,7 @@ const OPENABLE_SCHEMES = new Set(['http:', 'https:']) * match on a line; callers must reset `lastIndex` before reuse (the * helper does this defensively). */ -export const TERMINAL_URL_REGEX = /\bhttps?:\/\/[^\s"'<>\[\]{}|\\^`]+/gi +export const TERMINAL_URL_REGEX = /\bhttps?:\/\/[^\s"'<>[\]{}|\\^`]+/gi /** A URL match in a terminal line: the text and its 0-based start offset. */ export interface TerminalUrlMatch { diff --git a/src/config.ts b/src/config.ts index 4f1b227..3d055cb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,8 +7,6 @@ import z from 'schemastery' import { - SIDEBAR_PREFS_DEFAULTS, - SIDEBAR_PREFS_NS, TERMINAL_FONT_SIZE_DEFAULT, TERMINAL_FONT_SIZE_MAX, TERMINAL_FONT_SIZE_MIN, diff --git a/src/context-types.ts b/src/context-types.ts index d17faa1..3730749 100644 --- a/src/context-types.ts +++ b/src/context-types.ts @@ -119,6 +119,7 @@ export interface SidebarSlotRegisterOptions { locale?: string registrant?: string /** Business-face factory; args depend on the slot scope. */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mirrors the host slots signature, where inject args are untyped; unknown[] would reject concrete-typed implementations (contravariance) inject?: (...args: any[]) => Record children?: Record } diff --git a/src/fs-operations.ts b/src/fs-operations.ts index 919fe8a..fc6a48d 100644 --- a/src/fs-operations.ts +++ b/src/fs-operations.ts @@ -15,7 +15,6 @@ import { once } from 'node:events' import { createWriteStream } from 'node:fs' import { mkdir, rename, rm, stat } from 'node:fs/promises' import { basename, dirname, join } from 'node:path' -import type { SidebarHttpRequest } from './context-types.ts' import { requireAbsolute } from './fs-tree.ts' import { ensureWorkspacePath, ensureWorkspaceWritePath } from './path-security.ts' import { SidebarError } from './wire.ts' diff --git a/src/sidechat-core.ts b/src/sidechat-core.ts index 51b2a4b..af18208 100644 --- a/src/sidechat-core.ts +++ b/src/sidechat-core.ts @@ -259,7 +259,6 @@ export function buildOpenTurnSnapshot(events: readonly SidechatLogEvent[]): stri let reasoning = '' const tools: string[] = [] const pendingCalls = new Map() - let total = 0 for (let index = boundary + 1; index < events.length; index++) { const event = events[index] if (event === undefined) continue @@ -299,13 +298,11 @@ export function buildOpenTurnSnapshot(events: readonly SidechatLogEvent[]): stri ...(result === '' ? [] : [` Result: ${result}`]), ].join('\n') tools.push(line) - total += line.length } } for (const [, call] of pendingCalls) { const line = `- \`${call.name}\` (executing) — arguments: \`${call.args}\`` tools.push(line) - total += line.length } const sections: string[] = [] if (text.trim() !== '') sections.push(`Assistant output so far:\n\n${text}`) diff --git a/tests/add-plugin-modal.spec.tsx b/tests/add-plugin-modal.spec.tsx index d508dd0..85720e9 100644 --- a/tests/add-plugin-modal.spec.tsx +++ b/tests/add-plugin-modal.spec.tsx @@ -18,8 +18,7 @@ import { renderToString } from 'react-dom/server' import { createRoot } from 'react-dom/client' import { act } from 'react-dom/test-utils' import * as primitives from '@deepseek-ai/dsh-client-ui-primitives' -import { PLUGIN_TOPIC_URL, type PluginEntry } from '../src/client/plugins-shared.ts' -import { builtinTabPlugins } from '../src/client/plugins-tabs.ts' +import { type PluginEntry } from '../src/client/plugins-shared.ts' import { builtinViewerPlugins } from '../src/client/plugins-viewers.ts' import { AddPluginModal, PluginListBody } from '../src/client/add-plugin-modal.tsx' import { createBetterSidebarService } from '../src/client/service.ts' diff --git a/tests/agent-pty.spec.ts b/tests/agent-pty.spec.ts index 88896c6..7b69a18 100644 --- a/tests/agent-pty.spec.ts +++ b/tests/agent-pty.spec.ts @@ -11,7 +11,6 @@ import { ALLOWED_SIGNALS, snapshotOf, tryResizePty, - type AgentTerminalSnapshot, } from '../src/agent-pty.ts' /** diff --git a/tests/chunk-artifact.spec.ts b/tests/chunk-artifact.spec.ts index ec39364..4a6ca54 100644 --- a/tests/chunk-artifact.spec.ts +++ b/tests/chunk-artifact.spec.ts @@ -36,7 +36,6 @@ describe.skipIf(!chunksBuilt)('built chunk artifacts', () => { if (typeof g.removeEventListener !== 'function') g.removeEventListener = () => {} for (const name of CHUNKS) { const code = readFileSync(`lib/client-${name}.js`, 'utf8') - // eslint-disable-next-line no-new-func expect(() => new Function(code)(), name).not.toThrow() const registry = g.__dshChunks__ as Record expect(typeof registry[name], name).toBe('function') diff --git a/tests/chunk-loader.spec.ts b/tests/chunk-loader.spec.ts index 5fb94d3..b94327b 100644 --- a/tests/chunk-loader.spec.ts +++ b/tests/chunk-loader.spec.ts @@ -41,11 +41,6 @@ function removeModuleSystem(): void { delete (globalThis as Record).__DSH_MODULES__ } -/** The global registry the chunk scripts populate (mirror of chunk-loader). */ -function registry(): Record { - return (globalThis as { __dshChunks__?: Record }).__dshChunks__ ?? {} -} - /** Simulate a chunk script executing: it assigns its factory to the registry. */ function simulateScript(name: string, factory: (require: (spec: string) => unknown) => ChunkExports): void { const g = globalThis as { __dshChunks__?: Record } @@ -314,8 +309,7 @@ describe('revalidateChunksOnReactivate (HMR re-activation keeps unchanged chunks const revalidating = revalidateChunksOnReactivate() // A lazy open DURING the pending revalidation must NOT get the old cache. let resolved = false - let pendingLoad: Promise | null = null - pendingLoad = loadChunk('editor').then((exports) => { resolved = true; return exports }) + const pendingLoad = loadChunk('editor').then((exports) => { resolved = true; return exports }) await new Promise((resolve) => setTimeout(resolve, 5)) expect(resolved, 'loadChunk must await the pending revalidation').toBe(false) // Release the HEAD; the barrier lifts and the load re-injects fresh exports. @@ -369,7 +363,7 @@ describe('revalidateChunksOnReactivate (HMR re-activation keeps unchanged chunks scriptCalls += 1 simulateScript('editor', () => ({ TextEditor: `editor-view:${scriptCalls}` })) }) - let etag = '"v1"' + const etag = '"v1"' stubBundleHead(() => etag) await loadChunk('editor') await settleEtag() diff --git a/tests/consumer-types.ts b/tests/consumer-types.ts index cd15cf2..19fe249 100644 --- a/tests/consumer-types.ts +++ b/tests/consumer-types.ts @@ -43,7 +43,7 @@ import type { const tab: TabDescriptor = { id: 'my-plugin:db', title: () => 'Database', - icon: (size: number) => null, + icon: (_size: number) => null, order: 50, hidden: false, available: (ctx, scope, state) => scope.sessionId !== '' && state.panelOpen && ctx !== null, @@ -116,7 +116,7 @@ service.subscribe(() => {}) const seed: OpenTabSeed = { type: 'my-plugin:db', title: 'DB', path: '/p', id: 'x', meta: { a: 1 } } service.openTab(seed) service.openTab(seed, { sessionId: 's1', cwd: '/p' }) -service.version +const _version: string = service.version service.features.includes('badge') const snapshot: SidebarSnapshot | undefined = service.getSnapshot() void snapshot diff --git a/tests/editor-host.spec.tsx b/tests/editor-host.spec.tsx index 5f99828..707c08e 100644 --- a/tests/editor-host.spec.tsx +++ b/tests/editor-host.spec.tsx @@ -10,12 +10,12 @@ */ // @vitest-environment jsdom import { describe, expect, it } from 'vitest' -import { createElement, useEffect } from 'react' +import { createElement, useEffect, type ReactNode } from 'react' import { createRoot } from 'react-dom/client' import { act } from 'react-dom/test-utils' import type { Context } from '../src/context-types.ts' import { EditorHost } from '../src/client/EditorHost.tsx' -import { createBetterSidebarService } from '../src/client/service.ts' +import { createBetterSidebarService, type FileViewerProps } from '../src/client/service.ts' import { allLeaves, createSidebarStore, type SidebarTab } from '../src/client/state.ts' // The act() environment flag (React 18.2 reads it before flushing effects). @@ -258,22 +258,26 @@ describe('EditorHost (files window)', () => { const service = ctx.betterSidebar const calls: string[] = [] // A viewer with a hoisted toolbar (the TextEditor contract): register - // commands and report the state once on mount. + // commands and report the state once on mount. Capitalized so the hooks + // rules recognize it as a component. + const FakeViewer = (viewerProps: FileViewerProps): ReactNode => { + useEffect(() => { + viewerProps.onToolbarControls?.({ + setMode: (next) => { calls.push(`mode:${next}`) }, + save: () => { calls.push('save') }, + }) + viewerProps.onToolbarState?.({ modes: true, mode: 'preview', dirty: true, editable: true, saveState: 'idle' }) + return () => { viewerProps.onToolbarControls?.(null) } + // Mount-only: re-running would re-fire the toolbar registration. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + return null + } service.registerFileViewer({ id: 'test:fake', exts: ['fake'], fetchStrategy: 'none', - component: (viewerProps) => { - useEffect(() => { - viewerProps.onToolbarControls?.({ - setMode: (next) => { calls.push(`mode:${next}`) }, - save: () => { calls.push('save') }, - }) - viewerProps.onToolbarState?.({ modes: true, mode: 'preview', dirty: true, editable: true, saveState: 'idle' }) - return () => { viewerProps.onToolbarControls?.(null) } - }, []) - return null - }, + component: FakeViewer, }) service.openTab({ type: 'editor', title: 'x.fake', path: '/tmp/x.fake', id: 'editor:/tmp/x.fake' }) const fileTab = (): SidebarTab => diff --git a/tests/fs-operations.spec.ts b/tests/fs-operations.spec.ts index e0ebefb..fb31399 100644 --- a/tests/fs-operations.spec.ts +++ b/tests/fs-operations.spec.ts @@ -1,5 +1,5 @@ import { afterAll, describe, expect, it } from 'vitest' -import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync } from 'node:fs' +import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync } from 'node:fs' import { join } from 'node:path' import { tmpdir } from 'node:os' import { writeWorkspaceUpload } from '../src/fs-operations.ts' diff --git a/tests/markdown-manual-refresh.spec.tsx b/tests/markdown-manual-refresh.spec.tsx index 1f2df30..d2c0d18 100644 --- a/tests/markdown-manual-refresh.spec.tsx +++ b/tests/markdown-manual-refresh.spec.tsx @@ -37,6 +37,8 @@ function FakeMarkdownViewer(props: FileViewerProps) { markDirty = undefined props.onToolbarControls?.(null) } + // Only the callback identities must re-wire; content is read at render time. + // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.onToolbarControls, props.onToolbarState]) return createElement('div', { 'data-testid': 'markdown-content' }, props.content ?? '') } diff --git a/tests/panel-host-css.spec.ts b/tests/panel-host-css.spec.ts index 8b4e470..b3c6950 100644 --- a/tests/panel-host-css.spec.ts +++ b/tests/panel-host-css.spec.ts @@ -22,7 +22,7 @@ const css = readFileSync('src/client/sidebar.module.css', 'utf8') /** Body of the `:global([data-dsh-panel-host])` rule (up to the un-indented `}`). */ const hostRule = css.match(/:global\(\[data-dsh-panel-host\]\) \{([\s\S]*?)\n\}/)?.[1] -/** Strip /* ... *​/ comment blocks so prose mentions don't count as declarations. */ +/** Strip block comments (`/*` to `*`-`/`) so prose mentions don't count as declarations. */ const stripComments = (cssText: string): string => cssText.replace(/\/\*[\s\S]*?\*\//g, '') describe('panel host layer css', () => { diff --git a/tests/pty-helpers.spec.ts b/tests/pty-helpers.spec.ts index e1f4267..a02cefd 100644 --- a/tests/pty-helpers.spec.ts +++ b/tests/pty-helpers.spec.ts @@ -12,6 +12,9 @@ vi.mock('node:os', async (importOriginal) => { } }) +import { existsSync, statSync } from 'node:fs' +import { createRequire } from 'node:module' +import { dirname, join } from 'node:path' import { resolveSidebarConfig } from '../src/config.ts' import { defaultShell, @@ -141,9 +144,6 @@ describe('pty helpers', () => { if (process.platform !== 'darwin') return ensureSpawnHelper() ensureSpawnHelper() - const { existsSync, statSync } = require('node:fs') as typeof import('node:fs') - const { dirname, join } = require('node:path') as typeof import('node:path') - const { createRequire } = require('node:module') as typeof import('node:module') const entry = createRequire(import.meta.url).resolve('node-pty') const root = dirname(dirname(entry)) // Prebuilt (tarball) or node-gyp-compiled (build/Release): mirror diff --git a/tests/sidechat-core.spec.ts b/tests/sidechat-core.spec.ts index 1516d2a..8c3a207 100644 --- a/tests/sidechat-core.spec.ts +++ b/tests/sidechat-core.spec.ts @@ -22,7 +22,6 @@ import { SIDE_INJECTION_PLUGIN, SIDE_LABEL_PREFIX, type SeedEvent, - type SidechatLogEvent, } from '../src/sidechat-core.ts' /** One log event fixture (structural, seq === index like the live contract). diff --git a/tests/sidechat-seed-validation.spec.ts b/tests/sidechat-seed-validation.spec.ts index 9407d1f..3f929d4 100644 --- a/tests/sidechat-seed-validation.spec.ts +++ b/tests/sidechat-seed-validation.spec.ts @@ -40,15 +40,6 @@ function assistantMessage(text: string): Record { } } -function toolResultMessage(callId: string, text: string): Record { - return { - id: `m-${callId}`, - role: 'user', - content: [{ type: 'tool-result', toolCallId: callId, content: [{ type: 'text', text }] }], - source: { kind: 'tool', callId }, - } -} - /** A parent log with a completed turn, a pending question, and an open * in-progress turn (the exact shape a mid-stream thread creation sees). */ function parentLog(): SidebarSessionEvent[] { diff --git a/tests/sidechat-view.spec.tsx b/tests/sidechat-view.spec.tsx index 2d52500..8d15951 100644 --- a/tests/sidechat-view.spec.tsx +++ b/tests/sidechat-view.spec.tsx @@ -64,7 +64,7 @@ const EVENTS = [ /** A subscribable sessions-list snapshot (mirror of the runtime list feed). */ function makeStore(initial: SidebarSessionList) { - let snapshot = initial + const snapshot = initial const listeners = new Set<() => void>() return { getSnapshot: (): SidebarSessionList => snapshot, From 98e9a4ff0f5d3a6e99c53184206a4db5f114d727 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 3 Sep 2026 17:07:39 +0800 Subject: [PATCH 3/3] =?UTF-8?q?docs(readme):=20=E5=BC=80=E5=8F=91=E4=B8=8E?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=E5=91=BD=E4=BB=A4=E6=B8=85=E5=8D=95=E8=A1=A5?= =?UTF-8?q?=20pnpm=20lint=EF=BC=88=E5=8F=8C=E8=AF=AD=E9=95=9C=E5=83=8F?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + README_EN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 4fcc7b9..14b96e7 100644 --- a/README.md +++ b/README.md @@ -524,6 +524,7 @@ GitHub topic [`dsh-better-sidebar`](https://github.com/topics/dsh-better-sidebar ```sh pnpm install # @deepseek-ai/* devDependencies 已发布(基线 0.1.2-rc.1,next dist-tag),直接解析、无需令牌 pnpm typecheck # tsc --noEmit +pnpm lint # eslint .(flat config:js + typescript-eslint + react-hooks recommended) pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types pnpm test # vitest(含 manifest 一致性守卫,需先 build) pnpm watch # tsdown --watch diff --git a/README_EN.md b/README_EN.md index 0e8de64..99cbc4d 100644 --- a/README_EN.md +++ b/README_EN.md @@ -519,6 +519,7 @@ The dashed cards at the end of the "Sidebar content" / "File viewers" grids in t ```sh pnpm install # @deepseek-ai/* devDependencies resolve (baseline 0.1.2-rc.1, next dist-tag) — no token needed pnpm typecheck # tsc --noEmit +pnpm lint # eslint . (flat config: js + typescript-eslint + react-hooks recommended) pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types pnpm test # vitest (includes manifest consistency guard; build first) pnpm watch # tsdown --watch