diff --git a/strcalc/src/main/frontend/.eslintrc b/strcalc/src/main/frontend/.eslintrc index 1c6c7f7..ab7397d 100644 --- a/strcalc/src/main/frontend/.eslintrc +++ b/strcalc/src/main/frontend/.eslintrc @@ -1,8 +1,8 @@ { - "env" : { - "browser" : true, + "env": { + "browser": true, "node": true, - "es2023" : true + "es2023": true }, "parserOptions": { "ecmaVersion": "latest", @@ -15,7 +15,7 @@ ], "extends": [ "eslint:recommended", - "plugin:jsdoc/recommended" + "plugin:jsdoc/recommended-typescript-flavor-error" ], "overrides": [ { @@ -26,7 +26,7 @@ ] } ], - "rules" : { + "rules": { "@stylistic/js/comma-dangle": [ "error", "never" ], @@ -51,5 +51,12 @@ "no-console": [ "error", { "allow": [ "warn", "error" ]} ] + }, + "settings": { + "jsdoc": { + "preferredTypes": { + "Object": "object" + } + } } } diff --git a/strcalc/src/main/frontend/ci/vitest.config.browser.js b/strcalc/src/main/frontend/ci/vitest.config.browser.js index 3e8eedc..914dbbb 100644 --- a/strcalc/src/main/frontend/ci/vitest.config.browser.js +++ b/strcalc/src/main/frontend/ci/vitest.config.browser.js @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import viteConfig, { buildDir } from '../vite.config' +import viteConfig, { buildDir } from '../vite.config.js' export default mergeConfig(viteConfig, defineConfig({ test: { diff --git a/strcalc/src/main/frontend/ci/vitest.config.js b/strcalc/src/main/frontend/ci/vitest.config.js index 91ae21a..f8b69cf 100644 --- a/strcalc/src/main/frontend/ci/vitest.config.js +++ b/strcalc/src/main/frontend/ci/vitest.config.js @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import viteConfig from '../vite.config' +import viteConfig from '../vite.config.js' export default mergeConfig(viteConfig, defineConfig({ test: { diff --git a/strcalc/src/main/frontend/components/app.js b/strcalc/src/main/frontend/components/app.js index 2bac7a3..bac49d6 100644 --- a/strcalc/src/main/frontend/components/app.js +++ b/strcalc/src/main/frontend/components/app.js @@ -21,7 +21,8 @@ export default class App { * demonstrate how to design much larger applications for testability. * @param {object} params - parameters made available to all initializers * @param {Element} params.appElem - parent Element containing all components - * @param {object} params.calculators - calculator implementations + * @param {import('./calculators.js').StrCalcDescriptors} params.calculators - + * calculator implementations */ init(params) { // In this example application, none of the components depend on one diff --git a/strcalc/src/main/frontend/components/app.test.js b/strcalc/src/main/frontend/components/app.test.js index a9d1cba..e6c4471 100644 --- a/strcalc/src/main/frontend/components/app.test.js +++ b/strcalc/src/main/frontend/components/app.test.js @@ -6,17 +6,23 @@ */ import App from './app.js' import { afterAll, afterEach, describe, expect, test } from 'vitest' -import StringCalculatorPage from '../test/page' +import StringCalculatorPage from '../test/page.js' // @vitest-environment jsdom describe('initial state after calling App.init()', () => { - const page = StringCalculatorPage.new() + /** @type {import('./calculators.js').StrCalcCallback} */ + // eslint-disable-next-line no-unused-vars + const implStub = async _ => ({}) + + /** @type {import('./calculators.js').StrCalcDescriptors} */ const calculators = { - 'first': { label: 'First calculator', impl: null }, - 'second': { label: 'Second calculator', impl: null }, - 'third': { label: 'Third calculator', impl: null } + 'first': { label: 'First calculator', impl: implStub }, + 'second': { label: 'Second calculator', impl: implStub }, + 'third': { label: 'Third calculator', impl: implStub } } + const page = StringCalculatorPage.new() + afterEach(() => page.clear()) afterAll(() => page.remove()) @@ -28,4 +34,3 @@ describe('initial state after calling App.init()', () => { expect(e.href).toContain('%22Hello,_World!%22') }) }) - diff --git a/strcalc/src/main/frontend/components/calculator.js b/strcalc/src/main/frontend/components/calculator.js index 0f26f71..71314e2 100644 --- a/strcalc/src/main/frontend/components/calculator.js +++ b/strcalc/src/main/frontend/components/calculator.js @@ -11,29 +11,54 @@ export default class Calculator { * Initializes the Calculator within the document. * @param {object} params - parameters made available to all initializers * @param {Element} params.appElem - parent Element containing all components - * @param {object} params.calculators - calculator implementations + * @param {import('./calculators.js').StrCalcDescriptors} params.calculators - + * calculator implementations + * @param {Function} [params.instantiate] - alternative template instantiation + * function for testing + * @returns {void} */ - init({ appElem, calculators }) { + init({ appElem, calculators, instantiate = Template }) { const calcOptions = Object.entries(calculators) .map(([k, v]) => ({ value: k, label: v.label })) - const t = Template({ calcOptions }) + const t = instantiate({ calcOptions }) const [ form, resultElem ] = t.children appElem.appendChild(t) - document.querySelector('#numbers').focus() + + /** @type {(HTMLInputElement | null)} */ + const numbers = document.querySelector('#numbers') + if (numbers === null) return console.error('missing numbers input') + numbers.focus() + form.addEventListener( - 'submit', e => Calculator.#submitRequest(e, resultElem, calculators) + 'submit', + /** @param {Event} e - form submit event */ + e => {Calculator.#submitRequest(e, resultElem, calculators)} ) } - // https://simonplend.com/how-to-use-fetch-to-post-form-data-as-json-to-your-api/ + /** + * @param {Event} event - form submit event + * @param {Element} resultElem - element into which to write the result + * @param {import('./calculators.js').StrCalcDescriptors} calculators - + * calculator implementations + * @returns {Promise} + * @see https://simonplend.com/how-to-use-fetch-to-post-form-data-as-json-to-your-api/ + */ static async #submitRequest(event, resultElem, calculators) { event.preventDefault() - const form = event.currentTarget + const form = /** @type {HTMLFormElement} */ (event.currentTarget) const data = new FormData(form) - const selected = form.querySelector('input[name="impl"]:checked').value + + /** @type {(HTMLInputElement | null)} */ + const implInput = form.querySelector('input[name="impl"]:checked') + if (implInput === null) return console.error('missing implementation input') + const selected = implInput.value + + /** @type {(HTMLParagraphElement | null)} */ const result = resultElem.querySelector('p') + if (result === null) return console.error('missing result element') // None of the backends need the 'impl' parameter, and the Java backend // will return a 500 if we send it. @@ -43,7 +68,7 @@ export default class Calculator { const response = await calculators[selected].impl(data) result.textContent = `Result: ${response.result}` } catch (err) { - result.textContent = err + result.textContent = /** @type {any} */ (err) } } } diff --git a/strcalc/src/main/frontend/components/calculator.test.js b/strcalc/src/main/frontend/components/calculator.test.js index e2921bb..054b5df 100644 --- a/strcalc/src/main/frontend/components/calculator.test.js +++ b/strcalc/src/main/frontend/components/calculator.test.js @@ -5,9 +5,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import Calculator from './calculator' +import Calculator from './calculator.js' +import Template from './calculator.hbs' import { afterAll, afterEach, describe, expect, test, vi } from 'vitest' -import StringCalculatorPage from '../test/page' +import StringCalculatorPage from '../test/page.js' // @vitest-environment jsdom describe('Calculator', () => { @@ -15,22 +16,45 @@ describe('Calculator', () => { const setup = () => { const postFormData = vi.fn() + /** @type {import('./calculators.js').StrCalcDescriptors} */ const calculators = { 'api': { label: 'API', impl: postFormData }, - 'browser': { label: 'Browser', impl: () => {} } + 'browser': { label: 'Browser', impl: vi.fn() } } new Calculator().init({ appElem: page.appElem, calculators }) return { page, postFormData } } + const setupConsoleErrorSpy = () => { + const consoleSpy = vi.spyOn(console, 'error') + .mockImplementationOnce(() => {}) + + return { + consoleSpy, + loggedError: () => { + const lastCall = consoleSpy.mock.lastCall + if (!lastCall) throw new Error('error not logged') + return lastCall + } + } + } + + /** + * @param {string} numbersString - input to the StringCalculator + * @returns {FormData} - form data to submit to the implementation + */ const expectedFormData = (numbersString) => { const data = new FormData() data.append('numbers', numbersString) return data } - afterEach(() => page.clear()) + afterEach(() => { + vi.restoreAllMocks() + page.clear() + }) + afterAll(() => page.remove()) test('renders form and result placeholder', async () => { @@ -59,4 +83,51 @@ describe('Calculator', () => { await expect(result).resolves.toBe('Error: D\'oh!') expect(postFormData).toHaveBeenCalledWith(expectedFormData('2,2')) }) + + test('logs error if missing numbers input element', async () => { + const { loggedError } = setupConsoleErrorSpy() + /** @type {import('./calculators.js').StrCalcDescriptors} */ + const calculators = {} + /** + * @param {any} context - init parameters for template + * @returns {DocumentFragment} - template elements without #numbers element + */ + const BadTemplate = (context) => { + const t = Template({ context }) + const [ form ] = t.children + const input = form.querySelector('#numbers') + + if (input !== null) input.remove() + return t + } + + new Calculator().init( + { appElem: page.appElem, calculators, instantiate: BadTemplate } + ) + + expect(await vi.waitFor(loggedError)) + .toStrictEqual(['missing numbers input']) + }) + + test('logs error if missing implementation input element', async () => { + const { page } = setup() + const { loggedError } = setupConsoleErrorSpy() + + page.impl().remove() + page.enterValueAndSubmit('2,2') + + expect(await vi.waitFor(loggedError)) + .toStrictEqual(['missing implementation input']) + }) + + test('logs error if missing result element', async () => { + const { page } = setup() + const { loggedError } = setupConsoleErrorSpy() + + page.result().remove() + page.enterValueAndSubmit('2,2') + + expect(await vi.waitFor(loggedError)) + .toStrictEqual(['missing result element']) + }) }) diff --git a/strcalc/src/main/frontend/components/calculators.js b/strcalc/src/main/frontend/components/calculators.js index 6ab3691..77209c2 100644 --- a/strcalc/src/main/frontend/components/calculators.js +++ b/strcalc/src/main/frontend/components/calculators.js @@ -3,27 +3,58 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +/* global STRCALC_BACKEND */ import { postFormData } from './request.js' export const DEFAULT_ENDPOINT = './add' -const backendUrl = () => globalThis.STRCALC_BACKEND ? - new URL(DEFAULT_ENDPOINT, globalThis.STRCALC_BACKEND).toString() : +const backendUrl = () => STRCALC_BACKEND ? + new URL(DEFAULT_ENDPOINT, STRCALC_BACKEND).toString() : DEFAULT_ENDPOINT -const backendCalculator = async (data)=> postFormData(backendUrl(), data) +/** + * @typedef {object} StrCalcPayload + * @property {number} [result] - the result of the calculation + * @property {string} [error] - error message if the request failed + */ +/** + * Function that invokes a specific String Calculator implementation + * @callback StrCalcCallback + * @param {FormData} data - form data providing String Calculator input + * @returns {Promise} - the String Calculator result + */ + +/** + * Posts the String Calculator input to the backend implementation + * @type {StrCalcCallback} + */ +const backendCalculator = async (data) => postFormData(backendUrl(), data) + +/** + * Returns an error as a placeholder for an in-browser StringCalculator + * @type {StrCalcCallback} + */ const tempCalculator = async (data) => Promise.reject(new Error( `Temporary in-browser calculator received: "${data.get('numbers')}"` )) +/** + * Describes a specific StringCalculator implementation + * @typedef {object} StrCalcDescriptor + * @property {string} label - descriptive name describing the implementation + * @property {StrCalcCallback} impl - callback invoking StringCalculator impl + */ + /** * Collection of production String Calculator implementations * * Each implementation takes a FormData instance containing only a * 'numbers' field as its single argument. + * @typedef {Object.} StrCalcDescriptors */ +/** @type {StrCalcDescriptors} */ export default { 'api': { label: 'Tomcat backend API (Java)', impl: backendCalculator }, 'browser': { label: 'In-browser (JavaScript)', impl: tempCalculator } diff --git a/strcalc/src/main/frontend/components/calculators.test.js b/strcalc/src/main/frontend/components/calculators.test.js index 86d29ea..336decf 100644 --- a/strcalc/src/main/frontend/components/calculators.test.js +++ b/strcalc/src/main/frontend/components/calculators.test.js @@ -5,12 +5,16 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { default as calculators, DEFAULT_ENDPOINT } from './calculators' +import { default as calculators, DEFAULT_ENDPOINT } from './calculators.js' import { afterEach, describe, expect, test, vi } from 'vitest' -import setupFetchStub from '../test/fetch-stub' -import { postOptions } from './request' +import setupFetchStub from '../test/fetch-stub.js' +import { postOptions } from './request.js' describe('calculators', () => { + /** + * @param {string} numbersStr - input to the String Calculator + * @returns {FormData} - form data to submit to the String Calculator + */ const setupData = (numbersStr) => { const data = new FormData() data.append('numbers', numbersStr) @@ -22,7 +26,7 @@ describe('calculators', () => { describe('defaultPost', () => { test('posts same server by default', async () => { const data = setupData('2,2') - const fetchStub = setupFetchStub(JSON.stringify({ result: 5 })) + const fetchStub = setupFetchStub({ result: 5 }) await expect(calculators.api.impl(data)).resolves.toEqual({ result: 5 }) expect(fetchStub).toHaveBeenCalledWith( @@ -31,7 +35,7 @@ describe('calculators', () => { test('posts to globalThis.STRCALC_BACKEND', async () => { const data = setupData('2,2') - const fetchStub = setupFetchStub(JSON.stringify({ result: 5 })) + const fetchStub = setupFetchStub({ result: 5 }) vi.stubGlobal('STRCALC_BACKEND', 'http://localhost:8080/strcalc/') await expect(calculators.api.impl(data)).resolves.toEqual({ result: 5 }) diff --git a/strcalc/src/main/frontend/components/helpers.js b/strcalc/src/main/frontend/components/helpers.js index fb40541..b9d4205 100644 --- a/strcalc/src/main/frontend/components/helpers.js +++ b/strcalc/src/main/frontend/components/helpers.js @@ -21,7 +21,19 @@ * @param {module} Handlebars The Handlebars runtime module */ export default function(Handlebars) { - Handlebars.registerHelper('link', function(text, options) { + /** + * @typedef {object} LinkHelperOptions + * @property {Object.} hash - hash arguments from the link tag + * @see https://handlebarsjs.com/guide/expressions.html#helpers + */ + + /** + * @param {string} text - the anchor text for the generated link + * @param {LinkHelperOptions} options - options including the href URL + * @returns {import("handlebars").SafeString} - properly escaped element + * text + */ + const linkHelper = function(text, options) { const attrs = Object.keys(options.hash).map(key => { return `${Handlebars.escapeExpression(key)}=` + `"${Handlebars.escapeExpression(options.hash[key])}"` @@ -29,5 +41,6 @@ export default function(Handlebars) { return new Handlebars.SafeString( `${Handlebars.escapeExpression(text)}` ) - }) + } + Handlebars.registerHelper('link', linkHelper) } diff --git a/strcalc/src/main/frontend/components/request.test.js b/strcalc/src/main/frontend/components/request.test.js index a5532fd..637b043 100644 --- a/strcalc/src/main/frontend/components/request.test.js +++ b/strcalc/src/main/frontend/components/request.test.js @@ -4,9 +4,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { post, postFormData, postOptions } from './request' +import { post, postFormData, postOptions } from './request.js' import { afterEach, describe, expect, test, vi } from 'vitest' -import setupFetchStub from '../test/fetch-stub' +import setupFetchStub from '../test/fetch-stub.js' // @vitest-environment jsdom describe('Request', () => { @@ -17,7 +17,7 @@ describe('Request', () => { describe('post', () => { test('succeeds', async () => { const res = { foo: 'bar' } - const fetchStub = setupFetchStub(JSON.stringify(res)) + const fetchStub = setupFetchStub(res) await expect(post('/fetch', req)).resolves.toEqual(res) expect(fetchStub).toHaveBeenCalledWith('/fetch', postOptions(req)) @@ -25,7 +25,7 @@ describe('Request', () => { test('rejects with an error if the response contains "error"', async () => { const res = { error: 'OK status, but still an error' } - setupFetchStub(JSON.stringify(res)) + setupFetchStub(res) await expect(post('/fetch', req)).rejects.toThrow(res.error) }) @@ -49,7 +49,7 @@ describe('Request', () => { test('succeeds', async () => { const fd = new FormData() const res = { foo: 'bar' } - const fetchStub = setupFetchStub(JSON.stringify(res)) + const fetchStub = setupFetchStub(res) Object.entries(req).forEach(([k,v]) => fd.append(k,v)) await expect(postFormData('/fetch', fd)).resolves.toEqual(res) diff --git a/strcalc/src/main/frontend/components/template.d.ts b/strcalc/src/main/frontend/components/template.d.ts new file mode 100644 index 0000000..c9fef53 --- /dev/null +++ b/strcalc/src/main/frontend/components/template.d.ts @@ -0,0 +1,11 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +declare module "*.hbs" { + export const RawTemplate: HandlebarsTemplateDelegate + export default function (context: any, options?: RuntimeOptions): + DocumentFragment +} diff --git a/strcalc/src/main/frontend/globals.d.ts b/strcalc/src/main/frontend/globals.d.ts new file mode 100644 index 0000000..6bb4f70 --- /dev/null +++ b/strcalc/src/main/frontend/globals.d.ts @@ -0,0 +1,5 @@ +import 'globalThis' + +declare global { + var STRCALC_BACKEND: string +} diff --git a/strcalc/src/main/frontend/jsconfig.json b/strcalc/src/main/frontend/jsconfig.json new file mode 100644 index 0000000..4754f2f --- /dev/null +++ b/strcalc/src/main/frontend/jsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "checkJs": true, + "module": "nodenext", + "strict": true + }, + "exclude": [ + "node_modules/**", + "coverage/**", + "jsdoc/**" + ] +} diff --git a/strcalc/src/main/frontend/jsdoc.json b/strcalc/src/main/frontend/jsdoc.json index 5fa0a57..cc5248d 100644 --- a/strcalc/src/main/frontend/jsdoc.json +++ b/strcalc/src/main/frontend/jsdoc.json @@ -1,10 +1,16 @@ { - "plugins": [ "plugins/markdown" ], + "plugins": [ + "plugins/markdown", + "jsdoc-plugin-typescript" + ], "recurseDepth": 10, "source": { "includePattern": ".+\\.js$", "exclude": ["node_modules"] }, + "typescript":{ + "moduleRoot": "." + }, "opts": { "destination": "../../../build/jsdoc", "recurse": true, diff --git a/strcalc/src/main/frontend/main.js b/strcalc/src/main/frontend/main.js index 39d9e5d..33c63a3 100644 --- a/strcalc/src/main/frontend/main.js +++ b/strcalc/src/main/frontend/main.js @@ -30,7 +30,9 @@ document.addEventListener( 'DOMContentLoaded', () => { const appElem = document.querySelector('#app') - new App().init({ appElem, calculators }) + + if (appElem === null) console.error('missing #app element') + else new App().init({ appElem, calculators }) }, { once: true } ) diff --git a/strcalc/src/main/frontend/main.test.js b/strcalc/src/main/frontend/main.test.js index f831d1e..9327a7b 100644 --- a/strcalc/src/main/frontend/main.test.js +++ b/strcalc/src/main/frontend/main.test.js @@ -9,15 +9,18 @@ import StringCalculatorPage from './test/page.js' import TestPageOpener from 'test-page-opener' describe('String Calculator UI on initial page load', () => { + /** @type {TestPageOpener} */ let opener - beforeAll(async () => opener = await TestPageOpener.create('/strcalc/')) + beforeAll(async () => {opener = await TestPageOpener.create('/strcalc/')}) afterEach(() => opener.closeAll()) test('contains the "Hello, World!" placeholder', async () => { const { document } = await opener.open('index.html') + /** @type {(HTMLDivElement | null)} */ const appElem = document.querySelector('#app') + if (appElem === null) return expect(appElem).not.toBeNull() const e = new StringCalculatorPage(appElem, document).title() expect(e.textContent).toContain('Hello, World!') expect(e.href).toContain('%22Hello,_World!%22') diff --git a/strcalc/src/main/frontend/package.json b/strcalc/src/main/frontend/package.json index 1566192..07dda34 100644 --- a/strcalc/src/main/frontend/package.json +++ b/strcalc/src/main/frontend/package.json @@ -27,27 +27,32 @@ "test": "vitest", "test-run": "vitest run", "test-ui": "vitest --ui --coverage", - "test-ci": "eslint --color --max-warnings 0 . && vitest run --config ci/vitest.config.js && vitest run --config ci/vitest.config.browser.js", + "test-ci": "pnpm lint && pnpm jsdoc && pnpm typecheck && vitest run --config ci/vitest.config.js && vitest run --config ci/vitest.config.browser.js", "coverage": "vitest run --coverage", - "jsdoc": "jsdoc-cli-wrapper -c ./jsdoc.json ." + "jsdoc": "jsdoc-cli-wrapper -c ./jsdoc.json .", + "typecheck": "npx -p typescript tsc -p jsconfig.json --noEmit --pretty" }, "devDependencies": { "@rollup/pluginutils": "^5.1.0", "@stylistic/eslint-plugin-js": "^1.5.3", - "@vitest/browser": "^1.1.3", - "@vitest/coverage-istanbul": "^1.1.3", - "@vitest/coverage-v8": "^1.1.3", - "@vitest/ui": "^1.1.3", + "@types/chai": "^4.3.11", + "@vitest/browser": "^1.2.0", + "@vitest/coverage-istanbul": "^1.2.0", + "@vitest/coverage-v8": "^1.2.0", + "@vitest/ui": "^1.2.0", "eslint": "^8.56.0", "eslint-plugin-jsdoc": "^46.10.1", "eslint-plugin-vitest": "^0.3.20", "handlebars": "^4.7.8", - "jsdoc-cli-wrapper": "^1.0.4", - "jsdom": "^23.1.0", + "jsdoc": "^4.0.2", + "jsdoc-cli-wrapper": "^1.0.5", + "jsdoc-plugin-typescript": "^2.2.1", + "jsdom": "^23.2.0", "rollup-plugin-handlebars-precompiler": "^1.0.0", - "test-page-opener": "^1.0.3", + "test-page-opener": "^1.0.5", + "typescript": "^5.3.3", "vite": "^5.0.11", - "vitest": "^1.1.3", - "webdriverio": "^8.27.0" + "vitest": "^1.2.0", + "webdriverio": "^8.27.2" } } diff --git a/strcalc/src/main/frontend/pnpm-lock.yaml b/strcalc/src/main/frontend/pnpm-lock.yaml index 2bebf9e..dffff36 100644 --- a/strcalc/src/main/frontend/pnpm-lock.yaml +++ b/strcalc/src/main/frontend/pnpm-lock.yaml @@ -11,18 +11,21 @@ devDependencies: '@stylistic/eslint-plugin-js': specifier: ^1.5.3 version: 1.5.3(eslint@8.56.0) + '@types/chai': + specifier: ^4.3.11 + version: 4.3.11 '@vitest/browser': - specifier: ^1.1.3 - version: 1.1.3(vitest@1.1.3)(webdriverio@8.27.0) + specifier: ^1.2.0 + version: 1.2.0(vitest@1.2.0)(webdriverio@8.27.2) '@vitest/coverage-istanbul': - specifier: ^1.1.3 - version: 1.1.3(vitest@1.1.3) + specifier: ^1.2.0 + version: 1.2.0(vitest@1.2.0) '@vitest/coverage-v8': - specifier: ^1.1.3 - version: 1.1.3(vitest@1.1.3) + specifier: ^1.2.0 + version: 1.2.0(vitest@1.2.0) '@vitest/ui': - specifier: ^1.1.3 - version: 1.1.3(vitest@1.1.3) + specifier: ^1.2.0 + version: 1.2.0(vitest@1.2.0) eslint: specifier: ^8.56.0 version: 8.56.0 @@ -31,31 +34,40 @@ devDependencies: version: 46.10.1(eslint@8.56.0) eslint-plugin-vitest: specifier: ^0.3.20 - version: 0.3.20(eslint@8.56.0)(typescript@5.3.3)(vitest@1.1.3) + version: 0.3.20(eslint@8.56.0)(typescript@5.3.3)(vitest@1.2.0) handlebars: specifier: ^4.7.8 version: 4.7.8 + jsdoc: + specifier: ^4.0.2 + version: 4.0.2 jsdoc-cli-wrapper: - specifier: ^1.0.4 - version: 1.0.4 + specifier: ^1.0.5 + version: 1.0.5 + jsdoc-plugin-typescript: + specifier: ^2.2.1 + version: 2.2.1 jsdom: - specifier: ^23.1.0 - version: 23.1.0 + specifier: ^23.2.0 + version: 23.2.0 rollup-plugin-handlebars-precompiler: specifier: ^1.0.0 version: 1.0.0 test-page-opener: - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^1.0.5 + version: 1.0.5 + typescript: + specifier: ^5.3.3 + version: 5.3.3 vite: specifier: ^5.0.11 version: 5.0.11 vitest: - specifier: ^1.1.3 - version: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) + specifier: ^1.2.0 + version: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) webdriverio: - specifier: ^8.27.0 - version: 8.27.0(typescript@5.3.3) + specifier: ^8.27.2 + version: 8.27.2(typescript@5.3.3) packages: @@ -69,7 +81,15 @@ packages: engines: {node: '>=6.0.0'} dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.21 + dev: true + + /@asamuzakjp/dom-selector@2.0.2: + resolution: {integrity: sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==} + dependencies: + bidi-js: 1.0.3 + css-tree: 2.3.1 + is-potential-custom-element-name: 1.0.1 dev: true /@babel/code-frame@7.23.5: @@ -94,7 +114,7 @@ packages: '@babel/generator': 7.23.6 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) - '@babel/helpers': 7.23.7 + '@babel/helpers': 7.23.8 '@babel/parser': 7.23.6 '@babel/template': 7.22.15 '@babel/traverse': 7.23.7 @@ -114,7 +134,7 @@ packages: dependencies: '@babel/types': 7.23.6 '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.21 jsesc: 2.5.2 dev: true @@ -199,8 +219,8 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helpers@7.23.7: - resolution: {integrity: sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==} + /@babel/helpers@7.23.8: + resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.22.15 @@ -520,11 +540,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@humanwhocodes/config-array@0.11.13: - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 2.0.1 + '@humanwhocodes/object-schema': 2.0.2 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: @@ -536,8 +556,8 @@ packages: engines: {node: '>=12.22'} dev: true - /@humanwhocodes/object-schema@2.0.1: - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} dev: true /@isaacs/cliui@8.0.2: @@ -570,7 +590,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.21 dev: true /@jridgewell/resolve-uri@3.1.1: @@ -587,13 +607,20 @@ packages: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: true - /@jridgewell/trace-mapping@0.3.20: - resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + /@jridgewell/trace-mapping@0.3.21: + resolution: {integrity: sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@jsdoc/salty@0.2.7: + resolution: {integrity: sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==} + engines: {node: '>=v12.0.0'} + dependencies: + lodash: 4.17.21 + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -678,104 +705,104 @@ packages: picomatch: 2.3.1 dev: true - /@rollup/rollup-android-arm-eabi@4.9.3: - resolution: {integrity: sha512-nvh9bB41vXEoKKvlWCGptpGt8EhrEwPQFDCY0VAto+R+qpSbaErPS3OjMZuXR8i/2UVw952Dtlnl2JFxH31Qvg==} + /@rollup/rollup-android-arm-eabi@4.9.5: + resolution: {integrity: sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==} cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-android-arm64@4.9.3: - resolution: {integrity: sha512-kffYCJ2RhDL1DlshLzYPyJtVeusHlA8Q1j6k6s4AEVKLq/3HfGa2ADDycLsmPo3OW83r4XtOPqRMbcFzFsEIzQ==} + /@rollup/rollup-android-arm64@4.9.5: + resolution: {integrity: sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-arm64@4.9.3: - resolution: {integrity: sha512-Fo7DR6Q9/+ztTyMBZ79+WJtb8RWZonyCgkBCjV51rW5K/dizBzImTW6HLC0pzmHaAevwM0jW1GtB5LCFE81mSw==} + /@rollup/rollup-darwin-arm64@4.9.5: + resolution: {integrity: sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-x64@4.9.3: - resolution: {integrity: sha512-5HcxDF9fqHucIlTiw/gmMb3Qv23L8bLCg904I74Q2lpl4j/20z9ogaD3tWkeguRuz+/17cuS321PT3PAuyjQdg==} + /@rollup/rollup-darwin-x64@4.9.5: + resolution: {integrity: sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.9.3: - resolution: {integrity: sha512-cO6hKV+99D1V7uNJQn1chWaF9EGp7qV2N8sGH99q9Y62bsbN6Il55EwJppEWT+JiqDRg396vWCgwdHwje8itBQ==} + /@rollup/rollup-linux-arm-gnueabihf@4.9.5: + resolution: {integrity: sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.9.3: - resolution: {integrity: sha512-xANyq6lVg6KMO8UUs0LjA4q7di3tPpDbzLPgVEU2/F1ngIZ54eli8Zdt3uUUTMXVbgTCafIO+JPeGMhu097i3w==} + /@rollup/rollup-linux-arm64-gnu@4.9.5: + resolution: {integrity: sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-musl@4.9.3: - resolution: {integrity: sha512-TZJUfRTugVFATQToCMD8DNV6jv/KpSwhE1lLq5kXiQbBX3Pqw6dRKtzNkh5wcp0n09reBBq/7CGDERRw9KmE+g==} + /@rollup/rollup-linux-arm64-musl@4.9.5: + resolution: {integrity: sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.9.3: - resolution: {integrity: sha512-4/QVaRyaB5tkEAGfjVvWrmWdPF6F2NoaoO5uEP7N0AyeBw7l8SeCWWKAGrbx/00PUdHrJVURJiYikazslSKttQ==} + /@rollup/rollup-linux-riscv64-gnu@4.9.5: + resolution: {integrity: sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==} cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-gnu@4.9.3: - resolution: {integrity: sha512-koLC6D3pj1YLZSkTy/jsk3HOadp7q2h6VQl/lPX854twOmmLNekHB6yuS+MkWcKdGGdW1JPuPBv/ZYhr5Yhtdg==} + /@rollup/rollup-linux-x64-gnu@4.9.5: + resolution: {integrity: sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-musl@4.9.3: - resolution: {integrity: sha512-0OAkQ4HBp+JO2ip2Lgt/ShlrveOMzyhwt2D0KvqH28jFPqfZco28KSq76zymZwmU+F6GRojdxtQMJiNSXKNzeA==} + /@rollup/rollup-linux-x64-musl@4.9.5: + resolution: {integrity: sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.9.3: - resolution: {integrity: sha512-z5uvoMvdRWggigOnsb9OOCLERHV0ykRZoRB5O+URPZC9zM3pkoMg5fN4NKu2oHqgkzZtfx9u4njqqlYEzM1v9A==} + /@rollup/rollup-win32-arm64-msvc@4.9.5: + resolution: {integrity: sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.9.3: - resolution: {integrity: sha512-wxomCHjBVKws+O4N1WLnniKCXu7vkLtdq9Fl9CN/EbwEldojvUrkoHE/fBLZzC7IT/x12Ut6d6cRs4dFvqJkMg==} + /@rollup/rollup-win32-ia32-msvc@4.9.5: + resolution: {integrity: sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-x64-msvc@4.9.3: - resolution: {integrity: sha512-1Qf/qk/iEtx0aOi+AQQt5PBoW0mFngsm7bPuxHClC/hWh2hHBktR6ktSfUg5b5rC9v8hTwNmHE7lBWXkgqluUQ==} + /@rollup/rollup-win32-x64-msvc@4.9.5: + resolution: {integrity: sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==} cpu: [x64] os: [win32] requiresBuild: true @@ -815,6 +842,10 @@ packages: resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} dev: true + /@types/chai@4.3.11: + resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true @@ -831,8 +862,23 @@ packages: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true - /@types/node@20.10.6: - resolution: {integrity: sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==} + /@types/linkify-it@3.0.5: + resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==} + dev: true + + /@types/markdown-it@12.2.3: + resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + dependencies: + '@types/linkify-it': 3.0.5 + '@types/mdurl': 1.0.5 + dev: true + + /@types/mdurl@1.0.5: + resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==} + dev: true + + /@types/node@20.11.0: + resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==} dependencies: undici-types: 5.26.5 dev: true @@ -848,32 +894,32 @@ packages: /@types/ws@8.5.10: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.0 dev: true /@types/yauzl@2.10.3: resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} requiresBuild: true dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.0 dev: true optional: true - /@typescript-eslint/scope-manager@6.17.0: - resolution: {integrity: sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==} + /@typescript-eslint/scope-manager@6.18.1: + resolution: {integrity: sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/visitor-keys': 6.18.1 dev: true - /@typescript-eslint/types@6.17.0: - resolution: {integrity: sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==} + /@typescript-eslint/types@6.18.1: + resolution: {integrity: sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.17.0(typescript@5.3.3): - resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==} + /@typescript-eslint/typescript-estree@6.18.1(typescript@5.3.3): + resolution: {integrity: sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -881,8 +927,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/visitor-keys': 6.17.0 + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/visitor-keys': 6.18.1 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -894,8 +940,8 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@6.17.0(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==} + /@typescript-eslint/utils@6.18.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -903,9 +949,9 @@ packages: '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.17.0 - '@typescript-eslint/types': 6.17.0 - '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.18.1 + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) eslint: 8.56.0 semver: 7.5.4 transitivePeerDependencies: @@ -913,11 +959,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@6.17.0: - resolution: {integrity: sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==} + /@typescript-eslint/visitor-keys@6.18.1: + resolution: {integrity: sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.17.0 + '@typescript-eslint/types': 6.18.1 eslint-visitor-keys: 3.4.3 dev: true @@ -925,8 +971,8 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /@vitest/browser@1.1.3(vitest@1.1.3)(webdriverio@8.27.0): - resolution: {integrity: sha512-ksI0V8YqonFYfjVYMPTvDR84i7ix7QPL2Sc8G2mHirVGAf4jJS3uC/CsifRLe5/E2r8QUhHbAdZQpvMCqBJV5w==} + /@vitest/browser@1.2.0(vitest@1.2.0)(webdriverio@8.27.2): + resolution: {integrity: sha512-egA2juStgiDDiHSjw5dloOj9pG+Au1azleKBxEs8E8dafkfQbr5FxswhsAryXdT29kb8EU479wET0KQz3NUSsQ==} peerDependencies: playwright: '*' safaridriver: '*' @@ -940,15 +986,15 @@ packages: webdriverio: optional: true dependencies: - '@vitest/utils': 1.1.3 + '@vitest/utils': 1.2.0 magic-string: 0.30.5 sirv: 2.0.4 - vitest: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) - webdriverio: 8.27.0(typescript@5.3.3) + vitest: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) + webdriverio: 8.27.2(typescript@5.3.3) dev: true - /@vitest/coverage-istanbul@1.1.3(vitest@1.1.3): - resolution: {integrity: sha512-pqx/RaLjJ7oxsbi0Vc/CjyXBXd86yQ0lKq1PPnk9BMNLqMTEWwfcTelcNrl41yK+IVRhHlFtwcjDva3VslbMMQ==} + /@vitest/coverage-istanbul@1.2.0(vitest@1.2.0): + resolution: {integrity: sha512-hNN/pUR5la6P/L78+YcRl05Lpf6APXlH9ujkmCxxjVWtVG6WuKuqUMhHgYQBYfiOORBwDZ1MBgSUGCMPh4kpmQ==} peerDependencies: vitest: ^1.0.0 dependencies: @@ -961,13 +1007,13 @@ packages: magicast: 0.3.2 picocolors: 1.0.0 test-exclude: 6.0.0 - vitest: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) + vitest: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) transitivePeerDependencies: - supports-color dev: true - /@vitest/coverage-v8@1.1.3(vitest@1.1.3): - resolution: {integrity: sha512-Uput7t3eIcbSTOTQBzGtS+0kah96bX+szW9qQrLeGe3UmgL2Akn8POnyC2lH7XsnREZOds9aCUTxgXf+4HX5RA==} + /@vitest/coverage-v8@1.2.0(vitest@1.2.0): + resolution: {integrity: sha512-YvX8ULTUm1+zkvkl14IqXYGxE1h13OXKPoDsxazARKlp4YLrP28hHEBdplaU7ZTN/Yn6zy6Z3JadWNRJwcmyrQ==} peerDependencies: vitest: ^1.0.0 dependencies: @@ -984,58 +1030,58 @@ packages: std-env: 3.7.0 test-exclude: 6.0.0 v8-to-istanbul: 9.2.0 - vitest: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) + vitest: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) transitivePeerDependencies: - supports-color dev: true - /@vitest/expect@1.1.3: - resolution: {integrity: sha512-MnJqsKc1Ko04lksF9XoRJza0bGGwTtqfbyrsYv5on4rcEkdo+QgUdITenBQBUltKzdxW7K3rWh+nXRULwsdaVg==} + /@vitest/expect@1.2.0: + resolution: {integrity: sha512-H+2bHzhyvgp32o7Pgj2h9RTHN0pgYaoi26Oo3mE+dCi1PAqV31kIIVfTbqMO3Bvshd5mIrJLc73EwSRrbol9Lw==} dependencies: - '@vitest/spy': 1.1.3 - '@vitest/utils': 1.1.3 - chai: 4.4.0 + '@vitest/spy': 1.2.0 + '@vitest/utils': 1.2.0 + chai: 4.4.1 dev: true - /@vitest/runner@1.1.3: - resolution: {integrity: sha512-Va2XbWMnhSdDEh/OFxyUltgQuuDRxnarK1hW5QNN4URpQrqq6jtt8cfww/pQQ4i0LjoYxh/3bYWvDFlR9tU73g==} + /@vitest/runner@1.2.0: + resolution: {integrity: sha512-vaJkDoQaNUTroT70OhM0NPznP7H3WyRwt4LvGwCVYs/llLaqhoSLnlIhUClZpbF5RgAee29KRcNz0FEhYcgxqA==} dependencies: - '@vitest/utils': 1.1.3 + '@vitest/utils': 1.2.0 p-limit: 5.0.0 - pathe: 1.1.1 + pathe: 1.1.2 dev: true - /@vitest/snapshot@1.1.3: - resolution: {integrity: sha512-U0r8pRXsLAdxSVAyGNcqOU2H3Z4Y2dAAGGelL50O0QRMdi1WWeYHdrH/QWpN1e8juWfVKsb8B+pyJwTC+4Gy9w==} + /@vitest/snapshot@1.2.0: + resolution: {integrity: sha512-P33EE7TrVgB3HDLllrjK/GG6WSnmUtWohbwcQqmm7TAk9AVHpdgf7M3F3qRHKm6vhr7x3eGIln7VH052Smo6Kw==} dependencies: magic-string: 0.30.5 - pathe: 1.1.1 + pathe: 1.1.2 pretty-format: 29.7.0 dev: true - /@vitest/spy@1.1.3: - resolution: {integrity: sha512-Ec0qWyGS5LhATFQtldvChPTAHv08yHIOZfiNcjwRQbFPHpkih0md9KAbs7TfeIfL7OFKoe7B/6ukBTqByubXkQ==} + /@vitest/spy@1.2.0: + resolution: {integrity: sha512-MNxSAfxUaCeowqyyGwC293yZgk7cECZU9wGb8N1pYQ0yOn/SIr8t0l9XnGRdQZvNV/ZHBYu6GO/W3tj5K3VN1Q==} dependencies: tinyspy: 2.2.0 dev: true - /@vitest/ui@1.1.3(vitest@1.1.3): - resolution: {integrity: sha512-JKGgftXZgTtK7kfQNicE9Q2FuiUlYvCGyUENkA2/S1VBThtfQyGUwaJmiDFVAKBOrW305cNgjP67vsxMm9/SDQ==} + /@vitest/ui@1.2.0(vitest@1.2.0): + resolution: {integrity: sha512-AFU8FBiSioYacEd0b8+2R/4GJJhxseD6bNIiEVntb505u1B/mcNMTVRepZql7r3RQJZQ7uijY9QyLdhlbh4XvA==} peerDependencies: vitest: ^1.0.0 dependencies: - '@vitest/utils': 1.1.3 + '@vitest/utils': 1.2.0 fast-glob: 3.3.2 fflate: 0.8.1 flatted: 3.2.9 - pathe: 1.1.1 + pathe: 1.1.2 picocolors: 1.0.0 sirv: 2.0.4 - vitest: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) + vitest: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) dev: true - /@vitest/utils@1.1.3: - resolution: {integrity: sha512-Dyt3UMcdElTll2H75vhxfpZu03uFpXRCHxWnzcrFjZxT1kTbq8ALUYIeBgGolo1gldVdI0YSlQRacsqxTwNqwg==} + /@vitest/utils@1.2.0: + resolution: {integrity: sha512-FyD5bpugsXlwVpTcGLDf3wSPYy8g541fQt14qtzo8mJ4LdEpDKZ9mQy2+qdJm2TZRpjY5JLXihXCgIxiRJgi5g==} dependencies: diff-sequences: 29.6.3 estree-walker: 3.0.3 @@ -1043,13 +1089,13 @@ packages: pretty-format: 29.7.0 dev: true - /@wdio/config@8.27.0: - resolution: {integrity: sha512-zYM5daeiBVVAbQj0ASymAt0RUsocLVIwKiUHNa8gg/1GsZnztGjetXExSp1gXlxtMVM5xWUSKjh6ceFK79gWDQ==} + /@wdio/config@8.27.2: + resolution: {integrity: sha512-qR1r7K7/jsQhi9g5NiW40lgbvbzCcwwk8nz07hzTj6m8fQ8TXkQPob2fnrlDaNrXjzbZC4od0uv0a5fimK9YOQ==} engines: {node: ^16.13 || >=18} dependencies: '@wdio/logger': 8.24.12 - '@wdio/types': 8.27.0 - '@wdio/utils': 8.27.0 + '@wdio/types': 8.27.2 + '@wdio/utils': 8.27.2 decamelize: 6.0.0 deepmerge-ts: 5.1.0 glob: 10.3.10 @@ -1076,30 +1122,30 @@ packages: resolution: {integrity: sha512-321F3sWafnlw93uRTSjEBVuvWCxTkWNDs7ektQS15drrroL3TMeFOynu4rDrIz0jXD9Vas0HCD2Tq/P0uxFLdw==} engines: {node: ^16.13 || >=18} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.0 dev: true - /@wdio/types@8.27.0: - resolution: {integrity: sha512-LbP9FKh8r0uW9/dKhTIUCC1Su8PsP9TmzGKXkWt6/IMacgJiB/zW3u1CgyaLw9lG0UiQORHGoeJX9zB2HZAh4w==} + /@wdio/types@8.27.2: + resolution: {integrity: sha512-z/TtSQysEtAUNh+DooOs22G7xotTsJC2RcIZKaVtHY4Gl6lF+tn8kLRXD79jem2ta1byB1TpW62K366k1vzcLw==} engines: {node: ^16.13 || >=18} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.0 dev: true - /@wdio/utils@8.27.0: - resolution: {integrity: sha512-4BY+JBQssVn003P5lA289uDMie3LtGinHze5btkcW9timB6VaU+EeZS4eKTPC0pziizLhteVvXYxv3YTpeeRfA==} + /@wdio/utils@8.27.2: + resolution: {integrity: sha512-jWxUhGjlZ4L3uOsP96oLKWjkITpoH/KPTtKzU7xdoVGhd1LXK4d/Fr8cTFTNkDBXM7yuM7C+EMmQ8HJHR55KTA==} engines: {node: ^16.13 || >=18} dependencies: '@puppeteer/browsers': 1.9.1 '@wdio/logger': 8.24.12 - '@wdio/types': 8.27.0 + '@wdio/types': 8.27.2 decamelize: 6.0.0 deepmerge-ts: 5.1.0 edgedriver: 5.3.9 geckodriver: 4.3.0 get-port: 7.0.0 import-meta-resolve: 4.0.0 - locate-app: 2.2.4 + locate-app: 2.2.7 safaridriver: 0.1.2 split2: 4.2.0 wait-port: 1.1.0 @@ -1115,8 +1161,8 @@ packages: acorn: 8.11.3 dev: true - /acorn-walk@8.3.1: - resolution: {integrity: sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==} + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} dev: true @@ -1218,11 +1264,31 @@ packages: dequal: 2.0.3 dev: true + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} dev: true + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true @@ -1242,6 +1308,11 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + /b4a@1.6.4: resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} dev: true @@ -1259,6 +1330,12 @@ packages: engines: {node: '>=10.0.0'} dev: true + /bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + dependencies: + require-from-string: 2.0.2 + dev: true + /big-integer@1.6.52: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} @@ -1275,6 +1352,10 @@ packages: resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} dev: true + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: true + /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -1300,8 +1381,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001574 - electron-to-chromium: 1.4.623 + caniuse-lite: 1.0.30001576 + electron-to-chromium: 1.4.629 node-releases: 2.0.14 update-browserslist-db: 1.0.13(browserslist@4.22.2) dev: true @@ -1355,17 +1436,32 @@ packages: responselike: 3.0.0 dev: true + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + dev: true + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} dev: true - /caniuse-lite@1.0.30001574: - resolution: {integrity: sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==} + /caniuse-lite@1.0.30001576: + resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==} + dev: true + + /catharsis@0.9.0: + resolution: {integrity: sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==} + engines: {node: '>= 10'} + dependencies: + lodash: 4.17.21 dev: true - /chai@4.4.0: - resolution: {integrity: sha512-x9cHNq1uvkCdU+5xTkNh5WtgD4e4yDFCsp9jVc7N7qVeKeftv3gO/ZrviX5d+3ZfxdYnZXZYujjRInu1RogU6A==} + /chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} engines: {node: '>=4'} dependencies: assertion-error: 1.1.0 @@ -1524,6 +1620,14 @@ packages: resolution: {integrity: sha512-Md+Juc7M3uOdbAFwOYlTrccIZ7oCFuzrhKYQjdeUEW/sE1hv17Jp/Bws+ReOPpGVBTYCBoYo+G17V5Qo8QQ75A==} dev: true + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.0.2 + dev: true + /css-value@0.0.1: resolution: {integrity: sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==} dev: true @@ -1602,6 +1706,24 @@ packages: engines: {node: '>=10'} dev: true + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + /degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} @@ -1625,8 +1747,8 @@ packages: resolution: {integrity: sha512-hyWmRrexdhbZ1tcJUGpO95ivbRhWXz++F4Ko+n21AY5PNln2ovoJw+8ZMNDTtip+CNFQfrtLVh/w4009dXO/eQ==} dev: true - /devtools-protocol@0.0.1237913: - resolution: {integrity: sha512-Pxtmz2ZIqBkpU82HaIdsvCQBG94yTC4xajrEsWx9p38QKEfBCJktSazsHkrjf9j3dVVNPhg5LR21F6KWeXpjiQ==} + /devtools-protocol@0.0.1239539: + resolution: {integrity: sha512-uS7hZVqZxGyZwR8lX/8wWyNLGEYs1wWWxN7qeRC+wBZ4VM5JXYwCJg8hofEna5yX0W2cavpjHOE4ukHXLHlEaA==} dev: true /diff-sequences@29.6.3: @@ -1679,8 +1801,8 @@ packages: which: 4.0.0 dev: true - /electron-to-chromium@1.4.623: - resolution: {integrity: sha512-lKoz10iCYlP1WtRYdh5MvocQPWVRoI7ysp6qf18bmeBgR8abE6+I2CsfyNKztRDZvhdWc+krKT6wS7Neg8sw3A==} + /electron-to-chromium@1.4.629: + resolution: {integrity: sha512-5UUkr3k3CZ/k+9Sw7vaaIMyOzMC0XbPyprKI3n0tbKDqkzTDOjK4izm7DxlkueRMim6ZZQ1ja9F7hoFVplHihA==} dev: true /emoji-regex@8.0.0: @@ -1697,11 +1819,78 @@ packages: once: 1.4.0 dev: true + /entities@2.1.0: + resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} + dev: true + /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} dev: true + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.2 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + /esbuild@0.19.11: resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} engines: {node: '>=12'} @@ -1743,6 +1932,11 @@ packages: engines: {node: '>=0.8.0'} dev: true + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1780,7 +1974,7 @@ packages: - supports-color dev: true - /eslint-plugin-vitest@0.3.20(eslint@8.56.0)(typescript@5.3.3)(vitest@1.1.3): + /eslint-plugin-vitest@0.3.20(eslint@8.56.0)(typescript@5.3.3)(vitest@1.2.0): resolution: {integrity: sha512-O05k4j9TGMOkkghj9dRgpeLDyOSiVIxQWgNDPfhYPm5ioJsehcYV/zkRLekQs+c8+RBCVXucSED3fYOyy2EoWA==} engines: {node: ^18.0.0 || >= 20.0.0} peerDependencies: @@ -1793,9 +1987,9 @@ packages: vitest: optional: true dependencies: - '@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) eslint: 8.56.0 - vitest: 1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0) + vitest: 1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0) transitivePeerDependencies: - supports-color - typescript @@ -1823,7 +2017,7 @@ packages: '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/config-array': 0.11.14 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -2029,6 +2223,12 @@ packages: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + /foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} @@ -2089,6 +2289,24 @@ packages: rimraf: 2.7.1 dev: true + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + /geckodriver@4.3.0: resolution: {integrity: sha512-QfpvxFsMORwKpvnLslkHCr3NTCczHAvkte6+pQGsiUZXKBe6mO4TTb727b+9KMVSK6XZqhR6ZwImKdP+F5vS6A==} engines: {node: ^16.13 || >=18 || >=20} @@ -2121,6 +2339,15 @@ packages: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} dev: true + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: true + /get-port@7.0.0: resolution: {integrity: sha512-mDHFgApoQd+azgMdwylJrv2DX47ywGq1i5VFJE7fZ0dttNq3iQMfsU4IvEgBHojA3KqEudyu7Vq+oN8kNaNkWw==} engines: {node: '>=16'} @@ -2143,6 +2370,14 @@ packages: engines: {node: '>=16'} dev: true + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + /get-uri@6.0.2: resolution: {integrity: sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==} engines: {node: '>= 14'} @@ -2215,6 +2450,13 @@ packages: type-fest: 0.20.2 dev: true + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -2227,6 +2469,12 @@ packages: slash: 3.0.0 dev: true + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + /got@12.6.1: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} engines: {node: '>=14.16'} @@ -2269,6 +2517,10 @@ packages: uglify-js: 3.17.4 dev: true + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -2279,6 +2531,36 @@ packages: engines: {node: '>=8'} dev: true + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + /html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -2371,6 +2653,15 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + /ip@1.1.8: resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} dev: true @@ -2379,6 +2670,28 @@ packages: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} dev: true + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + /is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -2386,6 +2699,18 @@ packages: builtin-modules: 3.3.0 dev: true + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2403,6 +2728,18 @@ packages: is-extglob: 2.1.1 dev: true + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -2422,15 +2759,60 @@ packages: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: true + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true @@ -2506,19 +2888,53 @@ packages: argparse: 2.0.1 dev: true - /jsdoc-cli-wrapper@1.0.4: - resolution: {integrity: sha512-JzdBSsLkS5Q8BIaO8b9SC3kfUc7NsHc7egpJLJGqQQsm+X4rXooG0hClwGVm1LVNuca3bpeq/Mw99BcUiD4rQw==} + /js2xmlparser@4.0.2: + resolution: {integrity: sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==} + dependencies: + xmlcreate: 2.0.4 + dev: true + + /jsdoc-cli-wrapper@1.0.5: + resolution: {integrity: sha512-cRJyq/yB3G5lo3ByyYXJLEZI8fk9AH1iRkb75Aa9oEsfXJONG167p89+AlYhTtYR+x2vQfx6Pdon6Iogu2GrLw==} engines: {node: '>= 18.0.0'} hasBin: true dev: true + /jsdoc-plugin-typescript@2.2.1: + resolution: {integrity: sha512-xxuiqJ1O5+KIoOd8G8+iIZ89ns/ZvuzerrhCQhLPmeSIVsv5Ra42D9/YOHPi2DndUJbbkEpJCB95i7EXIOmhnA==} + dependencies: + string.prototype.matchall: 4.0.10 + dev: true + /jsdoc-type-pratt-parser@4.0.0: resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} engines: {node: '>=12.0.0'} dev: true - /jsdom@23.1.0: - resolution: {integrity: sha512-wRscu8dBFxi7O65Cvi0jFRDv0Qa7XEHPix8Qg/vlXHLAMQsRWV1EDeQHBermzXf4Dt7JtFgBLbva3iTcBZDXEQ==} + /jsdoc@4.0.2: + resolution: {integrity: sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@babel/parser': 7.23.6 + '@jsdoc/salty': 0.2.7 + '@types/markdown-it': 12.2.3 + bluebird: 3.7.2 + catharsis: 0.9.0 + escape-string-regexp: 2.0.0 + js2xmlparser: 4.0.2 + klaw: 3.0.0 + markdown-it: 12.3.2 + markdown-it-anchor: 8.6.7(@types/markdown-it@12.2.3)(markdown-it@12.3.2) + marked: 4.3.0 + mkdirp: 1.0.4 + requizzle: 0.2.4 + strip-json-comments: 3.1.1 + underscore: 1.13.6 + dev: true + + /jsdom@23.2.0: + resolution: {integrity: sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==} engines: {node: '>=18'} peerDependencies: canvas: ^2.11.2 @@ -2526,6 +2942,7 @@ packages: canvas: optional: true dependencies: + '@asamuzakjp/dom-selector': 2.0.2 cssstyle: 4.0.1 data-urls: 5.0.0 decimal.js: 10.4.3 @@ -2534,7 +2951,6 @@ packages: http-proxy-agent: 7.0.0 https-proxy-agent: 7.0.2 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.7 parse5: 7.1.2 rrweb-cssom: 0.6.0 saxes: 6.0.0 @@ -2593,6 +3009,12 @@ packages: json-buffer: 3.0.1 dev: true + /klaw@3.0.0: + resolution: {integrity: sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==} + dependencies: + graceful-fs: 4.2.11 + dev: true + /ky@0.33.3: resolution: {integrity: sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==} engines: {node: '>=14.16'} @@ -2613,6 +3035,12 @@ packages: type-check: 0.4.0 dev: true + /linkify-it@3.0.3: + resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} + dependencies: + uc.micro: 1.0.6 + dev: true + /listenercount@1.0.1: resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} dev: true @@ -2621,14 +3049,14 @@ packages: resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} engines: {node: '>=14'} dependencies: - mlly: 1.4.2 + mlly: 1.5.0 pkg-types: 1.0.3 dev: true - /locate-app@2.2.4: - resolution: {integrity: sha512-fGv1FEAMsJWW3F+/WdxZ4dnXT0k4dnj2RJa79tQ0KHwpWHXan8PnaIJ161Ot6UdUwyxFWplSaiHU8/Yo02R94Q==} + /locate-app@2.2.7: + resolution: {integrity: sha512-4NR8WidaCRCozDZ0BW0U5wL91EPuuIshFun2//4Kpca4DIi5XPQHAUEbj+MQt7NihZTYs+HKfOuaoqurZ58bUg==} dependencies: - n12: 1.8.6 + n12: 1.8.10 type-fest: 2.13.0 userhome: 1.0.0 dev: true @@ -2721,6 +3149,41 @@ packages: semver: 7.5.4 dev: true + /markdown-it-anchor@8.6.7(@types/markdown-it@12.2.3)(markdown-it@12.3.2): + resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==} + peerDependencies: + '@types/markdown-it': '*' + markdown-it: '*' + dependencies: + '@types/markdown-it': 12.2.3 + markdown-it: 12.3.2 + dev: true + + /markdown-it@12.3.2: + resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 2.1.0 + linkify-it: 3.0.3 + mdurl: 1.0.1 + uc.micro: 1.0.6 + dev: true + + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} + engines: {node: '>= 12'} + hasBin: true + dev: true + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + dev: true + + /mdurl@1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + dev: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -2809,11 +3272,17 @@ packages: minimist: 1.2.8 dev: true - /mlly@1.4.2: - resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mlly@1.5.0: + resolution: {integrity: sha512-NPVQvAY1xr1QoVeG0cy8yUYC7FQcOx6evl/RjT1wL5FvzPnzOysoqB/jmx/DhssT2dYa8nxECLAaFI/+gVLhDQ==} dependencies: acorn: 8.11.3 - pathe: 1.1.1 + pathe: 1.1.2 pkg-types: 1.0.3 ufo: 1.3.2 dev: true @@ -2827,8 +3296,8 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /n12@1.8.6: - resolution: {integrity: sha512-a+9bk4vwyYkBtoo1ONHLakCME4pl+qXZteHcDH3+91Wxa365SgxcXP4X0bLHYjoIR4u+b/yE8IJeQPJqhJpodQ==} + /n12@1.8.10: + resolution: {integrity: sha512-/iREutgBDWCLwSqVOTKyAXRfToeY8Y9PmFPk3egwWVf6UYUyL9UXIaVnEkW4mx+g3dBGBywfvWilfKFEkiGK+A==} dev: true /nanoid@3.3.7: @@ -2897,8 +3366,23 @@ packages: path-key: 4.0.0 dev: true - /nwsapi@2.2.7: - resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 dev: true /once@1.4.0: @@ -3023,8 +3507,8 @@ packages: engines: {node: '>=8'} dev: true - /pathe@1.1.1: - resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} dev: true /pathval@1.1.1: @@ -3048,8 +3532,8 @@ packages: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: jsonc-parser: 3.2.0 - mlly: 1.4.2 - pathe: 1.1.1 + mlly: 1.5.0 + pathe: 1.1.2 dev: true /postcss@8.4.33: @@ -3211,15 +3695,35 @@ packages: minimatch: 5.1.6 dev: true + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} dev: true + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true + /requizzle@0.2.4: + resolution: {integrity: sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==} + dependencies: + lodash: 4.17.21 + dev: true + /resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: true @@ -3275,26 +3779,26 @@ packages: - rollup dev: true - /rollup@4.9.3: - resolution: {integrity: sha512-JnchF0ZGFiqGpAPjg3e89j656Ne4tTtCY1VZc1AxtoQcRIxjTu9jyYHBAtkDXE+X681n4un/nX9SU52AroSRzg==} + /rollup@4.9.5: + resolution: {integrity: sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.9.3 - '@rollup/rollup-android-arm64': 4.9.3 - '@rollup/rollup-darwin-arm64': 4.9.3 - '@rollup/rollup-darwin-x64': 4.9.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.9.3 - '@rollup/rollup-linux-arm64-gnu': 4.9.3 - '@rollup/rollup-linux-arm64-musl': 4.9.3 - '@rollup/rollup-linux-riscv64-gnu': 4.9.3 - '@rollup/rollup-linux-x64-gnu': 4.9.3 - '@rollup/rollup-linux-x64-musl': 4.9.3 - '@rollup/rollup-win32-arm64-msvc': 4.9.3 - '@rollup/rollup-win32-ia32-msvc': 4.9.3 - '@rollup/rollup-win32-x64-msvc': 4.9.3 + '@rollup/rollup-android-arm-eabi': 4.9.5 + '@rollup/rollup-android-arm64': 4.9.5 + '@rollup/rollup-darwin-arm64': 4.9.5 + '@rollup/rollup-darwin-x64': 4.9.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.9.5 + '@rollup/rollup-linux-arm64-gnu': 4.9.5 + '@rollup/rollup-linux-arm64-musl': 4.9.5 + '@rollup/rollup-linux-riscv64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-musl': 4.9.5 + '@rollup/rollup-win32-arm64-msvc': 4.9.5 + '@rollup/rollup-win32-ia32-msvc': 4.9.5 + '@rollup/rollup-win32-x64-msvc': 4.9.5 fsevents: 2.3.3 dev: true @@ -3312,6 +3816,16 @@ packages: resolution: {integrity: sha512-4R309+gWflJktzPXBQCobbWEHlzC4aK3a+Ov3tz2Ib2aBxiwd11phkdIBH1l0EO22x24CJMUQkpKFumRriCSRg==} dev: true + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + /safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true @@ -3320,6 +3834,15 @@ packages: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: true + /safe-regex-test@1.0.2: + resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} dev: true @@ -3351,6 +3874,25 @@ packages: type-fest: 2.19.0 dev: true + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} dev: true @@ -3367,6 +3909,14 @@ packages: engines: {node: '>=8'} dev: true + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: true + /siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} dev: true @@ -3477,6 +4027,45 @@ packages: strip-ansi: 7.1.0 dev: true + /string.prototype.matchall@4.0.10: + resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + internal-slot: 1.0.6 + regexp.prototype.flags: 1.5.1 + set-function-name: 2.0.1 + side-channel: 1.0.4 + dev: true + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + /string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} dependencies: @@ -3562,8 +4151,8 @@ packages: minimatch: 3.1.2 dev: true - /test-page-opener@1.0.3: - resolution: {integrity: sha512-vHDT/nd39MhUS5ScCAZtdDKsbHN+e7954lIBeKYk/Ei7bBE6dwROPJs9b4tPHjmWjOcL6TT+6Pivhss2Oz7Jzg==} + /test-page-opener@1.0.5: + resolution: {integrity: sha512-KglC6Rbauoy9Rr106TVYPmxA24r13a/xODd229s/1XowaJkmya/NlTtKIY6tkw8eIoAqzHBbDwhSBVwDIXuBEw==} engines: {node: '>= 18.0.0'} dependencies: istanbul-lib-coverage: 3.2.2 @@ -3673,12 +4262,54 @@ packages: engines: {node: '>=12.20'} dev: true + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + /typescript@5.3.3: resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true dev: true + /uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + dev: true + /ufo@1.3.2: resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} dev: true @@ -3691,6 +4322,15 @@ packages: dev: true optional: true + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + /unbzip2-stream@1.4.3: resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} dependencies: @@ -3698,6 +4338,10 @@ packages: through: 2.3.8 dev: true + /underscore@1.13.6: + resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + dev: true + /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true @@ -3764,19 +4408,19 @@ packages: resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} engines: {node: '>=10.12.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.20 + '@jridgewell/trace-mapping': 0.3.21 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 dev: true - /vite-node@1.1.3: - resolution: {integrity: sha512-BLSO72YAkIUuNrOx+8uznYICJfTEbvBAmWClY3hpath5+h1mbPS5OMn42lrTxXuyCazVyZoDkSRnju78GiVCqA==} + /vite-node@1.2.0: + resolution: {integrity: sha512-ETnQTHeAbbOxl7/pyBck9oAPZZZo+kYnFt1uQDD+hPReOc+wCjXw4r4jHriBRuVDB5isHmPXxrfc1yJnfBERqg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true dependencies: cac: 6.7.14 debug: 4.3.4 - pathe: 1.1.1 + pathe: 1.1.2 picocolors: 1.0.0 vite: 5.0.11 transitivePeerDependencies: @@ -3820,13 +4464,13 @@ packages: dependencies: esbuild: 0.19.11 postcss: 8.4.33 - rollup: 4.9.3 + rollup: 4.9.5 optionalDependencies: fsevents: 2.3.3 dev: true - /vitest@1.1.3(@vitest/browser@1.1.3)(@vitest/ui@1.1.3)(jsdom@23.1.0): - resolution: {integrity: sha512-2l8om1NOkiA90/Y207PsEvJLYygddsOyr81wLQ20Ra8IlLKbyQncWsGZjnbkyG2KwwuTXLQjEPOJuxGMG8qJBQ==} + /vitest@1.2.0(@vitest/browser@1.2.0)(@vitest/ui@1.2.0)(jsdom@23.2.0): + resolution: {integrity: sha512-Ixs5m7BjqvLHXcibkzKRQUvD/XLw0E3rvqaCMlrm/0LMsA0309ZqYvTlPzkhh81VlEyVZXFlwWnkhb6/UMtcaQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -3850,29 +4494,29 @@ packages: jsdom: optional: true dependencies: - '@vitest/browser': 1.1.3(vitest@1.1.3)(webdriverio@8.27.0) - '@vitest/expect': 1.1.3 - '@vitest/runner': 1.1.3 - '@vitest/snapshot': 1.1.3 - '@vitest/spy': 1.1.3 - '@vitest/ui': 1.1.3(vitest@1.1.3) - '@vitest/utils': 1.1.3 - acorn-walk: 8.3.1 + '@vitest/browser': 1.2.0(vitest@1.2.0)(webdriverio@8.27.2) + '@vitest/expect': 1.2.0 + '@vitest/runner': 1.2.0 + '@vitest/snapshot': 1.2.0 + '@vitest/spy': 1.2.0 + '@vitest/ui': 1.2.0(vitest@1.2.0) + '@vitest/utils': 1.2.0 + acorn-walk: 8.3.2 cac: 6.7.14 - chai: 4.4.0 + chai: 4.4.1 debug: 4.3.4 execa: 8.0.1 - jsdom: 23.1.0 + jsdom: 23.2.0 local-pkg: 0.5.0 magic-string: 0.30.5 - pathe: 1.1.1 + pathe: 1.1.2 picocolors: 1.0.0 std-env: 3.7.0 strip-literal: 1.3.0 tinybench: 2.5.1 tinypool: 0.8.1 vite: 5.0.11 - vite-node: 1.1.3 + vite-node: 1.2.0 why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -3908,17 +4552,17 @@ packages: engines: {node: '>= 8'} dev: true - /webdriver@8.27.0: - resolution: {integrity: sha512-n1IA+rR3u84XxU9swiKUM06BkEC0GDimfZkBML57cny+utQOUbdM/mBpqCUnkWX/RBz/p2EfHdKNyOs3/REaog==} + /webdriver@8.27.2: + resolution: {integrity: sha512-vY2Lr0ZNr83n0v8PjLCXtJwR9E7QGycJVS+ev2G72gI54/rFwLv58HMSbJNn8CtE27VkhtewMUPlDpSkj5wGPQ==} engines: {node: ^16.13 || >=18} dependencies: - '@types/node': 20.10.6 + '@types/node': 20.11.0 '@types/ws': 8.5.10 - '@wdio/config': 8.27.0 + '@wdio/config': 8.27.2 '@wdio/logger': 8.24.12 '@wdio/protocols': 8.24.12 - '@wdio/types': 8.27.0 - '@wdio/utils': 8.27.0 + '@wdio/types': 8.27.2 + '@wdio/utils': 8.27.2 deepmerge-ts: 5.1.0 got: 12.6.1 ky: 0.33.3 @@ -3929,8 +4573,8 @@ packages: - utf-8-validate dev: true - /webdriverio@8.27.0(typescript@5.3.3): - resolution: {integrity: sha512-Qh5VCiBjEmxnmXcL1QEFoDzFqTtaWKrXriuU5G0yHKCModGAt2G7IHTkAok3CpmkVJfZpEvY630aP1MvgDtFhw==} + /webdriverio@8.27.2(typescript@5.3.3): + resolution: {integrity: sha512-X6PhKE8e8XsB33Q/KSS1zYKP2Rqkq2Nef0YKOhQO+5OTlTkeqMCjnEtyRcfmdtfAwT0DEFqMnGnUKEbTajFC4Q==} engines: {node: ^16.13 || >=18} peerDependencies: devtools: ^8.14.0 @@ -3938,18 +4582,18 @@ packages: devtools: optional: true dependencies: - '@types/node': 20.10.6 - '@wdio/config': 8.27.0 + '@types/node': 20.11.0 + '@wdio/config': 8.27.2 '@wdio/logger': 8.24.12 '@wdio/protocols': 8.24.12 '@wdio/repl': 8.24.12 - '@wdio/types': 8.27.0 - '@wdio/utils': 8.27.0 + '@wdio/types': 8.27.2 + '@wdio/utils': 8.27.2 archiver: 6.0.1 aria-query: 5.3.0 css-shorthand-properties: 1.1.1 css-value: 0.0.1 - devtools-protocol: 0.0.1237913 + devtools-protocol: 0.0.1239539 grapheme-splitter: 1.0.4 import-meta-resolve: 4.0.0 is-plain-obj: 4.1.0 @@ -3961,7 +4605,7 @@ packages: resq: 1.11.0 rgb2hex: 0.2.5 serialize-error: 11.0.3 - webdriver: 8.27.0 + webdriver: 8.27.2 transitivePeerDependencies: - bufferutil - encoding @@ -4006,6 +4650,27 @@ packages: webidl-conversions: 3.0.1 dev: true + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -4092,6 +4757,10 @@ packages: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} dev: true + /xmlcreate@2.0.4: + resolution: {integrity: sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==} + dev: true + /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} diff --git a/strcalc/src/main/frontend/test/fetch-stub.js b/strcalc/src/main/frontend/test/fetch-stub.js index 9f0164f..a8f35b4 100644 --- a/strcalc/src/main/frontend/test/fetch-stub.js +++ b/strcalc/src/main/frontend/test/fetch-stub.js @@ -14,17 +14,18 @@ import {vi} from 'vitest' * after every test. * @see https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch * @see https://developer.mozilla.org/docs/Web/API/Response/Response - * @param {object} body - an object defining a body for the response - * @param {object} options - optional values to include in the response - * @param {object} options.status - HTTP status code of the response - * @param {object} options.statusText - text accompanying the status response - * @param {object} options.headers - HTTP Headers to include with the response + * @param {(object | string)} body - object or string defining a body for the + * response + * @param {ResponseInit} [options] - optional values to include in the response * @returns {Function} - a vi.fn() stub configured to return a Response once */ export default function setupFetchStub(body, options) { const fetchStub = vi.fn() + const responseBody = typeof body === 'object' ? JSON.stringify(body) : body - fetchStub.mockReturnValueOnce(Promise.resolve(new Response(body, options))) + fetchStub.mockReturnValueOnce( + Promise.resolve(new Response(responseBody, options)) + ) vi.stubGlobal('fetch', fetchStub) return fetchStub } diff --git a/strcalc/src/main/frontend/test/main-missing-app-div.test.js b/strcalc/src/main/frontend/test/main-missing-app-div.test.js new file mode 100644 index 0000000..67a1a73 --- /dev/null +++ b/strcalc/src/main/frontend/test/main-missing-app-div.test.js @@ -0,0 +1,29 @@ +/* eslint-env browser, node, jest, vitest */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +import { afterEach, beforeAll, describe, expect, test, vi } from 'vitest' +import TestPageOpener from 'test-page-opener' + +const inBrowser = globalThis.window !== undefined + +describe.skipIf(inBrowser)('String Calculator UI missing root element', () => { + /** @type {TestPageOpener} */ + let opener + + beforeAll(async () => {opener = await TestPageOpener.create('/strcalc/')}) + afterEach(() => opener.closeAll()) + + test('logs error if missing app div', async () => { + const pagePath = 'test/missing.html' + const consoleSpy = vi.spyOn(console, 'error') + .mockImplementationOnce(() => {}) + + const { close } = await opener.open(pagePath) + close() + + expect(consoleSpy).toBeCalledWith('missing #app element') + }) +}) diff --git a/strcalc/src/main/frontend/test/missing.html b/strcalc/src/main/frontend/test/missing.html new file mode 100644 index 0000000..6192f57 --- /dev/null +++ b/strcalc/src/main/frontend/test/missing.html @@ -0,0 +1,15 @@ + + + + + + + Test Page for missing app div + + + +
+ + diff --git a/strcalc/src/main/frontend/test/page.js b/strcalc/src/main/frontend/test/page.js index 1b81d91..e1abc3f 100644 --- a/strcalc/src/main/frontend/test/page.js +++ b/strcalc/src/main/frontend/test/page.js @@ -18,9 +18,19 @@ export default class StringCalculatorPage { appElem #select + /** + * @param {Element} appElem - root element of the StringCalculator application + * @param {Document} doc - Document object containing the application + */ constructor(appElem, doc = document) { this.appElem = appElem - this.#select = sel => doc.querySelector(`#${appElem.id} ${sel}`) + + /** + * @param {string} sel - argument for Document.querySelector() + * @returns {(Element | {})} - the selected element from the doc, or an + * empty object if not found + */ + this.#select = sel => (doc.querySelector(`#${appElem.id} ${sel}`) || {}) } static new() { @@ -33,28 +43,69 @@ export default class StringCalculatorPage { clear() { this.appElem.replaceChildren() } remove() { this.appElem.remove() } - title() { return this.#select('.title a') } - form() { return this.#select('form') } - input() { return this.#select('form input[name="numbers"]') } - submit() { return this.#select('form input[type="submit"]') } - result() { return this.#select('.result p') } + title() { + return /** @type {HTMLAnchorElement} */ (this.#select('.title a')) + } + + form() { + return /** @type {HTMLFormElement} */ (this.#select('form')) + } + + input() { + return /** @type {HTMLInputElement} */ ( + this.#select('form input[name="numbers"]') + ) + } + + impl() { + return /** @type {HTMLInputElement} */ ( + this.#select('form input[name="impl"]:checked') + ) + } + + submitButton() { + return /** @type {HTMLInputElement} */ ( + this.#select('form input[type="submit"]') + ) + } + + result() { + return /** @type {HTMLParagraphElement} */ (this.#select('.result p')) + } + + /** + * @callback SubmitCallback + * @returns {Promise} the StringCalculator result + * @throws {Error} if the .result element is missing + * @throws {string} if the result field hasn't changed + */ + /** + * @param {string} value - input value for the StringCalculator UI + * @returns {SubmitCallback} - the StringCalculator result + */ enterValueAndSubmit(value) { const orig = this.result().textContent this.input().value = value - - // You would _think_ that this.submit().click() would submit the form... - // Nope: - // - https://developer.mozilla.org/docs/Web/API/HTMLFormElement/requestSubmit - this.form().requestSubmit(this.submit()) + this.doSubmit() return async () => { const result = this.result().textContent + if (result === null) throw new Error('missing .result element') if (result === orig) { return Promise.reject(`Result field hasn't changed: ${orig}`) } return Promise.resolve(result) } } + + /** + * Submits the form via HTMLFormElement.requestSubmit() + * You would _think_ that this.submit().click() would submit the form... Nope. + * @see https://developer.mozilla.org/docs/Web/API/HTMLFormElement/requestSubmit + */ + doSubmit() { + this.form().requestSubmit(this.submitButton()) + } }