From fabd60af637dad3f22e61f23f7adfe29316ec692 Mon Sep 17 00:00:00 2001 From: mutoe Date: Fri, 9 Aug 2024 13:53:08 +0800 Subject: [PATCH 01/17] chore: setup playwright as the e2e test framework # Conflicts: # pnpm-lock.yaml # Conflicts: # eslint.config.js # package.json # pnpm-lock.yaml --- .gitignore | 5 + cypress/fixtures/article.json | 2 +- eslint.config.js | 8 + index.html | 6 +- package.json | 14 +- playwright.config.ts | 81 ++++ playwright/article/article.spec.ts | 63 +++ .../markdown-render-chromium-darwin.html | 8 + playwright/conduct.page-object.ts | 69 ++++ playwright/constant.ts | 8 + playwright/extends.ts | 22 + playwright/tsconfig.json | 11 + playwright/utils/formatHTML.ts | 8 + playwright/utils/test-decorators.ts | 23 ++ pnpm-lock.yaml | 387 +++++++++++++----- pnpm-workspace.yaml | 7 + src/components/ArticleDetail.vue | 12 +- tsconfig.json | 5 +- tsconfig.node.json | 1 + vite.config.ts | 3 + 20 files changed, 621 insertions(+), 122 deletions(-) create mode 100644 playwright.config.ts create mode 100644 playwright/article/article.spec.ts create mode 100644 playwright/article/article.spec.ts-snapshots/markdown-render-chromium-darwin.html create mode 100644 playwright/conduct.page-object.ts create mode 100644 playwright/constant.ts create mode 100644 playwright/extends.ts create mode 100644 playwright/tsconfig.json create mode 100644 playwright/utils/formatHTML.ts create mode 100644 playwright/utils/test-decorators.ts create mode 100644 pnpm-workspace.yaml diff --git a/.gitignore b/.gitignore index 38adffa6..7bfad8c6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,11 @@ coverage /cypress/videos/ /cypress/screenshots/ +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ + # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/cypress/fixtures/article.json b/cypress/fixtures/article.json index 82bd64cd..a3d000f3 100644 --- a/cypress/fixtures/article.json +++ b/cypress/fixtures/article.json @@ -5,7 +5,7 @@ "body": "# Article body\n\nThis is **Strong** text", "createdAt": "2020-11-01T14:59:39.404Z", "updatedAt": "2020-11-01T14:59:39.404Z", - "tagList": [], + "tagList": ["foo", "bar"], "description": "this is descripion", "author": { "username": "plumrx", diff --git a/eslint.config.js b/eslint.config.js index 44d8826c..757ab49e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -26,4 +26,12 @@ export default defineConfig({ rules: { 'ts/method-signature-style': 'off', }, +}, { + files: [ + '*.config.ts', + 'playwright/**/*', + ], + rules: { + 'node/prefer-global/process': 'off', + }, }) diff --git a/index.html b/index.html index 08e2c793..6142a68f 100644 --- a/index.html +++ b/index.html @@ -6,10 +6,10 @@ - - + + - +
diff --git a/package.json b/package.json index 479b8689..5b646fcb 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,19 @@ "type": "module", "scripts": { "prepare": "simple-git-hooks", - "dev": "vite", + "dev": "vite --port 5173", "build": "vite build", "serve": "vite preview --port 4173", "type-check": "vue-tsc --noEmit", "lint": "eslint --fix .", "test": "npm run test:unit && npm run test:e2e:ci", + "test:cypress:local": "cypress open --e2e -c baseUrl=http://localhost:5173", + "test:cyprsss:prod": "cypress run --e2e -c baseUrl=https://vue3-realworld-example-app-mutoe.vercel.app", "test:e2e": "npm run build && concurrently -rk -s first \"npm run serve\" \"cypress open --e2e -c baseUrl=http://localhost:4173\"", "test:e2e:ci": "npm run build && concurrently -rk -s first \"npm run serve\" \"cypress run --e2e -c baseUrl=http://localhost:4173\"", - "test:e2e:local": "cypress open --e2e -c baseUrl=http://localhost:5173", - "test:e2e:prod": "cypress run --e2e -c baseUrl=https://vue3-realworld-example-app-mutoe.vercel.app", + "test:playwright:ci": "playwright test", + "test:playwright:local": "playwright test --ui", + "test:playwright:local:debug": "playwright test --ui --debug", "test:unit": "vitest run", "generate:api": "curl -sL https://raw.githubusercontent.com/gothinkster/realworld/refs/heads/main/api/openapi.yml -o ./src/services/openapi.yml && sta generate -p ./src/services/openapi.yml -o ./src/services -n api.ts" }, @@ -28,16 +31,21 @@ "devDependencies": { "@mutoe/eslint-config": "^4.11.0-2", "@pinia/testing": "^1.0.2", + "@playwright/test": "^1.55.1", "@testing-library/cypress": "^10.1.0", "@testing-library/user-event": "^14.6.1", "@testing-library/vue": "^8.1.0", + "@types/html": "^1.0.4", + "@types/node": "^24.5.2", "@vitejs/plugin-vue": "^6.0.1", "@vitest/coverage-v8": "^3.2.4", "concurrently": "^9.2.1", "cypress": "^13.13.2", "eslint": "^9.36.0", "eslint-plugin-cypress": "^5.1.1", + "eslint-plugin-vuejs-accessibility": "^2.4.1", "happy-dom": "^18.0.1", + "html": "^1.0.0", "lint-staged": "^16.2.0", "msw": "^2.11.3", "rollup-plugin-analyzer": "^4.0.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..cd5cb268 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,81 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +const baseURL = 'http://localhost:5173' + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './playwright', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 1 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: baseURL, + reuseExistingServer: !process.env.CI, + ignoreHTTPSErrors: true, + }, +}) diff --git a/playwright/article/article.spec.ts b/playwright/article/article.spec.ts new file mode 100644 index 00000000..42d685a6 --- /dev/null +++ b/playwright/article/article.spec.ts @@ -0,0 +1,63 @@ +import type { Article } from 'src/services/api.ts' +import { Route } from '../constant.ts' +import { expect, test } from '../extends' +import { formatHTML } from '../utils/formatHTML.ts' + +test.describe('article', () => { + test.beforeEach(async ({ conduct }) => { + await conduct.intercept('GET', /articles\?limit/, { fixture: 'articles.json' }) + await conduct.intercept('GET', /tags/, { fixture: 'articles-of-tag.json' }) + await conduct.intercept('GET', /profiles\/.+/, { fixture: 'profile.json' }) + + await conduct.login() + }) + + test.describe('post article', () => { + test('jump to post detail page when submit create article form', async ({ page, conduct }) => { + await conduct.goto(Route.ArticleCreate) + + const articleFixture = await conduct.getFixture<{ article: Article }>('article.json') + const waitForPostArticle = await conduct.intercept('POST', /articles$/, { body: articleFixture }) + + await page.getByPlaceholder('Article Title').fill(articleFixture.article.title) + await page.getByPlaceholder("What's this article about?").fill(articleFixture.article.description) + await page.getByPlaceholder('Write your article (in markdown)').fill(articleFixture.article.body) + for (const tag of articleFixture.article.tagList) { + await page.getByPlaceholder('Enter tags').fill(tag) + await page.getByPlaceholder('Enter tags').press('Enter') + } + + await page.getByRole('button', { name: 'Publish Article' }).dispatchEvent('click') + await waitForPostArticle() + + await conduct.intercept('GET', /articles\/.+/, { fixture: 'article.json' }) + await page.waitForURL(/article\/article-title/) + await expect (page.getByRole('heading', { name: 'Article title' })).toContainText('Article title') + }) + + test('should render markdown correctly', async ({ browserName, page, conduct }) => { + test.skip(browserName !== 'chromium') + await conduct.goto(Route.ArticleDetail) + + const waitForArticle = await conduct.intercept('GET', /articles\/.+/, { fixture: 'article.json' }) + await waitForArticle() + const innerHTML = await page.locator('.article-content').innerHTML() + expect(formatHTML(innerHTML)).toMatchSnapshot('markdown-render.html') + }) + }) + + test.describe('delete article', () => { + for (const [index, position] of ['banner', 'article footer'].entries()) { + test(`delete article from ${position}`, async ({ page, conduct }) => { + const waitForArticle = await conduct.intercept('GET', /articles\/.+/, { fixture: 'article.json' }) + await conduct.goto(Route.ArticleDetail) + await waitForArticle() + + await conduct.intercept('DELETE', /articles\/.+/) + await page.getByRole('button', { name: 'Delete Article' }).nth(index).click() + + await expect(page).toHaveURL(Route.Home) + }) + } + }) +}) diff --git a/playwright/article/article.spec.ts-snapshots/markdown-render-chromium-darwin.html b/playwright/article/article.spec.ts-snapshots/markdown-render-chromium-darwin.html new file mode 100644 index 00000000..c4567bb8 --- /dev/null +++ b/playwright/article/article.spec.ts-snapshots/markdown-render-chromium-darwin.html @@ -0,0 +1,8 @@ +
+

Article body

+

This is Strong text

+
+ diff --git a/playwright/conduct.page-object.ts b/playwright/conduct.page-object.ts new file mode 100644 index 00000000..70a4608a --- /dev/null +++ b/playwright/conduct.page-object.ts @@ -0,0 +1,69 @@ +import fs from 'node:fs/promises' +import path from 'node:path' +import url from 'node:url' +import type { Page, Response } from '@playwright/test' +import type { User } from '../src/services/api.ts' +import { Route } from './constant' +import { expect } from './extends.ts' +import { boxedStep } from './utils/test-decorators.ts' + +const __dirname = url.fileURLToPath(new URL('.', import.meta.url)) +const fixtureDir = path.join(__dirname, '../cypress/fixtures') + +export class ConductPageObject { + constructor( + public readonly page: Page, + ) {} + + async intercept(method: 'POST' | 'GET' | 'PATCH' | 'DELETE' | 'PUT', url: string | RegExp, options: { + fixture?: string + statusCode?: number + body?: unknown + } = {}): Promise<(timeout?: number) => Promise> { + await this.page.route(url, async route => { + if (route.request().method() !== method) + return await route.continue() + + return await route.fulfill({ + status: options.statusCode || undefined, + json: options.body ?? undefined, + path: options.fixture ? path.join(fixtureDir, options.fixture) : undefined, + }) + }) + + return (timeout: number = 1000) => this.page.waitForResponse(response => { + const request = response.request() + if (request.method() !== method) + return false + + if (typeof url === 'string') + return request.url().includes(url) + + return url.test(request.url()) + }, { timeout }) + } + + async getFixture(fixture: string): Promise { + const file = path.join(fixtureDir, fixture) + return JSON.parse(await fs.readFile(file, 'utf8')) as T + } + + async goto(route: Route) { + await this.page.goto(route) + } + + @boxedStep + async login(username = 'plumrx') { + const userFixture = await this.getFixture<{ user: User }>('user.json') + userFixture.user.username = username + await this.intercept('POST', /users\/login$/, { statusCode: 200, body: userFixture }) + + await this.goto(Route.Login) + + await this.page.getByPlaceholder('Email').fill('foo@example.com') + await this.page.getByPlaceholder('Password').fill('12345678') + await this.page.getByRole('button', { name: 'Sign in' }).click() + + await expect(this.page).toHaveURL(Route.Home) + } +} diff --git a/playwright/constant.ts b/playwright/constant.ts new file mode 100644 index 00000000..0f2a523f --- /dev/null +++ b/playwright/constant.ts @@ -0,0 +1,8 @@ +export enum Route { + Home = '/#/', + Login = '/#/login', + Register = '/#/register', + Settings = '/#/settings', + ArticleCreate = '/#/article/create', + ArticleDetail = '/#/article/article-title', +} diff --git a/playwright/extends.ts b/playwright/extends.ts new file mode 100644 index 00000000..49855c05 --- /dev/null +++ b/playwright/extends.ts @@ -0,0 +1,22 @@ +import { test as base } from '@playwright/test' +import { ConductPageObject } from './conduct.page-object.ts' + +export const test = base.extend<{ + conduct: ConductPageObject +}>({ + conduct: async ({ page }, use) => { + const buyscoutPageObject = new ConductPageObject(page) + await use(buyscoutPageObject) + }, +}) + +test.afterEach(async ({ page }, testInfo) => { + if (!process.env.CI && testInfo.status !== testInfo.expectedStatus) { + // eslint-disable-next-line ts/restrict-template-expressions + process.stderr.write(`❌ ❌ PLAYWRIGHT TEST FAILURE ❌ ❌\n${testInfo.error?.stack || testInfo.error}\n`) + testInfo.setTimeout(0) + await page.pause() + } +}) + +export const expect = test.expect diff --git a/playwright/tsconfig.json b/playwright/tsconfig.json new file mode 100644 index 00000000..384105c6 --- /dev/null +++ b/playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "lib": ["ESNext", "DOM"], + "isolatedModules": false + }, + "include": [ + "./**/*" + ] +} diff --git a/playwright/utils/formatHTML.ts b/playwright/utils/formatHTML.ts new file mode 100644 index 00000000..2a0722ca --- /dev/null +++ b/playwright/utils/formatHTML.ts @@ -0,0 +1,8 @@ +import { prettyPrint } from 'html' + +export function formatHTML(rawHTMLString: string) { + const removeComments = rawHTMLString.replaceAll(//gs, '') + const pretty = prettyPrint(removeComments, { indent_size: 2 }) + const removeEmptyLines = `${pretty}\n`.replaceAll(/\n{2,}/g, '\n') + return removeEmptyLines +} diff --git a/playwright/utils/test-decorators.ts b/playwright/utils/test-decorators.ts new file mode 100644 index 00000000..afdc3190 --- /dev/null +++ b/playwright/utils/test-decorators.ts @@ -0,0 +1,23 @@ +import { test } from '../extends' + +export function step(target: Function, context: ClassMethodDecoratorContext) { + return async function replacementMethod(this: Function, ...args: unknown[]) { + const className = this.constructor.name + const name = `${className.replace(/PageObject$/, '')}.${context.name as string}` + return await test.step(name, async () => { + // eslint-disable-next-line ts/no-unsafe-return + return await target.call(this, ...args) + }) + } +} + +export function boxedStep(target: Function, context: ClassMethodDecoratorContext) { + return async function replacementMethod(this: Function, ...args: unknown[]) { + const className = this.constructor.name + const name = `${className.replace(/PageObject$/, '')}.${context.name as string}` + return await test.step(name, async () => { + // eslint-disable-next-line ts/no-unsafe-return + return await target.call(this, ...args) + }, { box: true }) + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2374fd4..177ffc7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,10 +26,13 @@ importers: devDependencies: '@mutoe/eslint-config': specifier: ^4.11.0-2 - version: 4.11.0-2(@typescript-eslint/utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(@vue/compiler-sfc@3.5.22)(eslint-import-resolver-node@0.3.9)(eslint-plugin-vuejs-accessibility@2.4.1(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1)) + version: 4.11.0-2(@typescript-eslint/utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(@vue/compiler-sfc@3.5.22)(eslint-import-resolver-node@0.3.9)(eslint-plugin-vuejs-accessibility@2.4.1(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1)) '@pinia/testing': specifier: ^1.0.2 version: 1.0.2(pinia@3.0.3(typescript@5.9.2)(vue@3.5.22(typescript@5.9.2))) + '@playwright/test': + specifier: ^1.55.1 + version: 1.55.1 '@testing-library/cypress': specifier: ^10.1.0 version: 10.1.0(cypress@13.13.2) @@ -39,12 +42,18 @@ importers: '@testing-library/vue': specifier: ^8.1.0 version: 8.1.0(@vue/compiler-sfc@3.5.22)(@vue/server-renderer@3.5.22(vue@3.5.22(typescript@5.9.2)))(vue@3.5.22(typescript@5.9.2)) + '@types/html': + specifier: ^1.0.4 + version: 1.0.4 + '@types/node': + specifier: ^24.5.2 + version: 24.5.2 '@vitejs/plugin-vue': specifier: ^6.0.1 - version: 6.0.1(vite@7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2)) + version: 6.0.1(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2)) '@vitest/coverage-v8': specifier: ^3.2.4 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1)) concurrently: specifier: ^9.2.1 version: 9.2.1 @@ -57,15 +66,21 @@ importers: eslint-plugin-cypress: specifier: ^5.1.1 version: 5.1.1(eslint@9.36.0(jiti@2.6.0)) + eslint-plugin-vuejs-accessibility: + specifier: ^2.4.1 + version: 2.4.1(eslint@9.36.0(jiti@2.6.0)) happy-dom: specifier: ^18.0.1 version: 18.0.1 + html: + specifier: ^1.0.0 + version: 1.0.0 lint-staged: specifier: ^16.2.0 version: 16.2.0 msw: specifier: ^2.11.3 - version: 2.11.3(@types/node@20.19.17)(typescript@5.9.2) + version: 2.11.3(@types/node@24.5.2)(typescript@5.9.2) rollup-plugin-analyzer: specifier: ^4.0.0 version: 4.0.0 @@ -80,13 +95,13 @@ importers: version: 5.9.2 vite: specifier: ^7.1.7 - version: 7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) + version: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1) vitest-dom: specifier: ^0.1.1 - version: 0.1.1(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1)) + version: 0.1.1(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1)) vue-tsc: specifier: ^3.0.8 version: 3.0.8(typescript@5.9.2) @@ -124,6 +139,10 @@ packages: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.27.1': resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} @@ -373,12 +392,22 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} 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.10.0': + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -613,6 +642,11 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@playwright/test@1.55.1': + resolution: {integrity: sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==} + engines: {node: '>=18'} + hasBin: true + '@rolldown/pluginutils@1.0.0-beta.29': resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==} @@ -780,9 +814,15 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/html@1.0.4': + resolution: {integrity: sha512-Wb1ymSAftCLxhc3D6vS0Ike/0xg7W6c+DQxAkerU6pD7C8CMzTYwvrwnlcrTfsVO/nMelB9KOKIT7+N5lOeQUg==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -798,8 +838,8 @@ packages: '@types/node@20.19.17': resolution: {integrity: sha512-gfehUI8N1z92kygssiuWvLiwcbOB3IRktR6hTDgJlXMYh5OvkPSRmgfoBUmfZt+vhwJtX7v1Yw4KvvAf7c5QKQ==} - '@types/node@22.1.0': - resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==} + '@types/node@24.5.2': + resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1127,6 +1167,11 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -1198,10 +1243,6 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} @@ -1289,6 +1330,9 @@ packages: buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -1452,6 +1496,10 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + concurrently@9.2.1: resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==} engines: {node: '>=18'} @@ -1649,6 +1697,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2019,6 +2071,11 @@ packages: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2172,6 +2229,10 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html@1.0.0: + resolution: {integrity: sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==} + hasBin: true + http-signature@1.3.6: resolution: {integrity: sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==} engines: {node: '>=0.10'} @@ -2186,6 +2247,10 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2214,6 +2279,9 @@ packages: resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} engines: {node: '>=18'} + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} @@ -2342,6 +2410,9 @@ packages: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2396,6 +2467,10 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + jsdoc-type-pratt-parser@4.1.0: resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} @@ -2993,6 +3068,16 @@ packages: pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + playwright-core@1.55.1: + resolution: {integrity: sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.55.1: + resolution: {integrity: sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==} + engines: {node: '>=18'} + hasBin: true + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -3020,6 +3105,9 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} @@ -3067,6 +3155,9 @@ packages: resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} engines: {node: '>=18'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -3161,6 +3252,9 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -3320,6 +3414,9 @@ packages: resolution: {integrity: sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==} engines: {node: '>=20'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -3492,6 +3589,9 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + typescript@5.9.2: resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} engines: {node: '>=14.17'} @@ -3500,12 +3600,12 @@ packages: ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} - undici-types@6.13.0: - resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==} - undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.12.0: + resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==} + unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} @@ -3809,6 +3909,8 @@ snapshots: '@babel/helper-validator-identifier@7.22.20': {} + '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-identifier@7.27.1': {} '@babel/highlight@7.23.4': @@ -3832,7 +3934,7 @@ snapshots: '@babel/types@7.25.2': dependencies: '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 '@babel/types@7.28.4': @@ -4004,13 +4106,20 @@ snapshots: dependencies: escape-string-regexp: 4.0.0 eslint: 9.36.0(jiti@2.6.0) - ignore: 5.3.2 + ignore: 5.3.1 + + '@eslint-community/eslint-utils@4.4.0(eslint@9.36.0(jiti@2.6.0))': + dependencies: + eslint: 9.36.0(jiti@2.6.0) + eslint-visitor-keys: 3.4.3 '@eslint-community/eslint-utils@4.9.0(eslint@9.36.0(jiti@2.6.0))': dependencies: eslint: 9.36.0(jiti@2.6.0) eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.12.1': {} '@eslint/compat@1.4.0(eslint@9.36.0(jiti@2.6.0))': @@ -4022,7 +4131,7 @@ snapshots: '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -4044,10 +4153,10 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) espree: 10.4.0 globals: 14.0.0 - ignore: 5.3.2 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -4092,31 +4201,31 @@ snapshots: '@inquirer/ansi@1.0.0': {} - '@inquirer/confirm@5.1.18(@types/node@20.19.17)': + '@inquirer/confirm@5.1.18(@types/node@24.5.2)': dependencies: - '@inquirer/core': 10.2.2(@types/node@20.19.17) - '@inquirer/type': 3.0.8(@types/node@20.19.17) + '@inquirer/core': 10.2.2(@types/node@24.5.2) + '@inquirer/type': 3.0.8(@types/node@24.5.2) optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 24.5.2 - '@inquirer/core@10.2.2(@types/node@20.19.17)': + '@inquirer/core@10.2.2(@types/node@24.5.2)': dependencies: '@inquirer/ansi': 1.0.0 '@inquirer/figures': 1.0.13 - '@inquirer/type': 3.0.8(@types/node@20.19.17) + '@inquirer/type': 3.0.8(@types/node@24.5.2) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.2 optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 24.5.2 '@inquirer/figures@1.0.13': {} - '@inquirer/type@3.0.8(@types/node@20.19.17)': + '@inquirer/type@3.0.8(@types/node@24.5.2)': optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 24.5.2 '@isaacs/cliui@8.0.2': dependencies: @@ -4162,7 +4271,7 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@mutoe/eslint-config@4.11.0-2(@typescript-eslint/utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(@vue/compiler-sfc@3.5.22)(eslint-import-resolver-node@0.3.9)(eslint-plugin-vuejs-accessibility@2.4.1(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1))': + '@mutoe/eslint-config@4.11.0-2(@typescript-eslint/utils@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(@vue/compiler-sfc@3.5.22)(eslint-import-resolver-node@0.3.9)(eslint-plugin-vuejs-accessibility@2.4.1(eslint@9.36.0(jiti@2.6.0)))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1))': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 0.10.1 @@ -4172,7 +4281,7 @@ snapshots: '@stylistic/eslint-plugin': 4.4.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) '@typescript-eslint/eslint-plugin': 8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) '@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - '@vitest/eslint-plugin': 1.3.12(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1)) + '@vitest/eslint-plugin': 1.3.12(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1)) ansis: 3.17.0 cac: 6.7.14 eslint: 9.36.0(jiti@2.6.0) @@ -4262,6 +4371,10 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true + '@playwright/test@1.55.1': + dependencies: + playwright: 1.55.1 + '@rolldown/pluginutils@1.0.0-beta.29': {} '@rollup/rollup-android-arm-eabi@4.52.2': @@ -4350,7 +4463,7 @@ snapshots: '@testing-library/dom@10.4.0': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.23.4 '@babel/runtime': 7.23.4 '@types/aria-query': 5.0.4 aria-query: 5.3.0 @@ -4404,8 +4517,12 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.5': {} + '@types/estree@1.0.8': {} + '@types/html@1.0.4': {} + '@types/json-schema@7.0.15': {} '@types/lodash@4.17.20': {} @@ -4420,10 +4537,9 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@22.1.0': + '@types/node@24.5.2': dependencies: - undici-types: 6.13.0 - optional: true + undici-types: 7.12.0 '@types/normalize-package-data@2.4.4': {} @@ -4443,12 +4559,12 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.1.0 + '@types/node': 24.5.2 optional: true '@typescript-eslint/eslint-plugin@8.44.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)': dependencies: - '@eslint-community/regexpp': 4.12.1 + '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) '@typescript-eslint/scope-manager': 8.44.1 '@typescript-eslint/type-utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) @@ -4469,7 +4585,7 @@ snapshots: '@typescript-eslint/types': 8.44.1 '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.44.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) eslint: 9.36.0(jiti@2.6.0) typescript: 5.9.2 transitivePeerDependencies: @@ -4479,7 +4595,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.9.2) '@typescript-eslint/types': 8.44.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -4498,7 +4614,7 @@ snapshots: '@typescript-eslint/types': 8.44.1 '@typescript-eslint/typescript-estree': 8.44.1(typescript@5.9.2) '@typescript-eslint/utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) eslint: 9.36.0(jiti@2.6.0) ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 @@ -4513,11 +4629,11 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.44.1(typescript@5.9.2) '@typescript-eslint/types': 8.44.1 '@typescript-eslint/visitor-keys': 8.44.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.7.2 + semver: 7.6.3 ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -4598,18 +4714,18 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2))': + '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.29 - vite: 7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) vue: 3.5.22(typescript@5.9.2) - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 ast-v8-to-istanbul: 0.3.5 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -4619,18 +4735,18 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1) transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.3.12(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1))': + '@vitest/eslint-plugin@1.3.12(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1))': dependencies: '@typescript-eslint/scope-manager': 8.44.1 '@typescript-eslint/utils': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2) eslint: 9.36.0(jiti@2.6.0) optionalDependencies: typescript: 5.9.2 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -4642,14 +4758,14 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(vite@7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - msw: 2.11.3(@types/node@20.19.17)(typescript@5.9.2) - vite: 7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) + msw: 2.11.3(@types/node@24.5.2)(typescript@5.9.2) + vite: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -4766,7 +4882,7 @@ snapshots: alien-signals: 2.0.7 muggle-string: 0.4.1 path-browserify: 1.0.1 - picomatch: 4.0.3 + picomatch: 4.0.2 optionalDependencies: typescript: 5.9.2 @@ -4806,10 +4922,16 @@ snapshots: abbrev@2.0.0: {} + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 + acorn@8.12.1: {} + acorn@8.15.0: {} aggregate-error@3.1.0: @@ -4868,9 +4990,6 @@ snapshots: dependencies: dequal: 2.0.3 - aria-query@5.3.2: - optional: true - array-buffer-byte-length@1.0.0: dependencies: call-bind: 1.0.5 @@ -4947,6 +5066,8 @@ snapshots: buffer-crc32@0.2.13: {} + buffer-from@1.1.2: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -5098,6 +5219,13 @@ snapshots: concat-map@0.0.1: {} + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + concurrently@9.2.1: dependencies: chalk: 4.1.2 @@ -5213,11 +5341,9 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - debug@4.4.3(supports-color@8.1.1): + debug@4.4.3: dependencies: ms: 2.1.3 - optionalDependencies: - supports-color: 8.1.1 decode-named-character-reference@1.2.0: dependencies: @@ -5363,6 +5489,8 @@ snapshots: '@esbuild/win32-ia32': 0.25.10 '@esbuild/win32-x64': 0.25.10 + escalade@3.1.2: {} + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -5374,12 +5502,12 @@ snapshots: eslint-compat-utils@0.5.1(eslint@9.36.0(jiti@2.6.0)): dependencies: eslint: 9.36.0(jiti@2.6.0) - semver: 7.7.2 + semver: 7.6.3 eslint-compat-utils@0.6.5(eslint@9.36.0(jiti@2.6.0)): dependencies: eslint: 9.36.0(jiti@2.6.0) - semver: 7.7.2 + semver: 7.6.3 eslint-config-flat-gitignore@2.1.0(eslint@9.36.0(jiti@2.6.0)): dependencies: @@ -5441,7 +5569,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.44.1 comment-parser: 1.4.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.36.0(jiti@2.6.0) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 @@ -5460,7 +5588,7 @@ snapshots: '@es-joy/jsdoccomment': 0.50.2 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint: 9.36.0(jiti@2.6.0) espree: 10.4.0 @@ -5477,7 +5605,7 @@ snapshots: eslint: 9.36.0(jiti@2.6.0) eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.0)) eslint-json-compat-utils: 0.2.1(eslint@9.36.0(jiti@2.6.0))(jsonc-eslint-parser@2.4.0) - espree: 10.4.0 + espree: 9.6.1 graphemer: 1.4.0 jsonc-eslint-parser: 2.4.0 natural-compare: 1.4.0 @@ -5495,7 +5623,7 @@ snapshots: globals: 15.15.0 globrex: 0.1.2 ignore: 5.3.2 - semver: 7.7.2 + semver: 7.6.3 ts-declaration-location: 1.0.7(typescript@5.9.2) transitivePeerDependencies: - typescript @@ -5524,18 +5652,18 @@ snapshots: eslint-plugin-regexp@2.10.0(eslint@9.36.0(jiti@2.6.0)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0)) '@eslint-community/regexpp': 4.12.1 comment-parser: 1.4.1 eslint: 9.36.0(jiti@2.6.0) - jsdoc-type-pratt-parser: 4.1.0 + jsdoc-type-pratt-parser: 4.0.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 eslint-plugin-toml@0.12.0(eslint@9.36.0(jiti@2.6.0)): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) eslint: 9.36.0(jiti@2.6.0) eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.0)) lodash: 4.17.21 @@ -5571,12 +5699,12 @@ snapshots: eslint-plugin-vue@10.5.0(@stylistic/eslint-plugin@4.4.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))(vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.0))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.36.0(jiti@2.6.0)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.36.0(jiti@2.6.0)) eslint: 9.36.0(jiti@2.6.0) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.1 - semver: 7.7.2 + semver: 7.6.3 vue-eslint-parser: 10.2.0(eslint@9.36.0(jiti@2.6.0)) xml-name-validator: 4.0.0 optionalDependencies: @@ -5585,17 +5713,16 @@ snapshots: eslint-plugin-vuejs-accessibility@2.4.1(eslint@9.36.0(jiti@2.6.0)): dependencies: - aria-query: 5.3.2 + aria-query: 5.3.0 emoji-regex: 10.5.0 eslint: 9.36.0(jiti@2.6.0) vue-eslint-parser: 9.4.3(eslint@9.36.0(jiti@2.6.0)) transitivePeerDependencies: - supports-color - optional: true eslint-plugin-yml@1.18.0(eslint@9.36.0(jiti@2.6.0)): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint: 9.36.0(jiti@2.6.0) eslint-compat-utils: 0.6.5(eslint@9.36.0(jiti@2.6.0)) @@ -5613,7 +5740,6 @@ snapshots: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - optional: true eslint-scope@8.4.0: dependencies: @@ -5642,7 +5768,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -5653,7 +5779,7 @@ snapshots: file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - ignore: 5.3.2 + ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 @@ -5674,8 +5800,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 3.4.3 esquery@1.6.0: @@ -5692,7 +5818,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.5 esutils@2.0.3: {} @@ -5726,7 +5852,7 @@ snapshots: extract-zip@2.0.1(supports-color@8.1.1): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -5822,6 +5948,9 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.1 + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -5960,6 +6089,10 @@ snapshots: html-escaper@2.0.2: {} + html@1.0.0: + dependencies: + concat-stream: 1.6.2 + http-signature@1.3.6: dependencies: assert-plus: 1.0.0 @@ -5972,6 +6105,8 @@ snapshots: ieee754@1.2.1: {} + ignore@5.3.1: {} + ignore@5.3.2: {} ignore@7.0.5: {} @@ -5989,6 +6124,8 @@ snapshots: index-to-position@1.2.0: {} + inherits@2.0.4: {} + ini@1.3.8: {} ini@2.0.0: {} @@ -6110,6 +6247,8 @@ snapshots: is-what@4.1.16: {} + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -6127,7 +6266,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -6168,6 +6307,8 @@ snapshots: jsbn@0.1.1: {} + jsdoc-type-pratt-parser@4.0.0: {} + jsdoc-type-pratt-parser@4.1.0: {} jsesc@3.0.2: {} @@ -6186,10 +6327,10 @@ snapshots: jsonc-eslint-parser@2.4.0: dependencies: - acorn: 8.15.0 + acorn: 8.12.1 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - semver: 7.7.2 + semver: 7.6.3 jsonfile@6.1.0: dependencies: @@ -6311,7 +6452,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.6.3 markdown-table@3.0.4: {} @@ -6613,7 +6754,7 @@ snapshots: micromark@4.0.2: dependencies: '@types/debug': 4.1.12 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.3.6(supports-color@8.1.1) decode-named-character-reference: 1.2.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 @@ -6685,11 +6826,11 @@ snapshots: ms@2.1.3: {} - msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2): + msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2): dependencies: '@bundled-es-modules/cookie': 2.0.1 '@bundled-es-modules/statuses': 1.0.1 - '@inquirer/confirm': 5.1.18(@types/node@20.19.17) + '@inquirer/confirm': 5.1.18(@types/node@24.5.2) '@mswjs/interceptors': 0.39.6 '@open-draft/deferred-promise': 2.2.0 '@types/cookie': 0.6.0 @@ -6945,6 +7086,14 @@ snapshots: exsolve: 1.0.7 pathe: 2.0.3 + playwright-core@1.55.1: {} + + playwright@1.55.1: + dependencies: + playwright-core: 1.55.1 + optionalDependencies: + fsevents: 2.3.2 + pluralize@8.0.0: {} pnpm-workspace-yaml@0.3.1: @@ -6972,6 +7121,8 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 + process-nextick-args@2.0.1: {} + process@0.11.10: {} proto-list@1.2.4: {} @@ -7018,6 +7169,16 @@ snapshots: type-fest: 4.24.0 unicorn-magic: 0.1.0 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readdirp@4.1.2: {} redent@4.0.0: @@ -7129,6 +7290,8 @@ snapshots: dependencies: tslib: 2.6.2 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {} @@ -7297,6 +7460,10 @@ snapshots: get-east-asian-width: 1.4.0 strip-ansi: 7.1.0 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -7470,15 +7637,16 @@ snapshots: type-fest@4.41.0: {} + typedarray@0.0.6: {} + typescript@5.9.2: {} ufo@1.6.1: {} - undici-types@6.13.0: - optional: true - undici-types@6.21.0: {} + undici-types@7.12.0: {} + unicorn-magic@0.1.0: {} unist-util-is@6.0.0: @@ -7562,13 +7730,13 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@3.2.4(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1): dependencies: cac: 6.7.14 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -7583,7 +7751,7 @@ snapshots: - tsx - yaml - vite@7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1): + vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -7592,12 +7760,12 @@ snapshots: rollup: 4.52.2 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 20.19.17 + '@types/node': 24.5.2 fsevents: 2.3.3 jiti: 2.6.0 yaml: 2.8.1 - vitest-dom@0.1.1(vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1)): + vitest-dom@0.1.1(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1)): dependencies: aria-query: 5.3.0 chalk: 5.3.0 @@ -7605,36 +7773,36 @@ snapshots: dom-accessibility-api: 0.6.3 lodash-es: 4.17.21 redent: 4.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1) - vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.17)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(yaml@2.8.1): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.5.2)(happy-dom@18.0.1)(jiti@2.6.0)(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.11.3(@types/node@20.19.17)(typescript@5.9.2))(vite@7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(msw@2.11.3(@types/node@24.5.2)(typescript@5.9.2))(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 chai: 5.3.3 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 expect-type: 1.2.2 magic-string: 0.30.19 pathe: 2.0.3 - picomatch: 4.0.3 + picomatch: 4.0.2 std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.7(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@20.19.17)(jiti@2.6.0)(yaml@2.8.1) + vite: 7.1.7(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.5.2)(jiti@2.6.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 20.19.17 + '@types/node': 24.5.2 happy-dom: 18.0.1 transitivePeerDependencies: - jiti @@ -7656,19 +7824,19 @@ snapshots: vue-eslint-parser@10.2.0(eslint@9.36.0(jiti@2.6.0)): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.36.0(jiti@2.6.0) eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 esquery: 1.6.0 - semver: 7.7.2 + semver: 7.6.3 transitivePeerDependencies: - supports-color vue-eslint-parser@9.4.3(eslint@9.36.0(jiti@2.6.0)): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 9.36.0(jiti@2.6.0) eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 @@ -7678,7 +7846,6 @@ snapshots: semver: 7.7.2 transitivePeerDependencies: - supports-color - optional: true vue-router@4.5.1(vue@3.5.22(typescript@5.9.2)): dependencies: @@ -7788,7 +7955,7 @@ snapshots: yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.2.0 + escalade: 3.1.2 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 00000000..eb37b315 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,7 @@ +ignoredBuiltDependencies: + - msw + - unrs-resolver + +onlyBuiltDependencies: + - esbuild + - simple-git-hooks diff --git a/src/components/ArticleDetail.vue b/src/components/ArticleDetail.vue index fe2403be..f2546a0f 100644 --- a/src/components/ArticleDetail.vue +++ b/src/components/ArticleDetail.vue @@ -1,5 +1,5 @@