From 5b30b8acf85ffbd16e792532ab7fcb186a645324 Mon Sep 17 00:00:00 2001 From: RainbowBird Date: Fri, 9 Oct 2026 17:26:20 +0800 Subject: [PATCH 1/2] feat: add the alint action The action installs alint, writes the provider configuration, and restores the cache. Then it lints the changed files of a pull request and keeps the findings on changed lines. It publishes a check run with line annotations, one summary comment, and a job summary. The check run fails only when a finding is an error. Co-authored-by: Neko Ayaka Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 47 + README.md | 86 +- action.yml | 116 + dist/index.mjs | 1121 ++++++++++ eslint.config.ts | 22 + package.json | 34 + pnpm-lock.yaml | 4078 ++++++++++++++++++++++++++++++++++ src/changes.test.ts | 72 + src/changes.ts | 73 + src/findings.test.ts | 95 + src/findings.ts | 144 ++ src/github.ts | 119 + src/index.ts | 11 + src/lint.ts | 17 + src/main.test.ts | 253 +++ src/main.ts | 140 ++ src/output.ts | 25 + test/fixture/alint.config.ts | 30 + test/fixture/src/add.ts | 4 + tsconfig.json | 17 + tsdown.config.ts | 9 + 21 files changed, 6512 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml create mode 100644 action.yml create mode 100644 dist/index.mjs create mode 100644 eslint.config.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 src/changes.test.ts create mode 100644 src/changes.ts create mode 100644 src/findings.test.ts create mode 100644 src/findings.ts create mode 100644 src/github.ts create mode 100644 src/index.ts create mode 100644 src/lint.ts create mode 100644 src/main.test.ts create mode 100644 src/main.ts create mode 100644 src/output.ts create mode 100644 test/fixture/alint.config.ts create mode 100644 test/fixture/src/add.ts create mode 100644 tsconfig.json create mode 100644 tsdown.config.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9b44a05 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +jobs: + check: + name: Lint, typecheck, test, and build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v6 + with: + node-version: lts/* + cache: pnpm + - run: pnpm install + - run: pnpm lint + - run: pnpm typecheck + - run: pnpm test:run + - run: pnpm build + # The action runs the committed bundle, so it must match the source. + - name: Check that dist is current + run: git diff --exit-code -- dist + + e2e: + name: Run the action on the fixture + # The fixture rule reports a finding only on changed lines, and only a pull request has changed lines. + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + permissions: + checks: write + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v6 + - id: alint + uses: ./ + with: + version: 0.7.3 + working-directory: test/fixture + check-name: alint (fixture) + - name: Report the outputs + run: echo "errors=${{ steps.alint.outputs.errors }} warnings=${{ steps.alint.outputs.warnings }}" diff --git a/README.md b/README.md index d701f7b..565fb2f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,87 @@ # alint-dev/setup -GitHub Action that runs `alint` on a pull request and publishes the result. +GitHub Action that runs [`alint`](https://github.com/alint-dev/alint) on a pull request and publishes the result. + +The action does these steps: + +1. Installs `alint`. +2. Writes the model provider configuration. +3. Restores the `alint` cache. +4. Lints the changed files of the pull request and keeps the findings on changed lines. +5. Publishes a check run with line annotations, one summary comment, and a job summary. + +## Usage + +```yaml +name: alint + +on: + pull_request: + +jobs: + alint: + runs-on: ubuntu-latest + permissions: + checks: write + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v6 + - uses: alint-dev/setup@main + with: + provider-endpoint: https://api.openai.com/v1 + provider-model: gpt-5.4-mini + api-key: ${{ secrets.OPENAI_API_KEY }} +``` + +If the `alint` configuration imports packages, install the project dependencies before this action. + +## Inputs + +| Input | Default | Description | +| --- | --- | --- | +| `version` | | Version of `@alint-js/cli` to install. When empty, the action uses the `alint` in `node_modules`, or installs the latest version. | +| `provider-endpoint` | | Endpoint of an OpenAI-compatible model provider. When empty, the action does not write provider configuration. | +| `provider-model` | | Model id for the provider. Required with `provider-endpoint`. | +| `api-key` | | API key for the provider. The action sends it as a Bearer token. | +| `files` | | Files or directories to lint, separated by spaces or lines. | +| `working-directory` | `.` | Directory that contains the `alint` configuration. | +| `check-name` | `alint` | Name of the check run. | +| `github-token` | `github.token` | Token that creates the check run and the summary comment. | + +## Outputs + +| Output | Description | +| --- | --- | +| `errors` | Number of error findings. | +| `warnings` | Number of warning findings. | + +## Behavior + +- The check run fails when a finding is an error. It is neutral when there are only warnings, and it passes when there are no findings. +- The step itself fails only when `alint` cannot complete the run or GitHub rejects a request. +- Each run rewrites the same summary comment. A pull request that never had findings gets no comment. +- On a pull request, the action reads the changed files from the GitHub API. The checkout does not need the full history. +- When `files` is set, the action lints those files and keeps each finding. +- On other events, the action lints the working directory and writes no comment. +- A pull request from a fork gets no secrets and a read-only token. The action skips it with a notice. + +## When not to use it + +Do not use this action for local runs or for a CI system other than GitHub Actions. Run the `alint` CLI there. + +## Development + +```bash +pnpm install +pnpm test:run +pnpm build +``` + +The action runs `dist/index.mjs`. Run `pnpm build` and commit `dist` with each source change. CI fails when `dist` does not match the source. + +The `e2e` job runs the action on `test/fixture`. Its rule does not call a model, so the job needs no provider. + +## License + +MIT diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..d54f84d --- /dev/null +++ b/action.yml @@ -0,0 +1,116 @@ +name: alint +description: Run alint on a pull request and publish the result as a check run and a summary comment +author: alint-dev +branding: + icon: check-circle + color: purple + +inputs: + version: + description: >- + Version of @alint-js/cli to install. When empty, the action uses the alint that the project + installed in node_modules, or installs the latest version. + default: '' + provider-endpoint: + description: >- + Endpoint of an OpenAI-compatible model provider. When empty, the action does not write + provider configuration. + default: '' + provider-model: + description: Model id for the provider. Required with provider-endpoint. + default: '' + api-key: + description: API key for the provider. The action sends it as a Bearer token. + default: '' + files: + description: >- + Files or directories to lint, separated by spaces or lines. When empty, a pull request gets + its changed lines and other events get the working directory. + default: '' + working-directory: + description: Directory that contains the alint configuration. + default: . + check-name: + description: Name of the check run. + default: alint + github-token: + description: Token that creates the check run and the summary comment. + default: ${{ github.token }} + +outputs: + errors: + description: Number of error findings. + value: ${{ steps.run.outputs.errors }} + warnings: + description: Number of warning findings. + value: ${{ steps.run.outputs.warnings }} + +runs: + using: composite + steps: + # A pull request from a fork gets no secrets and a read-only token, so the action cannot publish there. + - id: guard + shell: bash + run: | + if [ "$GITHUB_EVENT_NAME" = "pull_request" ] && [ "$(jq -r '.pull_request.head.repo.full_name' "$GITHUB_EVENT_PATH")" != "$GITHUB_REPOSITORY" ]; then + echo "::notice title=alint::Skipped. A pull request from a fork cannot publish the result." + echo "skip=true" >> "$GITHUB_OUTPUT" + fi + + - id: install + if: steps.guard.outputs.skip != 'true' + shell: bash + working-directory: ${{ inputs.working-directory }} + env: + ALINT_VERSION: ${{ inputs.version }} + run: | + if [ -z "$ALINT_VERSION" ] && [ -x node_modules/.bin/alint ]; then + echo "command=$PWD/node_modules/.bin/alint" >> "$GITHUB_OUTPUT" + else + npm install --global "@alint-js/cli@${ALINT_VERSION:-latest}" + echo "command=alint" >> "$GITHUB_OUTPUT" + fi + + - if: steps.guard.outputs.skip != 'true' && inputs.provider-endpoint != '' + shell: bash + env: + ALINT: ${{ steps.install.outputs.command }} + ALINT_API_KEY: ${{ inputs.api-key }} + ALINT_ENDPOINT: ${{ inputs.provider-endpoint }} + ALINT_MODEL: ${{ inputs.provider-model }} + run: | + "$ALINT" setup --no-interactive \ + --provider-id ci \ + --provider-endpoint "$ALINT_ENDPOINT" \ + --provider-model "$ALINT_MODEL" \ + ${ALINT_API_KEY:+--provider-header "Authorization=Bearer $ALINT_API_KEY"} + + - if: steps.guard.outputs.skip != 'true' + shell: bash + working-directory: ${{ inputs.working-directory }} + env: + ALINT: ${{ steps.install.outputs.command }} + run: | + "$ALINT" plugin install + + - if: steps.guard.outputs.skip != 'true' + uses: actions/cache@v4 + with: + path: ${{ inputs.working-directory }}/.alintcache + # alint keys each cached result by the file content and the rule text. + # A new key for each commit saves the latest cache, and the prefix restores the most recent one. + key: alint-${{ runner.os }}-${{ github.sha }} + restore-keys: | + alint-${{ runner.os }}- + + - id: run + if: steps.guard.outputs.skip != 'true' + shell: bash + working-directory: ${{ inputs.working-directory }} + env: + ALINT_COMMAND: ${{ steps.install.outputs.command }} + GITHUB_TOKEN: ${{ inputs.github-token }} + INPUT_CHECK_NAME: ${{ inputs.check-name }} + INPUT_FILES: ${{ inputs.files }} + run: | + node "$GITHUB_ACTION_PATH/dist/index.mjs" diff --git a/dist/index.mjs b/dist/index.mjs new file mode 100644 index 0000000..839e027 --- /dev/null +++ b/dist/index.mjs @@ -0,0 +1,1121 @@ +import process$1, { cwd } from "node:process"; +import { closeSync, existsSync, openSync, readSync, statSync } from "node:fs"; +import { appendFile, readFile } from "node:fs/promises"; +import { spawn } from "node:child_process"; +import { basename, delimiter, dirname, normalize, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import { pipeline } from "node:stream/promises"; +import { PassThrough } from "node:stream"; +import readline from "node:readline"; +//#region node_modules/.pnpm/@moeru+std@0.1.0-beta.20/node_modules/@moeru/std/dist/error/index.js +const isError = (err) => { + if ("isError" in Error && Error.isError(new DOMException())) return Error.isError(err); + if (err === null || typeof err !== "object" && typeof err !== "function") return false; + if (err instanceof Error) return true; + const tag = Object.prototype.toString.call(err); + return tag === "[object DOMException]" || tag === "[object Error]"; +}; +const isErrorLike = (err) => { + if (isError(err)) return true; + if (err == null || typeof err !== "object" && typeof err !== "function") return false; + return "message" in err && typeof err.message === "string" && "name" in err && typeof err.name === "string"; +}; +const errorMessageFrom = (err) => isErrorLike(err) ? err.message : err == null ? void 0 : String(err); +//#endregion +//#region node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs +const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//; +function normalizeWindowsPath(input = "") { + if (!input) return input; + return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase()); +} +const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/; +const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/; +function cwd$1() { + if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/"); + return "/"; +} +const resolve$1 = function(...arguments_) { + arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument)); + let resolvedPath = ""; + let resolvedAbsolute = false; + for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) { + const path = index >= 0 ? arguments_[index] : cwd$1(); + if (!path || path.length === 0) continue; + resolvedPath = `${path}/${resolvedPath}`; + resolvedAbsolute = isAbsolute(path); + } + resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute); + if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`; + return resolvedPath.length > 0 ? resolvedPath : "."; +}; +function normalizeString(path, allowAboveRoot) { + let res = ""; + let lastSegmentLength = 0; + let lastSlash = -1; + let dots = 0; + let char = null; + for (let index = 0; index <= path.length; ++index) { + if (index < path.length) char = path[index]; + else if (char === "/") break; + else char = "/"; + if (char === "/") { + if (lastSlash === index - 1 || dots === 1); + else if (dots === 2) { + if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") { + if (res.length > 2) { + const lastSlashIndex = res.lastIndexOf("/"); + if (lastSlashIndex === -1) { + res = ""; + lastSegmentLength = 0; + } else { + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf("/"); + } + lastSlash = index; + dots = 0; + continue; + } else if (res.length > 0) { + res = ""; + lastSegmentLength = 0; + lastSlash = index; + dots = 0; + continue; + } + } + if (allowAboveRoot) { + res += res.length > 0 ? "/.." : ".."; + lastSegmentLength = 2; + } + } else { + if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`; + else res = path.slice(lastSlash + 1, index); + lastSegmentLength = index - lastSlash - 1; + } + lastSlash = index; + dots = 0; + } else if (char === "." && dots !== -1) ++dots; + else dots = -1; + } + return res; +} +const isAbsolute = function(p) { + return _IS_ABSOLUTE_RE.test(p); +}; +const relative = function(from, to) { + const _from = resolve$1(from).replace(_ROOT_FOLDER_RE, "$1").split("/"); + const _to = resolve$1(to).replace(_ROOT_FOLDER_RE, "$1").split("/"); + if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) return _to.join("/"); + const _fromCopy = [..._from]; + for (const segment of _fromCopy) { + if (_to[0] !== segment) break; + _from.shift(); + _to.shift(); + } + return [..._from.map(() => ".."), ..._to].join("/"); +}; +const DEFAULT_CONFIG = { + lang: void 0, + message: void 0, + abortEarly: void 0, + abortPipeEarly: void 0 +}; +/** +* Returns the global configuration. +* +* @param config The config to merge. +* +* @returns The configuration. +*/ +/* @__NO_SIDE_EFFECTS__ */ +function getGlobalConfig(config$1) { + if (!config$1 && true) return DEFAULT_CONFIG; + return { + lang: config$1?.lang ?? void 0, + message: config$1?.message, + abortEarly: config$1?.abortEarly ?? void 0, + abortPipeEarly: config$1?.abortPipeEarly ?? void 0 + }; +} +/** +* Stringifies an unknown input to a literal or type string. +* +* @param input The unknown input. +* +* @returns A literal or type string. +* +* @internal +*/ +/* @__NO_SIDE_EFFECTS__ */ +function _stringify(input) { + const type = typeof input; + if (type === "string") return `"${input}"`; + if (type === "number" || type === "bigint" || type === "boolean") return `${input}`; + if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null"; + return type; +} +/** +* Adds an issue to the dataset. +* +* @param context The issue context. +* @param label The issue label. +* @param dataset The input dataset. +* @param config The configuration. +* @param other The optional props. +* +* @internal +*/ +function _addIssue(context, label, dataset, config$1, other) { + const input = other && "input" in other ? other.input : dataset.value; + const expected = other?.expected ?? context.expects ?? null; + const received = other?.received ?? /* @__PURE__ */ _stringify(input); + const issue = { + kind: context.kind, + type: context.type, + input, + expected, + received, + message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`, + requirement: context.requirement, + path: other?.path, + issues: other?.issues, + lang: config$1.lang, + abortEarly: config$1.abortEarly, + abortPipeEarly: config$1.abortPipeEarly + }; + const isSchema = context.kind === "schema"; + const message$1 = other?.message ?? context.message ?? (context.reference, issue.lang, void 0) ?? (isSchema ? (issue.lang, void 0) : null) ?? config$1.message ?? (issue.lang, void 0); + if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1; + if (isSchema) dataset.typed = false; + if (dataset.issues) dataset.issues.push(issue); + else dataset.issues = [issue]; +} +/** +* Joins multiple `expects` values with the given separator. +* +* @param values The `expects` values. +* @param separator The separator. +* +* @returns The joined `expects` property. +* +* @internal +*/ +/* @__NO_SIDE_EFFECTS__ */ +function _joinExpects(values$1, separator) { + const list = [...new Set(values$1)]; + if (list.length > 1) return `(${list.join(` ${separator} `)})`; + return list[0] ?? "never"; +} +/** +* Eagerly creates and attaches the Standard Schema properties of a schema. +* +* Hint: The contextual `this` type includes the standard properties that are +* attached before the schema is returned. +* +* @param schema The schema to attach standard properties to. +* +* @returns The schema with standard properties attached. +* +* @internal +*/ +function _standardSchema(schema) { + schema["~standard"] = { + version: 1, + vendor: "valibot", + validate: (value$1) => schema["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig()) + }; + return schema; +} +/** +* A Valibot error with useful information. +*/ +var ValiError = class extends Error { + /** + * Creates a Valibot error with useful information. + * + * @param issues The error issues. + */ + constructor(issues) { + super(issues[0].message); + this.name = "ValiError"; + this.issues = issues; + } +}; +/** +* Returns the fallback value of the schema. +* +* @param schema The schema to get it from. +* @param dataset The output dataset if available. +* @param config The config if available. +* +* @returns The fallback value. +*/ +/* @__NO_SIDE_EFFECTS__ */ +function getFallback(schema, dataset, config$1) { + return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback; +} +/** +* Returns the default value of the schema. +* +* @param schema The schema to get it from. +* @param dataset The input dataset if available. +* @param config The config if available. +* +* @returns The default value. +*/ +/* @__NO_SIDE_EFFECTS__ */ +function getDefault(schema, dataset, config$1) { + return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default; +} +/* @__NO_SIDE_EFFECTS__ */ +function array(item, message$1) { + return _standardSchema({ + kind: "schema", + type: "array", + reference: array, + expects: "Array", + async: false, + item, + message: message$1, + "~run"(dataset, config$1) { + const input = dataset.value; + if (Array.isArray(input)) { + dataset.typed = true; + dataset.value = []; + for (let key = 0; key < input.length; key++) { + const value$1 = input[key]; + const itemDataset = this.item["~run"]({ value: value$1 }, config$1); + if (itemDataset.issues) { + const pathItem = { + type: "array", + origin: "value", + input, + key, + value: value$1 + }; + for (const issue of itemDataset.issues) { + if (issue.path) issue.path.unshift(pathItem); + else issue.path = [pathItem]; + dataset.issues?.push(issue); + } + if (!dataset.issues) dataset.issues = itemDataset.issues; + if (config$1.abortEarly) { + dataset.typed = false; + break; + } + } + if (!itemDataset.typed) dataset.typed = false; + dataset.value.push(itemDataset.value); + } + } else _addIssue(this, "type", dataset, config$1); + return dataset; + } + }); +} +/* @__NO_SIDE_EFFECTS__ */ +function number(message$1) { + return _standardSchema({ + kind: "schema", + type: "number", + reference: number, + expects: "number", + async: false, + message: message$1, + "~run"(dataset, config$1) { + if (typeof dataset.value === "number" && !isNaN(dataset.value)) dataset.typed = true; + else _addIssue(this, "type", dataset, config$1); + return dataset; + } + }); +} +/* @__NO_SIDE_EFFECTS__ */ +function object(entries$1, message$1) { + return _standardSchema({ + kind: "schema", + type: "object", + reference: object, + expects: "Object", + async: false, + entries: entries$1, + message: message$1, + "~run"(dataset, config$1) { + const input = dataset.value; + if (input && typeof input === "object") { + dataset.typed = true; + dataset.value = {}; + for (const key in this.entries) { + const valueSchema = this.entries[key]; + if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) { + const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema); + const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1); + if (valueDataset.issues) { + const pathItem = { + type: "object", + origin: "value", + input, + key, + value: value$1 + }; + for (const issue of valueDataset.issues) { + if (issue.path) issue.path.unshift(pathItem); + else issue.path = [pathItem]; + dataset.issues?.push(issue); + } + if (!dataset.issues) dataset.issues = valueDataset.issues; + if (config$1.abortEarly) { + dataset.typed = false; + break; + } + } + if (!valueDataset.typed) dataset.typed = false; + dataset.value[key] = valueDataset.value; + } else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema); + else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") { + _addIssue(this, "key", dataset, config$1, { + input: void 0, + expected: `"${key}"`, + path: [{ + type: "object", + origin: "key", + input, + key, + value: input[key] + }] + }); + if (config$1.abortEarly) break; + } + } + } else _addIssue(this, "type", dataset, config$1); + return dataset; + } + }); +} +/* @__NO_SIDE_EFFECTS__ */ +function optional(wrapped, default_) { + return _standardSchema({ + kind: "schema", + type: "optional", + reference: optional, + expects: `(${wrapped.expects} | undefined)`, + async: false, + wrapped, + default: default_, + "~run"(dataset, config$1) { + if (dataset.value === void 0) { + if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1); + if (dataset.value === void 0) { + dataset.typed = true; + return dataset; + } + } + return this.wrapped["~run"](dataset, config$1); + } + }); +} +/* @__NO_SIDE_EFFECTS__ */ +function picklist(options, message$1) { + return _standardSchema({ + kind: "schema", + type: "picklist", + reference: picklist, + expects: /* @__PURE__ */ _joinExpects(options.map(_stringify), "|"), + async: false, + options, + message: message$1, + "~run"(dataset, config$1) { + if (this.options.includes(dataset.value)) dataset.typed = true; + else _addIssue(this, "type", dataset, config$1); + return dataset; + } + }); +} +/* @__NO_SIDE_EFFECTS__ */ +function string(message$1) { + return _standardSchema({ + kind: "schema", + type: "string", + reference: string, + expects: "string", + async: false, + message: message$1, + "~run"(dataset, config$1) { + if (typeof dataset.value === "string") dataset.typed = true; + else _addIssue(this, "type", dataset, config$1); + return dataset; + } + }); +} +/** +* Creates a unknown schema. +* +* @returns A unknown schema. +*/ +/* @__NO_SIDE_EFFECTS__ */ +function unknown() { + return _standardSchema({ + kind: "schema", + type: "unknown", + reference: unknown, + expects: "unknown", + async: false, + "~run"(dataset) { + dataset.typed = true; + return dataset; + } + }); +} +/** +* Parses an unknown input based on a schema. +* +* @param schema The schema to be used. +* @param input The input to be parsed. +* @param config The parse configuration. +* +* @returns The parsed input. +*/ +function parse(schema, input, config$1) { + const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1)); + if (dataset.issues) throw new ValiError(dataset.issues); + return dataset.value; +} +//#endregion +//#region src/changes.ts +const hunkHeader = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/u; +/** Keeps file-wide diagnostics and diagnostics whose location intersects a changed line. */ +function filterToChangedLines(diagnostics, changedLines, toRepositoryPath) { + return diagnostics.filter((diagnostic) => { + const ranges = changedLines.get(toRepositoryPath(diagnostic.filePath)); + if (ranges === void 0) return false; + if (ranges === "all" || diagnostic.loc === void 0) return true; + const startLine = diagnostic.loc.start.line; + const endLine = diagnostic.loc.end?.line ?? startLine; + return ranges.some((range) => startLine <= range.endLine && endLine >= range.startLine); + }); +} +/** Reads the new-file line ranges from the hunk headers of a unified diff. */ +function parsePatch(patch) { + const ranges = []; + for (const line of patch.split("\n")) { + const match = hunkHeader.exec(line); + if (match === null) continue; + const startLine = Number(match[1]); + const count = match[2] === void 0 ? 1 : Number(match[2]); + if (count > 0) ranges.push({ + endLine: startLine + count - 1, + startLine + }); + } + return ranges; +} +function toChangedLines(files) { + return new Map(files.filter((file) => file.status !== "removed").map((file) => [file.filename, file.patch === void 0 ? "all" : parsePatch(file.patch)])); +} +//#endregion +//#region src/findings.ts +/** Identifies the summary comment so that later runs rewrite it instead of adding another one. */ +const summaryMarker = ""; +const maxSummaryRows = 100; +function formatSummary(findings, context) { + const icon = toConclusion(findings) === "failure" ? "❌" : findings.length > 0 ? "⚠️" : "✅"; + const shortSha = context.sha.slice(0, 7); + const lines = [ + summaryMarker, + `### ${icon} alint · ${formatTitle(findings)}`, + "" + ]; + if (findings.length === 0) lines.push(`Checked the changes at \`${shortSha}\`.`); + else { + lines.push("| | Location | Rule | Finding |", "| --- | --- | --- | --- |"); + for (const finding of findings.slice(0, maxSummaryRows)) { + const link = `${context.serverUrl}/${context.repository}/blob/${context.sha}/${encodeURI(finding.path)}#L${finding.line}`; + const detail = finding.suggestion === void 0 ? escapeCell(finding.message) : `${escapeCell(finding.message)}
💡 ${escapeCell(finding.suggestion)}`; + lines.push(`| ${finding.severity === "error" ? "❌" : "⚠️"} | [\`${finding.path}:${finding.line}\`](${link}) | \`${finding.ruleId}\` | ${detail} |`); + } + if (findings.length > maxSummaryRows) lines.push("", `${findings.length - maxSummaryRows} more findings are in the check annotations.`); + } + const footer = [ + `Commit \`${shortSha}\``, + context.runUrl === void 0 ? void 0 : `[run](${context.runUrl})`, + `${context.totalTokens.toLocaleString("en-US")} tokens` + ].filter((part) => part !== void 0); + lines.push("", `${footer.join(" · ")}`); + return lines.join("\n"); +} +function formatTitle(findings) { + if (findings.length === 0) return "No findings"; + const errors = findings.filter((finding) => finding.severity === "error").length; + const warnings = findings.length - errors; + return [errors > 0 ? pluralize(errors, "error") : void 0, warnings > 0 ? pluralize(warnings, "warning") : void 0].filter((part) => part !== void 0).join(", "); +} +function toAnnotations(findings) { + return findings.map((finding) => ({ + annotation_level: finding.severity === "error" ? "failure" : "warning", + end_line: finding.line, + message: finding.suggestion === void 0 ? finding.message : `${finding.message}\n\n${finding.suggestion}`, + path: finding.path, + start_line: finding.line, + title: finding.ruleId + })); +} +function toConclusion(findings) { + if (findings.some((finding) => finding.severity === "error")) return "failure"; + return findings.length > 0 ? "neutral" : "success"; +} +/** Converts diagnostics to findings with repository-relative paths. Errors come first. */ +function toFindings(diagnostics, toRepositoryPath) { + return diagnostics.map((diagnostic) => ({ + line: diagnostic.loc?.start.line ?? 1, + message: diagnostic.message.trim(), + path: toRepositoryPath(diagnostic.filePath), + ruleId: diagnostic.ruleId, + severity: diagnostic.severity, + suggestion: suggestionFrom(diagnostic.evidence) + })).sort((a, b) => Number(b.severity === "error") - Number(a.severity === "error") || a.path.localeCompare(b.path) || a.line - b.line); +} +function escapeCell(value) { + return value.replaceAll("|", "\\|").replaceAll(/\s*\n\s*/gu, " "); +} +function pluralize(count, noun) { + return `${count} ${noun}${count === 1 ? "" : "s"}`; +} +function suggestionFrom(evidence) { + if (typeof evidence !== "object" || evidence === null || !("suggestion" in evidence) || typeof evidence.suggestion !== "string") return; + return evidence.suggestion.trim() || void 0; +} +//#endregion +//#region src/github.ts +const annotationsPerRequest = 50; +const itemsPerPage = 100; +const checkRunSchema = /* @__PURE__ */ object({ id: /* @__PURE__ */ number() }); +const commentsSchema = /* @__PURE__ */ array(/* @__PURE__ */ object({ + body: /* @__PURE__ */ optional(/* @__PURE__ */ string()), + id: /* @__PURE__ */ number() +})); +const filesSchema = /* @__PURE__ */ array(/* @__PURE__ */ object({ + filename: /* @__PURE__ */ string(), + patch: /* @__PURE__ */ optional(/* @__PURE__ */ string()), + status: /* @__PURE__ */ string() +})); +async function listPullRequestFiles(repository, pullRequest) { + const files = []; + for (let page = 1;; page += 1) { + const items = parse(filesSchema, await request(repository, "GET", `/pulls/${pullRequest}/files?per_page=${itemsPerPage}&page=${page}`)); + files.push(...items); + if (items.length < itemsPerPage) return files; + } +} +async function publishCheckRun(repository, checkRun) { + const output = { + summary: checkRun.summary, + title: checkRun.title + }; + const created = parse(checkRunSchema, await request(repository, "POST", "/check-runs", { + conclusion: checkRun.conclusion, + head_sha: checkRun.sha, + name: checkRun.name, + output: { + ...output, + annotations: checkRun.annotations.slice(0, annotationsPerRequest) + }, + status: "completed" + })); + for (let offset = annotationsPerRequest; offset < checkRun.annotations.length; offset += annotationsPerRequest) await request(repository, "PATCH", `/check-runs/${created.id}`, { output: { + ...output, + annotations: checkRun.annotations.slice(offset, offset + annotationsPerRequest) + } }); +} +/** +* Rewrites the summary comment of a pull request. +* +* A pull request that never had findings gets no comment. After the first comment exists, +* each run rewrites it, so a fixed pull request shows the clean result. +*/ +async function publishSummaryComment(repository, pullRequest, body, hasFindings) { + const existing = await findSummaryComment(repository, pullRequest); + if (existing !== void 0) { + await request(repository, "PATCH", `/issues/comments/${existing}`, { body }); + return; + } + if (hasFindings) await request(repository, "POST", `/issues/${pullRequest}/comments`, { body }); +} +async function findSummaryComment(repository, pullRequest) { + for (let page = 1;; page += 1) { + const comments = parse(commentsSchema, await request(repository, "GET", `/issues/${pullRequest}/comments?per_page=${itemsPerPage}&page=${page}`)); + const summary = comments.find((comment) => comment.body?.includes(summaryMarker)); + if (summary !== void 0) return summary.id; + if (comments.length < itemsPerPage) return; + } +} +async function request(repository, method, path, body) { + const response = await fetch(`${repository.apiUrl}/repos/${repository.repository}${path}`, { + body: body === void 0 ? void 0 : JSON.stringify(body), + headers: { + "Accept": "application/vnd.github+json", + "Authorization": `Bearer ${repository.token}`, + "Content-Type": "application/json", + "X-GitHub-Api-Version": "2022-11-28" + }, + method + }); + if (!response.ok) throw new Error(`GitHub ${method} ${path} failed with ${response.status}: ${await response.text()}`); + return response.json(); +} +//#endregion +//#region node_modules/.pnpm/tinyexec@1.3.1/node_modules/tinyexec/dist/main.mjs +const isPathLikePattern = /^path$/i; +const defaultEnvPathInfo = { + key: "PATH", + value: "" +}; +function getPathFromEnv(env) { + for (const key in env) { + if (!Object.prototype.hasOwnProperty.call(env, key) || !isPathLikePattern.test(key)) continue; + const value = env[key]; + if (!value) return defaultEnvPathInfo; + return { + key, + value + }; + } + return defaultEnvPathInfo; +} +function addNodeBinToPath(cwd, path) { + const parts = path.value.split(delimiter); + const nodeBinPaths = []; + let currentPath = typeof cwd === "string" ? cwd : fileURLToPath(cwd, { windows: false }); + let lastPath; + do { + nodeBinPaths.push(resolve(currentPath, "node_modules", ".bin")); + lastPath = currentPath; + currentPath = dirname(currentPath); + } while (currentPath !== lastPath); + nodeBinPaths.push(dirname(process.execPath)); + const newPath = nodeBinPaths.concat(parts).join(delimiter); + return { + key: path.key, + value: newPath + }; +} +function computeEnv(cwd, env, nodePath = true) { + const envWithDefault = { + ...process.env, + ...env + }; + if (!nodePath) return envWithDefault; + const envPathInfo = addNodeBinToPath(cwd, getPathFromEnv(envWithDefault)); + envWithDefault[envPathInfo.key] = envPathInfo.value; + return envWithDefault; +} +const combineStreams = (streams) => { + let streamCount = streams.length; + const combined = new PassThrough(); + const maybeEmitEnd = () => { + if (--streamCount === 0) combined.end(); + }; + for (const stream of streams) pipeline(stream, combined, { end: false }).then(maybeEmitEnd).catch(maybeEmitEnd); + return combined; +}; +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; +const shebangRegExp = /^#!\s*(.+)/; +const isWindowsExecutableRegExp = /\.(?:com|exe)$/i; +const isNodeModulesCmdRegExp = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i; +const isWindows = process.platform === "win32"; +const defaultPathExt = [ + ".EXE", + ".CMD", + ".BAT", + ".COM" +]; +const noPathExt = [""]; +/** +* Normalizes the command and arguments to work cross-platform. +* On Windows, this basically handles things like shebangs, calling +* `node_modules/.bin` commands, and escaping meta characters. +* On other platforms, it just returns the command and arguments as-is. +*/ +function normalizeSpawnCommand(command, args = [], options = {}) { + if (options.shell === true || !isWindows) return { + command, + args, + options + }; + let file = resolveCommand(command, options); + let shebang = null; + if (file !== null) { + const size = 150; + const buffer = Buffer.alloc(size); + let fd = null; + try { + fd = openSync(file, "r"); + readSync(fd, buffer, 0, size, 0); + } catch {} finally { + if (fd !== null) closeSync(fd); + } + const match = buffer.toString().match(shebangRegExp); + if (match !== null) { + const line = match[1].trim(); + const separatorIndex = line.indexOf(" "); + const path = separatorIndex !== -1 ? line.slice(0, separatorIndex) : line; + const argument = separatorIndex !== -1 ? line.slice(separatorIndex + 1) : ""; + const binary = basename(path); + shebang = binary === "env" ? argument || null : binary; + } + } + if (shebang !== null && file !== null) { + args = [file, ...args]; + command = shebang; + file = resolveCommand(command, options); + } + if (file === null || !isWindowsExecutableRegExp.test(file)) { + const needsDoubleEscapeMetaChars = file !== null && isNodeModulesCmdRegExp.test(file); + command = normalize(command); + command = command.replace(metaCharsRegExp, "^$1"); + args = args.map((arg) => { + arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\""); + arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1"); + arg = `"${arg}"`; + arg = arg.replace(metaCharsRegExp, "^$1"); + if (needsDoubleEscapeMetaChars) arg = arg.replace(metaCharsRegExp, "^$1"); + return arg; + }); + args = [ + "/d", + "/s", + "/c", + `"${[command, ...args].join(" ")}"` + ]; + command = options.env?.comspec ?? "cmd.exe"; + options = { + ...options, + windowsVerbatimArguments: true + }; + } + return { + command, + args, + options + }; +} +/** +* Resolves the command to an absolute path if possible. +* Handles things like traversing PATH and adding extensions from PATHEXT +*/ +function resolveCommand(command, options) { + const cwd$3 = (options.cwd ?? cwd()).toString(); + const env = options.env ?? process.env; + const PATH = getPathFromEnv(env).value; + const pathEnv = command.includes("/") || command.includes("\\") ? [""] : [cwd$3, ...PATH.split(delimiter)]; + let pathExt = env.PATHEXT ? env.PATHEXT.split(delimiter) : defaultPathExt; + if (command.includes(".") && pathExt[0] !== "") pathExt = ["", ...pathExt]; + for (const extensions of [pathExt, noPathExt]) for (const path of pathEnv) { + const unquoted = path.startsWith("\"") && path.endsWith("\"") && path.length > 1 ? path.slice(1, -1) : path; + const dest = resolve(cwd$3, unquoted, command); + for (const ext of extensions) { + const destWithExt = dest + ext; + try { + if (statSync(destWithExt).isFile()) return destWithExt; + } catch {} + } + } + return null; +} +var NonZeroExitError = class extends Error { + result; + output; + exitCode; + get signalCode() { + return this.result.signalCode; + } + constructor(result, output, command, args) { + let target = "The process"; + if (command) target = `The command \`${args?.length ? `${command} ${args.map((a) => /[ "'`()]/.test(a) ? JSON.stringify(a) : a).join(" ")}` : command}\``; + const exitCode = result.exitCode ?? 1; + super(result.signalCode !== null ? `${target} was killed by the signal ${result.signalCode}` : `${target} exited with a non-zero status (${exitCode})`); + this.result = result; + this.output = output; + this.exitCode = exitCode; + Object.defineProperty(this, "result", { + enumerable: false, + writable: false, + configurable: false + }); + } +}; +const defaultOptions = { + timeout: void 0, + persist: false +}; +const defaultNodeOptions = { windowsHide: true }; +function combineSignals(signals) { + const controller = new AbortController(); + for (const signal of signals) { + if (signal.aborted) { + controller.abort(); + return signal; + } + const onAbort = () => { + controller.abort(signal.reason); + }; + signal.addEventListener("abort", onAbort, { signal: controller.signal }); + } + return controller.signal; +} +async function readStream(stream) { + let output = ""; + try { + for await (const chunk of stream) output += chunk.toString(); + } catch {} + return output; +} +var ExecProcess = class { + _process; + _aborted = false; + _options; + _command; + _args; + _resolveClose; + _processClosed; + _thrownError; + get process() { + return this._process; + } + get pid() { + return this._process?.pid; + } + get exitCode() { + if (this._process && this._process.exitCode !== null) return this._process.exitCode; + } + get signalCode() { + return this._process?.signalCode ?? null; + } + constructor(command, args, options) { + this._options = { + ...defaultOptions, + ...options + }; + this._command = command; + this._args = args ?? []; + this._processClosed = new Promise((resolve) => { + this._resolveClose = resolve; + }); + } + kill(signal) { + return this._process?.kill(signal) === true; + } + get aborted() { + return this._aborted; + } + get killed() { + return this._process?.killed === true; + } + pipe(command, args, options) { + return exec(command, args, { + ...options, + stdin: this + }); + } + async *[Symbol.asyncIterator]() { + const proc = this._process; + if (!proc) return; + const streams = []; + if (this._streamErr) streams.push(this._streamErr); + if (this._streamOut) streams.push(this._streamOut); + const streamCombined = combineStreams(streams); + const rl = readline.createInterface({ input: streamCombined }); + for await (const chunk of rl) yield chunk.toString(); + await this._processClosed; + proc.removeAllListeners(); + if (this._thrownError) throw this._thrownError; + if (this._options?.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, void 0, this._command, this._args); + } + async _waitForOutput() { + const proc = this._process; + if (!proc) throw new Error("No process was started"); + const [stdout, stderr] = await Promise.all([this._streamOut ? readStream(this._streamOut) : "", this._streamErr ? readStream(this._streamErr) : ""]); + await this._processClosed; + const { stdin } = this._options; + if (stdin && typeof stdin !== "string") await stdin; + proc.removeAllListeners(); + if (this._thrownError) throw this._thrownError; + const result = { + stderr, + stdout, + exitCode: this.exitCode + }; + if (this._options.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, result, this._command, this._args); + return result; + } + then(onfulfilled, onrejected) { + return this._waitForOutput().then(onfulfilled, onrejected); + } + _streamOut; + _streamErr; + spawn() { + const options = this._options; + const nodeOptions = { + ...defaultNodeOptions, + ...options.nodeOptions + }; + const cwd$1 = nodeOptions?.cwd ?? cwd(); + const signals = []; + this._resetState(); + if (options.timeout !== void 0) signals.push(AbortSignal.timeout(options.timeout)); + if (options.signal !== void 0) signals.push(options.signal); + if (options.persist === true) nodeOptions.detached = true; + if (signals.length > 0) nodeOptions.signal = combineSignals(signals); + nodeOptions.env = computeEnv(cwd$1, nodeOptions.env, options.nodePath); + const crossResult = normalizeSpawnCommand(this._command, this._args, nodeOptions); + const handle = spawn(crossResult.command, crossResult.args, crossResult.options); + if (handle.stderr) this._streamErr = handle.stderr; + if (handle.stdout) this._streamOut = handle.stdout; + this._process = handle; + handle.once("error", this._onError); + handle.once("close", this._onClose); + if (handle.stdin) { + const { stdin } = options; + if (typeof stdin === "string") handle.stdin.end(stdin); + else stdin?.process?.stdout?.pipe(handle.stdin); + } + } + _resetState() { + this._aborted = false; + this._processClosed = new Promise((resolve) => { + this._resolveClose = resolve; + }); + this._thrownError = void 0; + } + _onError = (err) => { + if (err.name === "AbortError" && (!(err.cause instanceof Error) || err.cause.name !== "TimeoutError")) { + this._aborted = true; + return; + } + this._thrownError = err; + }; + _onClose = () => { + if (this._resolveClose) this._resolveClose(); + }; +}; +const x = (command, args, userOptions) => { + const proc = new ExecProcess(command, args, userOptions); + proc.spawn(); + return proc; +}; +const exec = x; +//#endregion +//#region src/output.ts +const positionSchema = /* @__PURE__ */ object({ + column: /* @__PURE__ */ number(), + line: /* @__PURE__ */ number() +}); +const runResultSchema = /* @__PURE__ */ object({ + diagnostics: /* @__PURE__ */ array(/* @__PURE__ */ object({ + evidence: /* @__PURE__ */ optional(/* @__PURE__ */ unknown()), + filePath: /* @__PURE__ */ string(), + loc: /* @__PURE__ */ optional(/* @__PURE__ */ object({ + end: /* @__PURE__ */ optional(positionSchema), + start: positionSchema + })), + message: /* @__PURE__ */ string(), + ruleId: /* @__PURE__ */ string(), + severity: /* @__PURE__ */ picklist(["error", "warn"]) + })), + usage: /* @__PURE__ */ object({ totalTokens: /* @__PURE__ */ number() }) +}); +function parseRunResult(json) { + return parse(runResultSchema, JSON.parse(json)); +} +//#endregion +//#region src/lint.ts +/** Runs `alint --format json` on the targets and returns the parsed result. */ +async function runAlint(command, targets, cwd) { + const result = await x(command, [ + "--format", + "json", + ...targets + ], { nodeOptions: { cwd } }); + if (result.exitCode !== 0 && result.exitCode !== 1) throw new Error(`alint exited with code ${result.exitCode}.\n${result.stderr || result.stdout}`); + return parseRunResult(result.stdout); +} +//#endregion +//#region src/main.ts +const eventSchema = /* @__PURE__ */ object({ pull_request: /* @__PURE__ */ optional(/* @__PURE__ */ object({ + head: /* @__PURE__ */ object({ sha: /* @__PURE__ */ string() }), + number: /* @__PURE__ */ number() +})) }); +async function run(env, cwd) { + const repository = { + apiUrl: env.GITHUB_API_URL ?? "https://api.github.com", + repository: required(env, "GITHUB_REPOSITORY"), + token: required(env, "GITHUB_TOKEN") + }; + const workspace = env.GITHUB_WORKSPACE ?? cwd; + const serverUrl = env.GITHUB_SERVER_URL ?? "https://github.com"; + const pullRequest = await readPullRequest(env.GITHUB_EVENT_PATH); + const sha = pullRequest?.sha ?? required(env, "GITHUB_SHA"); + const toRepositoryPath = (filePath) => relative(workspace, resolve$1(cwd, filePath)); + const scope = await resolveScope(repository, pullRequest, env.INPUT_FILES ?? "", cwd, workspace); + const result = scope.targets.length === 0 ? { + diagnostics: [], + usage: { totalTokens: 0 } + } : await runAlint(required(env, "ALINT_COMMAND"), scope.targets, cwd); + const findings = toFindings(scope.changedLines === void 0 ? result.diagnostics : filterToChangedLines(result.diagnostics, scope.changedLines, toRepositoryPath), toRepositoryPath); + const title = formatTitle(findings); + const summary = formatSummary(findings, { + repository: repository.repository, + runUrl: env.GITHUB_RUN_ID === void 0 ? void 0 : `${serverUrl}/${repository.repository}/actions/runs/${env.GITHUB_RUN_ID}`, + serverUrl, + sha, + totalTokens: result.usage.totalTokens + }); + if (env.GITHUB_STEP_SUMMARY !== void 0) await appendFile(env.GITHUB_STEP_SUMMARY, `${summary}\n`); + if (env.GITHUB_OUTPUT !== void 0) { + const errors = findings.filter((finding) => finding.severity === "error").length; + await appendFile(env.GITHUB_OUTPUT, `errors=${errors}\nwarnings=${findings.length - errors}\n`); + } + await publishCheckRun(repository, { + annotations: toAnnotations(findings), + conclusion: toConclusion(findings), + name: env.INPUT_CHECK_NAME || "alint", + sha, + summary, + title + }); + if (pullRequest !== void 0) await publishSummaryComment(repository, pullRequest.number, summary, findings.length > 0); + console.info(`Published ${title.toLowerCase()} to ${repository.repository}@${sha.slice(0, 7)}.`); +} +async function readPullRequest(eventPath) { + if (eventPath === void 0) return; + const event = parse(eventSchema, JSON.parse(await readFile(eventPath, "utf8"))); + return event.pull_request === void 0 ? void 0 : { + number: event.pull_request.number, + sha: event.pull_request.head.sha + }; +} +function required(env, name) { + const value = env[name]; + if (!value) throw new Error(`${name} is not set.`); + return value; +} +/** +* Selects what alint reads. +* +* Explicit files win. A pull request without explicit files gets its changed files, +* and the result keeps only the changed lines. Other events get the whole working directory. +*/ +async function resolveScope(repository, pullRequest, files, cwd, workspace) { + const explicit = files.split(/\s+/u).filter(Boolean); + if (explicit.length > 0) return { targets: explicit }; + if (pullRequest === void 0) return { targets: ["."] }; + const changedLines = toChangedLines(await listPullRequestFiles(repository, pullRequest.number)); + return { + changedLines, + targets: [...changedLines.keys()].map((path) => relative(cwd, resolve$1(workspace, path))).filter((path) => !path.startsWith("..") && existsSync(resolve$1(cwd, path))) + }; +} +//#endregion +//#region src/index.ts +run(process$1.env, process$1.cwd()).catch((error) => { + console.error(`::error title=alint::${(errorMessageFrom(error) ?? "unknown error").replaceAll("\n", "%0A")}`); + process$1.exitCode = 1; +}); +//#endregion +export {}; diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000..aefb15d --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from '@moeru/eslint-config' + +export default defineConfig({ + masknet: false, + perfectionist: true, + preferArrow: false, + sonarjs: false, + sortPackageJsonScripts: false, + typescript: true, + unocss: false, + vue: false, +}, { + ignores: [ + 'dist/**', + '.worktrees/**', + 'test/fixture/**', + ], +}, { + rules: { + 'no-console': ['error', { allow: ['warn', 'error', 'info'] }], + }, +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..53e1f2f --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "@alint-js/setup", + "type": "module", + "version": "0.0.0", + "private": true, + "packageManager": "pnpm@11.18.0", + "description": "GitHub Action that runs alint on a pull request and publishes the result", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/alint-dev/setup.git" + }, + "scripts": { + "build": "tsdown", + "lint": "eslint --cache .", + "lint:fix": "eslint --cache . --fix", + "test": "vitest", + "test:run": "vitest run", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "@moeru/eslint-config": "^0.1.0-beta.20", + "@moeru/std": "^0.1.0-beta.20", + "@types/node": "^26.1.2", + "eslint": "^10.8.0", + "jiti": "^2.7.0", + "pathe": "^2.0.3", + "tinyexec": "^1.2.4", + "tsdown": "^0.22.14", + "typescript": "^6.0.3", + "valibot": "^1.4.2", + "vitest": "^4.1.10" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..bb4e2d1 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4078 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@moeru/eslint-config': + specifier: ^0.1.0-beta.20 + version: 0.1.0-beta.20(@antfu/eslint-config@8.3.0(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1))))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@moeru/std': + specifier: ^0.1.0-beta.20 + version: 0.1.0-beta.20 + '@types/node': + specifier: ^26.1.2 + version: 26.6.4 + eslint: + specifier: ^10.8.0 + version: 10.12.0(jiti@2.7.0) + jiti: + specifier: ^2.7.0 + version: 2.7.0 + pathe: + specifier: ^2.0.3 + version: 2.0.3 + tinyexec: + specifier: ^1.2.4 + version: 1.3.1 + tsdown: + specifier: ^0.22.14 + version: 0.22.14(typescript@6.0.3) + typescript: + specifier: ^6.0.3 + version: 6.0.3 + valibot: + specifier: ^1.4.2 + version: 1.5.0(typescript@6.0.3) + vitest: + specifier: ^4.1.10 + version: 4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)) + +packages: + + '@antfu/eslint-config@8.3.0': + resolution: {integrity: sha512-rPNuuDl6ssyw2WLrajtDv2r6aiHhxLBPckgqJbmgZE5Vg4dgPqEqx3ihVZ4rqz7P4XnHvDr1gsPniRoSztZ8/Q==} + hasBin: true + peerDependencies: + '@angular-eslint/eslint-plugin': ^21.1.0 + '@angular-eslint/eslint-plugin-template': ^21.1.0 + '@angular-eslint/template-parser': ^21.1.0 + '@eslint-react/eslint-plugin': ^3.0.0 + '@next/eslint-plugin-next': '>=15.0.0' + '@prettier/plugin-xml': ^3.4.1 + '@unocss/eslint-plugin': '>=0.50.0' + astro-eslint-parser: ^1.0.2 + eslint: ^9.10.0 || ^10.0.0 + eslint-plugin-astro: ^1.2.0 + eslint-plugin-format: '>=0.1.0' + eslint-plugin-jsx-a11y: '>=6.10.2' + eslint-plugin-react-refresh: ^0.5.0 + eslint-plugin-solid: ^0.14.3 + eslint-plugin-svelte: '>=2.35.1' + eslint-plugin-vuejs-accessibility: ^2.4.1 + prettier-plugin-astro: ^0.14.0 + prettier-plugin-slidev: ^1.0.5 + svelte-eslint-parser: '>=0.37.0' + peerDependenciesMeta: + '@angular-eslint/eslint-plugin': + optional: true + '@angular-eslint/eslint-plugin-template': + optional: true + '@angular-eslint/template-parser': + optional: true + '@eslint-react/eslint-plugin': + optional: true + '@next/eslint-plugin-next': + optional: true + '@prettier/plugin-xml': + optional: true + '@unocss/eslint-plugin': + optional: true + astro-eslint-parser: + optional: true + eslint-plugin-astro: + optional: true + eslint-plugin-format: + optional: true + eslint-plugin-jsx-a11y: + optional: true + eslint-plugin-react-refresh: + optional: true + eslint-plugin-solid: + optional: true + eslint-plugin-svelte: + optional: true + eslint-plugin-vuejs-accessibility: + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-slidev: + optional: true + svelte-eslint-parser: + optional: true + + '@antfu/install-pkg@1.1.0': + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@cacheable/memory@2.2.0': + resolution: {integrity: sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==} + + '@cacheable/utils@2.5.0': + resolution: {integrity: sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==} + + '@clack/core@1.5.1': + resolution: {integrity: sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ==} + engines: {node: '>= 20.12.0'} + + '@clack/prompts@1.8.1': + resolution: {integrity: sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==} + engines: {node: '>= 20.12.0'} + + '@e18e/eslint-plugin@0.4.1': + resolution: {integrity: sha512-Re00N8ad1HsNrzpuIX7Bhdr8RSaFWp6VgwJUEJF+47+D1CMcXoS7VNRkIG23e46pddhgxWU0cWk4wYiQIuMHqQ==} + peerDependencies: + eslint: ^9.0.0 || ^10.0.0 + oxlint: ^1.61.0 + peerDependenciesMeta: + eslint: + optional: true + oxlint: + optional: true + + '@es-joy/jsdoccomment@0.86.0': + resolution: {integrity: sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@es-joy/jsdoccomment@0.88.0': + resolution: {integrity: sha512-GK/HL/claLLNo5KG705auIlZMwEtmn88ofSGuLsmVZwKBqMPJhW9DiznYNq07QEqz9BPtA3LBfYImtZmhVvRAw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@es-joy/resolve.exports@1.2.0': + resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} + engines: {node: '>=10'} + + '@eslint-community/eslint-plugin-eslint-comments@4.8.1': + resolution: {integrity: sha512-vafrdi15JHBFh1qWOAucyJwlEEuhdoMof28jOdKdgnwZ7bXwd6v4wzHYSmAVLwnx0yc7bqAtfJ0EZQV1WAzV/Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/compat@2.1.1': + resolution: {integrity: sha512-rMcy8GSrwNzcISX/BlTDY/GLB4eCopEuy9woIls3To+15OLxykZrxxq+WUcylCPCQ6F4MujjBM1DX5V1aqI3Vw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^8.40 || 9 || 10 + peerDependenciesMeta: + eslint: + optional: true + + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.5.5': + resolution: {integrity: sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/markdown@8.0.3': + resolution: {integrity: sha512-rBTSSShrq7e4O+PWfeE4azH4/CWPNrC+VGxBXiW00o3vYVJnznsZiDayj3KC9JztIMVRZxZHn2nrDIUau/4j7A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.7.3': + resolution: {integrity: sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@keyv/bigmap@1.3.1': + resolution: {integrity: sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==} + engines: {node: '>= 18'} + peerDependencies: + keyv: ^5.6.0 + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} + + '@masknet/eslint-plugin@0.4.1': + resolution: {integrity: sha512-Bl0e0ZC2iZn+pvQcDA+kP9XZU5cuNRA6je9q7VxaaJrURpMGC/P7+DsqlqCDbZ5IF0Q4OZwivi75YDfXJuDjBw==} + engines: {node: '>= 22'} + peerDependencies: + eslint: '>= 9' + + '@moeru/eslint-config@0.1.0-beta.20': + resolution: {integrity: sha512-cWW+SofLkfrivM4J8P/Nc5q9zQM9tsJJgKwaqaDIKde83ZcbB8ZL3xVVoy242kvmMoPQTDe7lVQVCV4+43h4gw==} + hasBin: true + peerDependencies: + '@antfu/eslint-config': ^8.2.0 + eslint: ^10.3.0 + eslint-plugin-oxlint: ^1.62.0 + peerDependenciesMeta: + eslint-plugin-oxlint: + optional: true + + '@moeru/std@0.1.0-beta.20': + resolution: {integrity: sha512-09Nunc5dLT0+oAaLV18nIGHLkQO3LOUGOpGcQ2VIFTqWybJojT9geawhTVtuclYcJtIApgIt+3BLWI1K9dYpFw==} + + '@ota-meshi/ast-token-store@0.3.0': + resolution: {integrity: sha512-XRO0zi2NIUKq2lUk3T1ecFSld1fMWRKE6naRFGkgkdeosx7IslyUKNv5Dcb5PJTja9tHJoFu0v/7yEpAkrkrTg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@oxc-project/types@0.153.0': + resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==} + + '@pkgr/core@0.3.6': + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} + + '@quansync/fs@1.1.0': + resolution: {integrity: sha512-qAPG/t3HqML1TlN7sY/pTbEjzFVAKsMjNNMGheyDosro+kT4iw2KCUoHcVdmliwWjorm4elZbgNQyU2eD97eDg==} + + '@rolldown/binding-android-arm-eabi@1.2.13': + resolution: {integrity: sha512-Vu/NICrgdRvUOeaJZIyB2FP63s6fO/4ud5l8dXmxDx9yDyn+mN0y+gsvsVviSli+T361Aqo0h46EuMoobrwawA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.13': + resolution: {integrity: sha512-6LEoIrGy5vvCd2boNnv2soPSUZj/PRvhp8R/t9KlX+mIZxThIE/ZqxrGXxmuNX0FuvQFvLdZr7S4HrYpYBVhEQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.13': + resolution: {integrity: sha512-CaJSRzlQ6Q+zkDMVA9OkVxBjVoPRCDEE3v0FSJ9kIQBgRjFApA3Si4ijhbNVUji7ZJt+PfO0e46qy4nPInHUPA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.13': + resolution: {integrity: sha512-e4r340I5hxSzJkD3YJBxgzq/rJ3wwxwdLLb2FPt1Zpyem20nrQPT11DDEEkazwxaHumH8wpglsp/Ozgj/wT6mw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.13': + resolution: {integrity: sha512-hoBWDZ4/K/mJKVMbsgUd1jfpA2DiOrJ54mpegObU9TBHBBrtX4FLIXJJQRDPZ/2Dn91GvPob+Z2hwKJzf4E5SQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.13': + resolution: {integrity: sha512-oF9fZu3vTWnTiVAkDFxU9PJLt1nh20K9RRpuHsR7ZnE2L7XookBbDBVLojCVSLGbvtSlxeUNnjAj6DbNsKyzbg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.13': + resolution: {integrity: sha512-DTpb/+jMiqWMPgphn4ksW1zW+XLJ6dJJ9FMvnIk9I291LhCctMPhMYJrP5t9p6C9qa3KXadDdUEZHBaPh3kNxQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.2.13': + resolution: {integrity: sha512-xU+Kvv9N2A3SY35zFh1FWWNjxbadE/BKeqnkXe7vScU4GZsw757BlVmDLITZEq8DPpk6m7uoDYkK7P+x/uU5Ow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.2.13': + resolution: {integrity: sha512-XMk/hnhh25oQ756Lclb1Q11h4ll0xC0Esa5w4Vzp+mAE2S3AGJgeM0SonrIgY8fHhjarb6hcoTuwoFG0VVP2ig==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.2.13': + resolution: {integrity: sha512-U1BoTHYmlywE2n3HUWjzZ+8EQsKr+OwpxYuDWaubx42tUL8QSL7nOqRz/NVHanibbFP3M1Rxuprz/wNcbMKjqw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.2.13': + resolution: {integrity: sha512-J4cm80Pc6wEwV5AZ42o62sIQgDk+Y7R2s646jIwuvO+4V46QB58N4vVuMPWCBaNgursXLpmUWJV//WQAkPvHBQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.2.13': + resolution: {integrity: sha512-W0euZS40U4V6JkmEnVCIX9mcsL6cbXQ4X8c2w+MMOIjFg68TXUW+u3RT+2e1t1pv9mg/EP3pDtK3POXdQ7Rxyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.2.13': + resolution: {integrity: sha512-do/AF/4n9MRshia3a5aXoy8xM2c6mgfT6D7H/dY6my5z+hfCIR4ab7mk4IRj++nsEQpKy39kd0DQnDq+r692tw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-win32-arm64-msvc@1.2.13': + resolution: {integrity: sha512-6FtUf2cJZobutJdxnGYX8z0vtbgqU0b2v8vfBhkXb9wp2MppMFtkunE+IaOntyi01rkIQoPW2GHABtfzsC0BRQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.13': + resolution: {integrity: sha512-UKhFaZTeTcbKrb3iU82m17jVcPEAoqDkCN5MBqgPyZSwp/cQmib21crTS0DdH7T1B7wZRWEI89YQAOJMet5yhg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@sindresorhus/base62@1.0.0': + resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} + engines: {node: '>=18'} + + '@sonarsource/analyzer-commons-configurations@2.31.0-5284': + resolution: {integrity: sha512-ruk3blMs9BE9RNSp9LPpWZAIjxJmq4Cp00E3cELIHz7Kym3WxdWGRlKOMYLRQ5tJg/de7jN5AtEElY3bGIfTcw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@stylistic/eslint-plugin@5.10.0': + resolution: {integrity: sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.0.0 || ^10.0.0 + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/katex@0.16.8': + resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@26.6.4': + resolution: {integrity: sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@typescript-eslint/eslint-plugin@8.71.1': + resolution: {integrity: sha512-nNlBf6HuotqMgZvSkWD5hNdemiBIxQ2NmrlgfcUIeZRs+BbakjscCQRq/Hb74EFVnFiSWWdL12JruqwBy3ERDw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.71.1 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.71.1': + resolution: {integrity: sha512-oM/5sAqz/l1v/zYK1qTOPrn2+JIrBGC1V6uNYucRO5gh6eT9vWJ/RhPbGE59byvZEUQ4VP6XkLBaS5Jti5jpvw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.71.1': + resolution: {integrity: sha512-Oijc9RUsohHjncg6iGi7gCtjnEjYt9FWv9u6ygK8uKcHK5eLjLAkqERQ9BaytbpceOFdk6kifPCS/zAZE+A99g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.71.1': + resolution: {integrity: sha512-1YUDZXdTnXLlob03SFHBipdyMBsDVm7zoSz0ytTJ39dk5J1TgsTK03VlR/dLXG/RLLUrPcYbD4rp23BmHxHP0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.71.1': + resolution: {integrity: sha512-oTvkml5SxXhgg+WWKhod5qWQICDXtOB+/Hi9VdPKFAANJ2b7YOgMffgvzXuqog7R6A/JtrzRf128dsxummyWhg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.71.1': + resolution: {integrity: sha512-kH3t3jZCYv2PZSBEWPKTariLrCaoF1CLoPitYFBJOhAGEwWnSRAtGEifrfrpBa4K9JlwWNZotgA5w3/wLSk/FQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.71.1': + resolution: {integrity: sha512-ybYnPTUwg3VQQOFEiBPLs8Jxl1ry2vXdn1kVKguomBbvxpetdu3MKTNDqFNUrlG8ylP9MpZosmXMFYlGQHk1oQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.71.1': + resolution: {integrity: sha512-pSKSEK1JJpHs6KiKVtABCE4iJK5d7FLFzDXQNBQ2oRY7LEd3UwOt3TZemTgu9syTIf56dJWlTn/pdmrO9oKUXQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.71.1': + resolution: {integrity: sha512-CBjT6gfAz3DW2j9Q4moFnqt208Aq+506sVGXfpRcyAeqn0EpayL0mjdWoCO2t3RC7GewNrFxdeehuEaPg6DMzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.71.1': + resolution: {integrity: sha512-0GxiUGqMU0qXJt58cBsiG3DP8lUmBaFo2vChtUX+CT7PnR3v/VGLLrzVP4K9r1lNiZXjHYefMBbPunplr09v6w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitest/eslint-plugin@1.6.27': + resolution: {integrity: sha512-X1RCAfwbatG4GFbJ/1PIHP9MSZMt0JJThqbYID+vS4L783k6QGlLPe421wQE8dHXuGCcenVLsydiM4qzsYWxhg==} + engines: {node: '>=18'} + peerDependencies: + '@typescript-eslint/eslint-plugin': '*' + eslint: '>=8.57.0' + typescript: '>=5.0.0' + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + typescript: + optional: true + vitest: + optional: true + + '@vitest/expect@4.1.11': + resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + + '@vitest/mocker@4.1.11': + resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.11': + resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + + '@vitest/runner@4.1.11': + resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} + + '@vitest/snapshot@4.1.11': + resolution: {integrity: sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==} + + '@vitest/spy@4.1.11': + resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + + '@vitest/utils@4.1.11': + resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + + '@vue/compiler-core@3.5.43': + resolution: {integrity: sha512-zdiLhnbe1QQqgDT8xZMpNmyqZ3qlI+/Q/FHQco57Kwl/b05HhCzN6eVGN9QU9rbga4CrS0H5SYY8VGHZCt/1Hg==} + + '@vue/compiler-dom@3.5.43': + resolution: {integrity: sha512-PEZoAk3NQmsn/ejMzSOCyTYqwGqczrWm70PuhBKjjv1+TCoQAaO/zOqNwjV+honlNstT5ILxtc+8r8UUfj+iEQ==} + + '@vue/compiler-sfc@3.5.43': + resolution: {integrity: sha512-FCbrG3XNCRl+js3huuKx4IVHBLTvMkJhVepjbxSPu1gn4yWLaYtGNQdjJGZaMytXB6qb76qQDDmDSLy/vkmleQ==} + + '@vue/compiler-ssr@3.5.43': + resolution: {integrity: sha512-GF62orf7KiJX9RqrHNGrYBudsQGD0OhJ5nDs90O8UiDuS40+YMYomiXu6w6EuvtXuRDc3MSNis3EaaSKAVSWpg==} + + '@vue/shared@3.5.43': + resolution: {integrity: sha512-uksS7YGMR5NZyr4JNq0Rp+QyLns0ueaz20KwzIPW9R0LH1Vnt4E+XUM29PNseEbf1www2gOuhuDi5AKOIXag9Q==} + + '@yuku-codegen/binding-android-arm64@0.8.7': + resolution: {integrity: sha512-C/0zV5IhgVdYhGJTwrY0v8dknxlhiKwtVJkMUaexu9/QvRmzlV4vfU3hZlUSgqc2BxQHntL1mCVbDq8j0FRFDw==} + cpu: [arm64] + os: [android] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-darwin-arm64@0.8.7': + resolution: {integrity: sha512-/u+REDMI4a0/lsJXTM4c53/w31OGZLOReZIyg62uhgLs0kc8NHsj/nOcxTdlQjq5gi0zhdkccD9LaLTXcdzPvw==} + cpu: [arm64] + os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-darwin-x64@0.8.7': + resolution: {integrity: sha512-sMMzFOwCo4WXR+/6zIBThOocSC50iIIZZdfiIDbaLvj0Ax/rWt/iavyfEAqajyvzydLyCqR/ZItdLWSRlu1umw==} + cpu: [x64] + os: [darwin] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-freebsd-x64@0.8.7': + resolution: {integrity: sha512-MpdpKXix9P+Y1rKgjvcNeNtGjXeL1CmttNhYINrWls8kRpm4xM/oBGTmn6w7to8lAlwj5jm8q03dQPl5mRv4Qw==} + cpu: [x64] + os: [freebsd] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-arm-gnu@0.8.7': + resolution: {integrity: sha512-rr1srFLlPAmC1vtxfc9C1YLDe3iH09YjfSeeIidBqKhzx1MATjOAq4mjlRUOnhr/L27MotWIYOFKwVsd5JZFOg==} + cpu: [arm] + os: [linux] + libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-arm-musl@0.8.7': + resolution: {integrity: sha512-eAufXh8qBRpiSO6ueaMDL+yyoXIGLhpUce72YbcACtZU2qhExwBIJyEtQf5kH2Ki0X2aqkSjSfog4OPtKXan3Q==} + cpu: [arm] + os: [linux] + libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-arm64-gnu@0.8.7': + resolution: {integrity: sha512-gw4w6wPoHObBrdIC4duVWLmJOvpdE25j5D7yrM5mACNlK4klRz/lv8hK+ssQk9EJHBgZjSaqZIJVFgqNYbfv7A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-arm64-musl@0.8.7': + resolution: {integrity: sha512-L68N6Y4XkqcIaKo3Ra88JEvBEH4AHff44A4INcrxeVWZ8CZtu2tCpfVxe3hR8qQQMcvBSQlDn24KpkCKEhVvfA==} + cpu: [arm64] + os: [linux] + libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-x64-gnu@0.8.7': + resolution: {integrity: sha512-dzyAbltJmf3Cqlb8HcFuYIf5Yn0fl1vTr3XJ9HiVNNvOlhqPSArOqtw9vI1p6/VTXTjrMLXlU+s+/kNHiIy/Cw==} + cpu: [x64] + os: [linux] + libc: [glibc] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-linux-x64-musl@0.8.7': + resolution: {integrity: sha512-Otw4MH3404q0Bbvl+YTdW9aoUV5vXmUw8260bWvt1XlaoIX/ceSgI4ygheRDMfBPoHt6FDayQaO9OLVUZAgkFA==} + cpu: [x64] + os: [linux] + libc: [musl] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-win32-arm64@0.8.7': + resolution: {integrity: sha512-qo/jyrzryiBuKEsFiuWaBCBe3tRMynQ0qFWFgOEjcCMQeZfBm+wKiVEUEFXXLc7bh8YezguAWp0Mtnhq4ARNyA==} + cpu: [arm64] + os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-codegen/binding-win32-x64@0.8.7': + resolution: {integrity: sha512-D5lDsVDx6m00E6bWySlWdH72Ca4TPSaphDqB6QjU6MpuNLIJqoGoatYyq2rOmBE8Zv/kunot/o58KGL03P3eiA==} + cpu: [x64] + os: [win32] + deprecated: yuku-codegen is pure JavaScript since 0.14 + + '@yuku-parser/binding-android-arm64@0.8.7': + resolution: {integrity: sha512-eGKYiUDX7Y0V7tDTmg+JTVnXnjMqfXXsorZ+EDf5kxwchQ3Or1HS14MzI2fw+jFhHR85fCWt+mtX33Yao73hIQ==} + cpu: [arm64] + os: [android] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-darwin-arm64@0.8.7': + resolution: {integrity: sha512-Re0RHelKLnjEURulY2/KxW+Ngb8zuNA4BRZuMwgGQNzVumT6u4U2N2hc01oeYVNVof0i7GrXE4UCNBgbpRRnjQ==} + cpu: [arm64] + os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-darwin-x64@0.8.7': + resolution: {integrity: sha512-Hn8DROtQkjlA1ACbPgj4a7eP9IuVOI504oiTwpkWPbpaDWD9KdmnVYCqW+1LfenNK/g7O9NhWGpXEdaCNX7lIA==} + cpu: [x64] + os: [darwin] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-freebsd-x64@0.8.7': + resolution: {integrity: sha512-bAP2OV8wRuzplX/jYxv9+vvqQT8JxyNphI8fLfXGL054Xs+4/J5u33cIm3y4rxY8rdoLmmdiJs2Tq7r7lrDRfA==} + cpu: [x64] + os: [freebsd] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-arm-gnu@0.8.7': + resolution: {integrity: sha512-kTYwJQQgmZeAWdDIWabiReIZMpmfLueIj1tCmjStUtFGhR1Z0qwxonKVfUC4N7h/VhGGzLZ//7O1kgt1QKqgCg==} + cpu: [arm] + os: [linux] + libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-arm-musl@0.8.7': + resolution: {integrity: sha512-uL4jE8HPT2BLlxAXyD10LqgPuXa9eDa0BKpCdSANmzIJghq/2eZo3/gQNtaxPZMupWoxjYzSad9IXrwu7aYPXQ==} + cpu: [arm] + os: [linux] + libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-arm64-gnu@0.8.7': + resolution: {integrity: sha512-3gVN4pWSKZmXiNX7cU164dR9MPvesCHnlH6nPfpK+yQsCuYphjKKplcb4SnZBrhiqmXbgb2HR0c2TS0IZUPhgA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-arm64-musl@0.8.7': + resolution: {integrity: sha512-S0mwfEjoLpxzXeZw802Wa4RaELsQiPtWqG6INcy8j4GtvNFtl4LCX3eGO1XLn9pyLAISLzTRyU3zUCBUPin8lg==} + cpu: [arm64] + os: [linux] + libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-x64-gnu@0.8.7': + resolution: {integrity: sha512-lnbWdPmerE5D1uH1G4IEZKnPzCrWCStRGrtgpSIe1RibAo5bZIjDbbbPYXmMHCEh4F+x/JaJpElh26a3r+BPbg==} + cpu: [x64] + os: [linux] + libc: [glibc] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-linux-x64-musl@0.8.7': + resolution: {integrity: sha512-769uwndMvMzUvATWbAcEvyLHKA+DzhHSCl/obBUrRdYfRo26yxui6S8y3z7uJ+Naup7UKrDxrpK7OnQkxkl9KQ==} + cpu: [x64] + os: [linux] + libc: [musl] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-win32-arm64@0.8.7': + resolution: {integrity: sha512-mEB/9PlaAkisJ6KWGz0zvywXoU6+80dTlR2LwS7s/jcXXoU6fm2+sitBZXtqu3+Q4DcDgPxM45uWMCzPs0TSRw==} + cpu: [arm64] + os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-parser/binding-win32-x64@0.8.7': + resolution: {integrity: sha512-8vNB2DP0ou61nGb8tc/qfi41gfyDXz1MHr2zqL3nR+cJ6CEbiuWV/l/a/vv151gCgiZLLAyGkQGENpozdg716w==} + cpu: [x64] + os: [win32] + deprecated: yuku-parser runs on yuku-core since 0.14 + + '@yuku-toolchain/types@0.8.7': + resolution: {integrity: sha512-2Z53dNxAJL6UvFoIrDZvYf3zlO8s4VJK4O2hhaB4mXVwwpX/7ajtss3cmfqKvamlNLWyt9FSWs4eoYdlbxpnHA==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.19.0: + resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + ansis@4.4.0: + resolution: {integrity: sha512-9k3v7xcHwgdO/DruxGIg4HtjvlAZlcnsX/mzqUb1t3NkYnl9kK2UJ+Gq0io+vQf7iT//BD/HB/NBkUR1LWxoeA==} + engines: {node: '>=14'} + + are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.11.27: + resolution: {integrity: sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + + browserslist@4.29.3: + resolution: {integrity: sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + builtin-modules@5.4.0: + resolution: {integrity: sha512-JCWSCdun+4Ovd9BhM/Vtlmwb7oD6Wl4YiPRXXwhAuwlPhW1un/MKgXn7GZoFm53ginnoNzus69V8JWx0K393jg==} + engines: {node: '>=18.20'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@7.0.1: + resolution: {integrity: sha512-86diuUyeeWM8CrqhpGCaDafrzjS1s++7sWy2AbAPoFNz/xKv7ID57CR4pZsMuGCh60PtsnEx4z68b+Vgt07VPw==} + engines: {node: '>=20.19.0'} + + cacheable@2.5.0: + resolution: {integrity: sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==} + + caniuse-lite@1.0.30001815: + resolution: {integrity: sha512-uDybUEyfgbyJJ93J1vikTylBX31AkdVYeVPeffMQpf8XN7hSfr0oZOn4VFOIMNvtU5+rHvC5Udg2TgtJKHm23Q==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@6.3.0: + resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==} + engines: {node: '>=18'} + + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + clean-regexp@1.0.0: + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + comment-parser@1.4.6: + resolution: {integrity: sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==} + engines: {node: '>= 12.0.0'} + + comment-parser@1.4.7: + resolution: {integrity: sha512-0h+uSNtQGW3D98eQt3jJ8L06Fves8hncB4V/PKdw/Qb8Hnk19VaKuTr55UNRYiSoVa7WwrFls+rh3ux9agmkeQ==} + engines: {node: '>= 12.0.0'} + + comment-parser@1.4.9: + resolution: {integrity: sha512-+2AvZKjJaNq9GQljm3tr0utwrig5BL+jgJGvz5rDpGKNIp+ojcRXWUwBbh/sGIi1QCprR6PsKFakub+w1v+4hQ==} + engines: {node: '>= 12.0.0'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + confbox@0.3.1: + resolution: {integrity: sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.50.0: + resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==} + engines: {node: '>=6.4.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + dts-resolver@3.0.0: + resolution: {integrity: sha512-1T1f+z+4tl9XD+m+0HBgWoL/nm0bOIffyWaUuUSBlFg/86IWvfx+wjNaO/ybU0AJzG9/Mi5hBUgGV6zCmWEN7Q==} + engines: {node: ^22.18.0 || >=24.0.0} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + + electron-to-chromium@1.5.451: + resolution: {integrity: sha512-vUNKPrUzw8ByEMOxloq0a71iD/mPuPxVkbDm3G5YhnxTzOw/I6qAg2MUS0cYj/c267lWmw26yW4Vv7foxTxPLg==} + + empathic@2.1.0: + resolution: {integrity: sha512-AnfC1ATldl49/cvZdLPDjBfrRNwbDO05aibiOtzQu3qtlbJtomNLhF30HEtn/7iBz50dlMECqATo3fG0LrdEgw==} + engines: {node: '>=14'} + + enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} + engines: {node: '>=10.13.0'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + eslint-compat-utils@0.5.1: + resolution: {integrity: sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + + eslint-config-flat-gitignore@2.4.0: + resolution: {integrity: sha512-JhYC+V7qEDiCDsbJcVP8fxNc62fk4+i91YLP/YvmVHlkaQ8Xo99olYN8MO5COdxl7onGlsrfZVONe5NYsZP1UA==} + peerDependencies: + eslint: ^9.5.0 || ^10.0.0 + + eslint-flat-config-utils@3.2.0: + resolution: {integrity: sha512-PHgo1X5uqIorJONLVD9BIaOSdoYFD3z/AeJljdqDPlWVRpeCYkDbK9k0AXoYVqqNJr6FEYIEr5Rm2TSktLQcHw==} + + eslint-json-compat-utils@0.2.3: + resolution: {integrity: sha512-RbBmDFyu7FqnjE8F0ZxPNzx5UaptdeS9Uu50r7A+D7s/+FCX+ybiyViYEgFUaFIFqSWJgZRTpL5d8Kanxxl2lQ==} + engines: {node: '>=12'} + peerDependencies: + '@eslint/json': '*' + eslint: '*' + jsonc-eslint-parser: ^2.4.0 || ^3.0.0 + peerDependenciesMeta: + '@eslint/json': + optional: true + + eslint-merge-processors@2.0.0: + resolution: {integrity: sha512-sUuhSf3IrJdGooquEUB5TNpGNpBoQccbnaLHsb1XkBLUPPqCNivCpY05ZcpCOiV9uHwO2yxXEWVczVclzMxYlA==} + peerDependencies: + eslint: '*' + + eslint-plugin-antfu@3.2.3: + resolution: {integrity: sha512-U2fnz/H0gFPxpuC7QpaHa0Jv2AgCZ5hunp36SOP/yWo8yFzgvMh8X4pZ4uN4IKoqtBhk7G3HuVa93Urf51+sZg==} + peerDependencies: + eslint: '*' + + eslint-plugin-command@3.5.3: + resolution: {integrity: sha512-JIhmUOW2K2Dw1K+p4mtj5potkqTZ4ZaicrTkgCygPZCWErP2+O2F46n7ZwGKapeEjiwcVqoY8u01SxNUUXWPeQ==} + peerDependencies: + '@typescript-eslint/typescript-estree': '*' + '@typescript-eslint/utils': '*' + eslint: '*' + + eslint-plugin-de-morgan@2.2.0: + resolution: {integrity: sha512-bHg8e68rQTJ01av4sxhgNWQeoSzPWDjb6MqeKgmgRGaCzq83Ou6/g5S1ZssvFdHHS4BsblkJkagoioUmSEHPMg==} + engines: {node: ^20.0.0 || >=22.0.0} + peerDependencies: + eslint: ^8.45.0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-depend@1.5.0: + resolution: {integrity: sha512-i3UeLYmclf1Icp35+6W7CR4Bp2PIpDgBuf/mpmXK5UeLkZlvYJ21VuQKKHHAIBKRTPivPGX/gZl5JGno1o9Y0A==} + peerDependencies: + eslint: '>=8.40.0' + + eslint-plugin-es-x@7.8.0: + resolution: {integrity: sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + + eslint-plugin-import-lite@0.6.0: + resolution: {integrity: sha512-80vevx2A7i3H7n1/6pqDO8cc5wRz6OwLDvIyVl9UflBV1N1f46e9Ihzi65IOLYoSxM6YykK2fTw1xm0Ixx6aTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.0.0 || ^10.0.0 + + eslint-plugin-jsdoc@62.9.0: + resolution: {integrity: sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-jsonc@3.4.2: + resolution: {integrity: sha512-q5xzjCYFQuhFomTbctXzd3STfDJ8XduvaigjQmMEbP2gzSKrc58y3Fv6D775/cIK1/sRUn+4kpljiU2iW8k0zw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: '>=9.38.0' + + eslint-plugin-n@18.4.1: + resolution: {integrity: sha512-2sBReWOvCbzgkPri9M5SFmD5EbIwZLa1xz6B5RZsrI19WSFKpyx1sOMr+pdk8puCiXuEgCbErEHy1PuaUrc/4w==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: '>=8.57.1' + ts-declaration-location: ^1.0.6 + typescript: '>=5.0.0' + peerDependenciesMeta: + ts-declaration-location: + optional: true + typescript: + optional: true + + eslint-plugin-no-only-tests@3.4.0: + resolution: {integrity: sha512-4S3/9Nb7A2tiMcpzEQE9bQSlpeOz6WJkgryBuou/SA8W2x2c8Zf4j0NvTKBjv6qNhF9T79tmkecm/0CHqV0UGg==} + engines: {node: '>=5.0.0'} + + eslint-plugin-perfectionist@5.12.1: + resolution: {integrity: sha512-krdSE7Dz+TCtcVr2+rfNhlOIFFBJcUdoRvjaN7JQnsaVnxJw+BZh9wMkY3MSLCJat+yW+UPTQLKS82Epc7MGZA==} + engines: {node: ^20.0.0 || >=22.0.0} + peerDependencies: + eslint: ^8.45.0 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + eslint: + optional: true + + eslint-plugin-pnpm@1.9.1: + resolution: {integrity: sha512-8++1Egww2cqc9Wylmt7P+xXNMQVCosAZ4m4W4Gc0V5lGea8HFByHTRvUI+ZvvpO8fLXGg2O4MQc90EhuI3mMdQ==} + peerDependencies: + eslint: ^9.0.0 || ^10.0.0 + + eslint-plugin-prefer-arrow@1.2.3: + resolution: {integrity: sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ==} + peerDependencies: + eslint: '>=2.0.0' + + eslint-plugin-regexp@3.3.1: + resolution: {integrity: sha512-58bGUci/AaWAo1ETj6Lsnmy6QXwnSyVONRA805828nnqp7vrTwdaQMc02vtowmYB3A5OB3SLr3r5HgmfxX4dLg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: '>=9.38.0' + + eslint-plugin-sonarjs@4.2.2: + resolution: {integrity: sha512-usNF9GfP89ibwhfxpZaCMW40sC7UEOusDgDCk7lyqAhh4AYdbBaAgLVL5Y/QS0jSed8eJ2ACGH6zzE8ezd/yZQ==} + peerDependencies: + eslint: ^8.0.0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-toml@1.5.0: + resolution: {integrity: sha512-qBjRywEkKxO2uYOjus//6GVF1r+Hg5QDkRO8RTY6XcaXgWfBU0DhwpFmJa2Ljf0Sz49r7DdZlpKwwHmJ4nmH1Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + peerDependencies: + eslint: '>=9.38.0' + + eslint-plugin-unicorn@64.0.0: + resolution: {integrity: sha512-rNZwalHh8i0UfPlhNwg5BTUO1CMdKNmjqe+TgzOTZnpKoi8VBgsW7u9qCHIdpxEzZ1uwrJrPF0uRb7l//K38gA==} + engines: {node: ^20.10.0 || >=21.0.0} + peerDependencies: + eslint: '>=9.38.0' + + eslint-plugin-unused-imports@4.4.1: + resolution: {integrity: sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 + eslint: ^10.0.0 || ^9.0.0 || ^8.0.0 + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + + eslint-plugin-vue@10.11.1: + resolution: {integrity: sha512-pasVXhl7wUmIvhujoqs/m0mJ9r59QW1IR9XXYKGR0FETzSM+Hhlf4qKIYgWiDDP+9YKv4YfbwskD7LqIdVcgQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@stylistic/eslint-plugin': ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + '@typescript-eslint/parser': ^7.0.0 || ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + vue-eslint-parser: ^10.3.0 + peerDependenciesMeta: + '@stylistic/eslint-plugin': + optional: true + '@typescript-eslint/parser': + optional: true + + eslint-plugin-yml@3.8.1: + resolution: {integrity: sha512-E/70psRwxz5EJ8dBtzrFfqSiiInuSytbdtFCjueb/GcKjsWzPBfxfhtQePImMAPjHwMA/VDurO7DJwStDJ4wWg==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + eslint: '>=9.38.0' + + eslint-processor-vue-blocks@2.0.0: + resolution: {integrity: sha512-u4W0CJwGoWY3bjXAuFpc/b6eK3NQEI8MoeW7ritKj3G3z/WtHrKjkqf+wk8mPEy5rlMGS+k6AZYOw2XBoN/02Q==} + peerDependencies: + '@vue/compiler-sfc': ^3.3.0 + eslint: '>=9.0.0' + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.12.0: + resolution: {integrity: sha512-npHjrHb2o4ehH3mE+YuxABR+0gyb0aVWCIolgJDArwCiHEIsonBm3ZKjel5b0U5+a+MbEvIyRCGCzD3eKKK2NA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + exsolve@1.1.3: + resolution: {integrity: sha512-kuzL9zherLQoqDeQaS55AiiIg1kb4KYXaSusTtgZTPlvKP2gGCI82LNmBNh5RjDVUXIcmgx+/Mx7vPwRzBbhJA==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + + fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@11.1.5: + resolution: {integrity: sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==} + + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@6.1.23: + resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==} + + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} + + format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + functional-red-black-tree@1.0.1: + resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} + + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} + + get-tsconfig@5.0.0-beta.5: + resolution: {integrity: sha512-/6gFNr0N04nob252sTQxyFLi3eKFRqIg1I87YcqAMT1i6SQrSF6KujUEQrtrjMV0H/eejTCltLdDSTEMzHbnsQ==} + engines: {node: '>=20.20.0'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globals@17.13.0: + resolution: {integrity: sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==} + engines: {node: '>=18'} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + hashery@1.5.1: + resolution: {integrity: sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==} + engines: {node: '>=20'} + + hookable@6.1.2: + resolution: {integrity: sha512-+abwxtiEA52GCVIsQqut3S/uKTbUwYIp4Pe/vv+6py5XiXBCqMZHg6pA6Y5qhgLSEys0/cYuPbO0z1QFj5ZCmg==} + + hookified@1.15.1: + resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + + hookified@2.2.0: + resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.12: + resolution: {integrity: sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==} + engines: {node: '>= 4'} + + import-without-cache@0.4.1: + resolution: {integrity: sha512-vXoV9PjKHEednCUu01e98TkImxy67e3BJXbTIOmIq4Hyzw3IAwYRcuPkfeTzJzwyyts4kjuA73x+pWJLc4f86A==} + engines: {node: ^22.18.0 || >=24.0.0} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + + is-builtin-module@5.0.0: + resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} + engines: {node: '>=18.20'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + js-yaml@5.4.3: + resolution: {integrity: sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==} + hasBin: true + + jsdoc-type-pratt-parser@7.2.0: + resolution: {integrity: sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==} + engines: {node: '>=20.0.0'} + + jsdoc-type-pratt-parser@9.2.2: + resolution: {integrity: sha512-eFY7Rlscvv/BpY6UsVsjKwMhu1tJO/F4U/vC9g3yeRy/JqszuO1UP6Vdq+85G+3FP6fEw/sWR8a5ftPFY86csw==} + engines: {node: ^22.22.2 || >=24.15.0} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonc-eslint-parser@3.3.0: + resolution: {integrity: sha512-hYTGkHGNRZnXOFZ1urhINADoqDrGfpy53cjw+dxk84QE0pUDujQzeUeamNs6Mz44/TKD49z2x6/GVSu4ZrtA+Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + jsx-ast-utils-x@0.1.0: + resolution: {integrity: sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + katex@0.16.47: + resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==} + hasBin: true + + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} + engines: {node: '>=14'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + mdast-util-find-and-replace@3.0.3: + resolution: {integrity: sha512-xPgpDNl0/OXHsI7TlaIs22lWnH3KlpvZdXG1ET/m/YT2Hhdkx8lJV4kLphE6l9simyM4KPDFBwas08BgEob6Jw==} + + mdast-util-from-markdown@2.1.0: + resolution: {integrity: sha512-KRLgmPaP2H1ul2bpoJkOS+9pAcDAAj9Nu1mqLnh8NLeJG5tlvj42TH80PIGBpROWlRXLk0lDrWNuZCFy/tsB4A==} + + mdast-util-frontmatter@2.0.1: + resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.1: + resolution: {integrity: sha512-OuJHqvr455pwu2OaOrir7dbzqs4jlWKOtlu9L6GjcIjjQwNyw02VntQsr/Ek6/A13vgnXfUhBekWRUP1OkNivw==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-math@3.0.0: + resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-markdown@2.2.0: + resolution: {integrity: sha512-2Jn/ADrHFFyyniBMi0bncTbJqU78K3/TEYvzvwrWWzD9MYPUa/Gm4r3nOeKFQg/PDM5BsbDYdc8ackW4NTY6NA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + micromark-core-commonmark@2.0.4: + resolution: {integrity: sha512-wxEeE8v8XVvOrxn1TZj74qYhAtTQsSqufHVS3uNVyT1MupXxhyaHk8/9xDNPh9BmL77QNDgWTkZ3RsYHB2ry7w==} + + micromark-extension-frontmatter@2.0.0: + resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.2: + resolution: {integrity: sha512-pRzm4kDTu0MjlmBkxmS9yYhw60nncfcEwu9NNdPFSQEFXS95ZKyIIyTSHu/o3ReBUrLKYEq+7YaXCRn/bPB4MA==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-math@3.1.0: + resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.1.0: + resolution: {integrity: sha512-fS8hnLIjnjvdQIj39Geug8wWsR0HrYZ43KShKxNfwT7t2LOHo/LbWZEzEaSOjwtjdCsjoE6syHhonEzW0zv0+Q==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-edit-map@1.0.0: + resolution: {integrity: sha512-Pa2ljlsEL6sVwFaYeyrOLSYbQt73JvGbPOYFq+9AElXiSnfI5Q4465RRZ1sHv7lDjDOnGRDDaqPXqClqWK/q1Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.3: + resolution: {integrity: sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==} + + micromark@4.0.3: + resolution: {integrity: sha512-oGYfQzHSG5dOMovQcJ3fyTmZlWAWpi0XA0sJwJs+i6OT88o1+Jtw/8z0CmdowSLxGhhFK89rQ/oXph/wN02PNw==} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + module-replacements@2.11.0: + resolution: {integrity: sha512-j5sNQm3VCpQQ7nTqGeOZtoJtV3uKERgCBm9QRhmGRiXiqkf7iRFOkfxdJRZWLkqYY8PNf4cDQF/WfXUYLENrRA==} + + module-replacements@3.4.0: + resolution: {integrity: sha512-NKBNFM/uAUvSs+LOYfSly4EwrC9bgMoFuEnqNNjcDb910W+5IgS2KMB2ERLm5YZZm7R187jx1dMA9pOPvqbSbw==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + natural-orderby@5.0.0: + resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==} + engines: {node: '>=18'} + + node-releases@2.0.57: + resolution: {integrity: sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==} + engines: {node: '>=18'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-deep-merge@2.0.1: + resolution: {integrity: sha512-aKttDKcU3pyZqKcCkDhsMn70WmZFG2JGDQLP9EcLyTSIFQRCPWLAmBZRLJnrVUrhPG1jETEEbfdgbNtJf1LyMg==} + + obug@2.2.1: + resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==} + engines: {node: '>=12.20.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + package-manager-detector@1.9.0: + resolution: {integrity: sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==} + + parse-gitignore@2.0.0: + resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==} + engines: {node: '>=14'} + + parse-imports-exports@0.2.4: + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} + + parse-statements@1.0.11: + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + pkg-types@2.3.3: + resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + pnpm-workspace-yaml@1.9.1: + resolution: {integrity: sha512-Xj/T2X6DNAWbtk/9UQ0/TJRswltiHZevmcMjqoL7WrpJi67lu3qaslU4+I+zJ8wtwqmuvAE0KkB8rbv2ZdogBg==} + + postcss-selector-parser@7.1.6: + resolution: {integrity: sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw==} + engines: {node: '>=4'} + + postcss@8.5.29: + resolution: {integrity: sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qified@0.10.1: + resolution: {integrity: sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==} + engines: {node: '>=20'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + + refa@0.12.1: + resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + regexp-ast-analysis@0.7.1: + resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + + regjsparser@0.13.4: + resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==} + hasBin: true + + reserved-identifiers@1.2.0: + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + rolldown-plugin-dts@0.27.14: + resolution: {integrity: sha512-ZvuDDwoIpRK9RPxDXratCpklFO9QZZWndf/sd0VBFb4LEj0jj07UcHK9OCh7V4XiFz2Z89ziyBC2K6tJiDjrbw==} + engines: {node: ^22.18.0 || >=24.11.0} + peerDependencies: + '@typescript/native-preview': '*' + '@volar/typescript': ~2.4.0 + rolldown: ^1.0.0 + typescript: ^5.0.0 || ^6.0.0 || ~7.0.0 + vue-tsc: ~3.2.0 || ~3.3.0 + peerDependenciesMeta: + '@typescript/native-preview': + optional: true + '@volar/typescript': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.2.13: + resolution: {integrity: sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + scslre@0.3.0: + resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} + engines: {node: ^14.0.0 || >=16.0.0} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + + spdx-license-ids@3.0.24: + resolution: {integrity: sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.3.0: + resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} + + strip-indent@4.1.1: + resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} + engines: {node: '>=12'} + + synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} + engines: {node: ^14.18.0 || >=16.0.0} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.3.1: + resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinyrainbow@3.2.0: + resolution: {integrity: sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==} + engines: {node: '>=14.0.0'} + + to-valid-identifier@1.0.0: + resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} + engines: {node: '>=20'} + + toml-eslint-parser@1.0.3: + resolution: {integrity: sha512-A5F0cM6+mDleacLIEUkmfpkBbnHJFV1d2rprHU2MXNk7mlxHq2zGojA+SRvQD1RoMo9gqjZPWEaKG4v1BQ48lw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tsdown@0.22.14: + resolution: {integrity: sha512-ule7Y+fsAN2iZbLDoo7C4KYljFJNJJ+fLshyn+9gozeTspVersWHxwdGB+Dm2hzA38s6muFnUTl0jK3vJm9ifQ==} + engines: {node: ^22.18.0 || >=24.11.0} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@tsdown/css': 0.22.14 + '@tsdown/exe': 0.22.14 + '@vitejs/devtools': '*' + publint: ^0.3.8 + tsx: '*' + typescript: ^5.0.0 || ^6.0.0 || ^7.0.0 + unplugin-unused: ^0.5.0 + unrun: '*' + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@tsdown/css': + optional: true + '@tsdown/exe': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + tsx: + optional: true + typescript: + optional: true + unplugin-unused: + optional: true + unrun: + optional: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + update-browserslist-db@1.3.4: + resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + valibot@1.5.0: + resolution: {integrity: sha512-nil6AkP2TChWL43Z5uJ6GTxX01CUA+g8LWUM+N/rB9NBbkUMaUsi9PUNzlUPgoKASgmx9f7eGOYpJ04/fSa6FQ==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + + verkit@0.3.2: + resolution: {integrity: sha512-zj/ob3UsvJGN0whEAKFp53REA5X66hvffVqoCtVQAakJKnKlH+/PcOfMoFwIG/o4rElqLv/ycAFlx8ZlXUorCg==} + engines: {node: '>=18.12.0'} + + vite@8.3.3: + resolution: {integrity: sha512-cTAldKPImjg6c+gk48U19POPn3GCBzZwpdsN8ZMEEcbpes+6/wvfqUd0C2y3qYY4wsj8PwgFwrZ/1jBPVttMSg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.7.1 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.11: + resolution: {integrity: sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.11 + '@vitest/browser-preview': 4.1.11 + '@vitest/browser-webdriverio': 4.1.11 + '@vitest/coverage-istanbul': 4.1.11 + '@vitest/coverage-v8': 4.1.11 + '@vitest/ui': 4.1.11 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vue-eslint-parser@10.4.1: + resolution: {integrity: sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + yaml-eslint-parser@2.1.0: + resolution: {integrity: sha512-1zo9KRfp6vIAXBEhWAz09ex3hUwh3T+/6dGbGteHvNseA0Uk4FgQnPES55klZ6cDzSy9FpgKS0D/CoLUvCCj4w==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} + engines: {node: '>= 14.6'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yuku-ast@0.8.7: + resolution: {integrity: sha512-h6+4bDfyootiMB9vckk5uKo5r5j0GHrkr17FQTDNfEsFT3DWlN9uu1HJwQwc64pgmLCI945fWM3lbTIqxjT3GQ==} + + yuku-codegen@0.8.7: + resolution: {integrity: sha512-adwDZSh8oVDzhE6Du9PwVWxcOxeV0e2EVhUuMKWfhSY4wkrDq9eqixlxFF3l/XGUV1E7UFzhpz9393MUumkyNw==} + + yuku-parser@0.8.7: + resolution: {integrity: sha512-vRD9nwt4L3aYpxNqeSC4WqLv58xrXef0Ong1Mc45CTXTIpvLafx7JO05sczmQZwdLEZvywrLOGdNC5+Rp5N1BQ==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@antfu/eslint-config@8.3.0(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)))': + dependencies: + '@antfu/install-pkg': 1.1.0 + '@clack/prompts': 1.8.1 + '@e18e/eslint-plugin': 0.4.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint-community/eslint-plugin-eslint-comments': 4.8.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint/markdown': 8.0.3 + '@stylistic/eslint-plugin': 5.10.0(eslint@10.12.0(jiti@2.7.0)) + '@typescript-eslint/eslint-plugin': 8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/parser': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@vitest/eslint-plugin': 1.6.27(@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1))) + ansis: 4.4.0 + cac: 7.0.1 + eslint: 10.12.0(jiti@2.7.0) + eslint-config-flat-gitignore: 2.4.0(eslint@10.12.0(jiti@2.7.0)) + eslint-flat-config-utils: 3.2.0 + eslint-merge-processors: 2.0.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-antfu: 3.2.3(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-command: 3.5.3(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-import-lite: 0.6.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-jsdoc: 62.9.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-jsonc: 3.4.2(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-n: 18.4.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + eslint-plugin-no-only-tests: 3.4.0 + eslint-plugin-perfectionist: 5.12.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + eslint-plugin-pnpm: 1.9.1(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-regexp: 3.3.1(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-toml: 1.5.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-unicorn: 64.0.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-unused-imports: 4.4.1(@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-vue: 10.11.1(@stylistic/eslint-plugin@5.10.0(eslint@10.12.0(jiti@2.7.0)))(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(vue-eslint-parser@10.4.1(eslint@10.12.0(jiti@2.7.0))) + eslint-plugin-yml: 3.8.1(eslint@10.12.0(jiti@2.7.0)) + eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0)) + globals: 17.13.0 + local-pkg: 1.2.1 + parse-gitignore: 2.0.0 + toml-eslint-parser: 1.0.3 + vue-eslint-parser: 10.4.1(eslint@10.12.0(jiti@2.7.0)) + yaml-eslint-parser: 2.1.0 + transitivePeerDependencies: + - '@eslint/json' + - '@typescript-eslint/typescript-estree' + - '@typescript-eslint/utils' + - '@vue/compiler-sfc' + - oxlint + - supports-color + - ts-declaration-location + - typescript + - vitest + + '@antfu/install-pkg@1.1.0': + dependencies: + package-manager-detector: 1.9.0 + tinyexec: 1.3.1 + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@cacheable/memory@2.2.0': + dependencies: + '@cacheable/utils': 2.5.0 + '@keyv/bigmap': 1.3.1(keyv@5.6.0) + hookified: 1.15.1 + keyv: 5.6.0 + + '@cacheable/utils@2.5.0': + dependencies: + hashery: 1.5.1 + keyv: 5.6.0 + + '@clack/core@1.5.1': + dependencies: + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + + '@clack/prompts@1.8.1': + dependencies: + '@clack/core': 1.5.1 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + + '@e18e/eslint-plugin@0.4.1(eslint@10.12.0(jiti@2.7.0))': + dependencies: + empathic: 2.1.0 + module-replacements: 3.4.0 + semver: 7.8.5 + optionalDependencies: + eslint: 10.12.0(jiti@2.7.0) + + '@es-joy/jsdoccomment@0.86.0': + dependencies: + '@types/estree': 1.0.9 + '@typescript-eslint/types': 8.71.1 + comment-parser: 1.4.6 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 7.2.0 + + '@es-joy/jsdoccomment@0.88.0': + dependencies: + '@types/estree': 1.0.9 + '@typescript-eslint/types': 8.71.1 + comment-parser: 1.4.7 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 7.2.0 + + '@es-joy/resolve.exports@1.2.0': {} + + '@eslint-community/eslint-plugin-eslint-comments@4.8.1(eslint@10.12.0(jiti@2.7.0))': + dependencies: + escape-string-regexp: 4.0.0 + eslint: 10.12.0(jiti@2.7.0) + ignore: 7.0.12 + + '@eslint-community/eslint-utils@4.10.1(eslint@10.12.0(jiti@2.7.0))': + dependencies: + eslint: 10.12.0(jiti@2.7.0) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/compat@2.1.1(eslint@10.12.0(jiti@2.7.0))': + dependencies: + '@eslint/core': 1.2.1 + optionalDependencies: + eslint: 10.12.0(jiti@2.7.0) + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.6 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.5.5': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/config-helpers@0.7.0': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/core@1.2.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/markdown@8.0.3': + dependencies: + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.3 + github-slugger: 2.0.0 + mdast-util-from-markdown: 2.1.0 + mdast-util-frontmatter: 2.0.1 + mdast-util-gfm: 3.1.0 + mdast-util-math: 3.0.0 + micromark-extension-frontmatter: 2.0.0 + micromark-extension-gfm: 3.0.0 + micromark-extension-math: 3.1.0 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@eslint/object-schema@3.0.5': {} + + '@eslint/plugin-kit@0.7.3': + dependencies: + '@eslint/core': 1.2.1 + levn: 0.4.1 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@keyv/bigmap@1.3.1(keyv@5.6.0)': + dependencies: + hashery: 1.5.1 + hookified: 1.15.1 + keyv: 5.6.0 + + '@keyv/serialize@1.1.1': {} + + '@masknet/eslint-plugin@0.4.1(eslint@10.12.0(jiti@2.7.0))': + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + '@moeru/eslint-config@0.1.0-beta.20(@antfu/eslint-config@8.3.0(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1))))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@antfu/eslint-config': 8.3.0(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1))) + '@masknet/eslint-plugin': 0.4.1(eslint@10.12.0(jiti@2.7.0)) + '@moeru/std': 0.1.0-beta.20 + eslint: 10.12.0(jiti@2.7.0) + eslint-flat-config-utils: 3.2.0 + eslint-plugin-de-morgan: 2.2.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-depend: 1.5.0(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-perfectionist: 5.12.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + eslint-plugin-prefer-arrow: 1.2.3(eslint@10.12.0(jiti@2.7.0)) + eslint-plugin-sonarjs: 4.2.2(eslint@10.12.0(jiti@2.7.0)) + tinyexec: 1.3.1 + transitivePeerDependencies: + - supports-color + - typescript + + '@moeru/std@0.1.0-beta.20': {} + + '@ota-meshi/ast-token-store@0.3.0': {} + + '@oxc-project/types@0.153.0': {} + + '@pkgr/core@0.3.6': {} + + '@quansync/fs@1.1.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm-eabi@1.2.13': + optional: true + + '@rolldown/binding-android-arm64@1.2.13': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.13': + optional: true + + '@rolldown/binding-darwin-x64@1.2.13': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.13': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.13': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.13': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.13': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.13': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.13': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.13': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.13': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.13': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.13': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.13': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@sindresorhus/base62@1.0.0': {} + + '@sonarsource/analyzer-commons-configurations@2.31.0-5284': {} + + '@standard-schema/spec@1.1.0': {} + + '@stylistic/eslint-plugin@5.10.0(eslint@10.12.0(jiti@2.7.0))': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@typescript-eslint/types': 8.71.1 + eslint: 10.12.0(jiti@2.7.0) + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + estraverse: 5.3.0 + picomatch: 4.0.7 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/deep-eql@4.0.2': {} + + '@types/esrecurse@4.3.1': {} + + '@types/estree@1.0.9': {} + + '@types/hast@3.0.5': + dependencies: + '@types/unist': 3.0.3 + + '@types/json-schema@7.0.15': {} + + '@types/katex@0.16.8': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@2.1.0': {} + + '@types/node@26.6.4': + dependencies: + undici-types: 8.9.0 + + '@types/unist@3.0.3': {} + + '@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/type-utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.71.1 + eslint: 10.12.0(jiti@2.7.0) + ignore: 7.0.12 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.71.1 + debug: 4.4.3 + eslint: 10.12.0(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.71.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@6.0.3) + '@typescript-eslint/types': 8.71.1 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.71.1': + dependencies: + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/visitor-keys': 8.71.1 + + '@typescript-eslint/tsconfig-utils@8.71.1(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + debug: 4.4.3 + eslint: 10.12.0(jiti@2.7.0) + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.71.1': {} + + '@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.71.1(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.71.1(typescript@6.0.3) + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/visitor-keys': 8.71.1 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@6.0.3) + eslint: 10.12.0(jiti@2.7.0) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.71.1': + dependencies: + '@typescript-eslint/types': 8.71.1 + eslint-visitor-keys: 5.0.1 + + '@vitest/eslint-plugin@1.6.27(@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3)(vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)))': + dependencies: + '@typescript-eslint/scope-manager': 8.71.1 + '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.12.0(jiti@2.7.0) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + typescript: 6.0.3 + vitest: 4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@4.1.11': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 + chai: 6.3.0 + tinyrainbow: 3.2.0 + + '@vitest/mocker@4.1.11(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1))': + dependencies: + '@vitest/spy': 4.1.11 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1) + + '@vitest/pretty-format@4.1.11': + dependencies: + tinyrainbow: 3.2.0 + + '@vitest/runner@4.1.11': + dependencies: + '@vitest/utils': 4.1.11 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.11': + dependencies: + '@vitest/pretty-format': 4.1.11 + '@vitest/utils': 4.1.11 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.11': {} + + '@vitest/utils@4.1.11': + dependencies: + '@vitest/pretty-format': 4.1.11 + convert-source-map: 2.0.0 + tinyrainbow: 3.2.0 + + '@vue/compiler-core@3.5.43': + dependencies: + '@babel/parser': 7.29.9 + '@vue/shared': 3.5.43 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.2 + + '@vue/compiler-dom@3.5.43': + dependencies: + '@vue/compiler-core': 3.5.43 + '@vue/shared': 3.5.43 + + '@vue/compiler-sfc@3.5.43': + dependencies: + '@babel/parser': 7.29.9 + '@vue/compiler-core': 3.5.43 + '@vue/compiler-dom': 3.5.43 + '@vue/compiler-ssr': 3.5.43 + '@vue/shared': 3.5.43 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.29 + source-map-js: 1.2.2 + + '@vue/compiler-ssr@3.5.43': + dependencies: + '@vue/compiler-dom': 3.5.43 + '@vue/shared': 3.5.43 + + '@vue/shared@3.5.43': {} + + '@yuku-codegen/binding-android-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-darwin-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-darwin-x64@0.8.7': + optional: true + + '@yuku-codegen/binding-freebsd-x64@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm64-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-arm64-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-x64-gnu@0.8.7': + optional: true + + '@yuku-codegen/binding-linux-x64-musl@0.8.7': + optional: true + + '@yuku-codegen/binding-win32-arm64@0.8.7': + optional: true + + '@yuku-codegen/binding-win32-x64@0.8.7': + optional: true + + '@yuku-parser/binding-android-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-darwin-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-darwin-x64@0.8.7': + optional: true + + '@yuku-parser/binding-freebsd-x64@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm-musl@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm64-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-arm64-musl@0.8.7': + optional: true + + '@yuku-parser/binding-linux-x64-gnu@0.8.7': + optional: true + + '@yuku-parser/binding-linux-x64-musl@0.8.7': + optional: true + + '@yuku-parser/binding-win32-arm64@0.8.7': + optional: true + + '@yuku-parser/binding-win32-x64@0.8.7': + optional: true + + '@yuku-toolchain/types@0.8.7': {} + + acorn-jsx@5.3.2(acorn@8.19.0): + dependencies: + acorn: 8.19.0 + + acorn@8.19.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansis@4.4.0: {} + + are-docs-informative@0.0.2: {} + + argparse@2.0.1: {} + + assertion-error@2.0.1: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.11.27: {} + + boolbase@1.0.0: {} + + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.29.3: + dependencies: + baseline-browser-mapping: 2.11.27 + caniuse-lite: 1.0.30001815 + electron-to-chromium: 1.5.451 + node-releases: 2.0.57 + update-browserslist-db: 1.3.4(browserslist@4.29.3) + + builtin-modules@3.3.0: {} + + builtin-modules@5.4.0: {} + + bytes@3.1.2: {} + + cac@7.0.1: {} + + cacheable@2.5.0: + dependencies: + '@cacheable/memory': 2.2.0 + '@cacheable/utils': 2.5.0 + hookified: 1.15.1 + keyv: 5.6.0 + qified: 0.10.1 + + caniuse-lite@1.0.30001815: {} + + ccount@2.0.1: {} + + chai@6.3.0: {} + + change-case@5.4.4: {} + + character-entities@2.0.2: {} + + ci-info@4.4.0: {} + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + commander@8.3.0: {} + + comment-parser@1.4.6: {} + + comment-parser@1.4.7: {} + + comment-parser@1.4.9: {} + + confbox@0.1.8: {} + + confbox@0.3.1: {} + + convert-source-map@2.0.0: {} + + core-js-compat@3.50.0: + dependencies: + browserslist: 4.29.3 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + deep-is@0.1.4: {} + + defu@6.1.7: {} + + dequal@2.0.3: {} + + detect-libc@2.1.2: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff-sequences@29.6.3: {} + + dts-resolver@3.0.0: {} + + electron-to-chromium@1.5.451: {} + + empathic@2.1.0: {} + + enhanced-resolve@5.26.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + entities@7.0.1: {} + + es-module-lexer@2.3.2: {} + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escape-string-regexp@5.0.0: {} + + eslint-compat-utils@0.5.1(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + semver: 7.8.5 + + eslint-config-flat-gitignore@2.4.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint/compat': 2.1.1(eslint@10.12.0(jiti@2.7.0)) + eslint: 10.12.0(jiti@2.7.0) + + eslint-flat-config-utils@3.2.0: + dependencies: + '@eslint/config-helpers': 0.5.5 + pathe: 2.0.3 + + eslint-json-compat-utils@0.2.3(eslint@10.12.0(jiti@2.7.0))(jsonc-eslint-parser@3.3.0): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + esquery: 1.7.0 + jsonc-eslint-parser: 3.3.0 + + eslint-merge-processors@2.0.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-antfu@3.2.3(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-command@3.5.3(@typescript-eslint/typescript-estree@8.71.1(typescript@6.0.3))(@typescript-eslint/utils@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@es-joy/jsdoccomment': 0.88.0 + '@typescript-eslint/typescript-estree': 8.71.1(typescript@6.0.3) + '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-de-morgan@2.2.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-depend@1.5.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + empathic: 2.1.0 + eslint: 10.12.0(jiti@2.7.0) + module-replacements: 2.11.0 + semver: 7.8.5 + + eslint-plugin-es-x@7.8.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint-community/regexpp': 4.12.2 + eslint: 10.12.0(jiti@2.7.0) + eslint-compat-utils: 0.5.1(eslint@10.12.0(jiti@2.7.0)) + + eslint-plugin-import-lite@0.6.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-jsdoc@62.9.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@es-joy/jsdoccomment': 0.86.0 + '@es-joy/resolve.exports': 1.2.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint: 10.12.0(jiti@2.7.0) + espree: 11.2.0 + esquery: 1.7.0 + html-entities: 2.6.0 + object-deep-merge: 2.0.1 + parse-imports-exports: 0.2.4 + semver: 7.8.5 + spdx-expression-parse: 4.0.0 + to-valid-identifier: 1.0.0 + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsonc@3.4.2(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.3 + '@ota-meshi/ast-token-store': 0.3.0 + diff-sequences: 29.6.3 + eslint: 10.12.0(jiti@2.7.0) + eslint-json-compat-utils: 0.2.3(eslint@10.12.0(jiti@2.7.0))(jsonc-eslint-parser@3.3.0) + jsonc-eslint-parser: 3.3.0 + natural-compare: 1.4.0 + synckit: 0.11.13 + transitivePeerDependencies: + - '@eslint/json' + + eslint-plugin-n@18.4.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + enhanced-resolve: 5.26.0 + eslint: 10.12.0(jiti@2.7.0) + eslint-plugin-es-x: 7.8.0(eslint@10.12.0(jiti@2.7.0)) + get-tsconfig: 4.14.3 + globals: 15.15.0 + globrex: 0.1.2 + ignore: 5.3.2 + js-yaml: 5.4.3 + semver: 7.8.5 + optionalDependencies: + typescript: 6.0.3 + + eslint-plugin-no-only-tests@3.4.0: {} + + eslint-plugin-perfectionist@5.12.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@typescript-eslint/types': 8.71.1 + '@typescript-eslint/utils': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + natural-orderby: 5.0.0 + optionalDependencies: + eslint: 10.12.0(jiti@2.7.0) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-pnpm@1.9.1(eslint@10.12.0(jiti@2.7.0)): + dependencies: + empathic: 2.1.0 + eslint: 10.12.0(jiti@2.7.0) + eslint-json-compat-utils: 0.2.3(eslint@10.12.0(jiti@2.7.0))(jsonc-eslint-parser@3.3.0) + jsonc-eslint-parser: 3.3.0 + pathe: 2.0.3 + pnpm-workspace-yaml: 1.9.1 + tinyglobby: 0.2.17 + yaml: 2.9.1 + yaml-eslint-parser: 2.1.0 + transitivePeerDependencies: + - '@eslint/json' + + eslint-plugin-prefer-arrow@1.2.3(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + + eslint-plugin-regexp@3.3.1(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint-community/regexpp': 4.12.2 + comment-parser: 1.4.9 + eslint: 10.12.0(jiti@2.7.0) + jsdoc-type-pratt-parser: 9.2.2 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + + eslint-plugin-sonarjs@4.2.2(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@sonarsource/analyzer-commons-configurations': 2.31.0-5284 + builtin-modules: 3.3.0 + bytes: 3.1.2 + eslint: 10.12.0(jiti@2.7.0) + functional-red-black-tree: 1.0.1 + globals: 17.13.0 + jsx-ast-utils-x: 0.1.0 + lodash.merge: 4.6.2 + minimatch: 10.2.6 + scslre: 0.3.0 + semver: 7.8.5 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + yaml: 2.9.1 + + eslint-plugin-toml@1.5.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.3 + '@ota-meshi/ast-token-store': 0.3.0 + debug: 4.4.3 + eslint: 10.12.0(jiti@2.7.0) + toml-eslint-parser: 1.0.3 + transitivePeerDependencies: + - supports-color + + eslint-plugin-unicorn@64.0.0(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + change-case: 5.4.4 + ci-info: 4.4.0 + clean-regexp: 1.0.0 + core-js-compat: 3.50.0 + eslint: 10.12.0(jiti@2.7.0) + find-up-simple: 1.0.1 + globals: 17.13.0 + indent-string: 5.0.0 + is-builtin-module: 5.0.0 + jsesc: 3.1.0 + pluralize: 8.0.0 + regexp-tree: 0.1.27 + regjsparser: 0.13.4 + semver: 7.8.5 + strip-indent: 4.1.1 + + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0)): + dependencies: + eslint: 10.12.0(jiti@2.7.0) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.71.1(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + + eslint-plugin-vue@10.11.1(@stylistic/eslint-plugin@5.10.0(eslint@10.12.0(jiti@2.7.0)))(@typescript-eslint/parser@8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.12.0(jiti@2.7.0))(vue-eslint-parser@10.4.1(eslint@10.12.0(jiti@2.7.0))): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + eslint: 10.12.0(jiti@2.7.0) + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 7.1.6 + semver: 7.8.5 + vue-eslint-parser: 10.4.1(eslint@10.12.0(jiti@2.7.0)) + xml-name-validator: 5.0.0 + optionalDependencies: + '@stylistic/eslint-plugin': 5.10.0(eslint@10.12.0(jiti@2.7.0)) + '@typescript-eslint/parser': 8.71.1(eslint@10.12.0(jiti@2.7.0))(typescript@6.0.3) + + eslint-plugin-yml@3.8.1(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.3 + '@ota-meshi/ast-token-store': 0.3.0 + diff-sequences: 29.6.3 + escape-string-regexp: 5.0.0 + eslint: 10.12.0(jiti@2.7.0) + natural-compare: 1.4.0 + yaml-eslint-parser: 2.1.0 + + eslint-processor-vue-blocks@2.0.0(@vue/compiler-sfc@3.5.43)(eslint@10.12.0(jiti@2.7.0)): + dependencies: + '@vue/compiler-sfc': 3.5.43 + eslint: 10.12.0(jiti@2.7.0) + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@10.12.0(jiti@2.7.0): + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.12.0(jiti@2.7.0)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.7.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.3 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 11.1.5 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + minimatch: 10.2.6 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.19.0 + acorn-jsx: 5.3.2(acorn@8.19.0) + eslint-visitor-keys: 4.2.1 + + espree@11.2.0: + dependencies: + acorn: 8.19.0 + acorn-jsx: 5.3.2(acorn@8.19.0) + eslint-visitor-keys: 5.0.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + expect-type@1.4.0: {} + + exsolve@1.1.3: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-string-truncated-width@3.0.3: {} + + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + + fast-wrap-ansi@0.2.2: + dependencies: + fast-string-width: 3.0.2 + + fault@2.0.1: + dependencies: + format: 0.2.2 + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + file-entry-cache@11.1.5: + dependencies: + flat-cache: 6.1.23 + + find-up-simple@1.0.1: {} + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@6.1.23: + dependencies: + cacheable: 2.5.0 + flatted: 3.4.4 + hookified: 1.15.1 + + flatted@3.4.4: {} + + format@0.2.2: {} + + fsevents@2.3.3: + optional: true + + functional-red-black-tree@1.0.1: {} + + get-tsconfig@4.14.3: + dependencies: + resolve-pkg-maps: 1.0.0 + + get-tsconfig@5.0.0-beta.5: + dependencies: + resolve-pkg-maps: 1.0.0 + + github-slugger@2.0.0: {} + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + globals@15.15.0: {} + + globals@17.13.0: {} + + globrex@0.1.2: {} + + graceful-fs@4.2.11: {} + + hashery@1.5.1: + dependencies: + hookified: 1.15.1 + + hookable@6.1.2: {} + + hookified@1.15.1: {} + + hookified@2.2.0: {} + + html-entities@2.6.0: {} + + ignore@5.3.2: {} + + ignore@7.0.12: {} + + import-without-cache@0.4.1: {} + + imurmurhash@0.1.4: {} + + indent-string@5.0.0: {} + + is-builtin-module@5.0.0: + dependencies: + builtin-modules: 5.4.0 + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + isexe@2.0.0: {} + + jiti@2.7.0: {} + + js-yaml@5.4.3: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@7.2.0: {} + + jsdoc-type-pratt-parser@9.2.2: + dependencies: + '@types/estree': 1.0.9 + '@types/node': 26.6.4 + + jsesc@3.1.0: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jsonc-eslint-parser@3.3.0: + dependencies: + acorn: 8.19.0 + eslint-visitor-keys: 5.0.1 + verkit: 0.3.2 + + jsx-ast-utils-x@0.1.0: {} + + katex@0.16.47: + dependencies: + commander: 8.3.0 + + keyv@5.6.0: + dependencies: + '@keyv/serialize': 1.1.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + local-pkg@1.2.1: + dependencies: + mlly: 1.8.2 + pkg-types: 2.3.3 + quansync: 0.2.11 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + longest-streak@3.1.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + markdown-table@3.0.4: {} + + mdast-util-find-and-replace@3.0.3: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.3 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-frontmatter@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + escape-string-regexp: 5.0.0 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + micromark-extension-frontmatter: 2.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.3 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.1.0 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.0 + mdast-util-gfm-strikethrough: 2.0.1 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.2.0 + transitivePeerDependencies: + - supports-color + + mdast-util-math@3.0.0: + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + longest-streak: 3.1.0 + mdast-util-from-markdown: 2.1.0 + mdast-util-to-markdown: 2.2.0 + unist-util-remove-position: 5.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-markdown@2.2.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-character: 2.1.1 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + micromark-core-commonmark@2.0.4: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.1.0 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-edit-map: 1.0.0 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-frontmatter@2.0.0: + dependencies: + fault: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.4 + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm-table@2.1.2: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.3 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.2 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-extension-math@3.1.0: + dependencies: + '@types/katex': 0.16.8 + devlop: 1.1.0 + katex: 0.16.47 + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-factory-space@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.3 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-edit-map@1.0.0: + dependencies: + micromark-util-types: 2.0.3 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.3 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.3: {} + + micromark@4.0.3: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.4 + micromark-factory-space: 2.1.0 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-edit-map: 1.0.0 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + transitivePeerDependencies: + - supports-color + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + + mlly@1.8.2: + dependencies: + acorn: 8.19.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + module-replacements@2.11.0: {} + + module-replacements@3.4.0: {} + + ms@2.1.3: {} + + nanoid@3.3.20: {} + + natural-compare@1.4.0: {} + + natural-orderby@5.0.0: {} + + node-releases@2.0.57: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-deep-merge@2.0.1: {} + + obug@2.2.1: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + package-manager-detector@1.9.0: {} + + parse-gitignore@2.0.0: {} + + parse-imports-exports@0.2.4: + dependencies: + parse-statements: 1.0.11 + + parse-statements@1.0.11: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + pkg-types@2.3.3: + dependencies: + confbox: 0.3.1 + exsolve: 1.1.3 + pathe: 2.0.3 + + pluralize@8.0.0: {} + + pnpm-workspace-yaml@1.9.1: + dependencies: + yaml: 2.9.1 + + postcss-selector-parser@7.1.6: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss@8.5.29: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + prelude-ls@1.2.1: {} + + punycode@2.3.1: {} + + qified@0.10.1: + dependencies: + hookified: 2.2.0 + + quansync@0.2.11: {} + + quansync@1.0.0: {} + + refa@0.12.1: + dependencies: + '@eslint-community/regexpp': 4.12.2 + + regexp-ast-analysis@0.7.1: + dependencies: + '@eslint-community/regexpp': 4.12.2 + refa: 0.12.1 + + regexp-tree@0.1.27: {} + + regjsparser@0.13.4: + dependencies: + jsesc: 3.1.0 + + reserved-identifiers@1.2.0: {} + + resolve-pkg-maps@1.0.0: {} + + rolldown-plugin-dts@0.27.14(rolldown@1.2.13)(typescript@6.0.3): + dependencies: + dts-resolver: 3.0.0 + get-tsconfig: 5.0.0-beta.5 + obug: 2.2.1 + rolldown: 1.2.13 + yuku-ast: 0.8.7 + yuku-codegen: 0.8.7 + yuku-parser: 0.8.7 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.2.13: + dependencies: + '@oxc-project/types': 0.153.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm-eabi': 1.2.13 + '@rolldown/binding-android-arm64': 1.2.13 + '@rolldown/binding-darwin-arm64': 1.2.13 + '@rolldown/binding-darwin-x64': 1.2.13 + '@rolldown/binding-freebsd-x64': 1.2.13 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.13 + '@rolldown/binding-linux-arm64-gnu': 1.2.13 + '@rolldown/binding-linux-arm64-musl': 1.2.13 + '@rolldown/binding-linux-ppc64-gnu': 1.2.13 + '@rolldown/binding-linux-s390x-gnu': 1.2.13 + '@rolldown/binding-linux-x64-gnu': 1.2.13 + '@rolldown/binding-linux-x64-musl': 1.2.13 + '@rolldown/binding-openharmony-arm64': 1.2.13 + '@rolldown/binding-win32-arm64-msvc': 1.2.13 + '@rolldown/binding-win32-x64-msvc': 1.2.13 + + scslre@0.3.0: + dependencies: + '@eslint-community/regexpp': 4.12.2 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + + semver@7.8.5: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + sisteransi@1.0.5: {} + + source-map-js@1.2.2: {} + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.24 + + spdx-license-ids@3.0.24: {} + + stackback@0.0.2: {} + + std-env@4.3.0: {} + + strip-indent@4.1.1: {} + + synckit@0.11.13: + dependencies: + '@pkgr/core': 0.3.6 + + tapable@2.3.3: {} + + tinybench@2.9.0: {} + + tinyexec@1.3.1: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + tinyrainbow@3.2.0: {} + + to-valid-identifier@1.0.0: + dependencies: + '@sindresorhus/base62': 1.0.0 + reserved-identifiers: 1.2.0 + + toml-eslint-parser@1.0.3: + dependencies: + eslint-visitor-keys: 5.0.1 + + tree-kill@1.2.2: {} + + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + tsdown@0.22.14(typescript@6.0.3): + dependencies: + ansis: 4.4.0 + cac: 7.0.1 + defu: 6.1.7 + empathic: 2.1.0 + hookable: 6.1.2 + import-without-cache: 0.4.1 + obug: 2.2.1 + picomatch: 4.0.7 + rolldown: 1.2.13 + rolldown-plugin-dts: 0.27.14(rolldown@1.2.13)(typescript@6.0.3) + tinyexec: 1.3.1 + tinyglobby: 0.2.17 + tree-kill: 1.2.2 + unconfig-core: 7.5.0 + verkit: 0.3.2 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - '@typescript/native-preview' + - '@volar/typescript' + - oxc-resolver + - vue-tsc + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript@6.0.3: {} + + ufo@1.6.4: {} + + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.1.0 + quansync: 1.0.0 + + undici-types@8.9.0: {} + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + update-browserslist-db@1.3.4(browserslist@4.29.3): + dependencies: + browserslist: 4.29.3 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + util-deprecate@1.0.2: {} + + valibot@1.5.0(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + verkit@0.3.2: {} + + vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.29 + rolldown: 1.2.13 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 26.6.4 + fsevents: 2.3.3 + jiti: 2.7.0 + yaml: 2.9.1 + + vitest@4.1.11(@types/node@26.6.4)(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)): + dependencies: + '@vitest/expect': 4.1.11 + '@vitest/mocker': 4.1.11(vite@8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1)) + '@vitest/pretty-format': 4.1.11 + '@vitest/runner': 4.1.11 + '@vitest/snapshot': 4.1.11 + '@vitest/spy': 4.1.11 + '@vitest/utils': 4.1.11 + es-module-lexer: 2.3.2 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.2.1 + pathe: 2.0.3 + picomatch: 4.0.7 + std-env: 4.3.0 + tinybench: 2.9.0 + tinyexec: 1.3.1 + tinyglobby: 0.2.17 + tinyrainbow: 3.2.0 + vite: 8.3.3(@types/node@26.6.4)(jiti@2.7.0)(yaml@2.9.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 26.6.4 + transitivePeerDependencies: + - msw + + vue-eslint-parser@10.4.1(eslint@10.12.0(jiti@2.7.0)): + dependencies: + debug: 4.4.3 + eslint: 10.12.0(jiti@2.7.0) + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + xml-name-validator@5.0.0: {} + + yaml-eslint-parser@2.1.0: + dependencies: + eslint-visitor-keys: 5.0.1 + yaml: 2.9.1 + + yaml@2.9.1: {} + + yocto-queue@0.1.0: {} + + yuku-ast@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + + yuku-codegen@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + optionalDependencies: + '@yuku-codegen/binding-android-arm64': 0.8.7 + '@yuku-codegen/binding-darwin-arm64': 0.8.7 + '@yuku-codegen/binding-darwin-x64': 0.8.7 + '@yuku-codegen/binding-freebsd-x64': 0.8.7 + '@yuku-codegen/binding-linux-arm-gnu': 0.8.7 + '@yuku-codegen/binding-linux-arm-musl': 0.8.7 + '@yuku-codegen/binding-linux-arm64-gnu': 0.8.7 + '@yuku-codegen/binding-linux-arm64-musl': 0.8.7 + '@yuku-codegen/binding-linux-x64-gnu': 0.8.7 + '@yuku-codegen/binding-linux-x64-musl': 0.8.7 + '@yuku-codegen/binding-win32-arm64': 0.8.7 + '@yuku-codegen/binding-win32-x64': 0.8.7 + + yuku-parser@0.8.7: + dependencies: + '@yuku-toolchain/types': 0.8.7 + yuku-ast: 0.8.7 + optionalDependencies: + '@yuku-parser/binding-android-arm64': 0.8.7 + '@yuku-parser/binding-darwin-arm64': 0.8.7 + '@yuku-parser/binding-darwin-x64': 0.8.7 + '@yuku-parser/binding-freebsd-x64': 0.8.7 + '@yuku-parser/binding-linux-arm-gnu': 0.8.7 + '@yuku-parser/binding-linux-arm-musl': 0.8.7 + '@yuku-parser/binding-linux-arm64-gnu': 0.8.7 + '@yuku-parser/binding-linux-arm64-musl': 0.8.7 + '@yuku-parser/binding-linux-x64-gnu': 0.8.7 + '@yuku-parser/binding-linux-x64-musl': 0.8.7 + '@yuku-parser/binding-win32-arm64': 0.8.7 + '@yuku-parser/binding-win32-x64': 0.8.7 + + zwitch@2.0.4: {} diff --git a/src/changes.test.ts b/src/changes.test.ts new file mode 100644 index 0000000..c5a23aa --- /dev/null +++ b/src/changes.test.ts @@ -0,0 +1,72 @@ +import type { Diagnostic } from './output' + +import { describe, expect, it } from 'vitest' + +import { filterToChangedLines, parsePatch, toChangedLines } from './changes' + +function diagnostic(filePath: string, line?: number, endLine?: number): Diagnostic { + return { + filePath, + loc: line === undefined + ? undefined + : { end: endLine === undefined ? undefined : { column: 1, line: endLine }, start: { column: 1, line } }, + message: 'Problem.', + ruleId: 'demo/rule', + severity: 'warn', + } +} + +describe('changed lines', () => { + it('reads the new-file ranges from hunk headers', () => { + const patch = [ + '@@ -1,2 +1,3 @@ export function a() {', + ' context', + '+added', + '@@ -10 +11 @@', + '-old', + '+new', + '@@ -20,2 +20,0 @@', + '-removed', + ].join('\n') + + expect(parsePatch(patch)).toEqual([ + { endLine: 3, startLine: 1 }, + { endLine: 11, startLine: 11 }, + ]) + }) + + it('ignores removed files and keeps each line of a file without a patch', () => { + const changedLines = toChangedLines([ + { filename: 'src/a.ts', patch: '@@ -1 +1,2 @@', status: 'modified' }, + { filename: 'src/big.ts', status: 'modified' }, + { filename: 'src/gone.ts', patch: '@@ -1 +0,0 @@', status: 'removed' }, + ]) + + expect([...changedLines.entries()]).toEqual([ + ['src/a.ts', [{ endLine: 2, startLine: 1 }]], + ['src/big.ts', 'all'], + ]) + }) + + it('keeps diagnostics on changed lines and file-wide diagnostics', () => { + const changedLines = toChangedLines([ + { filename: 'src/a.ts', patch: '@@ -5,0 +5,2 @@', status: 'modified' }, + { filename: 'src/big.ts', status: 'modified' }, + ]) + const kept = filterToChangedLines([ + diagnostic('src/a.ts', 5), + diagnostic('src/a.ts', 7), + diagnostic('src/a.ts', 3, 5), + diagnostic('src/a.ts'), + diagnostic('src/big.ts', 900), + diagnostic('src/other.ts', 5), + ], changedLines, filePath => filePath) + + expect(kept.map(item => `${item.filePath}:${item.loc?.start.line ?? 'file'}`)).toEqual([ + 'src/a.ts:5', + 'src/a.ts:3', + 'src/a.ts:file', + 'src/big.ts:900', + ]) + }) +}) diff --git a/src/changes.ts b/src/changes.ts new file mode 100644 index 0000000..b057c9d --- /dev/null +++ b/src/changes.ts @@ -0,0 +1,73 @@ +import type { Diagnostic } from './output' + +/** Changed lines of each file. `all` means that GitHub did not send a patch, so each line counts. */ +export type ChangedLines = ReadonlyMap + +export interface LineRange { + endLine: number + startLine: number +} + +export interface PullRequestFile { + filename: string + /** GitHub omits the patch of a binary file and of a very large diff. */ + patch?: string + status: string +} + +const hunkHeader = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/u + +/** Keeps file-wide diagnostics and diagnostics whose location intersects a changed line. */ +export function filterToChangedLines( + diagnostics: readonly Diagnostic[], + changedLines: ChangedLines, + toRepositoryPath: (filePath: string) => string, +): Diagnostic[] { + return diagnostics.filter((diagnostic) => { + const ranges = changedLines.get(toRepositoryPath(diagnostic.filePath)) + + if (ranges === undefined) { + return false + } + + if (ranges === 'all' || diagnostic.loc === undefined) { + return true + } + + const startLine = diagnostic.loc.start.line + const endLine = diagnostic.loc.end?.line ?? startLine + + return ranges.some(range => startLine <= range.endLine && endLine >= range.startLine) + }) +} + +/** Reads the new-file line ranges from the hunk headers of a unified diff. */ +export function parsePatch(patch: string): LineRange[] { + const ranges: LineRange[] = [] + + for (const line of patch.split('\n')) { + const match = hunkHeader.exec(line) + + if (match === null) { + continue + } + + const startLine = Number(match[1]) + // A hunk header without a count covers one line. A count of 0 is a deletion with no new lines. + const count = match[2] === undefined ? 1 : Number(match[2]) + + if (count > 0) { + ranges.push({ endLine: startLine + count - 1, startLine }) + } + } + + return ranges +} + +export function toChangedLines(files: readonly PullRequestFile[]): ChangedLines { + return new Map( + files + .filter(file => file.status !== 'removed') + .map(file => [file.filename, file.patch === undefined ? 'all' : parsePatch(file.patch)]), + ) +} diff --git a/src/findings.test.ts b/src/findings.test.ts new file mode 100644 index 0000000..6445d45 --- /dev/null +++ b/src/findings.test.ts @@ -0,0 +1,95 @@ +import type { Diagnostic } from './output' + +import { describe, expect, it } from 'vitest' + +import { formatSummary, formatTitle, summaryMarker, toAnnotations, toConclusion, toFindings } from './findings' + +const context = { repository: 'acme/app', serverUrl: 'https://github.com', sha: '0123456789abcdef', totalTokens: 1234 } +const identity = (filePath: string) => filePath + +function diagnostic(overrides: Partial): Diagnostic { + return { + filePath: 'src/a.ts', + loc: { start: { column: 1, line: 3 } }, + message: 'Problem.', + ruleId: 'demo/rule', + severity: 'warn', + ...overrides, + } +} + +describe('findings', () => { + it('puts errors first and gives a file-wide diagnostic line 1', () => { + const findings = toFindings([ + diagnostic({ filePath: 'src/b.ts' }), + diagnostic({ filePath: 'src/c.ts', severity: 'error' }), + diagnostic({ loc: undefined }), + ], identity) + + expect(findings.map(finding => `${finding.severity} ${finding.path}:${finding.line}`)).toEqual([ + 'error src/c.ts:3', + 'warn src/a.ts:1', + 'warn src/b.ts:3', + ]) + }) + + it('reads the suggestion from evidence', () => { + const findings = toFindings([ + diagnostic({ evidence: { suggestion: ' Inline the helper. ' } }), + diagnostic({ evidence: { suggestion: 42 } }), + ], identity) + + expect(findings[0]?.suggestion).toBe('Inline the helper.') + expect(findings[1]?.suggestion).toBeUndefined() + expect(toAnnotations(findings)[0]).toEqual({ + annotation_level: 'warning', + end_line: 3, + message: 'Problem.\n\nInline the helper.', + path: 'src/a.ts', + start_line: 3, + title: 'demo/rule', + }) + }) + + it('fails the check only when a finding is an error', () => { + const warnings = toFindings([diagnostic({})], identity) + const errors = toFindings([diagnostic({}), diagnostic({ severity: 'error' })], identity) + + expect(toConclusion([])).toBe('success') + expect(toConclusion(warnings)).toBe('neutral') + expect(toConclusion(errors)).toBe('failure') + expect(formatTitle([])).toBe('No findings') + expect(formatTitle(errors)).toBe('1 error, 1 warning') + }) + + it('formats a table row that stays in one cell', () => { + const findings = toFindings([ + diagnostic({ evidence: { suggestion: 'Use a | b.' }, message: 'First line.\nSecond line.', severity: 'error' }), + ], identity) + const summary = formatSummary(findings, { ...context, runUrl: 'https://github.com/acme/app/actions/runs/7' }) + + expect(summary.startsWith(summaryMarker)).toBe(true) + expect(summary).toContain('### ❌ alint · 1 error') + expect(summary).toContain('| ❌ | [`src/a.ts:3`](https://github.com/acme/app/blob/0123456789abcdef/src/a.ts#L3) | `demo/rule` | First line. Second line.
💡 Use a \\| b. |') + expect(summary).toContain('Commit `0123456` · [run](https://github.com/acme/app/actions/runs/7) · 1,234 tokens') + }) + + it('formats a clean result without a table', () => { + const summary = formatSummary([], context) + + expect(summary).toContain('### ✅ alint · No findings') + expect(summary).toContain('Checked the changes at `0123456`.') + expect(summary).not.toContain('| --- |') + }) + + it('caps the table and reports the remaining findings', () => { + const findings = toFindings( + Array.from({ length: 103 }, (_, index) => diagnostic({ loc: { start: { column: 1, line: index + 1 } } })), + identity, + ) + const summary = formatSummary(findings, context) + + expect(summary.split('\n').filter(line => line.startsWith('| ⚠️'))).toHaveLength(100) + expect(summary).toContain('3 more findings are in the check annotations.') + }) +}) diff --git a/src/findings.ts b/src/findings.ts new file mode 100644 index 0000000..bfee7f5 --- /dev/null +++ b/src/findings.ts @@ -0,0 +1,144 @@ +import type { Diagnostic } from './output' + +export interface Annotation { + annotation_level: 'failure' | 'warning' + end_line: number + message: string + path: string + start_line: number + title: string +} + +export type Conclusion = 'failure' | 'neutral' | 'success' + +export interface Finding { + line: number + message: string + path: string + ruleId: string + severity: Diagnostic['severity'] + suggestion?: string +} + +export interface SummaryContext { + repository: string + runUrl?: string + serverUrl: string + sha: string + totalTokens: number +} + +/** Identifies the summary comment so that later runs rewrite it instead of adding another one. */ +export const summaryMarker = '' + +// GitHub rejects a comment or a check summary above 65536 characters. +// One row is a few hundred characters, so this cap keeps the table far below the limit. +const maxSummaryRows = 100 + +export function formatSummary(findings: readonly Finding[], context: SummaryContext): string { + const icon = toConclusion(findings) === 'failure' ? '❌' : findings.length > 0 ? '⚠️' : '✅' + const shortSha = context.sha.slice(0, 7) + const lines = [summaryMarker, `### ${icon} alint · ${formatTitle(findings)}`, ''] + + if (findings.length === 0) { + lines.push(`Checked the changes at \`${shortSha}\`.`) + } + else { + lines.push('| | Location | Rule | Finding |', '| --- | --- | --- | --- |') + + for (const finding of findings.slice(0, maxSummaryRows)) { + const link = `${context.serverUrl}/${context.repository}/blob/${context.sha}/${encodeURI(finding.path)}#L${finding.line}` + const detail = finding.suggestion === undefined + ? escapeCell(finding.message) + : `${escapeCell(finding.message)}
💡 ${escapeCell(finding.suggestion)}` + + lines.push(`| ${finding.severity === 'error' ? '❌' : '⚠️'} | [\`${finding.path}:${finding.line}\`](${link}) | \`${finding.ruleId}\` | ${detail} |`) + } + + if (findings.length > maxSummaryRows) { + lines.push('', `${findings.length - maxSummaryRows} more findings are in the check annotations.`) + } + } + + const footer = [ + `Commit \`${shortSha}\``, + context.runUrl === undefined ? undefined : `[run](${context.runUrl})`, + `${context.totalTokens.toLocaleString('en-US')} tokens`, + ].filter(part => part !== undefined) + + lines.push('', `${footer.join(' · ')}`) + + return lines.join('\n') +} + +export function formatTitle(findings: readonly Finding[]): string { + if (findings.length === 0) { + return 'No findings' + } + + const errors = findings.filter(finding => finding.severity === 'error').length + const warnings = findings.length - errors + + return [ + errors > 0 ? pluralize(errors, 'error') : undefined, + warnings > 0 ? pluralize(warnings, 'warning') : undefined, + ].filter(part => part !== undefined).join(', ') +} + +export function toAnnotations(findings: readonly Finding[]): Annotation[] { + return findings.map(finding => ({ + annotation_level: finding.severity === 'error' ? 'failure' : 'warning', + end_line: finding.line, + message: finding.suggestion === undefined ? finding.message : `${finding.message}\n\n${finding.suggestion}`, + path: finding.path, + start_line: finding.line, + title: finding.ruleId, + })) +} + +export function toConclusion(findings: readonly Finding[]): Conclusion { + if (findings.some(finding => finding.severity === 'error')) { + return 'failure' + } + + return findings.length > 0 ? 'neutral' : 'success' +} + +/** Converts diagnostics to findings with repository-relative paths. Errors come first. */ +export function toFindings( + diagnostics: readonly Diagnostic[], + toRepositoryPath: (filePath: string) => string, +): Finding[] { + return diagnostics + .map((diagnostic): Finding => ({ + // A diagnostic without a location is about the whole file. An annotation needs a line. + line: diagnostic.loc?.start.line ?? 1, + message: diagnostic.message.trim(), + path: toRepositoryPath(diagnostic.filePath), + ruleId: diagnostic.ruleId, + severity: diagnostic.severity, + suggestion: suggestionFrom(diagnostic.evidence), + })) + .sort((a, b) => + Number(b.severity === 'error') - Number(a.severity === 'error') + || a.path.localeCompare(b.path) + || a.line - b.line, + ) +} + +function escapeCell(value: string): string { + return value.replaceAll('|', '\\|').replaceAll(/\s*\n\s*/gu, ' ') +} + +function pluralize(count: number, noun: string): string { + return `${count} ${noun}${count === 1 ? '' : 's'}` +} + +// Declarative rules and `@alint-js/plugin-js` rules put the remediation text in `evidence.suggestion`. +function suggestionFrom(evidence: unknown): string | undefined { + if (typeof evidence !== 'object' || evidence === null || !('suggestion' in evidence) || typeof evidence.suggestion !== 'string') { + return undefined + } + + return evidence.suggestion.trim() || undefined +} diff --git a/src/github.ts b/src/github.ts new file mode 100644 index 0000000..dc638ee --- /dev/null +++ b/src/github.ts @@ -0,0 +1,119 @@ +import type { PullRequestFile } from './changes' +import type { Annotation, Conclusion } from './findings' + +import { array, number, object, optional, parse, string } from 'valibot' + +import { summaryMarker } from './findings' + +export interface CheckRun { + annotations: readonly Annotation[] + conclusion: Conclusion + name: string + sha: string + summary: string + title: string +} + +export interface Repository { + apiUrl: string + repository: string + token: string +} + +// https://docs.github.com/en/rest/checks/runs#create-a-check-run +// One request accepts at most 50 annotations. More annotations go in update requests. +const annotationsPerRequest = 50 +const itemsPerPage = 100 + +const checkRunSchema = object({ id: number() }) +const commentsSchema = array(object({ body: optional(string()), id: number() })) +const filesSchema = array(object({ filename: string(), patch: optional(string()), status: string() })) + +export async function listPullRequestFiles(repository: Repository, pullRequest: number): Promise { + const files: PullRequestFile[] = [] + + for (let page = 1; ; page += 1) { + const items = parse(filesSchema, await request(repository, 'GET', `/pulls/${pullRequest}/files?per_page=${itemsPerPage}&page=${page}`)) + + files.push(...items) + + if (items.length < itemsPerPage) { + return files + } + } +} + +export async function publishCheckRun(repository: Repository, checkRun: CheckRun): Promise { + const output = { summary: checkRun.summary, title: checkRun.title } + const created = parse(checkRunSchema, await request(repository, 'POST', '/check-runs', { + conclusion: checkRun.conclusion, + head_sha: checkRun.sha, + name: checkRun.name, + output: { ...output, annotations: checkRun.annotations.slice(0, annotationsPerRequest) }, + status: 'completed', + })) + + for (let offset = annotationsPerRequest; offset < checkRun.annotations.length; offset += annotationsPerRequest) { + await request(repository, 'PATCH', `/check-runs/${created.id}`, { + output: { ...output, annotations: checkRun.annotations.slice(offset, offset + annotationsPerRequest) }, + }) + } +} + +/** + * Rewrites the summary comment of a pull request. + * + * A pull request that never had findings gets no comment. After the first comment exists, + * each run rewrites it, so a fixed pull request shows the clean result. + */ +export async function publishSummaryComment( + repository: Repository, + pullRequest: number, + body: string, + hasFindings: boolean, +): Promise { + const existing = await findSummaryComment(repository, pullRequest) + + if (existing !== undefined) { + await request(repository, 'PATCH', `/issues/comments/${existing}`, { body }) + return + } + + if (hasFindings) { + await request(repository, 'POST', `/issues/${pullRequest}/comments`, { body }) + } +} + +async function findSummaryComment(repository: Repository, pullRequest: number): Promise { + for (let page = 1; ; page += 1) { + const comments = parse(commentsSchema, await request(repository, 'GET', `/issues/${pullRequest}/comments?per_page=${itemsPerPage}&page=${page}`)) + const summary = comments.find(comment => comment.body?.includes(summaryMarker)) + + if (summary !== undefined) { + return summary.id + } + + if (comments.length < itemsPerPage) { + return undefined + } + } +} + +async function request(repository: Repository, method: string, path: string, body?: unknown): Promise { + const response = await fetch(`${repository.apiUrl}/repos/${repository.repository}${path}`, { + body: body === undefined ? undefined : JSON.stringify(body), + headers: { + 'Accept': 'application/vnd.github+json', + 'Authorization': `Bearer ${repository.token}`, + 'Content-Type': 'application/json', + 'X-GitHub-Api-Version': '2022-11-28', + }, + method, + }) + + if (!response.ok) { + throw new Error(`GitHub ${method} ${path} failed with ${response.status}: ${await response.text()}`) + } + + return response.json() +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..9d02520 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,11 @@ +import process from 'node:process' + +import { errorMessageFrom } from '@moeru/std' + +import { run } from './main' + +run(process.env, process.cwd()).catch((error: unknown) => { + // https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + console.error(`::error title=alint::${(errorMessageFrom(error) ?? 'unknown error').replaceAll('\n', '%0A')}`) + process.exitCode = 1 +}) diff --git a/src/lint.ts b/src/lint.ts new file mode 100644 index 0000000..6abfb9f --- /dev/null +++ b/src/lint.ts @@ -0,0 +1,17 @@ +import type { RunResult } from './output' + +import { x } from 'tinyexec' + +import { parseRunResult } from './output' + +/** Runs `alint --format json` on the targets and returns the parsed result. */ +export async function runAlint(command: string, targets: readonly string[], cwd: string): Promise { + const result = await x(command, ['--format', 'json', ...targets], { nodeOptions: { cwd } }) + + // alint returns 1 when a diagnostic is an error. The check run reports that, so only 2 and above stop the action. + if (result.exitCode !== 0 && result.exitCode !== 1) { + throw new Error(`alint exited with code ${result.exitCode}.\n${result.stderr || result.stdout}`) + } + + return parseRunResult(result.stdout) +} diff --git a/src/main.test.ts b/src/main.test.ts new file mode 100644 index 0000000..6cfc33a --- /dev/null +++ b/src/main.test.ts @@ -0,0 +1,253 @@ +import type { AddressInfo } from 'node:net' + +import type { PullRequestFile } from './changes' +import type { Diagnostic } from './output' + +import { chmod, mkdir, mkdtemp, readFile, writeFile } from 'node:fs/promises' +import { createServer } from 'node:http' +import { tmpdir } from 'node:os' +import { join } from 'node:path' + +import { afterEach, describe, expect, it } from 'vitest' + +import { summaryMarker } from './findings' +import { run } from './main' + +interface FakeApi { + comments?: Array<{ body: string, id: number }> + files?: PullRequestFile[] + status?: number +} + +interface RecordedRequest { + body?: Record + method: string + url: string +} + +const servers: Array<() => Promise> = [] + +afterEach(async () => { + await Promise.all(servers.splice(0).map(close => close())) +}) + +describe('action', () => { + it('lints the changed files of a pull request and publishes the findings on changed lines', async () => { + const api = await startGitHubApi({ + files: [ + { filename: 'src/a.ts', patch: '@@ -1,0 +2,2 @@', status: 'modified' }, + { filename: 'src/gone.ts', patch: '@@ -1 +0,0 @@', status: 'removed' }, + { filename: 'docs/missing.md', patch: '@@ -1 +1 @@', status: 'modified' }, + ], + }) + const workspace = await createWorkspace({ + diagnostics: [warning('src/a.ts', 2), { ...warning('src/a.ts', 3), severity: 'error' }, warning('src/a.ts', 40)], + }) + + await run(environment(workspace, api.url), workspace) + + expect(await readArguments(workspace)).toEqual(['--format', 'json', 'src/a.ts']) + expect(api.requests.map(request => `${request.method} ${request.url}`)).toEqual([ + 'GET /repos/acme/app/pulls/12/files?per_page=100&page=1', + 'POST /repos/acme/app/check-runs', + 'GET /repos/acme/app/issues/12/comments?per_page=100&page=1', + 'POST /repos/acme/app/issues/12/comments', + ]) + + const checkRun = api.requests[1]?.body + expect(checkRun?.name).toBe('alint') + expect(checkRun?.conclusion).toBe('failure') + // The event head commit wins over GITHUB_SHA, which is the merge commit on pull request events. + expect(checkRun?.head_sha).toBe('abcdef0123') + expect(checkRun?.output.title).toBe('1 error, 1 warning') + expect(checkRun?.output.annotations.map((annotation: { path: string, start_line: number }) => `${annotation.path}:${annotation.start_line}`)).toEqual([ + 'src/a.ts:3', + 'src/a.ts:2', + ]) + + const comment = api.requests[3]?.body?.body + expect(comment).toContain(summaryMarker) + expect(await readFile(join(workspace, 'summary.md'), 'utf8')).toBe(`${comment}\n`) + expect(await readFile(join(workspace, 'output.txt'), 'utf8')).toBe('errors=1\nwarnings=1\n') + }) + + it('does not run alint when the pull request changed no file that exists', async () => { + const api = await startGitHubApi({ comments: [{ body: `${summaryMarker}\nold`, id: 2 }], files: [] }) + const workspace = await createWorkspace({ diagnostics: [] }) + + await run(environment(workspace, api.url), workspace) + + await expect(readArguments(workspace)).rejects.toThrow('ENOENT') + expect(api.requests[1]?.body?.conclusion).toBe('success') + // A comment that exists is rewritten with the clean result. + expect(api.requests.at(-1)?.method).toBe('PATCH') + expect(api.requests.at(-1)?.url).toBe('/repos/acme/app/issues/comments/2') + }) + + it('uses repository paths when the working directory is a subdirectory', async () => { + const api = await startGitHubApi({ + files: [ + { filename: 'packages/app/src/a.ts', patch: '@@ -1 +1 @@', status: 'modified' }, + { filename: 'src/a.ts', patch: '@@ -1 +1 @@', status: 'modified' }, + ], + }) + const workspace = await createWorkspace({ diagnostics: [warning('packages/app/src/a.ts', 1)] }) + const cwd = join(workspace, 'packages/app') + + await run(environment(workspace, api.url), cwd) + + expect(await readArguments(workspace)).toEqual(['--format', 'json', 'src/a.ts']) + expect(api.requests[1]?.body?.output.annotations[0].path).toBe('packages/app/src/a.ts') + }) + + it('lints explicit files without the changed-line filter', async () => { + const api = await startGitHubApi({}) + const workspace = await createWorkspace({ diagnostics: [warning('src/a.ts', 40)] }) + + await run({ ...environment(workspace, api.url), INPUT_CHECK_NAME: 'alint (docs)', INPUT_FILES: 'src\ndocs' }, workspace) + + expect(await readArguments(workspace)).toEqual(['--format', 'json', 'src', 'docs']) + expect(api.requests[0]?.url).toBe('/repos/acme/app/check-runs') + expect(api.requests[0]?.body?.name).toBe('alint (docs)') + expect(api.requests[0]?.body?.output.annotations).toHaveLength(1) + }) + + it('lints the working directory and writes no comment outside a pull request', async () => { + const api = await startGitHubApi({}) + const workspace = await createWorkspace({ diagnostics: [warning('src/a.ts', 40)] }) + + await run({ ...environment(workspace, api.url), GITHUB_EVENT_PATH: join(workspace, 'push.json') }, workspace) + + expect(await readArguments(workspace)).toEqual(['--format', 'json', '.']) + expect(api.requests.map(request => `${request.method} ${request.url}`)).toEqual(['POST /repos/acme/app/check-runs']) + expect(api.requests[0]?.body?.head_sha).toBe('push-commit') + }) + + it('sends annotations above the request limit in update requests', async () => { + const api = await startGitHubApi({}) + const workspace = await createWorkspace({ + diagnostics: Array.from({ length: 120 }, (_, index) => warning('src/a.ts', index + 1)), + }) + + await run({ ...environment(workspace, api.url), INPUT_FILES: 'src' }, workspace) + + expect(api.requests.slice(0, 3).map(request => `${request.method} ${request.url}`)).toEqual([ + 'POST /repos/acme/app/check-runs', + 'PATCH /repos/acme/app/check-runs/77', + 'PATCH /repos/acme/app/check-runs/77', + ]) + expect(api.requests.slice(0, 3).map(request => request.body?.output.annotations.length)).toEqual([50, 50, 20]) + }) + + it('fails when alint cannot complete the run', async () => { + const api = await startGitHubApi({}) + const workspace = await createWorkspace({ diagnostics: [], exitCode: 2, stderr: 'No provider is configured.' }) + + await expect(run({ ...environment(workspace, api.url), INPUT_FILES: 'src' }, workspace)) + .rejects + .toThrow('alint exited with code 2.\nNo provider is configured.') + expect(api.requests).toEqual([]) + }) + + it('fails when GitHub rejects the request', async () => { + const api = await startGitHubApi({ status: 403 }) + const workspace = await createWorkspace({ diagnostics: [] }) + + await expect(run({ ...environment(workspace, api.url), INPUT_FILES: 'src' }, workspace)) + .rejects + .toThrow('GitHub POST /check-runs failed with 403') + }) +}) + +/** + * Creates a repository checkout with a program that stands in for alint. + * + * The program records its arguments and prints the prepared result, so the tests + * run the real process boundary without a model provider. + */ +async function createWorkspace(result: { diagnostics: Diagnostic[], exitCode?: number, stderr?: string }): Promise { + const workspace = await mkdtemp(join(tmpdir(), 'alint-setup-')) + + await mkdir(join(workspace, 'packages/app/src'), { recursive: true }) + await mkdir(join(workspace, 'src'), { recursive: true }) + await writeFile(join(workspace, 'src/a.ts'), '') + await writeFile(join(workspace, 'packages/app/src/a.ts'), '') + await writeFile(join(workspace, 'event.json'), JSON.stringify({ pull_request: { head: { sha: 'abcdef0123' }, number: 12 } })) + await writeFile(join(workspace, 'push.json'), JSON.stringify({ ref: 'refs/heads/main' })) + await writeFile(join(workspace, 'result.json'), JSON.stringify({ + exitCode: result.exitCode ?? 0, + stderr: result.stderr ?? '', + stdout: JSON.stringify({ + diagnostics: result.diagnostics.map(diagnostic => ({ ...diagnostic, filePath: join(workspace, diagnostic.filePath) })), + usage: { inputTokens: 10, outputTokens: 5, records: [], totalTokens: 15 }, + }), + })) + await writeFile(join(workspace, 'alint'), [ + '#!/usr/bin/env node', + 'const { readFileSync, writeFileSync } = require("node:fs")', + 'const { join } = require("node:path")', + 'const result = JSON.parse(readFileSync(join(__dirname, "result.json"), "utf8"))', + 'writeFileSync(join(__dirname, "arguments.json"), JSON.stringify(process.argv.slice(2)))', + 'process.stdout.write(result.stdout)', + 'process.stderr.write(result.stderr)', + 'process.exitCode = result.exitCode', + ].join('\n')) + await chmod(join(workspace, 'alint'), 0o755) + + return workspace +} + +function environment(workspace: string, apiUrl: string): NodeJS.ProcessEnv { + return { + ALINT_COMMAND: join(workspace, 'alint'), + GITHUB_API_URL: apiUrl, + GITHUB_EVENT_PATH: join(workspace, 'event.json'), + GITHUB_OUTPUT: join(workspace, 'output.txt'), + GITHUB_REPOSITORY: 'acme/app', + GITHUB_SHA: 'push-commit', + GITHUB_STEP_SUMMARY: join(workspace, 'summary.md'), + GITHUB_TOKEN: 'test-token', + GITHUB_WORKSPACE: workspace, + } +} + +async function readArguments(workspace: string): Promise { + return JSON.parse(await readFile(join(workspace, 'arguments.json'), 'utf8')) +} + +async function startGitHubApi(options: FakeApi) { + const requests: RecordedRequest[] = [] + const server = createServer((request, response) => { + let text = '' + + request.on('data', chunk => text += chunk) + request.on('end', () => { + const url = request.url ?? '' + + requests.push({ body: text === '' ? undefined : JSON.parse(text), method: request.method ?? '', url }) + response.writeHead(options.status ?? 200, { 'Content-Type': 'application/json' }) + + if (request.method !== 'GET') { + response.end(JSON.stringify({ id: 77 })) + return + } + + response.end(JSON.stringify(url.includes('/pulls/') ? options.files ?? [] : options.comments ?? [])) + }) + }) + + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)) + servers.push(() => new Promise(resolve => server.close(() => resolve()))) + + return { requests, url: `http://127.0.0.1:${(server.address() as AddressInfo).port}` } +} + +function warning(filePath: string, line: number): Diagnostic { + return { + filePath, + loc: { start: { column: 1, line } }, + message: `Problem at line ${line}.`, + ruleId: 'demo/rule', + severity: 'warn', + } +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..3375b99 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,140 @@ +import type { ChangedLines } from './changes' +import type { Repository } from './github' + +import { existsSync } from 'node:fs' +import { appendFile, readFile } from 'node:fs/promises' + +import { relative, resolve } from 'pathe' +import { number, object, optional, parse, string } from 'valibot' + +import { filterToChangedLines, toChangedLines } from './changes' +import { formatSummary, formatTitle, toAnnotations, toConclusion, toFindings } from './findings' +import { listPullRequestFiles, publishCheckRun, publishSummaryComment } from './github' +import { runAlint } from './lint' + +interface PullRequest { + number: number + sha: string +} + +interface Scope { + /** Present when the scope is the changes of a pull request. */ + changedLines?: ChangedLines + targets: string[] +} + +const eventSchema = object({ + pull_request: optional(object({ head: object({ sha: string() }), number: number() })), +}) + +export async function run(env: NodeJS.ProcessEnv, cwd: string): Promise { + const repository: Repository = { + apiUrl: env.GITHUB_API_URL ?? 'https://api.github.com', + repository: required(env, 'GITHUB_REPOSITORY'), + token: required(env, 'GITHUB_TOKEN'), + } + const workspace = env.GITHUB_WORKSPACE ?? cwd + const serverUrl = env.GITHUB_SERVER_URL ?? 'https://github.com' + const pullRequest = await readPullRequest(env.GITHUB_EVENT_PATH) + // On a pull request event, GITHUB_SHA is the temporary merge commit. + // A check run on that commit does not show on the pull request, so the head commit comes first. + const sha = pullRequest?.sha ?? required(env, 'GITHUB_SHA') + const toRepositoryPath = (filePath: string) => relative(workspace, resolve(cwd, filePath)) + + const scope = await resolveScope(repository, pullRequest, env.INPUT_FILES ?? '', cwd, workspace) + const result = scope.targets.length === 0 + ? { diagnostics: [], usage: { totalTokens: 0 } } + : await runAlint(required(env, 'ALINT_COMMAND'), scope.targets, cwd) + const diagnostics = scope.changedLines === undefined + ? result.diagnostics + : filterToChangedLines(result.diagnostics, scope.changedLines, toRepositoryPath) + + const findings = toFindings(diagnostics, toRepositoryPath) + const title = formatTitle(findings) + const summary = formatSummary(findings, { + repository: repository.repository, + runUrl: env.GITHUB_RUN_ID === undefined ? undefined : `${serverUrl}/${repository.repository}/actions/runs/${env.GITHUB_RUN_ID}`, + serverUrl, + sha, + totalTokens: result.usage.totalTokens, + }) + + if (env.GITHUB_STEP_SUMMARY !== undefined) { + await appendFile(env.GITHUB_STEP_SUMMARY, `${summary}\n`) + } + + if (env.GITHUB_OUTPUT !== undefined) { + const errors = findings.filter(finding => finding.severity === 'error').length + + await appendFile(env.GITHUB_OUTPUT, `errors=${errors}\nwarnings=${findings.length - errors}\n`) + } + + await publishCheckRun(repository, { + annotations: toAnnotations(findings), + conclusion: toConclusion(findings), + name: env.INPUT_CHECK_NAME || 'alint', + sha, + summary, + title, + }) + + if (pullRequest !== undefined) { + await publishSummaryComment(repository, pullRequest.number, summary, findings.length > 0) + } + + console.info(`Published ${title.toLowerCase()} to ${repository.repository}@${sha.slice(0, 7)}.`) +} + +async function readPullRequest(eventPath: string | undefined): Promise { + if (eventPath === undefined) { + return undefined + } + + const event = parse(eventSchema, JSON.parse(await readFile(eventPath, 'utf8'))) + + return event.pull_request === undefined + ? undefined + : { number: event.pull_request.number, sha: event.pull_request.head.sha } +} + +function required(env: NodeJS.ProcessEnv, name: string): string { + const value = env[name] + + if (!value) { + throw new Error(`${name} is not set.`) + } + + return value +} + +/** + * Selects what alint reads. + * + * Explicit files win. A pull request without explicit files gets its changed files, + * and the result keeps only the changed lines. Other events get the whole working directory. + */ +async function resolveScope( + repository: Repository, + pullRequest: PullRequest | undefined, + files: string, + cwd: string, + workspace: string, +): Promise { + const explicit = files.split(/\s+/u).filter(Boolean) + + if (explicit.length > 0) { + return { targets: explicit } + } + + if (pullRequest === undefined) { + return { targets: ['.'] } + } + + const changedLines = toChangedLines(await listPullRequestFiles(repository, pullRequest.number)) + const targets = [...changedLines.keys()] + .map(path => relative(cwd, resolve(workspace, path))) + // A file outside the working directory belongs to another project. A file that the checkout does not have cannot be read. + .filter(path => !path.startsWith('..') && existsSync(resolve(cwd, path))) + + return { changedLines, targets } +} diff --git a/src/output.ts b/src/output.ts new file mode 100644 index 0000000..3542bdd --- /dev/null +++ b/src/output.ts @@ -0,0 +1,25 @@ +import type { InferOutput } from 'valibot' + +import { array, number, object, optional, parse, picklist, string, unknown } from 'valibot' + +const positionSchema = object({ column: number(), line: number() }) + +// The part of `alint --format json` that this action reads. +const runResultSchema = object({ + diagnostics: array(object({ + evidence: optional(unknown()), + filePath: string(), + loc: optional(object({ end: optional(positionSchema), start: positionSchema })), + message: string(), + ruleId: string(), + severity: picklist(['error', 'warn']), + })), + usage: object({ totalTokens: number() }), +}) + +export type Diagnostic = RunResult['diagnostics'][number] +export type RunResult = InferOutput + +export function parseRunResult(json: string): RunResult { + return parse(runResultSchema, JSON.parse(json)) +} diff --git a/test/fixture/alint.config.ts b/test/fixture/alint.config.ts new file mode 100644 index 0000000..2349e63 --- /dev/null +++ b/test/fixture/alint.config.ts @@ -0,0 +1,30 @@ +// A rule that does not call a model, so the end-to-end workflow needs no provider. +export default [{ + files: ['**/*.ts'], + ignores: ['alint.config.ts'], + plugins: { + fixture: { + rules: { + 'no-fixme': { + create: context => ({ + onTargetFile: async (target) => { + const file = await context.src.readFile(target.file) + + file.lines.forEach((line, index) => { + if (line.includes('FIXME')) { + context.report({ + evidence: { suggestion: 'Resolve the note or remove it.' }, + filePath: target.file.path, + loc: { start: { column: 1, line: index + 1 } }, + message: 'A FIXME note is in the changed code.', + }) + } + }) + }, + }), + }, + }, + }, + }, + rules: { 'fixture/no-fixme': 'warn' }, +}] diff --git a/test/fixture/src/add.ts b/test/fixture/src/add.ts new file mode 100644 index 0000000..63a27c0 --- /dev/null +++ b/test/fixture/src/add.ts @@ -0,0 +1,4 @@ +export function add(a: number, b: number): number { + // FIXME handle overflow + return a + b +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c7192ae --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"], + "strict": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noEmit": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true + }, + "include": ["src/**/*.ts", "*.config.ts"] +} diff --git a/tsdown.config.ts b/tsdown.config.ts new file mode 100644 index 0000000..61fa4c6 --- /dev/null +++ b/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown' + +export default defineConfig({ + clean: true, + entry: { index: 'src/index.ts' }, + format: 'esm', + // The action runs `dist/index.mjs` without an install step, so the bundle contains its dependencies. + noExternal: [/.*/], +}) From 83899e7d66afc1b1415bb0ef10d739f2fb210bab Mon Sep 17 00:00:00 2001 From: RainbowBird Date: Fri, 9 Oct 2026 19:35:02 +0800 Subject: [PATCH 2/2] chore: credit the author of the original report script The publication flow follows the report script that LobeHub wrote for its monorepo. Co-authored-by: Arvin Xu <28616219+arvinxx@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5