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: [/.*/],
+})