diff --git a/.ai/architecture.yaml b/.ai/architecture.yaml index c96e7296..21773d61 100644 --- a/.ai/architecture.yaml +++ b/.ai/architecture.yaml @@ -22,12 +22,12 @@ components: validationProvider.ts: Input validation with Quick Fixes componentBrowserProvider.ts: Component browser webview UI componentDetector.ts: Detect GitLab CI component usage in YAML - componentHtmlRenderer.ts: Render component docs as HTML + hoverContentBuilder.ts: Build the hover popup's markdown body (vscode-free, unit-tested) depends_on: - services - utils - types - - templates + - webview services: location: src/services/ purpose: Business logic and data management @@ -77,14 +77,17 @@ components: depends_on: - types - utils - templates: - location: src/templates/ - purpose: HTML template generation for webview UIs + webview: + location: src/webview/ + purpose: Helpers and assets for the webview documents rendered by the providers files: - detachedComponent.ts: Detached component view template - helpers/htmlBuilder.ts: HTML construction helper - helpers/styleBuilder.ts: CSS style helper - index.ts: Public exports + webviewHtml.ts: Nonce, Content-Security-Policy and asset-URI helpers for webview documents + inlineMarkdown.ts: HTML escaping and inline-Markdown rendering (vscode-free, unit-tested) + scriptData.ts: Safe JSON serialization for embedding data in a script block (vscode-free, unit-tested) + clientInlineMarkdown.ts: Source text for the browser-side twin of renderInlineMarkdown (vscode-free, unit-tested) + styles/: Stylesheets built to out/webview/styles/ and loaded via a CSP'd link + notes: Assets under styles/ (and client/ as scripts are extracted) are built by the webview esbuild + context and resolved at runtime through assetUri; they are not bundled into out/extension.js. depends_on: - types constants: @@ -213,8 +216,8 @@ data_flow: component: componentService action: Fetch component details (cache-first) - step: 4 - component: componentHtmlRenderer - action: Render documentation as HTML using templates/helpers + component: hoverContentBuilder + action: Build the hover markdown body (a MarkdownString, not HTML) - step: 5 component: hoverProvider action: Display hover card diff --git a/.ai/decisions.yaml b/.ai/decisions.yaml index 3867ad60..4a5b3a53 100644 --- a/.ai/decisions.yaml +++ b/.ai/decisions.yaml @@ -124,6 +124,42 @@ decisions: - .release-it/vscode-version.js - package.json (release:main, release:beta scripts) title: Release It + DEPENDABOT_TARGETS_BETA: + date: '2026-09-14' + status: accepted + context: Dependabot defaulted to the repository default branch (main), which is the stable + release line. Bumps opened there duplicated what had already landed on beta, and a merge + to main auto-cuts a stable release. + decision: 'Set target-branch: "beta" on every ecosystem in .github/dependabot.yml (npm, + github-actions, pip)' + rationale: + - A push to main runs release-it with .release-it.json and cuts a stable GitHub release, so + a routine dependency bump merged there ships a release out of band + - main trails beta by everything not yet released, so bumps against main duplicate versions + beta already carries (e.g. #291/#292/#295 re-proposed bumps merged weeks earlier) + - Retargeting such a PR to beta conflicts on package-lock.json, since beta has moved + - Updates reach main the same way every other change does, through the beta -> main release PR + implementation: + config: '.github/dependabot.yml, target-branch: "beta" on each of the three package-ecosystem + entries' + flow: dependabot -> beta -> release PR -> main + alternatives_considered: + - name: leave_targeting_main + rejected_because: Ships stable releases from dependency bumps and produces duplicate PRs + - name: retarget_each_pr_by_hand + rejected_because: Lockfile conflicts on every npm PR; recurring manual work + consequences: + positive: + - Dependency updates follow the same path as feature work + - No stable release cut by a dependency bump + - No duplicate bumps against a stale branch + negative: + - A security fix reaches main only when the next release PR merges + references: + - .github/dependabot.yml + - .release-it.json + - .release-it.beta.json + title: Dependabot Targets Beta MODULAR_SERVICE_SPLIT: date: '2026' status: accepted diff --git a/.ai/index.yaml b/.ai/index.yaml index efc14d4c..e06db923 100644 --- a/.ai/index.yaml +++ b/.ai/index.yaml @@ -25,9 +25,9 @@ keys: - providers - scripts - services - - templates - types - utils + - webview workflows: - add_configuration_option - add_new_command @@ -43,6 +43,7 @@ keys: - BATCH_API_REQUESTS - CACHE_COMPONENTS - CENTRALIZED_ERROR_HANDLING + - DEPENDABOT_TARGETS_BETA - EXTENSION_HOST_TEST_LAYER - FILE_SIZE_POLICY - MOCHA_OVER_JEST diff --git a/.ai/workflows.yaml b/.ai/workflows.yaml index e9285c21..09699ef5 100644 --- a/.ai/workflows.yaml +++ b/.ai/workflows.yaml @@ -145,6 +145,7 @@ common_commands: debug: F5 (in VS Code) package: npm run package lint: npm run lint + lint_ci: npm run lint:ci (eslint + stylelint with GitHub annotation formatters; run by CI) git_workflow: branch_naming: feature/description or fix/description commit_format: 'type(scope): description' diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8a8ce834..e83bba37 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,11 +6,18 @@ # in osv-scanner.toml that the Argus scan honors. Do NOT add a dev-dep `ignore:` here to suppress # those alerts -- `ignore:` also stops the version-update PRs below, which are how dev tools stay # current and how a transitive fix (e.g. serialize-javascript >= 7.0.5) actually lands. +# +# Every ecosystem below sets `target-branch: "beta"`. Without it Dependabot opens against the default +# branch (`main`), which is the STABLE release line: a push there auto-cuts a stable GitHub release, so a +# routine dependency bump would ship one out of band. `main` also trails `beta` by whatever has not been +# released yet, so bumps opened against it duplicate what already landed on `beta` and conflict on the +# lockfile when retargeted. Everything reaches `main` through the beta -> main release PR instead. version: 2 updates: # Maintain npm dependencies - package-ecosystem: "npm" directory: "/" + target-branch: "beta" schedule: interval: "weekly" day: "monday" @@ -68,6 +75,7 @@ updates: # Maintain GitHub Actions - package-ecosystem: "github-actions" directory: "/" + target-branch: "beta" schedule: interval: "weekly" day: "monday" @@ -85,6 +93,7 @@ updates: # Maintain pre-commit hooks - package-ecosystem: "pip" directory: "/" + target-branch: "beta" schedule: interval: "weekly" day: "monday" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5839f328..bdabbde2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: run: npm ci - name: Run lint - run: npm run lint + run: npm run lint:ci - name: Run compile run: node esbuild.js diff --git a/.github/workflows/security-hardening.yml b/.github/workflows/security-hardening.yml index 0eb89aa9..aefb63d7 100644 --- a/.github/workflows/security-hardening.yml +++ b/.github/workflows/security-hardening.yml @@ -19,8 +19,10 @@ permissions: jobs: argus-hardening: name: Argus Reusable Hardening - # Pinned to the commit for Argus v1.11.0 for supply-chain safety. - uses: huntridge-labs/argus/.github/workflows/reusable-security-hardening.yml@9b444d8975f4a2253cc53e09a7c5837e5b509d24 + # SHA-pinned rather than tag-pinned for supply-chain safety: a tag can be moved, a commit cannot. + # Dependabot bumps this SHA and names the tag it resolves to in the PR title, so read the version there + # rather than trusting a hand-written one here (this comment claimed v1.11.0 through three bumps past it). + uses: huntridge-labs/argus/.github/workflows/reusable-security-hardening.yml@6040db47e31f4db533967c3a5b70f4a208afead3 with: scanners: codeql,gitleaks,osv,dependency-review enable_code_security: true diff --git a/esbuild.js b/esbuild.js index 8eec0ae0..5f164dd0 100644 --- a/esbuild.js +++ b/esbuild.js @@ -1,9 +1,16 @@ const esbuild = require('esbuild'); +const fs = require('fs'); const production = process.argv.includes('--production'); const watch = process.argv.includes('--watch'); /** + * Emits the `[watch] build started`/`finished` markers VS Code's background problem matcher keys on. + * + * Only one context may emit them: the matcher treats the first `finished` as "task ready", so a second pair from a + * parallel build would mark the task ready while that build is still running. {@link errorReporterPlugin} covers the + * other contexts. + * * @type {import('esbuild').Plugin} */ const esbuildProblemMatcherPlugin = { @@ -14,42 +21,126 @@ const esbuildProblemMatcherPlugin = { console.log('[watch] build started'); }); build.onEnd((result) => { - result.errors.forEach(({ text, location }) => { - console.error(`✘ [ERROR] ${text}`); - console.error(` ${location.file}:${location.line}:${location.column}:`); - }); + reportErrors(result); console.log('[watch] build finished'); }); }, }; -async function main() { - const ctx = await esbuild.context({ - entryPoints: ['src/extension.ts'], - bundle: true, - format: 'cjs', - minify: production, - sourcemap: !production, - sourcesContent: false, - platform: 'node', - outfile: 'out/extension.js', - external: ['vscode'], - logLevel: 'silent', - // Additional optimizations - treeShaking: true, - metafile: production, - // Drop console logs in production for smaller bundle - drop: production ? ['console', 'debugger'] : [], - plugins: [ - /* add to the end of plugins array */ - esbuildProblemMatcherPlugin, - ], +/** + * Reports build errors without emitting watch markers, for contexts that build alongside the marker-emitting one. + * + * @param {string} label Which build the errors came from, since the output is interleaved. + * @returns {import('esbuild').Plugin} + */ +const errorReporterPlugin = (label) => ({ + name: `esbuild-error-reporter-${label}`, + + setup(build) { + build.onEnd((result) => reportErrors(result, label)); + }, +}); + +/** @param {import('esbuild').BuildResult} result @param {string} [label] */ +function reportErrors(result, label) { + const prefix = label ? `✘ [ERROR] [${label}] ` : '✘ [ERROR] '; + result.errors.forEach(({ text, location }) => { + console.error(`${prefix}${text}`); + if (location) { + console.error(` ${location.file}:${location.line}:${location.column}:`); + } + }); +} + +/** + * Build config for the Node-side extension bundle. + */ +const extensionConfig = { + entryPoints: ['src/extension.ts'], + bundle: true, + format: 'cjs', + minify: production, + sourcemap: !production, + sourcesContent: false, + platform: 'node', + outfile: 'out/extension.js', + external: ['vscode'], + logLevel: 'silent', + // Additional optimizations + treeShaking: true, + metafile: production, + // Drop console logs in production for smaller bundle + drop: production ? ['console', 'debugger'] : [], + plugins: [ + /* add to the end of plugins array */ + esbuildProblemMatcherPlugin, + ], +}; + +/** + * Every webview asset to build, discovered rather than listed. + * + * A stylesheet missing from a hand-maintained list still lints and typechecks, the build still exits 0, and the + * `` only 404s once the extension is packaged. Discovery keeps the build in step with the directory. + * + * Only the top level of each directory is collected, so shared modules imported by a client script are bundled into + * it rather than becoming entry points of their own. Directories that don't exist yet (`client/`, until scripts are + * extracted) contribute nothing. + * + * @returns {string[]} Paths of every asset entry point, relative to the repo root. + */ +function webviewEntryPoints() { + const assetDirs = [ + { dir: 'src/webview/styles', ext: '.css' }, + { dir: 'src/webview/client', ext: '.ts' }, + ]; + + return assetDirs.flatMap(({ dir, ext }) => { + if (!fs.existsSync(dir)) { + return []; + } + return fs + .readdirSync(dir, { withFileTypes: true }) + .filter((entry) => entry.isFile() && entry.name.endsWith(ext)) + .map((entry) => `${dir}/${entry.name}`); }); +} + +/** + * Build config for webview assets (styles, and client scripts as they are + * added). These run in the browser-like webview context, not Node, so they + * build separately and emit under out/webview for asWebviewUri loading. + */ +const webviewConfig = { + entryPoints: webviewEntryPoints(), + bundle: true, + minify: production, + sourcemap: production ? false : 'inline', + platform: 'browser', + // Pin the syntax level: webview assets run in the Electron renderer, not Node, so they must not inherit + // esbuild's `esnext` default. + target: ['es2020'], + format: 'iife', + outdir: 'out/webview', + // Preserve the src/webview/* folder structure (styles/, client/) under the + // output dir so asset URIs resolve to the same sub-path as the source. + outbase: 'src/webview', + logLevel: 'silent', + plugins: [errorReporterPlugin('webview')], +}; + +async function main() { + // Clear stale output: esbuild never removes files, so a renamed or deleted asset would leave a copy behind that + // still resolves through asWebviewUri — masking a broken reference until the extension is packaged. + fs.rmSync(webviewConfig.outdir, { recursive: true, force: true }); + + const ctx = await esbuild.context(extensionConfig); + const webviewCtx = await esbuild.context(webviewConfig); if (watch) { - await ctx.watch(); + await Promise.all([ctx.watch(), webviewCtx.watch()]); } else { - await ctx.rebuild(); - await ctx.dispose(); + await Promise.all([ctx.rebuild(), webviewCtx.rebuild()]); + await Promise.all([ctx.dispose(), webviewCtx.dispose()]); } } diff --git a/eslint.config.js b/eslint.config.js index 12cc5627..964ec2b5 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -40,4 +40,15 @@ module.exports = [ ...js.configs.recommended.rules, }, }, + { + // Webview client scripts run in the Electron renderer, not the extension host + files: ['src/webview/client/**/*.ts'], + languageOptions: { + globals: { + ...globals.browser, + // Injected by VS Code into the webview; not a browser global. + acquireVsCodeApi: 'readonly', + }, + }, + }, ]; diff --git a/package-lock.json b/package-lock.json index e8fbf063..d9c60187 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,49 +1,52 @@ { "name": "gitlab-component-helper", - "version": "0.16.12", + "version": "0.17.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.16.12", + "version": "0.17.13", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", "@commitlint/config-conventional": "^21.0.2", + "@csstools/stylelint-formatter-github": "^2.0.0", "@digitalroute/cz-conventional-changelog-for-jira": "^8.0.1", "@eslint/js": "^10.0.1", - "@octokit/core": "^7.0.7", + "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": "^15.0.0", - "@release-it/conventional-changelog": "^12.0.0", + "@release-it/conventional-changelog": "^12.0.2", "@types/glob": "^9.0.0", - "@types/js-yaml": "^4.0.9", "@types/mocha": "^10.0.10", - "@types/node": "^26.2.0", + "@types/node": "^26.6.1", "@types/vscode": "^1.120.0", - "@typescript-eslint/eslint-plugin": "^8.67.0", - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/eslint-plugin": "^8.70.0", + "@typescript-eslint/parser": "^8.70.0", "@vscode/test-electron": "^3.1.0", "commitizen": "^4.3.2", "conventional-changelog-conventionalcommits": "^9.3.1", "cz-conventional-changelog": "^3.3.0", - "cz-emoji-conventional": "^1.1.0", + "cz-emoji-conventional": "^1.3.0", "dateformat": "^5.0.3", - "dotenv": "^17.4.2", + "dotenv": "^18.0.0", "esbuild": "^0.28.2", - "eslint": "^10.8.1", - "globals": "^17.11.0", + "eslint": "^10.10.0", + "eslint-formatter-gha": "^2.0.1", + "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", - "js-yaml": "^5.3.0", + "js-yaml": "^5.4.2", "minimatch": "^10.2.6", - "mocha": "^11.8.0", + "mocha": "^12.0.2", "npm-run-all": "^4.1.5", - "release-it": "^21.0.2", + "release-it": "^21.1.0", "semver": "^7.8.5", - "tsx": "^4.23.12", + "stylelint": "^17.15.0", + "stylelint-config-standard": "^40.0.0", + "tsx": "^4.23.13", "typescript": "^6.0.3", - "typescript-eslint": "^8.67.0" + "typescript-eslint": "^8.70.0" }, "engines": { "node": ">=22.0.0", @@ -75,6 +78,30 @@ "node": ">=6.9.0" } }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.5.1", + "keyv": "^5.6.0" + } + }, "node_modules/@commitlint/cli": { "version": "21.2.2", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-21.2.2.tgz", @@ -340,9 +367,9 @@ } }, "node_modules/@conventional-changelog/git-client": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-3.1.0.tgz", - "integrity": "sha512-Tqa/gHco2WJWa740NRjOrfKVvzIqxkZpecb8bemaQ8sKM5PXb1UK4uTyTb/1wIqNuOVaDOFxyBdhTIQZn6gdjQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-3.1.2.tgz", + "integrity": "sha512-jZqwnJwf7nboIlAcw/mkOjVa6DexCcUOgT2oOQgkoi3z9vR8tGFkcMy2BFcYwjhL9sYcDDXkRQDayiDieCoW7A==", "dev": true, "license": "MIT", "dependencies": { @@ -355,7 +382,7 @@ }, "peerDependencies": { "conventional-commits-filter": "^6.0.1", - "conventional-commits-parser": "^7.0.1" + "conventional-commits-parser": "^7.1.2" }, "peerDependenciesMeta": { "conventional-commits-filter": { @@ -367,15 +394,200 @@ } }, "node_modules/@conventional-changelog/template": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@conventional-changelog/template/-/template-1.2.1.tgz", - "integrity": "sha512-TzlTVpKPjaqW6qOYjQcYUDuGsLCNsvFHVBXkYGTAnf5V37jCWrE5haKNXzz0WZUtVHjrpV76L1buANjwXMfT8w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@conventional-changelog/template/-/template-1.4.0.tgz", + "integrity": "sha512-aalGyl7dbB5PArRebDIX43ZvBlXrYm9uWzGJ26t+4SzJVPsOuvfILGGbw5X4yX7i50YEmJ8zvbiWnqH/AAnZqg==", "dev": true, "license": "MIT", "engines": { "node": ">=22" } }, + "node_modules/@csstools/css-calc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.12.tgz", + "integrity": "sha512-3vLQK+dXxhBMR2Wx99PTCifE+vHtW2ndZWyla8yK813ev6oGhyn8Lja8jCyGAWTJ+LEYZK7EVtJxrDj8ztevJw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-5.0.0.tgz", + "integrity": "sha512-T9lXmZOfnam3eMERPsszjY5NK0jX8RmThmmm99FZ8b7z8yMaFZWKwLWGZuTwdO3ddRY5fy13GmmEYZXB4I98Eg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-4.0.1.tgz", + "integrity": "sha512-j3vdQu0XwLME5qOTWxm8cnmvsf423R2YL6DbKklCHZwkDm7UdKNu6RPlw4REIJhSlKBICY3B70/7QZdicLqZgg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.1.1" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-6.0.0.tgz", + "integrity": "sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.1.1" + } + }, + "node_modules/@csstools/stylelint-formatter-github": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@csstools/stylelint-formatter-github/-/stylelint-formatter-github-2.0.0.tgz", + "integrity": "sha512-LAzHf7W1FmBNi/cA4n7ZqGW063UK+KZgcaoAmtkJZlbAxRlnthA/VEojmO06+eBAczKMMU1yslqsDh6Etvok8g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.0.0" + } + }, "node_modules/@digitalroute/cz-conventional-changelog-for-jira": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/@digitalroute/cz-conventional-changelog-for-jira/-/cz-conventional-changelog-for-jira-8.0.1.tgz", @@ -944,9 +1156,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", - "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1024,9 +1236,9 @@ } }, "node_modules/@inquirer/ansi": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.7.tgz", - "integrity": "sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.8.tgz", + "integrity": "sha512-WpQM+Ti6Z40EFwwt+uL2p4UabT+W179zHp6HhLVOzfbwnVn05IPO/eXIZXGNqcT1jbQ15SujNLzQ39k4QPPxBQ==", "dev": true, "license": "MIT", "engines": { @@ -1034,16 +1246,16 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.1.tgz", - "integrity": "sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.2.5.tgz", + "integrity": "sha512-bRt8J8m+Fot9CXv+zNQGXUq2ET0MggR1fPz7v6edN6MFYmsbfGnMmkmWZJEegMKqrAC8ej/o1sqisHZXZJMAfQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^11.2.1", - "@inquirer/figures": "^2.0.7", - "@inquirer/type": "^4.0.7" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1058,14 +1270,14 @@ } }, "node_modules/@inquirer/confirm": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.1.1.tgz", - "integrity": "sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ==", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.3.2.tgz", + "integrity": "sha512-Xvr/0HggjddPtGppuqVmxhTw+Hr8PvsZ/k0HmOEaAqQEt80OITNkFWnsdNmyT0/eM4Ab+iJLx2R8rctlEyfSVg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1080,15 +1292,15 @@ } }, "node_modules/@inquirer/core": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.2.1.tgz", - "integrity": "sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA==", + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-12.0.3.tgz", + "integrity": "sha512-wsSy0sznmXwkty+2PzZwx00Cazc/E0r0B7mAzdGROz2Ct+DFZXaK7WDjGZvgjRldxH5ZhFVfF2lgkYrqgOw2KA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/figures": "^2.0.7", - "@inquirer/type": "^4.0.7", + "@inquirer/ansi": "^2.0.8", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1", "cli-width": "^4.1.0", "fast-wrap-ansi": "^0.2.0", "mute-stream": "^3.0.0", @@ -1140,15 +1352,15 @@ } }, "node_modules/@inquirer/editor": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.2.2.tgz", - "integrity": "sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.3.3.tgz", + "integrity": "sha512-YsKkS2q63IiLtaDK/9nqzdComN97SDQrmKiyNggN+ceP4ty+Z6VwyTz3FpjeUWeW1Efss2xHFKCC9sx7hnrsxg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/external-editor": "^3.0.3", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/external-editor": "^3.0.5", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1163,9 +1375,9 @@ } }, "node_modules/@inquirer/editor/node_modules/@inquirer/external-editor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.3.tgz", - "integrity": "sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-3.0.5.tgz", + "integrity": "sha512-f3QQJRIX5ZEneBHNUIuPjmbdzHnmRFJA8r2dkcb8q+OM5Uv5KtnuAttQumnrjcBVBM3mcTX1CkmtAkU58VRZxg==", "dev": true, "license": "MIT", "dependencies": { @@ -1185,14 +1397,14 @@ } }, "node_modules/@inquirer/expand": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.1.tgz", - "integrity": "sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.1.5.tgz", + "integrity": "sha512-uHuXLmXW+TtIfT/9vSBotypAkqn1n34Ul+CLGPos/xANyO4Ff5xZzkYhbKR4NEcfVK4a9mHQOpwVZzluSHFRGw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1229,9 +1441,9 @@ } }, "node_modules/@inquirer/figures": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.7.tgz", - "integrity": "sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.9.tgz", + "integrity": "sha512-EAWgUTGQ/Umgga51dE3B2PUHbufuXarDfg86uVgoSgNHNNQnyFKcOrQLWVqYMghuSyHh8+2HUH0Js9cTC1WAdg==", "dev": true, "license": "MIT", "engines": { @@ -1239,14 +1451,14 @@ } }, "node_modules/@inquirer/input": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.2.tgz", - "integrity": "sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.1.6.tgz", + "integrity": "sha512-HtcJhB2QFVXbLuJ5S3syhNbTUVxYvwqV4VRBDkQceBloC9bmTViUoRFP5PbSaDZb3HzfPmpuU/gG4ybVBz4FHA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1261,14 +1473,14 @@ } }, "node_modules/@inquirer/number": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.1.1.tgz", - "integrity": "sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.2.3.tgz", + "integrity": "sha512-6Yuwh1NGSbu1Lo4N1EWjXs1jKRntLg/ZCwhmeorEHde90v1XxAozdbd4Iu30eOQLW+6h1hp2O9ujNfLSbTPJnA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1283,15 +1495,15 @@ } }, "node_modules/@inquirer/password": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.1.1.tgz", - "integrity": "sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.2.2.tgz", + "integrity": "sha512-W9zYdyzogK+6110mqwaSJWCBu2yA5Q/OfnGSjjZB1bNpHlmUozXxTl0+QOZBNeVd6Qo81/qT75gW05gLAtITxw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1306,22 +1518,22 @@ } }, "node_modules/@inquirer/prompts": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.5.2.tgz", - "integrity": "sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g==", + "version": "8.7.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.7.2.tgz", + "integrity": "sha512-QoRB4wFIjgH5iOhSjoIKMkTvSHDuV+O3OITlIqAYO0oK5x364GJILXiMBvlPiE+klg7Xx9tq5XVqQHcGUDYYPA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^5.2.1", - "@inquirer/confirm": "^6.1.1", - "@inquirer/editor": "^5.2.2", - "@inquirer/expand": "^5.1.1", - "@inquirer/input": "^5.1.2", - "@inquirer/number": "^4.1.1", - "@inquirer/password": "^5.1.1", - "@inquirer/rawlist": "^5.3.1", - "@inquirer/search": "^4.2.1", - "@inquirer/select": "^5.2.1" + "@inquirer/checkbox": "^5.2.5", + "@inquirer/confirm": "^6.3.2", + "@inquirer/editor": "^5.3.3", + "@inquirer/expand": "^5.1.5", + "@inquirer/input": "^5.1.6", + "@inquirer/number": "^4.2.3", + "@inquirer/password": "^5.2.2", + "@inquirer/rawlist": "^5.3.5", + "@inquirer/search": "^4.3.3", + "@inquirer/select": "^5.2.5" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1336,14 +1548,14 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.1.tgz", - "integrity": "sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.3.5.tgz", + "integrity": "sha512-1oHky1ONfCOwNrnkQGDE1oaSij/3fI6HFMSf2H/WsGO2lEyDX9My82iggITSy9ddSZ8yk8j9v41OI0fVoSIoaA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1358,15 +1570,15 @@ } }, "node_modules/@inquirer/search": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.2.1.tgz", - "integrity": "sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.3.3.tgz", + "integrity": "sha512-fyuIU1Nbpvwlikjg3gXwJFDI11+EFjqQ7P+iByfmivIKQ1vmaykNrD/vy5unHuUqUpsOsnvJ25//tPF7E/RBRA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^11.2.1", - "@inquirer/figures": "^2.0.7", - "@inquirer/type": "^4.0.7" + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1381,16 +1593,16 @@ } }, "node_modules/@inquirer/select": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.1.tgz", - "integrity": "sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.2.5.tgz", + "integrity": "sha512-9kc15hr8r/kI+3DO/xLog5nOzTz1jqsHXa6JBFzmQKhkoJ8Slda1I1L/uD8ZSZ9tF1yp79wwXe7mclvX1rqR2Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/ansi": "^2.0.7", - "@inquirer/core": "^11.2.1", - "@inquirer/figures": "^2.0.7", - "@inquirer/type": "^4.0.7" + "@inquirer/ansi": "^2.0.8", + "@inquirer/core": "^12.0.3", + "@inquirer/figures": "^2.0.9", + "@inquirer/type": "4.1.1" }, "engines": { "node": ">=23.5.0 || ^22.13.0 || ^20.17.0" @@ -1405,9 +1617,9 @@ } }, "node_modules/@inquirer/type": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.7.tgz", - "integrity": "sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.1.1.tgz", + "integrity": "sha512-yJoHYrMnxIsJZCY+0Vb66Dy3he3kL3e2wOBKhoSwWWAzZAY82emlxwgprCtp6yRixvNRNq9ztfRWQYPNr3Go7A==", "dev": true, "license": "MIT", "engines": { @@ -1422,107 +1634,66 @@ } } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 18" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "keyv": "^5.6.0" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, "license": "MIT" }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 8" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">= 8" } }, "node_modules/@octokit/auth-token": { @@ -1536,17 +1707,17 @@ } }, "node_modules/@octokit/core": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.7.tgz", - "integrity": "sha512-DcB0M3KFgr9ECI328lhBMVsyFT2DnmNucSBTqEN3exyNKUzkkpUSCHmTRcunF41Eou2TIQKW4seewri8ON9bSA==", + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.8.tgz", + "integrity": "sha512-L7y8eYc+AwxGr2PWI4WFt1VG4TiJ66c26BD16mXpYIlXxG0SMigM1+m4aTSlYyBr5BlQsGAlz8uDCoZN4SEMcg==", "dev": true, "license": "MIT", "dependencies": { "@octokit/auth-token": "^6.0.0", - "@octokit/graphql": "^9.0.4", - "@octokit/request": "^10.0.13", - "@octokit/request-error": "^7.1.1", - "@octokit/types": "^17.0.0", + "@octokit/graphql": "^9.0.5", + "@octokit/request": "^10.0.16", + "@octokit/request-error": "^7.1.2", + "@octokit/types": "^18.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" }, @@ -1555,30 +1726,30 @@ } }, "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", - "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/core/node_modules/@octokit/types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", - "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^28.0.0" + "@octokit/openapi-types": "^29.0.1" } }, "node_modules/@octokit/endpoint": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.4.tgz", - "integrity": "sha512-f1cOWoHPmxryJFknxbtDdjODWfV8A9tc8Aae6ermXPNgHFZ/x91AtHIz4gicEjL8hkJiip+u21QHJORfBv/qiA==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.5.tgz", + "integrity": "sha512-iXa654H3yFafF/ieHkukfbgWo2rmXD2ceD0ZOtrPhw1bc3FDch1d9N/TNs0FQ1/cIbwb7kspUX8jzIs8nzb9DQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^17.0.0", + "@octokit/types": "^18.0.0", "universal-user-agent": "^7.0.2" }, "engines": { @@ -1586,31 +1757,31 @@ } }, "node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", - "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/endpoint/node_modules/@octokit/types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", - "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^28.0.0" + "@octokit/openapi-types": "^29.0.1" } }, "node_modules/@octokit/graphql": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.4.tgz", - "integrity": "sha512-5s15CCiY8XXQ+FG+b1YQcl6Z2FA++nwAz/tg2VUrTmnMncP+2nnGUEYANImdnxsA2Fnq+Mbl7hDjUTw7cFAwcg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.5.tgz", + "integrity": "sha512-bt/hm03LeU6Vy7FwTrkkC9p3XGT/lBwClglMqxBSe5/q0E5CdJTXeAqEI0vlw89/LF/G6tryTIH8HirZ3prMVg==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/request": "^10.0.13", - "@octokit/types": "^17.0.0", + "@octokit/request": "^10.0.16", + "@octokit/types": "^18.0.0", "universal-user-agent": "^7.0.0" }, "engines": { @@ -1618,20 +1789,20 @@ } }, "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", - "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/graphql/node_modules/@octokit/types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", - "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^28.0.0" + "@octokit/openapi-types": "^29.0.1" } }, "node_modules/@octokit/openapi-types": { @@ -1704,17 +1875,17 @@ } }, "node_modules/@octokit/request": { - "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.13.tgz", - "integrity": "sha512-v2269YxL9Yf+x3d+gRI63FP0vFQEiWgLyBzxe/Y+0yFDg2B/Tzf5dhh9VNfccVAQnfcfwQWyk/y6Bn7rUXXs7A==", + "version": "10.0.16", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.16.tgz", + "integrity": "sha512-A0zWGjHzISIb+9ccG8s0dq7LKO5zVpJLRICjgUb+sJxEWqn8RUHB1rD3AE51+PECvXHIxqZ1VVvs4fHTSD9nUQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/endpoint": "^11.0.3", - "@octokit/request-error": "^7.1.1", - "@octokit/types": "^17.0.0", - "content-type": "^2.0.0", - "json-with-bigint": "^3.5.3", + "@octokit/endpoint": "^11.0.5", + "@octokit/request-error": "^7.1.2", + "@octokit/types": "^18.0.0", + "content-type": "^3.0.0", + "json-with-bigint": "^3.5.12", "universal-user-agent": "^7.0.2" }, "engines": { @@ -1722,50 +1893,50 @@ } }, "node_modules/@octokit/request-error": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.1.tgz", - "integrity": "sha512-+eaY7G2VVpSf2pc5Gn1+mph837V/d/TYTJAgWL9Tb0ogGYcpN3IlAVFgjL+Vv93F/sevrxkvsYCedtpLdcFLzA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.2.tgz", + "integrity": "sha512-XZRuT3xZ84D3gYErI1DZvhJ33dCWVV6uzBtWkaBB4TvA/L6eOeTZodxLFVB44bBEEo3vEx7y00UfX1tBLrtLRg==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^17.0.0" + "@octokit/types": "^18.0.0" }, "engines": { "node": ">= 20" } }, "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", - "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/request-error/node_modules/@octokit/types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", - "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^28.0.0" + "@octokit/openapi-types": "^29.0.1" } }, "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { - "version": "28.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", - "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", "dev": true, "license": "MIT" }, "node_modules/@octokit/request/node_modules/@octokit/types": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", - "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/openapi-types": "^28.0.0" + "@octokit/openapi-types": "^29.0.1" } }, "node_modules/@octokit/rest": { @@ -1824,47 +1995,36 @@ "url": "https://github.com/phun-ky/typeof?sponsor=1" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@release-it/conventional-changelog": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@release-it/conventional-changelog/-/conventional-changelog-12.0.0.tgz", - "integrity": "sha512-b9N8/tUjO9JNH1u2fVSmq8QmbqnE//Y5iCgvPcytsk0pj0GhgGCp+VmfzhEBIdd+lVGZJKs+ZSaGaOHjtmtv7g==", + "node_modules/@release-it/conventional-changelog": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/@release-it/conventional-changelog/-/conventional-changelog-12.0.2.tgz", + "integrity": "sha512-mJsfycScVqud9O+GzVLT1wQBsIR2WO3kEe6Xm7ucf9yP9KyKRTY9yqoFe/kjLCNSu0lP0PzpuOooUYyzHm1oFw==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/git-client": "^3.1.0", + "@conventional-changelog/git-client": "^3.1.2", "concat-stream": "^2.0.0", - "conventional-changelog": "^8.1.0", - "conventional-changelog-angular": "^9.2.1", - "conventional-changelog-conventionalcommits": "^10.2.1", + "conventional-changelog": "^8.1.3", + "conventional-changelog-angular": "^9.4.0", + "conventional-changelog-conventionalcommits": "^10.4.0", "conventional-recommended-bump": "^12.1.0", "semver": "^7.8.5" }, "engines": { - "node": "^22.21.0 || >=24.0.0" + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { "release-it": "^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0" } }, "node_modules/@release-it/conventional-changelog/node_modules/conventional-changelog-conventionalcommits": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-10.2.1.tgz", - "integrity": "sha512-n4Kr1HFMTf3iMbES0TMxKIcYtUUv4rKqyQQp2JwfOEfFCOfGT3Tq4mCyJ8S9/YPyWhydjfKrrvnyl+gCjA+mJQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-10.4.0.tgz", + "integrity": "sha512-Rriac6ZrAlVm6cy9Bz4NSp+WMHpwNXoPIYex+HjCgduAVUSbnew29DQjQw0C4g9u3HtSYzGiGY+pdBXAZo+4aA==", "dev": true, "license": "ISC", "dependencies": { - "@conventional-changelog/template": "^1.2.1" + "@conventional-changelog/template": "^1.4.0" }, "engines": { "node": ">=22" @@ -1929,6 +2089,19 @@ "url": "https://ko-fi.com/dangreen" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", @@ -1954,13 +2127,6 @@ "glob": "*" } }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1976,13 +2142,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", - "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", + "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~8.3.0" + "undici-types": "~8.9.0" } }, "node_modules/@types/parse-path": { @@ -2000,17 +2166,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", - "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.0.tgz", + "integrity": "sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/type-utils": "8.67.0", - "@typescript-eslint/utils": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/type-utils": "8.70.0", + "@typescript-eslint/utils": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2023,22 +2189,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/parser": "^8.70.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", - "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.0.tgz", + "integrity": "sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "debug": "^4.4.3" }, "engines": { @@ -2054,14 +2220,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", - "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.0.tgz", + "integrity": "sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.67.0", - "@typescript-eslint/types": "^8.67.0", + "@typescript-eslint/tsconfig-utils": "^8.70.0", + "@typescript-eslint/types": "^8.70.0", "debug": "^4.4.3" }, "engines": { @@ -2076,14 +2242,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", - "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.0.tgz", + "integrity": "sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0" + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2094,9 +2260,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", - "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.0.tgz", + "integrity": "sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==", "dev": true, "license": "MIT", "engines": { @@ -2111,15 +2277,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", - "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.0.tgz", + "integrity": "sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0", - "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/utils": "8.70.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2136,9 +2302,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", - "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.0.tgz", + "integrity": "sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==", "dev": true, "license": "MIT", "engines": { @@ -2150,16 +2316,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", - "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.0.tgz", + "integrity": "sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.67.0", - "@typescript-eslint/tsconfig-utils": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0", + "@typescript-eslint/project-service": "8.70.0", + "@typescript-eslint/tsconfig-utils": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2178,16 +2344,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", - "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.0.tgz", + "integrity": "sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.67.0", - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0" + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2202,13 +2368,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", - "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.0.tgz", + "integrity": "sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/types": "8.70.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2440,6 +2606,16 @@ "node": ">=4" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -2755,34 +2931,31 @@ } } }, - "node_modules/c12/node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "node_modules/c12/node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">= 20.19.0" + "node": ">=12" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://dotenvx.com" } }, - "node_modules/c12/node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "dependencies": { + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" } }, "node_modules/cachedir": { @@ -2891,16 +3064,16 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -3098,6 +3271,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colord": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.10.0.tgz", + "integrity": "sha512-AidJptpBJmjTclAp9BkLwJi0T93fo5epJnbaZslpg6QVzpHjAiveF55mE9AcUJiGMqRHgMDY8soMsQtuNYMHfw==", + "dev": true, + "license": "MIT" + }, "node_modules/commitizen": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.2.tgz", @@ -3224,13 +3404,13 @@ "license": "MIT" }, "node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-3.0.0.tgz", + "integrity": "sha512-AIi5H6p0xk5uknXcN3/rmhP8jgp69OfSe/JuKiQAFprJ7UGw7mwj7m4XcmDzlrnJDG+cGpphAINGdU3g3g7kDw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=22" }, "funding": { "type": "opencollective", @@ -3238,19 +3418,20 @@ } }, "node_modules/conventional-changelog": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-8.1.0.tgz", - "integrity": "sha512-idt1JK+3+Nt7gqH/d/sEYWdDeR+5XPov/jssmFN6XxmYSRlonTWSDWhWUPkmm0zbwYjtVdt+4My5aiPkKyvocw==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-8.1.3.tgz", + "integrity": "sha512-fOMwLCxm46znJKPB08jLxl1FD8SOZOQHktlzCVhvhhVUfq0KgQSryoYXsRRHs1aRlZPR1/QK5wztnY8sBNC2AA==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/git-client": "^3.1.0", + "@conventional-changelog/git-client": "^3.1.2", "@simple-libs/hosted-git-info": "^2.0.0", "@simple-libs/normalize-package-data": "^1.0.0", "argue-cli": "^3.1.0", "conventional-changelog-preset-loader": "^6.0.1", - "conventional-changelog-writer": "^9.2.0", - "conventional-commits-parser": "^7.1.0", + "conventional-changelog-writer": "^9.2.1", + "conventional-commits-filter": "^6.0.1", + "conventional-commits-parser": "^7.1.2", "fd-package-json": "^2.0.0" }, "bin": { @@ -3261,13 +3442,13 @@ } }, "node_modules/conventional-changelog-angular": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-9.2.1.tgz", - "integrity": "sha512-oWSL6ZhnXbYraOFTK3PgRAQJ8fADDAEv5K6AdeyQPLvjFmhG8+ejL0jZZp/R7vTmGJaBvZEE+sE7dB4bCv7sAw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-9.4.0.tgz", + "integrity": "sha512-HdxRxuS8bBXVIuo4V82gvSwAXT0vYQUizrjs/izmPg5JdDstr8v8I5hduGL3iQbG+o310dUDxC4+LetuS5hu9w==", "dev": true, "license": "ISC", "dependencies": { - "@conventional-changelog/template": "^1.2.1" + "@conventional-changelog/template": "^1.4.0" }, "engines": { "node": ">=22" @@ -3297,13 +3478,13 @@ } }, "node_modules/conventional-changelog-writer": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-9.2.0.tgz", - "integrity": "sha512-eACD5BaAQCYjeI3RExkCZopNaaIuXzCP4kaAb2lEFXcGa/KOuxJfj8v/SnjhvF6377pYn0A2Gji+6GhwUK8rEA==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-9.2.1.tgz", + "integrity": "sha512-StlYSmW3wLedRaqohJMpP3YuWiAqtgD0/cpsai9frdDkXv7rxj0hRbpJrubPYvJxJsjplONsOobEQnPuS9UgCg==", "dev": true, "license": "MIT", "dependencies": { - "@conventional-changelog/template": "^1.2.1", + "@conventional-changelog/template": "^1.3.0", "@simple-libs/stream-utils": "^2.0.0", "argue-cli": "^3.1.0", "conventional-commits-filter": "^6.0.1", @@ -3334,9 +3515,9 @@ } }, "node_modules/conventional-commits-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-7.1.1.tgz", - "integrity": "sha512-B0f42jI++V5Vb7qK+DDw68r0dNxz5hk+RdKUkx2NOi39emc9hsHa3u2M3doF7QQhRFzCrAj7uM90teG+RBTaYQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-7.1.2.tgz", + "integrity": "sha512-O+x4N2yH+ijvqWlIyTHsXTAP+algNWgGbjY2duCe8w2vUMvUB95cLRslCPfTMQyLAKlet3bhZTdu6ozn4M+QJQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3378,9 +3559,9 @@ "license": "MIT" }, "node_modules/cosmiconfig": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", - "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", + "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", "dev": true, "license": "MIT", "dependencies": { @@ -3423,9 +3604,9 @@ } }, "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, "funding": [ { @@ -3460,6 +3641,43 @@ "node": ">= 8" } }, + "node_modules/css-functions-list": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cz-conventional-changelog": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", @@ -3482,15 +3700,18 @@ } }, "node_modules/cz-emoji-conventional": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cz-emoji-conventional/-/cz-emoji-conventional-1.2.1.tgz", - "integrity": "sha512-ge1bnmUlRjQKCck65yqjPc2/dBtI9cBBE3e/j/2XkFVGXX94xQM7q9bD9a0NlKf9RvMb7oRGZwi86zgxkY3ujQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/cz-emoji-conventional/-/cz-emoji-conventional-1.3.0.tgz", + "integrity": "sha512-77Poz4EMKWNeNryvdGgfj8rOK6K90NiwIIh9EGJykjVeeGBlNVXAWWUXCHKO6XDORX2jx0a96jIVt/UNXziZvg==", "dev": true, "license": "ISC", "dependencies": { "chalk": "4.1.2", - "commitizen": "^4.3.0", - "word-wrap": "^1.2.3" + "commitizen": "^4.3.2", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">=18" } }, "node_modules/cz-emoji-conventional/node_modules/ansi-styles": { @@ -3661,19 +3882,6 @@ } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -3689,9 +3897,9 @@ "license": "MIT" }, "node_modules/default-browser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", - "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz", + "integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==", "dev": true, "license": "MIT", "dependencies": { @@ -3833,9 +4041,9 @@ } }, "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz", + "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -3856,11 +4064,14 @@ } }, "node_modules/dotenv": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", - "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.1.tgz", + "integrity": "sha512-0eR4m4D/jH5eaI3evo2ZqqMii5mrTCR12v12VChdie6O1gPHs7XAjzTep0CWc1Bd+oNx3vVfbi734dK4zghigw==", "dev": true, "license": "BSD-2-Clause", + "bin": { + "dotenv": "dist/index.cjs" + }, "engines": { "node": ">=12" }, @@ -3883,13 +4094,6 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4150,9 +4354,9 @@ } }, "node_modules/eslint": { - "version": "10.8.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.1.tgz", - "integrity": "sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==", + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.10.0.tgz", + "integrity": "sha512-NPXn6r5zl4uET1DAVPaOwzX3rut4c0wcmw3dWJAfOsTM5+TogXo0DDjz8pwm/hL8cyVNpHqeK4JpN0NjnyFFNw==", "dev": true, "license": "MIT", "workspaces": [ @@ -4164,7 +4368,7 @@ "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", - "@eslint/plugin-kit": "^0.7.2", + "@eslint/plugin-kit": "^0.7.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -4179,7 +4383,7 @@ "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", + "file-entry-cache": "11.1.5 || >11.1.6 <12", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", @@ -4208,6 +4412,118 @@ } } }, + "node_modules/eslint-formatter-gha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-formatter-gha/-/eslint-formatter-gha-2.0.1.tgz", + "integrity": "sha512-HbiPXXjIley/JRcQ9zRZ4HJhhU8ZIf0wVLbfyQKm/7HIcbvOsA2xwl/Lblyd8fhYalUWxKcodJOwsOwxw7O0Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-formatter-json": "^9.0.0", + "eslint-formatter-stylish": "^9.0.0" + } + }, + "node_modules/eslint-formatter-json": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/eslint-formatter-json/-/eslint-formatter-json-9.0.1.tgz", + "integrity": "sha512-EQ/X+bPjiOUDo4frNbkY+5R6emaHTL7t2jHsJw5s8p8w1BTJ6ao6S7g/PaRyx/CqqaYcjJkWAPHH/onNyFlJBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-formatter-stylish": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/eslint-formatter-stylish/-/eslint-formatter-stylish-9.0.1.tgz", + "integrity": "sha512-FlhMRUiDUHztGj+bhm3pYo5DJ6Gbjh/FGPClcDENme7f9+Sc3+HZg6wMq80KJmRD8/oj/Ib6gy4D/ppjmHfGVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/eslint-formatter-stylish/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint-formatter-stylish/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint-formatter-stylish/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint-formatter-stylish/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-formatter-stylish/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-formatter-stylish/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/eslint-scope": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", @@ -4431,6 +4747,36 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4463,9 +4809,9 @@ } }, "node_modules/fast-uri": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", - "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", + "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", "dev": true, "funding": [ { @@ -4489,6 +4835,26 @@ "fast-string-width": "^3.0.2" } }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fd-package-json": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-2.0.0.tgz", @@ -4516,16 +4882,13 @@ } }, "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" + "flat-cache": "^6.1.23" } }, "node_modules/fill-range": { @@ -4576,10 +4939,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/findup-sync": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", - "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4592,34 +4968,22 @@ "node": ">= 8" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" } }, "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, @@ -4639,36 +5003,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -4984,9 +5318,9 @@ } }, "node_modules/globals": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", - "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", + "version": "17.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.12.0.tgz", + "integrity": "sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==", "dev": true, "license": "MIT", "engines": { @@ -5013,6 +5347,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "16.2.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.4.tgz", + "integrity": "sha512-c8B/VNLmxRcmqqenRA9t+9IyOjf9+V6lTxPaUJLqOCONdQkWZ0ETYgX0qbtJqPsgCNusT9MZ5Jeidw8Eb9tn2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", + "micromatch": "^4.0.8", + "slash": "^5.1.0", + "unicorn-magic": "^0.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true, + "license": "MIT" + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -5114,6 +5477,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^1.15.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/hasown": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", @@ -5127,16 +5503,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -5150,6 +5516,26 @@ "node": ">=0.10.0" } }, + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-tags": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-5.1.0.tgz", + "integrity": "sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -5233,9 +5619,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.9.tgz", + "integrity": "sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==", "dev": true, "license": "MIT", "engines": { @@ -5276,6 +5662,17 @@ "node": ">=4" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5847,13 +6244,16 @@ } }, "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-plain-obj": { @@ -6101,22 +6501,6 @@ "node": "^18.17 || >=20.6.1" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -6135,9 +6519,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.3.0.tgz", - "integrity": "sha512-muutsYr+e2+d3rTgUGslq5rxbBlUy3cJ61IsHag2QNDQV+7zXWjkUpmALIajhrlLlrgRUiymj6U3zUr/TMK84Q==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.2.tgz", + "integrity": "sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==", "dev": true, "funding": [ { @@ -6157,13 +6541,6 @@ "js-yaml": "bin/js-yaml.mjs" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -6193,9 +6570,9 @@ "license": "MIT" }, "node_modules/json-with-bigint": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.10.tgz", - "integrity": "sha512-Vcx+JVNEBts/xfcoCS69sKrOhOk/3TVlvlT+XzUOefVKnnrbYSCKpDCm10pohsJFtsJVYnwa/cXRZ4eElzaM6w==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.12.tgz", + "integrity": "sha512-uwbF/wSSuOgC7qqlq27Xp5B6a2MHVug3t0idZdTqu0JnlFvgJuH7ju+KAk/J06C7GfhoYy2gnb9wz2INqcne7w==", "dev": true, "license": "MIT" }, @@ -6266,13 +6643,23 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "@keyv/serialize": "^1.1.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, "node_modules/levn": { @@ -6411,6 +6798,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.uniqby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", @@ -6521,13 +6915,6 @@ "node": ">=0.10.0" } }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/macos-release": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.4.0.tgz", @@ -6551,6 +6938,24 @@ "node": ">= 0.4" } }, + "node_modules/mathml-tag-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-4.0.0.tgz", + "integrity": "sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -6560,6 +6965,19 @@ "node": ">= 0.10.0" } }, + "node_modules/meow": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-14.1.0.tgz", + "integrity": "sha512-EDYo6VlmtnumlcBCbh1gLJ//9jvM/ndXHfVXIFrZVr6fGcwTUyCTFNTLCKuY3ffbK8L/+3Mzqnd58RojiZqHVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", @@ -6567,6 +6985,16 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -6668,228 +7096,112 @@ } }, "node_modules/mocha": { - "version": "11.8.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.8.0.tgz", - "integrity": "sha512-VyCeUdGN3A9lmCTTgG4yuvY9ixxaDk+xt2R/7/+1AP6EqNG+G9OKkzBwhVtVYoNX8YsxNSgAl8mOv3IAeOpFbw==", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-12.0.2.tgz", + "integrity": "sha512-SjAulGHxlMJLCD1bhvJBAiYwYxglydRzA9PDQ5MALq1oLRMMtIhxSQJ0olCFgA7c9YbTdxC0KOV0wl8JEDYVhA==", "dev": true, "license": "MIT", "dependencies": { "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", + "chokidar": "^5.0.0", "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", + "diff": "^9.0.0", + "find-up-simple": "^1.0.1", + "glob": "^13.0.0", + "is-path-inside": "^4.0.0", + "is-unicode-supported": "^0.1.0", + "js-yaml": "^5.0.0", + "minimatch": "^10.2.2", "ms": "^2.1.3", "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", + "serialize-javascript": "^7.1.1", + "strip-json-comments": "^5.0.3", "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" + "workerpool": "^10.0.0" }, "bin": { - "_mocha": "bin/_mocha", "mocha": "bin/mocha.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/mocha/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", + "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "has-flag": "^4.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/mocha/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true, - "license": "ISC" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, @@ -6939,6 +7251,16 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-all": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", @@ -7147,18 +7469,18 @@ } }, "node_modules/open": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", - "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.4.tgz", + "integrity": "sha512-++Zlftm0kVLPmzC06t6epuWmcRMDbI4z5P3NNX979WA/k23+NtSOynEGzsVfZwguKw2mi5umVgnBlJQMwRz4Pg==", "dev": true, "license": "MIT", "dependencies": { - "default-browser": "^5.4.0", + "default-browser": "^5.5.1", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", - "powershell-utils": "^0.1.0", - "wsl-utils": "^0.3.0" + "powershell-utils": "^0.2.1", + "wsl-utils": "^1.0.0" }, "engines": { "node": ">=20" @@ -7525,13 +7847,6 @@ "quickjs-wasi": "^2.2.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -7761,10 +8076,87 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-safe-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.1.0.tgz", + "integrity": "sha512-1WzZxRLaAFwEh6Do+zyGpjWV3nGJNxxhuh7Ubu/q1ICImMgZJnLwhoaEpRbG4pJppp2Y1ncL9ffA2f+LhrefQg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.6.tgz", + "integrity": "sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/powershell-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", - "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.2.1.tgz", + "integrity": "sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==", "dev": true, "license": "MIT", "engines": { @@ -7906,6 +8298,47 @@ "node": ">=6" } }, + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hookified": "^2.1.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/qified/node_modules/hookified": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/quickjs-wasi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz", @@ -7913,16 +8346,6 @@ "dev": true, "license": "MIT" }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/rc9": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/rc9/-/rc9-3.0.1.tgz", @@ -7995,13 +8418,13 @@ } }, "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 14.18.0" + "node": ">= 20.19.0" }, "funding": { "type": "individual", @@ -8053,9 +8476,9 @@ } }, "node_modules/release-it": { - "version": "21.0.2", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-21.0.2.tgz", - "integrity": "sha512-QwyDnWiQNB4d8Hc2b5FLMHcsKz9S2O1dMNnPB7w+0knsL5r8+qbnznDA1X7Bw5D863+Ud7eRHc71Cfth5Tlrgg==", + "version": "21.1.0", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-21.1.0.tgz", + "integrity": "sha512-jR179wu8Z9BKfhd0wVmUmzjshCnezUkULdHW5rSCjKTXApdr6mAJjw/R339uXS43mLCz6iAFO6ffS27+N1dy8A==", "dev": true, "funding": [ { @@ -8069,7 +8492,7 @@ ], "license": "MIT", "dependencies": { - "@inquirer/prompts": "8.5.2", + "@inquirer/prompts": "8.7.2", "@octokit/rest": "22.0.1", "@phun-ky/typeof": "2.0.3", "async-retry": "1.3.3", @@ -8082,21 +8505,21 @@ "lodash.merge": "4.6.2", "mime-types": "3.0.2", "new-github-release-url": "2.0.0", - "open": "11.0.0", + "open": "11.0.4", "ora": "9.4.1", "os-name": "7.0.0", "proxy-agent": "8.0.2", - "semver": "7.8.5", "tinyglobby": "0.2.17", "undici": "7.29.0", "url-join": "5.0.0", + "verkit": "0.4.0", "wildcard-match": "5.1.4" }, "bin": { "release-it": "bin/release-it.js" }, "engines": { - "node": "^22.21.0 || >=24.0.0" + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, "node_modules/release-it/node_modules/ansi-regex": { @@ -8299,16 +8722,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -8389,6 +8802,17 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/right-pad": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/right-pad/-/right-pad-1.1.1.tgz", @@ -8423,6 +8847,30 @@ "node": ">=0.12.0" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -8530,13 +8978,13 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.1.tgz", + "integrity": "sha512-k3CMsaIvvdSwm8oLB4MXSl0wH2/cwlH7xGcnRd2DaeRmBkbzYmyT8j0tsX60DwD1eRwHTpNpH8ljKu9oUT1MeQ==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=20.0.0" } }, "node_modules/set-function-length": { @@ -8714,6 +9162,73 @@ "dev": true, "license": "ISC" }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -8776,6 +9291,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -8864,22 +9389,6 @@ "node": ">=8" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/string.prototype.padend": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", @@ -8971,20 +9480,6 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -9008,6 +9503,209 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stylelint": { + "version": "17.15.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.15.0.tgz", + "integrity": "sha512-mWIkesYQvQjf4Kvdeu9ns0IL8/K/wtjaGxPqsPd6DlLZvaQxGysJsocxUDrBcyHQ5VleAk4uSMat4yMrVED7PA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^3.3.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-syntax-patches-for-csstree": "^1.1.9", + "@csstools/css-tokenizer": "^4.0.0", + "@csstools/media-query-list-parser": "^5.0.0", + "@csstools/selector-resolve-nested": "^4.0.1", + "@csstools/selector-specificity": "^6.0.0", + "colord": "^2.10.0", + "cosmiconfig": "^9.0.2", + "css-functions-list": "^3.3.3", + "css-tree": "^3.2.1", + "debug": "^4.4.3", + "fast-glob": "^3.3.3", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^11.1.5", + "global-modules": "^2.0.0", + "globby": "^16.2.4", + "globjoin": "^0.1.4", + "html-tags": "^5.1.0", + "ignore": "^7.0.6", + "import-meta-resolve": "^4.2.0", + "mathml-tag-names": "^4.0.0", + "meow": "^14.1.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.5.26", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.1.5", + "postcss-value-parser": "^4.2.0", + "string-width": "^8.2.2", + "supports-hyperlinks": "^4.5.0", + "svg-tags": "^1.0.0", + "table": "^6.9.0", + "write-file-atomic": "^7.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-18.0.0.tgz", + "integrity": "sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.0.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-40.0.0.tgz", + "integrity": "sha512-EznGJxOUhtWck2r6dJpbgAdPATIzvpLdK9+i5qPd4Lx70es66TkBPljSg4wN3Qnc6c4h2n+WbUrUynQ3fanjHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "stylelint-config-recommended": "^18.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "stylelint": "^17.0.0" + } + }, + "node_modules/stylelint/node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/stylelint/node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stylelint/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/stylelint/node_modules/string-width": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", + "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stylelint/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -9021,6 +9719,49 @@ "node": ">=4" } }, + "node_modules/supports-hyperlinks": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-4.5.0.tgz", + "integrity": "sha512-ZW2OvfeCXrNTbLakPUzjQG922EeGCOteFSVoek5DKStTh898wf7zgtuFlzQN8HfZCxC3Eh02yJVrRW51hADf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^5.0.1", + "supports-color": "^10.2.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-5.0.1.tgz", + "integrity": "sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -9034,6 +9775,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9133,9 +9904,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.23.12", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.12.tgz", - "integrity": "sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q==", + "version": "4.23.13", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", + "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", "dev": true, "license": "MIT", "dependencies": { @@ -9277,16 +10048,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.67.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz", - "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.70.0.tgz", + "integrity": "sha512-P/W5cz70/cQAuKfY3xwQMWWTV7BvJ0mAQmi+9mBcsVPaBUpd6Ohpa+fECv9rBFrQcig86jAiNBFNWUqnTjr4pw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.67.0", - "@typescript-eslint/parser": "8.67.0", - "@typescript-eslint/typescript-estree": "8.67.0", - "@typescript-eslint/utils": "8.67.0" + "@typescript-eslint/eslint-plugin": "8.70.0", + "@typescript-eslint/parser": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/utils": "8.70.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -9330,12 +10101,25 @@ } }, "node_modules/undici-types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", - "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", "dev": true, "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universal-user-agent": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", @@ -9391,6 +10175,19 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/verkit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.4.0.tgz", + "integrity": "sha512-sXMwN6DMHeouPfCxkxWkKAmxphWKEenHYY5H1nIBzU3PmDsmJp6kBXJdshjVdpMZuWCmL9SH7KFRx29AylpP6g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/walk-up-path": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", @@ -9552,19 +10349,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/windows-release/node_modules/powershell-utils": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.2.0.tgz", - "integrity": "sha512-ZlsFlG7MtSFCoc5xreOvBAozCJ6Pf06opgJjh9ONEv418xpZSAzNjstD36C6+JwOnfSqOW/9uDkqKjezTdxZhw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -9576,9 +10360,9 @@ } }, "node_modules/workerpool": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", - "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-10.0.3.tgz", + "integrity": "sha512-6z2Iis68Wqth93/G/wJP9u+R3O+d2XTlgWChGCwuT1qLbBsOYueGRZuJ++v3mtDP5KjYdy+WzvWC+VWETSVXJA==", "dev": true, "license": "Apache-2.0" }, @@ -9600,61 +10384,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -9698,10 +10427,36 @@ "dev": true, "license": "ISC" }, + "node_modules/write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "dev": true, + "license": "ISC", + "dependencies": { + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/wsl-utils": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", - "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-1.0.0.tgz", + "integrity": "sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==", "dev": true, "license": "MIT", "dependencies": { @@ -9715,6 +10470,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/wsl-utils/node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9743,42 +10511,6 @@ "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", diff --git a/package.json b/package.json index 874904a9..01dd6aa6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "gitlab-component-helper", "displayName": "GitLab Component Helper", "description": "Provides intellisense for GitLab CI components", - "version": "0.16.12", + "version": "0.17.13", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", @@ -281,7 +281,12 @@ "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", "package": "npm run check-types && node esbuild.js --production", "check-types": "tsc --noEmit && tsc --noEmit --project tsconfig.tests.json", - "lint": "eslint --max-warnings 0", + "lint": "npm-run-all -c lint:eslint lint:stylelint", + "lint:eslint": "eslint --max-warnings 0", + "lint:stylelint": "stylelint \"src/webview/**/*.css\"", + "lint:ci": "npm-run-all -c lint:ci:*", + "lint:ci:eslint": "eslint --max-warnings 0 --format gha", + "lint:ci:stylelint": "stylelint \"src/webview/**/*.css\" --custom-formatter @csstools/stylelint-formatter-github", "pretest": "npm run compile", "prepare": "husky", "test": "mocha", @@ -306,39 +311,42 @@ "devDependencies": { "@commitlint/cli": "^21.2.2", "@commitlint/config-conventional": "^21.0.2", + "@csstools/stylelint-formatter-github": "^2.0.0", "@digitalroute/cz-conventional-changelog-for-jira": "^8.0.1", "@eslint/js": "^10.0.1", - "@octokit/core": "^7.0.7", + "@octokit/core": "^7.0.8", "@octokit/plugin-paginate-rest": "^15.0.0", - "@release-it/conventional-changelog": "^12.0.0", + "@release-it/conventional-changelog": "^12.0.2", "@types/glob": "^9.0.0", - "@types/js-yaml": "^4.0.9", "@types/mocha": "^10.0.10", - "@types/node": "^26.2.0", + "@types/node": "^26.6.1", "@types/vscode": "^1.120.0", - "@typescript-eslint/eslint-plugin": "^8.67.0", - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/eslint-plugin": "^8.70.0", + "@typescript-eslint/parser": "^8.70.0", "@vscode/test-electron": "^3.1.0", "commitizen": "^4.3.2", "conventional-changelog-conventionalcommits": "^9.3.1", "cz-conventional-changelog": "^3.3.0", - "cz-emoji-conventional": "^1.1.0", + "cz-emoji-conventional": "^1.3.0", "dateformat": "^5.0.3", - "dotenv": "^17.4.2", + "dotenv": "^18.0.0", "esbuild": "^0.28.2", - "eslint": "^10.8.1", - "globals": "^17.11.0", + "eslint": "^10.10.0", + "eslint-formatter-gha": "^2.0.1", + "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", - "js-yaml": "^5.3.0", + "js-yaml": "^5.4.2", "minimatch": "^10.2.6", - "mocha": "^11.8.0", + "mocha": "^12.0.2", "npm-run-all": "^4.1.5", - "release-it": "^21.0.2", + "release-it": "^21.1.0", "semver": "^7.8.5", - "tsx": "^4.23.12", + "stylelint": "^17.15.0", + "stylelint-config-standard": "^40.0.0", + "tsx": "^4.23.13", "typescript": "^6.0.3", - "typescript-eslint": "^8.67.0" + "typescript-eslint": "^8.70.0" }, "keywords": [], "author": "eFAILution", diff --git a/src/extension.ts b/src/extension.ts index 876bfcc7..7c011fe6 100755 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,8 +5,8 @@ import { CompletionProvider } from './providers/completionProvider'; import { ComponentDocumentLinkProvider } from './providers/documentLinkProvider'; import { ComponentBrowserProvider } from './providers/componentBrowserProvider'; import { detectIncludeComponent, Component } from './providers/componentDetector'; -import { stripTagPrefix } from './services/component/tagScoping'; import { getComponentCacheManager, ComponentCacheManager } from './services/cache/componentCacheManager'; +import { assetRoots } from './webview/webviewHtml'; import { Logger } from './utils/logger'; import { ValidationProvider } from './providers/validationProvider'; import type { CachedComponent } from './types/cache'; @@ -16,22 +16,6 @@ import type { HoverContext } from './providers/hoverContentBuilder'; /** Component payload passed to the `detachHover` command. Adds the hover-builder's location context. */ type DetachableComponent = Component & { _hoverContext?: HoverContext }; -/** - * Type-guard narrowing a `Component`-shaped value to one that also satisfies `CachedComponent`. - * - * @param component A `Component` (typically `activeComponent` in the detach-hover panel) that may - * or may not have been enriched with cache details. - * @returns `true` if all `CachedComponent` required fields are present and string-typed, - * narrowing `component` to `Component & CachedComponent` in the truthy branch. - * `false` if any field is missing. - */ -function isCachedComponentShape(component: Component): component is Component & CachedComponent { - return typeof component.source === 'string' - && typeof component.sourcePath === 'string' - && typeof component.gitlabInstance === 'string' - && typeof component.version === 'string' - && typeof component.url === 'string'; -} import { getPerformanceMonitor } from './utils/performanceMonitor'; import { isGitLabCIFile, invalidateFileGlobsCache } from './utils/gitlabCiFileMatcher'; @@ -335,7 +319,7 @@ export function activate(context: vscode.ExtensionContext) { { enableScripts: true, retainContextWhenHidden: true, - localResourceRoots: [] + localResourceRoots: assetRoots(context.extensionUri) } ); @@ -430,145 +414,7 @@ export function activate(context: vscode.ExtensionContext) { }); }, PANEL_FOCUS_DELAY_MS); - // Handle messages from the detached webview - panel.webview.onDidReceiveMessage(async (message) => { - switch (message.command) { - case 'insertComponent': - try { - // Ensure the original editor is active and focused - await vscode.window.showTextDocument(originalEditor.document, originalEditor.viewColumn); - - // Wait a brief moment for the editor to fully activate - await new Promise(resolve => setTimeout(resolve, PANEL_FOCUS_DELAY_MS)); - - // Verify we have the correct active editor - const currentEditor = vscode.window.activeTextEditor; - if (!currentEditor || currentEditor.document.uri.toString() !== originalEditor.document.uri.toString()) { - vscode.window.showErrorMessage('Could not activate the original editor'); - return; - } - - // Handle different insertion options - const { version, includeInputs, selectedInputs } = message; - - // Update component version if specified - if (version && version !== activeComponent.version) { - if (!activeComponent.sourcePath || !activeComponent.gitlabInstance) { - vscode.window.showErrorMessage(`Cannot fetch version: component is missing source path or GitLab instance.`); - return; - } - const updatedComponent = await cacheManager.fetchSpecificVersion( - activeComponent.name, - activeComponent.sourcePath, - activeComponent.gitlabInstance, - version - ); - if (updatedComponent) { - if (activeComponent._hoverContext) { - await componentBrowser.editExistingComponentFromDetached( - updatedComponent, - activeComponent._hoverContext.documentUri, - activeComponent._hoverContext.position, - includeInputs || false, - selectedInputs || [] - ); - } else { - await componentBrowser.insertComponentFromDetached( - updatedComponent, - includeInputs || false, - selectedInputs || [] - ); - } - } else { - vscode.window.showErrorMessage(`Failed to fetch version ${version} of component ${activeComponent.name}`); - } - } else { - if (activeComponent._hoverContext) { - await componentBrowser.editExistingComponentFromDetached( - activeComponent, - activeComponent._hoverContext.documentUri, - activeComponent._hoverContext.position, - includeInputs || false, - selectedInputs || [] - ); - } else { - await componentBrowser.insertComponentFromDetached( - activeComponent, - includeInputs || false, - selectedInputs || [] - ); - } - } - - // Close the panel after successful insertion/edit - panel.dispose(); - } catch (error) { - logger.error(`[Extension] Error inserting component from detached view: ${error}`, 'Extension'); - vscode.window.showErrorMessage(`Error inserting component: ${error}`); - } - break; - case 'fetchVersions': - try { - if (!isCachedComponentShape(activeComponent)) { - throw new Error('Component is missing required fields (source, sourcePath, gitlabInstance, version) for version lookup.'); - } - const versions = await cacheManager.fetchComponentVersions(activeComponent); - // For a monorepo source, map each full tag to its stripped {version} so the dropdown shows short - // labels while keeping the full tag as the option value (the inserted ref). - let versionLabels: Record | undefined; - if (activeComponent.tagPattern) { - versionLabels = {}; - for (const v of versions) { - versionLabels[v] = stripTagPrefix(v, activeComponent.name, activeComponent.tagPattern); - } - } - panel.webview.postMessage({ - command: 'versionsLoaded', - versions: versions, - versionLabels, - currentVersion: activeComponent.version - }); - } catch (error) { - panel.webview.postMessage({ - command: 'versionsError', - error: error instanceof Error ? error.message : String(error) - }); - } - break; - case 'versionChanged': - try { - const { selectedVersion } = message; - if (!activeComponent.sourcePath || !activeComponent.gitlabInstance) { - vscode.window.showErrorMessage(`Cannot change version: component is missing source path or GitLab instance.`); - return; - } - const updatedComponent = await cacheManager.fetchSpecificVersion( - activeComponent.name, - activeComponent.sourcePath, - activeComponent.gitlabInstance, - selectedVersion - ); - if (updatedComponent) { - activeComponent = updatedComponent; - panel.webview.postMessage({ - command: 'componentDetailsUpdated', - component: updatedComponent - }); - } else { - panel.webview.postMessage({ - command: 'versionChangeError', - error: `Failed to fetch details for version ${selectedVersion}` - }); - } - } catch (error) { - panel.webview.postMessage({ - command: 'versionChangeError', - error: error instanceof Error ? error.message : String(error) - }); - } - break; - } - }); + componentBrowser.registerDetailsPanelMessageHandler(panel, activeComponent, { detachedFrom: originalEditor }); }) ); diff --git a/src/parsers/parameterDefaultShape.ts b/src/parsers/parameterDefaultShape.ts new file mode 100644 index 00000000..7d151164 --- /dev/null +++ b/src/parsers/parameterDefaultShape.ts @@ -0,0 +1,31 @@ +/** + * Shared type-guard for "is this value usable as an input's `default:`?". + * + * `vscode`-free and pure so the Mocha unit suite (and `specParser`, which must load under plain Node) can import it + * directly. Both spec parsers narrow the same union, so they share one definition rather than a copy each. + */ + +import type { ParameterDefault } from '../types/git-component'; + +/** + * Narrow an unknown value to {@link ParameterDefault}, the union accepted by an input's `default:` field. + * + * Guards the boundary where a parsed spec becomes a typed parameter: YAML and the catalog API both hand back + * `unknown`, and anything outside the union (a mapping, a nested array) is rejected rather than carried forward as + * a default no consumer can render. + * + * @param value - A value of unknown shape, typically straight from a YAML parse or an API response. + * @returns `true` when `value` is a string, number, boolean, `null`, or an array of those primitives. + */ +export function isParameterDefault(value: unknown): value is ParameterDefault { + if (value === null) return true; + const t = typeof value; + if (t === 'string' || t === 'number' || t === 'boolean') return true; + if (Array.isArray(value)) { + return value.every(v => { + const vt = typeof v; + return vt === 'string' || vt === 'number' || vt === 'boolean'; + }); + } + return false; +} diff --git a/src/parsers/specParser.ts b/src/parsers/specParser.ts index 2386a19a..acf6b000 100644 --- a/src/parsers/specParser.ts +++ b/src/parsers/specParser.ts @@ -3,17 +3,97 @@ import { Logger } from '../utils/logger'; // Import direct from errors/types (not the barrel) so this module can load from plain Node — the barrel re-exports // from errors/handler.ts which imports `vscode` at module load. Required for the Mocha unit suite. import { ParseError } from '../errors/types'; +import type { ParameterDefault } from '../types/git-component'; +import { isParameterDefault } from './parameterDefaultShape'; +import * as yaml from 'js-yaml'; +import { isYamlNode, GITLAB_CI_SCHEMA } from '../utils/yamlParser'; const logger = Logger.getInstance(); +/** + * Resolve one already-trimmed scalar to the value YAML reads it as. + * + * @param trimmed - A single scalar's text, surrounding whitespace already removed. + * @returns The parsed value, or the text with surrounding quotes stripped when it isn't a parseable YAML scalar. + */ +function parseScalar(trimmed: string): ParameterDefault { + try { + // `yaml.load` directly rather than `parseYaml`: these probes are one-off strings, so memoising them only evicts + // the document parses sharing that cache. + const parsed = yaml.load(`probe: ${trimmed}`, { schema: GITLAB_CI_SCHEMA }); + if (isYamlNode(parsed) && isParameterDefault(parsed.probe)) { + return parsed.probe; + } + } catch { + // Not valid YAML on its own (an unquoted `*`, a stray `{`, …) — fall back to the literal text. + } + return trimmed.replace(/^["']|["']$/g, '').trim(); +} + +/** + * Parse the text after `default:` into the value the input's type says it is. + * + * This parser reads the spec line-by-line rather than as a document, so a `default:` value arrives as raw text. Left + * as text, `default: false` on a `type: boolean` input becomes the string `"false"`, which downstream renders back + * as a quoted `"false"` — a string where GitLab expects a boolean. + * + * A `string` input's default is text by declaration, so it is never sent through YAML: `default: 1.0` stays `"1.0"` + * and `0755` keeps its leading zero. That covers an omitted `type:` as well — GitLab resolves an untyped input as + * `StringInput` (its `matches?` accepts a spec with no `:type` key) and coerces the default with `to_s`, so an + * untyped default is a string no matter what it looks like. + * + * @param rawValue - The text following `default:` on the line, e.g. `false`, `"0"`, `[a, b]`. + * @param inputType - The input's resolved `type:`; `'string'` when the spec omits it. + * @returns The parsed value, or the trimmed raw text when it doesn't parse as a YAML scalar. + */ +function parseDefaultValue(rawValue: string, inputType: string): ParameterDefault { + const trimmed = rawValue.trim(); + // An empty `default:` is an explicit empty string, not an absent default — absent inputs are marked required. + if (trimmed.length === 0) { + return ''; + } + if (inputType === 'string') { + return trimmed.replace(/^["']|["']$/g, '').trim(); + } + return parseScalar(trimmed); +} + +/** + * Parse one `options:` entry into the value YAML says it is. + * + * Kept in step with {@link parseDefaultValue}: an entry and a default that read the same in the spec must produce + * the same value, or a `default: false` never matches the `false` in `options: [true, false]` and fails to + * pre-select. A `string` input — declared or by omission — keeps entries literal for the same reason defaults do. + * + * @param entry - One option's raw text, quotes and surrounding whitespace included. + * @param inputType - The input's resolved `type:`; `'string'` when the spec omits it. + * @returns The entry as a string, number, or boolean. + */ +function parseOptionEntry(entry: string, inputType: string): string | number | boolean { + const trimmed = entry.trim(); + if (inputType === 'string') { + return trimmed.replace(/^["']|["']$/g, '').trim(); + } + const parsed = parseScalar(trimmed); + // `options:` entries are scalars; a null or nested-array entry isn't meaningful, so keep those as their text. + return parsed === null || Array.isArray(parsed) ? trimmed.replace(/^["']|["']$/g, '').trim() : parsed; +} + export interface ComponentVariable { name: string; description: string; required: boolean; type: string; - default?: string; - /** Allowed values from the input's `options:` list, in declaration order; absent when no `options:` is given. */ - options?: string[]; + /** + * The input's `default:`, as the value YAML says it is — `default: false` is the boolean `false`, not `"false"`. + * Consumers render it back to YAML by type, so a string default here must be a genuine string. + */ + default?: ParameterDefault; + /** + * Allowed values from the input's `options:` list, in declaration order; absent when no `options:` is given. + * Entries carry their YAML types, so they compare equal to a `default` that names one of them. + */ + options?: Array; } export interface ParsedSpec { @@ -26,11 +106,12 @@ export interface ParsedSpec { * Parse the inline form of an `options:` value (`options: [a, "b", c]`). * * Returns an empty array for the expanded form (`options:` with the values on following `- item` lines), which the - * caller then fills in as it reads those lines. Surrounding brackets and per-entry quotes are stripped; blank entries - * (e.g. a trailing comma) are dropped. + * caller then fills in as it reads those lines. Surrounding brackets are stripped and blank entries (e.g. a trailing + * comma) are dropped, but each entry stays raw text — {@link parseOptionEntry} types it once the input's `type:` is + * known, which may be declared after `options:`. * * @param rawValue - The text after `options:` on the same line, e.g. `[a, "b", c]` (or empty for the expanded form). - * @returns The parsed option values, or an empty array when the value isn't an inline `[...]` list. + * @returns The raw option entries, or an empty array when the value isn't an inline `[...]` list. */ function parseInlineOptions(rawValue: string): string[] { if (!rawValue.startsWith('[')) { @@ -39,7 +120,7 @@ function parseInlineOptions(rawValue: string): string[] { return rawValue .replace(/^\[|\]$/g, '') .split(',') - .map(entry => entry.trim().replace(/^["']|["']$/g, '').trim()) + .map(entry => entry.trim()) .filter(entry => entry.length > 0); } @@ -146,6 +227,35 @@ export class GitLabSpecParser { .filter(line => line.trim() && !line.trim().startsWith('#')); let currentInput: ComponentVariable | null = null; + // Indentation of the first input name seen, which every sibling input shares. Input names and their own keys are + // told apart by depth rather than by name: an input may legitimately be called `type` or `default`, and a spec + // indented `inputs:` at column 0 puts both at four spaces. + let inputIndent: number | null = null; + // The `default:` text for `currentInput`, held until the input ends so the declared `type:` can steer the parse. + let rawDefault: string | null = null; + // Raw `options:` entries for `currentInput`, typed by `finalizeInput` for the same reason as `rawDefault`. + let rawOptions: string[] | null = null; + + /** + * Resolve the pending `default:` and `options:` against the declared type and mark a defaultless input + * required. Deferred to here because `type:` may be declared after either of them. + */ + const finalizeInput = (input: ComponentVariable): ComponentVariable => { + // An omitted `type:` is `string` to GitLab, and `input.type` already holds that fallback. + if (rawDefault !== null) { + input.default = parseDefaultValue(rawDefault, input.type); + } else { + // GitLab CI/CD component behavior: an input with no default is required. + input.required = true; + } + if (rawOptions !== null) { + // Typed against the input's type so an entry matches a `default` naming the same value. + input.options = rawOptions.map(entry => parseOptionEntry(entry, input.type)); + } + rawDefault = null; + rawOptions = null; + return input; + }; for (const line of inputLines) { const trimmedLine = line.trim(); @@ -157,19 +267,24 @@ export class GitLabSpecParser { break; } + const indent = line.length - line.trimStart().length; + // New input parameter (indented under inputs) - handle both 2-space and 4-space indentation. // Match lines like " name:" where the input name ends with ":" and has only whitespace after. // The name class includes `-`: GitLab input names are commonly hyphenated (e.g. `job-name`). Without // it, a hyphenated key isn't recognised as a new input, so its `description:`/`default:` lines bleed // onto the previous (non-hyphenated) input and mis-map every field after it (issue #211). - if (line.match(/^\s{2,4}[a-zA-Z_][a-zA-Z0-9_-]*:\s*$/)) { + // + // Siblings must share the first input's indentation. A valueless `default:` under a spec indented `inputs:` + // at column 0 sits at four spaces and matches the shape of an input name, so without the depth check it + // opens a phantom input named `default` and swallows the real input's value. Depth rather than a list of + // reserved key names, because `type`, `default` and `options` are all legal input names. + const looksLikeInputName = /^\s{2,4}[a-zA-Z_][a-zA-Z0-9_-]*:\s*$/.test(line); + if (looksLikeInputName && (inputIndent === null || indent === inputIndent)) { + inputIndent = indent; // If we have a current input, finalize it before starting a new one if (currentInput) { - // Mark as required if no default was specified (GitLab CI/CD component behavior) - if (currentInput.default === undefined) { - currentInput.required = true; - } - extractedVariables.push(currentInput); + extractedVariables.push(finalizeInput(currentInput)); } const inputName = trimmedLine.split(':')[0]; currentInput = { @@ -181,32 +296,30 @@ export class GitLabSpecParser { }; logger.debug(`${logPrefix} Found input parameter: ${inputName}`, 'SpecParser'); } - // Property of current input (more deeply indented) - handle 4+ spaces of indentation - else if (currentInput && line.match(/^\s{4,}/)) { + // Property of the current input: anything indented deeper than the input names themselves. + else if (currentInput && inputIndent !== null && indent > inputIndent) { if (trimmedLine.startsWith('description:')) { currentInput.description = trimmedLine.substring(12).replace(/^["']|["']$/g, '').trim(); } else if (trimmedLine.startsWith('default:')) { - currentInput.default = trimmedLine.substring(8).replace(/^["']|["']$/g, '').trim(); + // Kept as text until the input is complete: `type:` may follow `default:`, and the declared type decides + // whether the value is parsed as YAML or kept literal. Resolved by `finalizeInput`. + rawDefault = trimmedLine.substring(8); } else if (trimmedLine.startsWith('type:')) { currentInput.type = trimmedLine.substring(5).replace(/^["']|["']$/g, '').trim(); } else if (trimmedLine.startsWith('options:')) { // Open the options list. An inline form (`options: [a, b]`) carries its values on the same line; // the expanded form leaves them for the `- item` lines below. - currentInput.options = parseInlineOptions(trimmedLine.substring(8).trim()); - } else if (trimmedLine.startsWith('- ') && currentInput.options) { + rawOptions = parseInlineOptions(trimmedLine.substring(8).trim()); + } else if (trimmedLine.startsWith('- ') && rawOptions) { // Expanded list item belonging to the open `options:` block. - currentInput.options.push(trimmedLine.substring(2).replace(/^["']|["']$/g, '').trim()); + rawOptions.push(trimmedLine.substring(2).trim()); } } } // Add the last input if (currentInput) { - // Mark as required if no default was specified (GitLab CI/CD component behavior) - if (currentInput.default === undefined) { - currentInput.required = true; - } - extractedVariables.push(currentInput); + extractedVariables.push(finalizeInput(currentInput)); } logger.debug(`${logPrefix} Extracted ${extractedVariables.length} input parameters from spec`, 'SpecParser'); @@ -274,7 +387,8 @@ export class GitLabSpecParser { description: `Parameter: ${varName}`, required: false, type: 'string', - default: defaultValue || undefined + // The legacy format declares no per-variable type, so values stay the text they appear as. + default: defaultValue ? parseDefaultValue(defaultValue, 'string') : undefined }; }); diff --git a/src/providers/completionInputContext.ts b/src/providers/completionInputContext.ts index f1e089de..9ff7b962 100644 --- a/src/providers/completionInputContext.ts +++ b/src/providers/completionInputContext.ts @@ -7,7 +7,7 @@ import { parseYaml, parseYamlDocuments, findDocumentWith, isYamlNode, type YamlNode } from '../utils/yamlParser'; import { findIncludeLine } from '../utils/includeMatcher'; -import type { ComponentParameter } from '../types/git-component'; +import type { ComponentParameter, ParameterDefault } from '../types/git-component'; /** * The completion slot a YAML cursor position resolves to. @@ -324,6 +324,22 @@ export function renderOptionValue(value: string | number | boolean): string { return typeof value === 'string' ? quoteYamlIfUnsafe(value) : String(value); } +/** + * Render an input's `default` as the YAML text to insert for it. + * + * Arrays become flow sequences (`[a, b]`); strings are bare or double-quoted by round-trip safety; everything else + * (booleans, numbers, `null`) is its bare scalar form, so a `false` default inserts as `false` and not `"false"`. + * + * @param value - The declared default for the input. + * @returns The YAML text for that value. + */ +export function renderDefaultValue(value: ParameterDefault): string { + if (Array.isArray(value)) { + return `[${value.map((v) => (typeof v === 'string' ? quoteYamlIfUnsafe(v, true) : String(v))).join(', ')}]`; + } + return typeof value === 'string' ? quoteYamlIfUnsafe(value) : String(value); +} + /** * Narrow a parameter default to the scalar shapes an `options:` entry can take (string/number/boolean), excluding * the `null` and array forms a default may also hold. @@ -335,6 +351,28 @@ function isOptionScalar(value: unknown): value is string | number | boolean { return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'; } +/** + * The values an input is allowed to take, if that set is known and finite. + * + * An explicit `options:` list is used as declared. A `boolean` input has no `options:` in the spec but is still a + * closed two-value enum, so it yields `true, false` — conventional reading order, which is what a reader scanning + * the dropdown expects. A declared default is floated to the front by the caller, so it still pre-selects. + * + * Shared by both completion slots so the input-name snippet and the value-slot dropdown always agree. + * + * @param param - The input being completed. + * @returns The allowed values, or `undefined` when the input accepts free-form text. + */ +export function allowedValuesFor(param: ComponentParameter): Array | undefined { + if (param.options && param.options.length > 0) { + return param.options; + } + if (param.type === 'boolean') { + return [true, false]; + } + return undefined; +} + /** * Build the value portion of the snippet inserted after `param.name: ` when an input is accepted from completion. * @@ -343,20 +381,24 @@ function isOptionScalar(value: unknown): value is string | number | boolean { * Values are inserted bare where a bare YAML scalar round-trips to the same string — GitLab CI parses a bare scalar * by the input's declared type, so a string input is a bare scalar, not a quoted one. Strings that bare YAML would * reinterpret (indicators, embedded `: `/` #`, type-like tokens, etc.) are double-quoted; see {@link quoteYamlIfUnsafe}. - * Precedence: an `options:` enum becomes a `${1|...|}` choice (with the default, if any, pre-selected first) so the - * allowed values stay one keystroke away; otherwise an explicit `default` is rendered as the YAML it represents; - * otherwise a type-appropriate placeholder. + * Precedence: an `options:` enum — or a `boolean` input, which is a closed two-value enum — becomes a `${1|...|}` + * choice (with the default, if any, pre-selected first) so the allowed values stay one keystroke away; otherwise an + * explicit `default` is rendered as the YAML it represents; otherwise a type-appropriate placeholder. * * @param param - The input parameter spec (type, optional default, optional `options` enum, requiredness). * @returns The snippet body to insert after `param.name: ` — a `${1|...|}` choice, a rendered value, or a `${1:...}` placeholder. */ export function buildInputInsertValue(param: ComponentParameter): string { - if (param.options && param.options.length > 0) { - // Offer the allowed values (`options:`) as a choice. Entries stay unquoted so a number/boolean option isn't + // Includes a `boolean` input's implicit true/false. Falling through to the default-rendering branch below would + // pre-fill the default with no alternatives shown. + const options = allowedValuesFor(param); + + if (options && options.length > 0) { + // Offer the allowed values as a choice. Entries stay unquoted so a number/boolean option isn't // turned into a string; string entries are quoted only when bare YAML would reinterpret them. When the input // also has a default, float the matching option to the front — VS Code pre-selects the first choice entry, so // accepting the input keeps the default while leaving the alternatives one arrow-key away. - const rendered = param.options.map(renderOptionValue); + const rendered = options.map(renderOptionValue); // Only a scalar default can name one of the options; a null or array default has no matching entry. const defaultRendered = isOptionScalar(param.default) ? renderOptionValue(param.default) : undefined; const ordered = @@ -367,17 +409,11 @@ export function buildInputInsertValue(param: ComponentParameter): string { } if (param.default !== undefined) { - // Render the default as the YAML the input expects: arrays as flow sequences (`[a, b]`), - // strings bare-or-quoted by round-trip safety, everything else as its bare scalar form. - if (Array.isArray(param.default)) { - return `[${param.default.map((v) => (typeof v === 'string' ? quoteYamlIfUnsafe(v, true) : String(v))).join(', ')}]`; - } - return typeof param.default === 'string' ? quoteYamlIfUnsafe(param.default) : String(param.default); + return renderDefaultValue(param.default); } switch (param.type) { - case 'boolean': - return param.required ? '${1|true,false|}' : '${1|false,true|}'; + // `boolean` is handled above as a two-value choice, with or without a default. case 'number': return '${1:0}'; case 'integer': diff --git a/src/providers/completionProvider.ts b/src/providers/completionProvider.ts index 084d3f1a..6fe7953c 100755 --- a/src/providers/completionProvider.ts +++ b/src/providers/completionProvider.ts @@ -5,7 +5,7 @@ import { getVariableCompletions, containsGitLabVariables, expandComponentUrl } f import { Logger } from '../utils/logger'; import { isGitLabCIFile } from '../utils/gitlabCiFileMatcher'; import { resolveLocalComponent } from './localComponentResolver'; -import { findCompletionInputContextAtLine, buildInputInsertValue, renderOptionValue } from './completionInputContext'; +import { findCompletionInputContextAtLine, buildInputInsertValue, renderOptionValue, allowedValuesFor } from './completionInputContext'; import type { ComponentParameter } from '../types/git-component'; import type { CachedComponent } from '../types/cache'; @@ -389,16 +389,21 @@ export class CompletionProvider implements vscode.CompletionItemProvider { // it also declares a default — the default is just the pre-filled choice, not a reason to hide the others. if (context.slot === 'value') { const param = component.parameters.find((p: ComponentParameter) => p.name === context.inputName); - if (!param?.options?.length) { + // A `boolean` input is a closed two-value enum, so offer `true`/`false` even though it declares no `options:`. + const values = param ? allowedValuesFor(param) : undefined; + if (!values?.length) { this.logger.debug(`[CompletionProvider] Value slot for ${context.inputName} has no options to offer`, 'CompletionProvider'); return null; } - return param.options.map((value, index) => { + return values.map((value, index) => { const rendered = renderOptionValue(value); const item = new vscode.CompletionItem(String(value), vscode.CompletionItemKind.EnumMember); item.insertText = rendered; - item.detail = `${param.type || 'string'} option`; - // Preserve the declared order of `options:` in the dropdown. + // Flag the declared default rather than reordering around it — the list stays in a stable, scannable + // order (`true` before `false`, or the spec's own `options:` order) whatever the default happens to be. + const isDefault = param?.default !== undefined && param.default === value; + item.detail = `${param?.type || 'string'} option${isDefault ? ' (default)' : ''}`; + // Preserve the declared order of the allowed values in the dropdown. item.sortText = String(index).padStart(4, '0'); return item; }); diff --git a/src/providers/componentBrowserProvider.ts b/src/providers/componentBrowserProvider.ts index 4d93a058..4c2e7821 100644 --- a/src/providers/componentBrowserProvider.ts +++ b/src/providers/componentBrowserProvider.ts @@ -3,18 +3,20 @@ import { getComponentService } from '../services/component'; import { ComponentCacheManager } from '../services/cache/componentCacheManager'; import { GitLabCatalogComponent, GitLabCatalogVariable } from '../types/gitlab-catalog'; import type { ComponentParameter, Component } from './componentDetector'; -import type { CachedComponent } from '../types/cache'; +import { isVersionLookupShape } from '../services/component/versionLookupShape'; import type { SourceGroup, ComponentGroup, ComponentVersion } from './componentBrowserTypes'; import type { HoverContext } from './hoverContentBuilder'; import { containsGitLabVariables } from '../utils/gitlabVariables'; import { Logger } from '../utils/logger'; import { templateFileUrlForResolved } from '../utils/templateFileUrl'; import { escapeHtml, renderInlineMarkdown } from '../webview/inlineMarkdown'; +import { clientRenderInlineMarkdownSource } from '../webview/clientInlineMarkdown'; import { serializeForScript } from '../webview/scriptData'; import { generateComponentText } from './componentBrowserGenerate'; import { findComponentLineRange, parseExistingComponentText } from './componentBrowserEdit'; import { transformCachedComponentsToGroups } from './componentBrowserTransform'; -import { compileTagTemplate, stripTagPrefix } from '../services/component/tagScoping'; +import { buildVersionLabels, compileTagTemplate, stripTagPrefix } from '../services/component/tagScoping'; +import { assetRoots, assetUri, createNonce, cspMetaTag } from '../webview/webviewHtml'; /** * Component shape carried through the detach-hover webview's "Open in Detailed View" round trip. @@ -24,18 +26,21 @@ import { compileTagTemplate, stripTagPrefix } from '../services/component/tagSco */ type DetachableComponent = Component & { _hoverContext?: HoverContext }; -/** - * Type-guard narrowing a `Component`-shaped value to one that also satisfies `CachedComponent`. - * `Component` carries `source`/`sourcePath`/`gitlabInstance`/`version`/`url` as optional; cache - * methods like `fetchComponentVersions` require them. The guard checks all five before the call so - * we don't pass a half-populated `Component` into a function expecting the full cache shape. - */ -function isCachedComponentShape(component: Component): component is Component & CachedComponent { - return typeof component.source === 'string' - && typeof component.sourcePath === 'string' - && typeof component.gitlabInstance === 'string' - && typeof component.version === 'string' - && typeof component.url === 'string'; +/** Per-entry-point behaviour for the shared details-panel message handler. */ +interface DetailsPanelOptions { + /** + * Set by the detached (hover) entry point to the editor the panel was opened from. Two effects, both of which + * exist because that entry point constructs its own provider rather than going through `show()`: + * + * 1. The editor is adopted as this provider's insertion target at registration, since nothing else has populated + * it and `insertComponent` refuses to insert without one. + * 2. The panel is disposed once an insert completes — it is a one-shot view, where the Component Browser's own + * details panel stays open. + * + * Refocusing the target editor is not one of them: `insertComponent` and `editExistingComponentFromDetached` each + * focus and verify their own document, on both entry points. + */ + detachedFrom?: vscode.TextEditor; } /** @@ -87,14 +92,12 @@ export class ComponentBrowserProvider { { enableScripts: true, retainContextWhenHidden: true, - localResourceRoots: [ - vscode.Uri.joinPath(this.context.extensionUri, 'media') - ] + localResourceRoots: assetRoots(this.context.extensionUri) } ); // Set initial HTML content with loading message - this.panel.webview.html = this.getLoadingHtml(); + this.panel.webview.html = this.getLoadingHtml(this.panel.webview); // Handle panel disposal this.panel.onDidDispose(() => { @@ -165,7 +168,7 @@ export class ComponentBrowserProvider { try { // Show loading state - this.panel.webview.html = this.getLoadingHtml(); + this.panel.webview.html = this.getLoadingHtml(this.panel.webview); this.logger.debug(`[ComponentBrowser] Loading components, forceRefresh: ${forceRefresh}`, 'ComponentBrowser'); @@ -480,11 +483,6 @@ export class ComponentBrowserProvider { vscode.window.showInformationMessage(message); } - // Public method to insert component from detached view (called from extension.ts) - public async insertComponentFromDetached(component: Component, includeInputs: boolean = false, selectedInputs?: string[]) { - return this.insertComponent(component, includeInputs, selectedInputs); - } - public async showComponentDetails(component: DetachableComponent) { // Create a new webview panel for component details const detailsPanel = vscode.window.createWebviewPanel( @@ -492,7 +490,8 @@ export class ComponentBrowserProvider { `Component: ${component.name}`, vscode.ViewColumn.Beside, { - enableScripts: true + enableScripts: true, + localResourceRoots: assetRoots(this.context.extensionUri) } ); @@ -503,91 +502,125 @@ export class ComponentBrowserProvider { // Show component details detailsPanel.webview.html = this.getComponentDetailsHtml({ ...component, ...enriched }); - // Handle messages from the details panel - detailsPanel.webview.onDidReceiveMessage( - async message => { - if (message.command === 'insertComponent') { - // Handle different insertion options - const { version, includeInputs, selectedInputs } = message; + this.registerDetailsPanelMessageHandler(detailsPanel, { ...component, ...enriched }); + } - // Update component version if specified - if (version && version !== component.version) { - if (!component.sourcePath || !component.gitlabInstance) { - vscode.window.showErrorMessage('Cannot fetch version: component is missing source path or GitLab instance.'); - return; - } - const updatedComponent = await this.cacheManager.fetchSpecificVersion( - component.name, - component.sourcePath, - component.gitlabInstance, - version - ); - if (updatedComponent) { - if (component._hoverContext) { - await this.editExistingComponentFromDetached( - updatedComponent, - component._hoverContext.documentUri, - component._hoverContext.position, - includeInputs || false, - selectedInputs || [] - ); - } else { - await this.insertComponent(updatedComponent, includeInputs, selectedInputs); + /** + * Wires the details panel's message handling. Both entry points — the Component Browser's Details button and the + * hover's "Open in Detailed View" — render the same HTML and speak the same protocol, so they share this handler; + * `options.detachedFrom` carries the only behavioural difference between them. + * + * @param panel The details webview panel to attach to. + * @param component The component being shown. Held mutably: a `versionChanged` round trip replaces it so later + * `fetchVersions`/`insertComponent` messages act on the version the user is actually looking at. + * @param options Per-entry-point behaviour; see {@link DetailsPanelOptions}. + */ + public registerDetailsPanelMessageHandler( + panel: vscode.WebviewPanel, + component: DetachableComponent, + options: DetailsPanelOptions = {} + ): void { + let active = component; + + if (options.detachedFrom) { + this.adoptOriginalEditor(options.detachedFrom); + } + + panel.webview.onDidReceiveMessage(async message => { + switch (message.command) { + case 'insertComponent': { + const { version, includeInputs, selectedInputs } = message; + try { + let target = active; + if (version && version !== active.version) { + if (!active.sourcePath || !active.gitlabInstance) { + vscode.window.showErrorMessage('Cannot fetch version: component is missing source path or GitLab instance.'); + return; } - } else { - vscode.window.showErrorMessage(`Failed to fetch version ${version} of component ${component.name}`); + const updatedComponent = await this.cacheManager.fetchSpecificVersion( + active.name, + active.sourcePath, + active.gitlabInstance, + version + ); + if (!updatedComponent) { + vscode.window.showErrorMessage(`Failed to fetch version ${version} of component ${active.name}`); + return; + } + target = updatedComponent; } - } else { - if (component._hoverContext) { + + if (active._hoverContext) { await this.editExistingComponentFromDetached( - component, - component._hoverContext.documentUri, - component._hoverContext.position, + target, + active._hoverContext.documentUri, + active._hoverContext.position, includeInputs || false, selectedInputs || [] ); } else { - await this.insertComponent(component, includeInputs, selectedInputs); + await this.insertComponent(target, includeInputs || false, selectedInputs || []); } + + // The detached panel is a one-shot view opened from a hover, so it closes once it has done its job. + if (options.detachedFrom) { + panel.dispose(); + } + } catch (error) { + this.logger.error(`[ComponentBrowser] Error inserting component from details panel: ${error}`, 'ComponentBrowser'); + vscode.window.showErrorMessage(`Error inserting component: ${error}`); } - } else if (message.command === 'fetchVersions') { - // Fetch available versions for the component + break; + } + + case 'fetchVersions': { try { - if (!isCachedComponentShape(component)) { - throw new Error('Component is missing required fields (source, sourcePath, gitlabInstance, version) for version lookup.'); + if (!isVersionLookupShape(active)) { + throw new Error(`Cannot look up versions for ${active.name}: missing source path or GitLab instance.`); } - const versions = await this.cacheManager.fetchComponentVersions(component); - detailsPanel.webview.postMessage({ + // Bind the narrowed value: `active` is reassignable, so TS widens it back across the await below. + const lookupTarget = active; + const versions = await this.cacheManager.fetchComponentVersions(lookupTarget); + // Same monorepo labelling as the detached panel: the webview can't reach the template matcher, so the + // full tag → stripped {version} map is built here. Without it a refresh reverts the dropdown to full tags. + panel.webview.postMessage({ command: 'versionsLoaded', - versions: versions, - currentVersion: component.version + versions, + versionLabels: buildVersionLabels(versions, lookupTarget.name, lookupTarget.tagPattern), + currentVersion: lookupTarget.version }); } catch (error) { - detailsPanel.webview.postMessage({ + const reason = error instanceof Error ? error.message : String(error); + this.logger.error(`[ComponentBrowser] Error fetching versions: ${reason}`, 'ComponentBrowser'); + panel.webview.postMessage({ command: 'versionsError', - error: error instanceof Error ? error.message : String(error) + error: reason }); } - } else if (message.command === 'versionChanged') { - // Fetch details for the selected version and update the display + break; + } + + case 'versionChanged': { const { selectedVersion } = message; try { this.logger.debug(`[ComponentBrowser] Version changed to ${selectedVersion}, fetching details...`, 'ComponentBrowser'); - if (!component.sourcePath || !component.gitlabInstance) { + if (!active.sourcePath || !active.gitlabInstance) { vscode.window.showErrorMessage('Cannot change version: component is missing source path or GitLab instance.'); return; } const updatedComponent = await this.cacheManager.fetchSpecificVersion( - component.name, - component.sourcePath, - component.gitlabInstance, + active.name, + active.sourcePath, + active.gitlabInstance, selectedVersion ); if (updatedComponent) { + // Carry the hover context forward so a later insert still edits in place rather than inserting anew. + active = { ...updatedComponent, _hoverContext: active._hoverContext }; // Send the updated component details to the webview, with the template-file URL precomputed // server-side so the webview never has to do its own URL routing. - detailsPanel.webview.postMessage({ + panel.webview.postMessage({ command: 'componentDetailsUpdated', component: { ...updatedComponent, @@ -595,56 +628,44 @@ export class ComponentBrowserProvider { } }); } else { - detailsPanel.webview.postMessage({ + panel.webview.postMessage({ command: 'versionChangeError', error: `Failed to fetch details for version ${selectedVersion}` }); } } catch (error) { this.logger.error(`[ComponentBrowser] Error fetching version details: ${error}`, 'ComponentBrowser'); - detailsPanel.webview.postMessage({ + panel.webview.postMessage({ command: 'versionChangeError', error: error instanceof Error ? error.message : String(error) }); } + break; } } - ); + }); } - private getLoadingHtml(): string { + /** + * Adopts `editor` as the insertion target for a panel opened outside `show()`. The detached (hover) panel builds its + * own provider, so nothing has populated `originalEditor` and `insertComponent` would otherwise refuse to insert. + */ + private adoptOriginalEditor(editor: vscode.TextEditor): void { + this.originalEditor = editor; + } + + private getLoadingHtml(webview: vscode.Webview): string { + const nonce = createNonce(); + const styleUri = assetUri(webview, this.context.extensionUri, 'styles/loading.css'); return ` + ${cspMetaTag(webview.cspSource, nonce)} + GitLab CI/CD Components -
@@ -1633,6 +1654,9 @@ export class ComponentBrowserProvider { font-size: 0.9em; color: var(--vscode-disabledForeground); } + .version-loading.version-error { + color: var(--vscode-errorForeground); + } .parameters { border: 1px solid var(--vscode-panel-border); border-radius: 5px; @@ -1913,7 +1937,9 @@ export class ComponentBrowserProvider { console.log('Version changed to:', selectedVersion); - // Show loading state + // Show loading state, clearing any error left by a previous attempt. + loading.textContent = 'Loading version details...'; + loading.classList.remove('version-error'); loading.style.display = 'inline'; // Send message to fetch details for this version @@ -1927,6 +1953,9 @@ export class ComponentBrowserProvider { const loading = document.getElementById('versionLoading'); const select = document.getElementById('versionSelect'); + // Clear any error left by a previous attempt before starting a new one. + loading.textContent = 'Loading version details...'; + loading.classList.remove('version-error'); loading.style.display = 'inline'; select.disabled = true; @@ -2103,19 +2132,29 @@ export class ComponentBrowserProvider { case 'versionsLoaded': updateVersionDropdown(message.versions, message.currentVersion, message.versionLabels); break; - case 'versionsError': - document.getElementById('versionLoading').style.display = 'none'; + case 'versionsError': { + // Reuse the loading slot to report the failure: a refresh that silently does nothing reads as an + // inert button, so the user is told rather than left guessing. + const versionStatus = document.getElementById('versionLoading'); + versionStatus.textContent = 'Could not load versions: ' + (message.error || 'unknown error'); + versionStatus.classList.add('version-error'); + versionStatus.style.display = 'inline'; document.getElementById('versionSelect').disabled = false; - // Could show error message here break; + } case 'componentDetailsUpdated': updateComponentDetails(message.component); break; - case 'versionChangeError': - document.getElementById('versionLoading').style.display = 'none'; - // Could show error message here + case 'versionChangeError': { + // Same treatment as versionsError: a failed version switch used to hide the spinner and say nothing, + // which reads as the dropdown simply not working. + const changeStatus = document.getElementById('versionLoading'); + changeStatus.textContent = 'Could not load that version: ' + (message.error || 'unknown error'); + changeStatus.classList.add('version-error'); + changeStatus.style.display = 'inline'; console.error('Version change error:', message.error); break; + } } }); @@ -2140,6 +2179,7 @@ export class ComponentBrowserProvider { }); loading.style.display = 'none'; + loading.classList.remove('version-error'); select.disabled = false; currentVersions = versions; versionsLoaded = true; @@ -2194,28 +2234,8 @@ export class ComponentBrowserProvider { return renderInlineMarkdown(value); } - /** - * Source for the client-side twin of {@link renderInlineMarkdown}, injected into every webview ` & 'q'`), + '<script>alert("x")</script> & 'q'', + ); + }); + + test('matches the server renderer across representative descriptions', () => { + const render = loadClientRenderer(); + const samples = [ + 'CI Job template to deploy a service to an ECS cluster', + 'A [GitLab CI/CD component](https://example.com/c) that lints Dockerfiles using [hadolint](https://example.com/h)', + 'Installs the `yu-ci-tools` binary CLI', + '**Bold** lead-in, *emphasis*, and a `code` span', + 'Ampersands & and "quotes"', + '', + ]; + + for (const sample of samples) { + assert.equal(render(sample), renderInlineMarkdown(sample), `mismatch for: ${sample}`); + } + }); +}); diff --git a/tests/unit/completionInputContext.test.ts b/tests/unit/completionInputContext.test.ts index e6b3d4f8..313d1b5a 100644 --- a/tests/unit/completionInputContext.test.ts +++ b/tests/unit/completionInputContext.test.ts @@ -13,6 +13,7 @@ import * as assert from 'node:assert/strict'; import { findCompletionInputContextAtLine, buildInputInsertValue, + allowedValuesFor, } from '../../src/providers/completionInputContext'; import type { ComponentParameter } from '../../src/types/git-component'; @@ -383,6 +384,25 @@ include: existingInputNames: [], }); }); + + // A `!reference` anywhere in the file used to fail the parse outright, so an empty inputs slot offered nothing. + test('resolves the inputs slot when a later job uses a !reference tag', () => { + // The slot line carries the indentation the user has typed into it, hence the explicit spaces. + const text = `include: + - component: ${FULL_PIPELINE_URL} + inputs: +${' '} +test: + script: + - !reference [.pnpm-setup, script]`; + const ctx = findCompletionInputContextAtLine(text, 3, 6); + assert.deepStrictEqual(ctx, { + componentUrl: FULL_PIPELINE_URL, + includeKind: 'component', + slot: 'name', + existingInputNames: [], + }); + }); }); suite('buildInputInsertValue', () => { @@ -391,7 +411,6 @@ suite('buildInputInsertValue', () => { test('renders a string default bare and stringifies a non-string default', () => { assert.strictEqual(buildInputInsertValue({ ...base, default: 'dev' }), 'dev'); assert.strictEqual(buildInputInsertValue({ ...base, type: 'number', default: 42 }), '42'); - assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', default: true }), 'true'); }); test('quotes a string default only when a bare scalar would not round-trip', () => { @@ -418,9 +437,44 @@ suite('buildInputInsertValue', () => { assert.strictEqual(buildInputInsertValue({ ...base, type: 'array', default: ['a,b', 'c'] }), '["a,b", c]'); }); - test('offers both boolean values, leading with the safer one by requiredness', () => { + test('offers both boolean values in conventional order when there is no default', () => { + // `true, false` reads the way someone scanning the dropdown expects, regardless of requiredness. assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', required: true }), '${1|true,false|}'); - assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', required: false }), '${1|false,true|}'); + assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', required: false }), '${1|true,false|}'); + }); + + test('offers both boolean values when the input has a default, pre-selecting the default', () => { + // A boolean is a closed two-value enum, so a default pre-fills the choice rather than replacing it. + assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', default: false }), '${1|false,true|}'); + assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', default: true }), '${1|true,false|}'); + // A default always leads, overriding the conventional true-first order. + assert.strictEqual( + buildInputInsertValue({ ...base, type: 'boolean', required: true, default: false }), + '${1|false,true|}' + ); + }); + + test('allowedValuesFor covers the value slot, where a boolean has no literal options list', () => { + // The value slot (cursor after `test:`) offers `allowedValuesFor`, so a boolean must yield true/false there + // even though the spec declares no `options:` — otherwise typing after `test:` suggests nothing. + assert.deepStrictEqual(allowedValuesFor({ ...base, type: 'boolean' }), [true, false]); + assert.deepStrictEqual(allowedValuesFor({ ...base, type: 'boolean', required: true }), [true, false]); + // An explicit options list is used as declared, and a free-text input offers nothing. + assert.deepStrictEqual(allowedValuesFor({ ...base, options: ['aws', 'gcp'] }), ['aws', 'gcp']); + assert.strictEqual(allowedValuesFor({ ...base, type: 'string' }), undefined); + }); + + test('offers the choice for a boolean input whose type was inferred from an untyped default', () => { + // A spec that declares `default: false` with no `type:` is a boolean input; the parser infers the type, so + // the snippet builder sees `type: 'boolean'` and offers the choice like any other boolean. + assert.strictEqual(buildInputInsertValue({ ...base, type: 'boolean', default: false }), '${1|false,true|}'); + }); + + test('inserts a boolean default unquoted, so GitLab reads it as a boolean', () => { + // Regression: a stringified `"false"` default (from the line-based spec parser) inserted `p: "false"` — a + // string where a boolean was declared. The choice list must carry bare `false`, never `"false"`. + const built = buildInputInsertValue({ ...base, type: 'boolean', default: false }); + assert.ok(!built.includes('"'), `boolean choice must not be quoted, got ${built}`); }); test('seeds empty literals for array and object inputs', () => { diff --git a/tests/unit/componentFetcherTemplates.test.ts b/tests/unit/componentFetcherTemplates.test.ts index 9768040c..dc7a0e86 100644 --- a/tests/unit/componentFetcherTemplates.test.ts +++ b/tests/unit/componentFetcherTemplates.test.ts @@ -12,7 +12,7 @@ import * as assert from 'node:assert/strict'; import type { GitLabTreeItem } from '../../src/types/api'; import type { ComponentParameter } from '../../src/types/git-component'; import { - backfillParameterOptions, + backfillParameterSpecDetail, deriveComponentName, filterSubdirectories, filterYamlBlobs, @@ -129,7 +129,7 @@ suite('deriveComponentName — deeper nesting and edge cases', () => { }); }); -suite('backfillParameterOptions', () => { +suite('backfillParameterSpecDetail', () => { const param = (name: string, extra: Partial = {}): ComponentParameter => ({ name, description: '', @@ -142,7 +142,7 @@ suite('backfillParameterOptions', () => { const catalog = [param('registry_type'), param('region')]; const template = [param('registry_type', { options: ['aws', 'gcp'] }), param('region')]; - const merged = backfillParameterOptions(catalog, template); + const merged = backfillParameterSpecDetail(catalog, template); assert.deepStrictEqual(merged.find((p) => p.name === 'registry_type')?.options, ['aws', 'gcp']); assert.strictEqual(merged.find((p) => p.name === 'region')?.options, undefined); @@ -152,7 +152,7 @@ suite('backfillParameterOptions', () => { const catalog = [param('region')]; const template = [param('registry_type', { options: ['aws'] })]; // different name - const merged = backfillParameterOptions(catalog, template); + const merged = backfillParameterSpecDetail(catalog, template); assert.strictEqual(merged[0].options, undefined); }); @@ -161,7 +161,7 @@ suite('backfillParameterOptions', () => { const catalog = [param('a'), param('b')]; const template = [param('a', { options: [] }), param('b')]; // empty + missing - const merged = backfillParameterOptions(catalog, template); + const merged = backfillParameterSpecDetail(catalog, template); assert.strictEqual(merged.find((p) => p.name === 'a')?.options, undefined); assert.strictEqual(merged.find((p) => p.name === 'b')?.options, undefined); @@ -172,8 +172,62 @@ suite('backfillParameterOptions', () => { const catalog = [catalogParam]; const template = [param('registry_type', { options: ['aws'] })]; - backfillParameterOptions(catalog, template); + backfillParameterSpecDetail(catalog, template); assert.strictEqual(catalogParam.options, undefined, 'original catalog param was mutated'); }); + + test('recovers a boolean type the catalog reported as an untyped string', () => { + // The catalog can describe a boolean input without a type, leaving the 'string' fallback in place. Completion + // keys off `type`, so without this the input gets no true/false choice. + const catalog = [param('debug', { default: 'false' })]; + const template = [param('debug', { type: 'boolean', default: false })]; + + const merged = backfillParameterSpecDetail(catalog, template); + + assert.strictEqual(merged[0].type, 'boolean'); + assert.strictEqual(merged[0].default, false, 'a stringified catalog default should yield to the parsed one'); + }); + + test('the local parse wins on the type signature, since both sides describe the same spec', () => { + // The catalog reports what GitLab read from this same template, only lossily — so on `type`/`default`/`options` + // the local parse is preferred rather than arbitrated against. + const catalog = [param('env', { type: 'string', default: 'production' })]; + const template = [param('env', { type: 'string', default: 'staging' })]; + + const merged = backfillParameterSpecDetail(catalog, template); + + assert.strictEqual(merged[0].default, 'staging'); + }); + + test('does not downgrade a catalog type to the template parse fallback', () => { + // Both sides fall back to 'string', so a template 'string' may just mean the line-based parse missed the + // `type:` line. Overwriting with it would lose a type the catalog got right. + const catalog = [param('count', { type: 'number' })]; + const template = [param('count', { type: 'string' })]; + + const merged = backfillParameterSpecDetail(catalog, template); + + assert.strictEqual(merged[0].type, 'number'); + }); + + test('keeps a catalog default the template parse does not have', () => { + const catalog = [param('env', { default: 'production' })]; + const template = [param('env')]; // no default parsed + + const merged = backfillParameterSpecDetail(catalog, template); + + assert.strictEqual(merged[0].default, 'production'); + }); + + test('leaves the fields the catalog is authoritative for untouched', () => { + const catalog = [param('debug', { description: 'from catalog', required: true })]; + const template = [param('debug', { description: 'from template', required: false, type: 'boolean' })]; + + const merged = backfillParameterSpecDetail(catalog, template); + + assert.strictEqual(merged[0].description, 'from catalog'); + assert.strictEqual(merged[0].required, true); + assert.strictEqual(merged[0].type, 'boolean', 'the type signature still comes from the local parse'); + }); }); diff --git a/tests/unit/csp.test.ts b/tests/unit/csp.test.ts new file mode 100644 index 00000000..660e0c0b --- /dev/null +++ b/tests/unit/csp.test.ts @@ -0,0 +1,66 @@ +// @mocha +/** + * Tests src/webview/csp.ts — the nonce and Content-Security-Policy meta tag every webview document is rendered with. + */ + +import * as assert from 'node:assert/strict'; +import { createNonce, cspMetaTag } from '../../src/webview/csp'; + +const CSP_SOURCE = 'vscode-webview://test-origin'; + +suite('createNonce', () => { + test('returns 32 characters from the nonce alphabet', () => { + const nonce = createNonce(); + assert.equal(nonce.length, 32); + assert.match(nonce, /^[A-Za-z0-9\-_]{32}$/); + }); + + test('returns a different value on each call', () => { + const nonces = new Set(Array.from({ length: 50 }, () => createNonce())); + assert.equal(nonces.size, 50); + }); + + test('draws uniformly across the alphabet', () => { + const counts = new Map(); + for (let i = 0; i < 2000; i++) { + for (const char of createNonce()) { + counts.set(char, (counts.get(char) ?? 0) + 1); + } + } + + const frequencies = [...counts.values()]; + const expected = (2000 * 32) / 64; + assert.equal(counts.size, 64, 'every character in the alphabet should appear'); + assert.ok( + Math.max(...frequencies) < expected * 1.15, + `no character should be over-represented: max ${Math.max(...frequencies)} vs expected ${expected}`, + ); + }); +}); + +suite('cspMetaTag', () => { + test('denies everything by default', () => { + assert.match(cspMetaTag(CSP_SOURCE, 'abc123'), /default-src 'none'/); + }); + + test('admits scripts only with the supplied nonce', () => { + const tag = cspMetaTag(CSP_SOURCE, 'abc123'); + assert.match(tag, /script-src 'nonce-abc123'/); + assert.doesNotMatch(tag, /script-src[^;]*'unsafe-inline'/); + }); + + test('admits styles from the webview origin but not inline', () => { + const tag = cspMetaTag(CSP_SOURCE, 'abc123'); + assert.match(tag, new RegExp(`style-src ${CSP_SOURCE}`)); + // Inline styles are what the external-stylesheet pattern exists to avoid; permitting them here would silently + // undo it for every document built on this helper. + assert.doesNotMatch(tag, /style-src[^;]*'unsafe-inline'/); + }); + + test('is a well-formed meta tag carrying the webview origin', () => { + const tag = cspMetaTag(CSP_SOURCE, 'abc123'); + assert.ok(tag.startsWith('')); + assert.ok(tag.includes(CSP_SOURCE)); + }); +}); diff --git a/tests/unit/tagScoping.test.ts b/tests/unit/tagScoping.test.ts index b31eac90..c463e9b9 100644 --- a/tests/unit/tagScoping.test.ts +++ b/tests/unit/tagScoping.test.ts @@ -9,12 +9,7 @@ */ import * as assert from 'node:assert/strict'; -import { - compileTagTemplate, - scopeTagsToComponent, - stripTagPrefix, - DEFAULT_TAG_PATTERN, -} from '../../src/services/component/tagScoping'; +import { DEFAULT_TAG_PATTERN, buildVersionLabels, compileTagTemplate, scopeTagsToComponent, stripTagPrefix } from '../../src/services/component/tagScoping'; import { selectDefaultVersion } from '../../src/providers/componentBrowserTransform'; // A realistic mixed tag list for a tag-per-component monorepo using the default `{name}-{version}` convention. @@ -136,3 +131,28 @@ suite('selectDefaultVersion — monorepo', () => { assert.strictEqual(chosen, scoped[0]); }); }); + +suite('buildVersionLabels', () => { + const versions = ['deploy-1.0.0', 'deploy-1.1.0', 'main']; + + test('maps each tag to its stripped {version} for a monorepo source', () => { + assert.deepStrictEqual(buildVersionLabels(versions, 'deploy', '{name}-{version}'), { + 'deploy-1.0.0': '1.0.0', + 'deploy-1.1.0': '1.1.0', + // A tag that doesn't match the template (a branch name) keeps its full form. + main: 'main', + }); + }); + + test('returns undefined with no template, so the webview falls back to the full tag', () => { + assert.strictEqual(buildVersionLabels(versions, 'deploy', undefined), undefined); + }); + + test('returns undefined when the template does not compile', () => { + assert.strictEqual(buildVersionLabels(versions, 'deploy', 'no-tokens-here'), undefined); + }); + + test('returns an empty map rather than undefined for an empty version list', () => { + assert.deepStrictEqual(buildVersionLabels([], 'deploy', '{name}-{version}'), {}); + }); +}); diff --git a/tests/unit/versionLookupShape.test.ts b/tests/unit/versionLookupShape.test.ts new file mode 100644 index 00000000..a878fc27 --- /dev/null +++ b/tests/unit/versionLookupShape.test.ts @@ -0,0 +1,56 @@ +// @mocha +/** + * Tests src/services/component/versionLookupShape.ts — the guard deciding whether a component can be used for a + * version lookup. It previously required `url`, which the details panel's webview-rebuilt component never carries, + * so Refresh Versions failed there for every component. + */ + +import * as assert from 'node:assert/strict'; +import { isVersionLookupShape } from '../../src/services/component/versionLookupShape'; +import type { Component } from '../../src/providers/componentDetector'; + +/** The shape the details panel receives: a `ComponentVersion` plus name/version, with no `url`. */ +const detailsPanelComponent: Component = { + name: 'deploy', + description: 'Deploy the thing', + parameters: [], + source: 'Test Source', + sourcePath: 'group/monorepo', + gitlabInstance: 'gitlab.com', + version: 'deploy-1.0.0', +}; + +/** The fixture minus one field, for the "what happens when this is missing" cases. */ +function without(field: keyof Component): Component { + const component = { ...detailsPanelComponent }; + delete component[field]; + return component; +} + +suite('isVersionLookupShape', () => { + test('accepts the details panel component, which has no url', () => { + assert.strictEqual('url' in detailsPanelComponent, false, 'fixture should model the missing url'); + assert.strictEqual(isVersionLookupShape(detailsPanelComponent), true); + }); + + test('accepts a component with no source, which the lookup never reads', () => { + assert.strictEqual(isVersionLookupShape(without('source')), true); + }); + + test('still accepts a fully populated cache entry', () => { + const cached = { ...detailsPanelComponent, url: 'https://gitlab.com/group/monorepo/deploy@deploy-1.0.0' }; + assert.strictEqual(isVersionLookupShape(cached), true); + }); + + test('rejects a component with no sourcePath', () => { + assert.strictEqual(isVersionLookupShape(without('sourcePath')), false); + }); + + test('rejects a component with no gitlabInstance', () => { + assert.strictEqual(isVersionLookupShape(without('gitlabInstance')), false); + }); + + test('rejects a component with no version', () => { + assert.strictEqual(isVersionLookupShape(without('version')), false); + }); +}); diff --git a/tests/unit/yamlParser.test.ts b/tests/unit/yamlParser.test.ts index 0314e74d..dcde39ad 100644 --- a/tests/unit/yamlParser.test.ts +++ b/tests/unit/yamlParser.test.ts @@ -9,7 +9,7 @@ */ import * as assert from 'node:assert/strict'; -import { parseYamlDocuments, findDocumentWith } from '../../src/utils/yamlParser'; +import { parseYaml, parseYamlDocuments, findDocumentWith, isYamlNode } from '../../src/utils/yamlParser'; suite('parseYamlDocuments', () => { test('returns every mapping document of a multi-document stream', () => { @@ -41,6 +41,135 @@ include: test('returns [] on unparseable input', () => { assert.deepStrictEqual(parseYamlDocuments('key: "unterminated', true), []); }); + + // A stock schema throws on GitLab's `!reference`, taking the whole document — `include:` and all — down with it. + test('parses a document using GitLab\'s !reference tag', () => { + const text = `include: + - component: https://gitlab.com/c/x@1.0.0 + inputs: + stage: build + +test: + script: + - !reference [.pnpm-setup, script] +`; + const docs = parseYamlDocuments(text, true); + assert.strictEqual(docs.length, 1); + const doc = findDocumentWith(docs, 'include'); + assert.ok(doc, 'the include-bearing document should survive the !reference tag'); + assert.deepStrictEqual(doc.include, [ + { component: 'https://gitlab.com/c/x@1.0.0', inputs: { stage: 'build' } }, + ]); + }); + + test('constructs !reference as the path sequence it points at', () => { + const docs = parseYamlDocuments('test:\n script:\n - !reference [.setup, script]\n', true); + assert.deepStrictEqual(docs[0].test, { script: [['.setup', 'script']] }); + }); + + // GitLab parses with Psych, where `<<: *anchor` merges. Left unmerged, an input inheriting its `default` through + // an anchor reads as required, and a merged `spec.inputs` offers an input named `<<`. + test('merges `<<:` into the surrounding mapping', () => { + const text = `.defaults: &defaults + stage: + type: string + default: build +spec: + inputs: + <<: *defaults + extra: + type: string +`; + const docs = parseYamlDocuments(text, true); + assert.deepStrictEqual(findDocumentWith(docs, 'spec')?.spec, { + inputs: { + stage: { type: 'string', default: 'build' }, + extra: { type: 'string' }, + }, + }); + }); + + test('merges a sequence of anchors, earlier entries winning', () => { + const text = `.a: &a + x: 1 + y: one +.b: &b + y: two + z: 3 +job: + <<: [*a, *b] +`; + const docs = parseYamlDocuments(text, true); + assert.deepStrictEqual(docs[0].job, { x: 1, y: 'one', z: 3 }); + }); + + // YAML 1.1 scalar resolution would make these booleans; all are plausible job or input names. + test('keeps `y`, `n`, `yes`, `no`, `on`, `off` as string keys', () => { + const text = 'spec:\n inputs:\n y: 1\n n: 2\n yes: 3\n no: 4\n on: 5\n off: 6\n'; + const spec = findDocumentWith(parseYamlDocuments(text, true), 'spec')?.spec; + assert.ok(isYamlNode(spec)); + assert.ok(isYamlNode(spec.inputs)); + assert.deepStrictEqual(Object.keys(spec.inputs), ['y', 'n', 'yes', 'no', 'on', 'off']); + }); + + // Any local tag is fatal to a stock parse, not just a sequence-position `!reference`. Each of these forms took the + // whole document down while only the sequence form was handled, so the tags match by prefix on `!` instead. + test('tolerates a local tag in every node position', () => { + const cases: [string, string, unknown][] = [ + ['scalar', 'key: !reference foo', { key: 'foo' }], + ['sequence', 'key: !reference [.setup, script]', { key: ['.setup', 'script'] }], + ['mapping', 'key: !reference\n nested: value', { key: { nested: 'value' } }], + ]; + for (const [position, text, expected] of cases) { + assert.deepStrictEqual(parseYamlDocuments(text, true)[0], expected, `${position} position`); + } + }); + + // The shape a user is mid-way through typing: `!reference` with no argument yet. Losing the parse here blanks + // completion at exactly the moment it is wanted. + test('tolerates a half-typed tag with no value yet', () => { + const text = `include: + - component: https://gitlab.com/c/x@1.0.0 + inputs: + stage: build + +test: + script: + - !reference +`; + const doc = findDocumentWith(parseYamlDocuments(text, true), 'include'); + assert.ok(doc, 'the include must still resolve while a tag is half-typed'); + }); + + test('tolerates an unknown tag that is not !reference', () => { + assert.deepStrictEqual(parseYamlDocuments('a: !custom [1, 2]', true)[0], { a: [1, 2] }); + }); + + // The tolerated tags must not disturb ordinary YAML: core scalars keep their types rather than becoming strings. + test('leaves untagged YAML and its scalar types alone', () => { + const text = 'num: 1\nbool: true\nnul: null\nstr: plain\nlist:\n - a\n'; + assert.deepStrictEqual(parseYamlDocuments(text, true)[0], { + num: 1, + bool: true, + nul: null, + str: 'plain', + list: ['a'], + }); + }); +}); + +// `parseYaml` is the single-document path (the completion round-trip probe, the component browser's wrapped-include +// parse). It takes the same schema, but the tests above all go through `parseYamlDocuments`. +suite('parseYaml', () => { + test('tolerates a local tag in every node position', () => { + assert.deepStrictEqual(parseYaml('key: !reference foo', true), { key: 'foo' }); + assert.deepStrictEqual(parseYaml('key: !reference [.setup, script]', true), { key: ['.setup', 'script'] }); + assert.deepStrictEqual(parseYaml('key: !reference\n nested: value', true), { key: { nested: 'value' } }); + }); + + test('still returns null on genuinely malformed YAML', () => { + assert.strictEqual(parseYaml('key: "unterminated', true), null); + }); }); suite('findDocumentWith', () => {