From 651c36367f12b0d684f0e5adc6b85fc83fabd7d1 Mon Sep 17 00:00:00 2001 From: CieanYau Date: Sat, 7 Nov 2026 01:24:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5=20ESLint=20=E4=B8=8E=20Prett?= =?UTF-8?q?ier=20=E5=B9=B6=E5=8A=A0=E5=85=A5=20CI=20=E9=9D=99=E6=80=81?= =?UTF-8?q?=E9=97=A8=E7=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/frontend.yml | 4 + .prettierignore | 13 + .prettierrc.json | 6 + README.md | 40 +- app/components/AuthProviders.vue | 2 +- app/components/OsIcon.vue | 1 + app/components/config/CommonConfig.vue | 2 +- app/components/config/FinanceConfig.vue | 2 +- app/components/instance/CommonUpgrade.vue | 1 + app/lib/auth-redirect.js | 2 + app/lib/backend-menu.js | 1 + app/lib/instance-data.js | 6 +- app/lib/modules.js | 1 + app/lib/oauth.js | 4 +- app/lib/order-image-continuation.js | 2 + app/lib/os-name.js | 4 +- app/lib/sanitize.js | 1 + app/lib/storage-capacity.js | 2 +- app/lib/ticketAttachments.js | 2 + app/lib/useOfficialSiteContent.js | 2 + app/pages/account/index.vue | 2 +- app/pages/account/realname/index.vue | 1 + app/pages/finance/index.vue | 3 - app/pages/invoices/invoice.vue | 1 + app/pages/notices/index.vue | 2 +- app/pages/products/[id].vue | 1 + app/pages/resources.vue | 2 +- app/pages/tickets/[id].vue | 3 - eslint.config.mjs | 71 ++ package-lock.json | 1258 ++++++++++++++++++++- package.json | 13 +- tests/README.md | 3 +- tests/helpers/console-browser.mjs | 2 +- 33 files changed, 1420 insertions(+), 40 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json create mode 100644 eslint.config.mjs diff --git a/.gitea/workflows/frontend.yml b/.gitea/workflows/frontend.yml index 4248a60..15a3c5d 100644 --- a/.gitea/workflows/frontend.yml +++ b/.gitea/workflows/frontend.yml @@ -22,6 +22,10 @@ jobs: node -e 'if (Number(process.versions.node.split(".")[0]) !== 22) { console.error("需要 Node 22"); process.exit(1) }' - name: 安装锁定依赖 run: npm ci + - name: 检查代码和格式 + run: | + npm run lint + npm run format:check - name: 安装测试浏览器 run: npx playwright install --with-deps chromium firefox - name: 检查源码并构建 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..2059b0c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,13 @@ +# Generated output and local-only reports are not source formatting targets. +node_modules/ +.nuxt/ +.output/ +.data/ +test-results/ +tests/fixtures/runs/ +docs/ +.claude/skills/crashwork-ops/ + +# Preserve supplied static assets and npm's lockfile serialization. +public/ +package-lock.json diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..e1cc780 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "semi": true, + "singleQuote": false, + "trailingComma": "all", + "endOfLine": "lf" +} diff --git a/README.md b/README.md index 73bc3a2..f073692 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,13 @@ ## 技术栈 -| 层次 | 技术 | -| ---------- | --------------------------------------------------------- | -| 应用框架 | Nuxt 4、Vue 3、Vue Router,客户端 SPA(`ssr: false`) | -| 状态与界面 | Pinia、PrimeVue 4、PrimeUI 主题、本地 Lucide 图标 | -| 图表与远控 | ECharts、vue-echarts、noVNC | -| 源码 | JavaScript、Vue 单文件组件、CSS,Nuxt 配置使用 TypeScript | -| 验证工具 | Node.js `node:test`、Playwright、源码检查脚本、Prettier | +| 层次 | 技术 | +| ---------- | --------------------------------------------------------------- | +| 应用框架 | Nuxt 4、Vue 3、Vue Router,客户端 SPA(`ssr: false`) | +| 状态与界面 | Pinia、PrimeVue 4、PrimeUI 主题、本地 Lucide 图标 | +| 图表与远控 | ECharts、vue-echarts、noVNC | +| 源码 | JavaScript、Vue 单文件组件、CSS,Nuxt 配置使用 TypeScript | +| 验证工具 | Node.js `node:test`、Playwright、源码检查脚本、ESLint、Prettier | 依赖的精确版本以 `package-lock.json` 为准。 @@ -70,19 +70,27 @@ npm run dev ## 常用命令 -| 命令 | 用途 | -| ----------------- | ----------------------------------------- | -| `npm run dev` | 启动本地开发服务 | -| `npm run check` | 检查应用源码语法、导入和历史部署路径依赖 | -| `npm run build` | 构建生产版本,输出到项目根目录 `.output/` | -| `npm run preview` | 运行已构建的 Node.js 服务 | -| `npm test` | 对生产构建运行浏览器端到端测试 | -| `npm run format` | 格式化应用、配置、脚本和测试代码 | +| 命令 | 用途 | +| ---------------------- | ----------------------------------------- | +| `npm run dev` | 启动本地开发服务 | +| `npm run check` | 检查应用源码语法、导入和历史部署路径依赖 | +| `npm run lint` | 检查应用、配置、脚本和测试的代码问题 | +| `npm run lint:fix` | 自动修复可安全修正的 ESLint 问题 | +| `npm run build` | 构建生产版本,输出到项目根目录 `.output/` | +| `npm run preview` | 运行已构建的 Node.js 服务 | +| `npm test` | 对生产构建运行浏览器端到端测试 | +| `npm run format` | 统一格式化应用、配置、脚本、测试和文档 | +| `npm run format:check` | 只检查格式,不改写文件 | + +格式规则在 `.prettierrc.json`,扫描范围由 `.prettierignore` 排除生成物、本地报告、 +静态资源和 npm 管理的锁文件;不会将 `docs/` 或测试产物重新纳入提交。 ### 构建与本地预览 ```sh npm run check +npm run lint +npm run format:check npm run build NUXT_PUBLIC_API_BASE=http://127.0.0.1:8080 HOST=127.0.0.1 PORT=3000 npm run preview ``` @@ -137,7 +145,7 @@ CHROME_PATH=/absolute/path/to/chrome npm test 测试产物保存在被忽略的 `tests/fixtures/runs/`。 详细使用方式见 [测试说明](tests/README.md)。 -仓库包含 `.gitea/workflows/frontend.yml`:安装锁定依赖后运行源码检查、生产构建、浏览器测试和 +仓库包含 `.gitea/workflows/frontend.yml`:安装锁定依赖后先运行 ESLint 和格式检查,再安装测试浏览器、运行源码检查、生产构建、浏览器测试和 `npm audit --audit-level=moderate`,不执行部署。Git 服务需启用 Actions 并配置兼容的 Linux runner; 仅提交工作流不代表远端任务已经运行通过。 diff --git a/app/components/AuthProviders.vue b/app/components/AuthProviders.vue index fbb51d6..ce66925 100644 --- a/app/components/AuthProviders.vue +++ b/app/components/AuthProviders.vue @@ -114,7 +114,7 @@ var fe = { let t = M.value.flatMap((e, t) => (e.enabled ? [t] : [])); if (!t.length) return; let n = t.indexOf(N.value), - r = n; + r; if (e.key === `ArrowRight`) r = (n + 1) % t.length; else if (e.key === `ArrowLeft`) r = (n + t.length - 1) % t.length; else if (e.key === `Home`) r = 0; diff --git a/app/components/OsIcon.vue b/app/components/OsIcon.vue index 641ab88..6ecf3ba 100644 --- a/app/components/OsIcon.vue +++ b/app/components/OsIcon.vue @@ -41,6 +41,7 @@ var f = [`src`, `width`, `height`], // 仅接收站内绝对路径或无认证信息的 HTTP(S) 地址,拒绝控制字符和反斜杠。 function m(e) { let t = String(e ?? ``).trim(); + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝图标 URL 内的控制字符。 if (!t || /[\u0000-\u0020\u007f\\]/.test(t)) return ``; if (/^\/(?!\/)/.test(t)) return t; try { diff --git a/app/components/config/CommonConfig.vue b/app/components/config/CommonConfig.vue index 2fd189b..befdd57 100644 --- a/app/components/config/CommonConfig.vue +++ b/app/components/config/CommonConfig.vue @@ -1002,7 +1002,7 @@ var le = { let Qe = computed(() => Ie.value.map((e) => { let t = N.value[String(e.id)], - n = ``; + n; if (e.option_type === `cascade`) { let t = Re(e); n = Z(e).find((e) => e.item_id === t)?.label ?? ``; diff --git a/app/components/config/FinanceConfig.vue b/app/components/config/FinanceConfig.vue index e056174..c002cdd 100644 --- a/app/components/config/FinanceConfig.vue +++ b/app/components/config/FinanceConfig.vue @@ -836,7 +836,7 @@ var ae = { let Ze = computed(() => (O.availableOptions?.value ?? F.value?.options ?? []).map((e) => { let t = I.value[e.id], - n = ``; + n; if (e.kind === `quantity`) { let r = (Ne(e) ? Le(e) : ``) || e.unit; n = typeof t == `number` ? `${t}${r ? ` ${r}` : ``}` : ``; diff --git a/app/components/instance/CommonUpgrade.vue b/app/components/instance/CommonUpgrade.vue index d947b31..1ff4908 100644 --- a/app/components/instance/CommonUpgrade.vue +++ b/app/components/instance/CommonUpgrade.vue @@ -632,6 +632,7 @@ function W(e, t) { return; (W(), (N.value = ``)); let t = L, + // eslint-disable-next-line no-useless-assignment -- 边界一致性:保留 try 外 computed 求值及异常传播顺序。 r = B.value; try { (G(), (t = L), (r = B.value)); diff --git a/app/lib/auth-redirect.js b/app/lib/auth-redirect.js index 1c67dad..9c68a8c 100644 --- a/app/lib/auth-redirect.js +++ b/app/lib/auth-redirect.js @@ -4,12 +4,14 @@ function e(e) { typeof e != `string` || !e.startsWith(`/`) || e.startsWith(`//`) || + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝跳转路径中的控制字符。 /[\\\u0000-\u0020\u007f]/.test(e) ) return `/`; try { // 路径解码后再次检查,避免编码后的双斜杠或反斜杠绕过站内限制。 let t = decodeURIComponent(e.split(/[?#]/, 1)[0] || ``); + // eslint-disable-next-line no-control-regex -- 安全边界:解码后仍须拒绝控制字符绕过。 if (t.startsWith(`//`) || /[\\\u0000-\u0020\u007f]/.test(t)) return `/`; } catch { return `/`; diff --git a/app/lib/backend-menu.js b/app/lib/backend-menu.js index b5a34e6..014a153 100644 --- a/app/lib/backend-menu.js +++ b/app/lib/backend-menu.js @@ -270,6 +270,7 @@ function d(e) { if ( typeof e != `string` || !/^https?:\/\//i.test(e) || + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝菜单 URL 内的控制字符。 /[\u0000-\u0020\\]/.test(e) ) return ``; diff --git a/app/lib/instance-data.js b/app/lib/instance-data.js index 702d1dc..687f742 100644 --- a/app/lib/instance-data.js +++ b/app/lib/instance-data.js @@ -104,10 +104,10 @@ function o(t, r, i) { [`available`, `none`, `not_applicable`].includes( String(s.quota_status ?? ``), ), - x = null, - S = null, + x, + S, C = null, - w = ``, + w, T = !1, E = t === `kky_ecs` && !!s.start_time && !!s.end_time, D = E ? a(s.incoming) : null; diff --git a/app/lib/modules.js b/app/lib/modules.js index 169dfcc..b0d04fe 100644 --- a/app/lib/modules.js +++ b/app/lib/modules.js @@ -21,6 +21,7 @@ var e = { /** 优先采用合法站内/HTTP(S)图片地址;否则从 e/n 的系统描述推断本地图标。 */ function t(e, t, n) { let r = String(e ?? ``).trim(); + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝模块 URL 内的控制字符。 if (r && !/[\u0000-\u0020\u007f\\]/.test(r)) { if (/^\/(?!\/)/.test(r)) return r; try { diff --git a/app/lib/oauth.js b/app/lib/oauth.js index 5e35650..266a5a3 100644 --- a/app/lib/oauth.js +++ b/app/lib/oauth.js @@ -13,6 +13,7 @@ function t(t) { return []; let n = typeof t.img == `string` ? t.img : ``, r = + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝登录图标路径中的控制字符。 /^\/(?!\/)/.test(n) && !/[\\\u0000-\u0020]/.test(n) ? n : backend_menu_o(n); @@ -29,7 +30,8 @@ function t(t) { } function n(t, n) { return typeof t == `string` - ? /^\/(?!\/)/.test(t) && !/[\\\u0000-\u0020]/.test(t) + ? // eslint-disable-next-line no-control-regex -- 安全边界:拒绝登录跳转地址中的控制字符。 + /^\/(?!\/)/.test(t) && !/[\\\u0000-\u0020]/.test(t) ? new URL(t, n).href : backend_menu_o(t) : ``; diff --git a/app/lib/order-image-continuation.js b/app/lib/order-image-continuation.js index 9be7e15..734ce7c 100644 --- a/app/lib/order-image-continuation.js +++ b/app/lib/order-image-continuation.js @@ -16,6 +16,7 @@ function n(e) { return ( t.startsWith(`/`) && !t.startsWith(`//`) && + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝订单续接路径中的控制字符。 !/[\\\u0000-\u0020\u007f]/.test(t) ); } @@ -24,6 +25,7 @@ function r(e, r) { try { if ( typeof e != `string` || + // eslint-disable-next-line no-control-regex -- 安全边界:解码后仍须拒绝控制字符绕过。 /[\\\u0000-\u0020\u007f]/.test(e) || !n(e.split(/[?#]/, 1)[0] || ``) ) diff --git a/app/lib/os-name.js b/app/lib/os-name.js index a91c7bc..873a9fa 100644 --- a/app/lib/os-name.js +++ b/app/lib/os-name.js @@ -44,7 +44,7 @@ function n(n) { a = !1, o = [e[r[0].replace(/[ _-]+/g, ` `).toLowerCase()]], s = - /^[\s_-]*(x86[_-]64|64[ _-]?(?:bits?|位)|32[ _-]?(?:bits?|位)|\d+(?:\.\d+)*(?:R2)?|Server|Stream|Datacenter|Standard|Enterprise|Professional|Essentials|Education|Desktop|Minimal|Core|Pro|Home|R2|LTS|SP\d+|UEFI|BIOS|GPT|BT|ARM64|aarch64|x64|amd64|x86|x32|i386|i686|ARM|cn|en|zh(?:[ _-](?:CN|TW))?|专业版|标准版|数据中心版|企业版|家庭版|教育版|中文版|英文版)(?=$|[\s_()()\[\]【】-])/i; + /^[\s_-]*(x86[_-]64|64[ _-]?(?:bits?|位)|32[ _-]?(?:bits?|位)|\d+(?:\.\d+)*(?:R2)?|Server|Stream|Datacenter|Standard|Enterprise|Professional|Essentials|Education|Desktop|Minimal|Core|Pro|Home|R2|LTS|SP\d+|UEFI|BIOS|GPT|BT|ARM64|aarch64|x64|amd64|x86|x32|i386|i686|ARM|cn|en|zh(?:[ _-](?:CN|TW))?|专业版|标准版|数据中心版|企业版|家庭版|教育版|中文版|英文版)(?=$|[\s_()()[\]【】-])/i; for (let e = i.match(s); e; e = i.match(s)) { let n = t[e[1].toLowerCase()] ?? e[1]; (/^\d+(?:\.\d+)*(?:R2)?$/i.test(n) && @@ -67,7 +67,7 @@ function r(e) { return ( n(t.replace(/\.(?:iso|qcow2?|img|raw|vhdx?|vmdk)$/i, ``)) .replace( - /[\s_-]*(?:[((【\[]\s*)?纯净优化版(?:\s*[))】\]])?(?=$|[\s_-])/g, + /[\s_-]*(?:[((【[]\s*)?纯净优化版(?:\s*[))】\]])?(?=$|[\s_-])/g, ``, ) .replace(RegExp(`[((\\[【]\\s*${r}\\s*[))\\]】]`, `gi`), ` `) diff --git a/app/lib/sanitize.js b/app/lib/sanitize.js index 1b4c409..4ff8333 100644 --- a/app/lib/sanitize.js +++ b/app/lib/sanitize.js @@ -36,6 +36,7 @@ var e = new Set( ]); // 图片额外允许有限位图类型的 base64 data URL;普通链接可用 mailto/tel,不允许脚本协议。 function n(e, t = !1) { + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝富文本链接和图片中的控制字符。 if (!e || /[\u0000-\u001f\u007f]/.test(e)) return !1; if ( t && diff --git a/app/lib/storage-capacity.js b/app/lib/storage-capacity.js index cef23b7..0081140 100644 --- a/app/lib/storage-capacity.js +++ b/app/lib/storage-capacity.js @@ -465,7 +465,7 @@ function C(e, t = ``) { if (!n || /[×*¥¥$€]|(?:^|[\s([{])[-+]\s*\d/.test(n)) return null; let r = [...n.matchAll(/\d+(?:\.\d+)?\s*(?:[kmgtpe](?:i?b)?|b)(?![a-z])/gi)], i = r[0], - a = ``; + a; if (r.length === 1) a = S(/[a-z]+$/i.exec(i[0])?.[0] ?? ``); else if (r.length === 0 && S(t)) { let e = [...n.matchAll(/\d+(?:\.\d+)?/g)]; diff --git a/app/lib/ticketAttachments.js b/app/lib/ticketAttachments.js index da71c33..3281d76 100644 --- a/app/lib/ticketAttachments.js +++ b/app/lib/ticketAttachments.js @@ -3,6 +3,7 @@ function e(e) { if ( !/^(?:https?:\/\/|\/(?!\/)|\.\.?\/)/i.test(e) || + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝附件 URL 内的控制字符。 /[\u0000-\u001f\u007f\\]/.test(e) ) return !1; @@ -56,6 +57,7 @@ function r(t) { u = c || (l ? n(l, i) : ``), d = l || + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝附件名中的控制字符。 (typeof o == `string` && !e(o) && !/[\\/:\u0000-\u001f]/.test(o) ? o : ``), diff --git a/app/lib/useOfficialSiteContent.js b/app/lib/useOfficialSiteContent.js index 0c33cc3..146dfe9 100644 --- a/app/lib/useOfficialSiteContent.js +++ b/app/lib/useOfficialSiteContent.js @@ -402,6 +402,7 @@ function o(e) { function s(e) { if (typeof e != `string`) return `#`; let t = e.trim(); + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝官网链接内的控制字符。 return !t || /[\u0000-\u001f\\]/.test(t) ? `#` : /^(https?:\/\/|mailto:|tel:|#|\/(?!\/))/i.test(t) @@ -412,6 +413,7 @@ function s(e) { function c(e) { if (typeof e != `string`) return ``; let t = e.trim(); + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝官网图片 URL 内的控制字符。 return !t || /[\u0000-\u001f\\]/.test(t) ? `` : /^(https?:\/\/|\/(?!\/))/i.test(t) diff --git a/app/pages/account/index.vue b/app/pages/account/index.vue index fc2f5a6..88298e0 100644 --- a/app/pages/account/index.vue +++ b/app/pages/account/index.vue @@ -329,7 +329,7 @@ var Ce = { ]; // 为账户设置标签提供左右方向键及 Home/End 导航,并同步实际焦点。 function Xt(e, t) { - let n = t; + let n; if (e.key === `ArrowRight`) n = (t + 1) % E.length; else if (e.key === `ArrowLeft`) n = (t + E.length - 1) % E.length; else if (e.key === `Home`) n = 0; diff --git a/app/pages/account/realname/index.vue b/app/pages/account/realname/index.vue index 1581433..a92e5ab 100644 --- a/app/pages/account/realname/index.vue +++ b/app/pages/account/realname/index.vue @@ -387,6 +387,7 @@ var xe = { Tt = computed(() => { let e = R.value?.certification_auth_template_url || ``; return /^(?:https?:\/\/|\/(?!\/))/i.test(e) && + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝认证模板 URL 内的控制字符。 !/[\\\u0000-\u0020]/.test(e) ? e : ``; diff --git a/app/pages/finance/index.vue b/app/pages/finance/index.vue index 8b6b5c9..d135c54 100644 --- a/app/pages/finance/index.vue +++ b/app/pages/finance/index.vue @@ -127,9 +127,6 @@ var je = { Xe = { class: `amount`, }, - Ze = { - class: `consumption-overview`, - }, x = _plugin_vue_export_helper_t( defineComponent({ __name: `index`, diff --git a/app/pages/invoices/invoice.vue b/app/pages/invoices/invoice.vue index 8e26417..6f92bd2 100644 --- a/app/pages/invoices/invoice.vue +++ b/app/pages/invoices/invoice.vue @@ -110,6 +110,7 @@ var T = { ); // 下载地址仅允许 HTTP(S) 或站内绝对路径,拒绝反斜杠、空白控制字符和协议相对地址。 function q(e) { + // eslint-disable-next-line no-control-regex -- 安全边界:拒绝发票下载地址中的控制字符。 return typeof e != `string` || /[\u0000-\u0020\\]/.test(e) ? `` : /^https?:\/\//i.test(e) || /^\/(?!\/)/.test(e) diff --git a/app/pages/notices/index.vue b/app/pages/notices/index.vue index 41d634d..330a457 100644 --- a/app/pages/notices/index.vue +++ b/app/pages/notices/index.vue @@ -295,7 +295,7 @@ var ue = { createElementVNode( `p`, ge, - `发布时间 ` + + `发布时间\u3000` + toDisplayString( (`formatTime` in n ? n.formatTime diff --git a/app/pages/products/[id].vue b/app/pages/products/[id].vue index b0ccbdf..f69de7e 100644 --- a/app/pages/products/[id].vue +++ b/app/pages/products/[id].vue @@ -121,6 +121,7 @@ var j = { position: K.value, item: U.value, }; + return undefined; }), J = ref(!1), Y = ref(null), diff --git a/app/pages/resources.vue b/app/pages/resources.vue index 8348d4f..109ae51 100644 --- a/app/pages/resources.vue +++ b/app/pages/resources.vue @@ -119,7 +119,7 @@ var j = { })); // 标签按左右方向键循环切换,Home/End 跳至首尾,并同步焦点到新标签。 function G(e, t) { - let n = t; + let n; if (e.key === `ArrowRight`) n = (t + 1) % V.length; else if (e.key === `ArrowLeft`) n = (t + V.length - 1) % V.length; else if (e.key === `Home`) n = 0; diff --git a/app/pages/tickets/[id].vue b/app/pages/tickets/[id].vue index 01f7038..bd186fa 100644 --- a/app/pages/tickets/[id].vue +++ b/app/pages/tickets/[id].vue @@ -61,9 +61,6 @@ var le = { me = { class: `ticket-title`, }, - he = { - class: `ticket-num`, - }, ge = { class: `ticket-meta`, }, diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..40feb84 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,71 @@ +import js from "@eslint/js"; +import ts from "typescript-eslint"; +import vue from "eslint-plugin-vue"; +import globals from "globals"; +import prettier from "eslint-config-prettier/flat"; + +export default [ + { + ignores: [ + "node_modules/**", + ".nuxt/**", + ".output/**", + ".data/**", + "test-results/**", + "tests/fixtures/runs/**", + "docs/**", + ".claude/skills/crashwork-ops/**", + "public/**", + ], + }, + { + linterOptions: { reportUnusedDisableDirectives: "error" }, + }, + js.configs.recommended, + ...vue.configs["flat/essential"], + ...ts.configs.recommended.map((config) => ({ + ...config, + files: ["**/*.{ts,mts,cts}"], + })), + { + files: ["app/**/*.{js,vue}"], + languageOptions: { globals: globals.browser }, + }, + { + files: ["*.mjs", "nuxt.config.ts", "scripts/**/*.mjs", "tests/**/*.mjs"], + languageOptions: { globals: globals.node }, + }, + { + // Playwright 的 evaluate 回调在浏览器运行,测试文件同时使用 Node 与 DOM 全局。 + files: ["tests/**/*.mjs"], + languageOptions: { globals: globals.browser }, + }, + { + // Nuxt 路由和布局文件名由框架约定,不能要求多词组件名。 + files: ["app/pages/**/*.vue", "app/layouts/**/*.vue"], + rules: { "vue/multi-word-component-names": "off" }, + }, + { + // 恢复的互操作辅助只在宿主提供 require 时访问它,不为浏览器注入 Node 全局。 + files: ["app/lib/rolldown-runtime.js"], + languageOptions: { globals: { require: "readonly" } }, + }, + { + files: ["nuxt.config.ts"], + languageOptions: { globals: { defineNuxtConfig: "readonly" } }, + }, + { + // 最佳努力清理和存储降级允许空 catch;其他空块仍报错。 + rules: { + "no-empty": ["error", { allowEmptyCatch: true }], + }, + }, + { + files: ["**/*.{js,mjs,cjs,vue}"], + rules: { + // 恢复的渲染回调保留位置参数,catch 也可不使用错误绑定;局部绑定仍检查。 + "no-unused-vars": ["error", { args: "none", caughtErrors: "none" }], + }, + }, + prettier, +]; diff --git a/package-lock.json b/package-lock.json index 3174aec..7b10946 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,9 +29,15 @@ "@babel/parser": "7.29.8", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", + "@eslint/js": "10.0.1", "@vue/compiler-sfc": "3.5.45", + "eslint": "10.14.0", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-vue": "10.12.0", + "globals": "17.14.0", "playwright": "^1.64.1", - "prettier": "^3.8.0" + "prettier": "3.9.10", + "typescript-eslint": "8.72.1" }, "engines": { "node": "^22.22.3 || ^24.15.0 || >=26.0.0" @@ -492,6 +498,30 @@ "node": ">=6.9.0" } }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.5.1", + "keyv": "^5.6.0" + } + }, "node_modules/@clack/core": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz", @@ -1008,6 +1038,200 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@iconify-json/lucide": { "version": "1.2.151", "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.151.tgz", @@ -1137,6 +1361,30 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@mapbox/node-pre-gyp": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.3.tgz", @@ -2715,18 +2963,265 @@ "integrity": "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==", "license": "CC0-1.0" }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.10.tgz", "integrity": "sha512-lTyOMnOcmRBzdCv6/4zUZCrEhV0xrqQiUZBZtVcbmLHBXKLnN8q89v/wKRF/Q0HbwVsqbIG3o5HDoFl9sduM+g==", "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.1.tgz", + "integrity": "sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/type-utils": "8.72.1", + "@typescript-eslint/utils": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.72.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.1.tgz", + "integrity": "sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.1.tgz", + "integrity": "sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.72.1", + "@typescript-eslint/types": "^8.72.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.1.tgz", + "integrity": "sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.1.tgz", + "integrity": "sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.1.tgz", + "integrity": "sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.1.tgz", + "integrity": "sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.1.tgz", + "integrity": "sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.72.1", + "@typescript-eslint/tsconfig-utils": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.1.tgz", + "integrity": "sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.1.tgz", + "integrity": "sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.72.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@unhead/bundler": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/@unhead/bundler/-/bundler-3.4.3.tgz", @@ -3179,6 +3674,16 @@ "acorn": "^8" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -3188,6 +3693,23 @@ "node": ">= 14" } }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-regex": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.5.0.tgz", @@ -3600,6 +4122,13 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "5.0.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", @@ -3754,6 +4283,20 @@ "node": ">=20.19.0" } }, + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -4037,6 +4580,19 @@ "deprecated": "Active development of CryptoJS has been discontinued. This library is no longer maintained.", "license": "MIT" }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cssnano": { "version": "9.9.0", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-9.9.0.tgz", @@ -4126,6 +4682,13 @@ "node": ">=0.10.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -4422,12 +4985,349 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "10.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.14.0.tgz", + "integrity": "sha512-T0pNsxkb9IKmtQjhpK3d7nWOpFv+YHuMbTJnSVMoQblF0onvXfErrtp4V1jHtsQPan7dKaGVD0q1WCXnzMF31A==", + "devOptional": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@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.3", + "@humanfs/node": "^0.16.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "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.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "11.1.5 || >11.1.6 <12", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.6", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.12.0.tgz", + "integrity": "sha512-YsrHHtMaxjWqmxr/Kv9yXUfakUlbTCWtIBvr9eounzj6ZsGJdz1I4UuTIHkhzKHes793Cwo3PGTcvsoBqNyzCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^7.1.4", + "semver": "^7.8.5", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "vue-eslint-parser": "^10.3.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "devOptional": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -4493,6 +5393,13 @@ "integrity": "sha512-h1pQPR9XoeSMdntRNCjyTznaume4UpfXrULBnlkZ2CUM/G5eSa+pBByGldO5uR8dxbPC+OuJXsPPNf+JZ81ADg==", "license": "MIT" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "devOptional": true, + "license": "MIT" + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -4515,6 +5422,20 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/fast-npm-meta": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/fast-npm-meta/-/fast-npm-meta-2.2.0.tgz", @@ -4586,6 +5507,16 @@ "integrity": "sha512-PJb4ZTGT2/wK78RmVrxZITStWabhZlKBsL52VOgq+c7clEkdHdEB+0rtzrXCbZJqeYJj+IwNWYqB5/G6vouA6A==", "license": "MIT" }, + "node_modules/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^6.1.23" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -4617,6 +5548,25 @@ "node": ">=8" } }, + "node_modules/flat-cache": { + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "devOptional": true, + "license": "ISC" + }, "node_modules/flru": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flru/-/flru-1.0.2.tgz", @@ -4793,6 +5743,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globals": { + "version": "17.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.14.0.tgz", + "integrity": "sha512-UtdkTVyAJePQv0J2M9Xe4L0ruNSDV314XiIJsADI2Zf40bcdAonE/D/OhAU8AT99oij9mhLByb+NvA3QWZYgCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globby": { "version": "16.2.4", "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.4.tgz", @@ -4858,6 +5821,19 @@ "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", "license": "MIT" }, + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.15.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/hasown": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", @@ -4876,6 +5852,13 @@ "integrity": "sha512-+abwxtiEA52GCVIsQqut3S/uKTbUwYIp4Pe/vv+6py5XiXBCqMZHg6pA6Y5qhgLSEys0/cYuPbO0z1QFj5ZCmg==", "license": "MIT" }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "devOptional": true, + "license": "MIT" + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -4992,6 +5975,16 @@ "unplugin-utils": "^0.3.1" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -5246,6 +6239,20 @@ "node": ">=6" } }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5258,6 +6265,16 @@ "node": ">=6" } }, + "node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -5334,6 +6351,20 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lightningcss": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", @@ -5982,6 +7013,13 @@ "integrity": "sha512-Kv2JYYiCzt16Kt5QwAc9BFG89xfPNBx+oQL4GQXD9nLqPkZBiNaqaCWtwnbk/q7UVsTYevvM1b0UF8zmEI4pCg==", "license": "MIT" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "devOptional": true, + "license": "MIT" + }, "node_modules/nitropack": { "version": "2.13.6", "resolved": "https://registry.npmjs.org/nitropack/-/nitropack-2.13.6.tgz", @@ -6302,6 +7340,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nuxt": { "version": "4.6.4", "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.6.4.tgz", @@ -6507,6 +7558,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/oxc-walker": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/oxc-walker/-/oxc-walker-1.1.1.tgz", @@ -6776,6 +7845,20 @@ "postcss": "^8.5.29" } }, + "node_modules/postcss-selector-parser": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.7.tgz", + "integrity": "sha512-wWBro/7hJ40ye6TPiXkUQoXKCw23xSsjriUvqd7Uls9Sso3oLiON1flc18cCdnjgCRXw4fBVqUJJeOdDTh3P3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -6794,6 +7877,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.9.10", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", @@ -6870,6 +7963,36 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "devOptional": true, + "license": "MIT" + }, "node_modules/qrcode": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", @@ -7940,12 +9063,38 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/tslib": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", "license": "0BSD" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", @@ -7961,6 +9110,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.1.tgz", + "integrity": "sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.72.1", + "@typescript-eslint/parser": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/ufo": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", @@ -8400,6 +9588,16 @@ "integrity": "sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA==", "license": "MIT" }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -8767,6 +9965,31 @@ "vue": "^3.3.0" } }, + "node_modules/vue-eslint-parser": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.2.tgz", + "integrity": "sha512-WMpzulb50kb6snghzoGzS++62wcOszAk/piYcnvzdStM8Wni/BmogYltpoOFv2eK9hDbXxvwFQgnwZGpAoUfpA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0 || ^9.0.0", + "eslint-visitor-keys": "^4.2.0 || ^5.0.0", + "espree": "^10.3.0 || ^11.0.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" + } + }, "node_modules/vue-router": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.4.0.tgz", @@ -8858,6 +10081,16 @@ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", @@ -8929,6 +10162,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -8970,6 +10213,19 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/youch": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.1.tgz", diff --git a/package.json b/package.json index df88601..ea7202d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,10 @@ "preview": "node .output/server/index.mjs", "prepare": "nuxt prepare", "check": "node scripts/check-source.mjs", - "format": "prettier --write app nuxt.config.ts tests scripts", + "lint": "eslint . --max-warnings 0", + "lint:fix": "eslint . --fix --max-warnings 0", + "format": "prettier --write .", + "format:check": "prettier --check .", "test": "node --test tests/*.test.mjs" }, "dependencies": { @@ -34,9 +37,15 @@ "@babel/parser": "7.29.8", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", + "@eslint/js": "10.0.1", "@vue/compiler-sfc": "3.5.45", + "eslint": "10.14.0", + "eslint-config-prettier": "10.1.8", + "eslint-plugin-vue": "10.12.0", + "globals": "17.14.0", "playwright": "^1.64.1", - "prettier": "^3.8.0" + "prettier": "3.9.10", + "typescript-eslint": "8.72.1" }, "overrides": { "glob": "14.0.3", diff --git a/tests/README.md b/tests/README.md index bccd27e..6e98007 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,7 @@ # 浏览器端到端验收 -先在项目根目录执行 `npm ci` 安装锁定依赖,执行 `npm run build`,再执行 `npm test`。 +先在项目根目录执行 `npm ci` 安装锁定依赖,执行 `npm run check`、`npm run lint`、 +`npm run format:check` 和 `npm run build`,再执行 `npm test`。 测试使用 Node 自带的 `node:test`。浏览器场景直接操作实际构建后的页面,不替换项目内部模块; 规则适配与随机密码另有公开模块入口的隔离失败模式测试,不能代替浏览器验收。 diff --git a/tests/helpers/console-browser.mjs b/tests/helpers/console-browser.mjs index f2383b3..bc754b4 100644 --- a/tests/helpers/console-browser.mjs +++ b/tests/helpers/console-browser.mjs @@ -260,7 +260,7 @@ export async function scenario(t, options, exercise) { const screenshot = `${t.name.replace(/[^a-z0-9]+/gi, "-").toLowerCase()}.png`; let failure; let observed; - let requests = []; + let requests; try { observed = await exercise(page); } catch (error) {