From d3e81debb42ecf64f9f6797569a026b1524260ea Mon Sep 17 00:00:00 2001 From: Simon Heather <32168619+X-Guardian@users.noreply.github.com> Date: Tue, 8 Sep 2026 12:59:52 +0100 Subject: [PATCH 01/27] fix(completion): a !reference tag anywhere in the file breaks all input completion (#263) * fix(completion): a !reference tag anywhere in the file suppresses all input completion * Fix referenceTag --------- Co-authored-by: Simon Heather --- package-lock.json | 8 --- package.json | 1 - src/providers/localComponentResolver.ts | 4 +- src/utils/yamlParser.ts | 24 ++++++- .../suite/referenceTagCompletion.test.ts | 68 +++++++++++++++++++ .../reference-tag-completion/.gitlab-ci.yml | 14 ++++ .../templates/deploy.yml | 16 +++++ tests/unit/completionInputContext.test.ts | 19 ++++++ tests/unit/yamlParser.test.ts | 25 +++++++ 9 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 tests/extension-host/suite/referenceTagCompletion.test.ts create mode 100644 tests/fixtures/reference-tag-completion/.gitlab-ci.yml create mode 100644 tests/fixtures/reference-tag-completion/templates/deploy.yml diff --git a/package-lock.json b/package-lock.json index e8fbf063..b87f928b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "@octokit/plugin-paginate-rest": "^15.0.0", "@release-it/conventional-changelog": "^12.0.0", "@types/glob": "^9.0.0", - "@types/js-yaml": "^4.0.9", "@types/mocha": "^10.0.10", "@types/node": "^26.2.0", "@types/vscode": "^1.120.0", @@ -1954,13 +1953,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", diff --git a/package.json b/package.json index 874904a9..01231fec 100644 --- a/package.json +++ b/package.json @@ -312,7 +312,6 @@ "@octokit/plugin-paginate-rest": "^15.0.0", "@release-it/conventional-changelog": "^12.0.0", "@types/glob": "^9.0.0", - "@types/js-yaml": "^4.0.9", "@types/mocha": "^10.0.10", "@types/node": "^26.2.0", "@types/vscode": "^1.120.0", diff --git a/src/providers/localComponentResolver.ts b/src/providers/localComponentResolver.ts index d9795bc3..7f916b60 100644 --- a/src/providers/localComponentResolver.ts +++ b/src/providers/localComponentResolver.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import * as yaml from 'js-yaml'; import { Component, ComponentParameter } from './componentDetector'; import { Logger } from '../utils/logger'; -import { isYamlNode } from '../utils/yamlParser'; +import { isYamlNode, GITLAB_CI_SCHEMA } from '../utils/yamlParser'; import type { ParameterDefault } from '../types/git-component'; // Pure parser helpers live in their own module so the unit suite can exercise them under plain Node. Re-exported @@ -229,7 +229,7 @@ export async function resolveLocalIncludeOutcome( } let docs: unknown[]; try { - docs = yaml.loadAll(text); + docs = yaml.loadAll(text, { schema: GITLAB_CI_SCHEMA }); } catch (err) { logger.debug(`[LocalComponentResolver] Failed to parse ${uri.fsPath}: ${err}`, 'LocalComponentResolver'); // The file exists and was read; it just isn't valid YAML. That's a plain include we can't extract inputs from, diff --git a/src/utils/yamlParser.ts b/src/utils/yamlParser.ts index 98b374c4..2af42402 100755 --- a/src/utils/yamlParser.ts +++ b/src/utils/yamlParser.ts @@ -3,6 +3,26 @@ import * as yaml from 'js-yaml'; /** Loose object shape returned by `js-yaml`. Callers narrow via property checks before reading fields. */ export type YamlNode = Record; +/** + * `!reference [.job, script]` — GitLab's own tag for splicing another job's key into this one. It belongs to no YAML + * schema, so a stock parser throws on it and the *whole file* — `include:` block included — yields nothing, killing + * completion/hover/validation for any pipeline that uses one. Resolving a reference needs the merged pipeline, which + * this extension never builds, so the tag constructs to its path sequence: enough for the surrounding document to + * parse, and a caller that reads one sees the target it points at rather than `undefined`. + */ +const referenceTag = yaml.defineSequenceTag('!reference', { + create: () => [], + addItem: (carrier, item) => { + carrier.push(item); + }, + // Load-only. `identify` selects the tag when *dumping*; returning false stops it claiming the plain arrays this + // constructs, which would re-emit unrelated sequences as `!reference`. + identify: () => false, +}); + +/** The core schema plus GitLab's CI-only tags, so a `.gitlab-ci.yml` using them still parses structurally. */ +export const GITLAB_CI_SCHEMA = yaml.CORE_SCHEMA.withTags(referenceTag); + /** Type-guard: a parsed YAML value is a non-null object (i.e. a mapping). Use to narrow `unknown` results. */ export function isYamlNode(value: unknown): value is YamlNode { return typeof value === 'object' && value !== null && !Array.isArray(value); @@ -34,7 +54,7 @@ export function parseYaml(text: string, silent = false): unknown { } // Parse and cache - const parsed = yaml.load(text); + const parsed = yaml.load(text, { schema: GITLAB_CI_SCHEMA }); parseCache.set(contentHash, { content: text, parsed, timestamp: now }); // Clean old cache entries periodically @@ -68,7 +88,7 @@ export function parseYaml(text: string, silent = false): unknown { */ export function parseYamlDocuments(text: string, silent = false): YamlNode[] { try { - const docs = yaml.loadAll(text); + const docs = yaml.loadAll(text, { schema: GITLAB_CI_SCHEMA }); return docs.filter(isYamlNode); } catch (e) { if (!silent) { diff --git a/tests/extension-host/suite/referenceTagCompletion.test.ts b/tests/extension-host/suite/referenceTagCompletion.test.ts new file mode 100644 index 00000000..1ef913f2 --- /dev/null +++ b/tests/extension-host/suite/referenceTagCompletion.test.ts @@ -0,0 +1,68 @@ +import * as assert from 'assert'; +import * as path from 'path'; +import * as vscode from 'vscode'; + +const EXTENSION_ID = 'eFAILution.gitlab-component-helper'; + +// __dirname is /out-test/suite at runtime; fixtures live under tests/fixtures. +const FIXTURE_DIR = path.resolve(__dirname, '..', '..', 'tests', 'fixtures', 'reference-tag-completion'); +const FIXTURE = path.join(FIXTURE_DIR, '.gitlab-ci.yml'); + +async function ensureActive(): Promise { + const ext = vscode.extensions.getExtension(EXTENSION_ID); + assert.ok(ext); + if (!ext.isActive) await ext.activate(); +} + +/** 0-indexed line whose trimmed text starts with `:`. */ +function lineStartingWith(doc: vscode.TextDocument, name: string): number { + const lines = doc.getText().split('\n'); + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim().startsWith(`${name}:`)) return i; + } + throw new Error(`fixture missing a line starting with ${name}:`); +} + +function labels(list: vscode.CompletionList | undefined): string[] { + return (list?.items ?? []).map((i) => (typeof i.label === 'string' ? i.label : i.label.label)); +} + +async function completionsAt(doc: vscode.TextDocument, position: vscode.Position): Promise { + const list = await vscode.commands.executeCommand( + 'vscode.executeCompletionItemProvider', + doc.uri, + position + ); + assert.ok(list, 'executeCompletionItemProvider returned no completion list'); + return list; +} + +// Regression for GitLab's `!reference [.job, key]` tag. It belongs to no YAML schema, so a stock parser threw on it +// and took the entire file down — `include:` block included — leaving the parse null and suppressing every input +// completion, even though the tag sits in an unrelated job further down the file. Drives VS Code's own completion +// engine end-to-end to confirm the name slot still resolves with a `!reference` present. +suite('Input completion in a file using a !reference tag', () => { + suiteSetup(ensureActive); + + test('name slot under the include offers the include\'s not-yet-set inputs', async () => { + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(FIXTURE)); + const editor = await vscode.window.showTextDocument(doc); + + // The include's inputs already set `job_name`; the remaining inputs are `environment` and `region`. Type a + // fresh name slot on a new line under `job_name:` at that key's indent, then ask for completions at the caret. + const jobNameLine = lineStartingWith(doc, 'job_name'); + const keyIndent = doc.lineAt(jobNameLine).firstNonWhitespaceCharacterIndex; + const insertAt = new vscode.Position(jobNameLine, doc.lineAt(jobNameLine).text.length); + await editor.edit((b) => b.insert(insertAt, `\n${' '.repeat(keyIndent)}`)); + + const slotLine = jobNameLine + 1; + const position = new vscode.Position(slotLine, keyIndent); + const list = await completionsAt(doc, position); + + const got = labels(list); + assert.ok(got.includes('environment'), `expected an 'environment' completion. Got: ${JSON.stringify(got)}`); + assert.ok(got.includes('region'), `expected a 'region' completion. Got: ${JSON.stringify(got)}`); + // The already-set input must not be re-offered. + assert.ok(!got.includes('job_name'), `'job_name' is already set and must not be offered. Got: ${JSON.stringify(got)}`); + }); +}); diff --git a/tests/fixtures/reference-tag-completion/.gitlab-ci.yml b/tests/fixtures/reference-tag-completion/.gitlab-ci.yml new file mode 100644 index 00000000..a07d62db --- /dev/null +++ b/tests/fixtures/reference-tag-completion/.gitlab-ci.yml @@ -0,0 +1,14 @@ +include: + - local: "reference-tag-completion/templates/deploy.yml" + inputs: + job_name: deploy + +.pnpm-setup: + script: + - corepack enable + - pnpm install --frozen-lockfile + +test: + script: + - !reference [.pnpm-setup, script] + - pnpm test diff --git a/tests/fixtures/reference-tag-completion/templates/deploy.yml b/tests/fixtures/reference-tag-completion/templates/deploy.yml new file mode 100644 index 00000000..514092da --- /dev/null +++ b/tests/fixtures/reference-tag-completion/templates/deploy.yml @@ -0,0 +1,16 @@ +spec: + inputs: + environment: + description: Target environment + type: string + default: staging + region: + description: Target region + type: string + job_name: + description: The name of the CI job + type: string +--- +$[[ inputs.job_name ]]: + script: + - echo "deploy $[[ inputs.job_name ]] to $[[ inputs.environment ]]/$[[ inputs.region ]]" diff --git a/tests/unit/completionInputContext.test.ts b/tests/unit/completionInputContext.test.ts index e6b3d4f8..d1ca979a 100644 --- a/tests/unit/completionInputContext.test.ts +++ b/tests/unit/completionInputContext.test.ts @@ -383,6 +383,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', () => { diff --git a/tests/unit/yamlParser.test.ts b/tests/unit/yamlParser.test.ts index 0314e74d..d6f040fe 100644 --- a/tests/unit/yamlParser.test.ts +++ b/tests/unit/yamlParser.test.ts @@ -41,6 +41,31 @@ 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']] }); + }); }); suite('findDocumentWith', () => { From 9538d21381d440bc14af109eae4f87a3fe8ba955 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:01:14 -0400 Subject: [PATCH 02/27] chore(deps): bump js-yaml from 4.2.0 to 4.3.2 (#264) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.2.0 to 4.3.2. - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.2/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.2.0...4.3.2) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.3.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index b87f928b..0ec6bab2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3415,9 +3415,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": [ { @@ -6127,9 +6127,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.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.1.tgz", + "integrity": "sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==", "dev": true, "funding": [ { @@ -6774,9 +6774,9 @@ } }, "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==", + "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": [ { From 099932484ccf6154d4e90d61855619c08d648f58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:01:25 -0400 Subject: [PATCH 03/27] chore(deps-dev): bump fast-uri from 3.1.5 to 3.1.7 (#265) Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.7. - [Release notes](https://github.com/fastify/fast-uri/releases) - [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.7) --- updated-dependencies: - dependency-name: fast-uri dependency-version: 3.1.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ec6bab2..70e7ecf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4455,9 +4455,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": [ { From ecd1aebe79f23a7888b203b9e360c772bcde8b33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:01:38 -0400 Subject: [PATCH 04/27] chore(deps-dev): bump the dev-dependencies group with 9 updates (#266) Bumps the dev-dependencies group with 9 updates: | Package | From | To | | --- | --- | --- | | [@octokit/core](https://github.com/octokit/core.js) | `7.0.7` | `7.0.8` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.2.0` | `26.4.1` | | [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.67.0` | `8.69.0` | | [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.67.0` | `8.69.0` | | [eslint](https://github.com/eslint/eslint) | `10.8.1` | `10.9.1` | | [globals](https://github.com/sindresorhus/globals) | `17.11.0` | `17.12.0` | | [js-yaml](https://github.com/nodeca/js-yaml) | `5.3.0` | `5.4.1` | | [tsx](https://github.com/privatenumber/tsx) | `4.23.12` | `4.23.13` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.67.0` | `8.69.0` | Updates `@octokit/core` from 7.0.7 to 7.0.8 - [Release notes](https://github.com/octokit/core.js/releases) - [Commits](https://github.com/octokit/core.js/compare/v7.0.7...v7.0.8) Updates `@types/node` from 26.2.0 to 26.4.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@typescript-eslint/eslint-plugin` from 8.67.0 to 8.69.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.69.0/packages/eslint-plugin) Updates `@typescript-eslint/parser` from 8.67.0 to 8.69.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.69.0/packages/parser) Updates `eslint` from 10.8.1 to 10.9.1 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v10.8.1...v10.9.1) Updates `globals` from 17.11.0 to 17.12.0 - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](https://github.com/sindresorhus/globals/compare/v17.11.0...v17.12.0) Updates `js-yaml` from 5.3.0 to 5.4.1 - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/5.3.0...5.4.1) Updates `tsx` from 4.23.12 to 4.23.13 - [Release notes](https://github.com/privatenumber/tsx/releases) - [Changelog](https://github.com/privatenumber/tsx/blob/master/release.config.cjs) - [Commits](https://github.com/privatenumber/tsx/compare/v4.23.12...v4.23.13) Updates `typescript-eslint` from 8.67.0 to 8.69.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.69.0/packages/typescript-eslint) --- updated-dependencies: - dependency-name: "@octokit/core" dependency-version: 7.0.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: "@types/node" dependency-version: 26.4.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/eslint-plugin" dependency-version: 8.69.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: "@typescript-eslint/parser" dependency-version: 8.69.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: eslint dependency-version: 10.9.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: globals dependency-version: 17.12.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: js-yaml dependency-version: 5.4.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: tsx dependency-version: 4.23.13 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: dev-dependencies - dependency-name: typescript-eslint dependency-version: 8.69.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 304 +++++++++++++++++++++++----------------------- package.json | 18 +-- 2 files changed, 161 insertions(+), 161 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70e7ecf7..8587ff24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,15 +13,15 @@ "@commitlint/config-conventional": "^21.0.2", "@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", "@types/glob": "^9.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^26.2.0", + "@types/node": "^26.4.1", "@types/vscode": "^1.120.0", - "@typescript-eslint/eslint-plugin": "^8.67.0", - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/eslint-plugin": "^8.69.0", + "@typescript-eslint/parser": "^8.69.0", "@vscode/test-electron": "^3.1.0", "commitizen": "^4.3.2", "conventional-changelog-conventionalcommits": "^9.3.1", @@ -30,19 +30,19 @@ "dateformat": "^5.0.3", "dotenv": "^17.4.2", "esbuild": "^0.28.2", - "eslint": "^10.8.1", - "globals": "^17.11.0", + "eslint": "^10.9.1", + "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", - "js-yaml": "^5.3.0", + "js-yaml": "^5.4.1", "minimatch": "^10.2.6", "mocha": "^11.8.0", "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", - "tsx": "^4.23.12", + "tsx": "^4.23.13", "typescript": "^6.0.3", - "typescript-eslint": "^8.67.0" + "typescript-eslint": "^8.69.0" }, "engines": { "node": ">=22.0.0", @@ -1535,17 +1535,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" }, @@ -1554,30 +1554,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": { @@ -1585,31 +1585,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": { @@ -1617,20 +1617,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": { @@ -1703,17 +1703,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": { @@ -1721,50 +1721,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": { @@ -1968,9 +1968,9 @@ "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.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz", + "integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==", "dev": true, "license": "MIT", "dependencies": { @@ -1992,17 +1992,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz", + "integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==", "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.69.0", + "@typescript-eslint/type-utils": "8.69.0", + "@typescript-eslint/utils": "8.69.0", + "@typescript-eslint/visitor-keys": "8.69.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2015,22 +2015,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/parser": "^8.69.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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz", + "integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==", "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.69.0", + "@typescript-eslint/types": "8.69.0", + "@typescript-eslint/typescript-estree": "8.69.0", + "@typescript-eslint/visitor-keys": "8.69.0", "debug": "^4.4.3" }, "engines": { @@ -2046,14 +2046,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz", + "integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.67.0", - "@typescript-eslint/types": "^8.67.0", + "@typescript-eslint/tsconfig-utils": "^8.69.0", + "@typescript-eslint/types": "^8.69.0", "debug": "^4.4.3" }, "engines": { @@ -2068,14 +2068,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz", + "integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.67.0", - "@typescript-eslint/visitor-keys": "8.67.0" + "@typescript-eslint/types": "8.69.0", + "@typescript-eslint/visitor-keys": "8.69.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2086,9 +2086,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz", + "integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==", "dev": true, "license": "MIT", "engines": { @@ -2103,15 +2103,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz", + "integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==", "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.69.0", + "@typescript-eslint/typescript-estree": "8.69.0", + "@typescript-eslint/utils": "8.69.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2128,9 +2128,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz", + "integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==", "dev": true, "license": "MIT", "engines": { @@ -2142,16 +2142,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz", + "integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==", "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.69.0", + "@typescript-eslint/tsconfig-utils": "8.69.0", + "@typescript-eslint/types": "8.69.0", + "@typescript-eslint/visitor-keys": "8.69.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2170,16 +2170,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz", + "integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==", "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.69.0", + "@typescript-eslint/types": "8.69.0", + "@typescript-eslint/typescript-estree": "8.69.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2194,13 +2194,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.69.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz", + "integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/types": "8.69.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -3216,13 +3216,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", @@ -4142,9 +4142,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.9.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.9.1.tgz", + "integrity": "sha512-9VaAkDURekixUQJy0oJYl2DcN6oKMfxay7XzaGYAWQwsb6qfKf+x76R2k1L8kb1boc+FyCAaTA9GmiKaaiaF+A==", "dev": true, "license": "MIT", "workspaces": [ @@ -4976,9 +4976,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": { @@ -6185,9 +6185,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" }, @@ -9125,9 +9125,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": { @@ -9269,16 +9269,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.69.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.69.0.tgz", + "integrity": "sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==", "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.69.0", + "@typescript-eslint/parser": "8.69.0", + "@typescript-eslint/typescript-estree": "8.69.0", + "@typescript-eslint/utils": "8.69.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index 01231fec..1afee95b 100644 --- a/package.json +++ b/package.json @@ -308,15 +308,15 @@ "@commitlint/config-conventional": "^21.0.2", "@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", "@types/glob": "^9.0.0", "@types/mocha": "^10.0.10", - "@types/node": "^26.2.0", + "@types/node": "^26.4.1", "@types/vscode": "^1.120.0", - "@typescript-eslint/eslint-plugin": "^8.67.0", - "@typescript-eslint/parser": "^8.67.0", + "@typescript-eslint/eslint-plugin": "^8.69.0", + "@typescript-eslint/parser": "^8.69.0", "@vscode/test-electron": "^3.1.0", "commitizen": "^4.3.2", "conventional-changelog-conventionalcommits": "^9.3.1", @@ -325,19 +325,19 @@ "dateformat": "^5.0.3", "dotenv": "^17.4.2", "esbuild": "^0.28.2", - "eslint": "^10.8.1", - "globals": "^17.11.0", + "eslint": "^10.9.1", + "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", - "js-yaml": "^5.3.0", + "js-yaml": "^5.4.1", "minimatch": "^10.2.6", "mocha": "^11.8.0", "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", - "tsx": "^4.23.12", + "tsx": "^4.23.13", "typescript": "^6.0.3", - "typescript-eslint": "^8.67.0" + "typescript-eslint": "^8.69.0" }, "keywords": [], "author": "eFAILution", From 574d38d41ba69d57ea73347db2f1bf5f38907611 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Sep 2026 12:04:38 +0000 Subject: [PATCH 05/27] chore(release): 0.17.0 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8587ff24..8ba36338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.16.12", + "version": "0.17.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.16.12", + "version": "0.17.0", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index 1afee95b..4f9bb4af 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.0", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From cabacbc79ad42430264c80b131cc07c1c6c4a10c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:06:57 -0400 Subject: [PATCH 06/27] chore(deps-dev): bump mocha from 11.8.0 to 12.0.0 (#267) Bumps [mocha](https://github.com/mochajs/mocha) from 11.8.0 to 12.0.0. - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v11.8.0...v12.0.0) --- updated-dependencies: - dependency-name: mocha dependency-version: 12.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: eFAILution --- package-lock.json | 600 ++++------------------------------------------ package.json | 2 +- 2 files changed, 41 insertions(+), 561 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8ba36338..0452346e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "is-ci": "^4.0.0", "js-yaml": "^5.4.1", "minimatch": "^10.2.6", - "mocha": "^11.8.0", + "mocha": "^12.0.0", "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", @@ -1421,109 +1421,6 @@ } } }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "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" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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==", - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "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/@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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@octokit/auth-token": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", @@ -1823,17 +1720,6 @@ "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", @@ -2747,36 +2633,6 @@ } } }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/cachedir": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", @@ -2883,16 +2739,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/" @@ -3653,19 +3509,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", @@ -3825,9 +3668,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": { @@ -3875,13 +3718,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", @@ -4584,16 +4420,6 @@ "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", @@ -4631,36 +4457,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", @@ -5119,16 +4915,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", @@ -6093,22 +5879,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", @@ -6513,13 +6283,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", @@ -6660,107 +6423,34 @@ } }, "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.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-12.0.0.tgz", + "integrity": "sha512-NYNh5IFt6WYqm9bi4601m7vix8MZdXC0DwS4gY6WhXO2RgJWhivhISVmq1oklCif18OSI9l+vx5Mdm5oh1XGiQ==", "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", + "diff": "^9.0.0", "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", + "glob": "^13.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", + "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.0.2", + "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_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==", - "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_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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "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", - "dev": true, - "license": "ISC", - "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" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^20.19.0 || >=22.12.0" } }, "node_modules/mocha/node_modules/has-flag": { @@ -6773,60 +6463,17 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/js-yaml": { - "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==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], "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" - }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mocha/node_modules/supports-color": { @@ -6845,25 +6492,6 @@ "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", @@ -7517,13 +7145,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", @@ -7905,16 +7526,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", @@ -7987,13 +7598,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", @@ -8291,16 +7902,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", @@ -8522,13 +8123,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": { @@ -8856,22 +8457,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", @@ -8963,20 +8548,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", @@ -9568,9 +9139,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" }, @@ -9592,61 +9163,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", @@ -9735,42 +9251,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 4f9bb4af..42f41d65 100644 --- a/package.json +++ b/package.json @@ -331,7 +331,7 @@ "is-ci": "^4.0.0", "js-yaml": "^5.4.1", "minimatch": "^10.2.6", - "mocha": "^11.8.0", + "mocha": "^12.0.0", "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", From ea9b26ad168d6d8d2813c103432dc46e12a2fefb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Sep 2026 12:09:18 +0000 Subject: [PATCH 07/27] chore(release): 0.17.1 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0452346e..4fe9c6d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.0", + "version": "0.17.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.0", + "version": "0.17.1", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index 42f41d65..4a642fd7 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.17.0", + "version": "0.17.1", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From 42d310c33770e3d4dff30001367da62fc9e53d1c Mon Sep 17 00:00:00 2001 From: Simon Heather <32168619+X-Guardian@users.noreply.github.com> Date: Wed, 9 Sep 2026 00:52:20 +0100 Subject: [PATCH 08/27] fix(parser): tolerate any local YAML tag, not just sequence !reference (#273) Co-authored-by: Simon Heather --- src/utils/yamlParser.ts | 48 +++++++++++---- .../templates/deploy.yml | 7 +++ tests/unit/yamlParser.test.ts | 61 ++++++++++++++++++- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/src/utils/yamlParser.ts b/src/utils/yamlParser.ts index 2af42402..bdc66e8b 100755 --- a/src/utils/yamlParser.ts +++ b/src/utils/yamlParser.ts @@ -4,24 +4,50 @@ import * as yaml from 'js-yaml'; export type YamlNode = Record; /** - * `!reference [.job, script]` — GitLab's own tag for splicing another job's key into this one. It belongs to no YAML - * schema, so a stock parser throws on it and the *whole file* — `include:` block included — yields nothing, killing - * completion/hover/validation for any pipeline that uses one. Resolving a reference needs the merged pipeline, which - * this extension never builds, so the tag constructs to its path sequence: enough for the surrounding document to - * parse, and a caller that reads one sees the target it points at rather than `undefined`. + * Shared options for the local-tag catch-alls below. A local tag (`!reference`, `!custom`, …) belongs to no schema, + * so a stock parse throws and the whole file — `include:` and all — yields nothing. Matching by prefix on `!` + * degrades any such tag to the value it wraps: this extension reads only `include:` and `spec.inputs`, never the + * tagged values. `identify` is dump-side only; false keeps these load-only. */ -const referenceTag = yaml.defineSequenceTag('!reference', { +const loadOnly = { matchByTagPrefix: true, identify: () => false } as const; + +/** One catch-all per node kind, since a tag is selected by the shape of the node it decorates. */ +const anyLocalScalarTag = yaml.defineScalarTag('!', { ...loadOnly, resolve: (source) => source }); + +const anyLocalSequenceTag = yaml.defineSequenceTag('!', { + ...loadOnly, create: () => [], addItem: (carrier, item) => { carrier.push(item); }, - // Load-only. `identify` selects the tag when *dumping*; returning false stops it claiming the plain arrays this - // constructs, which would re-emit unrelated sequences as `!reference`. - identify: () => false, }); -/** The core schema plus GitLab's CI-only tags, so a `.gitlab-ci.yml` using them still parses structurally. */ -export const GITLAB_CI_SCHEMA = yaml.CORE_SCHEMA.withTags(referenceTag); +const anyLocalMappingTag = yaml.defineMappingTag, YamlNode>('!', { + ...loadOnly, + // Map carrier so non-string keys survive; finalized to a plain object, which is what every reader here expects. + create: () => new Map(), + addPair: (carrier, key, value) => { + carrier.set(key, value); + return ''; // Success; a non-empty string is an error message. + }, + has: (carrier, key) => carrier.has(key), + keys: (result) => Object.keys(result), + get: (result, key) => result[String(key)], + finalize: (carrier) => { + const result: YamlNode = {}; + for (const [key, value] of carrier) { + result[String(key)] = value; + } + return result; + }, +}); + +/** The core schema plus tolerated local tags, so a `.gitlab-ci.yml` using them still parses structurally. */ +export const GITLAB_CI_SCHEMA = yaml.CORE_SCHEMA.withTags( + anyLocalScalarTag, + anyLocalSequenceTag, + anyLocalMappingTag +); /** Type-guard: a parsed YAML value is a non-null object (i.e. a mapping). Use to narrow `unknown` results. */ export function isYamlNode(value: unknown): value is YamlNode { diff --git a/tests/fixtures/reference-tag-completion/templates/deploy.yml b/tests/fixtures/reference-tag-completion/templates/deploy.yml index 514092da..1817f69e 100644 --- a/tests/fixtures/reference-tag-completion/templates/deploy.yml +++ b/tests/fixtures/reference-tag-completion/templates/deploy.yml @@ -11,6 +11,13 @@ spec: description: The name of the CI job type: string --- +# The `!reference` here is load-bearing: it exercises the local include's own parse in localComponentResolver, which +# reads this file's `spec:` block. Without it, that parse path is never given a tag to choke on. +.deploy-setup: + script: + - echo "authenticating against $[[ inputs.region ]]" + $[[ inputs.job_name ]]: script: + - !reference [.deploy-setup, script] - echo "deploy $[[ inputs.job_name ]] to $[[ inputs.environment ]]/$[[ inputs.region ]]" diff --git a/tests/unit/yamlParser.test.ts b/tests/unit/yamlParser.test.ts index d6f040fe..e74eaadd 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 } from '../../src/utils/yamlParser'; suite('parseYamlDocuments', () => { test('returns every mapping document of a multi-document stream', () => { @@ -66,6 +66,65 @@ test: const docs = parseYamlDocuments('test:\n script:\n - !reference [.setup, script]\n', true); assert.deepStrictEqual(docs[0].test, { script: [['.setup', 'script']] }); }); + + // 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', () => { From aaf85b3d234129e19cfe6a98005ab7f8751e4d6e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Sep 2026 23:54:54 +0000 Subject: [PATCH 09/27] chore(release): 0.17.2 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4fe9c6d4..edb1b29c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.1", + "version": "0.17.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.1", + "version": "0.17.2", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index 4a642fd7..f5265290 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.17.1", + "version": "0.17.2", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From 8bd3ed0e6ca8f8d91ed9c04ed9608c0f8cb129a9 Mon Sep 17 00:00:00 2001 From: Simon Heather <32168619+X-Guardian@users.noreply.github.com> Date: Wed, 9 Sep 2026 00:56:43 +0100 Subject: [PATCH 10/27] fix(parser): merge YAML merge keys (`<<:`) as GitLab does (#274) Co-authored-by: Simon Heather Co-authored-by: eFAILution --- src/utils/yamlParser.ts | 8 +- tests/extension-host/suite/mergeKey.test.ts | 75 +++++++++++++++++++ tests/fixtures/merge-key/.gitlab-ci.yml | 7 ++ tests/fixtures/merge-key/templates/deploy.yml | 23 ++++++ tests/unit/yamlParser.test.ts | 47 +++++++++++- 5 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 tests/extension-host/suite/mergeKey.test.ts create mode 100644 tests/fixtures/merge-key/.gitlab-ci.yml create mode 100644 tests/fixtures/merge-key/templates/deploy.yml diff --git a/src/utils/yamlParser.ts b/src/utils/yamlParser.ts index bdc66e8b..2dcee1f4 100755 --- a/src/utils/yamlParser.ts +++ b/src/utils/yamlParser.ts @@ -42,8 +42,14 @@ const anyLocalMappingTag = yaml.defineMappingTag, YamlNode }, }); -/** The core schema plus tolerated local tags, so a `.gitlab-ci.yml` using them still parses structurally. */ +/** + * The core schema plus tolerated local tags, so a `.gitlab-ci.yml` using them still parses structurally. + * + * `mergeTag` gives `<<: *anchor` its YAML 1.1 meaning — merge the anchored mapping in — which is how GitLab's own + * parser (Ruby's Psych) reads it, and how anchors are shared between jobs in practice. + */ export const GITLAB_CI_SCHEMA = yaml.CORE_SCHEMA.withTags( + yaml.mergeTag, anyLocalScalarTag, anyLocalSequenceTag, anyLocalMappingTag diff --git a/tests/extension-host/suite/mergeKey.test.ts b/tests/extension-host/suite/mergeKey.test.ts new file mode 100644 index 00000000..1c35a411 --- /dev/null +++ b/tests/extension-host/suite/mergeKey.test.ts @@ -0,0 +1,75 @@ +import * as assert from 'assert'; +import * as path from 'path'; +import * as vscode from 'vscode'; + +const EXTENSION_ID = 'eFAILution.gitlab-component-helper'; + +// __dirname is /out-test/suite at runtime; fixtures live under tests/fixtures. +const FIXTURE_DIR = path.resolve(__dirname, '..', '..', 'tests', 'fixtures', 'merge-key'); +const FIXTURE = path.join(FIXTURE_DIR, '.gitlab-ci.yml'); + +async function ensureActive(): Promise { + const ext = vscode.extensions.getExtension(EXTENSION_ID); + assert.ok(ext); + if (!ext.isActive) await ext.activate(); +} + +/** Wait until our own validation has run — the fixture's `bogus_input` guarantees one diagnostic to key off. */ +async function waitForOurDiagnostics(uri: vscode.Uri, timeoutMs = 5000): Promise { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + const ours = vscode.languages.getDiagnostics(uri).filter((d) => d.source === 'gitlab-component-helper'); + if (ours.some((d) => d.code === 'unknown-input')) return ours; + await new Promise((resolve) => setTimeout(resolve, 100)); + } + return vscode.languages.getDiagnostics(uri).filter((d) => d.source === 'gitlab-component-helper'); +} + +function labels(list: vscode.CompletionList | undefined): string[] { + return (list?.items ?? []).map((i) => (typeof i.label === 'string' ? i.label : i.label.label)); +} + +// Regression for the YAML merge key. GitLab parses with Psych, where `<<: *anchor` merges the anchored mapping in; +// without `mergeTag` the parser leaves a literal `<<` key, so a `spec.inputs` entry inheriting its `default` through +// the merge reads as having no default — reported missing — and `<<` itself surfaces as an input. Drives VS Code's +// diagnostics and completion engine end-to-end, which is where the user actually sees the bug. +suite('Merge-key inputs in a local include', () => { + suiteSetup(ensureActive); + + test('inputs inheriting a default through `<<:` are not reported missing', async () => { + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(FIXTURE)); + await vscode.window.showTextDocument(doc); + + const ours = await waitForOurDiagnostics(doc.uri); + const missing = ours.filter((d) => d.code === 'missing-required-input'); + assert.deepStrictEqual( + missing.map((d) => d.message), + [], + `stage and region both carry a default through the merge key, so neither is required. Got: ${JSON.stringify(ours.map((d) => ({ code: d.code, msg: d.message })))}` + ); + }); + + test('the merge key itself is not offered as an input', async () => { + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(FIXTURE)); + const editor = await vscode.window.showTextDocument(doc); + + // Open a fresh name slot under `job_name:` at that key's indent, then ask for completions at the caret. + const lines = doc.getText().split('\n'); + const jobNameLine = lines.findIndex((l) => l.trim().startsWith('job_name:')); + assert.ok(jobNameLine !== -1, 'fixture missing a job_name input line'); + const keyIndent = doc.lineAt(jobNameLine).firstNonWhitespaceCharacterIndex; + const insertAt = new vscode.Position(jobNameLine, doc.lineAt(jobNameLine).text.length); + await editor.edit((b) => b.insert(insertAt, `\n${' '.repeat(keyIndent)}`)); + + const list = await vscode.commands.executeCommand( + 'vscode.executeCompletionItemProvider', + doc.uri, + new vscode.Position(jobNameLine + 1, keyIndent) + ); + const got = labels(list); + + assert.ok(!got.includes('<<'), `'<<' is a merge key, not an input. Got: ${JSON.stringify(got)}`); + assert.ok(got.includes('stage'), `expected the merged-in 'stage' input. Got: ${JSON.stringify(got)}`); + assert.ok(got.includes('region'), `expected the merged-in 'region' input. Got: ${JSON.stringify(got)}`); + }); +}); diff --git a/tests/fixtures/merge-key/.gitlab-ci.yml b/tests/fixtures/merge-key/.gitlab-ci.yml new file mode 100644 index 00000000..1adc123a --- /dev/null +++ b/tests/fixtures/merge-key/.gitlab-ci.yml @@ -0,0 +1,7 @@ +include: + - local: "merge-key/templates/deploy.yml" + inputs: + job_name: deploy-prod + # Deliberately unknown: gives the test a diagnostic to wait for, so asserting the *absence* of a + # missing-required-input for the merge-inherited inputs cannot pass before validation has run. + bogus_input: oops diff --git a/tests/fixtures/merge-key/templates/deploy.yml b/tests/fixtures/merge-key/templates/deploy.yml new file mode 100644 index 00000000..7e4472d4 --- /dev/null +++ b/tests/fixtures/merge-key/templates/deploy.yml @@ -0,0 +1,23 @@ +.common-inputs: &common + stage: + description: The stage the job runs in + type: string + default: deploy + region: + description: Target region + type: string + default: eu-west-1 + +spec: + inputs: + # `stage` and `region` arrive through the merge key. Both carry a default, so neither is required — a parser + # that leaves `<<` literal instead reports them missing and offers an input named `<<`. + <<: *common + job_name: + description: The name of the CI job + type: string +--- +$[[ inputs.job_name ]]: + stage: $[[ inputs.stage ]] + script: + - echo "deploy to $[[ inputs.region ]]" diff --git a/tests/unit/yamlParser.test.ts b/tests/unit/yamlParser.test.ts index e74eaadd..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 { parseYaml, 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', () => { @@ -67,6 +67,51 @@ test: 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', () => { From 48e72c10bb9060926c0a12318e7a175c0c7d6921 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 8 Sep 2026 23:59:37 +0000 Subject: [PATCH 11/27] chore(release): 0.17.3 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index edb1b29c..5b8f4265 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.2", + "version": "0.17.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.2", + "version": "0.17.3", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index f5265290..c36d2f2f 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.17.2", + "version": "0.17.3", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From dfed5024f9655d5cd272b122face22414811034a Mon Sep 17 00:00:00 2001 From: Cid-oe Date: Wed, 9 Sep 2026 17:01:48 +0530 Subject: [PATCH 12/27] fix(providers): match cached component templatePath regardless of ref (#276) (#278) --- src/providers/documentLinkProvider.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/providers/documentLinkProvider.ts b/src/providers/documentLinkProvider.ts index 498ac7c9..04e21579 100644 --- a/src/providers/documentLinkProvider.ts +++ b/src/providers/documentLinkProvider.ts @@ -88,8 +88,7 @@ export class ComponentDocumentLinkProvider implements vscode.DocumentLinkProvide (c) => c.gitlabInstance === parsed.gitlabInstance && c.sourcePath === parsed.path && - c.name === parsed.name && - (!parsed.version || c.version === parsed.version) + c.name === parsed.name ); // Only produce a link when the cache has a resolved templatePath for the component. Uncached components are From a83832c177e9acbeee274274fa4e208fb4fb9935 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 9 Sep 2026 11:34:29 +0000 Subject: [PATCH 13/27] chore(release): 0.17.4 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b8f4265..e1837c99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.3", + "version": "0.17.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.3", + "version": "0.17.4", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index c36d2f2f..25b46cbf 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.17.3", + "version": "0.17.4", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From e3cac4f9628788e3cb3364a1455d1d263dbfcbdc Mon Sep 17 00:00:00 2001 From: Simon Heather <32168619+X-Guardian@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:45:11 +0100 Subject: [PATCH 14/27] fix(details): make Refresh Versions work in the browser-opened details panel (#280) * fix(details): make Refresh Versions work in the browser-opened details panel * Fix test * fix(browser): label monorepo versions and surface version-change failures Ports the two gaps #281 caught into this branch. - The browser details panel's fetchVersions never sent versionLabels, so a refresh reverted the dropdown from '1.0.0' back to 'deploy-1.0.0' on a tag-per-component source. It now sends them like the detached panel does. - versionChangeError still hid the spinner and said nothing, the same silent failure this branch fixes one case block over. It now reports in the same slot, and both entry points clear a stale error before retrying. Rather than copy the label loop a third time, it moves to buildVersionLabels in tagScoping (pure, unit-tested) and the two existing copies collapse onto it. That also compiles the tag template once per list instead of once per tag. Co-authored-by: Cid-oe --------- Co-authored-by: Simon Heather Co-authored-by: eFAILution Co-authored-by: Cid-oe --- src/extension.ts | 41 ++++------- src/providers/componentBrowserProvider.ts | 73 ++++++++++---------- src/services/cache/componentCacheManager.ts | 9 ++- src/services/cache/versionCache.ts | 4 +- src/services/component/tagScoping.ts | 26 +++++++ src/services/component/versionLookupShape.ts | 29 ++++++++ src/types/cache.ts | 11 +++ tests/unit/tagScoping.test.ts | 32 +++++++-- tests/unit/versionLookupShape.test.ts | 56 +++++++++++++++ 9 files changed, 206 insertions(+), 75 deletions(-) create mode 100644 src/services/component/versionLookupShape.ts create mode 100644 tests/unit/versionLookupShape.test.ts diff --git a/src/extension.ts b/src/extension.ts index 876bfcc7..b4c54387 100755 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,33 +5,18 @@ 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 { buildVersionLabels } from './services/component/tagScoping'; import { getComponentCacheManager, ComponentCacheManager } from './services/cache/componentCacheManager'; import { Logger } from './utils/logger'; import { ValidationProvider } from './providers/validationProvider'; import type { CachedComponent } from './types/cache'; +import { isVersionLookupShape } from './services/component/versionLookupShape'; import type { GitLabYamlFragment } from './types/gitlab-catalog'; 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'; @@ -509,29 +494,27 @@ export function activate(context: vscode.ExtensionContext) { break; case 'fetchVersions': try { - if (!isCachedComponentShape(activeComponent)) { - throw new Error('Component is missing required fields (source, sourcePath, gitlabInstance, version) for version lookup.'); + if (!isVersionLookupShape(activeComponent)) { + throw new Error(`Cannot look up versions for ${activeComponent.name}: missing source path or GitLab instance.`); } - const versions = await cacheManager.fetchComponentVersions(activeComponent); + // Bind the narrowed value: `activeComponent` is reassignable, so TS widens it back across the await. + const lookupTarget = activeComponent; + const versions = await cacheManager.fetchComponentVersions(lookupTarget); // 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); - } - } + const versionLabels = buildVersionLabels(versions, lookupTarget.name, lookupTarget.tagPattern); panel.webview.postMessage({ command: 'versionsLoaded', versions: versions, versionLabels, - currentVersion: activeComponent.version + currentVersion: lookupTarget.version }); } catch (error) { + const reason = error instanceof Error ? error.message : String(error); + logger.error(`[Extension] Error fetching versions for detached details panel: ${reason}`, 'Extension'); panel.webview.postMessage({ command: 'versionsError', - error: error instanceof Error ? error.message : String(error) + error: reason }); } break; diff --git a/src/providers/componentBrowserProvider.ts b/src/providers/componentBrowserProvider.ts index 4d93a058..428222ed 100644 --- a/src/providers/componentBrowserProvider.ts +++ b/src/providers/componentBrowserProvider.ts @@ -3,7 +3,7 @@ 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'; @@ -14,7 +14,7 @@ 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'; /** * Component shape carried through the detach-hover webview's "Open in Detailed View" round trip. @@ -24,19 +24,6 @@ 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'; -} /** * Pre-existing component shape parsed out of a `.gitlab-ci.yml` include line by @@ -553,19 +540,25 @@ export class ComponentBrowserProvider { } else if (message.command === 'fetchVersions') { // Fetch available versions for the component try { - if (!isCachedComponentShape(component)) { - throw new Error('Component is missing required fields (source, sourcePath, gitlabInstance, version) for version lookup.'); + if (!isVersionLookupShape(component)) { + throw new Error(`Cannot look up versions for ${component.name}: missing source path or GitLab instance.`); } const versions = await this.cacheManager.fetchComponentVersions(component); + // 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. + const versionLabels = buildVersionLabels(versions, component.name, component.tagPattern); detailsPanel.webview.postMessage({ command: 'versionsLoaded', versions: versions, + versionLabels, currentVersion: component.version }); } catch (error) { + const reason = error instanceof Error ? error.message : String(error); + this.logger.error(`[ComponentBrowser] Error fetching versions: ${reason}`, 'ComponentBrowser'); detailsPanel.webview.postMessage({ command: 'versionsError', - error: error instanceof Error ? error.message : String(error) + error: reason }); } } else if (message.command === 'versionChanged') { @@ -1633,6 +1626,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 +1909,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 +1925,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 +2104,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 +2151,7 @@ export class ComponentBrowserProvider { }); loading.style.display = 'none'; + loading.classList.remove('version-error'); select.disabled = false; currentVersions = versions; versionsLoaded = true; @@ -2800,16 +2812,7 @@ ${sourceErrors.size > 0 ? '\nErrors:\n' + Array.from(sourceErrors.entries()).map // For a monorepo source, precompute display labels (full tag → stripped {version}) server-side, since the // webview can't reach the template matcher. Non-monorepo sources send no labels (value == label). - let versionLabels: Record | undefined; - if (updatedComponent.tagPattern) { - const matcher = compileTagTemplate(updatedComponent.tagPattern, componentName); - if (matcher) { - versionLabels = {}; - for (const v of availableVersions) { - versionLabels[v] = matcher.extractVersion(v) ?? v; - } - } - } + const versionLabels = buildVersionLabels(availableVersions, componentName, updatedComponent.tagPattern); // Send versions to webview if (this.panel) { diff --git a/src/services/cache/componentCacheManager.ts b/src/services/cache/componentCacheManager.ts index 2a76ae13..411361ed 100644 --- a/src/services/cache/componentCacheManager.ts +++ b/src/services/cache/componentCacheManager.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import { getComponentService } from '../component'; import { Logger } from '../../utils/logger'; import { getPerformanceMonitor } from '../../utils/performanceMonitor'; -import { CachedComponent, PersistentCacheData } from '../../types/cache'; +import { CachedComponent, PersistentCacheData, VersionLookupComponent } from '../../types/cache'; import { ComponentSource } from '../../types/api'; import { reconcileComponentSource } from './sourceReconciliation'; import { ProjectCache } from './projectCache'; @@ -424,9 +424,12 @@ export class ComponentCacheManager implements vscode.Disposable { } /** - * Fetch and cache all available versions for a specific component + * Fetch and cache all available versions for a specific component. + * + * Takes the narrow {@link VersionLookupComponent} rather than a full cache entry: the lookup is driven entirely by + * the project coordinates, so callers holding a partial component (the details panel) can use it too. */ - public async fetchComponentVersions(component: CachedComponent): Promise { + public async fetchComponentVersions(component: VersionLookupComponent): Promise { try { const sortedVersions = await this.versionCache.fetchComponentVersions(component); diff --git a/src/services/cache/versionCache.ts b/src/services/cache/versionCache.ts index 9e7dfaed..75e9a46a 100644 --- a/src/services/cache/versionCache.ts +++ b/src/services/cache/versionCache.ts @@ -1,7 +1,7 @@ import { getComponentService } from '../component'; import { compileTagTemplate, scopeTagsToComponent } from '../component/tagScoping'; import { Logger } from '../../utils/logger'; -import { CachedComponent, VersionCacheSnapshot } from '../../types/cache'; +import { VersionCacheSnapshot, VersionLookupComponent } from '../../types/cache'; /** * VersionCache - Handles version fetching and caching for components @@ -30,7 +30,7 @@ export class VersionCache { * @param component Component to fetch versions for * @returns Array of sorted version strings (full prefixed tags for monorepo sources, plus `main`/`master`) */ - async fetchComponentVersions(component: CachedComponent): Promise { + async fetchComponentVersions(component: VersionLookupComponent): Promise { try { const cacheKey = `${component.gitlabInstance}|${component.sourcePath}`; let projectTags: string[] | undefined = this.projectTagsCache.get(cacheKey); diff --git a/src/services/component/tagScoping.ts b/src/services/component/tagScoping.ts index a8eb1d32..57a12963 100644 --- a/src/services/component/tagScoping.ts +++ b/src/services/component/tagScoping.ts @@ -132,3 +132,29 @@ export function stripTagPrefix(tag: string, componentName: string, template?: st const matcher = compileTagTemplate(template, componentName); return matcher?.extractVersion(tag) ?? tag; } + +/** + * Build the display-label map the version dropdown uses: full tag → stripped `{version}`. + * + * Returns `undefined` when the source is not a tag-per-component monorepo (no template, or one that doesn't + * compile), which is the "no labels — value is the label" signal the webview already falls back on. The template is + * compiled once for the whole list rather than per tag. + * + * @param versions The full tags to label. + * @param componentName The component name substituted for `{name}`. + * @param template The per-source tag-version template. Absent for ordinary sources. + */ +export function buildVersionLabels( + versions: string[], + componentName: string, + template?: string +): Record | undefined { + if (!template) { + return undefined; + } + const matcher = compileTagTemplate(template, componentName); + if (!matcher) { + return undefined; + } + return Object.fromEntries(versions.map((tag) => [tag, matcher.extractVersion(tag) ?? tag])); +} diff --git a/src/services/component/versionLookupShape.ts b/src/services/component/versionLookupShape.ts new file mode 100644 index 00000000..bab8a247 --- /dev/null +++ b/src/services/component/versionLookupShape.ts @@ -0,0 +1,29 @@ +/** + * Shared type-guard for "can this component be used to look up versions?". + * + * `vscode`-free and pure so the unit suite can drive it directly. Both details-panel entry points check the same + * thing, so they share one definition rather than a copy each. + */ + +import type { Component } from '../../providers/componentDetector'; +import type { VersionLookupComponent } from '../../types/cache'; + +/** + * Narrow a `Component` to the fields a version lookup needs: the project coordinates to query and the ref to fall + * back on. `Component` carries all three as optional, so they are checked before calling the cache. + * + * Deliberately does **not** require `url` or `source`. The details panel's component is rebuilt in the webview from + * a `ComponentVersion`, which has no `url`, and nothing in the lookup path reads one — `fetchComponentVersions` + * queries by `gitlabInstance` + `sourcePath` and scopes by `tagPattern`. Demanding `url` here only rejects + * components the cache could have served. + * + * @param component The component to check. + * @returns `true` when `sourcePath`, `gitlabInstance` and `version` are all present and string-typed. + */ +export function isVersionLookupShape( + component: Component +): component is Component & VersionLookupComponent { + return typeof component.sourcePath === 'string' + && typeof component.gitlabInstance === 'string' + && typeof component.version === 'string'; +} diff --git a/src/types/cache.ts b/src/types/cache.ts index 535b8d5f..6fd173e8 100644 --- a/src/types/cache.ts +++ b/src/types/cache.ts @@ -110,6 +110,17 @@ export interface CachedComponent { tagPattern?: string; } +/** + * The subset of {@link CachedComponent} a version lookup actually needs: the project coordinates to query, the + * current ref to fall back on, and the monorepo template used to scope the returned tags. + * + * Version fetching is reachable from surfaces that hold less than a full cache entry — the details panel receives a + * `ComponentVersion` built in the webview, which carries no `url`. Naming the real requirement lets those callers + * through instead of failing a `CachedComponent` check on fields the lookup never reads. + */ +export type VersionLookupComponent = Pick + & Pick; + /** * Serialized form of the per-project version caches, persisted in global state. * 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); + }); +}); From 70e144c6f5b5391faa7d4a1cfa389288d31f9c7c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 13:48:46 +0000 Subject: [PATCH 15/27] chore(release): 0.17.5 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e1837c99..59f8e9b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.4", + "version": "0.17.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.4", + "version": "0.17.5", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index 25b46cbf..5d3344bc 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.17.4", + "version": "0.17.5", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From b020d2d652237d8c114d00dd442f8df853a73180 Mon Sep 17 00:00:00 2001 From: Simon Heather <32168619+X-Guardian@users.noreply.github.com> Date: Fri, 11 Sep 2026 12:54:45 +0100 Subject: [PATCH 16/27] refactor(webview): serve loading-view CSS from linted external file under CSP (#275) * refactor(webview): serve loading-view CSS from linted external file under CSP * Bump stylelint version * Fix review comments --------- Co-authored-by: Simon Heather --- .ai/architecture.yaml | 16 +- .ai/workflows.yaml | 1 + .github/workflows/ci.yml | 2 +- esbuild.js | 147 ++- package-lock.json | 1336 ++++++++++++++++++++- package.json | 11 +- src/providers/componentBrowserProvider.ts | 40 +- src/webview/styles/loading.css | 31 + src/webview/webviewHtml.ts | 65 + stylelint.config.mjs | 8 + 10 files changed, 1566 insertions(+), 91 deletions(-) create mode 100644 src/webview/styles/loading.css create mode 100644 src/webview/webviewHtml.ts create mode 100644 stylelint.config.mjs diff --git a/.ai/architecture.yaml b/.ai/architecture.yaml index c96e7296..b0d8a868 100644 --- a/.ai/architecture.yaml +++ b/.ai/architecture.yaml @@ -77,14 +77,16 @@ 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) + 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: 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/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/esbuild.js b/esbuild.js index 8eec0ae0..7303585b 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, + 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/package-lock.json b/package-lock.json index 59f8e9b0..340aebd8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "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.8", @@ -31,6 +32,7 @@ "dotenv": "^17.4.2", "esbuild": "^0.28.2", "eslint": "^10.9.1", + "eslint-formatter-gha": "^2.0.1", "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", @@ -40,6 +42,8 @@ "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", + "stylelint": "^17.15.0", + "stylelint-config-standard": "^40.0.0", "tsx": "^4.23.13", "typescript": "^6.0.3", "typescript-eslint": "^8.69.0" @@ -74,6 +78,67 @@ "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/memory/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", + "dependencies": { + "hashery": "^1.4.0", + "hookified": "^1.15.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/memory/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, + "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/@cacheable/utils/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/@commitlint/cli": { "version": "21.2.2", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-21.2.2.tgz", @@ -375,6 +440,191 @@ "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", @@ -1421,6 +1671,51 @@ } } }, + "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/@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": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "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", + "engines": { + "node": ">= 8" + } + }, + "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": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@octokit/auth-token": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", @@ -1814,6 +2109,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", @@ -2318,6 +2626,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", @@ -2633,6 +2951,30 @@ } } }, + "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", + "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/cacheable/node_modules/keyv": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@keyv/serialize": "^1.1.1" + } + }, "node_modules/cachedir": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", @@ -2946,6 +3288,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", @@ -3226,9 +3575,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": { @@ -3308,6 +3657,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", @@ -4036,22 +4422,134 @@ } } }, - "node_modules/eslint-scope": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "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": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { + "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", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { "url": "https://opencollective.com/eslint" } }, @@ -4259,6 +4757,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", @@ -4317,6 +4845,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", @@ -4801,6 +5349,48 @@ "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/globby/node_modules/is-path-inside": { + "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": ">=12" + }, + "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", @@ -4902,6 +5492,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", @@ -4928,6 +5531,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", @@ -5011,9 +5634,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": { @@ -5054,6 +5677,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", @@ -6037,6 +6671,16 @@ "json-buffer": "3.0.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": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6173,6 +6817,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", @@ -6306,6 +6957,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", @@ -6315,6 +6984,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", @@ -6322,6 +7004,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", @@ -6506,6 +7198,25 @@ "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/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6559,6 +7270,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", @@ -7374,10 +8095,87 @@ "node": ">= 0.4" } }, - "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==", + "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==", "dev": true, "license": "MIT", "engines": { @@ -7519,6 +8317,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", @@ -7982,6 +8821,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", @@ -8016,6 +8866,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", @@ -8307,6 +9181,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", @@ -8369,6 +9310,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", @@ -8571,6 +9522,231 @@ "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/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^6.1.23" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" + } + }, + "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", @@ -8584,6 +9760,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", @@ -8597,6 +9816,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", @@ -8899,6 +10148,19 @@ "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", @@ -9206,6 +10468,32 @@ "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", diff --git a/package.json b/package.json index 5d3344bc..18f85da2 100644 --- a/package.json +++ b/package.json @@ -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,6 +311,7 @@ "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.8", @@ -326,6 +332,7 @@ "dotenv": "^17.4.2", "esbuild": "^0.28.2", "eslint": "^10.9.1", + "eslint-formatter-gha": "^2.0.1", "globals": "^17.12.0", "husky": "^9.1.6", "is-ci": "^4.0.0", @@ -335,6 +342,8 @@ "npm-run-all": "^4.1.5", "release-it": "^21.0.2", "semver": "^7.8.5", + "stylelint": "^17.15.0", + "stylelint-config-standard": "^40.0.0", "tsx": "^4.23.13", "typescript": "^6.0.3", "typescript-eslint": "^8.69.0" diff --git a/src/providers/componentBrowserProvider.ts b/src/providers/componentBrowserProvider.ts index 428222ed..8e176fb7 100644 --- a/src/providers/componentBrowserProvider.ts +++ b/src/providers/componentBrowserProvider.ts @@ -15,6 +15,7 @@ import { generateComponentText } from './componentBrowserGenerate'; import { findComponentLineRange, parseExistingComponentText } from './componentBrowserEdit'; import { transformCachedComponentsToGroups } from './componentBrowserTransform'; import { buildVersionLabels, compileTagTemplate, stripTagPrefix } from '../services/component/tagScoping'; +import { assetUri, createNonce, cspMetaTag } from '../webview/webviewHtml'; /** * Component shape carried through the detach-hover webview's "Open in Detailed View" round trip. @@ -75,13 +76,13 @@ export class ComponentBrowserProvider { enableScripts: true, retainContextWhenHidden: true, localResourceRoots: [ - vscode.Uri.joinPath(this.context.extensionUri, 'media') + vscode.Uri.joinPath(this.context.extensionUri, 'out', 'webview') ] } ); // 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(() => { @@ -152,7 +153,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'); @@ -605,39 +606,18 @@ export class ComponentBrowserProvider { ); } - private getLoadingHtml(): string { + private getLoadingHtml(webview: vscode.Webview): string { + const nonce = createNonce(); + const styleUri = assetUri(webview, this.context.extensionUri, 'styles/loading.css'); return ` + ${cspMetaTag(webview, nonce)} + GitLab CI/CD Components -
@@ -2528,7 +2508,7 @@ ${sourceErrors.size > 0 ? '\nErrors:\n' + Array.from(sourceErrors.entries()).map // Clear the browser and show empty state if (this.panel) { - this.panel.webview.html = this.getLoadingHtml(); + this.panel.webview.html = this.getLoadingHtml(this.panel.webview); } // Reload components in the browser (this will fetch fresh data) diff --git a/src/webview/styles/loading.css b/src/webview/styles/loading.css new file mode 100644 index 00000000..9460b326 --- /dev/null +++ b/src/webview/styles/loading.css @@ -0,0 +1,31 @@ +body { + font-family: var(--vscode-font-family); + color: var(--vscode-editor-foreground); + padding: 20px; + background-color: var(--vscode-editor-background); +} + +.loading { + text-align: center; + padding: 40px; +} + +.spinner { + border: 4px solid rgb(0 0 0 / 10%); + width: 36px; + height: 36px; + border-radius: 50%; + border-left-color: var(--vscode-button-background); + animation: spin 1s linear infinite; + margin: 0 auto 20px; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/src/webview/webviewHtml.ts b/src/webview/webviewHtml.ts new file mode 100644 index 00000000..0b3ff864 --- /dev/null +++ b/src/webview/webviewHtml.ts @@ -0,0 +1,65 @@ +import * as vscode from 'vscode'; + +/** + * Shared helpers for rendering webview HTML with a Content-Security-Policy, + * a per-render nonce, and webview-safe asset URIs. + * + * VS Code webviews cannot load extension files by path: every / & '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}`); + } + }); +}); From 4ba468adfd90a7f648dd2391040b2265882e308c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Sep 2026 01:49:12 +0000 Subject: [PATCH 25/27] chore(release): 0.17.10 [skip ci] --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2c86d2cc..33efbcb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gitlab-component-helper", - "version": "0.17.9", + "version": "0.17.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gitlab-component-helper", - "version": "0.17.9", + "version": "0.17.10", "license": "MIT", "devDependencies": { "@commitlint/cli": "^21.2.2", diff --git a/package.json b/package.json index 788cb609..6c110cb6 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.17.9", + "version": "0.17.10", "icon": "images/icon.png", "engines": { "node": ">=22.0.0", From 8a9374500072e47cea57eb9aece48711a36bbe6d Mon Sep 17 00:00:00 2001 From: eFAILution <128437814+eFAILution@users.noreply.github.com> Date: Mon, 14 Sep 2026 22:06:05 -0400 Subject: [PATCH 26/27] fix(ai): repair dangling component references in architecture.yaml (#298) The AICaC Adoption check has been failing since #275: architecture.yaml[providers].depends_on references unknown component 'templates' #275 correctly renamed the 'templates' component to 'webview' when src/templates/ was removed, but left providers.depends_on pointing at the old name. Repointed at 'webview', which is what the providers actually import (componentBrowserProvider pulls in inlineMarkdown, scriptData, webviewHtml and clientInlineMarkdown). aicac.yml triggers only on main, so no beta PR runs it. The failures surface on the open release PR #271 (beta -> main), which re-runs on every push to beta, and would follow onto main itself on merge. Two adjacent staleness issues the checker does not catch, fixed while here: - providers.files listed componentHtmlRenderer.ts, deleted as dead code in #158. Replaced with hoverContentBuilder.ts, which holds that role now. - The hover_documentation data flow named the same deleted file and claimed it renders HTML 'using templates/helpers'. Hover builds a MarkdownString; there are no HTML templates in that path and no src/templates/ directory. Also lists clientInlineMarkdown.ts under the webview component, added in #290. Co-authored-by: eFAILution --- .ai/architecture.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.ai/architecture.yaml b/.ai/architecture.yaml index b0d8a868..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 @@ -84,6 +84,7 @@ components: 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. @@ -215,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 From 7ebd81a0bb9faa2088a810c926d5090677360f7d Mon Sep 17 00:00:00 2001 From: eFAILution <128437814+eFAILution@users.noreply.github.com> Date: Tue, 15 Sep 2026 02:06:25 +0000 Subject: [PATCH 27/27] chore(ai): regenerate .ai/index.yaml --- .ai/index.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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