diff --git a/.changes/README.md b/.changes/README.md new file mode 100644 index 000000000..2e529ab0f --- /dev/null +++ b/.changes/README.md @@ -0,0 +1,86 @@ +# Release notes (`.changes/`) + +Every PR with a user-visible change drops one file here describing that change +in plain language. At release time +`tools/release/build-release-notes.mjs` turns the accumulated files into the +GitHub release body, the `CHANGELOG.md` section, and a blog-post scaffold for +the website — then deletes them. + +The point is to write the note **while the context is still fresh**, instead of +reconstructing three months of work from commit titles at release time. + +## File + +Name it `-.md`, e.g. `.changes/playback-up-next-rail.md`. + +```markdown +--- +type: feature +area: playback +issues: [1187] +screenshot: up-next-rail +--- + +Series now show an "Up Next" rail beside the player on wide windows: the rest +of the current season, watch progress, and click-to-play inline. +``` + +| Field | Required | Value | +| ------------ | -------- | ----------------------------------------------------------- | +| `type` | yes | `breaking`, `feature`, `fix`, `perf`, or `internal` | +| `area` | yes | lowercase slug, same as the conventional-commit scope | +| `issues` | no | issue numbers this closes — `[1187]` or `1187` | +| `screenshot` | no | slug from the release screenshot manifest | + +There is **no version field**. The release version is chosen deliberately at +release time, not derived from these files. + +You never write a PR number: the generator resolves it from the commit that +added the file. + +## Writing the body + +One to three sentences, present tense, **written for a user, not a reviewer**. +The body is capped at 400 characters — depth belongs in the blog post. + +- ❌ "Refactor `WebVideoControlsAdapter` to hoist volume state into the session" +- ✅ "The player now remembers volume between episodes" + +- ❌ "Fix off-by-one in `resolveEnrichmentSeasonNumber`" +- ✅ "Series whose title carries a season marker no longer show the wrong season" + +`type: internal` is for changes with no user-visible effect that are still worth +recording (dependency bumps with behaviour risk, packaging moves). They stay out +of the release body and blog post, and land collapsed in `CHANGELOG.md`. + +## When a note is not needed + +Skip the note — and apply the `no-release-note` label — for test-only changes, +docs, CI/workflow plumbing, and pure refactors with no behaviour change. + +## Commands + +```bash +pnpm run release:notes:validate +pnpm run release:notes:github +pnpm run release:notes:changelog +pnpm run release:notes:blog +node tools/release/build-release-notes.mjs --consume +``` + +The release version comes from the root `package.json` — bump it first, then +generate. `--version 0.24.0` overrides it for a dry run before the bump. + +Only `--consume` deletes anything; every other mode is a safe dry run. + +The release sequence is: bump the version → `release:notes:changelog` → +`release:notes:blog` → `--consume` → commit → tag → push. The tag build then +extracts the new `CHANGELOG.md` section into the GitHub release body +(`tools/release/extract-changelog-section.mjs`) and **fails the release** if +the section is missing — a tag cut without the changelog step cannot silently +ship PR-title-only notes. + +The website publishes **one post per minor version** (`v0-18` … `v0-22`), and +release screenshots live under the matching `blog/v0-24/` directory. A patch +release therefore edits the existing post rather than generating a new one, so +`--format blog` refuses to overwrite unless you pass `--force`. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..887886187 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ + + +## What changed + +## Why + +## Release note + +Changes a user could notice need one file in `.changes/` describing the change +in plain language — see +[`.changes/README.md`](https://github.com/4gray/iptvnator/blob/master/.changes/README.md). +It becomes the release notes and the website post, so it is worth a minute. + +- [ ] Added a note under `.changes/` +- [ ] Not needed (test-only, docs, CI, or a refactor with no behavior change) + +## Checks + +- [ ] Tests added or updated for the changed behavior +- [ ] `pnpm run lint` and the affected `pnpm nx test ` pass diff --git a/.github/workflows/build-and-make.yaml b/.github/workflows/build-and-make.yaml index bb162af7f..abbac03eb 100644 --- a/.github/workflows/build-and-make.yaml +++ b/.github/workflows/build-and-make.yaml @@ -1450,7 +1450,15 @@ jobs: if [ "${IS_TAG_BUILD}" = "true" ]; then NAME="Release v${VERSION}" TAG="${GITHUB_REF_NAME}" - BODY="" + # Authored release notes: the release flow writes this + # CHANGELOG section from .changes/*.md before tagging + # (see .changes/README.md), so at tag time the changelog + # is the authored source of truth. The extractor exits + # non-zero when the section is missing, failing the + # release rather than silently shipping PR-title-only + # notes. generate_release_notes stays on below, so the + # GitHub commit list still renders under this body. + BODY="$(node tools/release/extract-changelog-section.mjs "${VERSION}")" elif [ "${EVENT_NAME}" = "pull_request" ]; then NAME="v${VERSION} — PR #${PR_NUMBER} @ ${SHORT_SHA} [test]" TAG="test-pr-${PR_NUMBER}" diff --git a/AGENTS.md b/AGENTS.md index 180f023c2..1c608607c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,6 +33,16 @@ This file provides guidance to coding agents working in this repository. - Repo docs are canonical even when they were originally drafted by an LLM. - Final task summaries should state whether docs were updated and which doc changed. +## Release Notes For User-Visible Changes + +- Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change — must add one note file under `.changes/` in the same PR. Format, field table, and writing rules: `.changes/README.md`. +- Name it `-.md`; `area` matches the conventional-commit scope. There is no version field — the release version is chosen at release time. +- Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist volume state into the session". Max 400 characters; depth belongs in the release blog post. +- Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior change. When skipping on a PR that touches `apps/**` or `libs/**`, apply the `no-release-note` label. +- Validate before finishing: `pnpm run release:notes:validate`. +- Release-post screenshots come only from the release capture script running against the mock servers. Never add a screenshot taken from a real playlist or account to `apps/website/public/blog/**` — real streams, logos, and metadata are copyrighted, and credentials must never reach a published image. +- Final task summaries should state whether a release note was added or why it was skipped. + ## Regression Prevention And Test Updates - Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron IPC/database change, or user-visible UI workflow change, complete a test impact pass. Identify the affected projects and decide whether unit, integration, E2E, build, lint, or manual/CDP verification is required. diff --git a/CHANGELOG.md b/CHANGELOG.md index 42aacde10..854fbf7e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# Changelog + +Releases **0.13.0 – 0.23.0** were published as +[GitHub releases](https://github.com/4gray/iptvnator/releases) and +[website posts](https://4gray.github.io/iptvnator/blog/) rather than collected +here. This file resumes from the next release onwards; the entries below are +kept as they were written. + +New sections are generated from `.changes/*.md` and inserted directly below +this marker — see `.changes/README.md`. + + + # [0.12.0](https://github.com/4gray/iptvnator/compare/v0.11.1...v0.12.0) (2023-03-11) diff --git a/CLAUDE.md b/CLAUDE.md index a4b2938d8..df74fe116 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,6 +26,16 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - Repo docs are canonical even when they were originally drafted by an LLM. - Final task summaries should state whether docs were updated and which doc changed. +## Release Notes For User-Visible Changes + +- Any change a user could notice — new behavior, changed behavior, bug fix, performance win, breaking change — must add one note file under `.changes/` in the same PR. Format, field table, and writing rules: `.changes/README.md`. +- Name it `-.md`; `area` matches the conventional-commit scope. There is no version field — the release version is chosen at release time. +- Write the body for a user, not a reviewer: "the player now remembers volume between episodes", not "hoist volume state into the session". Max 400 characters; depth belongs in the release blog post. +- Skip the note for test-only changes, docs, CI/workflow plumbing, and pure refactors with no behavior change. When skipping on a PR that touches `apps/**` or `libs/**`, apply the `no-release-note` label. +- Validate before finishing: `pnpm run release:notes:validate`. +- Release-post screenshots come only from the release capture script running against the mock servers. Never add a screenshot taken from a real playlist or account to `apps/website/public/blog/**` — real streams, logos, and metadata are copyrighted, and credentials must never reach a published image. +- Final task summaries should state whether a release note was added or why it was skipped. + ## Regression Prevention And Test Updates - Before the final summary for any feature, behavior change, bug fix, data-flow change, Electron IPC/database change, or user-visible UI workflow change, Claude Code must complete a test impact pass. Identify the affected projects and decide whether unit, integration, E2E, build, lint, or manual/CDP verification is required. diff --git a/package.json b/package.json index 5601cb22f..872879829 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,10 @@ "release:artwork:manifest": "tsx tools/release/generate-marketing-artwork.ts --manifest", "release:artwork:generate": "tsx tools/release/generate-marketing-artwork.ts --generate", "release:artwork:validate": "tsx tools/release/generate-marketing-artwork.ts --validate", + "release:notes:validate": "node tools/release/build-release-notes.mjs --validate", + "release:notes:github": "node tools/release/build-release-notes.mjs --format github", + "release:notes:changelog": "node tools/release/build-release-notes.mjs --format changelog", + "release:notes:blog": "node tools/release/build-release-notes.mjs --format blog", "lint": "nx run-many --target=lint --all", "build": "nx build electron-backend" }, @@ -157,9 +161,6 @@ "@nx/workspace": "22.7.1", "@playwright/test": "^1.36.0", "@schematics/angular": "21.2.9", - "@semantic-release/changelog": "6.0.3", - "@semantic-release/git": "10.0.1", - "@semantic-release/npm": "12.0.1", "@swc-node/register": "1.11.1", "@swc/core": "1.15.8", "@swc/helpers": "0.5.18", @@ -177,7 +178,6 @@ "@typescript-eslint/utils": "^8.46.2", "angular-eslint": "21.3.1", "astro": "5.18.1", - "conventional-changelog-cli": "5.0.0", "cors": "2.8.6", "drizzle-kit": "0.31.5", "electron": "^41.7.2", @@ -204,7 +204,6 @@ "nx": "22.7.1", "nx-electron": "22.0.0", "prettier": "^3.8.1", - "semantic-release": "24.2.9", "sharp": "0.34.5", "tailwindcss": "^3.4.19", "ts-jest": "^29.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94ef0f18f..b5659b2ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -279,15 +279,6 @@ importers: '@schematics/angular': specifier: 21.2.9 version: 21.2.9(chokidar@5.0.0) - '@semantic-release/changelog': - specifier: 6.0.3 - version: 6.0.3(semantic-release@24.2.9(typescript@5.9.3)) - '@semantic-release/git': - specifier: 10.0.1 - version: 10.0.1(semantic-release@24.2.9(typescript@5.9.3)) - '@semantic-release/npm': - specifier: 12.0.1 - version: 12.0.1(semantic-release@24.2.9(typescript@5.9.3)) '@swc-node/register': specifier: 1.11.1 version: 1.11.1(@swc/core@1.15.8(@swc/helpers@0.5.18))(@swc/types@0.1.25)(typescript@5.9.3) @@ -339,9 +330,6 @@ importers: astro: specifier: 5.18.1 version: 5.18.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(rollup@4.59.0)(sass-embedded@1.97.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) - conventional-changelog-cli: - specifier: 5.0.0 - version: 5.0.0(conventional-commits-filter@5.0.0) cors: specifier: 2.8.6 version: 2.8.6 @@ -420,9 +408,6 @@ importers: prettier: specifier: ^3.8.1 version: 3.8.1 - semantic-release: - specifier: 24.2.9 - version: 24.2.9(typescript@5.9.3) sharp: specifier: 0.34.5 version: 0.34.5 @@ -1557,22 +1542,6 @@ packages: '@colordx/core@5.4.3': resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==} - '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} - engines: {node: '>=0.1.90'} - - '@conventional-changelog/git-client@1.0.1': - resolution: {integrity: sha512-PJEqBwAleffCMETaVm/fUgHldzBE35JFk3/9LL6NUA5EXa3qednu+UT6M7E5iBu3zIQZCULYIiZ90fBYHt6xUw==} - engines: {node: '>=18'} - peerDependencies: - conventional-commits-filter: ^5.0.0 - conventional-commits-parser: ^6.0.0 - peerDependenciesMeta: - conventional-commits-filter: - optional: true - conventional-commits-parser: - optional: true - '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -2375,10 +2344,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@hutson/parse-repository-url@5.0.0': - resolution: {integrity: sha512-e5+YUKENATs1JgYHMzTr2MW/NDcXGfYFAuOQU8gJgF/kEh4EqKgfGrfLI67bMD4tbhZVlkigz/9YYwWcbOFthg==} - engines: {node: '>=10.13.0'} - '@img/colour@1.0.0': resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} engines: {node: '>=18'} @@ -3550,60 +3515,6 @@ packages: '@nx/workspace@22.7.1': resolution: {integrity: sha512-wnBMgeogdGaRdxDDzZspSt1U87PMeYJhz1ygr42L9Lot9E5nCf17E85iyHl3YxcMSNslHxnHyTkq7MyQ8hHjdQ==} - '@octokit/auth-token@6.0.0': - resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==} - engines: {node: '>= 20'} - - '@octokit/core@7.0.6': - resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==} - engines: {node: '>= 20'} - - '@octokit/endpoint@11.0.2': - resolution: {integrity: sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==} - engines: {node: '>= 20'} - - '@octokit/graphql@9.0.3': - resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==} - engines: {node: '>= 20'} - - '@octokit/openapi-types@26.0.0': - resolution: {integrity: sha512-7AtcfKtpo77j7Ts73b4OWhOZHTKo/gGY8bB3bNBQz4H+GRSWqx2yvj8TXRsbdTE0eRmYmXOEY66jM7mJ7LzfsA==} - - '@octokit/openapi-types@27.0.0': - resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==} - - '@octokit/plugin-paginate-rest@13.2.1': - resolution: {integrity: sha512-Tj4PkZyIL6eBMYcG/76QGsedF0+dWVeLhYprTmuFVVxzDW7PQh23tM0TP0z+1MvSkxB29YFZwnUX+cXfTiSdyw==} - engines: {node: '>= 20'} - peerDependencies: - '@octokit/core': '>=6' - - '@octokit/plugin-retry@8.0.3': - resolution: {integrity: sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==} - engines: {node: '>= 20'} - peerDependencies: - '@octokit/core': '>=7' - - '@octokit/plugin-throttling@11.0.3': - resolution: {integrity: sha512-34eE0RkFCKycLl2D2kq7W+LovheM/ex3AwZCYN8udpi6bxsyjZidb2McXs69hZhLmJlDqTSP8cH+jSRpiaijBg==} - engines: {node: '>= 20'} - peerDependencies: - '@octokit/core': ^7.0.0 - - '@octokit/request-error@7.1.0': - resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} - engines: {node: '>= 20'} - - '@octokit/request@10.0.7': - resolution: {integrity: sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==} - engines: {node: '>= 20'} - - '@octokit/types@15.0.2': - resolution: {integrity: sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q==} - - '@octokit/types@16.0.0': - resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==} - '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} @@ -3824,18 +3735,6 @@ packages: engines: {node: '>=18'} hasBin: true - '@pnpm/config.env-replace@1.1.0': - resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} - engines: {node: '>=12.22.0'} - - '@pnpm/network.ca-file@1.0.2': - resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} - engines: {node: '>=12.22.0'} - - '@pnpm/npm-conf@2.3.1': - resolution: {integrity: sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==} - engines: {node: '>=12'} - '@rolldown/binding-android-arm64@1.0.0-rc.4': resolution: {integrity: sha512-vRq9f4NzvbdZavhQbjkJBx7rRebDKYR9zHfO/Wg486+I7bSecdUapzCm5cyXoK+LHokTxgSq7A5baAXUZkIz0w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4161,59 +4060,6 @@ packages: resolution: {integrity: sha512-1renEbBZz9Yw3A0GUOJ6x6E1jd2Vu/fX5tEGiFNbIoWaNwa71SlFTvKKqaYxiYQkrpc7oexVJ2ymuvOfgTbI1w==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@sec-ant/readable-stream@0.4.1': - resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} - - '@semantic-release/changelog@6.0.3': - resolution: {integrity: sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==} - engines: {node: '>=14.17'} - peerDependencies: - semantic-release: '>=18.0.0' - - '@semantic-release/commit-analyzer@13.0.1': - resolution: {integrity: sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==} - engines: {node: '>=20.8.1'} - peerDependencies: - semantic-release: '>=20.1.0' - - '@semantic-release/error@3.0.0': - resolution: {integrity: sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==} - engines: {node: '>=14.17'} - - '@semantic-release/error@4.0.0': - resolution: {integrity: sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==} - engines: {node: '>=18'} - - '@semantic-release/git@10.0.1': - resolution: {integrity: sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==} - engines: {node: '>=14.17'} - peerDependencies: - semantic-release: '>=18.0.0' - - '@semantic-release/github@11.0.6': - resolution: {integrity: sha512-ctDzdSMrT3H+pwKBPdyCPty6Y47X8dSrjd3aPZ5KKIKKWTwZBE9De8GtsH3TyAlw3Uyo2stegMx6rJMXKpJwJA==} - engines: {node: '>=20.8.1'} - peerDependencies: - semantic-release: '>=24.1.0' - - '@semantic-release/npm@12.0.1': - resolution: {integrity: sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==} - engines: {node: '>=20.8.1'} - peerDependencies: - semantic-release: '>=20.1.0' - - '@semantic-release/npm@12.0.2': - resolution: {integrity: sha512-+M9/Lb35IgnlUO6OSJ40Ie+hUsZLuph2fqXC/qrKn0fMvUU/jiCjpoL6zEm69vzcmaZJ8yNKtMBEKHWN49WBbQ==} - engines: {node: '>=20.8.1'} - peerDependencies: - semantic-release: '>=20.1.0' - - '@semantic-release/release-notes-generator@14.1.0': - resolution: {integrity: sha512-CcyDRk7xq+ON/20YNR+1I/jP7BYKICr1uKd1HHpROSnnTdGqOTburi4jcRiTYz0cpfhxSloQO3cGhnoot7IEkA==} - engines: {node: '>=20.8.1'} - peerDependencies: - semantic-release: '>=20.1.0' - '@shikijs/core@3.22.0': resolution: {integrity: sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==} @@ -4270,10 +4116,6 @@ packages: resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@sindresorhus/merge-streams@4.0.0': - resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} - engines: {node: '>=18'} - '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -4555,9 +4397,6 @@ packages: '@types/node@24.13.1': resolution: {integrity: sha512-RSpUJGmvsJ1ZeBehQZFhIdpsz+bIpES0nIQXko4Ybq+N+kX6XvOq3Jo+iJ82FWLdblFq85AsMikd3m35jgezYg==} - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -4582,9 +4421,6 @@ packages: '@types/semver@7.5.8': resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/semver@7.7.1': - resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} - '@types/send@0.17.6': resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} @@ -4933,9 +4769,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - add-stream@1.0.0: - resolution: {integrity: sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==} - address@1.2.2: resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} @@ -4970,10 +4803,6 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - aggregate-error@5.0.0: - resolution: {integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==} - engines: {node: '>=18'} - ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -5055,10 +4884,6 @@ packages: resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} engines: {node: '>=12'} - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -5100,9 +4925,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - argv-formatter@1.0.0: - resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==} - aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -5114,9 +4936,6 @@ packages: array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - array-ify@1.0.0: - resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - array-includes@3.1.9: resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} engines: {node: '>= 0.4'} @@ -5300,9 +5119,6 @@ packages: resolution: {integrity: sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==} engines: {node: '>=18.0.0'} - before-after-hook@4.0.0: - resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} - better-sqlite3@12.9.0: resolution: {integrity: sha512-wqUv4Gm3toFpHDQmaKD4QhZm3g1DjUBI0yzS4UBl6lElUmXFYdTQmmEDpAFa5o8FiFiymURypEnfVHzILKaxqQ==} engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x} @@ -5334,9 +5150,6 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - bottleneck@2.19.5: - resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - boxen@8.0.1: resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} engines: {node: '>=18'} @@ -5465,10 +5278,6 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -5545,10 +5354,6 @@ packages: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - clean-stack@5.3.0: - resolution: {integrity: sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg==} - engines: {node: '>=14.16'} - cli-boxes@3.0.0: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} @@ -5561,11 +5366,6 @@ packages: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} - cli-highlight@2.1.11: - resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} - engines: {node: '>=8.0.0', npm: '>=5.0.0'} - hasBin: true - cli-spinners@2.6.1: resolution: {integrity: sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==} engines: {node: '>=6'} @@ -5578,10 +5378,6 @@ packages: resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} engines: {node: '>=18.20'} - cli-table3@0.6.5: - resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} - engines: {node: 10.* || >= 12.*} - cli-truncate@2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -5597,9 +5393,6 @@ packages: cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -5633,16 +5426,10 @@ packages: collect-v8-coverage@1.0.3: resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} @@ -5688,9 +5475,6 @@ packages: common-path-prefix@3.0.0: resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - compare-func@2.0.0: - resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} - compare-version@0.1.2: resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} engines: {node: '>=0.10.0'} @@ -5706,9 +5490,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} - config-file-ts@0.2.8-rc1: resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} @@ -5731,78 +5512,6 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - conventional-changelog-angular@8.1.0: - resolution: {integrity: sha512-GGf2Nipn1RUCAktxuVauVr1e3r8QrLP/B0lEUsFktmGqc3ddbQkhoJZHJctVU829U1c6mTSWftrVOCHaL85Q3w==} - engines: {node: '>=18'} - - conventional-changelog-atom@5.0.0: - resolution: {integrity: sha512-WfzCaAvSCFPkznnLgLnfacRAzjgqjLUjvf3MftfsJzQdDICqkOOpcMtdJF3wTerxSpv2IAAjX8doM3Vozqle3g==} - engines: {node: '>=18'} - - conventional-changelog-cli@5.0.0: - resolution: {integrity: sha512-9Y8fucJe18/6ef6ZlyIlT2YQUbczvoQZZuYmDLaGvcSBP+M6h+LAvf7ON7waRxKJemcCII8Yqu5/8HEfskTxJQ==} - engines: {node: '>=18'} - deprecated: This package is no longer maintained. Please use the conventional-changelog package instead. - hasBin: true - - conventional-changelog-codemirror@5.0.0: - resolution: {integrity: sha512-8gsBDI5Y3vrKUCxN6Ue8xr6occZ5nsDEc4C7jO/EovFGozx8uttCAyfhRrvoUAWi2WMm3OmYs+0mPJU7kQdYWQ==} - engines: {node: '>=18'} - - conventional-changelog-conventionalcommits@8.0.0: - resolution: {integrity: sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==} - engines: {node: '>=18'} - - conventional-changelog-core@8.0.0: - resolution: {integrity: sha512-EATUx5y9xewpEe10UEGNpbSHRC6cVZgO+hXQjofMqpy+gFIrcGvH3Fl6yk2VFKh7m+ffenup2N7SZJYpyD9evw==} - engines: {node: '>=18'} - - conventional-changelog-ember@5.0.0: - resolution: {integrity: sha512-RPflVfm5s4cSO33GH/Ey26oxhiC67akcxSKL8CLRT3kQX2W3dbE19sSOM56iFqUJYEwv9mD9r6k79weWe1urfg==} - engines: {node: '>=18'} - - conventional-changelog-eslint@6.0.0: - resolution: {integrity: sha512-eiUyULWjzq+ybPjXwU6NNRflApDWlPEQEHvI8UAItYW/h22RKkMnOAtfCZxMmrcMO1OKUWtcf2MxKYMWe9zJuw==} - engines: {node: '>=18'} - - conventional-changelog-express@5.0.0: - resolution: {integrity: sha512-D8Q6WctPkQpvr2HNCCmwU5GkX22BVHM0r4EW8vN0230TSyS/d6VQJDAxGb84lbg0dFjpO22MwmsikKL++Oo/oQ==} - engines: {node: '>=18'} - - conventional-changelog-jquery@6.0.0: - resolution: {integrity: sha512-2kxmVakyehgyrho2ZHBi90v4AHswkGzHuTaoH40bmeNqUt20yEkDOSpw8HlPBfvEQBwGtbE+5HpRwzj6ac2UfA==} - engines: {node: '>=18'} - - conventional-changelog-jshint@5.0.0: - resolution: {integrity: sha512-gGNphSb/opc76n2eWaO6ma4/Wqu3tpa2w7i9WYqI6Cs2fncDSI2/ihOfMvXveeTTeld0oFvwMVNV+IYQIk3F3g==} - engines: {node: '>=18'} - - conventional-changelog-preset-loader@5.0.0: - resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==} - engines: {node: '>=18'} - - conventional-changelog-writer@8.2.0: - resolution: {integrity: sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==} - engines: {node: '>=18'} - hasBin: true - - conventional-changelog@6.0.0: - resolution: {integrity: sha512-tuUH8H/19VjtD9Ig7l6TQRh+Z0Yt0NZ6w/cCkkyzUbGQTnUEmKfGtkC9gGfVgCfOL1Rzno5NgNF4KY8vR+Jo3w==} - engines: {node: '>=18'} - - conventional-commits-filter@5.0.0: - resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} - engines: {node: '>=18'} - - conventional-commits-parser@6.2.1: - resolution: {integrity: sha512-20pyHgnO40rvfI0NGF/xiEoFMkXDtkF8FwHvk5BokoFoCuTQRI8vrNCNFWUOfuolKJMm1tPCHc8GgYEtr1XRNA==} - engines: {node: '>=18'} - hasBin: true - - convert-hrtime@5.0.0: - resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} - engines: {node: '>=12'} - convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -5905,10 +5614,6 @@ packages: crossws@0.3.5: resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} - crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} - css-declaration-sorter@7.3.1: resolution: {integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==} engines: {node: ^14 || ^16 || >=18} @@ -6201,10 +5906,6 @@ packages: dir-compare@4.2.0: resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -6241,10 +5942,6 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dot-prop@5.3.0: - resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} - engines: {node: '>=8'} - dotenv-expand@11.0.7: resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} engines: {node: '>=12'} @@ -6365,9 +6062,6 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - duplexer2@0.1.4: - resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -6434,9 +6128,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - emojilib@2.4.0: - resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - emojis-list@3.0.0: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} @@ -6467,10 +6158,6 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} - env-ci@11.2.0: - resolution: {integrity: sha512-D5kWfzkmaOQDioPmiviWAVtKmpPT4/iJmMVQxWxMPJTFyTkdc5JQUfc5iXEeWxcOdsYTKSAiA/Age4NUOqKsRA==} - engines: {node: ^18.17 || >=20.6.1} - env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -6758,14 +6445,6 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - - execa@9.6.1: - resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} - engines: {node: ^18.19.0 || >=20.5.0} - exit-x@0.2.2: resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} engines: {node: '>= 0.8.0'} @@ -6806,9 +6485,6 @@ packages: resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} engines: {'0': node >=0.6.0} - fast-content-type-parse@3.0.0: - resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -6844,18 +6520,10 @@ packages: picomatch: optional: true - figures@2.0.0: - resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} - engines: {node: '>=4'} - figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} - figures@6.1.0: - resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} - engines: {node: '>=18'} - file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -6890,14 +6558,6 @@ packages: resolution: {integrity: sha512-WgZ+nKbELDa6N3i/9nrHeNznm+lY3z4YfhDDWgW+5P0pdmMj26bxaxU11ookgY3NyP9GC7HvZ9etp0jRFqGEeQ==} engines: {node: '>=8'} - find-up-simple@1.0.1: - resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} - engines: {node: '>=18'} - - find-up@2.1.0: - resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} - engines: {node: '>=4'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -6910,10 +6570,6 @@ packages: resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - find-versions@6.0.0: - resolution: {integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==} - engines: {node: '>=18'} - fix-path@5.0.0: resolution: {integrity: sha512-erEWGGCN7RIu1bXTCfNVpVBdm0f5mwcbeja+4QXiEZzIQukP401sbpu8gd3Ny1vS34YNeswyMO0TdT2tP5OlHA==} engines: {node: '>=20'} @@ -6983,9 +6639,6 @@ packages: resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} engines: {node: '>= 0.8'} - from2@2.3.0: - resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} - fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} @@ -6993,10 +6646,6 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} - fs-extra@11.3.3: - resolution: {integrity: sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==} - engines: {node: '>=14.14'} - fs-extra@11.3.5: resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} engines: {node: '>=14.14'} @@ -7040,10 +6689,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function-timeout@1.0.2: - resolution: {integrity: sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==} - engines: {node: '>=18'} - function.prototype.name@1.1.8: resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} @@ -7091,18 +6736,6 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-stream@7.0.1: - resolution: {integrity: sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==} - engines: {node: '>=16'} - - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - - get-stream@9.0.1: - resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} - engines: {node: '>=18'} - get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} @@ -7110,21 +6743,6 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} - git-log-parser@1.2.1: - resolution: {integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==} - - git-raw-commits@5.0.0: - resolution: {integrity: sha512-I2ZXrXeOc0KrCvC7swqtIFXFN+rbjnC7b2T943tvemIOVNl+XP8YnA9UVwqFhzzLClnSA60KR/qEjLpXzs73Qg==} - engines: {node: '>=18'} - deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. - hasBin: true - - git-semver-tags@8.0.0: - resolution: {integrity: sha512-N7YRIklvPH3wYWAR2vysaqGLPRcpwQ0GKdlqTiVN5w1UmCdaeY3K8s6DMKRCh54DDdzyt/OAB6C8jgVtb7Y2Fg==} - engines: {node: '>=18'} - deprecated: This package is no longer maintained. For the JavaScript API, please use @conventional-changelog/git-client instead. - hasBin: true - github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -7205,9 +6823,6 @@ packages: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} engines: {node: '>=10.19.0'} - graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -7229,10 +6844,6 @@ packages: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -7300,9 +6911,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - hls.js@1.6.13: resolution: {integrity: sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA==} @@ -7314,22 +6922,10 @@ packages: resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==} engines: {node: '>=16.9.0'} - hook-std@4.0.0: - resolution: {integrity: sha512-IHI4bEVOt3vRUDJ+bFA9VUJlo7SzvFARPNLw75pqSmAOP2HmTWfFJtPvLBrDrlgjEYXY9zs7SFdHPQaJShkSCQ==} - engines: {node: '>=20'} - hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - hosted-git-info@7.0.2: - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} - engines: {node: ^16.14.0 || >=18.0.0} - - hosted-git-info@8.1.0: - resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==} - engines: {node: ^18.17.0 || >=20.5.0} - hosted-git-info@9.0.2: resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} engines: {node: ^20.17.0 || >=22.9.0} @@ -7431,14 +7027,6 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - human-signals@8.0.1: - resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} - engines: {node: '>=18.18.0'} - humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} @@ -7500,10 +7088,6 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-from-esm@2.0.0: - resolution: {integrity: sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==} - engines: {node: '>=18.20'} - import-local@3.2.0: resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} @@ -7520,14 +7104,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - indent-string@5.0.0: - resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} - engines: {node: '>=12'} - - index-to-position@1.2.0: - resolution: {integrity: sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==} - engines: {node: '>=18'} - individual@2.0.0: resolution: {integrity: sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g==} @@ -7558,10 +7134,6 @@ packages: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} - into-stream@7.0.0: - resolution: {integrity: sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==} - engines: {node: '>=12'} - ip-address@10.1.0: resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} @@ -7718,10 +7290,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj@2.0.0: - resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} - engines: {node: '>=8'} - is-plain-obj@3.0.0: resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} engines: {node: '>=10'} @@ -7760,14 +7328,6 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-stream@4.0.1: - resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} - engines: {node: '>=18'} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -7845,10 +7405,6 @@ packages: peerDependencies: ws: '*' - issue-parser@7.0.1: - resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==} - engines: {node: ^18.17 || >=20.6.1} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -7877,10 +7433,6 @@ packages: engines: {node: '>=10'} hasBin: true - java-properties@1.0.2: - resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==} - engines: {node: '>= 0.6.0'} - jest-changed-files@30.2.0: resolution: {integrity: sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -8077,9 +7629,6 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-better-errors@1.0.2: - resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -8212,10 +7761,6 @@ packages: resolution: {integrity: sha512-NYHA0MRPjvNX+vSw8Xxg6FLKxzAG+e7Pt8RqAQA/EehzHVXq9SxDqJIN3JL1hK0dweb884y8kIh6rkWvPyg9Wg==} hasBin: true - load-json-file@4.0.0: - resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} - engines: {node: '>=4'} - loader-runner@4.3.1: resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} @@ -8224,10 +7769,6 @@ packages: resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} engines: {node: '>=8.9.0'} - locate-path@2.0.0: - resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} - engines: {node: '>=4'} - locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -8240,12 +7781,6 @@ packages: resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lodash-es@4.18.1: - resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} - - lodash.capitalize@4.2.1: - resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} - lodash.clonedeepwith@4.5.0: resolution: {integrity: sha512-QRBRSxhbtsX1nc0baxSkkK5WlVTTm/s48DSukcGcWZwIyI8Zz+lB+kFiELJXtzfH4Aj6kMWQ1VWW4U5uUDgZMA==} @@ -8259,12 +7794,6 @@ packages: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - lodash.isplainobject@4.0.6: - resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} - - lodash.isstring@4.0.1: - resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} - lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -8274,9 +7803,6 @@ packages: lodash.uniq@4.5.0: resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash.uniqby@4.7.0: - resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} - lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -8340,10 +7866,6 @@ packages: magicast@0.5.2: resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} - make-asynchronous@1.0.1: - resolution: {integrity: sha512-T9BPOmEOhp6SmV25SwLVcHK4E6JyG/coH3C6F1NjNXSziv/fd4GmsqMk8YR6qpPOswfaOCApSNkZv6fxoaYFcQ==} - engines: {node: '>=18'} - make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -8373,17 +7895,6 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - marked-terminal@7.3.0: - resolution: {integrity: sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==} - engines: {node: '>=16.0.0'} - peerDependencies: - marked: '>=1 <16' - - marked@15.0.12: - resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} - engines: {node: '>= 18'} - hasBin: true - marked@18.0.5: resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==} engines: {node: '>= 20'} @@ -8468,10 +7979,6 @@ packages: memfs@4.51.1: resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==} - meow@13.2.0: - resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} - engines: {node: '>=18'} - merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} @@ -8625,19 +8132,10 @@ packages: engines: {node: '>=4.0.0'} hasBin: true - mime@4.1.0: - resolution: {integrity: sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==} - engines: {node: '>=16'} - hasBin: true - mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - mimic-function@5.0.1: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} @@ -8837,9 +8335,6 @@ packages: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} - nerf-dart@1.0.0: - resolution: {integrity: sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==} - ng-mocks@14.15.1: resolution: {integrity: sha512-qytFlHgR8YkyH2Hsc6ssGHf817pku6UvV1vpKelh9K07+2IYxfgZJrAyTAGmwH0+9i9hjtdoTrZSP5A4KdQu4Q==} peerDependencies: @@ -8882,10 +8377,6 @@ packages: node-api-version@0.2.1: resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} - node-emoji@2.2.0: - resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} - engines: {node: '>=18'} - node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} @@ -8937,10 +8428,6 @@ packages: engines: {node: ^20.17.0 || >=22.9.0} hasBin: true - normalize-package-data@6.0.2: - resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} - engines: {node: ^16.14.0 || >=18.0.0} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -8949,10 +8436,6 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} - normalize-url@8.1.1: - resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} - engines: {node: '>=14.16'} - npm-bundled@5.0.0: resolution: {integrity: sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -8985,88 +8468,6 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - npm-run-path@6.0.0: - resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} - engines: {node: '>=18'} - - npm@10.9.4: - resolution: {integrity: sha512-OnUG836FwboQIbqtefDNlyR0gTHzIfwRfE3DuiNewBvnMnWEpB0VEXwBlFVgqpNzIgYo/MHh3d2Hel/pszapAA==} - engines: {node: ^18.17.0 || >=20.5.0} - hasBin: true - bundledDependencies: - - '@isaacs/string-locale-compare' - - '@npmcli/arborist' - - '@npmcli/config' - - '@npmcli/fs' - - '@npmcli/map-workspaces' - - '@npmcli/package-json' - - '@npmcli/promise-spawn' - - '@npmcli/redact' - - '@npmcli/run-script' - - '@sigstore/tuf' - - abbrev - - archy - - cacache - - chalk - - ci-info - - cli-columns - - fastest-levenshtein - - fs-minipass - - glob - - graceful-fs - - hosted-git-info - - ini - - init-package-json - - is-cidr - - json-parse-even-better-errors - - libnpmaccess - - libnpmdiff - - libnpmexec - - libnpmfund - - libnpmhook - - libnpmorg - - libnpmpack - - libnpmpublish - - libnpmsearch - - libnpmteam - - libnpmversion - - make-fetch-happen - - minimatch - - minipass - - minipass-pipeline - - ms - - node-gyp - - nopt - - normalize-package-data - - npm-audit-report - - npm-install-checks - - npm-package-arg - - npm-pick-manifest - - npm-profile - - npm-registry-fetch - - npm-user-validate - - p-map - - pacote - - parse-conflict-json - - proc-log - - qrcode-terminal - - read - - semver - - spdx-expression-parse - - ssri - - supports-color - - tar - - text-table - - tiny-relative-date - - treeverse - - validate-npm-package-name - - which - - write-file-atomic - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -9148,10 +8549,6 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - onetime@7.0.0: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} @@ -9207,26 +8604,6 @@ packages: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} - p-each-series@3.0.0: - resolution: {integrity: sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==} - engines: {node: '>=12'} - - p-event@6.0.1: - resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==} - engines: {node: '>=16.17'} - - p-filter@4.1.0: - resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} - engines: {node: '>=18'} - - p-is-promise@3.0.0: - resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} - engines: {node: '>=8'} - - p-limit@1.3.0: - resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} - engines: {node: '>=4'} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -9243,10 +8620,6 @@ packages: resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} engines: {node: '>=18'} - p-locate@2.0.0: - resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} - engines: {node: '>=4'} - p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -9271,14 +8644,6 @@ packages: resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==} engines: {node: '>=18'} - p-reduce@2.1.0: - resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} - engines: {node: '>=8'} - - p-reduce@3.0.0: - resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==} - engines: {node: '>=12'} - p-retry@6.2.1: resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} @@ -9287,10 +8652,6 @@ packages: resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} engines: {node: '>=14.16'} - p-try@1.0.0: - resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} - engines: {node: '>=4'} - p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -9313,25 +8674,13 @@ packages: parse-entities@4.0.2: resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - parse-json@4.0.0: - resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} - engines: {node: '>=4'} - parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse-json@8.3.0: - resolution: {integrity: sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==} - engines: {node: '>=18'} - parse-latin@7.0.0: resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} - parse-ms@4.0.0: - resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} - engines: {node: '>=18'} - parse-node-version@1.0.1: resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} engines: {node: '>= 0.10'} @@ -9343,21 +8692,12 @@ packages: parse5-html-rewriting-stream@8.0.0: resolution: {integrity: sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==} - parse5-htmlparser2-tree-adapter@6.0.1: - resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} - parse5-sax-parser@8.0.0: resolution: {integrity: sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==} parse5@4.0.0: resolution: {integrity: sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==} - parse5@5.1.1: - resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} - - parse5@6.0.1: - resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -9368,10 +8708,6 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} - path-exists@3.0.0: - resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} - engines: {node: '>=4'} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -9388,10 +8724,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -9443,10 +8775,6 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} - pify@3.0.0: - resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} - engines: {node: '>=4'} - pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -9467,10 +8795,6 @@ packages: resolution: {integrity: sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==} hasBin: true - pkg-conf@2.1.0: - resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==} - engines: {node: '>=4'} - pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -9823,10 +9147,6 @@ packages: resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - pretty-ms@9.3.0: - resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} - engines: {node: '>=18'} - prismjs@1.30.0: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} @@ -9869,9 +9189,6 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -9957,14 +9274,6 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - read-package-up@11.0.0: - resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==} - engines: {node: '>=18'} - - read-pkg@9.0.1: - resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} - engines: {node: '>=18'} - readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -10029,10 +9338,6 @@ packages: resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} engines: {node: '>=4'} - registry-auth-token@5.1.0: - resolution: {integrity: sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==} - engines: {node: '>=14'} - regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} @@ -10421,20 +9726,6 @@ packages: resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} engines: {node: '>=10'} - semantic-release@24.2.9: - resolution: {integrity: sha512-phCkJ6pjDi9ANdhuF5ElS10GGdAKY6R1Pvt9lT3SFhOwM4T7QZE7MLpBDbNruUx/Q3gFD92/UOFringGipRqZA==} - engines: {node: '>=20.8.1'} - hasBin: true - - semver-diff@5.0.0: - resolution: {integrity: sha512-0HbGtOm+S7T6NGQ/pxJSJipJvc4DK3FcRVMRkhsIwJDJ4Jcz5DQC1cPPzB5GhzyHjwttW878HaWQq46CkL3cqg==} - engines: {node: '>=12'} - deprecated: Deprecated as the semver package now supports this built-in. - - semver-regex@4.0.5: - resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} - engines: {node: '>=12'} - semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true @@ -10563,10 +9854,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - signale@1.4.0: - resolution: {integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==} - engines: {node: '>=6'} - sigstore@4.1.0: resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==} engines: {node: ^20.17.0 || >=22.9.0} @@ -10589,10 +9876,6 @@ packages: engines: {node: '>=14.0.0', npm: '>=6.0.0'} hasBin: true - skin-tone@2.0.0: - resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} - engines: {node: '>=8'} - slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -10665,18 +9948,9 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - spawn-error-forwarder@1.0.0: - resolution: {integrity: sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==} - - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - spdx-exceptions@2.5.0: resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} @@ -10690,9 +9964,6 @@ packages: resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} engines: {node: '>=6.0.0'} - split2@1.0.0: - resolution: {integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -10731,9 +10002,6 @@ packages: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} - stream-combiner2@1.1.1: - resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==} - stream-replace-string@2.0.0: resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} @@ -10802,14 +10070,6 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - - strip-final-newline@4.0.0: - resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} - engines: {node: '>=18'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -10845,14 +10105,6 @@ packages: resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} engines: {node: '>= 8.0'} - super-regex@1.1.0: - resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==} - engines: {node: '>=18'} - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -10861,10 +10113,6 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-hyperlinks@3.2.0: - resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} - engines: {node: '>=14.18'} - supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -10919,10 +10167,6 @@ packages: resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==} engines: {node: '>=18'} - temp-dir@3.0.0: - resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} - engines: {node: '>=14.16'} - temp-file@3.4.0: resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} @@ -10930,14 +10174,6 @@ packages: resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} engines: {node: '>=6.0.0'} - tempfile@5.0.0: - resolution: {integrity: sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==} - engines: {node: '>=14.18'} - - tempy@3.1.0: - resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} - engines: {node: '>=14.16'} - terser-webpack-plugin@5.3.16: resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} engines: {node: '>= 10.13.0'} @@ -10976,16 +10212,9 @@ packages: peerDependencies: tslib: ^2 - through2@2.0.5: - resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} - thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - time-span@5.1.0: - resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} - engines: {node: '>=12'} - tiny-async-pool@1.3.0: resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} @@ -11043,10 +10272,6 @@ packages: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} - traverse@0.6.8: - resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} - engines: {node: '>= 0.4'} - tree-dump@1.1.0: resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} engines: {node: '>=10.0'} @@ -11188,14 +10413,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - - type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - type-fest@4.41.0: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} @@ -11275,10 +10492,6 @@ packages: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} - unicode-emoji-modifier-base@1.0.0: - resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} - engines: {node: '>=4'} - unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} @@ -11291,10 +10504,6 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} - unicorn-magic@0.1.0: - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} - engines: {node: '>=18'} - unicorn-magic@0.3.0: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} @@ -11325,10 +10534,6 @@ packages: resolution: {integrity: sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==} engines: {node: ^20.17.0 || >=22.9.0} - unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} - unist-util-find-after@5.0.0: resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} @@ -11359,9 +10564,6 @@ packages: unist-util-visit@5.1.0: resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} - universal-user-agent@7.0.3: - resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==} - universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -11455,10 +10657,6 @@ packages: url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - url-join@5.0.0: - resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - url-toolkit@2.2.5: resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==} @@ -11489,9 +10687,6 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validate-npm-package-name@7.0.2: resolution: {integrity: sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==} engines: {node: ^20.17.0 || >=22.9.0} @@ -11656,9 +10851,6 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - web-worker@1.2.0: - resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} - webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -11870,10 +11062,6 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - xxhash-wasm@1.1.0: resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} @@ -11912,10 +11100,6 @@ packages: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} - yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -11928,10 +11112,6 @@ packages: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} - yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -13583,17 +12763,6 @@ snapshots: '@colordx/core@5.4.3': {} - '@colors/colors@1.5.0': - optional: true - - '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1)': - dependencies: - '@types/semver': 7.7.1 - semver: 7.7.4 - optionalDependencies: - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -14150,8 +13319,6 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@hutson/parse-repository-url@5.0.0': {} - '@img/colour@1.0.0': {} '@img/sharp-darwin-arm64@0.34.5': @@ -15839,71 +15006,6 @@ snapshots: - '@swc/core' - debug - '@octokit/auth-token@6.0.0': {} - - '@octokit/core@7.0.6': - dependencies: - '@octokit/auth-token': 6.0.0 - '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.7 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - before-after-hook: 4.0.0 - universal-user-agent: 7.0.3 - - '@octokit/endpoint@11.0.2': - dependencies: - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 - - '@octokit/graphql@9.0.3': - dependencies: - '@octokit/request': 10.0.7 - '@octokit/types': 16.0.0 - universal-user-agent: 7.0.3 - - '@octokit/openapi-types@26.0.0': {} - - '@octokit/openapi-types@27.0.0': {} - - '@octokit/plugin-paginate-rest@13.2.1(@octokit/core@7.0.6)': - dependencies: - '@octokit/core': 7.0.6 - '@octokit/types': 15.0.2 - - '@octokit/plugin-retry@8.0.3(@octokit/core@7.0.6)': - dependencies: - '@octokit/core': 7.0.6 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - bottleneck: 2.19.5 - - '@octokit/plugin-throttling@11.0.3(@octokit/core@7.0.6)': - dependencies: - '@octokit/core': 7.0.6 - '@octokit/types': 16.0.0 - bottleneck: 2.19.5 - - '@octokit/request-error@7.1.0': - dependencies: - '@octokit/types': 16.0.0 - - '@octokit/request@10.0.7': - dependencies: - '@octokit/endpoint': 11.0.2 - '@octokit/request-error': 7.1.0 - '@octokit/types': 16.0.0 - fast-content-type-parse: 3.0.0 - universal-user-agent: 7.0.3 - - '@octokit/types@15.0.2': - dependencies: - '@octokit/openapi-types': 26.0.0 - - '@octokit/types@16.0.0': - dependencies: - '@octokit/openapi-types': 27.0.0 - '@oslojs/encoding@1.1.0': {} '@oxc-project/types@0.113.0': {} @@ -16046,18 +15148,6 @@ snapshots: dependencies: playwright: 1.57.0 - '@pnpm/config.env-replace@1.1.0': {} - - '@pnpm/network.ca-file@1.0.2': - dependencies: - graceful-fs: 4.2.10 - - '@pnpm/npm-conf@2.3.1': - dependencies: - '@pnpm/config.env-replace': 1.1.0 - '@pnpm/network.ca-file': 1.0.2 - config-chain: 1.1.13 - '@rolldown/binding-android-arm64@1.0.0-rc.4': optional: true @@ -16280,120 +15370,6 @@ snapshots: transitivePeerDependencies: - chokidar - '@sec-ant/readable-stream@0.4.1': {} - - '@semantic-release/changelog@6.0.3(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - '@semantic-release/error': 3.0.0 - aggregate-error: 3.1.0 - fs-extra: 11.3.3 - lodash: 4.18.1 - semantic-release: 24.2.9(typescript@5.9.3) - - '@semantic-release/commit-analyzer@13.0.1(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.3 - import-from-esm: 2.0.0 - lodash-es: 4.18.1 - micromatch: 4.0.8 - semantic-release: 24.2.9(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - '@semantic-release/error@3.0.0': {} - - '@semantic-release/error@4.0.0': {} - - '@semantic-release/git@10.0.1(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - '@semantic-release/error': 3.0.0 - aggregate-error: 3.1.0 - debug: 4.4.3 - dir-glob: 3.0.1 - execa: 5.1.1 - lodash: 4.18.1 - micromatch: 4.0.8 - p-reduce: 2.1.0 - semantic-release: 24.2.9(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - '@semantic-release/github@11.0.6(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - '@octokit/core': 7.0.6 - '@octokit/plugin-paginate-rest': 13.2.1(@octokit/core@7.0.6) - '@octokit/plugin-retry': 8.0.3(@octokit/core@7.0.6) - '@octokit/plugin-throttling': 11.0.3(@octokit/core@7.0.6) - '@semantic-release/error': 4.0.0 - aggregate-error: 5.0.0 - debug: 4.4.3 - dir-glob: 3.0.1 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - issue-parser: 7.0.1 - lodash-es: 4.18.1 - mime: 4.1.0 - p-filter: 4.1.0 - semantic-release: 24.2.9(typescript@5.9.3) - tinyglobby: 0.2.15 - url-join: 5.0.0 - transitivePeerDependencies: - - supports-color - - '@semantic-release/npm@12.0.1(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - '@semantic-release/error': 4.0.0 - aggregate-error: 5.0.0 - execa: 9.6.1 - fs-extra: 11.3.3 - lodash-es: 4.18.1 - nerf-dart: 1.0.0 - normalize-url: 8.1.1 - npm: 10.9.4 - rc: 1.2.8 - read-pkg: 9.0.1 - registry-auth-token: 5.1.0 - semantic-release: 24.2.9(typescript@5.9.3) - semver: 7.7.3 - tempy: 3.1.0 - - '@semantic-release/npm@12.0.2(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - '@semantic-release/error': 4.0.0 - aggregate-error: 5.0.0 - execa: 9.6.1 - fs-extra: 11.3.3 - lodash-es: 4.18.1 - nerf-dart: 1.0.0 - normalize-url: 8.1.1 - npm: 10.9.4 - rc: 1.2.8 - read-pkg: 9.0.1 - registry-auth-token: 5.1.0 - semantic-release: 24.2.9(typescript@5.9.3) - semver: 7.7.4 - tempy: 3.1.0 - - '@semantic-release/release-notes-generator@14.1.0(semantic-release@24.2.9(typescript@5.9.3))': - dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-writer: 8.2.0 - conventional-commits-filter: 5.0.0 - conventional-commits-parser: 6.2.1 - debug: 4.4.3 - get-stream: 7.0.1 - import-from-esm: 2.0.0 - into-stream: 7.0.0 - lodash-es: 4.18.1 - read-package-up: 11.0.0 - semantic-release: 24.2.9(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - '@shikijs/core@3.22.0': dependencies: '@shikijs/types': 3.22.0 @@ -16465,8 +15441,6 @@ snapshots: '@sindresorhus/merge-streams@2.3.0': {} - '@sindresorhus/merge-streams@4.0.0': {} - '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 @@ -16776,8 +15750,6 @@ snapshots: dependencies: undici-types: 7.18.2 - '@types/normalize-package-data@2.4.4': {} - '@types/parse-json@4.0.2': {} '@types/plist@3.0.5': @@ -16802,8 +15774,6 @@ snapshots: '@types/semver@7.5.8': {} - '@types/semver@7.7.1': {} - '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 @@ -17179,8 +16149,6 @@ snapshots: acorn@8.15.0: {} - add-stream@1.0.0: {} - address@1.2.2: {} adm-zip@0.5.10: {} @@ -17218,11 +16186,6 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - aggregate-error@5.0.0: - dependencies: - clean-stack: 5.3.0 - indent-string: 5.0.0 - ajv-formats@2.1.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 @@ -17328,10 +16291,6 @@ snapshots: ansi-regex@6.2.2: {} - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -17400,8 +16359,6 @@ snapshots: argparse@2.0.1: {} - argv-formatter@1.0.0: {} - aria-query@5.3.2: {} array-buffer-byte-length@1.0.2: @@ -17411,8 +16368,6 @@ snapshots: array-flatten@1.1.1: {} - array-ify@1.0.0: {} - array-includes@3.1.9: dependencies: call-bind: 1.0.8 @@ -17792,8 +16747,6 @@ snapshots: postcss-media-query-parser: 0.2.3 postcss-safe-parser: 7.0.1(postcss@8.5.6) - before-after-hook@4.0.0: {} - better-sqlite3@12.9.0: dependencies: bindings: 1.5.0 @@ -17851,8 +16804,6 @@ snapshots: boolbase@1.0.0: {} - bottleneck@2.19.5: {} - boxen@8.0.1: dependencies: ansi-align: 3.0.1 @@ -18047,12 +16998,6 @@ snapshots: ccount@2.0.1: {} - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - chalk@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -18115,10 +17060,6 @@ snapshots: clean-stack@2.2.0: {} - clean-stack@5.3.0: - dependencies: - escape-string-regexp: 5.0.0 - cli-boxes@3.0.0: {} cli-cursor@3.1.0: @@ -18129,27 +17070,12 @@ snapshots: dependencies: restore-cursor: 5.1.0 - cli-highlight@2.1.11: - dependencies: - chalk: 4.1.2 - highlight.js: 10.7.3 - mz: 2.7.0 - parse5: 5.1.1 - parse5-htmlparser2-tree-adapter: 6.0.1 - yargs: 16.2.0 - cli-spinners@2.6.1: {} cli-spinners@2.9.2: {} cli-spinners@3.4.0: {} - cli-table3@0.6.5: - dependencies: - string-width: 4.2.3 - optionalDependencies: - '@colors/colors': 1.5.0 - cli-truncate@2.1.0: dependencies: slice-ansi: 3.0.0 @@ -18169,12 +17095,6 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - cliui@7.0.4: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -18207,16 +17127,10 @@ snapshots: collect-v8-coverage@1.0.3: {} - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - color-convert@2.0.1: dependencies: color-name: 1.1.4 - color-name@1.1.3: {} - color-name@1.1.4: {} colorette@2.0.20: {} @@ -18249,11 +17163,6 @@ snapshots: common-path-prefix@3.0.0: {} - compare-func@2.0.0: - dependencies: - array-ify: 1.0.0 - dot-prop: 5.3.0 - compare-version@0.1.2: {} compressible@2.0.18: @@ -18274,11 +17183,6 @@ snapshots: concat-map@0.0.1: {} - config-chain@1.1.13: - dependencies: - ini: 1.3.8 - proto-list: 1.2.4 - config-file-ts@0.2.8-rc1: dependencies: glob: 10.5.0 @@ -18296,87 +17200,6 @@ snapshots: content-type@1.0.5: {} - conventional-changelog-angular@8.1.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-atom@5.0.0: {} - - conventional-changelog-cli@5.0.0(conventional-commits-filter@5.0.0): - dependencies: - add-stream: 1.0.0 - conventional-changelog: 6.0.0(conventional-commits-filter@5.0.0) - meow: 13.2.0 - tempfile: 5.0.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-changelog-codemirror@5.0.0: {} - - conventional-changelog-conventionalcommits@8.0.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-core@8.0.0(conventional-commits-filter@5.0.0): - dependencies: - '@hutson/parse-repository-url': 5.0.0 - add-stream: 1.0.0 - conventional-changelog-writer: 8.2.0 - conventional-commits-parser: 6.2.1 - git-raw-commits: 5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1) - git-semver-tags: 8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1) - hosted-git-info: 7.0.2 - normalize-package-data: 6.0.2 - read-package-up: 11.0.0 - read-pkg: 9.0.1 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-changelog-ember@5.0.0: {} - - conventional-changelog-eslint@6.0.0: {} - - conventional-changelog-express@5.0.0: {} - - conventional-changelog-jquery@6.0.0: {} - - conventional-changelog-jshint@5.0.0: - dependencies: - compare-func: 2.0.0 - - conventional-changelog-preset-loader@5.0.0: {} - - conventional-changelog-writer@8.2.0: - dependencies: - conventional-commits-filter: 5.0.0 - handlebars: 4.7.8 - meow: 13.2.0 - semver: 7.7.4 - - conventional-changelog@6.0.0(conventional-commits-filter@5.0.0): - dependencies: - conventional-changelog-angular: 8.1.0 - conventional-changelog-atom: 5.0.0 - conventional-changelog-codemirror: 5.0.0 - conventional-changelog-conventionalcommits: 8.0.0 - conventional-changelog-core: 8.0.0(conventional-commits-filter@5.0.0) - conventional-changelog-ember: 5.0.0 - conventional-changelog-eslint: 6.0.0 - conventional-changelog-express: 5.0.0 - conventional-changelog-jquery: 6.0.0 - conventional-changelog-jshint: 5.0.0 - conventional-changelog-preset-loader: 5.0.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-filter@5.0.0: {} - - conventional-commits-parser@6.2.1: - dependencies: - meow: 13.2.0 - - convert-hrtime@5.0.0: {} - convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} @@ -18485,10 +17308,6 @@ snapshots: dependencies: uncrypto: 0.1.3 - crypto-random-string@4.0.0: - dependencies: - type-fest: 1.4.0 - css-declaration-sorter@7.3.1(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -18753,10 +17572,6 @@ snapshots: minimatch: 3.1.2 p-limit: 3.1.0 - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - dlv@1.1.3: {} dmg-builder@26.0.12(electron-builder-squirrel-windows@26.0.12): @@ -18814,10 +17629,6 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 - dot-prop@5.3.0: - dependencies: - is-obj: 2.0.0 - dotenv-expand@11.0.7: dependencies: dotenv: 16.6.1 @@ -18852,10 +17663,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - duplexer2@0.1.4: - dependencies: - readable-stream: 2.3.8 - eastasianwidth@0.2.0: {} ee-first@1.1.1: {} @@ -18960,8 +17767,6 @@ snapshots: emoji-regex@9.2.2: {} - emojilib@2.4.0: {} - emojis-list@3.0.0: {} encodeurl@2.0.0: {} @@ -18987,11 +17792,6 @@ snapshots: entities@6.0.1: {} - env-ci@11.2.0: - dependencies: - execa: 8.0.1 - java-properties: 1.0.2 - env-paths@2.2.1: {} env-paths@3.0.0: {} @@ -19467,33 +18267,6 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - execa@8.0.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - - execa@9.6.1: - dependencies: - '@sindresorhus/merge-streams': 4.0.0 - cross-spawn: 7.0.6 - figures: 6.1.0 - get-stream: 9.0.1 - human-signals: 8.0.1 - is-plain-obj: 4.1.0 - is-stream: 4.0.1 - npm-run-path: 6.0.0 - pretty-ms: 9.3.0 - signal-exit: 4.1.0 - strip-final-newline: 4.0.0 - yoctocolors: 2.1.2 - exit-x@0.2.2: {} expand-template@2.0.3: {} @@ -19592,8 +18365,6 @@ snapshots: extsprintf@1.4.1: optional: true - fast-content-type-parse@3.0.0: {} - fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -19626,18 +18397,10 @@ snapshots: optionalDependencies: picomatch: 4.0.4 - figures@2.0.0: - dependencies: - escape-string-regexp: 1.0.5 - figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 - figures@6.1.0: - dependencies: - is-unicode-supported: 2.1.0 - file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -19688,12 +18451,6 @@ snapshots: dependencies: find-file-up: 2.0.1 - find-up-simple@1.0.1: {} - - find-up@2.1.0: - dependencies: - locate-path: 2.0.0 - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -19709,11 +18466,6 @@ snapshots: locate-path: 7.2.0 path-exists: 5.0.0 - find-versions@6.0.0: - dependencies: - semver-regex: 4.0.5 - super-regex: 1.1.0 - fix-path@5.0.0: dependencies: shell-path: 3.1.0 @@ -19784,11 +18536,6 @@ snapshots: fresh@2.0.0: {} - from2@2.3.0: - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - fs-constants@1.0.0: {} fs-extra@10.1.0: @@ -19797,12 +18544,6 @@ snapshots: jsonfile: 6.2.0 universalify: 2.0.1 - fs-extra@11.3.3: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - fs-extra@11.3.5: dependencies: graceful-fs: 4.2.11 @@ -19848,8 +18589,6 @@ snapshots: function-bind@1.1.2: {} - function-timeout@1.0.2: {} - function.prototype.name@1.1.8: dependencies: call-bind: 1.0.8 @@ -19897,15 +18636,6 @@ snapshots: get-stream@6.0.1: {} - get-stream@7.0.1: {} - - get-stream@8.0.1: {} - - get-stream@9.0.1: - dependencies: - '@sec-ant/readable-stream': 0.4.1 - is-stream: 4.0.1 - get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -19916,31 +18646,6 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - git-log-parser@1.2.1: - dependencies: - argv-formatter: 1.0.0 - spawn-error-forwarder: 1.0.0 - split2: 1.0.0 - stream-combiner2: 1.1.1 - through2: 2.0.5 - traverse: 0.6.8 - - git-raw-commits@5.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1): - dependencies: - '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1) - meow: 13.2.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - - git-semver-tags@8.0.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1): - dependencies: - '@conventional-changelog/git-client': 1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.2.1) - meow: 13.2.0 - transitivePeerDependencies: - - conventional-commits-filter - - conventional-commits-parser - github-from-package@0.0.0: {} github-slugger@2.0.0: {} @@ -20048,8 +18753,6 @@ snapshots: p-cancelable: 2.1.1 responselike: 2.0.1 - graceful-fs@4.2.10: {} - graceful-fs@4.2.11: {} h3@1.15.10: @@ -20079,8 +18782,6 @@ snapshots: has-bigints@1.1.0: {} - has-flag@3.0.0: {} - has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -20235,8 +18936,6 @@ snapshots: he@1.2.0: {} - highlight.js@10.7.3: {} - hls.js@1.6.13: {} homedir-polyfill@1.0.3: @@ -20245,20 +18944,10 @@ snapshots: hono@4.12.14: {} - hook-std@4.0.0: {} - hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 - hosted-git-info@7.0.2: - dependencies: - lru-cache: 10.4.3 - - hosted-git-info@8.1.0: - dependencies: - lru-cache: 10.4.3 - hosted-git-info@9.0.2: dependencies: lru-cache: 11.2.4 @@ -20425,10 +19114,6 @@ snapshots: human-signals@2.1.0: {} - human-signals@5.0.0: {} - - human-signals@8.0.1: {} - humanize-ms@1.2.1: dependencies: ms: 2.1.3 @@ -20481,13 +19166,6 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-from-esm@2.0.0: - dependencies: - debug: 4.4.3 - import-meta-resolve: 4.2.0 - transitivePeerDependencies: - - supports-color - import-local@3.2.0: dependencies: pkg-dir: 4.2.0 @@ -20499,10 +19177,6 @@ snapshots: indent-string@4.0.0: {} - indent-string@5.0.0: {} - - index-to-position@1.2.0: {} - individual@2.0.0: {} infer-owner@1.0.4: {} @@ -20528,11 +19202,6 @@ snapshots: hasown: 2.0.3 side-channel: 1.1.0 - into-stream@7.0.0: - dependencies: - from2: 2.3.0 - p-is-promise: 3.0.0 - ip-address@10.1.0: {} ip-address@10.2.0: {} @@ -20661,8 +19330,6 @@ snapshots: is-number@7.0.0: {} - is-obj@2.0.0: {} - is-plain-obj@3.0.0: {} is-plain-obj@4.1.0: {} @@ -20692,10 +19359,6 @@ snapshots: is-stream@2.0.1: {} - is-stream@3.0.0: {} - - is-stream@4.0.1: {} - is-string@1.1.1: dependencies: call-bound: 1.0.4 @@ -20756,14 +19419,6 @@ snapshots: dependencies: ws: 8.18.0 - issue-parser@7.0.1: - dependencies: - lodash.capitalize: 4.2.1 - lodash.escaperegexp: 4.1.2 - lodash.isplainobject: 4.0.6 - lodash.isstring: 4.0.1 - lodash.uniqby: 4.7.0 - istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@6.0.3: @@ -20807,8 +19462,6 @@ snapshots: filelist: 1.0.4 picocolors: 1.1.1 - java-properties@1.0.2: {} - jest-changed-files@30.2.0: dependencies: execa: 5.1.1 @@ -21214,8 +19867,6 @@ snapshots: json-buffer@3.0.1: {} - json-parse-better-errors@1.0.2: {} - json-parse-even-better-errors@2.3.1: {} json-parse-even-better-errors@5.0.0: {} @@ -21368,13 +20019,6 @@ snapshots: '@lmdb/lmdb-win32-x64': 3.5.1 optional: true - load-json-file@4.0.0: - dependencies: - graceful-fs: 4.2.11 - parse-json: 4.0.0 - pify: 3.0.0 - strip-bom: 3.0.0 - loader-runner@4.3.1: {} loader-utils@2.0.4: @@ -21383,11 +20027,6 @@ snapshots: emojis-list: 3.0.0 json5: 2.2.3 - locate-path@2.0.0: - dependencies: - p-locate: 2.0.0 - path-exists: 3.0.0 - locate-path@5.0.0: dependencies: p-locate: 4.1.0 @@ -21400,10 +20039,6 @@ snapshots: dependencies: p-locate: 6.0.0 - lodash-es@4.18.1: {} - - lodash.capitalize@4.2.1: {} - lodash.clonedeepwith@4.5.0: {} lodash.debounce@4.0.8: {} @@ -21412,18 +20047,12 @@ snapshots: lodash.isequal@4.5.0: {} - lodash.isplainobject@4.0.6: {} - - lodash.isstring@4.0.1: {} - lodash.memoize@4.1.2: {} lodash.merge@4.6.2: {} lodash.uniq@4.5.0: {} - lodash.uniqby@4.7.0: {} - lodash@4.18.1: {} log-symbols@4.1.0: @@ -21498,12 +20127,6 @@ snapshots: '@babel/types': 7.29.0 source-map-js: 1.2.1 - make-asynchronous@1.0.1: - dependencies: - p-event: 6.0.1 - type-fest: 4.41.0 - web-worker: 1.2.0 - make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -21562,19 +20185,6 @@ snapshots: markdown-table@3.0.4: {} - marked-terminal@7.3.0(marked@15.0.12): - dependencies: - ansi-escapes: 7.2.0 - ansi-regex: 6.2.2 - chalk: 5.6.2 - cli-highlight: 2.1.11 - cli-table3: 0.6.5 - marked: 15.0.12 - node-emoji: 2.2.0 - supports-hyperlinks: 3.2.0 - - marked@15.0.12: {} - marked@18.0.5: {} material-design-icons-iconfont@6.7.0: {} @@ -21771,8 +20381,6 @@ snapshots: tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 - meow@13.2.0: {} - merge-descriptors@1.0.3: {} merge-descriptors@2.0.0: {} @@ -22068,12 +20676,8 @@ snapshots: mime@2.6.0: {} - mime@4.1.0: {} - mimic-fn@2.1.0: {} - mimic-fn@4.0.0: {} - mimic-function@5.0.1: {} mimic-response@1.0.1: {} @@ -22267,8 +20871,6 @@ snapshots: neotraverse@0.6.18: {} - nerf-dart@1.0.0: {} - ng-mocks@14.15.1(3bd9032d10655768ae17cd8d4331ec90): dependencies: '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.15.1))(rxjs@7.8.2) @@ -22311,13 +20913,6 @@ snapshots: dependencies: semver: 7.7.4 - node-emoji@2.2.0: - dependencies: - '@sindresorhus/is': 4.6.0 - char-regex: 1.0.2 - emojilib: 2.4.0 - skin-tone: 2.0.0 - node-fetch-native@1.6.7: {} node-fetch@2.7.0(encoding@0.1.13): @@ -22370,18 +20965,10 @@ snapshots: dependencies: abbrev: 4.0.0 - normalize-package-data@6.0.2: - dependencies: - hosted-git-info: 7.0.2 - semver: 7.7.4 - validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} normalize-url@6.1.0: {} - normalize-url@8.1.1: {} - npm-bundled@5.0.0: dependencies: npm-normalize-package-bin: 5.0.0 @@ -22428,17 +21015,6 @@ snapshots: dependencies: path-key: 3.1.1 - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - - npm-run-path@6.0.0: - dependencies: - path-key: 4.0.0 - unicorn-magic: 0.3.0 - - npm@10.9.4: {} - nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -22662,10 +21238,6 @@ snapshots: dependencies: mimic-fn: 2.1.0 - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - onetime@7.0.0: dependencies: mimic-function: 5.0.1 @@ -22774,22 +21346,6 @@ snapshots: p-cancelable@2.1.1: {} - p-each-series@3.0.0: {} - - p-event@6.0.1: - dependencies: - p-timeout: 6.1.4 - - p-filter@4.1.0: - dependencies: - p-map: 7.0.4 - - p-is-promise@3.0.0: {} - - p-limit@1.3.0: - dependencies: - p-try: 1.0.0 - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -22806,10 +21362,6 @@ snapshots: dependencies: yocto-queue: 1.2.2 - p-locate@2.0.0: - dependencies: - p-limit: 1.3.0 - p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -22833,10 +21385,6 @@ snapshots: eventemitter3: 5.0.1 p-timeout: 6.1.4 - p-reduce@2.1.0: {} - - p-reduce@3.0.0: {} - p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 @@ -22845,8 +21393,6 @@ snapshots: p-timeout@6.1.4: {} - p-try@1.0.0: {} - p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -22889,11 +21435,6 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 - parse-json@4.0.0: - dependencies: - error-ex: 1.3.4 - json-parse-better-errors: 1.0.2 - parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 @@ -22901,12 +21442,6 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse-json@8.3.0: - dependencies: - '@babel/code-frame': 7.27.1 - index-to-position: 1.2.0 - type-fest: 4.41.0 - parse-latin@7.0.0: dependencies: '@types/nlcst': 2.0.3 @@ -22916,8 +21451,6 @@ snapshots: unist-util-visit-children: 3.0.0 vfile: 6.0.3 - parse-ms@4.0.0: {} - parse-node-version@1.0.1: {} parse-passwd@1.0.0: {} @@ -22928,20 +21461,12 @@ snapshots: parse5: 8.0.0 parse5-sax-parser: 8.0.0 - parse5-htmlparser2-tree-adapter@6.0.1: - dependencies: - parse5: 6.0.1 - parse5-sax-parser@8.0.0: dependencies: parse5: 8.0.0 parse5@4.0.0: {} - parse5@5.1.1: {} - - parse5@6.0.1: {} - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -22952,8 +21477,6 @@ snapshots: parseurl@1.3.3: {} - path-exists@3.0.0: {} - path-exists@4.0.0: {} path-exists@5.0.0: {} @@ -22962,8 +21485,6 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} path-scurry@1.11.1: @@ -22998,8 +21519,6 @@ snapshots: pify@2.3.0: {} - pify@3.0.0: {} - pify@4.0.1: optional: true @@ -23015,11 +21534,6 @@ snapshots: dependencies: '@babel/runtime': 7.28.4 - pkg-conf@2.1.0: - dependencies: - find-up: 2.1.0 - load-json-file: 4.0.0 - pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -23349,10 +21863,6 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 - pretty-ms@9.3.0: - dependencies: - parse-ms: 4.0.0 - prismjs@1.30.0: {} proc-log@2.0.1: {} @@ -23379,8 +21889,6 @@ snapshots: property-information@7.1.0: {} - proto-list@1.2.4: {} - proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -23466,20 +21974,6 @@ snapshots: dependencies: pify: 2.3.0 - read-package-up@11.0.0: - dependencies: - find-up-simple: 1.0.1 - read-pkg: 9.0.1 - type-fest: 4.41.0 - - read-pkg@9.0.1: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 6.0.2 - parse-json: 8.3.0 - type-fest: 4.41.0 - unicorn-magic: 0.1.0 - readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -23580,10 +22074,6 @@ snapshots: unicode-match-property-ecmascript: 2.0.0 unicode-match-property-value-ecmascript: 2.2.1 - registry-auth-token@5.1.0: - dependencies: - '@pnpm/npm-conf': 2.3.1 - regjsgen@0.8.0: {} regjsparser@0.13.0: @@ -24034,47 +22524,6 @@ snapshots: '@types/node-forge': 1.3.14 node-forge: 1.4.0 - semantic-release@24.2.9(typescript@5.9.3): - dependencies: - '@semantic-release/commit-analyzer': 13.0.1(semantic-release@24.2.9(typescript@5.9.3)) - '@semantic-release/error': 4.0.0 - '@semantic-release/github': 11.0.6(semantic-release@24.2.9(typescript@5.9.3)) - '@semantic-release/npm': 12.0.2(semantic-release@24.2.9(typescript@5.9.3)) - '@semantic-release/release-notes-generator': 14.1.0(semantic-release@24.2.9(typescript@5.9.3)) - aggregate-error: 5.0.0 - cosmiconfig: 9.0.0(typescript@5.9.3) - debug: 4.4.3 - env-ci: 11.2.0 - execa: 9.6.1 - figures: 6.1.0 - find-versions: 6.0.0 - get-stream: 6.0.1 - git-log-parser: 1.2.1 - hook-std: 4.0.0 - hosted-git-info: 8.1.0 - import-from-esm: 2.0.0 - lodash-es: 4.18.1 - marked: 15.0.12 - marked-terminal: 7.3.0(marked@15.0.12) - micromatch: 4.0.8 - p-each-series: 3.0.0 - p-reduce: 3.0.0 - read-package-up: 11.0.0 - resolve-from: 5.0.0 - semver: 7.7.3 - semver-diff: 5.0.0 - signale: 1.4.0 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - - typescript - - semver-diff@5.0.0: - dependencies: - semver: 7.7.4 - - semver-regex@4.0.5: {} - semver@5.7.2: {} semver@6.3.1: {} @@ -24281,12 +22730,6 @@ snapshots: signal-exit@4.1.0: {} - signale@1.4.0: - dependencies: - chalk: 2.4.2 - figures: 2.0.0 - pkg-conf: 2.1.0 - sigstore@4.1.0: dependencies: '@sigstore/bundle': 4.0.0 @@ -24319,10 +22762,6 @@ snapshots: arg: 5.0.2 sax: 1.4.3 - skin-tone@2.0.0: - dependencies: - unicode-emoji-modifier-base: 1.0.0 - slash@3.0.0: {} slash@5.1.0: {} @@ -24401,20 +22840,8 @@ snapshots: space-separated-tokens@2.0.2: {} - spawn-error-forwarder@1.0.0: {} - - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 - spdx-exceptions@2.5.0: {} - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 - spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 @@ -24443,10 +22870,6 @@ snapshots: transitivePeerDependencies: - supports-color - split2@1.0.0: - dependencies: - through2: 2.0.5 - sprintf-js@1.0.3: {} ssri@13.0.1: @@ -24476,11 +22899,6 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 - stream-combiner2@1.1.1: - dependencies: - duplexer2: 0.1.4 - readable-stream: 2.3.8 - stream-replace-string@2.0.0: {} streamroller@3.1.5: @@ -24569,10 +22987,6 @@ snapshots: strip-final-newline@2.0.0: {} - strip-final-newline@3.0.0: {} - - strip-final-newline@4.0.0: {} - strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -24611,16 +23025,6 @@ snapshots: transitivePeerDependencies: - supports-color - super-regex@1.1.0: - dependencies: - function-timeout: 1.0.2 - make-asynchronous: 1.0.1 - time-span: 5.1.0 - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -24629,11 +23033,6 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-hyperlinks@3.2.0: - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - supports-preserve-symlinks-flag@1.0.0: {} svgo@4.0.0: @@ -24730,8 +23129,6 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - temp-dir@3.0.0: {} - temp-file@3.4.0: dependencies: async-exit-hook: 2.0.1 @@ -24742,17 +23139,6 @@ snapshots: mkdirp: 0.5.6 rimraf: 2.6.3 - tempfile@5.0.0: - dependencies: - temp-dir: 3.0.0 - - tempy@3.1.0: - dependencies: - is-stream: 3.0.0 - temp-dir: 3.0.0 - type-fest: 2.19.0 - unique-string: 3.0.0 - terser-webpack-plugin@5.3.16(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.28.1)(webpack@5.104.1(@swc/core@1.15.8(@swc/helpers@0.5.18))(esbuild@0.28.1)): dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -24790,17 +23176,8 @@ snapshots: dependencies: tslib: 2.8.1 - through2@2.0.5: - dependencies: - readable-stream: 2.3.8 - xtend: 4.0.2 - thunky@1.1.0: {} - time-span@5.1.0: - dependencies: - convert-hrtime: 5.0.0 - tiny-async-pool@1.3.0: dependencies: semver: 5.7.2 @@ -24848,8 +23225,6 @@ snapshots: dependencies: punycode: 2.3.1 - traverse@0.6.8: {} - tree-dump@1.1.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -24991,10 +23366,6 @@ snapshots: type-fest@0.21.3: {} - type-fest@1.4.0: {} - - type-fest@2.19.0: {} - type-fest@4.41.0: {} type-is@1.6.18: @@ -25082,8 +23453,6 @@ snapshots: unicode-canonical-property-names-ecmascript@2.0.1: {} - unicode-emoji-modifier-base@1.0.0: {} - unicode-match-property-ecmascript@2.0.0: dependencies: unicode-canonical-property-names-ecmascript: 2.0.1 @@ -25093,8 +23462,6 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} - unicorn-magic@0.1.0: {} - unicorn-magic@0.3.0: {} unified@11.0.5: @@ -25133,10 +23500,6 @@ snapshots: dependencies: imurmurhash: 0.1.4 - unique-string@3.0.0: - dependencies: - crypto-random-string: 4.0.0 - unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.3 @@ -25183,8 +23546,6 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - universal-user-agent@7.0.3: {} - universalify@0.1.2: {} universalify@2.0.1: {} @@ -25246,8 +23607,6 @@ snapshots: url-join@4.0.1: {} - url-join@5.0.0: {} - url-toolkit@2.2.5: {} utf8-byte-length@1.0.5: {} @@ -25268,11 +23627,6 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - validate-npm-package-name@7.0.2: {} varint@6.0.0: {} @@ -25424,8 +23778,6 @@ snapshots: web-namespaces@2.0.1: {} - web-worker@1.2.0: {} - webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} @@ -25672,8 +24024,6 @@ snapshots: xmlchars@2.2.0: {} - xtend@4.0.2: {} - xxhash-wasm@1.1.0: {} y18n@4.0.3: {} @@ -25697,8 +24047,6 @@ snapshots: camelcase: 5.3.1 decamelize: 1.2.0 - yargs-parser@20.2.9: {} - yargs-parser@21.1.1: {} yargs-parser@22.0.0: {} @@ -25717,16 +24065,6 @@ snapshots: y18n: 4.0.3 yargs-parser: 18.1.3 - yargs@16.2.0: - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - yargs@17.7.2: dependencies: cliui: 8.0.1 diff --git a/tools/release/build-release-notes.mjs b/tools/release/build-release-notes.mjs new file mode 100644 index 000000000..7f7a27de1 --- /dev/null +++ b/tools/release/build-release-notes.mjs @@ -0,0 +1,312 @@ +#!/usr/bin/env node +/** + * Composes release surfaces from the notes accumulated in `.changes/`. + * + * node tools/release/build-release-notes.mjs --validate + * node tools/release/build-release-notes.mjs --version 0.24.0 --format github + * node tools/release/build-release-notes.mjs --version 0.24.0 --format changelog + * node tools/release/build-release-notes.mjs --version 0.24.0 --format blog + * node tools/release/build-release-notes.mjs --version 0.24.0 --consume + * + * Every mode except `--consume` is a safe dry run: nothing is deleted unless + * `--consume` is passed explicitly. + */ + +import { execFileSync } from 'node:child_process'; +import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +import { loadNotes } from './release-notes.mjs'; +import { + releaseSlug, + renderBlogScaffold, + renderChangelogSection, + renderGithubBody, + upsertChangelogSection, +} from './release-notes-render.mjs'; + +const workspaceRoot = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + '../..' +); +const CHANGELOG_PATH = path.join(workspaceRoot, 'CHANGELOG.md'); +const BLOG_DIR = path.join(workspaceRoot, 'apps/website/src/content/blog'); + +/** Generated sections are inserted directly below this marker. */ +const CHANGELOG_MARKER = ''; + +const FORMATS = new Set(['github', 'changelog', 'blog']); + +function parseArgs(argv) { + const options = { + format: null, + version: null, + previous: null, + date: new Date().toISOString().slice(0, 10), + dir: '.changes', + validate: false, + consume: false, + force: false, + }; + + for (let index = 0; index < argv.length; index += 1) { + const arg = argv[index]; + const takeValue = () => { + const value = argv[index + 1]; + + if (value === undefined || value.startsWith('--')) { + throw new Error(`${arg} requires a value`); + } + + index += 1; + return value; + }; + + switch (arg) { + case '--format': + options.format = takeValue(); + break; + case '--version': + options.version = takeValue(); + break; + case '--previous': + options.previous = takeValue(); + break; + case '--date': + options.date = takeValue(); + break; + case '--dir': + options.dir = takeValue(); + break; + case '--validate': + options.validate = true; + break; + case '--consume': + options.consume = true; + break; + case '--force': + options.force = true; + break; + default: + throw new Error(`unknown argument: ${arg}`); + } + } + + return options; +} + +function git(args) { + return execFileSync('git', args, { + cwd: workspaceRoot, + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'ignore'], + }).trim(); +} + +/** + * Resolves each note to the commit that added it, and to a PR number when the + * commit subject carries one. Authors never write a PR number themselves — + * they cannot know it while the branch is still local. + * + * @param {object[]} notes + * @returns {Map} + */ +function resolveLinks(notes) { + const links = new Map(); + + for (const note of notes) { + let output = ''; + + try { + output = git([ + 'log', + '--diff-filter=A', + '--format=%H%x00%s', + '-1', + '--', + note.sourcePath, + ]); + } catch { + // Not a git checkout, or the note is not committed yet. Entries + // simply render without a reference link. + } + + if (!output) { + continue; + } + + const [commit, subject = ''] = output.split('\0'); + const prMatch = subject.match(/\(#(\d+)\)\s*$/); + + links.set(note.sourcePath, { + commit, + pr: prMatch ? Number(prMatch[1]) : undefined, + }); + } + + return links; +} + +/** Latest `v*` tag, used for the CHANGELOG compare link. */ +function detectPreviousVersion() { + try { + return git(['describe', '--tags', '--abbrev=0', '--match=v*']).replace( + /^v/, + '' + ); + } catch { + return null; + } +} + +/** + * The release version is the one in the root package.json — bumping it is the + * deliberate act that starts a release. `--version` stays available as an + * override (dry runs, previewing a version before the bump), but the default + * keeps a single source of truth and lets the package scripts run bare. + */ +function resolveVersion(options) { + let version = options.version; + + if (!version) { + version = JSON.parse( + readFileSync(path.join(workspaceRoot, 'package.json'), 'utf8') + ).version; + + // stderr, so `--format github` keeps a clean pipeable stdout. + console.error(`Using version ${version} from package.json.`); + } + + if (!/^\d+\.\d+\.\d+$/.test(version)) { + throw new Error( + `version must be a bare semver like 0.24.0, got "${version}"` + ); + } + + return version; +} + +function writeChangelog(section, version) { + const { content, replaced } = upsertChangelogSection( + readFileSync(CHANGELOG_PATH, 'utf8'), + section, + version, + CHANGELOG_MARKER + ); + + if (replaced) { + console.error(`Replacing existing CHANGELOG.md section for ${version}.`); + } + + writeFileSync(CHANGELOG_PATH, content, 'utf8'); + + return CHANGELOG_PATH; +} + +function writeBlogScaffold(content, version, force) { + const target = path.join( + BLOG_DIR, + `${releaseSlug(version)}-release-notes.mdx` + ); + + if (existsSync(target) && !force) { + throw new Error( + [ + `${path.relative(workspaceRoot, target)} already exists.`, + 'The website publishes one post per minor version, so a patch', + 'release edits the existing post instead of creating a new one.', + 'Pass --force only to regenerate it from scratch.', + ].join(' ') + ); + } + + writeFileSync(target, content, 'utf8'); + + return target; +} + +function main() { + const options = parseArgs(process.argv.slice(2)); + const notesDir = path.resolve(workspaceRoot, options.dir); + const { notes, errors } = loadNotes(notesDir); + + if (errors.length > 0) { + console.error('Invalid release notes:\n'); + for (const error of errors) { + console.error(` ${error}`); + } + console.error( + '\nSee .changes/README.md for the expected format.' + ); + process.exit(1); + } + + if (options.validate) { + console.log(`${notes.length} release note(s) valid.`); + } + + if (options.format) { + if (!FORMATS.has(options.format)) { + throw new Error( + `unknown --format "${options.format}" (expected ${[...FORMATS].join(', ')})` + ); + } + + const version = resolveVersion(options); + const links = resolveLinks(notes); + + if (notes.length === 0) { + throw new Error( + `no notes found in ${path.relative(workspaceRoot, notesDir)}/ — nothing to render` + ); + } + + if (options.format === 'github') { + process.stdout.write(`${renderGithubBody(notes, { links })}\n`); + } + + if (options.format === 'changelog') { + const section = renderChangelogSection(notes, { + version, + date: options.date, + previousVersion: options.previous ?? detectPreviousVersion(), + links, + }); + const target = writeChangelog(section, version); + console.log(`Updated ${path.relative(workspaceRoot, target)}`); + } + + if (options.format === 'blog') { + const content = renderBlogScaffold(notes, { + version, + date: options.date, + links, + }); + const target = writeBlogScaffold(content, version, options.force); + console.log(`Wrote ${path.relative(workspaceRoot, target)}`); + } + } + + if (options.consume) { + for (const note of notes) { + rmSync(note.sourcePath); + } + + console.log(`Removed ${notes.length} consumed note(s).`); + } + + if (!options.format && !options.validate && !options.consume) { + throw new Error( + 'nothing to do — pass --validate, --format , or --consume' + ); + } +} + +try { + main(); +} catch (error) { + console.error(error.message); + process.exit(1); +} diff --git a/tools/release/extract-changelog-section.mjs b/tools/release/extract-changelog-section.mjs new file mode 100644 index 000000000..65a5aa697 --- /dev/null +++ b/tools/release/extract-changelog-section.mjs @@ -0,0 +1,99 @@ +#!/usr/bin/env node +/** + * Prints the CHANGELOG.md section for one version to stdout. + * + * node tools/release/extract-changelog-section.mjs 0.24.0 + * + * Used by the tag-build release job to put the authored notes into the + * GitHub release body. `.changes/*.md` files are consumed before the tag + * exists, so at tag time the changelog section IS the authored source of + * truth — this reads what the generator already wrote. + * + * Exits non-zero when the section is missing so a forgotten + * `release:notes:changelog` fails the release instead of silently shipping + * PR-title-only notes. + */ + +import { readFileSync } from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const workspaceRoot = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + '../..' +); + +/** + * @param {string} changelog full CHANGELOG.md content + * @param {string} version bare semver, e.g. `0.24.0` + * @returns {string | null} section body without its own H1 heading + */ +export function extractSection(changelog, version) { + const lines = changelog.replace(/\r\n/g, '\n').split('\n'); + // The CLI validates its argument, but this function is exported on its + // own — escape every regex metacharacter rather than only dots so no + // caller can inject pattern syntax. + const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + // Matches both heading shapes used in this file: + // # [0.24.0](compare-url) (2026-08-01) + // # 0.24.0 (2026-08-01) + const headingPattern = new RegExp( + `^#\\s+\\[?${escapedVersion}\\]?\\s*[( ]` + ); + const start = lines.findIndex((line) => headingPattern.test(line)); + + if (start === -1) { + return null; + } + + let end = lines.length; + + for (let index = start + 1; index < lines.length; index += 1) { + if (/^#\s/.test(lines[index])) { + end = index; + break; + } + } + + return lines.slice(start + 1, end).join('\n').trim(); +} + +function main() { + const version = process.argv[2]; + + if (!version || !/^\d+\.\d+\.\d+$/.test(version)) { + console.error( + 'Usage: extract-changelog-section.mjs (for example 0.24.0)' + ); + process.exit(2); + } + + const changelogPath = path.join(workspaceRoot, 'CHANGELOG.md'); + const section = extractSection(readFileSync(changelogPath, 'utf8'), version); + + if (section === null) { + console.error( + [ + `CHANGELOG.md has no section for ${version}.`, + 'The release flow writes it before tagging:', + ' pnpm run release:notes:changelog', + ' node tools/release/build-release-notes.mjs --consume', + 'Commit the changelog, then re-tag.', + ].join('\n') + ); + process.exit(1); + } + + if (section === '') { + console.error(`CHANGELOG.md section for ${version} is empty.`); + process.exit(1); + } + + process.stdout.write(`${section}\n`); +} + +// Allow importing extractSection from tests without running the CLI. +if (process.argv[1] === fileURLToPath(import.meta.url)) { + main(); +} diff --git a/tools/release/project.json b/tools/release/project.json new file mode 100644 index 000000000..d3d47110b --- /dev/null +++ b/tools/release/project.json @@ -0,0 +1,32 @@ +{ + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "name": "release-tools", + "projectType": "library", + "sourceRoot": "tools/release", + "targets": { + "test": { + "executor": "nx:run-commands", + "cache": true, + "inputs": [ + "{workspaceRoot}/tools/release/release-notes.mjs", + "{workspaceRoot}/tools/release/release-notes-render.mjs", + "{workspaceRoot}/tools/release/extract-changelog-section.mjs", + "{workspaceRoot}/tools/release/release-notes.test.mjs" + ], + "options": { + "command": "node --test tools/release/release-notes.test.mjs", + "cwd": "{workspaceRoot}" + } + }, + "lint": { + "inputs": [ + "default", + "{workspaceRoot}/eslint.config.mjs", + "{workspaceRoot}/tools/eslint-rules/**/*", + "{workspaceRoot}/tools/eslint/**/*" + ], + "command": "eslint \"tools/release/*.mjs\"" + } + }, + "tags": ["scope:tools", "domain:release", "type:tool"] +} diff --git a/tools/release/release-notes-render.mjs b/tools/release/release-notes-render.mjs new file mode 100644 index 000000000..a8e4006b4 --- /dev/null +++ b/tools/release/release-notes-render.mjs @@ -0,0 +1,324 @@ +/** + * Renderers turning grouped `.changes/*.md` notes into the three release + * surfaces: the GitHub release body, the CHANGELOG.md section, and the + * website blog scaffold. + */ + +import { extractSection } from './extract-changelog-section.mjs'; +import { groupNotes, REPO_URL } from './release-notes.mjs'; + +const MONTHS = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +/** + * @param {string} isoDate `YYYY-MM-DD` + * @returns {string} e.g. `August 1, 2026` + */ +export function formatLongDate(isoDate) { + const [year, month, day] = isoDate.split('-').map(Number); + + return `${MONTHS[month - 1]} ${day}, ${year}`; +} + +/** + * Deliberately minor-scoped: the website publishes one release post per minor + * version (`v0-18` … `v0-22`), and its screenshot assets live under the same + * directory. A patch release therefore reuses its minor's post rather than + * starting a new one. + * + * @param {string} version + * @returns {string} e.g. `v0-24` for both `0.24.0` and `0.24.1` + */ +export function releaseSlug(version) { + const [major, minor] = version.split('.'); + + return `v${major}-${minor}`; +} + +/** Collapses a note body to a single line for list entries. */ +function oneLine(body) { + return body.replace(/\s+/g, ' ').trim(); +} + +/** Trims to a word boundary; used for image alt text, never for prose. */ +function truncate(text, max) { + if (text.length <= max) { + return text; + } + + const cut = text.slice(0, max); + const lastSpace = cut.lastIndexOf(' '); + + return `${(lastSpace > max / 2 ? cut.slice(0, lastSpace) : cut).trimEnd()}…`; +} + +/** + * MDX parses `<` and `{` as markup. Note bodies are plain prose written by + * humans and agents, so escape them rather than letting a stray character + * break the website build. The closing counterparts are escaped too, so a + * body like `` renders as written instead of half-escaped. + */ +function escapeMdx(text) { + return text + .replace(//g, '>') + .replace(/\{/g, '{') + .replace(/\}/g, '}'); +} + +/** + * @param {object} note + * @param {Map} links + * @returns {string} trailing `([#123](url), closes [#45](url))` or '' + */ +function formatReferences(note, links) { + const parts = []; + const link = links.get(note.sourcePath); + + if (link?.pr) { + parts.push(`[#${link.pr}](${REPO_URL}/pull/${link.pr})`); + } else if (link?.commit) { + parts.push( + `[${link.commit.slice(0, 7)}](${REPO_URL}/commit/${link.commit})` + ); + } + + for (const issue of note.issues) { + parts.push(`closes [#${issue}](${REPO_URL}/issues/${issue})`); + } + + return parts.length > 0 ? ` (${parts.join(', ')})` : ''; +} + +function formatEntry(note, links) { + return `- **${note.area}** — ${oneLine(note.body)}${formatReferences(note, links)}`; +} + +/** + * GitHub release body. `internal` notes are omitted: the release page is read + * by users, and GitHub still appends its own full commit list below. + * + * @param {object[]} notes + * @param {{ links?: Map }} [options] + * @returns {string} + */ +export function renderGithubBody(notes, { links = new Map() } = {}) { + const sections = groupNotes(notes) + .filter((group) => group.type !== 'internal') + .map((group) => { + const entries = group.notes + .map((note) => formatEntry(note, links)) + .join('\n'); + + return `## ${group.heading}\n\n${entries}`; + }); + + return sections.join('\n\n'); +} + +/** + * CHANGELOG.md section. Unlike the release body this keeps `internal` notes, + * collapsed, so the file stays a complete record. + * + * @param {object[]} notes + * @param {{ version: string, date: string, previousVersion?: string | null, links?: Map }} options + * @returns {string} + */ +export function renderChangelogSection( + notes, + { version, date, previousVersion = null, links = new Map() } +) { + const heading = previousVersion + ? `# [${version}](${REPO_URL}/compare/v${previousVersion}...v${version}) (${date})` + : `# ${version} (${date})`; + + const blocks = [heading]; + + for (const group of groupNotes(notes)) { + const entries = group.notes + .map((note) => formatEntry(note, links)) + .join('\n'); + + if (group.type === 'internal') { + blocks.push( + `
\nInternal changes\n\n${entries}\n\n
` + ); + continue; + } + + blocks.push(`### ${group.heading}\n\n${entries}`); + } + + return `${blocks.join('\n\n')}\n`; +} + +/** + * Inserts a version section below the marker, replacing any existing section + * for the same version — rerunning `--format changelog` after correcting a + * note must not prepend a duplicate. + * + * @param {string} changelog full CHANGELOG.md content + * @param {string} section rendered section (from renderChangelogSection) + * @param {string} version bare semver the section describes + * @param {string} marker insertion marker line + * @returns {{ content: string, replaced: boolean }} + */ +export function upsertChangelogSection(changelog, section, version, marker) { + if (!changelog.includes(marker)) { + throw new Error( + `changelog is missing the \`${marker}\` marker that new sections are inserted below` + ); + } + + let current = changelog; + const replaced = extractSection(current, version) !== null; + + if (replaced) { + const lines = current.split('\n'); + const headingIndex = lines.findIndex( + (line) => + line.startsWith(`# [${version}]`) || + line.startsWith(`# ${version} `) + ); + let end = lines.length; + + for (let index = headingIndex + 1; index < lines.length; index += 1) { + if (/^#\s/.test(lines[index])) { + end = index; + break; + } + } + + current = [...lines.slice(0, headingIndex), ...lines.slice(end)].join( + '\n' + ); + } + + // Rebuild around the marker instead of string-replacing into it, so the + // blank-line count on both sides of the section stays exact regardless of + // whether a removal just happened. + const markerIndex = current.indexOf(marker); + const before = current.slice(0, markerIndex); + const after = current + .slice(markerIndex + marker.length) + .replace(/^\n+/, ''); + + return { + content: `${before}${marker}\n\n${section.trim()}\n\n${after}`, + replaced, + }; +} + +/** + * Blog entries carrying a `screenshot:` slug become their own subsection with + * an image slider; the rest stay bullets. + */ +function renderBlogGroup(group, { slug, links }) { + const bullets = group.notes.filter((note) => !note.screenshot); + const featured = group.notes.filter((note) => note.screenshot); + const blocks = [`## ${group.heading}`]; + + if (bullets.length > 0) { + blocks.push( + bullets + .map( + (note) => + `- **${note.area}** — ${escapeMdx(oneLine(note.body))}${formatReferences(note, links)}` + ) + .join('\n') + ); + } + + for (const note of featured) { + // The heading is editorial work — a note body makes a terrible one. + // Leave a visible TODO instead of pretending otherwise; the whole + // scaffold ships as `draft: true` anyway. + // Embedded in a single-quoted JS string inside MDX. Backslashes must + // be escaped before apostrophes, or a body ending in `\` produces an + // unterminated string and breaks the website build. + const alt = truncate(oneLine(note.body), 120) + .replace(/\\/g, '\\\\') + .replace(/'/g, "\\'"); + const images = ['dark', 'light'] + .map( + (theme) => + ` {\n src: '/iptvnator/blog/${slug}/screenshots/${note.screenshot}-${theme}.png',\n alt: '${alt}',\n },` + ) + .join('\n'); + + blocks.push(`### TODO headline (${note.area})`); + blocks.push( + `${escapeMdx(oneLine(note.body))}${formatReferences(note, links)}` + ); + blocks.push(``); + } + + return blocks.join('\n\n'); +} + +/** + * Scaffold for `apps/website/src/content/blog/v0-24-release-notes.mdx`. + * Deliberately incomplete: `draft: true`, TODO markers for the narrative and + * description. The prose is editorial work, only the inventory is mechanical. + * + * @param {object[]} notes + * @param {{ version: string, date: string, links?: Map }} options + * @returns {string} + */ +export function renderBlogScaffold(notes, { version, date, links = new Map() }) { + const slug = releaseSlug(version); + const shortVersion = slug.replace('-', '.'); + const sections = groupNotes(notes) + .filter((group) => group.type !== 'internal') + .map((group) => renderBlogGroup(group, { slug, links })); + + const frontmatter = [ + '---', + `title: ${shortVersion} - Release Notes`, + 'description: TODO — one sentence naming the two or three headline changes.', + 'featured: true', + `pubDate: ${date}`, + 'author: 4gray', + `heroImage: /iptvnator/blog/${slug}/hero.jpg`, + 'tags:', + ' - release', + ' - release-notes', + ` - ${shortVersion}`, + 'draft: true', + '---', + ].join('\n'); + + const imports = [ + "import BlogImageSlider from '../../components/blog/BlogImageSlider.astro';", + "import ReleaseMeta from '../../components/blog/ReleaseMeta.astro';", + ].join('\n'); + + const meta = [ + '', + ].join('\n'); + + return [ + frontmatter, + imports, + '{/* TODO: narrative intro — what this release is about, not what it contains. */}', + meta, + ...sections, + '', + ].join('\n\n'); +} diff --git a/tools/release/release-notes.mjs b/tools/release/release-notes.mjs new file mode 100644 index 000000000..8f50c4027 --- /dev/null +++ b/tools/release/release-notes.mjs @@ -0,0 +1,260 @@ +/** + * Parsing and validation for `.changes/*.md` release notes. + * + * One file per user-visible change, written by the PR author while the + * context is still fresh. The generator (build-release-notes.mjs) turns the + * accumulated files into the GitHub release body, the CHANGELOG.md section, + * and the website blog scaffold. + * + * Deliberately dependency-free: a hand-rolled parser for this tiny, closed + * schema is more predictable than a YAML engine, and it can reject unknown + * keys — which is what catches agent typos. + */ + +import { readdirSync, readFileSync } from 'node:fs'; +import path from 'node:path'; + +export const REPO_URL = 'https://github.com/4gray/iptvnator'; + +/** Render order. `internal` is last and is excluded from user-facing output. */ +export const NOTE_TYPES = ['breaking', 'feature', 'fix', 'perf', 'internal']; + +export const TYPE_HEADINGS = { + breaking: 'Breaking changes', + feature: 'Features', + fix: 'Fixes', + perf: 'Performance', + internal: 'Internal', +}; + +const KNOWN_KEYS = new Set(['type', 'area', 'issues', 'screenshot']); +const SLUG_PATTERN = /^[a-z0-9][a-z0-9-]*$/; +const DELIMITER = '---'; + +/** Keeps entries to a sentence or three; essays belong in the blog post. */ +const MAX_BODY_LENGTH = 400; + +/** + * Splits a note into its frontmatter lines and body. + * + * @param {string} content raw file content + * @returns {{ frontmatterLines: string[], body: string }} + */ +function splitFrontmatter(content) { + const lines = content.replace(/\r\n/g, '\n').split('\n'); + + if (lines[0]?.trim() !== DELIMITER) { + throw new Error('missing opening `---` frontmatter delimiter'); + } + + const closingIndex = lines.findIndex( + (line, index) => index > 0 && line.trim() === DELIMITER + ); + + if (closingIndex === -1) { + throw new Error('missing closing `---` frontmatter delimiter'); + } + + return { + frontmatterLines: lines.slice(1, closingIndex), + body: lines.slice(closingIndex + 1).join('\n').trim(), + }; +} + +/** + * Parses a single `key: value` frontmatter line. + * + * Trailing `# comment` text is stripped: no value in this schema (enum slug, + * area slug, issue numbers) can legitimately contain `#`, and the documented + * examples carry explanatory comments. + * + * @param {string} line + * @returns {[string, string] | null} key/value pair, or null for blank lines + */ +function parseFrontmatterLine(line) { + const withoutComment = line.replace(/\s+#.*$/, '').trim(); + + if (!withoutComment) { + return null; + } + + const separatorIndex = withoutComment.indexOf(':'); + + if (separatorIndex === -1) { + throw new Error(`frontmatter line is not \`key: value\`: "${line.trim()}"`); + } + + const key = withoutComment.slice(0, separatorIndex).trim(); + const value = withoutComment + .slice(separatorIndex + 1) + .trim() + .replace(/^['"]|['"]$/g, ''); + + return [key, value]; +} + +/** + * @param {string} value e.g. `[1187, 1188]` or `1187` + * @returns {number[]} + */ +function parseIssueList(value) { + const inner = value.startsWith('[') ? value.replace(/^\[|\]$/g, '') : value; + + return inner + .split(',') + .map((entry) => entry.trim().replace(/^#/, '')) + .filter(Boolean) + .map((entry) => Number(entry)); +} + +/** + * Parses a note file into a structured record. Shape errors throw; semantic + * errors are reported by validateNote() so a run can list every problem at + * once instead of failing on the first one. + * + * @param {string} content + * @param {string} sourcePath path used in error messages and PR resolution + * @returns {{ type: string, area: string, issues: number[], screenshot: string | null, body: string, sourcePath: string }} + */ +export function parseNote(content, sourcePath) { + const { frontmatterLines, body } = splitFrontmatter(content); + const fields = new Map(); + + for (const line of frontmatterLines) { + const parsed = parseFrontmatterLine(line); + + if (!parsed) { + continue; + } + + const [key, value] = parsed; + + if (fields.has(key)) { + throw new Error(`duplicate frontmatter key: \`${key}\``); + } + + fields.set(key, value); + } + + return { + type: fields.get('type') ?? '', + area: fields.get('area') ?? '', + issues: fields.has('issues') ? parseIssueList(fields.get('issues')) : [], + screenshot: fields.get('screenshot') ?? null, + unknownKeys: [...fields.keys()].filter((key) => !KNOWN_KEYS.has(key)), + body, + sourcePath, + }; +} + +/** + * @param {ReturnType} note + * @returns {string[]} human-readable problems, empty when the note is valid + */ +export function validateNote(note) { + const errors = []; + + if (!note.type) { + errors.push('`type` is required'); + } else if (!NOTE_TYPES.includes(note.type)) { + errors.push( + `unknown \`type\`: "${note.type}" (expected one of ${NOTE_TYPES.join(', ')})` + ); + } + + if (!note.area) { + errors.push('`area` is required (use the conventional-commit scope)'); + } else if (!SLUG_PATTERN.test(note.area)) { + errors.push(`\`area\` must be a lowercase slug, got "${note.area}"`); + } + + if (!note.body) { + errors.push('body is empty — describe the change for a user'); + } else if (note.body.length > MAX_BODY_LENGTH) { + errors.push( + `body is ${note.body.length} characters, max ${MAX_BODY_LENGTH} — keep it to a few sentences and put detail in the blog post` + ); + } + + for (const issue of note.issues) { + if (!Number.isInteger(issue) || issue <= 0) { + errors.push(`\`issues\` must be positive integers, got "${issue}"`); + } + } + + if (note.screenshot !== null && !SLUG_PATTERN.test(note.screenshot)) { + errors.push( + `\`screenshot\` must be a lowercase slug from the screenshot manifest, got "${note.screenshot}"` + ); + } + + for (const key of note.unknownKeys) { + errors.push( + `unknown frontmatter key: \`${key}\` (expected ${[...KNOWN_KEYS].join(', ')})` + ); + } + + return errors; +} + +/** + * Reads and parses every note in a directory, sorted by filename so output + * ordering is stable across machines. + * + * @param {string} directory + * @returns {{ notes: object[], errors: string[] }} + */ +export function loadNotes(directory) { + let entries = []; + + try { + entries = readdirSync(directory); + } catch (error) { + if (error.code === 'ENOENT') { + return { notes: [], errors: [] }; + } + + throw error; + } + + const files = entries + .filter((name) => name.endsWith('.md') && name !== 'README.md') + .sort(); + + const notes = []; + const errors = []; + + for (const name of files) { + const sourcePath = path.join(directory, name); + + try { + const note = parseNote(readFileSync(sourcePath, 'utf8'), sourcePath); + const problems = validateNote(note); + + if (problems.length > 0) { + errors.push(...problems.map((problem) => `${name}: ${problem}`)); + continue; + } + + notes.push(note); + } catch (error) { + errors.push(`${name}: ${error.message}`); + } + } + + return { notes, errors }; +} + +/** + * Groups notes by type in render order, dropping empty groups. + * + * @param {object[]} notes + * @returns {{ type: string, heading: string, notes: object[] }[]} + */ +export function groupNotes(notes) { + return NOTE_TYPES.map((type) => ({ + type, + heading: TYPE_HEADINGS[type], + notes: notes.filter((note) => note.type === type), + })).filter((group) => group.notes.length > 0); +} diff --git a/tools/release/release-notes.test.mjs b/tools/release/release-notes.test.mjs new file mode 100644 index 000000000..6445d5f59 --- /dev/null +++ b/tools/release/release-notes.test.mjs @@ -0,0 +1,517 @@ +import assert from 'node:assert/strict'; +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; +import { after, describe, it } from 'node:test'; + +import { + groupNotes, + loadNotes, + parseNote, + validateNote, +} from './release-notes.mjs'; +import { + formatLongDate, + releaseSlug, + renderBlogScaffold, + renderChangelogSection, + renderGithubBody, + upsertChangelogSection, +} from './release-notes-render.mjs'; +import { extractSection } from './extract-changelog-section.mjs'; + +const tempDirs = []; + +function makeNotesDir(files) { + const directory = mkdtempSync(path.join(tmpdir(), 'release-notes-')); + tempDirs.push(directory); + + for (const [name, content] of Object.entries(files)) { + writeFileSync(path.join(directory, name), content, 'utf8'); + } + + return directory; +} + +function note(overrides = {}) { + return { + type: 'feature', + area: 'playback', + issues: [], + screenshot: null, + unknownKeys: [], + body: 'Series now show an Up Next rail beside the player.', + sourcePath: '.changes/playback-up-next.md', + ...overrides, + }; +} + +after(() => { + for (const directory of tempDirs) { + rmSync(directory, { recursive: true, force: true }); + } +}); + +describe('parseNote', () => { + it('parses frontmatter, issue list and body', () => { + const parsed = parseNote( + [ + '---', + 'type: feature', + 'area: playback', + 'issues: [1187, 1188]', + 'screenshot: up-next-rail', + '---', + '', + 'Series now show an Up Next rail.', + '', + ].join('\n'), + '.changes/playback-up-next.md' + ); + + assert.equal(parsed.type, 'feature'); + assert.equal(parsed.area, 'playback'); + assert.deepEqual(parsed.issues, [1187, 1188]); + assert.equal(parsed.screenshot, 'up-next-rail'); + assert.equal(parsed.body, 'Series now show an Up Next rail.'); + assert.deepEqual(parsed.unknownKeys, []); + }); + + it('strips trailing comments and quotes, and accepts a bare issue', () => { + const parsed = parseNote( + [ + '---', + 'type: fix # one of feature | fix | perf', + "area: 'm3u'", + 'issues: 1204', + '---', + 'Playlists with very long URLs parse again.', + ].join('\n'), + 'x.md' + ); + + assert.equal(parsed.type, 'fix'); + assert.equal(parsed.area, 'm3u'); + assert.deepEqual(parsed.issues, [1204]); + }); + + it('records unknown keys instead of dropping them silently', () => { + const parsed = parseNote( + ['---', 'type: fix', 'area: m3u', 'scope: m3u', '---', 'Body.'].join( + '\n' + ), + 'x.md' + ); + + assert.deepEqual(parsed.unknownKeys, ['scope']); + }); + + it('rejects a missing or unterminated frontmatter block', () => { + assert.throws( + () => parseNote('type: fix\nBody.', 'x.md'), + /missing opening/ + ); + assert.throws( + () => parseNote('---\ntype: fix\nBody.', 'x.md'), + /missing closing/ + ); + }); + + it('rejects duplicate keys', () => { + assert.throws( + () => + parseNote( + ['---', 'type: fix', 'type: feature', '---', 'Body.'].join( + '\n' + ), + 'x.md' + ), + /duplicate frontmatter key/ + ); + }); +}); + +describe('validateNote', () => { + it('accepts a well-formed note', () => { + assert.deepEqual(validateNote(note()), []); + }); + + it('rejects an unknown type', () => { + const errors = validateNote(note({ type: 'chore' })); + + assert.equal(errors.length, 1); + assert.match(errors[0], /unknown `type`: "chore"/); + }); + + it('rejects an unknown frontmatter key', () => { + const errors = validateNote(note({ unknownKeys: ['scope'] })); + + assert.match(errors[0], /unknown frontmatter key: `scope`/); + }); + + it('rejects an empty body and an essay', () => { + assert.match(validateNote(note({ body: '' }))[0], /body is empty/); + assert.match( + validateNote(note({ body: 'x'.repeat(401) }))[0], + /max 400/ + ); + }); + + it('rejects a non-slug area and screenshot', () => { + assert.match( + validateNote(note({ area: 'Playback Engine' }))[0], + /`area` must be a lowercase slug/ + ); + assert.match( + validateNote(note({ screenshot: 'Up Next' }))[0], + /`screenshot` must be a lowercase slug/ + ); + }); + + it('rejects non-numeric issues', () => { + assert.match( + validateNote(note({ issues: [Number.NaN] }))[0], + /`issues` must be positive integers/ + ); + }); +}); + +describe('loadNotes', () => { + it('returns an empty result for a missing directory', () => { + const result = loadNotes(path.join(tmpdir(), 'definitely-not-here-9d3f')); + + assert.deepEqual(result, { notes: [], errors: [] }); + }); + + it('skips README.md and reports per-file errors', () => { + const directory = makeNotesDir({ + 'README.md': '# How to write notes', + 'a-good.md': '---\ntype: fix\narea: m3u\n---\nParses again.', + 'b-bad.md': '---\ntype: chore\narea: m3u\n---\nNope.', + }); + + const { notes, errors } = loadNotes(directory); + + assert.equal(notes.length, 1); + assert.equal(notes[0].area, 'm3u'); + assert.equal(errors.length, 1); + assert.match(errors[0], /^b-bad\.md: unknown `type`/); + }); + + it('sorts notes by filename for stable output', () => { + const directory = makeNotesDir({ + 'z-last.md': '---\ntype: fix\narea: zzz\n---\nLast.', + 'a-first.md': '---\ntype: fix\narea: aaa\n---\nFirst.', + }); + + assert.deepEqual( + loadNotes(directory).notes.map((entry) => entry.area), + ['aaa', 'zzz'] + ); + }); +}); + +describe('groupNotes', () => { + it('orders groups by severity and drops empty ones', () => { + const grouped = groupNotes([ + note({ type: 'fix' }), + note({ type: 'breaking' }), + note({ type: 'feature' }), + ]); + + assert.deepEqual( + grouped.map((group) => group.type), + ['breaking', 'feature', 'fix'] + ); + }); +}); + +describe('renderGithubBody', () => { + it('groups entries, prefixes the area and links the PR', () => { + const links = new Map([ + ['.changes/playback-up-next.md', { commit: 'abc1234', pr: 1231 }], + ]); + + const body = renderGithubBody([note({ issues: [1187] })], { links }); + + assert.match(body, /^## Features\n\n- \*\*playback\*\* — Series now/); + assert.match(body, /\[#1231\]\(https:\/\/github\.com\/4gray\/iptvnator\/pull\/1231\)/); + assert.match(body, /closes \[#1187\]/); + }); + + it('falls back to a commit link when the note carries no PR', () => { + const links = new Map([ + ['.changes/playback-up-next.md', { commit: 'abcdef1234567' }], + ]); + + assert.match(renderGithubBody([note()], { links }), /\[abcdef1\]\(.*\/commit\/abcdef1234567\)/); + }); + + it('omits internal notes from the user-facing body', () => { + const body = renderGithubBody([ + note({ type: 'internal', body: 'Split the store feature.' }), + note(), + ]); + + assert.match(body, /## Features/); + assert.doesNotMatch(body, /Internal|Split the store feature/); + }); +}); + +describe('renderChangelogSection', () => { + it('links the compare range when a previous version is known', () => { + const section = renderChangelogSection([note()], { + version: '0.24.0', + date: '2026-08-01', + previousVersion: '0.23.0', + }); + + assert.match( + section, + /^# \[0\.24\.0\]\(https:\/\/github\.com\/4gray\/iptvnator\/compare\/v0\.23\.0\.\.\.v0\.24\.0\) \(2026-08-01\)/ + ); + }); + + it('keeps internal notes but collapses them', () => { + const section = renderChangelogSection( + [note(), note({ type: 'internal', body: 'Split the store.' })], + { version: '0.24.0', date: '2026-08-01' } + ); + + assert.match(section, /### Features/); + assert.match(section, /Internal changes<\/summary>/); + assert.match(section, /Split the store\./); + }); +}); + +describe('renderBlogScaffold', () => { + it('emits a draft with TODO markers and a release meta block', () => { + const content = renderBlogScaffold([note()], { + version: '0.24.0', + date: '2026-08-01', + }); + + assert.match(content, /^---\ntitle: v0\.24 - Release Notes/); + assert.match(content, /draft: true/); + assert.match(content, /TODO/); + assert.match(content, /releaseDate="August 1, 2026"/); + }); + + it('gives screenshot notes their own section with a dark/light slider', () => { + const content = renderBlogScaffold( + [note({ screenshot: 'up-next-rail' })], + { version: '0.24.0', date: '2026-08-01' } + ); + + assert.match(content, /### TODO headline \(playback\)/); + assert.match( + content, + /\/iptvnator\/blog\/v0-24\/screenshots\/up-next-rail-dark\.png/ + ); + assert.match( + content, + /\/iptvnator\/blog\/v0-24\/screenshots\/up-next-rail-light\.png/ + ); + }); + + it('truncates a long body for image alt text without cutting mid-word', () => { + const body = `${'Series show the rest of the season beside the player '.repeat(4)}now.`; + const content = renderBlogScaffold( + [note({ body, screenshot: 'up-next-rail' })], + { version: '0.24.0', date: '2026-08-01' } + ); + const alt = content.match(/alt: '([^']*)'/)[1]; + + assert.ok(alt.length <= 121, `alt was ${alt.length} characters`); + assert.match(alt, /…$/); + assert.doesNotMatch(alt, /\s…$/); + }); + + it('escapes backslashes and apostrophes inside the alt string literal', () => { + const content = renderBlogScaffold( + [ + note({ + body: "Windows paths like C:\\Users no longer break the app's import.", + screenshot: 'windows-import', + }), + ], + { version: '0.24.0', date: '2026-08-01' } + ); + const alt = content.match(/alt: '(.*)',/)[1]; + + assert.match(alt, /C:\\\\Users/); + assert.match(alt, /app\\'s/); + // An odd number of trailing backslashes would escape the closing quote. + assert.doesNotMatch(alt, /(^|[^\\])(\\\\)*\\$/); + }); + + it('escapes characters MDX would parse as markup', () => { + const content = renderBlogScaffold( + [note({ body: 'Channels named and {vod} now sort correctly.' })], + { version: '0.24.0', date: '2026-08-01' } + ); + + assert.doesNotMatch(content, //); + assert.doesNotMatch(content, /\{vod\}/); + assert.match(content, /<live>/); + assert.match(content, /{vod}/); + }); + + it('imports only the components it emits', () => { + const content = renderBlogScaffold([note()], { + version: '0.24.0', + date: '2026-08-01', + }); + + assert.match(content, /import ReleaseMeta from/); + assert.match(content, /import BlogImageSlider from/); + }); +}); + +describe('upsertChangelogSection', () => { + const marker = ''; + const base = [ + '# Changelog', + '', + marker, + '', + '# [0.12.0](https://example.com) (2023-03-11)', + '', + '- old entry', + ].join('\n'); + + it('inserts a new section below the marker', () => { + const { content, replaced } = upsertChangelogSection( + base, + '# [0.24.0](url) (2026-08-01)\n\n### Features\n\n- entry', + '0.24.0', + marker + ); + + assert.equal(replaced, false); + assert.match( + content, + /\n\n# \[0\.24\.0\]\(url\) \(2026-08-01\)/ + ); + assert.match(content, /- entry\n\n# \[0\.12\.0\]/); + }); + + it('replaces an existing section for the same version instead of duplicating', () => { + const first = upsertChangelogSection( + base, + '# [0.24.0](url) (2026-08-01)\n\n- v1 entry', + '0.24.0', + marker + ).content; + const { content, replaced } = upsertChangelogSection( + first, + '# [0.24.0](url) (2026-08-02)\n\n- v2 entry', + '0.24.0', + marker + ); + + assert.equal(replaced, true); + assert.equal(content.match(/^# \[0\.24\.0\]/gm).length, 1); + assert.match(content, /v2 entry/); + assert.doesNotMatch(content, /v1 entry/); + assert.match(content, /- v2 entry\n\n# \[0\.12\.0\]/); + }); + + it('keeps other versions untouched when replacing', () => { + const first = upsertChangelogSection( + base, + '# [0.24.0](url) (2026-08-01)\n\n- v1', + '0.24.0', + marker + ).content; + const { content } = upsertChangelogSection( + first, + '# [0.24.1](url) (2026-08-09)\n\n- patch', + '0.24.1', + marker + ); + + assert.match(content, /0\.24\.1.*\n\n- patch\n\n# \[0\.24\.0\]/); + assert.match(content, /- v1\n\n# \[0\.12\.0\]/); + }); + + it('throws when the marker is missing', () => { + assert.throws( + () => upsertChangelogSection('# Changelog', '# s', '0.24.0', marker), + /missing the/ + ); + }); +}); + +describe('extractSection', () => { + const changelog = [ + '# Changelog', + '', + 'Intro paragraph with a pointer.', + '', + '', + '', + '# [0.24.0](https://github.com/4gray/iptvnator/compare/v0.23.0...v0.24.0) (2026-08-01)', + '', + '### Features', + '', + '- **playback** — Up Next rail.', + '', + '
', + 'Internal changes', + '', + '- **deps** — parser bump.', + '', + '
', + '', + '# [0.12.0](https://github.com/4gray/iptvnator/compare/v0.11.1...v0.12.0) (2023-03-11)', + '', + '### Bug Fixes', + '', + '- old entry', + ].join('\n'); + + it('returns the section body without its own heading', () => { + const section = extractSection(changelog, '0.24.0'); + + assert.match(section, /^### Features/); + assert.match(section, /Up Next rail/); + assert.match(section, /<\/details>$/); + }); + + it('stops at the next release heading', () => { + const section = extractSection(changelog, '0.24.0'); + + assert.doesNotMatch(section, /0\.12\.0|old entry/); + }); + + it('matches the plain heading shape without a compare link', () => { + const plain = '# 0.24.0 (2026-08-01)\n\n### Fixes\n\n- entry'; + + assert.match(extractSection(plain, '0.24.0'), /^### Fixes/); + }); + + it('does not match a different patch of the same minor', () => { + assert.equal(extractSection(changelog, '0.24.1'), null); + }); + + it('returns null when the version is absent', () => { + assert.equal(extractSection(changelog, '9.9.9'), null); + }); + + it('treats regex metacharacters in the version as literals', () => { + // `.` must not act as a wildcard: 0x24y0 would match an unescaped 0.24.0 + assert.equal(extractSection('# 0x24y0 (2026-08-01)\n\n- e', '0.24.0'), null); + // Injected pattern syntax must not throw or widen the match. + assert.equal(extractSection(changelog, '0.24.0|0.12.0'), null); + assert.equal(extractSection(changelog, '.*'), null); + assert.equal(extractSection(changelog, '0.24\\.0'), null); + }); +}); + +describe('helpers', () => { + it('formats dates and release slugs', () => { + assert.equal(formatLongDate('2026-08-01'), 'August 1, 2026'); + assert.equal(releaseSlug('0.24.0'), 'v0-24'); + }); +});