diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 4c7030bd7a..d633738694 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -22,25 +22,27 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - - name: ๐ŸŽจ Check for non-RTL/non-a11y CSS classes - run: vp run lint:css + - parallel: + - name: ๐ŸŽจ Check for non-RTL/non-a11y CSS classes + run: vp run lint:css - - name: ๐ŸŒ Compare translations - run: vp run i18n:check + - name: ๐ŸŒ Compare translations + run: vp run i18n:check - - name: ๐ŸŒ Update lunaria data - run: vp run build:lunaria + - name: ๐ŸŒ Update lunaria data + run: vp run build:lunaria - - name: ๐Ÿ”  Fix lint errors - run: vp run lint:fix + - name: ๐Ÿ”  Fix lint errors + run: vp run lint:fix - uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 # v1.3.2 diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index 1cbf9719b8..97b46d7d0e 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -20,23 +20,24 @@ jobs: steps: - name: โ˜‘๏ธ Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} ref: ${{ github.event.pull_request.head.sha || github.sha }} persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true - - - name: ๐ŸŸง Install pnpm globally - run: vp install -g pnpm + sfw: true - name: ๐Ÿงช Run Chromatic Visual and Accessibility Tests - uses: chromaui/action@8a2b82547aef5a3efc8ec3c7905f4ab09a76ed0b # v16.1.0 + uses: chromaui/action@7804f34e4e59c0d9b3c856848f46ad96d7897429 # v17.5.0 + with: + buildCommand: vp run build-storybook + outputDir: storybook-static env: CHROMATIC_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }} CHROMATIC_SHA: ${{ github.event.pull_request.head.sha || github.sha }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37bd15e85f..554607d6a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,17 +26,17 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* - run-install: false - - - name: ๐Ÿ“ฆ Install dependencies (root only, no scripts) - run: vp install --filter . --ignore-scripts + sfw: true + # root only, no scripts + run-install: | + - args: ['--filter', '.', '--ignore-scripts'] - name: ๐Ÿ”  Lint project run: vp run lint @@ -46,14 +46,15 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐Ÿ’ช Type check run: vp run test:types @@ -63,21 +64,22 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐Ÿงช Unit tests run: vp test --project unit --coverage --reporter=default --reporter=junit --outputFile=test-report.junit.xml - name: โฌ†๏ธŽ Upload test results to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: disable_search: true files: test-report.junit.xml @@ -88,7 +90,7 @@ jobs: - name: โฌ†๏ธŽ Upload coverage reports to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: disable_search: true files: coverage/clover.xml @@ -101,14 +103,15 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐ŸŒ Install browser run: vp exec playwright install chromium-headless-shell @@ -118,7 +121,7 @@ jobs: - name: โฌ†๏ธŽ Upload test results to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: disable_search: true files: test-report.junit.xml @@ -129,7 +132,7 @@ jobs: - name: โฌ†๏ธŽ Upload coverage reports to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: disable_search: true files: coverage/clover.xml @@ -144,17 +147,18 @@ jobs: image: mcr.microsoft.com/playwright:v1.60.0-noble@sha256:9bd26ad900bb5e0f4dee75839e957a89ae89c2b7ab1e76050e559790e946b948 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: ๐Ÿ‘‘ Fix Git ownership run: git config --global --add safe.directory /__w/npmx.dev/npmx.dev - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐Ÿ—๏ธ Build project run: vp run build:test @@ -166,7 +170,7 @@ jobs: - name: โฌ†๏ธŽ Upload test results to Codecov if: ${{ !cancelled() }} - uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: disable_search: true files: test-report.junit.xml @@ -184,14 +188,15 @@ jobs: mode: [dark, light] steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐Ÿ—๏ธ Build project run: vp run build:test @@ -207,14 +212,15 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: ๐Ÿงน Check for unused code run: vp run knip @@ -224,17 +230,17 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* - run-install: false - - - name: ๐Ÿ“ฆ Install dependencies (root only, no scripts) - run: vp install --filter . --ignore-scripts + sfw: true + # root only, no scripts + run-install: | + - args: ['--filter', '.', '--ignore-scripts'] - name: ๐ŸŒ Check for missing or dynamic i18n keys run: vp run i18n:report diff --git a/.github/workflows/dependency-diff.yml b/.github/workflows/dependency-diff.yml index ef8984539f..fca4e75c86 100644 --- a/.github/workflows/dependency-diff.yml +++ b/.github/workflows/dependency-diff.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-slim steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/deploy-canary.yml b/.github/workflows/deploy-canary.yml index 52ec4f761f..05f270ef9a 100644 --- a/.github/workflows/deploy-canary.yml +++ b/.github/workflows/deploy-canary.yml @@ -17,16 +17,23 @@ jobs: name: ๐Ÿš€ Deploy to canary (main.npmx.dev) runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false + fetch-depth: 2 - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* run-install: false - - run: vp install -g vercel + - uses: SocketDev/action@ba6de6cc0565af1f42295590380973573297e31f # v1.3.2 + with: + mode: firewall-free + # Version of the underlying sfw to use (no `v` prefix): https://github.com/SocketDev/sfw-free/releases + firewall-version: 1.12.0 + + - run: sfw vp i -g vercel@54.12.2 - run: vercel deploy --target=canary env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} diff --git a/.github/workflows/lunaria.yml b/.github/workflows/lunaria.yml index e4fc52f092..58520eb038 100644 --- a/.github/workflows/lunaria.yml +++ b/.github/workflows/lunaria.yml @@ -22,17 +22,18 @@ jobs: steps: - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: # Necessary for Lunaria to work properly # Makes the action clone the entire git history fetch-depth: 0 persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* cache: true + sfw: true - name: Generate Lunaria Overview uses: lunariajs/action@4911ad0736d1e3b20af4cb70f5079aea2327ed8e # astro-docs diff --git a/.github/workflows/mirror-tangled.yml b/.github/workflows/mirror-tangled.yml index adae34ae0c..2e6e083e6b 100644 --- a/.github/workflows/mirror-tangled.yml +++ b/.github/workflows/mirror-tangled.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-24.04-arm steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index fdb614e08e..5053df0db9 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -21,12 +21,12 @@ jobs: pull-requests: write # create or update the release pull request steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* run-install: false diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index e6d050daa0..35a184a3d4 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -23,12 +23,12 @@ jobs: skipped: ${{ steps.check.outputs.skip }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: true - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* run-install: false @@ -66,7 +66,11 @@ jobs: - name: ๐Ÿ“ฆ Install dependencies if: steps.check.outputs.skip == 'false' - run: vp install --filter . --ignore-scripts + uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 + with: + sfw: true + run-install: | + - args: ['--filter', '.', '--ignore-scripts'] - name: ๐Ÿ“ Generate release notes if: steps.check.outputs.skip == 'false' @@ -96,19 +100,23 @@ jobs: environment: npm-publish steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: release persist-credentials: false - - uses: voidzero-dev/setup-vp@ca1c46663915d6c1042ae23bd39ab85718bfb0fa # v1.10.0 + - uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 with: node-version: lts/* registry-url: https://registry.npmjs.org run-install: false - name: ๐Ÿ“ฆ Install dependencies - run: vp install --filter npmx-connector... + uses: voidzero-dev/setup-vp@2dec1e33f4ab2c6d5bce1b0c4607961bb1a3f7a1 # v1.12.0 + with: + sfw: true + run-install: | + - args: ['--filter', 'npmx-connector...'] - name: ๐Ÿ”ข Set connector version env: diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index e3454a5dbe..8c317ef6d1 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -26,7 +26,7 @@ jobs: contents: read # checkout repository steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 273a9114d2..600359efcb 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -4,7 +4,7 @@ rules: stale-action-refs: ignore: # lunariajs/action has no tag refs; keep the branch commit hash-pinned. - - lunaria.yml:38 + - lunaria.yml:39 dangerous-triggers: ignore: - enforce-release-source.yml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 254c6385b7..237d15a28d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,6 +68,7 @@ This focus helps guide our project decisions as a community and what we choose t - [Configuration](#configuration) - [Global app settings](#global-app-settings) - [Known limitations](#known-limitations) +- [Adding a noodle](#adding-a-noodle) - [Submitting changes](#submitting-changes) - [Before submitting](#before-submitting) - [Pull request process](#pull-request-process) @@ -434,21 +435,24 @@ The command palette is a first-class navigation surface. When you add a new user #### Available route names -| Route name | URL pattern | Parameters | -| ----------------- | --------------------------------- | ------------------------- | -| `index` | `/` | — | -| `about` | `/about` | — | -| `compare` | `/compare` | — | -| `privacy` | `/privacy` | — | -| `search` | `/search` | — | -| `settings` | `/settings` | — | -| `package` | `/package/:org?/:name` | `org?`, `name` | -| `package-version` | `/package/:org?/:name/v/:version` | `org?`, `name`, `version` | -| `code` | `/package-code/:path+` | `path` (array) | -| `docs` | `/package-docs/:path+` | `path` (array) | -| `org` | `/org/:org` | `org` | -| `~username` | `/~:username` | `username` | -| `~username-orgs` | `/~:username/orgs` | `username` | +| Route name | URL pattern | Parameters | +| ------------------- | ------------------------------------------------- | -------------------------------- | +| `index` | `/` | — | +| `about` | `/about` | — | +| `compare` | `/compare` | — | +| `privacy` | `/privacy` | — | +| `search` | `/search` | — | +| `settings` | `/settings` | — | +| `package` | `/package/:org?/:name` | `org?`, `name` | +| `package-version` | `/package/:org?/:name/v/:version` | `org?`, `name`, `version` | +| `code` | `/package-code/:path+` | `path` (array) | +| `docs` | `/package-docs/:path+` | `path` (array) | +| `changelog` | `/package-changelog/:org?/:name` | `org?`, `name` | +| `changelog-version` | `/package-changelog/:org?/:name/v/:version` | `org?`, `name`, `version` | +| `timeline` | `/package-timeline/:org?/:packageName/v/:version` | `org?`, `packageName`, `version` | +| `org` | `/org/:org` | `org` | +| `~username` | `/~:username` | `username` | +| `~username-orgs` | `/~:username/orgs` | `username` | ### Cursor and navigation @@ -1045,6 +1049,116 @@ Global application settings are added to the Storybook toolbar for easy testing - `pnpm storybook` may log warnings or non-breaking errors for Nuxt modules due to the lack of mocks. If the UI renders correctly, these can be safely ignored. - Do not `import type` from `.vue` files. The `vue-docgen-api` parser used by `@storybook/addon-docs` cannot follow type imports across SFCs and will crash. Extract shared types into a separate `.ts` file instead. +## Adding a noodle + +"Noodles" are the occasional themed npmx logos that celebrate a day or event (Pride Month, World Tetris Day, the Node.js birthday, โ€ฆ). A noodle has two homes: + +- the **homepage**, where it temporarily replaces the logo while it is active, and +- the **`/noodles` archive**, where every past noodle lives on permanently with its own detail page. + +The two are wired up independently, so shipping a noodle to the homepage **and** the archive in the same PR keeps things in sync. Do both at once. + +### 1. Add the logo component + +Create `app/components/Noodle//Logo.vue`. +It's recommended to add a tooltip with event information to each noodle. If the poster is an image, add it to the `public/extra` directory. If the image differs between light and dark modes - prefer `ColorSchemeImg` component for poster + +```vue + +``` + +### 2. Register the logo and show it on the homepage + +In `app/components/Noodle/index.ts`: + +- import the component, and +- add it to the homepage rotation โ€” `ACTIVE_NOODLES` for a date-bound noodle, or `PERMANENT_NOODLES` for one shown only behind a query param (e.g. `?kawaii`), and +- register it in the `NOODLE_LOGOS` map so the archive can resolve it by `key`. + +```ts +import NoodleTetrisLogo from './Tetris/Logo.vue' + +export const ACTIVE_NOODLES: Noodle[] = [ + { + key: 'tetris', + logo: NoodleTetrisLogo, + date: '2026-06-06', + dateTo: '2026-06-08', + timezone: 'auto', // visitor's local time; or an IANA name like 'America/Los_Angeles' + tagline: false, // hide the npmx tagline while active + }, +] + +const NOODLE_LOGOS: Record = { + // โ€ฆ + tetris: NoodleTetrisLogo, +} +``` + +> [!IMPORTANT] +> The `date` and `dateTo` keys are inclusive, meaning they specify the start (at 00:00) and end (at 23:59) dates. If the dates overlap, a noodle will be randomly selected on each visit. + +> [!IMPORTANT] +> The `key` here must exactly match the `key` of the archive entry you add in the next step โ€” that is how the archive looks up the logo. + +### 3. Add the archive entry + +Append an entry to `app/noodles.ts`. Only `key`, `title`, `slug`, and `date` are required; every other field is optional, and the detail page renders a section only for the fields you fill in. The list is sorted by date automatically. + +```ts +{ + key: 'tetris', + title: 'World Tetris Day', + slug: 'tetris', // becomes /noodles/tetris โ€” must be unique + date: '2026-06-06', + dateTo: '2026-06-08', + timezone: 'auto', + tagline: false, + occasion: 'The legendary console turns 42. โ€ฆ', + prUrl: 'https://github.com/npmx-dev/npmx.dev/pull/2855', + authors: [ALEX], // reuse the author consts at the top of the file + posterImage: '/extra/tetris.svg', // OG-image hero + references: [{ label: 'Tetris (1984)', url: 'https://en.wikipedia.org/wiki/Tetris' }], +}, +``` + +Authors link out to Bluesky via their `blueskyHandle`. Reuse an existing author const (`ALEX`, `ALFON`, โ€ฆ) or add a new one at the top of the file. + +#### Grouping a series with `variants` + +When a single occasion ships as several rotating designs (Pride Month, for example, cycles through three logos), add **one** archive entry rather than one per design. Point `posterImage` at the lead artwork and list the others in `variants` โ€” the detail page's lens carousel shows the registered logo first, then each variant image: + +```ts +{ + key: 'pride-1', // matches the registered NOODLE_LOGOS key (renders first in the lens) + title: 'Pride Month', + slug: 'pride', + // โ€ฆ + posterImage: '/extra/pride-1.svg', + variants: ['/extra/pride-2.svg', '/extra/pride-3.png'], +}, +``` + +### 4. Verify + +```bash +pnpm test:types +``` + +Then run `pnpm dev` and confirm the card appears at `/noodles` and its detail page renders at `/noodles/`. Archive routes are prerendered by crawling links from the index page, so no route list needs editing. + ## Submitting changes ### Before submitting diff --git a/README.md b/README.md index d74939ad29..0312364812 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ What npmx offers: - **Dark mode and light mode** – plus customize the color palette to your preferences - **Translated interface** – localized UI across 39+ locales, including RTL support - **First-class accessibility** – accessible components, keyboard workflows, and automated axe/Lighthouse checks -- **URL-driven feature views** – share exact package versions, search results, compare sets, source files and lines, diffs, docs, changelogs, and timelines +- **URL-driven feature views** – share exact package versions, search results, compare sets, source files and lines, diffs, docs, changelogs, stats and timelines - **Fast search** – quick package search with instant results - **Package details** – READMEs, versions, dependencies, and metadata - **Code viewer** – browse package source code with syntax highlighting and permalink to specific lines @@ -186,6 +186,7 @@ We welcome contributions – please do feel free to explore the project and - [npmx-weekly](https://npmx-weekly.trueberryless.org/) – A weekly newsletter for the npmx ecosystem. Add your own content via suggestions in the weekly PR on [GitHub](https://github.com/trueberryless-org/npmx-weekly/pulls?q=is%3Aopen+is%3Apr+label%3A%22%F0%9F%95%94+weekly+post%22). - [npmx-digest](https://npmx-digest.trueberryless.org/) – An automated news aggregation website that summarizes npmx activity from GitHub and Bluesky every 8 hours. - [npmx-badge](https://npmx-badge.vercel.app/) – A playground to help you create custom badges quickly. +- [npmxers](https://npmxers.trueberryless.org/) – Discover the number of contributions you made to npmx and share your npmxer profile. If you're building something cool, let us know! ๐Ÿ™ @@ -204,3 +205,9 @@ Published under [MIT License](./LICENSE). Star History Chart + +## Sponsors + + + Sponsors + diff --git a/app/assets/logos/sponsors/coderabbit-light.svg b/app/assets/logos/sponsors/coderabbit-light.svg new file mode 100644 index 0000000000..01abf42273 --- /dev/null +++ b/app/assets/logos/sponsors/coderabbit-light.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/app/assets/logos/sponsors/coderabbit.svg b/app/assets/logos/sponsors/coderabbit.svg new file mode 100644 index 0000000000..84d0fe7f3f --- /dev/null +++ b/app/assets/logos/sponsors/coderabbit.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/app/assets/logos/sponsors/index.ts b/app/assets/logos/sponsors/index.ts index 07d5532534..6a4347eeee 100644 --- a/app/assets/logos/sponsors/index.ts +++ b/app/assets/logos/sponsors/index.ts @@ -12,6 +12,8 @@ import LogoBadrap from './badrap.svg' import LogoBadrapLight from './badrap-light.svg' import LogoChromatic from './chromatic.svg' import LogoChromaticLight from './chromatic-light.svg' +import LogoCodeRabbit from './coderabbit.svg' +import LogoCodeRabbitLight from './coderabbit-light.svg' // The list is used on the about page. To add, simply upload the logos nearby and add an entry here. Prefer SVGs. // For logo src, specify a string or object with the light and dark theme variants. @@ -20,68 +22,81 @@ import LogoChromaticLight from './chromatic-light.svg' // If there are no original assets and the logo is not universal, you can add only the dark theme variant // and specify 'auto' for the light one - this will grayscale the logo and invert it in light mode. // The normalisingIndent is the Y-axis space to visually stabilize favicon-only logos with logotypes that contain long name. -export const SPONSORS = [ - { - name: 'Vercel', - logo: { - dark: LogoVercel, - light: LogoVercelLight, +export const SPONSORS = { + gold: [ + { + name: 'Vercel', + logo: { + dark: LogoVercel, + light: LogoVercelLight, + }, + normalisingIndent: '0.875rem', + url: 'https://vercel.com/', }, - normalisingIndent: '0.875rem', - url: 'https://vercel.com/', - }, - { - name: 'Void Zero', - logo: { - dark: LogoVoidZero, - light: LogoVoidZeroLight, + { + name: 'CodeRabbit', + logo: { + dark: LogoCodeRabbit, + light: LogoCodeRabbitLight, + }, + normalisingIndent: '0.875rem', + url: 'https://www.coderabbit.ai', }, - normalisingIndent: '0.875rem', - url: 'https://voidzero.dev/', - }, - { - name: 'vlt', - logo: { - dark: LogoVlt, - light: LogoVltLight, + ], + silver: [ + { + name: 'Void Zero', + logo: { + dark: LogoVoidZero, + light: LogoVoidZeroLight, + }, + normalisingIndent: '0.875rem', + url: 'https://voidzero.dev/', }, - normalisingIndent: '0.875rem', - url: 'https://vlt.sh/', - }, - { - name: 'Netlify', - logo: { - dark: LogoNetlify, - light: LogoNetlifyLight, + { + name: 'vlt', + logo: { + dark: LogoVlt, + light: LogoVltLight, + }, + normalisingIndent: '0.875rem', + url: 'https://vlt.sh/', }, - normalisingIndent: '0.25rem', - url: 'https://netlify.com/', - }, - { - name: 'Bluesky', - logo: { - dark: LogoBluesky, - light: LogoBlueskyLight, + { + name: 'Netlify', + logo: { + dark: LogoNetlify, + light: LogoNetlifyLight, + }, + normalisingIndent: '0.25rem', + url: 'https://netlify.com/', }, - normalisingIndent: '0.625rem', - url: 'https://bsky.app/', - }, - { - name: 'Chromatic', - logo: { - dark: LogoChromatic, - light: LogoChromaticLight, + { + name: 'Bluesky', + logo: { + dark: LogoBluesky, + light: LogoBlueskyLight, + }, + normalisingIndent: '0.625rem', + url: 'https://bsky.app/', }, - normalisingIndent: '0.5rem', - url: 'https://chromatic.com/', - }, - { - name: 'Badrap', - logo: { - dark: LogoBadrap, - light: LogoBadrapLight, + { + name: 'Chromatic', + logo: { + dark: LogoChromatic, + light: LogoChromaticLight, + }, + normalisingIndent: '0.5rem', + url: 'https://chromatic.com/', }, - normalisingIndent: '0.5rem', - url: 'https://badrap.io/', - }, -] + { + name: 'Badrap', + logo: { + dark: LogoBadrap, + light: LogoBadrapLight, + }, + normalisingIndent: '0.5rem', + url: 'https://badrap.io/', + }, + ], +} diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue index 179e9b1d64..3a59dea60e 100644 --- a/app/components/AppFooter.vue +++ b/app/components/AppFooter.vue @@ -1,9 +1,10 @@ diff --git a/app/utils/charts.ts b/app/utils/charts.ts index 7c5a86ff3b..6dcc781292 100644 --- a/app/utils/charts.ts +++ b/app/utils/charts.ts @@ -9,7 +9,13 @@ import type { VueUiXyDatasetLineItem, } from 'vue-data-ui' import type { ChartTimeGranularity } from '~/types/chart' -import type { SubEvent } from '~~/server/api/registry/timeline/[...pkg].get' + +interface SubEvent { + key: string + positive: boolean + icon: string + text: string +} export function sum(numbers: number[]): number { return numbers.reduce((a, b) => a + b, 0) @@ -799,16 +805,6 @@ export async function copyAltTextForTimelineChart({ await config.copy(altText) } -// Used in chart context menu callbacks -// @todo replace with downloadFileLink -export function loadFile(link: string, filename: string) { - const a = document.createElement('a') - a.href = link - a.download = filename - a.click() - a.remove() -} - export function sanitise(value: string) { return value .replace(/^@/, '') diff --git a/app/utils/compare-scatter-chart.ts b/app/utils/compare-scatter-chart.ts index 7d14f5e298..d78f53f115 100644 --- a/app/utils/compare-scatter-chart.ts +++ b/app/utils/compare-scatter-chart.ts @@ -76,7 +76,10 @@ function getNumericFacetValue( return isFiniteNumber(packageData.metadata?.github?.stars) ? packageData.metadata.github.stars : null - + case 'githubForks': + return isFiniteNumber(packageData.metadata?.github?.forks) + ? packageData.metadata.github.forks + : null case 'githubIssues': return isFiniteNumber(packageData.metadata?.github?.issues) ? packageData.metadata.github.issues diff --git a/app/utils/date.ts b/app/utils/date.ts index c3165feb2e..67a74b2678 100644 --- a/app/utils/date.ts +++ b/app/utils/date.ts @@ -22,3 +22,30 @@ export function daysInMonth(year: number, month: number): number { export function daysInYear(year: number): number { return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 366 : 365 } + +export function getEffectiveEndDateIso(endDate?: string): string { + if (endDate) { + return endDate + } + + const today = new Date() + + return new Date(Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate() - 1)) + .toISOString() + .slice(0, 10) +} + +export function isLastDayOfMonth(dateIso: string): boolean { + const date = new Date(`${dateIso}T00:00:00.000Z`) + + const lastDayOfMonth = new Date( + Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0), + ).getUTCDate() + + return date.getUTCDate() === lastDayOfMonth +} + +export function isLastDayOfYear(dateIso: string): boolean { + const date = new Date(`${dateIso}T00:00:00.000Z`) + return date.getUTCMonth() === 11 && date.getUTCDate() === 31 +} diff --git a/app/utils/file-icons.ts b/app/utils/file-icons.ts index 6647e43a0e..e0220a0f99 100644 --- a/app/utils/file-icons.ts +++ b/app/utils/file-icons.ts @@ -264,12 +264,12 @@ export const FILENAME_ICONS: Record = { 'CONTRIBUTING.md': 'vscode-icons-file-type-markdown', 'contributing.md': 'vscode-icons-file-type-markdown', 'CODE_OF_CONDUCT.md': 'vscode-icons-file-type-markdown', - 'LICENSE': 'vscode-icons-file-type-license', - 'LICENSE.md': 'vscode-icons-file-type-license', - 'LICENSE.txt': 'vscode-icons-file-type-license', - 'license': 'vscode-icons-file-type-license', - 'license.md': 'vscode-icons-file-type-license', - 'license.txt': 'vscode-icons-file-type-license', + 'LICENSE': 'custom-license-minified', + 'LICENSE.md': 'custom-license-minified', + 'LICENSE.txt': 'custom-license-minified', + 'license': 'custom-license-minified', + 'license.md': 'custom-license-minified', + 'license.txt': 'custom-license-minified', // Node '.npmrc': 'vscode-icons-file-type-npm', diff --git a/app/utils/header-version-matcher.ts b/app/utils/header-version-matcher.ts new file mode 100644 index 0000000000..694cf1b266 --- /dev/null +++ b/app/utils/header-version-matcher.ts @@ -0,0 +1,12 @@ +// This is used by changelog for matching version in a heading, this is here to allow testing + +/** + * Check a toc heading if it contains the asked version + * @param version the version that needs to match + */ +export function createHeadingVersionMatcher(version: string) { + // only matches the exact version for normal version, pre releases could match but shouldn't if ordered by release time + const escapedVersion = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const versionRegex = new RegExp(`(? versionRegex.test(heading) +} diff --git a/app/utils/router.ts b/app/utils/router.ts index c9f2c5247c..5c608ba742 100644 --- a/app/utils/router.ts +++ b/app/utils/router.ts @@ -32,7 +32,7 @@ export function packageRoute( /** Full version history page (`/package/.../versions`) */ export function packageVersionsRoute(packageName: string): RouteLocationRaw { - const [org, name = ''] = packageName.startsWith('@') ? packageName.split('/') : ['', packageName] + const { org, name } = splitPackageName(packageName) return { name: 'package-versions', params: { org, name } } } @@ -58,7 +58,7 @@ export function changelogRoute( version?: string | null, hash?: string, ): RouteLocationRaw { - const [org, name = ''] = packageName.startsWith('@') ? packageName.split('/') : ['', packageName] + const { org, name } = splitPackageName(packageName) if (version) { return { @@ -94,3 +94,21 @@ export function packageTimelineRoute(packageName: string, version: string): Rout }, } } + +export function packageStatsRoute( + packageName: string, + version: string, + hash?: '#distribution' | '#trends', +): RouteLocationRaw { + const { org, name } = splitPackageName(packageName) + + return { + name: 'stats', + hash, + params: { + org: org || undefined, + packageName: name, + version: version.replace(/\s+/g, ''), + }, + } +} diff --git a/assets/media/custom-icons.json b/assets/media/custom-icons.json new file mode 100644 index 0000000000..53f540db9c --- /dev/null +++ b/assets/media/custom-icons.json @@ -0,0 +1,27 @@ +{ + "agent-skills": { + "body": "", + "width": 32, + "height": 32 + }, + "tangled": { + "body": "", + "width": 25, + "height": 25 + }, + "vlt": { + "body": "", + "width": 24, + "height": 24 + }, + "a11y": { + "body": "", + "width": 24, + "height": 24 + }, + "license-minified": { + "body": "", + "width": 32, + "height": 32 + } +} diff --git a/assets/media/sponsors.png b/assets/media/sponsors.png new file mode 100644 index 0000000000..5ffc124374 Binary files /dev/null and b/assets/media/sponsors.png differ diff --git a/docs/app/components/BadgeGeneratorParameters.vue b/docs/app/components/BadgeGeneratorParameters.vue index bf0a4e5d6e..ba5420cdc8 100644 --- a/docs/app/components/BadgeGeneratorParameters.vue +++ b/docs/app/components/BadgeGeneratorParameters.vue @@ -253,9 +253,11 @@ const copyToClipboard = async () => { > diff --git a/docs/content/1.getting-started/1.introduction.md b/docs/content/1.getting-started/1.introduction.md index b052a90dd4..0a48c5ca63 100644 --- a/docs/content/1.getting-started/1.introduction.md +++ b/docs/content/1.getting-started/1.introduction.md @@ -16,7 +16,7 @@ npmx.dev is a fast, modern browser for the npm registry, focused on a great deve - **Search packages** - Quick package search with instant results and infinite scroll - **Browse source code** - View package source code with syntax highlighting - **Compare packages** - Evaluate package size, dependencies, types, security, and repository health side-by-side -- **Share exact views** - Package versions, code files, diffs, docs, changelogs, timelines, search, and compare states are URL-driven +- **Share exact views** - Package versions, code files, diffs, docs, changelogs, timelines, stats, search, and compare states are URL-driven - **Check security** - See vulnerability warnings and provenance indicators - **Manage packages and orgs** - Update package access, owners, organization members, and teams - **Use your language** - Browse a translated interface across dozens of locales @@ -30,7 +30,7 @@ Use npmx.dev when you want to: - Quickly find and evaluate npm packages - Browse package source code without downloading - Compare packages before adding a dependency -- Share a permalink to the exact package, code, docs, diff, changelog, timeline, search, or comparison view +- Share a permalink to the exact package, code, docs, diff, changelog, timeline, stats, search, or comparison view - Check package security and provenance - Manage npm package access and organization teams - View package metadata in a clean, translated, dark-mode interface diff --git a/docs/content/2.guide/1.features.md b/docs/content/2.guide/1.features.md index d957d2c561..758329252d 100644 --- a/docs/content/2.guide/1.features.md +++ b/docs/content/2.guide/1.features.md @@ -15,7 +15,7 @@ Open the command palette with `โŒ˜K` on macOS, or `Ctrl+K` on Windows and Linux, ### Share exact views -npmx.dev keeps shareable state in the URL. Package versions, source files and line anchors, generated docs, version diffs, changelogs, timelines, search results, and package comparisons can all be copied and shared as direct links. +npmx.dev keeps shareable state in the URL. Package versions, source files and line anchors, generated docs, version diffs, changelogs, timelines, stats, search results, and package comparisons can all be copied and shared as direct links. ### View package details diff --git a/docs/content/2.guide/2.keyboard-shortcuts.md b/docs/content/2.guide/2.keyboard-shortcuts.md index 2fcd673225..1c35a31660 100644 --- a/docs/content/2.guide/2.keyboard-shortcuts.md +++ b/docs/content/2.guide/2.keyboard-shortcuts.md @@ -50,4 +50,6 @@ These shortcuts work anywhere on the site. Press `/` from any page to quickly se | `d` | Open docs | | `f` | Open diff view | | `c` | Compare package | -| `-` | open changelog | +| `-` | Open changelog | +| `t` | Open timeline | +| `s` | Open stats | diff --git a/docs/content/2.guide/3.url-structure.md b/docs/content/2.guide/3.url-structure.md index cd1c82a8c4..9e0df4bbfe 100644 --- a/docs/content/2.guide/3.url-structure.md +++ b/docs/content/2.guide/3.url-structure.md @@ -49,6 +49,7 @@ npmx.dev keeps package exploration views in routes or query parameters so you ca | Version diff | `/diff/vue/v/3.5.26...3.5.27` | | Changelog | `/package-changelog/vue/v/3.5.27` | | Timeline | `/package-timeline/vue/v/3.5.27` | +| Stats | `/package-stats/vue/v/3.5.27` | ## Understand URL limitations diff --git a/docs/content/2.guide/6.badges.md b/docs/content/2.guide/6.badges.md index f249ffafa4..8b336acea0 100644 --- a/docs/content/2.guide/6.badges.md +++ b/docs/content/2.guide/6.badges.md @@ -87,6 +87,14 @@ Overrides the default label color. You can pass a standard hex code (with or wit - **Default**: `#0a0a0a` - **Usage**: `?labelColor=HEX_CODE` +::note +In URLs, `#` starts the fragment part. If you write `?labelColor=#000000`, the `#000000` part is treated as a fragment and the query value is lost. + +- Wrong: `.../badge/version/nuxt?labelColor=#000000` +- Correct (URL-encoded `#`): `.../badge/version/nuxt?labelColor=%23000000` +- Also correct (no prefix): `.../badge/version/nuxt?labelColor=000000` + :: + ### `color` Overrides the default strategy color. You can pass a standard hex code (with or without the `#` prefix). The text color is automatically chosen (black or white) based on WCAG contrast ratio, so the badge remains readable. @@ -94,6 +102,14 @@ Overrides the default strategy color. You can pass a standard hex code (with or - **Default**: Depends on the badge type (e.g., version is blue, downloads are orange). - **Usage**: `?color=HEX_CODE` +::note +In URLs, `#` starts the fragment part. If you write `?color=#000000`, the `#000000` part is treated as a fragment and the query value is lost. + +- Wrong: `.../badge/version/nuxt?color=#000000` +- Correct (URL-encoded `#`): `.../badge/version/nuxt?color=%23000000` +- Also correct (no prefix): `.../badge/version/nuxt?color=000000` + :: + | Example | URL | | :------------- | :------------------------------------ | | **Hot Pink** | `.../badge/version/nuxt?color=ff69b4` | diff --git a/docs/content/index.md b/docs/content/index.md index c0e3895c40..012bd7ce8f 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -39,7 +39,7 @@ links: :::u-page-feature{icon="i-lucide:git-compare" to="/guide/features" title="Compare packages" description="Compare package size, install size, dependencies, types, security, repository health, and social signals."} ::: -:::u-page-feature{icon="i-lucide:link" to="/guide/url-structure" title="Use familiar URLs" description="Replace npmjs.com with npmx.dev in any URL and share exact package, code, diff, docs, changelog, timeline, search, and compare views."} +:::u-page-feature{icon="i-lucide:link" to="/guide/url-structure" title="Use familiar URLs" description="Replace npmjs.com with npmx.dev in any URL and share exact package, code, diff, docs, changelog, timeline, stats, search, and compare views."} ::: :::u-page-feature{icon="i-lucide:keyboard" to="/guide/keyboard-shortcuts" title="Navigate with keyboard" description="Open the command palette with โŒ˜K on macOS or Ctrl+K on Windows and Linux. Press / to search. Use arrow keys to browse results."} diff --git a/docs/package.json b/docs/package.json index 3d080948fd..6122def196 100644 --- a/docs/package.json +++ b/docs/package.json @@ -23,7 +23,7 @@ "@nuxtjs/mdc": "0.21.1", "better-sqlite3": "12.8.0", "docus": "5.9.0", - "nuxt": "4.4.5", + "nuxt": "4.4.8", "tailwindcss": "4.2.2" } } diff --git a/i18n/locales/ar.json b/i18n/locales/ar.json index 519b623f7e..cc72524203 100644 --- a/i18n/locales/ar.json +++ b/i18n/locales/ar.json @@ -173,12 +173,9 @@ "replacement": { "title": "ู‚ุฏ ู„ุง ุชุญุชุงุฌ ุฅู„ู‰ ู‡ุฐู‡ ุงู„ุชุจุนูŠุฉ.", "native": "ูŠู…ูƒู† ุงุณุชุจุฏุงู„ู‡ุง ุจู€ {replacement}ุŒ ุงู„ู…ุชูˆูุฑุฉ ู…ู†ุฐ Node {nodeVersion}.", - "simple": "ุฃุดุงุฑ {community} ุฅู„ู‰ ุฃู† ู‡ุฐู‡ ุงู„ุญุฒู…ุฉ ุฒุงุฆุฏุฉุŒ ู…ุน ุงู„ู†ุตูŠุญุฉ: {replacement}.", - "documented": "ุฃุดุงุฑ {community} ุฅู„ู‰ ุฃู† ู‡ุฐู‡ ุงู„ุญุฒู…ุฉ ู„ู‡ุง ุจุฏุงุฆู„ ุฃูƒุซุฑ ุฃุฏุงุกู‹.", "none": "ุชู… ูˆุถุน ุนู„ุงู…ุฉ ุนู„ู‰ ู‡ุฐู‡ ุงู„ุญุฒู…ุฉ ุจุฃู†ู‡ุง ู„ู… ุชุนุฏ ู…ุทู„ูˆุจุฉุŒ ูˆู…ู† ุงู„ู…ุฑุฌุญ ุฃู† ูˆุธูŠูุชู‡ุง ู…ุชุงุญุฉ ุฃุตู„ู‹ุง ููŠ ุฌู…ูŠุน ุงู„ู…ุญุฑูƒุงุช.", "learn_more": "ุงุนุฑู ุงู„ู…ุฒูŠุฏ", "learn_more_above": "ุงุนุฑู ุงู„ู…ุฒูŠุฏ ุฃุนู„ุงู‡.", - "community": "ุงู„ู…ุฌุชู…ุน", "consider_no_dep": "+ ู‡ู„ ุชุฑูŠุฏ ุฎูŠุงุฑ ยซุจุฏูˆู† ุชุจุนูŠุฉยปุŸ" }, "stats": { @@ -304,7 +301,6 @@ "deprecated_title": "{version} (ู…ู‡ู…ู„)", "view_all": "ุนุฑุถ {count} ุฅุตุฏุงุฑ | ุนุฑุถ ุฅุตุฏุงุฑ ูˆุงุญุฏุฉ | ุนุฑุถ ุฅุตุฏุงุฑูŠู† | ุนุฑุถ {count} ุฅุตุฏุงุฑุงุช | ุนุฑุถ {count} ุฅุตุฏุงุฑ | ุนุฑุถ {count} ุฅุตุฏุงุฑ", "distribution_title": "ู…ุฌู…ูˆุนุฉ Semver", - "distribution_modal_title": "ุงู„ุฅุตุฏุงุฑุงุช", "grouping_major": "ุฑุฆูŠุณูŠ", "grouping_minor": "ุซุงู†ูˆูŠ", "recent_versions_only_tooltip": "ุฅุธู‡ุงุฑ ุงู„ุฅุตุฏุงุฑุงุช ุงู„ู…ู†ุดูˆุฑุฉ ุฎู„ุงู„ ุงู„ุณู†ุฉ ุงู„ู…ุงุถูŠุฉ ูู‚ุท.", diff --git a/i18n/locales/az-AZ.json b/i18n/locales/az-AZ.json index 23805f4f0e..4737416609 100644 --- a/i18n/locales/az-AZ.json +++ b/i18n/locales/az-AZ.json @@ -73,6 +73,23 @@ "instant_search_turn_off": "baฤŸla", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "ฦsas", "popular_packages": "Populyar paketlษ™r", @@ -235,15 +252,13 @@ "size": "QuraลŸdฤฑrma hษ™cmi {percent} artฤฑb ({size} daha bรถyรผk)", "deps": "{count} daha รงox asฤฑlฤฑlฤฑq" }, + "size_decrease": {}, "replacement": { "title": "Bu asฤฑlฤฑlฤฑฤŸa ehtiyacฤฑnฤฑz olmaya bilษ™r.", "native": "Bu, Node {nodeVersion}-dษ™n bษ™ri mรถvcud olan {replacement} ilษ™ ษ™vษ™z edilษ™ bilษ™r.", - "simple": "{community} bu paketi artฤฑq lazฤฑmsฤฑz olaraq qeyd edib, tรถvsiyษ™si: {replacement}.", - "documented": "{community} bu paketin daha performanslฤฑ alternativlษ™rinin olduฤŸunu qeyd edib.", "none": "Bu paket artฤฑq lazฤฑmsฤฑz olaraq qeyd edilib vษ™ funksionallฤฑฤŸฤฑ bรผtรผn mรผhษ™rriklษ™rdษ™ yerli olaraq mรถvcuddur.", "learn_more": "ฦtraflฤฑ รถyrษ™n", "learn_more_above": "Yuxarฤฑda ษ™traflฤฑ รถyrษ™nin.", - "community": "icma", "consider_no_dep": "+ Asฤฑlฤฑlฤฑqsฤฑz dรผลŸรผnรผn?" }, "stats": { @@ -369,7 +384,6 @@ "deprecated_title": "{version} (kรถhnษ™lmiลŸ)", "view_all": "{count} versiyanฤฑ gรถstษ™r | Bรผtรผn {count} versiyanฤฑ gรถstษ™r", "distribution_title": "Semver Qrupu", - "distribution_modal_title": "Versiyalar", "distribution_range_date_same_year": "{from}-dษ™n {to}-yษ™, {endYear}", "distribution_range_date_multiple_years": "{from}, {startYear}-dษ™n {to}, {endYear}-ษ™", "grouping_major": "Major", @@ -393,6 +407,11 @@ "general_description": "{package_name} paketinin {versions_count} {semver_grouping_mode} versiyasฤฑ รผรงรผn versiya baลŸฤฑna endirmษ™lษ™ri gรถstษ™rษ™n รงubuq diaqramฤฑ, {date_range_label} {first_version} versiyasฤฑndan {last_version} versiyasฤฑna qษ™dษ™r. ฦn รงox endirilษ™n versiya {max_version_downloads} endirmษ™ ilษ™ {max_downloaded_version}-dir. {per_version_analysis}. {watermark}." } }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Asฤฑlฤฑlฤฑq ({count}) | Asฤฑlฤฑlฤฑqlar ({count})", "list_label": "Paket asฤฑlฤฑlฤฑqlarฤฑ", @@ -429,6 +448,7 @@ "show_less": "(daha az gรถstษ™r)" }, "trends": { + "chart_assistive_text": {}, "granularity": "Dษ™rษ™cษ™lilik", "granularity_daily": "Gรผnlรผk", "granularity_weekly": "Hษ™ftษ™lik", @@ -576,6 +596,9 @@ }, "download": {} }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Lokal Konnektor", @@ -1037,6 +1060,9 @@ "packages_selected": "{count}/{max} paket seรงilib.", "add_hint": "Mรผqayisษ™ รผรงรผn ษ™n azฤฑ 2 paket ษ™lavษ™ edin." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(Asฤฑlฤฑlฤฑq yoxdur)", "typeahead_title": "James Nษ™ Edษ™rdi?", @@ -1111,7 +1137,10 @@ "vulnerabilities": { "label": "Zษ™ifliklษ™r", "description": "Mษ™lum tษ™hlรผkษ™sizlik zษ™ifliklษ™ri" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "ฤฐstษ™nilษ™n", @@ -1131,8 +1160,6 @@ "file_changes": "Fayl Dษ™yiลŸikliklษ™ri", "files_count": "{count} fayl", "lines_hidden": "{count} sษ™tir gizlษ™dilib", - "file_too_large": "Fayl mรผqayisษ™ รผรงรผn รงox bรถyรผkdรผr", - "file_size_warning": "{size} mรผqayisษ™ รผรงรผn 250KB limitini keรงir", "compare_versions": "fษ™rq", "compare_versions_title": "Versiyalarฤฑ mรผqayisษ™ et", "version_invalid_url_format": {}, @@ -1304,5 +1331,23 @@ "translation_status": { "table": {} }, - "action_bar": {} + "vacations": { + "what": {}, + "meantime": {}, + "return": {}, + "stats": { + "subtitle": {} + } + }, + "action_bar": {}, + "logo_menu": {}, + "brand": { + "logos": {}, + "customize": {}, + "typography": {}, + "guidelines": {} + }, + "changelog": { + "error": {} + } } diff --git a/i18n/locales/bg-BG.json b/i18n/locales/bg-BG.json index c2d1d1701f..d289b44e80 100644 --- a/i18n/locales/bg-BG.json +++ b/i18n/locales/bg-BG.json @@ -65,6 +65,23 @@ "view_org_packages": "ะŸะพะบะฐะทะฒะฐะฝะต ะฝะฐ ะฟะฐะบะตั‚ะธ ะพั‚ ั‚ะฐะทะธ ะพั€ะณะฐะฝะธะทะฐั†ะธั" } }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "ะ“ะปะฐะฒะฝะฐ", "popular_packages": "ะŸะพะฟัƒะปัั€ะฝะธ ะฟะฐะบะตั‚ะธ", @@ -198,15 +215,13 @@ "size": "ะ ะฐะทะผะตั€ัŠั‚ ะฟั€ะธ ะธะฝัั‚ะฐะปะฐั†ะธั ัะต ะต ัƒะฒะตะปะธั‡ะธะป ั {percent} ({size} ะฟะพ-ะณะพะปัะผ)", "deps": "{count} ะฟะพะฒะตั‡ะต ะทะฐะฒะธัะธะผะพัั‚ะธ" }, + "size_decrease": {}, "replacement": { "title": "ะœะพะถะต ะดะฐ ะฝะต ัะต ะฝัƒะถะดะฐะตั‚ะต ะพั‚ ั‚ะฐะทะธ ะทะฐะฒะธัะธะผะพัั‚.", "native": "ะขะพะฒะฐ ะผะพะถะต ะดะฐ ะฑัŠะดะต ะทะฐะผะตะฝะตะฝะพ ั {replacement}, ะฝะฐะปะธั‡ะฝะพ ะพั‚ Node {nodeVersion}.", - "simple": "{community} ะต ะพั‚ะฑะตะปัะทะฐะปะฐ ั‚ะพะทะธ ะฟะฐะบะตั‚ ะบะฐั‚ะพ ะธะทะปะธัˆะตะฝ, ััŠั ััŠะฒะตั‚ะฐ: {replacement}.", - "documented": "{community} ะต ะพั‚ะฑะตะปัะทะฐะปะฐ ั‚ะพะทะธ ะฟะฐะบะตั‚ ะบะฐั‚ะพ ะธะผะฐั‰ ะฟะพ-ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปะฝะธ ะฐะปั‚ะตั€ะฝะฐั‚ะธะฒะธ.", "none": "ะขะพะทะธ ะฟะฐะบะตั‚ ะต ะพั‚ะฑะตะปัะทะฐะฝ ะบะฐั‚ะพ ะฒะตั‡ะต ะฝะตะฝัƒะถะตะฝ ะธ ั„ัƒะฝะบั†ะธะพะฝะฐะปะฝะพัั‚ั‚ะฐ ะผัƒ ะฒะตั€ะพัั‚ะฝะพ ะต ะฝะฐะปะธั‡ะฝะฐ ะฝะฐั‚ะธะฒะฝะพ ะฒัŠะฒ ะฒัะธั‡ะบะธ ะดะฒะธะณะฐั‚ะตะปะธ.", "learn_more": "ะะฐัƒั‡ะตั‚ะต ะฟะพะฒะตั‡ะต", "learn_more_above": "ะะฐัƒั‡ะตั‚ะต ะฟะพะฒะตั‡ะต ะฟะพ-ะณะพั€ะต.", - "community": "ะพะฑั‰ะฝะพัั‚", "consider_no_dep": "+ ะžะฑะผะธัะปะตั‚ะต ะฑะตะท ะทะฐะฒะธัะธะผะพัั‚ะธ?" }, "stats": { @@ -332,7 +347,6 @@ "deprecated_title": "{version} (ะพัั‚ะฐั€ัะปะฐ)", "view_all": "ะŸั€ะตะณะปะตะด ะฝะฐ {count} ะฒะตั€ัะธั | ะŸั€ะตะณะปะตะด ะฝะฐ ะฒัะธั‡ะบะธ {count} ะฒะตั€ัะธะธ", "distribution_title": "Semver ะณั€ัƒะฟะฐ", - "distribution_modal_title": "ะ’ะตั€ัะธะธ", "distribution_range_date_same_year": "ะพั‚ {from} ะดะพ {to}, {endYear}", "distribution_range_date_multiple_years": "ะพั‚ {from}, {startYear} ะดะพ {to}, {endYear}", "grouping_major": "Major", @@ -356,6 +370,11 @@ "general_description": "ะกั‚ัŠะปะฑะพะฒะธะดะฝะฐ ะดะธะฐะณั€ะฐะผะฐ, ะฟะพะบะฐะทะฒะฐั‰ะฐ ะธะทั‚ะตะณะปัะฝะธัั‚ะฐ ะฟะพ ะฒะตั€ัะธะธ ะทะฐ {versions_count} {semver_grouping_mode} ะฒะตั€ัะธะธ ะฝะฐ ะฟะฐะบะตั‚ะฐ {package_name}, {date_range_label} ะพั‚ ะฒะตั€ัะธั {first_version} ะดะพ ะฒะตั€ัะธั {last_version}. ะะฐะน-ะธะทั‚ะตะณะปัะฝะฐั‚ะฐ ะฒะตั€ัะธั ะต {max_downloaded_version} ั {max_version_downloads} ะธะทั‚ะตะณะปัะฝะธั. {per_version_analysis}. {watermark}." } }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "ะ—ะฐะฒะธัะธะผะพัั‚ ({count}) | ะ—ะฐะฒะธัะธะผะพัั‚ะธ ({count})", "list_label": "ะ—ะฐะฒะธัะธะผะพัั‚ะธ ะฝะฐ ะฟะฐะบะตั‚ะฐ", @@ -392,6 +411,7 @@ "show_less": "(ะฟะพะบะฐะทะฒะฐะฝะต ะฝะฐ ะฟะพ-ะผะฐะปะบะพ)" }, "trends": { + "chart_assistive_text": {}, "granularity": "ะ“ั€ะฐะฝัƒะปะฐั†ะธั", "granularity_daily": "ะ”ะฝะตะฒะฝะฐ", "granularity_weekly": "ะกะตะดะผะธั‡ะฝะฐ", @@ -537,6 +557,9 @@ }, "download": {} }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "ะ›ะพะบะฐะปะตะฝ ะบะพะฝะตะบั‚ะพั€", @@ -994,6 +1017,9 @@ "packages_selected": "{count}/{max} ะธะทะฑั€ะฐะฝะธ ะฟะฐะบะตั‚ะฐ.", "add_hint": "ะ”ะพะฑะฐะฒะตั‚ะต ะฟะพะฝะต 2 ะฟะฐะบะตั‚ะฐ ะทะฐ ัั€ะฐะฒะฝะตะฝะธะต." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(ะ‘ะตะท ะทะฐะฒะธัะธะผะพัั‚)", "typeahead_title": "ะšะฐะบะฒะพ ะฑะธ ะฝะฐะฟั€ะฐะฒะธะป James?", @@ -1068,7 +1094,10 @@ "vulnerabilities": { "label": "ะฃัะทะฒะธะผะพัั‚ะธ", "description": "ะ˜ะทะฒะตัั‚ะฝะธ ัƒัะทะฒะธะผะพัั‚ะธ ะฒ ัะธะณัƒั€ะฝะพัั‚ั‚ะฐ" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "ะ’ััะบะฐะบัŠะฒ", @@ -1088,8 +1117,6 @@ "file_changes": "ะŸั€ะพะผะตะฝะธ ะฒ ั„ะฐะนะปะพะฒะตั‚ะต", "files_count": "{count} ั„ะฐะนะปะฐ", "lines_hidden": "{count} ั€ะตะดะฐ ัะบั€ะธั‚ะธ", - "file_too_large": "ะคะฐะนะปัŠั‚ ะต ั‚ะฒัŠั€ะดะต ะณะพะปัะผ ะทะฐ ัั€ะฐะฒะฝะตะฝะธะต", - "file_size_warning": "{size} ะฝะฐะดะฒะธัˆะฐะฒะฐ ะปะธะผะธั‚ะฐ ะพั‚ 250KB ะทะฐ ัั€ะฐะฒะฝะตะฝะธะต", "compare_versions": "diff", "version_invalid_url_format": {}, "summary": "ะ ะตะทัŽะผะต", @@ -1237,5 +1264,23 @@ "translation_status": { "table": {} }, - "action_bar": {} + "vacations": { + "what": {}, + "meantime": {}, + "return": {}, + "stats": { + "subtitle": {} + } + }, + "action_bar": {}, + "logo_menu": {}, + "brand": { + "logos": {}, + "customize": {}, + "typography": {}, + "guidelines": {} + }, + "changelog": { + "error": {} + } } diff --git a/i18n/locales/bn-IN.json b/i18n/locales/bn-IN.json index da2e2dccd2..81392dff76 100644 --- a/i18n/locales/bn-IN.json +++ b/i18n/locales/bn-IN.json @@ -13,11 +13,11 @@ "trademark_disclaimer": "npm, npm, Inc. เฆเฆฐ เฆเฆ•เฆŸเฆฟ เฆจเฆฟเฆฌเฆจเงเฆงเฆฟเฆค เฆŸเงเฆฐเง‡เฆกเฆฎเฆพเฆฐเงเฆ•เฅค เฆเฆ‡ เฆธเฆพเฆ‡เฆŸเฆŸเฆฟ npm, Inc. เฆเฆฐ เฆธเฆพเฆฅเง‡ เฆธเฆ‚เฆฏเงเฆ•เงเฆค เฆจเฆฏเฆผเฅค", "footer": { "about": "เฆ†เฆฎเฆพเฆฆเง‡เฆฐ เฆธเฆฎเงเฆชเฆฐเงเฆ•เง‡", + "blog": "เฆฌเงเฆฒเฆ—", "docs": "เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ", "source": "เฆธเง‹เฆฐเงเฆธ", "social": "เฆธเง‹เฆถเงเฆฏเฆพเฆฒ", "chat": "เฆšเงเฆฏเฆพเฆŸ", - "blog": "เฆฌเงเฆฒเฆ—", "builders_chat": "เฆจเฆฟเฆฐเงเฆฎเฆพเฆคเฆพเฆฆเง‡เฆฐ เฆšเงเฆฏเฆพเฆŸ", "keyboard_shortcuts": "เฆ•เง€เฆฌเง‹เฆฐเงเฆก เฆถเฆฐเงเฆŸเฆ•เฆพเฆŸเฆธ", "brand": "เฆฌเงเฆฐเงเฆฏเฆพเฆจเงเฆก", @@ -400,12 +400,9 @@ "example": "เฆ‰เฆฆเฆพเฆนเฆฐเฆฃ:", "native": "เฆเฆŸเฆฟเฆ•เง‡ {replacement} เฆฆเฆฟเฆฏเฆผเง‡ เฆชเงเฆฐเฆคเฆฟเฆธเงเฆฅเฆพเฆชเฆจ เฆ•เฆฐเฆพ เฆฏเง‡เฆคเง‡ เฆชเฆพเฆฐเง‡, เฆฏเฆพ Node {nodeVersion} เฆฅเง‡เฆ•เง‡ เฆ‰เฆชเฆฒเฆฌเงเฆงเฅค", "native_no_version": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟ {replacement} เฆฆเฆฟเฆฏเฆผเง‡ เฆชเงเฆฐเฆคเฆฟเฆธเงเฆฅเฆพเฆชเฆจ เฆ•เฆฐเฆพ เฆฏเง‡เฆคเง‡ เฆชเฆพเฆฐเง‡เฅค", - "simple": "{community} เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟเฆ•เง‡ เฆ…เฆจเฆพเฆฌเฆถเงเฆฏเฆ• เฆนเฆฟเฆธเฆพเฆฌเง‡ เฆšเฆฟเฆนเงเฆจเฆฟเฆค เฆ•เฆฐเง‡เฆ›เง‡, เฆชเฆฐเฆพเฆฎเฆฐเงเฆถ: {replacement}เฅค", - "documented": "{community} เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟเฆ•เง‡ เฆ†เฆฐเง‹ เฆญเฆพเฆฒ เฆชเฆพเฆฐเฆซเฆฐเฆฎเงเฆฏเฆพเฆจเงเฆธ เฆ…เฆชเฆถเฆจ เฆนเฆฟเฆธเฆพเฆฌเง‡ เฆšเฆฟเฆนเงเฆจเฆฟเฆค เฆ•เฆฐเง‡เฆ›เง‡เฅค", "none": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟ เฆเฆ–เฆจ เฆ…เฆจเฆพเฆฌเฆถเงเฆฏเฆ• เฆนเฆฟเฆธเฆพเฆฌเง‡ เฆšเฆฟเฆนเงเฆจเฆฟเฆค, เฆเฆฌเฆ‚ เฆเฆฐ เฆ•เฆพเฆฐเงเฆฏเฆ•เฆฐเฆฟเฆคเฆพ เฆธเฆฎเฆธเงเฆค เฆ‡เฆžเงเฆœเฆฟเฆจเง‡ เฆจเง‡เฆŸเฆฟเฆญเฆญเฆพเฆฌเง‡ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆนเฆ“เฆฏเฆผเฆพเฆฐ เฆธเฆฎเงเฆญเฆพเฆฌเฆจเฆพ เฆ†เฆ›เง‡เฅค", "learn_more": "เฆ†เฆฐเง‹ เฆœเฆพเฆจเงเฆจ", "learn_more_above": "เฆ†เฆฐเง‹ เฆœเฆพเฆจเงเฆจ เฆ‰เฆชเฆฐเง‡เฅค", - "community": "เฆ•เฆฎเฆฟเฆ‰เฆจเฆฟเฆŸเฆฟ", "consider_no_dep": "+ เฆ•เง‹เฆจ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ เฆฌเฆฟเฆฌเง‡เฆšเฆจเฆพ?" }, "stats": { @@ -462,10 +459,10 @@ "top_rank_link_label": "เฆชเฆ›เฆจเงเฆฆ เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก เฆฆเง‡เฆ–เงเฆจ. เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟ #{rank} เฆฐโ€Œเงเฆฏเฆพเฆ™เงเฆ• เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡." }, "docs": { - "not_available": "เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆจเง‡เฆ‡", - "not_available_detail": "เฆ†เฆฎเฆฐเฆพ เฆเฆ‡ เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆœเฆจเงเฆฏ เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ เฆคเงˆเฆฐเฆฟ เฆ•เฆฐเฆคเง‡ เฆชเฆพเฆฐเฆฟเฆจเฆฟเฅค", "contents": "เฆฌเฆฟเฆทเฆฏเฆผเฆฌเฆธเงเฆคเง", "default_not_available": "เฆเฆ‡ เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆœเฆจเงเฆฏ เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆจเฆฏเฆผเฅค", + "not_available": "เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆจเง‡เฆ‡", + "not_available_detail": "เฆ†เฆฎเฆฐเฆพ เฆเฆ‡ เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆœเฆจเงเฆฏ เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ เฆคเงˆเฆฐเฆฟ เฆ•เฆฐเฆคเง‡ เฆชเฆพเฆฐเฆฟเฆจเฆฟเฅค", "page_title": "API เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ - npmx", "page_title_name": "{name} เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ - npmx", "page_title_version": "{name} เฆกเฆ•เงเฆฎเง‡เฆจเงเฆŸเง‡เฆถเฆจ - npmx", @@ -476,9 +473,9 @@ "title": "เฆถเงเฆฐเง เฆ•เฆฐเงเฆจ", "pm_label": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฎเงเฆฏเฆพเฆจเง‡เฆœเฆพเฆฐ", "copy_command": "เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆ•เฆฎเฆพเฆจเงเฆก เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", - "view_types": "{package} เฆฆเง‡เฆ–เงเฆจ", "copy_dev_command": "เฆกเง‡เฆญ เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆ•เฆฎเฆพเฆจเงเฆก เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", - "dev_dependency_hint": "เฆธเฆพเฆงเฆพเฆฐเฆฃเฆค เฆกเง‡เฆญ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆ•เฆฐเฆพ เฆนเฆฏเฆผ" + "dev_dependency_hint": "เฆธเฆพเฆงเฆพเฆฐเฆฃเฆค เฆกเง‡เฆญ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆ•เฆฐเฆพ เฆนเฆฏเฆผ", + "view_types": "{package} เฆฆเง‡เฆ–เงเฆจ" }, "create": { "title": "เฆจเฆคเงเฆจ เฆชเงเฆฐเฆ•เฆฒเงเฆช เฆคเงˆเฆฐเฆฟ เฆ•เฆฐเงเฆจ", @@ -492,6 +489,7 @@ "readme": { "title": "เฆฐเฆฟเฆกเฆฎเฆฟ", "no_readme": "README เฆ‰เฆชเฆฒเฆฌเงเฆง เฆจเง‡เฆ‡เฅค", + "toc_title": "เฆ†เฆ‰เฆŸเฆฒเฆพเฆ‡เฆจ", "callout": { "note": "เฆฆเงเฆฐเฆทเงเฆŸเฆฌเงเฆฏ", "tip": "เฆŸเฆฟเฆช", @@ -499,7 +497,6 @@ "warning": "เฆธเฆคเฆฐเงเฆ•เฆคเฆพ", "caution": "เฆธเฆคเฆฐเงเฆ•เฆคเฆพ" }, - "toc_title": "เฆ†เฆ‰เฆŸเฆฒเฆพเฆ‡เฆจ", "copy_as_markdown": "เฆฎเฆพเฆฐเงเฆ•เฆกเฆพเฆ‰เฆจ เฆนเฆฟเฆธเฆพเฆฌเง‡ README เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "error_loading": "README เฆฌเฆฟเฆถเฆฆ เฆฒเง‹เฆก เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅ เฆนเฆฏเฆผเง‡เฆ›เง‡เงท" }, @@ -528,10 +525,10 @@ "compatibility": "เฆธเฆพเฆฎเฆžเงเฆœเฆธเงเฆฏ", "card": { "publisher": "เฆชเงเฆฐเฆ•เฆพเฆถเฆ•", + "published": "เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", "weekly_downloads": "เฆธเฆพเฆชเงเฆคเฆพเฆนเฆฟเฆ• เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก", "keywords": "เฆ•เง€เฆ“เฆฏเฆผเฆพเฆฐเงเฆก", "license": "เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ", - "published": "เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", "select": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", "select_maximum": "เฆธเฆฐเงเฆฌเง‹เฆšเงเฆš {count}เฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเฆพ เฆฏเฆพเฆฌเง‡" }, @@ -548,13 +545,8 @@ "all_covered": "เฆธเฆฌ เฆญเฆพเฆฐเงเฆธเฆจ เฆ‰เฆชเฆฐเง‡เฆฐ เฆŸเงเฆฏเฆพเฆ— เฆฆเงเฆฌเฆพเฆฐเฆพ เฆ†เฆฌเงƒเฆค", "deprecated_title": "{version} (เฆจเฆฟเฆทเงเฆ•เงเฆฐเฆฟเฆฏเฆผ)", "view_all": "{count}เฆŸเฆฟ เฆญเฆพเฆฐเงเฆธเฆจ เฆฆเง‡เฆ–เงเฆจ | เฆธเฆฌ {count}เฆŸเฆฟ เฆญเฆพเฆฐเงเฆธเฆจ เฆฆเง‡เฆ–เงเฆจ", - "copy_alt": { - "per_version_analysis": "{version} เฆญเฆพเฆฐเงเฆธเฆจเฆŸเฆฟ {downloads} เฆฌเฆพเฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "general_description": "{package_name} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ {versions_count}เฆŸเฆฟ {semver_grouping_mode} เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆชเงเฆฐเฆคเฆฟ-เฆญเฆพเฆฐเงเฆธเฆจ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆฆเง‡เฆ–เฆพเฆจเง‹ เฆฌเฆพเฆฐ เฆšเฆพเฆฐเงเฆŸ, {first_version} เฆญเฆพเฆฐเงเฆธเฆจ เฆฅเง‡เฆ•เง‡ {last_version} เฆญเฆพเฆฐเงเฆธเฆจ เฆชเฆฐเงเฆฏเฆจเงเฆค, {date_range_label} เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฏเฆผเฅค เฆธเฆฌเฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆนเฆ“เฆฏเฆผเฆพ เฆญเฆพเฆฐเงเฆธเฆจ เฆนเฆฒเง‹ {max_downloaded_version}, เฆฏเฆพเฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆธเฆ‚เฆ–เงเฆฏเฆพ {max_version_downloads}เฅค {per_version_analysis}เฅค {watermark}เฅค" - }, "view_all_versions": "เฆธเฆฌ เฆญเฆพเฆฐเงเฆธเฆจ เฆฆเง‡เฆ–เงเฆจ", "distribution_title": "Semver เฆ—เงเฆฐเงเฆช", - "distribution_modal_title": "เฆญเฆพเฆฐเงเฆธเฆจเฆธเฆฎเง‚เฆน", "distribution_range_date_same_year": "{from} เฆฅเง‡เฆ•เง‡ {to}, {endYear}", "distribution_range_date_multiple_years": "{from}, {startYear} เฆฅเง‡เฆ•เง‡ {to}, {endYear}", "grouping_major": "เฆฎเง‡เฆœเฆฐ", @@ -579,10 +571,43 @@ "license_change_warning": "เฆ†เฆ—เง‡เฆฐ เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆชเฆฐ เฆฅเง‡เฆ•เง‡ เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", "license_change_record": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ \"{from}\" เฆฅเง‡เฆ•เง‡ \"{to}\" เฆคเง‡ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", "no_matches": "เฆเฆ‡ เฆชเฆฐเฆฟเฆธเฆฐเง‡เฆฐ เฆธเฆพเฆฅเง‡ เฆ•เง‹เฆจเง‹ เฆญเฆพเฆฐเงเฆธเฆจ เฆฎเง‡เฆฒเง‡เฆจเฆฟ", + "copy_alt": { + "per_version_analysis": "{version} เฆญเฆพเฆฐเงเฆธเฆจเฆŸเฆฟ {downloads} เฆฌเฆพเฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "general_description": "{package_name} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ {versions_count}เฆŸเฆฟ {semver_grouping_mode} เฆญเฆพเฆฐเงเฆธเฆจเง‡เฆฐ เฆชเงเฆฐเฆคเฆฟ-เฆญเฆพเฆฐเงเฆธเฆจ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆฆเง‡เฆ–เฆพเฆจเง‹ เฆฌเฆพเฆฐ เฆšเฆพเฆฐเงเฆŸ, {first_version} เฆญเฆพเฆฐเงเฆธเฆจ เฆฅเง‡เฆ•เง‡ {last_version} เฆญเฆพเฆฐเงเฆธเฆจ เฆชเฆฐเงเฆฏเฆจเงเฆค, {date_range_label} เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฏเฆผเฅค เฆธเฆฌเฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆนเฆ“เฆฏเฆผเฆพ เฆญเฆพเฆฐเงเฆธเฆจ เฆนเฆฒเง‹ {max_downloaded_version}, เฆฏเฆพเฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆธเฆ‚เฆ–เงเฆฏเฆพ {max_version_downloads}เฅค {per_version_analysis}เฅค {watermark}เฅค" + }, "page_title": "เฆญเฆพเฆฐเงเฆธเฆจ เฆ‡เฆคเฆฟเฆนเฆพเฆธ", "current_tags": "เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆŸเงเฆฏเฆพเฆ—เฆธเฆฎเง‚เฆน", "no_match_filter": "{filter} เฆเฆฐ เฆธเฆพเฆฅเง‡ เฆ•เง‹เฆจเง‹ เฆญเฆพเฆฐเงเฆธเฆจ เฆฎเง‡เฆฒเง‡เฆจเฆฟ" }, + "timeline": { + "load_more": "เฆ†เฆฐเง‹ เฆฒเง‹เฆก เฆ•เฆฐเงเฆจ", + "load_error": "เฆŸเฆพเฆ‡เฆฎเฆฒเฆพเฆ‡เฆจ เฆฒเง‹เฆก เฆ•เฆฐเฆพ เฆฏเฆพเฆฏเฆผเฆจเฆฟเฅค เฆ…เฆจเงเฆ—เงเฆฐเฆน เฆ•เฆฐเง‡ เฆชเฆฐเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจเฅค", + "size_increase": "เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆธเฆพเฆ‡เฆœ {percent}% เฆฌเงƒเฆฆเงเฆงเฆฟ เฆชเง‡เฆฏเฆผเง‡เฆ›เง‡ ({size})", + "size_decrease": "เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆธเฆพเฆ‡เฆœ {percent}% เฆ•เฆฎเง‡เฆ›เง‡ ({size})", + "dep_increase": "{count}เฆŸเฆฟ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆฏเง‹เฆ— เฆนเฆฏเฆผเง‡เฆ›เง‡", + "dep_decrease": "{count}เฆŸเฆฟ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "license_change": "เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ {from} เฆฅเง‡เฆ•เง‡ {to} เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", + "esm_added": "เฆฎเฆกเฆฟเฆ‰เฆฒ เฆŸเฆพเฆ‡เฆช ESM เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", + "esm_removed": "เฆฎเฆกเฆฟเฆ‰เฆฒ เฆŸเฆพเฆ‡เฆช ESM เฆฅเง‡เฆ•เง‡ CJS เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", + "types_added": "TypeScript เฆŸเฆพเฆ‡เฆช เฆฏเง‹เฆ— เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "types_removed": "TypeScript เฆŸเฆพเฆ‡เฆช เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "trusted_publisher_added": "เฆฌเฆฟเฆถเงเฆฌเฆธเงเฆค เฆชเงเฆฐเฆ•เฆพเฆถเฆจเฆพ เฆธเฆ•เงเฆฐเฆฟเฆฏเฆผ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "trusted_publisher_removed": "เฆฌเฆฟเฆถเงเฆฌเฆธเงเฆค เฆชเงเฆฐเฆ•เฆพเฆถเฆจเฆพ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "provenance_added": "เฆชเงเฆฐเง‹เฆญเง‡เฆจเงเฆฏเฆพเฆจเงเฆธ เฆธเฆ•เงเฆฐเฆฟเฆฏเฆผ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "provenance_removed": "เฆชเงเฆฐเง‹เฆญเง‡เฆจเงเฆฏเฆพเฆจเงเฆธ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "chart": { + "tab_aria_label": "เฆฎเง‡เฆŸเงเฆฐเฆฟเฆ• เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ", + "base_scale": "y-เฆ…เฆ•เงเฆท เฆถเง‚เฆจเงเฆฏ เฆฅเง‡เฆ•เง‡ เฆถเงเฆฐเง เฆ•เฆฐเงเฆจ", + "zoom": "เฆœเงเฆฎ", + "reset_minimap": "เฆฎเฆฟเฆจเฆฟเฆฎเงเฆฏเฆพเฆช เฆฐเฆฟเฆธเง‡เฆŸ เฆ•เฆฐเงเฆจ", + "ordered_versions": "เฆถเงเฆงเงเฆฎเฆพเฆคเงเฆฐ เฆธเงเฆฅเฆฟเฆคเฆฟเฆถเง€เฆฒ", + "copy_alt": { + "key_changes": "เฆฎเง‚เฆฒ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจเฆธเฆฎเง‚เฆน: {version_events}เฅค", + "version_events": "เฆญเฆพเฆฐเงเฆธเฆจ {version}: {events}", + "general_description": "{package} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ {metric} เฆชเงเฆฐเฆฆเฆฐเงเฆถเฆจเฆ•เฆพเฆฐเง€ เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸ, {first} เฆญเฆพเฆฐเงเฆธเฆจ เฆฅเง‡เฆ•เง‡ {last} เฆญเฆพเฆฐเงเฆธเฆจ เฆชเฆฐเงเฆฏเฆจเงเฆคเฅค {first} เฆญเฆพเฆฐเงเฆธเฆจเง‡ {metric} เฆเฆฐ เฆฎเฆพเฆจ {first_value}, เฆเฆฌเฆ‚ {last} เฆญเฆพเฆฐเงเฆธเฆจเง‡ {last_value} ({overall_progress_percentage}% เฆธเฆพเฆฎเฆ—เงเฆฐเฆฟเฆ• เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ)เฅค {key_changes} {watermark}เฅค" + } + } + }, "dependencies": { "title": "เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ ({count})", "list_label": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ", @@ -621,6 +646,15 @@ "maintainer_template": "{avatar} {char126}{name}" }, "trends": { + "chart_assistive_text": { + "keyboard_navigation_horizontal": "เฆกเง‡เฆŸเฆพ เฆชเฆฏเฆผเง‡เฆจเงเฆŸเฆ—เงเฆฒเง‹เฆฐ เฆฎเฆงเงเฆฏเง‡ เฆฏเง‡เฆคเง‡ เฆฌเฆพเฆฎ เฆเฆฌเฆ‚ เฆกเฆพเฆจ เฆ…เงเฆฏเฆพเฆฐเง‹ เฆ•เง€ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจเฅค", + "keyboard_navigation_vertical": "เฆกเง‡เฆŸเฆพ เฆชเฆฏเฆผเง‡เฆจเงเฆŸเฆ—เงเฆฒเง‹เฆฐ เฆฎเฆงเงเฆฏเง‡ เฆฏเง‡เฆคเง‡ เฆ‰เฆชเฆฐเง‡ เฆเฆฌเฆ‚ เฆจเฆฟเฆšเง‡เฆฐ เฆ…เงเฆฏเฆพเฆฐเง‹ เฆ•เง€ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจเฅค", + "table_available": "เฆเฆ‡ เฆšเฆพเฆฐเงเฆŸเง‡เฆฐ เฆœเฆจเงเฆฏ เฆเฆ•เฆŸเฆฟ เฆกเง‡เฆŸเฆพ เฆŸเง‡เฆฌเฆฟเฆฒ เฆจเฆฟเฆšเง‡ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆฐเฆฏเฆผเง‡เฆ›เง‡เฅค", + "table_caption": "เฆšเฆพเฆฐเงเฆŸ เฆกเง‡เฆŸเฆพ เฆŸเง‡เฆฌเฆฟเฆฒ" + }, + "chart_view_toggle": "เฆญเฆฟเฆ‰ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ เฆ•เฆฐเงเฆจ", + "chart_view_combined": "เฆธเฆฎเฆจเงเฆฌเฆฟเฆค เฆญเฆฟเฆ‰", + "chart_view_split": "เฆฌเฆฟเฆญเฆ•เงเฆค เฆญเฆฟเฆ‰", "granularity": "เฆฌเฆฟเฆธเงเฆคเงƒเฆคเฆฟ", "granularity_daily": "เฆฆเงˆเฆจเฆฟเฆ•", "granularity_weekly": "เฆธเฆพเฆชเงเฆคเฆพเฆนเฆฟเฆ•", @@ -633,36 +667,6 @@ "date_range_multiline": "{start}\nเฆฅเง‡เฆ•เง‡ {end}", "download_file": "{fileType} เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆ•เฆฐเงเฆจ", "toggle_annotator": "เฆ…เงเฆฏเฆพเฆจเง‹เฆŸเง‡เฆŸเฆฐ เฆŸเฆ—เฆฒ เฆ•เฆฐเงเฆจ", - "items": { - "downloads": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก", - "likes": "เฆชเฆ›เฆจเงเฆฆ", - "contributors": "เฆ…เฆฌเฆฆเฆพเฆจเฆ•เฆพเฆฐเง€" - }, - "copy_alt": { - "trend_none": "เฆฎเง‚เฆฒเฆค เฆธเฆฎเฆคเฆฒ", - "trend_strong": "เฆถเฆ•เงเฆคเฆฟเฆถเฆพเฆฒเง€", - "trend_weak": "เฆฆเงเฆฐเงเฆฌเฆฒ", - "trend_undefined": "เฆ…เฆจเฆฟเฆฐเงเฆงเฆพเฆฐเฆฟเฆค (เฆ…เฆชเฆฐเงเฆฏเฆพเฆชเงเฆค เฆกเง‡เฆŸเฆพ)", - "button_label": "เฆฌเฆฟเฆ•เฆฒเงเฆช เฆŸเง‡เฆ•เงเฆธเฆŸ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", - "watermark": "เฆจเฆฟเฆšเง‡ เฆเฆ•เฆŸเฆฟ เฆ“เฆฏเฆผเฆพเฆŸเฆพเฆฐเฆฎเฆพเฆฐเงเฆ•เง‡ เฆฒเง‡เฆ–เฆพ เฆ†เฆ›เง‡ \"./npmx a fast, modern browser for the npm registry\"", - "analysis": "{package_name} เฆเฆฐ เฆถเงเฆฐเง {start_value} เฆฅเง‡เฆ•เง‡ เฆเฆฌเฆ‚ เฆถเง‡เฆท {end_value} เฆ, เฆฏเฆพ เฆชเงเฆฐเฆคเฆฟ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฏเฆผ {downloads_slope} เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆกเง‡เฆฐ เฆขเฆพเฆฒเฆธเฆน เฆเฆ•เฆŸเฆฟ {trend} เฆชเงเฆฐเฆฌเฆฃเฆคเฆพ เฆฆเง‡เฆ–เฆพเฆฏเฆผ", - "estimation": "เฆšเง‚เฆกเฆผเฆพเฆจเงเฆค เฆฎเฆพเฆจเฆŸเฆฟ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฐ เฆ†เฆ‚เฆถเฆฟเฆ• เฆกเง‡เฆŸเฆพเฆฐ เฆ‰เฆชเฆฐ เฆญเฆฟเฆคเงเฆคเฆฟ เฆ•เฆฐเง‡ เฆเฆ•เฆŸเฆฟ เฆ…เฆจเงเฆฎเฆพเฆจเฅค", - "estimations": "เฆšเง‚เฆกเฆผเฆพเฆจเงเฆค เฆฎเฆพเฆจเฆ—เงเฆฒเง‹ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฐ เฆ†เฆ‚เฆถเฆฟเฆ• เฆกเง‡เฆŸเฆพเฆฐ เฆ‰เฆชเฆฐ เฆญเฆฟเฆคเงเฆคเฆฟ เฆ•เฆฐเง‡ เฆ…เฆจเงเฆฎเฆพเฆจ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", - "compare": "{packages} เฆเฆฐ เฆœเฆจเงเฆฏ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆคเงเฆฒเฆจเฆพเฆฎเง‚เฆฒเฆ• เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸเฅค", - "single_package": "{package} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸเฅค", - "general_description": "Y เฆ…เฆ•เงเฆท เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆกเง‡เฆฐ เฆธเฆ‚เฆ–เงเฆฏเฆพ เฆจเฆฟเฆฐเงเฆฆเง‡เฆถ เฆ•เฆฐเง‡เฅค X เฆ…เฆ•เงเฆท {start_date} เฆฅเง‡เฆ•เง‡ {end_date} เฆชเฆฐเงเฆฏเฆจเงเฆค เฆคเฆพเฆฐเฆฟเฆ–เง‡เฆฐ เฆชเฆฐเฆฟเฆธเฆฐ เฆจเฆฟเฆฐเงเฆฆเง‡เฆถ เฆ•เฆฐเง‡, เฆฏเง‡เฆ–เฆพเฆจเง‡ เฆธเฆฎเฆฏเฆผเฆ•เฆพเฆฒ เฆนเฆฒเง‹ {granularity}เฅค {estimation_notice} {packages_analysis}เฅค {watermark}เฅค", - "facet_bar_general_description": "{packages} เฆเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆจเงเฆญเง‚เฆฎเฆฟเฆ• เฆฌเฆพเฆฐ เฆšเฆพเฆฐเงเฆŸ, เฆฏเง‡เฆ–เฆพเฆจเง‡ {facet} ({description}) เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค {facet_analysis} {watermark}เฅค", - "facet_bar_analysis": "{package_name} เฆเฆฐ เฆฎเฆพเฆจ {value}เฅค" - }, - "chart_assistive_text": { - "keyboard_navigation_horizontal": "เฆกเง‡เฆŸเฆพ เฆชเฆฏเฆผเง‡เฆจเงเฆŸเฆ—เงเฆฒเง‹เฆฐ เฆฎเฆงเงเฆฏเง‡ เฆฏเง‡เฆคเง‡ เฆฌเฆพเฆฎ เฆเฆฌเฆ‚ เฆกเฆพเฆจ เฆ…เงเฆฏเฆพเฆฐเง‹ เฆ•เง€ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจเฅค", - "keyboard_navigation_vertical": "เฆกเง‡เฆŸเฆพ เฆชเฆฏเฆผเง‡เฆจเงเฆŸเฆ—เงเฆฒเง‹เฆฐ เฆฎเฆงเงเฆฏเง‡ เฆฏเง‡เฆคเง‡ เฆ‰เฆชเฆฐเง‡ เฆเฆฌเฆ‚ เฆจเฆฟเฆšเง‡เฆฐ เฆ…เงเฆฏเฆพเฆฐเง‹ เฆ•เง€ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจเฅค", - "table_available": "เฆเฆ‡ เฆšเฆพเฆฐเงเฆŸเง‡เฆฐ เฆœเฆจเงเฆฏ เฆเฆ•เฆŸเฆฟ เฆกเง‡เฆŸเฆพ เฆŸเง‡เฆฌเฆฟเฆฒ เฆจเฆฟเฆšเง‡ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆฐเฆฏเฆผเง‡เฆ›เง‡เฅค", - "table_caption": "เฆšเฆพเฆฐเงเฆŸ เฆกเง‡เฆŸเฆพ เฆŸเง‡เฆฌเฆฟเฆฒ" - }, - "chart_view_toggle": "เฆญเฆฟเฆ‰ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ เฆ•เฆฐเงเฆจ", - "chart_view_combined": "เฆธเฆฎเฆจเงเฆฌเฆฟเฆค เฆญเฆฟเฆ‰", - "chart_view_split": "เฆฌเฆฟเฆญเฆ•เงเฆค เฆญเฆฟเฆ‰", "toggle_stack_mode": "เฆธเงเฆŸเงเฆฏเฆพเฆ• เฆฎเง‹เฆก เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ เฆ•เฆฐเงเฆจ", "open_options": "เฆ…เฆชเฆถเฆจ เฆ–เงเฆฒเงเฆจ", "close_options": "เฆ…เฆชเฆถเฆจ เฆฌเฆจเงเฆง เฆ•เฆฐเงเฆจ", @@ -672,6 +676,11 @@ "facet": "เฆฌเฆฟเฆญเฆพเฆ—", "title": "เฆชเงเฆฐเฆฌเฆฃเฆคเฆพ", "contributors_skip": "Contributors-เฆ เฆฆเง‡เฆ–เฆพเฆจเง‹ เฆนเฆฏเฆผเฆจเฆฟ (GitHub เฆฐเฆฟเฆชเง‹เฆœเฆฟเฆŸเฆฐเฆฟ เฆจเง‡เฆ‡):", + "items": { + "downloads": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก", + "likes": "เฆชเฆ›เฆจเงเฆฆ", + "contributors": "เฆ…เฆฌเฆฆเฆพเฆจเฆ•เฆพเฆฐเง€" + }, "data_correction": "เฆกเง‡เฆŸเฆพ เฆธเฆ‚เฆถเง‹เฆงเฆจ", "average_window": "เฆ—เฆกเฆผ เฆ‰เฆ‡เฆจเงเฆกเง‹", "smoothing": "เฆฎเฆธเงƒเฆฃเฆ•เฆฐเฆฃ", @@ -683,7 +692,23 @@ "known_anomalies_range_named": "{packageName}: {start} เฆฅเง‡เฆ•เง‡ {end}", "known_anomalies_none": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆœเฆจเงเฆฏ เฆ•เง‹เฆจเง‹ เฆชเฆฐเฆฟเฆšเฆฟเฆค เฆ…เฆธเงเฆฌเฆพเฆญเฆพเฆฌเฆฟเฆ•เฆคเฆพ เฆจเง‡เฆ‡เฅค | เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆ—เงเฆฒเง‹เฆฐ เฆœเฆจเงเฆฏ เฆ•เง‹เฆจเง‹ เฆชเฆฐเฆฟเฆšเฆฟเฆค เฆ…เฆธเงเฆฌเฆพเฆญเฆพเฆฌเฆฟเฆ•เฆคเฆพ เฆจเง‡เฆ‡เฅค", "known_anomalies_contribute": "เฆ…เฆธเงเฆฌเฆพเฆญเฆพเฆฌเฆฟเฆ•เฆคเฆพเฆฐ เฆกเง‡เฆŸเฆพ เฆฏเง‹เฆ— เฆ•เฆฐเงเฆจ", - "apply_correction": "เฆธเฆ‚เฆถเง‹เฆงเฆจ เฆชเงเฆฐเฆฏเฆผเง‹เฆ— เฆ•เฆฐเงเฆจ" + "apply_correction": "เฆธเฆ‚เฆถเง‹เฆงเฆจ เฆชเงเฆฐเฆฏเฆผเง‹เฆ— เฆ•เฆฐเงเฆจ", + "copy_alt": { + "trend_none": "เฆฎเง‚เฆฒเฆค เฆธเฆฎเฆคเฆฒ", + "trend_strong": "เฆถเฆ•เงเฆคเฆฟเฆถเฆพเฆฒเง€", + "trend_weak": "เฆฆเงเฆฐเงเฆฌเฆฒ", + "trend_undefined": "เฆ…เฆจเฆฟเฆฐเงเฆงเฆพเฆฐเฆฟเฆค (เฆ…เฆชเฆฐเงเฆฏเฆพเฆชเงเฆค เฆกเง‡เฆŸเฆพ)", + "button_label": "เฆฌเฆฟเฆ•เฆฒเงเฆช เฆŸเง‡เฆ•เงเฆธเฆŸ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", + "watermark": "เฆจเฆฟเฆšเง‡ เฆเฆ•เฆŸเฆฟ เฆ“เฆฏเฆผเฆพเฆŸเฆพเฆฐเฆฎเฆพเฆฐเงเฆ•เง‡ เฆฒเง‡เฆ–เฆพ เฆ†เฆ›เง‡ \"./npmx a fast, modern browser for the npm registry\"", + "analysis": "{package_name} เฆเฆฐ เฆถเงเฆฐเง {start_value} เฆฅเง‡เฆ•เง‡ เฆเฆฌเฆ‚ เฆถเง‡เฆท {end_value} เฆ, เฆฏเฆพ เฆชเงเฆฐเฆคเฆฟ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฏเฆผ {downloads_slope} เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆกเง‡เฆฐ เฆขเฆพเฆฒเฆธเฆน เฆเฆ•เฆŸเฆฟ {trend} เฆชเงเฆฐเฆฌเฆฃเฆคเฆพ เฆฆเง‡เฆ–เฆพเฆฏเฆผ", + "estimation": "เฆšเง‚เฆกเฆผเฆพเฆจเงเฆค เฆฎเฆพเฆจเฆŸเฆฟ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฐ เฆ†เฆ‚เฆถเฆฟเฆ• เฆกเง‡เฆŸเฆพเฆฐ เฆ‰เฆชเฆฐ เฆญเฆฟเฆคเงเฆคเฆฟ เฆ•เฆฐเง‡ เฆเฆ•เฆŸเฆฟ เฆ…เฆจเงเฆฎเฆพเฆจเฅค", + "estimations": "เฆšเง‚เฆกเฆผเฆพเฆจเงเฆค เฆฎเฆพเฆจเฆ—เงเฆฒเง‹ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆธเฆฎเฆฏเฆผเฆธเง€เฆฎเฆพเฆฐ เฆ†เฆ‚เฆถเฆฟเฆ• เฆกเง‡เฆŸเฆพเฆฐ เฆ‰เฆชเฆฐ เฆญเฆฟเฆคเงเฆคเฆฟ เฆ•เฆฐเง‡ เฆ…เฆจเงเฆฎเฆพเฆจ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", + "compare": "{packages} เฆเฆฐ เฆœเฆจเงเฆฏ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆคเงเฆฒเฆจเฆพเฆฎเง‚เฆฒเฆ• เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸเฅค", + "single_package": "{package} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸเฅค", + "general_description": "Y เฆ…เฆ•เงเฆท เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆกเง‡เฆฐ เฆธเฆ‚เฆ–เงเฆฏเฆพ เฆจเฆฟเฆฐเงเฆฆเง‡เฆถ เฆ•เฆฐเง‡เฅค X เฆ…เฆ•เงเฆท {start_date} เฆฅเง‡เฆ•เง‡ {end_date} เฆชเฆฐเงเฆฏเฆจเงเฆค เฆคเฆพเฆฐเฆฟเฆ–เง‡เฆฐ เฆชเฆฐเฆฟเฆธเฆฐ เฆจเฆฟเฆฐเงเฆฆเง‡เฆถ เฆ•เฆฐเง‡, เฆฏเง‡เฆ–เฆพเฆจเง‡ เฆธเฆฎเฆฏเฆผเฆ•เฆพเฆฒ เฆนเฆฒเง‹ {granularity}เฅค {estimation_notice} {packages_analysis}เฅค {watermark}เฅค", + "facet_bar_general_description": "{packages} เฆเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆจเงเฆญเง‚เฆฎเฆฟเฆ• เฆฌเฆพเฆฐ เฆšเฆพเฆฐเงเฆŸ, เฆฏเง‡เฆ–เฆพเฆจเง‡ {facet} ({description}) เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค {facet_analysis} {watermark}เฅค", + "facet_bar_analysis": "{package_name} เฆเฆฐ เฆฎเฆพเฆจ {value}เฅค" + } }, "downloads": { "title": "เฆธเฆพเฆชเงเฆคเฆพเฆนเฆฟเฆ• เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก", @@ -705,11 +730,11 @@ "esm": "ES Modules เฆธเฆฎเฆฐเงเฆฅเฆจ เฆ†เฆ›เง‡", "cjs": "CommonJS เฆธเฆฎเฆฐเงเฆฅเฆจ เฆ†เฆ›เง‡", "no_esm": "ES Modules เฆธเฆฎเฆฐเงเฆฅเฆจ เฆจเง‡เฆ‡", + "wasm": "WebAssembly เฆฐเฆฏเฆผเง‡เฆ›เง‡", "types_label": "เฆŸเฆพเฆ‡เฆช", "types_included": "เฆŸเฆพเฆ‡เฆช เฆ…เฆจเงเฆคเฆฐเงเฆญเงเฆ•เงเฆค", "types_available": "เฆŸเฆพเฆ‡เฆช {package} เฆเฆฐ เฆฎเฆพเฆงเงเฆฏเฆฎเง‡ เฆ‰เฆชเฆฒเฆฌเงเฆง", - "no_types": "TypeScript เฆŸเฆพเฆ‡เฆช เฆจเง‡เฆ‡", - "wasm": "WebAssembly เฆฐเฆฏเฆผเง‡เฆ›เง‡" + "no_types": "TypeScript เฆŸเฆพเฆ‡เฆช เฆจเง‡เฆ‡" }, "license": { "view_spdx": "SPDX เฆ เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ เฆŸเง‡เฆ•เงเฆธเฆŸ เฆฆเง‡เฆ–เงเฆจ", @@ -771,9 +796,9 @@ }, "sort": { "downloads": "เฆธเฆฌเฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆกเฆ•เงƒเฆค", + "published": "เฆธเฆฎเงเฆชเงเฆฐเฆคเฆฟ เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", "name_asc": "เฆจเฆพเฆฎ (A-Z)", - "name_desc": "เฆจเฆพเฆฎ (Z-A)", - "published": "เฆธเฆฎเงเฆชเงเฆฐเฆคเฆฟ เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค" + "name_desc": "เฆจเฆพเฆฎ (Z-A)" }, "size": { "b": "{size} B", @@ -783,35 +808,16 @@ "download": { "button": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก", "tarball": ".tar.gz เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆŸเฆพเฆฐเฆฌเฆฒ เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก เฆ•เฆฐเงเฆจ" - }, - "timeline": { - "load_more": "เฆ†เฆฐเง‹ เฆฒเง‹เฆก เฆ•เฆฐเงเฆจ", - "load_error": "เฆŸเฆพเฆ‡เฆฎเฆฒเฆพเฆ‡เฆจ เฆฒเง‹เฆก เฆ•เฆฐเฆพ เฆฏเฆพเฆฏเฆผเฆจเฆฟเฅค เฆ…เฆจเงเฆ—เงเฆฐเฆน เฆ•เฆฐเง‡ เฆชเฆฐเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจเฅค", - "size_increase": "เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆธเฆพเฆ‡เฆœ {percent}% เฆฌเงƒเฆฆเงเฆงเฆฟ เฆชเง‡เฆฏเฆผเง‡เฆ›เง‡ ({size})", - "size_decrease": "เฆ‡เฆจเฆธเงเฆŸเฆฒ เฆธเฆพเฆ‡เฆœ {percent}% เฆ•เฆฎเง‡เฆ›เง‡ ({size})", - "dep_increase": "{count}เฆŸเฆฟ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆฏเง‹เฆ— เฆนเฆฏเฆผเง‡เฆ›เง‡", - "dep_decrease": "{count}เฆŸเฆฟ เฆกเฆฟเฆชเง‡เฆจเฆกเง‡เฆจเงเฆธเฆฟ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "license_change": "เฆฒเฆพเฆ‡เฆธเง‡เฆจเงเฆธ {from} เฆฅเง‡เฆ•เง‡ {to} เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", - "esm_added": "เฆฎเฆกเฆฟเฆ‰เฆฒ เฆŸเฆพเฆ‡เฆช ESM เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", - "esm_removed": "เฆฎเฆกเฆฟเฆ‰เฆฒ เฆŸเฆพเฆ‡เฆช ESM เฆฅเง‡เฆ•เง‡ CJS เฆ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡", - "types_added": "TypeScript เฆŸเฆพเฆ‡เฆช เฆฏเง‹เฆ— เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "types_removed": "TypeScript เฆŸเฆพเฆ‡เฆช เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "trusted_publisher_added": "เฆฌเฆฟเฆถเงเฆฌเฆธเงเฆค เฆชเงเฆฐเฆ•เฆพเฆถเฆจเฆพ เฆธเฆ•เงเฆฐเฆฟเฆฏเฆผ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "trusted_publisher_removed": "เฆฌเฆฟเฆถเงเฆฌเฆธเงเฆค เฆชเงเฆฐเฆ•เฆพเฆถเฆจเฆพ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "provenance_added": "เฆชเงเฆฐเง‹เฆญเง‡เฆจเงเฆฏเฆพเฆจเงเฆธ เฆธเฆ•เงเฆฐเฆฟเฆฏเฆผ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "provenance_removed": "เฆชเงเฆฐเง‹เฆญเง‡เฆจเงเฆฏเฆพเฆจเงเฆธ เฆธเฆฐเฆพเฆจเง‹ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "chart": { - "tab_aria_label": "เฆฎเง‡เฆŸเงเฆฐเฆฟเฆ• เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ", - "base_scale": "y-เฆ…เฆ•เงเฆท เฆถเง‚เฆจเงเฆฏ เฆฅเง‡เฆ•เง‡ เฆถเงเฆฐเง เฆ•เฆฐเงเฆจ", - "zoom": "เฆœเงเฆฎ", - "reset_minimap": "เฆฎเฆฟเฆจเฆฟเฆฎเงเฆฏเฆพเฆช เฆฐเฆฟเฆธเง‡เฆŸ เฆ•เฆฐเงเฆจ", - "ordered_versions": "เฆถเงเฆงเงเฆฎเฆพเฆคเงเฆฐ เฆธเงเฆฅเฆฟเฆคเฆฟเฆถเง€เฆฒ", - "copy_alt": { - "key_changes": "เฆฎเง‚เฆฒ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจเฆธเฆฎเง‚เฆน: {version_events}เฅค", - "version_events": "เฆญเฆพเฆฐเงเฆธเฆจ {version}: {events}", - "general_description": "{package} เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ {metric} เฆชเงเฆฐเฆฆเฆฐเงเฆถเฆจเฆ•เฆพเฆฐเง€ เฆฒเฆพเฆ‡เฆจ เฆšเฆพเฆฐเงเฆŸ, {first} เฆญเฆพเฆฐเงเฆธเฆจ เฆฅเง‡เฆ•เง‡ {last} เฆญเฆพเฆฐเงเฆธเฆจ เฆชเฆฐเงเฆฏเฆจเงเฆคเฅค {first} เฆญเฆพเฆฐเงเฆธเฆจเง‡ {metric} เฆเฆฐ เฆฎเฆพเฆจ {first_value}, เฆเฆฌเฆ‚ {last} เฆญเฆพเฆฐเงเฆธเฆจเง‡ {last_value} ({overall_progress_percentage}% เฆธเฆพเฆฎเฆ—เงเฆฐเฆฟเฆ• เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ)เฅค {key_changes} {watermark}เฅค" - } - } + } + }, + "leaderboard": { + "likes": { + "title": "เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก", + "description": "เฆฌเฆฐเงเฆคเฆฎเฆพเฆจเง‡ npmx-เฆเฆฐ เฆธเฆฌเฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ เฆฒเฆพเฆ‡เฆ• เฆชเฆพเฆ“เฆฏเฆผเฆพ เงงเงฆเฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฅค", + "rank": "เฆฐโ€เงเฆฏเฆพเฆ™เงเฆ•", + "likes": "เฆฒเฆพเฆ‡เฆ•", + "unavailable_title": "เฆเฆ–เฆจเฆ“ เฆ•เง‹เฆจเง‹ เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก เฆจเง‡เฆ‡", + "unavailable_description": "เฆเฆ‡ เฆฎเงเฆนเง‚เฆฐเงเฆคเง‡ เฆฆเง‡เฆ–เฆพเฆจเง‹เฆฐ เฆฎเฆคเง‹ เฆ•เง‹เฆจเง‹ เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก เฆจเง‡เฆ‡เฅค" } }, "connector": { @@ -849,7 +855,9 @@ "otp_placeholder": "OTP เฆ•เง‹เฆก เฆฆเฆฟเฆจ...", "otp_label": "เฆเฆ•เฆฌเฆพเฆฐ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐเง‡เฆฐ เฆชเฆพเฆธเฆ“เฆฏเฆผเฆพเฆฐเงเฆก", "retry_otp": "OTP เฆฆเฆฟเงŸเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจ", + "retry_web_auth": "เฆ“เฆฏเฆผเง‡เฆฌ เฆ…เฆฅ เฆฆเฆฟเฆฏเฆผเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจ", "retrying": "เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเฆพ เฆนเฆšเงเฆ›เง‡...", + "open_web_auth": "เฆ“เฆฏเฆผเง‡เฆฌ เฆ…เฆฅ เฆฒเฆฟเฆ‚เฆ• เฆ–เงเฆฒเงเฆจ", "approve_operation": "เฆ…เฆชเฆพเฆฐเง‡เฆถเฆจ เฆ…เฆจเงเฆฎเง‹เฆฆเฆจ เฆ•เฆฐเงเฆจ", "remove_operation": "เฆ…เฆชเฆพเฆฐเง‡เฆถเฆจ เฆธเฆฐเฆพเฆจ", "approve_all": "เฆธเฆฌ เฆ…เฆจเงเฆฎเง‹เฆฆเฆจ เฆ•เฆฐเงเฆจ", @@ -857,9 +865,7 @@ "executing": "เฆšเฆพเฆฒเฆพเฆจเง‹ เฆนเฆšเงเฆ›เง‡...", "log": "เฆฒเฆ—", "log_label": "เฆธเฆฎเงเฆชเง‚เฆฐเงเฆฃ เฆ…เฆชเฆพเฆฐเง‡เฆถเฆจ เฆฒเฆ—", - "remove_from_log": "เฆฒเฆ— เฆฅเง‡เฆ•เง‡ เฆธเฆฐเฆพเฆจ", - "retry_web_auth": "เฆ“เฆฏเฆผเง‡เฆฌ เฆ…เฆฅ เฆฆเฆฟเฆฏเฆผเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจ", - "open_web_auth": "เฆ“เฆฏเฆผเง‡เฆฌ เฆ…เฆฅ เฆฒเฆฟเฆ‚เฆ• เฆ–เงเฆฒเงเฆจ" + "remove_from_log": "เฆฒเฆ— เฆฅเง‡เฆ•เง‡ เฆธเฆฐเฆพเฆจ" } }, "org": { @@ -973,6 +979,7 @@ "invalid_name": "เฆ…เฆฌเงˆเฆง เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆพเฆฎ:", "available": "เฆเฆ‡ เฆจเฆพเฆฎเฆŸเฆฟ เฆ‰เฆชเฆฒเฆฌเงเฆง!", "taken": "เฆเฆ‡ เฆจเฆพเฆฎเฆŸเฆฟ เฆ‡เฆคเฆฟเฆฎเฆงเงเฆฏเง‡ เฆจเง‡เฆ“เฆฏเฆผเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", + "missing_permission": "เฆ†เฆชเฆจเฆพเฆฐ เฆ•เฆพเฆ›เง‡ {'@'}{scope} เฆธเงเฆ•เง‹เฆชเง‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฏเง‹เฆ— เฆ•เฆฐเฆพเฆฐ เฆ…เฆจเงเฆฎเฆคเฆฟ เฆจเง‡เฆ‡เฅค", "similar_warning": "เฆธเฆฎเฆพเฆจ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฐเฆฏเฆผเง‡เฆ›เง‡ - npm เฆเฆ‡ เฆจเฆพเฆฎเฆŸเฆฟ เฆชเงเฆฐเฆคเงเฆฏเฆพเฆ–เงเฆฏเฆพเฆจ เฆ•เฆฐเฆคเง‡ เฆชเฆพเฆฐเง‡:", "related": "เฆธเฆ‚เฆถเงเฆฒเฆฟเฆทเงเฆŸ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ:", "scope_warning_title": "เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเง‡ เฆธเงเฆ•เง‹เฆชเฆก เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆฌเฆฟเฆฌเง‡เฆšเฆจเฆพ เฆ•เฆฐเงเฆจ", @@ -985,8 +992,7 @@ "publishing": "เฆชเงเฆฐเฆ•เฆพเฆถ เฆ•เฆฐเฆพ เฆนเฆšเงเฆ›เง‡...", "checking": "เฆชเงเฆฐเฆพเฆชเงเฆฏเฆคเฆพ เฆฏเฆพเฆšเฆพเฆ‡ เฆ•เฆฐเฆพ เฆนเฆšเงเฆ›เง‡...", "failed_to_check": "เฆจเฆพเฆฎเง‡เฆฐ เฆชเงเฆฐเฆพเฆชเงเฆฏเฆคเฆพ เฆฏเฆพเฆšเฆพเฆ‡ เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅ", - "failed_to_claim": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฆเฆพเฆฌเฆฟ เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅ", - "missing_permission": "เฆ†เฆชเฆจเฆพเฆฐ เฆ•เฆพเฆ›เง‡ {'@'}{scope} เฆธเงเฆ•เง‹เฆชเง‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฏเง‹เฆ— เฆ•เฆฐเฆพเฆฐ เฆ…เฆจเงเฆฎเฆคเฆฟ เฆจเง‡เฆ‡เฅค" + "failed_to_claim": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฆเฆพเฆฌเฆฟ เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅ" } }, "code": { @@ -995,8 +1001,12 @@ "lines": "{count}เฆŸเฆฟ เฆฒเฆพเฆ‡เฆจ", "toggle_tree": "เฆซเฆพเฆ‡เฆฒ เฆŸเงเฆฐเฆฟ เฆŸเฆ—เฆฒ เฆ•เฆฐเงเฆจ", "close_tree": "เฆซเฆพเฆ‡เฆฒ เฆŸเงเฆฐเฆฟ เฆฌเฆจเงเฆง เฆ•เฆฐเงเฆจ", + "copy_content": "เฆซเฆพเฆ‡เฆฒ เฆ•เฆจเงเฆŸเง‡เฆจเงเฆŸ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "copy_link": "เฆฒเฆฟเฆ™เงเฆ• เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "view_raw": "เฆฐเฆ“ เฆซเฆพเฆ‡เฆฒ เฆฆเง‡เฆ–เงเฆจ", + "toggle_container": "เฆ•เง‹เฆก เฆ•เฆจเงเฆŸเง‡เฆ‡เฆจเฆพเฆฐ เฆชเงเฆฐเฆธเงเฆฅ เฆŸเฆ—เฆฒ เฆ•เฆฐเงเฆจ", + "open_raw_file": "เฆฐเฆ“ เฆซเฆพเฆ‡เฆฒ เฆ–เงเฆฒเงเฆจ", + "open_path_dropdown": "เฆชเฆพเฆฅ เฆธเง‡เฆ—เฆฎเง‡เฆจเงเฆŸเฆธ เฆกเงเฆฐเฆชเฆกเฆพเฆ‰เฆจ เฆ–เงเฆฒเงเฆจ", "file_too_large": "เฆชเงเฆฐเฆฟเฆญเฆฟเฆ‰-เฆฐ เฆœเฆจเงเฆฏ เฆซเฆพเฆ‡เฆฒ เฆ–เงเฆฌ เฆฌเฆกเฆผ", "file_size_warning": "{size} เฆธเฆฟเฆจเฆŸเงเฆฏเฆพเฆ•เงเฆธ เฆนเฆพเฆ‡เฆฒเฆพเฆ‡เฆŸเฆฟเฆ‚-เฆเฆฐ เฆœเฆจเงเฆฏ 500KB เฆธเง€เฆฎเฆพเฆฐ เฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ", "failed_to_load": "เฆซเฆพเฆ‡เฆฒ เฆฒเง‹เฆก เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅ", @@ -1015,10 +1025,6 @@ "code": "เฆ•เง‹เฆก" }, "file_path": "เฆซเฆพเฆ‡เฆฒ เฆชเฆพเฆฅ", - "copy_content": "เฆซเฆพเฆ‡เฆฒ เฆ•เฆจเงเฆŸเง‡เฆจเงเฆŸ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", - "toggle_container": "เฆ•เง‹เฆก เฆ•เฆจเงเฆŸเง‡เฆ‡เฆจเฆพเฆฐ เฆชเงเฆฐเฆธเงเฆฅ เฆŸเฆ—เฆฒ เฆ•เฆฐเงเฆจ", - "open_raw_file": "เฆฐเฆ“ เฆซเฆพเฆ‡เฆฒ เฆ–เงเฆฒเงเฆจ", - "open_path_dropdown": "เฆชเฆพเฆฅ เฆธเง‡เฆ—เฆฎเง‡เฆจเงเฆŸเฆธ เฆกเงเฆฐเฆชเฆกเฆพเฆ‰เฆจ เฆ–เงเฆฒเงเฆจ", "binary_file": "เฆฌเฆพเฆ‡เฆจเฆพเฆฐเฆฟ เฆซเฆพเฆ‡เฆฒ", "binary_rendering_warning": "เฆซเฆพเฆ‡เฆฒ เฆŸเฆพเฆ‡เฆช \"{contentType}\" เฆชเงเฆฐเฆฟเฆญเฆฟเฆ‰เฆฏเฆผเง‡เฆฐ เฆœเฆจเงเฆฏ เฆธเฆฎเฆฐเงเฆฅเฆฟเฆค เฆจเฆฏเฆผ." }, @@ -1082,6 +1088,8 @@ "secure": "เฆธเฆคเฆฐเงเฆ•เฆคเฆพ เฆ›เฆพเฆกเฆผเฆพ", "insecure": "เฆธเฆคเฆฐเงเฆ•เฆคเฆพ เฆธเฆน" }, + "view_selected": "เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆฆเง‡เฆ–เงเฆจ", + "clear_selected_label": "เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆธเฆพเฆซ เฆ•เฆฐเงเฆจ", "sort": { "label": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆ—เงเฆฒเฆฟ เฆธเฆพเฆœเฆพเฆจ", "toggle_direction": "เฆ•เงเฆฐเฆฎ เฆฆเฆฟเฆ• เฆŸเฆ—เฆฒ เฆ•เฆฐเงเฆจ", @@ -1092,8 +1100,8 @@ "downloads_day": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก/เฆฆเฆฟเฆจ", "downloads_month": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก/เฆฎเฆพเฆธ", "downloads_year": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก/เฆฌเฆ›เฆฐ", - "name": "เฆจเฆพเฆฎ", - "published": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค" + "published": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", + "name": "เฆจเฆพเฆฎ" }, "columns": { "title": "เฆ•เฆฒเฆพเฆฎ", @@ -1104,10 +1112,10 @@ "version": "เฆญเฆพเฆฐเงเฆธเฆจ", "description": "เฆฌเฆฐเงเฆฃเฆจเฆพ", "downloads": "เฆกเฆพเฆ‰เฆจเฆฒเง‹เฆก/เฆธเฆชเงเฆคเฆพเฆน", + "published": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", "maintainers": "เฆฐเฆ•เงเฆทเฆฃเฆพเฆฌเง‡เฆ•เงเฆทเฆฃเฆ•เฆพเฆฐเง€", "keywords": "เฆ•เง€เฆ“เฆฏเฆผเฆพเฆฐเงเฆก", "security": "เฆจเฆฟเฆฐเฆพเฆชเฆคเงเฆคเฆพ", - "published": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆชเงเฆฐเฆ•เฆพเฆถเฆฟเฆค", "selection": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ" }, "view_mode": { @@ -1135,9 +1143,7 @@ "security_warning": "เฆจเฆฟเฆฐเฆพเฆชเฆคเงเฆคเฆพ เฆธเฆคเฆฐเงเฆ•เฆคเฆพ", "secure": "เฆจเฆฟเฆฐเฆพเฆชเฆฆ", "no_packages": "เฆ•เง‹เฆจเง‹ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆชเฆพเฆ“เฆฏเฆผเฆพ เฆฏเฆพเฆฏเฆผเฆจเฆฟ" - }, - "view_selected": "เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆฆเง‡เฆ–เงเฆจ", - "clear_selected_label": "เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆธเฆพเฆซ เฆ•เฆฐเงเฆจ" + } }, "about": { "title": "เฆ†เฆฎเฆพเฆฆเง‡เฆฐ เฆธเฆฎเงเฆชเฆฐเงเฆ•เง‡", @@ -1270,11 +1276,11 @@ "section_packages": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ", "section_facets": "เฆซเงเฆฏเฆพเฆธเง‡เฆŸ", "section_comparison": "เฆคเงเฆฒเฆจเฆพ", + "copy_as_markdown": "เฆฎเฆพเฆฐเงเฆ•เฆกเฆพเฆ‰เฆจ เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "loading": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆกเง‡เฆŸเฆพ เฆฒเง‹เฆก เฆนเฆšเงเฆ›เง‡...", "error": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆกเง‡เฆŸเฆพ เฆฒเง‹เฆก เฆ•เฆฐเฆคเง‡ เฆฌเงเฆฏเฆฐเงเฆฅเฅค เฆ…เฆจเงเฆ—เงเฆฐเฆน เฆ•เฆฐเง‡ เฆ†เฆฌเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเงเฆจเฅค", "empty_title": "เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเฆพเฆฐ เฆœเฆจเงเฆฏ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", "empty_description": "เฆคเฆพเฆฆเง‡เฆฐ เฆฎเง‡เฆŸเงเฆฐเฆฟเฆ•เงเฆธ เฆชเฆพเฆถเฆพเฆชเฆพเฆถเฆฟ เฆคเงเฆฒเฆจเฆพ เฆฆเง‡เฆ–เฆคเง‡ เฆ‰เฆชเฆฐเง‡ เฆ•เฆฎเฆชเฆ•เงเฆทเง‡ เงจเฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆ…เฆจเงเฆธเฆจเงเฆงเฆพเฆจ เฆ•เฆฐเง‡ เฆฏเง‹เฆ— เฆ•เฆฐเงเฆจเฅค", - "copy_as_markdown": "เฆฎเฆพเฆฐเงเฆ•เฆกเฆพเฆ‰เฆจ เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "table_view": "เฆŸเง‡เฆฌเฆฟเฆฒ", "charts_view": "เฆšเฆพเฆฐเงเฆŸ", "no_chartable_data": "เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆซเงเฆฏเฆพเฆธเง‡เฆŸเฆ—เงเฆฒเง‹เฆฐ เฆœเฆจเงเฆฏ เฆ•เง‹เฆจเง‹ เฆšเฆพเฆฐเงเฆŸเฆฏเง‹เฆ—เงเฆฏ เฆกเง‡เฆŸเฆพ เฆ‰เฆชเฆฒเฆฌเงเฆง เฆจเง‡เฆ‡เฅค", @@ -1290,6 +1296,17 @@ "packages_selected": "{count}/{max}เฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆคเฅค", "add_hint": "เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเฆพเฆฐ เฆœเฆจเงเฆฏ เฆ•เฆฎเฆชเฆ•เงเฆทเง‡ เงจเฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœ เฆฏเง‹เฆ— เฆ•เฆฐเงเฆจเฅค" }, + "scatter_chart": { + "title": "{x} เฆฌเฆจเฆพเฆฎ {y} เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเงเฆจ", + "freshness_score": "เฆจเฆคเงเฆจเฆคเงเฆฌ เฆธเงเฆ•เง‹เฆฐ", + "copy_alt": { + "analysis": "{package}: {x_name} ({x_value}) เฆเฆฌเฆ‚ {y_name} ({y_value})", + "description": "{packages}เฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆœเฆจเงเฆฏ {x_name} เฆฌเฆจเฆพเฆฎ {y_name} เฆเฆฐ เฆธเงเฆ•เงเฆฏเฆพเฆŸเฆพเฆฐ เฆชเงเฆฒเฆŸ เฆšเฆพเฆฐเงเฆŸเฅค {analysis}. {watermark}" + }, + "filename": "{x}-vs-{y}-scatter-chart", + "x_axis": "X-เฆ…เฆ•เงเฆท โ†ฆ", + "y_axis": "Y-เฆ…เฆ•เงเฆท โ†ฅ" + }, "no_dependency": { "label": "(เฆ•เง‹เฆจเง‹ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ เฆจเง‡เฆ‡)", "typeahead_title": "เฆœเง‡เฆฎเฆธ เฆ•เง€ เฆ•เฆฐเฆคเง‡เฆจ?", @@ -1302,9 +1319,14 @@ "facets": { "all": "เฆธเฆฌ", "none": "เฆ•เฆฟเฆ›เง เฆจเฆพ", + "select_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", + "deselect_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆฌเฆพเฆคเฆฟเฆฒ เฆ•เฆฐเงเฆจ", + "selected_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", + "deselected_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆฌเฆพเฆคเฆฟเฆฒ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", "coming_soon": "เฆถเง€เฆ˜เงเฆฐเฆ‡ เฆ†เฆธเฆ›เง‡", "select_all": "เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", "deselect_all": "เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆ…เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค เฆ•เฆฐเงเฆจ", + "binary_only_tooltip": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟ เฆฌเฆพเฆ‡เฆจเฆพเฆฐเฆฟ เฆธเฆฐเฆฌเฆฐเฆพเฆน เฆ•เฆฐเง‡ เฆเฆฌเฆ‚ เฆ•เง‹เฆจเง‹ เฆเฆ•เงเฆธเฆชเง‹เฆฐเงเฆŸ เฆจเง‡เฆ‡", "categories": { "performance": "เฆ•เฆฐเงเฆฎเฆ•เงเฆทเฆฎเฆคเฆพ", "health": "เฆธเงเฆฌเฆพเฆธเงเฆฅเงเฆฏ", @@ -1390,50 +1412,21 @@ }, "trends": { "title": "เฆชเงเฆฐเฆฌเฆฃเฆคเฆพ เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเงเฆจ" - }, - "select_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", - "deselect_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆฌเฆพเฆคเฆฟเฆฒ เฆ•เฆฐเงเฆจ", - "selected_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "deselected_all_category_facets": "{category}-เฆเฆฐ เฆธเฆฌ เฆซเงเฆฏเฆพเฆธเง‡เฆŸ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆฌเฆพเฆคเฆฟเฆฒ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡", - "binary_only_tooltip": "เฆเฆ‡ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฆŸเฆฟ เฆฌเฆพเฆ‡เฆจเฆพเฆฐเฆฟ เฆธเฆฐเฆฌเฆฐเฆพเฆน เฆ•เฆฐเง‡ เฆเฆฌเฆ‚ เฆ•เง‹เฆจเง‹ เฆเฆ•เงเฆธเฆชเง‹เฆฐเงเฆŸ เฆจเง‡เฆ‡" - }, - "version_invalid_url_format": { - "hint": "เฆ…เฆฌเงˆเฆง เฆคเงเฆฒเฆจเฆพ URLเฅค เฆเฆ‡ เฆซเฆฐเฆฎเงเฆฏเฆพเฆŸ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจ: {0}", - "from_version": "เฆฅเง‡เฆ•เง‡", - "to_version": "เฆชเฆฐเงเฆฏเฆจเงเฆค" - }, - "file_filter_option": { - "all": "เฆธเฆฌ ({count})", - "added": "เฆฏเง‹เฆ— เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡ ({count})", - "removed": "เฆฎเงเฆ›เง‡ เฆซเง‡เฆฒเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡ ({count})", - "modified": "เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค ({count})" - }, - "filter": { - "added": "เฆฏเง‹เฆ— เฆ•เฆฐเฆพ", - "removed": "เฆฎเงเฆ›เง‡ เฆซเง‡เฆฒเฆพ", - "modified": "เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค" - }, - "scatter_chart": { - "title": "{x} เฆฌเฆจเฆพเฆฎ {y} เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเงเฆจ", - "freshness_score": "เฆจเฆคเงเฆจเฆคเงเฆฌ เฆธเงเฆ•เง‹เฆฐ", - "copy_alt": { - "analysis": "{package}: {x_name} ({x_value}) เฆเฆฌเฆ‚ {y_name} ({y_value})", - "description": "{packages}เฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡เฆฐ เฆœเฆจเงเฆฏ {x_name} เฆฌเฆจเฆพเฆฎ {y_name} เฆเฆฐ เฆธเงเฆ•เงเฆฏเฆพเฆŸเฆพเฆฐ เฆชเงเฆฒเฆŸ เฆšเฆพเฆฐเงเฆŸเฅค {analysis}. {watermark}" - }, - "filename": "{x}-vs-{y}-scatter-chart", - "x_axis": "X-เฆ…เฆ•เงเฆท โ†ฆ", - "y_axis": "Y-เฆ…เฆ•เงเฆท โ†ฅ" + } }, "file_changes": "เฆซเฆพเฆ‡เฆฒ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ", "files_count": "{count}เฆŸเฆฟ เฆซเฆพเฆ‡เฆฒ | {count}เฆŸเฆฟ เฆซเฆพเฆ‡เฆฒ", "lines_hidden": "{count}เฆŸเฆฟ เฆฒเฆพเฆ‡เฆจ เฆฒเงเฆ•เฆพเฆจเง‹ | {count}เฆŸเฆฟ เฆฒเฆพเฆ‡เฆจ เฆฒเงเฆ•เฆพเฆจเง‹", - "file_too_large": "เฆคเงเฆฒเฆจเฆพเฆฐ เฆœเฆจเงเฆฏ เฆซเฆพเฆ‡เฆฒเฆŸเฆฟ เฆ–เงเฆฌ เฆฌเฆกเฆผ", - "file_size_warning": "{size} เฆคเงเฆฒเฆจเฆพเฆฐ 250KB เฆธเง€เฆฎเฆพ เฆ…เฆคเฆฟเฆ•เงเฆฐเฆฎ เฆ•เฆฐเง‡เฆ›เง‡", "compare_versions": "เฆกเฆฟเฆซ", "compare_versions_title": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆธเฆ‚เฆธเงเฆ•เฆฐเฆฃเง‡เฆฐ เฆธเฆพเฆฅเง‡ เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเงเฆจ", "comparing_versions_label": "เฆธเฆ‚เฆธเงเฆ•เฆฐเฆฃ เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเฆพ เฆนเฆšเงเฆ›เง‡...", "version_back_to_package": "เฆชเงเฆฏเฆพเฆ•เง‡เฆœเง‡ เฆซเฆฟเฆฐเง‡ เฆฏเฆพเฆจ", "version_error_message": "เฆธเฆ‚เฆธเงเฆ•เฆฐเฆฃ เฆคเงเฆฒเฆจเฆพ เฆฌเงเฆฏเฆฐเงเฆฅ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", + "version_invalid_url_format": { + "hint": "เฆ…เฆฌเงˆเฆง เฆคเงเฆฒเฆจเฆพ URLเฅค เฆเฆ‡ เฆซเฆฐเฆฎเงเฆฏเฆพเฆŸ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเงเฆจ: {0}", + "from_version": "เฆฅเง‡เฆ•เง‡", + "to_version": "เฆชเฆฐเงเฆฏเฆจเงเฆค" + }, "version_selector_title": "เฆธเฆ‚เฆธเงเฆ•เฆฐเฆฃเง‡เฆฐ เฆธเฆพเฆฅเง‡ เฆคเงเฆฒเฆจเฆพ เฆ•เฆฐเงเฆจ", "summary": "เฆธเฆพเฆฐเฆพเฆ‚เฆถ", "deps_count": "{count}เฆŸเฆฟ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ | {count}เฆŸเฆฟ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ", @@ -1442,10 +1435,21 @@ "peer_dependencies": "เฆชเฆฟเฆฏเฆผเฆพเฆฐ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ", "optional_dependencies": "เฆเฆšเงเฆ›เฆฟเฆ• เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ", "no_dependency_changes": "เฆ•เง‹เฆจเง‹ เฆจเฆฟเฆฐเงเฆญเฆฐเฆคเฆพ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ เฆจเง‡เฆ‡", + "file_filter_option": { + "all": "เฆธเฆฌ ({count})", + "added": "เฆฏเง‹เฆ— เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡ ({count})", + "removed": "เฆฎเงเฆ›เง‡ เฆซเง‡เฆฒเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡ ({count})", + "modified": "เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค ({count})" + }, "search_files_placeholder": "เฆซเฆพเฆ‡เฆฒ เฆ–เงเฆเฆœเงเฆจ...", "no_files_all": "เฆ•เง‹เฆจเง‹ เฆซเฆพเฆ‡เฆฒ เฆจเง‡เฆ‡", "no_files_search": "\"{query}\" เฆเฆฐ เฆธเฆพเฆฅเง‡ เฆฎเฆฟเฆฒ เฆฅเฆพเฆ•เฆพ เฆ•เง‹เฆจเง‹ เฆซเฆพเฆ‡เฆฒ เฆจเง‡เฆ‡", "no_files_filtered": "เฆ•เง‹เฆจเง‹ {filter} เฆซเฆพเฆ‡เฆฒ เฆจเง‡เฆ‡", + "filter": { + "added": "เฆฏเง‹เฆ— เฆ•เฆฐเฆพ", + "removed": "เฆฎเงเฆ›เง‡ เฆซเง‡เฆฒเฆพ", + "modified": "เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆฟเฆค" + }, "files_button": "เฆซเฆพเฆ‡เฆฒเฆธเฆฎเง‚เฆน", "select_file_prompt": "เฆกเฆฟเฆซ เฆฆเง‡เฆ–เฆคเง‡ เฆธเฆพเฆ‡เฆกเฆฌเฆพเฆฐ เฆฅเง‡เฆ•เง‡ เฆเฆ•เฆŸเฆฟ เฆซเฆพเฆ‡เฆฒ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆจ เฆ•เฆฐเงเฆจ", "close_files_panel": "เฆซเฆพเฆ‡เฆฒ เฆชเงเฆฏเฆพเฆจเง‡เฆฒ เฆฌเฆจเงเฆง เฆ•เฆฐเงเฆจ", @@ -1463,6 +1467,8 @@ "word_wrap": "เฆฒเฆพเฆ‡เฆจ เฆฎเง‹เฆกเฆผเฆพเฆจเง‹" }, "pds": { + "title": "npmx.social", + "meta_description": "npmx เฆ•เฆฎเฆฟเฆ‰เฆจเฆฟเฆŸเฆฟเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆซเฆฟเฆธเฆฟเฆฏเฆผเฆพเฆฒ AT Protocol Personal Data Server (PDS)เฅค", "join": { "title": "เฆ•เฆฎเฆฟเฆ‰เฆจเฆฟเฆŸเฆฟเฆคเง‡ เฆฏเง‹เฆ— เฆฆเฆฟเฆจ", "description": "เฆ†เฆชเฆจเฆฟ เฆ…เงเฆฏเฆพเฆŸเฆฎเง‹เฆธเฆซเฆฟเฆฏเฆผเฆพเฆฐเง‡ เฆชเงเฆฐเฆฅเฆฎ เฆ…เงเฆฏเฆพเฆ•เฆพเฆ‰เฆจเงเฆŸ เฆคเงˆเฆฐเฆฟ เฆ•เฆฐเฆ›เง‡เฆจ เฆฌเฆพ เฆฌเฆฟเฆฆเงเฆฏเฆฎเฆพเฆจ เฆ…เงเฆฏเฆพเฆ•เฆพเฆ‰เฆจเงเฆŸ เฆธเงเฆฅเฆพเฆจเฆพเฆจเงเฆคเฆฐ เฆ•เฆฐเฆ›เง‡เฆจโ€”เฆ†เฆชเฆจเฆฟ เฆเฆ–เฆพเฆจเง‡ เฆธเงเฆฌเฆพเฆ—เฆคเฆฎเฅค เฆ†เฆชเฆจเฆฟ เฆ†เฆชเฆจเฆพเฆฐ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจ เฆ…เงเฆฏเฆพเฆ•เฆพเฆ‰เฆจเงเฆŸ เฆนเงเฆฏเฆพเฆจเงเฆกเง‡เฆฒ, เฆชเง‹เฆธเงเฆŸ เฆฌเฆพ เฆซเฆฒเง‹เฆฏเฆผเฆพเฆฐ เฆนเฆพเฆฐเฆพเฆจเง‹ เฆ›เฆพเงœเฆพเฆ‡ เฆธเงเฆฅเฆพเฆจเฆพเฆจเงเฆคเฆฐ เฆ•เฆฐเฆคเง‡ เฆชเฆพเฆฐเง‡เฆจเฅค", @@ -1486,11 +1492,12 @@ "empty": "เฆฆเง‡เฆ–เฆพเฆจเง‹เฆฐ เฆฎเฆคเง‹ เฆ•เง‹เฆจเง‹ เฆ•เฆฎเฆฟเฆ‰เฆจเฆฟเฆŸเฆฟ เฆธเฆฆเฆธเงเฆฏ เฆจเง‡เฆ‡เฅค", "view_profile": "{handle}-เฆเฆฐ เฆชเงเฆฐเง‹เฆซเฆพเฆ‡เฆฒ เฆฆเง‡เฆ–เงเฆจ", "new_accounts": "...เฆเฆ›เฆพเงœเฆพ เฆ†เฆฐเฆ“ {count}เฆŸเฆฟ เฆจเฆคเงเฆจ เฆ…เงเฆฏเฆพเฆ•เฆพเฆ‰เฆจเงเฆŸ เฆ…เงเฆฏเฆพเฆŸเฆฎเง‹เฆธเฆซเฆฟเฆฏเฆผเฆพเฆฐเง‡ เฆฏเงเฆ•เงเฆค เฆนเฆฏเฆผเง‡เฆ›เง‡" - }, - "title": "npmx.social", - "meta_description": "npmx เฆ•เฆฎเฆฟเฆ‰เฆจเฆฟเฆŸเฆฟเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆซเฆฟเฆธเฆฟเฆฏเฆผเฆพเฆฒ AT Protocol Personal Data Server (PDS)เฅค" + } }, "privacy_policy": { + "title": "เฆชเงเฆฐเฆพเฆ‡เฆญเง‡เฆธเฆฟ เฆชเฆฒเฆฟเฆธเฆฟ", + "last_updated": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆ†เฆชเฆกเง‡เฆŸ: {date}", + "welcome": "{app}-เฆ เฆธเงเฆฌเฆพเฆ—เฆคเฆฎเฅค เฆ†เฆฎเฆฐเฆพ เฆ†เฆชเฆจเฆพเฆฐ เฆ—เง‹เฆชเฆจเง€เฆฏเฆผเฆคเฆพ เฆฐเฆ•เงเฆทเฆพเฆฏเฆผ เฆชเงเฆฐเฆคเฆฟเฆถเงเฆฐเงเฆคเฆฟเฆฌเฆฆเงเฆงเฅค เฆเฆ‡ เฆจเง€เฆคเฆฟเฆคเง‡ เฆ†เฆฎเฆฐเฆพ เฆ•เง€ เฆกเง‡เฆŸเฆพ เฆธเฆ‚เฆ—เงเฆฐเฆน เฆ•เฆฐเฆฟ, เฆ•เง€เฆญเฆพเฆฌเง‡ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเฆฟ เฆเฆฌเฆ‚ เฆ†เฆชเฆจเฆพเฆฐ เฆกเง‡เฆŸเฆพ เฆธเฆฎเงเฆชเฆฐเงเฆ•เฆฟเฆค เฆ…เฆงเฆฟเฆ•เฆพเฆฐ เฆฌเงเฆฏเฆพเฆ–เงเฆฏเฆพ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", "cookies": { "what_are": { "title": "เฆ•เงเฆ•เฆฟ เฆ•เง€?", @@ -1565,12 +1572,12 @@ "changes": { "title": "เฆเฆ‡ เฆจเง€เฆคเฆฟเฆฐ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ", "p1": "เฆ†เฆฎเฆฐเฆพ เฆธเฆฎเฆฏเฆผเง‡ เฆธเฆฎเฆฏเฆผเง‡ เฆเฆ‡ เฆชเงเฆฐเฆพเฆ‡เฆญเง‡เฆธเฆฟ เฆชเฆฒเฆฟเฆธเฆฟ เฆ†เฆชเฆกเง‡เฆŸ เฆ•เฆฐเฆคเง‡ เฆชเฆพเฆฐเฆฟเฅค เฆฏเง‡เฆ•เง‹เฆจเง‹ เฆชเฆฐเฆฟเฆฌเฆฐเงเฆคเฆจ เฆเฆ‡ เฆชเฆพเฆคเฆพเฆฏเฆผ เฆ†เฆชเฆกเง‡เฆŸเง‡เฆก เฆฐเฆฟเฆญเฆฟเฆถเฆจ เฆคเฆพเฆฐเฆฟเฆ–เฆธเฆน เฆชเงเฆฐเฆ•เฆพเฆถ เฆ•เฆฐเฆพ เฆนเฆฌเง‡เฅค" - }, - "title": "เฆชเงเฆฐเฆพเฆ‡เฆญเง‡เฆธเฆฟ เฆชเฆฒเฆฟเฆธเฆฟ", - "last_updated": "เฆธเฆฐเงเฆฌเฆถเง‡เฆท เฆ†เฆชเฆกเง‡เฆŸ: {date}", - "welcome": "{app}-เฆ เฆธเงเฆฌเฆพเฆ—เฆคเฆฎเฅค เฆ†เฆฎเฆฐเฆพ เฆ†เฆชเฆจเฆพเฆฐ เฆ—เง‹เฆชเฆจเง€เฆฏเฆผเฆคเฆพ เฆฐเฆ•เงเฆทเฆพเฆฏเฆผ เฆชเงเฆฐเฆคเฆฟเฆถเงเฆฐเงเฆคเฆฟเฆฌเฆฆเงเฆงเฅค เฆเฆ‡ เฆจเง€เฆคเฆฟเฆคเง‡ เฆ†เฆฎเฆฐเฆพ เฆ•เง€ เฆกเง‡เฆŸเฆพ เฆธเฆ‚เฆ—เงเฆฐเฆน เฆ•เฆฐเฆฟ, เฆ•เง€เฆญเฆพเฆฌเง‡ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเฆฟ เฆเฆฌเฆ‚ เฆ†เฆชเฆจเฆพเฆฐ เฆกเง‡เฆŸเฆพ เฆธเฆฎเงเฆชเฆฐเงเฆ•เฆฟเฆค เฆ…เฆงเฆฟเฆ•เฆพเฆฐ เฆฌเงเฆฏเฆพเฆ–เงเฆฏเฆพ เฆ•เฆฐเฆพ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค" + } }, "a11y": { + "title": "เฆ…เงเฆฏเฆพเฆ•เงเฆธเง‡เฆธเฆฟเฆฌเฆฟเฆฒเฆฟเฆŸเฆฟ", + "footer_title": "a11y", + "welcome": "เฆ†เฆฎเฆฐเฆพ เฆšเฆพเฆ‡ {app} เฆฏเฆค เฆฌเง‡เฆถเฆฟ เฆธเฆฎเงเฆญเฆฌ เฆฎเฆพเฆจเงเฆทเง‡เฆฐ เฆœเฆจเงเฆฏ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐเฆฏเง‹เฆ—เงเฆฏ เฆนเง‹เฆ•เฅค", "approach": { "title": "เฆ†เฆฎเฆพเฆฆเง‡เฆฐ เฆฆเงƒเฆทเงเฆŸเฆฟเฆญเฆ™เงเฆ—เฆฟ", "p1": "เฆ†เฆฎเฆฐเฆพ Web Content Accessibility Guidelines (WCAG) 2.2 เฆ…เฆจเงเฆธเฆฐเฆฃ เฆ•เฆฐเฆพเฆฐ เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเฆฟ เฆเฆฌเฆ‚ เฆซเฆฟเฆšเฆพเฆฐ เฆคเงˆเฆฐเฆฟ เฆ•เฆฐเฆพเฆฐ เฆธเฆฎเฆฏเฆผ เฆเฆŸเฆฟเฆ•เง‡ เฆฐเง‡เฆซเฆพเฆฐเง‡เฆจเงเฆธ เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐ เฆ•เฆฐเฆฟเฅค เฆ†เฆฎเฆฐเฆพ เฆ•เง‹เฆจเง‹ WCAG เฆธเงเฆคเฆฐเง‡เฆฐ เฆชเง‚เฆฐเงเฆฃ เฆธเฆฎเงเฆฎเฆคเฆฟ เฆฆเฆพเฆฌเฆฟ เฆ•เฆฐเฆฟ เฆจเฆพโ€”เฆ…เงเฆฏเฆพเฆ•เงเฆธเง‡เฆธเฆฟเฆฌเฆฟเฆฒเฆฟเฆŸเฆฟ เฆเฆ•เฆŸเฆฟ เฆšเฆฒเฆฎเฆพเฆจ เฆชเงเฆฐเฆ•เงเฆฐเฆฟเฆฏเฆผเฆพ เฆเฆฌเฆ‚ เฆธเฆฌเฆธเฆฎเฆฏเฆผ เฆ‰เฆจเงเฆจเฆคเฆฟเฆฐ เฆธเงเฆฏเง‹เฆ— เฆฅเฆพเฆ•เง‡เฅค", @@ -1595,19 +1602,9 @@ "title": "เฆชเงเฆฐเฆคเฆฟเฆ•เงเฆฐเฆฟเฆฏเฆผเฆพ", "p1": "{app}-เฆ เฆฏเฆฆเฆฟ เฆ†เฆชเฆจเฆฟ เฆ•เง‹เฆจเง‹ เฆ…เงเฆฏเฆพเฆ•เงเฆธเง‡เฆธเฆฟเฆฌเฆฟเฆฒเฆฟเฆŸเฆฟ เฆธเฆฎเฆธเงเฆฏเฆพ เฆชเฆพเฆจ, เฆ…เฆจเงเฆ—เงเฆฐเฆน เฆ•เฆฐเง‡ เฆ†เฆฎเฆพเฆฆเง‡เฆฐ {link}-เฆ เฆ‡เฆธเงเฆฏเง เฆ–เงเฆฒเง‡ เฆœเฆพเฆจเฆพเฆจเฅค เฆ†เฆฎเฆฐเฆพ เฆเฆธเฆฌ เฆฐเฆฟเฆชเง‹เฆฐเงเฆŸ เฆ—เงเฆฐเงเฆคเงเฆฌ เฆธเฆนเฆ•เฆพเฆฐเง‡ เฆจเง‡เฆ‡ เฆเฆฌเฆ‚ เฆธเฆฎเฆพเฆงเฆพเฆจเง‡เฆฐ เฆธเฆฐเงเฆฌเง‹เฆšเงเฆš เฆšเง‡เฆทเงเฆŸเฆพ เฆ•เฆฐเฆฟเฅค", "link": "GitHub เฆฐเฆฟเฆชเง‹เฆœเฆฟเฆŸเฆฐเฆฟ" - }, - "title": "เฆ…เงเฆฏเฆพเฆ•เงเฆธเง‡เฆธเฆฟเฆฌเฆฟเฆฒเฆฟเฆŸเฆฟ", - "footer_title": "a11y", - "welcome": "เฆ†เฆฎเฆฐเฆพ เฆšเฆพเฆ‡ {app} เฆฏเฆค เฆฌเง‡เฆถเฆฟ เฆธเฆฎเงเฆญเฆฌ เฆฎเฆพเฆจเงเฆทเง‡เฆฐ เฆœเฆจเงเฆฏ เฆฌเงเฆฏเฆฌเฆนเฆพเฆฐเฆฏเง‹เฆ—เงเฆฏ เฆนเง‹เฆ•เฅค" + } }, "translation_status": { - "table": { - "file": "เฆซเฆพเฆ‡เฆฒ", - "status": "เฆ…เฆฌเฆธเงเฆฅเฆพ", - "error": "เฆซเฆพเฆ‡เฆฒ เฆคเฆพเฆฒเฆฟเฆ•เฆพ เฆฒเง‹เฆก เฆ•เฆฐเฆพเฆฐ เฆธเฆฎเฆฏเฆผ เฆคเงเฆฐเงเฆŸเฆฟ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", - "empty": "เฆ•เง‹เฆจเง‹ เฆซเฆพเฆ‡เฆฒ เฆชเฆพเฆ“เฆฏเฆผเฆพ เฆฏเฆพเฆฏเฆผเฆจเฆฟ", - "file_link": "{file} ({lang}) GitHub-เฆ เฆธเฆฎเงเฆชเฆพเฆฆเฆจเฆพ เฆ•เฆฐเงเฆจ" - }, "title": "เฆ…เฆจเงเฆฌเฆพเฆฆ เฆ…เฆฌเฆธเงเฆฅเฆพ", "generated_at": "เฆ‰เงŽเฆชเฆพเฆฆเฆจเง‡เฆฐ เฆคเฆพเฆฐเฆฟเฆ–: {date}", "welcome": "{npmx}-เฆ•เง‡ เฆฌเฆฟเฆญเฆฟเฆจเงเฆจ เฆญเฆพเฆทเฆพเฆฏเฆผ เฆ…เฆจเงเฆฌเฆพเฆฆ เฆ•เฆฐเฆคเง‡ เฆธเฆพเฆนเฆพเฆฏเงเฆฏ เฆ•เฆฐเฆคเง‡ เฆ†เฆ—เงเฆฐเฆนเง€ เฆนเฆฒเง‡ เฆ†เฆชเฆจเฆฟ เฆธเฆ เฆฟเฆ• เฆœเฆพเฆฏเฆผเฆ—เฆพเฆฏเฆผ เฆเฆธเง‡เฆ›เง‡เฆจ! เฆเฆ‡ เฆธเงเฆฌเฆฏเฆผเฆ‚เฆ•เงเฆฐเฆฟเฆฏเฆผเฆญเฆพเฆฌเง‡ เฆ†เฆชเฆกเง‡เฆŸ เฆนเฆ“เฆฏเฆผเฆพ เฆชเง‡เฆœเฆŸเฆฟ เฆฌเฆฐเงเฆคเฆฎเฆพเฆจเง‡ เฆฏเง‡เฆธเฆฌ เฆ•เฆจเฆŸเง‡เฆจเงเฆŸเง‡ เฆธเฆพเฆนเฆพเฆฏเงเฆฏ เฆฆเฆฐเฆ•เฆพเฆฐ เฆคเฆพ เฆฆเง‡เฆ–เฆพเฆฏเฆผเฅค", @@ -1621,22 +1618,13 @@ "complete_text": "เฆเฆ‡ เฆ…เฆจเงเฆฌเฆพเฆฆ เฆธเฆฎเงเฆชเง‚เฆฐเงเฆฃ เฆนเฆฏเฆผเง‡เฆ›เง‡, เฆฆเฆพเฆฐเงเฆฃ เฆ•เฆพเฆœ!", "missing_text": "เฆ…เฆจเงเฆชเฆธเงเฆฅเฆฟเฆค", "missing_keys": "เฆ•เง‹เฆจเง‹ เฆ…เฆจเงเฆฌเฆพเฆฆ เฆ…เฆจเงเฆชเฆธเงเฆฅเฆฟเฆค เฆจเง‡เฆ‡ | เฆ…เฆจเงเฆชเฆธเงเฆฅเฆฟเฆค เฆ…เฆจเงเฆฌเฆพเฆฆ | เฆ…เฆจเงเฆชเฆธเงเฆฅเฆฟเฆค เฆ…เฆจเงเฆฌเฆพเฆฆเฆธเฆฎเง‚เฆน", - "progress_label": "{locale}-เฆเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆ—เงเฆฐเฆ—เฆคเฆฟเฆฐ เฆ…เฆฌเฆธเงเฆฅเฆพ" - }, - "action_bar": { - "title": "เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆฌเฆพเฆฐ", - "selection": "เงฆเฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค | เงงเฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค | {count}เฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค", - "shortcut": "\"{key}\" เฆšเฆพเฆชเงเฆจ เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆซเง‹เฆ•เฆพเฆธ เฆ•เฆฐเฆคเง‡", - "button_close_aria_label": "เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆฌเฆพเฆฐ เฆฌเฆจเงเฆง เฆ•เฆฐเงเฆจ" - }, - "leaderboard": { - "likes": { - "title": "เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก", - "description": "เฆฌเฆฐเงเฆคเฆฎเฆพเฆจเง‡ npmx-เฆเฆฐ เฆธเฆฌเฆšเง‡เฆฏเฆผเง‡ เฆฌเง‡เฆถเฆฟ เฆฒเฆพเฆ‡เฆ• เฆชเฆพเฆ“เฆฏเฆผเฆพ เงงเงฆเฆŸเฆฟ เฆชเงเฆฏเฆพเฆ•เง‡เฆœเฅค", - "rank": "เฆฐโ€เงเฆฏเฆพเฆ™เงเฆ•", - "likes": "เฆฒเฆพเฆ‡เฆ•", - "unavailable_title": "เฆเฆ–เฆจเฆ“ เฆ•เง‹เฆจเง‹ เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก เฆจเง‡เฆ‡", - "unavailable_description": "เฆเฆ‡ เฆฎเงเฆนเง‚เฆฐเงเฆคเง‡ เฆฆเง‡เฆ–เฆพเฆจเง‹เฆฐ เฆฎเฆคเง‹ เฆ•เง‹เฆจเง‹ เฆฒเฆพเฆ‡เฆ• เฆฒเฆฟเฆกเฆพเฆฐเฆฌเง‹เฆฐเงเฆก เฆจเง‡เฆ‡เฅค" + "progress_label": "{locale}-เฆเฆฐ เฆœเฆจเงเฆฏ เฆ…เฆ—เงเฆฐเฆ—เฆคเฆฟเฆฐ เฆ…เฆฌเฆธเงเฆฅเฆพ", + "table": { + "file": "เฆซเฆพเฆ‡เฆฒ", + "status": "เฆ…เฆฌเฆธเงเฆฅเฆพ", + "error": "เฆซเฆพเฆ‡เฆฒ เฆคเฆพเฆฒเฆฟเฆ•เฆพ เฆฒเง‹เฆก เฆ•เฆฐเฆพเฆฐ เฆธเฆฎเฆฏเฆผ เฆคเงเฆฐเงเฆŸเฆฟ เฆนเฆฏเฆผเง‡เฆ›เง‡เฅค", + "empty": "เฆ•เง‹เฆจเง‹ เฆซเฆพเฆ‡เฆฒ เฆชเฆพเฆ“เฆฏเฆผเฆพ เฆฏเฆพเฆฏเฆผเฆจเฆฟ", + "file_link": "{file} ({lang}) GitHub-เฆ เฆธเฆฎเงเฆชเฆพเฆฆเฆจเฆพ เฆ•เฆฐเงเฆจ" } }, "vacations": { @@ -1673,6 +1661,12 @@ } } }, + "action_bar": { + "title": "เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆฌเฆพเฆฐ", + "selection": "เงฆเฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค | เงงเฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค | {count}เฆŸเฆฟ เฆจเฆฟเฆฐเงเฆฌเฆพเฆšเฆฟเฆค", + "shortcut": "\"{key}\" เฆšเฆพเฆชเงเฆจ เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆซเง‹เฆ•เฆพเฆธ เฆ•เฆฐเฆคเง‡", + "button_close_aria_label": "เฆ…เงเฆฏเฆพเฆ•เฆถเฆจ เฆฌเฆพเฆฐ เฆฌเฆจเงเฆง เฆ•เฆฐเงเฆจ" + }, "logo_menu": { "copy_svg": "SVG เฆนเฆฟเฆธเง‡เฆฌเง‡ เฆฒเง‹เฆ—เง‹ เฆ•เฆชเฆฟ เฆ•เฆฐเงเฆจ", "copied": "เฆ•เฆชเฆฟ เฆนเฆฏเฆผเง‡เฆ›เง‡!", diff --git a/i18n/locales/cs-CZ.json b/i18n/locales/cs-CZ.json index 7fefeb1a20..52e946ae33 100644 --- a/i18n/locales/cs-CZ.json +++ b/i18n/locales/cs-CZ.json @@ -20,7 +20,10 @@ "chat": "chat", "builders_chat": "stavitelรฉ", "keyboard_shortcuts": "klรกvesovรฉ zkratky", - "brand": "znaฤka" + "brand": "znaฤka", + "resources": "Zdroje", + "features": "Funkce", + "other": "Ostatnรญ" }, "shortcuts": { "section": { @@ -42,7 +45,9 @@ "open_docs": "Otevล™รญt dokumentaci", "disable_shortcuts": "Klรกvesovรฉ zkratky mลฏลพete zakรกzat v {settings}.", "open_main": "Otevล™รญt hlavnรญ informace", - "open_diff": "Otevล™รญt rozdรญly verzรญ" + "open_diff": "Otevล™รญt rozdรญly verzรญ", + "open_timeline": "Otevล™รญt ฤasovou osu", + "open_stats": "Otevล™รญt statistiky" }, "search": { "label": "Hledat npm balรญฤky", @@ -94,6 +99,11 @@ "current": "aktuรกlnรญ", "here": "tady jste", "connected": "pล™ipojeno", + "keyboard_shortcuts": { + "navigate": "navigovat", + "select": "vybrat", + "close": "zavล™รญt" + }, "state": { "on": "zapnuto", "off": "vypnuto" @@ -149,7 +159,9 @@ "code": "Kรณd", "diff": "Rozdรญl", "compare": "Porovnat tento balรญฤek", - "download": "Stรกhnout tarball" + "download": "Stรกhnout tarball", + "changelog": "Seznam zmฤ›n", + "stats": "Statistiky" }, "package_actions": { "copy_run": "Kopรญrovat pล™รญkaz spuลกtฤ›nรญ" @@ -224,6 +236,31 @@ "more_replies": "jeลกtฤ› {count} odpovฤ›ฤโ€ฆ | jeลกtฤ› {count} odpovฤ›diโ€ฆ | jeลกtฤ› {count} odpovฤ›dรญโ€ฆ" } }, + "noodles": { + "title": "noodly", + "meta_description": "Kaลพdรฝ noodle, kterรฝ jsme kdy ukรกzali na npmx โ€” sezรณnnรญ loga, velikonoฤnรญ vajรญฤka a pล™รญbฤ›hy za nimi.", + "latest": "Nejnovฤ›jลกรญ noodly", + "what_is": "Co jsou noodly", + "what_is_body": "Noodly jsou hravรฉ varianty loga npmx, kterรฉ zobrazujeme na domovskรฉ strรกnce pล™i novรฝch vydรกnรญch, svรกtcรญch, udรกlostech a dalลกรญch momentech, kterรฉ stojรญ za oslavu. Pล™edstavte si je jako Google Doodles, ale pro npm balรญฤky.", + "empty": "Jeลกtฤ› ลพรกdnรฉ noodly.", + "load_more": "Naฤรญst dalลกรญch {count}", + "dates": "Aktivnรญ mezi", + "shipped_in": "Pล™idรกno v", + "credits": "Autoล™i", + "learn_more": "Vรญce informacรญ", + "carousel_prev": "Pล™edchozรญ obrรกzek", + "carousel_next": "Dalลกรญ obrรกzek", + "carousel_dots": "Navigace mezi variantami obrรกzkลฏ", + "carousel_jump": "Pล™ejรญt na obrรกzek ฤ. {index}", + "lens_label": "{title} โ€” obrazovรก smyฤka", + "lens_slide": "obrรกzek {index}", + "lens_slide_position": "Obrรกzek {index} z(e) {total}", + "back_to_archive": "Zpฤ›t na vลกechny noodly", + "missing": { + "title": "Tento noodle jeลกtฤ› nebyl uvaล™en.", + "body": "Na menu noodle โ€œ{slug}โ€ jeลกtฤ› nemรกme. Buฤ se stรกle pล™ipravuje, nebo nรกm chybรญ receptura. Kaลพdopรกdnฤ› โ€” zpฤ›t do archivu." + } + }, "settings": { "title": "nastavenรญ", "tagline": "pล™izpลฏsobte si svรฉ npmx", @@ -281,7 +318,9 @@ }, "keyboard_shortcuts_enabled": "Povolit klรกvesovรฉ zkratky", "keyboard_shortcuts_enabled_description": "Klรกvesovรฉ zkratky lze zakรกzat, pokud se stล™etรกvajรญ s jinรฝmi zkratkami prohlรญลพeฤe nebo systรฉmu", - "enable_code_ligatures": "Zapnout ligatury v kรณdu" + "enable_code_ligatures": "Zapnout ligatury v kรณdu", + "enable_changelog_autoscroll": "Automaticky posouvat na poลพadovanou verzi", + "enable_changelog_autoscroll_description": "Automaticky posouvat na nebo blรญzko poลพadovanรฉ verze v seznamu zmฤ›n balรญฤku" }, "i18n": { "missing_keys": "{count} chybฤ›jรญcรญ pล™eklad | {count} chybฤ›jรญcรญ pล™eklady | {count} chybฤ›jรญcรญch pล™ekladลฏ", @@ -313,6 +352,7 @@ "warnings": "Varovรกnรญ:", "go_back_home": "Zpฤ›t na zaฤรกtek", "per_week": "/ tรฝden", + "per_week_short": "/tรฝd", "vanity_downloads_hint": "Pro zobrazenรฝ balรญฤek | Souฤet pro {count} zobrazenรฉ balรญฤky | Souฤet pro {count} zobrazenรฝch balรญฤkลฏ", "sort": { "name": "jmรฉno", @@ -378,17 +418,25 @@ "title_deps": "Vรฝznamnรฉ zvรฝลกenรญ poฤtu zรกvislostรญ od verze v{version}", "title_both": "Vรฝznamnรฉ zvรฝลกenรญ velikosti a poฤtu zรกvislostรญ od verze v{version}", "size": "Velikost instalace se zvรฝลกila o {percent} (vฤ›tลกรญ o {size})", - "deps": "{count} dalลกรญ zรกvislostรญ" + "deps": "o zรกvislost vรญce | o {count} zรกvislosti vรญce | o {count} zรกvislostรญ vรญce" + }, + "size_decrease": { + "title_size": "Balรญฤek se od v{version} zmenลกil!", + "title_deps": "Poฤet zรกvislostรญ se od v{version} snรญลพil!", + "title_both": "Velikost balรญฤku a poฤet zรกvislostรญ se od v{version} snรญลพily!", + "size": "Velikost instalace se snรญลพila o {percent} ({size} menลกรญ)", + "deps": "o zรกvislost mรฉnฤ› | o {count} zรกvislosti mรฉnฤ› | o {count} zรกvislostรญ mรฉnฤ›" }, "replacement": { "title": "Moลพnรก tuto zรกvislost nepotล™ebujete.", - "native": "Tento balรญฤek lze nahradit {replacement}, dostupnรฉ od Node {nodeVersion}.", - "simple": "{community} oznaฤila tento balรญฤek jako zbyteฤnรฝ s doporuฤenรญm: {replacement}.", - "documented": "{community} oznaฤila tento balรญฤek jako majรญcรญ vรฝkonnฤ›jลกรญ alternativy.", + "example": "Pล™รญklad:", + "native": "Tento balรญฤek lze nahradit pomocรญ {replacement}, dostupnรฉ od Node {nodeVersion}.", + "native_no_version": "Tento balรญฤek lze nahradit {replacement}.", + "simple": "Tento balรญฤek byl oznaฤen jako nadbyteฤnรฝ, s doporuฤenรญm: {replacement}", + "documented": "Tento balรญฤek byl oznaฤen jako majรญcรญ vรฝkonnฤ›jลกรญ alternativy.", "none": "Tento balรญฤek byl oznaฤen jako jiลพ nepotล™ebnรฝ a jeho funkฤnost je pravdฤ›podobnฤ› dostupnรก nativnฤ› ve vลกech enginech.", "learn_more": "Zjistit vรญce", "learn_more_above": "Zjistit vรญce vรฝลกe.", - "community": "komunita", "consider_no_dep": "+ Zvรกลพit ลพรกdnou zรกvislost?" }, "stats": { @@ -403,7 +451,10 @@ "size_tooltip": { "unpacked": "{size} velikost po rozbalenรญ (tento balรญฤek)", "total": "{size} celkovรก velikost po rozbalenรญ (vฤetnฤ› vลกech zรกvislostรญ ({count}) pro linux-x64)" - } + }, + "main_information": "Hlavnรญ informace", + "trends": "Trendy", + "version_distribution": "Distribuce verzรญ" }, "skills": { "title": "Dovednosti agentลฏ", @@ -433,11 +484,17 @@ "docs": "dokumentace", "fund": "financovat", "compare": "porovnat", - "compare_this_package": "porovnat tento balรญฤek" + "timeline": "ฤasovรก osa", + "stats": "statistiky", + "compare_this_package": "porovnat tento balรญฤek", + "changelog": "seznam zmฤ›n" }, "likes": { "like": "Lรญbรญ se mi tento balรญฤek", - "unlike": "Nelรญbรญ se mi tento balรญฤek" + "unlike": "Nelรญbรญ se mi tento balรญฤek", + "top_rank_tooltip": "Tento balรญฤek je mezi 10 nejvรญce olajkovanรฝmi balรญฤky na npmx! ({rank}.)", + "top_rank_label": "{rank}.", + "top_rank_link_label": "Zobrazit ลพebล™รญฤek oblรญbenosti. Tento balรญฤek je na {rank}. mรญstฤ›." }, "docs": { "contents": "Obsah", @@ -478,7 +535,8 @@ "warning": "Varovรกnรญ", "caution": "Upozornฤ›nรญ" }, - "copy_as_markdown": "Zkopรญrovat ฤŒTI Mฤš jako Markdown" + "copy_as_markdown": "Zkopรญrovat ฤŒTI Mฤš jako Markdown", + "error_loading": "ฤŒTI Mฤš se nepodaล™ilo naฤรญst" }, "provenance_section": { "title": "Pลฏvod", @@ -509,6 +567,7 @@ "weekly_downloads": "Tรฝdennรญ staลพenรญ", "keywords": "Klรญฤovรก slova", "license": "Licence", + "version": "Verze", "select": "Vybrat balรญฤek", "select_maximum": "Maximรกlnฤ› lze vybrat {count} balรญฤkลฏ" }, @@ -527,7 +586,6 @@ "view_all": "Zobrazit {count} verzi | Zobrazit {count} verze | Zobrazit {count} verzรญ", "view_all_versions": "Zobrazit vลกechny verze", "distribution_title": "Skupina Semver", - "distribution_modal_title": "Verze", "distribution_range_date_same_year": "od {from} do {to}, {endYear}", "distribution_range_date_multiple_years": "od {from}, {startYear} do {to}, {endYear}", "grouping_major": "Hlavnรญ", @@ -548,6 +606,9 @@ "filter_help": "Pomoc s filtrovรกnรญm rozsahu semver", "filter_tooltip": "Filtrovat verze pomocรญ {link}. Napล™รญklad ^3.0.0 zobrazรญ vลกechny verze 3.x.", "filter_tooltip_link": "semver rozsahu", + "license_change_help": "Podrobnosti o zmฤ›nฤ› licence", + "license_change_warning": "Licence se od pล™edchozรญ verze zmฤ›nila.", + "license_change_record": "Licence tohoto balรญฤku se zmฤ›nila z \"{from}\" na \"{to}\".", "no_matches": "ลฝรกdnรฉ verze neodpovรญdajรญ tomuto rozsahu", "copy_alt": { "per_version_analysis": "Verze {version} byla staลพena {downloads} krรกt", @@ -557,6 +618,35 @@ "current_tags": "Aktuรกlnรญ znaฤky", "no_match_filter": "ลฝรกdnรฉ verze neodpovรญdajรญ {filter}" }, + "timeline": { + "load_more": "Naฤรญst vรญce", + "load_error": "Nepodaล™ilo se naฤรญst ฤasovou osu. Zkuste to prosรญm pozdฤ›ji.", + "size_increase": "Velikost instalace se zvรฝลกila o {percent} % ({size})", + "size_decrease": "Velikost instalace se snรญลพila o {percent} % ({size})", + "dep_increase": "{count} zรกvislost pล™idรกna | {count} zรกvislosti pล™idรกny | {count} zรกvislostรญ pล™idรกno", + "dep_decrease": "{count} zรกvislost odstranฤ›na | {count} zรกvislosti odstranฤ›ny | {count} zรกvislostรญ odstranฤ›no", + "license_change": "Licence se zmฤ›nila z {from} na {to}", + "esm_added": "Typ modulu zmฤ›nฤ›n na ESM", + "esm_removed": "Typ modulu zmฤ›nฤ›n z ESM na CJS", + "types_added": "Pล™idรกny TypeScript typy", + "types_removed": "Odebrรกny TypeScript typy", + "trusted_publisher_added": "Dลฏvฤ›ryhodnรฉ publikovรกnรญ bylo povoleno", + "trusted_publisher_removed": "Dลฏvฤ›ryhodnรฉ publikovรกnรญ bylo vypnuto", + "provenance_added": "Provenience byla zapnuta", + "provenance_removed": "Provenience byla vypnuta", + "chart": { + "tab_aria_label": "Vรฝbฤ›r metriky", + "base_scale": "zaฤรญt osu y od nuly", + "zoom": "pล™iblรญลพit", + "reset_minimap": "obnovit minimapu", + "ordered_versions": "pouze stabilnรญ verze", + "copy_alt": { + "key_changes": "Klรญฤovรฉ zmฤ›ny: {version_events}.", + "version_events": "verze {version}: {events}", + "general_description": "Graf zobrazujรญcรญ {metric} balรญฤku {package}, od verze {first} do verze {last}. {metric} ve verzi {first} je {first_value}, ve verzi {last} je {last_value} ({overall_progress_percentage} % celkem). {key_changes} {watermark}." + } + } + }, "dependencies": { "title": "Zรกvislosti ({count})", "list_label": "Zรกvislosti balรญฤku", @@ -657,10 +747,17 @@ "general_description": "Osa Y pล™edstavuje poฤet staลพenรญ. Osa X pล™edstavuje ฤasovรฝ rozsah od {start_date} do {end_date} s ฤasovรฝm obdobรญm {granularity}.{estimation_notice} {packages_analysis}. {watermark}.", "facet_bar_general_description": "Horizontรกlnรญ sloupcovรฝ graf pro: {packages}, porovnรกvajรญcรญ {facet} ({description}). {facet_analysis} {watermark}.", "facet_bar_analysis": "{package_name} mรก hodnotu {value}." + }, + "embedding": { + "chart": "Umรญstit tento graf", + "copy_url": "Zkopรญrujte tuto URL pro vloลพenรญ grafu na vรกลก web", + "preview": "Nรกhled", + "tip": "Pokud nejsou zadรกny startDate a endDate, graf zobrazรญ poslednรญch 12 mฤ›sรญcลฏ." } }, "downloads": { "title": "Tรฝdennรญ staลพenรญ", + "version_distribution_title": "tรฝdennรญ staลพenรญ pro verzi {version}", "community_distribution": "Zobrazit rozloลพenรญ adopce v komunitฤ›", "subtitle": "Napล™รญฤ vลกemi verzemi", "sparkline_nav_hint": "Pouลพijte โ† โ†’" @@ -759,6 +856,16 @@ "tarball": "Stรกhnout Tarball jako .tar.gz" } }, + "leaderboard": { + "likes": { + "title": "ลฝebล™รญฤek lajkลฏ", + "description": "10 nejvรญce olajkovanรฝch balรญฤkลฏ na npmx prรกvฤ› teฤ.", + "rank": "Poล™adรญ", + "likes": "Lajky", + "unavailable_title": "ลฝebล™รญฤek lajkลฏ zatรญm nenรญ k dispozici", + "unavailable_description": "Momentรกlnฤ› nemรกme ลพรกdnรฝ ลพebล™รญฤek lajkลฏ k zobrazenรญ." + } + }, "connector": { "modal": { "title": "Lokรกlnรญ konektor", @@ -1119,10 +1226,13 @@ }, "team": { "title": "Tรฝm", - "role_steward": "Vedoucรญ", - "role_maintainer": "Sprรกvce", - "sponsor": "Sponzor", - "sponsor_aria": "Sponzor {name} na GitHubu" + "core": "Jรกdro", + "maintainers": "Sprรกvci", + "role_core": "jรกdro", + "role_steward": "vedoucรญ", + "role_maintainer": "sprรกvce", + "sponsor": "sponzor", + "sponsor_aria": "Sponzorovat {name} na GitHubu" }, "contributors": { "title": "Pล™ispฤ›vatelรฉ | {count} pล™ispฤ›vatelรฉ | {count} pล™ispฤ›vatelลฏ", @@ -1235,6 +1345,17 @@ "packages_selected": "Vybranรฉ balรญฤky: {count}/{max}.", "add_hint": "Pล™idejte alespoลˆ 2 balรญฤky ke srovnรกnรญ." }, + "scatter_chart": { + "title": "Porovnat {x} a {y}", + "freshness_score": "Skรณre ฤerstvosti", + "copy_alt": { + "analysis": "{package} : {x_name} ({x_value}) a {y_name} ({y_value})", + "description": "Bodovรฝ graf mapujรญcรญ {x_name} vลฏฤi {y_name} pro balรญฤky {packages}. {analysis}. {watermark}" + }, + "filename": "{x}-vs-{y}-bodovy-graf", + "x_axis": "Osa X โ†ฆ", + "y_axis": "Osa Y โ†ฅ" + }, "no_dependency": { "label": "(ลฝรกdnรก zรกvislost)", "typeahead_title": "Co by udฤ›lal James?", @@ -1313,6 +1434,22 @@ "vulnerabilities": { "label": "Zranitelnosti", "description": "Znรกmรฉ bezpeฤnostnรญ zranitelnosti" + }, + "githubStars": { + "label": "GitHub Hvฤ›zdy", + "description": "Poฤet hvฤ›zdiฤek na GitHub repozitรกล™i" + }, + "githubForks": { + "label": "GitHub forky", + "description": "Poฤet forkลฏ na GitHub repozitรกล™i" + }, + "githubIssues": { + "label": "GitHub รบkoly", + "description": "Poฤet รบkolลฏ na GitHub repozitรกล™i" + }, + "createdAt": { + "label": "Vytvoล™eno", + "description": "Kdy byl balรญฤek vytvoล™en" } }, "values": { @@ -1333,8 +1470,6 @@ "file_changes": "Zmฤ›ny souborลฏ", "files_count": "{count} souborลฏ", "lines_hidden": "{count} skrytรฝch ล™รกdkลฏ", - "file_too_large": "Soubor je k porovnรกnรญ pล™รญliลก velkรฝ", - "file_size_warning": "{size} pล™ekraฤuje limit 250KB pro porovnรกnรญ", "compare_versions": "porovnat", "compare_versions_title": "Porovnat s nejnovฤ›jลกรญ verzรญ", "comparing_versions_label": "Porovnรกnรญ verzรญ...", @@ -1375,6 +1510,9 @@ "change_ratio": "Pomฤ›r zmฤ›n", "char_edits": "Zmฤ›ny znakลฏ", "diff_distance": "Vzdรกlenost rozdรญlลฏ", + "diff_truncated": "Srovnรกnรญ bylo zkrรกceno z dลฏvodu vรฝkonu. Zobrazujรญ se pouze prvnรญ zmฤ›nฤ›nรฉ ล™รกdky.", + "large_diff_mode": "Velkรฉ srovnรกnรญ souborลฏ zobrazeno s vypnutรฝm sluฤovรกnรญm inline รบprav z dลฏvodu vรฝkonu.", + "large_diff_options_disabled": "Velkรฉ srovnรกnรญ souborลฏ vypรญnรก sluฤovรกnรญ inline รบprav z dลฏvodu vรฝkonu.", "loading_diff": "Naฤรญtรกnรญ rozdรญlลฏ...", "loading_diff_error": "Nepodaล™ilo se naฤรญst rozdรญly", "merge_modified_lines": "Slouฤit upravenรฉ ล™รกdky", @@ -1635,5 +1773,16 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "Roztomilรก, zaoblenรก a barevnรก verze loga npmx." + "alt_logo_kawaii": "Roztomilรก, zaoblenรก a barevnรก verze loga npmx.", + "changelog": { + "pre_release": "Pre-release", + "draft": "Nรกvrh", + "no_logs": "Omlouvรกme se, tento balรญฤek nezveล™ejลˆuje seznam zmฤ›n nebo jeho formรกt nenรญ podporovรกn.", + "error": { + "p1": "Omlouvรกme se, seznam zmฤ›n pro {package} nelze naฤรญst", + "p2": "Zkuste to prosรญm pozdฤ›ji nebo {viewon}" + }, + "rate_limit_ungh": "Omlouvรกme se, byl dosaลพen limit GitHubu, zkuste to prosรญm za chvรญli znovu", + "version_unavailable": "Omlouvรกme se, poลพadovanรก verze nenรญ k dispozici." + } } diff --git a/i18n/locales/de.json b/i18n/locales/de.json index 40d3b9499a..69f128ff87 100644 --- a/i18n/locales/de.json +++ b/i18n/locales/de.json @@ -400,12 +400,9 @@ "example": "Beispiel:", "native": "Dies kann seit Node {nodeVersion} durch {replacement} ersetzt werden.", "native_no_version": "Dieses Paket kann durch {replacement} ersetzt werden.", - "simple": "Die {community} hat dieses Paket als รผberflรผssig markiert und empfiehlt: {replacement}.", - "documented": "Die {community} hat leistungsstรคrkere Alternativen fรผr dieses Paket aufgezeigt.", "none": "Dieses Paket wurde als nicht mehr nรถtig markiert, und seine Funktionalitรคt ist wahrscheinlich in allen Engines nativ verfรผgbar.", "learn_more": "Mehr erfahren", "learn_more_above": "Erfahre oben mehr.", - "community": "Community", "consider_no_dep": "+ Ohne Abhรคngigkeit lรถsen?" }, "stats": { @@ -551,7 +548,6 @@ "view_all": "{count} Version anzeigen | Alle {count} Versionen anzeigen", "view_all_versions": "Alle Versionen anzeigen", "distribution_title": "SemVer Gruppe", - "distribution_modal_title": "Versionen", "distribution_range_date_same_year": "von {from} bis {to} {endYear}", "distribution_range_date_multiple_years": "von {from} {startYear} bis {to} {endYear}", "grouping_major": "Major", @@ -1426,8 +1422,6 @@ "file_changes": "Dateiรคnderungen", "files_count": "{count} Datei | {count} Dateien", "lines_hidden": "{count} Zeile ausgeblendet | {count} Zeilen ausgeblendet", - "file_too_large": "Datei zu groรŸ fรผr Diff-Ansicht", - "file_size_warning": "{size} รผberschreitet das Limit fรผr die Diff-Anzeige", "compare_versions": "Diff", "compare_versions_title": "Mit neuester Version vergleichen", "comparing_versions_label": "Versionen werden verglichen...", diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 7b56e0311e..a568f4a81d 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -13,6 +13,7 @@ "trademark_disclaimer": "npm is a registered trademark of npm, Inc. This site is not affiliated with npm, Inc.", "footer": { "about": "about", + "sponsors": "sponsors", "blog": "blog", "docs": "docs", "source": "source", @@ -23,7 +24,8 @@ "brand": "brand", "resources": "Resources", "features": "Features", - "other": "Other" + "other": "Other", + "sponsored_by": "Sponsored by {list}" }, "shortcuts": { "section": { @@ -46,7 +48,8 @@ "disable_shortcuts": "You can disable keyboard shortcuts in {settings}.", "open_main": "Open main information", "open_diff": "Open version differences", - "open_timeline": "Open timeline" + "open_timeline": "Open timeline", + "open_stats": "Open stats" }, "search": { "label": "Search npm packages", @@ -98,6 +101,11 @@ "current": "current", "here": "you are here", "connected": "connected", + "keyboard_shortcuts": { + "navigate": "to navigate", + "select": "to select", + "close": "to close" + }, "state": { "on": "on", "off": "off" @@ -154,7 +162,8 @@ "diff": "Diff", "compare": "Compare this package", "download": "Download tarball", - "changelog": "Changelog" + "changelog": "Changelog", + "stats": "Stats" }, "package_actions": { "copy_run": "Copy run command" @@ -229,6 +238,31 @@ "more_replies": "{count} more reply... | {count} more replies..." } }, + "noodles": { + "title": "noodles", + "meta_description": "Every noodle we've ever shown on npmx โ€” the seasonal logos, easter eggs, and the stories behind them.", + "latest": "Latest noodles", + "what_is": "What is noodles", + "what_is_body": "Noodles are the playful variants of the npmx logo we run on the homepage to mark releases, holidays, events, and other moments worth celebrating. Think of them like Google Doodles, but for npm packages.", + "empty": "No noodles yet.", + "load_more": "Load {count} more", + "dates": "Active dates", + "shipped_in": "Shipped in", + "credits": "Credits", + "learn_more": "Learn more", + "carousel_prev": "Previous image", + "carousel_next": "Next image", + "carousel_dots": "Variant image navigation", + "carousel_jump": "Go to image {index}", + "lens_label": "{title} โ€” image reel", + "lens_slide": "image {index}", + "lens_slide_position": "Slide {index} of {total}", + "back_to_archive": "Back to all noodles", + "missing": { + "title": "This noodle never made it out of the bowl.", + "body": "We don't have a โ€œ{slug}โ€ noodle on the menu. Either it's still being plated, or it was never written. Either way โ€” back to the archive." + } + }, "settings": { "title": "settings", "tagline": "customize your npmx experience", @@ -400,12 +434,11 @@ "example": "Example:", "native": "This package can be replaced with {replacement}, available since Node {nodeVersion}.", "native_no_version": "This package can be replaced with {replacement}.", - "simple": "The {community} has flagged this package as redundant, with the advice: {replacement}", - "documented": "The {community} has flagged this package as having more performant alternatives.", + "simple": "This package has been flagged as redundant, with the advice: {replacement}", + "documented": "This package has been flagged as having more performant alternatives.", "none": "This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.", "learn_more": "Learn more", "learn_more_above": "Learn more above.", - "community": "community", "consider_no_dep": "+ Consider no dep?" }, "stats": { @@ -420,7 +453,10 @@ "size_tooltip": { "unpacked": "{size} unpacked size (this package)", "total": "{size} total unpacked size (including {count} dependency for linux-x64) | {size} total unpacked size (including all {count} dependencies for linux-x64)" - } + }, + "main_information": "Main Information", + "trends": "Trends", + "version_distribution": "Version Distribution" }, "skills": { "title": "Agent Skills", @@ -451,6 +487,7 @@ "fund": "fund", "compare": "compare", "timeline": "timeline", + "stats": "stats", "compare_this_package": "compare this package", "changelog": "changelog" }, @@ -551,7 +588,6 @@ "view_all": "View {count} version | View all {count} versions", "view_all_versions": "View all versions", "distribution_title": "Semver Group", - "distribution_modal_title": "Versions", "distribution_range_date_same_year": "from {from} to {to}, {endYear}", "distribution_range_date_multiple_years": "from {from}, {startYear} to {to}, {endYear}", "grouping_major": "Major", @@ -713,6 +749,12 @@ "general_description": "The Y axis represents the number of downloads. The X axis represents the date range, from {start_date} to {end_date}, with a {granularity} time period.{estimation_notice} {packages_analysis}. {watermark}.", "facet_bar_general_description": "Horizontal bar chart for: {packages}, comparing {facet} ({description}). {facet_analysis} {watermark}.", "facet_bar_analysis": "{package_name} has a value of {value}." + }, + "embedding": { + "chart": "Embed this chart", + "copy_url": "Copy this URL to embed the chart into your website", + "preview": "Preview", + "tip": "If startDate and endDate are not provided, the chart defaults to the last 12 months." } }, "downloads": { @@ -1179,7 +1221,9 @@ } }, "sponsors": { - "title": "Sponsors" + "title": "Sponsors", + "gold": "Gold Sponsors", + "silver": "Silver Sponsors" }, "oss_partners": { "title": "OSS Partners" @@ -1225,6 +1269,64 @@ } } }, + "sponsors_page": { + "title": "Sponsors", + "heading": "sponsors", + "meta_description": "Support npmx and help us accelerate ecosystem work around security, trust, optimization, and research.", + "intro": "Support npmx and help us grow the ecosystem work we do for developers and maintainers.", + "what_we_do": { + "title": "What we do", + "description": "We're building an ecosystem that solves problems around security, trust, optimization, and research for the tools we use in everyday development - quickly, conveniently, and with high quality. This project is built by developers for developers. As authors of widely used libraries, we understand team needs and actively study what maintainers and projects need most." + }, + "what_support_means": { + "title": "What support means", + "description": "Our plans and connections keep growing, along with our desire to share what we've built and learn from others. Your support helps fund the project, external talks, conferences, and the broader ecosystem, and, most importantly, enables us to keep growing our community." + }, + "cta": "See sponsorship tiers", + "community_growth_footnote": "* According to {link} Q1 2026 research.", + "what_this_means_for_you": { + "title": "What this means for you", + "description": "npmx is not only about improving developer experience and closing critical everyday gaps. In our first six months, we have already become the default source for thousands of teams and a huge number of developers. You get not only a more stable tool for your teams, but also visibility in front of a constantly growing audience of top-tier engineers.", + "cards": { + "people": { + "contributors": "contributors", + "community_members": "community members" + }, + "visitors": { + "description": "unique monthly visitors" + }, + "stars": { + "title": "stars" + }, + "community": { + "title": "fast-growing", + "description": "We are one of the fastest-growing communities in the ecosystem" + }, + "adoption": { + "title": "adoption", + "description": "charts at conferences, talks, and articles rely on our data" + }, + "default_source": { + "title": "default source", + "description": "pnpm made npmx the default source, many packages have been configured to link to npmx" + } + } + }, + "tiers": { + "title": "Sponsorship tiers", + "per_month": "/month", + "custom": "Custom", + "silver": { + "name": "Silver" + }, + "gold": { + "name": "Gold" + }, + "platinum": { + "name": "Platinum" + } + } + }, "account_menu": { "connect": "connect", "account": "Account", @@ -1399,6 +1501,10 @@ "label": "GitHub Stars", "description": "Number of stars on the GitHub repository" }, + "githubForks": { + "label": "GitHub Forks", + "description": "Number of forks on the GitHub repository" + }, "githubIssues": { "label": "GitHub Issues", "description": "Number of issues on the GitHub repository" @@ -1426,8 +1532,6 @@ "file_changes": "File Changes", "files_count": "{count} file | {count} files", "lines_hidden": "{count} line hidden | {count} lines hidden", - "file_too_large": "File too large to compare", - "file_size_warning": "{size} exceeds the 250KB limit for comparison", "compare_versions": "diff", "compare_versions_title": "Compare with latest version", "comparing_versions_label": "Comparing versions...", @@ -1468,6 +1572,9 @@ "change_ratio": "Change ratio", "char_edits": "Char edits", "diff_distance": "Diff distance", + "diff_truncated": "Diff truncated for performance. Showing the first changed lines only.", + "large_diff_mode": "Large file diff shown with inline edit merging disabled for performance.", + "large_diff_options_disabled": "Large file mode disables inline edit merging for performance.", "loading_diff": "Loading diff...", "loading_diff_error": "Failed to load diff", "merge_modified_lines": "Merge modified lines", diff --git a/i18n/locales/es.json b/i18n/locales/es.json index fff67c83e8..3674128de3 100644 --- a/i18n/locales/es.json +++ b/i18n/locales/es.json @@ -400,12 +400,9 @@ "example": "Ejemplo:", "native": "Esto se puede reemplazar con {replacement}, disponible desde Node {nodeVersion}.", "native_no_version": "Este paquete se puede reemplazar con {replacement}.", - "simple": "La {community} ha marcado este paquete como redundante, con el siguiente consejo: {replacement}.", - "documented": "La {community} ha seรฑalado que este paquete tiene alternativas con mejor rendimiento.", "none": "Este paquete se ha marcado como ya no necesario y es probable que su funcionalidad estรฉ disponible de forma nativa en todos los motores.", "learn_more": "Mรกs informaciรณn", "learn_more_above": "Mรกs informaciรณn arriba.", - "community": "comunidad", "consider_no_dep": "+ ยฟConsiderar sin dependencia?" }, "stats": { @@ -550,7 +547,6 @@ "view_all": "Ver {count} versiรณn | Ver las {count} versiones", "view_all_versions": "Ver todas las versiones", "distribution_title": "Grupo Semver", - "distribution_modal_title": "Versiones", "distribution_range_date_same_year": "de {from} a {to}, {endYear}", "distribution_range_date_multiple_years": "de {from}, {startYear} a {to}, {endYear}", "grouping_major": "Mayor", @@ -1421,8 +1417,6 @@ "file_changes": "Cambios en archivos", "files_count": "{count} archivos", "lines_hidden": "{count} lรญneas ocultas", - "file_too_large": "Archivo demasiado grande para comparar", - "file_size_warning": "{size} excede el lรญmite de 250KB para la comparaciรณn", "compare_versions": "diferencia", "compare_versions_title": "Comparar con la รบltima versiรณn", "comparing_versions_label": "Comparando versiones...", diff --git a/i18n/locales/fr-FR.json b/i18n/locales/fr-FR.json index a85b4a926b..12ea672f09 100644 --- a/i18n/locales/fr-FR.json +++ b/i18n/locales/fr-FR.json @@ -20,7 +20,10 @@ "chat": "espace de discussion", "builders_chat": "builders", "keyboard_shortcuts": "raccourcis clavier", - "brand": "Marque" + "brand": "Marque", + "resources": "Ressources", + "features": "Fonctionnalitรฉs", + "other": "Autres" }, "shortcuts": { "section": { @@ -254,7 +257,6 @@ "hide_platform_packages_description": "Masquer les paquets binaires natifs comme {'@'}esbuild/linux-x64 des rรฉsultats", "enable_graph_pulse_loop": "Activer la boucle de l'effet de pulsation sur le mini-graphe", "enable_graph_pulse_loop_description": "Activer une animation de pulsation continue sur le graphique des tรฉlรฉchargements hebdomadaires. Cette animation peut รชtre gรชnante pour certaines personnes.", - "enable_code_ligatures": "Activer les ligatures de code", "theme": "Thรจme", "theme_light": "Clair", "theme_dark": "Sombre", @@ -284,6 +286,7 @@ }, "keyboard_shortcuts_enabled": "Activer les raccourcis clavier", "keyboard_shortcuts_enabled_description": "Les raccourcis clavier peuvent รชtre dรฉsactivรฉs s'ils entrent en conflit avec d'autres raccourcis du navigateur ou du systรจme", + "enable_code_ligatures": "Activer les ligatures de code", "enable_changelog_autoscroll": "Scroller automatiquement ร  la version voulue", "enable_changelog_autoscroll_description": "Scroller automatiquement ร  โ€” ou prรจs โ€” de la version voulue dans la page des changements" }, @@ -345,8 +348,8 @@ "tangled": "Voir sur Tangled" }, "collapse": "Rรฉduire", - "expand": "Dรฉvelopper", "collapse_with_name": "Rรฉduire {name}", + "expand": "Dรฉvelopper", "expand_with_name": "Dรฉvelopper {name}" }, "profile": { @@ -385,15 +388,21 @@ "size": "La taille d'installation a augmentรฉ de {percent} ({size} de plus)", "deps": "{count} dรฉpendances supplรฉmentaires" }, + "size_decrease": { + "title_size": "La taille du paquet a diminuรฉ depuis la v{version} !", + "title_deps": "Le nombre de dรฉpendances a diminuรฉ depuis la v{version} !", + "title_both": "La taille du paquet et le nombre de dรฉpendances ont diminuรฉ depuis la v{version} !", + "size": "Taille d'installation rรฉduite de {percent} ({size} de moins)", + "deps": "{count} dรฉpendance en moins | {count} dรฉpendances en moins" + }, "replacement": { "title": "Vous n'avez peut-รชtre pas besoin de cette dรฉpendance.", + "example": "Exemple :", "native": "Ceci peut รชtre remplacรฉ par {replacement}, disponible depuis Node {nodeVersion}.", - "simple": "La {community} a signalรฉ ce paquet comme redondant, avec ce conseil : {replacement}.", - "documented": "La {community} a signalรฉ que ce paquet a des alternatives plus performantes.", + "native_no_version": "Ce paquet peut รชtre remplacรฉ par {replacement}.", "none": "Ce paquet a รฉtรฉ signalรฉ comme n'รฉtant plus nรฉcessaire, et sa fonctionnalitรฉ est probablement disponible nativement dans tous les moteurs.", "learn_more": "En savoir plus", "learn_more_above": "En savoir plus ci-dessus.", - "community": "communautรฉ", "consider_no_dep": "+ Envisager sans dรฉpendance ?" }, "stats": { @@ -520,6 +529,7 @@ "weekly_downloads": "Tรฉlรฉchargements hebdomadaires", "keywords": "Mots-clรฉs", "license": "Licence", + "version": "Version", "select": "Sรฉlectionner le paquet", "select_maximum": "Vous pouvez sรฉlectionner jusqu'ร  {count} paquets" }, @@ -538,7 +548,6 @@ "view_all": "Voir la version | Voir les {count} versions", "view_all_versions": "Voir toutes les versions", "distribution_title": "Groupe Semver", - "distribution_modal_title": "Versions", "distribution_range_date_same_year": "de {from} ร  {to} {endYear}", "distribution_range_date_multiple_years": "de {from} {startYear} ร  {to} {endYear}", "grouping_major": "Majeure", @@ -559,6 +568,9 @@ "filter_help": "Infos sur le filtre de plage semver", "filter_tooltip": "Filtrer les versions avec une {link}. Par exemple, ^3.0.0 affiche toutes les versions 3.x.", "filter_tooltip_link": "plage semver", + "license_change_help": "Dรฉtails sur le changement de licence", + "license_change_warning": "La licence a changรฉ depuis la version prรฉcรฉdente.", + "license_change_record": "La licence de ce paquet est passรฉe de \"{from}\" ร  \"{to}\".", "no_matches": "Aucune version ne correspond ร  cette plage", "copy_alt": { "per_version_analysis": "La version {version} a รฉtรฉ tรฉlรฉchargรฉe {downloads} fois", @@ -697,10 +709,17 @@ "general_description": "Lโ€™axe Y reprรฉsente le nombre de tรฉlรฉchargements. Lโ€™axe X reprรฉsente la plage de dates, de {start_date} ร  {end_date}, avec une pรฉriode de temps {granularity}.{estimation_notice} {packages_analysis}. {watermark}.", "facet_bar_general_description": "Graphique en barres horizontales pour : {packages}, comparant {facet} ({description}). {facet_analysis} {watermark}.", "facet_bar_analysis": "{package_name} a une valeur de {value}." + }, + "embedding": { + "chart": "Intรฉgrer ce graphique", + "copy_url": "Copiez cette URL pour intรฉgrer le graphique ร  votre site web", + "preview": "Aperรงu", + "tip": "Par dรฉfaut, si startDate et endDate ne sont pas renseignรฉs, la pรฉriode couvre les 12 derniers mois." } }, "downloads": { "title": "Tรฉlรฉchargements hebdo.", + "version_distribution_title": "tรฉlรฉchargements hebdomadaires pour la version {version}", "community_distribution": "Voir la distribution des versions tรฉlรฉchargรฉes par la communautรฉ", "subtitle": "Toutes versions confondues", "sparkline_nav_hint": "Utilisez โ† โ†’" @@ -995,6 +1014,7 @@ "view_raw": "Voir le fichier brut", "toggle_container": "Changer la largeur du conteneur", "open_raw_file": "Ouvrir le fichier brut", + "open_path_dropdown": "Ouvrir le menu du chemin", "file_too_large": "Fichier trop volumineux pour l'aperรงu", "file_size_warning": "{size} dรฉpasse la limite de 500 Ko pour la coloration syntaxique", "failed_to_load": "ร‰chec du chargement du fichier", @@ -1012,7 +1032,6 @@ "preview": "aperรงu", "code": "code" }, - "open_path_dropdown": "Ouvrir le menu du chemin", "file_path": "Chemin du fichier", "binary_file": "Fichier binaire", "binary_rendering_warning": "Le type de fichier \"{contentType}\" n'est pas pris en charge pour l'aperรงu." @@ -1169,6 +1188,9 @@ }, "team": { "title": "ร‰quipe", + "core": "Noyau", + "maintainers": "Mainteneurs", + "role_core": "noyau", "role_steward": "pilote", "role_maintainer": "mainteneur", "sponsor": "sponsor", @@ -1406,8 +1428,6 @@ "file_changes": "Modifications de fichiers", "files_count": "{count} fichiers", "lines_hidden": "{count} lignes masquรฉes", - "file_too_large": "Fichier trop volumineux pour รชtre comparรฉ", - "file_size_warning": "{size} dรฉpasse la limite de 250 Ko pour la comparaison", "compare_versions": "diff", "compare_versions_title": "Comparer avec la derniรจre version", "comparing_versions_label": "Comparaison des versions...", @@ -1708,6 +1728,7 @@ "discord_link_text": "chat.npmx.dev" } }, + "alt_logo_kawaii": "Une version mignonne, arrondie et colorรฉe du logo npmx.", "changelog": { "pre_release": "Prรฉ-version", "draft": "Brouillon", @@ -1718,6 +1739,5 @@ }, "rate_limit_ungh": "Dรฉsolรฉ, la limite de requรชtes ร  l'API GitHub a รฉtรฉ atteinte, rรฉessayez plus tard", "version_unavailable": "La version demandรฉe n'est pas disponible." - }, - "alt_logo_kawaii": "Une version mignonne, arrondie et colorรฉe du logo npmx." + } } diff --git a/i18n/locales/hi-IN.json b/i18n/locales/hi-IN.json index 16ddb8fe46..04dae41584 100644 --- a/i18n/locales/hi-IN.json +++ b/i18n/locales/hi-IN.json @@ -75,6 +75,23 @@ "instant_search_turn_off": "เคฌเค‚เคฆ เค•เคฐเฅ‡เค‚", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "เคฎเฅเค–เฅเคฏ", "popular_packages": "เคฒเฅ‹เค•เคชเฅเคฐเคฟเคฏ เคชเฅˆเค•เฅ‡เคœ", @@ -250,15 +267,13 @@ "size": "เค‡เค‚เคธเฅเคŸเฅ‰เคฒ เค†เค•เคพเคฐ {percent} เคฌเคขเคผเคพ ({size} เค…เคงเคฟเค•)", "deps": "{count} เค”เคฐ เคจเคฟเคฐเฅเคญเคฐเคคเคพเคเค" }, + "size_decrease": {}, "replacement": { "title": "เค†เคชเค•เฅ‹ เค‡เคธ เคจเคฟเคฐเฅเคญเคฐเคคเคพ เค•เฅ€ เค†เคตเคถเฅเคฏเค•เคคเคพ เคจเคนเฅ€เค‚ เคนเฅ‹ เคธเค•เคคเฅ€เฅค", "native": "เค‡เคธเฅ‡ {replacement} เคธเฅ‡ เคฌเคฆเคฒเคพ เคœเคพ เคธเค•เคคเคพ เคนเฅˆ, เคœเฅ‹ Node {nodeVersion} เคธเฅ‡ เค‰เคชเคฒเคฌเฅเคง เคนเฅˆเฅค", - "simple": "{community} เคจเฅ‡ เค‡เคธ เคชเฅˆเค•เฅ‡เคœ เค•เฅ‹ เคจเคฟเคฐเคฐเฅเคฅเค• เค•เฅ‡ เคฐเฅ‚เคช เคฎเฅ‡เค‚ เคซเคผเฅเคฒเฅˆเค— เค•เคฟเคฏเคพ เคนเฅˆ, เคธเคฒเคพเคน เค•เฅ‡ เคธเคพเคฅ: {replacement}เฅค", - "documented": "{community} เคจเฅ‡ เค‡เคธ เคชเฅˆเค•เฅ‡เคœ เค•เฅ‹ เค…เคงเคฟเค• เคชเฅเคฐเคฆเคฐเฅเคถเคจเค•เคพเคฐเฅ€ เคตเคฟเค•เคฒเฅเคชเฅ‹เค‚ เค•เฅ‡ เคฐเฅ‚เคช เคฎเฅ‡เค‚ เคซเคผเฅเคฒเฅˆเค— เค•เคฟเคฏเคพ เคนเฅˆเฅค", "none": "เคฏเคน เคชเฅˆเค•เฅ‡เคœ เค…เคฌ เค†เคตเคถเฅเคฏเค• เคจเคนเฅ€เค‚ เคนเฅ‹เคจเฅ‡ เค•เฅ‡ เคฐเฅ‚เคช เคฎเฅ‡เค‚ เคซเคผเฅเคฒเฅˆเค— เค•เคฟเคฏเคพ เค—เคฏเคพ เคนเฅˆ, เค”เคฐ เค‡เคธเค•เฅ€ เค•เคพเคฐเฅเคฏเค•เฅเคทเคฎเคคเคพ เคธเคญเฅ€ เค‡เค‚เคœเคจเฅ‹เค‚ เคฎเฅ‡เค‚ เคจเฅ‡เคŸเคฟเคตเคฒเฅ€ เค‰เคชเคฒเคฌเฅเคง เคนเฅ‹เคจเฅ‡ เค•เฅ€ เคธเค‚เคญเคพเคตเคจเคพ เคนเฅˆเฅค", "learn_more": "เค”เคฐ เคœเคพเคจเฅ‡เค‚", "learn_more_above": "เคŠเคชเคฐ เค”เคฐ เคœเคพเคจเฅ‡เค‚เฅค", - "community": "เคธเคฎเฅเคฆเคพเคฏ", "consider_no_dep": "+ เคฌเคฟเคจเคพ เคจเคฟเคฐเฅเคญเคฐเคคเคพ เคชเคฐ เคตเคฟเคšเคพเคฐ เค•เคฐเฅ‡เค‚?" }, "stats": { @@ -397,7 +412,6 @@ "view_all": "{count} เคธเค‚เคธเฅเค•เคฐเคฃ เคฆเฅ‡เค–เฅ‡เค‚ | เคธเคญเฅ€ {count} เคธเค‚เคธเฅเค•เคฐเคฃ เคฆเฅ‡เค–เฅ‡เค‚", "view_all_versions": "เคธเคญเฅ€ เคธเค‚เคธเฅเค•เคฐเคฃ เคฆเฅ‡เค–เฅ‡เค‚", "distribution_title": "Semver เคธเคฎเฅ‚เคน", - "distribution_modal_title": "เคธเค‚เคธเฅเค•เคฐเคฃ", "distribution_range_date_same_year": "{from} เคธเฅ‡ {to}, {endYear} เคคเค•", "distribution_range_date_multiple_years": "{from}, {startYear} เคธเฅ‡ {to}, {endYear} เคคเค•", "grouping_major": "เคฎเฅ‡เคœเคฐ", @@ -427,6 +441,11 @@ "current_tags": "เคตเคฐเฅเคคเคฎเคพเคจ เคŸเฅˆเค—เฅเคธ", "no_match_filter": "เค•เฅ‹เคˆ เคธเค‚เคธเฅเค•เคฐเคฃ {filter} เคธเฅ‡ เคฎเฅ‡เคฒ เคจเคนเฅ€เค‚ เค–เคพเคคเคพ" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "เคจเคฟเคฐเฅเคญเคฐเคคเคพเคเค ({count})", "list_label": "เคชเฅˆเค•เฅ‡เคœ เคจเคฟเคฐเฅเคญเคฐเคคเคพเคเค", @@ -626,6 +645,9 @@ "tarball": ".tar.gz เค•เฅ‡ เคฐเฅ‚เคช เคฎเฅ‡เค‚ Tarball เคกเคพเค‰เคจเคฒเฅ‹เคก เค•เคฐเฅ‡เค‚" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "เคฒเฅ‹เค•เคฒ เค•เคจเฅ‡เค•เฅเคŸเคฐ", @@ -1097,6 +1119,9 @@ "packages_selected": "{count}/{max} เคชเฅˆเค•เฅ‡เคœ เคšเฅเคจเฅ‡ เค—เคเฅค", "add_hint": "เคคเฅเคฒเคจเคพ เค•เคฐเคจเฅ‡ เค•เฅ‡ เคฒเคฟเค เค•เคฎ เคธเฅ‡ เค•เคฎ 2 เคชเฅˆเค•เฅ‡เคœ เคœเฅ‹เคกเคผเฅ‡เค‚เฅค" }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(เค•เฅ‹เคˆ เคจเคฟเคฐเฅเคญเคฐเคคเคพ เคจเคนเฅ€เค‚)", "typeahead_title": "James เค•เฅเคฏเคพ เค•เคฐเคคเฅ‡?", @@ -1171,7 +1196,10 @@ "vulnerabilities": { "label": "เค•เคฎเคœเฅ‹เคฐเคฟเคฏเคพเค", "description": "เคœเฅเคžเคพเคค เคธเฅเคฐเค•เฅเคทเคพ เค•เคฎเคœเฅ‹เคฐเคฟเคฏเคพเค" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "เค•เฅ‹เคˆ เคญเฅ€", @@ -1191,8 +1219,6 @@ "file_changes": "เคซเคผเคพเค‡เคฒ เคชเคฐเคฟเคตเคฐเฅเคคเคจ", "files_count": "{count} เคซเคผเคพเค‡เคฒ | {count} เคซเคผเคพเค‡เคฒเฅ‡เค‚", "lines_hidden": "{count} เคชเค‚เค•เฅเคคเคฟ เค›เคฟเคชเฅ€ | {count} เคชเค‚เค•เฅเคคเคฟเคฏเคพเค เค›เคฟเคชเฅ€", - "file_too_large": "เคคเฅเคฒเคจเคพ เค•เฅ‡ เคฒเคฟเค เคซเคผเคพเค‡เคฒ เคฌเคนเฅเคค เคฌเคกเคผเฅ€ เคนเฅˆ", - "file_size_warning": "เคคเฅเคฒเคจเคพ เค•เฅ‡ เคฒเคฟเค {size} 250KB เคธเฅ€เคฎเคพ เคธเฅ‡ เค…เคงเคฟเค• เคนเฅˆ", "compare_versions": "diff", "compare_versions_title": "เคจเคตเฅ€เคจเคคเคฎ เคธเค‚เคธเฅเค•เคฐเคฃ เคธเฅ‡ เคคเฅเคฒเคจเคพ เค•เคฐเฅ‡เค‚", "comparing_versions_label": "เคธเค‚เคธเฅเค•เคฐเคฃเฅ‹เค‚ เค•เฅ€ เคคเฅเคฒเคจเคพ เค•เฅ€ เคœเคพ เคฐเคนเฅ€ เคนเฅˆ...", @@ -1449,5 +1475,8 @@ "customize": {}, "typography": {}, "guidelines": {} + }, + "changelog": { + "error": {} } } diff --git a/i18n/locales/hu-HU.json b/i18n/locales/hu-HU.json index 5b2f287810..bfb78e3d27 100644 --- a/i18n/locales/hu-HU.json +++ b/i18n/locales/hu-HU.json @@ -65,6 +65,23 @@ "view_org_packages": "E szervezet csomagjainak megtekintรฉse" } }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "Fล‘menรผ", "popular_packages": "Nรฉpszerลฑ csomagok", @@ -198,15 +215,13 @@ "size": "A telepรญtรฉsi mรฉret {percent}-kal nล‘tt ({size} nagyobb)", "deps": "{count} tovรกbbi fรผggล‘sรฉg" }, + "size_decrease": {}, "replacement": { "title": "Lehet, hogy nincs szรผksรฉged erre a fรผggล‘sรฉgre.", "native": "Ez helyettesรญthetล‘ a kรถvetkezล‘vel: {replacement}, amely elรฉrhetล‘ a Node {nodeVersion} verziรณ รณta.", - "simple": "A {community} szerint ez a csomag felesleges, az alรกbbi javaslattal: {replacement}.", - "documented": "A {community} szerint ennek a csomagnak vannak jobb teljesรญtmรฉnyลฑ alternatรญvรกi.", "none": "Ez a csomag feleslegesnek lett jelรถlve, a funkciรณ valรณszรญnลฑleg natรญvan elรฉrhetล‘.", "learn_more": "Tudj meg tรถbbet", "learn_more_above": "Tudj meg tรถbbet fentebb.", - "community": "kรถzรถssรฉg", "consider_no_dep": "+ Fontold meg a fรผggล‘sรฉg nรฉlkรผlรถzรฉst?" }, "stats": { @@ -332,7 +347,6 @@ "deprecated_title": "{version} (elavult)", "view_all": "{count} verziรณ megtekintรฉse | Az รถsszes {count} verziรณ megtekintรฉse", "distribution_title": "Semver csoport", - "distribution_modal_title": "Verziรณk", "distribution_range_date_same_year": "{from} -tรณl {to} -ig, {endYear}", "distribution_range_date_multiple_years": "{from} -tรณl, {startYear} -ben {to} -ig, {endYear}", "grouping_major": "Fล‘", @@ -356,6 +370,11 @@ "general_description": "Sรกvdiagram, amely a(z) {package_name} csomag {semver_grouping_mode} verziรณinak verziรณ szerinti letรถltรฉseit mutatja, {date_range_label} a(z) {first_version} verziรณtรณl a(z) {last_version} verziรณig. A legtรถbbszรถr letรถltรถtt verziรณ a(z) {max_downloaded_version}, {max_version_downloads} letรถltรฉssel. {per_version_analysis}. {watermark}." } }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Fรผggล‘sรฉg ({count}) | Fรผggล‘sรฉgek ({count})", "list_label": "Csomag fรผggล‘sรฉgei", @@ -392,6 +411,7 @@ "show_less": "(kevesebb megjelenรญtรฉse)" }, "trends": { + "chart_assistive_text": {}, "granularity": "Bontรกs", "granularity_daily": "Napi", "granularity_weekly": "Heti", @@ -537,6 +557,9 @@ }, "download": {} }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Helyi Connector", @@ -994,6 +1017,9 @@ "packages_selected": "{count}/{max} csomag kivรกlasztva.", "add_hint": "Adj hozzรก legalรกbb 2 csomagot az รถsszehasonlรญtรกshoz." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(Nincs fรผggล‘sรฉg)", "typeahead_title": "Mit tenne James?", @@ -1068,7 +1094,10 @@ "vulnerabilities": { "label": "Sebezhetล‘sรฉgek", "description": "Ismert biztonsรกgi sebezhetล‘sรฉgek" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "Bรกrmely", @@ -1088,8 +1117,6 @@ "file_changes": "Fรกjl mรณdosรญtรกsok", "files_count": "{count} fรกjl", "lines_hidden": "{count} sor elrejtve", - "file_too_large": "A fรกjl tรบl nagy az รถsszehasonlรญtรกshoz", - "file_size_warning": "{size} meghaladja a 250KB-os limitet az รถsszehasonlรญtรกshoz", "compare_versions": "diff", "version_invalid_url_format": {}, "summary": "ร–sszegzรฉs", @@ -1237,5 +1264,23 @@ "translation_status": { "table": {} }, - "action_bar": {} + "vacations": { + "what": {}, + "meantime": {}, + "return": {}, + "stats": { + "subtitle": {} + } + }, + "action_bar": {}, + "logo_menu": {}, + "brand": { + "logos": {}, + "customize": {}, + "typography": {}, + "guidelines": {} + }, + "changelog": { + "error": {} + } } diff --git a/i18n/locales/id-ID.json b/i18n/locales/id-ID.json index d35c639463..b21589bd24 100644 --- a/i18n/locales/id-ID.json +++ b/i18n/locales/id-ID.json @@ -76,6 +76,23 @@ "instant_search_turn_off": "nonaktifkan", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "Utama", "popular_packages": "Paket populer", @@ -265,15 +282,13 @@ "size": "Ukuran instalasi meningkat sebesar {percent} ({size} lebih besar)", "deps": "{count} lebih banyak dependensi" }, + "size_decrease": {}, "replacement": { "title": "Mungkin Anda tidak butuh dependensi ini.", "native": "Paket ini dapat diganti dengan {replacement}, tersedia sejak Node {nodeVersion}.", - "simple": "{community} menganggap paket ini redundan, dengan saran: {replacement}.", - "documented": "{community} menganggap paket ini memiliki alternatif yang lebih berperforma.", "none": "Paket ini ditandai sudah tidak diperlukan, fungsinya kemungkinan sudah tersedia secara bawaan (native).", "learn_more": "Pelajari lebih lanjut", "learn_more_above": "Pelajari selengkapnya di atas.", - "community": "komunitas", "consider_no_dep": "+ Pertimbangkan tanpa dependensi?" }, "stats": { @@ -412,7 +427,6 @@ "view_all": "Lihat {count} versi | Lihat semua {count} versi", "view_all_versions": "Lihat semua versi", "distribution_title": "Grup Semver", - "distribution_modal_title": "Versi", "distribution_range_date_same_year": "dari {from} hingga {to}, {endYear}", "distribution_range_date_multiple_years": "dari {from}, {startYear} hingga {to}, {endYear}", "grouping_major": "Mayor", @@ -442,6 +456,11 @@ "current_tags": "Tag Saat Ini", "no_match_filter": "Tidak ada versi yang cocok dengan {filter}" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Dependensi ({count})", "list_label": "Dependensi paket", @@ -644,6 +663,9 @@ "tarball": "Unduh Tarball sebagai .tar.gz" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Konektor Lokal", @@ -1116,6 +1138,9 @@ "packages_selected": "{count}/{max} paket dipilih.", "add_hint": "Tambah setidaknya 2 paket untuk dibandingkan." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(Tanpa Ketergantungan)", "typeahead_title": "Apa yang Akan Anda Lakukan?", @@ -1194,7 +1219,10 @@ "vulnerabilities": { "label": "Kerentanan", "description": "Kerentanan keamanan yang diketahui" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "Apa saja", @@ -1214,8 +1242,6 @@ "file_changes": "Perubahan Berkas", "files_count": "{count} file", "lines_hidden": "{count} baris disembunyikan", - "file_too_large": "File terlalu besar untuk dibandingkan", - "file_size_warning": "{size} melebihi batas 250KB untuk perbandingan", "compare_versions": "diff", "compare_versions_title": "Bandingkan dengan versi terbaru", "comparing_versions_label": "Membandingkan versi...", @@ -1515,5 +1541,8 @@ "message": "Aksesibilitas penting bagi kami, dan kami ingin Anda ikut mendukung visi ini. Saat menggunakan media yang disebutkan, pastikan kontras dengan latar cukup, dan jangan gunakan ukuran kurang dari 24px. Jika Anda membutuhkan sumber daya lain atau informasi tambahan tentang proyek ini, silakan hubungi kami di {link}.", "discord_link_text": "chat.npmx.dev" } + }, + "changelog": { + "error": {} } } diff --git a/i18n/locales/it-IT.json b/i18n/locales/it-IT.json index b19efca8db..24f00a8039 100644 --- a/i18n/locales/it-IT.json +++ b/i18n/locales/it-IT.json @@ -13,11 +13,17 @@ "trademark_disclaimer": "npm รจ un marchio registrato da npm, Inc. Questo sito non รจ affiliato con npm, Inc.", "footer": { "about": "info", + "blog": "blog", "docs": "docs", "source": "codice", "social": "social", "chat": "chat", - "keyboard_shortcuts": "shortcuts tastiera" + "builders_chat": "costruttori", + "keyboard_shortcuts": "shortcuts tastiera", + "brand": "marca", + "resources": "Risorse", + "features": "funzionalitร ", + "other": "Altro" }, "shortcuts": { "section": { @@ -25,6 +31,9 @@ "search": "Cerca", "package": "Pacchetto" }, + "ctrl_key": "Ctrl", + "command_palette": "Apri tavola dei comandi", + "command_palette_description": "Usa la tavola dei comandi per navigare pagine, pacchetti, configurazioni, e link esterni senza lasciare la tastiera. Premi {ctrlKey}+K.", "focus_search": "Focus cerca", "show_kbd_hints": "Evidenzia suggerimenti da tastiera", "settings": "Apri impostazioni", @@ -33,7 +42,12 @@ "navigate_results": "Naviga risultati", "go_to_result": "Vai al risultato", "open_code_view": "Apri vista codice", - "open_docs": "Apri documentazione" + "open_docs": "Apri documentazione", + "disable_shortcuts": "Puoi disabilitare le scorciatoie della tastiera in {settings}.", + "open_main": "Apri informazioni principali", + "open_diff": "Apri differenze tra versioni", + "open_timeline": "Apri cronologia", + "open_stats": "Apri statistiche" }, "search": { "label": "Cerca i pacchetti npm", @@ -62,6 +76,121 @@ "org": "organizzazione", "view_user_packages": "Vedi pacchetti di questo utente", "view_org_packages": "Vedi pacchetti di questa organizzazione" + }, + "instant_search": "Ricerca istantanea", + "instant_search_on": "attiva", + "instant_search_off": "disattiva", + "instant_search_turn_on": "attiva", + "instant_search_turn_off": "disattiva", + "instant_search_advisory": "{label} {state} โ€” {action}" + }, + "command_palette": { + "title": "Palette dei comandi", + "quick_actions": "vai a...", + "subtitle": "naviga in npmx e modifica le impostazioni rapidamente", + "subtitle_languages": "scegli una lingua o aiuta a migliorare le traduzioni", + "instructions": "Digita per filtrare i comandi. Usa i tasti freccia per scorrere i risultati e Invio per eseguire un comando.", + "input_label": "Ricerca nella palette dei comandi", + "results_label": "Risultati dei comandi", + "placeholder": "digita un comando...", + "back": "Indietro", + "empty": "Nessun comando trovato", + "empty_search_hint": "Premi Invio per cercare \"{query}\".", + "current": "corrente", + "here": "sei qui", + "connected": "connesso", + "state": { + "on": "attivo", + "off": "disattivo" + }, + "groups": { + "actions": "Azioni", + "help": "Aiuto", + "language": "Lingua", + "connections": "Connessioni", + "navigation": "Navigazione", + "links": "Link", + "npmx": "npmx", + "package": "Pacchetto", + "package_with_name": "Pacchetto ({name})", + "versions": "Versioni", + "versions_with_name": "Versioni di {name}" + }, + "actions": { + "search": "Cerca", + "search_for": "Cerca \"{query}\"", + "keyboard_shortcuts": "Scorciatoie da tastiera", + "help_translate": "Aiuta a tradurre" + }, + "connections": { + "npm_connect": "Connetti a npm CLI", + "npm_connected": "npm CLI (~{username})", + "npm_disconnect": "Disconnetti npm CLI", + "atmosphere_connect": "Connetti ad Atmosphere", + "atmosphere_connected": "atmosphere ({'@'}{handle})", + "atmosphere_disconnect": "Disconnetti Atmosphere" + }, + "navigation": { + "home": "home", + "packages": "pacchetti (~{username})", + "orgs": "organizzazioni (~{username})", + "profile": "profilo ({'@'}{handle})" + }, + "links": { + "external": "Link esterno" + }, + "package_links": { + "stars": "Star del repository", + "forks": "Fork del repository" + }, + "theme": { + "system": "Usa tema di sistema", + "light": "Usa tema chiaro", + "dark": "Usa tema scuro" + }, + "package": { + "main": "Pagina del pacchetto", + "docs": "Documentazione", + "code": "Codice", + "diff": "Diff", + "compare": "Confronta questo pacchetto", + "download": "Scarica tarball", + "changelog": "Changelog", + "stats": "Statistiche" + }, + "package_actions": { + "copy_run": "Copia comando di esecuzione" + }, + "code": { + "copy_file": "Copia contenuto del file" + }, + "diff": { + "merge_modified_lines": "Unisci righe modificate", + "word_wrap": "A capo automatico" + }, + "version": { + "label": "{version}" + }, + "status": { + "available_in_context": "{context}. Nessun comando disponibile | {context}. 1 comando disponibile | {context}. {count} comandi disponibili", + "matching_in_context": "{context}. Nessun comando trovato | {context}. 1 comando trovato | {context}. {count} comandi trovati", + "no_matches_search_in_context": "{context}. Nessun comando trovato. Premi Invio per cercare \"{query}\"." + }, + "announcements": { + "language_changed": "Lingua impostata su {language}.", + "relative_dates_on": "Date relative attive.", + "relative_dates_off": "Date relative disattive.", + "theme_changed": "Tema impostato su {theme}.", + "accent_color_changed": "Colore principale impostato su {color}.", + "background_theme_changed": "Sfumatura di sfondo impostata su {theme}.", + "download_started": "Download del tarball {package} in corso.", + "copied_to_clipboard": "Copiato negli appunti.", + "npm_disconnected": "npm CLI disconnesso.", + "atmosphere_disconnected": "Atmosphere disconnesso.", + "facets_all_selected": "Tutti i filtri selezionati.", + "facets_all_deselected": "Tutti i filtri deselezionati.", + "view_switched": "Passato alla vista {view}.", + "setting_toggled": "{setting} {state}." } }, "nav": { @@ -77,8 +206,55 @@ "tap_to_search": "Tocca per cercare" }, "blog": { - "author": {}, - "atproto": {} + "title": "Blog", + "heading": "blog", + "meta_description": "Approfondimenti e aggiornamenti dalla community di npmx", + "author": { + "view_profile": "Visualizza il profilo di {name} su Bluesky" + }, + "draft_badge": "Bozza", + "draft_banner": "Questa รจ una bozza non pubblicata. Potrebbe essere incompleta o contenere imprecisioni.", + "no_posts": "Nessun articolo trovato.", + "atproto": { + "view_on_bluesky": "Visualizza su Bluesky", + "reply_on_bluesky": "Rispondi su Bluesky", + "likes_on_bluesky": "Mi piace su Bluesky", + "like_or_reply_on_bluesky": "Metti mi piace o aggiungi un commento su Bluesky", + "no_comments_yet": "Ancora nessun commento.", + "could_not_load_comments": "Impossibile caricare i commenti.", + "comments": "Commenti", + "loading_comments": "Caricamento commenti...", + "updating": "Aggiornamento in corso...", + "reply_count": "{count} risposta | {count} risposte", + "like_count": "{count} mi piace | {count} mi piace", + "repost_count": "{count} repost | {count} repost", + "more_replies": "{count} altra risposta... | {count} altre risposte..." + } + }, + "noodles": { + "title": "noodles", + "meta_description": "Tutti i noodle che abbiamo mostrato su npmx: i loghi stagionali, gli easter egg e le storie dietro di essi.", + "latest": "Ultimi noodle", + "what_is": "Cosa sono i noodle", + "what_is_body": "I noodle sono le varianti giocose del logo npmx che pubblichiamo in homepage per celebrare release, festivitร , eventi e altri momenti speciali. Pensali come i Google Doodle, ma per i pacchetti npm.", + "empty": "Ancora nessun noodle.", + "load_more": "Carica altri {count}", + "dates": "Date di attivazione", + "shipped_in": "Pubblicato in", + "credits": "Crediti", + "learn_more": "Scopri di piรน", + "carousel_prev": "Immagine precedente", + "carousel_next": "Immagine successiva", + "carousel_dots": "Navigazione varianti immagine", + "carousel_jump": "Vai all'immagine {index}", + "lens_label": "{title} โ€” sequenza immagini", + "lens_slide": "immagine {index}", + "lens_slide_position": "Slide {index} di {total}", + "back_to_archive": "Torna a tutti i noodle", + "missing": { + "title": "Questo noodle non รจ mai uscito dalla ciotola.", + "body": "Non abbiamo un noodle \"{slug}\" nel menu. O รจ ancora in preparazione, o non รจ mai stato scritto. In ogni caso, torna all'archivio." + } }, "settings": { "title": "impostazioni", @@ -88,7 +264,8 @@ "appearance": "Aspetto", "display": "Visualizzazione", "search": "Fonte dati", - "language": "Lingua" + "language": "Lingua", + "keyboard_shortcuts": "Scorciatoie tastiera" }, "data_source": { "label": "Fonte dati", @@ -98,25 +275,47 @@ "algolia": "Algolia", "algolia_description": "Usa Algolia per una ricerca piรน veloce, pagine organizzazione e utente." }, + "instant_search": "Ricerca istantanea", + "instant_search_description": "Naviga alla pagina di ricerca e aggiorna i risultati mentre digiti.", "relative_dates": "Date relative", "include_types": "Includi {'@'}types durante l'installazione", "include_types_description": "Aggiungi il pacchetto {'@'}types al comando install per i pacchetti senza tipo", "hide_platform_packages": "Nascondi pacchetti specifici della piattaforma nella ricerca", "hide_platform_packages_description": "Nascondi i pacchetti binari nativi come {'@'}esbuild/linux-x64 dai risultati", + "enable_graph_pulse_loop": "Abilita l'animazione pulse in loop sul mini grafico", + "enable_graph_pulse_loop_description": "Attiva un'animazione pulse continua sul grafico dei download settimanali. Questa animazione potrebbe risultare fastidiosa per alcuni utenti.", "theme": "Tema", "theme_light": "Chiaro", "theme_dark": "Scuro", "theme_system": "Sistema", "language": "Lingua", "help_translate": "Aiuta a tradurre npmx", + "translation_status": "Controlla lo stato globale delle traduzioni", "accent_colors": { - "label": "Colori di accento" + "label": "Colori di accento", + "neutral": "Neutro", + "sky": "Cielo", + "coral": "Corallo", + "amber": "Ambra", + "emerald": "Smeraldo", + "violet": "Viola", + "magenta": "Magenta" }, "clear_accent": "Cancella colore di accento", "translation_progress": "Progresso della traduzione", "background_themes": { - "label": "Sfumatura di sfondo" - } + "label": "Sfumatura di sfondo", + "neutral": "Neutro", + "stone": "Pietra", + "zinc": "Zinco", + "slate": "Ardesia", + "black": "Nero" + }, + "keyboard_shortcuts_enabled": "Abilita scorciatoie da tastiera", + "keyboard_shortcuts_enabled_description": "Le scorciatoie da tastiera possono essere disabilitate se entrano in conflitto con altre scorciatoie del browser o del sistema", + "enable_code_ligatures": "Abilita legature nel codice", + "enable_changelog_autoscroll": "Scorri automaticamente alla versione richiesta", + "enable_changelog_autoscroll_description": "Scorri automaticamente fino alla versione richiesta nel changelog del pacchetto" }, "i18n": { "missing_keys": "{count} chiave mancante | {count} chiavi mancanti", @@ -126,7 +325,13 @@ "edit_on_github": "Modifica su GitHub", "view_guide": "Guida alla traduzione" }, - "error": {}, + "error": { + "401": "Non autorizzato", + "404": "Pagina non trovata", + "500": "Errore interno del server", + "503": "Servizio non disponibile", + "default": "Qualcosa รจ andato storto" + }, "common": { "loading": "Caricando...", "loading_more": "Caricando altri...", @@ -142,6 +347,7 @@ "warnings": "Avvisi:", "go_back_home": "Torna alla home", "per_week": "/ settimana", + "per_week_short": "/sett", "vanity_downloads_hint": "Numero di vanitร : nessun pacchetto visualizzato | Numero di vanitร : per il pacchetto visualizzato | Numero di vanitร : somma di {count} pacchetti visualizzati", "sort": { "name": "nome", @@ -149,13 +355,46 @@ "members": "membri" }, "scroll_to_top": "Torna su", + "cancel": "Annulla", + "save": "Salva", + "edit": "Modifica", + "error": "Errore", "view_on": { "npm": "vedi su npm", - "github": "Vedi su GitHub" - } + "github": "Vedi su GitHub", + "gitlab": "Vedi su GitLab", + "bitbucket": "Vedi su Bitbucket", + "codeberg": "Vedi su Codeberg", + "git_repo": "Vedi sul repository Git", + "forgejo": "Vedi su Forgejo", + "gitea": "Vedi su Gitea", + "gitee": "Vedi su Gitee", + "radicle": "Vedi su Radicle", + "socket_dev": "Vedi su socket.dev", + "sourcehut": "Vedi su SourceHut", + "tangled": "Vedi su Tangled" + }, + "collapse": "Comprimi", + "collapse_with_name": "Comprimi {name}", + "expand": "Espandi", + "expand_with_name": "Espandi {name}" }, "profile": { - "invite": {} + "display_name": "Nome visualizzato", + "description": "Descrizione", + "no_description": "Nessuna descrizione", + "website": "Sito web", + "website_placeholder": "https://example.com", + "likes": "Mi piace", + "seo_title": "{handle} - npmx", + "seo_description": "Profilo npmx di {handle}", + "not_found": "Profilo non trovato", + "not_found_message": "Il profilo di {handle} non รจ stato trovato.", + "invite": { + "message": "Sembra che non stia ancora usando npmx. Vuoi farglielo sapere?", + "share_button": "Condividi su Bluesky", + "compose_text": "Ciao {'@'}{handle}! Hai giร  visto npmx.dev? รˆ un browser per il registro npm: veloce, moderno e open source.\nhttps://npmx.dev" + } }, "package": { "not_found": "Pacchetto Non Trovato", @@ -176,15 +415,23 @@ "size": "Dimensione di installazione aumentato del {percent} ({size} larger)", "deps": "{count} dipendenze in piรน" }, + "size_decrease": { + "title_size": "La dimensione del pacchetto รจ diminuita dalla v{version}!", + "title_deps": "Il numero di dipendenze รจ diminuito dalla v{version}!", + "title_both": "La dimensione del pacchetto e il numero di dipendenze sono diminuiti dalla v{version}!", + "size": "Dimensione di installazione ridotta del {percent} ({size} in meno)", + "deps": "{count} dipendenza in meno | {count} dipendenze in meno" + }, "replacement": { "title": "Questa dipendenza potrebbe non essere necessaria.", + "example": "Esempio:", "native": "Questo puรฒ essere sostituito con {replacement}, disponibile da Node {nodeVersion}.", - "simple": "La {community} ha segnalato questo pacchetto come ridondante, con il consiglio: {replacement}.", - "documented": "La {community} ha segnalato questo pacchetto come avente alternative piรน performanti.", + "native_no_version": "Questo pacchetto puรฒ essere sostituito con {replacement}.", + "simple": "Questo pacchetto รจ stato segnalato come ridondante, con il suggerimento: {replacement}", + "documented": "Questo pacchetto รจ stato segnalato come avente alternative piรน performanti.", "none": "Questo pacchetto รจ stato segnalato come non piรน necessario, e la sua funzionalitร  รจ probabilmente disponibile nativamente in tutti i motori.", "learn_more": "Scopri di piรน", "learn_more_above": "Scopri di piรน sopra", - "community": "comunitร ", "consider_no_dep": "Considera nessuna dipendenza?" }, "stats": { @@ -199,7 +446,10 @@ "size_tooltip": { "unpacked": "{size} dimensione non compattata (questo pacchetto)", "total": "{size} dimensione totale non compattata (inclusa {count} dipendenza per linux-x64) | {size} dimensione totale non compattata (incluse tutte le {count} dipendenze per linux-x64)" - } + }, + "main_information": "Informazioni Principali", + "trends": "Tendenze", + "version_distribution": "Distribuzione delle Versioni" }, "skills": { "title": "Competenze dell'agente", @@ -216,9 +466,11 @@ "refs": "{count} ref | {count} ref", "assets": "{count} risorsa | {count} risorse" }, - "view_source": "Visualizza sorgente" + "view_source": "Visualizza sorgente", + "skills_cli": "skills CLI" }, "links": { + "main": "main", "repo": "repo", "homepage": "homepage", "issues": "issues", @@ -226,15 +478,29 @@ "code": "codice", "docs": "documenti", "fund": "finanzia", - "compare": "confronta" + "compare": "confronta", + "timeline": "Cronologia", + "stats": "Statistiche", + "compare_this_package": "Confronta questo pacchetto", + "changelog": "Registro delle modifiche" }, "likes": { "like": "Metti mi piace a questo pacchetto", - "unlike": "Togli mi piace a questo pacchetto" + "unlike": "Togli mi piace a questo pacchetto", + "top_rank_tooltip": "Questo รจ tra i 10 pacchetti piรน apprezzati su npmx! (#{rank})", + "top_rank_label": "#{rank}", + "top_rank_link_label": "Visualizza la classifica dei preferiti. Questo pacchetto รจ al #{rank} posto." }, "docs": { + "contents": "Contenuti", + "default_not_available": "I documenti non sono disponibili per questa versione.", "not_available": "Documenti non disponibili", - "not_available_detail": "Non abbiamo potuto generare i documenti per questa versione." + "not_available_detail": "Non abbiamo potuto generare i documenti per questa versione.", + "page_title": "Documentazione API - npmx", + "page_title_name": "Documentazione {name} - npmx", + "page_title_version": "Documentazione {name} - npmx", + "og_title": "{name} - Documentazione", + "view_package": "Visualizza pacchetto" }, "get_started": { "title": "Inizia", @@ -264,7 +530,8 @@ "warning": "Avvertenza", "caution": "Cautela" }, - "copy_as_markdown": "Copia README come Markdown" + "copy_as_markdown": "Copia README come Markdown", + "error_loading": "Impossibile caricare i dettagli del README" }, "provenance_section": { "title": "Provenienza", @@ -294,7 +561,10 @@ "published": "Pubblicato", "weekly_downloads": "Download settimanali", "keywords": "Keywords", - "license": "Licenza" + "license": "Licenza", + "version": "Versione", + "select": "Seleziona pacchetto", + "select_maximum": "รˆ possibile selezionare massimo {count} pacchetti" }, "versions": { "title": "Versioni", @@ -309,7 +579,68 @@ "all_covered": "Tutte le versioni sono coperte dai tag sopra", "deprecated_title": "{version} (deprecato)", "view_all": "Visualizza {count} versione | Visualizza tutte le {count} versioni", - "copy_alt": {} + "view_all_versions": "Visualizza tutte le versioni", + "distribution_title": "Gruppo Semver", + "distribution_range_date_same_year": "da {from} a {to}, {endYear}", + "distribution_range_date_multiple_years": "da {from}, {startYear} a {to}, {endYear}", + "grouping_major": "Major", + "grouping_minor": "Minor", + "grouping_versions_title": "Versioni", + "grouping_versions_about": "Informazioni sul raggruppamento versioni", + "grouping_versions_all": "Tutte", + "grouping_versions_only_recent": "Solo recenti", + "grouping_usage_title": "Utilizzo", + "grouping_usage_about": "Informazioni sul raggruppamento per utilizzo", + "grouping_usage_all": "Tutti", + "grouping_usage_most_used": "Piรน utilizzati", + "recent_versions_only_tooltip": "Mostra solo le versioni pubblicate nell'ultimo anno.", + "show_low_usage_tooltip": "Includi gruppi di versioni con meno dell'1% dei download totali.", + "y_axis_label": "Download", + "filter_placeholder": "Filtra per semver (es. ^3.0.0)", + "filter_invalid": "Intervallo semver non valido", + "filter_help": "Guida al filtro per intervallo semver", + "filter_tooltip": "Filtra le versioni usando un {link}. Ad esempio, ^3.0.0 mostra tutte le versioni 3.x.", + "filter_tooltip_link": "intervallo semver", + "license_change_help": "Dettagli modifica licenza", + "license_change_warning": "La licenza รจ cambiata rispetto alla versione precedente.", + "license_change_record": "La licenza di questo pacchetto รจ cambiata da \"{from}\" a \"{to}\".", + "no_matches": "Nessuna versione corrisponde a questo intervallo", + "copy_alt": { + "per_version_analysis": "La versione {version} รจ stata scaricata {downloads} volte", + "general_description": "Grafico a barre che mostra i download per versione per {versions_count} versioni {semver_grouping_mode} del pacchetto {package_name}, {date_range_label} dalla versione {first_version} alla versione {last_version}. La versione piรน scaricata รจ {max_downloaded_version} con {max_version_downloads} download. {per_version_analysis}. {watermark}." + }, + "page_title": "Cronologia versioni", + "current_tags": "Tag correnti", + "no_match_filter": "Nessuna versione corrisponde a {filter}" + }, + "timeline": { + "load_more": "Carica altri", + "load_error": "Impossibile caricare la cronologia. Riprova piรน tardi.", + "size_increase": "Dimensione di installazione aumentata del {percent}% ({size})", + "size_decrease": "Dimensione di installazione diminuita del {percent}% ({size})", + "dep_increase": "{count} dipendenza aggiunta | {count} dipendenze aggiunte", + "dep_decrease": "{count} dipendenza rimossa | {count} dipendenze rimosse", + "license_change": "Licenza cambiata da {from} a {to}", + "esm_added": "Tipo di modulo cambiato in ESM", + "esm_removed": "Tipo di modulo cambiato da ESM a CJS", + "types_added": "Tipi TypeScript aggiunti", + "types_removed": "Tipi TypeScript rimossi", + "trusted_publisher_added": "Pubblicazione attendibile abilitata", + "trusted_publisher_removed": "Pubblicazione attendibile rimossa", + "provenance_added": "Provenienza abilitata", + "provenance_removed": "Provenienza rimossa", + "chart": { + "tab_aria_label": "Selezione metrica", + "base_scale": "inizia l'asse Y da zero", + "zoom": "zoom", + "reset_minimap": "reimposta minimappa", + "ordered_versions": "solo stabili", + "copy_alt": { + "key_changes": "Modifiche principali: {version_events}.", + "version_events": "versione {version}: {events}", + "general_description": "Grafico a linee che mostra {metric} del pacchetto {package}, dalla versione {first} alla {last}. Il valore di {metric} nella versione {first} รจ {first_value}, nella versione {last} รจ {last_value} ({overall_progress_percentage}% complessivo). {key_changes} {watermark}." + } + } }, "dependencies": { "title": "Dipendenza ({count}) | Dipendenze ({count})", @@ -319,7 +650,9 @@ "view_vulnerabilities": "Visualizza vulnerabilitร ", "outdated_major": "{count} versione principale indietro (latest: {latest}) | {count} versioni principali indietro (latest: {latest})", "outdated_minor": "{count} versione minore indietro (latest: {latest}) | {count} versioni minori indietro (latest: {latest})", - "outdated_patch": "Aggiornamento patch disponibile (latest: {latest})" + "outdated_patch": "Aggiornamento patch disponibile (latest: {latest})", + "has_replacement": "Questa dipendenza ha sostituzioni suggerite", + "vulnerabilities_count": "{count} vulnerabilitร  | {count} vulnerabilitร " }, "peer_dependencies": { "title": "Dipendenza peer ({count}) | Dipendenze peer ({count})", @@ -343,9 +676,19 @@ "cancel_add": "Cancella aggiunta proprietario", "add_owner": "+ Aggiungi proprietario", "show_more": "(mostra altri {count})", - "show_less": "(mostra meno)" + "show_less": "(mostra meno)", + "maintainer_template": "{avatar} ~{name}" }, "trends": { + "chart_assistive_text": { + "keyboard_navigation_horizontal": "Usa i tasti freccia sinistra e destra per scorrere i punti dati.", + "keyboard_navigation_vertical": "Usa i tasti freccia su e giรน per scorrere i punti dati.", + "table_available": "Una tabella dati per questo grafico รจ disponibile di seguito.", + "table_caption": "Tabella dati del grafico" + }, + "chart_view_toggle": "Cambia visualizzazione", + "chart_view_combined": "Visualizzazione combinata", + "chart_view_split": "Visualizzazione divisa", "granularity": "Granularitร ", "granularity_daily": "Giornaliero", "granularity_weekly": "Settimanale", @@ -358,17 +701,61 @@ "date_range_multiline": "{start}\na {end}", "download_file": "Scarica {fileType}", "toggle_annotator": "Attiva/disattiva annotatore", + "toggle_stack_mode": "Attiva modalitร  stack", + "open_options": "Apri opzioni", + "close_options": "Chiudi opzioni", "legend_estimation": "Stima", "no_data": "Nessun dato disponibile", "y_axis_label": "{granularity} {facet}", + "facet": "Aspetto", + "title": "Tendenze", + "contributors_skip": "Non mostrati in Contributori (nessun repository GitHub):", "items": { - "downloads": "Download" + "downloads": "Download", + "likes": "Preferiti", + "contributors": "Contributori" }, - "copy_alt": {} + "data_correction": "Correzione dati", + "average_window": "Finestra media", + "smoothing": "Livellamento", + "prediction": "Previsione", + "known_anomalies": "Anomalie note", + "known_anomalies_description": "Interpola i picchi di download noti causati da bot o problemi di CI.", + "known_anomalies_ranges": "Intervalli di anomalia", + "known_anomalies_range": "Da {start} a {end}", + "known_anomalies_range_named": "{packageName}: da {start} a {end}", + "known_anomalies_none": "Nessuna anomalia nota per questo pacchetto. | Nessuna anomalia nota per questi pacchetti.", + "known_anomalies_contribute": "Contribuisci con dati sulle anomalie", + "apply_correction": "Applica correzione", + "copy_alt": { + "trend_none": "sostanzialmente stabile", + "trend_strong": "forte", + "trend_weak": "debole", + "trend_undefined": "indefinito (dati insufficienti)", + "button_label": "Copia testo alternativo", + "watermark": "In basso, una filigrana recita \"./npmx un browser veloce e moderno per il registro npm\"", + "analysis": "{package_name} inizia a {start_value} e termina a {end_value}, mostrando un trend {trend} con una pendenza di {downloads_slope} download per intervallo di tempo", + "estimation": "Il valore finale รจ una stima basata su dati parziali per il periodo corrente.", + "estimations": "I valori finali sono stime basate su dati parziali per il periodo corrente.", + "compare": "Grafico a linee di confronto download per: {packages}.", + "single_package": "Grafico a linee dei download per il pacchetto {package}.", + "general_description": "L'asse Y rappresenta il numero di download. L'asse X rappresenta l'intervallo di date, da {start_date} a {end_date}, con un periodo di tempo {granularity}.{estimation_notice} {packages_analysis}. {watermark}.", + "facet_bar_general_description": "Grafico a barre orizzontale per: {packages}, che confronta {facet} ({description}). {facet_analysis} {watermark}.", + "facet_bar_analysis": "{package_name} ha un valore di {value}." + }, + "embedding": { + "chart": "Incorpora questo grafico", + "copy_url": "Copia questo URL per incorporare il grafico nel tuo sito web", + "preview": "Anteprima", + "tip": "Se startDate e endDate non vengono forniti, il grafico mostra di default gli ultimi 12 mesi." + } }, "downloads": { "title": "Download settimanali", - "community_distribution": "Visualizza distribuzione adozione della comunitร " + "version_distribution_title": "download settimanali per la versione {version}", + "community_distribution": "Visualizza distribuzione adozione della comunitร ", + "subtitle": "Su tutte le versioni", + "sparkline_nav_hint": "Usa โ† โ†’" }, "install_scripts": { "title": "Script di installazione", @@ -384,6 +771,7 @@ "esm": "ES Modules supportati", "cjs": "CommonJS supportato", "no_esm": "Nessun supporto per ES Modules", + "wasm": "Ha WebAssembly", "types_label": "Tipi", "types_included": "Tipi inclusi", "types_available": "Tipi disponibili tramite {package}", @@ -405,7 +793,8 @@ "high": "alta", "moderate": "moderata", "low": "bassa" - } + }, + "fixed_in_title": "Risolto nella versione {version}" }, "deprecated": { "label": "Deprecato", @@ -457,7 +846,20 @@ "kb": "{size} kB", "mb": "{size} MB" }, - "download": {} + "download": { + "button": "Scarica", + "tarball": "Scarica Tarball come .tar.gz" + } + }, + "leaderboard": { + "likes": { + "title": "Classifica preferiti", + "description": "I 10 pacchetti piรน apprezzati su npmx in questo momento.", + "rank": "Posizione", + "likes": "Preferiti", + "unavailable_title": "Nessuna classifica preferiti disponibile", + "unavailable_description": "Non abbiamo una classifica dei preferiti da mostrare al momento." + } }, "connector": { "modal": { @@ -477,7 +879,8 @@ "warning": "AVVISO", "warning_text": "Questo consente a npmx di accedere alla tua CLI npm. Connettiti solo a siti di cui ti fidi.", "connect": "Connetti", - "connecting": "Connettendo..." + "connecting": "Connettendo...", + "auto_open_url": "Apri automaticamente la pagina di autenticazione" } }, "operations": { @@ -493,7 +896,9 @@ "otp_placeholder": "Inserisci il codice OTP...", "otp_label": "One-time password", "retry_otp": "Riprova la OTP", + "retry_web_auth": "Riprova con l'autenticazione web", "retrying": "Riprovando...", + "open_web_auth": "Apri il link di autenticazione web", "approve_operation": "Approva operazione", "remove_operation": "Rimuovi operazione", "approve_all": "Approva Tutto", @@ -615,6 +1020,7 @@ "invalid_name": "Nome del pacchetto non valido:", "available": "Questo nome รจ disponibile!", "taken": "Questo nome รจ giร  occupato.", + "missing_permission": "Non hai i permessi per aggiungere un pacchetto allo scope {'@'}{scope}.", "similar_warning": "Esistono pacchetti simili โ€” npm potrebbe rifiutare questo nome:", "related": "Pacchetti correlati:", "scope_warning_title": "Valuta l'uso di un pacchetto con scope", @@ -636,8 +1042,12 @@ "lines": "{count} riga | {count} righe", "toggle_tree": "Attiva/disattiva albero dei file", "close_tree": "Chiudi albero dei file", + "copy_content": "Copia contenuto file", "copy_link": "Copia link", "view_raw": "Visualizza file raw", + "toggle_container": "Cambia larghezza contenitore codice", + "open_raw_file": "Apri file raw", + "open_path_dropdown": "Apri menu a tendina dei segmenti del percorso", "file_too_large": "File troppo grande per visualizzare l'anteprima", "file_size_warning": "{size} supera il limite di 500 KB per l'evidenziatore di sintassi", "failed_to_load": "Caricamento del file non riuscito", @@ -655,7 +1065,9 @@ "preview": "anteprima", "code": "codice" }, - "file_path": "Percorso del file" + "file_path": "Percorso del file", + "binary_file": "File binario", + "binary_rendering_warning": "Il tipo di file \"{contentType}\" non รจ supportato per l'anteprima." }, "badges": { "provenance": { @@ -717,6 +1129,8 @@ "secure": "Senza avvisi", "insecure": "Con avvisi" }, + "view_selected": "Visualizza selezionati", + "clear_selected_label": "Deseleziona tutti", "sort": { "label": "Ordina pacchetti", "toggle_direction": "Cambia direzione ordinamento", @@ -742,7 +1156,8 @@ "published": "Ultimo pubblicato", "maintainers": "Manutentori", "keywords": "Keywords", - "security": "Sicurezza" + "security": "Sicurezza", + "selection": "Seleziona pacchetto" }, "view_mode": { "label": "Modalitร  di visualizzazione", @@ -798,9 +1213,22 @@ "managers": "gestori di pacchetti" } }, - "sponsors": {}, - "oss_partners": {}, - "team": {}, + "sponsors": { + "title": "Sponsor" + }, + "oss_partners": { + "title": "Partner OSS" + }, + "team": { + "title": "Team", + "core": "Core", + "maintainers": "Maintainer", + "role_core": "core", + "role_steward": "steward", + "role_maintainer": "maintainer", + "sponsor": "sponsor", + "sponsor_aria": "Sponsorizza {name} su GitHub" + }, "contributors": { "title": "{count} Collaboratore | {count} Collaboratori", "description": "npmx รจ completamente open source, costruito da una straordinaria comunitร  di collaboratori. Unisciti a noi e costruiamo insieme l'esperienza di navigazione npm che abbiamo sempre voluto.", @@ -820,7 +1248,11 @@ "description": "Chatta, fai domande e condividi idee.", "cta": "Unisciti a Discord" }, - "builders": {}, + "builders": { + "title": "Aiuta a costruire npmx", + "description": "Unisciti ai costruttori che stanno plasmando il futuro di npmx.", + "cta": "Unisciti al Discord dei Costruttori" + }, "follow": { "title": "Rimani aggiornato", "description": "Scopri le ultime novitร  su npmx.", @@ -853,7 +1285,8 @@ "connect_bluesky": "Connetti con Bluesky", "what_is_atmosphere": "Cos'รจ un account Atmosphere?", "atmosphere_explanation": "{npmx} utilizza {atproto} per potenziare molte delle sue funzionalitร  sociali, consentendo agli utenti di possedere i loro dati e utilizzare un account per tutte le applicazioni compatibili. Una volta creato un account, puoi utilizzare altre app come {bluesky} e {tangled} con lo stesso account.", - "default_input_error": "Inserisci un handle valido, DID o URL PDS completo" + "default_input_error": "Inserisci un handle valido, DID o URL PDS completo", + "profile": "Profilo" } }, "header": { @@ -873,7 +1306,8 @@ "error": "Impossibile caricare le organizzazioni", "empty": "Nessuna organizzazione trovata", "view_all": "Visualizza tutto" - } + }, + "pr": "Apri GitHub pull request #{prNumber}" }, "compare": { "packages": { @@ -886,10 +1320,16 @@ "section_packages": "Pacchetti", "section_facets": "Sfaccettature", "section_comparison": "Confronto", + "copy_as_markdown": "Copia tabella", "loading": "Caricamento dati del pacchetto...", "error": "Impossibile caricare i dati del pacchetto. Riprova.", "empty_title": "Seleziona pacchetti da confrontare", - "empty_description": "Cerca e aggiungi almeno 2 pacchetti sopra per vedere un confronto fianco a fianco delle loro metriche." + "empty_description": "Cerca e aggiungi almeno 2 pacchetti sopra per vedere un confronto fianco a fianco delle loro metriche.", + "table_view": "Tabella", + "charts_view": "Grafici", + "no_chartable_data": "Nessun dato disponibile per i filtri selezionati.", + "bar_chart_nav_hint": "Usa โ†‘ โ†“", + "line_chart_nav_hint": "Usa โ† โ†’" }, "selector": { "search_label": "Cerca pacchetti", @@ -900,6 +1340,17 @@ "packages_selected": "{count}/{max} pacchetti selezionati.", "add_hint": "Aggiungi almeno 2 pacchetti da confrontare." }, + "scatter_chart": { + "title": "Confronta {x} vs {y}", + "freshness_score": "Punteggio di freschezza", + "copy_alt": { + "analysis": "{package} : {x_name} ({x_value}) e {y_name} ({y_value})", + "description": "Grafico a dispersione che mappa {x_name} rispetto a {y_name} per i pacchetti {packages}. {analysis}. {watermark}" + }, + "filename": "{x}-vs-{y}-grafico-dispersione", + "x_axis": "ASSE X โ†ฆ", + "y_axis": "ASSE Y โ†ฅ" + }, "no_dependency": { "label": "Nessuna dipendenza", "typeahead_title": "Cosa farebbe James?", @@ -912,6 +1363,10 @@ "facets": { "all": "tutto", "none": "niente", + "select_all_category_facets": "Seleziona tutti i filtri {category}", + "deselect_all_category_facets": "Deseleziona tutti i filtri {category}", + "selected_all_category_facets": "Selezionati tutti i filtri {category}", + "deselected_all_category_facets": "Deselezionati tutti i filtri {category}", "coming_soon": "Prossimamente", "select_all": "Seleziona tutte le sfaccettature", "deselect_all": "Deseleziona tutte le sfaccettature", @@ -974,6 +1429,22 @@ "vulnerabilities": { "label": "Vulnerabilitร ", "description": "Vulnerabilitร  di sicurezza note" + }, + "githubStars": { + "label": "Stelle GitHub", + "description": "Numero di stelle sul repository GitHub" + }, + "githubForks": { + "label": "Fork GitHub", + "description": "Numero di fork sul repository GitHub" + }, + "githubIssues": { + "label": "Issue GitHub", + "description": "Numero di issue sul repository GitHub" + }, + "createdAt": { + "label": "Creato il", + "description": "Quando รจ stato creato il pacchetto" } }, "values": { @@ -987,105 +1458,246 @@ "vulnerabilities_summary": "{count} ({critical}C/{high}H)", "up_to_you": "A tua scelta!" }, - "trends": {} + "trends": { + "title": "Confronta tendenze" + } }, - "version_invalid_url_format": {}, - "file_filter_option": {}, - "filter": {} + "file_changes": "Modifiche ai file", + "files_count": "{count} file | {count} file", + "lines_hidden": "{count} riga nascosta | {count} righe nascoste", + "compare_versions": "diff", + "compare_versions_title": "Confronta con l'ultima versione", + "comparing_versions_label": "Confronto versioni in corso...", + "version_back_to_package": "Torna al pacchetto", + "version_error_message": "Confronto versioni non riuscito.", + "version_invalid_url_format": { + "hint": "URL di confronto non valido. Usa il formato: {0}", + "from_version": "da", + "to_version": "a" + }, + "version_selector_title": "Confronta con versione", + "summary": "Riepilogo", + "deps_count": "{count} dip | {count} dip", + "dependencies": "Dipendenze", + "dev_dependencies": "Dipendenze di sviluppo", + "peer_dependencies": "Dipendenze peer", + "optional_dependencies": "Dipendenze opzionali", + "no_dependency_changes": "Nessuna modifica alle dipendenze", + "file_filter_option": { + "all": "Tutti ({count})", + "added": "Aggiunti ({count})", + "removed": "Rimossi ({count})", + "modified": "Modificati ({count})" + }, + "search_files_placeholder": "Cerca file...", + "no_files_all": "Nessun file", + "no_files_search": "Nessun file corrispondente a \"{query}\"", + "no_files_filtered": "Nessun file {filter}", + "filter": { + "added": "aggiunto", + "removed": "rimosso", + "modified": "modificato" + }, + "files_button": "File", + "select_file_prompt": "Seleziona un file dalla barra laterale per visualizzarne il diff", + "close_files_panel": "Chiudi pannello file", + "filter_files_label": "Filtra file per tipo di modifica", + "change_ratio": "Rapporto di modifica", + "char_edits": "Modifiche ai caratteri", + "diff_distance": "Distanza diff", + "diff_truncated": "Diff troncato per prestazioni. Vengono mostrate solo le prime righe modificate.", + "large_diff_mode": "Diff di file di grandi dimensioni mostrato con unione delle modifiche inline disabilitata per prestazioni.", + "large_diff_options_disabled": "La modalitร  file di grandi dimensioni disabilita l'unione delle modifiche inline per prestazioni.", + "loading_diff": "Caricamento diff...", + "loading_diff_error": "Caricamento diff non riuscito", + "merge_modified_lines": "Unisci righe modificate", + "no_content_changes": "Nessuna modifica al contenuto rilevata", + "options": "Opzioni", + "view_file": "Visualizza file", + "view_in_code_browser": "Visualizza nel browser del codice", + "word_wrap": "A capo automatico" }, "pds": { - "join": {}, - "server": {}, - "community": {} + "title": "npmx.social", + "meta_description": "Il server per dati personali (PDS) ufficiale del protocollo AT per la community npmx.", + "join": { + "title": "Unisciti alla community", + "description": "Che tu stia creando il tuo primo account sull'atmosphere o migrando uno esistente, sei nel posto giusto. Puoi migrare il tuo account attuale senza perdere il tuo handle, i tuoi post o i tuoi follower.", + "migrate": "Migra con PDS MOOver" + }, + "server": { + "title": "Dettagli server", + "location_label": "Posizione:", + "location_value": "Norimberga, Germania", + "infrastructure_label": "Infrastruttura:", + "infrastructure_value": "Ospitato su Hetzner", + "privacy_label": "Privacy:", + "privacy_value": "Soggetto alle rigide leggi europee sulla protezione dei dati", + "learn_more": "Scopri come npmx utilizza l'Atmosphere" + }, + "community": { + "title": "Chi รจ qui", + "description": "Alcuni dei {count} account che hanno giร  scelto npmx.social come casa:", + "loading": "Caricamento community PDS...", + "error": "Caricamento community PDS non riuscito.", + "empty": "Nessun membro della community da visualizzare.", + "view_profile": "Visualizza il profilo di {handle}", + "new_accounts": "...piรน altri {count} che sono nuovi sull'atmosphere" + } }, - "privacy_policy": { - "title": "Informativa sulla privacy", - "last_updated": "Ultimo aggiornamento: {date}", - "welcome": "Benvenuti su {app}. Ci impegniamo a proteggere la tua privacy. Questa informativa spiega quali dati raccogliamo, come li utilizziamo e i tuoi diritti riguardo alle tue informazioni.", - "cookies": { - "what_are": { - "title": "Cosa sono i cookies?", - "p1": "I cookies sono piccoli file di testo memorizzati sul tuo dispositivo quando visiti un sito web. Il loro scopo รจ migliorare la tua esperienza di navigazione ricordando alcune preferenze e impostazioni." - }, - "types": { - "title": "Quali cookie usiamo?", - "p1": "Usiamo solo {bold} per scopi strettamente necessari al funzionamento del sito. Non utilizziamo cookie di terze parti o pubblicitari.", - "bold": "cookie tecnici essenziali", - "li1": "{li11}{separator} {li12}", - "li2": "{li21}{separator} {li22}", - "separator": ":", - "cookie_vdpl": "__vdpl", - "cookie_vdpl_desc": "Questo cookie รจ utilizzato dal nostro provider di hosting (Vercel) per la protezione dallo skew. Garantisce che tu scarichi le risorse dalla versione di deployment corretta se viene rilasciato un nuovo aggiornamento mentre stai navigando. Non ti traccia.", - "cookie_h3": "h3", - "cookie_h3_desc": "Questo รจ il nostro cookie di sessione sicuro. Memorizza il token di accesso OAuth quando colleghi il tuo account Atmosphere. รˆ essenziale per mantenere la tua sessione autenticata." - }, - "local_storage": { - "title": "Archiviazione locale", - "p1": "Oltre ai cookie di sessione, utilizziamo l'{bold} del tuo browser per salvare le tue preferenze di visualizzazione. Questo ci permette di ricordare il tema (chiaro/scuro) e alcune altre {settings} che hai selezionato, cosรฌ non devi riconfigurarle a ogni visita.", - "bold": "archiviazione locale", - "p2": "Queste informazioni sono puramente funzionali, memorizzate solo sul tuo dispositivo, e {bold2}. Le usiamo esclusivamente per migliorare la tua esperienza sul nostro sito web.", - "bold2": "non contengono dati personali nรฉ vengono usate per tracciarti", - "settings": "impostazioni" - }, - "management": { - "title": "Gestire i cookies", - "p1": "Puoi configurare il tuo browser per accettare, rifiutare o eliminare i cookie in base alle tue preferenze. Tuttavia, tieni presente che {bold}.", - "bold": "rifiutare i cookie essenziali potrebbe impedire il completo accesso all'applicazione", - "p2": "Di seguito sono riportati i link con le istruzioni per la gestione dei cookie nei browser piรน comunemente usati:", - "chrome": "Google Chrome (si apre in una nuova finestra)", - "firefox": "Mozilla Firefox (si apre in una nuova finestra)", - "edge": "Microsoft Edge (si apre in una nuova finestra)" - } - }, - "analytics": { - "title": "Analitiche", - "p1": "Usiamo le {bold} per capire come i visitatori utilizzano il nostro sito web. Questo ci aiuta a migliorare l'esperienza utente e a identificare eventuali problemi.", - "bold": "Vercel Web Analytics", - "p2": "Vercel Analytics รจ progettato con la privacy in mente:", - "li1": "Non usa cookies", - "li2": "Non raccoglie identificatori personali", - "li3": "Non traccia gli utenti attraverso i siti web", - "li4": "Tutti i dati sono aggregati e anonimizzati", - "p3": "Le uniche informazioni raccolte includono: URL delle pagine, referrer, paese/regione, tipo di dispositivo, browser e sistema operativo. Questi dati non possono essere utilizzati per identificare singoli utenti." - }, - "authenticated": { - "title": "Utenti autenticati", - "p1": "Quando colleghi il tuo account {bold} a npmx, memorizziamo il tuo token di accesso OAuth in un cookie di sessione sicuro e HTTP-only. Questo token viene utilizzato esclusivamente per autenticare le richieste a tuo nome.", - "bold": "Atmosphere", - "p2": "Non memorizziamo le tue credenziali e non accediamo a dati oltre a quelli necessari per fornire le funzionalitร  che utilizzi. Puoi disconnettere il tuo account in qualsiasi momento dalla pagina {settings}.", - "settings": "impostazioni" - }, - "data_retention": { - "title": "Conservazione dei dati", - "p1": "I cookie di sessione vengono eliminati automaticamente quando chiudi il browser o dopo un periodo di inattivitร . Le preferenze memorizzate nel local storage rimangono sul tuo dispositivo fino a quando non cancelli i dati del browser. I dati analitici vengono conservati in forma aggregata e non possono essere collegati a singoli utenti." - }, - "your_rights": { - "title": "I tuoi diritti", - "p1": "Hai il diritto di:", - "li1": "Accedere alle informazioni sui dati che raccogliamo", - "li2": "Cancellare la tua archiviazione locale e i cookie in qualsiasi momento", - "li3": "Disconnettere la tua sessione autenticata", - "li4": "Richiedere informazioni sulle nostre pratiche di gestione dei dati", - "p2": "Poichรฉ non raccogliamo dati personali, di solito non ci sono informazioni personali da cancellare o esportare." + "a11y": { + "title": "accessibilitร ", + "footer_title": "a11y", + "welcome": "Vogliamo che {app} sia utilizzabile dal maggior numero di persone possibile.", + "approach": { + "title": "Il nostro approccio", + "p1": "Cerchiamo di seguire le Web Content Accessibility Guidelines (WCAG) 2.2 e le usiamo come riferimento nella creazione delle funzionalitร . Non dichiariamo la piena conformitร  ad alcun livello WCAG: l'accessibilitร  รจ un processo continuo e c'รจ sempre altro lavoro da fare.", + "p2": "Questo sito รจ un {about}. I miglioramenti all'accessibilitร  vengono apportati in modo incrementale come parte del nostro sviluppo regolare.", + "about_link": "progetto open-source guidato dalla community" + }, + "measures": { + "title": "Cosa facciamo", + "p1": "Alcune delle cose che puntiamo a fare su tutto il sito:", + "li1": "Usare HTML semantico e attributi ARIA dove appropriato.", + "li2": "Usare dimensioni di testo relative in modo che tu possa regolarle nel browser.", + "li3": "Supportare la navigazione da tastiera in tutta l'interfaccia.", + "li4": "Rispettare le media query prefers-reduced-motion e prefers-color-scheme.", + "li5": "Progettare tenendo in mente un contrasto cromatico sufficiente.", + "li6": "Garantire che i contenuti essenziali siano disponibili senza JavaScript, sebbene alcune funzionalitร  interattive lo richiedano." + }, + "limitations": { + "title": "Limitazioni note", + "p1": "Alcune parti del sito, in particolare i contenuti di terze parti come i README dei pacchetti, potrebbero non soddisfare gli standard di accessibilitร . Stiamo lavorando per migliorare queste aree nel tempo." }, "contact": { - "title": "Contattaci", - "p1": "Per qualsiasi domanda o preoccupazione riguardo a questa informativa sulla privacy, puoi contattarci aprendo una issue sulla nostra {link}.", + "title": "Feedback", + "p1": "Se riscontri una barriera di accessibilitร  su {app}, ti preghiamo di segnalarcelo aprendo una issue sulla nostra {link}. Prendiamo queste segnalazioni sul serio e faremo del nostro meglio per risolverle.", "link": "repository GitHub" + } + }, + "translation_status": { + "title": "stato traduzioni", + "generated_at": "Data di generazione: {date}", + "welcome": "Se sei interessato ad aiutarci a tradurre {npmx} in una delle lingue elencate di seguito, sei nel posto giusto! Questa pagina, aggiornata automaticamente, mostra sempre tutti i contenuti che potrebbero beneficiare del tuo aiuto in questo momento.", + "p1": "Usiamo {lang} come lingua predefinita, con un totale di {count}. Se vuoi contribuire con le traduzioni, trova la lingua in {bylang} ed espandi i dettagli.", + "p1_lang": "Inglese americano (en-US)", + "p1_count": "0 messaggi | 1 messaggio | {count} messaggi", + "p2": "Prima di iniziare, leggi la nostra {guide} per scoprire il nostro processo di traduzione e come puoi contribuire.", + "guide": "guida alla localizzazione (i18n)", + "by_locale": "Avanzamento traduzione per lingua", + "by_file": "Avanzamento traduzione per file", + "complete_text": "Questa traduzione รจ completa, ottimo lavoro!", + "missing_text": "mancante", + "missing_keys": "Non mancano traduzioni | Traduzione mancante | Traduzioni mancanti", + "progress_label": "Stato avanzamento per {locale}", + "table": { + "file": "File", + "status": "Stato", + "error": "Errore durante il caricamento dell'elenco file.", + "empty": "Nessun file trovato", + "file_link": "Modifica {file} ({lang}) su GitHub" + } + }, + "vacations": { + "title": "in vacanza", + "meta_description": "Il team di npmx si stava rigenerando. Il Discord ha riaperto dopo una settimana.", + "heading": "ricarica", + "subtitle": "stavamo costruendo npmx a un ritmo che stava costando il sonno a {some} di noi. non volevamo che diventasse la norma! quindi ci siamo presi una settimana di pausa. insieme.", + "illustration_alt": "una singola fila di icone accoglienti", + "poke_log": "Attizza il fuoco del campo", + "what": { + "title": "cosa รจ successo", + "p1": "il discord era chiuso {dates}.", + "dates": "dal 14 al 21 febbraio", + "p2": "tutti i link di invito erano spariti e i canali erano bloccati, tranne {garden}, rimasto aperto per chi voleva continuare a stare insieme.", + "garden": "#garden" + }, + "meantime": { + "title": "nel frattempo", + "p1": "{site} e {repo} sono rimasti aperti: qualcuno ha continuato a lavorare, ha aperto alcune issue e qualche PR, ma in generale tutti hanno trascorso del tempo vicino a un caminetto accogliente.", + "repo_link": "il repository" + }, + "return": { + "title": "siamo tornati!", + "p1": "siamo tornati rigenerati e pronti per la spinta finale verso il 3 marzo. {social} per gli aggiornamenti.", + "social_link": "seguici su Bluesky" }, - "changes": { - "title": "Modifiche a questa informativa sulla privacy", - "p1": "Potremmo aggiornare questa informativa sulla privacy di tanto in tanto. Eventuali modifiche saranno pubblicate su questa pagina con una data di revisione aggiornata." + "stats": { + "contributors": "Contributori", + "commits": "Commit", + "pr": "PR unite", + "subtitle": { + "some": "alcuni", + "all": "tutti" + } } }, - "a11y": { - "approach": {}, - "measures": {}, - "limitations": {}, - "contact": {} + "action_bar": { + "title": "barra delle azioni", + "selection": "0 selezionati | 1 selezionato | {count} selezionati", + "shortcut": "Premi \"{key}\" per mettere a fuoco le azioni", + "button_close_aria_label": "Chiudi barra delle azioni" }, - "translation_status": { - "table": {} + "logo_menu": { + "copy_svg": "Copia logo come SVG", + "copied": "Copiato!", + "browse_brand": "Esplora il kit del brand" + }, + "brand": { + "title": "Brand", + "heading": "brand", + "meta_description": "Linee guida del brand npmx, loghi, colori e tipografia per uso stampa e media.", + "intro": "Risorse e linee guida per l'utilizzo del brand npmx nei tuoi progetti, articoli e media.", + "logos": { + "title": "loghi", + "description": "Scarica i loghi npmx in formato SVG e PNG. Usa la variante appropriata per il tuo sfondo.", + "wordmark": "WORDMARK COMPLETO", + "wordmark_alt": "Logo wordmark completo di npmx con barra blu su sfondo scuro", + "wordmark_light_alt": "Logo wordmark completo di npmx con barra accent su sfondo chiaro", + "mark": "SIMBOLO DEL LOGO", + "mark_alt": "Simbolo del logo npmx con punto e barra su sfondo scuro", + "mark_light_alt": "Simbolo del logo npmx con punto e barra su sfondo chiaro", + "on_dark": "su scuro", + "on_light": "su chiaro", + "download_svg": "SVG", + "download_png": "PNG", + "download_svg_aria": "Scarica {name} come SVG", + "download_png_aria": "Scarica {name} come PNG" + }, + "customize": { + "title": "personalizza il tuo logo", + "description": "Anteprima del logo npmx con il tuo colore accent e sfondo. L'anteprima riflette le tue impostazioni attuali: scegli un colore, cambia lo sfondo e scarica.", + "accent_label": "accent", + "bg_label": "sfondo", + "download_svg_aria": "Scarica il logo personalizzato come SVG", + "download_png_aria": "Scarica il logo personalizzato come PNG" + }, + "typography": { + "title": "tipografia", + "description": "npmx usa la famiglia di font Geist di Vercel sia per il testo dell'interfaccia che per il codice.", + "sans": "Geist Sans", + "sans_desc": "Usato per il testo del corpo e gli elementi UI.", + "mono": "Geist Mono", + "mono_desc": "Usato per il codice, i titoli e i contenuti tecnici.", + "pangram": "Il veloce volpe marrone salta sopra il cane pigro", + "numbers": "0123456789" + }, + "guidelines": { + "title": "una nota", + "message": "L'accessibilitร  รจ importante per noi e ci piacerebbe che tu condividessi questa visione. Quando usi i media menzionati, assicurati che ci sia abbastanza contrasto rispetto allo sfondo e non scendere sotto i 24px. Se hai bisogno di altre risorse o informazioni aggiuntive sul progetto, contattaci su {link}.", + "discord_link_text": "chat.npmx.dev" + } }, - "action_bar": {} + "alt_logo_kawaii": "Una versione carina, arrotondata e colorata del logo npmx.", + "changelog": { + "pre_release": "Pre-release", + "draft": "Bozza", + "no_logs": "Spiacenti, questo pacchetto non pubblica changelog o il suo formato non รจ supportato.", + "error": { + "p1": "Spiacenti, il changelog per {package} non ha potuto essere caricato", + "p2": "Riprova piรน tardi o {viewon}" + }, + "rate_limit_ungh": "Spiacenti, รจ stato raggiunto il limite di richieste di GitHub. Riprova tra un momento.", + "version_unavailable": "La versione richiesta non รจ disponibile." + } } diff --git a/i18n/locales/ja-JP.json b/i18n/locales/ja-JP.json index 4e2cd238c6..792bf2550f 100644 --- a/i18n/locales/ja-JP.json +++ b/i18n/locales/ja-JP.json @@ -46,7 +46,8 @@ "disable_shortcuts": "{settings} ใงใ‚ญใƒผใƒœใƒผใƒ‰ใ‚ทใƒงใƒผใƒˆใ‚ซใƒƒใƒˆใ‚’็„กๅŠนๅŒ–ใงใใพใ™ใ€‚", "open_main": "ใƒกใ‚คใƒณๆƒ…ๅ ฑใ‚’้–‹ใ", "open_diff": "ใƒใƒผใ‚ธใƒงใƒณใฎๅทฎๅˆ†ใ‚’้–‹ใ", - "open_timeline": "ใ‚ฟใ‚คใƒ ใƒฉใ‚คใƒณใ‚’้–‹ใ" + "open_timeline": "ใ‚ฟใ‚คใƒ ใƒฉใ‚คใƒณใ‚’้–‹ใ", + "open_stats": "็ตฑ่จˆใ‚’่กจ็คบ" }, "search": { "label": "npmใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ๆคœ็ดข", @@ -154,7 +155,8 @@ "diff": "ๅทฎๅˆ†", "compare": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ๆฏ”่ผƒ", "download": "tarballใ‚’ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰", - "changelog": "Changelog" + "changelog": "Changelog", + "stats": "็ตฑ่จˆ" }, "package_actions": { "copy_run": "ๅฎŸ่กŒใ‚ณใƒžใƒณใƒ‰ใ‚’ใ‚ณใƒ”ใƒผ" @@ -229,6 +231,31 @@ "more_replies": "ใ•ใ‚‰ใซ{count}ไปถใฎ่ฟ”ไฟกโ€ฆ" } }, + "noodles": { + "title": "noodles", + "meta_description": "ๅญฃ็ฏ€ใ”ใจใฎใƒญใ‚ดใ‚„ใ‚คใƒผใ‚นใ‚ฟใƒผใ‚จใƒƒใ‚ฐใ€ใใฎ่ƒŒๆ™ฏใซใ‚ใ‚‹ใ‚นใƒˆใƒผใƒชใƒผใชใฉใ€npmxใงใ“ใ‚Œใพใงใซๅ…ฌ้–‹ใ•ใ‚ŒใŸใ™ในใฆใฎnoodlesใ€‚", + "latest": "ๆœ€ๆ–ฐใฎnoodles", + "what_is": "noodlesใจใฏ", + "what_is_body": "noodlesใจใฏใ€ใƒชใƒชใƒผใ‚นใ€็ฅๆ—ฅใ€ใ‚คใƒ™ใƒณใƒˆใ€ใใฎไป–ใฎ่จ˜ๅฟตใ™ในใ็žฌ้–“ใ‚’็ฅใ†ใŸใ‚ใซใƒ›ใƒผใƒ ใƒšใƒผใ‚ธใซๆŽฒ่ผ‰ใ•ใ‚Œใ‚‹ใ€npmxใƒญใ‚ดใฎ้Šใณๅฟƒใ‚ใตใ‚Œใ‚‹ใƒใƒชใ‚จใƒผใ‚ทใƒงใƒณใงใ™ใ€‚Google Doodlesใฎnpmใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ็‰ˆใฎใ‚ˆใ†ใชใ‚‚ใฎใจ่€ƒใˆใฆใใ ใ•ใ„ใ€‚", + "empty": "noodlesใฏใพใ ใ‚ใ‚Šใพใ›ใ‚“ใ€‚", + "load_more": "ใ•ใ‚‰ใซ {count} ไปถใ‚’่ชญใฟ่พผใ‚€", + "dates": "ๅ…ฌ้–‹ๆœŸ้–“", + "shipped_in": "ใƒชใƒชใƒผใ‚น", + "credits": "ใ‚ฏใƒฌใ‚ธใƒƒใƒˆ", + "learn_more": "่ฉณ็ดฐใฏใ“ใกใ‚‰", + "carousel_prev": "ๅ‰ใฎ็”ปๅƒ", + "carousel_next": "ๆฌกใฎ็”ปๅƒ", + "carousel_dots": "ใƒใƒชใ‚จใƒผใ‚ทใƒงใƒณ็”ปๅƒใฎใƒŠใƒ“ใ‚ฒใƒผใ‚ทใƒงใƒณ", + "carousel_jump": "็”ปๅƒ {index} ใธ็งปๅ‹•", + "lens_label": "{title} โ€” ็”ปๅƒใƒชใƒผใƒซ", + "lens_slide": "็”ปๅƒ {index}", + "lens_slide_position": "ใ‚นใƒฉใ‚คใƒ‰ {index} / {total}", + "back_to_archive": "ใ™ในใฆใฎnoodlesใซๆˆปใ‚‹", + "missing": { + "title": "ใ“ใฎnoodleใฏใƒœใ‚ฆใƒซใ‹ใ‚‰ๅ‡บใ‚‰ใ‚Œใพใ›ใ‚“ใงใ—ใŸใ€‚", + "body": "ใƒกใƒ‹ใƒฅใƒผใซใ€Œ{slug}ใ€ใจใ„ใ†noodleใฏใ‚ใ‚Šใพใ›ใ‚“ใ€‚ใพใ ่ชฟ็†ไธญใ‹ใ€ไฝœๆˆใ•ใ‚Œใชใ‹ใฃใŸใ‹ใฎใฉใกใ‚‰ใ‹ใงใ™ใ€‚ใ„ใšใ‚Œใซใ›ใ‚ˆใ€ใ‚ขใƒผใ‚ซใ‚คใƒ–ใซๆˆปใ‚Šใพใ—ใ‚‡ใ†ใ€‚" + } + }, "settings": { "title": "่จญๅฎš", "tagline": "npmxใฎไฝ“้จ“ใ‚’ใ‚ซใ‚นใ‚ฟใƒžใ‚คใ‚บ", @@ -400,12 +427,11 @@ "example": "ไพ‹:", "native": "ใ“ใ‚Œใฏ Node {nodeVersion} ไปฅ้™ใงๅˆฉ็”จๅฏ่ƒฝใช {replacement} ใง็ฝฎใๆ›ใˆๅฏ่ƒฝใงใ™ใ€‚", "native_no_version": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏ {replacement} ใง็ฝฎใๆ›ใˆๅฏ่ƒฝใงใ™ใ€‚", - "simple": "{community} ใฏใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ๅ†—้•ทใจใ—ใฆใƒ•ใƒฉใ‚ฐใ‚’็ซ‹ใฆใฆใŠใ‚Šใ€ๆฌกใฎใ‚ขใƒ‰ใƒใ‚คใ‚นใŒใ‚ใ‚Šใพใ™: {replacement}", - "documented": "{community} ใซใ‚ˆใ‚Šใ€ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใซใฏใ‚ˆใ‚Šใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใฎ้ซ˜ใ„ไปฃๆ›ฟๆ‰‹ๆฎตใŒใ‚ใ‚‹ใ“ใจใŒๅ ฑๅ‘Šใ•ใ‚Œใฆใ„ใพใ™ใ€‚", + "simple": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏๅ†—้•ทใจใ—ใฆใƒ•ใƒฉใ‚ฐใŒ็ซ‹ใฆใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ๆŽจๅฅจ๏ผš{replacement}", + "documented": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏใ€ใ‚ˆใ‚Šใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นใฎ้ซ˜ใ„ไปฃๆ›ฟๆ‰‹ๆฎตใŒใ‚ใ‚‹ใจใƒ•ใƒฉใ‚ฐใŒ็ซ‹ใฆใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚", "none": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฏไธ่ฆใซใชใฃใŸใจใƒ•ใƒฉใ‚ฐใŒ็ซ‹ใฆใ‚‰ใ‚Œใฆใ„ใพใ™ใ€‚ใใฎๆฉŸ่ƒฝใฏใ™ในใฆใฎใ‚จใƒณใ‚ธใƒณใงใƒใ‚คใƒ†ใ‚ฃใƒ–ใซๅˆฉ็”จใงใใ‚‹ๅฏ่ƒฝๆ€งใŒใ‚ใ‚Šใพใ™ใ€‚", "learn_more": "่ฉณ็ดฐใฏใ“ใกใ‚‰", "learn_more_above": "่ฉณ็ดฐใฏไธŠ่จ˜ใ‚’็ขบ่ชใ—ใฆใใ ใ•ใ„ใ€‚", - "community": "ใ‚ณใƒŸใƒฅใƒ‹ใƒ†ใ‚ฃ", "consider_no_dep": "+ ไพๅญ˜้–ขไฟ‚ใชใ—ใ‚’ๆคœ่จŽใ—ใพใ™ใ‹๏ผŸ" }, "stats": { @@ -420,7 +446,10 @@ "size_tooltip": { "unpacked": "ๅฑ•้–‹ใ‚ตใ‚คใ‚บ: {size} (ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธ)", "total": "็ทๅฑ•้–‹ใ‚ตใ‚คใ‚บ: {size} (linux-x64ๅ‘ใ‘ใฎๅ…จ {count} ๅ€‹ใฎไพๅญ˜้–ขไฟ‚ใ‚’ๅซใ‚€)" - } + }, + "main_information": "ไธปใชๆƒ…ๅ ฑ", + "trends": "ใƒˆใƒฌใƒณใƒ‰", + "version_distribution": "ใƒใƒผใ‚ธใƒงใƒณๅˆ†ๅธƒ" }, "skills": { "title": "ใ‚จใƒผใ‚ธใ‚งใƒณใƒˆ ใ‚นใ‚ญใƒซ", @@ -451,6 +480,7 @@ "fund": "่ณ‡้‡‘ๆดๅŠฉ", "compare": "ๆฏ”่ผƒ", "timeline": "ใ‚ฟใ‚คใƒ ใƒฉใ‚คใƒณ", + "stats": "็ตฑ่จˆ", "compare_this_package": "ใ“ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’ๆฏ”่ผƒ", "changelog": "changelog" }, @@ -532,6 +562,7 @@ "weekly_downloads": "้€ฑ้–“ใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆ•ฐ", "keywords": "ใ‚ญใƒผใƒฏใƒผใƒ‰", "license": "ใƒฉใ‚คใ‚ปใƒณใ‚น", + "version": "ใƒใƒผใ‚ธใƒงใƒณ", "select": "ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’้ธๆŠž", "select_maximum": "ๆœ€ๅคง {count} ๅ€‹ใฎใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใ‚’้ธๆŠžใงใใพใ™" }, @@ -550,7 +581,6 @@ "view_all": "{count} ๅ€‹ใฎใƒใƒผใ‚ธใƒงใƒณใ‚’่กจ็คบ|{count} ๅ€‹ใฎใ™ในใฆใฎใƒใƒผใ‚ธใƒงใƒณใ‚’่กจ็คบ", "view_all_versions": "ใ™ในใฆใฎใƒใƒผใ‚ธใƒงใƒณใ‚’่กจ็คบ", "distribution_title": "Semverใ‚ฐใƒซใƒผใƒ—", - "distribution_modal_title": "ใƒใƒผใ‚ธใƒงใƒณ", "distribution_range_date_same_year": "{endYear} ๅนด {from} ใ‹ใ‚‰ {to}", "distribution_range_date_multiple_years": "{startYear} ๅนด {from} ใ‹ใ‚‰ {endYear} ๅนด {to}", "grouping_major": "ใƒกใ‚ธใƒฃใƒผ", @@ -699,19 +729,25 @@ "apply_correction": "่ฃœๆญฃใ‚’้ฉ็”จ", "copy_alt": { "trend_none": "ใปใผๆจชใฐใ„", - "trend_strong": "ๅผทใ„", - "trend_weak": "ๅผฑใ„", + "trend_strong": "ไธŠๆ˜‡", + "trend_weak": "ไธ‹้™", "trend_undefined": "ๆœชๅฎš็พฉ๏ผˆใƒ‡ใƒผใ‚ฟไธ่ถณ๏ผ‰", "button_label": "altใƒ†ใ‚ญใ‚นใƒˆใ‚’ใ‚ณใƒ”ใƒผ", "watermark": "ไธ‹้ƒจใซใ€Œ./npmx a fast, modern browser for the npm registryใ€ใฎใ‚ฆใ‚ฉใƒผใ‚ฟใƒผใƒžใƒผใ‚ฏใ‚ใ‚Š", - "analysis": "{package_name} ใฏ {start_value} ใงๅง‹ใพใ‚Š {end_value} ใง็ต‚ไบ†ใ€‚{trend} ๅ‚พๅ‘ใ‚’็คบใ—ใ€ๆ™‚้–“้–“้š”ใ‚ใŸใ‚Šใฎใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๅ‚พๆ–œใฏ {downloads_slope} ใงใ™ใ€‚", + "analysis": "{package_name} ใฏ {start_value} ใงๅง‹ใพใ‚Š {end_value} ใง็ต‚ไบ†ใ€‚{trend} ใฎๅ‚พๅ‘ใ‚’็คบใ—ใ€ๆ™‚้–“้–“้š”ใ‚ใŸใ‚Šใฎใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆ•ฐใฎใ‚ฐใƒฉใƒ•ใฎๅ‚พใใฏ {downloads_slope} ใงใ™ใ€‚", "estimation": "ๆœ€็ต‚ๅ€คใฏใ€็พๅœจใฎๆœŸ้–“ใฎ้ƒจๅˆ†็š„ใƒ‡ใƒผใ‚ฟใซๅŸบใฅใๆŽจๅฎšๅ€คใงใ™ใ€‚", "estimations": "ๆœ€็ต‚ๅ€คใฏใ€็พๅœจใฎๆœŸ้–“ใฎ้ƒจๅˆ†็š„ใƒ‡ใƒผใ‚ฟใซๅŸบใฅใๆŽจๅฎšๅ€คใงใ™ใ€‚", "compare": "ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆฏ”่ผƒๆŠ˜ใ‚Œ็ทšใ‚ฐใƒฉใƒ•: {packages}", "single_package": "{package} ใƒ‘ใƒƒใ‚ฑใƒผใ‚ธใฎใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆŠ˜ใ‚Œ็ทšใ‚ฐใƒฉใƒ•", - "general_description": "Y่ปธใฏใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆ•ฐใ€X่ปธใฏ {start_date} ใ‹ใ‚‰ {end_date} ใพใงใฎๆœŸ้–“๏ผˆๅ˜ไฝ๏ผš{granularity}๏ผ‰ใ‚’็คบใ—ใพใ™ใ€‚{estimation_notice} {packages_analysis}ใ€‚{watermark}ใ€‚", + "general_description": "Y่ปธใฏใƒ€ใ‚ฆใƒณใƒญใƒผใƒ‰ๆ•ฐใ€X่ปธใฏ {start_date} ใ‹ใ‚‰ {end_date} ใพใงใฎๆœŸ้–“๏ผˆๅ˜ไฝ๏ผš{granularity}๏ผ‰ใ‚’็คบใ—ใพใ™ใ€‚{estimation_notice} {packages_analysis} {watermark}ใ€‚", "facet_bar_general_description": "{packages} ใฎๆจชๆฃ’ใ‚ฐใƒฉใƒ•: {facet} ใฎๆฏ”่ผƒ ({description})ใ€‚{facet_analysis} {watermark}ใ€‚", "facet_bar_analysis": "{package_name} ใฎๅ€คใฏ {value} ใงใ™ใ€‚" + }, + "embedding": { + "chart": "ใ“ใฎใƒใƒฃใƒผใƒˆใ‚’ๅŸ‹ใ‚่พผใ‚€", + "copy_url": "ใ‚ฆใ‚งใƒ–ใ‚ตใ‚คใƒˆใซใƒใƒฃใƒผใƒˆใ‚’ๅŸ‹ใ‚่พผใ‚€ใซใฏใ€ใ“ใฎURLใ‚’ใ‚ณใƒ”ใƒผใ—ใฆใใ ใ•ใ„", + "preview": "ใƒ—ใƒฌใƒ“ใƒฅใƒผ", + "tip": "startDateใจendDateใŒๆŒ‡ๅฎšใ•ใ‚Œใฆใ„ใชใ„ๅ ดๅˆใ€ใƒใƒฃใƒผใƒˆใฏใƒ‡ใƒ•ใ‚ฉใƒซใƒˆใง้ŽๅŽป12ใƒถๆœˆ้–“ใฎใƒ‡ใƒผใ‚ฟใ‚’่กจ็คบใ—ใพใ™ใ€‚" } }, "downloads": { @@ -1398,6 +1434,10 @@ "label": "GitHub Stars", "description": "GitHubใƒชใƒใ‚ธใƒˆใƒชใฎใ‚นใ‚ฟใƒผๆ•ฐ" }, + "githubForks": { + "label": "GitHub Forks", + "description": "GitHubใƒชใƒใ‚ธใƒˆใƒชใฎใƒ•ใ‚ฉใƒผใ‚ฏๆ•ฐ" + }, "githubIssues": { "label": "GitHub Issues", "description": "GitHubใƒชใƒใ‚ธใƒˆใƒชใฎIssuesๆ•ฐ" @@ -1425,8 +1465,6 @@ "file_changes": "ใƒ•ใ‚กใ‚คใƒซๅค‰ๆ›ด", "files_count": "{count} ใƒ•ใ‚กใ‚คใƒซ", "lines_hidden": "{count} ่กŒใ‚’้ž่กจ็คบ", - "file_too_large": "ใƒ•ใ‚กใ‚คใƒซใ‚ตใ‚คใ‚บใŒๅคงใใ™ใŽใ‚‹ใŸใ‚ๆฏ”่ผƒใงใใพใ›ใ‚“", - "file_size_warning": "{size} ใฏๆฏ”่ผƒๅˆถ้™ใฎ250KBใ‚’่ถ…ใˆใฆใ„ใพใ™", "compare_versions": "diff", "compare_versions_title": "ๆœ€ๆ–ฐใƒใƒผใ‚ธใƒงใƒณใจๆฏ”่ผƒ", "comparing_versions_label": "ใƒใƒผใ‚ธใƒงใƒณใ‚’ๆฏ”่ผƒไธญ...", @@ -1467,6 +1505,9 @@ "change_ratio": "ๅค‰ๆ›ด็އ", "char_edits": "ๆ–‡ๅญ—็ทจ้›†ๆ•ฐ", "diff_distance": "ๅทฎๅˆ†่ท้›ข", + "diff_truncated": "ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๅ‘ไธŠใฎใŸใ‚ใ€diffใŒ้€”ไธญใงๅˆ‡ใ‚Šๆจใฆใ‚‰ใ‚Œใพใ—ใŸใ€‚ๆœ€ๅˆใฎๅค‰ๆ›ดใ•ใ‚ŒใŸ่กŒใฎใฟใ‚’่กจ็คบใ—ใฆใ„ใพใ™ใ€‚", + "large_diff_mode": "ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๅ‘ไธŠใฎใŸใ‚ใ€ใ‚คใƒณใƒฉใ‚คใƒณ็ทจ้›†ใฎใƒžใƒผใ‚ธใ‚’็„กๅŠนใซใ—ใฆๅคงๅž‹ใƒ•ใ‚กใ‚คใƒซใฎdiffใ‚’่กจ็คบใ—ใฆใ„ใพใ™ใ€‚", + "large_diff_options_disabled": "ๅคงๅž‹ใƒ•ใ‚กใ‚คใƒซใƒขใƒผใƒ‰ใงใฏใ€ใƒ‘ใƒ•ใ‚ฉใƒผใƒžใƒณใ‚นๅ‘ไธŠใฎใŸใ‚ใ‚คใƒณใƒฉใ‚คใƒณ็ทจ้›†ใฎใƒžใƒผใ‚ธใŒ็„กๅŠนใซใชใ‚Šใพใ™ใ€‚", "loading_diff": "ๅทฎๅˆ†ใ‚’่ชญใฟ่พผใฟไธญ...", "loading_diff_error": "ๅทฎๅˆ†ใฎ่ชญใฟ่พผใฟใซๅคฑๆ•—ใ—ใพใ—ใŸ", "merge_modified_lines": "ๅค‰ๆ›ด่กŒใ‚’ใƒžใƒผใ‚ธ", diff --git a/i18n/locales/kn-IN.json b/i18n/locales/kn-IN.json index 31c0b57196..340a157d81 100644 --- a/i18n/locales/kn-IN.json +++ b/i18n/locales/kn-IN.json @@ -140,11 +140,8 @@ "replacement": { "title": "เฒจเฒฟเฒฎเฒ—เณ† เฒˆ เฒ…เฒตเฒฒเฒ‚เฒฌเฒจเณ† เฒ…เฒ—เฒคเณเฒฏเฒตเฒฟเฒฒเณเฒฒเฒฆเฒฟเฒฐเฒฌเฒนเณเฒฆเณ.", "native": "เฒ‡เฒฆเฒจเณเฒจเณ {replacement} เฒฎเณ‚เฒฒเฒ• เฒฌเฒฆเฒฒเฒพเฒฏเฒฟเฒธเฒฌเฒนเณเฒฆเณ, เฒ‡เฒฆเณ Node {nodeVersion} เฒฐเฒฟเฒ‚เฒฆ เฒฒเฒญเณเฒฏเฒตเฒฟเฒฆเณ†.", - "simple": "{community} เฒˆ เฒชเณเฒฏเฒพเฒ•เณ‡เฒœเณ เฒ…เฒจเณเฒจเณ เฒ…เฒจเฒพเฒตเฒถเณเฒฏเฒ•เฒตเณ†เฒ‚เฒฆเณ เฒ—เณเฒฐเณเฒคเฒฟเฒธเฒฟเฒฆเณ†, เฒถเฒฟเฒซเฒพเฒฐเฒธเณ: {replacement}.", - "documented": "{community} เฒˆ เฒชเณเฒฏเฒพเฒ•เณ‡เฒœเณ เฒ…เฒจเณเฒจเณ เฒ‰เฒคเณเฒคเฒฎ เฒ•เฒพเฒฐเณเฒฏเฒ•เณเฒทเฒฎเฒคเณ†เฒฏ เฒ†เฒฏเณเฒ•เณ†เฒฏเณ†เฒ‚เฒฆเณ เฒ—เณเฒฐเณเฒคเฒฟเฒธเฒฟเฒฆเณ†.", "none": "เฒˆ เฒชเณเฒฏเฒพเฒ•เณ‡เฒœเณ เฒˆเฒ— เฒ…เฒจเฒพเฒตเฒถเณเฒฏเฒ•เฒตเณ†เฒ‚เฒฆเณ เฒ—เณเฒฐเณเฒคเฒฟเฒธเฒฒเฒพเฒ—เฒฟเฒฆเณ† เฒฎเฒคเณเฒคเณ เฒ‡เฒฆเฒฐ เฒ•เฒพเฒฐเณเฒฏเฒ•เณเฒทเฒฎเฒคเณ† เฒŽเฒฒเณเฒฒเฒพ เฒŽเฒ‚เฒœเฒฟเฒจเณโ€Œเฒ—เฒณเฒฒเณเฒฒเฒฟ เฒจเณ†เฒŸเฒฟเฒตเณ เฒ†เฒ—เฒฟ เฒฒเฒญเณเฒฏเฒตเฒฟเฒฐเฒฌเฒนเณเฒฆเณ.", - "learn_more": "เฒ‡เฒจเณเฒจเฒทเณเฒŸเณ เฒคเฒฟเฒณเฒฟเฒฆเณเฒ•เณŠเฒณเณเฒณเฒฟ", - "community": "เฒธเฒฎเณเฒฆเฒพเฒฏ" + "learn_more": "เฒ‡เฒจเณเฒจเฒทเณเฒŸเณ เฒคเฒฟเฒณเฒฟเฒฆเณเฒ•เณŠเฒณเณเฒณเฒฟ" }, "stats": { "license": "เฒชเฒฐเฒตเฒพเฒจเฒ—เฒฟ", diff --git a/i18n/locales/mr-IN.json b/i18n/locales/mr-IN.json index 7aa91dcc71..09e258f33a 100644 --- a/i18n/locales/mr-IN.json +++ b/i18n/locales/mr-IN.json @@ -59,6 +59,23 @@ "instant_search_turn_off": "เคฌเค‚เคฆ เค•เคฐเคพ", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "เคฎเฅเค–เฅเคฏ", "popular_packages": "เคฒเฅ‹เค•เคชเฅเคฐเคฟเคฏ เคชเฅ…เค•เฅ‡เคœเฅ‡เคธ", @@ -234,15 +251,13 @@ "size": "เค‡เค‚เคธเฅเคŸเฅ‰เคฒ เค†เค•เคพเคฐ {percent} เคจเฅ‡ เคตเคพเคขเคฒเคพ ({size} เคจเฅ‡ เคฎเฅ‹เค เคพ)", "deps": "{count} เค…เคงเคฟเค• เคจเคฟเคฐเฅเคญเคฐเคคเคพ" }, + "size_decrease": {}, "replacement": { "title": "เค•เคฆเคพเคšเคฟเคค เคคเฅเคฎเฅเคนเคพเคฒเคพ เคฏเคพ เคจเคฟเคฐเฅเคญเคฐเคคเฅ‡เคšเฅ€ เค—เคฐเคœ เคจเคธเฅ‡เคฒ.", "native": "เคนเฅ‡ {replacement} เคธเคน เคฌเคฆเคฒเคฒเฅ‡ เคœเคพเคŠ เคถเค•เคคเฅ‡, Node {nodeVersion} เคชเคพเคธเฅ‚เคจ เค‰เคชเคฒเคฌเฅเคง เค†เคนเฅ‡.", - "simple": "{community} เคจเฅ‡ เคฏเคพ เคชเฅ…เค•เฅ‡เคœเคฒเคพ เค…เคจเคพเคตเคถเฅเคฏเค• เคฎเฅเคนเคฃเฅ‚เคจ เคšเคฟเคจเฅเคนเคพเค‚เค•เคฟเคค เค•เฅ‡เคฒเฅ‡ เค†เคนเฅ‡, เคธเคฒเฅเคฒเฅเคฏเคพเคธเคน: {replacement}.", - "documented": "{community} เคจเฅ‡ เคฏเคพ เคชเฅ…เค•เฅ‡เคœเคฒเคพ เค…เคงเคฟเค• เค•เคพเคฐเฅเคฏเค•เฅเคทเคฎ เคชเคฐเฅเคฏเคพเคฏ เค…เคธเคฒเฅเคฏเคพเคจเฅ‡ เคšเคฟเคจเฅเคนเคพเค‚เค•เคฟเคค เค•เฅ‡เคฒเฅ‡ เค†เคนเฅ‡.", "none": "เคนเฅ‡ เคชเฅ…เค•เฅ‡เคœ เคฏเคพเคชเฅเคขเฅ‡ เค†เคตเคถเฅเคฏเค• เคจเคพเคนเฅ€ เค…เคธเฅ‡ เคšเคฟเคจเฅเคนเคพเค‚เค•เคฟเคค เค•เฅ‡เคฒเฅ‡ เค—เฅ‡เคฒเฅ‡ เค†เคนเฅ‡, เค†เคฃเคฟ เคคเฅเคฏเคพเคšเฅ€ เค•เคพเคฐเฅเคฏเค•เฅเคทเคฎเคคเคพ เคธเคฐเฅเคต เค‡เค‚เคœเคฟเคจเคพเค‚เคฎเคงเฅเคฏเฅ‡ เคฎเฅ‚เคณเคคเคƒ เค‰เคชเคฒเคฌเฅเคง เค…เคธเฅ‚ เคถเค•เคคเฅ‡.", "learn_more": "เค…เคงเคฟเค• เคœเคพเคฃเฅ‚เคจ เค˜เฅเคฏเคพ", "learn_more_above": "เคตเคฐ เค…เคงเคฟเค• เคœเคพเคฃเฅ‚เคจ เค˜เฅเคฏเคพ.", - "community": "เคธเคฎเฅเคฆเคพเคฏ", "consider_no_dep": "+ เคจเคฟเคฐเฅเคญเคฐเคคเคพ เคจเค•เฅ‹ เค•เคพ?" }, "stats": { @@ -381,7 +396,6 @@ "view_all": "{count} เค†เคตเฅƒเคคเฅเคคเฅ€ เคชเคนเคพ | เคธเคฐเฅเคต {count} เค†เคตเฅƒเคคเฅเคคเฅเคฏเคพ เคชเคนเคพ", "view_all_versions": "เคธเคฐเฅเคต เค†เคตเฅƒเคคเฅเคคเฅเคฏเคพ เคชเคนเคพ", "distribution_title": "Semver เค—เคŸ", - "distribution_modal_title": "เค†เคตเฅƒเคคเฅเคคเฅเคฏเคพ", "distribution_range_date_same_year": "{from} เคคเฅ‡ {to}, {endYear}", "distribution_range_date_multiple_years": "{from}, {startYear} เคคเฅ‡ {to}, {endYear}", "grouping_major": "เคชเฅเคฐเคฎเฅเค–", @@ -411,6 +425,11 @@ "current_tags": "เคธเคงเฅเคฏเคพเคšเฅ‡ เคŸเฅ…เค—เฅเคธ", "no_match_filter": "{filter} เคถเฅ€ เคœเฅเคณเคฃเคพเคฐเฅ€ เค•เฅ‹เคฃเคคเฅ€เคนเฅ€ เค†เคตเฅƒเคคเฅเคคเฅ€ เคจเคพเคนเฅ€" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "{count} เคจเคฟเคฐเฅเคญเคฐเคคเคพ | {count} เคจเคฟเคฐเฅเคญเคฐเคคเคพ", "list_label": "เคชเฅ…เค•เฅ‡เคœ เคจเคฟเคฐเฅเคญเคฐเคคเคพ", @@ -604,6 +623,9 @@ "tarball": ".tar.gz เคธเฅเคตเคฐเฅ‚เคชเคพเคค เคŸเคพเคฐเคฌเฅ‰เคฒ เคกเคพเค‰เคจเคฒเฅ‹เคก เค•เคฐเคพ" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "เคฒเฅ‹เค•เคฒ เค•เคจเฅ‡เค•เฅเคŸเคฐ", @@ -1073,6 +1095,9 @@ "packages_selected": "{count}/{max} เคชเฅ…เค•เฅ‡เคœเฅ‡เคธ เคจเคฟเคตเคกเคฒเฅ€.", "add_hint": "เคคเฅเคฒเคจเฅ‡เคธเคพเค เฅ€ เค•เคฟเคฎเคพเคจ 2 เคชเฅ…เค•เฅ‡เคœเฅ‡เคธ เคœเฅ‹เคกเคพ." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(เคจเคฟเคฐเฅเคญเคฐเคคเคพ เคจเคพเคนเฅ€)", "typeahead_title": "James เค•เคพเคฏ เค•เคฐเฅ‡เคฒ?", @@ -1147,7 +1172,10 @@ "vulnerabilities": { "label": "เค…เคธเฅเคฐเค•เฅเคทเคฟเคคเคคเคพ", "description": "เคœเฅเคžเคพเคค เคธเฅเคฐเค•เฅเคทเคพ เค…เคธเฅเคฐเค•เฅเคทเคฟเคคเคคเคพ" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "เค•เฅ‹เคฃเคคเฅ‡เคนเฅ€", @@ -1167,8 +1195,6 @@ "file_changes": "เคซเคพเค‡เคฒ เคฌเคฆเคฒ", "files_count": "{count} เคซเคพเค‡เคฒ | {count} เคซเคพเค‡เคฒเฅเคธ", "lines_hidden": "{count} เค“เคณ เคฒเคชเคตเคฒเฅ€ | {count} เค“เคณเฅ€ เคฒเคชเคตเคฒเฅเคฏเคพ", - "file_too_large": "เคซเคพเค‡เคฒ เคคเฅเคฒเคจเคพ เค•เคฐเคฃเฅเคฏเคพเคธเคพเค เฅ€ เค–เฅ‚เคช เคฎเฅ‹เค เฅ€ เค†เคนเฅ‡", - "file_size_warning": "เคคเฅเคฒเคจเฅ‡เคธเคพเค เฅ€เคšเฅ€ 250KB เคฎเคฐเฅเคฏเคพเคฆเคพ {size} เคจเฅ‡ เค“เคฒเคพเค‚เคกเคฒเฅ€ เค†เคนเฅ‡", "compare_versions": "เคซเคฐเค•", "compare_versions_title": "เคจเคตเฅ€เคจเคคเคฎ เค†เคตเฅƒเคคเฅเคคเฅ€เคถเฅ€ เคคเฅเคฒเคจเคพ เค•เคฐเคพ", "comparing_versions_label": "เค†เคตเฅƒเคคเฅเคคเฅเคฏเคพเค‚เคšเฅ€ เคคเฅเคฒเคจเคพ เค•เคฐเคค เค†เคนเฅ‡...", @@ -1392,5 +1418,15 @@ "selection": "0 เคจเคฟเคตเคกเคฒเฅ‡ | 1 เคจเคฟเคตเคกเคฒเฅ‡ | {count} เคจเคฟเคตเคกเคฒเฅ‡", "shortcut": "\"{key}\" เคฆเคพเคฌเฅ‚เคจ เค•เฅเคฐเคฟเคฏเคพเค‚เคตเคฐ เคซเฅ‹เค•เคธ เค•เคฐเคพ", "button_close_aria_label": "เค•เฅเคฐเคฟเคฏเคพ เคชเคŸเฅเคŸเฅ€ เคฌเค‚เคฆ เค•เคฐเคพ" + }, + "logo_menu": {}, + "brand": { + "logos": {}, + "customize": {}, + "typography": {}, + "guidelines": {} + }, + "changelog": { + "error": {} } } diff --git a/i18n/locales/nb-NO.json b/i18n/locales/nb-NO.json index 7a9b3c4012..2caa3e1c74 100644 --- a/i18n/locales/nb-NO.json +++ b/i18n/locales/nb-NO.json @@ -46,7 +46,8 @@ "disable_shortcuts": "Du kan deaktivere tastatursnarveier i {settings}.", "open_main": "ร…pne hovedinformasjon", "open_diff": "ร…pne versjonsforskjeller", - "open_timeline": "ร…pne tidslinje" + "open_timeline": "ร…pne tidslinje", + "open_stats": "ร…pne statistikk" }, "search": { "label": "Sรธk etter npm-pakker", @@ -98,6 +99,11 @@ "current": "gjeldende", "here": "du er her", "connected": "tilkoblet", + "keyboard_shortcuts": { + "navigate": "รฅ navigere", + "select": "velge", + "close": "lukke" + }, "state": { "on": "pรฅ", "off": "av" @@ -153,7 +159,9 @@ "code": "Kode", "diff": "Diff", "compare": "Sammenlign denne pakken", - "download": "Last ned tarball" + "download": "Last ned tarball", + "changelog": "Endringslogg", + "stats": "Statistikk" }, "package_actions": { "copy_run": "Kopier kjรธrekommando" @@ -228,6 +236,31 @@ "more_replies": "{count} svar til... | {count} svar til..." } }, + "noodles": { + "title": "nudler", + "meta_description": "Alle nudler vi noensinne har vist pรฅ npmx โ€” sesonglogoer, pรฅskeegg og historiene bak dem.", + "latest": "Siste nudler", + "what_is": "Hva er nudler", + "what_is_body": "Nudler er de lekne variantene av npmx-logoen vi viser pรฅ forsiden for รฅ markere utgivelser, helligdager, arrangementer og andre รธyeblikk verdt รฅ feire. Tenk pรฅ dem som Google Doodles, men for npm-pakker.", + "empty": "Ingen nudler ennรฅ.", + "load_more": "Last {count} til", + "dates": "Aktive datoer", + "shipped_in": "Lansert i", + "credits": "Krediteringer", + "learn_more": "Lรฆr mer", + "carousel_prev": "Forrige bilde", + "carousel_next": "Neste bilde", + "carousel_dots": "Navigering av variantbilder", + "carousel_jump": "Gรฅ til bilde {index}", + "lens_label": "{title} โ€” bildeopptak", + "lens_slide": "bilde {index}", + "lens_slide_position": "Bilde {index} av {total}", + "back_to_archive": "Tilbake til alle nudler", + "missing": { + "title": "Denne nudelen kom aldri ut av bollen.", + "body": "Vi har ikke en {slug}-nudel pรฅ menyen. Enten blir den fortsatt lagt opp, eller den ble aldri laget. Uansett โ€” tilbake til arkivet." + } + }, "settings": { "title": "innstillinger", "tagline": "tilpass din npmx-opplevelse", @@ -285,7 +318,9 @@ }, "keyboard_shortcuts_enabled": "Aktiver tastatursnarveier", "keyboard_shortcuts_enabled_description": "Tastatursnarveier kan deaktiveres hvis de er i konflikt med andre nettleser- eller systemsnarveier", - "enable_code_ligatures": "Aktiver ligaturer i kode" + "enable_code_ligatures": "Aktiver ligaturer i kode", + "enable_changelog_autoscroll": "Automatisk skrolling til forespurt versjon", + "enable_changelog_autoscroll_description": "Automatisk skrolling til eller nรฆr den forespurte versjonen i pakkens endringslogg" }, "i18n": { "missing_keys": "{count} manglende oversettelse | {count} manglende oversettelser", @@ -397,12 +432,11 @@ "example": "Eksempel:", "native": "Denne kan erstattes med {replacement}, tilgjengelig siden Node {nodeVersion}.", "native_no_version": "Denne pakken kan erstattes med {replacement}.", - "simple": "{community} har flagget denne pakken som overflรธdig, med rรฅdet: {replacement}.", - "documented": "{community} har flagget denne pakken da det finnes alternativer med bedre ytelse.", + "simple": "Denne pakken er flagget som overflรธdig, med rรฅd: {replacement}", + "documented": "Denne pakken er flagget som รฅ ha mer ytelseseffektive alternativer.", "none": "Denne pakken er flagget som ikke lenger nรธdvendig, og funksjonaliteten er sannsynligvis tilgjengelig innebygd i alle motorer.", "learn_more": "Lรฆr mer", "learn_more_above": "Lรฆr mer ovenfor.", - "community": "fellesskapet", "consider_no_dep": "+ Vurdere ingen avhengighet?" }, "stats": { @@ -417,7 +451,10 @@ "size_tooltip": { "unpacked": "{size} utpakket stรธrrelse (denne pakken)", "total": "{size} total utpakket stรธrrelse (inkludert {count} avhengighet for linux-x64) | {size} total utpakket stรธrrelse (inkludert alle {count} avhengigheter for linux-x64)" - } + }, + "main_information": "Hovedinformasjon", + "trends": "Trender", + "version_distribution": "Versjonsfordeling" }, "skills": { "title": "Agentferdigheter", @@ -448,7 +485,9 @@ "fund": "stรธtt", "compare": "sammenlign", "timeline": "tidslinje", - "compare_this_package": "sammenlign denne pakken" + "stats": "statistikk", + "compare_this_package": "sammenlign denne pakken", + "changelog": "endringslogg" }, "likes": { "like": "Lik denne pakken", @@ -528,6 +567,7 @@ "weekly_downloads": "Ukentlige nedlastinger", "keywords": "Nรธkkelord", "license": "Lisens", + "version": "Versjon", "select": "Velg pakke", "select_maximum": "Maksimalt {count} pakker kan velges" }, @@ -546,7 +586,6 @@ "view_all": "Vis {count} versjon | Vis alle {count} versjoner", "view_all_versions": "Vis alle versjoner", "distribution_title": "Semver-gruppe", - "distribution_modal_title": "Versjoner", "distribution_range_date_same_year": "fra {from} til {to}, {endYear}", "distribution_range_date_multiple_years": "fra {from}, {startYear} til {to}, {endYear}", "grouping_major": "Major", @@ -600,6 +639,7 @@ "base_scale": "start y-aksen pรฅ null", "zoom": "zoom", "reset_minimap": "tilbakestill minikart", + "ordered_versions": "kun stabile versjoner", "copy_alt": { "key_changes": "Viktige endringer: {version_events}.", "version_events": "versjon {version}: {events}", @@ -707,10 +747,17 @@ "general_description": "Y-aksen representerer antall nedlastinger. X-aksen representerer datoomrรฅdet, fra {start_date} til {end_date}, med en {granularity} tidsperiode.{estimation_notice} {packages_analysis}. {watermark}.", "facet_bar_general_description": "Horisontalt stolpediagram for: {packages}, sammenligner {facet} ({description}). {facet_analysis} {watermark}.", "facet_bar_analysis": "{package_name} har en verdi pรฅ {value}." + }, + "embedding": { + "chart": "Bygg inn dette diagrammet", + "copy_url": "Kopier denne URL-en for รฅ bygge inn diagrammet pรฅ nettsiden din", + "preview": "Forhรฅndsvisning", + "tip": "Hvis startDato og sluttDato ikke er oppgitt, bruker diagrammet standard de siste 12 mรฅnedene." } }, "downloads": { "title": "Ukentlige nedlastinger", + "version_distribution_title": "ukentlige nedlastinger for versjon {version}", "community_distribution": "Vis distribusjon av bruk i fellesskapet", "subtitle": "Pรฅ tvers av alle versjoner", "sparkline_nav_hint": "Bruk โ† โ†’" @@ -1179,6 +1226,9 @@ }, "team": { "title": "Team", + "core": "Kjerne", + "maintainers": "Vedlikeholdere", + "role_core": "kjerne", "role_steward": "forvalter", "role_maintainer": "vedlikeholder", "sponsor": "sponsor", @@ -1389,6 +1439,10 @@ "label": "GitHub-stjerner", "description": "Antall stjerner pรฅ GitHub-repositoriet" }, + "githubForks": { + "label": "GitHub-forks", + "description": "Antall forks pรฅ GitHub-repositoriet" + }, "githubIssues": { "label": "GitHub-saker", "description": "Antall saker pรฅ GitHub-repositoriet" @@ -1416,8 +1470,6 @@ "file_changes": "Filendringer", "files_count": "{count} fil | {count} filer", "lines_hidden": "{count} linje skjult | {count} linjer skjult", - "file_too_large": "Filen er for stor til รฅ sammenligne", - "file_size_warning": "{size} overstiger grensen pรฅ 250KB for sammenligning", "compare_versions": "diff", "compare_versions_title": "Sammenlign med nyeste versjon", "comparing_versions_label": "Sammenligner versjoner...", @@ -1458,6 +1510,9 @@ "change_ratio": "Endringsforhold", "char_edits": "Tegnredigeringer", "diff_distance": "Diff-avstand", + "diff_truncated": "Diff trunkert for ytelse. Viser kun de fรธrste endrede linjene.", + "large_diff_mode": "Stor fildiff vist med deaktivert sammenslรฅing av redigeringer for ytelse.", + "large_diff_options_disabled": "Stor filmodus deaktiverer sammenslรฅing av redigeringer for ytelse.", "loading_diff": "Laster diff...", "loading_diff_error": "Kunne ikke laste diff", "merge_modified_lines": "Slรฅ sammen endrede linjer", @@ -1718,5 +1773,16 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "En sรธt, avrundet og fargerik versjon av npmx-logoen." + "alt_logo_kawaii": "En sรธt, avrundet og fargerik versjon av npmx-logoen.", + "changelog": { + "pre_release": "Forhรฅndsutgivelse", + "draft": "Utkast", + "no_logs": "Beklager, denne pakken publiserer ikke endringslogger eller formatet stรธttes ikke.", + "error": { + "p1": "Beklager, endringsloggen for {package} kunne ikke lastes", + "p2": "Prรธv igjen senere eller {viewon}" + }, + "rate_limit_ungh": "Beklager, GitHubs rate limit er nรฅdd, prรธv igjen om et รธyeblikk", + "version_unavailable": "Den forespurte versjonen er ikke tilgjengelig." + } } diff --git a/i18n/locales/ne-NP.json b/i18n/locales/ne-NP.json index 60b7dec1f1..f02718bd7e 100644 --- a/i18n/locales/ne-NP.json +++ b/i18n/locales/ne-NP.json @@ -140,11 +140,8 @@ "replacement": { "title": "เคคเคชเคพเคˆเค‚เคฒเคพเคˆ เคฏเฅ‹ เคกเคฟเคชเฅ‡เคจเฅเคกเฅ‡เคจเฅเคธเฅ€ เค†เคตเคถเฅเคฏเค• เคจเคชเคฐเฅเคจ เคธเค•เฅเค›เฅค", "native": "Node {nodeVersion} เคฆเฅ‡เค–เคฟ เค‰เคชเคฒเคฌเฅเคง {replacement} เคฒเฅ‡ เคฏเคธเคฒเคพเคˆ เคชเฅเคฐเคคเคฟเคธเฅเคฅเคพเคชเคจ เค—เคฐเฅเคจ เคธเค•เฅเค›เฅค", - "simple": "{community} เคฒเฅ‡ เคฏเฅ‹ เคชเฅเคฏเคพเค•เฅ‡เคœเคฒเคพเคˆ เค…เคจเคพเคตเคถเฅเคฏเค• เคญเคจเฅ‡เคฐ เคšเคฟเคจเฅเคน เคฒเค—เคพเคเค•เฅ‹ เค›, เคธเคฒเฅเคฒเคพเคน: {replacement}เฅค", - "documented": "{community} เคฒเฅ‡ เคฏเฅ‹ เคชเฅเคฏเคพเค•เฅ‡เคœเค•เคพ เคฅเคช เค‰เคšเฅเคš เคชเฅเคฐเคฆเคฐเฅเคถเคจ เคญเคเค•เคพ เคตเคฟเค•เคฒเฅเคชเคนเคฐเฅ‚ เค›เคจเฅ เคญเคจเฅ‡เคฐ เคšเคฟเคจเฅเคน เคฒเค—เคพเคเค•เฅ‹ เค›เฅค", "none": "เคฏเฅ‹ เคชเฅเคฏเคพเค•เฅ‡เคœ เค…เคฌ เค†เคตเคถเฅเคฏเค• เค›เฅˆเคจ เคญเคจเฅ‡เคฐ เคšเคฟเคจเฅเคน เคฒเค—เคพเค‡เคเค•เฅ‹ เค›, เคฐ เคฏเคธเค•เฅ‹ เค•เคพเคฐเฅเคฏเค•เฅเคทเคฎเคคเคพ เคธเคฎเฅเคญเคตเคคเคƒ เคธเคฌเฅˆ เค‡เคจเฅเคœเคฟเคจเคนเคฐเฅ‚เคฎเคพ เคจเฅˆ เคฌเคฟเคฒเฅเคŸ-เค‡เคจ เคฐเฅ‚เคชเคฎเคพ เค‰เคชเคฒเคฌเฅเคง เค›เฅค", - "learn_more": "เคฅเคช เคœเคพเคจเฅเคจเฅเคนเฅ‹เคธเฅ", - "community": "เคธเคฎเฅเคฆเคพเคฏ" + "learn_more": "เคฅเคช เคœเคพเคจเฅเคจเฅเคนเฅ‹เคธเฅ" }, "stats": { "license": "เคฒเคพเค‡เคธเฅ‡เคจเฅเคธ", diff --git a/i18n/locales/nl.json b/i18n/locales/nl.json index 9f1282b71a..abd844fb98 100644 --- a/i18n/locales/nl.json +++ b/i18n/locales/nl.json @@ -9,8 +9,8 @@ "built_at": "gebouwd {0}", "alt_logo": "npmx logo", "tagline": "een snelle, moderne browser voor het npm-register", - "non_affiliation_disclaimer": "niet affiliรซerd met npm, Inc.", - "trademark_disclaimer": "npm is een geregisteerd trademark van npm, Inc. Deze website is niet affiliรซerd met npm, Inc.", + "non_affiliation_disclaimer": "niet geaffilieerd met npm, Inc.", + "trademark_disclaimer": "npm is een geregistreerd handelsmerk van npm, Inc. Deze website is niet geaffilieerd met npm, Inc.", "footer": { "about": "over ons", "blog": "blog", @@ -23,7 +23,8 @@ "brand": "merk", "resources": "Informatie", "features": "Functies", - "other": "Overig" + "other": "Overig", + "sponsored_by": "Gesponsord door {list}" }, "shortcuts": { "section": { @@ -46,7 +47,8 @@ "disable_shortcuts": "U kunt toetsenbordnavigatie uitschakelen in {instellingen}.", "open_main": "Open pakket overzicht", "open_diff": "Open versie verschillen", - "open_timeline": "Open tijdlijn" + "open_timeline": "Open tijdlijn", + "open_stats": "Open statistieken" }, "search": { "label": "Zoek npm pakketten", @@ -98,6 +100,11 @@ "current": "huidige", "here": "u bent hier", "connected": "verbonden", + "keyboard_shortcuts": { + "navigate": "navigeren", + "select": "selecteren", + "close": "sluiten" + }, "state": { "on": "aan", "off": "uit" @@ -154,7 +161,8 @@ "diff": "Verschillen", "compare": "Vergelijk dit pakket", "download": "Download tarball", - "changelog": "Wijzigingenoverzicht" + "changelog": "Wijzigingen", + "stats": "Statistieken" }, "package_actions": { "copy_run": "Kopieer uitvoor command" @@ -229,6 +237,31 @@ "more_replies": "{count} meer reactie... | {count} meer reacties..." } }, + "noodles": { + "title": "noodles", + "meta_description": "Elke noodle die ooit op npmx verscheen โ€” de seizoenslogo's, easter eggs en de verhalen erachter.", + "latest": "Laatste noodles", + "what_is": "Wat zijn noodles", + "what_is_body": "Noodles zijn de speelse varianten van het npmx-logo die we op de homepage tonen bij releases, feestdagen, evenementen en andere momenten die de moeite waard zijn om te vieren. Zie ze als Google Doodles, maar dan voor npm-packages.", + "empty": "Nog geen noodles.", + "load_more": "Laad nog {count}", + "dates": "Actieve datums", + "shipped_in": "Uitgebracht in", + "credits": "Credits", + "learn_more": "Meer informatie", + "carousel_prev": "Vorige afbeelding", + "carousel_next": "Volgende afbeelding", + "carousel_dots": "Navigatie variantafbeeldingen", + "carousel_jump": "Ga naar afbeelding {index}", + "lens_label": "{title} โ€” beeldreeks", + "lens_slide": "afbeelding {index}", + "lens_slide_position": "Slide {index} van {total}", + "back_to_archive": "Terug naar alle noodles", + "missing": { + "title": "Deze noodle heeft de kom nooit verlaten.", + "body": "We hebben geen \"{slug}\"-noodle op het menu. Hij is misschien nog in de maak, of hij heeft nooit bestaan. Hoe dan ook โ€” terug naar het archief." + } + }, "settings": { "title": "instellingen", "tagline": "Pas uw npmx.dev ervaring aan", @@ -386,26 +419,25 @@ "title_deps": "Aanzienlijke toename van het aantal dependencies sinds versie {version}", "title_both": "Aanzienlijke toename in omvang en dependencies sinds v{version}", "size": "De installatiegrootte is toegenomen met {percent} ({size} groter)", - "deps": "{count} meer dependencies" + "deps": "{count} meer dependency | {count} meer dependencies" }, "size_decrease": { "title_size": "Pakketgrootte is afgenomen sinds v{version}!", "title_deps": "Aantal dependencies is afgenomen sinds v{version}!", "title_both": "De pakketgrootte en het aantal dependencies zijn sindsdien afgenomen v{version}!", "size": "De installatiegrootte is met {percent} verminderd ({size} kleiner)", - "deps": "{count} minder dependencies" + "deps": "{count} minder dependency | {count} minder dependencies" }, "replacement": { "title": "U heeft waarschijnlijk dit niet nodig", "example": "Voorbeeld:", "native": "Dit kan vervangen worden door {replacement}, Beschikbaar sinds node {nodeVersion}.", "native_no_version": "Dit pakket kan vervangen worden door {replacement}.", - "simple": "De {community} heeft dit pakket als overbodig gemarkeerd, met het advies: {replacement}.", - "documented": "De {community} heeft aangegeven dat er voor dit pakket beter presterende alternatieven zijn.", + "simple": "Dit pakket is als overbodig gemarkeerd, met het advies: {replacement}.", + "documented": "Dit pakket is gemarkeerd omdat er beter presterende alternatieven beschikbaar.", "none": "Dit pakket is gemarkeerd als overbodig en de functionaliteit ervan is waarschijnlijk standaard beschikbaar in alle omgevingen.", "learn_more": "Leer meer", "learn_more_above": "Lees hierboven meer.", - "community": "gemeenschap", "consider_no_dep": "+ Geen dependency overwegen?" }, "stats": { @@ -420,7 +452,10 @@ "size_tooltip": { "unpacked": "{size} uitgepakte grootte (dit pakket)", "total": "totale grootte na uitpakken (inclusief {count} dependencies voor linux-x64)" - } + }, + "main_information": "Hoofdinformatie", + "trends": "Trends", + "version_distribution": "Versieverdeling" }, "skills": { "title": "Agent Skills", @@ -451,8 +486,9 @@ "fund": "Steunen", "compare": "vergelijk", "timeline": "tijdlijn", + "stats": "stats", "compare_this_package": "Vergelijk dit pakket", - "changelog": "wijzigingenoverzicht" + "changelog": "Wijzigingen" }, "likes": { "like": "Dit pakket leuk vinden", @@ -507,7 +543,7 @@ "title": "Herkomst verificatie gegevens", "built_and_signed_on": "Gebouwd en getekend op {provider}", "view_build_summary": "Bekijk bouw samenvatting", - "source_commit": "Bron Commit", + "source_commit": "Bron commit", "build_file": "Bouw bestand", "public_ledger": "Publiek logboek", "transparency_log_entry": "Vermelding in het transparantielogboek", @@ -532,6 +568,7 @@ "weekly_downloads": "Wekelijkse downloads", "keywords": "Trefwoorden", "license": "Licentie", + "version": "Versie", "select": "Selecteer pakket", "select_maximum": "Er kunnen maximaal {count} pakketten worden geselecteerd" }, @@ -550,7 +587,6 @@ "view_all": "Bekijk {count} versie | Bekijk alle {count} versies", "view_all_versions": "Bekijk alle versies", "distribution_title": "Semver Groep", - "distribution_modal_title": "Versies", "distribution_range_date_same_year": "van {from} t/m {to}, {endYear}", "distribution_range_date_multiple_years": "van {from}, {startYear} t/m {to}, {endYear}", "grouping_major": "Hoofd", @@ -588,8 +624,8 @@ "load_error": "De tijdlijn kan niet worden geladen. Probeer het later nog eens.", "size_increase": "De installatiegrootte is toegenomen met {percent}% ({size})", "size_decrease": "De installatiegrootte is afgenomen met {percent}% ({size})", - "dep_increase": "{count} dependencies toegevoegd", - "dep_decrease": "{count} dependencies verwijderd", + "dep_increase": "{count} dependency toegevoegd | {count} dependencies toegevoegd", + "dep_decrease": "{count} dependency verwijderd | {count} dependencies verwijderd", "license_change": "Licentie gewijzigd van {from} naar {to}", "esm_added": "Moduletype is gewijzigd naar ESM", "esm_removed": "Moduletype is gewijzigd van ESM naar CJS", @@ -712,10 +748,17 @@ "general_description": "De Y-as toont het aantal downloads. De X-as toont de periode, van {start_date} tot {end_date}, met een {granularity} tijdsinterval. {estimation_notice} {packages_analysis}. {watermark}.", "facet_bar_general_description": " Horizontaal staafdiagram voor: {packages}, ter vergelijking van {facet} ({description}). {facet_analysis} {watermark}.", "facet_bar_analysis": "{package_name} heeft een waarde van {value}." + }, + "embedding": { + "chart": "Deze grafiek insluiten", + "copy_url": "Kopieer deze URL om de grafiek in uw website in te sluiten", + "preview": "Voorbeeld", + "tip": "Als startDate en endDate niet zijn opgegeven, toont de grafiek standaard de laatste 12 maanden." } }, "downloads": { "title": "Wekelijkse Downloads", + "version_distribution_title": "wekelijkse downloads voor versie {version}", "community_distribution": "Bekijk adoptiegraad", "subtitle": "Over alle versies", "sparkline_nav_hint": "Gebruik โ† โ†’" @@ -1058,7 +1101,7 @@ "scope_keywords_description": "Alleen zoeken op trefwoorden", "scope_all": "Alle", "scope_all_description": "Zoek alle velden, ondersteund naam: beschrijving: tf: beheerders", - "weekly_downloads": "Weekelijkse downloads", + "weekly_downloads": "Wekelijkse downloads", "updated_within": "Bijgewerkt binnen", "security": "Beveiliging", "keywords": "Trefwoorden", @@ -1177,15 +1220,20 @@ } }, "sponsors": { - "title": "Sponsoren" + "title": "Sponsoren", + "gold": "Gouden sponsors", + "silver": "Zilveren sponsors" }, "oss_partners": { "title": "Open Source Software Partners" }, "team": { "title": "Team", + "core": "Kern", + "maintainers": "Onderhouders", + "role_core": "kernlid", "role_steward": "Coรถrdinator", - "role_maintainer": "Onderhouder", + "role_maintainer": "Beheerder", "sponsor": "sponsor", "sponsor_aria": "Sponsor {name} op GitHub" }, @@ -1392,11 +1440,15 @@ }, "githubStars": { "label": "GitHub Sterren", - "description": "Aantal sterren van een GitHub repository" + "description": "Aantal sterren van de GitHub-repository" + }, + "githubForks": { + "label": "GitHub Forks", + "description": "Aantal forks van de GitHub-repository" }, "githubIssues": { "label": "GitHub Issues", - "description": "Aantal issues van een GitHub repository" + "description": "Aantal issues van de GitHub-repository" }, "createdAt": { "label": "Aangemaakt op", @@ -1412,7 +1464,7 @@ "types_included": "Inbegrepen", "types_none": "Geen", "vulnerabilities_summary": "{count} ({critical}C/{high}H)", - "up_to_you": "Jij beslist!" + "up_to_you": "U beslist!" }, "trends": { "title": "Trends vergelijken" @@ -1421,8 +1473,6 @@ "file_changes": "Bestand Veranderingen", "files_count": "{count} bestand | {count} bestanden", "lines_hidden": "{count} verborgen lijn | {count} verborgen lijn", - "file_too_large": "Bestand te groot om te vergelijken", - "file_size_warning": "{size} overschrijdt de limiet van 250 KB voor vergelijking", "compare_versions": "verschillen", "compare_versions_title": "Vergelijk met de laatste versie", "comparing_versions_label": "Versies vergelijken...", @@ -1463,6 +1513,9 @@ "change_ratio": "Wijziging verhouding", "char_edits": "Tekenbewerkingen", "diff_distance": "Verschilafstand", + "diff_truncated": "Diff ingekort om prestaties te verbeteren. Alleen de eerste gewijzigde regels worden getoond.", + "large_diff_mode": "Grote bestandsdiff weergegeven met inline samenvoegen van bewerkingen uitgeschakeld om prestaties te verbeteren.", + "large_diff_options_disabled": "Bij grote bestanden is inline samenvoegen van bewerkingen uitgeschakeld om prestaties te verbeteren.", "loading_diff": "Verschillen laden...", "loading_diff_error": "Laden van het verschillen is mislukt", "merge_modified_lines": "Gewijzigde regels samenvoegen", @@ -1517,9 +1570,9 @@ "li2": "{li21}{separator} {li22}", "separator": ":", "cookie_vdpl": "__vdpl", - "cookie_vdpl_desc": "Dit cookie wordt door onze hostingprovider (Vercel) gebruikt voor 'skew protection' (versiebeveiliging). Het zorgt ervoor dat je de juiste bestanden van de website laadt als er een nieuwe update wordt uitgebracht terwijl je de site bezoekt. Het volgt je niet.", + "cookie_vdpl_desc": "Dit cookie wordt door onze hostingprovider (Vercel) gebruikt voor 'skew protection' (versiebeveiliging). Het zorgt ervoor dat u de juiste bestanden van de website laadt als er een nieuwe update wordt uitgebracht terwijl u de site bezoekt. Het volgt u niet.", "cookie_h3": "h3", - "cookie_h3_desc": "Dit is ons beveiligde sessiecookie. Het slaat het OAuth-toegangstoken op wanneer je verbinding maakt met je Atmosphere-account. Dit cookie is essentieel om je ingelogde sessie te behouden." + "cookie_h3_desc": "Dit is ons beveiligde sessiecookie. Het slaat het OAuth-toegangstoken op wanneer u verbinding maakt met uw Atmosphere-account. Dit cookie is essentieel om uw ingelogde sessie te behouden." }, "local_storage": { "title": "Lokale opslag", diff --git a/i18n/locales/pl-PL.json b/i18n/locales/pl-PL.json index 7abdf7e745..9888a88aaf 100644 --- a/i18n/locales/pl-PL.json +++ b/i18n/locales/pl-PL.json @@ -73,6 +73,23 @@ "instant_search_turn_off": "wyล‚ฤ…cz", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "Gล‚รณwne", "popular_packages": "Popularne pakiety", @@ -245,15 +262,13 @@ "size": "Rozmiar instalacji wzrรณsล‚ o {percent} ({size} wiฤ™cej)", "deps": "{count} wiฤ™cej zaleลผnoล›ci" }, + "size_decrease": {}, "replacement": { "title": "Moลผliwe, ลผe nie potrzebujesz tej zaleลผnoล›ci.", "native": "Moลผna to zastฤ…piฤ‡ {replacement}, dostฤ™pne od Node {nodeVersion}.", - "simple": "{community} oznaczyล‚a ten pakiet jako zbฤ™dny, z sugestiฤ…: {replacement}.", - "documented": "{community} wskazuje, ลผe istniejฤ… wydajniejsze alternatywy.", "none": "Ten pakiet zostaล‚ oznaczony jako zbฤ™dny, a jego funkcjonalnoล›ฤ‡ jest prawdopodobnie dostฤ™pna natywnie we wszystkich ล›rodowiskach.", "learn_more": "Dowiedz siฤ™ wiฤ™cej", "learn_more_above": "Dowiedz siฤ™ wiฤ™cej powyลผej", - "community": "Spoล‚ecznoล›ฤ‡", "consider_no_dep": "+ Rozwaลผ brak zaleลผnoล›ci?" }, "stats": { @@ -379,7 +394,6 @@ "deprecated_title": "{version} (przestarzaล‚a)", "view_all": "Zobacz wszystkie {count} wersje | Zobacz {count} wersjฤ™ | Zobacz {count} wersje | Zobacz {count} wersji | Zobacz {count} wersji", "distribution_title": "Grupa semver", - "distribution_modal_title": "Wersje", "distribution_range_date_same_year": "od {from} do {to}, {endYear}", "distribution_range_date_multiple_years": "od {from}, {startYear} do {to}, {endYear}", "grouping_major": "Major", @@ -404,6 +418,11 @@ "general_description": "Wykres sล‚upkowy pokazujฤ…cy liczbฤ™ pobraล„ dla kaลผdej z {version_count} {semver_grouping_mode} wersji pakietu {package_name}, {date_range_label} od wersji {first_version} do wersji {last_version}. Najczฤ™ล›ciej pobieranฤ… wersjฤ… jest {max_downloaded_version}, pobrana zostaล‚a {max_version_downloads} razy. {per_version_analysis}. {watermark}." } }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Zaleลผnoล›ci ({count})", "list_label": "Zaleลผnoล›ci pakietu", @@ -440,6 +459,7 @@ "show_less": "(pokaลผ mniej)" }, "trends": { + "chart_assistive_text": {}, "granularity": "Agregacja", "granularity_daily": "Dzienna", "granularity_weekly": "Tygodniowa", @@ -590,6 +610,9 @@ }, "download": {} }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Lokalny konektor", @@ -1053,6 +1076,9 @@ "packages_selected": "Wybrano pakiety: {count}/{max}.", "add_hint": "Dodaj co najmniej 2 pakiety do porรณwnania." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(brak zaleลผnoล›ci)", "typeahead_title": "Co zrobiล‚by James?", @@ -1127,7 +1153,10 @@ "vulnerabilities": { "label": "Podatnoล›ci", "description": "Znane luki bezpieczeล„stwa" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "Dowolne", @@ -1147,8 +1176,6 @@ "file_changes": "Zmiany w plikach", "files_count": "{count} plikรณw", "lines_hidden": "ukryto {count} linii", - "file_too_large": "Plik jest zbyt duลผy do porรณwnania", - "file_size_warning": "{size} przekracza limit dla porรณwnaล„ wynoszฤ…cy 250KB", "compare_versions": "porรณwnaj", "compare_versions_title": "Porรณwnaj z najnowszฤ… wersjฤ…", "version_invalid_url_format": {}, @@ -1320,5 +1347,23 @@ "translation_status": { "table": {} }, - "action_bar": {} + "vacations": { + "what": {}, + "meantime": {}, + "return": {}, + "stats": { + "subtitle": {} + } + }, + "action_bar": {}, + "logo_menu": {}, + "brand": { + "logos": {}, + "customize": {}, + "typography": {}, + "guidelines": {} + }, + "changelog": { + "error": {} + } } diff --git a/i18n/locales/pt-BR.json b/i18n/locales/pt-BR.json index f7ba0028f0..8be735de9f 100644 --- a/i18n/locales/pt-BR.json +++ b/i18n/locales/pt-BR.json @@ -396,12 +396,9 @@ "example": "Exemplo:", "native": "Este pacote pode ser substituรญdo por {replacement}, disponรญvel desde Node {nodeVersion}.", "native_no_version": "Este pacote pode ser substituรญdo por {replacement}.", - "simple": "A {community} marcou este pacote como redundante, com o conselho: {replacement}.", - "documented": "A {community} marcou este pacote como tendo alternativas mais performรกticas.", "none": "Este pacote foi marcado como nรฃo mais necessรกrio, e sua funcionalidade provavelmente estรก disponรญvel nativamente em todas as engines.", "learn_more": "Saiba mais", "learn_more_above": "Saiba mais acima.", - "community": "comunidade", "consider_no_dep": "+ Considerar sem dependรชncias?" }, "stats": { @@ -542,7 +539,6 @@ "view_all": "Ver {count} versรฃo | Ver todas as {count} versรตes", "view_all_versions": "Ver todas as versรตes", "distribution_title": "Grupo Semver", - "distribution_modal_title": "Versรตes", "distribution_range_date_same_year": "de {from} a {to}, {endYear}", "distribution_range_date_multiple_years": "de {from}, {startYear} a {to}, {endYear}", "grouping_major": "Principal", @@ -587,7 +583,10 @@ "trusted_publisher_added": "Publicaรงรฃo de confianรงa ativada", "trusted_publisher_removed": "Publicaรงรฃo de confianรงa removida", "provenance_added": "Proveniรชncia ativada", - "provenance_removed": "Proveniรชncia removida" + "provenance_removed": "Proveniรชncia removida", + "chart": { + "copy_alt": {} + } }, "dependencies": { "title": "Dependรชncias ({count})", @@ -791,6 +790,9 @@ "tarball": "Baixar Tarball como .tar.gz" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Conector Local", @@ -1388,8 +1390,6 @@ "file_changes": "Alteraรงรตes de arquivo", "files_count": "{count} arquivo | {count} arquivos", "lines_hidden": "{count} linha escondida | {count} linhas escondidas", - "file_too_large": "Arquivo muito grande para comparar", - "file_size_warning": "{size} excede o limite de 250 KB para comparaรงรฃo", "compare_versions": "diferenรงa", "compare_versions_title": "Compare com a versรฃo mais recente", "comparing_versions_label": "Comparando versรตes...", @@ -1690,5 +1690,8 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "Uma versรฃo fofa, arredondada e colorida do logotipo do npmx." + "alt_logo_kawaii": "Uma versรฃo fofa, arredondada e colorida do logotipo do npmx.", + "changelog": { + "error": {} + } } diff --git a/i18n/locales/pt-PT.json b/i18n/locales/pt-PT.json index 683ce28ae6..8589219401 100644 --- a/i18n/locales/pt-PT.json +++ b/i18n/locales/pt-PT.json @@ -397,12 +397,9 @@ "example": "Exemplo:", "native": "Este pacote pode ser substituรญdo por {replacement}, disponรญvel desde Node {nodeVersion}.", "native_no_version": "Este pacote pode ser substituรญdo por {replacement}.", - "simple": "A {community} marcou este pacote como redundante, com o conselho: {replacement}.", - "documented": "A {community} marcou este pacote como tendo alternativas mais performรกticas.", "none": "Este pacote foi marcado como jรก nรฃo sendo necessรกrio, e a sua funcionalidade provavelmente estรก disponรญvel nativamente em todas as engines.", "learn_more": "Sabe mais", "learn_more_above": "Sabe mais acima.", - "community": "comunidade", "consider_no_dep": "+ Considerar sem dependรชncias?" }, "stats": { @@ -546,7 +543,6 @@ "view_all": "Ver {count} versรฃo | Ver todas as {count} versรตes", "view_all_versions": "Ver todas as versรตes", "distribution_title": "Grupo Semver", - "distribution_modal_title": "Versรตes", "distribution_range_date_same_year": "de {from} a {to}, {endYear}", "distribution_range_date_multiple_years": "de {from}, {startYear} a {to}, {endYear}", "grouping_major": "Major", @@ -591,7 +587,10 @@ "trusted_publisher_added": "Publicaรงรฃo de confianรงa ativada", "trusted_publisher_removed": "Publicaรงรฃo de confianรงa removida", "provenance_added": "Proveniรชncia ativada", - "provenance_removed": "Proveniรชncia removida" + "provenance_removed": "Proveniรชncia removida", + "chart": { + "copy_alt": {} + } }, "dependencies": { "title": "Dependรชncia ({count}) | Dependรชncias ({count})", @@ -1402,8 +1401,6 @@ "file_changes": "Alteraรงรตes de Ficheiro", "files_count": "{count} ficheiro | {count} ficheiros", "lines_hidden": "{count} linha escondida | {count} linhas escondidas", - "file_too_large": "Ficheiro muito grande para comparar", - "file_size_warning": "{size} excede o limite de 250 kB para comparaรงรฃo", "compare_versions": "diff", "compare_versions_title": "Compara com a versรฃo mais recente", "comparing_versions_label": "A comparar versรตes...", @@ -1704,5 +1701,8 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "Uma versรฃo fofa, arredondada e colorida do logรณtipo do npmx." + "alt_logo_kawaii": "Uma versรฃo fofa, arredondada e colorida do logรณtipo do npmx.", + "changelog": { + "error": {} + } } diff --git a/i18n/locales/ro-RO.json b/i18n/locales/ro-RO.json index 07e880b329..6667f08eaf 100644 --- a/i18n/locales/ro-RO.json +++ b/i18n/locales/ro-RO.json @@ -397,12 +397,9 @@ "example": "Exemplu:", "native": "Acest pachet poate fi รฎnlocuit cu {replacement}, disponibil de la Node {nodeVersion}.", "native_no_version": "Acest pachet poate fi รฎnlocuit cu {replacement}.", - "simple": "Comunitatea {community} a semnalat acest pachet ca redundant, cu recomandarea: {replacement}", - "documented": "Comunitatea {community} a semnalat acest pachet ca avรขnd alternative performante.", "none": "Acest pachet a fost semnalat ca nu mai este necesar, ศ™i funcศ›ionalitatea este probabil disponibil nativ รฎn toate motorii.", "learn_more": "Aflฤƒ mai multe", "learn_more_above": "Aflฤƒ mai multe mai sus.", - "community": "comunitate", "consider_no_dep": "+ A considera fฤƒrฤƒ dependenศ›e?" }, "stats": { @@ -546,7 +543,6 @@ "view_all": "Vizualizeazฤƒ versiunea {count} | Vizualizeazฤƒ toate cele {count} versiuni", "view_all_versions": "Vizualizeazฤƒ toate versiunile", "distribution_title": "Grupul Semver", - "distribution_modal_title": "Versiuni", "distribution_range_date_same_year": "de la {from} pรขnฤƒ la {to}, {endYear}", "distribution_range_date_multiple_years": "de la {from}, {startYear} pรขnฤƒ la {to}, {endYear}", "grouping_major": "Majorฤƒ", @@ -1413,8 +1409,6 @@ "file_changes": "Modificฤƒri Fiศ™ier", "files_count": "{count} fiศ™ier | {count} fiศ™iere", "lines_hidden": "{count} linie ascunsฤƒ | {count} linii ascunse", - "file_too_large": "Fiศ™ier prea mare pentru comparare", - "file_size_warning": "{size} depฤƒศ™eศ™te limita de 250KB pentru comparare", "compare_versions": "diff", "compare_versions_title": "Comparฤƒ cu cea mai recentฤƒ versiune", "comparing_versions_label": "Se comparฤƒ versiunile...", diff --git a/i18n/locales/ru-RU.json b/i18n/locales/ru-RU.json index 3b5ee6174f..5e91121215 100644 --- a/i18n/locales/ru-RU.json +++ b/i18n/locales/ru-RU.json @@ -400,12 +400,9 @@ "example": "ะŸั€ะธะผะตั€:", "native": "ะญั‚ะพั‚ ะฟะฐะบะตั‚ ะผะพะถะฝะพ ะทะฐะผะตะฝะธั‚ัŒ ะฝะฐ {replacement}, ะดะพัั‚ัƒะฟะฝั‹ะน ะฝะฐั‡ะธะฝะฐั ั Node {nodeVersion}.", "native_no_version": "ะญั‚ะพั‚ ะฟะฐะบะตั‚ ะผะพะถะฝะพ ะทะฐะผะตะฝะธั‚ัŒ ะฝะฐ {replacement}.", - "simple": "ะกะพะพะฑั‰ะตัั‚ะฒะพ ะพั‚ะผะตั‚ะธะปะพ ัั‚ะพั‚ ะฟะฐะบะตั‚ ะบะฐะบ ะธะทะฑั‹ั‚ะพั‡ะฝั‹ะน, ั ั€ะตะบะพะผะตะฝะดะฐั†ะธะตะน: {replacement}.", - "documented": "ะกะพะพะฑั‰ะตัั‚ะฒะพ ะพั‚ะผะตั‚ะธะปะพ, ั‡ั‚ะพ ัƒ ัั‚ะพะณะพ ะฟะฐะบะตั‚ะฐ ะตัั‚ัŒ ะฑะพะปะตะต ะฟั€ะพะธะทะฒะพะดะธั‚ะตะปัŒะฝั‹ะต ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒั‹.", "none": "ะญั‚ะพั‚ ะฟะฐะบะตั‚ ะฑั‹ะป ะพั‚ะผะตั‡ะตะฝ ะบะฐะบ ะฝะตะฝัƒะถะฝั‹ะน, ั‚ะฐะบ ะบะฐะบ ะตะณะพ ั„ัƒะฝะบั†ะธะพะฝะฐะปัŒะฝะพัั‚ัŒ, ะฒะตั€ะพัั‚ะฝะพ, ะดะพัั‚ัƒะฟะฝะฐ ะฝะฐั‚ะธะฒะฝะพ ะฒะพ ะฒัะตั… ะดะฒะธะถะบะฐั….", "learn_more": "ะŸะพะดั€ะพะฑะฝะตะต", "learn_more_above": "ะฃะทะฝะฐะนั‚ะต ะฑะพะปัŒัˆะต ะฒั‹ัˆะต.", - "community": "ัะพะพะฑั‰ะตัั‚ะฒะพ", "consider_no_dep": "+ ะ ะฐััะผะพั‚ั€ะตั‚ัŒ ะฒะฐั€ะธะฐะฝั‚ ะฑะตะท ะทะฐะฒะธัะธะผะพัั‚ะธ?" }, "stats": { @@ -550,7 +547,6 @@ "view_all": "ะŸะพัะผะพั‚ั€ะตั‚ัŒ {count} ะฒะตั€ัะธัŽ | ะŸะพัะผะพั‚ั€ะตั‚ัŒ ะฒัะต {count} ะฒะตั€ัะธะธ | ะŸะพัะผะพั‚ั€ะตั‚ัŒ ะฒัะต {count} ะฒะตั€ัะธะน", "view_all_versions": "ะ’ัะต ะฒะตั€ัะธะธ", "distribution_title": "ะ“ั€ัƒะฟะฟะฐ Semver", - "distribution_modal_title": "ะ’ะตั€ัะธะธ", "distribution_range_date_same_year": "ั {from} ะฟะพ {to}, {endYear}", "distribution_range_date_multiple_years": "ั {from} {startYear} ะฟะพ {to} {endYear}", "grouping_major": "ะœะฐะถะพั€ะฝั‹ะต", @@ -1420,8 +1416,6 @@ "file_changes": "ะ˜ะทะผะตะฝะตะฝะธั ั„ะฐะนะปะพะฒ", "files_count": "ั„ะฐะนะปะพะฒ: {count}", "lines_hidden": "ัะบั€ั‹ั‚ะพ ัั‚ั€ะพะบ: {count}", - "file_too_large": "ะคะฐะนะป ัะปะธัˆะบะพะผ ะฑะพะปัŒัˆะพะน ะดะปั ัั€ะฐะฒะฝะตะฝะธั", - "file_size_warning": "{size} ะฟั€ะตะฒั‹ัˆะฐะตั‚ ะปะธะผะธั‚ ะฒ 250 ะšะ‘ ะดะปั ัั€ะฐะฒะฝะตะฝะธั", "compare_versions": "ัั€ะฐะฒะฝะตะฝะธะต", "compare_versions_title": "ะกั€ะฐะฒะฝะธั‚ัŒ ั ะฟะพัะปะตะดะฝะตะน ะฒะตั€ัะธะตะน", "comparing_versions_label": "ะกั€ะฐะฒะฝะตะฝะธะต ะฒะตั€ัะธะนโ€ฆ", diff --git a/i18n/locales/sr-Latn-RS.json b/i18n/locales/sr-Latn-RS.json index e164313a05..2c76fa50b9 100644 --- a/i18n/locales/sr-Latn-RS.json +++ b/i18n/locales/sr-Latn-RS.json @@ -76,6 +76,23 @@ "instant_search_turn_off": "iskljuฤite", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "Glavno", "popular_packages": "Popularni paketi", @@ -265,15 +282,13 @@ "size": "Veliฤina instalacije poveฤ‡ana za {percent} ({size} veฤ‡a)", "deps": "{count} viลกe zavisnosti" }, + "size_decrease": {}, "replacement": { "title": "Moลพda vam ova zavisnost ne treba.", "native": "Ovo se moลพe zameniti sa {replacement}, dostupno od Node verzije {nodeVersion}.", - "simple": "{community} je oznaฤio ovaj paket kao suviลกan, sa savetom: {replacement}.", - "documented": "{community} je oznaฤio ovaj paket kao onaj koji ima performantnije alternative.", "none": "Ovaj paket je oznaฤen kao nepotreban, a njegova funkcionalnost je verovatno dostupna izvorno u svim okruลพenjima.", "learn_more": "Saznajte viลกe", "learn_more_above": "Saznajte viลกe iznad.", - "community": "zajednica", "consider_no_dep": "+ Razmislite bez zavisnosti?" }, "stats": { @@ -412,7 +427,6 @@ "view_all": "Pogledajte {count} verziju | Pogledajte {count} verzije | Pogledajte svih {count} verzija", "view_all_versions": "Pogledajte sve verzije", "distribution_title": "Semver grupa", - "distribution_modal_title": "Verzije", "distribution_range_date_same_year": "od {from} do {to}, {endYear}", "distribution_range_date_multiple_years": "od {from}, {startYear} do {to}, {endYear}", "grouping_major": "Glavni", @@ -442,6 +456,11 @@ "current_tags": "Trenutne oznake", "no_match_filter": "Nijedna verzija ne odgovara filteru {filter}" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Zavisnost ({count}) | Zavisnosti ({count})", "list_label": "Zavisnosti paketa", @@ -641,6 +660,9 @@ "tarball": "Preuzmite Tarball kao .tar.gz" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Lokalni konektor", @@ -1112,6 +1134,9 @@ "packages_selected": "{count}/{max} paketa izabrano.", "add_hint": "Dodajte najmanje 2 paketa za poreฤ‘enje." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(Bez zavisnosti)", "typeahead_title": "ล ta bi James uradio?", @@ -1190,7 +1215,10 @@ "vulnerabilities": { "label": "Ranjivosti", "description": "Poznate bezbednosne ranjivosti" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "Bilo koje", @@ -1210,8 +1238,6 @@ "file_changes": "Izmene datoteka", "files_count": "{count} datoteka | {count} datoteke | {count} datoteka", "lines_hidden": "{count} linija sakrivena | {count} linije sakrivene | {count} linija sakriveno", - "file_too_large": "Datoteka je prevelika za poreฤ‘enje", - "file_size_warning": "{size} premaลกuje ograniฤenje od 250KB za poreฤ‘enje", "compare_versions": "razlika", "compare_versions_title": "Uporedite sa najnovijom verzijom", "comparing_versions_label": "Poreฤ‘enje verzija...", @@ -1511,5 +1537,8 @@ "message": "Pristupaฤnost nam je vaลพna, i voleli bismo da nas pratite u ovoj viziji. Kada koristite pomenute medije, osigurajte dovoljan kontrast u odnosu na pozadinu i nemojte iฤ‡i manje od 24px. Ako su vam potrebni bilo kakvi drugi resursi ili dodatne informacije o projektu, slobodno nas kontaktirajte na {link}.", "discord_link_text": "chat.npmx.dev" } + }, + "changelog": { + "error": {} } } diff --git a/i18n/locales/ta-IN.json b/i18n/locales/ta-IN.json index e8b657110c..17f6da22df 100644 --- a/i18n/locales/ta-IN.json +++ b/i18n/locales/ta-IN.json @@ -172,12 +172,9 @@ "replacement": { "title": "เฎ‡เฎจเฏเฎค เฎšเฎพเฎฐเฏเฎชเฏ เฎ‰เฎ™เฏเฎ•เฎณเฏเฎ•เฏเฎ•เฏเฎคเฏ เฎคเฏ‡เฎตเฏˆเฎชเฏเฎชเฎŸเฎพเฎฎเฎฒเฏ เฎ‡เฎฐเฏเฎ•เฏเฎ•เฎฒเฎพเฎฎเฏ.", "native": "เฎ‡เฎคเฏˆ {replacement} เฎฎเฏ‚เฎฒเฎฎเฏ เฎฎเฎพเฎฑเฏเฎฑเฎฒเฎพเฎฎเฏ, Node {nodeVersion} เฎฎเฏเฎคเฎฒเฏ เฎ•เฎฟเฎŸเฏˆเฎ•เฏเฎ•เฎฟเฎฑเฎคเฏ.", - "simple": "{community} เฎ‡เฎจเฏเฎค เฎคเฏŠเฎ•เฏเฎชเฏเฎชเฏˆ เฎ…เฎคเฎฟเฎ•เฎชเฏเฎชเฎŸเฎฟเฎฏเฎพเฎฉเฎคเฏ เฎŽเฎฉเฏเฎฑเฏ เฎ•เฏŠเฎŸเฎฟเฎฏเฎฟเฎŸเฏเฎŸเฏเฎณเฏเฎณเฎคเฏ, เฎ…เฎฑเฎฟเฎตเฏเฎฐเฏˆ: {replacement}.", - "documented": "{community} เฎ‡เฎจเฏเฎค เฎคเฏŠเฎ•เฏเฎชเฏเฎชเฏเฎ•เฏเฎ•เฏ เฎฎเฏ‡เฎฒเฏเฎฎเฏ เฎšเฏ†เฎฏเฎฒเฏเฎคเฎฟเฎฑเฎฉเฏ เฎฎเฎฟเฎ•เฏเฎ• เฎฎเฎพเฎฑเฏเฎฑเฏเฎ•เฎณเฏ เฎ‰เฎณเฏเฎณเฎฉ เฎŽเฎฉเฏเฎฑเฏ เฎ•เฏŠเฎŸเฎฟเฎฏเฎฟเฎŸเฏเฎŸเฏเฎณเฏเฎณเฎคเฏ.", "none": "เฎ‡เฎจเฏเฎค เฎคเฏŠเฎ•เฏเฎชเฏเฎชเฏ เฎ‡เฎฉเฎฟ เฎคเฏ‡เฎตเฏˆเฎฏเฎฟเฎฒเฏเฎฒเฏˆ เฎŽเฎฉเฏเฎฑเฏ เฎ•เฏŠเฎŸเฎฟเฎฏเฎฟเฎŸเฎชเฏเฎชเฎŸเฏเฎŸเฏเฎณเฏเฎณเฎคเฏ, เฎ…เฎคเฎฉเฏ เฎšเฏ†เฎฏเฎฒเฏเฎชเฎพเฎŸเฏ เฎ…เฎฉเฏˆเฎคเฏเฎคเฏ เฎ‡เฎฏเฎจเฏเฎคเฎฟเฎฐเฎ™เฏเฎ•เฎณเฎฟเฎฒเฏเฎฎเฏ เฎจเฏ‡เฎฐเฎŸเฎฟเฎฏเฎพเฎ•เฎ•เฏ เฎ•เฎฟเฎŸเฏˆเฎ•เฏเฎ•เฎฟเฎฑเฎคเฏ.", "learn_more": "เฎฎเฏ‡เฎฒเฏเฎฎเฏ เฎ…เฎฑเฎฟเฎ•", "learn_more_above": "เฎฎเฏ‡เฎฒเฏ‡ เฎฎเฏ‡เฎฒเฏเฎฎเฏ เฎ…เฎฑเฎฟเฎ•.", - "community": "เฎšเฎฎเฏ‚เฎ•เฎฎเฏ", "consider_no_dep": "+ เฎšเฎพเฎฐเฏเฎชเฏ เฎตเฏ‡เฎฃเฏเฎŸเฎพเฎฎเฎพ?" }, "stats": { diff --git a/i18n/locales/te-IN.json b/i18n/locales/te-IN.json index 7e92347d2e..9f6e5a8622 100644 --- a/i18n/locales/te-IN.json +++ b/i18n/locales/te-IN.json @@ -140,11 +140,8 @@ "replacement": { "title": "เฐฎเฑ€เฐ•เฑ เฐˆ เฐกเฐฟเฐชเฑ†เฐ‚เฐกเฑ†เฐจเฑเฐธเฑ€ เฐ…เฐตเฐธเฐฐเฐ‚ เฐฒเฑ‡เฐ•เฐชเฑ‹เฐตเฐšเฑเฐšเฑ.", "native": "เฐฆเฑ€เฐจเฐฟเฐจเฐฟ {replacement} เฐคเฑ‹ เฐญเฐฐเฑเฐคเฑ€ เฐšเฑ‡เฐฏเฐตเฐšเฑเฐšเฑ, เฐ‡เฐฆเฐฟ Node {nodeVersion} เฐจเฑเฐ‚เฐกเฐฟ เฐ…เฐ‚เฐฆเฑเฐฌเฐพเฐŸเฑเฐฒเฑ‹ เฐ‰เฐ‚เฐฆเฐฟ.", - "simple": "{community} เฐˆ เฐชเฑเฐฏเฐพเฐ•เฑ‡เฐœเฑโ€Œเฐจเฑ เฐจเฐฟเฐฐเฑเฐชเฐฏเฑ‹เฐ—เฐ‚เฐ—เฐพ เฐซเฑเฐฒเฐพเฐ—เฑ เฐšเฑ‡เฐธเฐฟเฐ‚เฐฆเฐฟ, เฐธเฐฒเฐนเฐพเฐคเฑ‹: {replacement}.", - "documented": "{community} เฐˆ เฐชเฑเฐฏเฐพเฐ•เฑ‡เฐœเฑโ€Œเฐจเฑ เฐฎเฐฐเฐฟเฐ‚เฐค เฐชเฐจเฐฟเฐคเฑ€เฐฐเฑ เฐŽเฐ‚เฐชเฐฟเฐ•เฐฒเฑเฐ—เฐพ เฐซเฑเฐฒเฐพเฐ—เฑ เฐšเฑ‡เฐธเฐฟเฐ‚เฐฆเฐฟ.", "none": "เฐˆ เฐชเฑเฐฏเฐพเฐ•เฑ‡เฐœเฑ เฐ‡เฐชเฑเฐชเฑเฐกเฑ เฐ…เฐตเฐธเฐฐเฐ‚ เฐฒเฑ‡เฐจเฐฟเฐฆเฐฟเฐ—เฐพ เฐซเฑเฐฒเฐพเฐ—เฑ เฐšเฑ‡เฐฏเฐฌเฐกเฐฟเฐ‚เฐฆเฐฟ, เฐฎเฐฐเฐฟเฐฏเฑ เฐฆเฑ€เฐจเฐฟ เฐ•เฐพเฐฐเฑเฐฏเฐพเฐšเฐฐเฐฃ เฐ…เฐจเฑเฐจเฐฟ เฐ‡เฐ‚เฐœเฐฟเฐจเฑโ€Œเฐฒเฐฒเฑ‹ เฐจเฑ‡เฐŸเฐฟเฐตเฑโ€Œเฐ—เฐพ เฐ…เฐ‚เฐฆเฑเฐฌเฐพเฐŸเฑเฐฒเฑ‹ เฐ‰เฐ‚เฐกเฑ‡ เฐ…เฐตเฐ•เฐพเฐถเฐ‚ เฐ‰เฐ‚เฐฆเฐฟ.", - "learn_more": "เฐฎเฐฐเฐฟเฐจเฑเฐจเฐฟ เฐคเฑ†เฐฒเฑเฐธเฑเฐ•เฑ‹เฐ‚เฐกเฐฟ", - "community": "เฐ•เฐฎเฑเฐฏเฑ‚เฐจเฐฟเฐŸเฑ€" + "learn_more": "เฐฎเฐฐเฐฟเฐจเฑเฐจเฐฟ เฐคเฑ†เฐฒเฑเฐธเฑเฐ•เฑ‹เฐ‚เฐกเฐฟ" }, "stats": { "license": "เฐฒเฑˆเฐธเฑ†เฐจเฑเฐธเฑ", diff --git a/i18n/locales/tr-TR.json b/i18n/locales/tr-TR.json index 6189f3d8ce..911af52729 100644 --- a/i18n/locales/tr-TR.json +++ b/i18n/locales/tr-TR.json @@ -400,12 +400,9 @@ "example": "ร–rnek:", "native": "Bu, Node {nodeVersion}'dan beri mevcut olan {replacement} ile deฤŸiลŸtirilebilir.", "native_no_version": "Bu paket {replacement} ile deฤŸiลŸtirilebilir.", - "simple": "{community} bu paketi artฤฑk gereksiz olarak iลŸaretledi, รถnerisi: {replacement}.", - "documented": "{community} bu paketin daha performanslฤฑ alternatiflerinin olduฤŸunu belirtti.", "none": "Bu paket artฤฑk gereksiz olarak iลŸaretlendi ve iลŸlevselliฤŸi tรผm motorlarda yerel olarak mevcuttur.", "learn_more": "Daha fazla bilgi", "learn_more_above": "Yukarฤฑda daha fazla bilgi edinin.", - "community": "topluluk", "consider_no_dep": "+ BaฤŸฤฑmlฤฑlฤฑksฤฑz dรผลŸรผnรผn?" }, "stats": { @@ -550,7 +547,6 @@ "view_all": "{count} sรผrรผmรผ gรถster | Tรผm {count} sรผrรผmรผ gรถster", "view_all_versions": "Tรผm sรผrรผmleri gรถrรผntรผle", "distribution_title": "Semver Grubu", - "distribution_modal_title": "Sรผrรผmler", "distribution_range_date_same_year": "{from}'den {to}'ya, {endYear}", "distribution_range_date_multiple_years": "{from}, {startYear}'den {to}, {endYear}'e", "grouping_major": "Major", @@ -1421,8 +1417,6 @@ "file_changes": "Dosya deฤŸiลŸiklikleri", "files_count": "{count} dosya", "lines_hidden": "{count} satฤฑr gizlendi", - "file_too_large": "Dosya รงok bรผyรผk", - "file_size_warning": "Dosya boyutu {size}", "compare_versions": "fark", "compare_versions_title": "Sรผrรผmleri karลŸฤฑlaลŸtฤฑr", "comparing_versions_label": "Sรผrรผmler karลŸฤฑlaลŸtฤฑrฤฑlฤฑyor...", diff --git a/i18n/locales/uk-UA.json b/i18n/locales/uk-UA.json index 4b7a443e46..af398342f5 100644 --- a/i18n/locales/uk-UA.json +++ b/i18n/locales/uk-UA.json @@ -397,12 +397,9 @@ "example": "ะŸั€ะธะบะปะฐะด:", "native": "ะฆะต ะผะพะถะฝะฐ ะทะฐะผั–ะฝะธั‚ะธ ะฝะฐ {replacement}, ะดะพัั‚ัƒะฟะฝะต ะท Node {nodeVersion}.", "native_no_version": "ะฆะตะน ะฟะฐะบะตั‚ ะผะพะถะฝะฐ ะทะฐะผั–ะฝะธั‚ะธ ะฝะฐ {replacement}.", - "simple": "{community} ะฟะพะทะฝะฐั‡ะธะปะฐ ั†ะตะน ะฟะฐะบะตั‚ ัะบ ะฝะฐะดะปะธัˆะบะพะฒะธะน ั–ะท ั€ะตะบะพะผะตะฝะดะฐั†ั–ั”ัŽ: {replacement}.", - "documented": "{community} ะฟะพะทะฝะฐั‡ะธะปะฐ ั†ะตะน ะฟะฐะบะตั‚ ัะบ ั‚ะฐะบะธะน, ั‰ะพ ะผะฐั” ะตั„ะตะบั‚ะธะฒะฝั–ัˆั– ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะธ.", "none": "ะฆะตะน ะฟะฐะบะตั‚ ะฑัƒะปะพ ะฟะพะทะฝะฐั‡ะตะฝะพ ัะบ ะฑั–ะปัŒัˆะต ะฝะต ะฝะตะพะฑั…ั–ะดะฝะธะน, ั– ะนะพะณะพ ั„ัƒะฝะบั†ั–ะพะฝะฐะปัŒะฝั–ัั‚ัŒ, ะนะผะพะฒั–ั€ะฝะพ, ะดะพัั‚ัƒะฟะฝะฐ ะฒ ัƒัั–ั… ัะธัั‚ะตะผะฐั….", "learn_more": "ะ”ั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต", "learn_more_above": "ะ”ั–ะทะฝะฐั‚ะธัั ะฑั–ะปัŒัˆะต ะฒะธั‰ะต.", - "community": "ัะฟั–ะปัŒะฝะพั‚ะฐ", "consider_no_dep": "+ ะ ะพะทะณะปัะฝัƒั‚ะธ ะฒะฐั€ั–ะฐะฝั‚ ะฑะตะท ะทะฐะปะตะถะฝะพัั‚ั–?" }, "stats": { @@ -546,7 +543,6 @@ "view_all": "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ {count} ะฒะตั€ัั–ัŽ | ะŸะตั€ะตะณะปัะฝัƒั‚ะธ {count} ะฒะตั€ัั–ั— | ะŸะตั€ะตะณะปัะฝัƒั‚ะธ {count} ะฒะตั€ัั–ะน", "view_all_versions": "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ ะฒัั– ะฒะตั€ัั–ั—", "distribution_title": "ะ“ั€ัƒะฟะฐ Semver", - "distribution_modal_title": "ะ’ะตั€ัั–ั—", "distribution_range_date_same_year": "ะฒั–ะด {from} ะดะพ {to}, {endYear}", "distribution_range_date_multiple_years": "ะฒั–ะด {from}, {startYear} ะดะพ {to}, {endYear}", "grouping_major": "ะžัะฝะพะฒะฝะฐ", @@ -998,14 +994,14 @@ "files_label": "ะคะฐะนะปะธ", "no_files": "ะะตะผะฐั” ั„ะฐะนะปั–ะฒ ัƒ ั†ั–ะน ะฟะฐะฟั†ั–", "lines": "{count} ั€ัะดะพะบ | {count} ั€ัะดะบะธ | {count} ั€ัะดะบั–ะฒ", - "copy_content": "ะšะพะฟั–ัŽะฒะฐั‚ะธ ะฒะผั–ัั‚ ั„ะฐะนะปัƒ", - "toggle_container": "ะŸะตั€ะตะผะบะฝัƒั‚ะธ ัˆะธั€ะธะฝัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะบะพะดัƒ", - "open_raw_file": "ะ’ั–ะดะบั€ะธั‚ะธ raw-ั„ะฐะนะป", - "open_path_dropdown": "ะ’ั–ะดะบั€ะธั‚ะธ ะผะตะฝัŽ ัะตะณะผะตะฝั‚ั–ะฒ ัˆะปัั…ัƒ", "toggle_tree": "ะŸะตั€ะตะผะบะฝัƒั‚ะธ ะดะตั€ะตะฒะพ ั„ะฐะนะปั–ะฒ", "close_tree": "ะ—ะฐะบั€ะธั‚ะธ ะดะตั€ะตะฒะพ ั„ะฐะนะปั–ะฒ", + "copy_content": "ะšะพะฟั–ัŽะฒะฐั‚ะธ ะฒะผั–ัั‚ ั„ะฐะนะปัƒ", "copy_link": "ะšะพะฟั–ัŽะฒะฐั‚ะธ ะฟะพัะธะปะฐะฝะฝั", "view_raw": "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ raw-ั„ะฐะนะป", + "toggle_container": "ะŸะตั€ะตะผะบะฝัƒั‚ะธ ัˆะธั€ะธะฝัƒ ะบะพะฝั‚ะตะนะฝะตั€ะฐ ะบะพะดัƒ", + "open_raw_file": "ะ’ั–ะดะบั€ะธั‚ะธ raw-ั„ะฐะนะป", + "open_path_dropdown": "ะ’ั–ะดะบั€ะธั‚ะธ ะผะตะฝัŽ ัะตะณะผะตะฝั‚ั–ะฒ ัˆะปัั…ัƒ", "file_too_large": "ะคะฐะนะป ะทะฐะฒะตะปะธะบะธะน ะดะปั ะฟะพะฟะตั€ะตะดะฝัŒะพะณะพ ะฟะตั€ะตะณะปัะดัƒ", "file_size_warning": "{size} ะฟะตั€ะตะฒะธั‰ัƒั” ะปั–ะผั–ั‚ 500KB ะดะปั ะฒะธะดั–ะปะตะฝะฝั ัะธะฝั‚ะฐะบัะธััƒ", "failed_to_load": "ะะต ะฒะดะฐะปะพัั ะทะฐะฒะฐะฝั‚ะฐะถะธั‚ะธ ั„ะฐะนะป", @@ -1295,15 +1291,6 @@ "packages_selected": "ะ’ะธะฑั€ะฐะฝะพ {count}/{max} ะฟะฐะบะตั‚ั–ะฒ.", "add_hint": "ะ”ะพะดะฐะนั‚ะต ั‰ะพะฝะฐะนะผะตะฝัˆะต 2 ะฟะฐะบะตั‚ะธ ะดะปั ะฟะพั€ั–ะฒะฝัะฝะฝั." }, - "no_dependency": { - "label": "(ะ‘ะตะท ะทะฐะปะตะถะฝะพัั‚ั–)", - "typeahead_title": "ะฉะพ ะฑ ะทั€ะพะฑะธะฒ ะ”ะถะตะนะผั?", - "typeahead_description": "ะŸะพั€ั–ะฒะฝัะนั‚ะต ะท ะฒั–ะดััƒั‚ะฝั–ัั‚ัŽ ะทะฐะปะตะถะฝะพัั‚ั–! ะกั…ะฒะฐะปะตะฝะพ e18e.", - "tooltip_title": "ะœะพะถะปะธะฒะพ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะฐ ั†ั ะทะฐะปะตะถะฝั–ัั‚ัŒ", - "tooltip_description": "ะŸะพั€ั–ะฒะฝัะนั‚ะต ะท ะฒั–ะดััƒั‚ะฝั–ัั‚ัŽ ะทะฐะปะตะถะฝะพัั‚ั–! {link} ะฟั–ะดั‚ั€ะธะผัƒั” ัะฟะธัะพะบ ะฟะฐะบะตั‚ั–ะฒ, ัะบั– ะผะพะถะฝะฐ ะทะฐะผั–ะฝะธั‚ะธ ะฝะฐั‚ะธะฒะฝะธะผะธ API ะฐะฑะพ ะฟั€ะพัั‚ั–ัˆะธะผะธ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฐะผะธ.", - "e18e_community": "ะกะฟั–ะปัŒะฝะพั‚ะฐ e18e", - "add_column": "ะ”ะพะดะฐั‚ะธ ะบะพะปะพะฝะบัƒ ะฑะตะท ะทะฐะปะตะถะฝะพัั‚ั– ะดะพ ะฟะพั€ั–ะฒะฝัะฝะฝั" - }, "scatter_chart": { "title": "ะŸะพั€ั–ะฒะฝัั‚ะธ {x} ั– {y}", "freshness_score": "ะžั†ั–ะฝะบะฐ ัะฒั–ะถะพัั‚ั–", @@ -1315,6 +1302,15 @@ "x_axis": "ะ’ะ†ะกะฌ X โ†ฆ", "y_axis": "ะ’ะ†ะกะฌ Y โ†ฅ" }, + "no_dependency": { + "label": "(ะ‘ะตะท ะทะฐะปะตะถะฝะพัั‚ั–)", + "typeahead_title": "ะฉะพ ะฑ ะทั€ะพะฑะธะฒ ะ”ะถะตะนะผั?", + "typeahead_description": "ะŸะพั€ั–ะฒะฝัะนั‚ะต ะท ะฒั–ะดััƒั‚ะฝั–ัั‚ัŽ ะทะฐะปะตะถะฝะพัั‚ั–! ะกั…ะฒะฐะปะตะฝะพ e18e.", + "tooltip_title": "ะœะพะถะปะธะฒะพ, ะฒะฐะผ ะฝะต ะฟะพั‚ั€ั–ะฑะฝะฐ ั†ั ะทะฐะปะตะถะฝั–ัั‚ัŒ", + "tooltip_description": "ะŸะพั€ั–ะฒะฝัะนั‚ะต ะท ะฒั–ะดััƒั‚ะฝั–ัั‚ัŽ ะทะฐะปะตะถะฝะพัั‚ั–! {link} ะฟั–ะดั‚ั€ะธะผัƒั” ัะฟะธัะพะบ ะฟะฐะบะตั‚ั–ะฒ, ัะบั– ะผะพะถะฝะฐ ะทะฐะผั–ะฝะธั‚ะธ ะฝะฐั‚ะธะฒะฝะธะผะธ API ะฐะฑะพ ะฟั€ะพัั‚ั–ัˆะธะผะธ ะฐะปัŒั‚ะตั€ะฝะฐั‚ะธะฒะฐะผะธ.", + "e18e_community": "ะกะฟั–ะปัŒะฝะพั‚ะฐ e18e", + "add_column": "ะ”ะพะดะฐั‚ะธ ะบะพะปะพะฝะบัƒ ะฑะตะท ะทะฐะปะตะถะฝะพัั‚ั– ะดะพ ะฟะพั€ั–ะฒะฝัะฝะฝั" + }, "facets": { "all": "ะฒัั–", "none": "ะถะพะดะฝะพะณะพ", @@ -1416,8 +1412,6 @@ "file_changes": "ะ—ะผั–ะฝะธ ั„ะฐะนะปั–ะฒ", "files_count": "{count} ั„ะฐะนะป | {count} ั„ะฐะนะปะธ | {count} ั„ะฐะนะปั–ะฒ", "lines_hidden": "{count} ั€ัะดะพะบ ะฟั€ะธั…ะพะฒะฐะฝะพ | {count} ั€ัะดะบะธ ะฟั€ะธั…ะพะฒะฐะฝะพ | {count} ั€ัะดะบั–ะฒ ะฟั€ะธั…ะพะฒะฐะฝะพ", - "file_too_large": "ะคะฐะนะป ะทะฐะฒะตะปะธะบะธะน ะดะปั ะฟะพั€ั–ะฒะฝัะฝะฝั", - "file_size_warning": "{size} ะฟะตั€ะตะฒะธั‰ัƒั” ะปั–ะผั–ั‚ 250 ะšะ‘ ะดะปั ะฟะพั€ั–ะฒะฝัะฝะฝั", "compare_versions": "ะทะผั–ะฝะธ", "compare_versions_title": "ะŸะพั€ั–ะฒะฝัั‚ะธ ะท ะพัั‚ะฐะฝะฝัŒะพัŽ ะฒะตั€ัั–ั”ัŽ", "comparing_versions_label": "ะŸะพั€ั–ะฒะฝัะฝะฝั ะฒะตั€ัั–ะน...", @@ -1673,7 +1667,6 @@ "copied": "ะกะบะพะฟั–ะนะพะฒะฐะฝะพ!", "browse_brand": "ะŸะตั€ะตะณะปัะฝัƒั‚ะธ ะฑั€ะตะฝะดะฑัƒะบ" }, - "alt_logo_kawaii": "ะœะธะปะฐ, ะพะบั€ัƒะณะปะฐ ะน ะฑะฐั€ะฒะธัั‚ะฐ ะฒะตั€ัั–ั ะปะพะณะพั‚ะธะฟัƒ npmx.", "brand": { "title": "ะ‘ั€ะตะฝะด", "heading": "ะฑั€ะตะฝะด", @@ -1718,5 +1711,9 @@ "message": "ะ”ะพัั‚ัƒะฟะฝั–ัั‚ัŒ ะฒะฐะถะปะธะฒะฐ ะดะปั ะฝะฐั ั– ะผะธ ั…ะพั‚ั–ะปะธ ะฑ, ั‰ะพะฑ ะฒะธ ะฟะพะดั–ะปัะปะธ ั†ัŽ ะฟะพะทะธั†ั–ัŽ. ะ’ะธะบะพั€ะธัั‚ะพะฒัƒัŽั‡ะธ ะทะฐะทะฝะฐั‡ะตะฝั– ะผะฐั‚ะตั€ั–ะฐะปะธ, ะฟะตั€ะตะบะพะฝะฐะนั‚ะตัั, ั‰ะพ ั” ะดะพัั‚ะฐั‚ะฝั–ะน ะบะพะฝั‚ั€ะฐัั‚ ั–ะท ั„ะพะฝะพะผ, ั– ะฝะต ะทะผะตะฝัˆัƒะนั‚ะต ั€ะพะทะผั–ั€ ะผะตะฝัˆะต 24px. ะฏะบั‰ะพ ะฒะฐะผ ะฟะพั‚ั€ั–ะฑะฝั– ั–ะฝัˆั– ั€ะตััƒั€ัะธ ะฐะฑะพ ะดะพะดะฐั‚ะบะพะฒะฐ ั–ะฝั„ะพั€ะผะฐั†ั–ั ะฟั€ะพ ะฟั€ะพั”ะบั‚, ะทะฒ'ัะถั–ั‚ัŒัั ะท ะฝะฐะผะธ ะทะฐ ะฟะพัะธะปะฐะฝะฝัะผ {link}.", "discord_link_text": "chat.npmx.dev" } + }, + "alt_logo_kawaii": "ะœะธะปะฐ, ะพะบั€ัƒะณะปะฐ ะน ะฑะฐั€ะฒะธัั‚ะฐ ะฒะตั€ัั–ั ะปะพะณะพั‚ะธะฟัƒ npmx.", + "changelog": { + "error": {} } } diff --git a/i18n/locales/vi-VN.json b/i18n/locales/vi-VN.json index 4594ee1b87..1301de2d17 100644 --- a/i18n/locales/vi-VN.json +++ b/i18n/locales/vi-VN.json @@ -76,6 +76,23 @@ "instant_search_turn_off": "tแบฏt", "instant_search_advisory": "{label} {state} โ€” {action}" }, + "command_palette": { + "state": {}, + "groups": {}, + "actions": {}, + "connections": {}, + "navigation": {}, + "links": {}, + "package_links": {}, + "theme": {}, + "package": {}, + "package_actions": {}, + "code": {}, + "diff": {}, + "version": {}, + "status": {}, + "announcements": {} + }, "nav": { "main_navigation": "Trang chรญnh", "popular_packages": "Package phแป• biแบฟn", @@ -265,15 +282,13 @@ "size": "Kรญch thฦฐแป›c cร i ฤ‘แบทt tฤƒng {percent} (lแป›n hฦกn {size})", "deps": "Thรชm {count} dependency" }, + "size_decrease": {}, "replacement": { "title": "Bแบกn cรณ thแปƒ khรดng cแบงn dependency nร y.", "native": "Cรณ thแปƒ thay thแบฟ bแบฑng {replacement}, cรณ sแบตn tแปซ Node {nodeVersion}.", - "simple": "{community} ฤ‘รฃ ฤ‘รกnh dแบฅu gรณi nร y lร  dฦฐ thแปซa, vแป›i gแปฃi รฝ: {replacement}.", - "documented": "{community} ฤ‘รฃ ฤ‘รกnh dแบฅu gรณi nร y cรณ cรกc lแปฑa chแปn thay thแบฟ hiแป‡u nฤƒng tแป‘t hฦกn.", "none": "Gรณi nร y ฤ‘รฃ ฤ‘ฦฐแปฃc ฤ‘รกnh dแบฅu lร  khรดng cรฒn cแบงn thiแบฟt, chแปฉc nฤƒng cแปงa nรณ cรณ thแปƒ ฤ‘รฃ cรณ sแบตn sแบตn trong cรกc engine.", "learn_more": "Tรฌm hiแปƒu thรชm", "learn_more_above": "Tรฌm hiแปƒu thรชm แปŸ trรชn.", - "community": "cแป™ng ฤ‘แป“ng", "consider_no_dep": "+ Cรขn nhแบฏc khรดng dรนng dep?" }, "stats": { @@ -412,7 +427,6 @@ "view_all": "Xem {count} phiรชn bแบฃn | Xem tแบฅt cแบฃ {count} phiรชn bแบฃn", "view_all_versions": "Xem tแบฅt cแบฃ phiรชn bแบฃn", "distribution_title": "Nhรณm Semver", - "distribution_modal_title": "Phiรชn bแบฃn", "distribution_range_date_same_year": "tแปซ {from} ฤ‘แบฟn {to}, {endYear}", "distribution_range_date_multiple_years": "tแปซ {from}, {startYear} ฤ‘แบฟn {to}, {endYear}", "grouping_major": "Major", @@ -442,6 +456,11 @@ "current_tags": "Thแบป hiแป‡n tแบกi", "no_match_filter": "Khรดng cรณ phiรชn bแบฃn khแป›p {filter}" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "Dependency ({count}) | Dependency ({count})", "list_label": "Dependency cแปงa gรณi", @@ -641,6 +660,9 @@ "tarball": "Tแบฃi tarball dแบกng .tar.gz" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "Local Connector", @@ -1112,6 +1134,9 @@ "packages_selected": "ฤรฃ chแปn {count}/{max} package.", "add_hint": "Thรชm รญt nhแบฅt 2 package ฤ‘แปƒ so sรกnh." }, + "scatter_chart": { + "copy_alt": {} + }, "no_dependency": { "label": "(Khรดng dependency)", "typeahead_title": "Vฤƒn sแบฝ lร m gรฌ?", @@ -1190,7 +1215,10 @@ "vulnerabilities": { "label": "Lแป— hแป•ng", "description": "Cรกc lแป— hแป•ng bแบฃo mแบญt phแป• biแบฟn" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "Bแบฅt kแปณ", @@ -1210,8 +1238,6 @@ "file_changes": "Thay ฤ‘แป•i tแป‡p", "files_count": "{count} tแป‡p | {count} tแป‡p", "lines_hidden": "{count} dรฒng แบฉn | {count} dรฒng แบฉn", - "file_too_large": "Tแป‡p quรก lแป›n ฤ‘แปƒ so sรกnh", - "file_size_warning": "{size} vฦฐแปฃt quรก giแป›i hแบกn 250KB ฤ‘แปƒ so sรกnh", "compare_versions": "diff", "compare_versions_title": "So sรกnh vแป›i phiรชn bแบฃn mแป›i nhแบฅt", "comparing_versions_label": "ฤang so sรกnh cรกc phiรชn bแบฃn...", @@ -1511,5 +1537,8 @@ "message": "Trแปฃ nฤƒng lร  vแบฅn ฤ‘แป rแบฅt quan trแปng ฤ‘แป‘i vแป›i chรบng tรดi vร  chรบng tรดi rแบฅt mong bแบกn cรนng chia sแบป tแบงm nhรฌn nร y. Khi sแปญ dแปฅng cรกc phฦฐฦกng tiแป‡n truyแปn thรดng ฤ‘รฃ ฤ‘แป cแบญp, hรฃy ฤ‘แบฃm bแบฃo cรณ ฤ‘แปง ฤ‘แป™ tฦฐฦกng phแบฃn vแป›i nแปn vร  khรดng ฤ‘แปƒ kรญch thฦฐแป›c nhแป hฦกn 24px. Nแบฟu bแบกn cแบงn bแบฅt kแปณ tร i nguyรชn nร o khรกc hoแบทc thรดng tin bแป• sung vแป dแปฑ รกn, vui lรฒng liรชn hแป‡ vแป›i chรบng tรดi tแบกi {link}.", "discord_link_text": "chat.npmx.dev" } + }, + "changelog": { + "error": {} } } diff --git a/i18n/locales/zh-CN.json b/i18n/locales/zh-CN.json index e8f028d69f..99d9019d6a 100644 --- a/i18n/locales/zh-CN.json +++ b/i18n/locales/zh-CN.json @@ -397,12 +397,9 @@ "example": "็คบไพ‹๏ผš", "native": "่ฏฅๅŠŸ่ƒฝ่‡ช Node.js {nodeVersion} ่ตทๅทฒ่ขซๅ†…็ฝฎ๏ผŒๅฏ็›ดๆŽฅไฝฟ็”จ {replacement} ๆ›ฟไปฃใ€‚", "native_no_version": "ๆญคๅŒ…ๅฏ็›ดๆŽฅไฝฟ็”จ {replacement} ๆ›ฟไปฃใ€‚", - "simple": "็คพๅŒบๆ ‡่ฎฐๆญคๅŒ…ไธบๅ†—ไฝ™๏ผŒๅปบ่ฎฎๆ›ฟๆขไธบ๏ผš{replacement}ใ€‚", - "documented": "็คพๅŒบๆ ‡่ฎฐๆญคๅŒ…ๅญ˜ๅœจๆ€ง่ƒฝๆ›ดไผ˜็š„ๆ›ฟไปฃๆ–นๆกˆ", "none": "ๆญคๅŒ…ๅทฒ่ขซๆ ‡่ฎฐไธบไธๅ†้œ€่ฆ๏ผŒๅ…ถๅŠŸ่ƒฝๅพˆๅฏ่ƒฝๅทฒ็”ฑๆ‰€ๆœ‰ๅผ•ๆ“ŽๅŽŸ็”Ÿๆไพ›ใ€‚", "learn_more": "ไบ†่งฃๆ›ดๅคš", "learn_more_above": "ๅœจไธŠๆ–นไบ†่งฃๆ›ดๅคšใ€‚", - "community": "็คพๅŒบ", "consider_no_dep": "+ ไธไฝฟ็”จไพ่ต–?" }, "stats": { @@ -546,7 +543,6 @@ "view_all": "ๆŸฅ็œ‹ๅ…จ้ƒจ {count} ไธช็‰ˆๆœฌ", "view_all_versions": "ๆŸฅ็œ‹ๆ‰€ๆœ‰็‰ˆๆœฌ", "distribution_title": "่ฏญไน‰ๅŒ–็‰ˆๆœฌๅˆ†็ป„", - "distribution_modal_title": "็‰ˆๆœฌ", "distribution_range_date_same_year": "{endYear}ๅนด {from} ่‡ณ {to}", "distribution_range_date_multiple_years": "{startYear}ๅนด {from} ่‡ณ {endYear}ๅนด {to}", "grouping_major": "ไธป็‰ˆๆœฌ", @@ -1417,8 +1413,6 @@ "file_changes": "ๆ–‡ไปถๆ›ดๆ”น", "files_count": "{count} ไธชๆ–‡ไปถ", "lines_hidden": "ๅทฒ้š่— {count} ่กŒ", - "file_too_large": "ๆ–‡ไปถ่ฟ‡ๅคง๏ผŒๆ— ๆณ•ๅฏนๆฏ”", - "file_size_warning": "{size} ่ถ…ๅ‡บไบ† 250KB ็š„ๅฏนๆฏ”้™ๅˆถ", "compare_versions": "ๅทฎๅผ‚", "compare_versions_title": "ไธŽๆœ€ๆ–ฐ็‰ˆๆœฌๅฏนๆฏ”", "comparing_versions_label": "ๆฏ”่พƒ็‰ˆๆœฌ...", @@ -1719,5 +1713,8 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "ไธ€ไธชๅœ†ๆถฆๅฏ็ˆฑใ€่‰ฒๅฝฉๆดปๆณผ็š„ npmx logo ็‰ˆๆœฌใ€‚" + "alt_logo_kawaii": "ไธ€ไธชๅœ†ๆถฆๅฏ็ˆฑใ€่‰ฒๅฝฉๆดปๆณผ็š„ npmx logo ็‰ˆๆœฌใ€‚", + "changelog": { + "error": {} + } } diff --git a/i18n/locales/zh-TW.json b/i18n/locales/zh-TW.json index 069716b94d..e2b15eefb7 100644 --- a/i18n/locales/zh-TW.json +++ b/i18n/locales/zh-TW.json @@ -378,15 +378,13 @@ "size": "ๅฎ‰่ฃๅคงๅฐๅขžๅŠ ไบ† {percent}๏ผˆๅคšๅ‡บ {size}๏ผ‰", "deps": "ๅขžๅŠ ไบ† {count} ๅ€‹็›ธไพๅฅ—ไปถ" }, + "size_decrease": {}, "replacement": { "title": "ไฝ ๅฏ่ƒฝไธ้œ€่ฆ้€™ๅ€‹็›ธไพๅฅ—ไปถใ€‚", "native": "ๆญคๅŠŸ่ƒฝ่‡ช Node.js {nodeVersion} ่ตทๅทฒๅ…งๅปบ๏ผŒๅฏ็›ดๆŽฅไฝฟ็”จ {replacement} ๅ–ไปฃใ€‚", - "simple": "็คพ็พคๆจ™่จ˜ๆญคๅฅ—ไปถ็‚บๅ†—้ค˜๏ผŒๅปบ่ญฐๆ”น็”จ๏ผš{replacement}ใ€‚", - "documented": "็คพ็พคๆจ™่จ˜ๆญคๅฅ—ไปถๆœ‰ๆ›ด้ซ˜ๆ•ˆ่ƒฝ็š„ๆ›ฟไปฃๆ–นๆกˆ", "none": "ๆญคๅฅ—ไปถๅทฒ่ขซๆจ™่จ˜็‚บไธๅ†้œ€่ฆ๏ผŒๅ…ถๅŠŸ่ƒฝๅพˆๅฏ่ƒฝๅทฒ็”ฑๆ‰€ๆœ‰ๅผ•ๆ“ŽๅŽŸ็”Ÿๆไพ›ใ€‚", "learn_more": "ไบ†่งฃๆ›ดๅคš", "learn_more_above": "ๅƒ้–ฑไธŠๆ–น่ชชๆ˜Ž", - "community": "็คพ็พค", "consider_no_dep": "+ ่€ƒๆ…ฎไธไฝฟ็”จ็›ธไพๅฅ—ไปถ๏ผŸ" }, "stats": { @@ -525,7 +523,6 @@ "view_all": "ๆชข่ฆ–ๅ…จ้ƒจ {count} ๅ€‹็‰ˆๆœฌ", "view_all_versions": "ๆชข่ฆ–ๅ…จ้ƒจ็‰ˆๆœฌ", "distribution_title": "่ชž็พฉๅŒ–็‰ˆๆœฌ็พค็ต„", - "distribution_modal_title": "็‰ˆๆœฌ", "distribution_range_date_same_year": "ๅพž {from} ่‡ณ {to}, {endYear}", "distribution_range_date_multiple_years": "ๅพž {from}, {startYear} ่‡ณ {to}, {endYear}", "grouping_major": "ไธป", @@ -555,6 +552,11 @@ "current_tags": "็•ถๅ‰ๆจ™็ฑค", "no_match_filter": "ๆฒ’ๆœ‰็‰ˆๆœฌ็ฌฆๅˆ {filter}" }, + "timeline": { + "chart": { + "copy_alt": {} + } + }, "dependencies": { "title": "็›ธไพ๏ผˆ{count} ๅ€‹๏ผ‰", "list_label": "ๅฅ—ไปถ็›ธไพ", @@ -758,6 +760,9 @@ "tarball": "ไธ‹่ผ‰ Tarball๏ผˆ.tar.gz๏ผ‰" } }, + "leaderboard": { + "likes": {} + }, "connector": { "modal": { "title": "ๆœฌๆฉŸ้€ฃ็ทšๅ™จ", @@ -1323,7 +1328,10 @@ "vulnerabilities": { "label": "ๆผๆดž", "description": "ๅทฒ็Ÿฅๅฎ‰ๅ…จๆผๆดž" - } + }, + "githubStars": {}, + "githubIssues": {}, + "createdAt": {} }, "values": { "any": "ไธ้™", @@ -1343,8 +1351,6 @@ "file_changes": "ๆช”ๆกˆ่ฎŠๆ›ด", "files_count": "{count} ๅ€‹ๆช”ๆกˆ", "lines_hidden": "ๅทฒ้šฑ่— {count} ่กŒ", - "file_too_large": "ๆช”ๆกˆๅคงๅฐ้Žๅคง๏ผŒ็„กๆณ•ๆฏ”่ผƒ", - "file_size_warning": "ๆช”ๆกˆๅคงๅฐ {size} ่ถ…้Ž 250KB๏ผŒ็„กๆณ•ๆฏ”่ผƒ", "compare_versions": "ๅทฎ็•ฐ", "compare_versions_title": "ๆฏ”่ผƒๆœ€ๆ–ฐ็‰ˆๆœฌ", "comparing_versions_label": "ๆญฃๅœจๆฏ”่ผƒ็‰ˆๆœฌโ€ฆ", @@ -1645,5 +1651,8 @@ "discord_link_text": "chat.npmx.dev" } }, - "alt_logo_kawaii": "ไธ€ๅ€‹ๅฏๆ„›ใ€ๅœ“ๆฝคไธ”่‰ฒๅฝฉ็นฝ็ด›็š„ npmx ๆจ™่ชŒ็‰ˆๆœฌใ€‚" + "alt_logo_kawaii": "ไธ€ๅ€‹ๅฏๆ„›ใ€ๅœ“ๆฝคไธ”่‰ฒๅฝฉ็นฝ็ด›็š„ npmx ๆจ™่ชŒ็‰ˆๆœฌใ€‚", + "changelog": { + "error": {} + } } diff --git a/i18n/schema.json b/i18n/schema.json index 8ab3e4a2da..1fe63c4793 100644 --- a/i18n/schema.json +++ b/i18n/schema.json @@ -43,6 +43,9 @@ "about": { "type": "string" }, + "sponsors": { + "type": "string" + }, "blog": { "type": "string" }, @@ -75,6 +78,9 @@ }, "other": { "type": "string" + }, + "sponsored_by": { + "type": "string" } }, "additionalProperties": false @@ -144,6 +150,9 @@ }, "open_timeline": { "type": "string" + }, + "open_stats": { + "type": "string" } }, "additionalProperties": false @@ -298,6 +307,21 @@ "connected": { "type": "string" }, + "keyboard_shortcuts": { + "type": "object", + "properties": { + "navigate": { + "type": "string" + }, + "select": { + "type": "string" + }, + "close": { + "type": "string" + } + }, + "additionalProperties": false + }, "state": { "type": "object", "properties": { @@ -468,6 +492,9 @@ }, "changelog": { "type": "string" + }, + "stats": { + "type": "string" } }, "additionalProperties": false @@ -691,6 +718,81 @@ }, "additionalProperties": false }, + "noodles": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "meta_description": { + "type": "string" + }, + "latest": { + "type": "string" + }, + "what_is": { + "type": "string" + }, + "what_is_body": { + "type": "string" + }, + "empty": { + "type": "string" + }, + "load_more": { + "type": "string" + }, + "dates": { + "type": "string" + }, + "shipped_in": { + "type": "string" + }, + "credits": { + "type": "string" + }, + "learn_more": { + "type": "string" + }, + "carousel_prev": { + "type": "string" + }, + "carousel_next": { + "type": "string" + }, + "carousel_dots": { + "type": "string" + }, + "carousel_jump": { + "type": "string" + }, + "lens_label": { + "type": "string" + }, + "lens_slide": { + "type": "string" + }, + "lens_slide_position": { + "type": "string" + }, + "back_to_archive": { + "type": "string" + }, + "missing": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "body": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, "settings": { "type": "object", "properties": { @@ -1219,9 +1321,6 @@ "learn_more_above": { "type": "string" }, - "community": { - "type": "string" - }, "consider_no_dep": { "type": "string" } @@ -1266,6 +1365,15 @@ } }, "additionalProperties": false + }, + "main_information": { + "type": "string" + }, + "trends": { + "type": "string" + }, + "version_distribution": { + "type": "string" } }, "additionalProperties": false @@ -1357,6 +1465,9 @@ "timeline": { "type": "string" }, + "stats": { + "type": "string" + }, "compare_this_package": { "type": "string" }, @@ -1657,9 +1768,6 @@ "distribution_title": { "type": "string" }, - "distribution_modal_title": { - "type": "string" - }, "distribution_range_date_same_year": { "type": "string" }, @@ -2145,6 +2253,24 @@ } }, "additionalProperties": false + }, + "embedding": { + "type": "object", + "properties": { + "chart": { + "type": "string" + }, + "copy_url": { + "type": "string" + }, + "preview": { + "type": "string" + }, + "tip": { + "type": "string" + } + }, + "additionalProperties": false } }, "additionalProperties": false @@ -3543,6 +3669,12 @@ "properties": { "title": { "type": "string" + }, + "gold": { + "type": "string" + }, + "silver": { + "type": "string" } }, "additionalProperties": false @@ -3679,6 +3811,180 @@ }, "additionalProperties": false }, + "sponsors_page": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "heading": { + "type": "string" + }, + "meta_description": { + "type": "string" + }, + "intro": { + "type": "string" + }, + "what_we_do": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, + "what_support_means": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, + "cta": { + "type": "string" + }, + "community_growth_footnote": { + "type": "string" + }, + "what_this_means_for_you": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "cards": { + "type": "object", + "properties": { + "people": { + "type": "object", + "properties": { + "contributors": { + "type": "string" + }, + "community_members": { + "type": "string" + } + }, + "additionalProperties": false + }, + "visitors": { + "type": "object", + "properties": { + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, + "stars": { + "type": "object", + "properties": { + "title": { + "type": "string" + } + }, + "additionalProperties": false + }, + "community": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, + "adoption": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, + "default_source": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, + "tiers": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "per_month": { + "type": "string" + }, + "custom": { + "type": "string" + }, + "silver": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + }, + "gold": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + }, + "platinum": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + }, "account_menu": { "type": "object", "properties": { @@ -4201,6 +4507,18 @@ }, "additionalProperties": false }, + "githubForks": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false + }, "githubIssues": { "type": "object", "properties": { @@ -4282,12 +4600,6 @@ "lines_hidden": { "type": "string" }, - "file_too_large": { - "type": "string" - }, - "file_size_warning": { - "type": "string" - }, "compare_versions": { "type": "string" }, @@ -4408,6 +4720,15 @@ "diff_distance": { "type": "string" }, + "diff_truncated": { + "type": "string" + }, + "large_diff_mode": { + "type": "string" + }, + "large_diff_options_disabled": { + "type": "string" + }, "loading_diff": { "type": "string" }, diff --git a/knip.ts b/knip.ts index eff59ca6fc..e282259290 100644 --- a/knip.ts +++ b/knip.ts @@ -44,8 +44,6 @@ const config: KnipConfig = { ignoreFiles: [ 'app/components/Tooltip/Announce.vue', 'app/components/UserCombobox.vue', - 'app/components/ColorScheme/Img.vue', - 'app/components/Noodle/Nodejs/Logo.vue', '**/*.unused.*', ], }, diff --git a/modules/lunaria.ts b/modules/lunaria.ts index a7a58369a7..0ba5f39313 100644 --- a/modules/lunaria.ts +++ b/modules/lunaria.ts @@ -31,6 +31,7 @@ export default defineNuxtModule({ try { execSync('node --experimental-transform-types ./lunaria/lunaria.ts', { cwd: nuxt.options.rootDir, + stdio: 'inherit', }) } catch (e) { // Always throw in local dev. @@ -38,6 +39,8 @@ export default defineNuxtModule({ const { env } = await getEnv(!isCI) if (env === 'dev' || env === 'release') { throw e + } else { + console.error(e) } } }) diff --git a/modules/runtime/server/cache.ts b/modules/runtime/server/cache.ts index b00279266f..d5efaa8d53 100644 --- a/modules/runtime/server/cache.ts +++ b/modules/runtime/server/cache.ts @@ -1,5 +1,6 @@ import process from 'node:process' import type { CachedFetchResult } from '#shared/utils/fetch-cache-config' +import { parsePackageSpec } from '#shared/utils/parse-package-param' import { createFetch } from 'ofetch' /** @@ -65,42 +66,6 @@ function getFixturePath(type: FixtureType, name: string): string { return `${dir}:${filename.replace(/\//g, ':')}` } -/** - * Parse a scoped package name with optional version. - * Handles formats like: @scope/name, @scope/name@version, name, name@version - */ -function parseScopedPackageWithVersion(input: string): { name: string; version?: string } { - if (input.startsWith('@')) { - // Scoped package: @scope/name or @scope/name@version - const slashIndex = input.indexOf('/') - if (slashIndex === -1) { - // Invalid format like just "@scope" - return { name: input } - } - const afterSlash = input.slice(slashIndex + 1) - const atIndex = afterSlash.indexOf('@') - if (atIndex === -1) { - // @scope/name (no version) - return { name: input } - } - // @scope/name@version - return { - name: input.slice(0, slashIndex + 1 + atIndex), - version: afterSlash.slice(atIndex + 1), - } - } - - // Unscoped package: name or name@version - const atIndex = input.indexOf('@') - if (atIndex === -1) { - return { name: input } - } - return { - name: input.slice(0, atIndex), - version: input.slice(atIndex + 1), - } -} - function getMockForUrl(url: string): MockResult | null { const urlObj = URL.parse(url) if (!urlObj) return null @@ -563,7 +528,7 @@ async function handleJsdelivrDataApi( const packageMatch = decodeURIComponent(urlObj.pathname).match(/^\/v1\/packages\/npm\/(.+)$/) if (!packageMatch?.[1]) return null - const parsed = parseScopedPackageWithVersion(packageMatch[1]) + const parsed = parsePackageSpec(packageMatch[1]) // Try per-package fixture first const fixturePath = getFixturePath('jsdelivr', parsed.name) diff --git a/modules/security-headers.ts b/modules/security-headers.ts index b3d9584475..25b6b2a63d 100644 --- a/modules/security-headers.ts +++ b/modules/security-headers.ts @@ -50,6 +50,8 @@ export default defineNuxtModule({ 'https://registry.npmjs.org', 'https://api.npmjs.org', 'https://npm.antfu.dev', + 'https://video.bsky.app', + 'https://video.cdn.bsky.app', BLUESKY_API, ...ALL_KNOWN_GIT_API_ORIGINS, // Local CLI connector (npmx CLI communicates via localhost) @@ -76,7 +78,7 @@ export default defineNuxtModule({ `script-src 'self' 'unsafe-inline'`, `style-src 'self' 'unsafe-inline'`, `img-src ${imgSrc}`, - `media-src 'self'`, + `media-src 'self' blob:`, `font-src 'self'`, `connect-src ${connectSrc}`, `frame-src ${frameSrc}`, diff --git a/nuxt.config.ts b/nuxt.config.ts index eccbdb4e8e..401dfd006e 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -142,6 +142,26 @@ export default defineNuxtConfig({ '/.well-known/jwks.json': { prerender: true }, '/.well-known/site.standard.publication': { prerender: true }, '/api/leaderboard/likes': { isr: 900 }, + '/api/embed/downloads.svg': { + isr: { + expiration: 60 * 60 /* one hour */, + passQuery: true, + allowQuery: [ + 'packages', + 'package', + 'metric', + 'startDate', + 'start', + 'endDate', + 'end', + 'mode', + 'granularity', + 'locale', + 'accent', + 'yLabel', + ], + }, + }, // never cache '/api/auth/**': { isr: false, cache: false }, '/api/social/**': { isr: false, cache: false }, @@ -170,7 +190,11 @@ export default defineNuxtConfig({ }, // pages '/leaderboard/likes': getISRConfig(900), - '/package/**': getISRConfig(300, { fallback: 'html' }), + '/package/**': getISRConfig(300, { + fallback: 'html', + passQuery: true, + allowQuery: ['activeTab'], + }), '/package/:name/_payload.json': getISRConfig(300, { fallback: 'json' }), '/package/:name/v/:version/_payload.json': getISRConfig(300, { fallback: 'json' }), '/package/:org/:name/_payload.json': getISRConfig(300, { fallback: 'json' }), @@ -195,6 +219,8 @@ export default defineNuxtConfig({ '/recharging': { prerender: true }, '/pds': { isr: 86400 }, // revalidate daily '/blog/**': { prerender: true }, + '/noodles/**': { prerender: true }, + '/sponsors': { prerender: true }, // proxy for insights '/_v/script.js': { proxy: 'https://npmx.dev/_vercel/insights/script.js', @@ -273,6 +299,9 @@ export default defineNuxtConfig({ providers: { fontshare: false, }, + experimental: { + disableLocalFallbacks: true, + }, families: [ { name: 'Geist', @@ -385,6 +414,9 @@ export default defineNuxtConfig({ }, vite: { + css: { + transformer: 'lightningcss', + }, optimizeDeps: { include: [ '@vueuse/core', @@ -422,8 +454,14 @@ export default defineNuxtConfig({ interface ISRConfigOptions { fallback?: 'html' | 'json' + allowQuery?: string[] + passQuery?: boolean } function getISRConfig(expirationSeconds: number, options: ISRConfigOptions = {}) { + const extraISR = { + ...(options.passQuery ? { passQuery: true } : {}), + ...(options.allowQuery ? { allowQuery: options.allowQuery } : {}), + } if (options.fallback) { return { isr: { @@ -431,12 +469,14 @@ function getISRConfig(expirationSeconds: number, options: ISRConfigOptions = {}) fallback: options.fallback === 'html' ? 'spa.prerender-fallback.html' : 'payload-fallback.json', initialHeaders: options.fallback === 'json' ? { 'content-type': 'application/json' } : {}, + ...extraISR, } as { expiration: number }, } } return { isr: { expiration: expirationSeconds, + ...extraISR, }, } } diff --git a/package.json b/package.json index 21e41ec52c..68bc410270 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@atproto/lex-password-session": "0.0.12", "@atproto/oauth-client-node": "^0.3.15", "@deno/doc": "jsr:^0.189.1", - "@floating-ui/vue": "1.1.11", + "@floating-ui/vue": "2.0.0", "@iconify-json/lucide": "1.2.101", "@iconify-json/simple-icons": "1.2.76", "@iconify-json/svg-spinners": "1.2.4", @@ -88,11 +88,12 @@ "fast-npm-meta": "1.4.2", "focus-trap": "^8.0.0", "gray-matter": "4.0.3", + "hls.js": "1.6.16", "ipaddr.js": "2.3.0", "marked": "18.0.0", "module-replacements": "3.0.0-beta.8", - "nuxt": "4.4.5", - "nuxt-og-image": "^6.4.3", + "nuxt": "4.4.8", + "nuxt-og-image": "^6.6.0", "ofetch": "1.5.1", "ohash": "2.0.11", "packumeta": "0.4.1", @@ -110,12 +111,12 @@ "virtua": "0.49.0", "vite-plugin-pwa": "1.3.0", "vite-plus": "0.1.20", - "vue": "3.5.34", - "vue-data-ui": "3.20.11", + "vue": "3.5.39", + "vue-data-ui": "3.22.0", "vue-router": "5.0.4" }, "devDependencies": { - "@e18e/eslint-plugin": "0.4.1", + "@e18e/eslint-plugin": "0.5.1", "@intlify/core-base": "11.3.0", "@npm/types": "2.1.0", "@playwright/test": "1.60.0", @@ -131,9 +132,9 @@ "@vue/test-utils": "2.4.6", "axe-core": "4.11.2", "changelogen": "0.6.2", - "chromatic": "16.1.0", + "chromatic": "17.5.0", "devalue": "5.6.4", - "eslint-plugin-regexp": "3.1.0", + "eslint-plugin-regexp": "3.1.1", "fast-check": "4.6.0", "h3": "1.15.11", "h3-next": "npm:h3@2.0.1-rc.16", @@ -145,7 +146,7 @@ "storybook": "catalog:storybook", "storybook-i18n": "catalog:storybook", "typescript": "6.0.2", - "unplugin-vue-markdown": "30.0.0", + "unplugin-vue-markdown": "32.0.0", "vitest": "npm:@voidzero-dev/vite-plus-test@0.1.20", "vue-i18n-extract": "2.0.7", "vue-tsc": "3.2.6" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1d666694a6..06bdd8375a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,7 +35,7 @@ catalogs: overrides: '@types/node': 24.12.0 - nuxt-og-image: ^6.4.3 + nuxt-og-image: ^6.6.0 sharp: 0.34.5 vite: npm:@voidzero-dev/vite-plus-core@0.1.20 vitest: npm:@voidzero-dev/vite-plus-test@0.1.20 @@ -73,8 +73,8 @@ importers: specifier: jsr:^0.189.1 version: '@jsr/deno__doc@0.189.1(patch_hash=24f326e123c822a07976329a5afe91a8713e82d53134b5586625b72431c87832)' '@floating-ui/vue': - specifier: 1.1.11 - version: 1.1.11(vue@3.5.34) + specifier: 2.0.0 + version: 2.0.0(vue@3.5.39) '@iconify-json/lucide': specifier: 1.2.101 version: 1.2.101 @@ -98,25 +98,25 @@ importers: version: 1.0.0 '@nuxt/a11y': specifier: 1.0.0-alpha.1 - version: 1.0.0-alpha.1(magicast@0.5.2)(vite@8.0.0) + version: 1.0.0-alpha.1(magicast@0.5.3)(vite@8.0.0) '@nuxt/fonts': specifier: 0.14.0 - version: 0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(vite@8.0.0) + version: 0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(vite@8.0.0) '@nuxt/scripts': specifier: 1.0.1 - version: 1.0.1(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(typescript@6.0.2)(vite@8.0.0)(vue@3.5.34) + version: 1.0.1(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(typescript@6.0.2)(vite@8.0.0)(vue@3.5.39) '@nuxt/test-utils': specifier: 4.0.3 - version: 4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.2)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) + version: 4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) '@nuxtjs/color-mode': specifier: 4.0.0 - version: 4.0.0(magicast@0.5.2) + version: 4.0.0(magicast@0.5.3) '@nuxtjs/html-validator': specifier: 2.1.0 - version: 2.1.0(@voidzero-dev/vite-plus-test@0.1.20)(magicast@0.5.2) + version: 2.1.0(@voidzero-dev/vite-plus-test@0.1.20)(magicast@0.5.3) '@nuxtjs/i18n': specifier: 10.2.4 - version: 10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.34) + version: 10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.39) '@shikijs/langs': specifier: 4.0.2 version: 4.0.2 @@ -134,7 +134,7 @@ importers: version: 1.0.9(react-dom@19.2.4)(react@19.2.4) '@unocss/nuxt': specifier: 66.6.7 - version: 66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(magicast@0.5.2)(vite@8.0.0)(webpack@5.104.1) + version: 66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(magicast@0.5.3)(vite@8.0.0)(webpack@5.104.1) '@unocss/preset-wind4': specifier: 66.6.7 version: 66.6.7 @@ -143,28 +143,28 @@ importers: version: 1.37.0 '@vercel/speed-insights': specifier: 2.0.0 - version: 2.0.0(nuxt@4.4.5)(react@19.2.4)(vue-router@5.0.4)(vue@3.5.34) + version: 2.0.0(nuxt@4.4.8)(react@19.2.4)(vue-router@5.0.4)(vue@3.5.39) '@vite-pwa/assets-generator': specifier: 1.0.2 version: 1.0.2 '@vite-pwa/nuxt': specifier: 1.1.1 - version: 1.1.1(@vite-pwa/assets-generator@1.0.2)(magicast@0.5.2)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0) + version: 1.1.1(@vite-pwa/assets-generator@1.0.2)(magicast@0.5.3)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0) '@vueuse/core': specifier: 14.3.0 - version: 14.3.0(vue@3.5.34) + version: 14.3.0(vue@3.5.39) '@vueuse/integrations': specifier: 14.2.1 - version: 14.2.1(focus-trap@8.0.0)(fuse.js@7.3.0)(vue@3.5.34) + version: 14.2.1(focus-trap@8.0.0)(fuse.js@7.4.2)(vue@3.5.39) '@vueuse/nuxt': specifier: 14.2.1 - version: 14.2.1(magicast@0.5.2)(nuxt@4.4.5)(vue@3.5.34) + version: 14.2.1(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39) '@vueuse/router': specifier: ^14.2.1 - version: 14.2.1(vue-router@5.0.4)(vue@3.5.34) + version: 14.2.1(vue-router@5.0.4)(vue@3.5.39) '@vueuse/shared': specifier: 14.2.1 - version: 14.2.1(vue@3.5.34) + version: 14.2.1(vue@3.5.39) algoliasearch: specifier: 5.50.1 version: 5.50.1 @@ -183,6 +183,9 @@ importers: gray-matter: specifier: 4.0.3 version: 4.0.3 + hls.js: + specifier: 1.6.16 + version: 1.6.16 ipaddr.js: specifier: 2.3.0 version: 2.3.0 @@ -193,11 +196,11 @@ importers: specifier: 3.0.0-beta.8 version: 3.0.0-beta.8 nuxt: - specifier: 4.4.5 - version: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + specifier: 4.4.8 + version: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) nuxt-og-image: - specifier: ^6.4.3 - version: 6.4.3(@nuxt/schema@4.4.5)(@takumi-rs/core@1.0.9)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.13)(fontless@0.2.1)(nuxt@4.4.5)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.3.0)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + specifier: ^6.6.0 + version: 6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@1.0.9)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.3.0)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) ofetch: specifier: 1.5.1 version: 1.5.1 @@ -242,7 +245,7 @@ importers: version: 8.0.0 virtua: specifier: 0.49.0 - version: 0.49.0(react-dom@19.2.4)(react@19.2.4)(vue@3.5.34) + version: 0.49.0(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39) vite-plugin-pwa: specifier: 1.3.0 version: 1.3.0(@vite-pwa/assets-generator@1.0.2)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0) @@ -250,18 +253,18 @@ importers: specifier: 0.1.20 version: 0.1.20(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(@vitest/coverage-v8@4.1.6)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(yaml@2.9.0) vue: - specifier: 3.5.34 - version: 3.5.34(typescript@6.0.2) + specifier: 3.5.39 + version: 3.5.39(typescript@6.0.2) vue-data-ui: - specifier: 3.20.11 - version: 3.20.11(vue@3.5.34) + specifier: 3.22.0 + version: 3.22.0(vue@3.5.39) vue-router: specifier: 5.0.4 - version: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + version: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) devDependencies: '@e18e/eslint-plugin': - specifier: 0.4.1 - version: 0.4.1(eslint@9.39.2)(oxlint@1.61.0) + specifier: 0.5.1 + version: 0.5.1(eslint@9.39.2) '@intlify/core-base': specifier: 11.3.0 version: 11.3.0 @@ -273,7 +276,7 @@ importers: version: 1.60.0 '@storybook-vue/nuxt': specifier: catalog:storybook - version: https://pkg.pr.new/@storybook-vue/nuxt@1021(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.34)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.2)(nuxt@4.4.5)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(storybook@10.3.5)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(vue@3.5.34)(webpack@5.104.1)(yaml@2.9.0) + version: https://pkg.pr.new/@storybook-vue/nuxt@1021(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.39)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(storybook@10.3.5)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(vue@3.5.39)(webpack@5.104.1)(yaml@2.9.0) '@storybook/addon-a11y': specifier: catalog:storybook version: 10.3.5(storybook@10.3.5) @@ -306,16 +309,16 @@ importers: version: 4.11.2 changelogen: specifier: 0.6.2 - version: 0.6.2(magicast@0.5.2) + version: 0.6.2(magicast@0.5.3) chromatic: - specifier: 16.1.0 - version: 16.1.0 + specifier: 17.5.0 + version: 17.5.0 devalue: specifier: 5.6.4 version: 5.6.4 eslint-plugin-regexp: - specifier: 3.1.0 - version: 3.1.0(eslint@9.39.2) + specifier: 3.1.1 + version: 3.1.1(eslint@9.39.2) fast-check: specifier: 4.6.0 version: 4.6.0 @@ -350,8 +353,8 @@ importers: specifier: 6.0.2 version: 6.0.2 unplugin-vue-markdown: - specifier: 30.0.0 - version: 30.0.0(vite@8.0.0) + specifier: 32.0.0 + version: 32.0.0(vite@8.0.0) vitest: specifier: npm:@voidzero-dev/vite-plus-test@0.1.20 version: '@voidzero-dev/vite-plus-test@0.1.20(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(@vitest/coverage-v8@4.1.6)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(yaml@2.9.0)' @@ -366,7 +369,7 @@ importers: dependencies: '@clack/prompts': specifier: ^1.0.1 - version: 1.2.0 + version: 1.6.0 '@lydell/node-pty': specifier: 1.2.0-beta.12 version: 1.2.0-beta.12 @@ -381,7 +384,7 @@ importers: version: 2.1.1 srvx: specifier: ^0.11.7 - version: 0.11.15 + version: 0.11.17 valibot: specifier: ^1.2.0 version: 1.3.1(typescript@6.0.2) @@ -406,19 +409,19 @@ importers: dependencies: '@nuxt/ui': specifier: 4.6.1 - version: 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.2)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29)(zod@4.3.6) + version: 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) '@nuxtjs/mdc': specifier: 0.21.1 - version: 0.21.1(magicast@0.5.2) + version: 0.21.1(magicast@0.5.3) better-sqlite3: specifier: 12.8.0 version: 12.8.0 docus: specifier: 5.9.0 - version: 5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29) + version: 5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29) nuxt: - specifier: 4.4.5 - version: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + specifier: 4.4.8 + version: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) tailwindcss: specifier: 4.2.2 version: 4.2.2 @@ -815,16 +818,16 @@ packages: resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@8.0.0-rc.6': resolution: {integrity: sha512-BCkFy+zN6kXQed3YOT7aJl93NfDSzQc3pBfsvTVPs9gU9X3V0aefEF5kwBT0E+mDWH9QgKaZstYUQN9VdQZT4g==} engines: {node: ^22.18.0 || >=24.11.0} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@8.0.0-rc.3': @@ -843,8 +846,8 @@ packages: resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.3': - resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} engines: {node: '>=6.0.0'} hasBin: true @@ -1254,8 +1257,8 @@ packages: resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} '@babel/types@8.0.0-rc.3': @@ -1266,8 +1269,8 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@bomb.sh/tab@0.0.14': - resolution: {integrity: sha512-cHMk2LI430MVoX1unTt9oK1iZzQS4CYDz97MSxKLNErW69T43Z2QLFTpdS/3jVOIKrIADWfuxQ+nQNJkNV7E4w==} + '@bomb.sh/tab@0.0.16': + resolution: {integrity: sha512-xFtIH6JYVdXgkSft97gsQyJODZbjGXw+l+wkT06lBiBPuaF0CFYNulQNsgnYud7rURI7D4lyLmOQeAzRkvl1Fg==} hasBin: true peerDependencies: cac: ^6.7.14 @@ -1291,9 +1294,17 @@ packages: '@clack/core@1.2.0': resolution: {integrity: sha512-qfxof/3T3t9DPU/Rj3OmcFyZInceqj/NVtO9rwIuJqCUgh32gwPjpFQQp/ben07qKlhpwq7GzfWpST4qdJ5Drg==} + '@clack/core@1.4.2': + resolution: {integrity: sha512-0Ty/1Gfm+Kb07sXcuESjyKfwEhSy4Ns1AgeEisHb/bDY5fWme0tTeTkU14T1Gmcs17YIjB/teiDe4uaCghbYqQ==} + engines: {node: '>= 20.12.0'} + '@clack/prompts@1.2.0': resolution: {integrity: sha512-4jmztR9fMqPMjz6H/UZXj0zEmE43ha1euENwkckKKel4XpSfokExPo5AiVStdHSAlHekz4d0CA/r45Ok1E4D3w==} + '@clack/prompts@1.6.0': + resolution: {integrity: sha512-EYlRokl8szrP9Z25qT5aepMdBjzBvHF9ZEhzIiUBc9guz/T31EqRgvD0QSgZcpE93xiwrr+OkB4nz0BZyF6fSA==} + engines: {node: '>= 20.12.0'} + '@cloudflare/kv-asset-handler@0.4.2': resolution: {integrity: sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==} engines: {node: '>=18.0.0'} @@ -1312,11 +1323,11 @@ packages: '@dxup/unimport@0.1.2': resolution: {integrity: sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==} - '@e18e/eslint-plugin@0.4.1': - resolution: {integrity: sha512-Re00N8ad1HsNrzpuIX7Bhdr8RSaFWp6VgwJUEJF+47+D1CMcXoS7VNRkIG23e46pddhgxWU0cWk4wYiQIuMHqQ==} + '@e18e/eslint-plugin@0.5.1': + resolution: {integrity: sha512-mqUozeyNI9xvJbjrOO7y765dT7Kud3bwCm/DHwctxdEngPdJWQaS9BNGgpM1wCCzZfOtlKQh4ZRhm3VRomT9KA==} peerDependencies: eslint: ^9.0.0 || ^10.0.0 - oxlint: ^1.61.0 + oxlint: ^1.68.0 peerDependenciesMeta: eslint: optional: true @@ -1862,6 +1873,11 @@ packages: '@floating-ui/vue@1.1.11': resolution: {integrity: sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw==} + '@floating-ui/vue@2.0.0': + resolution: {integrity: sha512-I7hYpCAkgBrtXdZbfCpGaqAV+E09fENSHBIm81z6WhSgcl1ctkb3+1gW9h8PVDus0Em2FwGRR41epgxILS6YhQ==} + peerDependencies: + vue: '>=3.3.0' + '@hono/node-server@1.19.9': resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==} engines: {node: '>=18.14.1'} @@ -2269,7 +2285,7 @@ packages: resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} '@lunariajs/core@https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935': - resolution: {integrity: sha512-N0PDFIitA/Vzh5V6BtTacWU9jgSDJJtPLHamRLMU85mohmyuVW/pggHX8dzdV5ieqZeHEz8pDZSzH4I0hOYxOg==, tarball: https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935} + resolution: {tarball: https://pkg.pr.new/lunariajs/lunaria/@lunariajs/core@904b935} version: 0.1.1 engines: {node: '>=18.17.0'} @@ -2456,12 +2472,12 @@ packages: '@nuxt/a11y@1.0.0-alpha.1': resolution: {integrity: sha512-TwON9I0uI4erv9IJ6cD4nx9QcaxfXnAg7CwcQyjMKfDHCfI3xitezg4CZhQOHl0FGqHYGRf9Y9kSwh6fahCJrQ==} - '@nuxt/cli@3.35.1': - resolution: {integrity: sha512-nX9XO+e3l9pnhHL2zsbnBmQb/nsOQYhGz2XiqE8X962QN9ufc1ZSuDZoTmQVv/ymkbYNR6hpNWW8RZQhuhzadw==} + '@nuxt/cli@3.36.0': + resolution: {integrity: sha512-qkrADSow9WLG/26bhqkVljKd6lMO0z7FXqLINNwnehBOBclra3xz8jVK1kTDPegZehwNdc7QUSsj2Bgv9/Fw/A==} engines: {node: ^16.14.0 || >=18.0.0} hasBin: true peerDependencies: - '@nuxt/schema': ^4.4.2 + '@nuxt/schema': ^4.4.6 peerDependenciesMeta: '@nuxt/schema': optional: true @@ -2536,29 +2552,28 @@ packages: resolution: {integrity: sha512-Bd6m6mrDrqpBEbX+g0rc66/ALd1sxlgdx5nfK9MAYO0yKLTOSK7McSYz1KcOYn3LQFCXOWfvXwaqih/b+REI1g==} engines: {node: '>=18.12.0'} - '@nuxt/kit@4.4.5': - resolution: {integrity: sha512-J0BpoOomzd3iVZozYlZJ7AwAVliXRgeChZnAkQLfg8d0h/Q+aMK9kkHuhwFULASaRn5idiD4BIhOUz7/uoLbSw==} - engines: {node: '>=18.12.0'} - - '@nuxt/kit@4.4.6': - resolution: {integrity: sha512-AzsqBJeG7b3whIciyzkz4nBossEotM314KzKAptc8kH07ORBIR8Qh3QYKepo2YZwtxiDP2Y9aqzAztwpSEDHtw==} + '@nuxt/kit@4.4.8': + resolution: {integrity: sha512-ZUlZ5iYfyfJFDPluhn6ZxFWcsuxWbLnZBc8w3MAROcQ4lYfZ+qFpALBLSNlpc0zhOa++33EE+5PEbOAdVIY+dw==} engines: {node: '>=18.12.0'} - '@nuxt/nitro-server@4.4.5': - resolution: {integrity: sha512-ZxmfxZbQ6Yr/DYkuGmPFtE/A1hDbbcOurlPeh/H4oHfAkv/N6W7OWg/3PGViKwckmF69jUMe/a89HAguaH+r5A==} - engines: {node: ^20.19.0 || >=22.12.0} + '@nuxt/nitro-server@4.4.8': + resolution: {integrity: sha512-cc1fxgSx34Htesx3JBO+hMhbqd6VljXDC06P+UOA5z53cR224TmEFYT/MUuZDkrtt4qLnSG8yq0IxhEM3NCUlw==} + engines: {node: ^22.12.0 || ^24.11.0 || >=26.0.0} peerDependencies: '@babel/plugin-proposal-decorators': ^7.25.0 + '@babel/plugin-syntax-typescript': ^7.25.0 '@rollup/plugin-babel': ^6.0.0 || ^7.0.0 - nuxt: ^4.4.5 + nuxt: ^4.4.8 peerDependenciesMeta: '@babel/plugin-proposal-decorators': optional: true + '@babel/plugin-syntax-typescript': + optional: true '@rollup/plugin-babel': optional: true - '@nuxt/schema@4.4.5': - resolution: {integrity: sha512-kPacVsBInUgM3JiFiHUGd5fr8Ohe+79PGrBwjipfGzA61UMPfj7CmPuKrvmL1i4oLS1I3/flHvU5VFVyQ/wyxQ==} + '@nuxt/schema@4.4.8': + resolution: {integrity: sha512-igfWuMF0x0Pmx/XwhPwH/bcXgbuwNnjUjqxCAsY6VQhmGKo0e9soJq3Q0ohj+rBkBfX6o2ysTP1/t2M82aK4qA==} engines: {node: ^14.18.0 || >=16.10.0} '@nuxt/scripts@1.0.1': @@ -2665,13 +2680,13 @@ packages: zod: optional: true - '@nuxt/vite-builder@4.4.5': - resolution: {integrity: sha512-PLb1a3yjSES6CEAKqCuT9qPqT7xLtf5VH3XeE3rZ0iBQ+ReVkglwouE+M/lRR61R7PjlvAszjOyjnKbOG1pOAg==} - engines: {node: ^20.19.0 || >=22.12.0} + '@nuxt/vite-builder@4.4.8': + resolution: {integrity: sha512-54M/k6qVY85Qeoe1m/lPZ0SANGJEbI50r5uYgh3XT942ENve3K5Nk6TMYp8i5wGGC4TWvPea+1mlCrp8rjsXag==} + engines: {node: ^22.12.0 || ^24.11.0 || >=26.0.0} peerDependencies: '@babel/plugin-proposal-decorators': ^7.25.0 '@babel/plugin-syntax-jsx': ^7.25.0 - nuxt: 4.4.5 + nuxt: 4.4.8 rolldown: ^1.0.0-beta.38 rollup-plugin-visualizer: ^6.0.0 || ^7.0.1 vue: ^3.3.4 @@ -2741,129 +2756,129 @@ packages: resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@oxc-minify/binding-android-arm-eabi@0.128.0': - resolution: {integrity: sha512-EwdDhZLRmXxSnfy0v9gdOru7TutM8ItRg1Xv8e2B4boWMnHlFCIH38JfwgQnenbkF8SVTwVJtDCkmwEzN4q3xA==} + '@oxc-minify/binding-android-arm-eabi@0.133.0': + resolution: {integrity: sha512-D8M1+nqwLaACHZsld/t6f+cE4N97XOu5iQ88f1ZaYH4ptFzFrXo5N7wUKACTI4xmNUD+6W0Y4Apk5U2r8HLdBQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-minify/binding-android-arm64@0.128.0': - resolution: {integrity: sha512-kwJ8YxWTzty8hD36jXxKiB+Po/ecmHZvT1xAYklkATbr0A4NUqV32sV+3Wfm8TecdA6jX34/mc+4CKK2+Hha2Q==} + '@oxc-minify/binding-android-arm64@0.133.0': + resolution: {integrity: sha512-dnQUJdpOEh/nZfQtvGGN61VcCCcPJ2aCm+ndl8GIA2lk2GpmIBgZ9h+phLVhgUFGt2es+2AQc0xvtK7RFNsViw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-minify/binding-darwin-arm64@0.128.0': - resolution: {integrity: sha512-WBV8j5EZ7/3rvFbiJ8LxowmobR/XH+l2iRzkE7zRYLD5VC+TvZayYGrVGGDXQvXm6cGED0B1NweByTmeT4lpGQ==} + '@oxc-minify/binding-darwin-arm64@0.133.0': + resolution: {integrity: sha512-K6+aXlOlsCcibpTiTitQYNXWGGwea0fEKF/kGHCNB+MNqOLCkdC7wesycaABYcXcyr58DhDoJnVb8E4Hq95iVw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-minify/binding-darwin-x64@0.128.0': - resolution: {integrity: sha512-U4k1CSBsY1uf6yHE+vCNJp0mHzjsUUXgOZXMyhRN3sE2ovBDT9Gl8oACmLWPjg0R68jwP+1vhnNPsSqpTEOycg==} + '@oxc-minify/binding-darwin-x64@0.133.0': + resolution: {integrity: sha512-BFEXHxYNwThyaO63p1VE5MOOXNGkHsHfkmajOCKXH40TfllTHQenXhpJ9mHDoF7EhaQjArpPjlDY88BuPjhurw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-minify/binding-freebsd-x64@0.128.0': - resolution: {integrity: sha512-NT1GtcWpX4sOuU5dMdSNpdXJRpk9BGAHHnKc42IUId8E+jEhZUrg9vqIRIlspZG5O9Y7FjO2r6GBK93bpyIIUg==} + '@oxc-minify/binding-freebsd-x64@0.133.0': + resolution: {integrity: sha512-oT5dbcXnS/cbpdXCpudAeVg/fqH1XnKhLUE/vkuRTuocjOd/GA2MoNMMhLWUvqNXO0xJnYmo2ISmDxShkItfOQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-minify/binding-linux-arm-gnueabihf@0.128.0': - resolution: {integrity: sha512-OskPMYMH2KtkqvRMULF2/+55hFo/qmRz2p/g7Cp7XNiqdjZ/DvQDiVbME63rVoX3dYjgS15DolGbo54mHTyA9w==} + '@oxc-minify/binding-linux-arm-gnueabihf@0.133.0': + resolution: {integrity: sha512-tJ3B+b7DOuTsIMXSmu5xHHCakrBqqcrp4COYd/lelOdDvkbFoDRGnwH91POUOSUEOI/WLzIMkDqAH2SZ3N2jhQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-minify/binding-linux-arm-musleabihf@0.128.0': - resolution: {integrity: sha512-fKUY7Y1vb8CYlGnS5FzqTeeM5zQz1Fleyaqz/T9iNHYAYNJ0Os9iT0rACLfAVCQKP9yOqPSwZ80xgZdVVGD61w==} + '@oxc-minify/binding-linux-arm-musleabihf@0.133.0': + resolution: {integrity: sha512-XMUHfdilk1KTtOM2vA1bwDso07/wkLm/GgDOO9z/ioxrZoQyjXnJRW665VXa08z2BqEgwHRc1zH9p7s6sKPQbg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-minify/binding-linux-arm64-gnu@0.128.0': - resolution: {integrity: sha512-T+CQQZ3BoWY/TxQk9LZsXZYj3madR/5tCErV6wzphTYZJfVjvKmQxnxMaT+TKE40Jha6+iGgwzxwcYWJfltULQ==} + '@oxc-minify/binding-linux-arm64-gnu@0.133.0': + resolution: {integrity: sha512-UEff2jopbwJ4SndmxK06uqXrOpwWiJERJPdgDTBywwXP9QgW0p1YkQnBNt4+jK0I/hdLpbbyaCLLuUPKbaU70w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-arm64-musl@0.128.0': - resolution: {integrity: sha512-F6RkJ90S1Xt25Mk7/wPUmddsE4RZ7Nei+HlEa2FAjfhpoaTciOwV6E/Gtp7wPIYbwft7UfhMYwuEuZiZQytVWw==} + '@oxc-minify/binding-linux-arm64-musl@0.133.0': + resolution: {integrity: sha512-yqskeIapQvx7Tu/OLsepLPcGsHGzfYy9PX6gIbhaOHfF+LA2zHBKnKb587FGx+lQjHLQR0llfmoSuXQ6q2EN+A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-minify/binding-linux-ppc64-gnu@0.128.0': - resolution: {integrity: sha512-0HP2FBGMlquLjShIIJvS4cebc6sdRRYL04GtxVpg96MtpejrkHYI2gQWcezsTUaGgg+eNRsuv2tdZPENu5+iWA==} + '@oxc-minify/binding-linux-ppc64-gnu@0.133.0': + resolution: {integrity: sha512-r7PnUNxRB9D/gQjCVeasoieJVUF48n43rvk/jYbGAw9sRfYGoEo/rOs0GyTZU9ttss8HzjBaerAbADbAL8K8vw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-riscv64-gnu@0.128.0': - resolution: {integrity: sha512-2j6Bd340IZqZbu4KUI28z87Ao9aHhq56HH1Qz5/+EdE732ajFYIoDF3z+QcxHXY0CFOG/Ur1ZOKTBEIWQ6BYIw==} + '@oxc-minify/binding-linux-riscv64-gnu@0.133.0': + resolution: {integrity: sha512-omXWC8I9lAMMjQIeadfItP5H4VDAiuU2BiVCtHMH3ktTbFq04sxscZhK4NFUUuw3fApDdXmfd7LW18q0JBHarg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-riscv64-musl@0.128.0': - resolution: {integrity: sha512-z5HSppdxNwB6//3Eo7mDWbTrLeyuTKvL/iLXaKEgocrJg1MhZLbRR7P5ore9gKvS4lF4EtEpA24xzilFxQK0iw==} + '@oxc-minify/binding-linux-riscv64-musl@0.133.0': + resolution: {integrity: sha512-LtFA3Hi8LVD/zuiPLKy9Aiz7N1IOj8rRhdXiW38GKQ9mAhj+Ko6IHGcTk2A7yNDA1DZBl7r+Qd4PEGWgVelPPw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-minify/binding-linux-s390x-gnu@0.128.0': - resolution: {integrity: sha512-9rxYqH7P8NiYqRlLxlnNjJSF8BYADOmihM5ZHVkmlE4tqjHkoLNevdAyAP2ZBkL8QJflm1WGOXFWmFnWA54EvA==} + '@oxc-minify/binding-linux-s390x-gnu@0.133.0': + resolution: {integrity: sha512-rFsPDsT1j3beSInbrFukAAlTg101PcqdVMXDioR9AgJ1180tZ8s8D+pNDpQTRmPd3956mnpAE+Cs77Xoo/QZAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-x64-gnu@0.128.0': - resolution: {integrity: sha512-sy5+4Oamw6Ly5gUNUIDQ7346Lryt7AhqjKhOtWl5dzYZnTIwwoI0V2DeIl3bR/vU8D629ZMYQOqhquRtSyBUOA==} + '@oxc-minify/binding-linux-x64-gnu@0.133.0': + resolution: {integrity: sha512-xlrtAmDWZI8BEmsaXMYfblWuLIY5UnnRkit1VLkmVDb5ceZRZf4oEXK1QeYf5Z33dT0WK1Ek++P+TL/ZMCpyGQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-minify/binding-linux-x64-musl@0.128.0': - resolution: {integrity: sha512-59Cxvjppy09TsaB15gr6rA9Bf87rm9t0bD1EW9dCZsdxWElnAC+TvWZ7v9dFUIeYeZUkhAAMPtpdqa3Y9CI2zA==} + '@oxc-minify/binding-linux-x64-musl@0.133.0': + resolution: {integrity: sha512-kd36CDkTkZDMNfVceNTSfpWnitE1+GjZmzJCeq8yaxsgvs/MXg8aauI2RgFjElYZIHSMyZku4pQ7Jtl3ZEYI6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxc-minify/binding-openharmony-arm64@0.128.0': - resolution: {integrity: sha512-XGa03zmiYpD7Kf1aXy6vjgkjfaCR90qH0TzGplnUXo6FF6gNe6sH9Zgneo9kxOyYt8CKKzXYD4VudT/nDTXq8Q==} + '@oxc-minify/binding-openharmony-arm64@0.133.0': + resolution: {integrity: sha512-pI38dJBqfkNbFoL/GEarAzGDjKGVCZTdg0a8NKh1PP9GqWleXT6HLtXE4CZ+54e+2u68qVYVBwhbWAiRfwlUZA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-minify/binding-wasm32-wasi@0.128.0': - resolution: {integrity: sha512-W+fK3cWhu/cUgx3NIAmDYcAyJs01aULlr3E3n/ZN79Q1/CX+FS+yWfwt/IysIi4FhpVL7z58azbJHDzhEx4X4g==} + '@oxc-minify/binding-wasm32-wasi@0.133.0': + resolution: {integrity: sha512-AkLr+d+LLY4/55J/TrE0srNBUpZPzyU+cygdse7yZ9AhCndryNqe2y6e8naVK0TV7n8lxBd2OGGJAkho6blAkw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@oxc-minify/binding-win32-arm64-msvc@0.128.0': - resolution: {integrity: sha512-pwMZd27FF+j4tHLYKtu4QBl6KI0gkt6xTNGLffs8VlH5vfDPHUvLo/AS6y66tdEjQ3chhs8OGg1mAFhPoQldDw==} + '@oxc-minify/binding-win32-arm64-msvc@0.133.0': + resolution: {integrity: sha512-V92v7397t2073g+mSfaLHnPeoz6hA/1U4JNLeUBP87eWGZgVxDZ2qz3t3wFyYqXGJ/0VoEwdP8yrHLQQ7QzAOQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-minify/binding-win32-ia32-msvc@0.128.0': - resolution: {integrity: sha512-GskPdx/Fsn3ttkJbzxh51LYhla4N4p1sMufJKgf6PHupt5RukBaHI/GKM/2ni6ObxUI0b9UK37fROdV+5ekpMQ==} + '@oxc-minify/binding-win32-ia32-msvc@0.133.0': + resolution: {integrity: sha512-2DP5RbG/SSaRVtmuwgTH6Ati4+uuOJjoI88dQnC5hD0zCC90EVDXZSXyJQ5i/OxLE1UAy58Wo2DJot/OrUspzA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-minify/binding-win32-x64-msvc@0.128.0': - resolution: {integrity: sha512-m8oakspZCbCod3WuY0U9DvwQlhMYaU31bK+Way1Rb+JGs455WLtkebEie/luSuN5DeF+aZyRH/zt1AY4weKQQg==} + '@oxc-minify/binding-win32-x64-msvc@0.133.0': + resolution: {integrity: sha512-PJ75c6PlBx87tau0W35J43eGCv4wrDmdZ+4ddTZAnGtZqEeCVsLdmDPOEMe2DepogqlSVUF2kGBWtnFUJ5c7Rw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -2886,14 +2901,14 @@ packages: cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm-eabi@0.128.0': - resolution: {integrity: sha512-aca6ZvzmCBUGOANQRiRQRZuRKYI3ENhcit6GisnknOOmcezfQc7xJ4dxlPU7MV7mOvrC7RNR1u3LAD7xyaiCxA==} + '@oxc-parser/binding-android-arm-eabi@0.133.0': + resolution: {integrity: sha512-l/44caGse+VpnY9gx0yvvc5QnnG3yG1FO3KZgYvNL1GZrfK86zIwAOgGEVlxDyRymzrU/KHiblPFpevKOmJmUA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxc-parser/binding-android-arm-eabi@0.133.0': - resolution: {integrity: sha512-l/44caGse+VpnY9gx0yvvc5QnnG3yG1FO3KZgYvNL1GZrfK86zIwAOgGEVlxDyRymzrU/KHiblPFpevKOmJmUA==} + '@oxc-parser/binding-android-arm-eabi@0.135.0': + resolution: {integrity: sha512-sHeZItACNcA5WRAWqF6ixriR4GkZDyY10gVgnZU7pXku1DjHFATSqnwZM809jl0gXPHxb6fKzYQCK7bNK5cACQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] @@ -2916,14 +2931,14 @@ packages: cpu: [arm64] os: [android] - '@oxc-parser/binding-android-arm64@0.128.0': - resolution: {integrity: sha512-BbeDmuohoJ7Rz/it5wnkj69i/OsCPS3Z51nLEzwO/Y6YshtC4JU+15oNwhY8v4LRKRYclRc7ggOikwrsJ/eOEQ==} + '@oxc-parser/binding-android-arm64@0.133.0': + resolution: {integrity: sha512-KUHmPMziLBp4u+zbrLdB7iWS7KshuZe+RAp7ELnY9SI9nNXBZ+dp8fiBqWOxhXqn+FQg3a4UcQhwmsJOKV8Jjg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxc-parser/binding-android-arm64@0.133.0': - resolution: {integrity: sha512-KUHmPMziLBp4u+zbrLdB7iWS7KshuZe+RAp7ELnY9SI9nNXBZ+dp8fiBqWOxhXqn+FQg3a4UcQhwmsJOKV8Jjg==} + '@oxc-parser/binding-android-arm64@0.135.0': + resolution: {integrity: sha512-wPte+SzgzWWFgMSF8YZDNM+tBXtJg0AXBi7+tU3yS2z1f2Af9kRLZLKuJojADmuD/cZexmnMHHC3SDItTW77Iw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -2946,14 +2961,14 @@ packages: cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-arm64@0.128.0': - resolution: {integrity: sha512-tRUHPt80417QmvNpoSslJT1VY8NUbWdrWR+L14Zn+RbOTcaqB8E6PYE/ZGN8jjWBzqporiA/H4MfO50ew/NCNA==} + '@oxc-parser/binding-darwin-arm64@0.133.0': + resolution: {integrity: sha512-q8dWmnU/8ea2tga9w2f1PinQ5rcMPDUGkF64T189b65YMjUomET4oy5oRldOr4AwOQkneOG/Zttnz1Dvrc62wg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxc-parser/binding-darwin-arm64@0.133.0': - resolution: {integrity: sha512-q8dWmnU/8ea2tga9w2f1PinQ5rcMPDUGkF64T189b65YMjUomET4oy5oRldOr4AwOQkneOG/Zttnz1Dvrc62wg==} + '@oxc-parser/binding-darwin-arm64@0.135.0': + resolution: {integrity: sha512-BmKz3lHIsqVos+9aPcdYCT9MG3APoUyM43KlEFhJMWNVDOGG8FKyiFz81Bc+mGz2o0hpuQ3PfXLfVWJrKXjo2g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -2976,14 +2991,14 @@ packages: cpu: [x64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.128.0': - resolution: {integrity: sha512-rWI2Hb1Nt3U/vKsjyNvZzDC8i/l144U20DKjhzaTmwIhIiSRGeroPWWiImwypmKLqrw8GuIixbWJkpGWLbkzrQ==} + '@oxc-parser/binding-darwin-x64@0.133.0': + resolution: {integrity: sha512-cOKeIELIB2bJnCKwqx4Rdj+1Lss/U6uCbLxRySZrhyOOQa1flKhwZFjEHRHxk8fU1NKmhK5OnTdPQ4CpjuFuVw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxc-parser/binding-darwin-x64@0.133.0': - resolution: {integrity: sha512-cOKeIELIB2bJnCKwqx4Rdj+1Lss/U6uCbLxRySZrhyOOQa1flKhwZFjEHRHxk8fU1NKmhK5OnTdPQ4CpjuFuVw==} + '@oxc-parser/binding-darwin-x64@0.135.0': + resolution: {integrity: sha512-dM8BS+8+Br1fNvmh2QZbGiHaYttwLebRa6J4Uz9vuFzMNmvsdRYwf7993ptOaV0JTrR63AaoVLjX7nhWbijxjQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -3006,14 +3021,14 @@ packages: cpu: [x64] os: [freebsd] - '@oxc-parser/binding-freebsd-x64@0.128.0': - resolution: {integrity: sha512-hhpdVMaNCLgQxjgNPeeFzSeJMmZPc5lKfv0NGSI3egZq9EdnEGqeC8JsYsQjK7PoQgbvZ17xlj0SO5ziH5Obkg==} + '@oxc-parser/binding-freebsd-x64@0.133.0': + resolution: {integrity: sha512-OpaSv4pW3KgFrMYQxTaS0aOE4T1DQF3qZE/4B6uqqv1KgPWWd4UQhJALi8PJPX1RRV5K7ThKXRfF7qGg2+3l1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxc-parser/binding-freebsd-x64@0.133.0': - resolution: {integrity: sha512-OpaSv4pW3KgFrMYQxTaS0aOE4T1DQF3qZE/4B6uqqv1KgPWWd4UQhJALi8PJPX1RRV5K7ThKXRfF7qGg2+3l1A==} + '@oxc-parser/binding-freebsd-x64@0.135.0': + resolution: {integrity: sha512-xlZnvvJdR9bGu2pOhvR5hMuKPHCE6Sa9owK5A484mzjHdm75VRV5nCs5w/jkmGODMMTFc+KN7EnZqEieM813kw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -3036,14 +3051,14 @@ packages: cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-gnueabihf@0.128.0': - resolution: {integrity: sha512-093zNw0zZ/e/obML+rhlSdmnzR0mVZluPcAkxunEc5E3F0yBVsFn24Y1ILfsEte11Ud041qn/gp2OJ1jxNqUng==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': + resolution: {integrity: sha512-JGK1wlGrGwxBIlVSF7KWTX1/ru6BEtf28fRROztDRkLfiW+Kxa4onnriezMIiogfn9hVw2KzYcKiLjkLR2ns8A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': - resolution: {integrity: sha512-JGK1wlGrGwxBIlVSF7KWTX1/ru6BEtf28fRROztDRkLfiW+Kxa4onnriezMIiogfn9hVw2KzYcKiLjkLR2ns8A==} + '@oxc-parser/binding-linux-arm-gnueabihf@0.135.0': + resolution: {integrity: sha512-PSR8LmBK/H/PQRiN8g7RebQgZX/ntVCrdT/JBfNxE5ezdHG1s2i4rbazsRJYD83TTI1MmgTpC0MGL42PLtskQQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -3066,14 +3081,14 @@ packages: cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.128.0': - resolution: {integrity: sha512-fq7DmKmfC+dvD97IXrgbph6Jzwe0EDu+PYMofmzZ6fv5X1k9vtaqLpDGMuICO9MmUnyKAQmVl+wIv2RNy4Dz8g==} + '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': + resolution: {integrity: sha512-yuZO533Ftonxn/iyoqQzURzLQHMspvsIyfiCSNi1t/ER4eIQaR0SsmUOUm5b/lmSig7IWIUa5/BrbEkAPwcilQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': - resolution: {integrity: sha512-yuZO533Ftonxn/iyoqQzURzLQHMspvsIyfiCSNi1t/ER4eIQaR0SsmUOUm5b/lmSig7IWIUa5/BrbEkAPwcilQ==} + '@oxc-parser/binding-linux-arm-musleabihf@0.135.0': + resolution: {integrity: sha512-I85GJXzfUsigkkk7Ngdz95C217M4FdUi1Z2HrX5UyPmURobwQZ7m2bbUvwFkz4VGZd+lymFGKHvDZ3RQC9qOzA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -3099,15 +3114,15 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-gnu@0.128.0': - resolution: {integrity: sha512-Xvm48jJah8TlIrURIjNOP/gNiGe6aKvCB+r06VliflFo8Kq7VOLE8PxtgShJzZIqubrgdMdYfvuPPozn7F6MbQ==} + '@oxc-parser/binding-linux-arm64-gnu@0.133.0': + resolution: {integrity: sha512-hvpbqT5pN2rR+3+xtWeizwfR/aZ0vGceg6TqYMl+ToxMpk9/tmnX7kSvQnfEUkoua8mhogzvIKsAkn0wxgblBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-arm64-gnu@0.133.0': - resolution: {integrity: sha512-hvpbqT5pN2rR+3+xtWeizwfR/aZ0vGceg6TqYMl+ToxMpk9/tmnX7kSvQnfEUkoua8mhogzvIKsAkn0wxgblBA==} + '@oxc-parser/binding-linux-arm64-gnu@0.135.0': + resolution: {integrity: sha512-zqEY0npz0g0aGZj/8a5BclunjVDytsBQHYtIC10Gd26HcrLwbVF6YDbqRQjunMGYdSo97u6xOBl05aTDI2diDQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -3134,15 +3149,15 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-linux-arm64-musl@0.128.0': - resolution: {integrity: sha512-M7iwBGmYJTx+pKOYFjI0buop4gJvlmcVzFGaXPt21DKpQkbQZG1f63Yg7LloIYT/t9yLxCw0Lhfx/RFlAlMSjA==} + '@oxc-parser/binding-linux-arm64-musl@0.133.0': + resolution: {integrity: sha512-wJQGamIosQBoJHW9+S5XxrtKRo3eyJxsnS1XCPrqN0LHi8uw1pTqqTfn3t/NVuvbBg7Pumn4ez9Eidgcn0xbEg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-arm64-musl@0.133.0': - resolution: {integrity: sha512-wJQGamIosQBoJHW9+S5XxrtKRo3eyJxsnS1XCPrqN0LHi8uw1pTqqTfn3t/NVuvbBg7Pumn4ez9Eidgcn0xbEg==} + '@oxc-parser/binding-linux-arm64-musl@0.135.0': + resolution: {integrity: sha512-mWAfprP819gQ2qYst1RxgTI8b/z0b29OpoKfRflIXLHde2dZLihQD4g47Onuvtpo5GPIkMYPRlX9QoeZfs/GnQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -3169,15 +3184,15 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-ppc64-gnu@0.128.0': - resolution: {integrity: sha512-21LGNIZb1Pcfk5/EGsqabrxv4yqQOWis1407JJrClS7XpFCrbvr74YAB1V+m54cYbwvO6UWwQqS4WecxiyfCRg==} + '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': + resolution: {integrity: sha512-Koaz32/O5+abIfrNGdyndgRvdOZ9jEf5/z3Ep9h3h2QWpdDiUQpVwgH0OcMXCs+l9aXxPLtkupqyVig9W6FDKw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': - resolution: {integrity: sha512-Koaz32/O5+abIfrNGdyndgRvdOZ9jEf5/z3Ep9h3h2QWpdDiUQpVwgH0OcMXCs+l9aXxPLtkupqyVig9W6FDKw==} + '@oxc-parser/binding-linux-ppc64-gnu@0.135.0': + resolution: {integrity: sha512-gri8c2AOmJKJwOux2KTHFBfUaXoJURuVMKhmKEi/2hTF55cQteTDV2XNfTiE5oCC+Tnem1Y4/MWzcyDadtsSag==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] @@ -3204,15 +3219,15 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.128.0': - resolution: {integrity: sha512-gyHjOTFpg9bTTYjxPmQirvufb89+VdZwVfcMtAUyPr6F5H8ZswvCQshK4qOW+Q+2Xyb33hduRgY/eFHJQjU/vQ==} + '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': + resolution: {integrity: sha512-R4vOjWzxhnNWHnVLeiB6jNuIifdy9vcMXZGPc7StXcxBovI+U2zg1QhZ9o8OjV80oGivs1lX5NfPLzk4IPqlRA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': - resolution: {integrity: sha512-R4vOjWzxhnNWHnVLeiB6jNuIifdy9vcMXZGPc7StXcxBovI+U2zg1QhZ9o8OjV80oGivs1lX5NfPLzk4IPqlRA==} + '@oxc-parser/binding-linux-riscv64-gnu@0.135.0': + resolution: {integrity: sha512-Y2tkupCG5wo0SxH2rMLG4d4Kmv6DaM3sBp+GuM5lox0S8Za6VxKgQrY2Mut088QQxKkEE89n/4CCCgmw2o0e3Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] @@ -3239,15 +3254,15 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-linux-riscv64-musl@0.128.0': - resolution: {integrity: sha512-X6Q2oKUrP5GyDd2xniuEBLk6aFQCZ97W2+aVXGgJXdjx5t4/oFuA9ri0wLOUrBIX+qdSuK581snMBio4z910eA==} + '@oxc-parser/binding-linux-riscv64-musl@0.133.0': + resolution: {integrity: sha512-iwgBNUTHiMdxARLYuM0SBlnYeb19iw1Ea5M+4ERZupCsBMLArti6FyZ6UfFjJxIiTDr2oW2DGQFxlQVQ/dW9rA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-riscv64-musl@0.133.0': - resolution: {integrity: sha512-iwgBNUTHiMdxARLYuM0SBlnYeb19iw1Ea5M+4ERZupCsBMLArti6FyZ6UfFjJxIiTDr2oW2DGQFxlQVQ/dW9rA==} + '@oxc-parser/binding-linux-riscv64-musl@0.135.0': + resolution: {integrity: sha512-xDRJq6i6WTynjeP+ISbDpyH4p9BaJ0wuQcL0lCSDkt9qOXC9dmwpOu1VG/TlwmPI3KpYntmO9nJCuc3TMTsNBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] @@ -3274,15 +3289,15 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-s390x-gnu@0.128.0': - resolution: {integrity: sha512-BdzTmqxfxoYkpgokoLaSnOX6T+R3/goL42klre2tnG+kHbG2TXS0VN+P5BPofH1axdKOHy5ei4ENZrjmCOt2lA==} + '@oxc-parser/binding-linux-s390x-gnu@0.133.0': + resolution: {integrity: sha512-ZwZNo8FZmB/gVfboQl+wXilBigGl+6nQQs+nITOeAP/HcAOjiHl6XZJL9F/KXNEspODQcbjAiyjUbeCJd9a0fA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-s390x-gnu@0.133.0': - resolution: {integrity: sha512-ZwZNo8FZmB/gVfboQl+wXilBigGl+6nQQs+nITOeAP/HcAOjiHl6XZJL9F/KXNEspODQcbjAiyjUbeCJd9a0fA==} + '@oxc-parser/binding-linux-s390x-gnu@0.135.0': + resolution: {integrity: sha512-V4MoUuiCRNvihxhIufRxvK+ka013V4joTSK0FAGA1KEjLuNprfH6N/Qw2uxQEVIFuNYMhD/hV6xJ/ptbzlKdHg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] @@ -3309,15 +3324,15 @@ packages: os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.128.0': - resolution: {integrity: sha512-OO1nW2Q7sSYYvJZpDHdvyFSdRaVcQqRijZSSmWVMqFxPYy8cEF45zJ9fcdIYuzIT3jYq6YRhEFm/VMWNWhE22Q==} + '@oxc-parser/binding-linux-x64-gnu@0.133.0': + resolution: {integrity: sha512-govCvWx1dBlED3uu4qXctxpRcouu9I8Kn+DBktGCl760JtlGJzc9l/OmPJKlYWSbrRqKkMZehNeZ/4Wfma7uSA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-parser/binding-linux-x64-gnu@0.133.0': - resolution: {integrity: sha512-govCvWx1dBlED3uu4qXctxpRcouu9I8Kn+DBktGCl760JtlGJzc9l/OmPJKlYWSbrRqKkMZehNeZ/4Wfma7uSA==} + '@oxc-parser/binding-linux-x64-gnu@0.135.0': + resolution: {integrity: sha512-JCFZ7zM7KXOKoPAbK/ZB4wY0M1jxRECiem2UQuiXLjzGqS9+hno7mtX+qyK2F7HWK2xPhyJb+frpcOtk5DKOtg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -3344,15 +3359,15 @@ packages: os: [linux] libc: [musl] - '@oxc-parser/binding-linux-x64-musl@0.128.0': - resolution: {integrity: sha512-4NehAe404MRdoZVS9DW8C5XbJwbXIc/KfVlYdpi5vE4081zc9Y0YzKVqyOYj/Puye7/Do+ohaONBFWlEHYl9hw==} + '@oxc-parser/binding-linux-x64-musl@0.133.0': + resolution: {integrity: sha512-ssTlpXD5Mq9uCssDJPzlRWqBt4Y7Zzd9i+XZhWmK/9Y6KUIuAxVYTYiI8lxcGWi0+3/Cz4A8q9UrD4NK9Y2j7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxc-parser/binding-linux-x64-musl@0.133.0': - resolution: {integrity: sha512-ssTlpXD5Mq9uCssDJPzlRWqBt4Y7Zzd9i+XZhWmK/9Y6KUIuAxVYTYiI8lxcGWi0+3/Cz4A8q9UrD4NK9Y2j7g==} + '@oxc-parser/binding-linux-x64-musl@0.135.0': + resolution: {integrity: sha512-9jSVS1b3hOV7sdKH4aA2DFfnTz0RgQd0v2BefR+LYbH8yIlmSM22JJZbAAjVeVXmFgUAk3zJQ1tpE/Nd+Vi2YQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -3376,14 +3391,14 @@ packages: cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-openharmony-arm64@0.128.0': - resolution: {integrity: sha512-kVbqgW9xLL8bh8oc7aYOJilRKXE5G33+tE0jan+duo/9OriaFRpijcCwT2waWs2oqYROYq0GlE7/p3ywoshVeg==} + '@oxc-parser/binding-openharmony-arm64@0.133.0': + resolution: {integrity: sha512-51aByfXhPtLEdWG4a2Ihdw6cPWV1ei1AarALpFdDP8MLWDLE2NuUMgbo3DERR2Kt8fT/ok1GUvBiLxVGke9uUQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxc-parser/binding-openharmony-arm64@0.133.0': - resolution: {integrity: sha512-51aByfXhPtLEdWG4a2Ihdw6cPWV1ei1AarALpFdDP8MLWDLE2NuUMgbo3DERR2Kt8fT/ok1GUvBiLxVGke9uUQ==} + '@oxc-parser/binding-openharmony-arm64@0.135.0': + resolution: {integrity: sha512-M857ZLBSdn1Uy/SJJz5zh0qGu67B4P9omCgXGBU2LLqTzraX6ZjVNaKq5yW1PDw/LgJXDXR/dbZfgmB310f11Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -3403,13 +3418,13 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-parser/binding-wasm32-wasi@0.128.0': - resolution: {integrity: sha512-L38ojghJYHmgiz6fJd7jwLB/ESDBpB02NdFxh+smqVM6P2anCEvHn0jhaSrt5eVNR1Ak8+moOeftUlofeyvniA==} + '@oxc-parser/binding-wasm32-wasi@0.133.0': + resolution: {integrity: sha512-2e16tkKp+wDO2GTAmXfxbBcCmGEaFPIJEIRBBmVKNVXSc8/fJsSIaBGyFTPHM9ST5GNWgJcYIt94rDTks+PLwA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@oxc-parser/binding-wasm32-wasi@0.133.0': - resolution: {integrity: sha512-2e16tkKp+wDO2GTAmXfxbBcCmGEaFPIJEIRBBmVKNVXSc8/fJsSIaBGyFTPHM9ST5GNWgJcYIt94rDTks+PLwA==} + '@oxc-parser/binding-wasm32-wasi@0.135.0': + resolution: {integrity: sha512-2w6DVcntQZX9U5RhXtgiWb3FLWFB5EcwI1U8yr3htOCJUJjagN4BFUHz/Y/d9ZsumndZ6ByxxWEtbUZNE1bfFw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] @@ -3431,14 +3446,14 @@ packages: cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-arm64-msvc@0.128.0': - resolution: {integrity: sha512-xgvO35GyHBtjlQ5AEpaYr7Rll1rvY7zqIhT6ty8E3ezBW2J1SFLjIDEvI/tcgDg6oaseDAqVcM+jU1HuCekgZw==} + '@oxc-parser/binding-win32-arm64-msvc@0.133.0': + resolution: {integrity: sha512-KPTNDKbxH1cglrqTyVeXHb4Pk4oksz8EcE1/v8zqU7N4UXbiHfA/IwtXZ2U77fnRAWBbgVkl/lZbL7o3hRdejg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxc-parser/binding-win32-arm64-msvc@0.133.0': - resolution: {integrity: sha512-KPTNDKbxH1cglrqTyVeXHb4Pk4oksz8EcE1/v8zqU7N4UXbiHfA/IwtXZ2U77fnRAWBbgVkl/lZbL7o3hRdejg==} + '@oxc-parser/binding-win32-arm64-msvc@0.135.0': + resolution: {integrity: sha512-rX1U8+IH2Z37EJjDXKa1iifvUQAdba+vZ4Ewj1iaG5eA/QaSybzclCOwtWa0/5BuUQnnK/T2JHUEFrwhL6Ck2Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -3461,14 +3476,14 @@ packages: cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.128.0': - resolution: {integrity: sha512-OY+3eM2SN72prHKRB22mPz8o5A/7dJ+f5DFLBVvggyZhEaNDAH9IB+ElMjmOkOIwf5MDCUAowCK7pAncNxzpBA==} + '@oxc-parser/binding-win32-ia32-msvc@0.133.0': + resolution: {integrity: sha512-Una1bNYv9zCavQrfnDR9wuZVB3itLjCEH4Oz7i6CwAJN/Xq9b+zbbcxmvdkKvvJt4Ngc/MBmIYlbLo3zS4TQ0A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxc-parser/binding-win32-ia32-msvc@0.133.0': - resolution: {integrity: sha512-Una1bNYv9zCavQrfnDR9wuZVB3itLjCEH4Oz7i6CwAJN/Xq9b+zbbcxmvdkKvvJt4Ngc/MBmIYlbLo3zS4TQ0A==} + '@oxc-parser/binding-win32-ia32-msvc@0.135.0': + resolution: {integrity: sha512-9FAisBbH1QICGAjlJobiuKGd/jOuVmyqniWdQMwTa5SkCl6hhuotBCJf1n46B0flYbSOR5TzfV9HZCWSyb3c/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] @@ -3491,14 +3506,14 @@ packages: cpu: [x64] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.128.0': - resolution: {integrity: sha512-NE9ny+cPUCCObXa0IKLfj0tCdPd7pe/dz9ZpkxpUOymB3miNeMPybdlYYTBSGJUalMWeBM85/4JcCErCNTqOXw==} + '@oxc-parser/binding-win32-x64-msvc@0.133.0': + resolution: {integrity: sha512-kjBhCiOGSYTwDJQuuZa7a94JbP8htWu7J0X1KwH74kV2K5eYf6eyJRYmkpCDvr0XEL8tMxYI4WU1VekblFCLgg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxc-parser/binding-win32-x64-msvc@0.133.0': - resolution: {integrity: sha512-kjBhCiOGSYTwDJQuuZa7a94JbP8htWu7J0X1KwH74kV2K5eYf6eyJRYmkpCDvr0XEL8tMxYI4WU1VekblFCLgg==} + '@oxc-parser/binding-win32-x64-msvc@0.135.0': + resolution: {integrity: sha512-wYF+A2AzJ2n7ul6q+Z2G/ia0S2+8cUp0AgWZzoFvF4WmUcl1P7p+o6se1Gdr5wGnWuF0iAMIkGddrjCarNr2yA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -3526,12 +3541,12 @@ packages: '@oxc-project/types@0.127.0': resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} - '@oxc-project/types@0.128.0': - resolution: {integrity: sha512-huv1Y/LzBJkBVHt3OlC7u0zHBW9qXf1FdD7sGmc1rXc2P1mTwHssYv7jyGx5KAACSCH+9B3Bhn6Z9luHRvf7pQ==} - '@oxc-project/types@0.133.0': resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxc-project/types@0.135.0': + resolution: {integrity: sha512-wR+xRdFkUBMvcAjBJ2q2kcZM6d+DKu2NgoOyxZgYwZdLhmiv6+rnO8PZ/P68kMiZtIKm+pW7zyEJ4kSOs0vo+Q==} + '@oxc-resolver/binding-android-arm-eabi@11.20.0': resolution: {integrity: sha512-IjfWOXRgJFNdORDl+Uf1aibNgZY2guOD3zmOhx1BGVb/MIiqlFTdmjpQNplSN58lhWehnX4UNqC3QwpUo8pjJg==} cpu: [arm] @@ -3641,8 +3656,8 @@ packages: cpu: [arm] os: [android] - '@oxc-transform/binding-android-arm-eabi@0.128.0': - resolution: {integrity: sha512-qVO4izEs88ZSo7KOK4P+O5nAXXJmkSadInvFjGkhVnm2R2Wr8trU/GLhjAK0S0u8Qv9bkXspNhgpECk+CTQ/ew==} + '@oxc-transform/binding-android-arm-eabi@0.133.0': + resolution: {integrity: sha512-2A79NBpyBKgHJ0FwgC8D1hzp3x2ujyvqq/kG+M76YyDMMkxLhX6A3vjnAnfEKycOoZxuKhwYu8BF9hKq67ykIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] @@ -3653,8 +3668,8 @@ packages: cpu: [arm64] os: [android] - '@oxc-transform/binding-android-arm64@0.128.0': - resolution: {integrity: sha512-F3RXlbCzIgkpRWlz1PEguDZl5NzZRmbeHKTFTQWFnK6mIdw2EkWihPVv9+CIcO80c7+sF/YRGOBaji6hwUDhtQ==} + '@oxc-transform/binding-android-arm64@0.133.0': + resolution: {integrity: sha512-dynEph/hyoSgBzd2XbNlW37NK97nU6tZMs5jrhObUxSasBV/Gv9THZrWj9AlbWiMXR07WFYE82C9axjntYyBSw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] @@ -3665,8 +3680,8 @@ packages: cpu: [arm64] os: [darwin] - '@oxc-transform/binding-darwin-arm64@0.128.0': - resolution: {integrity: sha512-xj63gIzQ67LDYHCOWXSHgfx4LbPVz1ck0G3y0eR6mbgYk3CwwylbhWi/CaDC6BWsHwoLQryeYjHB5XBCR0EPMQ==} + '@oxc-transform/binding-darwin-arm64@0.133.0': + resolution: {integrity: sha512-4hGgKOG+dZSN3xjcgNWpcihekRG7/YbbAdjyz07yv0HjzA6kdqYAhGrn84374UPO2h6etYJwsCBoM9iJHHvJ8w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] @@ -3677,8 +3692,8 @@ packages: cpu: [x64] os: [darwin] - '@oxc-transform/binding-darwin-x64@0.128.0': - resolution: {integrity: sha512-YQkvFqNqpwEt197RjREAOWeRANalPtCD+ayZlx4IjTQ6IOYZEP83B9/++gTQisHV3r8E7dU8UqJKeSS1cHlTQg==} + '@oxc-transform/binding-darwin-x64@0.133.0': + resolution: {integrity: sha512-7J11/9PFkznmKuANkCAjt3znV1BcDFXQSgDiBvDxXT3Wm6995/zxrJD5zmo+5XSgY4sm+2V8/ED6ZSD3mKOC5A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] @@ -3689,8 +3704,8 @@ packages: cpu: [x64] os: [freebsd] - '@oxc-transform/binding-freebsd-x64@0.128.0': - resolution: {integrity: sha512-Jvd3Ximb3x3o0+xRBB5lq63JlzxhJN787IsBjn0PEnmuocYQj+tJ5BB4n9xPIG27GXwg3ycckQPO/RsWeEcBPg==} + '@oxc-transform/binding-freebsd-x64@0.133.0': + resolution: {integrity: sha512-5EMAO0vzCpUfhn6aSjIUeJeRI2ztevHwSVr/M8sZ2VBYc79UuOfjjMCQ67LtUbgpvQtpBWkzeAHCP3L7JFYmlg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] @@ -3701,8 +3716,8 @@ packages: cpu: [arm] os: [linux] - '@oxc-transform/binding-linux-arm-gnueabihf@0.128.0': - resolution: {integrity: sha512-TaRKWeGnAJNIdCa5+m0I8/SksBgkLX94iH40qy3chvLuaIOGAmOViUStYx8geXBzO9P99V7En8nHXLoqCONBRQ==} + '@oxc-transform/binding-linux-arm-gnueabihf@0.133.0': + resolution: {integrity: sha512-z6XT8tmo9sPmCIYaFIxDelBU4wXLwwWMX2VNCMIY6bkQp5r+kRtVXYS3yLbJHMKEhRKvw/g+Z7fO9aadsGGEAw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -3713,8 +3728,8 @@ packages: cpu: [arm] os: [linux] - '@oxc-transform/binding-linux-arm-musleabihf@0.128.0': - resolution: {integrity: sha512-7TMrtA5/3SCvS+yMPrGnri5T4ZhIoCbjwKWV6Kn8d3v+vx7MpEmNkfe+CdF3rb5LlnuxeDMPwr1E2ntya0b8HQ==} + '@oxc-transform/binding-linux-arm-musleabihf@0.133.0': + resolution: {integrity: sha512-GQDpEV2VhHG8hT5BviDv+emi9oHYhfv+JJJWROYp+eGgWjiQMp4QZVb6Bu3kwVMzkwy0r200ToA1KThYTq53ug==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] @@ -3726,8 +3741,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-transform/binding-linux-arm64-gnu@0.128.0': - resolution: {integrity: sha512-lMQEa1jLBNm1N+5uvyj9zX9urVY4xKkLnhO8/4CtSGdXX+mExqsVawyQPAZqbtq1fLQ0yt1QYJ9YuM0+fiSJTQ==} + '@oxc-transform/binding-linux-arm64-gnu@0.133.0': + resolution: {integrity: sha512-VstR+NEQAJb80ysWk2vPjEvg0JzwEjKn2hDbC/joa5zGXkCnVVCWgAGG8c6o23S981a7XRpCMcClBgeD1q9H2A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -3740,8 +3755,8 @@ packages: os: [linux] libc: [musl] - '@oxc-transform/binding-linux-arm64-musl@0.128.0': - resolution: {integrity: sha512-dPSjyd0gQ9dE3mpdJi0BHNJaqQz4V7mVW6Fbs6jRSiGnrxwGfXdMJFInXoJ49B3k5Zhfa9Is9Ixp6St7c6ouCA==} + '@oxc-transform/binding-linux-arm64-musl@0.133.0': + resolution: {integrity: sha512-Ec7xJdDrnukgiz20E3iDNzAIgx1XXn8cVVsNNUpgEIAvNlXZaocqlQT8Zalk0Lv3fbkxcJ+9BuWB0ndBRHQtzg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] @@ -3754,8 +3769,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-transform/binding-linux-ppc64-gnu@0.128.0': - resolution: {integrity: sha512-YNa9XAotPKvAXFJrHC7kBsHMVg0HOB4vRiKuYUjzFsfLkxTbuztKHTKG/gW5kjp7dBw+TNFofTaVCVZgOnHXPQ==} + '@oxc-transform/binding-linux-ppc64-gnu@0.133.0': + resolution: {integrity: sha512-6YX38grimcigz20eYpyz6e4c9rDKzwK3i+tcDpgwYj0bWreaAOwrABmSmKplPJOorkDVlbT69wPCN+d11irBQw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] @@ -3768,8 +3783,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-transform/binding-linux-riscv64-gnu@0.128.0': - resolution: {integrity: sha512-jjSiG9H8ya/U3igW5DdIBFIDwhffF7Vbc7th2tcHV73eg0DQz75n36a9RmQ1/0aS9vknUuNtY6SODr8/gmuzsQ==} + '@oxc-transform/binding-linux-riscv64-gnu@0.133.0': + resolution: {integrity: sha512-WxMIzItRJR66lgaAyyqj0FFwLMpcuCV9mTFcUMQpIz8+Hey1Enk8xuv+7QpSsqCR5zRlwNr092dsFkz5cbvtrw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] @@ -3782,8 +3797,8 @@ packages: os: [linux] libc: [musl] - '@oxc-transform/binding-linux-riscv64-musl@0.128.0': - resolution: {integrity: sha512-FVUr/XNT7BfQA4XVMel/HTCJi5mQyEitslgX42ztYPnCFMRFG1sQQKgnlLJdl7qifuyxpvKLR1f7h7HEuwWw1Q==} + '@oxc-transform/binding-linux-riscv64-musl@0.133.0': + resolution: {integrity: sha512-+x6dnO87986rjVNjcF0tg8wVS0e/SH8nzLa/X0Wsh7jtEniN7buvR8iqZm8pnsfaZ8DH5F4GCSZpoPRrd9jJ6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] @@ -3796,8 +3811,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-transform/binding-linux-s390x-gnu@0.128.0': - resolution: {integrity: sha512-caJnVw5PG8v339zAyHgA7p34xXa3A4Kc9VyrDgsT1znr51qacaUv4BRlgRi0qkqxRWXYNVFfsbU2g0t1qS7E9w==} + '@oxc-transform/binding-linux-s390x-gnu@0.133.0': + resolution: {integrity: sha512-oEyQudXIwWM/+v0vZzPbAi25YMWyvjtQYYjuSrhMEQwe7ZEMDXscX7U1j6alrVdZq2DtCMeror3X/Dv7p/JUwg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] @@ -3810,8 +3825,8 @@ packages: os: [linux] libc: [glibc] - '@oxc-transform/binding-linux-x64-gnu@0.128.0': - resolution: {integrity: sha512-zkQKjsHEUX3ckQBcZTtHE/7pgFMkWQp6y/4t7N8eT3j8wnoL+vapv7l4ISjgx1/EePRJN1HErYXmriz7tPVKRg==} + '@oxc-transform/binding-linux-x64-gnu@0.133.0': + resolution: {integrity: sha512-G8P/OadKTbyUHz5TK63sDDtUHwn2SXG/o0oGo4GGTzBu70xmUSN5/ZUgpyl6ypAmbshoyw8nC7+msb3BjzHxaA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -3824,8 +3839,8 @@ packages: os: [linux] libc: [musl] - '@oxc-transform/binding-linux-x64-musl@0.128.0': - resolution: {integrity: sha512-NjYtwl9ijp34iisHxYBvE7nii1Ac0QPP3doHv8MQHhDA3zjUcDCROuBNybfaEYCxnJ1aF+cAPqsyeopnAGsyuQ==} + '@oxc-transform/binding-linux-x64-musl@0.133.0': + resolution: {integrity: sha512-Oi/fyOzZ+aytmmsRND5pGgvux4n++v9cG4qNFiXj7qFwSqBKWZHBq7cJLXqbH1I81pyI3kvU1Za+1qk3afXuwg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] @@ -3837,8 +3852,8 @@ packages: cpu: [arm64] os: [openharmony] - '@oxc-transform/binding-openharmony-arm64@0.128.0': - resolution: {integrity: sha512-itsi0tVkVdrYphSppdFChLq9tD0pvbRRS3EV8NQYKZ/NWHMoxzjlf9TFA/ZZYV113juYo1Dq3glVX48knhBeFQ==} + '@oxc-transform/binding-openharmony-arm64@0.133.0': + resolution: {integrity: sha512-/ZElgq+/tcga27X2G2AUpxcYX0baX94Gz658w6Zz2P+6Kr06bfYSrdtC0P7oPrbu3Gy/6kpiSoJPgZy8R2IjYQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] @@ -3848,8 +3863,8 @@ packages: engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-transform/binding-wasm32-wasi@0.128.0': - resolution: {integrity: sha512-elzjX2gy1jcseeFaKtbk/6T2FPTpGNx0IpeD0iyk6cahWN7wD6eHY5u7th1X85cYbRq9rqniS+xYIxN3StthWg==} + '@oxc-transform/binding-wasm32-wasi@0.133.0': + resolution: {integrity: sha512-GANcoEa8Nzza7saxdb4qWO24U6jk4nK6G+g87lGp8TTU45CUvWf1Igdze2+NrebgiwOy6F1/h6Esag4DM3JTtQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] @@ -3859,8 +3874,8 @@ packages: cpu: [arm64] os: [win32] - '@oxc-transform/binding-win32-arm64-msvc@0.128.0': - resolution: {integrity: sha512-p5LmbI66dk2dziJSUzjQ24gOWeI6pJpXcOC6famloRtKCq54V5/KegsztFgZZCtYFEAEqFgcfspFHrV+CcKWcg==} + '@oxc-transform/binding-win32-arm64-msvc@0.133.0': + resolution: {integrity: sha512-2+uDo/+ZvGQu10J8xryg/l5PdBt2vXPtf+0aIosVKJavqCaKcBDdo95OUaEulx0bqvoytAQ4yyz2gcPZ40mjcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] @@ -3871,8 +3886,8 @@ packages: cpu: [ia32] os: [win32] - '@oxc-transform/binding-win32-ia32-msvc@0.128.0': - resolution: {integrity: sha512-CMU3Yn05rXeLw7GyVlDB3bbp2iV14yt3VWyF0pNuMK9NVgOmUkXgFLe5SOcX9rEm64TRJjOMEghtE5+r0GtqIQ==} + '@oxc-transform/binding-win32-ia32-msvc@0.133.0': + resolution: {integrity: sha512-zpPIZ1S3JHmSEFyyGyPYCwhOiNLyfaPifYxK8BQY21JXyHglu/wUr3/ESFrXb+XegEy/iBlWbzr3FzPtcq1MUw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] @@ -3883,8 +3898,8 @@ packages: cpu: [x64] os: [win32] - '@oxc-transform/binding-win32-x64-msvc@0.128.0': - resolution: {integrity: sha512-Vck5AdNH2JPYMQWVDxvX5PbDFfqVG+tCOgKJzAC/S9bgbD3qcMjN5Dx6FOmEbwY3hZm//fzOsY4tErofoiK/aQ==} + '@oxc-transform/binding-win32-x64-msvc@0.133.0': + resolution: {integrity: sha512-cADrfLvc/VeyvpvQS+t5ktqfyqyyGANZC5NHp++JAElacfXqq/+k8bYkjqMWzNZ3HxkJtL1qDHfZZCA9+4hlSQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -4569,15 +4584,15 @@ packages: '@rolldown/pluginutils@1.0.0-rc.12': resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==} - '@rolldown/pluginutils@1.0.0-rc.13': - resolution: {integrity: sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==} - '@rolldown/pluginutils@1.0.0-rc.16': resolution: {integrity: sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==} '@rolldown/pluginutils@1.0.0-rc.9': resolution: {integrity: sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==} + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@rollup/plugin-alias@6.0.0': resolution: {integrity: sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g==} engines: {node: '>=20.19.0'} @@ -4941,7 +4956,7 @@ packages: resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@storybook-vue/nuxt@https://pkg.pr.new/@storybook-vue/nuxt@1021': - resolution: {integrity: sha512-OmpGHtbapfpljOkFY8/g+9EkNa+SPcVAcqOiOPyP6upXMSpwNHHfEXFMBiFWqF7xru82zHg2kkfmWArVpVG7tg==, tarball: https://pkg.pr.new/@storybook-vue/nuxt@1021} + resolution: {tarball: https://pkg.pr.new/@storybook-vue/nuxt@1021} version: 9.0.1 engines: {node: '>=20.19.0'} peerDependencies: @@ -5651,8 +5666,8 @@ packages: resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} deprecated: Potential CWE-502 - Update to 1.3.1 or higher - '@unhead/vue@2.1.13': - resolution: {integrity: sha512-HYy0shaHRnLNW9r85gppO8IiGz0ONWVV3zGdlT8CQ0tbTwixznJCIiyqV4BSV1aIF1jJIye0pd1p/k6Eab8Z/A==} + '@unhead/vue@2.1.15': + resolution: {integrity: sha512-SSByXfEjhzPn8gXdEdgpYqpLMPSkLUH2HVE0GxZfOtNsJ0GgOHQs0g9T67ZZ1z0kTELLKdtOtYrzrbv9+ffF7g==} peerDependencies: vue: '>=3.5.18' @@ -5665,9 +5680,15 @@ packages: resolution: {integrity: sha512-1uleyRLyJc6PNNc2L3hEaKL89zXwvQAtP36oFySgL47RAxZHPZ4vfqFpbwR0eEN4iSqTS24ZFr7CTRWCaEGjzQ==} engines: {node: '>=14'} + '@unocss/config@66.7.2': + resolution: {integrity: sha512-m8LZUZOFHBesViFOnC1MzMMQ1ovYbZ/F2ntkKSIWzLO/VvEYo2/HK8qhBhtI/FyL27+gvePL4sZ6a5ZChyl0Ug==} + '@unocss/core@66.6.7': resolution: {integrity: sha512-Q8456iWFtdwrUNYKVOQY8ygRggjZOVtLc6Jc8KIkxig7OiNlUWOgXJTfCh4I8g6jBYzC5eHaHFDLgJOmOrxBsg==} + '@unocss/core@66.7.2': + resolution: {integrity: sha512-NNnhm9IVPEZ34drwztREP+mq1rio0L4Tp0u247qBKxJJWYec1+I+FTRsw7EvtukZKvr56YAxFA1qbBV+LjyV+Q==} + '@unocss/extractor-arbitrary-variants@66.6.7': resolution: {integrity: sha512-PQiBHK0yUJ0BR+3GYnTPU6va6HVSRPV+O+s1zZmt23TWbyIeucoKCNR47TDtv+Z1xuksY8krIjtDYtufdrVWKw==} @@ -5794,8 +5815,8 @@ packages: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.0.0 - '@vitejs/plugin-vue@6.0.6': - resolution: {integrity: sha512-u9HHgfrq3AjXlysn0eINFnWQOJQLO9WN6VprZ8FXl7A2bYisv3Hui9Ij+7QZ41F/WYWarHjwBbXtD7dKg3uxbg==} + '@vitejs/plugin-vue@6.0.7': + resolution: {integrity: sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -6014,17 +6035,17 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@vue/compiler-core@3.5.34': - resolution: {integrity: sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==} + '@vue/compiler-core@3.5.39': + resolution: {integrity: sha512-16KBTEXAJCpDr0mwlw+AZyhu8iyC7R3S2vBwsI7QnWJU6X3WKc9VKeNEZpiMdZ569qWhz9574L3vV55qRL0Vtw==} - '@vue/compiler-dom@3.5.34': - resolution: {integrity: sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==} + '@vue/compiler-dom@3.5.39': + resolution: {integrity: sha512-oQPigALqYbNxTNPvNgSOe+czwVExfbVF02lz8jP0S3AXJiu3jxYDygNUiqSep4ezzW8XgnubqH63My2A7JR/vg==} - '@vue/compiler-sfc@3.5.34': - resolution: {integrity: sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==} + '@vue/compiler-sfc@3.5.39': + resolution: {integrity: sha512-d0ki86iOyN8LoZPBmk5SJWNwHP19CnDDCfuo//+2WJa2g5Ke0Jay983PIBIcSSzldC68I8DrD5GrHV3OSDfodg==} - '@vue/compiler-ssr@3.5.34': - resolution: {integrity: sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==} + '@vue/compiler-ssr@3.5.39': + resolution: {integrity: sha512-Ce7/wvwMHai74bdszfXExdazFigYnlF9zgCmEQUcM1j0fOymlouZ7XilTYNo8oUjhlnjYOZbGrcYKuqjz89Ucw==} '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -6060,22 +6081,22 @@ packages: '@vue/language-core@3.2.6': resolution: {integrity: sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg==} - '@vue/reactivity@3.5.34': - resolution: {integrity: sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==} + '@vue/reactivity@3.5.39': + resolution: {integrity: sha512-TpsuBJ9gGlZa5d23XcM2y8EXanz9dZeVDQBXRwzy46ItgvM+rWpzs+UVM0wcRLxGvcav0HE5jz2gNL53xlRAog==} - '@vue/runtime-core@3.5.34': - resolution: {integrity: sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==} + '@vue/runtime-core@3.5.39': + resolution: {integrity: sha512-9GLtNyRvPAUMbX+7ono0RC2j0guo2LXVi8LvcmAooImACUKm0oFf0jjwbX8/H0AE/t1nxhAkn8RSl9PMCzzxZw==} - '@vue/runtime-dom@3.5.34': - resolution: {integrity: sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==} + '@vue/runtime-dom@3.5.39': + resolution: {integrity: sha512-7Y6aAGboKcXAZ3ECuUy7RrS5yy2r47dhTp2SKaJmYxjopImaVFaNa5Ne66NwGovsrxVAl5S5rwc7m22UG7Lmww==} - '@vue/server-renderer@3.5.34': - resolution: {integrity: sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==} + '@vue/server-renderer@3.5.39': + resolution: {integrity: sha512-yZSakiAGw85rZfG7UM8akMnIF+FmeiNk47uvHf2nVBBSe+dIKUhZuZq9+XgJhbV3nS5Z4ALH23/MpXofW+mbcw==} peerDependencies: - vue: 3.5.34 + vue: 3.5.39 - '@vue/shared@3.5.34': - resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==} + '@vue/shared@3.5.39': + resolution: {integrity: sha512-l1rrBtBfTnmxvtsvdQDXltUUy8S1Y+ZaqdfUzmAnJkTd8Z8rv5v/ytW+TKiqEOWyHPoqtPlNFSs0lhRmYVSHVA==} '@vue/test-utils@2.4.6': resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} @@ -6592,8 +6613,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + caniuse-api@4.0.0: + resolution: {integrity: sha512-B0hQ1OLyJuHTQSOWXvwibWqM6DCoqJdvBA6X1S/53bd4XU7LJ1yurIPlrsouol3mw1jh9pGI4ivubSpmJeIqCA==} caniuse-lite@1.0.30001791: resolution: {integrity: sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==} @@ -6640,10 +6661,6 @@ packages: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} - chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} - chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} @@ -6655,17 +6672,21 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} - chromatic@16.1.0: - resolution: {integrity: sha512-7xyOUXe8jfY6c+g9S/U/cbvzVXMjdhh9cVZYvDp8dDGonjiKSbWO1dzWApdYHIiF2xj29pvWQB7N5LT6967IDw==} + chromatic@17.5.0: + resolution: {integrity: sha512-jYtXDaY1VeaNaWMom4HewLQTL574s4wTtkg5Kryov9Cj7D6i8Pe7twpLsetG7apxD0aITWUhx6KiqfN6p380rw==} + engines: {node: '>=22.0.0'} hasBin: true peerDependencies: '@chromatic-com/cypress': ^0.*.* || ^1.0.0 '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + '@chromatic-com/vitest': ^0.*.* || ^1.0.0 peerDependenciesMeta: '@chromatic-com/cypress': optional: true '@chromatic-com/playwright': optional: true + '@chromatic-com/vitest': + optional: true chrome-launcher@1.2.1: resolution: {integrity: sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A==} @@ -6844,12 +6865,6 @@ packages: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} - css-declaration-sorter@7.3.1: - resolution: {integrity: sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==} - engines: {node: ^14 || ^16 || >=18} - peerDependencies: - postcss: ^8.0.9 - css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -6876,23 +6891,23 @@ packages: cssfilter@0.0.10: resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} - cssnano-preset-default@7.0.17: - resolution: {integrity: sha512-11qO63A+czwguQFJCaTdICvbaxn0pJzz/XghLlv+OT7WyToDxAMR0Xb3/26/l0y0hQJywwNbj/SLSQlGBHE1OA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + cssnano-preset-default@8.0.2: + resolution: {integrity: sha512-+jQAqIKCqMmBjZs7741XkilU93ITZ/EW8gjAkMmujdCzfDkfjrDBv2VqkSu29Fzeig/0rZ3S9IAwfPLlmXEUfQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - cssnano-utils@5.0.3: - resolution: {integrity: sha512-ynIREMICLxkxm7e9bCR9sh75s4Q5drICi0ua1yxo5jH2XPBqSKkl4dOh4EbFqtUmnTMhRffHgYL0EKKkMjtJTg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + cssnano-utils@6.0.1: + resolution: {integrity: sha512-zk65GIxA8tCjqVk7nTm1mE+ZKxtnxAvU5JSUaBLXbAr3ZF7IOvz3fbPOnEDvZKhnS7GOIitXTS5BgehLzNoc8Q==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - cssnano@7.1.9: - resolution: {integrity: sha512-uPR75+5Dk/WJ/YSPR1/YDHdwMM9c5FsaARljfKWgeCKLKOtJ0we21xy/RcCjn53fZnD/f6yYEIZ8pu18+GnbNQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + cssnano@8.0.2: + resolution: {integrity: sha512-K+a76gA1v0/CsYgcsE95HGGyIuPKxpQSetwSwz4nHEM8fFXqSkzq2JzEXFL8v5+CCjxzVVVhPcTK3Oo8SaF/xA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 csso@5.0.5: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} @@ -7033,8 +7048,8 @@ packages: devalue@5.6.4: resolution: {integrity: sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==} - devalue@5.8.0: - resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + devalue@5.8.1: + resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==} devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -7184,8 +7199,8 @@ packages: emoticon@4.1.0: resolution: {integrity: sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==} - empathic@2.0.0: - resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + empathic@2.0.1: + resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} engines: {node: '>=14'} encodeurl@2.0.0: @@ -7289,8 +7304,8 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-plugin-regexp@3.1.0: - resolution: {integrity: sha512-qGXIC3DIKZHcK1H9A9+Byz9gmndY6TTSRkSMTZpNXdyCw2ObSehRgccJv35n9AdUakEjQp5VFNLas6BMXizCZg==} + eslint-plugin-regexp@3.1.1: + resolution: {integrity: sha512-MxR5nqoQCtVWmJwia0D2+NlXX1xzdpkslsVOZLEYQ4PQWEaL65PCZXURxaBc3lPnkNFpNxzMIRmYVxdl8giXRA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} peerDependencies: eslint: '>=9.38.0' @@ -7456,15 +7471,24 @@ packages: fast-string-truncated-width@1.2.1: resolution: {integrity: sha512-Q9acT/+Uu3GwGj+5w/zsGuQjh9O1TyywhIwAxHudtWrgF09nHOPrvTLhQevPbttcxjr/SNN7mJmfOw/B1bXgow==} + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + fast-string-width@1.1.0: resolution: {integrity: sha512-O3fwIVIH5gKB38QNbdg+3760ZmGz0SZMgvwJbA1b2TGXceKE6A2cOlfogh1iw8lr049zPyd7YADHy+B7U4W9bQ==} + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} fast-wrap-ansi@0.1.6: resolution: {integrity: sha512-HlUwET7a5gqjURj70D5jl7aC3Zmy4weA1SHUfM0JFI0Ptq987NH2TwbBFLoERhfwk+E+eaq4EK3jXoT+R3yp3w==} + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -7602,8 +7626,8 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - fuse.js@7.3.0: - resolution: {integrity: sha512-plz8RVjfcDedTGfVngWH1jmJvBvAwi1v2jecfDerbEnMcmOYUEEwKFTHbNoCiYyzaK2Ws8lABkTCcRSqCY1q4w==} + fuse.js@7.4.2: + resolution: {integrity: sha512-LVbzjD4WA6UP5B1UnP8wuaXJiLnqMdM/E4fiJXTJ5haJ5b/MBNsK29h2fm6swEoQaVQjvYFWKLE2RanyZIoRVQ==} engines: {node: '>=10'} fzf@0.5.2: @@ -7650,8 +7674,8 @@ packages: get-tsconfig@4.14.0: resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} - giget@3.2.0: - resolution: {integrity: sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==} + giget@3.3.0: + resolution: {integrity: sha512-gzi2D96p+AMfDcmJHGDj3KJ9NRiwvlFAU5yfa3ROwWZmFUjX4P43x3BcyRaOMMLto1vUo7C+86+MFhYTl6Ryiw==} hasBin: true git-up@8.1.1: @@ -7857,6 +7881,9 @@ packages: hey-listen@1.0.8: resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} + hls.js@1.6.16: + resolution: {integrity: sha512-VSIRpLfRwlAAdGL4wiTucx2ScRipo0ed1FBatWkyt832jC4CReKstga6yIhYVwGu9LOBjuX9wzmRMeQdBJtzEA==} + hono@4.12.3: resolution: {integrity: sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==} engines: {node: '>=16.9.0'} @@ -8524,18 +8551,12 @@ packages: lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash@4.17.23: resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} @@ -8566,6 +8587,9 @@ packages: magic-regexp@0.10.0: resolution: {integrity: sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg==} + magic-regexp@0.11.0: + resolution: {integrity: sha512-LG77Z/gVnwz7oaDpD4heX6ryl+lcr4l1B2gnP4MMvt2pGhGC1Dfj7dl1pXpP4ih+VQFLuAadeKVa+lARAzfW+Q==} + magic-string-ast@1.0.3: resolution: {integrity: sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==} engines: {node: '>=20.19.0'} @@ -8576,8 +8600,8 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.5.2: - resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + magicast@0.5.3: + resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -8842,9 +8866,6 @@ packages: mocked-exports@0.1.1: resolution: {integrity: sha512-aF7yRQr/Q0O2/4pIXm6PZ5G+jAd7QS4Yu8m+WEeEHGnbo+7mE36CbLSDQiXYV8bVL3NfmdeqPJct0tUlnjVSnA==} - module-replacements@3.0.0-beta.7: - resolution: {integrity: sha512-n1F9l3gF1wNh13xmnXS2JU7P9c3DlzCgVEyLKrVN0U37RwrXyYoePMMvYvs/6aUONAxbnscphzESZTCorXFh7Q==} - module-replacements@3.0.0-beta.8: resolution: {integrity: sha512-sc8TepP9elxoOBXEpxmhPzKKjTjbswHVcmsKGbgvm3k6jZlLu/WMV/Lfmga6IGMgHU/V3WtY2s6VEgM4nTElUQ==} @@ -8899,8 +8920,8 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.14: + resolution: {integrity: sha512-U9kYi5bpVMEI31yC8iw4bJJp0avcHXA0W8/wNfLfnvJYzihQo2ZRPYPvpAAd570HAcCBjCTN7vnr+v4StKl1IQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -9006,8 +9027,8 @@ packages: nuxt-llms@0.2.0: resolution: {integrity: sha512-GoEW00x8zaZ1wS0R0aOYptt3b54JEaRwlyVtuAiQoH51BwYdjN5/3+00/+4wi39M5cT4j5XcnGwOxJ7v4WVb9A==} - nuxt-og-image@6.4.3: - resolution: {integrity: sha512-c26AHSFGbmalJ6WlAgMaFA2ORjz9pqT0YXypTcbFUYJUYdskWh5q01TZV9IRSqa3BamCTGs7djvzHFwyVnEIkA==} + nuxt-og-image@6.6.0: + resolution: {integrity: sha512-PsnLWVf2D3/pmVvQ/7H17qKtFcKJlH0O611XZhpSx5bEwalNY8tbotmHAqlavhRk5KUvCJBUuCE+QCIW3aBE7w==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: @@ -9017,12 +9038,14 @@ packages: '@takumi-rs/wasm': ^1.0.0-beta.3 '@unhead/vue': ^2.0.5 || ^3.0.0 fontless: ^0.2.0 + nitropack: ^2.13.4 playwright-core: ^1.50.0 satori: '>=0.19.2' sharp: 0.34.5 tailwindcss: ^4.0.0 unifont: ^0.7.0 unstorage: ^1.15.0 + zod: '>=3' peerDependenciesMeta: '@resvg/resvg-js': optional: true @@ -9034,6 +9057,8 @@ packages: optional: true fontless: optional: true + nitropack: + optional: true playwright-core: optional: true satori: @@ -9044,6 +9069,8 @@ packages: optional: true unifont: optional: true + zod: + optional: true nuxt-site-config-kit@4.0.8: resolution: {integrity: sha512-7g3giKXt0M2vssCUg8XFfR6+u4U0zywQ8p8i4msy4p+9etteFNrkrCmVHZ83xiWGFbnoTgiaymPjbaQH3KZqAg==} @@ -9051,9 +9078,9 @@ packages: nuxt-site-config@4.0.8: resolution: {integrity: sha512-H7wHoOJ5Z6ZnTqD5vUugaKkWZbejZ9kGmzpr2dheOaC6RdT8JafCfMrmJG7W+cyJiJJ3YmzL+bzPBW2bW6MExA==} - nuxt@4.4.5: - resolution: {integrity: sha512-MwTf3wyaEIm1U9/T1VKpqg7rGhhrn5Cx2ZS40lwo8GxsiY9xE7UOj5Cg0eAI0fSbJzyXlzdxspytgqWsgL+nIA==} - engines: {node: ^20.19.0 || >=22.12.0} + nuxt@4.4.8: + resolution: {integrity: sha512-r/DGE4cNkEDclOw9tbJ18zqu+ix3me+7QCfumPdl5lBXGWgCajskzuq/HzDkHKfIZsn7ACVEjMLRNA2teh++bQ==} + engines: {node: ^22.12.0 || ^24.11.0 || >=26.0.0} hasBin: true peerDependencies: '@parcel/watcher': ^2.1.0 @@ -9064,8 +9091,8 @@ packages: '@types/node': optional: true - nuxtseo-shared@5.1.3: - resolution: {integrity: sha512-euCaYANxdjeLzJcxvEczKpLuikxPy/LUT/v69orStKlG2U4pvWaqDv74QO8YMCCmUbAO+8BoRj/SJccu9GcJGQ==} + nuxtseo-shared@5.3.0: + resolution: {integrity: sha512-vr7ZIxAbaoZqa1auE5OffY3mj5byCSbgRS9UU7XsdSpsQxUe6h8kW4GhQ/1whXzvQ8z111/mQGvJVqJy2W/bdg==} peerDependencies: '@nuxt/schema': ^3.16.0 || ^4.0.0 nuxt: ^3.16.0 || ^4.0.0 @@ -9078,8 +9105,8 @@ packages: zod: optional: true - nypm@0.6.6: - resolution: {integrity: sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q==} + nypm@0.6.7: + resolution: {integrity: sha512-s3ds97SD5pd1dULE+tHUk1DrV0cSHOnsfpcdGATJ8JpBo21DoKqN9exTH4/2nhPQNOLomBdTFMicN94S4DrZrQ==} engines: {node: '>=18'} hasBin: true @@ -9158,8 +9185,8 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxc-minify@0.128.0: - resolution: {integrity: sha512-VIXQO2W886aB+N17yV55Sack6aCpbUqtuNAYhNcPV6dFiWIZ5+kwOjvvw36igWwoljfjWhasu99CQ5wtvPJDYg==} + oxc-minify@0.133.0: + resolution: {integrity: sha512-6bNsYU+5WNIaNHB16zHnL24cUaJuKiPzUvjENoMale3+U8ZBMbGYgdgt//frx0ge7UcgEGIpqtukGGNPT0kxfQ==} engines: {node: ^20.19.0 || >=22.12.0} oxc-parser@0.112.0: @@ -9174,14 +9201,14 @@ packages: resolution: {integrity: sha512-FktCvLby/mOHyuijZt22+nOt10dS24gGUZE3XwIbUg7Kf4+rer3/5T7RgwzazlNuVsCjPloZ3p8E+4ONT3A8Kw==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-parser@0.128.0: - resolution: {integrity: sha512-XkOw3eiIxAgQ19WRew/Bq9wc5Ga/guaWIzDBzq80z1PyuDNGvWBpPby9k6YGwV8A8uMw+Nlq3xqlzuDYmUFYUw==} - engines: {node: ^20.19.0 || >=22.12.0} - oxc-parser@0.133.0: resolution: {integrity: sha512-661RSx+ZcjBmjBYid+Fpp/2F5EbtildpeoZh5HdgnGs+jZ03nqQEQW8yGkt4BGyOC3OMPDQQRl8M5kqD2/g6jw==} engines: {node: ^20.19.0 || >=22.12.0} + oxc-parser@0.135.0: + resolution: {integrity: sha512-/DaPStu0s2zzNSRRniKyTPM6Z/o+DapOp2JYNKDL8AsgaBGPK2IdZyB87SQjVH+xeQPz+Qr9mrjglfkYgtbVRA==} + engines: {node: ^20.19.0 || >=22.12.0} + oxc-resolver@11.20.0: resolution: {integrity: sha512-CblytBiV/a/ZXY34dsVU2NxhIOxMXst8CvDCtyBelVITgd7PLrKzbEbA6oKLdPjvDKDzCiW48qzmzZ+mYaqn+g==} @@ -9189,8 +9216,8 @@ packages: resolution: {integrity: sha512-cIRRvZgrHfsAHrkt8LWdAX4+Do8R0MzQSfeo9yzErzHeYiuyNiP4PCTPbOy/wBXL4MYzt3ebrBa5jt3akQkKAg==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-transform@0.128.0: - resolution: {integrity: sha512-8DfEHlmUiLOHlCK9DGX+d5tORc1xwPPvoRSHSJCYgLHyGjKp4PvfBrvgi59DkEW0SMOWfO8GL9t+R7vdKtupbg==} + oxc-transform@0.133.0: + resolution: {integrity: sha512-9lt2b+hkG6yqe0fUDMHhMk7rgI9uTjNxU9wauQiYnHzc4kZI8JP/OhBqXTIJQTrqRJ8CkSH3O5AhQ13ke28yNg==} engines: {node: ^20.19.0 || >=22.12.0} oxc-walker@0.7.0: @@ -9198,6 +9225,17 @@ packages: peerDependencies: oxc-parser: '>=0.98.0' + oxc-walker@1.0.0: + resolution: {integrity: sha512-eMsHflAGfOskpWxtp9xP/f5b96XLEU8ifTd2gOOCkdux9HMxKGy5S1ru0Gh1B3aPu+YbfmWUUVkcb7MrZz3XyQ==} + peerDependencies: + oxc-parser: '>=0.98.0' + rolldown: '>=1.0.0' + peerDependenciesMeta: + oxc-parser: + optional: true + rolldown: + optional: true + oxfmt@0.46.0: resolution: {integrity: sha512-CopwJOwPAjZ9p76fCvz+mSOJTw9/NY3cSksZK3VO/bUQ8UoEcketNgUuYS0UB3p+R9XnXe7wGGXUmyFxc7QxJA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -9385,171 +9423,171 @@ packages: peerDependencies: postcss: ^8.4.38 - postcss-colormin@7.0.10: - resolution: {integrity: sha512-yFr6JezOolHLta/buLE71VKPh2mXursp4saVe98/ol8ZnEWhL+racShqPKlvd/DKWLre/39B6HhcMXf7RZ3hxg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-colormin@8.0.1: + resolution: {integrity: sha512-qBY4ABQ6d8/mk5RRZHwMllrZMxeMey3azVY2dZUEk+RgiUC4ARdPR3/AITzNqqKTbvW/3y/MJKinDrzwqn8RDQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-convert-values@7.0.12: - resolution: {integrity: sha512-xurKu5qqk4viR3Cp3p4xBR4KfnZm4w4ys6+UBwBmeuBSNkH7+DtLnYOYnOffgtE4yx8sH9S1VZ6RAAvROXzP2Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-convert-values@8.0.1: + resolution: {integrity: sha512-IdOSIX3BzfMvCc1TAHIha2gfy17xnb5vfML8e2BIKARnFOghksESfaSAB/3CXgyLfMozZAbTRPVQF5dbuKOidw==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-discard-comments@7.0.8: - resolution: {integrity: sha512-CvvS5S9WrXblFXCEJ9nVo+4z+eA7zSC7Z88V1HEJuwlQhlFnYTIjg1xJY+BCUiG2bvICap2tXii4mP22BD108Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-discard-comments@8.0.1: + resolution: {integrity: sha512-FDvzm3tXlEsQBO2XQgnta5ugsAqwBrgWH+j5QgXpegEIDYA0VPnZg2aP7LtmWtC49POskeIhXesFiU/k3NyFHA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-discard-duplicates@7.0.4: - resolution: {integrity: sha512-VBNn1+EuMZkeGVVtz0gRfbNGtx9IFgAsAV+E2pHtXPrp4qfGBkhTIiAuE/wrb+Y6Pakg9NewAlfTpYIFAWODtw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-discard-duplicates@8.0.1: + resolution: {integrity: sha512-stTDXkI8YkCUfADurQhp03oq5ynsgSx6Qrw5B1swds6oTHtAeOZ9I0SHGK8cY/VpWUsIYFDWMs3IWf9jIEfFvA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-discard-empty@7.0.3: - resolution: {integrity: sha512-M2pyjQCU+/7cMHVtL6bKTHjv0lZnPLMpicgr67Dlth7AbuV9gjVTtUqaRwn6Pp6BwSDspUzhz8SaUrRykJU5Dw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-discard-empty@8.0.1: + resolution: {integrity: sha512-Zv4fM1Yfhk71tbt6gfiptbL6jDHi+7apSnaMeaO9n1uET+1embrXQw5m93Zp5x28UyQSuv+AVkFY193jdwZ33w==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-discard-overridden@7.0.3: - resolution: {integrity: sha512-aNovXo9UsZuRNLzHJtp13lHIvinDPfiXBPePpXkSjCbgp++iU2FqE+YxvjIsg6EdyPZsASFbfu+JcBFVsErXIQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-discard-overridden@8.0.1: + resolution: {integrity: sha512-ykt4fvrC7yYGzbxKyqBVjDCbsjF/11JgWK8enrdkobRyqqEtb/uDUCbKOGdvrK8X7BrShW8Lv5cCRNbdkNHGkQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-merge-longhand@7.0.7: - resolution: {integrity: sha512-b3mfYUxR388u5Pt0HPcVIUtUDn/k15UfTY9M+ORW+meCR6JLNxoZffiYvXyOYQoRYQNZyX/UFkMCM/mNHxe1qA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-merge-longhand@8.0.1: + resolution: {integrity: sha512-huTfSYgQ13O81SFvAuOi7GWnO48vvybjj3xF+X3qUoPjzvvaLpJH5DcUqqXcwOEulZUcvaV4s0V9WtWs+IAQPA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-merge-rules@7.0.11: - resolution: {integrity: sha512-SJUPM18g2BmPhf8BVlbwqWz4aK3pLu6u6xjfwEzra7xL6IBR10sUaiB++EzqcVfadPHrKBSMlNdP+XieykhI+Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-merge-rules@8.0.1: + resolution: {integrity: sha512-o3rk4UpnPNg469tklYwbR/NtvKc/f/wJiVDTnNQ/EFPw/LeiPOHUCvV1GIBQIZHGrBAYdPjToK6a+ojYprsrxQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-minify-font-values@7.0.3: - resolution: {integrity: sha512-yilG/VOaNI74IylQvAQQxm3/wZVBkXyYUqNUAdxqwtbWUXPsbK1q8Ms0mL83v+f8YicgcyfYCRZtWACUdYajpA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-minify-font-values@8.0.1: + resolution: {integrity: sha512-L8Nzs/PRlBSPrLdY/7rAiU5ZN5800+2J/4LRbfyG8SJnPljmgMaXVmQiCklvRS+yObfVRNtvmk/Ean/eoYcSeg==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-minify-gradients@7.0.5: - resolution: {integrity: sha512-YraROyQRg3BI1+Hg8E05B/JPdnTm8EDSVu4P2BxdM+CRiOyfmou809+chGIqo6fQqwjPGQ947nbGncSjmTU1WQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-minify-gradients@8.0.1: + resolution: {integrity: sha512-qf+4s/hZMqTwpWN2teqf6+1yvR/SZK5HgHqXYuACeJXV7ABe7AXtBEomgxagUzcN4bSnmqBh5vnIml0dYqykYg==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-minify-params@7.0.9: - resolution: {integrity: sha512-R8itbB8BhlpoYyBm1ou0dD+vJnQ3F6adQipR4UnkCHUwlo+S9WXJaDRg1RHjC8YVAtIdrQzSWvJl40HnGDTKjA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-minify-params@8.0.1: + resolution: {integrity: sha512-L0h3H59deFfFg0wQN1NVaS/8E/LfGvaMuZKGO7siwlG995zo3OshtQyRkqKdVqcBwAORBvZ1nDZrKPLRapYkQw==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-minify-selectors@7.1.2: - resolution: {integrity: sha512-aQtrEWKwqafNlExcKHQvPGsXR2+vlUqqJtf5XsCQcgsSb5PL4wlujWBYDJuWsP4UnQX1YHDHU8qRlD+1PzTQ+Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-minify-selectors@8.0.2: + resolution: {integrity: sha512-3icdxc/zght5UAizdwqZBDE2KOWHf1jMQCxET6iLACeNlRxfTPyXS0/COpGk8CQ2cECyaEKTRUd/i/k8Gxmz4g==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-charset@7.0.3: - resolution: {integrity: sha512-NoBfZu8PR4c2NlmjvrqQTzCzLY79hwcSRgNQ3ZiNK0ABzf9kYKloE/jNj+/8GQY1wsm8pRRgANk6ydLH8cwo0Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-charset@8.0.1: + resolution: {integrity: sha512-xzqr36F8UeIZOvOHsf3aul+RVJCADvSwuwpMLgizqKjisHZpBfztgW0XFLBfJvz9pJgaStaOXAtGb0zLqT6B0w==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-display-values@7.0.3: - resolution: {integrity: sha512-ldsCX0QIt05pKIOobZtVQ48wXJecr+czw4+e1/YjVhLMqslShgpVxgPtI2CefURR8oyVoYaU/l829MMwExDMLw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-display-values@8.0.1: + resolution: {integrity: sha512-ZDWOijOK1FFMlpgiQCUO9fCNKd7HJ9L7z9HWEq4iyubnUFWzdTSwm/LcrMbNW6iZ1oAtqeLYA0WA3xHszOI08g==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-positions@7.0.4: - resolution: {integrity: sha512-VEvlpeGd3Ju1Hqa/oN4jaP3+ms4laYwkEL9N9u+B6k54PZjXbW1n6wI+aVprf1BQXlCYpS5+1pl/7/vHiKgARg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-positions@8.0.1: + resolution: {integrity: sha512-uuivan2poSqbE48ST4do20dGaFUeXey9/H8rhHzoyVHB2I6BmkoVLZ/C9+BRjUlpaAFYVOoDY7epkiidzaYbvA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-repeat-style@7.0.4: - resolution: {integrity: sha512-6mPKlY/8cSaDHxX502wERADarJsccwlky6yIrOapHH2ZgfoKAV94SbiTKfKEs4EEpdazuc3J72WsqeYk7hp9+Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-repeat-style@8.0.1: + resolution: {integrity: sha512-q2hq5fmKxk29K6DjKA3nZ17Q2dtjhLYFNmFweKALmooUqx6UWAHF1bBoWTu/EqlJ88josb82A/J0Atj9LJUmpQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-string@7.0.3: - resolution: {integrity: sha512-HnEQPUchi1eznmDKEYrKUTqrprEq97SrpUYClgUkv7V2zRODD9DFoUsYU+m9ZOetmD5ku7fEMZB/lwy8IT6xVQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-string@8.0.1: + resolution: {integrity: sha512-+Wf+kQJhm1WgSGEAuUaswE9rdpR9QbrKRVemcVHs6rhOoOTVIdAbgaicftfYA6vLM346P8onRzkEVbFN29ktKQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-timing-functions@7.0.3: - resolution: {integrity: sha512-zmEzHdvpZBZu0OKlbJSfgASQvaayyAoVuWtvyr34IJ/LyS+DaOKvvR3EvFJ9RWWtNIx+CMvO125OVophaxNYew==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-timing-functions@8.0.1: + resolution: {integrity: sha512-W8/tvwRlm3T+yjGkg0IRTF4bvHj0vILYr/LOogCrJKHz2ey2HFRwfsAA8Bk9N4BGR7z7WmmDu/KzzwhJ6FoGPQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-unicode@7.0.9: - resolution: {integrity: sha512-DRAdWfeh/TjmhLJsw91vdiWCnUod9iwvM7xyS02/nF/sLsCR3A8l3pztrSUrWG8DSBqfX7yEk9FM0USaVJ2mSg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-unicode@8.0.1: + resolution: {integrity: sha512-Ad0YHNRBp4WHEOYUM/4wL/8MoL2fimEF8se/0q+Rt/owMzYpbxsypC1P8fN/oluwoRmRKdNVX7X2oycEobPWcQ==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-url@7.0.3: - resolution: {integrity: sha512-CL93wmloq5qsffmFv+bw24MIRbmhHrp53qoh1LDAb/5TtjWEXI/np4xcP/Gw9oWCb2XyWnqHYLDUwiKRoJBA1Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-url@8.0.1: + resolution: {integrity: sha512-tkYcip6pCDY806xuxpJYqMW2M3/623jzGFJmz3m5Us47q8P28+gbRZxaea3Rr/CmwwLUiVlh+BTGYwQ6gvaP8A==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-normalize-whitespace@7.0.3: - resolution: {integrity: sha512-FdHjjn+Ht5Z2ZRjNOmeCbNq6lq09sUYKpmlF/Aq0XjVNSLTL6fmHlA/3swN2wP2caY9GV/tjSDcIIyS7aN7W0A==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-normalize-whitespace@8.0.1: + resolution: {integrity: sha512-XzORadNfSrKWDZZpgAEHPKINKx8r9r9RIfE9c70g/HThdpbmPHhDYCodHSVESDxmKeySAYw1p4liuBCf7j6LyA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-ordered-values@7.0.4: - resolution: {integrity: sha512-nubSi49hDHQk4E8KIj+IbLY8Bg+8OcSUEhgyolgM+atnOvXjV7EjaR6bac4YGZoFyPa9mWoAF3EaYbWdFkKqVg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-ordered-values@8.0.1: + resolution: {integrity: sha512-OLXq5lR1yk3KWQ1FPK6aWjFFdktHE9f9kb8cnt4LmIw7w30DnzgD9+sOVYJc5HenkWCX8i1MJhhFwmqc/GYqLg==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-reduce-initial@7.0.9: - resolution: {integrity: sha512-ztTNPdIxXTxtBcG03E9u8v44M4ElXbMIRT7pf2onlquGula0Y83nKKxqM22FA/hMgkfCjN7ohevkVlaNwI8iOQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-reduce-initial@8.0.1: + resolution: {integrity: sha512-+aQsR6+61KRoIfcFNLP3v9RM7+0iYOTtPnjl1wr6JqMW1zx6S+t2ktHRefXwacFdHIDj5+ETG0KY7K3+SGQ4Nw==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-reduce-transforms@7.0.3: - resolution: {integrity: sha512-FXsnN9ZwcZTT8Yf8cAHA8qIGUXcX6WfLd9JoYhrdDfmvsVhhfqkkv7m4AC3rwFOfz+GzkUa87OCKF9dUcicd+g==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-reduce-transforms@8.0.1: + resolution: {integrity: sha512-x71slHVykiFi5RuKEXM0wgYpY2PngC78x6R8TnZhHF3lhqt+u/w3MGwYLX+2t5O87ssRiMfEAhQH+3J4QwVzCw==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-selector-parser@7.1.1: - resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + postcss-selector-parser@7.1.4: + resolution: {integrity: sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==} engines: {node: '>=4'} - postcss-svgo@7.1.3: - resolution: {integrity: sha512-2QfoFOYMcj8lwcVEf9WeTlkVIAm7u2QvOEhMzkQU3KUhhGX/l8hVV9EtjMv4iq3E9iI3OeeMN0YoMLbGusuigw==} - engines: {node: ^18.12.0 || ^20.9.0 || >= 18} + postcss-svgo@8.0.1: + resolution: {integrity: sha512-HpnvWii7W0/FPrsejJa6ZTi0kNtTJP/Iba7CUMPX0xPV6QpnndOp+SDP74tFtgjA2cYKYNWJPOlmLXMsvi/9yA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 - postcss-unique-selectors@7.0.7: - resolution: {integrity: sha512-d+sCkaRnSefghOUdH8CMJZV9yUQhj2ojpe8Nw/lA+LV1UOfeleGkLTl6XdCFFSai9UJ+DJPb69FFuqthXYsY8w==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + postcss-unique-selectors@8.0.1: + resolution: {integrity: sha512-+xvKI5+/Cl8yYQwxDV39Uhuc4WV951xngFvPPjiPj2NIbIfm6vbbRTXblyw0FioLkIoGlw+7qUcY1h2YhaZYgw==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.5.14: - resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} powershell-utils@0.1.0: @@ -9772,10 +9810,6 @@ packages: readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} - readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} - readdirp@5.0.0: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} @@ -10069,8 +10103,8 @@ packages: engines: {node: '>=10'} hasBin: true - semver@7.8.1: - resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==} + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} hasBin: true @@ -10085,8 +10119,8 @@ packages: resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==} engines: {node: '>=20.0.0'} - seroval@1.5.3: - resolution: {integrity: sha512-BXe0x4buEeYiIKaRUnth1WqCILQ3k4O67KP/B4pC3pVz0Mv2c96ngA9QDREUYxWY1sb2RZVRqwI9RcpVMyHCVw==} + seroval@1.5.4: + resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} engines: {node: '>=10'} serve-placeholder@2.0.2: @@ -10268,8 +10302,8 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - srvx@0.11.15: - resolution: {integrity: sha512-iXsux0UcOjdvs0LCMa2Ws3WwcDUozA3JN3BquNXkaFPP7TpRqgunKdEgoZ/uwb1J6xaYHfxtz9Twlh6yzwM6Tg==} + srvx@0.11.17: + resolution: {integrity: sha512-43yM4luKfCJamyCMhrUeHUPOrf8TdZe7kN8s5zayZCH5OeprYqi49Aso5ZvHXR4aB+DHaRNO/diNFgZSMNG8Xw==} engines: {node: '>=20.16.0'} hasBin: true @@ -10396,11 +10430,11 @@ packages: structured-clone-es@2.0.0: resolution: {integrity: sha512-5UuAHmBLXYPCl22xWJrFuGmIhBKQzxISPVz6E7nmTmTcAOpUzlbjKJsRrCE4vADmMQ0dzeCnlWn9XufnAGf76Q==} - stylehacks@7.0.11: - resolution: {integrity: sha512-iODNfhXVLqc5LADs+Y6Oh5wJuK5ZcHbVng8aiK3y9pjMQdc5hLrBW0eFU6FtnpNrE6PoEg/MmFTU4waotj5WNg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + stylehacks@8.0.1: + resolution: {integrity: sha512-Gv095oTD0N+BdJALNFDsxZpETHZLTxbOl5RyIO7y6VAE6sR3z0MnV3Nix7N0IATNldNTrkvSASp2KR1Yt526HA==} + engines: {node: ^22.11.0 || ^24.11.0 || >=26.0} peerDependencies: - postcss: ^8.5.13 + postcss: ^8.5.15 supports-color@10.2.2: resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} @@ -10517,16 +10551,16 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyclip@0.1.12: - resolution: {integrity: sha512-Ae3OVUqifDw0wBriIBS7yVaW44Dp6eSHQcyq4Igc7eN2TJH/2YsicswaW+J/OuMvhpDPOKEgpAZCjkb4hpoyeA==} + tinyclip@0.1.14: + resolution: {integrity: sha512-F1oWdz8tjT17qe1d5JgDK6z03WGOhYYAN0lK3/D/fzNiy93xswLLEw7pk+3g05onhAy6Bsc6PLNUGhdgVjemMQ==} engines: {node: ^16.14.0 || >= 17.3.0} - tinyexec@1.1.1: - resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} - tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} tinypool@2.1.0: @@ -10755,8 +10789,8 @@ packages: unenv@2.0.0-rc.24: resolution: {integrity: sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==} - unhead@2.1.13: - resolution: {integrity: sha512-jO9M1sI6b2h/1KpIu4Jeu+ptumLmUKboRRLxys5pYHFeT+lqTzfNHbYUX9bxVDhC1FBszAGuWcUVlmvIPsah8Q==} + unhead@2.1.15: + resolution: {integrity: sha512-MCt5T90mCWyr3Z6pUCdM9lVRXoMoVBlL7z7U4CYVIiaDiuzad/UCfLuMqz5MeNmpZUgoBCQnrucJimU7EZR+XA==} unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} @@ -10799,14 +10833,17 @@ packages: resolution: {integrity: sha512-8rqAmtJV8o60x46kBAJKtHpJDJWkA2xcBqWKPI14MgUb05o1pnpnCnXSxedUXyeq7p8fR5g3pTo2BaswZ9lD9A==} engines: {node: '>=18.12.0'} - unimport@6.2.0: - resolution: {integrity: sha512-4NcqaphAHQff4eBWQ3pjVOCYNLlmVGGMoLDmboobh8+OQe9yP7UyeoMP043M1bG0YNc3CqtukD2VuINxOqm4rQ==} + unimport@6.3.0: + resolution: {integrity: sha512-M+Dxk5W9WRd+8j56W9tp8lGW/dmMc7g5zj7BWQnEjKQhryBstqsi1V0izb0zHwSkEN8cSYV7K75/bykairV2tA==} engines: {node: '>=18.12.0'} peerDependencies: oxc-parser: '*' + rolldown: ^1.0.0 peerDependenciesMeta: oxc-parser: optional: true + rolldown: + optional: true unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} @@ -10882,11 +10919,11 @@ packages: '@nuxt/kit': optional: true - unplugin-vue-markdown@30.0.0: - resolution: {integrity: sha512-FVdKAb7jmZslfdkOCfm6jxHaUafltBpOXdoLvKY+0I0EeMmhxXTSzeDldwXFJeV0IH8LyIXIiU29E6gv02WJFQ==} - engines: {node: '>=20'} + unplugin-vue-markdown@32.0.0: + resolution: {integrity: sha512-K9uiYJF9kvngrN/NRx8fVPZFXiqJR7tbnXQV4mVFxjcsKhuiL6+vVQ5woam59RqeCDprecBmbg+cCGADz0somA==} + engines: {node: '>=22'} peerDependencies: - vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 + vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 unplugin@2.3.11: resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} @@ -11078,11 +11115,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - vite-plugin-checker@0.13.0: - resolution: {integrity: sha512-14EkOZmfinVZNxRmg2uCNDwtqGc/33lU/UEJansHgu27+ad+r6mMBf1Xtnq57jGZWiO/xzwtiEKPYsganw7ZFQ==} - engines: {node: '>=16.11'} + vite-plugin-checker@0.14.4: + resolution: {integrity: sha512-Tw0U9UgHIRiZ+Yoe4Gh0RrYoBiCVmO9j4tomVdYr0KUjUsqXMPhqW8ouoSWmOzGp5Iimipbl3bNXZcK7OeP7Qg==} + engines: {node: '>=20.19.0'} peerDependencies: - '@biomejs/biome': '>=1.7' + '@biomejs/biome': '>=2.4.12' eslint: '>=9.39.4' meow: ^13.2.0 || ^14.0.0 optionator: ^0.9.4 @@ -11090,8 +11127,6 @@ packages: stylelint: '>=16.26.1' typescript: '*' vite: '>=5.4.21' - vls: '*' - vti: '*' vue-tsc: ~2.2.10 || ^3.0.0 peerDependenciesMeta: '@biomejs/biome': @@ -11108,10 +11143,6 @@ packages: optional: true typescript: optional: true - vls: - optional: true - vti: - optional: true vue-tsc: optional: true @@ -11223,11 +11254,11 @@ packages: vue-component-type-helpers@2.2.12: resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} - vue-component-type-helpers@3.3.3: - resolution: {integrity: sha512-x4nsFpy5Pe8fqPzp/5vkTPeTTDBpAx4WVtV47Ejt0+2FQrq4pRRsJs7JmYRqMFzTu/LW+pCWEjQ3YVCkPV7f9g==} + vue-component-type-helpers@3.3.5: + resolution: {integrity: sha512-Fe1jyPJoUGpJOYKOri44jduR7My4yYINOMJISuMAbmrs+L5LbIDUc8NTWZYY3EJLK0yPLuCmcd5zoCsE4k2/KA==} - vue-data-ui@3.20.11: - resolution: {integrity: sha512-BvK9amlFqGWF40J00guYmy4IYraDV1qrgMgKC48HGvn6HUCGw4HrAhRBr/7eRrRdMkR3ym6E77/GKLQhr1fQow==} + vue-data-ui@3.22.0: + resolution: {integrity: sha512-FwEv+dtzrIny8jYR1qQ8Ye6IYMA7MDCy+86LQAldV5n/iWF1Ebfx6LI8LHfOBXL7mMZLZ0kggeukGo9y1Ssuyw==} peerDependencies: jspdf: '>=3.0.1' vue: '>=3.3.0' @@ -11290,8 +11321,8 @@ packages: peerDependencies: typescript: '>=5.0.0' - vue@3.5.34: - resolution: {integrity: sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==} + vue@3.5.39: + resolution: {integrity: sha512-xmZCYabFGcirU8r0fTuvl/LICc1OU620rnqepaJDL/a141ZigkG7AyaxQLdqJ02ZRYzWe6YPaDHeQx7MfknQfA==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -11609,12 +11640,12 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/vue@3.0.141(vue@3.5.34)(zod@4.3.6)': + '@ai-sdk/vue@3.0.141(vue@3.5.39)(zod@4.3.6)': dependencies: '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) ai: 6.0.141(zod@4.3.6) - swrv: 1.1.0(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + swrv: 1.1.0(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - zod @@ -11707,7 +11738,7 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: package-manager-detector: 1.6.0 - tinyexec: 1.1.1 + tinyexec: 1.2.4 '@apideck/better-ajv-errors@0.3.6(ajv@8.18.0)': dependencies: @@ -12064,7 +12095,7 @@ snapshots: '@babel/code-frame@7.29.0': dependencies: - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 @@ -12077,10 +12108,10 @@ snapshots: '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.28.6 - '@babel/parser': 7.29.3 + '@babel/parser': 7.29.7 '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -12092,8 +12123,8 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -12109,7 +12140,7 @@ snapshots: '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@babel/helper-compilation-targets@7.28.6': dependencies: @@ -12155,14 +12186,14 @@ snapshots: '@babel/helper-member-expression-to-functions@7.28.5': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.28.6': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -12170,14 +12201,14 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@babel/helper-plugin-utils@7.28.6': {} @@ -12202,15 +12233,15 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} '@babel/helper-string-parser@8.0.0-rc.6': {} - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} '@babel/helper-validator-identifier@8.0.0-rc.3': {} @@ -12220,18 +12251,18 @@ snapshots: dependencies: '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color '@babel/helpers@7.28.6': dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 - '@babel/parser@7.29.3': + '@babel/parser@7.29.7': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@babel/parser@8.0.0-rc.3': dependencies: @@ -12475,7 +12506,7 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -12726,7 +12757,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 esutils: 2.0.3 '@babel/runtime@7.28.6': {} @@ -12734,25 +12765,25 @@ snapshots: '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@babel/traverse@7.29.0': dependencies: '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.3 + '@babel/parser': 7.29.7 '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': + '@babel/types@7.29.7': dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 '@babel/types@8.0.0-rc.3': dependencies: @@ -12761,7 +12792,7 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@bomb.sh/tab@0.0.14(cac@6.7.14)(citty@0.2.2)': + '@bomb.sh/tab@0.0.16(cac@6.7.14)(citty@0.2.2)': optionalDependencies: cac: 6.7.14 citty: 0.2.2 @@ -12777,6 +12808,11 @@ snapshots: fast-wrap-ansi: 0.1.6 sisteransi: 1.0.5 + '@clack/core@1.4.2': + dependencies: + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + '@clack/prompts@1.2.0': dependencies: '@clack/core': 1.2.0 @@ -12784,17 +12820,24 @@ snapshots: fast-wrap-ansi: 0.1.6 sisteransi: 1.0.5 + '@clack/prompts@1.6.0': + dependencies: + '@clack/core': 1.4.2 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + '@cloudflare/kv-asset-handler@0.4.2': {} '@colordx/core@5.4.3': {} - '@dxup/nuxt@0.4.1(magicast@0.5.2)(typescript@6.0.2)': + '@dxup/nuxt@0.4.1(magicast@0.5.3)(typescript@6.0.2)': dependencies: '@dxup/unimport': 0.1.2 - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) chokidar: 5.0.0 pathe: 2.0.3 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 optionalDependencies: typescript: 6.0.2 transitivePeerDependencies: @@ -12802,14 +12845,13 @@ snapshots: '@dxup/unimport@0.1.2': {} - '@e18e/eslint-plugin@0.4.1(eslint@9.39.2)(oxlint@1.61.0)': + '@e18e/eslint-plugin@0.5.1(eslint@9.39.2)': dependencies: - empathic: 2.0.0 - module-replacements: 3.0.0-beta.7 - semver: 7.7.4 + empathic: 2.0.1 + module-replacements: 3.0.0-beta.8 + semver: 7.8.5 optionalDependencies: eslint: 9.39.2(jiti@2.7.0) - oxlint: 1.61.0(oxlint-tsgolint@0.22.0) '@emnapi/core@1.10.0': dependencies: @@ -13134,15 +13176,21 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@floating-ui/vue@1.1.11(vue@3.5.34)': + '@floating-ui/vue@1.1.11(vue@3.5.39)': dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 - vue-demi: 0.14.10(vue@3.5.34) + vue-demi: 0.14.10(vue@3.5.39) transitivePeerDependencies: - '@vue/composition-api' - vue + '@floating-ui/vue@2.0.0(vue@3.5.39)': + dependencies: + '@floating-ui/dom': 1.7.6 + '@floating-ui/utils': 0.2.11 + vue: 3.5.39(typescript@6.0.2) + '@hono/node-server@1.19.9(hono@4.12.3)': dependencies: hono: 4.12.3 @@ -13190,10 +13238,10 @@ snapshots: '@iconify/types': 2.0.0 mlly: 1.8.2 - '@iconify/vue@5.0.0(vue@3.5.34)': + '@iconify/vue@5.0.0(vue@3.5.39)': dependencies: '@iconify/types': 2.0.0 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@img/colour@1.0.0': {} @@ -13339,7 +13387,7 @@ snapshots: source-map-js: 1.2.1 yaml-eslint-parser: 1.3.2 optionalDependencies: - vue-i18n: 11.2.8(vue@3.5.34) + vue-i18n: 11.2.8(vue@3.5.39) '@intlify/core-base@11.2.8': dependencies: @@ -13381,12 +13429,12 @@ snapshots: '@intlify/shared@11.3.0': {} - '@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.34)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.2)(vue-i18n@11.2.8)(vue@3.5.34)': + '@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.39)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.2)(vue-i18n@11.2.8)(vue@3.5.39)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) '@intlify/bundle-utils': 11.0.7(vue-i18n@11.2.8) '@intlify/shared': 11.3.0 - '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.34)(vue-i18n@11.2.8)(vue@3.5.34) + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.39)(vue-i18n@11.2.8)(vue@3.5.39) '@rollup/pluginutils': 5.3.0(rollup@4.60.3) '@typescript-eslint/scope-manager': 8.56.1 '@typescript-eslint/typescript-estree': 8.56.1(typescript@6.0.2) @@ -13395,9 +13443,9 @@ snapshots: pathe: 2.0.3 picocolors: 1.1.1 unplugin: 2.3.11 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) optionalDependencies: - vue-i18n: 11.2.8(vue@3.5.34) + vue-i18n: 11.2.8(vue@3.5.39) transitivePeerDependencies: - '@vue/compiler-dom' - eslint @@ -13409,14 +13457,14 @@ snapshots: '@intlify/utils@0.14.1': {} - '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.34)(vue-i18n@11.2.8)(vue@3.5.34)': + '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.3.0)(@vue/compiler-dom@3.5.39)(vue-i18n@11.2.8)(vue@3.5.39)': dependencies: - '@babel/parser': 7.29.3 + '@babel/parser': 7.29.7 optionalDependencies: '@intlify/shared': 11.3.0 - '@vue/compiler-dom': 3.5.34 - vue: 3.5.34(typescript@6.0.2) - vue-i18n: 11.2.8(vue@3.5.34) + '@vue/compiler-dom': 3.5.39 + vue: 3.5.39(typescript@6.0.2) + vue-i18n: 11.2.8(vue@3.5.39) '@ioredis/commands@1.5.1': {} @@ -13515,7 +13563,7 @@ snapshots: path-to-regexp: 6.3.0 picomatch: 4.0.4 simple-git: 3.33.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ultramatter: 0.0.4 zod: 3.25.76 transitivePeerDependencies: @@ -13699,63 +13747,63 @@ snapshots: '@npm/types@2.1.0': {} - '@nuxt/a11y@1.0.0-alpha.1(magicast@0.5.2)(vite@8.0.0)': + '@nuxt/a11y@1.0.0-alpha.1(magicast@0.5.3)(vite@8.0.0)': dependencies: - '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) axe-core: 4.11.2 sirv: 3.0.2 transitivePeerDependencies: - magicast - vite - '@nuxt/cli@3.35.1(@nuxt/schema@4.4.5)(cac@6.7.14)(magicast@0.5.2)': + '@nuxt/cli@3.36.0(@nuxt/schema@4.4.8)(cac@6.7.14)(magicast@0.5.3)': dependencies: - '@bomb.sh/tab': 0.0.14(cac@6.7.14)(citty@0.2.2) - '@clack/prompts': 1.2.0 - c12: 3.3.4(magicast@0.5.2) + '@bomb.sh/tab': 0.0.16(cac@6.7.14)(citty@0.2.2) + '@clack/prompts': 1.6.0 + c12: 3.3.4(magicast@0.5.3) citty: 0.2.2 confbox: 0.2.4 consola: 3.4.2 debug: 4.4.3 defu: 6.1.7 exsolve: 1.0.8 - fuse.js: 7.3.0 + fuse.js: 7.4.2 fzf: 0.5.2 - giget: 3.2.0 + giget: 3.3.0 jiti: 2.7.0 listhen: 1.10.0 - nypm: 0.6.6 + nypm: 0.6.7 ofetch: 1.5.1 ohash: 2.0.11 pathe: 2.0.3 perfect-debounce: 2.1.0 pkg-types: 2.3.1 scule: 1.3.0 - semver: 7.7.4 - srvx: 0.11.15 + semver: 7.8.5 + srvx: 0.11.17 std-env: 4.1.0 - tinyclip: 0.1.12 - tinyexec: 1.1.1 - ufo: 1.6.3 + tinyclip: 0.1.14 + tinyexec: 1.2.4 + ufo: 1.6.4 youch: 4.1.1 optionalDependencies: - '@nuxt/schema': 4.4.5 + '@nuxt/schema': 4.4.8 transitivePeerDependencies: - cac - commander - magicast - supports-color - '@nuxt/content@3.12.0(better-sqlite3@12.8.0)(magicast@0.5.2)(valibot@1.3.1)': + '@nuxt/content@3.12.0(better-sqlite3@12.8.0)(magicast@0.5.3)(valibot@1.3.1)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@nuxtjs/mdc': 0.20.2(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxtjs/mdc': 0.20.2(magicast@0.5.3) '@shikijs/langs': 3.23.0 '@sqlite.org/sqlite-wasm': 3.50.4-build1 '@standard-schema/spec': 1.1.0 '@webcontainer/env': 1.1.1 - c12: 3.3.4(magicast@0.5.2) + c12: 3.3.4(magicast@0.5.3) chokidar: 5.0.0 consola: 3.4.2 db0: 0.3.4(better-sqlite3@12.8.0) @@ -13776,8 +13824,8 @@ snapshots: micromatch: 4.0.8 minimark: 0.2.0 minimatch: 10.2.4 - nuxt-component-meta: 0.17.2(magicast@0.5.2) - nypm: 0.6.6 + nuxt-component-meta: 0.17.2(magicast@0.5.3) + nypm: 0.6.7 ohash: 2.0.11 pathe: 2.0.3 pkg-types: 2.3.1 @@ -13787,7 +13835,7 @@ snapshots: slugify: 1.6.6 socket.io-client: 4.8.3 std-env: 3.10.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ufo: 1.6.3 unctx: 2.5.0 unified: 11.0.5 @@ -13809,47 +13857,47 @@ snapshots: '@nuxt/devalue@2.0.2': {} - '@nuxt/devtools-kit@2.7.0(magicast@0.5.2)(vite@8.0.0)': + '@nuxt/devtools-kit@2.7.0(magicast@0.5.3)(vite@8.0.0)': dependencies: - '@nuxt/kit': 3.21.2(magicast@0.5.2) + '@nuxt/kit': 3.21.2(magicast@0.5.3) execa: 8.0.1 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) transitivePeerDependencies: - magicast - '@nuxt/devtools-kit@3.2.4(magicast@0.5.2)(vite@8.0.0)': + '@nuxt/devtools-kit@3.2.4(magicast@0.5.3)(vite@8.0.0)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) execa: 8.0.1 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) transitivePeerDependencies: - magicast - '@nuxt/devtools-kit@4.0.0-alpha.3(magicast@0.5.2)(vite@8.0.0)': + '@nuxt/devtools-kit@4.0.0-alpha.3(magicast@0.5.3)(vite@8.0.0)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - tinyexec: 1.1.1 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + tinyexec: 1.2.4 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) transitivePeerDependencies: - magicast '@nuxt/devtools-wizard@3.2.4': dependencies: - '@clack/prompts': 1.2.0 + '@clack/prompts': 1.6.0 consola: 3.4.2 diff: 8.0.3 execa: 8.0.1 - magicast: 0.5.2 + magicast: 0.5.3 pathe: 2.0.3 pkg-types: 2.3.1 semver: 7.7.4 - '@nuxt/devtools@3.2.4(vite@8.0.0)(vue@3.5.34)': + '@nuxt/devtools@3.2.4(vite@8.0.0)(vue@3.5.39)': dependencies: - '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@8.0.0) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.0.0) '@nuxt/devtools-wizard': 3.2.4 - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@vue/devtools-core': 8.1.0(vue@3.5.34) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@vue/devtools-core': 8.1.0(vue@3.5.39) '@vue/devtools-kit': 8.1.0 birpc: 4.0.0 consola: 3.4.2 @@ -13863,8 +13911,8 @@ snapshots: is-installed-globally: 1.0.0 launch-editor: 2.13.1 local-pkg: 1.2.1 - magicast: 0.5.2 - nypm: 0.6.6 + magicast: 0.5.3 + nypm: 0.6.7 ohash: 2.0.11 pathe: 2.0.3 perfect-debounce: 2.1.0 @@ -13873,10 +13921,10 @@ snapshots: simple-git: 3.33.0 sirv: 3.0.2 structured-clone-es: 2.0.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) - vite-plugin-inspect: 11.3.3(@nuxt/kit@4.4.6)(vite@8.0.0) - vite-plugin-vue-tracer: 1.3.0(vite@8.0.0)(vue@3.5.34) + vite-plugin-inspect: 11.3.3(@nuxt/kit@4.4.8)(vite@8.0.0) + vite-plugin-vue-tracer: 1.3.0(vite@8.0.0)(vue@3.5.39) which: 6.0.1 ws: 8.19.0 transitivePeerDependencies: @@ -13885,10 +13933,10 @@ snapshots: - utf-8-validate - vue - '@nuxt/fonts@0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(vite@8.0.0)': + '@nuxt/fonts@0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(vite@8.0.0)': dependencies: - '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 defu: 6.1.6 fontless: 0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.0.0) @@ -13897,7 +13945,7 @@ snapshots: ofetch: 1.5.1 pathe: 2.0.3 sirv: 3.0.2 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ufo: 1.6.3 unifont: 0.7.4 unplugin: 3.0.0 @@ -13925,14 +13973,14 @@ snapshots: - uploadthing - vite - '@nuxt/icon@2.2.1(magicast@0.5.2)(vite@8.0.0)(vue@3.5.34)': + '@nuxt/icon@2.2.1(magicast@0.5.3)(vite@8.0.0)(vue@3.5.39)': dependencies: '@iconify/collections': 1.0.654 '@iconify/types': 2.0.0 '@iconify/utils': 3.1.0 - '@iconify/vue': 5.0.0(vue@3.5.34) - '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@iconify/vue': 5.0.0(vue@3.5.39) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 local-pkg: 1.2.1 mlly: 1.8.2 @@ -13940,15 +13988,15 @@ snapshots: pathe: 2.0.3 picomatch: 4.0.4 std-env: 3.10.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 transitivePeerDependencies: - magicast - vite - vue - '@nuxt/image@2.0.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)': + '@nuxt/image@2.0.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 defu: 6.1.6 h3: 1.15.11 @@ -13982,9 +14030,9 @@ snapshots: - magicast - uploadthing - '@nuxt/kit@3.21.2(magicast@0.5.2)': + '@nuxt/kit@3.21.2(magicast@0.5.3)': dependencies: - c12: 3.3.4(magicast@0.5.2) + c12: 3.3.4(magicast@0.5.3) consola: 3.4.2 defu: 6.1.6 destr: 2.0.5 @@ -14001,41 +14049,16 @@ snapshots: rc9: 3.0.1 scule: 1.3.0 semver: 7.7.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ufo: 1.6.3 unctx: 2.5.0 untyped: 2.0.0 transitivePeerDependencies: - magicast - '@nuxt/kit@4.4.5(magicast@0.5.2)': - dependencies: - c12: 3.3.4(magicast@0.5.2) - consola: 3.4.2 - defu: 6.1.7 - destr: 2.0.5 - errx: 0.1.0 - exsolve: 1.0.8 - ignore: 7.0.5 - jiti: 2.7.0 - klona: 2.0.6 - mlly: 1.8.2 - ohash: 2.0.11 - pathe: 2.0.3 - pkg-types: 2.3.1 - rc9: 3.0.1 - scule: 1.3.0 - semver: 7.7.4 - tinyglobby: 0.2.16 - ufo: 1.6.4 - unctx: 2.5.0 - untyped: 2.0.0 - transitivePeerDependencies: - - magicast - - '@nuxt/kit@4.4.6(magicast@0.5.2)': + '@nuxt/kit@4.4.8(magicast@0.5.3)': dependencies: - c12: 3.3.4(magicast@0.5.2) + c12: 3.3.4(magicast@0.5.3) consola: 3.4.2 defu: 6.1.7 destr: 2.0.5 @@ -14050,25 +14073,24 @@ snapshots: pkg-types: 2.3.1 rc9: 3.0.1 scule: 1.3.0 - semver: 7.8.1 - tinyglobby: 0.2.16 + semver: 7.8.5 + tinyglobby: 0.2.17 ufo: 1.6.4 unctx: 2.5.0 untyped: 2.0.0 transitivePeerDependencies: - magicast - '@nuxt/nitro-server@4.4.5(@babel/core@7.29.0)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(oxc-parser@0.128.0)(rolldown@1.0.0-rc.16)(typescript@6.0.2)': + '@nuxt/nitro-server@4.4.8(@babel/plugin-syntax-typescript@7.28.6)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(nuxt@4.4.8)(oxc-parser@0.133.0)(typescript@6.0.2)': dependencies: - '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) '@nuxt/devalue': 2.0.2 - '@nuxt/kit': 4.4.5(magicast@0.5.2) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vue/shared': 3.5.34 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vue/shared': 3.5.39 consola: 3.4.2 defu: 6.1.7 destr: 2.0.5 - devalue: 5.8.0 + devalue: 5.8.1 errx: 0.1.0 escape-string-regexp: 5.0.0 exsolve: 1.0.8 @@ -14076,9 +14098,9 @@ snapshots: impound: 1.1.5 klona: 2.0.6 mocked-exports: 0.1.1 - nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.128.0)(rolldown@1.0.0-rc.16) - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) - nypm: 0.6.6 + nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.133.0) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 ohash: 2.0.11 pathe: 2.0.3 rou3: 0.8.1 @@ -14086,9 +14108,11 @@ snapshots: ufo: 1.6.4 unctx: 2.5.0 unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) vue-bundle-renderer: 2.2.0 vue-devtools-stub: 0.1.0 + optionalDependencies: + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -14096,7 +14120,6 @@ snapshots: - '@azure/identity' - '@azure/keyvault-secrets' - '@azure/storage-blob' - - '@babel/core' - '@capacitor/preferences' - '@deno/kv' - '@electric-sql/pglite' @@ -14126,21 +14149,21 @@ snapshots: - uploadthing - xml2js - '@nuxt/schema@4.4.5': + '@nuxt/schema@4.4.8': dependencies: - '@vue/shared': 3.5.34 + '@vue/shared': 3.5.39 defu: 6.1.7 pathe: 2.0.3 pkg-types: 2.3.1 std-env: 4.1.0 - '@nuxt/scripts@1.0.1(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(typescript@6.0.2)(vite@8.0.0)(vue@3.5.34)': + '@nuxt/scripts@1.0.1(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(typescript@6.0.2)(vite@8.0.0)(vue@3.5.39)': dependencies: - '@nuxt/devtools-kit': 3.2.4(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vueuse/core': 14.3.0(vue@3.5.34) - '@vueuse/shared': 14.2.1(vue@3.5.34) + '@nuxt/devtools-kit': 3.2.4(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vueuse/core': 14.3.0(vue@3.5.39) + '@vueuse/shared': 14.2.1(vue@3.5.39) consola: 3.4.2 defu: 6.1.7 estree-walker: 3.0.3 @@ -14184,21 +14207,21 @@ snapshots: - vite - vue - '@nuxt/telemetry@2.8.0(@nuxt/kit@4.4.5)': + '@nuxt/telemetry@2.8.0(@nuxt/kit@4.4.8)': dependencies: - '@nuxt/kit': 4.4.5(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) citty: 0.2.2 consola: 3.4.2 ofetch: 2.0.0-alpha.3 rc9: 3.0.1 std-env: 4.0.0 - '@nuxt/test-utils@4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.2)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0)': + '@nuxt/test-utils@4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0)': dependencies: '@clack/prompts': 1.2.0 - '@nuxt/devtools-kit': 2.7.0(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 3.21.2(magicast@0.5.2) - c12: 3.3.4(magicast@0.5.2) + '@nuxt/devtools-kit': 2.7.0(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 3.21.2(magicast@0.5.3) + c12: 3.3.4(magicast@0.5.3) consola: 3.4.2 defu: 6.1.7 destr: 2.0.5 @@ -14212,18 +14235,18 @@ snapshots: magic-string: 0.30.21 node-fetch-native: 1.6.7 node-mock-http: 1.0.4 - nypm: 0.6.6 + nypm: 0.6.7 ofetch: 1.5.1 pathe: 2.0.3 perfect-debounce: 2.1.0 radix3: 1.1.2 scule: 1.3.0 std-env: 4.1.0 - tinyexec: 1.1.1 + tinyexec: 1.2.4 ufo: 1.6.3 unplugin: 3.0.0 - vitest-environment-nuxt: 2.0.0(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.2)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) - vue: 3.5.34(typescript@6.0.2) + vitest-environment-nuxt: 2.0.0(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) + vue: 3.5.39(typescript@6.0.2) optionalDependencies: '@playwright/test': 1.60.0 '@vue/test-utils': 2.4.6 @@ -14235,28 +14258,28 @@ snapshots: - typescript - vite - '@nuxt/ui@4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.2)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29)(zod@4.3.6)': + '@nuxt/ui@4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6)': dependencies: '@floating-ui/dom': 1.7.6 - '@iconify/vue': 5.0.0(vue@3.5.34) + '@iconify/vue': 5.0.0(vue@3.5.39) '@internationalized/date': 3.12.2 '@internationalized/number': 3.6.5 - '@nuxt/fonts': 0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(vite@8.0.0) - '@nuxt/icon': 2.2.1(magicast@0.5.2)(vite@8.0.0)(vue@3.5.34) - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@nuxt/schema': 4.4.5 - '@nuxtjs/color-mode': 3.5.2(magicast@0.5.2) + '@nuxt/fonts': 0.14.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(vite@8.0.0) + '@nuxt/icon': 2.2.1(magicast@0.5.3)(vite@8.0.0)(vue@3.5.39) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/schema': 4.4.8 + '@nuxtjs/color-mode': 3.5.2(magicast@0.5.3) '@standard-schema/spec': 1.1.0 '@tailwindcss/postcss': 4.3.0 '@tailwindcss/vite': 4.3.0(vite@8.0.0) - '@tanstack/vue-table': 8.21.3(vue@3.5.34) - '@tanstack/vue-virtual': 3.13.26(vue@3.5.34) + '@tanstack/vue-table': 8.21.3(vue@3.5.39) + '@tanstack/vue-virtual': 3.13.26(vue@3.5.39) '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) '@tiptap/extension-bubble-menu': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) '@tiptap/extension-code': 3.24.0(@tiptap/core@3.24.0) '@tiptap/extension-collaboration': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2)(yjs@13.6.29) '@tiptap/extension-drag-handle': 3.24.0(@tiptap/core@3.24.0)(@tiptap/extension-collaboration@3.24.0)(@tiptap/extension-node-range@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2) - '@tiptap/extension-drag-handle-vue-3': 3.24.0(@tiptap/extension-drag-handle@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/vue-3@3.24.0)(vue@3.5.34) + '@tiptap/extension-drag-handle-vue-3': 3.24.0(@tiptap/extension-drag-handle@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/vue-3@3.24.0)(vue@3.5.39) '@tiptap/extension-floating-menu': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) '@tiptap/extension-horizontal-rule': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) '@tiptap/extension-image': 3.24.0(@tiptap/core@3.24.0) @@ -14267,11 +14290,11 @@ snapshots: '@tiptap/pm': 3.24.0 '@tiptap/starter-kit': 3.24.0 '@tiptap/suggestion': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) - '@tiptap/vue-3': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.34) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vueuse/core': 14.3.0(vue@3.5.34) - '@vueuse/integrations': 14.2.1(focus-trap@8.0.0)(fuse.js@7.3.0)(vue@3.5.34) - '@vueuse/shared': 14.2.1(vue@3.5.34) + '@tiptap/vue-3': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.39) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vueuse/core': 14.3.0(vue@3.5.39) + '@vueuse/integrations': 14.2.1(focus-trap@8.0.0)(fuse.js@7.4.2)(vue@3.5.39) + '@vueuse/shared': 14.2.1(vue@3.5.39) colortranslator: 5.0.0 consola: 3.4.2 defu: 6.1.6 @@ -14280,33 +14303,33 @@ snapshots: embla-carousel-autoplay: 8.6.0(embla-carousel@8.6.0) embla-carousel-class-names: 8.6.0(embla-carousel@8.6.0) embla-carousel-fade: 8.6.0(embla-carousel@8.6.0) - embla-carousel-vue: 8.6.0(vue@3.5.34) + embla-carousel-vue: 8.6.0(vue@3.5.39) embla-carousel-wheel-gestures: 8.1.0(embla-carousel@8.6.0) - fuse.js: 7.3.0 + fuse.js: 7.4.2 hookable: 6.1.1 knitwork: 1.3.0 magic-string: 0.30.21 mlly: 1.8.2 - motion-v: 2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.34) + motion-v: 2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39) ohash: 2.0.11 pathe: 2.0.3 - reka-ui: 2.9.3(vue@3.5.34) + reka-ui: 2.9.3(vue@3.5.39) scule: 1.3.0 tailwind-merge: 3.5.0 tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2) tailwindcss: 4.2.2 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 typescript: 6.0.2 ufo: 1.6.3 unplugin: 3.0.0 - unplugin-auto-import: 21.0.0(@nuxt/kit@4.4.6)(@vueuse/core@14.3.0) - unplugin-vue-components: 32.1.0(@nuxt/kit@4.4.6)(vue@3.5.34) - vaul-vue: 0.4.1(reka-ui@2.9.3)(vue@3.5.34) - vue-component-type-helpers: 3.3.3 + unplugin-auto-import: 21.0.0(@nuxt/kit@4.4.8)(@vueuse/core@14.3.0) + unplugin-vue-components: 32.1.0(@nuxt/kit@4.4.8)(vue@3.5.39) + vaul-vue: 0.4.1(reka-ui@2.9.3)(vue@3.5.39) + vue-component-type-helpers: 3.3.5 optionalDependencies: - '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.2)(valibot@1.3.1) + '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.3)(valibot@1.3.1) valibot: 1.3.1(typescript@6.0.2) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) zod: 4.3.6 transitivePeerDependencies: - '@azure/app-configuration' @@ -14350,15 +14373,15 @@ snapshots: - vue - yjs - '@nuxt/vite-builder@4.4.5(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.2)(nuxt@4.4.5)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.34)(yaml@2.9.0)': + '@nuxt/vite-builder@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0)': dependencies: - '@nuxt/kit': 4.4.5(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) - '@vitejs/plugin-vue': 6.0.6(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.34) - '@vitejs/plugin-vue-jsx': 5.1.5(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.34) - autoprefixer: 10.5.0(postcss@8.5.14) + '@vitejs/plugin-vue': 6.0.7(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39) + '@vitejs/plugin-vue-jsx': 5.1.5(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39) + autoprefixer: 10.5.0(postcss@8.5.15) consola: 3.4.2 - cssnano: 7.1.9(postcss@8.5.14) + cssnano: 8.0.2(postcss@8.5.15) defu: 6.1.7 escape-string-regexp: 5.0.0 exsolve: 1.0.8 @@ -14368,24 +14391,87 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.2 mocked-exports: 0.1.1 - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) - nypm: 0.6.6 + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 pathe: 2.0.3 pkg-types: 2.3.1 - postcss: 8.5.14 - seroval: 1.5.3 + postcss: 8.5.15 + seroval: 1.5.4 std-env: 4.1.0 ufo: 1.6.4 unenv: 2.0.0-rc.24 vite: '@voidzero-dev/vite-plus-core@0.1.20(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0)' vite-node: 5.3.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0) - vite-plugin-checker: 0.13.0(@voidzero-dev/vite-plus-core@0.1.20)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.61.0)(typescript@6.0.2)(vue-tsc@3.2.6) - vue: 3.5.34(typescript@6.0.2) + vite-plugin-checker: 0.14.4(@voidzero-dev/vite-plus-core@0.1.20)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.61.0)(typescript@6.0.2)(vue-tsc@3.2.6) + vue: 3.5.39(typescript@6.0.2) vue-bundle-renderer: 2.2.0 optionalDependencies: '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) - rolldown: 1.0.0-rc.16 - rollup-plugin-visualizer: 7.0.1(rolldown@1.0.0-rc.16)(rollup@4.60.3) + rollup-plugin-visualizer: 7.0.1(rollup@4.60.3) + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@biomejs/biome' + - '@tsdown/css' + - '@tsdown/exe' + - '@types/node' + - '@vitejs/devtools' + - esbuild + - eslint + - less + - magicast + - meow + - optionator + - oxlint + - publint + - rollup + - sass + - sass-embedded + - stylelint + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unplugin-unused + - vue-tsc + - yaml + + '@nuxt/vite-builder@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0)': + dependencies: + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) + '@vitejs/plugin-vue': 6.0.7(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39) + '@vitejs/plugin-vue-jsx': 5.1.5(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39) + autoprefixer: 10.5.0(postcss@8.5.15) + consola: 3.4.2 + cssnano: 8.0.2(postcss@8.5.15) + defu: 6.1.7 + escape-string-regexp: 5.0.0 + exsolve: 1.0.8 + get-port-please: 3.2.0 + jiti: 2.7.0 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.2 + mocked-exports: 0.1.1 + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 + pathe: 2.0.3 + pkg-types: 2.3.1 + postcss: 8.5.15 + seroval: 1.5.4 + std-env: 4.1.0 + ufo: 1.6.4 + unenv: 2.0.0-rc.24 + vite: '@voidzero-dev/vite-plus-core@0.1.20(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0)' + vite-node: 5.3.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0) + vite-plugin-checker: 0.14.4(@voidzero-dev/vite-plus-core@0.1.20)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.61.0)(typescript@6.0.2)(vue-tsc@3.2.6) + vue: 3.5.39(typescript@6.0.2) + vue-bundle-renderer: 2.2.0 + optionalDependencies: + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + rollup-plugin-visualizer: 7.0.1(rollup@4.60.3) transitivePeerDependencies: - '@arethetypeswrong/core' - '@biomejs/biome' @@ -14412,23 +14498,21 @@ snapshots: - tsx - typescript - unplugin-unused - - vls - - vti - vue-tsc - yaml - '@nuxtjs/color-mode@3.5.2(magicast@0.5.2)': + '@nuxtjs/color-mode@3.5.2(magicast@0.5.3)': dependencies: - '@nuxt/kit': 3.21.2(magicast@0.5.2) + '@nuxt/kit': 3.21.2(magicast@0.5.3) pathe: 1.1.2 pkg-types: 1.3.1 semver: 7.7.4 transitivePeerDependencies: - magicast - '@nuxtjs/color-mode@4.0.0(magicast@0.5.2)': + '@nuxtjs/color-mode@4.0.0(magicast@0.5.3)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) exsolve: 1.0.8 pathe: 2.0.3 pkg-types: 2.3.1 @@ -14436,9 +14520,9 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxtjs/html-validator@2.1.0(@voidzero-dev/vite-plus-test@0.1.20)(magicast@0.5.2)': + '@nuxtjs/html-validator@2.1.0(@voidzero-dev/vite-plus-test@0.1.20)(magicast@0.5.3)': dependencies: - '@nuxt/kit': 3.21.2(magicast@0.5.2) + '@nuxt/kit': 3.21.2(magicast@0.5.3) consola: 3.4.2 html-validate: 9.4.2(@voidzero-dev/vite-plus-test@0.1.20) knitwork: 1.3.0 @@ -14452,17 +14536,17 @@ snapshots: - magicast - vitest - '@nuxtjs/i18n@10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.34)': + '@nuxtjs/i18n@10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.39)': dependencies: '@intlify/core': 11.2.8 '@intlify/h3': 0.7.4 '@intlify/shared': 11.3.0 - '@intlify/unplugin-vue-i18n': 11.0.7(@vue/compiler-dom@3.5.34)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.2)(vue-i18n@11.2.8)(vue@3.5.34) + '@intlify/unplugin-vue-i18n': 11.0.7(@vue/compiler-dom@3.5.39)(eslint@9.39.2)(rollup@4.60.3)(typescript@6.0.2)(vue-i18n@11.2.8)(vue@3.5.39) '@intlify/utils': 0.14.1 '@miyaneee/rollup-plugin-json5': 1.2.0(rollup@4.60.3) - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) '@rollup/plugin-yaml': 4.1.2(rollup@4.60.3) - '@vue/compiler-sfc': 3.5.34 + '@vue/compiler-sfc': 3.5.39 defu: 6.1.6 devalue: 5.6.4 h3: 1.15.11 @@ -14479,8 +14563,8 @@ snapshots: unplugin: 2.3.11 unrouting: 0.1.7 unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) - vue-i18n: 11.2.8(vue@3.5.34) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + vue-i18n: 11.2.8(vue@3.5.39) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -14514,28 +14598,28 @@ snapshots: - uploadthing - vue - '@nuxtjs/mcp-toolkit@0.13.4(h3@1.15.11)(magicast@0.5.2)(zod@4.3.6)': + '@nuxtjs/mcp-toolkit@0.13.4(h3@1.15.11)(magicast@0.5.3)(zod@4.3.6)': dependencies: '@modelcontextprotocol/sdk': 1.29.0(zod@4.3.6) - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) h3: 1.15.11 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 zod: 4.3.6 transitivePeerDependencies: - '@cfworker/json-schema' - magicast - supports-color - '@nuxtjs/mdc@0.20.2(magicast@0.5.2)': + '@nuxtjs/mdc@0.20.2(magicast@0.5.3)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) '@shikijs/core': 3.23.0 '@shikijs/langs': 3.23.0 '@shikijs/themes': 3.23.0 '@shikijs/transformers': 3.23.0 '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@vue/compiler-core': 3.5.34 + '@vue/compiler-core': 3.5.39 consola: 3.4.2 debug: 4.4.3 defu: 6.1.6 @@ -14575,9 +14659,9 @@ snapshots: - magicast - supports-color - '@nuxtjs/mdc@0.21.1(magicast@0.5.2)': + '@nuxtjs/mdc@0.21.1(magicast@0.5.3)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) '@shikijs/core': 4.1.0 '@shikijs/engine-javascript': 4.0.2 '@shikijs/langs': 4.0.2 @@ -14585,7 +14669,7 @@ snapshots: '@shikijs/transformers': 4.1.0 '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@vue/compiler-core': 3.5.34 + '@vue/compiler-core': 3.5.39 consola: 3.4.2 debug: 4.4.3 defu: 6.1.6 @@ -14625,15 +14709,15 @@ snapshots: - magicast - supports-color - '@nuxtjs/robots@6.0.9(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6)': + '@nuxtjs/robots@6.0.9(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6)': dependencies: '@fingerprintjs/botd': 2.0.0 - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) consola: 3.4.2 defu: 6.1.7 h3: 1.15.11 - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) - nuxtseo-shared: 5.1.3(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt-site-config@4.0.8)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) pathe: 2.0.3 pkg-types: 2.3.1 ufo: 1.6.4 @@ -14659,68 +14743,68 @@ snapshots: '@opentelemetry/api@1.9.0': {} - '@oxc-minify/binding-android-arm-eabi@0.128.0': + '@oxc-minify/binding-android-arm-eabi@0.133.0': optional: true - '@oxc-minify/binding-android-arm64@0.128.0': + '@oxc-minify/binding-android-arm64@0.133.0': optional: true - '@oxc-minify/binding-darwin-arm64@0.128.0': + '@oxc-minify/binding-darwin-arm64@0.133.0': optional: true - '@oxc-minify/binding-darwin-x64@0.128.0': + '@oxc-minify/binding-darwin-x64@0.133.0': optional: true - '@oxc-minify/binding-freebsd-x64@0.128.0': + '@oxc-minify/binding-freebsd-x64@0.133.0': optional: true - '@oxc-minify/binding-linux-arm-gnueabihf@0.128.0': + '@oxc-minify/binding-linux-arm-gnueabihf@0.133.0': optional: true - '@oxc-minify/binding-linux-arm-musleabihf@0.128.0': + '@oxc-minify/binding-linux-arm-musleabihf@0.133.0': optional: true - '@oxc-minify/binding-linux-arm64-gnu@0.128.0': + '@oxc-minify/binding-linux-arm64-gnu@0.133.0': optional: true - '@oxc-minify/binding-linux-arm64-musl@0.128.0': + '@oxc-minify/binding-linux-arm64-musl@0.133.0': optional: true - '@oxc-minify/binding-linux-ppc64-gnu@0.128.0': + '@oxc-minify/binding-linux-ppc64-gnu@0.133.0': optional: true - '@oxc-minify/binding-linux-riscv64-gnu@0.128.0': + '@oxc-minify/binding-linux-riscv64-gnu@0.133.0': optional: true - '@oxc-minify/binding-linux-riscv64-musl@0.128.0': + '@oxc-minify/binding-linux-riscv64-musl@0.133.0': optional: true - '@oxc-minify/binding-linux-s390x-gnu@0.128.0': + '@oxc-minify/binding-linux-s390x-gnu@0.133.0': optional: true - '@oxc-minify/binding-linux-x64-gnu@0.128.0': + '@oxc-minify/binding-linux-x64-gnu@0.133.0': optional: true - '@oxc-minify/binding-linux-x64-musl@0.128.0': + '@oxc-minify/binding-linux-x64-musl@0.133.0': optional: true - '@oxc-minify/binding-openharmony-arm64@0.128.0': + '@oxc-minify/binding-openharmony-arm64@0.133.0': optional: true - '@oxc-minify/binding-wasm32-wasi@0.128.0': + '@oxc-minify/binding-wasm32-wasi@0.133.0': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@oxc-minify/binding-win32-arm64-msvc@0.128.0': + '@oxc-minify/binding-win32-arm64-msvc@0.133.0': optional: true - '@oxc-minify/binding-win32-ia32-msvc@0.128.0': + '@oxc-minify/binding-win32-ia32-msvc@0.133.0': optional: true - '@oxc-minify/binding-win32-x64-msvc@0.128.0': + '@oxc-minify/binding-win32-x64-msvc@0.133.0': optional: true '@oxc-parser/binding-android-arm-eabi@0.112.0': @@ -14732,10 +14816,10 @@ snapshots: '@oxc-parser/binding-android-arm-eabi@0.126.0': optional: true - '@oxc-parser/binding-android-arm-eabi@0.128.0': + '@oxc-parser/binding-android-arm-eabi@0.133.0': optional: true - '@oxc-parser/binding-android-arm-eabi@0.133.0': + '@oxc-parser/binding-android-arm-eabi@0.135.0': optional: true '@oxc-parser/binding-android-arm64@0.112.0': @@ -14747,10 +14831,10 @@ snapshots: '@oxc-parser/binding-android-arm64@0.126.0': optional: true - '@oxc-parser/binding-android-arm64@0.128.0': + '@oxc-parser/binding-android-arm64@0.133.0': optional: true - '@oxc-parser/binding-android-arm64@0.133.0': + '@oxc-parser/binding-android-arm64@0.135.0': optional: true '@oxc-parser/binding-darwin-arm64@0.112.0': @@ -14762,10 +14846,10 @@ snapshots: '@oxc-parser/binding-darwin-arm64@0.126.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.128.0': + '@oxc-parser/binding-darwin-arm64@0.133.0': optional: true - '@oxc-parser/binding-darwin-arm64@0.133.0': + '@oxc-parser/binding-darwin-arm64@0.135.0': optional: true '@oxc-parser/binding-darwin-x64@0.112.0': @@ -14777,10 +14861,10 @@ snapshots: '@oxc-parser/binding-darwin-x64@0.126.0': optional: true - '@oxc-parser/binding-darwin-x64@0.128.0': + '@oxc-parser/binding-darwin-x64@0.133.0': optional: true - '@oxc-parser/binding-darwin-x64@0.133.0': + '@oxc-parser/binding-darwin-x64@0.135.0': optional: true '@oxc-parser/binding-freebsd-x64@0.112.0': @@ -14792,10 +14876,10 @@ snapshots: '@oxc-parser/binding-freebsd-x64@0.126.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.128.0': + '@oxc-parser/binding-freebsd-x64@0.133.0': optional: true - '@oxc-parser/binding-freebsd-x64@0.133.0': + '@oxc-parser/binding-freebsd-x64@0.135.0': optional: true '@oxc-parser/binding-linux-arm-gnueabihf@0.112.0': @@ -14807,10 +14891,10 @@ snapshots: '@oxc-parser/binding-linux-arm-gnueabihf@0.126.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.128.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': optional: true - '@oxc-parser/binding-linux-arm-gnueabihf@0.133.0': + '@oxc-parser/binding-linux-arm-gnueabihf@0.135.0': optional: true '@oxc-parser/binding-linux-arm-musleabihf@0.112.0': @@ -14822,10 +14906,10 @@ snapshots: '@oxc-parser/binding-linux-arm-musleabihf@0.126.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.128.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': optional: true - '@oxc-parser/binding-linux-arm-musleabihf@0.133.0': + '@oxc-parser/binding-linux-arm-musleabihf@0.135.0': optional: true '@oxc-parser/binding-linux-arm64-gnu@0.112.0': @@ -14837,10 +14921,10 @@ snapshots: '@oxc-parser/binding-linux-arm64-gnu@0.126.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.128.0': + '@oxc-parser/binding-linux-arm64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-arm64-gnu@0.133.0': + '@oxc-parser/binding-linux-arm64-gnu@0.135.0': optional: true '@oxc-parser/binding-linux-arm64-musl@0.112.0': @@ -14852,10 +14936,10 @@ snapshots: '@oxc-parser/binding-linux-arm64-musl@0.126.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.128.0': + '@oxc-parser/binding-linux-arm64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-arm64-musl@0.133.0': + '@oxc-parser/binding-linux-arm64-musl@0.135.0': optional: true '@oxc-parser/binding-linux-ppc64-gnu@0.112.0': @@ -14867,10 +14951,10 @@ snapshots: '@oxc-parser/binding-linux-ppc64-gnu@0.126.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.128.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-ppc64-gnu@0.133.0': + '@oxc-parser/binding-linux-ppc64-gnu@0.135.0': optional: true '@oxc-parser/binding-linux-riscv64-gnu@0.112.0': @@ -14882,10 +14966,10 @@ snapshots: '@oxc-parser/binding-linux-riscv64-gnu@0.126.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.128.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-riscv64-gnu@0.133.0': + '@oxc-parser/binding-linux-riscv64-gnu@0.135.0': optional: true '@oxc-parser/binding-linux-riscv64-musl@0.112.0': @@ -14897,10 +14981,10 @@ snapshots: '@oxc-parser/binding-linux-riscv64-musl@0.126.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.128.0': + '@oxc-parser/binding-linux-riscv64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-riscv64-musl@0.133.0': + '@oxc-parser/binding-linux-riscv64-musl@0.135.0': optional: true '@oxc-parser/binding-linux-s390x-gnu@0.112.0': @@ -14912,10 +14996,10 @@ snapshots: '@oxc-parser/binding-linux-s390x-gnu@0.126.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.128.0': + '@oxc-parser/binding-linux-s390x-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-s390x-gnu@0.133.0': + '@oxc-parser/binding-linux-s390x-gnu@0.135.0': optional: true '@oxc-parser/binding-linux-x64-gnu@0.112.0': @@ -14927,10 +15011,10 @@ snapshots: '@oxc-parser/binding-linux-x64-gnu@0.126.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.128.0': + '@oxc-parser/binding-linux-x64-gnu@0.133.0': optional: true - '@oxc-parser/binding-linux-x64-gnu@0.133.0': + '@oxc-parser/binding-linux-x64-gnu@0.135.0': optional: true '@oxc-parser/binding-linux-x64-musl@0.112.0': @@ -14942,10 +15026,10 @@ snapshots: '@oxc-parser/binding-linux-x64-musl@0.126.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.128.0': + '@oxc-parser/binding-linux-x64-musl@0.133.0': optional: true - '@oxc-parser/binding-linux-x64-musl@0.133.0': + '@oxc-parser/binding-linux-x64-musl@0.135.0': optional: true '@oxc-parser/binding-openharmony-arm64@0.112.0': @@ -14957,10 +15041,10 @@ snapshots: '@oxc-parser/binding-openharmony-arm64@0.126.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.128.0': + '@oxc-parser/binding-openharmony-arm64@0.133.0': optional: true - '@oxc-parser/binding-openharmony-arm64@0.133.0': + '@oxc-parser/binding-openharmony-arm64@0.135.0': optional: true '@oxc-parser/binding-wasm32-wasi@0.112.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': @@ -14986,14 +15070,14 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true - '@oxc-parser/binding-wasm32-wasi@0.128.0': + '@oxc-parser/binding-wasm32-wasi@0.133.0': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@oxc-parser/binding-wasm32-wasi@0.133.0': + '@oxc-parser/binding-wasm32-wasi@0.135.0': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 @@ -15009,10 +15093,10 @@ snapshots: '@oxc-parser/binding-win32-arm64-msvc@0.126.0': optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.128.0': + '@oxc-parser/binding-win32-arm64-msvc@0.133.0': optional: true - '@oxc-parser/binding-win32-arm64-msvc@0.133.0': + '@oxc-parser/binding-win32-arm64-msvc@0.135.0': optional: true '@oxc-parser/binding-win32-ia32-msvc@0.112.0': @@ -15024,10 +15108,10 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc@0.126.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.128.0': + '@oxc-parser/binding-win32-ia32-msvc@0.133.0': optional: true - '@oxc-parser/binding-win32-ia32-msvc@0.133.0': + '@oxc-parser/binding-win32-ia32-msvc@0.135.0': optional: true '@oxc-parser/binding-win32-x64-msvc@0.112.0': @@ -15039,10 +15123,10 @@ snapshots: '@oxc-parser/binding-win32-x64-msvc@0.126.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.128.0': + '@oxc-parser/binding-win32-x64-msvc@0.133.0': optional: true - '@oxc-parser/binding-win32-x64-msvc@0.133.0': + '@oxc-parser/binding-win32-x64-msvc@0.135.0': optional: true '@oxc-project/runtime@0.115.0': {} @@ -15059,10 +15143,10 @@ snapshots: '@oxc-project/types@0.127.0': {} - '@oxc-project/types@0.128.0': {} - '@oxc-project/types@0.133.0': {} + '@oxc-project/types@0.135.0': {} + '@oxc-resolver/binding-android-arm-eabi@11.20.0': optional: true @@ -15127,97 +15211,97 @@ snapshots: '@oxc-transform/binding-android-arm-eabi@0.112.0': optional: true - '@oxc-transform/binding-android-arm-eabi@0.128.0': + '@oxc-transform/binding-android-arm-eabi@0.133.0': optional: true '@oxc-transform/binding-android-arm64@0.112.0': optional: true - '@oxc-transform/binding-android-arm64@0.128.0': + '@oxc-transform/binding-android-arm64@0.133.0': optional: true '@oxc-transform/binding-darwin-arm64@0.112.0': optional: true - '@oxc-transform/binding-darwin-arm64@0.128.0': + '@oxc-transform/binding-darwin-arm64@0.133.0': optional: true '@oxc-transform/binding-darwin-x64@0.112.0': optional: true - '@oxc-transform/binding-darwin-x64@0.128.0': + '@oxc-transform/binding-darwin-x64@0.133.0': optional: true '@oxc-transform/binding-freebsd-x64@0.112.0': optional: true - '@oxc-transform/binding-freebsd-x64@0.128.0': + '@oxc-transform/binding-freebsd-x64@0.133.0': optional: true '@oxc-transform/binding-linux-arm-gnueabihf@0.112.0': optional: true - '@oxc-transform/binding-linux-arm-gnueabihf@0.128.0': + '@oxc-transform/binding-linux-arm-gnueabihf@0.133.0': optional: true '@oxc-transform/binding-linux-arm-musleabihf@0.112.0': optional: true - '@oxc-transform/binding-linux-arm-musleabihf@0.128.0': + '@oxc-transform/binding-linux-arm-musleabihf@0.133.0': optional: true '@oxc-transform/binding-linux-arm64-gnu@0.112.0': optional: true - '@oxc-transform/binding-linux-arm64-gnu@0.128.0': + '@oxc-transform/binding-linux-arm64-gnu@0.133.0': optional: true '@oxc-transform/binding-linux-arm64-musl@0.112.0': optional: true - '@oxc-transform/binding-linux-arm64-musl@0.128.0': + '@oxc-transform/binding-linux-arm64-musl@0.133.0': optional: true '@oxc-transform/binding-linux-ppc64-gnu@0.112.0': optional: true - '@oxc-transform/binding-linux-ppc64-gnu@0.128.0': + '@oxc-transform/binding-linux-ppc64-gnu@0.133.0': optional: true '@oxc-transform/binding-linux-riscv64-gnu@0.112.0': optional: true - '@oxc-transform/binding-linux-riscv64-gnu@0.128.0': + '@oxc-transform/binding-linux-riscv64-gnu@0.133.0': optional: true '@oxc-transform/binding-linux-riscv64-musl@0.112.0': optional: true - '@oxc-transform/binding-linux-riscv64-musl@0.128.0': + '@oxc-transform/binding-linux-riscv64-musl@0.133.0': optional: true '@oxc-transform/binding-linux-s390x-gnu@0.112.0': optional: true - '@oxc-transform/binding-linux-s390x-gnu@0.128.0': + '@oxc-transform/binding-linux-s390x-gnu@0.133.0': optional: true '@oxc-transform/binding-linux-x64-gnu@0.112.0': optional: true - '@oxc-transform/binding-linux-x64-gnu@0.128.0': + '@oxc-transform/binding-linux-x64-gnu@0.133.0': optional: true '@oxc-transform/binding-linux-x64-musl@0.112.0': optional: true - '@oxc-transform/binding-linux-x64-musl@0.128.0': + '@oxc-transform/binding-linux-x64-musl@0.133.0': optional: true '@oxc-transform/binding-openharmony-arm64@0.112.0': optional: true - '@oxc-transform/binding-openharmony-arm64@0.128.0': + '@oxc-transform/binding-openharmony-arm64@0.133.0': optional: true '@oxc-transform/binding-wasm32-wasi@0.112.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': @@ -15228,7 +15312,7 @@ snapshots: - '@emnapi/runtime' optional: true - '@oxc-transform/binding-wasm32-wasi@0.128.0': + '@oxc-transform/binding-wasm32-wasi@0.133.0': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 @@ -15238,19 +15322,19 @@ snapshots: '@oxc-transform/binding-win32-arm64-msvc@0.112.0': optional: true - '@oxc-transform/binding-win32-arm64-msvc@0.128.0': + '@oxc-transform/binding-win32-arm64-msvc@0.133.0': optional: true '@oxc-transform/binding-win32-ia32-msvc@0.112.0': optional: true - '@oxc-transform/binding-win32-ia32-msvc@0.128.0': + '@oxc-transform/binding-win32-ia32-msvc@0.133.0': optional: true '@oxc-transform/binding-win32-x64-msvc@0.112.0': optional: true - '@oxc-transform/binding-win32-x64-msvc@0.128.0': + '@oxc-transform/binding-win32-x64-msvc@0.133.0': optional: true '@oxfmt/binding-android-arm-eabi@0.46.0': @@ -15626,12 +15710,12 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.12': {} - '@rolldown/pluginutils@1.0.0-rc.13': {} - '@rolldown/pluginutils@1.0.0-rc.16': {} '@rolldown/pluginutils@1.0.0-rc.9': {} + '@rolldown/pluginutils@1.0.1': {} + '@rollup/plugin-alias@6.0.0(rollup@4.60.3)': optionalDependencies: rollup: 4.60.3 @@ -15950,25 +16034,25 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@storybook-vue/nuxt@https://pkg.pr.new/@storybook-vue/nuxt@1021(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.34)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.2)(nuxt@4.4.5)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(storybook@10.3.5)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(vue@3.5.34)(webpack@5.104.1)(yaml@2.9.0)': + '@storybook-vue/nuxt@https://pkg.pr.new/@storybook-vue/nuxt@1021(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(@vue/compiler-sfc@3.5.39)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(storybook@10.3.5)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(vue@3.5.39)(webpack@5.104.1)(yaml@2.9.0)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@nuxt/schema': 4.4.5 - '@nuxt/vite-builder': 4.4.5(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.2)(nuxt@4.4.5)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.34)(yaml@2.9.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/schema': 4.4.8 + '@nuxt/vite-builder': 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0) '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) '@storybook/builder-vite': 10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(webpack@5.104.1) - '@storybook/vue3': 10.3.4(storybook@10.3.5)(vue@3.5.34) - '@storybook/vue3-vite': 10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(vue@3.5.34)(webpack@5.104.1) + '@storybook/vue3': 10.3.4(storybook@10.3.5)(vue@3.5.39) + '@storybook/vue3-vite': 10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(vue@3.5.39)(webpack@5.104.1) json-stable-stringify: 1.3.0 mlly: 1.8.2 - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) ofetch: 1.5.1 pathe: 2.0.3 storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4)(react@19.2.4) unctx: 2.5.0 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) - vue: 3.5.34(typescript@6.0.2) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + vue: 3.5.39(typescript@6.0.2) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) transitivePeerDependencies: - '@arethetypeswrong/core' - '@babel/plugin-proposal-decorators' @@ -16002,8 +16086,6 @@ snapshots: - tsx - typescript - unplugin-unused - - vls - - vti - vue-tsc - webpack - yaml @@ -16080,29 +16162,29 @@ snapshots: react-dom: 19.2.4(react@19.2.4) storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4)(react@19.2.4) - '@storybook/vue3-vite@10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(vue@3.5.34)(webpack@5.104.1)': + '@storybook/vue3-vite@10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(vue@3.5.39)(webpack@5.104.1)': dependencies: '@storybook/builder-vite': 10.3.4(esbuild@0.27.3)(rollup@4.60.3)(storybook@10.3.5)(vite@8.0.0)(webpack@5.104.1) - '@storybook/vue3': 10.3.4(storybook@10.3.5)(vue@3.5.34) + '@storybook/vue3': 10.3.4(storybook@10.3.5)(vue@3.5.39) magic-string: 0.30.21 storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4)(react@19.2.4) typescript: 5.9.3 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) vue-component-meta: 2.2.12(typescript@5.9.3) - vue-docgen-api: 4.79.2(vue@3.5.34) + vue-docgen-api: 4.79.2(vue@3.5.39) transitivePeerDependencies: - esbuild - rollup - vue - webpack - '@storybook/vue3@10.3.4(storybook@10.3.5)(vue@3.5.34)': + '@storybook/vue3@10.3.4(storybook@10.3.5)(vue@3.5.39)': dependencies: '@storybook/global': 5.0.0 storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4)(react@19.2.4) type-fest: 2.19.0 - vue: 3.5.34(typescript@6.0.2) - vue-component-type-helpers: 3.3.3 + vue: 3.5.39(typescript@6.0.2) + vue-component-type-helpers: 3.3.5 '@surma/rollup-plugin-off-main-thread@2.2.3': dependencies: @@ -16181,7 +16263,7 @@ snapshots: '@alloc/quick-lru': 5.2.0 '@tailwindcss/node': 4.3.0 '@tailwindcss/oxide': 4.3.0 - postcss: 8.5.14 + postcss: 8.5.15 tailwindcss: 4.3.0 '@tailwindcss/vite@4.3.0(vite@8.0.0)': @@ -16287,15 +16369,15 @@ snapshots: '@tanstack/virtual-core@3.16.0': {} - '@tanstack/vue-table@8.21.3(vue@3.5.34)': + '@tanstack/vue-table@8.21.3(vue@3.5.39)': dependencies: '@tanstack/table-core': 8.21.3 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) - '@tanstack/vue-virtual@3.13.26(vue@3.5.34)': + '@tanstack/vue-virtual@3.13.26(vue@3.5.39)': dependencies: '@tanstack/virtual-core': 3.16.0 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@testing-library/dom@10.4.1': dependencies: @@ -16363,12 +16445,12 @@ snapshots: dependencies: '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) - '@tiptap/extension-drag-handle-vue-3@3.24.0(@tiptap/extension-drag-handle@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/vue-3@3.24.0)(vue@3.5.34)': + '@tiptap/extension-drag-handle-vue-3@3.24.0(@tiptap/extension-drag-handle@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/vue-3@3.24.0)(vue@3.5.39)': dependencies: '@tiptap/extension-drag-handle': 3.24.0(@tiptap/core@3.24.0)(@tiptap/extension-collaboration@3.24.0)(@tiptap/extension-node-range@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2) '@tiptap/pm': 3.24.0 - '@tiptap/vue-3': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + '@tiptap/vue-3': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) '@tiptap/extension-drag-handle@3.24.0(@tiptap/core@3.24.0)(@tiptap/extension-collaboration@3.24.0)(@tiptap/extension-node-range@3.24.0)(@tiptap/pm@3.24.0)(@tiptap/y-tiptap@3.0.2)': dependencies: @@ -16527,12 +16609,12 @@ snapshots: '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) '@tiptap/pm': 3.24.0 - '@tiptap/vue-3@3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.34)': + '@tiptap/vue-3@3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0)(vue@3.5.39)': dependencies: '@floating-ui/dom': 1.7.6 '@tiptap/core': 3.24.0(@tiptap/pm@3.24.0) '@tiptap/pm': 3.24.0 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) optionalDependencies: '@tiptap/extension-bubble-menu': 3.24.0(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) '@tiptap/extension-floating-menu': 3.24.0(@floating-ui/dom@1.7.6)(@tiptap/core@3.24.0)(@tiptap/pm@3.24.0) @@ -16550,7 +16632,7 @@ snapshots: dependencies: minimatch: 10.2.4 path-browserify: 1.0.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 '@tybys/wasm-util@0.10.1': dependencies: @@ -16678,7 +16760,7 @@ snapshots: debug: 4.4.3 minimatch: 10.2.4 semver: 7.7.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ts-api-utils: 2.4.0(typescript@6.0.2) typescript: 6.0.2 transitivePeerDependencies: @@ -16691,11 +16773,11 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@unhead/vue@2.1.13(vue@3.5.34)': + '@unhead/vue@2.1.15(vue@3.5.39)': dependencies: hookable: 6.1.1 - unhead: 2.1.13 - vue: 3.5.34(typescript@6.0.2) + unhead: 2.1.15 + vue: 3.5.39(typescript@6.0.2) '@unocss/cli@66.6.7': dependencies: @@ -16712,7 +16794,7 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 perfect-debounce: 2.1.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin-utils: 0.3.1 '@unocss/config@66.6.7': @@ -16722,8 +16804,17 @@ snapshots: consola: 3.4.2 unconfig: 7.5.0 + '@unocss/config@66.7.2': + dependencies: + '@unocss/core': 66.7.2 + colorette: 2.0.20 + consola: 3.4.2 + unconfig: 7.5.0 + '@unocss/core@66.6.7': {} + '@unocss/core@66.7.2': {} + '@unocss/extractor-arbitrary-variants@66.6.7': dependencies: '@unocss/core': 66.6.7 @@ -16736,9 +16827,9 @@ snapshots: gzip-size: 6.0.0 sirv: 3.0.2 - '@unocss/nuxt@66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(magicast@0.5.2)(vite@8.0.0)(webpack@5.104.1)': + '@unocss/nuxt@66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(magicast@0.5.3)(vite@8.0.0)(webpack@5.104.1)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) '@unocss/config': 66.6.7 '@unocss/core': 66.6.7 '@unocss/preset-attributify': 66.6.7 @@ -16817,7 +16908,7 @@ snapshots: '@unocss/rule-utils@66.6.7': dependencies: - '@unocss/core': 66.6.7 + '@unocss/core': 66.7.2 magic-string: 0.30.21 '@unocss/transformer-attributify-jsx@66.6.7(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': @@ -16852,7 +16943,7 @@ snapshots: chokidar: 5.0.0 magic-string: 0.30.21 pathe: 2.0.3 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin-utils: 0.3.1 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) @@ -16864,7 +16955,7 @@ snapshots: chokidar: 5.0.0 magic-string: 0.30.21 pathe: 2.0.3 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin: 2.3.11 unplugin-utils: 0.3.1 webpack: 5.104.1(esbuild@0.27.3) @@ -16895,12 +16986,12 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vercel/speed-insights@2.0.0(nuxt@4.4.5)(react@19.2.4)(vue-router@5.0.4)(vue@3.5.34)': + '@vercel/speed-insights@2.0.0(nuxt@4.4.8)(react@19.2.4)(vue-router@5.0.4)(vue@3.5.39)': optionalDependencies: - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) react: 19.2.4 - vue: 3.5.34(typescript@6.0.2) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + vue: 3.5.39(typescript@6.0.2) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) '@vite-pwa/assets-generator@1.0.2': dependencies: @@ -16911,9 +17002,9 @@ snapshots: sharp-ico: 0.1.5 unconfig: 7.5.0 - '@vite-pwa/nuxt@1.1.1(@vite-pwa/assets-generator@1.0.2)(magicast@0.5.2)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0)': + '@vite-pwa/nuxt@1.1.1(@vite-pwa/assets-generator@1.0.2)(magicast@0.5.3)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0)': dependencies: - '@nuxt/kit': 3.21.2(magicast@0.5.2) + '@nuxt/kit': 3.21.2(magicast@0.5.3) pathe: 1.1.2 ufo: 1.6.3 vite-plugin-pwa: 1.3.0(@vite-pwa/assets-generator@1.0.2)(vite@8.0.0)(workbox-build@7.4.0)(workbox-window@7.4.0) @@ -16926,23 +17017,23 @@ snapshots: - workbox-build - workbox-window - '@vitejs/plugin-vue-jsx@5.1.5(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.34)': + '@vitejs/plugin-vue-jsx@5.1.5(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39)': dependencies: '@babel/core': 7.29.0 '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-rc.16 + '@rolldown/pluginutils': 1.0.1 '@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0) vite: '@voidzero-dev/vite-plus-core@0.1.20(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0)' - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@6.0.6(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.34)': + '@vitejs/plugin-vue@6.0.7(@voidzero-dev/vite-plus-core@0.1.20)(vue@3.5.39)': dependencies: - '@rolldown/pluginutils': 1.0.0-rc.13 + '@rolldown/pluginutils': 1.0.1 vite: '@voidzero-dev/vite-plus-core@0.1.20(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0)' - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@vitest/coverage-v8@4.1.6(@voidzero-dev/vite-plus-test@0.1.20)': dependencies: @@ -16952,7 +17043,7 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - magicast: 0.5.2 + magicast: 0.5.3 obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 @@ -16995,7 +17086,7 @@ snapshots: '@oxc-project/runtime': 0.127.0 '@oxc-project/types': 0.127.0 lightningcss: 1.32.0 - postcss: 8.5.14 + postcss: 8.5.15 optionalDependencies: '@types/node': 24.12.0 esbuild: 0.27.3 @@ -17035,8 +17126,8 @@ snapshots: sirv: 3.0.2 std-env: 4.0.0 tinybench: 2.9.0 - tinyexec: 1.1.1 - tinyglobby: 0.2.16 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) ws: 8.19.0 optionalDependencies: @@ -17094,15 +17185,15 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue-macros/common@3.1.2(vue@3.5.34)': + '@vue-macros/common@3.1.2(vue@3.5.39)': dependencies: - '@vue/compiler-sfc': 3.5.34 + '@vue/compiler-sfc': 3.5.39 ast-kit: 2.2.0 local-pkg: 1.2.1 magic-string-ast: 1.0.3 unplugin-utils: 0.3.1 optionalDependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@vue/babel-helper-vue-transform-on@2.0.1': {} @@ -17113,10 +17204,10 @@ snapshots: '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) '@babel/template': 7.28.6 '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@vue/babel-helper-vue-transform-on': 2.0.1 '@vue/babel-plugin-resolve-type': 2.0.1(@babel/core@7.29.0) - '@vue/shared': 3.5.34 + '@vue/shared': 3.5.39 optionalDependencies: '@babel/core': 7.29.0 transitivePeerDependencies: @@ -17128,40 +17219,40 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 '@babel/helper-plugin-utils': 7.28.6 - '@babel/parser': 7.29.3 - '@vue/compiler-sfc': 3.5.34 + '@babel/parser': 7.29.7 + '@vue/compiler-sfc': 3.5.39 transitivePeerDependencies: - supports-color - '@vue/compiler-core@3.5.34': + '@vue/compiler-core@3.5.39': dependencies: - '@babel/parser': 7.29.3 - '@vue/shared': 3.5.34 + '@babel/parser': 7.29.7 + '@vue/shared': 3.5.39 entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.34': + '@vue/compiler-dom@3.5.39': dependencies: - '@vue/compiler-core': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/compiler-core': 3.5.39 + '@vue/shared': 3.5.39 - '@vue/compiler-sfc@3.5.34': + '@vue/compiler-sfc@3.5.39': dependencies: - '@babel/parser': 7.29.3 - '@vue/compiler-core': 3.5.34 - '@vue/compiler-dom': 3.5.34 - '@vue/compiler-ssr': 3.5.34 - '@vue/shared': 3.5.34 + '@babel/parser': 7.29.7 + '@vue/compiler-core': 3.5.39 + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-ssr': 3.5.39 + '@vue/shared': 3.5.39 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.14 + postcss: 8.5.15 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.34': + '@vue/compiler-ssr@3.5.39': dependencies: - '@vue/compiler-dom': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/compiler-dom': 3.5.39 + '@vue/shared': 3.5.39 '@vue/compiler-vue2@2.7.16': dependencies: @@ -17174,11 +17265,11 @@ snapshots: dependencies: '@vue/devtools-kit': 8.1.0 - '@vue/devtools-core@8.1.0(vue@3.5.34)': + '@vue/devtools-core@8.1.0(vue@3.5.39)': dependencies: '@vue/devtools-kit': 8.1.0 '@vue/devtools-shared': 8.1.0 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@vue/devtools-kit@8.1.0': dependencies: @@ -17192,9 +17283,9 @@ snapshots: '@vue/language-core@2.2.12(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.15 - '@vue/compiler-dom': 3.5.34 + '@vue/compiler-dom': 3.5.39 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.34 + '@vue/shared': 3.5.39 alien-signals: 1.0.13 minimatch: 9.0.5 muggle-string: 0.4.1 @@ -17205,8 +17296,8 @@ snapshots: '@vue/language-core@3.2.5': dependencies: '@volar/language-core': 2.4.28 - '@vue/compiler-dom': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/compiler-dom': 3.5.39 + '@vue/shared': 3.5.39 alien-signals: 3.1.2 muggle-string: 0.4.1 path-browserify: 1.0.1 @@ -17215,74 +17306,74 @@ snapshots: '@vue/language-core@3.2.6': dependencies: '@volar/language-core': 2.4.28 - '@vue/compiler-dom': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/compiler-dom': 3.5.39 + '@vue/shared': 3.5.39 alien-signals: 3.1.2 muggle-string: 0.4.1 path-browserify: 1.0.1 picomatch: 4.0.4 - '@vue/reactivity@3.5.34': + '@vue/reactivity@3.5.39': dependencies: - '@vue/shared': 3.5.34 + '@vue/shared': 3.5.39 - '@vue/runtime-core@3.5.34': + '@vue/runtime-core@3.5.39': dependencies: - '@vue/reactivity': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/reactivity': 3.5.39 + '@vue/shared': 3.5.39 - '@vue/runtime-dom@3.5.34': + '@vue/runtime-dom@3.5.39': dependencies: - '@vue/reactivity': 3.5.34 - '@vue/runtime-core': 3.5.34 - '@vue/shared': 3.5.34 + '@vue/reactivity': 3.5.39 + '@vue/runtime-core': 3.5.39 + '@vue/shared': 3.5.39 csstype: 3.2.3 - '@vue/server-renderer@3.5.34(vue@3.5.34)': + '@vue/server-renderer@3.5.39(vue@3.5.39)': dependencies: - '@vue/compiler-ssr': 3.5.34 - '@vue/shared': 3.5.34 - vue: 3.5.34(typescript@6.0.2) + '@vue/compiler-ssr': 3.5.39 + '@vue/shared': 3.5.39 + vue: 3.5.39(typescript@6.0.2) - '@vue/shared@3.5.34': {} + '@vue/shared@3.5.39': {} '@vue/test-utils@2.4.6': dependencies: js-beautify: 1.15.4 vue-component-type-helpers: 2.2.12 - '@vueuse/core@10.11.1(vue@3.5.34)': + '@vueuse/core@10.11.1(vue@3.5.39)': dependencies: '@types/web-bluetooth': 0.0.20 '@vueuse/metadata': 10.11.1 - '@vueuse/shared': 10.11.1(vue@3.5.34) - vue-demi: 0.14.10(vue@3.5.34) + '@vueuse/shared': 10.11.1(vue@3.5.39) + vue-demi: 0.14.10(vue@3.5.39) transitivePeerDependencies: - '@vue/composition-api' - vue - '@vueuse/core@14.2.1(vue@3.5.34)': + '@vueuse/core@14.2.1(vue@3.5.39)': dependencies: '@types/web-bluetooth': 0.0.21 '@vueuse/metadata': 14.2.1 - '@vueuse/shared': 14.2.1(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + '@vueuse/shared': 14.2.1(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) - '@vueuse/core@14.3.0(vue@3.5.34)': + '@vueuse/core@14.3.0(vue@3.5.39)': dependencies: '@types/web-bluetooth': 0.0.21 '@vueuse/metadata': 14.3.0 - '@vueuse/shared': 14.3.0(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + '@vueuse/shared': 14.3.0(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) - '@vueuse/integrations@14.2.1(focus-trap@8.0.0)(fuse.js@7.3.0)(vue@3.5.34)': + '@vueuse/integrations@14.2.1(focus-trap@8.0.0)(fuse.js@7.4.2)(vue@3.5.39)': dependencies: - '@vueuse/core': 14.2.1(vue@3.5.34) - '@vueuse/shared': 14.2.1(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + '@vueuse/core': 14.2.1(vue@3.5.39) + '@vueuse/shared': 14.2.1(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) optionalDependencies: focus-trap: 8.0.0 - fuse.js: 7.3.0 + fuse.js: 7.4.2 '@vueuse/metadata@10.11.1': {} @@ -17290,37 +17381,37 @@ snapshots: '@vueuse/metadata@14.3.0': {} - '@vueuse/nuxt@14.2.1(magicast@0.5.2)(nuxt@4.4.5)(vue@3.5.34)': + '@vueuse/nuxt@14.2.1(magicast@0.5.3)(nuxt@4.4.8)(vue@3.5.39)': dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@vueuse/core': 14.2.1(vue@3.5.34) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@vueuse/core': 14.2.1(vue@3.5.39) '@vueuse/metadata': 14.2.1 local-pkg: 1.2.1 - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) - vue: 3.5.34(typescript@6.0.2) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - magicast - '@vueuse/router@14.2.1(vue-router@5.0.4)(vue@3.5.34)': + '@vueuse/router@14.2.1(vue-router@5.0.4)(vue@3.5.39)': dependencies: - '@vueuse/shared': 14.2.1(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + '@vueuse/shared': 14.2.1(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) - '@vueuse/shared@10.11.1(vue@3.5.34)': + '@vueuse/shared@10.11.1(vue@3.5.39)': dependencies: - vue-demi: 0.14.10(vue@3.5.34) + vue-demi: 0.14.10(vue@3.5.39) transitivePeerDependencies: - '@vue/composition-api' - vue - '@vueuse/shared@14.2.1(vue@3.5.34)': + '@vueuse/shared@14.2.1(vue@3.5.39)': dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) - '@vueuse/shared@14.3.0(vue@3.5.34)': + '@vueuse/shared@14.3.0(vue@3.5.39)': dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) '@webassemblyjs/ast@1.14.1': dependencies: @@ -17572,7 +17663,7 @@ snapshots: ast-kit@2.2.0: dependencies: - '@babel/parser': 7.29.3 + '@babel/parser': 7.29.7 pathe: 2.0.3 ast-kit@3.0.0-beta.1: @@ -17593,7 +17684,7 @@ snapshots: ast-walker-scope@0.8.3: dependencies: - '@babel/parser': 7.29.3 + '@babel/parser': 7.29.7 ast-kit: 2.2.0 async-function@1.0.0: {} @@ -17608,13 +17699,13 @@ snapshots: atomic-sleep@1.0.0: {} - autoprefixer@10.5.0(postcss@8.5.14): + autoprefixer@10.5.0(postcss@8.5.15): dependencies: browserslist: 4.28.2 caniuse-lite: 1.0.30001791 fraction.js: 5.3.4 picocolors: 1.1.1 - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -17653,7 +17744,7 @@ snapshots: babel-walk@3.0.0-canary-5: dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 bail@2.0.2: {} @@ -17751,14 +17842,14 @@ snapshots: bytes@3.1.2: {} - c12@3.3.4(magicast@0.5.2): + c12@3.3.4(magicast@0.5.3): dependencies: chokidar: 5.0.0 confbox: 0.2.4 defu: 6.1.6 dotenv: 17.4.2 exsolve: 1.0.8 - giget: 3.2.0 + giget: 3.3.0 jiti: 2.7.0 ohash: 2.0.11 pathe: 2.0.3 @@ -17766,7 +17857,7 @@ snapshots: pkg-types: 2.3.1 rc9: 3.0.1 optionalDependencies: - magicast: 0.5.2 + magicast: 0.5.3 cac@6.7.14: {} @@ -17791,12 +17882,10 @@ snapshots: callsites@3.1.0: {} - caniuse-api@3.0.0: + caniuse-api@4.0.0: dependencies: browserslist: 4.28.2 caniuse-lite: 1.0.30001791 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 caniuse-lite@1.0.30001791: {} @@ -17817,9 +17906,9 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - changelogen@0.6.2(magicast@0.5.2): + changelogen@0.6.2(magicast@0.5.3): dependencies: - c12: 3.3.4(magicast@0.5.2) + c12: 3.3.4(magicast@0.5.3) confbox: 0.2.4 consola: 3.4.2 convert-gitmoji: 0.1.5 @@ -17851,10 +17940,6 @@ snapshots: check-error@2.1.3: {} - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 - chokidar@5.0.0: dependencies: readdirp: 5.0.0 @@ -17863,7 +17948,9 @@ snapshots: chownr@3.0.0: {} - chromatic@16.1.0: {} + chromatic@17.5.0: + dependencies: + semver: 7.7.4 chrome-launcher@1.2.1: dependencies: @@ -17953,8 +18040,8 @@ snapshots: constantinople@4.0.1: dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 content-disposition@1.0.1: {} @@ -18010,10 +18097,6 @@ snapshots: crypto-random-string@2.0.0: {} - css-declaration-sorter@7.3.1(postcss@8.5.14): - dependencies: - postcss: 8.5.14 - css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -18041,49 +18124,48 @@ snapshots: cssfilter@0.0.10: optional: true - cssnano-preset-default@7.0.17(postcss@8.5.14): + cssnano-preset-default@8.0.2(postcss@8.5.15): dependencies: browserslist: 4.28.2 - css-declaration-sorter: 7.3.1(postcss@8.5.14) - cssnano-utils: 5.0.3(postcss@8.5.14) - postcss: 8.5.14 - postcss-calc: 10.1.1(postcss@8.5.14) - postcss-colormin: 7.0.10(postcss@8.5.14) - postcss-convert-values: 7.0.12(postcss@8.5.14) - postcss-discard-comments: 7.0.8(postcss@8.5.14) - postcss-discard-duplicates: 7.0.4(postcss@8.5.14) - postcss-discard-empty: 7.0.3(postcss@8.5.14) - postcss-discard-overridden: 7.0.3(postcss@8.5.14) - postcss-merge-longhand: 7.0.7(postcss@8.5.14) - postcss-merge-rules: 7.0.11(postcss@8.5.14) - postcss-minify-font-values: 7.0.3(postcss@8.5.14) - postcss-minify-gradients: 7.0.5(postcss@8.5.14) - postcss-minify-params: 7.0.9(postcss@8.5.14) - postcss-minify-selectors: 7.1.2(postcss@8.5.14) - postcss-normalize-charset: 7.0.3(postcss@8.5.14) - postcss-normalize-display-values: 7.0.3(postcss@8.5.14) - postcss-normalize-positions: 7.0.4(postcss@8.5.14) - postcss-normalize-repeat-style: 7.0.4(postcss@8.5.14) - postcss-normalize-string: 7.0.3(postcss@8.5.14) - postcss-normalize-timing-functions: 7.0.3(postcss@8.5.14) - postcss-normalize-unicode: 7.0.9(postcss@8.5.14) - postcss-normalize-url: 7.0.3(postcss@8.5.14) - postcss-normalize-whitespace: 7.0.3(postcss@8.5.14) - postcss-ordered-values: 7.0.4(postcss@8.5.14) - postcss-reduce-initial: 7.0.9(postcss@8.5.14) - postcss-reduce-transforms: 7.0.3(postcss@8.5.14) - postcss-svgo: 7.1.3(postcss@8.5.14) - postcss-unique-selectors: 7.0.7(postcss@8.5.14) - - cssnano-utils@5.0.3(postcss@8.5.14): - dependencies: - postcss: 8.5.14 - - cssnano@7.1.9(postcss@8.5.14): - dependencies: - cssnano-preset-default: 7.0.17(postcss@8.5.14) + cssnano-utils: 6.0.1(postcss@8.5.15) + postcss: 8.5.15 + postcss-calc: 10.1.1(postcss@8.5.15) + postcss-colormin: 8.0.1(postcss@8.5.15) + postcss-convert-values: 8.0.1(postcss@8.5.15) + postcss-discard-comments: 8.0.1(postcss@8.5.15) + postcss-discard-duplicates: 8.0.1(postcss@8.5.15) + postcss-discard-empty: 8.0.1(postcss@8.5.15) + postcss-discard-overridden: 8.0.1(postcss@8.5.15) + postcss-merge-longhand: 8.0.1(postcss@8.5.15) + postcss-merge-rules: 8.0.1(postcss@8.5.15) + postcss-minify-font-values: 8.0.1(postcss@8.5.15) + postcss-minify-gradients: 8.0.1(postcss@8.5.15) + postcss-minify-params: 8.0.1(postcss@8.5.15) + postcss-minify-selectors: 8.0.2(postcss@8.5.15) + postcss-normalize-charset: 8.0.1(postcss@8.5.15) + postcss-normalize-display-values: 8.0.1(postcss@8.5.15) + postcss-normalize-positions: 8.0.1(postcss@8.5.15) + postcss-normalize-repeat-style: 8.0.1(postcss@8.5.15) + postcss-normalize-string: 8.0.1(postcss@8.5.15) + postcss-normalize-timing-functions: 8.0.1(postcss@8.5.15) + postcss-normalize-unicode: 8.0.1(postcss@8.5.15) + postcss-normalize-url: 8.0.1(postcss@8.5.15) + postcss-normalize-whitespace: 8.0.1(postcss@8.5.15) + postcss-ordered-values: 8.0.1(postcss@8.5.15) + postcss-reduce-initial: 8.0.1(postcss@8.5.15) + postcss-reduce-transforms: 8.0.1(postcss@8.5.15) + postcss-svgo: 8.0.1(postcss@8.5.15) + postcss-unique-selectors: 8.0.1(postcss@8.5.15) + + cssnano-utils@6.0.1(postcss@8.5.15): + dependencies: + postcss: 8.5.15 + + cssnano@8.0.2(postcss@8.5.15): + dependencies: + cssnano-preset-default: 8.0.2(postcss@8.5.15) lilconfig: 3.1.3 - postcss: 8.5.14 + postcss: 8.5.15 csso@5.0.5: dependencies: @@ -18187,7 +18269,7 @@ snapshots: devalue@5.6.4: {} - devalue@5.8.0: {} + devalue@5.8.1: {} devlop@1.1.0: dependencies: @@ -18201,40 +18283,40 @@ snapshots: doctypes@1.1.0: {} - docus@5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.5)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.13)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29): + docus@5.9.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@nuxt/schema@4.4.8)(@takumi-rs/wasm@1.0.9)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@unhead/vue@2.1.15)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(better-sqlite3@12.8.0)(db0@0.3.4)(embla-carousel@8.6.0)(eslint@9.39.2)(focus-trap@8.0.0)(fontless@0.2.1)(h3@1.15.11)(ioredis@5.10.1)(magicast@0.5.3)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(react-dom@19.2.4)(react@19.2.4)(rollup@4.60.3)(sharp@0.34.5)(typescript@6.0.2)(unifont@0.7.4)(unstorage@1.17.5)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29): dependencies: '@ai-sdk/gateway': 3.0.101(zod@4.3.6) '@ai-sdk/mcp': 1.0.36(zod@4.3.6) - '@ai-sdk/vue': 3.0.141(vue@3.5.34)(zod@4.3.6) + '@ai-sdk/vue': 3.0.141(vue@3.5.39)(zod@4.3.6) '@iconify-json/lucide': 1.2.101 '@iconify-json/simple-icons': 1.2.76 '@iconify-json/vscode-icons': 1.2.45 - '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.2)(valibot@1.3.1) - '@nuxt/image': 2.0.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2) - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@nuxt/ui': 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.2)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.34)(yjs@13.6.29)(zod@4.3.6) - '@nuxtjs/i18n': 10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.34)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.34) - '@nuxtjs/mcp-toolkit': 0.13.4(h3@1.15.11)(magicast@0.5.2)(zod@4.3.6) - '@nuxtjs/mdc': 0.21.1(magicast@0.5.2) - '@nuxtjs/robots': 6.0.9(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + '@nuxt/content': 3.12.0(better-sqlite3@12.8.0)(magicast@0.5.3)(valibot@1.3.1) + '@nuxt/image': 2.0.0(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/ui': 4.6.1(@nuxt/content@3.12.0)(@tiptap/extensions@3.24.0)(@tiptap/y-tiptap@3.0.2)(@upstash/redis@1.37.0)(db0@0.3.4)(embla-carousel@8.6.0)(focus-trap@8.0.0)(ioredis@5.10.1)(magicast@0.5.3)(react-dom@19.2.4)(react@19.2.4)(tailwindcss@4.2.2)(typescript@6.0.2)(valibot@1.3.1)(vite@8.0.0)(vue-router@5.0.4)(vue@3.5.39)(yjs@13.6.29)(zod@4.3.6) + '@nuxtjs/i18n': 10.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@upstash/redis@1.37.0)(@vue/compiler-dom@3.5.39)(db0@0.3.4)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(rollup@4.60.3)(typescript@6.0.2)(vue@3.5.39) + '@nuxtjs/mcp-toolkit': 0.13.4(h3@1.15.11)(magicast@0.5.3)(zod@4.3.6) + '@nuxtjs/mdc': 0.21.1(magicast@0.5.3) + '@nuxtjs/robots': 6.0.9(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) '@shikijs/core': 4.1.0 '@shikijs/engine-javascript': 4.0.2 '@shikijs/langs': 4.0.2 '@shikijs/themes': 4.0.2 '@takumi-rs/core': 0.73.1 - '@vueuse/core': 14.3.0(vue@3.5.34) + '@vueuse/core': 14.3.0(vue@3.5.39) ai: 6.0.141(zod@4.3.6) better-sqlite3: 12.8.0 defu: 6.1.6 exsolve: 1.0.8 git-url-parse: 16.1.0 - motion-v: 2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.34) - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) - nuxt-llms: 0.2.0(magicast@0.5.2) - nuxt-og-image: 6.4.3(@nuxt/schema@4.4.5)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.13)(fontless@0.2.1)(nuxt@4.4.5)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + motion-v: 2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nuxt-llms: 0.2.0(magicast@0.5.3) + nuxt-og-image: 6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) pkg-types: 2.3.1 scule: 1.3.0 - shiki-stream: 0.1.4(react@19.2.4)(vue@3.5.34) + shiki-stream: 0.1.4(react@19.2.4)(vue@3.5.39) tailwindcss: 4.2.2 ufo: 1.6.3 yaml: 2.9.0 @@ -18293,6 +18375,7 @@ snapshots: - jwt-decode - magicast - mysql2 + - nitropack - nprogress - petite-vue-i18n - pinia @@ -18300,6 +18383,7 @@ snapshots: - qrcode - react - react-dom + - rolldown - rollup - satori - secure-exec @@ -18408,11 +18492,11 @@ snapshots: dependencies: embla-carousel: 8.6.0 - embla-carousel-vue@8.6.0(vue@3.5.34): + embla-carousel-vue@8.6.0(vue@3.5.39): dependencies: embla-carousel: 8.6.0 embla-carousel-reactive-utils: 8.6.0(embla-carousel@8.6.0) - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) embla-carousel-wheel-gestures@8.1.0(embla-carousel@8.6.0): dependencies: @@ -18431,7 +18515,7 @@ snapshots: emoticon@4.1.0: {} - empathic@2.0.0: {} + empathic@2.0.1: {} encodeurl@2.0.0: {} @@ -18653,7 +18737,7 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-plugin-regexp@3.1.0(eslint@9.39.2): + eslint-plugin-regexp@3.1.1(eslint@9.39.2): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) '@eslint-community/regexpp': 4.12.2 @@ -18865,16 +18949,26 @@ snapshots: fast-string-truncated-width@1.2.1: {} + fast-string-truncated-width@3.0.3: {} + fast-string-width@1.1.0: dependencies: fast-string-truncated-width: 1.2.1 + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + fast-uri@3.1.0: {} fast-wrap-ansi@0.1.6: dependencies: fast-string-width: 1.1.0 + fast-wrap-ansi@0.2.2: + dependencies: + fast-string-width: 3.0.2 + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -19040,7 +19134,7 @@ snapshots: functions-have-names@1.2.3: {} - fuse.js@7.3.0: {} + fuse.js@7.4.2: {} fzf@0.5.2: {} @@ -19086,7 +19180,7 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 - giget@3.2.0: {} + giget@3.3.0: {} git-up@8.1.1: dependencies: @@ -19208,12 +19302,12 @@ snapshots: h3@2.0.1-rc.16: dependencies: rou3: 0.8.1 - srvx: 0.11.15 + srvx: 0.11.17 h3@2.0.1-rc.20: dependencies: rou3: 0.8.1 - srvx: 0.11.15 + srvx: 0.11.17 has-bigints@1.1.0: {} @@ -19387,6 +19481,8 @@ snapshots: hey-listen@1.0.8: {} + hls.js@1.6.16: {} + hono@4.12.3: {} hookable@5.5.3: {} @@ -19853,7 +19949,7 @@ snapshots: lodash: 4.17.23 minimist: 1.2.8 prettier: 3.8.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 json-schema-traverse@0.4.1: {} @@ -19921,7 +20017,7 @@ snapshots: picomatch: 4.0.4 smol-toml: 1.6.1 strip-json-comments: 5.0.3 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unbash: 3.0.0 yaml: 2.9.0 zod: 4.3.6 @@ -20028,7 +20124,7 @@ snapshots: node-forge: 1.4.0 pathe: 2.0.3 std-env: 4.1.0 - tinyclip: 0.1.12 + tinyclip: 0.1.14 ufo: 1.6.4 untun: 0.1.3 uqr: 0.1.3 @@ -20051,14 +20147,10 @@ snapshots: lodash.isarguments@3.1.0: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} lodash.sortby@4.7.0: {} - lodash.uniq@4.5.0: {} - lodash@4.17.23: {} longest-streak@3.1.0: {} @@ -20087,6 +20179,13 @@ snapshots: ufo: 1.6.3 unplugin: 2.3.11 + magic-regexp@0.11.0: + dependencies: + magic-string: 0.30.21 + regexp-tree: 0.1.27 + type-level-regexp: 0.1.17 + unplugin: 3.0.0 + magic-string-ast@1.0.3: dependencies: magic-string: 0.30.21 @@ -20099,10 +20198,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.5.2: + magicast@0.5.3: dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 source-map-js: 1.2.1 make-dir@4.0.0: @@ -20532,8 +20631,6 @@ snapshots: mocked-exports@0.1.1: {} - module-replacements@3.0.0-beta.7: {} - module-replacements@3.0.0-beta.8: {} motion-dom@12.40.0: @@ -20542,14 +20639,14 @@ snapshots: motion-utils@12.39.0: {} - motion-v@2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.34): + motion-v@2.2.1(@vueuse/core@14.3.0)(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39): dependencies: - '@vueuse/core': 14.3.0(vue@3.5.34) + '@vueuse/core': 14.3.0(vue@3.5.39) framer-motion: 12.40.0(react-dom@19.2.4)(react@19.2.4) hey-listen: 1.0.8 motion-dom: 12.40.0 motion-utils: 12.39.0 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - '@emotion/is-prop-valid' - react @@ -20599,7 +20696,7 @@ snapshots: mute-stream@2.0.0: {} - nanoid@3.3.11: {} + nanoid@3.3.14: {} nanotar@0.3.0: {} @@ -20613,7 +20710,214 @@ snapshots: neotraverse@0.6.18: {} - nitropack@2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.128.0)(rolldown@1.0.0-rc.16): + nitropack@2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.115.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.4.2 + '@rollup/plugin-alias': 6.0.0(rollup@4.60.3) + '@rollup/plugin-commonjs': 29.0.2(rollup@4.60.3) + '@rollup/plugin-inject': 5.0.5(rollup@4.60.3) + '@rollup/plugin-json': 6.1.0(rollup@4.60.3) + '@rollup/plugin-node-resolve': 16.0.3(rollup@4.60.3) + '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) + '@rollup/plugin-terser': 1.0.0(rollup@4.60.3) + '@vercel/nft': 1.5.0(rollup@4.60.3) + archiver: 7.0.1 + c12: 3.3.4(magicast@0.5.3) + chokidar: 5.0.0 + citty: 0.2.2 + compatx: 0.2.0 + confbox: 0.2.4 + consola: 3.4.2 + cookie-es: 2.0.1 + croner: 10.0.1 + crossws: 0.3.5 + db0: 0.3.4(better-sqlite3@12.8.0) + defu: 6.1.7 + destr: 2.0.5 + dot-prop: 10.1.0 + esbuild: 0.28.0 + escape-string-regexp: 5.0.0 + etag: 1.8.1 + exsolve: 1.0.8 + globby: 16.2.0 + gzip-size: 7.0.0 + h3: 1.15.11 + hookable: 5.5.3 + httpxy: 0.5.1 + ioredis: 5.10.1 + jiti: 2.7.0 + klona: 2.0.6 + knitwork: 1.3.0 + listhen: 1.10.0 + magic-string: 0.30.21 + magicast: 0.5.3 + mime: 4.1.0 + mlly: 1.8.2 + node-fetch-native: 1.6.7 + node-mock-http: 1.0.4 + ofetch: 1.5.1 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + pkg-types: 2.3.1 + pretty-bytes: 7.1.0 + radix3: 1.1.2 + rollup: 4.60.3 + rollup-plugin-visualizer: 7.0.1(rollup@4.60.3) + scule: 1.3.0 + semver: 7.7.4 + serve-placeholder: 2.0.2 + serve-static: 2.2.1 + source-map: 0.7.6 + std-env: 4.1.0 + ufo: 1.6.4 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.5.0 + unenv: 2.0.0-rc.24 + unimport: 6.3.0(oxc-parser@0.115.0) + unplugin-utils: 0.3.1 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + untyped: 2.0.0 + unwasm: 0.5.3 + youch: 4.1.1 + youch-core: 0.3.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - drizzle-orm + - encoding + - idb-keyval + - mysql2 + - oxc-parser + - react-native-b4a + - rolldown + - sqlite3 + - supports-color + - uploadthing + optional: true + + nitropack@2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.133.0): + dependencies: + '@cloudflare/kv-asset-handler': 0.4.2 + '@rollup/plugin-alias': 6.0.0(rollup@4.60.3) + '@rollup/plugin-commonjs': 29.0.2(rollup@4.60.3) + '@rollup/plugin-inject': 5.0.5(rollup@4.60.3) + '@rollup/plugin-json': 6.1.0(rollup@4.60.3) + '@rollup/plugin-node-resolve': 16.0.3(rollup@4.60.3) + '@rollup/plugin-replace': 6.0.3(rollup@4.60.3) + '@rollup/plugin-terser': 1.0.0(rollup@4.60.3) + '@vercel/nft': 1.5.0(rollup@4.60.3) + archiver: 7.0.1 + c12: 3.3.4(magicast@0.5.3) + chokidar: 5.0.0 + citty: 0.2.2 + compatx: 0.2.0 + confbox: 0.2.4 + consola: 3.4.2 + cookie-es: 2.0.1 + croner: 10.0.1 + crossws: 0.3.5 + db0: 0.3.4(better-sqlite3@12.8.0) + defu: 6.1.7 + destr: 2.0.5 + dot-prop: 10.1.0 + esbuild: 0.28.0 + escape-string-regexp: 5.0.0 + etag: 1.8.1 + exsolve: 1.0.8 + globby: 16.2.0 + gzip-size: 7.0.0 + h3: 1.15.11 + hookable: 5.5.3 + httpxy: 0.5.1 + ioredis: 5.10.1 + jiti: 2.7.0 + klona: 2.0.6 + knitwork: 1.3.0 + listhen: 1.10.0 + magic-string: 0.30.21 + magicast: 0.5.3 + mime: 4.1.0 + mlly: 1.8.2 + node-fetch-native: 1.6.7 + node-mock-http: 1.0.4 + ofetch: 1.5.1 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 2.1.0 + pkg-types: 2.3.1 + pretty-bytes: 7.1.0 + radix3: 1.1.2 + rollup: 4.60.3 + rollup-plugin-visualizer: 7.0.1(rollup@4.60.3) + scule: 1.3.0 + semver: 7.7.4 + serve-placeholder: 2.0.2 + serve-static: 2.2.1 + source-map: 0.7.6 + std-env: 4.1.0 + ufo: 1.6.4 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.5.0 + unenv: 2.0.0-rc.24 + unimport: 6.3.0(oxc-parser@0.133.0) + unplugin-utils: 0.3.1 + unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) + untyped: 2.0.0 + unwasm: 0.5.3 + youch: 4.1.1 + youch-core: 0.3.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@planetscale/database' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - drizzle-orm + - encoding + - idb-keyval + - mysql2 + - oxc-parser + - react-native-b4a + - rolldown + - sqlite3 + - supports-color + - uploadthing + + nitropack@2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.135.0): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 '@rollup/plugin-alias': 6.0.0(rollup@4.60.3) @@ -20625,7 +20929,7 @@ snapshots: '@rollup/plugin-terser': 1.0.0(rollup@4.60.3) '@vercel/nft': 1.5.0(rollup@4.60.3) archiver: 7.0.1 - c12: 3.3.4(magicast@0.5.2) + c12: 3.3.4(magicast@0.5.3) chokidar: 5.0.0 citty: 0.2.2 compatx: 0.2.0 @@ -20653,7 +20957,7 @@ snapshots: knitwork: 1.3.0 listhen: 1.10.0 magic-string: 0.30.21 - magicast: 0.5.2 + magicast: 0.5.3 mime: 4.1.0 mlly: 1.8.2 node-fetch-native: 1.6.7 @@ -20666,7 +20970,7 @@ snapshots: pretty-bytes: 7.1.0 radix3: 1.1.2 rollup: 4.60.3 - rollup-plugin-visualizer: 7.0.1(rolldown@1.0.0-rc.16)(rollup@4.60.3) + rollup-plugin-visualizer: 7.0.1(rollup@4.60.3) scule: 1.3.0 semver: 7.7.4 serve-placeholder: 2.0.2 @@ -20678,7 +20982,7 @@ snapshots: uncrypto: 0.1.3 unctx: 2.5.0 unenv: 2.0.0-rc.24 - unimport: 6.2.0(oxc-parser@0.128.0) + unimport: 6.3.0(oxc-parser@0.135.0) unplugin-utils: 0.3.1 unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) untyped: 2.0.0 @@ -20715,6 +21019,7 @@ snapshots: - sqlite3 - supports-color - uploadthing + optional: true node-abi@3.87.0: dependencies: @@ -20766,9 +21071,9 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxt-component-meta@0.17.2(magicast@0.5.2): + nuxt-component-meta@0.17.2(magicast@0.5.3): dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) citty: 0.1.6 mlly: 1.8.2 ohash: 2.0.11 @@ -20781,43 +21086,45 @@ snapshots: nuxt-define@1.0.0: {} - nuxt-llms@0.2.0(magicast@0.5.2): + nuxt-llms@0.2.0(magicast@0.5.3): dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) transitivePeerDependencies: - magicast - nuxt-og-image@6.4.3(@nuxt/schema@4.4.5)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.13)(fontless@0.2.1)(nuxt@4.4.5)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6): + nuxt-og-image@6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@0.73.1)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.2.2)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6): dependencies: - '@clack/prompts': 1.2.0 - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vue/compiler-sfc': 3.5.34 + '@clack/prompts': 1.6.0 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@unocss/config': 66.7.2 + '@unocss/core': 66.7.2 + '@vue/compiler-sfc': 3.5.39 chrome-launcher: 1.2.1 consola: 3.4.2 culori: 4.0.2 defu: 6.1.7 - devalue: 5.8.0 + devalue: 5.8.1 exsolve: 1.0.8 lightningcss: 1.32.0 magic-string: 0.30.21 - magicast: 0.5.2 + magicast: 0.5.3 mocked-exports: 0.1.1 - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) - nuxtseo-shared: 5.1.3(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt-site-config@4.0.8)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) - nypm: 0.6.6 + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) + nypm: 0.6.7 ofetch: 1.5.1 ohash: 2.0.11 - oxc-parser: 0.126.0 - oxc-walker: 0.7.0(oxc-parser@0.126.0) + oxc-parser: 0.135.0 + oxc-walker: 1.0.0(oxc-parser@0.135.0) pathe: 2.0.3 pkg-types: 2.3.1 radix3: 1.1.2 std-env: 4.1.0 strip-literal: 3.1.0 - tinyexec: 1.1.1 - tinyglobby: 0.2.16 - ufo: 1.6.3 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + ufo: 1.6.4 ultrahtml: 1.6.0 unplugin: 3.0.0 unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) @@ -20825,49 +21132,53 @@ snapshots: '@takumi-rs/core': 0.73.1 '@takumi-rs/wasm': 1.0.9(react-dom@19.2.4)(react@19.2.4) fontless: 0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.0.0) + nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.135.0) playwright-core: 1.60.0 sharp: 0.34.5 tailwindcss: 4.2.2 unifont: 0.7.4 + zod: 4.3.6 transitivePeerDependencies: - '@nuxt/schema' - nuxt + - rolldown - supports-color - vite - vue - - zod - nuxt-og-image@6.4.3(@nuxt/schema@4.4.5)(@takumi-rs/core@1.0.9)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.13)(fontless@0.2.1)(nuxt@4.4.5)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.3.0)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6): + nuxt-og-image@6.6.0(@nuxt/schema@4.4.8)(@takumi-rs/core@1.0.9)(@takumi-rs/wasm@1.0.9)(@unhead/vue@2.1.15)(fontless@0.2.1)(nitropack@2.13.4)(nuxt@4.4.8)(playwright-core@1.60.0)(sharp@0.34.5)(tailwindcss@4.3.0)(unifont@0.7.4)(unstorage@1.17.5)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6): dependencies: - '@clack/prompts': 1.2.0 - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vue/compiler-sfc': 3.5.34 + '@clack/prompts': 1.6.0 + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@unocss/config': 66.7.2 + '@unocss/core': 66.7.2 + '@vue/compiler-sfc': 3.5.39 chrome-launcher: 1.2.1 consola: 3.4.2 culori: 4.0.2 defu: 6.1.7 - devalue: 5.8.0 + devalue: 5.8.1 exsolve: 1.0.8 lightningcss: 1.32.0 magic-string: 0.30.21 - magicast: 0.5.2 + magicast: 0.5.3 mocked-exports: 0.1.1 - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) - nuxtseo-shared: 5.1.3(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt-site-config@4.0.8)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) - nypm: 0.6.6 + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) + nypm: 0.6.7 ofetch: 1.5.1 ohash: 2.0.11 - oxc-parser: 0.126.0 - oxc-walker: 0.7.0(oxc-parser@0.126.0) + oxc-parser: 0.135.0 + oxc-walker: 1.0.0(oxc-parser@0.135.0) pathe: 2.0.3 pkg-types: 2.3.1 radix3: 1.1.2 std-env: 4.1.0 strip-literal: 3.1.0 - tinyexec: 1.1.1 - tinyglobby: 0.2.16 - ufo: 1.6.3 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + ufo: 1.6.4 ultrahtml: 1.6.0 unplugin: 3.0.0 unstorage: 1.17.5(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1) @@ -20875,37 +21186,39 @@ snapshots: '@takumi-rs/core': 1.0.9(react-dom@19.2.4)(react@19.2.4) '@takumi-rs/wasm': 1.0.9(react-dom@19.2.4)(react@19.2.4) fontless: 0.2.1(@upstash/redis@1.37.0)(db0@0.3.4)(ioredis@5.10.1)(vite@8.0.0) + nitropack: 2.13.4(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(oxc-parser@0.115.0) playwright-core: 1.60.0 sharp: 0.34.5 tailwindcss: 4.3.0 unifont: 0.7.4 + zod: 4.3.6 transitivePeerDependencies: - '@nuxt/schema' - nuxt + - rolldown - supports-color - vite - vue - - zod - nuxt-site-config-kit@4.0.8(magicast@0.5.2)(vue@3.5.34): + nuxt-site-config-kit@4.0.8(magicast@0.5.3)(vue@3.5.39): dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - site-config-stack: 4.0.8(vue@3.5.34) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + site-config-stack: 4.0.8(vue@3.5.39) std-env: 4.0.0 ufo: 1.6.3 transitivePeerDependencies: - magicast - vue - nuxt-site-config@4.0.8(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6): + nuxt-site-config@4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6): dependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) h3: 1.15.11 - nuxt-site-config-kit: 4.0.8(magicast@0.5.2)(vue@3.5.34) - nuxtseo-shared: 5.1.3(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt-site-config@4.0.8)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + nuxt-site-config-kit: 4.0.8(magicast@0.5.3)(vue@3.5.39) + nuxtseo-shared: 5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) pathe: 2.0.3 pkg-types: 2.3.1 - site-config-stack: 4.0.8(vue@3.5.34) + site-config-stack: 4.0.8(vue@3.5.39) ufo: 1.6.3 transitivePeerDependencies: - '@nuxt/schema' @@ -20915,24 +21228,24 @@ snapshots: - vue - zod - nuxt@4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0): - dependencies: - '@dxup/nuxt': 0.4.1(magicast@0.5.2)(typescript@6.0.2) - '@nuxt/cli': 3.35.1(@nuxt/schema@4.4.5)(cac@6.7.14)(magicast@0.5.2) - '@nuxt/devtools': 3.2.4(vite@8.0.0)(vue@3.5.34) - '@nuxt/kit': 4.4.5(magicast@0.5.2) - '@nuxt/nitro-server': 4.4.5(@babel/core@7.29.0)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.2)(nuxt@4.4.5)(oxc-parser@0.128.0)(rolldown@1.0.0-rc.16)(typescript@6.0.2) - '@nuxt/schema': 4.4.5 - '@nuxt/telemetry': 2.8.0(@nuxt/kit@4.4.5) - '@nuxt/vite-builder': 4.4.5(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.2)(nuxt@4.4.5)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.34)(yaml@2.9.0) - '@unhead/vue': 2.1.13(vue@3.5.34) - '@vue/shared': 3.5.34 + nuxt@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0): + dependencies: + '@dxup/nuxt': 0.4.1(magicast@0.5.3)(typescript@6.0.2) + '@nuxt/cli': 3.36.0(@nuxt/schema@4.4.8)(cac@6.7.14)(magicast@0.5.3) + '@nuxt/devtools': 3.2.4(vite@8.0.0)(vue@3.5.39) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/nitro-server': 4.4.8(@babel/plugin-syntax-typescript@7.28.6)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(nuxt@4.4.8)(oxc-parser@0.133.0)(typescript@6.0.2) + '@nuxt/schema': 4.4.8 + '@nuxt/telemetry': 2.8.0(@nuxt/kit@4.4.8) + '@nuxt/vite-builder': 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(oxlint@1.61.0)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vue/shared': 3.5.39 chokidar: 5.0.0 compatx: 0.2.0 consola: 3.4.2 - cookie-es: 2.0.1 + cookie-es: 3.1.1 defu: 6.1.7 - devalue: 5.8.0 + devalue: 5.8.1 errx: 0.1.0 escape-string-regexp: 5.0.0 exsolve: 1.0.8 @@ -20945,33 +21258,166 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.2 nanotar: 0.3.0 - nypm: 0.6.6 + nypm: 0.6.7 ofetch: 1.5.1 ohash: 2.0.11 on-change: 6.0.2 - oxc-minify: 0.128.0 - oxc-parser: 0.128.0 - oxc-transform: 0.128.0 - oxc-walker: 0.7.0(oxc-parser@0.128.0) + oxc-minify: 0.133.0 + oxc-parser: 0.133.0 + oxc-transform: 0.133.0 + oxc-walker: 1.0.0(oxc-parser@0.133.0) pathe: 2.0.3 perfect-debounce: 2.1.0 picomatch: 4.0.4 pkg-types: 2.3.1 rou3: 0.8.1 scule: 1.3.0 - semver: 7.7.4 + semver: 7.8.5 + std-env: 4.1.0 + tinyglobby: 0.2.17 + ufo: 1.6.4 + ultrahtml: 1.6.0 + uncrypto: 0.1.3 + unctx: 2.5.0 + unhead: 2.1.15 + unimport: 6.3.0(oxc-parser@0.133.0) + unplugin: 3.0.0 + unrouting: 0.1.7 + untyped: 2.0.0 + vue: 3.5.39(typescript@6.0.2) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) + optionalDependencies: + '@parcel/watcher': 2.5.6 + '@types/node': 24.12.0 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@babel/plugin-proposal-decorators' + - '@babel/plugin-syntax-jsx' + - '@babel/plugin-syntax-typescript' + - '@biomejs/biome' + - '@capacitor/preferences' + - '@deno/kv' + - '@electric-sql/pglite' + - '@libsql/client' + - '@netlify/blobs' + - '@pinia/colada' + - '@planetscale/database' + - '@rollup/plugin-babel' + - '@tsdown/css' + - '@tsdown/exe' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@vitejs/devtools' + - '@vue/compiler-sfc' + - aws4fetch + - bare-abort-controller + - better-sqlite3 + - bufferutil + - cac + - commander + - db0 + - drizzle-orm + - encoding + - esbuild + - eslint + - idb-keyval + - ioredis + - less + - magicast + - meow + - mysql2 + - optionator + - oxlint + - pinia + - publint + - react-native-b4a + - rolldown + - rollup + - rollup-plugin-visualizer + - sass + - sass-embedded + - sqlite3 + - stylelint + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unplugin-unused + - uploadthing + - utf-8-validate + - vite + - vue-tsc + - xml2js + - yaml + + nuxt@4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0): + dependencies: + '@dxup/nuxt': 0.4.1(magicast@0.5.3)(typescript@6.0.2) + '@nuxt/cli': 3.36.0(@nuxt/schema@4.4.8)(cac@6.7.14)(magicast@0.5.3) + '@nuxt/devtools': 3.2.4(vite@8.0.0)(vue@3.5.39) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/nitro-server': 4.4.8(@babel/plugin-syntax-typescript@7.28.6)(@upstash/redis@1.37.0)(better-sqlite3@12.8.0)(db0@0.3.4)(ioredis@5.10.1)(magicast@0.5.3)(nuxt@4.4.8)(oxc-parser@0.133.0)(typescript@6.0.2) + '@nuxt/schema': 4.4.8 + '@nuxt/telemetry': 2.8.0(@nuxt/kit@4.4.8) + '@nuxt/vite-builder': 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@types/node@24.12.0)(esbuild@0.27.3)(eslint@9.39.2)(magicast@0.5.3)(nuxt@4.4.8)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vue-tsc@3.2.6)(vue@3.5.39)(yaml@2.9.0) + '@unhead/vue': 2.1.15(vue@3.5.39) + '@vue/shared': 3.5.39 + chokidar: 5.0.0 + compatx: 0.2.0 + consola: 3.4.2 + cookie-es: 3.1.1 + defu: 6.1.7 + devalue: 5.8.1 + errx: 0.1.0 + escape-string-regexp: 5.0.0 + exsolve: 1.0.8 + hookable: 6.1.1 + ignore: 7.0.5 + impound: 1.1.5 + jiti: 2.7.0 + klona: 2.0.6 + knitwork: 1.3.0 + magic-string: 0.30.21 + mlly: 1.8.2 + nanotar: 0.3.0 + nypm: 0.6.7 + ofetch: 1.5.1 + ohash: 2.0.11 + on-change: 6.0.2 + oxc-minify: 0.133.0 + oxc-parser: 0.133.0 + oxc-transform: 0.133.0 + oxc-walker: 1.0.0(oxc-parser@0.133.0) + pathe: 2.0.3 + perfect-debounce: 2.1.0 + picomatch: 4.0.4 + pkg-types: 2.3.1 + rou3: 0.8.1 + scule: 1.3.0 + semver: 7.8.5 std-env: 4.1.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 ufo: 1.6.4 ultrahtml: 1.6.0 uncrypto: 0.1.3 unctx: 2.5.0 - unimport: 6.2.0(oxc-parser@0.128.0) + unhead: 2.1.15 + unimport: 6.3.0(oxc-parser@0.133.0) unplugin: 3.0.0 unrouting: 0.1.7 untyped: 2.0.0 - vue: 3.5.34(typescript@6.0.2) - vue-router: 5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34) + vue: 3.5.39(typescript@6.0.2) + vue-router: 5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39) optionalDependencies: '@parcel/watcher': 2.5.6 '@types/node': 24.12.0 @@ -20983,9 +21429,9 @@ snapshots: - '@azure/identity' - '@azure/keyvault-secrets' - '@azure/storage-blob' - - '@babel/core' - '@babel/plugin-proposal-decorators' - '@babel/plugin-syntax-jsx' + - '@babel/plugin-syntax-typescript' - '@biomejs/biome' - '@capacitor/preferences' - '@deno/kv' @@ -21042,42 +21488,41 @@ snapshots: - uploadthing - utf-8-validate - vite - - vls - - vti - vue-tsc - xml2js - yaml - nuxtseo-shared@5.1.3(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt-site-config@4.0.8)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6): + nuxtseo-shared@5.3.0(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt-site-config@4.0.8)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6): dependencies: - '@clack/prompts': 1.2.0 - '@nuxt/devtools-kit': 4.0.0-alpha.3(magicast@0.5.2)(vite@8.0.0) - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@nuxt/schema': 4.4.5 + '@clack/prompts': 1.6.0 + '@nuxt/devtools-kit': 4.0.0-alpha.3(magicast@0.5.3)(vite@8.0.0) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@nuxt/schema': 4.4.8 birpc: 4.0.0 consola: 3.4.2 defu: 6.1.7 - nuxt: 4.4.5(@babel/core@7.29.0)(@babel/plugin-syntax-jsx@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.34)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.2)(optionator@0.9.4)(oxlint@1.61.0)(rolldown@1.0.0-rc.16)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nuxt: 4.4.8(@babel/plugin-syntax-jsx@7.28.6)(@babel/plugin-syntax-typescript@7.28.6)(@parcel/watcher@2.5.6)(@types/node@24.12.0)(@upstash/redis@1.37.0)(@vue/compiler-sfc@3.5.39)(better-sqlite3@12.8.0)(cac@6.7.14)(db0@0.3.4)(esbuild@0.27.3)(eslint@9.39.2)(ioredis@5.10.1)(magicast@0.5.3)(optionator@0.9.4)(rollup-plugin-visualizer@7.0.1)(rollup@4.60.3)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(vue-tsc@3.2.6)(yaml@2.9.0) + nypm: 0.6.7 ofetch: 1.5.1 pathe: 2.0.3 pkg-types: 2.3.1 radix3: 1.1.2 sirv: 3.0.2 - std-env: 4.0.0 - ufo: 1.6.3 - vue: 3.5.34(typescript@6.0.2) + std-env: 4.1.0 + ufo: 1.6.4 + vue: 3.5.39(typescript@6.0.2) optionalDependencies: - nuxt-site-config: 4.0.8(@nuxt/schema@4.4.5)(magicast@0.5.2)(nuxt@4.4.5)(vite@8.0.0)(vue@3.5.34)(zod@4.3.6) + nuxt-site-config: 4.0.8(@nuxt/schema@4.4.8)(magicast@0.5.3)(nuxt@4.4.8)(vite@8.0.0)(vue@3.5.39)(zod@4.3.6) zod: 4.3.6 transitivePeerDependencies: - magicast - vite - nypm@0.6.6: + nypm@0.6.7: dependencies: citty: 0.2.2 pathe: 2.0.3 - tinyexec: 1.1.1 + tinyexec: 1.2.4 object-assign@4.1.1: {} @@ -21165,28 +21610,28 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxc-minify@0.128.0: + oxc-minify@0.133.0: optionalDependencies: - '@oxc-minify/binding-android-arm-eabi': 0.128.0 - '@oxc-minify/binding-android-arm64': 0.128.0 - '@oxc-minify/binding-darwin-arm64': 0.128.0 - '@oxc-minify/binding-darwin-x64': 0.128.0 - '@oxc-minify/binding-freebsd-x64': 0.128.0 - '@oxc-minify/binding-linux-arm-gnueabihf': 0.128.0 - '@oxc-minify/binding-linux-arm-musleabihf': 0.128.0 - '@oxc-minify/binding-linux-arm64-gnu': 0.128.0 - '@oxc-minify/binding-linux-arm64-musl': 0.128.0 - '@oxc-minify/binding-linux-ppc64-gnu': 0.128.0 - '@oxc-minify/binding-linux-riscv64-gnu': 0.128.0 - '@oxc-minify/binding-linux-riscv64-musl': 0.128.0 - '@oxc-minify/binding-linux-s390x-gnu': 0.128.0 - '@oxc-minify/binding-linux-x64-gnu': 0.128.0 - '@oxc-minify/binding-linux-x64-musl': 0.128.0 - '@oxc-minify/binding-openharmony-arm64': 0.128.0 - '@oxc-minify/binding-wasm32-wasi': 0.128.0 - '@oxc-minify/binding-win32-arm64-msvc': 0.128.0 - '@oxc-minify/binding-win32-ia32-msvc': 0.128.0 - '@oxc-minify/binding-win32-x64-msvc': 0.128.0 + '@oxc-minify/binding-android-arm-eabi': 0.133.0 + '@oxc-minify/binding-android-arm64': 0.133.0 + '@oxc-minify/binding-darwin-arm64': 0.133.0 + '@oxc-minify/binding-darwin-x64': 0.133.0 + '@oxc-minify/binding-freebsd-x64': 0.133.0 + '@oxc-minify/binding-linux-arm-gnueabihf': 0.133.0 + '@oxc-minify/binding-linux-arm-musleabihf': 0.133.0 + '@oxc-minify/binding-linux-arm64-gnu': 0.133.0 + '@oxc-minify/binding-linux-arm64-musl': 0.133.0 + '@oxc-minify/binding-linux-ppc64-gnu': 0.133.0 + '@oxc-minify/binding-linux-riscv64-gnu': 0.133.0 + '@oxc-minify/binding-linux-riscv64-musl': 0.133.0 + '@oxc-minify/binding-linux-s390x-gnu': 0.133.0 + '@oxc-minify/binding-linux-x64-gnu': 0.133.0 + '@oxc-minify/binding-linux-x64-musl': 0.133.0 + '@oxc-minify/binding-openharmony-arm64': 0.133.0 + '@oxc-minify/binding-wasm32-wasi': 0.133.0 + '@oxc-minify/binding-win32-arm64-msvc': 0.133.0 + '@oxc-minify/binding-win32-ia32-msvc': 0.133.0 + '@oxc-minify/binding-win32-x64-msvc': 0.133.0 oxc-parser@0.112.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0): dependencies: @@ -21269,31 +21714,6 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.126.0 '@oxc-parser/binding-win32-x64-msvc': 0.126.0 - oxc-parser@0.128.0: - dependencies: - '@oxc-project/types': 0.128.0 - optionalDependencies: - '@oxc-parser/binding-android-arm-eabi': 0.128.0 - '@oxc-parser/binding-android-arm64': 0.128.0 - '@oxc-parser/binding-darwin-arm64': 0.128.0 - '@oxc-parser/binding-darwin-x64': 0.128.0 - '@oxc-parser/binding-freebsd-x64': 0.128.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.128.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.128.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.128.0 - '@oxc-parser/binding-linux-arm64-musl': 0.128.0 - '@oxc-parser/binding-linux-ppc64-gnu': 0.128.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.128.0 - '@oxc-parser/binding-linux-riscv64-musl': 0.128.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.128.0 - '@oxc-parser/binding-linux-x64-gnu': 0.128.0 - '@oxc-parser/binding-linux-x64-musl': 0.128.0 - '@oxc-parser/binding-openharmony-arm64': 0.128.0 - '@oxc-parser/binding-wasm32-wasi': 0.128.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.128.0 - '@oxc-parser/binding-win32-ia32-msvc': 0.128.0 - '@oxc-parser/binding-win32-x64-msvc': 0.128.0 - oxc-parser@0.133.0: dependencies: '@oxc-project/types': 0.133.0 @@ -21319,6 +21739,31 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.133.0 '@oxc-parser/binding-win32-x64-msvc': 0.133.0 + oxc-parser@0.135.0: + dependencies: + '@oxc-project/types': 0.135.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.135.0 + '@oxc-parser/binding-android-arm64': 0.135.0 + '@oxc-parser/binding-darwin-arm64': 0.135.0 + '@oxc-parser/binding-darwin-x64': 0.135.0 + '@oxc-parser/binding-freebsd-x64': 0.135.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.135.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.135.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.135.0 + '@oxc-parser/binding-linux-arm64-musl': 0.135.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.135.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.135.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.135.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.135.0 + '@oxc-parser/binding-linux-x64-gnu': 0.135.0 + '@oxc-parser/binding-linux-x64-musl': 0.135.0 + '@oxc-parser/binding-openharmony-arm64': 0.135.0 + '@oxc-parser/binding-wasm32-wasi': 0.135.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.135.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.135.0 + '@oxc-parser/binding-win32-x64-msvc': 0.135.0 + oxc-resolver@11.20.0: optionalDependencies: '@oxc-resolver/binding-android-arm-eabi': 11.20.0 @@ -21367,28 +21812,28 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - oxc-transform@0.128.0: + oxc-transform@0.133.0: optionalDependencies: - '@oxc-transform/binding-android-arm-eabi': 0.128.0 - '@oxc-transform/binding-android-arm64': 0.128.0 - '@oxc-transform/binding-darwin-arm64': 0.128.0 - '@oxc-transform/binding-darwin-x64': 0.128.0 - '@oxc-transform/binding-freebsd-x64': 0.128.0 - '@oxc-transform/binding-linux-arm-gnueabihf': 0.128.0 - '@oxc-transform/binding-linux-arm-musleabihf': 0.128.0 - '@oxc-transform/binding-linux-arm64-gnu': 0.128.0 - '@oxc-transform/binding-linux-arm64-musl': 0.128.0 - '@oxc-transform/binding-linux-ppc64-gnu': 0.128.0 - '@oxc-transform/binding-linux-riscv64-gnu': 0.128.0 - '@oxc-transform/binding-linux-riscv64-musl': 0.128.0 - '@oxc-transform/binding-linux-s390x-gnu': 0.128.0 - '@oxc-transform/binding-linux-x64-gnu': 0.128.0 - '@oxc-transform/binding-linux-x64-musl': 0.128.0 - '@oxc-transform/binding-openharmony-arm64': 0.128.0 - '@oxc-transform/binding-wasm32-wasi': 0.128.0 - '@oxc-transform/binding-win32-arm64-msvc': 0.128.0 - '@oxc-transform/binding-win32-ia32-msvc': 0.128.0 - '@oxc-transform/binding-win32-x64-msvc': 0.128.0 + '@oxc-transform/binding-android-arm-eabi': 0.133.0 + '@oxc-transform/binding-android-arm64': 0.133.0 + '@oxc-transform/binding-darwin-arm64': 0.133.0 + '@oxc-transform/binding-darwin-x64': 0.133.0 + '@oxc-transform/binding-freebsd-x64': 0.133.0 + '@oxc-transform/binding-linux-arm-gnueabihf': 0.133.0 + '@oxc-transform/binding-linux-arm-musleabihf': 0.133.0 + '@oxc-transform/binding-linux-arm64-gnu': 0.133.0 + '@oxc-transform/binding-linux-arm64-musl': 0.133.0 + '@oxc-transform/binding-linux-ppc64-gnu': 0.133.0 + '@oxc-transform/binding-linux-riscv64-gnu': 0.133.0 + '@oxc-transform/binding-linux-riscv64-musl': 0.133.0 + '@oxc-transform/binding-linux-s390x-gnu': 0.133.0 + '@oxc-transform/binding-linux-x64-gnu': 0.133.0 + '@oxc-transform/binding-linux-x64-musl': 0.133.0 + '@oxc-transform/binding-openharmony-arm64': 0.133.0 + '@oxc-transform/binding-wasm32-wasi': 0.133.0 + '@oxc-transform/binding-win32-arm64-msvc': 0.133.0 + '@oxc-transform/binding-win32-ia32-msvc': 0.133.0 + '@oxc-transform/binding-win32-x64-msvc': 0.133.0 oxc-walker@0.7.0(oxc-parser@0.112.0): dependencies: @@ -21405,10 +21850,17 @@ snapshots: magic-regexp: 0.10.0 oxc-parser: 0.126.0 - oxc-walker@0.7.0(oxc-parser@0.128.0): + oxc-walker@1.0.0(oxc-parser@0.133.0): dependencies: - magic-regexp: 0.10.0 - oxc-parser: 0.128.0 + magic-regexp: 0.11.0 + optionalDependencies: + oxc-parser: 0.133.0 + + oxc-walker@1.0.0(oxc-parser@0.135.0): + dependencies: + magic-regexp: 0.11.0 + optionalDependencies: + oxc-parser: 0.135.0 oxfmt@0.46.0: dependencies: @@ -21616,167 +22068,167 @@ snapshots: possible-typed-array-names@1.1.0: {} - postcss-calc@10.1.1(postcss@8.5.14): + postcss-calc@10.1.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 postcss-value-parser: 4.2.0 - postcss-colormin@7.0.10(postcss@8.5.14): + postcss-colormin@8.0.1(postcss@8.5.15): dependencies: '@colordx/core': 5.4.3 browserslist: 4.28.2 - caniuse-api: 3.0.0 - postcss: 8.5.14 + caniuse-api: 4.0.0 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-convert-values@7.0.12(postcss@8.5.14): + postcss-convert-values@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-discard-comments@7.0.8(postcss@8.5.14): + postcss-discard-comments@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 - postcss-discard-duplicates@7.0.4(postcss@8.5.14): + postcss-discard-duplicates@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 - postcss-discard-empty@7.0.3(postcss@8.5.14): + postcss-discard-empty@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 - postcss-discard-overridden@7.0.3(postcss@8.5.14): + postcss-discard-overridden@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 - postcss-merge-longhand@7.0.7(postcss@8.5.14): + postcss-merge-longhand@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - stylehacks: 7.0.11(postcss@8.5.14) + stylehacks: 8.0.1(postcss@8.5.15) - postcss-merge-rules@7.0.11(postcss@8.5.14): + postcss-merge-rules@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - caniuse-api: 3.0.0 - cssnano-utils: 5.0.3(postcss@8.5.14) - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + caniuse-api: 4.0.0 + cssnano-utils: 6.0.1(postcss@8.5.15) + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 - postcss-minify-font-values@7.0.3(postcss@8.5.14): + postcss-minify-font-values@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-minify-gradients@7.0.5(postcss@8.5.14): + postcss-minify-gradients@8.0.1(postcss@8.5.15): dependencies: '@colordx/core': 5.4.3 - cssnano-utils: 5.0.3(postcss@8.5.14) - postcss: 8.5.14 + cssnano-utils: 6.0.1(postcss@8.5.15) + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-minify-params@7.0.9(postcss@8.5.14): + postcss-minify-params@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - cssnano-utils: 5.0.3(postcss@8.5.14) - postcss: 8.5.14 + cssnano-utils: 6.0.1(postcss@8.5.15) + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-minify-selectors@7.1.2(postcss@8.5.14): + postcss-minify-selectors@8.0.2(postcss@8.5.15): dependencies: browserslist: 4.28.2 - caniuse-api: 3.0.0 + caniuse-api: 4.0.0 cssesc: 3.0.0 - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 - postcss-normalize-charset@7.0.3(postcss@8.5.14): + postcss-normalize-charset@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 - postcss-normalize-display-values@7.0.3(postcss@8.5.14): + postcss-normalize-display-values@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-positions@7.0.4(postcss@8.5.14): + postcss-normalize-positions@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@7.0.4(postcss@8.5.14): + postcss-normalize-repeat-style@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-string@7.0.3(postcss@8.5.14): + postcss-normalize-string@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@7.0.3(postcss@8.5.14): + postcss-normalize-timing-functions@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@7.0.9(postcss@8.5.14): + postcss-normalize-unicode@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-url@7.0.3(postcss@8.5.14): + postcss-normalize-url@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@7.0.3(postcss@8.5.14): + postcss-normalize-whitespace@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-ordered-values@7.0.4(postcss@8.5.14): + postcss-ordered-values@8.0.1(postcss@8.5.15): dependencies: - cssnano-utils: 5.0.3(postcss@8.5.14) - postcss: 8.5.14 + cssnano-utils: 6.0.1(postcss@8.5.15) + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-reduce-initial@7.0.9(postcss@8.5.14): + postcss-reduce-initial@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - caniuse-api: 3.0.0 - postcss: 8.5.14 + caniuse-api: 4.0.0 + postcss: 8.5.15 - postcss-reduce-transforms@7.0.3(postcss@8.5.14): + postcss-reduce-transforms@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 - postcss-selector-parser@7.1.1: + postcss-selector-parser@7.1.4: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-svgo@7.1.3(postcss@8.5.14): + postcss-svgo@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 + postcss: 8.5.15 postcss-value-parser: 4.2.0 svgo: 4.0.1 - postcss-unique-selectors@7.0.7(postcss@8.5.14): + postcss-unique-selectors@8.0.1(postcss@8.5.15): dependencies: - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 postcss-value-parser@4.2.0: {} - postcss@8.5.14: + postcss@8.5.15: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.14 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -22073,8 +22525,6 @@ snapshots: dependencies: minimatch: 5.1.9 - readdirp@4.1.2: {} - readdirp@5.0.0: {} real-require@0.2.0: {} @@ -22207,19 +22657,19 @@ snapshots: '@types/hast': 3.0.4 unist-util-visit: 5.1.0 - reka-ui@2.9.3(vue@3.5.34): + reka-ui@2.9.3(vue@3.5.39): dependencies: '@floating-ui/dom': 1.7.6 - '@floating-ui/vue': 1.1.11(vue@3.5.34) + '@floating-ui/vue': 1.1.11(vue@3.5.39) '@internationalized/date': 3.12.2 '@internationalized/number': 3.6.5 - '@tanstack/vue-virtual': 3.13.26(vue@3.5.34) - '@vueuse/core': 14.3.0(vue@3.5.34) - '@vueuse/shared': 14.2.1(vue@3.5.34) + '@tanstack/vue-virtual': 3.13.26(vue@3.5.39) + '@vueuse/core': 14.3.0(vue@3.5.39) + '@vueuse/shared': 14.2.1(vue@3.5.39) aria-hidden: 1.2.6 defu: 6.1.6 ohash: 2.0.11 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - '@vue/composition-api' @@ -22398,14 +22848,13 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - rollup-plugin-visualizer@7.0.1(rolldown@1.0.0-rc.16)(rollup@4.60.3): + rollup-plugin-visualizer@7.0.1(rollup@4.60.3): dependencies: open: 11.0.0 picomatch: 4.0.4 source-map: 0.7.6 yargs: 18.0.0 optionalDependencies: - rolldown: 1.0.0-rc.16 rollup: 4.60.3 rollup@2.79.2: @@ -22497,7 +22946,7 @@ snapshots: htmlparser2: 10.1.0 is-plain-object: 5.0.0 parse-srcset: 1.0.2 - postcss: 8.5.14 + postcss: 8.5.15 sax@1.5.0: {} @@ -22537,7 +22986,7 @@ snapshots: semver@7.7.4: {} - semver@7.8.1: {} + semver@7.8.5: {} send@1.2.1: dependencies: @@ -22561,7 +23010,7 @@ snapshots: serialize-javascript@7.0.5: {} - seroval@1.5.3: {} + seroval@1.5.4: {} serve-placeholder@2.0.2: dependencies: @@ -22651,12 +23100,12 @@ snapshots: shell-quote@1.8.3: {} - shiki-stream@0.1.4(react@19.2.4)(vue@3.5.34): + shiki-stream@0.1.4(react@19.2.4)(vue@3.5.39): dependencies: '@shikijs/core': 3.23.0 optionalDependencies: react: 19.2.4 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) shiki@3.23.0: dependencies: @@ -22736,10 +23185,10 @@ snapshots: sisteransi@1.0.5: {} - site-config-stack@4.0.8(vue@3.5.34): + site-config-stack@4.0.8(vue@3.5.39): dependencies: ufo: 1.6.3 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) skin-tone@2.0.0: dependencies: @@ -22800,7 +23249,7 @@ snapshots: sprintf-js@1.0.3: {} - srvx@0.11.15: {} + srvx@0.11.17: {} standard-as-callback@2.1.0: {} @@ -22966,11 +23415,11 @@ snapshots: structured-clone-es@2.0.0: {} - stylehacks@7.0.11(postcss@8.5.14): + stylehacks@8.0.1(postcss@8.5.15): dependencies: browserslist: 4.28.2 - postcss: 8.5.14 - postcss-selector-parser: 7.1.1 + postcss: 8.5.15 + postcss-selector-parser: 7.1.4 supports-color@10.2.2: {} @@ -22994,9 +23443,9 @@ snapshots: picocolors: 1.1.1 sax: 1.5.0 - swrv@1.1.0(vue@3.5.34): + swrv@1.1.0(vue@3.5.39): dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) tabbable@6.4.0: {} @@ -23091,11 +23540,11 @@ snapshots: tinybench@2.9.0: {} - tinyclip@0.1.12: {} + tinyclip@0.1.14: {} - tinyexec@1.1.1: {} + tinyexec@1.2.4: {} - tinyglobby@0.2.16: + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 @@ -23172,7 +23621,7 @@ snapshots: ansis: 4.2.0 cac: 7.0.0 defu: 6.1.6 - empathic: 2.0.0 + empathic: 2.0.1 hookable: 6.1.1 import-without-cache: 0.2.5 obug: 2.1.1 @@ -23180,8 +23629,8 @@ snapshots: rolldown: 1.0.0-rc.12(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) rolldown-plugin-dts: 0.23.2(oxc-resolver@11.20.0)(rolldown@1.0.0-rc.12)(typescript@6.0.2)(vue-tsc@3.2.6) semver: 7.7.4 - tinyexec: 1.1.1 - tinyglobby: 0.2.16 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 tree-kill: 1.2.2 unconfig-core: 7.5.0 unrun: 0.2.36 @@ -23316,7 +23765,7 @@ snapshots: dependencies: pathe: 2.0.3 - unhead@2.1.13: + unhead@2.1.15: dependencies: hookable: 6.1.1 @@ -23368,11 +23817,31 @@ snapshots: pkg-types: 2.3.1 scule: 1.3.0 strip-literal: 3.1.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin: 2.3.11 unplugin-utils: 0.3.1 - unimport@6.2.0(oxc-parser@0.128.0): + unimport@6.3.0(oxc-parser@0.115.0): + dependencies: + acorn: 8.16.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.4 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.17 + unplugin: 3.0.0 + unplugin-utils: 0.3.1 + optionalDependencies: + oxc-parser: 0.115.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + unimport@6.3.0(oxc-parser@0.133.0): dependencies: acorn: 8.16.0 escape-string-regexp: 5.0.0 @@ -23385,11 +23854,31 @@ snapshots: pkg-types: 2.3.1 scule: 1.3.0 strip-literal: 3.1.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin: 3.0.0 unplugin-utils: 0.3.1 optionalDependencies: - oxc-parser: 0.128.0 + oxc-parser: 0.133.0 + + unimport@6.3.0(oxc-parser@0.135.0): + dependencies: + acorn: 8.16.0 + escape-string-regexp: 5.0.0 + estree-walker: 3.0.3 + local-pkg: 1.2.1 + magic-string: 0.30.21 + mlly: 1.8.2 + pathe: 2.0.3 + picomatch: 4.0.4 + pkg-types: 2.3.1 + scule: 1.3.0 + strip-literal: 3.1.0 + tinyglobby: 0.2.17 + unplugin: 3.0.0 + unplugin-utils: 0.3.1 + optionalDependencies: + oxc-parser: 0.135.0 + optional: true unique-string@2.0.0: dependencies: @@ -23457,7 +23946,7 @@ snapshots: unpipe@1.0.0: {} - unplugin-auto-import@21.0.0(@nuxt/kit@4.4.6)(@vueuse/core@14.3.0): + unplugin-auto-import@21.0.0(@nuxt/kit@4.4.8)(@vueuse/core@14.3.0): dependencies: local-pkg: 1.2.1 magic-string: 0.30.21 @@ -23466,15 +23955,15 @@ snapshots: unplugin: 2.3.11 unplugin-utils: 0.3.1 optionalDependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) - '@vueuse/core': 14.3.0(vue@3.5.34) + '@nuxt/kit': 4.4.8(magicast@0.5.3) + '@vueuse/core': 14.3.0(vue@3.5.39) unplugin-utils@0.3.1: dependencies: pathe: 2.0.3 picomatch: 4.0.4 - unplugin-vue-components@32.1.0(@nuxt/kit@4.4.6)(vue@3.5.34): + unplugin-vue-components@32.1.0(@nuxt/kit@4.4.8)(vue@3.5.39): dependencies: chokidar: 5.0.0 local-pkg: 1.2.1 @@ -23482,20 +23971,20 @@ snapshots: mlly: 1.8.2 obug: 2.1.1 picomatch: 4.0.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin: 3.0.0 unplugin-utils: 0.3.1 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) optionalDependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) - unplugin-vue-markdown@30.0.0(vite@8.0.0): + unplugin-vue-markdown@32.0.0(vite@8.0.0): dependencies: '@mdit-vue/plugin-component': 3.0.2 '@mdit-vue/plugin-frontmatter': 3.0.2 '@mdit-vue/types': 3.0.2 markdown-exit: 1.0.0-beta.9 - unplugin: 2.3.11 + unplugin: 3.0.0 unplugin-utils: 0.3.1 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) @@ -23591,11 +24080,11 @@ snapshots: vary@1.1.2: {} - vaul-vue@0.4.1(reka-ui@2.9.3)(vue@3.5.34): + vaul-vue@0.4.1(reka-ui@2.9.3)(vue@3.5.39): dependencies: - '@vueuse/core': 10.11.1(vue@3.5.34) - reka-ui: 2.9.3(vue@3.5.34) - vue: 3.5.34(typescript@6.0.2) + '@vueuse/core': 10.11.1(vue@3.5.39) + reka-ui: 2.9.3(vue@3.5.39) + vue: 3.5.39(typescript@6.0.2) transitivePeerDependencies: - '@vue/composition-api' @@ -23614,11 +24103,11 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - virtua@0.49.0(react-dom@19.2.4)(react@19.2.4)(vue@3.5.34): + virtua@0.49.0(react-dom@19.2.4)(react@19.2.4)(vue@3.5.39): optionalDependencies: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) vite-dev-rpc@1.1.0(vite@8.0.0): dependencies: @@ -23657,18 +24146,16 @@ snapshots: - unplugin-unused - yaml - vite-plugin-checker@0.13.0(@voidzero-dev/vite-plus-core@0.1.20)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.61.0)(typescript@6.0.2)(vue-tsc@3.2.6): + vite-plugin-checker@0.14.4(@voidzero-dev/vite-plus-core@0.1.20)(eslint@9.39.2)(optionator@0.9.4)(oxlint@1.61.0)(typescript@6.0.2)(vue-tsc@3.2.6): dependencies: '@babel/code-frame': 7.29.0 - chokidar: 4.0.3 + chokidar: 5.0.0 npm-run-path: 6.0.0 picocolors: 1.1.1 picomatch: 4.0.4 proper-lockfile: 4.1.2 tiny-invariant: 1.3.3 - tinyglobby: 0.2.16 vite: '@voidzero-dev/vite-plus-core@0.1.20(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(yaml@2.9.0)' - vscode-uri: 3.1.0 optionalDependencies: eslint: 9.39.2(jiti@2.7.0) optionator: 0.9.4 @@ -23676,7 +24163,7 @@ snapshots: typescript: 6.0.2 vue-tsc: 3.2.6(typescript@6.0.2) - vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.6)(vite@8.0.0): + vite-plugin-inspect@11.3.3(@nuxt/kit@4.4.8)(vite@8.0.0): dependencies: ansis: 4.2.0 debug: 4.4.3 @@ -23689,7 +24176,7 @@ snapshots: vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) vite-dev-rpc: 1.1.0(vite@8.0.0) optionalDependencies: - '@nuxt/kit': 4.4.6(magicast@0.5.2) + '@nuxt/kit': 4.4.8(magicast@0.5.3) transitivePeerDependencies: - supports-color @@ -23697,7 +24184,7 @@ snapshots: dependencies: debug: 4.4.3 pretty-bytes: 6.1.1 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) workbox-build: 7.4.0 workbox-window: 7.4.0 @@ -23706,7 +24193,7 @@ snapshots: transitivePeerDependencies: - supports-color - vite-plugin-vue-tracer@1.3.0(vite@8.0.0)(vue@3.5.34): + vite-plugin-vue-tracer@1.3.0(vite@8.0.0)(vue@3.5.39): dependencies: estree-walker: 3.0.3 exsolve: 1.0.8 @@ -23714,7 +24201,7 @@ snapshots: pathe: 2.0.3 source-map-js: 1.2.1 vite: 8.0.0(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(yaml@2.9.0) - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) vite-plus@0.1.20(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(@vitest/coverage-v8@4.1.6)(esbuild@0.27.3)(jiti@2.7.0)(terser@5.46.0)(typescript@6.0.2)(vite@8.0.0)(yaml@2.9.0): dependencies: @@ -23768,9 +24255,9 @@ snapshots: '@oxc-project/runtime': 0.115.0 lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.14 + postcss: 8.5.15 rolldown: 1.0.0-rc.9(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 optionalDependencies: '@types/node': 24.12.0 esbuild: 0.27.3 @@ -23782,9 +24269,9 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - vitest-environment-nuxt@2.0.0(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.2)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0): + vitest-environment-nuxt@2.0.0(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0): dependencies: - '@nuxt/test-utils': 4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.2)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) + '@nuxt/test-utils': 4.0.3(patch_hash=8438d6588e19230d3392ce53e45dd8e9bff54eaa3ce18092602fefd40c2eefe9)(@playwright/test@1.60.0)(@voidzero-dev/vite-plus-test@0.1.20)(@vue/test-utils@2.4.6)(magicast@0.5.3)(playwright-core@1.60.0)(typescript@6.0.2)(vite@8.0.0) transitivePeerDependencies: - '@cucumber/cucumber' - '@jest/globals' @@ -23828,24 +24315,24 @@ snapshots: vue-component-type-helpers@2.2.12: {} - vue-component-type-helpers@3.3.3: {} + vue-component-type-helpers@3.3.5: {} - vue-data-ui@3.20.11(vue@3.5.34): + vue-data-ui@3.22.0(vue@3.5.39): dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) - vue-demi@0.14.10(vue@3.5.34): + vue-demi@0.14.10(vue@3.5.39): dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) vue-devtools-stub@0.1.0: {} - vue-docgen-api@4.79.2(vue@3.5.34): + vue-docgen-api@4.79.2(vue@3.5.39): dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 - '@vue/compiler-dom': 3.5.34 - '@vue/compiler-sfc': 3.5.34 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-sfc': 3.5.39 ast-types: 0.16.1 esm-resolve: 1.0.11 hash-sum: 2.0.0 @@ -23853,8 +24340,8 @@ snapshots: pug: 3.0.3 recast: 0.23.11 ts-map: 1.0.3 - vue: 3.5.34(typescript@6.0.2) - vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.34) + vue: 3.5.39(typescript@6.0.2) + vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.39) vue-i18n-extract@2.0.7: dependencies: @@ -23864,21 +24351,21 @@ snapshots: is-valid-glob: 1.0.0 js-yaml: 4.1.1 - vue-i18n@11.2.8(vue@3.5.34): + vue-i18n@11.2.8(vue@3.5.39): dependencies: '@intlify/core-base': 11.2.8 '@intlify/shared': 11.2.8 '@vue/devtools-api': 6.6.4 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) - vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.5.34): + vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.5.39): dependencies: - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) - vue-router@5.0.4(@vue/compiler-sfc@3.5.34)(vue@3.5.34): + vue-router@5.0.4(@vue/compiler-sfc@3.5.39)(vue@3.5.39): dependencies: '@babel/generator': 7.29.1 - '@vue-macros/common': 3.1.2(vue@3.5.34) + '@vue-macros/common': 3.1.2(vue@3.5.39) '@vue/devtools-api': 8.1.0 ast-walker-scope: 0.8.3 chokidar: 5.0.0 @@ -23890,13 +24377,13 @@ snapshots: pathe: 2.0.3 picomatch: 4.0.4 scule: 1.3.0 - tinyglobby: 0.2.16 + tinyglobby: 0.2.17 unplugin: 3.0.0 unplugin-utils: 0.3.1 - vue: 3.5.34(typescript@6.0.2) + vue: 3.5.39(typescript@6.0.2) yaml: 2.9.0 optionalDependencies: - '@vue/compiler-sfc': 3.5.34 + '@vue/compiler-sfc': 3.5.39 vue-tsc@3.2.6(typescript@6.0.2): dependencies: @@ -23904,13 +24391,13 @@ snapshots: '@vue/language-core': 3.2.6 typescript: 6.0.2 - vue@3.5.34(typescript@6.0.2): + vue@3.5.39(typescript@6.0.2): dependencies: - '@vue/compiler-dom': 3.5.34 - '@vue/compiler-sfc': 3.5.34 - '@vue/runtime-dom': 3.5.34 - '@vue/server-renderer': 3.5.34(vue@3.5.34) - '@vue/shared': 3.5.34 + '@vue/compiler-dom': 3.5.39 + '@vue/compiler-sfc': 3.5.39 + '@vue/runtime-dom': 3.5.39 + '@vue/server-renderer': 3.5.39(vue@3.5.39) + '@vue/shared': 3.5.39 optionalDependencies: typescript: 6.0.2 @@ -24029,8 +24516,8 @@ snapshots: with@7.0.2: dependencies: - '@babel/parser': 7.29.3 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 assert-never: 1.4.0 babel-walk: 3.0.0-canary-5 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f5f4ead8d4..a4e58c5bb4 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -36,7 +36,7 @@ ignoreWorkspaceRootCheck: true overrides: '@types/node': 24.12.0 - nuxt-og-image: ^6.4.3 + nuxt-og-image: ^6.6.0 sharp: 0.34.5 vite: npm:@voidzero-dev/vite-plus-core@0.1.20 vitest: npm:@voidzero-dev/vite-plus-test@0.1.20 @@ -48,7 +48,8 @@ packageExtensions: estree-walker: ^3.0.3 'unplugin-vue-markdown': peerDependencies: - 'vite': '^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 || ^8.0.0' + 'vite': '^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 || + ^8.0.0' patchedDependencies: '@jsr/deno__doc@0.189.1': patches/@jsr__deno__doc@0.189.1.patch diff --git a/public/blog/coderabbit-x-npmx.png b/public/blog/coderabbit-x-npmx.png new file mode 100644 index 0000000000..c61786c605 Binary files /dev/null and b/public/blog/coderabbit-x-npmx.png differ diff --git a/public/blog/languages-rainbow-comet.png b/public/blog/languages-rainbow-comet.png new file mode 100644 index 0000000000..0348f648d4 Binary files /dev/null and b/public/blog/languages-rainbow-comet.png differ diff --git a/public/blog/noodles-rainbow-comet.png b/public/blog/noodles-rainbow-comet.png new file mode 100644 index 0000000000..bed7b47510 Binary files /dev/null and b/public/blog/noodles-rainbow-comet.png differ diff --git a/public/blog/og/release-rainbow-comet.png b/public/blog/og/release-rainbow-comet.png new file mode 100644 index 0000000000..7dd4ddb8a2 Binary files /dev/null and b/public/blog/og/release-rainbow-comet.png differ diff --git a/public/blog/stats-tab.png b/public/blog/stats-tab.png new file mode 100644 index 0000000000..8c6e375ee8 Binary files /dev/null and b/public/blog/stats-tab.png differ diff --git a/public/robots.txt b/public/robots.txt index 8e8a84d320..09de95ffc7 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,3 +1,7 @@ +# Default Settings +User-agent: * + +# Pages that bots are allowed to visit Allow: /$ Allow: /about$ Allow: /accessibility$ @@ -12,9 +16,6 @@ Allow: /opensearch.xml$ Disallow: / -# User-agent: * -# Allow: / - # Search pages: infinite query-param combinations Disallow: /search diff --git a/scripts/generate-file-tree-sprite.ts b/scripts/generate-file-tree-sprite.ts index ac691de737..29bf2d615e 100644 --- a/scripts/generate-file-tree-sprite.ts +++ b/scripts/generate-file-tree-sprite.ts @@ -10,19 +10,22 @@ import { COMPOUND_EXTENSIONS, DEFAULT_ICON, } from '../app/utils/file-icons.ts' +import customIcons from '../assets/media/custom-icons.json' with { type: 'json' } const rootDir = process.cwd() -const outputDevPath = path.join(rootDir, 'public', 'file-tree-sprite.svg') -const outputStagePath = path.join(rootDir, 'public-dev', 'file-tree-sprite.svg') -const outputProdPath = path.join(rootDir, 'public-prod', 'file-tree-sprite.svg') +const outputDevPath = path.join(rootDir, 'public-dev', 'file-tree-sprite.svg') +const outputStagePath = path.join(rootDir, 'public-staging', 'file-tree-sprite.svg') +const outputProdPath = path.join(rootDir, 'public', 'file-tree-sprite.svg') -const COLLECTION_NAMES = ['lucide', 'simple-icons', 'svg-spinners', 'vscode-icons'] +const ICONIFY_COLLECTION_NAMES = ['lucide', 'simple-icons', 'svg-spinners', 'vscode-icons'] -const COLLECTION_REGEXP = new RegExp(`^(${COLLECTION_NAMES.join('|')})-(.+)$`) +const COLLECTION_REGEXP = new RegExp(`^(${ICONIFY_COLLECTION_NAMES.join('|')}|custom)-(.+)$`) async function loadCollections() { - const collections: { [key: string]: IconifyJSON } = {} - for (const name of COLLECTION_NAMES) { + const collections: { [key: string]: IconifyJSON } = { + custom: { icons: customIcons, prefix: 'custom' }, + } + for (const name of ICONIFY_COLLECTION_NAMES) { const filePathUrl = import.meta.resolve(`@iconify-json/${name}/icons.json`) const filePath = fileURLToPath(filePathUrl) const raw = await fs.readFile(filePath, 'utf8') diff --git a/server/api/changelog/info/[name]/v/[version].get.ts b/server/api/changelog/info/[name]/v/[version].get.ts index af77ea44ce..b01365900d 100644 --- a/server/api/changelog/info/[name]/v/[version].get.ts +++ b/server/api/changelog/info/[name]/v/[version].get.ts @@ -38,7 +38,7 @@ export default defineCachedEventHandler(async event => { return await detectChangelog(pkg) } catch (error) { handleApiError(error, { - statusCode: 502, + statusCode: 500, message: ERROR_PACKAGE_DETECT_CHANGELOG, }) } diff --git a/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts b/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts index 8b6252bd12..a9be7b4251 100644 --- a/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts +++ b/server/api/changelog/md/[provider]/[owner]/[repo]/[...path].get.ts @@ -31,7 +31,7 @@ export default defineCachedEventHandler( } } catch (error) { handleApiError(error, { - statusCode: 502, + statusCode: 500, message: ERROR_CHANGELOG_FILE_FAILED, }) } @@ -44,13 +44,14 @@ export default defineCachedEventHandler( const repo = getRouterParam(event, 'repo') ?? '' const owner = getRouterParam(event, 'owner') ?? '' const path = getRouterParam(event, 'path') ?? '' - return `changelogMarkdown:v1:${provider}:${owner}:${repo}:${path.replaceAll('/', ':')}` + return `changelogMarkdown:v2:${provider}:${owner}:${repo}:${path.replaceAll('/', ':')}` }, + shouldBypassCache: () => import.meta.dev, }, ) async function getGithubMarkDown(owner: string, repo: string, path: string) { - const data = await $fetch(`https://ungh.cc/repos/${owner}/${repo}/files/HEAD/${path}`) + const data = await $fetch(`https://raw.githubusercontent.com/${owner}/${repo}/HEAD/${path}`) const markdown = v.parse(v.string(), data) diff --git a/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts b/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts index e7d2b528a5..eb249ca832 100644 --- a/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts +++ b/server/api/changelog/releases/[provider]/[owner]/[repo].get.ts @@ -34,7 +34,7 @@ export default defineCachedEventHandler( } } catch (error) { handleApiError(error, { - statusCode: 502, + statusCode: 500, message: ERROR_CHANGELOG_RELEASES_FAILED, }) } @@ -46,8 +46,9 @@ export default defineCachedEventHandler( const provider = getRouterParam(event, 'provider') const repo = getRouterParam(event, 'repo') const owner = getRouterParam(event, 'owner') - return `changelogRelease:v1:${provider}:${owner}:${repo}` + return `changelogRelease:v2:${provider}:${owner}:${repo}` }, + shouldBypassCache: () => import.meta.dev, }, ) @@ -77,6 +78,7 @@ async function getReleasesFromGithub(owner: string, repo: string) { prerelease: r.prerelease, toc, publishedAt: r.publishedAt, + link: `https://github.com/${owner}/${repo}/releases/tag/${r.tag}`, } satisfies ReleaseData }) } diff --git a/server/api/embed/downloads.svg.get.ts b/server/api/embed/downloads.svg.get.ts new file mode 100644 index 0000000000..c009e79d0a --- /dev/null +++ b/server/api/embed/downloads.svg.get.ts @@ -0,0 +1,24 @@ +/** + * Embedding of the downloads trends chart (single package via ChartModal, or multiple via compare) + * A static svg is generated from the endpoint. + */ +import { createDownloadsSvgResponse } from '~~/server/utils/embed-downloads-svg' +import { CACHE_MAX_AGE_ONE_HOUR } from '#shared/utils/constants' + +export default defineCachedEventHandler( + async event => { + const svg = await createDownloadsSvgResponse(getQuery(event)) + + setHeader(event, 'Content-Type', 'image/svg+xml; charset=utf-8') + setHeader(event, 'Cache-Control', 'public, max-age=3600, s-maxage=86400') + setHeader(event, 'Access-Control-Allow-Origin', '*') + + return svg + }, + { + maxAge: CACHE_MAX_AGE_ONE_HOUR, + swr: true, + name: 'embed-package-downloads', + getKey: event => event.node.req.url || event.path, + }, +) diff --git a/server/api/registry/compare-file/[...pkg].get.ts b/server/api/registry/compare-file/[...pkg].get.ts index eb0f03e1ad..5f5504e01d 100644 --- a/server/api/registry/compare-file/[...pkg].get.ts +++ b/server/api/registry/compare-file/[...pkg].get.ts @@ -1,11 +1,53 @@ import * as v from 'valibot' import { PackageFileDiffQuerySchema } from '#shared/schemas/package' +import { countDiffStats, createDiff, insertSkipBlocks, truncateDiffHunks } from '#shared/utils/diff' +import type { DiffHunk, DiffSkipBlock } from '#shared/types/compare' -const CACHE_VERSION = 1 +const CACHE_VERSION = 3 const DIFF_TIMEOUT = 15000 // 15 sec -/** Maximum file size for diffing (250KB - smaller than viewing since we diff two files) */ -const MAX_DIFF_FILE_SIZE = 250 * 1024 +/** Files above this size use a cheaper plain-text diff renderer. */ +const LARGE_DIFF_MODE_BYTES = 250 * 1024 +/** Maximum file size for modified-file diffs. */ +const MAX_MODIFIED_DIFF_INPUT_BYTES = 1024 * 1024 +/** Maximum file size for added/removed-file diffs, which render the whole file. */ +const MAX_SINGLE_SIDED_DIFF_INPUT_BYTES = LARGE_DIFF_MODE_BYTES +/** Maximum number of changed/context lines returned to the client. */ +const MAX_DIFF_OUTPUT_LINES = 5000 +/** Maximum rendered diff lines we'll syntax-highlight. */ +const MAX_HIGHLIGHT_DIFF_LINES = 1000 +/** Maximum rendered diff text we'll syntax-highlight. */ +const MAX_HIGHLIGHT_DIFF_BYTES = 128 * 1024 + +function byteLength(content: string): number { + return Buffer.byteLength(content, 'utf8') +} + +function countRenderableDiffLines(hunks: (DiffHunk | DiffSkipBlock)[]): number { + let count = 0 + + for (const hunk of hunks) { + if (hunk.type === 'hunk') count += hunk.lines.length + } + + return count +} + +function countRenderableDiffBytes(hunks: (DiffHunk | DiffSkipBlock)[]): number { + let count = 0 + + for (const hunk of hunks) { + if (hunk.type !== 'hunk') continue + for (const line of hunk.lines) { + for (const segment of line.content) { + count += byteLength(segment.value) + } + count += 1 + } + } + + return count +} /** * Fetch file content from jsDelivr with size check @@ -14,6 +56,7 @@ async function fetchFileContentForDiff( packageName: string, version: string, filePath: string, + maxBytes: number, signal?: AbortSignal, ): Promise { const url = `https://cdn.jsdelivr.net/npm/${packageName}@${version}/${filePath}` @@ -35,19 +78,19 @@ async function fetchFileContentForDiff( } const contentLength = response.headers.get('content-length') - if (contentLength && parseInt(contentLength, 10) > MAX_DIFF_FILE_SIZE) { + if (contentLength && parseInt(contentLength, 10) > maxBytes) { throw createError({ statusCode: 413, - message: `File too large to diff (${(parseInt(contentLength, 10) / 1024).toFixed(0)}KB). Maximum is ${MAX_DIFF_FILE_SIZE / 1024}KB.`, + message: `File too large to diff (${(parseInt(contentLength, 10) / 1024).toFixed(0)}KB). Maximum is ${maxBytes / 1024}KB.`, }) } const content = await response.text() - if (content.length > MAX_DIFF_FILE_SIZE) { + if (byteLength(content) > maxBytes) { throw createError({ statusCode: 413, - message: `File too large to diff (${(content.length / 1024).toFixed(0)}KB). Maximum is ${MAX_DIFF_FILE_SIZE / 1024}KB.`, + message: `File too large to diff (${(byteLength(content) / 1024).toFixed(0)}KB). Maximum is ${maxBytes / 1024}KB.`, }) } @@ -138,8 +181,20 @@ export default defineCachedEventHandler( // Fetch file contents in parallel const [fromContent, toContent] = await Promise.all([ - fetchFileContentForDiff(packageName, fromVersion, filePath, controller.signal), - fetchFileContentForDiff(packageName, toVersion, filePath, controller.signal), + fetchFileContentForDiff( + packageName, + fromVersion, + filePath, + MAX_MODIFIED_DIFF_INPUT_BYTES, + controller.signal, + ), + fetchFileContentForDiff( + packageName, + toVersion, + filePath, + MAX_MODIFIED_DIFF_INPUT_BYTES, + controller.signal, + ), ]) clearTimeout(timeoutId) @@ -159,8 +214,27 @@ export default defineCachedEventHandler( type = 'modify' } + const fromSize = fromContent === null ? 0 : byteLength(fromContent) + const toSize = toContent === null ? 0 : byteLength(toContent) + const largestSize = Math.max(fromSize, toSize) + + if (type !== 'modify' && largestSize > MAX_SINGLE_SIDED_DIFF_INPUT_BYTES) { + throw createError({ + statusCode: 413, + message: `File too large to diff (${(largestSize / 1024).toFixed(0)}KB). Maximum is ${MAX_SINGLE_SIDED_DIFF_INPUT_BYTES / 1024}KB for added or removed files.`, + }) + } + + const large = largestSize > LARGE_DIFF_MODE_BYTES + const effectiveDiffOptions = large + ? { + ...diffOptions, + mergeModifiedLines: false, + } + : diffOptions + // Create diff with options - const diff = createDiff(fromContent ?? '', toContent ?? '', filePath, diffOptions) + const diff = createDiff(fromContent ?? '', toContent ?? '', filePath, effectiveDiffOptions) if (!diff) { // No changes (shouldn't happen but handle it) @@ -172,7 +246,7 @@ export default defineCachedEventHandler( type, hunks: [], stats: { additions: 0, deletions: 0 }, - meta: { computeTime: Date.now() - startTime }, + meta: { large, computeTime: Date.now() - startTime }, } satisfies FileDiffResponse } @@ -180,15 +254,19 @@ export default defineCachedEventHandler( const hunkOnly = diff.hunks.filter((h): h is DiffHunk => h.type === 'hunk') const hunksWithSkips = insertSkipBlocks(hunkOnly) const stats = countDiffStats(hunksWithSkips) + const { hunks, truncated } = truncateDiffHunks(hunksWithSkips, MAX_DIFF_OUTPUT_LINES) + const shouldHighlight = + !truncated && + countRenderableDiffLines(hunks) <= MAX_HIGHLIGHT_DIFF_LINES && + countRenderableDiffBytes(hunks) <= MAX_HIGHLIGHT_DIFF_BYTES // Syntax-highlight diff segments using server-side Shiki const language = getLanguageFromPath(filePath) - const shiki = await getShikiHighlighter() - const loadedLangs = shiki.getLoadedLanguages() - const canHighlight = loadedLangs.includes(language as never) + const shiki = shouldHighlight ? await getShikiHighlighter() : null + const loadedLangs = shiki?.getLoadedLanguages() ?? [] - if (canHighlight) { - for (const hunk of hunksWithSkips) { + if (shiki && loadedLangs.includes(language as never)) { + for (const hunk of hunks) { if (hunk.type !== 'hunk') continue for (const line of hunk.lines) { line.content = line.content.map(seg => { @@ -215,9 +293,14 @@ export default defineCachedEventHandler( to: toVersion, path: filePath, type, - hunks: hunksWithSkips, + hunks, stats, - meta: { computeTime: Date.now() - startTime }, + meta: { + large, + truncated, + truncationReason: truncated ? 'too_many_lines' : undefined, + computeTime: Date.now() - startTime, + }, } satisfies FileDiffResponse } catch (error) { clearTimeout(timeoutId) diff --git a/server/api/registry/file/[...pkg].get.ts b/server/api/registry/file/[...pkg].get.ts index e3d0c37d2d..da250d9026 100644 --- a/server/api/registry/file/[...pkg].get.ts +++ b/server/api/registry/file/[...pkg].get.ts @@ -1,4 +1,5 @@ import * as v from 'valibot' +import type { InternalImportsMap, PackageExportsMap } from '#server/utils/import-resolver' import { PackageFileQuerySchema } from '#shared/schemas/package' import type { ReadmeResponse } from '#shared/types/readme' import { @@ -27,6 +28,8 @@ interface PackageJson { devDependencies?: Record peerDependencies?: Record optionalDependencies?: Record + imports?: InternalImportsMap + exports?: PackageExportsMap } /** @@ -161,7 +164,14 @@ export default defineCachedEventHandler( // Create resolver for relative imports if (fileTreeResponse) { const files = flattenFileTree(fileTreeResponse.tree) - resolveRelative = createImportResolver(files, filePath, packageName, version) + resolveRelative = createImportResolver( + files, + filePath, + packageName, + version, + pkgJson?.imports, + pkgJson?.exports, + ) } } diff --git a/server/middleware/canonical-redirects.global.ts b/server/middleware/canonical-redirects.global.ts index 89f1d2a813..738612c2a7 100644 --- a/server/middleware/canonical-redirects.global.ts +++ b/server/middleware/canonical-redirects.global.ts @@ -21,6 +21,8 @@ const pages = [ '/blog', '/brand', '/compare', + '/noodles', + '/sponsors', '/org', '/package', '/package-code', diff --git a/server/utils/changelog/detectChangelog.ts b/server/utils/changelog/detectChangelog.ts index 6f8393a4af..9c98e16416 100644 --- a/server/utils/changelog/detectChangelog.ts +++ b/server/utils/changelog/detectChangelog.ts @@ -1,9 +1,5 @@ -import type { - ChangelogMarkdownInfo, - ChangelogInfo, - ChangelogReleaseInfo, -} from '~~/shared/types/changelog' -import type { FetchError } from 'ofetch' +import type { ChangelogMarkdownInfo, ChangelogInfo } from '~~/shared/types/changelog' +import { FetchError } from 'ofetch' import type { ExtendedPackageJson } from '~~/shared/utils/package-analysis' import { type RepoRef, parseRepoUrl } from '~~/shared/utils/git-providers' import { ERROR_CHANGELOG_NOT_FOUND, ERROR_UNGH_API_KEY_EXHAUSTED } from '~~/shared/utils/constants' @@ -11,6 +7,8 @@ import { GithubReleaseSchama } from '~~/shared/schemas/changelog/release' import { resolveURL } from 'ufo' import * as v from 'valibot' +type SafeResult = [R, null] | [null, E] + /** * Detect whether changelogs/releases are available for this package * @@ -26,8 +24,8 @@ export async function detectChangelog(pkg: ExtendedPackageJson) { return false } - const releases = await checkReleases(repoRef, pkg.repository.directory) - if (releases && !isError(releases)) { + const [releases, releasesError] = await checkReleases(repoRef, pkg.repository.directory) + if (releases) { return releases } @@ -36,8 +34,8 @@ export async function detectChangelog(pkg: ExtendedPackageJson) { return changelog } - if (isError(releases)) { - throw releases + if (releasesError) { + throw releasesError } throw createError({ @@ -53,14 +51,13 @@ export async function detectChangelog(pkg: ExtendedPackageJson) { async function checkReleases( ref: RepoRef, directory?: string, -): Promise { +): Promise> { switch (ref.provider) { case 'github': { return checkLatestGithubRelease(ref, directory) } } - - return false + return [false, null] } /// releases @@ -68,50 +65,74 @@ async function checkReleases( const MD_REGEX = /(?<=\[.*?(changelog|releases|changes|history|news)\.md.*?\]\()(.*?)(?=\))/i const ROOT_ONLY_REGEX = /^\/[^/]+$/ -function checkLatestGithubRelease( +async function checkLatestGithubRelease( ref: RepoRef, directory?: string, -): Promise { - return $fetch(`https://ungh.cc/repos/${ref.owner}/${ref.repo}/releases/latest`) - .then(r => { - const { release } = v.parse(v.object({ release: GithubReleaseSchama }), r) +): Promise> { + try { + const response = await $fetch(`https://ungh.cc/repos/${ref.owner}/${ref.repo}/releases/latest`) - const matchedChangelog = release.markdown?.match(MD_REGEX)?.at(0) + const { release } = v.parse(v.object({ release: GithubReleaseSchama }), response) - // if no changelog.md or the url doesn't contain /blob/ - if (!matchedChangelog || !matchedChangelog.includes('/blob/')) { - return { + const matchedChangelog = release.markdown?.match(MD_REGEX)?.at(0) + + // if no changelog.md or the url doesn't contain /blob/ + if (!matchedChangelog || !matchedChangelog.includes('/blob/')) { + return [ + { provider: ref.provider, type: 'release', repo: `${ref.owner}/${ref.repo}`, link: `https://github.com/${ref.owner}/${ref.repo}/releases`, - } satisfies ChangelogReleaseInfo - } - - const path = matchedChangelog.replace(/^.*\/blob\/[^/]+\//i, '') + }, + null, + ] + } - if (directory && !(path.startsWith(directory) || ROOT_ONLY_REGEX.test(path))) { - return false as const - } - return { + const path = matchedChangelog.replace(/^.*\/blob\/[^/]+\//i, '') + + // makes sure that the correct directory is matched + if ( + directory && + !( + path.startsWith(directory.endsWith('/') ? directory : `${directory}/`) || + ROOT_ONLY_REGEX.test(path) + ) + ) { + return [false, null] + } + return [ + { provider: ref.provider, type: 'md', path, repo: `${ref.owner}/${ref.repo}`, link: matchedChangelog, - } satisfies ChangelogMarkdownInfo - }) - .catch((e: FetchError) => { + }, + null, + ] + } catch (e) { + if (!(e instanceof Error)) { + // shouldn't be reachable, but is here for type safety + return [false, null] + } + if (e instanceof FetchError) { + if (e.statusCode == 404) { + return [false, null] + } if (e.statusCode === 403 || e.statusCode === 429) { - // with 403/429 ungh.cc has exhausted it's api keys, returning error to indicate this - return createError({ - statusCode: 502, - statusMessage: ERROR_UNGH_API_KEY_EXHAUSTED, - }) + return [ + null, + createError({ + statusCode: 502, + statusMessage: ERROR_UNGH_API_KEY_EXHAUSTED, + }), + ] } - - return false as const - }) + } + console.error('[checkLatestGithubRelease] unexpected error: ', e) + return [null, e] + } } /// changelog markdown @@ -176,7 +197,7 @@ function getBaseFileUrl(ref: RepoRef): RepoFileUrl | null { switch (ref.provider) { case 'github': return { - raw: `https://ungh.cc/repos/${ref.owner}/${ref.repo}/files/HEAD`, + raw: `https://raw.githubusercontent.com/${ref.owner}/${ref.repo}/HEAD`, blob: `https://github.com/${ref.owner}/${ref.repo}/blob/HEAD`, } } diff --git a/server/utils/changelog/markdown.ts b/server/utils/changelog/markdown.ts index 7557f3150a..aa11c19f88 100644 --- a/server/utils/changelog/markdown.ts +++ b/server/utils/changelog/markdown.ts @@ -1,231 +1,106 @@ -import { type Tokens, marked } from 'marked' import { - type prefixId as prefixIdFn, - ALLOWED_ATTR, - ALLOWED_TAGS, - calculateSemanticDepth, + type ProcessImageUrlFn, + type ProcessLinkFn, + type ToUserContentIdFn, + USER_CONTENT_PREFIX, + blockquote, + createCodeHighlighter, + createHeading, + createHtml, + createImage, + createLink, + decodeHashFragment, isNpmJsUrlThatCanBeRedirected, -} from '../readme' -import { stripHtmlTags, slugify } from '#shared/utils/html' -import sanitizeHtml from 'sanitize-html' -import { hasProtocol } from 'ufo' - -const EMAIL_REGEX = /^[\w+\-.]+@[\w\-.]+\.[a-z]+$/i + createMarkedHeadingExtension, + renderToRawHtml, + sanitizeRawHTML, +} from '../mdKit' +import { slugify } from '#shared/utils/html' +import { Marked } from 'marked' +import { hasProtocol, joinRelativeURL, parseFilename } from 'ufo' +import { convertToEmoji } from '#shared/utils/emoji' + +// cl = ChangeLog +const clMarked = new Marked() + +clMarked.use({ + tokenizer: { + heading: createMarkedHeadingExtension(true), + }, +}) export async function changelogRenderer(mdRepoInfo: MarkdownRepoInfo) { - const renderer = new marked.Renderer({ + const renderer = new clMarked.Renderer({ gfm: true, }) - const shiki = await getShikiHighlighter() - - renderer.link = function ({ href, title, tokens }: Tokens.Link) { - const eTitle = escapeHtml(title ?? '') - const text = this.parser.parseInline(tokens) - const titleAttr = eTitle ? ` title="${eTitle}"` : '' - const plainText = escapeHtml(stripHtmlTags(text).trim()) - - if (href.startsWith('mailto:') && !EMAIL_REGEX.test(plainText)) { - return text - } - - const intermediateTitleAttr = `data-title-intermediate="${plainText || eTitle}"` - - return `${text}` - } - // GitHub-style callouts: > [!NOTE], > [!TIP], etc. - renderer.blockquote = function ({ tokens }: Tokens.Blockquote) { - const body = this.parser.parse(tokens) - - const calloutMatch = body.match(/^

\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\](?:
)?\s*/i) - - if (calloutMatch?.[1]) { - const calloutType = calloutMatch[1].toLowerCase() - const cleanedBody = body.replace(calloutMatch[0], '

') - return `

${cleanedBody}
\n` - } - - return `
${body}
\n` - } + renderer.blockquote = blockquote // Syntax highlighting for code blocks (uses shared highlighter) - renderer.code = ({ text, lang }: Tokens.Code) => { - const html = highlightCodeSync(shiki, text, lang || 'text') - // Add copy button - return `
- - ${html} -
` - } + renderer.code = await createCodeHighlighter() - return (markdown: string | null, releaseId?: string | number) => { + return (markdownBody: string | null, releaseId?: string | number) => { // Collect table of contents items during parsing - const toc: TocItem[] = [] + // const toc: TocItem[] = [] - if (!markdown) { + if (!markdownBody) { return { html: null, - toc, + toc: [], } } const idPrefix = releaseId ? `user-content-${releaseId}` : `user-content` - // Track used heading slugs to handle duplicates (GitHub-style: foo, foo-1, foo-2) - const usedSlugs = new Map() + const lastSemanticLevel = releaseId ? 2 : 1 - let lastSemanticLevel = releaseId ? 2 : 1 // Start after h2 (the "Readme" section heading) - renderer.heading = function ({ tokens, depth }: Tokens.Heading) { - // Calculate the target semantic level based on document structure - // Start at h3 (since page h1 + section h2 already exist) - // But ensure we never skip levels - can only go down by 1 or stay same/go up - const semanticLevel = calculateSemanticDepth(depth, lastSemanticLevel) - lastSemanticLevel = semanticLevel - const text = this.parser.parseInline(tokens) + function toUserContentId(id: string) { + return `${idPrefix}-${id}` + } - // Generate GitHub-style slug for anchor links - // adding release id to prevent conflicts - let slug = slugify(text) - if (!slug) slug = 'heading' // Fallback for empty headings + const processLink: ProcessLinkFn = (href: string, _label: string) => { + const resolvedHref = resolveUrl(href, mdRepoInfo, toUserContentId) - // Handle duplicate slugs (GitHub-style: foo, foo-1, foo-2) - const count = usedSlugs.get(slug) ?? 0 - usedSlugs.set(slug, count + 1) - const uniqueSlug = count === 0 ? slug : `${slug}-${count}` + // Security attributes for external links + let extraAttrs = + resolvedHref && hasProtocol(resolvedHref, { acceptRelative: true }) + ? ' rel="nofollow noreferrer noopener" target="_blank"' + : '' - // Prefix with 'user-content-' to avoid collisions with page IDs - // (e.g., #install, #dependencies, #versions are used by the package page) - const id = `${idPrefix}-${uniqueSlug}` + return { resolvedHref, extraAttrs } + } - // Collect TOC item with plain text (HTML stripped & emoji's added) - const plainText = convertToEmoji(stripHtmlTags(text)) - .replace(/ ?/g, '') // remove non breaking spaces - .trim() - if (plainText) { - toc.push({ text: plainText, id, depth }) - } + renderer.link = createLink(processLink) - return `${text} \n` - } + const { heading, toc, processHeading } = createHeading({ + lastSemanticLevel, + toUserContentId, + }) + renderer.heading = heading - // Helper to prefix id attributes with 'user-content-' - const prefixId: typeof prefixIdFn = (tagName: string, attribs: sanitizeHtml.Attributes) => { - if (attribs.id && !attribs.id.startsWith('user-content-')) { - attribs.id = `${idPrefix}-${attribs.id}` - } - return { tagName, attribs } - } + renderer.html = createHtml({ processHeading, processLink }) + + const processImageUrl: ProcessImageUrlFn = href => + resolveImageUrl(href, mdRepoInfo, toUserContentId) + + renderer.image = createImage(processImageUrl) + + const rawHtml = renderToRawHtml({ renderer, markdownBody, markedInstance: clMarked }) return { - html: sanitizeRawHTML( - convertToEmoji( - marked.parse(markdown, { - renderer, - }) as string, - ), - mdRepoInfo, - prefixId, - idPrefix, - ), + html: sanitizeRawHTML(convertToEmoji(rawHtml), { + processImageUrl, + processLink, + toUserContentId, + lastSemanticLevel, + }), toc, } } } -export function sanitizeRawHTML( - rawHtml: string, - mdRepoInfo: MarkdownRepoInfo, - prefixId: typeof prefixIdFn, - idPrefix: string, -) { - return sanitizeHtml(rawHtml, { - allowedTags: ALLOWED_TAGS, - allowedAttributes: ALLOWED_ATTR, - allowedSchemes: ['http', 'https', 'mailto'], - // Transform img src URLs (GitHub blob โ†’ raw, relative โ†’ GitHub raw) - transformTags: { - h1: (_, attribs) => { - return { tagName: 'h3', attribs: { ...attribs, 'data-level': '1' } } - }, - h2: (_, attribs) => { - return { tagName: 'h4', attribs: { ...attribs, 'data-level': '2' } } - }, - h3: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h3', attribs: attribs } - return { tagName: 'h5', attribs: { ...attribs, 'data-level': '3' } } - }, - h4: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h4', attribs: attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '4' } } - }, - h5: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h5', attribs: attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '5' } } - }, - h6: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h6', attribs: attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '6' } } - }, - img: (tagName, attribs) => { - if (attribs.src) { - attribs.src = resolveUrl(attribs.src, mdRepoInfo, idPrefix) - } - return { tagName, attribs } - }, - source: (tagName, attribs) => { - if (attribs.src) { - attribs.src = resolveUrl(attribs.src, mdRepoInfo, idPrefix) - } - if (attribs.srcset) { - attribs.srcset = attribs.srcset - .split(',') - .map(entry => { - const parts = entry.trim().split(/\s+/) - const url = parts[0] - if (!url) return entry.trim() - const descriptor = parts[1] - const resolvedUrl = resolveUrl(url, mdRepoInfo, idPrefix) - return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl - }) - .join(', ') - } - return { tagName, attribs } - }, - a: (tagName, attribs) => { - if (!attribs.href) { - return { tagName, attribs } - } - - let resolvedHref = resolveUrl(attribs.href, mdRepoInfo, idPrefix) - - if (resolvedHref.startsWith('$')) { - resolvedHref = resolvedHref.replace('$', '') - } - - // Add security attributes for external links - if (resolvedHref && hasProtocol(resolvedHref, { acceptRelative: true })) { - attribs.rel = 'nofollow noreferrer noopener' - attribs.target = '_blank' - } else { - attribs.target = '' - } - attribs.href = resolvedHref - return { tagName, attribs } - }, - div: prefixId, - p: prefixId, - span: prefixId, - section: prefixId, - article: prefixId, - }, - }) -} - -interface MarkdownRepoInfo { +export interface MarkdownRepoInfo { /** Raw file URL base (e.g., https://raw.githubusercontent.com/owner/repo/HEAD) */ rawBaseUrl: string /** Blob/rendered file URL base (e.g., https://github.com/owner/repo/blob/HEAD) */ @@ -236,14 +111,14 @@ interface MarkdownRepoInfo { path?: string } -function resolveUrl(url: string, repoInfo: MarkdownRepoInfo, idPrefix: string) { +function resolveUrl(url: string, repoInfo: MarkdownRepoInfo, toUserContentId: ToUserContentIdFn) { if (!url || url.startsWith('$')) return url if (url.startsWith('#')) { - if (url.startsWith('#user-content')) { + if (url.startsWith(`#${USER_CONTENT_PREFIX}`)) { return url } // Prefix anchor links to match heading IDs (avoids collision with page IDs) - return `#${idPrefix}-${slugify(url.slice(1))}` + return `#${toUserContentId(slugify(decodeHashFragment(url.slice(1))))}` } if (hasProtocol(url, { acceptRelative: true })) { try { @@ -281,13 +156,28 @@ function resolveUrl(url: string, repoInfo: MarkdownRepoInfo, idPrefix: string) { return url } +function resolveImageUrl( + url: string, + repoInfo: MarkdownRepoInfo, + toUserContentId: ToUserContentIdFn, +): string { + // Skip already-proxied URLs (from a previous resolveImageUrl call in the + // marked renderer โ€” sanitizeHtml transformTags may call this again) + if (url.startsWith('/api/registry/image-proxy')) { + return url + } + const rawUrl = resolveUrl(url, repoInfo, toUserContentId) + const { imageProxySecret } = useRuntimeConfig() + return toProxiedImageUrl(rawUrl, imageProxySecret) +} + /** * check resolved url that it still contains the base url - * @returns the resolved url if starting with baseUrl else baseUrl + * @returns the resolved url if starting with baseUrl else baseUrl/filename.ext */ function checkResolvedUrl(resolved: string, baseUrl: string) { if (resolved.startsWith(baseUrl)) { return resolved } - return baseUrl + return joinRelativeURL(baseUrl, parseFilename(resolved) ?? '') } diff --git a/server/utils/code-highlight.ts b/server/utils/code-highlight.ts index cbb7669af1..e0eb6bb885 100644 --- a/server/utils/code-highlight.ts +++ b/server/utils/code-highlight.ts @@ -171,11 +171,12 @@ export function linkifyModuleSpecifiers(html: string, options?: LinkifyOptions): const { dependencies, resolveRelative } = options ?? {} const getHref = (moduleSpecifier: string): string | null => { - const cleanSpec = moduleSpecifier.replace(/^['"]|['"]$/g, '').trim() - - // Try relative import resolution first - if (cleanSpec.startsWith('.') && resolveRelative) { - return resolveRelative(moduleSpecifier) + // First try file-aware resolution (relative imports, aliases, and self-package subpaths). + if (resolveRelative) { + const resolved = resolveRelative(moduleSpecifier) + if (resolved) { + return resolved + } } // Not a relative import - check if it's an npm package @@ -196,7 +197,7 @@ export function linkifyModuleSpecifiers(html: string, options?: LinkifyOptions): // Match: from keyword span followed by string span containing module specifier // Pattern: from 'module' let result = html.replace( - /(]*> ?from<\/span>)(]*>) (['"][^'"]+['"])<\/span>/g, + /(]*>\s*from\s*<\/span>)\s*(]*>)\s*(['"][^'"]+['"])\s*<\/span>/g, (match, fromSpan, stringSpanOpen, moduleSpecifier) => { const href = getHref(moduleSpecifier) if (!href) return match @@ -208,7 +209,7 @@ export function linkifyModuleSpecifiers(html: string, options?: LinkifyOptions): // Pattern: import 'module' // But NOT: import ... from, import(, or import { result = result.replace( - /(]*>import<\/span>)(]*>) (['"][^'"]+['"])<\/span>/g, + /(]*>\s*import\s*<\/span>)\s*(]*>)\s*(['"][^'"]+['"])\s*<\/span>/g, (match, importSpan, stringSpanOpen, moduleSpecifier) => { const href = getHref(moduleSpecifier) if (!href) return match diff --git a/server/utils/download-evolution.ts b/server/utils/download-evolution.ts new file mode 100644 index 0000000000..17422823b0 --- /dev/null +++ b/server/utils/download-evolution.ts @@ -0,0 +1,177 @@ +import type { EvolutionOptions } from '~/types/chart' + +import { mapWithConcurrency } from '#shared/utils/async' + +import { + buildDailyEvolution, + buildMonthlyEvolution, + buildWeeklyEvolution, + buildYearlyEvolution, +} from '~/utils/chart-data-buckets' + +import { addDays, parseIsoDate, toIsoDate } from '~/utils/date' + +import { + mergeDailyPoints, + splitIsoRangeIntoChunksInclusive, +} from '../../shared/utils/download-ranges' + +type DailyDownloadPoint = { + day: string + value: number +} + +type NpmDownloadsRangeResponse = { + downloads: Array<{ + day: string + downloads: number + }> +} + +function toDateOnly(value?: string): string | null { + if (!value) { + return null + } + + const dateOnly = value.slice(0, 10) + + return /^\d{4}-\d{2}-\d{2}$/.test(dateOnly) ? dateOnly : null +} + +function startOfUtcMonth(date: Date): Date { + return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1)) +} + +function startOfUtcYear(date: Date): Date { + return new Date(Date.UTC(date.getUTCFullYear(), 0, 1)) +} + +function resolveDateRange(evolutionOptions: EvolutionOptions, packageCreatedIso: string | null) { + const today = new Date() + + const yesterday = new Date( + Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate() - 1), + ) + + const endDateOnly = toDateOnly(evolutionOptions.endDate) + + const end = endDateOnly ? parseIsoDate(endDateOnly) : yesterday + + const startDateOnly = toDateOnly(evolutionOptions.startDate) + + if (startDateOnly) { + return { + start: parseIsoDate(startDateOnly), + end, + } + } + + let start: Date + + if (evolutionOptions.granularity === 'year') { + start = packageCreatedIso + ? startOfUtcYear(new Date(packageCreatedIso)) + : addDays(end, -(5 * 365) + 1) + } else if (evolutionOptions.granularity === 'month') { + const monthCount = evolutionOptions.months ?? 12 + const firstOfThisMonth = startOfUtcMonth(end) + + start = new Date( + Date.UTC( + firstOfThisMonth.getUTCFullYear(), + firstOfThisMonth.getUTCMonth() - (monthCount - 1), + 1, + ), + ) + } else if (evolutionOptions.granularity === 'week') { + const weekCount = evolutionOptions.weeks ?? 52 + + start = addDays(end, -(weekCount * 7) + 1) + } else { + start = addDays(end, -29) + } + + return { + start, + end, + } +} + +async function fetchNpmDownloadsRangeServer( + packageName: string, + startIso: string, + endIso: string, +): Promise { + const encodedName = encodeURIComponent(packageName) + + return await $fetch( + `https://api.npmjs.org/downloads/range/${startIso}:${endIso}/${encodedName}`, + ) +} + +async function fetchDailyRange( + packageName: string, + startIso: string, + endIso: string, +): Promise { + const response = await fetchNpmDownloadsRangeServer(packageName, startIso, endIso) + const downloads = Array.isArray(response?.downloads) ? response.downloads : [] + + return downloads + .slice() + .sort((a, b) => a.day.localeCompare(b.day)) + .map(download => ({ + day: download.day, + value: Number(download.downloads) || 0, + })) +} + +async function fetchDailyRangeChunked( + packageName: string, + startIso: string, + endIso: string, +): Promise { + const maximumDaysPerRequest = 540 + + const ranges = splitIsoRangeIntoChunksInclusive(startIso, endIso, maximumDaysPerRequest) + + if (ranges.length === 1) { + return fetchDailyRange(packageName, startIso, endIso) + } + + const parts = await mapWithConcurrency( + ranges, + range => fetchDailyRange(packageName, range.startIso, range.endIso), + 10, + ) + + return mergeDailyPoints(parts.flat()) +} + +export async function fetchDownloadsEvolution( + packageName: string, + evolutionOptions: EvolutionOptions, + packageCreatedIso: string | null = null, +) { + const { start, end } = resolveDateRange(evolutionOptions, packageCreatedIso) + + const startIso = toIsoDate(start) + const endIso = toIsoDate(end) + + const dailyData = await fetchDailyRangeChunked(packageName, startIso, endIso) + + switch (evolutionOptions.granularity) { + case 'year': + return buildYearlyEvolution(dailyData, startIso, endIso) + + case 'month': + return buildMonthlyEvolution(dailyData, startIso, endIso) + + case 'week': + return buildWeeklyEvolution(dailyData, startIso, endIso) + + case 'day': + default: + return buildDailyEvolution(dailyData) + } +} diff --git a/server/utils/embed-downloads-svg.ts b/server/utils/embed-downloads-svg.ts new file mode 100644 index 0000000000..454f73b13c --- /dev/null +++ b/server/utils/embed-downloads-svg.ts @@ -0,0 +1,338 @@ +import { createError } from 'h3' +import { createStaticVueUiXy } from 'vue-data-ui/ssr/vue-ui-xy' +import { mergeConfigs } from 'vue-data-ui/utils' +import { generateWatermarkLogo, LOCALES_WITH_EXTRA_SPACE } from '#shared/utils/trends-chart' +import { + buildNormalisedTrendsDataset, + buildTrendsChartConfig, + buildTrendsChartData, +} from '#shared/utils/trends-chart' +import { resolveEmbedChartColors } from '#shared/utils/embed-chart-colors' +import { OKLCH_NEUTRAL_FALLBACK } from '~/utils/colors' +import { getEffectiveEndDateIso, isLastDayOfMonth, isLastDayOfYear } from '~/utils/date' +import { fetchDownloadsEvolution } from '~~/server/utils/download-evolution' +import { createLastDatapointLabelsSvg } from '#shared/utils/download-chart-last-label' + +type FetchGranularity = 'day' | 'week' | 'month' | 'year' +type ChartGranularity = 'daily' | 'weekly' | 'monthly' | 'yearly' +type Metric = 'downloads' | 'likes' | 'contributors' +type QueryParameters = Record + +export function parsePackageNames(value: unknown): string[] { + return String(value ?? '') + .split(',') + .map(name => name.trim().toLowerCase()) + .filter(name => /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/.test(name)) + .slice(0, 8) +} + +export function parseFetchGranularity(value: unknown): FetchGranularity { + if (value === 'daily' || value === 'day') return 'day' + if (value === 'weekly' || value === 'week') return 'week' + if (value === 'monthly' || value === 'month') return 'month' + if (value === 'yearly' || value === 'year') return 'year' + return 'week' +} + +export function toChartGranularity(granularity: FetchGranularity): ChartGranularity { + const mapping: Record = { + day: 'daily', + week: 'weekly', + month: 'monthly', + year: 'yearly', + } + + return mapping[granularity] +} + +export function parseLocale(value: unknown): string { + if (typeof value !== 'string') return 'en' + + try { + return Intl.getCanonicalLocales(value.trim())[0] ?? 'en' + } catch { + return 'en' + } +} + +export function parseAccent(value: unknown): string { + if (typeof value !== 'string') { + return OKLCH_NEUTRAL_FALLBACK + } + + const accent = value.trim() + + if (/^#(?:[\da-f]{3}|[\da-f]{6})$/i.test(accent)) { + return accent + } + + if ( + /^oklch\(\s*(?:0|1|0?\.\d+|\d{1,3}(?:\.\d+)?%)\s+(?:0|0?\.\d+|\d+(?:\.\d+)?)\s+(?:\d+(?:\.\d+)?|none)(?:deg|rad|grad|turn)?(?:\s*\/\s*(?:0|1|0?\.\d+|\d{1,3}(?:\.\d+)?%))?\s*\)$/i.test( + accent, + ) + ) { + return accent + } + + return OKLCH_NEUTRAL_FALLBACK +} + +export function parseSafeText(value: unknown, fallback = '', maximumLength = 100): string { + if (typeof value !== 'string') return fallback + + return ( + value + .replace(/[<>&"'`]/g, '') + // eslint-disable-next-line no-control-regex + .replace(/[\u{0000}-\u{001F}\u{007F}]/gu, '') + .trim() + .slice(0, maximumLength) + ) +} + +export function parseDateQuery(value: unknown): string | undefined { + if (typeof value !== 'string') return undefined + + const date = value.trim() + + return /^\d{4}-\d{2}-\d{2}$/.test(date) ? date : undefined +} + +export function clampNumber( + value: unknown, + minimum: number, + maximum: number, + fallback: number, +): number { + const parsed = Number(value) + + if (!Number.isFinite(parsed)) { + return fallback + } + + return Math.min(maximum, Math.max(minimum, parsed)) +} + +export function parseMetric(value: unknown): Metric { + if (value === 'likes') return 'likes' + if (value === 'contributors') return 'contributors' + + return 'downloads' +} + +function dateIsoToUtcMs(dateIso: string): number { + return new Date(`${dateIso}T00:00:00.000Z`).getTime() +} + +export async function createDownloadsSvgResponse(query: QueryParameters): Promise { + const packageNames = parsePackageNames(query.packages ?? query.package) + + if (!packageNames.length) { + throw createError({ + statusCode: 400, + statusMessage: 'Missing package name. Use ?package=nuxt or ?packages=vite,rolldown', + }) + } + + const fetchGranularity = parseFetchGranularity(query.granularity) + const chartGranularity = toChartGranularity(fetchGranularity) + const metric = parseMetric(query.metric) + const isDarkMode = query.mode === 'dark' + const width = clampNumber(query.width, 360, 1600, 900) + const height = clampNumber(query.height, 240, 900, 420) + + const locale = parseLocale(query.locale) + const accent = parseAccent(query.accent) + const yLabel = parseSafeText(query.yLabel, '', 100) + + const evolutionOptions = { + granularity: fetchGranularity, + weeks: clampNumber(query.weeks, 1, 260, 52), + months: clampNumber(query.months, 1, 120, 12), + startDate: parseDateQuery(query.startDate ?? query.start), + endDate: parseDateQuery(query.endDate ?? query.end), + } + + if (metric !== 'downloads') { + throw createError({ + statusCode: 501, + statusMessage: 'Only the downloads metric is currently supported by the SVG endpoint', + }) + } + + const evolutionsByPackage = Object.fromEntries( + await Promise.all( + packageNames.map(async packageName => [ + packageName, + await fetchDownloadsEvolution(packageName, evolutionOptions), + ]), + ), + ) + + const colors = resolveEmbedChartColors(isDarkMode ? 'dark' : 'light') + const compactNumberFormatter = new Intl.NumberFormat(locale, { + notation: 'compact', + maximumFractionDigits: 1, + }) + + const chartFilter = { + averageWindow: 0, + smoothingTau: 0, + predictionPoints: 0, + } + + const chartData = buildTrendsChartData({ + packageNames, + effectivePackageNamesForMetric: packageNames, + isMultiPackageMode: packageNames.length > 1, + selectedMetric: metric, + selectedMetricLabel: '', + selectedGranularity: chartGranularity, + displayedGranularity: chartGranularity, + singleEvolution: evolutionsByPackage[packageNames[0]!] ?? [], + evolutionsByPackage, + colors, + isDarkMode, + chartFilter, + t: ((key: string) => key) as any, + compactNumberFormatter, + accent, + }) + + const effectiveEndDateIso = getEffectiveEndDateIso(evolutionOptions.endDate) + const effectiveEndDateMs = dateIsoToUtcMs(effectiveEndDateIso) + + const dataset = buildNormalisedTrendsDataset({ + dataset: chartData.dataset, + dates: chartData.dates, + granularity: chartGranularity, + selectedMetric: metric, + chartFilter, + endDateMs: effectiveEndDateMs, + }) + + if (!chartData.dataset?.length) { + throw createError({ + statusCode: 404, + statusMessage: 'No chart dataset generated', + }) + } + + if (!dataset.length) { + throw createError({ + statusCode: 404, + statusMessage: 'No normalized dataset generated', + }) + } + + const baseConfig = buildTrendsChartConfig({ + packageNames, + effectivePackageNamesForMetric: packageNames, + isMultiPackageMode: packageNames.length > 1, + selectedMetric: metric, + selectedMetricLabel: '', + selectedGranularity: chartGranularity, + displayedGranularity: chartGranularity, + singleEvolution: evolutionsByPackage[packageNames[0]!] ?? [], + evolutionsByPackage, + dates: chartData.dates, + colors, + isDarkMode, + isMobile: false, + pending: false, + locale, + chartHeight: height, + chartFilter, + t: ((key: string) => key) as any, + compactNumberFormatter, + tooltipPosition: 'center', + }) + + const config = mergeConfigs({ + defaultConfig: baseConfig, + userConfig: { + line: { + useGradient: false, + area: { + opacity: 12, + }, + }, + chart: { + width, + height, + padding: { + left: 12, + right: + packageNames.length > 1 ? (LOCALES_WITH_EXTRA_SPACE.includes(locale) ? 180 : 160) : 145, + }, + legend: { + show: true, + position: 'top', + fontSize: 24, + color: colors.fgMuted, + }, + grid: { + labels: { + fontSize: 12, + axis: { + fontSize: 16, + yLabel, + }, + yAxis: { + scaleLabelOffsetX: 0, + crosshairSize: 6, + }, + xAxisLabels: { + fontSize: 12, + color: colors.fgMuted, + }, + }, + }, + }, + }, + }) + + const shouldDashLastPoint = + (chartGranularity === 'monthly' && !isLastDayOfMonth(effectiveEndDateIso)) || + (chartGranularity === 'yearly' && !isLastDayOfYear(effectiveEndDateIso)) + + return await createStaticVueUiXy({ + dataset: dataset.map(datapoint => { + const dashIndices = shouldDashLastPoint + ? [...new Set([...(datapoint.dashIndices ?? []), datapoint.series.length - 1])].filter( + index => index >= 0, + ) + : datapoint.dashIndices + + return Object.assign({}, datapoint, { dashIndices }) + }), + config, + additionalSvgContent: ({ series, drawingArea }) => { + const lastPlotValues = createLastDatapointLabelsSvg({ + series, + drawingArea, + colors: { + foreground: colors.fg, + background: colors.bg, + fallbackSerieColor: colors.fg, + }, + formatValue: value => compactNumberFormatter.format(value), + isDarkMode, + }) + + const logo = generateWatermarkLogo({ + x: 12, + y: drawingArea.bottom + 60, + width: 80, + height: 30, + fill: colors.fgSubtle, + }) + + return ` + + ${lastPlotValues} + ${logo} + ` + }, + }) +} diff --git a/server/utils/import-resolver.ts b/server/utils/import-resolver.ts index 1740b6facd..db42226092 100644 --- a/server/utils/import-resolver.ts +++ b/server/utils/import-resolver.ts @@ -101,6 +101,48 @@ function getExtensionPriority(sourceFile: string): string[][] { return [[], ['.ts', '.js'], ['.d.ts'], ['.json']] } +/** + * Resolve an alias specifier to the directory path within a file path. + * Supports #, ~, @, and $ prefixes (e.g. #app, ~/app, @/app, $/app). + * The alias must match a path segment exactly (no partial matches). + */ +export function resolveAliasToDir(aliasSpec: string, filePath?: string | null): string | null { + if ( + (!aliasSpec.startsWith('#') && + !aliasSpec.startsWith('~') && + !aliasSpec.startsWith('@') && + !aliasSpec.startsWith('$')) || + !filePath + ) { + return null + } + + // Support #app, #/app, ~app, ~/app, @app, @/app, $app, $/app + const alias = aliasSpec.replace(/^[#~@$]\/?/, '') + const normalizedFilePath = filePath.replace(/\/+$/, '') + if (!normalizedFilePath) { + return null + } + + if (alias === '') { + return normalizedFilePath + } + + const segments = normalizedFilePath.split('/') + let lastMatchIndex = -1 + for (let i = 0; i < segments.length; i++) { + if (segments[i] === alias) { + lastMatchIndex = i + } + } + + if (lastMatchIndex === -1) { + return null + } + + return segments.slice(0, lastMatchIndex + 1).join('/') +} + /** * Get index file extensions to try for directory imports. */ @@ -131,6 +173,23 @@ export interface ResolvedImport { path: string } +export type InternalImportTarget = string | { default?: string; import?: string } | null | undefined + +export type InternalImportsMap = Record + +export type PackageExportTarget = + | string + | { + default?: string + import?: string + require?: string + types?: string + } + | null + | undefined + +export type PackageExportsMap = Record + /** * Resolve a relative import specifier to an actual file path. * @@ -198,6 +257,253 @@ export function resolveRelativeImport( return null } +function normalizeInternalImportTarget(target: InternalImportTarget): string | null { + if (typeof target === 'string') { + return target + } + + if (target && typeof target === 'object') { + if (typeof target.import === 'string') { + return target.import + } + + if (typeof target.default === 'string') { + return target.default + } + } + + return null +} + +function normalizeAliasPrefix(value: string): string { + return value.replace(/^([#~@$])\//, '$1') +} + +function guessInternalImportTarget( + imports: InternalImportsMap, + specifier: string, + files: FileSet, + currentFile: string, +): string | null { + const normalizedSpecifier = normalizeAliasPrefix(specifier) + + for (const [key, value] of Object.entries(imports)) { + const normalizedKey = normalizeAliasPrefix(key) + if ( + normalizedSpecifier === normalizedKey || + normalizedSpecifier.startsWith(`${normalizedKey}/`) + ) { + const basePath = resolveAliasToDir(key, normalizeInternalImportTarget(value)) + if (!basePath) continue + + const suffix = normalizedSpecifier.slice(normalizedKey.length).replace(/^\//, '') + const pathWithoutExt = suffix ? `${basePath}/${suffix}` : basePath + + const toCheckPath = (p: string) => files.has(normalizePath(p)) || files.has(p) + + // Path already has an extension-like suffix on the last segment - return as is if exists + const filename = pathWithoutExt.split('/').pop() ?? '' + if (filename.includes('.') && !filename.endsWith('.')) { + if (toCheckPath(pathWithoutExt)) { + return pathWithoutExt.startsWith('./') ? pathWithoutExt : `./${pathWithoutExt}` + } + return null + } + + // Try adding extensions based on currentFile type + const extensionGroups = getExtensionPriority(currentFile) + for (const extensions of extensionGroups) { + if (extensions.length === 0) { + if (toCheckPath(pathWithoutExt)) { + return pathWithoutExt.startsWith('./') ? pathWithoutExt : `./${pathWithoutExt}` + } + } else { + for (const ext of extensions) { + const pathWithExt = pathWithoutExt + ext + if (toCheckPath(pathWithExt)) { + return pathWithExt.startsWith('./') ? pathWithExt : `./${pathWithExt}` + } + } + } + } + + // Try as directory with index file + for (const indexFile of getIndexExtensions(currentFile)) { + const indexPath = `${pathWithoutExt}/${indexFile}` + if (toCheckPath(indexPath)) { + return indexPath.startsWith('./') ? indexPath : `./${indexPath}` + } + } + } + } + return null +} + +/** + * import ... from '#components/Button.vue' + * import ... from '#/components/Button.vue' + * import ... from '~/components/Button.vue' + * import ... from '~components/Button.vue' + * import ... from '$components/Button.vue' + * import ... from '$/components/Button.vue' + */ +export function resolveInternalImport( + specifier: string, + currentFile: string, + imports: InternalImportsMap | undefined, + files: FileSet, +): ResolvedImport | null { + const cleanSpecifier = specifier.replace(/^['"]|['"]$/g, '').trim() + + if ( + (!cleanSpecifier.startsWith('#') && + !cleanSpecifier.startsWith('~') && + !cleanSpecifier.startsWith('@') && + !cleanSpecifier.startsWith('$')) || + !imports + ) { + return null + } + + const importTarget = normalizeInternalImportTarget(imports[cleanSpecifier]) + const target = + importTarget != null + ? importTarget + : guessInternalImportTarget(imports, cleanSpecifier, files, currentFile) + + if (!target || !target.startsWith('./')) { + return null + } + + const path = normalizePath(target) + if (!path || path.startsWith('..')) { + return null + } + + if (files.has(path)) { + return { path } + } + + for (const extensions of getExtensionPriority(currentFile)) { + for (const ext of extensions) { + const candidate = `${path}${ext}` + if (files.has(candidate)) { + return { path: candidate } + } + } + } + + for (const indexFile of getIndexExtensions(currentFile)) { + const candidate = `${path}/${indexFile}` + if (files.has(candidate)) { + return { path: candidate } + } + } + + return null +} + +function normalizePackageSubpath(specifier: string, packageName: string): string | null { + const cleanSpecifier = specifier.replace(/^['"]|['"]$/g, '').trim() + + if (cleanSpecifier === packageName) { + return '.' + } + + if (!cleanSpecifier.startsWith(`${packageName}/`)) { + return null + } + + return `.${cleanSpecifier.slice(packageName.length)}` +} + +function normalizePackageExportTarget(target: PackageExportTarget): string | null { + if (typeof target === 'string') { + return target + } + + if (target && typeof target === 'object') { + if (typeof target.import === 'string') { + return target.import + } + + if (typeof target.default === 'string') { + return target.default + } + + if (typeof target.require === 'string') { + return target.require + } + + if (typeof target.types === 'string') { + return target.types + } + } + + return null +} + +export function resolvePackageSelfImport( + specifier: string, + packageName: string, + exportsMap: PackageExportsMap | undefined, + currentFile: string, + files: FileSet, +): ResolvedImport | null { + const exportKey = normalizePackageSubpath(specifier, packageName) + if (!exportKey) { + return null + } + + const resolvePath = (path: string): ResolvedImport | null => { + if (!path || path.startsWith('..')) { + return null + } + + if (files.has(path)) { + return { path } + } + + for (const extensions of getExtensionPriority(currentFile)) { + for (const ext of extensions) { + const candidate = `${path}${ext}` + if (files.has(candidate)) { + return { path: candidate } + } + } + } + + for (const indexFile of getIndexExtensions(currentFile)) { + const candidate = `${path}/${indexFile}` + if (files.has(candidate)) { + return { path: candidate } + } + } + + return null + } + + const target = exportsMap ? normalizePackageExportTarget(exportsMap[exportKey]) : null + if (target?.startsWith('./')) { + const resolvedFromExports = resolvePath(normalizePath(target)) + if (resolvedFromExports) { + return resolvedFromExports + } + } + + // Fallback for packages whose exports could not be fetched at runtime: + // map `pkg/subpath` to `subpath` and apply normal extension/index resolution. + if (exportKey !== '.') { + const fallbackPath = normalizePath(exportKey.slice(2)) + const resolvedFallback = resolvePath(fallbackPath) + if (resolvedFallback) { + return resolvedFallback + } + } + + return null +} + /** * Create a resolver function bound to a specific file tree and current file. */ @@ -206,9 +512,21 @@ export function createImportResolver( currentFile: string, packageName: string, version: string, + internalImports?: InternalImportsMap, + exportsMap?: PackageExportsMap, ): (specifier: string) => string | null { return (specifier: string) => { - const resolved = resolveRelativeImport(specifier, currentFile, files) + const relativeResolved = resolveRelativeImport(specifier, currentFile, files) + const internalResolved = resolveInternalImport(specifier, currentFile, internalImports, files) + const selfResolved = resolvePackageSelfImport( + specifier, + packageName, + exportsMap, + currentFile, + files, + ) + const resolved = relativeResolved ?? internalResolved ?? selfResolved + if (resolved) { return `/package-code/${packageName}/v/${version}/${resolved.path}` } diff --git a/server/utils/mdKit.ts b/server/utils/mdKit.ts new file mode 100644 index 0000000000..3ebe367d95 --- /dev/null +++ b/server/utils/mdKit.ts @@ -0,0 +1,561 @@ +import { + type Tokens, + type RendererApi, + type Renderer, + type TokenizerObject, + type Marked, + marked, +} from 'marked' +import { highlightCodeSync } from './shiki' +import { decodeHtmlEntities, stripHtmlTags, slugify } from '#shared/utils/html' +import { escapeHtml } from './docs/text' +import sanitizeHtml from 'sanitize-html' +import { hasProtocol } from 'ufo' + +/// for marked + +// constands +const npmJsHosts = new Set(['www.npmjs.com', 'npmjs.com', 'www.npmjs.org', 'npmjs.org']) + +/** These path on npmjs.com don't belong to packages or search, so we shouldn't try to replace them with npmx.dev urls */ +const reservedPathsNpmJs = [ + 'products', + 'login', + 'signup', + 'advisories', + 'blog', + 'about', + 'press', + 'policies', +] + +// blockquote & code + +/** + * GitHub-style callouts: > [!NOTE], > [!TIP], etc. + */ +export const blockquote: RendererApi['blockquote'] = function ( + this: Renderer, + { tokens }, +) { + const body = this.parser.parse(tokens) + + const calloutMatch = body.match(/^

\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\](?:
)?\s*/i) + + if (calloutMatch?.[1]) { + const calloutType = calloutMatch[1].toLowerCase() + const cleanedBody = body.replace(calloutMatch[0], '

') + return `

${cleanedBody}
\n` + } + + return `
${body}
\n` +} + +/** + * created code highlighter with Shiki for Marked + */ +export async function createCodeHighlighter(): Promise { + const shiki = await getShikiHighlighter() + + // Syntax highlighting for code blocks (uses shared highlighter) + return ({ text, lang }: Tokens.Code) => { + const html = highlightCodeSync(shiki, text, lang || 'text') + // Add copy button + return `
+ + ${html} +
` + } +} + +// link +export type ProcessLinkFn = ( + href: string, + label: string, + // readme.ts also needs the extraAttrs for more things, so can't be a boolean +) => { resolvedHref: string; extraAttrs: string } + +export function decodeHashFragment(value: string): string { + try { + return decodeURIComponent(value) + } catch { + return value + } +} + +const EMAIL_REGEX = /^[\w+\-.]+@[\w\-.]+\.[a-z]+$/i + +/** + * Resolve link URLs, add security attributes, and collect playground links + * + * โ€” all in a single pass during marked rendering (no deferred processing) + */ +export function createLink(processLink: ProcessLinkFn): RendererApi['link'] { + return function (this: Renderer, { href, title, tokens }: Tokens.Link) { + const eTitle = escapeHtml(title ?? '') + const text = this.parser.parseInline(tokens) + const titleAttr = eTitle ? ` title="${eTitle}"` : '' + let plainText = stripHtmlTags(text).trim() + + // If plain text is empty, check if we have an image with alt text + if (!plainText && tokens.length === 1 && tokens[0]?.type === 'image') { + plainText = tokens[0].text + } + + const { resolvedHref, extraAttrs } = processLink(href, plainText || eTitle || '') + + if (!resolvedHref) return text + + // prevents package@1.0.0 being made into an email + if (href.startsWith('mailto:') && !EMAIL_REGEX.test(plainText)) { + return text + } + + return `${text}` + } +} + +export const isNpmJsUrlThatCanBeRedirected = (url: URL) => { + if (!npmJsHosts.has(url.host)) { + return false + } + + if ( + url.pathname === '/' || + reservedPathsNpmJs.some(path => url.pathname.startsWith(`/${path}`)) + ) { + return false + } + + return true +} + +// image + +export type ProcessImageUrlFn = (href: string) => string + +export const createImage = function (processImageUrl: ProcessImageUrlFn): RendererApi['image'] { + return function (this: Renderer, { href, title, text }) { + const resolvedHref = processImageUrl(href) + const titleAttr = title ? ` title="${escapeHtml(title)}"` : '' + const altAttr = text ? ` alt="${escapeHtml(text)}"` : '' + return `` + } +} + +// heading + +/** + * Lazy ATX heading extension for marked: allows headings without a space after `#`. + * + * Reimplements the behavior of markdown-it-lazy-headers + * (https://npmx.dev/package/markdown-it-lazy-headers), which is used by npm's own markdown renderer + * marky-markdown (https://npmx.dev/package/marky-markdown). + * + * CommonMark requires a space after # for ATX headings, but many READMEs in the npm registry omit + * this space. This extension allows marked to parse these headings the same way npm does. + * + * @param exemptIssuePr do not turn #{number} into a heading, treat it as an issue/pr instead + */ +export function createMarkedHeadingExtension(exemptIssuePr?: boolean): TokenizerObject['heading'] { + return function (src: string) { + // Only match headings where `#` is immediately followed by non-whitespace, non-`#` content. + // Normal headings (with space) return false to fall through to marked's default tokenizer. + const match = /^ {0,3}(#{1,6})([^\s#][^\n]*)(?:\n+|$)/.exec(src) + if (!match) return false + if (exemptIssuePr && /^#\d+\b/.test(match[0])) return false + + console.log({ match, test: /^#\d+\b/.test(match[0]), exemptIssuePr }) + + let text = match[2]!.trim() + + // Strip trailing # characters only if preceded by a space (CommonMark behavior). + // e.g., "#heading ##" โ†’ "heading", but "#heading#" stays as "heading#" + if (text.endsWith('#')) { + const stripped = text.replace(/#+$/, '') + if (!stripped || stripped.endsWith(' ')) { + text = stripped.trim() + } + } + + return { + type: 'heading' as const, + raw: match[0]!, + depth: match[1]!.length as number, + text, + tokens: this.lexer.inline(text), + } + } +} + +export const USER_CONTENT_PREFIX = 'user-content-' + +// README h1 always becomes h3 +// For deeper levels, ensure sequential order +// Don't allow jumping more than 1 level deeper than previous +export function calculateSemanticDepth( + depth: number, + lastSemanticLevel: number, + minSemanticLevel: number, +) { + if (depth === 1) return minSemanticLevel + 1 + const maxAllowed = Math.min(lastSemanticLevel + 1, 6) + return Math.min(depth + minSemanticLevel, maxAllowed) +} + +export function getHeadingPlainText(text: string): string { + return decodeHtmlEntities(stripHtmlTags(text).trim()) +} + +export function getHeadingSlugSource(text: string): string { + return stripHtmlTags(text).trim() +} + +const htmlAnchorRe = /]*?)href=(["'])([^"']*)\2([^>]*)>([\s\S]*?)<\/a>/gi + +export type ToUserContentIdFn = (id: string) => string + +type ProcessHeadingFn = ( + depth: number, + displayHtml: string, + plainText: string, + slugSource: string, + preservedAttrs?: string, +) => string + +export function createHeading(options: { + lastSemanticLevel?: number + toUserContentId: ToUserContentIdFn +}) { + let { lastSemanticLevel = 2, toUserContentId } = options + const minSemanticLevel = lastSemanticLevel + const toc: TocItem[] = [] + const usedSlugs = new Map() + + const heading: RendererApi['heading'] = function ( + this: Renderer, + { tokens, depth }, + ) { + const displayHtml = this.parser.parseInline(tokens) + const plainText = getHeadingPlainText(displayHtml) + const slugSource = getHeadingSlugSource(displayHtml) + return processHeading(depth, displayHtml, plainText, slugSource) + } + + const processHeading: ProcessHeadingFn = function ( + depth: number, + displayHtml: string, + plainText: string, + slugSource: string, + preservedAttrs = '', + ) { + const semanticLevel = calculateSemanticDepth(depth, lastSemanticLevel, minSemanticLevel) + lastSemanticLevel = semanticLevel + + let slug = slugify(slugSource) + if (!slug) slug = 'heading' + + const count = usedSlugs.get(slug) ?? 0 + usedSlugs.set(slug, count + 1) + const uniqueSlug = count === 0 ? slug : `${slug}-${count}` + const id = toUserContentId(uniqueSlug) + + if (plainText) { + toc.push({ text: plainText, id, depth }) + } + + // The browser doesn't support anchors within anchors and automatically extracts them from each other, + // causing a hydration error. To prevent this from happening in such cases, we use the anchor separately + if (displayHtml.match(htmlAnchorRe)?.length) { + return `${displayHtml}\n` + } + + return `${displayHtml}\n` + } + + return { heading, toc, processHeading } +} + +// html + +// Extract and preserve allowed attributes from HTML heading tags +export function extractHeadingAttrs(attrsString: string): string { + if (!attrsString) return '' + const preserved: string[] = [] + const alignMatch = /\balign=(["']?)([^"'\s>]+)\1/i.exec(attrsString) + if (alignMatch?.[2]) { + preserved.push(`align="${alignMatch[2]}"`) + } + return preserved.length > 0 ? ` ${preserved.join(' ')}` : '' +} + +// Intercept HTML headings so they get id, TOC entry, and correct semantic level. +// Also intercept raw HTML tags so playground links are collected in the same pass. +const htmlHeadingRe = /]*)?>([\s\S]*?)<\/h\1>/gi + +function normalizePreservedAnchorAttrs(attrs: string): string { + const cleanedAttrs = attrs + .replace(/\s+href\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') + .replace(/\s+rel\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') + .replace(/\s+target\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') + .trim() + + return cleanedAttrs ? ` ${cleanedAttrs}` : '' +} + +export function createHtml({ + processHeading, + processLink, +}: { + processHeading: ProcessHeadingFn + processLink: ProcessLinkFn +}) { + // function withUserContentPrefix(value: string): string { + // return value.startsWith(USER_CONTENT_PREFIX) ? value : `${USER_CONTENT_PREFIX}${value}` + // } + + return function ({ text }: Tokens.HTML) { + let result = text.replace(htmlHeadingRe, (_, level, attrs = '', inner) => { + const depth = parseInt(level) + const plainText = getHeadingPlainText(inner) + const slugSource = getHeadingSlugSource(inner) + const preservedAttrs = extractHeadingAttrs(attrs) + return processHeading(depth, inner, plainText, slugSource, preservedAttrs).trimEnd() + }) + // Process raw HTML tags for playground link collection and URL resolution + result = result.replace(htmlAnchorRe, (_full, beforeHref, _quote, href, afterHref, inner) => { + const label = decodeHtmlEntities(stripHtmlTags(inner).trim()) + const { resolvedHref, extraAttrs } = processLink(href, label) + const preservedAttrs = normalizePreservedAnchorAttrs(`${beforeHref ?? ''}${afterHref ?? ''}`) + return `${inner}` + }) + return result + } +} + +// html rendering + +export function renderToRawHtml({ + renderer, + markdownBody, + frontmatterHtml = '', + markedInstance, +}: { + renderer: Renderer + markdownBody: string + frontmatterHtml?: string + markedInstance?: Marked +}) { + // Strip trailing whitespace (tabs/spaces) from code block closing fences. + // While marky-markdown handles these gracefully, marked fails to recognize + // the end of a code block if the closing fences are followed by unexpected whitespaces. + const normalizedContent = markdownBody.replace(/^( {0,3}(?:`{3,}|~{3,}))\s*$/gm, '$1') + return ( + frontmatterHtml + + ((markedInstance ?? marked).parse(normalizedContent, { + renderer, + }) as string) + ) +} + +/// sanatizer + +export const ALLOWED_ATTR: Record = { + '*': ['id'], // Allow id on all tags + 'a': ['href', 'title', 'target', 'rel', 'tabindex', 'aria-hidden'], + 'img': ['src', 'alt', 'title', 'width', 'height', 'align'], + 'source': ['src', 'srcset', 'type', 'media'], + 'button': ['class', 'title', 'type', 'aria-label', 'data-copy'], + 'th': ['colspan', 'rowspan', 'align', 'valign', 'width'], + 'td': ['colspan', 'rowspan', 'align', 'valign', 'width'], + 'h2': ['data-level', 'align'], + 'h3': ['data-level', 'align'], + 'h4': ['data-level', 'align'], + 'h5': ['data-level', 'align'], + 'h6': ['data-level', 'align'], + 'blockquote': ['data-callout'], + 'details': ['open'], + 'code': ['class'], + 'pre': ['class'], + 'span': ['class', 'style'], + 'div': ['class', 'align'], + 'p': ['align'], +} + +// allow h1-h6, but replace h1-h2 later since we shift README headings down by 2 levels +// (page h1 = package name, h2 = "Readme" section, so README h1 โ†’ h3) +export const ALLOWED_TAGS = [ + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'p', + 'br', + 'hr', + 'ul', + 'ol', + 'li', + 'blockquote', + 'pre', + 'code', + 'a', + 'strong', + 'em', + 'del', + 's', + 'table', + 'thead', + 'tbody', + 'tr', + 'th', + 'td', + 'img', + 'picture', + 'source', + 'details', + 'summary', + 'div', + 'span', + 'sup', + 'sub', + 'kbd', + 'mark', + 'button', + 'dl', + 'dt', + 'dd', +] + +export function sanitizeRawHTML( + rawHtml: string, + { + processImageUrl, + processLink, + toUserContentId, + lastSemanticLevel = 2, + }: { + processImageUrl: ProcessImageUrlFn + processLink: ProcessLinkFn + toUserContentId: ToUserContentIdFn + lastSemanticLevel?: number + }, +) { + // Helper to prefix id attributes with 'user-content-' + function prefixId(tagName: string, attribs: sanitizeHtml.Attributes) { + if (attribs.id) { + attribs.id = attribs.id.startsWith(USER_CONTENT_PREFIX) + ? attribs.id + : toUserContentId(attribs.id) + } + return { tagName, attribs } + } + + const h1 = `h${lastSemanticLevel + 1}`, + h2 = `h${lastSemanticLevel + 2}`, + h3 = `h${lastSemanticLevel + 3}`, + h4 = `h${lastSemanticLevel + 4}` + + return sanitizeHtml(rawHtml, { + allowedTags: ALLOWED_TAGS, + allowedAttributes: ALLOWED_ATTR, + allowedSchemes: ['http', 'https', 'mailto'], + // disallow styles other than the ones shiki emits + allowedStyles: { + span: { + 'color': [/^#[0-9a-f]{3,8}$/i], + '--shiki-light': [/^#[0-9a-f]{3,8}$/i], + }, + }, + transformTags: { + // Headings are already processed to correct semantic levels by processHeading() + // during the marked rendering pass. The sanitizer just needs to preserve them. + // For any stray headings that didn't go through processHeading (shouldn't happen), + // we still apply a safe fallback shift. + h1: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h1', attribs } + return { tagName: h1, attribs: { ...attribs, 'data-level': '1' } } + }, + h2: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h2', attribs } + return { tagName: h2, attribs: { ...attribs, 'data-level': '2' } } + }, + h3: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h3', attribs } + return { tagName: h3, attribs: { ...attribs, 'data-level': '3' } } + }, + h4: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h4', attribs } + return { tagName: h4, attribs: { ...attribs, 'data-level': '4' } } + }, + h5: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h5', attribs } + return { tagName: 'h6', attribs: { ...attribs, 'data-level': '5' } } + }, + h6: (_, attribs) => { + if (attribs['data-level']) return { tagName: 'h6', attribs } + return { tagName: 'h6', attribs: { ...attribs, 'data-level': '6' } } + }, + img: (tagName, attribs) => { + if (attribs.src) { + attribs.src = processImageUrl(attribs.src) + } + return { tagName, attribs } + }, + source: (tagName, attribs) => { + if (attribs.src) { + attribs.src = processImageUrl(attribs.src) + } + if (attribs.srcset) { + attribs.srcset = attribs.srcset + .split(',') + .map(entry => { + const parts = entry.trim().split(/\s+/) + const url = parts[0] + if (!url) return entry.trim() + const descriptor = parts[1] + const resolvedUrl = processImageUrl(url) + return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl + }) + .join(', ') + } + return { tagName, attribs } + }, + // Markdown links are fully processed in renderer.link (single-pass). + // However, inline HTML tags inside paragraphs are NOT seen by + // renderer.html (marked parses them as paragraph tokens, not html tokens). + // So we still need to collect playground links here for those cases via processUrl from readme. + // The seenUrls set ensures no duplicates across both paths. + a: (tagName, attribs) => { + if (!attribs.href) { + return { tagName, attribs } + } + + let { resolvedHref } = processLink(attribs.href, '') + + // for changelog all routes are orianted around the git provider, prefixing with $ set it to npmx + if (resolvedHref.startsWith('$')) { + resolvedHref = resolvedHref.replace('$', '') + } + + // Add security attributes for external links (idempotent) + if (resolvedHref && hasProtocol(resolvedHref, { acceptRelative: true })) { + attribs.rel = 'nofollow noreferrer noopener' + attribs.target = '_blank' + } + attribs.href = resolvedHref + return { tagName, attribs } + }, + + div: prefixId, + p: prefixId, + span: prefixId, + section: prefixId, + article: prefixId, + }, + }) +} diff --git a/server/utils/readme.ts b/server/utils/readme.ts index 6e220f7827..717136f981 100644 --- a/server/utils/readme.ts +++ b/server/utils/readme.ts @@ -1,14 +1,26 @@ -import type { ReadmeResponse, TocItem } from '#shared/types/readme' -import type { Tokens } from 'marked' +import type { ReadmeResponse } from '#shared/types/readme' +import { + type ProcessLinkFn, + blockquote, + createCodeHighlighter, + isNpmJsUrlThatCanBeRedirected, + createLink, + createHeading, + createHtml, + USER_CONTENT_PREFIX, + createMarkedHeadingExtension, + renderToRawHtml, + createImage, + sanitizeRawHTML, + decodeHashFragment, +} from './mdKit' import matter from 'gray-matter' import { marked } from 'marked' -import sanitizeHtml from 'sanitize-html' import { hasProtocol } from 'ufo' import { convertBlobOrFileToRawUrl, type RepositoryInfo } from '#shared/utils/git-providers' -import { decodeHtmlEntities, stripHtmlTags, slugify } from '#shared/utils/html' +import { decodeHtmlEntities, slugify } from '#shared/utils/html' import { convertToEmoji } from '#shared/utils/emoji' import { toProxiedImageUrl } from '#server/utils/image-proxy' -import { highlightCodeSync } from './shiki' import { escapeHtml } from './docs/text' /** @@ -139,137 +151,12 @@ function matchPlaygroundProvider(url: string): PlaygroundProvider | null { return null } -// allow h1-h6, but replace h1-h2 later since we shift README headings down by 2 levels -// (page h1 = package name, h2 = "Readme" section, so README h1 โ†’ h3) -export const ALLOWED_TAGS = [ - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'p', - 'br', - 'hr', - 'ul', - 'ol', - 'li', - 'blockquote', - 'pre', - 'code', - 'a', - 'strong', - 'em', - 'del', - 's', - 'table', - 'thead', - 'tbody', - 'tr', - 'th', - 'td', - 'img', - 'picture', - 'source', - 'details', - 'summary', - 'div', - 'span', - 'sup', - 'sub', - 'kbd', - 'mark', - 'button', - 'dl', - 'dt', - 'dd', -] - -export const ALLOWED_ATTR: Record = { - '*': ['id'], // Allow id on all tags - 'a': ['href', 'title', 'target', 'rel'], - 'img': ['src', 'alt', 'title', 'width', 'height', 'align'], - 'source': ['src', 'srcset', 'type', 'media'], - 'button': ['class', 'title', 'type', 'aria-label', 'data-copy'], - 'th': ['colspan', 'rowspan', 'align', 'valign', 'width'], - 'td': ['colspan', 'rowspan', 'align', 'valign', 'width'], - 'h3': ['data-level', 'align'], - 'h4': ['data-level', 'align'], - 'h5': ['data-level', 'align'], - 'h6': ['data-level', 'align'], - 'blockquote': ['data-callout'], - 'details': ['open'], - 'code': ['class'], - 'pre': ['class'], - 'span': ['class', 'style'], - 'div': ['class', 'align'], - 'p': ['align'], -} - -function getHeadingPlainText(text: string): string { - return decodeHtmlEntities(stripHtmlTags(text).trim()) -} - -function getHeadingSlugSource(text: string): string { - return stripHtmlTags(text).trim() -} - -/** - * Lazy ATX heading extension for marked: allows headings without a space after `#`. - * - * Reimplements the behavior of markdown-it-lazy-headers - * (https://npmx.dev/package/markdown-it-lazy-headers), which is used by npm's own markdown renderer - * marky-markdown (https://npmx.dev/package/marky-markdown). - * - * CommonMark requires a space after # for ATX headings, but many READMEs in the npm registry omit - * this space. This extension allows marked to parse these headings the same way npm does. - */ marked.use({ tokenizer: { - heading(src: string) { - // Only match headings where `#` is immediately followed by non-whitespace, non-`#` content. - // Normal headings (with space) return false to fall through to marked's default tokenizer. - const match = /^ {0,3}(#{1,6})([^\s#][^\n]*)(?:\n+|$)/.exec(src) - if (!match) return false - - let text = match[2]!.trim() - - // Strip trailing # characters only if preceded by a space (CommonMark behavior). - // e.g., "#heading ##" โ†’ "heading", but "#heading#" stays as "heading#" - if (text.endsWith('#')) { - const stripped = text.replace(/#+$/, '') - if (!stripped || stripped.endsWith(' ')) { - text = stripped.trim() - } - } - - return { - type: 'heading' as const, - raw: match[0]!, - depth: match[1]!.length as number, - text, - tokens: this.lexer.inline(text), - } - }, + heading: createMarkedHeadingExtension(), }, }) -/** These path on npmjs.com don't belong to packages or search, so we shouldn't try to replace them with npmx.dev urls */ -const reservedPathsNpmJs = [ - 'products', - 'login', - 'signup', - 'advisories', - 'blog', - 'about', - 'press', - 'policies', -] - -const npmJsHosts = new Set(['www.npmjs.com', 'npmjs.com', 'www.npmjs.org', 'npmjs.org']) - -const USER_CONTENT_PREFIX = 'user-content-' - function withUserContentPrefix(value: string): string { return value.startsWith(USER_CONTENT_PREFIX) ? value : `${USER_CONTENT_PREFIX}${value}` } @@ -282,39 +169,6 @@ function toUserContentHash(value: string): string { return `#${withUserContentPrefix(value)}` } -function decodeHashFragment(value: string): string { - try { - return decodeURIComponent(value) - } catch { - return value - } -} - -function normalizePreservedAnchorAttrs(attrs: string): string { - const cleanedAttrs = attrs - .replace(/\s+href\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') - .replace(/\s+rel\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') - .replace(/\s+target\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, '') - .trim() - - return cleanedAttrs ? ` ${cleanedAttrs}` : '' -} - -export const isNpmJsUrlThatCanBeRedirected = (url: URL) => { - if (!npmJsHosts.has(url.host)) { - return false - } - - if ( - url.pathname === '/' || - reservedPathsNpmJs.some(path => url.pathname.startsWith(`/${path}`)) - ) { - return false - } - - return true -} - /** * Resolve a relative URL to an absolute URL. * If repository info is available, resolve to provider's raw file URLs. @@ -426,24 +280,6 @@ function resolveImageUrl(url: string, packageName: string, repoInfo?: Repository return toProxiedImageUrl(rawUrl, imageProxySecret) } -// Helper to prefix id attributes with 'user-content-' - -export function prefixId(tagName: string, attribs: sanitizeHtml.Attributes) { - if (attribs.id) { - attribs.id = withUserContentPrefix(attribs.id) - } - return { tagName, attribs } -} - -// README h1 always becomes h3 -// For deeper levels, ensure sequential order -// Don't allow jumping more than 1 level deeper than previous -export function calculateSemanticDepth(depth: number, lastSemanticLevel: number) { - if (depth === 1) return 3 - const maxAllowed = Math.min(lastSemanticLevel + 1, 6) - return Math.min(depth + 2, maxAllowed) -} - /** * Render YAML frontmatter as a GitHub-style key-value table. */ @@ -461,17 +297,6 @@ function renderFrontmatterTable(data: Record): string { return `\n${rows}\n
KeyValue
\n` } -// Extract and preserve allowed attributes from HTML heading tags -function extractHeadingAttrs(attrsString: string): string { - if (!attrsString) return '' - const preserved: string[] = [] - const alignMatch = /\balign=(["']?)([^"'\s>]+)\1/i.exec(attrsString) - if (alignMatch?.[2]) { - preserved.push(`align="${alignMatch[2]}"`) - } - return preserved.length > 0 ? ` ${preserved.join(' ')}` : '' -} - export async function renderReadmeHtml( content: string, packageName: string, @@ -492,117 +317,29 @@ export async function renderReadmeHtml( // If frontmatter parsing fails, render the full content as-is } - const shiki = await getShikiHighlighter() const renderer = new marked.Renderer() // Collect playground links during parsing const collectedLinks: PlaygroundLink[] = [] const seenUrls = new Set() - // Collect table of contents items during parsing - const toc: TocItem[] = [] - - // Track used heading slugs to handle duplicates (GitHub-style: foo, foo-1, foo-2) - const usedSlugs = new Map() - - // Track heading hierarchy to ensure sequential order for accessibility - // Page h1 = package name, h2 = "Readme" section heading - // So README starts at h3, and we ensure no levels are skipped - // Visual styling preserved via data-level attribute (original depth) - let lastSemanticLevel = 2 // Start after h2 (the "Readme" section heading) - - // Shared heading processing for both markdown and HTML headings - function processHeading( - depth: number, - displayHtml: string, - plainText: string, - slugSource: string, - preservedAttrs = '', - ) { - const semanticLevel = calculateSemanticDepth(depth, lastSemanticLevel) - lastSemanticLevel = semanticLevel - - let slug = slugify(slugSource) - if (!slug) slug = 'heading' - - const count = usedSlugs.get(slug) ?? 0 - usedSlugs.set(slug, count + 1) - const uniqueSlug = count === 0 ? slug : `${slug}-${count}` - const id = toUserContentId(uniqueSlug) - - if (plainText) { - toc.push({ text: plainText, id, depth }) - } - - // The browser doesn't support anchors within anchors and automatically extracts them from each other, - // causing a hydration error. To prevent this from happening in such cases, we use the anchor separately - if (htmlAnchorRe.test(displayHtml)) { - return `${displayHtml}
\n` - } - - return `${displayHtml}\n` - } + const { toc, heading, processHeading } = createHeading({ toUserContentId }) - const anchorTokenRegex = /^$/ - renderer.heading = function ({ tokens, depth }: Tokens.Heading) { - const isAnchorHeading = - anchorTokenRegex.test(tokens[0]?.raw ?? '') && tokens[tokens.length - 1]?.raw === '' - - // for anchor headings, we will ignore user-added id and add our own - const tokensWithoutAnchor = isAnchorHeading ? tokens.slice(1, -1) : tokens - const displayHtml = this.parser.parseInline(tokensWithoutAnchor) - const plainText = getHeadingPlainText(displayHtml) - const slugSource = getHeadingSlugSource(displayHtml) - return processHeading(depth, displayHtml, plainText, slugSource) - } - - // Intercept HTML headings so they get id, TOC entry, and correct semantic level. - // Also intercept raw HTML tags so playground links are collected in the same pass. - const htmlHeadingRe = /]*)?>([\s\S]*?)<\/h\1>/gi - const htmlAnchorRe = /]*?)href=(["'])([^"']*)\2([^>]*)>([\s\S]*?)<\/a>/gi - renderer.html = function ({ text }: Tokens.HTML) { - let result = text.replace(htmlHeadingRe, (_, level, attrs = '', inner) => { - const depth = parseInt(level) - const plainText = getHeadingPlainText(inner) - const slugSource = getHeadingSlugSource(inner) - const preservedAttrs = extractHeadingAttrs(attrs) - return processHeading(depth, inner, plainText, slugSource, preservedAttrs).trimEnd() - }) - // Process raw HTML tags for playground link collection and URL resolution - result = result.replace(htmlAnchorRe, (_full, beforeHref, _quote, href, afterHref, inner) => { - const label = decodeHtmlEntities(stripHtmlTags(inner).trim()) - const { resolvedHref, extraAttrs } = processLink(href, label) - const preservedAttrs = normalizePreservedAnchorAttrs(`${beforeHref ?? ''}${afterHref ?? ''}`) - return `${inner}` - }) - return result - } + renderer.heading = heading // Syntax highlighting for code blocks (uses shared highlighter) - renderer.code = ({ text, lang }: Tokens.Code) => { - const html = highlightCodeSync(shiki, text, lang || 'text') - // Add copy button - return `
- -${html} -
` - } + renderer.code = await createCodeHighlighter() - // Resolve image URLs (with GitHub blob โ†’ raw conversion) - renderer.image = ({ href, title, text }: Tokens.Image) => { - const resolvedHref = resolveImageUrl(href, packageName, repoInfo) - const titleAttr = title ? ` title="${escapeHtml(title)}"` : '' - const altAttr = text ? ` alt="${escapeHtml(text)}"` : '' - return `` + function processImageUrl(href: string) { + return resolveImageUrl(href, packageName, repoInfo) } + renderer.image = createImage(processImageUrl) + // Helper: resolve a link href, collect playground links, and build attributes. // Used by both the markdown renderer.link and the HTML interceptor so that // all link processing happens in a single pass during marked rendering. - function processLink(href: string, label: string): { resolvedHref: string; extraAttrs: string } { + const processLink: ProcessLinkFn = (href: string, label: string) => { const resolvedHref = resolveUrl(href, packageName, repoInfo) // Collect playground links @@ -618,7 +355,7 @@ ${html} } // Security attributes for external links - let extraAttrs = + const extraAttrs = resolvedHref && hasProtocol(resolvedHref, { acceptRelative: true }) ? ' rel="nofollow noreferrer noopener" target="_blank"' : '' @@ -626,155 +363,18 @@ ${html} return { resolvedHref, extraAttrs } } - // Resolve link URLs, add security attributes, and collect playground links - // โ€” all in a single pass during marked rendering (no deferred processing) - renderer.link = function ({ href, title, tokens }: Tokens.Link) { - const text = this.parser.parseInline(tokens) - const titleAttr = title ? ` title="${title}"` : '' - let plainText = stripHtmlTags(text).trim() - - // If plain text is empty, check if we have an image with alt text - if (!plainText && tokens.length === 1 && tokens[0]?.type === 'image') { - plainText = tokens[0].text - } - - const { resolvedHref, extraAttrs } = processLink(href, plainText || title || '') - - if (!resolvedHref) return text - - return `${text}` - } + renderer.link = createLink(processLink) + renderer.html = createHtml({ processHeading, processLink }) // GitHub-style callouts: > [!NOTE], > [!TIP], etc. - renderer.blockquote = function ({ tokens }: Tokens.Blockquote) { - const body = this.parser.parse(tokens) + renderer.blockquote = blockquote - const calloutMatch = body.match(/^

\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\](?:
)?\s*/i) - - if (calloutMatch?.[1]) { - const calloutType = calloutMatch[1].toLowerCase() - const cleanedBody = body.replace(calloutMatch[0], '

') - return `

${cleanedBody}
\n` - } - - return `
${body}
\n` - } + const rawHtml = renderToRawHtml({ renderer, markdownBody, frontmatterHtml }) - marked.setOptions({ renderer }) - - // Strip trailing whitespace (tabs/spaces) from code block closing fences. - // While marky-markdown handles these gracefully, marked fails to recognize - // the end of a code block if the closing fences are followed by unexpected whitespaces. - const normalizedContent = markdownBody.replace(/^( {0,3}(?:`{3,}|~{3,}))\s*$/gm, '$1') - const rawHtml = frontmatterHtml + (marked.parse(normalizedContent) as string) - - const sanitized = sanitizeHtml(rawHtml, { - allowedTags: ALLOWED_TAGS, - allowedAttributes: ALLOWED_ATTR, - allowedSchemes: ['http', 'https', 'mailto'], - // disallow styles other than the ones shiki emits - allowedStyles: { - span: { - 'color': [/^#[0-9a-f]{3,8}$/i], - '--shiki-light': [/^#[0-9a-f]{3,8}$/i], - }, - }, - // Transform img src URLs (GitHub blob โ†’ raw, relative โ†’ GitHub raw) - transformTags: { - // Headings are already processed to correct semantic levels by processHeading() - // during the marked rendering pass. The sanitizer just needs to preserve them. - // For any stray headings that didn't go through processHeading (shouldn't happen), - // we still apply a safe fallback shift. - h1: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h1', attribs } - return { tagName: 'h3', attribs: { ...attribs, 'data-level': '1' } } - }, - h2: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h2', attribs } - return { tagName: 'h4', attribs: { ...attribs, 'data-level': '2' } } - }, - h3: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h3', attribs } - return { tagName: 'h5', attribs: { ...attribs, 'data-level': '3' } } - }, - h4: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h4', attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '4' } } - }, - h5: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h5', attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '5' } } - }, - h6: (_, attribs) => { - if (attribs['data-level']) return { tagName: 'h6', attribs } - return { tagName: 'h6', attribs: { ...attribs, 'data-level': '6' } } - }, - img: (tagName, attribs) => { - if (attribs.src) { - attribs.src = resolveImageUrl(attribs.src, packageName, repoInfo) - } - return { tagName, attribs } - }, - source: (tagName, attribs) => { - if (attribs.src) { - attribs.src = resolveImageUrl(attribs.src, packageName, repoInfo) - } - if (attribs.srcset) { - attribs.srcset = attribs.srcset - .split(',') - .map(entry => { - const parts = entry.trim().split(/\s+/) - const url = parts[0] - if (!url) return entry.trim() - const descriptor = parts[1] - const resolvedUrl = resolveImageUrl(url, packageName, repoInfo) - return descriptor ? `${resolvedUrl} ${descriptor}` : resolvedUrl - }) - .join(', ') - } - return { tagName, attribs } - }, - // Markdown links are fully processed in renderer.link (single-pass). - // However, inline HTML tags inside paragraphs are NOT seen by - // renderer.html (marked parses them as paragraph tokens, not html tokens). - // So we still need to collect playground links here for those cases. - // The seenUrls set ensures no duplicates across both paths. - a: (tagName, attribs) => { - if (!attribs.href) { - return { tagName, attribs } - } - - const resolvedHref = resolveUrl(attribs.href, packageName, repoInfo) - - // Collect playground links from inline HTML tags that weren't - // caught by renderer.link or renderer.html - const provider = matchPlaygroundProvider(resolvedHref) - if (provider && !seenUrls.has(resolvedHref)) { - seenUrls.add(resolvedHref) - collectedLinks.push({ - url: resolvedHref, - provider: provider.id, - providerName: provider.name, - // sanitize-html transformTags doesn't provide element text content, - // so we fall back to the provider name for the label - label: provider.name, - }) - } - - // Add security attributes for external links (idempotent) - if (resolvedHref && hasProtocol(resolvedHref, { acceptRelative: true })) { - attribs.rel = 'nofollow noreferrer noopener' - attribs.target = '_blank' - } - attribs.href = resolvedHref - return { tagName, attribs } - }, - div: prefixId, - p: prefixId, - span: prefixId, - section: prefixId, - article: prefixId, - }, + const sanitized = sanitizeRawHTML(rawHtml, { + processImageUrl, + processLink, + toUserContentId, }) return { diff --git a/shared/schemas/noodle.ts b/shared/schemas/noodle.ts new file mode 100644 index 0000000000..7d8a45af07 --- /dev/null +++ b/shared/schemas/noodle.ts @@ -0,0 +1,39 @@ +import * as v from 'valibot' + +const NoodleAuthorSchema = v.object({ + name: v.string(), + blueskyHandle: v.optional(v.string()), +}) + +const NoodleReferenceSchema = v.object({ + label: v.optional(v.string()), + url: v.string(), +}) + +// Required: key, title, slug, date. Everything else is optional and the +// detail page only renders sections for fields that are filled in. +const NoodleSchema = v.object({ + key: v.string(), + title: v.string(), + slug: v.string(), + date: v.string(), + dateTo: v.optional(v.string()), + // IANA timezone name, or "auto" for the visitor's local time. + timezone: v.optional(v.string()), + // When true, the npmx tagline is hidden while this noodle is active. + tagline: v.optional(v.boolean()), + occasion: v.optional(v.string()), + description: v.optional(v.string()), + // Public paths to variant images (draft / alternate takes), used by the lens carousel. + variants: v.optional(v.array(v.string())), + prUrl: v.optional(v.string()), + authors: v.optional(v.array(NoodleAuthorSchema)), + // External links (Wikipedia, NASA mission page, etc.) shown in the detail right panel. + references: v.optional(v.array(NoodleReferenceSchema)), + // Public path to the OG-image hero asset. + posterImage: v.optional(v.string()), + // Optional image rendered behind `posterImage` (e.g. a backdrop the wordmark sits on). + posterBackdrop: v.optional(v.string()), +}) + +export type Noodle = v.InferOutput diff --git a/shared/types/changelog.ts b/shared/types/changelog.ts index 3ec410d08d..d3e5f5858b 100644 --- a/shared/types/changelog.ts +++ b/shared/types/changelog.ts @@ -32,4 +32,5 @@ export interface ReleaseData { id: string | number publishedAt?: string toc?: TocItem[] + link: string } diff --git a/shared/types/compare.ts b/shared/types/compare.ts index bce433b877..ca6a0cdf4b 100644 --- a/shared/types/compare.ts +++ b/shared/types/compare.ts @@ -147,8 +147,12 @@ export interface FileDiffResponse { } /** Metadata */ meta: { + /** Whether diff was rendered in large-file degraded mode */ + large?: boolean /** Whether diff was truncated */ truncated?: boolean + /** Why the diff was truncated */ + truncationReason?: 'too_many_lines' /** Time taken to compute (ms) */ computeTime?: number } diff --git a/shared/types/comparison.ts b/shared/types/comparison.ts index c7bfafdc70..bedcda8d33 100644 --- a/shared/types/comparison.ts +++ b/shared/types/comparison.ts @@ -18,6 +18,7 @@ export type ComparisonFacet = | 'deprecated' | 'totalLikes' | 'githubStars' + | 'githubForks' | 'githubIssues' | 'createdAt' @@ -62,6 +63,9 @@ export const FACET_INFO: Record> = { githubStars: { category: 'health', }, + githubForks: { + category: 'health', + }, githubIssues: { category: 'health', }, diff --git a/shared/utils/diff.ts b/shared/utils/diff.ts index aa8541e12f..a9a4c68627 100644 --- a/shared/utils/diff.ts +++ b/shared/utils/diff.ts @@ -342,6 +342,39 @@ export function insertSkipBlocks(hunks: DiffHunk[]): (DiffHunk | DiffSkipBlock)[ return result } +export function truncateDiffHunks( + hunks: (DiffHunk | DiffSkipBlock)[], + maxLines: number, +): { hunks: (DiffHunk | DiffSkipBlock)[]; truncated: boolean } { + const result: (DiffHunk | DiffSkipBlock)[] = [] + let remainingLines = maxLines + + for (const hunk of hunks) { + if (remainingLines <= 0) { + return { hunks: result, truncated: true } + } + + if (hunk.type === 'skip') { + result.push(hunk) + continue + } + + if (hunk.lines.length <= remainingLines) { + result.push(hunk) + remainingLines -= hunk.lines.length + continue + } + + result.push({ + ...hunk, + lines: hunk.lines.slice(0, remainingLines), + }) + return { hunks: result, truncated: true } + } + + return { hunks: result, truncated: false } +} + export function createDiff( oldContent: string, newContent: string, diff --git a/shared/utils/download-chart-last-label.ts b/shared/utils/download-chart-last-label.ts new file mode 100644 index 0000000000..16ad6b15ae --- /dev/null +++ b/shared/utils/download-chart-last-label.ts @@ -0,0 +1,182 @@ +/** + * Utility to be used in vue-data-ui line charts (`VueUiXy`) using the `#svg` slot to display the last value as data label. + * In case of mutliple series, if label collisions are detected, labels are distributed as close as possible to their related datapoint, shifted to avoid overlaps, and linked to the last datapoint with an elbowed marker + */ +export function createLastDatapointLabelsSvg({ + series, + drawingArea, + colors, + formatValue, + isDarkMode, + fontSize = 20, + labelOffset = 24, + labelHeight = 30, +}: { + series: LastDatapointLabelSerie[] + drawingArea: { + top: number + height?: number + bottom?: number + } + colors: LastDatapointLabelColors + formatValue: (value: number) => string + isDarkMode: boolean + svgWidth?: number + fontSize?: number + labelOffset?: number + labelHeight?: number +}) { + const drawingAreaTop = Number(drawingArea.top ?? 0) + const drawingAreaHeight = Number( + drawingArea.height ?? Number(drawingArea.bottom ?? 0) - drawingAreaTop, + ) + const drawingAreaBottom = drawingAreaTop + drawingAreaHeight + + const labels = series + .map(serie => { + const lastPlot = Array.isArray(serie.plots) ? serie.plots.at(-1) : null + if (!lastPlot) return null + + const value = Number(lastPlot.value ?? 0) + const safeValue = Number.isFinite(value) ? value : 0 + const text = formatValue(safeValue) + + return { + x: Number(lastPlot.x ?? 0), + y: Number(lastPlot.y ?? 0), + value: safeValue, + color: String(serie.color ?? colors.fallbackSerieColor), + text, + width: text.length * fontSize * 0.58, + } + }) + .filter(isLastDatapointLabel) + + if (!labels.length) return '' + + const hasCollision = labels.some((label, labelIndex) => + labels.some((otherLabel, otherLabelIndex) => { + if (labelIndex === otherLabelIndex) return false + + return ( + label.x + labelOffset < otherLabel.x + labelOffset + otherLabel.width && + label.x + labelOffset + label.width > otherLabel.x + labelOffset && + label.y - labelHeight / 2 < otherLabel.y + labelHeight / 2 && + label.y + labelHeight / 2 > otherLabel.y - labelHeight / 2 + ) + }), + ) + + if (!hasCollision) { + return labels + .map( + label => ` + + ${label.text} + + `, + ) + .join('\n') + } + + const sortedLabels = [...labels].sort((firstLabel, secondLabel) => { + return firstLabel.y - secondLabel.y + }) + + const minimumLabelY = drawingAreaTop + labelHeight / 2 + const maximumLabelY = drawingAreaBottom - labelHeight / 2 + + const positionedLabels = sortedLabels.map(label => ({ + ...label, + labelY: Math.min(maximumLabelY, Math.max(minimumLabelY, label.y)), + })) + + for (let index = 1; index < positionedLabels.length; index += 1) { + const previousLabel = positionedLabels[index - 1] + const currentLabel = positionedLabels[index] + if (!previousLabel || !currentLabel) continue + if (currentLabel.labelY - previousLabel.labelY < labelHeight) { + currentLabel.labelY = previousLabel.labelY + labelHeight + } + } + + const lastLabel = positionedLabels.at(-1) + if (!lastLabel) return '' + const overflow = lastLabel.labelY - maximumLabelY + + if (overflow > 0) { + for (const label of positionedLabels) { + label.labelY -= overflow + } + } + + const labelX = Math.max(...positionedLabels.map(label => label.x)) + labelOffset + 10 + + return positionedLabels + .map(label => { + const connectorStartX = label.x + 5 + const connectorEndX = labelX + + return ` + + + ${label.text} + + ` + }) + .join('\n') +} + +export type LastDatapointLabelColors = { + foreground: string + background: string + fallbackSerieColor: string +} + +export type LastDatapointLabelSerie = { + color?: string + plots?: { + x?: number | null + y?: number | null + value?: number | null + }[] +} + +type LastDatapointLabel = { + x: number + y: number + value: number + color: string + text: string + width: number +} + +function isLastDatapointLabel(label: LastDatapointLabel | null): label is LastDatapointLabel { + return label !== null +} diff --git a/shared/utils/download-ranges.ts b/shared/utils/download-ranges.ts new file mode 100644 index 0000000000..c555493a9c --- /dev/null +++ b/shared/utils/download-ranges.ts @@ -0,0 +1,52 @@ +import type { DailyRawPoint } from '~/types/chart' +import { addDays, parseIsoDate, toIsoDate } from '~/utils/date' + +export function differenceInUtcDaysInclusive(startIso: string, endIso: string): number { + const start = parseIsoDate(startIso) + const end = parseIsoDate(endIso) + + return Math.floor((end.getTime() - start.getTime()) / 86400000) + 1 +} + +export function splitIsoRangeIntoChunksInclusive( + startIso: string, + endIso: string, + maximumDaysPerRequest: number, +): Array<{ startIso: string; endIso: string }> { + const totalDays = differenceInUtcDaysInclusive(startIso, endIso) + + if (totalDays <= maximumDaysPerRequest) { + return [{ startIso, endIso }] + } + + const chunks: Array<{ startIso: string; endIso: string }> = [] + + let cursorStart = parseIsoDate(startIso) + const finalEnd = parseIsoDate(endIso) + + while (cursorStart.getTime() <= finalEnd.getTime()) { + const cursorEnd = addDays(cursorStart, maximumDaysPerRequest - 1) + const actualEnd = cursorEnd.getTime() < finalEnd.getTime() ? cursorEnd : finalEnd + + chunks.push({ + startIso: toIsoDate(cursorStart), + endIso: toIsoDate(actualEnd), + }) + + cursorStart = addDays(actualEnd, 1) + } + + return chunks +} + +export function mergeDailyPoints(points: DailyRawPoint[]): DailyRawPoint[] { + const valuesByDay = new Map() + + for (const point of points) { + valuesByDay.set(point.day, (valuesByDay.get(point.day) ?? 0) + point.value) + } + + return Array.from(valuesByDay.entries()) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([day, value]) => ({ day, value })) +} diff --git a/shared/utils/embed-chart-colors.ts b/shared/utils/embed-chart-colors.ts new file mode 100644 index 0000000000..990c617da6 --- /dev/null +++ b/shared/utils/embed-chart-colors.ts @@ -0,0 +1,37 @@ +type EmbedTheme = 'light' | 'dark' + +export function resolveEmbedChartColors(theme: EmbedTheme = 'light') { + // duplicated from main.css + const palettes = { + dark: { + default: { + bg: 'oklch(0.171 0 0)', + bgSubtle: 'oklch(0.198 0 0)', + bgMuted: 'oklch(0.236 0 0)', + bgElevated: 'oklch(0.266 0 0)', + fg: 'oklch(0.982 0 0)', + fgMuted: 'oklch(0.749 0 0)', + fgSubtle: 'oklch(0.673 0 0)', + border: 'oklch(0.269 0 0)', + accent: 'oklch(0.787 0.128 230.318)', + }, + }, + light: { + default: { + bg: 'oklch(1 0 0)', + bgSubtle: 'oklch(0.979 0.001 286.375)', + bgMuted: 'oklch(0.955 0.001 286.76)', + bgElevated: 'oklch(0.94 0.002 287.29)', + fg: 'oklch(0.146 0 0)', + fgMuted: 'oklch(0.398 0 0)', + fgSubtle: 'oklch(0.48 0 0)', + border: 'oklch(0.8514 0 0)', + accent: 'oklch(0.5 0.16 247.27)', + }, + }, + } as const + + return { + ...palettes[theme].default, + } +} diff --git a/shared/utils/parse-package-param.ts b/shared/utils/parse-package-param.ts index 310fcd2fd0..7ea86c73b8 100644 --- a/shared/utils/parse-package-param.ts +++ b/shared/utils/parse-package-param.ts @@ -58,3 +58,50 @@ export function parsePackageParam(pkgParam: string): ParsedPackageParams { rest: [], } } + +/** + * Parse a package spec into its name and optional version. + * Handles formats like: `name`, `name@version`, `@scope/name`, `@scope/name@version`. + * + * The version segment may be an exact version or a dist-tag (e.g. `next`); it is + * returned verbatim for the caller to resolve. + * + * @example + * ```ts + * parsePackageSpec('react') // { name: 'react' } + * parsePackageSpec('react@18.2.0') // { name: 'react', version: '18.2.0' } + * parsePackageSpec('@vue/reactivity') // { name: '@vue/reactivity' } + * parsePackageSpec('@vue/reactivity@3.4.0') // { name: '@vue/reactivity', version: '3.4.0' } + * ``` + */ +export function parsePackageSpec(input: string): { name: string; version?: string } { + if (input.startsWith('@')) { + // Scoped package: @scope/name or @scope/name@version + const slashIndex = input.indexOf('/') + if (slashIndex === -1) { + // Invalid format like just "@scope" + return { name: input } + } + const afterSlash = input.slice(slashIndex + 1) + const atIndex = afterSlash.indexOf('@') + if (atIndex === -1) { + // @scope/name (no version) + return { name: input } + } + // @scope/name@version + return { + name: input.slice(0, slashIndex + 1 + atIndex), + version: afterSlash.slice(atIndex + 1), + } + } + + // Unscoped package: name or name@version + const atIndex = input.indexOf('@') + if (atIndex === -1) { + return { name: input } + } + return { + name: input.slice(0, atIndex), + version: input.slice(atIndex + 1), + } +} diff --git a/shared/utils/trends-chart.ts b/shared/utils/trends-chart.ts new file mode 100644 index 0000000000..0033a4cdba --- /dev/null +++ b/shared/utils/trends-chart.ts @@ -0,0 +1,709 @@ +// Shared utilies for client & embed versions of the downloads trend chart + +import type { TextAlign, Theme as VueDataUiTheme } from 'vue-data-ui' +import type { VueUiXyConfig, VueUiXyDatasetItem } from 'vue-data-ui/vue-ui-xy' +import { OKLCH_NEUTRAL_FALLBACK, lightenOklch } from '~/utils/colors' +import { getFrameworkColor, isListedFramework } from '~/utils/frameworks' +import { applyEllipsis } from '~/utils/charts' +import { applyDataPipeline, DEFAULT_PREDICTION_POINTS } from '~/utils/chart-data-prediction' +import type { + ChartTimeGranularity, + DailyDataPoint, + EvolutionData, + MonthlyDataPoint, + WeeklyDataPoint, + YearlyDataPoint, +} from '~/types/chart' + +type TrendMetricId = 'downloads' | 'likes' | 'contributors' + +type TrendColors = Record + +type TrendFormatter = { + format: (value: number) => string +} + +type TranslateFn = (key: string, params?: Record) => string + +type TrendChartBaseOptions = { + packageNames: string[] + isMultiPackageMode: boolean + selectedMetric: TrendMetricId + selectedMetricLabel: string + selectedGranularity: ChartTimeGranularity + displayedGranularity: ChartTimeGranularity + singleEvolution: EvolutionData + evolutionsByPackage?: Record + effectivePackageNamesForMetric?: string[] + colors: TrendColors + accent?: string + isDarkMode: boolean + chartFilter: { + averageWindow: number + smoothingTau: number + predictionPoints?: number + } + useAnomalyCorrection?: boolean + applyAnomalyCorrection?: (params: { + data: EvolutionData + packageName: string + granularity: ChartTimeGranularity + }) => EvolutionData + t: TranslateFn + compactNumberFormatter: Intl.NumberFormat +} + +type TrendChartDataOptions = TrendChartBaseOptions + +type TrendChartConfigOptions = TrendChartBaseOptions & { + dates: number[] + isMobile: boolean + pending: boolean + locale: string + chartHeight: number + inModal?: boolean + tooltipPosition?: string +} +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + +export function isWeeklyDataset(data: unknown): data is WeeklyDataPoint[] { + return ( + Array.isArray(data) && + data.length > 0 && + isRecord(data[0]) && + 'weekStart' in data[0] && + 'weekEnd' in data[0] && + 'value' in data[0] + ) +} + +export function isDailyDataset(data: unknown): data is DailyDataPoint[] { + return ( + Array.isArray(data) && + data.length > 0 && + isRecord(data[0]) && + 'day' in data[0] && + 'value' in data[0] + ) +} + +export function isMonthlyDataset(data: unknown): data is MonthlyDataPoint[] { + return ( + Array.isArray(data) && + data.length > 0 && + isRecord(data[0]) && + 'month' in data[0] && + 'value' in data[0] + ) +} + +export function isYearlyDataset(data: unknown): data is YearlyDataPoint[] { + return ( + Array.isArray(data) && + data.length > 0 && + isRecord(data[0]) && + 'year' in data[0] && + 'value' in data[0] + ) +} + +function extractSeriesPoints( + granularity: ChartTimeGranularity, + dataset: EvolutionData, +): Array<{ timestamp: number; value: number; hasAnomaly: boolean }> { + if (granularity === 'weekly' && isWeeklyDataset(dataset)) { + return dataset.map(item => ({ + timestamp: item.timestampEnd, + value: item.value, + hasAnomaly: !!item.hasAnomaly, + })) + } + + if ( + (granularity === 'daily' && isDailyDataset(dataset)) || + (granularity === 'monthly' && isMonthlyDataset(dataset)) || + (granularity === 'yearly' && isYearlyDataset(dataset)) + ) { + return (dataset as Array<{ timestamp: number; value: number; hasAnomaly?: boolean }>).map( + item => ({ + timestamp: item.timestamp, + value: item.value, + hasAnomaly: !!item.hasAnomaly, + }), + ) + } + + return [] +} + +function formatSingleXyDataset(options: { + granularity: ChartTimeGranularity + dataset: EvolutionData + seriesName: string + accent: string + isDarkMode: boolean +}): { dataset: VueUiXyDatasetItem[] | null; dates: number[] } { + const lightColor = options.isDarkMode ? lightenOklch(options.accent, 0.618) : undefined + const temperatureColors = lightColor ? [lightColor, options.accent] : undefined + + const datasetItem: VueUiXyDatasetItem = { + name: applyEllipsis(options.seriesName, 32), + type: 'line', + series: options.dataset.map(item => item.value), + color: options.accent, + temperatureColors, + useArea: true, + dashIndices: options.dataset + .map((item, index) => (item.hasAnomaly ? index : -1)) + .filter(index => index !== -1), + } + + if (options.granularity === 'weekly' && isWeeklyDataset(options.dataset)) { + return { + dataset: [datasetItem], + dates: options.dataset.map(item => item.timestampEnd), + } + } + + if (options.granularity === 'daily' && isDailyDataset(options.dataset)) { + return { + dataset: [datasetItem], + dates: options.dataset.map(item => item.timestamp), + } + } + + if (options.granularity === 'monthly' && isMonthlyDataset(options.dataset)) { + return { + dataset: [datasetItem], + dates: options.dataset.map(item => item.timestamp), + } + } + + if (options.granularity === 'yearly' && isYearlyDataset(options.dataset)) { + return { + dataset: [datasetItem], + dates: options.dataset.map(item => item.timestamp), + } + } + + return { dataset: null, dates: [] } +} + +export function buildTrendsChartData(options: TrendChartDataOptions): { + dataset: VueUiXyDatasetItem[] | null + dates: number[] +} { + const accent = options.accent ?? options.colors.fgSubtle ?? OKLCH_NEUTRAL_FALLBACK + + if (!options.isMultiPackageMode) { + const packageName = options.packageNames[0] ?? '' + return formatSingleXyDataset({ + granularity: options.displayedGranularity, + dataset: options.singleEvolution, + seriesName: packageName, + accent, + isDarkMode: options.isDarkMode, + }) + } + + const names = options.effectivePackageNamesForMetric ?? options.packageNames + const timestampSet = new Set() + const pointsByPackage = new Map< + string, + Array<{ timestamp: number; value: number; hasAnomaly?: boolean }> + >() + + for (const packageName of names) { + let data = options.evolutionsByPackage?.[packageName] ?? [] + + if ( + options.selectedMetric === 'downloads' && + options.useAnomalyCorrection && + options.applyAnomalyCorrection + ) { + data = options.applyAnomalyCorrection({ + data, + packageName, + granularity: options.displayedGranularity, + }) + } + + const points = extractSeriesPoints(options.displayedGranularity, data) + pointsByPackage.set(packageName, points) + + for (const point of points) { + timestampSet.add(point.timestamp) + } + } + + const dates = Array.from(timestampSet).sort((a, b) => a - b) + + if (!dates.length) { + return { dataset: null, dates: [] } + } + + const dataset = names.map(packageName => { + const points = pointsByPackage.get(packageName) ?? [] + const valueByTimestamp = new Map() + const anomalyTimestamps = new Set() + + for (const point of points) { + valueByTimestamp.set(point.timestamp, point.value) + + if (point.hasAnomaly) { + anomalyTimestamps.add(point.timestamp) + } + } + + const series = dates.map(timestamp => valueByTimestamp.get(timestamp) ?? 0) + const dashIndices = dates + .map((timestamp, index) => (anomalyTimestamps.has(timestamp) ? index : -1)) + .filter(index => index !== -1) + + const item: VueUiXyDatasetItem = { + name: applyEllipsis(packageName, 32), + type: 'line', + series, + dashIndices, + } + + if (isListedFramework(packageName)) { + item.color = getFrameworkColor(packageName) + } + + return item + }) + + return { dataset, dates } +} + +type TrendsNormalisedDatasetItem = VueUiXyDatasetItem & { + color?: string + series: number[] + dashIndices?: number[] +} + +export function buildNormalisedTrendsDataset(options: { + dataset: VueUiXyDatasetItem[] | null + dates: number[] + granularity: ChartTimeGranularity + selectedMetric: TrendMetricId + chartFilter: { + averageWindow: number + smoothingTau: number + predictionPoints?: number + } + endDateMs?: number | null +}): TrendsNormalisedDatasetItem[] { + const referenceMs = options.endDateMs ?? Date.now() + const lastDateMs = options.dates.at(-1) ?? 0 + const isAbsoluteMetric = options.selectedMetric === 'contributors' + + return (options.dataset ?? []).map(item => { + const sourceSeries = item.series.map(value => { + if (typeof value === 'number') { + return value + } + + if (value && typeof value === 'object' && typeof value.y === 'number') { + return value.y + } + + return 0 + }) + + const series = applyDataPipeline( + sourceSeries, + { + averageWindow: options.chartFilter.averageWindow, + smoothingTau: options.chartFilter.smoothingTau, + predictionPoints: + options.granularity === 'weekly' + ? 0 + : (options.chartFilter.predictionPoints ?? DEFAULT_PREDICTION_POINTS), + }, + { + granularity: options.granularity, + lastDateMs, + referenceMs, + isAbsoluteMetric, + }, + ) + + return Object.assign({}, item, { + series, + dashIndices: item.dashIndices ?? [], + }) + }) +} +export function getTrendsDatetimeFormatterOptions(granularity: ChartTimeGranularity) { + return { + daily: { year: 'yyyy-MM-dd', month: 'yyyy-MM-dd', day: 'yyyy-MM-dd' }, + weekly: { year: 'yyyy-MM-dd', month: 'yyyy-MM-dd', day: 'yyyy-MM-dd' }, + monthly: { year: 'MMM yyyy', month: 'MMM yyyy', day: 'MMM yyyy' }, + yearly: { year: 'yyyy', month: 'yyyy', day: 'yyyy' }, + }[granularity] +} + +// Some locales require more spacing for the last label value displayed on the chart, and for which some extra padding is reserved in the chart config. +export const LOCALES_WITH_EXTRA_SPACE = [ + 'bg-BG', + 'ru-RU', + 'cs-CZ', + 'de-AT', + 'de-DE', + 'id-ID', + 'it-IT', + 'ja-JP', + 'nb-NO', + 'nl-NL', + 'pl-PL', + 'pt-BR', + 'ro-RO', + 'sr-Latn-RS', + 'uk-UA', +] + +export function buildTrendsChartConfig( + options: TrendChartConfigOptions & { + dates: number[] + }, +): VueUiXyConfig { + return { + theme: options.isDarkMode ? 'dark' : ('' as VueDataUiTheme), + downsample: { + threshold: 5000, + }, + a11y: { + translations: { + keyboardNavigation: options.t( + 'package.trends.chart_assistive_text.keyboard_navigation_horizontal', + ), + tableAvailable: options.t('package.trends.chart_assistive_text.table_available'), + tableCaption: options.t('package.trends.chart_assistive_text.table_caption'), + }, + }, + chart: { + height: options.chartHeight, + backgroundColor: options.colors.bg, + padding: { + bottom: options.displayedGranularity === 'yearly' ? 84 : 64, + right: options.isMultiPackageMode + ? LOCALES_WITH_EXTRA_SPACE.includes(options.locale) + ? 180 + : 160 + : 145, + }, + userOptions: { + buttons: { + pdf: false, + labels: false, + fullscreen: false, + table: false, + tooltip: false, + altCopy: true, + }, + buttonTitles: { + csv: options.t('package.trends.download_file', { fileType: 'CSV' }), + img: options.t('package.trends.download_file', { fileType: 'PNG' }), + svg: options.t('package.trends.download_file', { fileType: 'SVG' }), + annotator: options.t('package.trends.toggle_annotator'), + stack: options.t('package.trends.toggle_stack_mode'), + altCopy: options.t('package.trends.copy_alt.button_label'), + open: options.t('package.trends.open_options'), + close: options.t('package.trends.close_options'), + }, + useCursorPointer: true, + }, + grid: { + position: 'start', + stroke: options.colors.border, + showHorizontalLines: true, + labels: { + fontSize: options.isMobile ? 24 : 16, + color: options.pending ? options.colors.border : options.colors.fgSubtle, + axis: { + yLabel: options.t('package.trends.y_axis_label', { + granularity: options.t(`package.trends.granularity_${options.selectedGranularity}`), + facet: options.selectedMetricLabel, + }), + yLabelOffsetX: 12, + fontSize: options.isMobile ? 32 : 24, + }, + xAxisLabels: { + show: true, + showOnlyAtModulo: true, + modulo: 12, + values: options.dates, + datetimeFormatter: { + enable: true, + locale: options.locale, + useUTC: true, + options: getTrendsDatetimeFormatterOptions(options.selectedGranularity), + }, + }, + yAxis: { + formatter: ({ value }: { value: number }) => { + return options.compactNumberFormatter.format(Number.isFinite(value) ? value : 0) + }, + useNiceScale: true, + gap: 24, + }, + }, + }, + timeTag: { + show: true, + backgroundColor: options.colors.bgElevated ?? options.colors.bg, + color: options.colors.fg, + fontSize: 16, + circleMarker: { + radius: 3, + color: options.colors.border, + }, + useDefaultFormat: true, + timeFormat: 'yyyy-MM-dd HH:mm:ss', + }, + highlighter: { + useLine: true, + }, + legend: { + show: false, + position: 'top', + }, + tooltip: { + teleportTo: options.inModal ? '#chart-modal' : undefined, + position: (options.tooltipPosition ?? 'center') as TextAlign, + offsetX: 24, + offsetY: options.isMultiPackageMode ? undefined : -24, + borderColor: 'transparent', + backdropFilter: false, + backgroundColor: 'transparent', + }, + }, + line: { + radius: 4, + useGradient: true, + dot: { + useSerieColor: true, + }, + labels: { + show: false, + }, + area: { + useGradient: true, + opacity: 12, + }, + }, + } +} + +export function drawTrendsEstimationLine(options: { + svg: Record + colors: TrendColors + shouldRender: boolean +}): string { + if (!options.shouldRender) { + return '' + } + + const data = Array.isArray(options.svg?.data) + ? options.svg.data + : Array.isArray(options.svg?.series) + ? options.svg.series + : [] + + if (!data.length) { + return '' + } + + const lines: string[] = [] + + for (const serie of data) { + const plots = serie?.plots + + if (!Array.isArray(plots) || plots.length < 2) { + continue + } + + const previousPoint = plots.at(-2) + const lastPoint = plots.at(-1) + + if (!previousPoint || !lastPoint) { + continue + } + + const stroke = String(serie?.color ?? options.colors.fg) + + lines.push(` + + + + `) + } + + return lines.join('\n') +} + +export function drawTrendsLastDatapointLabel(options: { + svg: Record + colors: TrendColors + compactNumberFormatter: TrendFormatter +}): string { + const data = Array.isArray(options.svg?.data) + ? options.svg.data + : Array.isArray(options.svg?.series) + ? options.svg.series + : [] + + if (!data.length) { + return '' + } + + const labels: string[] = [] + + for (const serie of data) { + const lastPlot = serie?.plots?.at(-1) + + if (!lastPlot) { + continue + } + + labels.push(` + + ${options.compactNumberFormatter.format(Number.isFinite(lastPlot.value) ? lastPlot.value : 0)} + + `) + } + + return labels.join('\n') +} + +export function drawTrendsSvgPrintLegend(options: { + svg: Record + colors: TrendColors + showEstimationLegend: boolean + estimationLabel: string +}): string { + const data = Array.isArray(options.svg?.data) + ? options.svg.data + : Array.isArray(options.svg?.series) + ? options.svg.series + : [] + + if (!data.length) { + return '' + } + + const output: string[] = [] + + data.forEach((serie, index) => { + output.push(` + + + ${serie.name} + + `) + }) + + if (options.showEstimationLegend) { + output.push(` + + + ${options.estimationLabel} + + `) + } + + return output.join('\n') +} + +export function generateWatermarkLogo({ + x, + y, + width, + height, + fill, +}: { + x: number + y: number + width: number + height: number + fill: string +}) { + return ` + + + + ` +} diff --git a/test/fixtures/jsdelivr-cdn/empathic@2.0.0/find.mjs b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/find.mjs new file mode 100644 index 0000000000..2c050ce0b4 --- /dev/null +++ b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/find.mjs @@ -0,0 +1,75 @@ +/* oxlint-disable */ +import { join } from 'node:path' +import { existsSync, statSync } from 'node:fs' +import * as walk from 'empathic/walk' +/** + * Find an item by name, walking parent directories until found. + * + * @param name The item name to find. + * @returns The absolute path to the item, if found. + */ +export function up(name, options) { + let dir, tmp + let start = (options && options.cwd) || '' + for (dir of walk.up(start, options)) { + tmp = join(dir, name) + if (existsSync(tmp)) return tmp + } +} +/** + * Get the first path that matches any of the names provided. + * + * > [NOTE] + * > The order of {@link names} is respected. + * + * @param names The item names to find. + * @returns The absolute path of the first item found, if any. + */ +export function any(names, options) { + const start = (options && options.cwd) || '' + const len = names.length + for (const dir of walk.up(start, options)) { + for (let j = 0; j < len; j++) { + const tmp = join(dir, names[j]) + if (existsSync(tmp)) return tmp + } + } +} +/** + * Find a file by name, walking parent directories until found. + * + * > [NOTE] + * > This function only returns a value for file matches. + * > A directory match with the same name will be ignored. + * + * @param name The file name to find. + * @returns The absolute path to the file, if found. + */ +export function file(name, options) { + const start = (options && options.cwd) || '' + for (const dir of walk.up(start, options)) { + try { + const tmp = join(dir, name) + if (statSync(tmp).isFile()) return tmp + } catch {} + } +} +/** + * Find a directory by name, walking parent directories until found. + * + * > [NOTE] + * > This function only returns a value for directory matches. + * > A file match with the same name will be ignored. + * + * @param name The directory name to find. + * @returns The absolute path to the file, if found. + */ +export function dir(name, options) { + const start = (options && options.cwd) || '' + for (const dir of walk.up(start, options)) { + try { + const tmp = join(dir, name) + if (statSync(tmp).isDirectory()) return tmp + } catch {} + } +} diff --git a/test/fixtures/jsdelivr-cdn/empathic@2.0.0/package.json b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/package.json new file mode 100644 index 0000000000..65ac290eb7 --- /dev/null +++ b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/package.json @@ -0,0 +1,49 @@ +{ + "name": "empathic", + "version": "2.0.0", + "description": "A set of small and fast Node.js utilities to understand your pathing needs.", + "license": "MIT", + "author": { + "name": "Luke Edwards", + "email": "luke.edwards05@gmail.com", + "url": "https://lukeed.com" + }, + "repository": "lukeed/empathic", + "exports": { + "./access": { + "types": "./access.d.ts", + "import": "./access.mjs", + "require": "./access.js" + }, + "./find": { + "types": "./find.d.ts", + "import": "./find.mjs", + "require": "./find.js" + }, + "./package": { + "types": "./package.d.ts", + "import": "./package.mjs", + "require": "./package.js" + }, + "./resolve": { + "types": "./resolve.d.ts", + "import": "./resolve.mjs", + "require": "./resolve.js" + }, + "./walk": { + "types": "./walk.d.ts", + "import": "./walk.mjs", + "require": "./walk.js" + }, + "./package.json": "./package.json" + }, + "scripts": { + "test": "uvu" + }, + "devDependencies": { + "uvu": "0.5" + }, + "engines": { + "node": ">=14" + } +} diff --git a/test/fixtures/jsdelivr-cdn/empathic@2.0.0/resolve.mjs b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/resolve.mjs new file mode 100644 index 0000000000..8b9379c491 --- /dev/null +++ b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/resolve.mjs @@ -0,0 +1,30 @@ +import { createRequire } from 'node:module' +import { isAbsolute, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +/** + * Resolve an absolute path from {@link root}, but only + * if {@link input} isn't already absolute. + * + * @param input The path to resolve. + * @param root The base path; default = process.cwd() + * @returns The resolved absolute path. + */ +export function absolute(input, root) { + return isAbsolute(input) ? input : resolve(root || '.', input) +} +export function from(root, ident, silent) { + try { + // NOTE: dirs need a trailing "/" OR filename. With "/" route, + // Node adds "noop.js" as main file, so just do "noop.js" anyway. + let r = + root instanceof URL || root.startsWith('file://') + ? join(fileURLToPath(root), 'noop.js') + : join(absolute(root), 'noop.js') + return createRequire(r).resolve(ident) + } catch (err) { + if (!silent) throw err + } +} +export function cwd(ident, silent) { + return from(resolve(), ident, silent) +} diff --git a/test/fixtures/jsdelivr-cdn/empathic@2.0.0/walk.mjs b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/walk.mjs new file mode 100644 index 0000000000..bf9a109cc8 --- /dev/null +++ b/test/fixtures/jsdelivr-cdn/empathic@2.0.0/walk.mjs @@ -0,0 +1,21 @@ +import { dirname } from 'node:path' +import { absolute } from 'empathic/resolve' +/** + * Get all parent directories of {@link base}. + * Stops after {@link Options['last']} is processed. + * + * @returns An array of absolute paths of all parent directories. + */ +export function up(base, options) { + let { last, cwd } = options || {} + let tmp = absolute(base, cwd) + let root = absolute(last || '/', cwd) + let prev, + arr = [] + while (prev !== root) { + arr.push(tmp) + tmp = dirname((prev = tmp)) + if (tmp === prev) break + } + return arr +} diff --git a/test/fixtures/jsdelivr/empathic.json b/test/fixtures/jsdelivr/empathic.json new file mode 100644 index 0000000000..3f8484dbc0 --- /dev/null +++ b/test/fixtures/jsdelivr/empathic.json @@ -0,0 +1,120 @@ +{ + "type": "npm", + "name": "empathic", + "version": "2.0.0", + "default": null, + "files": [ + { + "type": "file", + "name": "access.d.ts", + "hash": "BrF3r4FaA0GzI59lpo+Fga4gUk3RW/S1KBsFsfqa0Uc=", + "size": 618 + }, + { + "type": "file", + "name": "access.js", + "hash": "fOI6MfpljmYsMFoKxlT3hlksRGV+CzTG4PV17Tzj9bw=", + "size": 811 + }, + { + "type": "file", + "name": "access.mjs", + "hash": "XwPL8Rwp7LRA2P4L7k83MiVgJm+9ijt79kY2vYP1xfc=", + "size": 726 + }, + { + "type": "file", + "name": "find.d.ts", + "hash": "pnvypI9UlFlmFC/HEOemsr9P0LpvNLOdDHcxgWjReuI=", + "size": 1381 + }, + { + "type": "file", + "name": "find.js", + "hash": "4gQt2eiJdVuSz8qXxpVa7fSZ4my86ppZE559Axg1ZBA=", + "size": 2091 + }, + { + "type": "file", + "name": "find.mjs", + "hash": "lvJ7HCj4b9ulEfJmIu0emj6pPI/n3YsIKU6s/O2x1Zk=", + "size": 2033 + }, + { + "type": "file", + "name": "license", + "hash": "mp7a17quUmIr3fPBWy74oz0sifLSVAitE+inSBxrDJc=", + "size": 1104 + }, + { + "type": "file", + "name": "package.d.ts", + "hash": "JsRlIyi79zNkf8ANVGzKc3gREEhag4EuUipOTxyTHUI=", + "size": 1004 + }, + { + "type": "file", + "name": "package.js", + "hash": "+w109RqMZ0fjqw4X/RHR+yJCD0tb5NB/QBFcMOHPX9s=", + "size": 1696 + }, + { + "type": "file", + "name": "package.json", + "hash": "7qOfQHA0O99rY/ZP/hrK6E9yYxMNXbODNS9Sqjb/oVY=", + "size": 997 + }, + { + "type": "file", + "name": "package.mjs", + "hash": "ZHkKNK56yB982/jqiLzBxBX5/9oHD5J0Nzg/3OpmXAk=", + "size": 1650 + }, + { + "type": "file", + "name": "readme.md", + "hash": "gDnGtevykzLCMhqswkdNy0dc07Qa92MY2qvCeJ1MwEE=", + "size": 2336 + }, + { + "type": "file", + "name": "resolve.d.ts", + "hash": "ektazhZ/Xm9pQygPANVhSsn0DJ7TjBBPrORhvsAFLVE=", + "size": 1198 + }, + { + "type": "file", + "name": "resolve.js", + "hash": "pvj0JULeAbxLjvdmYSR6H/TL4QR+xwbwXBc2kwd7gCs=", + "size": 1034 + }, + { + "type": "file", + "name": "resolve.mjs", + "hash": "qGhTjwjoVA0gs8GDGeu3vEN614gN3NfyUAGFTClz61g=", + "size": 971 + }, + { + "type": "file", + "name": "walk.d.ts", + "hash": "lQsJOYxJZxLobTYn5gRgJJpxoBx42ABi/hLS30rTCQQ=", + "size": 482 + }, + { + "type": "file", + "name": "walk.js", + "hash": "O3GSAQ7+J1ETKRIf2d1gB6/r8ef1Ap6z0pHB3s7dN7s=", + "size": 555 + }, + { + "type": "file", + "name": "walk.mjs", + "hash": "d4kE/ieohzkyhmxdH1nAT2O4sR/BA4EUCFFBXJTvx2w=", + "size": 535 + } + ], + "links": { + "stats": "https://data.jsdelivr.com/v1/stats/packages/npm/empathic@2.0.0", + "entrypoints": "https://data.jsdelivr.com/v1/packages/npm/empathic@2.0.0/entrypoints" + } +} diff --git a/test/nuxt/a11y.spec.ts b/test/nuxt/a11y.spec.ts index 880daab411..0915d94d26 100644 --- a/test/nuxt/a11y.spec.ts +++ b/test/nuxt/a11y.spec.ts @@ -158,15 +158,21 @@ import { BuildEnvironment, ButtonBase, LandingIntroHeader, + NoodleArtemisLogo, NoodleKawaiiLogo, + NoodleTransgenderVisibilityLogo, + NoodleListCard, NoodleNodejsLogo, + NoodlePressLogo, NoodlePride1Logo, NoodlePride2Logo, + NoodleLens, NoodlePride3Logo, NoodleTetrisLogo, LinkBase, CallToAction, ChangelogCard, + ChangelogSkeleton, ChangelogErrorMsg, CodeDirectoryListing, CodeFileTree, @@ -201,7 +207,6 @@ import { OrgTeamsPanel, PackageAccessControls, PackageCard, - PackageChartModal, PackageClaimPackageModal, PackageCompatibility, PackageDependencies, @@ -378,12 +383,30 @@ describe('component accessibility audits', () => { expect(results.violations).toEqual([]) }) + it('should have no accessibility violations', async () => { + const component = await mountSuspended(NoodleTransgenderVisibilityLogo) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + + it('should have no accessibility violations', async () => { + const component = await mountSuspended(NoodlePressLogo) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + it('should have no accessibility violations', async () => { const component = await mountSuspended(NoodleNodejsLogo) const results = await runAxe(component) expect(results.violations).toEqual([]) }) + it('should have no accessibility violations', async () => { + const component = await mountSuspended(NoodleArtemisLogo) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + it('should have no accessibility violations', async () => { const component = await mountSuspended(NoodlePride1Logo) const results = await runAxe(component) @@ -407,6 +430,16 @@ describe('component accessibility audits', () => { const results = await runAxe(component) expect(results.violations).toEqual([]) }) + + it('should have no accessibility violations', async () => { + const component = await mountSuspended(NoodleLens, { + props: { + logo: NoodleKawaiiLogo, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) }) describe('AppFooter', () => { @@ -962,12 +995,12 @@ describe('component accessibility audits', () => { homepage: 'https://react.dev', repository: { type: 'git', - url: 'https://github.com/facebook/react.git', + url: 'https://github.com/react/react.git', }, bugs: { - url: 'https://github.com/facebook/react/issues', + url: 'https://github.com/react/react/issues', }, - funding: 'https://github.com/sponsors/facebook', + funding: 'https://github.com/facebook', dist: { shasum: 'abc123def456', tarball: 'https://registry.npmjs.org/react/-/react-18.2.0.tgz', @@ -1091,22 +1124,6 @@ describe('component accessibility audits', () => { // component has issues in the test environment (requires DOM measurements that aren't // available during SSR-like test mounting). - describe('PackageChartModal', () => { - it('should have no accessibility violations when closed', async () => { - const component = await mountSuspended(PackageChartModal, { - props: { open: false, title: 'Downloads' }, - slots: { default: '
Chart content
' }, - }) - const results = await runAxe(component) - expect(results.violations).toEqual([]) - }) - - // Note: Testing the open state is challenging because native .showModal() - // requires the element to be in the DOM and connected, which doesn't work well - // with the test environment's cloning approach. The dialog accessibility is - // inherently provided by the native element with aria-labelledby. - }) - describe('PackageTrendsChart', () => { const mockWeeklyDownloads = [ { @@ -1670,6 +1687,18 @@ describe('component accessibility audits', () => { const results = await runAxe(component) expect(results.violations).toEqual([]) }) + + it('should have no accessibility violations with import-link markup', async () => { + const component = await mountSuspended(CodeViewer, { + props: { + html: '
vite
', + lines: 1, + selectedLines: null, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) }) describe('CodeDirectoryListing', () => { @@ -2710,6 +2739,7 @@ describe('component accessibility audits', () => { id: 'a11y', title: '1.0.0', publishedAt: '2026-02-11 10:00:00.000Z', + link: 'https://github.com/nuxt/nuxt/releases/tag/v4.4.5', }, tocHeaderClass: 'toc', }, @@ -2718,6 +2748,12 @@ describe('component accessibility audits', () => { expect(results.violations).toEqual([]) }) + it('ChangelogSkeleton', async () => { + const component = await mountSuspended(ChangelogSkeleton) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + it('ChangelogErrorMsg should have no accessibility violations for warning variant', async () => { const component = await mountSuspended(ChangelogErrorMsg, { props: { @@ -2928,6 +2964,24 @@ describe('component accessibility audits', () => { }) }) + describe('NoodleListCard', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(NoodleListCard, { + props: { + noodle: { + key: 'press', + slug: 'press', + title: 'Press', + date: '2026-05-01', + dateTo: '2026-05-04', + }, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + describe('BlueskyComment', () => { it('should have no accessibility violations', async () => { const component = await mountSuspended(BlueskyComment, { diff --git a/test/nuxt/app/utils/header-version-matcher.spec.ts b/test/nuxt/app/utils/header-version-matcher.spec.ts new file mode 100644 index 0000000000..8bf28c78d5 --- /dev/null +++ b/test/nuxt/app/utils/header-version-matcher.spec.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest' +import { createHeadingVersionMatcher } from '~/utils/header-version-matcher' + +describe('createHeadingVersionMatcher', () => { + it('should only match version 3.5.1', () => { + const isMatching = createHeadingVersionMatcher('3.5.1') + + expect(isMatching('test-pkg@3.5.1')).toBe(true) + expect(isMatching('test-pkg: 3.5.1')).toBe(true) + expect(isMatching('v3.5.1 (2026-03-03)')).toBe(true) + expect(isMatching('3.5.1')).toBe(true) + expect(isMatching('3.5.1/3.5.2')).toBe(true) + expect(isMatching('v3.5.0/v3.5.1')).toBe(true) + + expect(isMatching('test-pkg@3.5.15')).toBe(false) + expect(isMatching('test-pkg: 3.5.15')).toBe(false) + expect(isMatching('v3.5.15 (2026-03-03)')).toBe(false) + expect(isMatching('3.5.15')).toBe(false) + expect(isMatching('3.5.12/3.5.20')).toBe(false) + expect(isMatching('3.5.9/3.5.10')).toBe(false) + }) +}) diff --git a/test/nuxt/components/CodeViewer.spec.ts b/test/nuxt/components/CodeViewer.spec.ts new file mode 100644 index 0000000000..7ea43a151e --- /dev/null +++ b/test/nuxt/components/CodeViewer.spec.ts @@ -0,0 +1,159 @@ +import { mountSuspended } from '@nuxt/test-utils/runtime' +import { nextTick } from 'vue' +import { afterEach, describe, expect, it, vi } from 'vitest' +import CodeViewer from '~/components/Code/Viewer.vue' + +const html = [ + '
',
+  'import { ref } from "vue"',
+  'const count = ref(0)',
+  'export { count }',
+  '
', +].join('') + +const updatedHtml = html.replace('const count = ref(0)', 'const counter = ref(0)') + +async function mountCodeViewer( + selectedLines: { start: number; end: number } | null = null, + componentHtml: string = html, +) { + return mountSuspended(CodeViewer, { + attachTo: document.body, + props: { + html: componentHtml, + lines: 3, + selectedLines, + }, + }) +} + +function getRenderedCodeLines(wrapper: Awaited>) { + const root = wrapper.element as HTMLElement + return Array.from(root.querySelectorAll('code > .line')) as HTMLElement[] +} + +describe('CodeViewer', () => { + afterEach(() => { + vi.restoreAllMocks() + document.body.innerHTML = '' + }) + + it('renders line numbers, highlights the selected range, and emits clicks', async () => { + const wrapper = await mountCodeViewer() + + try { + const lineNumbers = wrapper.findAll('.line-number') + expect(lineNumbers).toHaveLength(3) + expect(lineNumbers.map(line => line.text())).toEqual(['1', '2', '3']) + expect(wrapper.find('.line-numbers').attributes('style')).toContain('--line-digits: 1') + + await wrapper.setProps({ selectedLines: { start: 2, end: 3 } }) + await nextTick() + await vi.waitFor(() => { + const codeLines = getRenderedCodeLines(wrapper) + expect(codeLines[0]?.classList.contains('highlighted')).toBe(false) + expect(codeLines[1]?.classList.contains('highlighted')).toBe(true) + expect(codeLines[2]?.classList.contains('highlighted')).toBe(true) + }) + + expect(lineNumbers[0]?.classes()).toContain('text-fg-subtle') + expect(lineNumbers[1]?.classes()).toContain('bg-yellow-500/20') + expect(lineNumbers[2]?.classes()).toContain('bg-yellow-500/20') + + await lineNumbers[1]!.trigger('click') + expect(wrapper.emitted('lineClick')).toHaveLength(1) + expect(wrapper.emitted('lineClick')?.[0]?.[0]).toBe(2) + expect(wrapper.emitted('lineClick')?.[0]?.[1]).toBeInstanceOf(MouseEvent) + } finally { + wrapper.unmount() + } + }) + + it('updates highlighted lines when the selected range changes or clears', async () => { + const wrapper = await mountCodeViewer() + + try { + await wrapper.setProps({ selectedLines: { start: 1, end: 1 } }) + await nextTick() + await vi.waitFor(() => { + expect(getRenderedCodeLines(wrapper)[0]?.classList.contains('highlighted')).toBe(true) + }) + + await wrapper.setProps({ selectedLines: { start: 3, end: 3 } }) + await nextTick() + await vi.waitFor(() => { + const codeLines = getRenderedCodeLines(wrapper) + expect(codeLines[0]?.classList.contains('highlighted')).toBe(false) + expect(codeLines[1]?.classList.contains('highlighted')).toBe(false) + expect(codeLines[2]?.classList.contains('highlighted')).toBe(true) + }) + + await wrapper.setProps({ selectedLines: null }) + await nextTick() + await vi.waitFor(() => { + getRenderedCodeLines(wrapper).forEach(line => { + expect(line.classList.contains('highlighted')).toBe(false) + }) + }) + } finally { + wrapper.unmount() + } + }) + + it('routes import-link clicks through vue-router and preserves modifier-assisted navigation', async () => { + const wrapper = await mountCodeViewer(null, updatedHtml) + + try { + const router = useRouter() + const pushSpy = vi.spyOn(router, 'push').mockImplementation(() => Promise.resolve()) + + await wrapper.setProps({ html }) + await nextTick() + const anchor = wrapper.find('a.import-link') + expect(anchor.exists()).toBe(true) + + const plainClick = new MouseEvent('click', { bubbles: true, cancelable: true }) + anchor.element.dispatchEvent(plainClick) + + expect(plainClick.defaultPrevented).toBe(true) + expect(pushSpy).toHaveBeenCalledWith('#package-vue') + + const ctrlClick = new MouseEvent('click', { bubbles: true, cancelable: true, ctrlKey: true }) + anchor.element.dispatchEvent(ctrlClick) + + expect(ctrlClick.defaultPrevented).toBe(false) + expect(pushSpy).toHaveBeenCalledTimes(1) + } finally { + wrapper.unmount() + } + }) + + it('ignores import-link clicks without an href', async () => { + const router = useRouter() + const pushSpy = vi.spyOn(router, 'push').mockImplementation(() => Promise.resolve()) + + const wrapper = await mountSuspended(CodeViewer, { + attachTo: document.body, + props: { + html: '
placeholder
', + lines: 1, + selectedLines: null, + }, + }) + + try { + await wrapper.setProps({ + html: '
missing href
', + }) + const anchor = wrapper.find('a.import-link') + await nextTick() + const click = new MouseEvent('click', { bubbles: true, cancelable: true }) + anchor.element.dispatchEvent(click) + + expect(click.defaultPrevented).toBe(false) + expect(pushSpy).not.toHaveBeenCalled() + } finally { + wrapper.unmount() + } + }) +}) diff --git a/test/nuxt/components/CommandPalette.spec.ts b/test/nuxt/components/CommandPalette.spec.ts index 3570d63ab4..3678730578 100644 --- a/test/nuxt/components/CommandPalette.spec.ts +++ b/test/nuxt/components/CommandPalette.spec.ts @@ -98,6 +98,17 @@ describe('CommandPalette', () => { expect(input?.getAttribute('aria-controls')).toBe('command-palette-modal-results') }) + it('shows keyboard shortcut hints in the command palette', async () => { + await mountPalette() + + const shortcuts = document.querySelector('[data-command-palette-keyboard-shortcuts="true"]') + + expect(shortcuts).not.toBeNull() + expect(shortcuts?.textContent).toContain('to navigate') + expect(shortcuts?.textContent).toContain('to select') + expect(shortcuts?.textContent).toContain('to close') + }) + it('updates the live region when the query changes', async () => { await mountPalette() diff --git a/test/nuxt/components/Package/Versions.spec.ts b/test/nuxt/components/Package/Versions.spec.ts index a1aa43c67c..ff8220391b 100644 --- a/test/nuxt/components/Package/Versions.spec.ts +++ b/test/nuxt/components/Package/Versions.spec.ts @@ -38,7 +38,8 @@ function isVersionLink(a: DOMWrapper): boolean { return ( !a.attributes('href')?.startsWith('#') && a.attributes('target') !== '_blank' && - !a.attributes('data-testid')?.includes('view-all-versions') + !a.attributes('data-testid')?.includes('view-distribution-link') && + !a.attributes('data-testid')?.includes('view-all-versions-link') ) } diff --git a/test/nuxt/components/compare/FacetSelector.spec.ts b/test/nuxt/components/compare/FacetSelector.spec.ts index 11904946c7..d90ee51c5a 100644 --- a/test/nuxt/components/compare/FacetSelector.spec.ts +++ b/test/nuxt/components/compare/FacetSelector.spec.ts @@ -33,6 +33,7 @@ const facetLabels: Record { }) describe('github metadata', () => { - it('fetches github stars and issues when repository is on github', async () => { + it('fetches github stars, forks, and issues when repository is on github', async () => { const pkgName = 'github-pkg' vi.stubGlobal( '$fetch', @@ -211,7 +211,7 @@ describe('usePackageComparison', () => { }) } if (fullUrl.includes('ungh.cc/repos/owner/repo')) { - return Promise.resolve({ repo: { stars: 1500 } }) + return Promise.resolve({ repo: { stars: 1500, forks: 100 } }) } if (fullUrl.includes('/api/github/issues/owner/repo')) { return Promise.resolve({ issues: 50 }) @@ -226,9 +226,11 @@ describe('usePackageComparison', () => { }) const stars = getFacetValues('githubStars')[0] + const forks = getFacetValues('githubForks')[0] const issues = getFacetValues('githubIssues')[0] expect(stars).toMatchObject({ raw: 1500, status: 'neutral' }) + expect(forks).toMatchObject({ raw: 100, status: 'neutral' }) expect(issues).toMatchObject({ raw: 50, status: 'neutral' }) }) @@ -266,6 +268,7 @@ describe('usePackageComparison', () => { }) expect(getFacetValues('githubStars')[0]).toBeNull() + expect(getFacetValues('githubForks')[0]).toBeNull() expect(getFacetValues('githubIssues')[0]).toBeNull() }) @@ -298,10 +301,132 @@ describe('usePackageComparison', () => { expect(fetchMock).not.toHaveBeenCalledWith(expect.stringContaining('/api/github/issues')) expect(getFacetValues('githubStars')[0]).toBeNull() + expect(getFacetValues('githubForks')[0]).toBeNull() expect(getFacetValues('githubIssues')[0]).toBeNull() }) }) + describe('custom version', () => { + it('fetches version-specific data when a version is pinned in the spec', async () => { + const requestedUrls: string[] = [] + vi.stubGlobal( + '$fetch', + vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => { + const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url + requestedUrls.push(fullUrl) + if (fullUrl.startsWith('https://registry.npmjs.org/')) { + return Promise.resolve({ + 'name': 'test-package', + 'dist-tags': { latest: '2.0.0' }, + 'time': { + 'modified': '2025-01-01T00:00:00.000Z', + '1.0.0': '2022-03-20T00:00:00.000Z', + '2.0.0': '2025-01-01T00:00:00.000Z', + }, + 'license': 'MIT', + 'versions': { + '1.0.0': { dist: { unpackedSize: 10000 } }, + '2.0.0': { dist: { unpackedSize: 20000 } }, + }, + }) + } + if (fullUrl.includes('/api/registry/install-size/')) { + return Promise.resolve({ selfSize: 1, totalSize: 2, dependencyCount: 3 }) + } + return Promise.resolve(null) + }), + ) + + const { packagesData, status, getFacetValues } = await usePackageComparisonInComponent([ + 'test-package@1.0.0', + ]) + + await vi.waitFor(() => { + expect(status.value).toBe('success') + }) + + // Uses the pinned version, not the latest dist-tag + expect(packagesData.value[0]?.package.version).toBe('1.0.0') + + // Version-specific metadata and size + expect(packagesData.value[0]?.metadata?.lastUpdated).toBe('2022-03-20T00:00:00.000Z') + expect(getFacetValues('packageSize')[0]?.raw).toBe(10000) + + // Version-aware endpoints are hit with the /v/ segment + expect(requestedUrls).toContainEqual( + expect.stringContaining('/api/registry/analysis/test-package/v/1.0.0'), + ) + expect(requestedUrls).toContainEqual( + expect.stringContaining('/api/registry/vulnerabilities/test-package/v/1.0.0'), + ) + await vi.waitFor(() => { + expect(requestedUrls).toContainEqual( + expect.stringContaining('/api/registry/install-size/test-package/v/1.0.0'), + ) + }) + }) + + it('resolves a dist-tag spec to its concrete version', async () => { + vi.stubGlobal( + '$fetch', + vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => { + const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url + if (fullUrl.startsWith('https://registry.npmjs.org/')) { + return Promise.resolve({ + 'name': 'test-package', + 'dist-tags': { latest: '1.0.0', next: '2.0.0-beta.1' }, + 'time': { + '1.0.0': '2024-01-01T00:00:00.000Z', + '2.0.0-beta.1': '2025-01-01T00:00:00.000Z', + }, + 'license': 'MIT', + 'versions': { + '1.0.0': { dist: { unpackedSize: 10000 } }, + '2.0.0-beta.1': { dist: { unpackedSize: 20000 } }, + }, + }) + } + return Promise.resolve(null) + }), + ) + + const { packagesData, status } = await usePackageComparisonInComponent(['test-package@next']) + + await vi.waitFor(() => { + expect(status.value).toBe('success') + }) + + expect(packagesData.value[0]?.package.version).toBe('2.0.0-beta.1') + }) + + it('returns null when the pinned version cannot be resolved', async () => { + vi.stubGlobal( + '$fetch', + vi.fn().mockImplementation((url: string, options?: { baseURL?: string }) => { + const fullUrl = options?.baseURL ? `${options.baseURL}${url}` : url + if (fullUrl.startsWith('https://registry.npmjs.org/')) { + return Promise.resolve({ + 'name': 'test-package', + 'dist-tags': { latest: '1.0.0' }, + 'versions': { + '1.0.0': { dist: { unpackedSize: 10000 } }, + }, + }) + } + return Promise.resolve(null) + }), + ) + + const { packagesData, status } = await usePackageComparisonInComponent(['test-package@9.9.9']) + + await vi.waitFor(() => { + expect(status.value).toBe('success') + }) + + expect(packagesData.value[0]).toBeNull() + }) + }) + describe('createdAt facet', () => { it('displays the creation date without status', async () => { const createdDate = '2020-01-01T00:00:00.000Z' diff --git a/test/unit/a11y-component-coverage.spec.ts b/test/unit/a11y-component-coverage.spec.ts index 1f5570aaa3..86f8371613 100644 --- a/test/unit/a11y-component-coverage.spec.ts +++ b/test/unit/a11y-component-coverage.spec.ts @@ -27,6 +27,7 @@ const SKIPPED_COMPONENTS: Record = { 'OgImage/BlogPost.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Compare.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Package.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', + 'OgImage/Noodle.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Page.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Profile.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Splash.takumi.vue': 'OG Image component - server-rendered image, not interactive UI', @@ -55,10 +56,11 @@ const SKIPPED_COMPONENTS: Record = { 'SkeletonBlock.vue': 'Already covered indirectly via other component tests', 'SkeletonInline.vue': 'Already covered indirectly via other component tests', 'Button/Group.vue': "Wrapper component, tests wouldn't make much sense here", - 'Changelog/Releases.vue': 'Requires API calls', - 'Changelog/Markdown.vue': 'Requires API call & only renders markdown html', + 'Changelog/Releases.vue': 'Requires API calls & only renders ChangelogCard components in a list', + 'Changelog/Markdown.vue': 'Requires API call & mostly renders markdown html', 'Translation/StatusByFile.unused.vue': 'Unused component, might be needed in the future', 'ColorScheme/Img.vue': 'Image component, basic ui', + 'VideoPlayer.vue': 'Atproto video component, basic ui', } function normalizeComponentPath(filePath: string): string { diff --git a/test/unit/app/composables/use-chart-tooltip-position.spec.ts b/test/unit/app/composables/use-chart-tooltip-position.spec.ts deleted file mode 100644 index 70429da797..0000000000 --- a/test/unit/app/composables/use-chart-tooltip-position.spec.ts +++ /dev/null @@ -1,122 +0,0 @@ -import type { computed } from 'vue' -import { ref, shallowRef } from 'vue' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { useChartTooltipPosition } from '~/composables/useChartTooltipPosition' - -const mouseState = vi.hoisted(() => ({ - target: null as unknown, -})) - -const elementX = ref(0) -const elementWidth = ref(0) -const isOutside = ref(true) - -const MockHTMLElement = class { - public readonly nodeType = 1 -} - -vi.stubGlobal('HTMLElement', MockHTMLElement) - -afterEach(() => { - vi.unstubAllGlobals() -}) - -vi.mock('@vueuse/core', () => ({ - useMouseInElement: vi.fn(target => { - mouseState.target = target - - return { - elementX, - elementWidth, - isOutside, - } - }), -})) - -describe('useChartTooltipPosition', () => { - beforeEach(() => { - vi.stubGlobal('HTMLElement', MockHTMLElement) - elementX.value = 0 - elementWidth.value = 0 - isOutside.value = true - mouseState.target = null - }) - - it('returns center when the mouse is outside', () => { - const element = new MockHTMLElement() as HTMLElement - const position = useChartTooltipPosition(shallowRef(element)) - - isOutside.value = true - elementWidth.value = 100 - elementX.value = 75 - - expect(position.value).toBe('center') - }) - - it('returns center when element width is 0', () => { - const element = new MockHTMLElement() as HTMLElement - const position = useChartTooltipPosition(shallowRef(element)) - isOutside.value = false - elementWidth.value = 0 - elementX.value = 75 - expect(position.value).toBe('center') - }) - - it('returns left when the mouse is on the right half of the element', () => { - const element = new MockHTMLElement() as HTMLElement - const position = useChartTooltipPosition(shallowRef(element)) - isOutside.value = false - elementWidth.value = 100 - elementX.value = 51 - expect(position.value).toBe('left') - }) - - it('returns right when the mouse is on the left half of the element', () => { - const element = new MockHTMLElement() as HTMLElement - const position = useChartTooltipPosition(shallowRef(element)) - isOutside.value = false - elementWidth.value = 100 - elementX.value = 49 - expect(position.value).toBe('right') - }) - - it('returns right when the mouse is exactly at the center', () => { - const element = new MockHTMLElement() as HTMLElement - const position = useChartTooltipPosition(shallowRef(element)) - isOutside.value = false - elementWidth.value = 100 - elementX.value = 50 - expect(position.value).toBe('right') - }) - - it('accepts a Vue component ref exposing $el', () => { - const element = new MockHTMLElement() as HTMLElement - const componentReference = shallowRef({ $el: element }) - useChartTooltipPosition(componentReference) - expect((mouseState.target as ReturnType).value).toBe(element) - }) - - it('returns null as target when ref value is null', () => { - useChartTooltipPosition(shallowRef(null)) - expect((mouseState.target as ReturnType).value).toBe(null) - }) - - it('returns null when component ref has no $el', () => { - const componentReference = shallowRef({}) - useChartTooltipPosition(componentReference) - expect((mouseState.target as ReturnType).value).toBe(null) - }) - - it('uses the HTMLElement directly as target', () => { - const element = new MockHTMLElement() as HTMLElement - useChartTooltipPosition(shallowRef(element)) - expect((mouseState.target as ReturnType).value).toBe(element) - }) - - it('uses the component $el as target', () => { - const element = new MockHTMLElement() as HTMLElement - const componentReference = shallowRef({ $el: element }) - useChartTooltipPosition(componentReference) - expect((mouseState.target as ReturnType).value).toBe(element) - }) -}) diff --git a/test/unit/app/utils/charts.spec.ts b/test/unit/app/utils/charts.spec.ts index ae2ff47593..bd5ff80513 100644 --- a/test/unit/app/utils/charts.spec.ts +++ b/test/unit/app/utils/charts.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import { sum, chunkIntoWeeks, @@ -13,7 +13,6 @@ import { copyAltTextForVersionsBarChart, createAltTextForTimelineChart, copyAltTextForTimelineChart, - loadFile, sanitise, insertLineBreaks, applyEllipsis, @@ -1278,57 +1277,6 @@ describe('copyAltTextForTimelineChart', () => { }) }) -describe('loadFile', () => { - let createElementMock: ReturnType - let clickMock: ReturnType - let removeMock: ReturnType - let originalDocument: typeof globalThis.document | undefined - - beforeEach(() => { - clickMock = vi.fn() - removeMock = vi.fn() - - createElementMock = vi.fn().mockReturnValue({ - href: '', - download: '', - click: clickMock, - remove: removeMock, - }) - - originalDocument = globalThis.document - - Object.defineProperty(globalThis, 'document', { - value: { - createElement: createElementMock, - }, - configurable: true, - writable: true, - }) - }) - - afterEach(() => { - vi.restoreAllMocks() - - Object.defineProperty(globalThis, 'document', { - value: originalDocument, - configurable: true, - writable: true, - }) - }) - - it('creates an anchor element and triggers a download', () => { - const link = 'https://npmx.dev/file.png' - const filename = 'file.png' - loadFile(link, filename) - expect(createElementMock).toHaveBeenCalledWith('a') - const anchor = createElementMock.mock.results[0]?.value as HTMLAnchorElement - expect(anchor.href).toBe(link) - expect(anchor.download).toBe(filename) - expect(clickMock).toHaveBeenCalledTimes(1) - expect(removeMock).toHaveBeenCalledTimes(1) - }) -}) - describe('sanitise', () => { it('returns the same string when no sanitisation is needed', () => { expect(sanitise('nuxt-package')).toBe('nuxt-package') diff --git a/test/unit/app/utils/date.spec.ts b/test/unit/app/utils/date.spec.ts index 34517e6aa3..ee17fb377f 100644 --- a/test/unit/app/utils/date.spec.ts +++ b/test/unit/app/utils/date.spec.ts @@ -1,5 +1,15 @@ -import { describe, expect, it } from 'vitest' -import { addDays, DAY_MS, daysInMonth, daysInYear, parseIsoDate, toIsoDate } from '~/utils/date' +import { describe, expect, it, vi } from 'vitest' +import { + addDays, + DAY_MS, + daysInMonth, + daysInYear, + parseIsoDate, + toIsoDate, + getEffectiveEndDateIso, + isLastDayOfMonth, + isLastDayOfYear, +} from '~/utils/date' describe('DAY_MS', () => { it('equals 86 400 000', () => { @@ -89,3 +99,76 @@ describe('daysInYear', () => { expect(daysInYear(2000)).toBe(366) }) }) + +describe('getEffectiveEndDateIso', () => { + it('returns the provided end date when present', () => { + expect(getEffectiveEndDateIso('2026-05-31')).toBe('2026-05-31') + }) + + it('returns yesterday in UTC when no end date is provided', () => { + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-06-01T12:00:00.000Z')) + + expect(getEffectiveEndDateIso()).toBe('2026-05-31') + + vi.useRealTimers() + }) + + it('handles UTC month boundaries', () => { + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-03-01T00:30:00.000Z')) + + expect(getEffectiveEndDateIso()).toBe('2026-02-28') + + vi.useRealTimers() + }) + + it('handles UTC year boundaries', () => { + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-01-01T00:30:00.000Z')) + + expect(getEffectiveEndDateIso()).toBe('2025-12-31') + + vi.useRealTimers() + }) +}) + +describe('isLastDayOfMonth', () => { + it('returns true for the last day of a 31-day month', () => { + expect(isLastDayOfMonth('2026-01-31')).toBe(true) + }) + + it('returns true for the last day of a 30-day month', () => { + expect(isLastDayOfMonth('2026-04-30')).toBe(true) + }) + + it('returns true for February 29 in a leap year', () => { + expect(isLastDayOfMonth('2024-02-29')).toBe(true) + }) + + it('returns true for February 28 in a non-leap year', () => { + expect(isLastDayOfMonth('2023-02-28')).toBe(true) + }) + + it('returns false when the date is not the last day of the month', () => { + expect(isLastDayOfMonth('2026-05-30')).toBe(false) + }) +}) + +describe('isLastDayOfYear', () => { + it('returns true for December 31', () => { + expect(isLastDayOfYear('2026-12-31')).toBe(true) + }) + + it('returns false for any other day in December', () => { + expect(isLastDayOfYear('2026-12-30')).toBe(false) + }) + + it('returns false for the last day of a month that is not December', () => { + expect(isLastDayOfYear('2026-11-30')).toBe(false) + }) + + it('returns true for leap years on December 31', () => { + expect(isLastDayOfYear('2024-12-31')).toBe(true) + }) +}) diff --git a/test/unit/server/utils/changelog/markdown.spec.ts b/test/unit/server/utils/changelog/markdown.spec.ts new file mode 100644 index 0000000000..05302f3277 --- /dev/null +++ b/test/unit/server/utils/changelog/markdown.spec.ts @@ -0,0 +1,542 @@ +import type { MarkdownRepoInfo } from '~~/server/utils/changelog/markdown' +import { describe, expect, it, vi, beforeAll } from 'vitest' + +// testing changelog specific needs, others things are tested at ../readme.spec.ts + +beforeAll(() => { + vi.stubGlobal( + 'getShikiHighlighter', + vi.fn().mockResolvedValue({ + getLoadedLanguages: () => [], + codeToHtml: (code: string) => `
${code}
`, + }), + ) + vi.stubGlobal( + 'useRuntimeConfig', + vi.fn().mockReturnValue({ + imageProxySecret: 'test-secret-for-readme-tests', + }), + ) +}) + +const { changelogRenderer } = await import('#server/utils/changelog/markdown') + +function changelogMdinfo(): MarkdownRepoInfo { + return { + blobBaseUrl: `https://github.com/test-owner/test-repo/blob/HEAD`, + rawBaseUrl: `https://raw.githubusercontent.com/test-owner/test-repo/HEAD`, + } +} + +function changelogMdInfoWithPath() { + return { + blobBaseUrl: `https://github.com/test-owner/test-repo/blob/HEAD`, + rawBaseUrl: `https://raw.githubusercontent.com/test-owner/test-repo/HEAD`, + path: 'packages/test/changelog.md', + } +} + +describe('URL Resolution', () => { + describe('resolves from /markdown.md & releases', () => { + it('resolves relative .md links to blob URL for rendered viewing', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Contributing](./CONTRIBUTING.md)` + const result = renderer(markdown) + + expect(result.html).toContain( + `href="https://github.com/test-owner/test-repo/blob/HEAD/CONTRIBUTING.md"`, + ) + }) + + it('resolves without ./ or / .md links to blob URL', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Guide](GUIDE.MD)` + const result = renderer(markdown) + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/GUIDE.MD"', + ) + }) + + it('resolves absolute .md links to blob URL', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Security](/SECURITY.MD)` + + const result = renderer(markdown) + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/SECURITY.MD"', + ) + }) + + it('resolves nested relative .md links to blob URL', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[API Docs](./docs/api/reference.md)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/docs/api/reference.md"', + ) + }) + + it('resolves relative .md links with query strings to blob URL', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[FAQ](./FAQ.md?ref=main)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/FAQ.md?ref=main"', + ) + }) + + it('resolves relative .md links with anchors to blob URL', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Install Section](./CONTRIBUTING.md#installation)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/CONTRIBUTING.md#installation"', + ) + }) + + it('resolves non-.md files to raw URL (not blob)', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Image](./assets/logo.png)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://raw.githubusercontent.com/test-owner/test-repo/HEAD/assets/logo.png"', + ) + }) + + it('resolves to the root when going to far back', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[License](../../../LICENSE)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://raw.githubusercontent.com/test-owner/test-repo/HEAD/LICENSE"', + ) + }) + }) + + describe('resolves from a deeper changelog.md', () => { + it('resolves relative .md links to blob URL for rendered viewing', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[Contributing](./CONTRIBUTING.md)` + const result = renderer(markdown) + + expect(result.html).toContain( + `href="https://github.com/test-owner/test-repo/blob/HEAD/packages/test/CONTRIBUTING.md"`, + ) + }) + + it('resolves without ./ or / .md links to a relative blob URL', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[Guide](GUIDE.MD)` + const result = renderer(markdown) + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/packages/test/GUIDE.MD"', + ) + }) + + it('resolves absolute .md links to blob URL', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[Security](/SECURITY.MD)` + + const result = renderer(markdown) + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/SECURITY.MD"', + ) + }) + + it('resolves nested relative .md links to blob URL', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[API Docs](./docs/api/reference.md)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/packages/test/docs/api/reference.md"', + ) + }) + + it('resolves relative .md links with query strings to blob URL', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[FAQ](./FAQ.md?ref=main)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/packages/test/FAQ.md?ref=main"', + ) + }) + + it('resolves relative .md links with anchors to blob URL', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[Install Section](./CONTRIBUTING.md#installation)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://github.com/test-owner/test-repo/blob/HEAD/packages/test/CONTRIBUTING.md#installation"', + ) + }) + + it('resolves non-.md files to raw URL (not blob)', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[Image](./assets/logo.png)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://raw.githubusercontent.com/test-owner/test-repo/HEAD/packages/test/assets/logo.png"', + ) + }) + + it('resolves to the root when going to far back', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[License](../../../LICENSE)` + const result = renderer(markdown) + + expect(result.html).toContain( + 'href="https://raw.githubusercontent.com/test-owner/test-repo/HEAD/LICENSE"', + ) + }) + }) + + describe('resolves full urls', () => { + it('leaves absolute .md URLs unchanged', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `[External Guide](https://example.com/guide.md)` + const result = renderer(markdown) + expect(result.html).toContain('href="https://example.com/guide.md"') + }) + + it('leaves absolute non-.md URLs unchanged', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Docs](https://docs.example.com/)` + const result = renderer(markdown) + expect(result.html).toContain('href="https://docs.example.com/"') + }) + }) + + describe('anchor links', () => { + describe('for changelog.md', () => { + it('prefixes anchor links with user-content-', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + + const markdown = `[Jump to section](#installation)` + const result = renderer(markdown) + + expect(result.html).toContain('href="#user-content-installation"') + }) + + it('normalizes mixed-case heading fragments to lowercase slugs', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Associations section](#Associations)` + const result = renderer(markdown) + + expect(result.html).toContain('href="#user-content-associations"') + }) + }) + + describe('for releases', () => { + it('prefixes anchor links with user-content-', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + + const markdown = `[Jump to section](#installation)` + const result = renderer(markdown, '123456789') + + expect(result.html).toContain('href="#user-content-123456789-installation"') + }) + + it('normalizes mixed-case heading fragments to lowercase slugs', async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `[Associations section](#Associations)` + const result = renderer(markdown, 123456789) + + expect(result.html).toContain('href="#user-content-123456789-associations"') + }) + }) + }) + + describe('npm.js urls', () => { + it('redirects npmjs.com urls to local', async () => { + const markdown = `[Some npmjs.com link](https://www.npmjs.com/package/test-pkg)` + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const result = renderer(markdown) + + expect(result.html).toContain('href="/package/test-pkg"') + }) + + it('redirects npmjs.com urls to local (no www and http)', async () => { + const markdown = `[Some npmjs.com link](http://npmjs.com/package/test-pkg)` + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const result = renderer(markdown) + + expect(result.html).toContain('href="/package/test-pkg"') + }) + + it('does not redirect npmjs.com to local if they are in the list of exceptions', async () => { + const markdown = `[Root Contributing](https://www.npmjs.com/products)` + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const result = renderer(markdown) + + expect(result.html).toContain('href="https://www.npmjs.com/products"') + }) + + it('redirects npmjs.org urls to local', async () => { + const markdown = `[Some npmjs.org link](https://www.npmjs.org/package/test-pkg)` + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const result = renderer(markdown) + + expect(result.html).toContain('href="/package/test-pkg"') + }) + + it('redirects npmjs.org urls to local (no www and http)', async () => { + const markdown = `[Some npmjs.org link](http://npmjs.org/package/test-pkg)` + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const result = renderer(markdown) + + expect(result.html).toContain('href="/package/test-pkg"') + }) + }) +}) + +describe('Heading & toc resolution', () => { + describe('for markdown.md headings', () => { + it('should resolve heading starting from h2 & return to h3 at depth 2 correctly', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `# Vue +##v3 +###v3.5 +#### v3.5.33 +##### Features +###### Notes +##v2 +###v2.7 +#### v2.7.15 +##### Bug fixes +###### Notes` + const result = renderer(markdown) + + expect(result.html) + .toBe(`

Vue

+

v3

+

v3.5

+
v3.5.33
+
Features
+
Notes
+

v2

+

v2.7

+
v2.7.15
+
Bug fixes
+
Notes
+`) + expect(result.toc).toEqual([ + { + depth: 1, + id: 'user-content-vue', + text: 'Vue', + }, + { + depth: 2, + id: 'user-content-v3', + text: 'v3', + }, + { + depth: 3, + id: 'user-content-v35', + text: 'v3.5', + }, + { + depth: 4, + id: 'user-content-v3533', + text: 'v3.5.33', + }, + { + depth: 5, + id: 'user-content-features', + text: 'Features', + }, + { + depth: 6, + id: 'user-content-notes', + text: 'Notes', + }, + { + depth: 2, + id: 'user-content-v2', + text: 'v2', + }, + { + depth: 3, + id: 'user-content-v27', + text: 'v2.7', + }, + { + depth: 4, + id: 'user-content-v2715', + text: 'v2.7.15', + }, + { + depth: 5, + id: 'user-content-bug-fixes', + text: 'Bug fixes', + }, + { + depth: 6, + id: 'user-content-notes-1', + text: 'Notes', + }, + ]) + }) + }) + + describe('for releases headings', () => { + it('should resolve heading starting from h3 & return to h4 at depth 2 correctly', async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = `# Vue +##v3 +###v3.5 +#### v3.5.33 +##### Features +###### Notes +##v2 +###v2.7 +#### v2.7.15 +##### Bug fixes +###### Notes` + const result = renderer(markdown, 123456789) + + expect(result.html) + .toBe(`

Vue

+

v3

+
v3.5
+
v3.5.33
+
Features
+
Notes
+

v2

+
v2.7
+
v2.7.15
+
Bug fixes
+
Notes
+`) + expect(result.toc).toEqual([ + { + depth: 1, + id: 'user-content-123456789-vue', + text: 'Vue', + }, + { + depth: 2, + id: 'user-content-123456789-v3', + text: 'v3', + }, + { + depth: 3, + id: 'user-content-123456789-v35', + text: 'v3.5', + }, + { + depth: 4, + id: 'user-content-123456789-v3533', + text: 'v3.5.33', + }, + { + depth: 5, + id: 'user-content-123456789-features', + text: 'Features', + }, + { + depth: 6, + id: 'user-content-123456789-notes', + text: 'Notes', + }, + { + depth: 2, + id: 'user-content-123456789-v2', + text: 'v2', + }, + { + depth: 3, + id: 'user-content-123456789-v27', + text: 'v2.7', + }, + { + depth: 4, + id: 'user-content-123456789-v2715', + text: 'v2.7.15', + }, + { + depth: 5, + id: 'user-content-123456789-bug-fixes', + text: 'Bug fixes', + }, + { + depth: 6, + id: 'user-content-123456789-notes-1', + text: 'Notes', + }, + ]) + }) + }) + + it("shouldn't resolve package@version to an email", async () => { + const info = changelogMdInfoWithPath() + const renderer = await changelogRenderer(info) + const markdown = '## test-pkg@1.0.0' + const result = renderer(markdown) + + expect(result.html).toBe( + '

test-pkg@1.0.0

\n', + ) + }) +}) + +describe('ATX heading #issue/#pr exemption', () => { + it("shouldn't turn issues/PRs into headings", async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `#2869 hello + +#2717 world` + + const result = renderer(markdown) + expect(result.html).toBe('

#2869 hello

\n

#2717 world

\n') + }) + + it("shouldn't turn issues/PRs in list into headings", async () => { + const info = changelogMdinfo() + const renderer = await changelogRenderer(info) + const markdown = `- #2869 hello +- #2717 world` + + const result = renderer(markdown) + expect(result.html).toBe('
    \n
  • #2869 hello
  • \n
  • #2717 world
  • \n
\n') + }) +}) diff --git a/test/unit/server/utils/code-highlight.spec.ts b/test/unit/server/utils/code-highlight.spec.ts index c57edef1e2..6408b13288 100644 --- a/test/unit/server/utils/code-highlight.spec.ts +++ b/test/unit/server/utils/code-highlight.spec.ts @@ -1,5 +1,16 @@ -import { describe, expect, it } from 'vitest' -import { linkifyModuleSpecifiers } from '#server/utils/code-highlight' +import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest' +import { + getLanguageFromPath, + highlightCode, + linkifyModuleSpecifiers, +} from '#server/utils/code-highlight' + +const mockGetShikiHighlighter = vi.fn() + +beforeAll(() => { + vi.stubGlobal('escapeRawGt', (html: string) => html) + vi.stubGlobal('getShikiHighlighter', mockGetShikiHighlighter) +}) describe('linkifyModuleSpecifiers', () => { const dependencies = { @@ -38,4 +49,226 @@ describe('linkifyModuleSpecifiers', () => { '', ) }) + + it('prefers file-aware resolver for self package subpath imports', () => { + const html = + '' + + 'import' + + ' * as walk ' + + 'from' + + ' "empathic/walk"' + + '' + + const result = linkifyModuleSpecifiers(html, { + dependencies, + resolveRelative: specifier => + specifier.includes('empathic/walk') ? '/package-code/empathic/v/2.0.0/walk.mjs' : null, + }) + + expect(result).toContain( + '"empathic/walk"', + ) + }) + + it('linkifies when spacing around "from" varies across tokens', () => { + const html = + '' + + 'import' + + ' * as walk ' + + 'from ' + + '"empathic/walk"' + + '' + + const result = linkifyModuleSpecifiers(html, { + resolveRelative: specifier => + specifier.includes('empathic/walk') ? '/package-code/empathic/v/2.0.0/walk.mjs' : null, + }) + + expect(result).toContain( + '"empathic/walk"', + ) + }) + + it('falls back to dependency links when the file-aware resolver cannot resolve a specifier', () => { + const html = + '' + + 'import' + + ' "vue"' + + '' + + const result = linkifyModuleSpecifiers(html, { + dependencies, + resolveRelative: () => null, + }) + + expect(result).toContain('"vue"') + }) + + it('linkifies side-effect imports even when import token spacing varies', () => { + const html = + '' + + ' import ' + + ' "@unocss/webpack" ' + + '' + + const result = linkifyModuleSpecifiers(html, { dependencies }) + + expect(result).toContain( + '"@unocss/webpack"', + ) + }) + + it('does not link Node built-ins or package specifiers when they are not dependencies', () => { + const htmlFrom = `from "fs"` + const htmlSide = + ' import ' + + ' "node:path" ' + + expect(linkifyModuleSpecifiers(htmlFrom, { dependencies: {} })).toBe(htmlFrom) + expect(linkifyModuleSpecifiers(htmlSide, { dependencies: {} })).toBe(htmlSide) + + const unknown = + 'from' + + ' "not-in-deps"' + const linked = linkifyModuleSpecifiers(unknown, { dependencies: {} }) + expect(linked).toContain('"not-in-deps"') + }) + + it('linkifies require() and dynamic import() calls', () => { + const requireHtml = + '' + + 'require' + + '(' + + '\'vue\'' + + '' + + const dynImportHtml = + '' + + 'import' + + '(' + + '"vue"' + + '' + + const deps = { vue: { version: '3.4.0' } } + + expect(linkifyModuleSpecifiers(requireHtml, { dependencies: deps })).toContain( + '\'vue\'', + ) + expect(linkifyModuleSpecifiers(dynImportHtml, { dependencies: deps })).toContain( + '"vue"', + ) + }) + + it('still links import() when the keyword is split across adjacent spans (e.g. dyn+import)', () => { + const html = + '' + + 'dynimport' + + '(' + + "'vue'" + + '' + + const linked = linkifyModuleSpecifiers(html, { dependencies: { vue: { version: '3.4.0' } } }) + expect(linked).toContain('') + }) +}) + +describe('getLanguageFromPath', () => { + it('prefers well-known filenames over extension heuristics', () => { + expect(getLanguageFromPath('foo/README.md')).toBe('markdown') + expect(getLanguageFromPath('nested/tsconfig.json')).toBe('jsonc') + expect(getLanguageFromPath('.gitignore')).toBe('bash') + expect(getLanguageFromPath('pnpm-lock.yaml')).toBe('yaml') + }) + + it('maps extensions and falls back to plain text', () => { + expect(getLanguageFromPath('src/a.ts')).toBe('typescript') + expect(getLanguageFromPath('src/b.vue')).toBe('vue') + expect(getLanguageFromPath('notes.mdx')).toBe('markdown') + expect(getLanguageFromPath('weird.unknownext')).toBe('text') + }) +}) + +describe('highlightCode', () => { + afterEach(() => { + mockGetShikiHighlighter.mockReset() + }) + + it('collapses newline gaps between Shiki line spans', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['typescript'], + codeToHtml: () => + '
const x = 1;\nconsole.log(x)
', + }) + + const html = await highlightCode('const x = 1;\nconsole.log(x)', 'typescript') + expect(html).not.toContain('\n') + expect(html).toContain('') + }) + + it('wraps lines manually when Shiki output omits .line spans', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['typescript'], + codeToHtml: () => + '
line-a\nline-b
', + }) + + const html = await highlightCode('line-a\nline-b', 'typescript') + expect(html).toContain('line-a') + expect(html).toContain('line-b') + }) + + it('runs linkify when the loaded language is import-aware', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['javascript'], + codeToHtml: () => + '
' +
+        '' +
+        'import foo from "vue"' +
+        '
', + }) + + const html = await highlightCode('import foo from "vue"', 'javascript', { + dependencies: { vue: { version: '3.4.0' } }, + }) + expect(html).toContain('/package-code/vue/v/3.4.0') + }) + + it('does not treat markdown as an import-linking language', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['markdown'], + codeToHtml: () => + '
' +
+        'import x from "vue"' +
+        '
', + }) + + const html = await highlightCode('import x from "vue"', 'markdown', { + dependencies: { vue: { version: '3.4.0' } }, + }) + expect(html).not.toContain('import-link') + }) + + it('falls back to escaped wrappers when the language is not loaded', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['typescript'], + codeToHtml: () => '', + }) + + const html = await highlightCode('a < b', 'not-a-real-lang', {}) + expect(html).toContain('<') + expect(html).toContain('') + expect(html).toContain('github-dark') + }) + + it('falls back when Shiki throws while highlighting', async () => { + mockGetShikiHighlighter.mockResolvedValue({ + getLoadedLanguages: () => ['typescript'], + codeToHtml: () => { + throw new Error('shiki failed') + }, + }) + + const html = await highlightCode('hello', 'typescript', {}) + expect(html).toContain('hello') + }) }) diff --git a/test/unit/server/utils/download-evolution.spec.ts b/test/unit/server/utils/download-evolution.spec.ts new file mode 100644 index 0000000000..85a6400b6e --- /dev/null +++ b/test/unit/server/utils/download-evolution.spec.ts @@ -0,0 +1,264 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import type { EvolutionOptions } from '~/types/chart' +import { + buildDailyEvolution, + buildMonthlyEvolution, + buildWeeklyEvolution, + buildYearlyEvolution, +} from '~/utils/chart-data-buckets' +import { fetchDownloadsEvolution } from '#server/utils/download-evolution' + +vi.mock('~/utils/chart-data-buckets', () => ({ + buildDailyEvolution: vi.fn(), + buildMonthlyEvolution: vi.fn(), + buildWeeklyEvolution: vi.fn(), + buildYearlyEvolution: vi.fn(), +})) + +const buildDailyEvolutionMock = vi.mocked(buildDailyEvolution) +const buildMonthlyEvolutionMock = vi.mocked(buildMonthlyEvolution) +const buildWeeklyEvolutionMock = vi.mocked(buildWeeklyEvolution) +const buildYearlyEvolutionMock = vi.mocked(buildYearlyEvolution) + +beforeEach(() => { + vi.clearAllMocks() + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-06-01T12:00:00.000Z')) + + vi.stubGlobal( + '$fetch', + vi.fn(async () => ({ + downloads: [ + { day: '2026-05-30', downloads: 30 }, + { day: '2026-05-29', downloads: 20 }, + { day: '2026-05-31', downloads: 40 }, + ], + })), + ) + + buildDailyEvolutionMock.mockReturnValue('daily-result' as never) + buildWeeklyEvolutionMock.mockReturnValue('weekly-result' as never) + buildMonthlyEvolutionMock.mockReturnValue('monthly-result' as never) + buildYearlyEvolutionMock.mockReturnValue('yearly-result' as never) +}) + +afterEach(() => { + vi.useRealTimers() + vi.unstubAllGlobals() +}) + +describe('fetchDownloadsEvolution', () => { + it('fetches the last 30 days by default and builds daily evolution', async () => { + const result = await fetchDownloadsEvolution('vue', { + granularity: 'day', + } as EvolutionOptions) + + expect(result).toBe('daily-result') + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-05-02:2026-05-31/vue', + ) + expect(buildDailyEvolutionMock).toHaveBeenCalledWith([ + { day: '2026-05-29', value: 20 }, + { day: '2026-05-30', value: 30 }, + { day: '2026-05-31', value: 40 }, + ]) + }) + + it('uses explicit startDate and endDate when provided', async () => { + const result = await fetchDownloadsEvolution('@scope/pkg', { + granularity: 'week', + startDate: '2026-01-01T10:30:00.000Z', + endDate: '2026-01-31T18:45:00.000Z', + } as EvolutionOptions) + + expect(result).toBe('weekly-result') + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-01-01:2026-01-31/%40scope%2Fpkg', + ) + expect(buildWeeklyEvolutionMock).toHaveBeenCalledWith( + [ + { day: '2026-05-29', value: 20 }, + { day: '2026-05-30', value: 30 }, + { day: '2026-05-31', value: 40 }, + ], + '2026-01-01', + '2026-01-31', + ) + }) + + it('builds monthly evolution from the configured month window', async () => { + const result = await fetchDownloadsEvolution('nuxt', { + granularity: 'month', + months: 3, + } as EvolutionOptions) + + expect(result).toBe('monthly-result') + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-03-01:2026-05-31/nuxt', + ) + expect(buildMonthlyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2026-03-01', + '2026-05-31', + ) + }) + + it('builds yearly evolution from the package creation year', async () => { + const result = await fetchDownloadsEvolution( + 'react', + { + granularity: 'year', + } as EvolutionOptions, + '2013-05-29T00:00:00.000Z', + ) + + expect(result).toBe('yearly-result') + expect($fetch).toHaveBeenCalledTimes(10) + expect($fetch).toHaveBeenNthCalledWith( + 1, + 'https://api.npmjs.org/downloads/range/2013-01-01:2014-06-24/react', + ) + expect($fetch).toHaveBeenNthCalledWith( + 10, + 'https://api.npmjs.org/downloads/range/2026-04-23:2026-05-31/react', + ) + expect(buildYearlyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2013-01-01', + '2026-05-31', + ) + }) + + it('splits large ranges into npm-compatible chunks and merges the results', async () => { + await fetchDownloadsEvolution('vue', { + granularity: 'year', + startDate: '2024-01-01', + endDate: '2026-05-31', + } as EvolutionOptions) + + expect($fetch).toHaveBeenCalledTimes(2) + expect($fetch).toHaveBeenNthCalledWith( + 1, + 'https://api.npmjs.org/downloads/range/2024-01-01:2025-06-23/vue', + ) + expect($fetch).toHaveBeenNthCalledWith( + 2, + 'https://api.npmjs.org/downloads/range/2025-06-24:2026-05-31/vue', + ) + }) + + it('accepts ISO datetime strings for startDate and endDate', async () => { + await fetchDownloadsEvolution('vue', { + granularity: 'day', + startDate: '2026-05-01T12:34:56.000Z', + endDate: '2026-05-31T23:59:59.999Z', + } as EvolutionOptions) + + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-05-01:2026-05-31/vue', + ) + }) + + it('falls back to the default 5-year window for yearly ranges without packageCreatedIso', async () => { + await fetchDownloadsEvolution('react', { + granularity: 'year', + } as EvolutionOptions) + + expect($fetch).toHaveBeenCalledTimes(4) + + expect($fetch).toHaveBeenNthCalledWith( + 1, + 'https://api.npmjs.org/downloads/range/2021-06-02:2022-11-23/react', + ) + + expect($fetch).toHaveBeenNthCalledWith( + 4, + 'https://api.npmjs.org/downloads/range/2025-11-08:2026-05-31/react', + ) + + expect(buildYearlyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2021-06-02', + '2026-05-31', + ) + }) + + it('uses a 12 month window by default for monthly evolution', async () => { + await fetchDownloadsEvolution('nuxt', { + granularity: 'month', + } as EvolutionOptions) + + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2025-06-01:2026-05-31/nuxt', + ) + + expect(buildMonthlyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2025-06-01', + '2026-05-31', + ) + }) + + it('uses a 52 week window by default for weekly evolution', async () => { + await fetchDownloadsEvolution('vue', { + granularity: 'week', + } as EvolutionOptions) + + expect(buildWeeklyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2025-06-02', + '2026-05-31', + ) + }) + + it('uses packageCreatedIso when resolving a yearly range without startDate', async () => { + await fetchDownloadsEvolution( + 'react', + { + granularity: 'year', + endDate: '2013-12-31', + } as EvolutionOptions, + '2013-05-29T00:00:00.000Z', + ) + + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2013-01-01:2013-12-31/react', + ) + + expect(buildYearlyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2013-01-01', + '2013-12-31', + ) + }) + + it('ignores invalid date formats', async () => { + await fetchDownloadsEvolution('vue', { + granularity: 'day', + startDate: 'not-a-date', + } as EvolutionOptions) + + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-05-02:2026-05-31/vue', + ) + }) + + it('uses the configured week window when granularity is week', async () => { + const result = await fetchDownloadsEvolution('vue', { + granularity: 'week', + weeks: 4, + } as EvolutionOptions) + + expect(result).toBe('weekly-result') + + expect($fetch).toHaveBeenCalledWith( + 'https://api.npmjs.org/downloads/range/2026-05-04:2026-05-31/vue', + ) + + expect(buildWeeklyEvolutionMock).toHaveBeenCalledWith( + expect.any(Array), + '2026-05-04', + '2026-05-31', + ) + }) +}) diff --git a/test/unit/server/utils/embed-downloads-svg.spec.ts b/test/unit/server/utils/embed-downloads-svg.spec.ts new file mode 100644 index 0000000000..456758a652 --- /dev/null +++ b/test/unit/server/utils/embed-downloads-svg.spec.ts @@ -0,0 +1,718 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { createDownloadsSvgResponse } from '../../../../server/utils/embed-downloads-svg' + +const mocks = vi.hoisted(() => ({ + fetchDownloadsEvolution: vi.fn(), + buildTrendsChartData: vi.fn(), + buildNormalisedTrendsDataset: vi.fn(), + buildTrendsChartConfig: vi.fn(), + resolveEmbedChartColors: vi.fn(), + mergeConfigs: vi.fn(), + createStaticVueUiXy: vi.fn(), + generateWatermarkLogo: vi.fn(), + isLastDayOfMonth: vi.fn(), + getEffectiveEndDateIso: vi.fn(), + isLastDayOfYear: vi.fn(), +})) + +vi.mock('#server/utils/download-evolution', () => ({ + fetchDownloadsEvolution: mocks.fetchDownloadsEvolution, +})) + +vi.mock('#shared/utils/trends-chart', () => ({ + LOCALES_WITH_EXTRA_SPACE: ['fr', 'fr-FR'], + buildTrendsChartData: mocks.buildTrendsChartData, + buildNormalisedTrendsDataset: mocks.buildNormalisedTrendsDataset, + buildTrendsChartConfig: mocks.buildTrendsChartConfig, + generateWatermarkLogo: mocks.generateWatermarkLogo, +})) + +vi.mock('#shared/utils/embed-chart-colors', () => ({ + resolveEmbedChartColors: mocks.resolveEmbedChartColors, +})) + +vi.mock('vue-data-ui/utils', () => ({ + mergeConfigs: mocks.mergeConfigs, +})) + +vi.mock('vue-data-ui/ssr/vue-ui-xy', () => ({ + createStaticVueUiXy: mocks.createStaticVueUiXy, +})) + +vi.mock('~/utils/date', () => ({ + getEffectiveEndDateIso: mocks.getEffectiveEndDateIso, + isLastDayOfMonth: mocks.isLastDayOfMonth, + isLastDayOfYear: mocks.isLastDayOfYear, +})) + +vi.mock('~/utils/colors', () => ({ + OKLCH_NEUTRAL_FALLBACK: 'oklch-neutral-fallback', +})) + +function createEvolution(packageName: string) { + return [ + { + period: '2026-05-01', + downloads: packageName.length * 100, + }, + ] +} + +function createDataset(overrides: Record = {}) { + return [ + { + name: 'vue', + series: [10, 20], + dashIndices: undefined, + ...overrides, + }, + ] +} + +beforeEach(() => { + vi.clearAllMocks() + + mocks.fetchDownloadsEvolution.mockImplementation(async (packageName: string) => + createEvolution(packageName), + ) + + mocks.resolveEmbedChartColors.mockReturnValue({ + fg: '#111111', + bg: '#ffffff', + fgMuted: '#666666', + fgSubtle: '#999999', + }) + + mocks.buildTrendsChartData.mockReturnValue({ + dates: ['2026-05-01', '2026-05-02'], + dataset: createDataset(), + }) + + mocks.buildNormalisedTrendsDataset.mockReturnValue(createDataset()) + + mocks.buildTrendsChartConfig.mockReturnValue({ + chart: { + base: true, + }, + }) + + mocks.mergeConfigs.mockImplementation(({ defaultConfig, userConfig }) => ({ + defaultConfig, + userConfig, + })) + + mocks.generateWatermarkLogo.mockReturnValue('') + mocks.getEffectiveEndDateIso.mockReturnValue('2026-05-31') + mocks.isLastDayOfMonth.mockReturnValue(true) + mocks.isLastDayOfYear.mockReturnValue(true) + + mocks.createStaticVueUiXy.mockImplementation(async options => { + options.additionalSvgContent({ + drawingArea: { + bottom: 300, + }, + series: [ + { + plots: [ + { + x: 100, + y: 50, + value: 1200, + }, + ], + }, + { + plots: [], + }, + ], + }) + + return '' + }) +}) + +describe('downloads SVG embed response', () => { + it('throws 400 when no valid package name is provided', async () => { + await expect(createDownloadsSvgResponse({})).rejects.toMatchObject({ + statusCode: 400, + statusMessage: 'Missing package name. Use ?package=nuxt or ?packages=vite,rolldown', + }) + }) + + it('throws 501 for likes metric', async () => { + await expect( + createDownloadsSvgResponse({ + package: 'vue', + metric: 'likes', + }), + ).rejects.toMatchObject({ + statusCode: 501, + }) + }) + + it('throws 501 for contributors metric', async () => { + await expect( + createDownloadsSvgResponse({ + package: 'vue', + metric: 'contributors', + }), + ).rejects.toMatchObject({ + statusCode: 501, + }) + }) + + it('renders an SVG response for a single package', async () => { + const result = await createDownloadsSvgResponse({ + package: 'vue', + }) + + expect(result).toBe('') + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith('vue', { + granularity: 'week', + weeks: 52, + months: 12, + startDate: undefined, + endDate: undefined, + }) + }) + + it('supports multiple packages from the packages query', async () => { + await createDownloadsSvgResponse({ + packages: 'Vue, @Nuxt/Kit, invalid package, React', + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledTimes(3) + expect(mocks.fetchDownloadsEvolution).toHaveBeenNthCalledWith(1, 'vue', expect.any(Object)) + expect(mocks.fetchDownloadsEvolution).toHaveBeenNthCalledWith( + 2, + '@nuxt/kit', + expect.any(Object), + ) + expect(mocks.fetchDownloadsEvolution).toHaveBeenNthCalledWith(3, 'react', expect.any(Object)) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + packageNames: ['vue', '@nuxt/kit', 'react'], + isMultiPackageMode: true, + }), + ) + }) + + it('limits package names to 8 entries', async () => { + await createDownloadsSvgResponse({ + packages: 'a,b,c,d,e,f,g,h,i,j', + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledTimes(8) + }) + + it.each([ + ['daily', 'day', 'daily'], + ['day', 'day', 'daily'], + ['weekly', 'week', 'weekly'], + ['week', 'week', 'weekly'], + ['monthly', 'month', 'monthly'], + ['month', 'month', 'monthly'], + ['yearly', 'year', 'yearly'], + ['year', 'year', 'yearly'], + ])('parses granularity %s', async (queryGranularity, fetchGranularity, chartGranularity) => { + await createDownloadsSvgResponse({ + package: 'vue', + granularity: queryGranularity, + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith( + 'vue', + expect.objectContaining({ + granularity: fetchGranularity, + }), + ) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + selectedGranularity: chartGranularity, + displayedGranularity: chartGranularity, + }), + ) + }) + + it('clamps width, height, weeks, and months', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + width: 99999, + height: 1, + weeks: 99999, + months: 0, + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith( + 'vue', + expect.objectContaining({ + weeks: 260, + months: 1, + }), + ) + + expect(mocks.mergeConfigs).toHaveBeenCalledWith( + expect.objectContaining({ + userConfig: expect.objectContaining({ + chart: expect.objectContaining({ + width: 1600, + height: 240, + }), + }), + }), + ) + }) + + it('uses fallback dimensions and periods for invalid numeric query values', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + width: 'nope', + height: 'nope', + weeks: 'nope', + months: 'nope', + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith( + 'vue', + expect.objectContaining({ + weeks: 52, + months: 12, + }), + ) + + expect(mocks.mergeConfigs).toHaveBeenCalledWith( + expect.objectContaining({ + userConfig: expect.objectContaining({ + chart: expect.objectContaining({ + width: 900, + height: 420, + }), + }), + }), + ) + }) + + it('parses valid dates and ignores invalid dates', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + start: 'invalid', + endDate: '2026-05-31', + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith( + 'vue', + expect.objectContaining({ + startDate: undefined, + endDate: '2026-05-31', + }), + ) + }) + + it('uses startDate and end aliases', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + startDate: '2026-01-01', + end: '2026-05-31', + }) + + expect(mocks.fetchDownloadsEvolution).toHaveBeenCalledWith( + 'vue', + expect.objectContaining({ + startDate: '2026-01-01', + endDate: '2026-05-31', + }), + ) + }) + + it('uses dark colors when mode is dark', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + mode: 'dark', + }) + + expect(mocks.resolveEmbedChartColors).toHaveBeenCalledWith('dark') + }) + + it('uses light colors by default', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + expect(mocks.resolveEmbedChartColors).toHaveBeenCalledWith('light') + }) + + it('uses a valid locale', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + locale: 'fr-FR', + }) + + const chartDataOptions = mocks.buildTrendsChartData.mock.calls[0]![0] + expect(chartDataOptions.compactNumberFormatter.resolvedOptions().locale).toBe('fr-FR') + }) + + it('falls back to en for invalid locale', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + locale: 'not a locale', + }) + + const chartDataOptions = mocks.buildTrendsChartData.mock.calls[0]![0] + expect(chartDataOptions.compactNumberFormatter.resolvedOptions().locale).toBe('en') + }) + + it('uses an identity translation function for chart data', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const chartDataOptions = mocks.buildTrendsChartData.mock.calls[0]![0] + + expect(chartDataOptions.t('downloads')).toBe('downloads') + }) + + it('sanitizes yLabel', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + yLabel: '&"`\u0000', + }) + + const userConfig = mocks.mergeConfigs.mock.calls[0]![0].userConfig + expect(userConfig.chart.grid.labels.axis.yLabel).toBe('Downloads') + }) + + it('uses fallback yLabel for non-string values', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + yLabel: 123, + }) + + const userConfig = mocks.mergeConfigs.mock.calls[0]![0].userConfig + expect(userConfig.chart.grid.labels.axis.yLabel).toBe('') + }) + + it('accepts hex accent colors', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + accent: '#abc', + }) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + accent: '#abc', + }), + ) + }) + + it('accepts oklch accent colors', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + accent: 'oklch(0.787 0.128 230.318)', + }) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + accent: 'oklch(0.787 0.128 230.318)', + }), + ) + }) + + it('falls back for invalid accent colors', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + accent: 'red', + }) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + accent: 'oklch-neutral-fallback', + }), + ) + }) + + it('falls back for non-string accent colors', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + accent: 42, + }) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + accent: 'oklch-neutral-fallback', + }), + ) + }) + + it('throws 404 when chart dataset is empty', async () => { + mocks.buildTrendsChartData.mockReturnValue({ + dates: [], + dataset: [], + }) + + await expect( + createDownloadsSvgResponse({ + package: 'vue', + }), + ).rejects.toMatchObject({ + statusCode: 404, + statusMessage: 'No chart dataset generated', + }) + }) + + it('throws 404 when normalized dataset is empty', async () => { + mocks.buildNormalisedTrendsDataset.mockReturnValue([]) + + await expect( + createDownloadsSvgResponse({ + package: 'vue', + }), + ).rejects.toMatchObject({ + statusCode: 404, + statusMessage: 'No normalized dataset generated', + }) + }) + + it('adds a dash index to the last monthly point when the effective end date is not the last day of month', async () => { + mocks.isLastDayOfMonth.mockReturnValue(false) + mocks.getEffectiveEndDateIso.mockReturnValue('2026-05-12') + mocks.buildNormalisedTrendsDataset.mockReturnValue([ + { + name: 'vue', + series: [10, 20, 30], + dashIndices: [0, 2], + }, + ]) + + await createDownloadsSvgResponse({ + package: 'vue', + granularity: 'month', + endDate: '2026-05-12', + }) + + expect(mocks.createStaticVueUiXy).toHaveBeenCalledWith( + expect.objectContaining({ + dataset: [ + expect.objectContaining({ + dashIndices: [0, 2], + }), + ], + }), + ) + }) + + it('filters negative dash index for empty monthly series', async () => { + mocks.isLastDayOfMonth.mockReturnValue(false) + mocks.buildNormalisedTrendsDataset.mockReturnValue([ + { + name: 'vue', + series: [], + }, + ]) + + await createDownloadsSvgResponse({ + package: 'vue', + granularity: 'month', + }) + + expect(mocks.createStaticVueUiXy).toHaveBeenCalledWith( + expect.objectContaining({ + dataset: [ + expect.objectContaining({ + dashIndices: [], + }), + ], + }), + ) + }) + + it('keeps dash indices unchanged outside incomplete monthly data', async () => { + mocks.buildNormalisedTrendsDataset.mockReturnValue([ + { + name: 'vue', + series: [10, 20], + dashIndices: [1], + }, + ]) + + await createDownloadsSvgResponse({ + package: 'vue', + }) + + expect(mocks.createStaticVueUiXy).toHaveBeenCalledWith( + expect.objectContaining({ + dataset: [ + expect.objectContaining({ + dashIndices: [1], + }), + ], + }), + ) + }) + + it('generates extra SVG labels and watermark content', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const options = mocks.createStaticVueUiXy.mock.calls[0]![0] + const content = options.additionalSvgContent({ + drawingArea: { + bottom: 300, + }, + series: [ + { + plots: [ + { + x: 100, + y: 50, + value: 1200, + }, + ], + }, + { + plots: [], + }, + ], + }) + + expect(content).toContain('') + expect(mocks.generateWatermarkLogo).toHaveBeenCalledWith({ + x: 12, + y: 360, + width: 80, + height: 30, + fill: '#999999', + }) + }) + + it('falls back to an empty singleEvolution when the first package has no evolution', async () => { + mocks.fetchDownloadsEvolution.mockImplementation(async (packageName: string) => { + if (packageName === 'vue') { + return undefined + } + + return createEvolution(packageName) + }) + + await createDownloadsSvgResponse({ + package: 'vue', + }) + + expect(mocks.buildTrendsChartData).toHaveBeenCalledWith( + expect.objectContaining({ + singleEvolution: [], + }), + ) + + expect(mocks.buildTrendsChartConfig).toHaveBeenCalledWith( + expect.objectContaining({ + singleEvolution: [], + }), + ) + }) + + it('uses an identity translation function for chart config', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const chartConfigOptions = mocks.buildTrendsChartConfig.mock.calls[0]![0] + + expect(chartConfigOptions.t('downloads')).toBe('downloads') + }) + + it('formats the last plot value in additionalSvgContent', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const options = mocks.createStaticVueUiXy.mock.calls[0]![0] + + const content = options.additionalSvgContent({ + drawingArea: { + bottom: 300, + }, + series: [ + { + plots: [ + { + x: 10, + y: 20, + value: 1234, + }, + ], + }, + ], + }) + + expect(content).toContain('1.2K') + }) + + it('falls back to 0 when the last plot value is missing', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const options = mocks.createStaticVueUiXy.mock.calls[0]![0] + + const content = options.additionalSvgContent({ + drawingArea: { + bottom: 300, + }, + series: [ + { + plots: [ + { + x: 10, + y: 20, + value: undefined, + }, + ], + }, + ], + }) + + expect(content).toContain('0') + }) + + it('falls back to en when canonical locales returns an empty array', async () => { + const spy = vi.spyOn(Intl, 'getCanonicalLocales').mockReturnValue([]) + + await createDownloadsSvgResponse({ + package: 'vue', + locale: 'fr', + }) + + const chartDataOptions = mocks.buildTrendsChartData.mock.calls[0]![0] + + expect(chartDataOptions.compactNumberFormatter.resolvedOptions().locale).toBe('en') + + spy.mockRestore() + }) + + it('handles series without plots', async () => { + await createDownloadsSvgResponse({ + package: 'vue', + }) + + const options = mocks.createStaticVueUiXy.mock.calls[0]![0] + + const content = options.additionalSvgContent({ + drawingArea: { + bottom: 300, + }, + series: [ + { + plots: undefined, + }, + ], + }) + + expect(content).toContain('') + expect(content).not.toContain(' vi.fn()) + +vi.mock('node:dns/promises', () => ({ + lookup: dnsLookupMock, +})) + import { isTrustedImageDomain, isAllowedImageUrl, @@ -122,13 +129,17 @@ describe('Image Proxy Utils', () => { }) describe('resolveAndValidateHost', () => { + afterEach(() => { + dnsLookupMock.mockReset() + }) + it('allows URLs with publicly-resolvable hostnames', async () => { - // example.com resolves to a public IP + dnsLookupMock.mockResolvedValue([{ address: '93.184.215.14', family: 4 }]) expect(await resolveAndValidateHost('https://example.com/image.png')).toBe(true) }) it('blocks URLs with hostnames that resolve to loopback', async () => { - // localhost resolves to 127.0.0.1 + dnsLookupMock.mockResolvedValue([{ address: '127.0.0.1', family: 4 }]) expect(await resolveAndValidateHost('http://localhost/image.png')).toBe(false) }) @@ -143,6 +154,7 @@ describe('Image Proxy Utils', () => { }) it('blocks hostnames that fail DNS resolution', async () => { + dnsLookupMock.mockRejectedValue(new Error('ENOTFOUND')) expect( await resolveAndValidateHost( 'http://this-domain-definitely-does-not-exist.invalid/img.png', diff --git a/test/unit/server/utils/import-resolver.spec.ts b/test/unit/server/utils/import-resolver.spec.ts index 6bf0a4f8c2..7f872d5b25 100644 --- a/test/unit/server/utils/import-resolver.spec.ts +++ b/test/unit/server/utils/import-resolver.spec.ts @@ -3,7 +3,11 @@ import type { PackageFileTree } from '#shared/types' import { createImportResolver, flattenFileTree, + resolveAliasToDir, + resolvePackageSelfImport, + resolveInternalImport, resolveRelativeImport, + type InternalImportTarget, } from '#server/utils/import-resolver' describe('flattenFileTree', () => { @@ -48,6 +52,55 @@ describe('flattenFileTree', () => { expect(files.has('index.js')).toBe(true) expect(files.has('cli.js')).toBe(true) }) + + it('ignores directory nodes without children', () => { + const tree: PackageFileTree[] = [ + { name: 'empty', path: 'empty', type: 'directory', children: undefined }, + { name: 'readme.md', path: 'readme.md', type: 'file', size: 1 }, + ] + + const files = flattenFileTree(tree) + + expect(files.has('readme.md')).toBe(true) + expect(files.has('empty')).toBe(false) + }) +}) + +describe('resolveAliasToDir', () => { + it('returns the deepest matching alias directory', () => { + expect(resolveAliasToDir('#app', './src/app/generated/app/index.js')).toBe( + './src/app/generated/app', + ) + }) + + it('returns the full path for root aliases', () => { + expect(resolveAliasToDir('#', './src/app/index.js')).toBe('./src/app/index.js') + }) + + it('returns null when the alias does not match a path segment', () => { + expect(resolveAliasToDir('#components', './src/app/index.js')).toBeNull() + }) + + it('returns null for unsupported alias prefixes', () => { + expect(resolveAliasToDir('components', './src/components/index.js')).toBeNull() + }) + + it('returns null when filePath is missing', () => { + expect(resolveAliasToDir('#app', null)).toBeNull() + expect(resolveAliasToDir('#app', undefined)).toBeNull() + }) + + it('normalizes #/foo style aliases', () => { + expect(resolveAliasToDir('#/dist', 'root/dist/pkg/index.js')).toBe('root/dist') + }) + + it('normalizes $/foo style aliases', () => { + expect(resolveAliasToDir('$/dist', 'root/dist/pkg/index.js')).toBe('root/dist') + }) + + it('returns null when the file path trims to empty', () => { + expect(resolveAliasToDir('#', '///')).toBeNull() + }) }) describe('resolveRelativeImport', () => { @@ -148,6 +201,27 @@ describe('resolveRelativeImport', () => { expect(resolved).toBeNull() }) + + it('uses default extension priority for non-js/ts sources such as .vue', () => { + const files = new Set(['src/helper.ts', 'src/helper.js']) + const resolved = resolveRelativeImport('./helper', 'src/Component.vue', files) + + expect(resolved?.path).toBe('src/helper.ts') + }) + + it('prefers declaration peers when resolving from .d.mts', () => { + const files = new Set(['types/mod.d.mts']) + const resolved = resolveRelativeImport('./mod', 'types/index.d.mts', files) + + expect(resolved?.path).toBe('types/mod.d.mts') + }) + + it('resolves jsx shims when matching a tsx source and only jsx exists on disk', () => { + const files = new Set(['ui/Box.jsx']) + const resolved = resolveRelativeImport('./Box', 'ui/App.tsx', files) + + expect(resolved?.path).toBe('ui/Box.jsx') + }) }) describe('createImportResolver', () => { @@ -177,4 +251,415 @@ describe('createImportResolver', () => { expect(url).toBe('/package-code/@scope/pkg/v/1.2.3/dist/utils.js') }) + + it('resolves package imports aliases to code browser URLs', () => { + const files = new Set(['dist/app/nuxt.js']) + const resolver = createImportResolver(files, 'dist/index.js', 'nuxt', '4.3.1', { + '#app/nuxt': './dist/app/nuxt.js', + }) + + const url = resolver('#app/nuxt') + + expect(url).toBe('/package-code/nuxt/v/4.3.1/dist/app/nuxt.js') + }) + + it('resolves self package subpath imports to code browser URLs', () => { + const files = new Set(['find.mjs', 'walk.mjs']) + const resolver = createImportResolver(files, 'find.mjs', 'empathic', '2.0.0', undefined, { + './walk': { import: './walk.mjs' }, + }) + + const url = resolver('empathic/walk') + + expect(url).toBe('/package-code/empathic/v/2.0.0/walk.mjs') + }) +}) + +describe('resolveInternalImport', () => { + it('resolves exact imports map matches to files in the package', () => { + const files = new Set(['dist/app/nuxt.js']) + + const resolved = resolveInternalImport( + '#app/nuxt', + 'dist/index.js', + { + '#app/nuxt': './dist/app/nuxt.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/nuxt.js') + }) + + it('supports import condition objects', () => { + const files = new Set(['dist/app/nuxt.js']) + + const resolved = resolveInternalImport( + '#app/nuxt', + 'dist/index.js', + { + '#app/nuxt': { import: './dist/app/nuxt.js' }, + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/nuxt.js') + }) + + it('returns null when the target file does not exist', () => { + const files = new Set(['dist/app/index.js']) + + const resolved = resolveInternalImport( + '#app/nuxt', + 'dist/index.js', + { + '#app/nuxt': './dist/app/nuxt.js', + }, + files, + ) + + expect(resolved).toBeNull() + }) + + it('resolves prefix matches with extension resolution via guessInternalImportTarget', () => { + const files = new Set(['dist/app/components/button.js']) + + const resolved = resolveInternalImport( + '#app/components/button.js', + 'dist/index.js', + { + '#app': './dist/app/index.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/button.js') + }) + + it('resolves file that could not found in the files', () => { + const files = new Set(['dist/app/index.js']) + + const resolved = resolveInternalImport( + '#app/components/button.js', + 'dist/index.js', + { + '#app': './dist/app/index.js', + }, + files, + ) + + expect(resolved).toBeNull() + }) + + it('resolves file that prefix is "~/"', () => { + const files = new Set(['dist/app/components/button.js']) + + const resolved = resolveInternalImport( + '~/app/components/button.js', + 'dist/index.js', + { + '~/app': './dist/app/index.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/button.js') + }) + + it('resolves file that prefix is "@/"', () => { + const files = new Set(['dist/app/components/button.js']) + + const resolved = resolveInternalImport( + '@/app/components/button.js', + 'dist/index.js', + { + '@/app': './dist/app/index.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/button.js') + }) + + it('resolves file that prefix is "$/"', () => { + const files = new Set(['dist/app/components/button.js']) + + const resolved = resolveInternalImport( + '$/app/components/button.js', + 'dist/index.js', + { + '$/app': './dist/app/index.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/button.js') + }) + + it('resolves guessed alias targets to directory index files', () => { + const files = new Set(['dist/app/components/index.js']) + + const resolved = resolveInternalImport( + '#app/components', + 'dist/index.js', + { + '#app': './dist/app/index.js', + }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/index.js') + }) + + it('infers extensions for exact import map targets without a file suffix', () => { + const files = new Set(['src/a.ts']) + + const resolved = resolveInternalImport('#token', 'index.ts', { '#token': './src/a' }, files) + + expect(resolved?.path).toBe('src/a.ts') + }) + + it('returns null when imports map is missing', () => { + const files = new Set(['dist/a.js']) + + expect(resolveInternalImport('#x', 'dist/index.js', undefined, files)).toBeNull() + }) + + it('returns null when specifier is not an internal alias style', () => { + const files = new Set(['dist/a.js']) + + expect( + resolveInternalImport('lodash', 'dist/index.js', { '#a': './dist/a.js' }, files), + ).toBeNull() + }) + + it('returns null when the mapped target is not package-relative', () => { + const files = new Set([]) + + const resolved = resolveInternalImport( + '#pkg', + 'index.js', + { '#pkg': '/absolute/outside.js' }, + files, + ) + + expect(resolved).toBeNull() + }) + + it('returns null for guessed paths with extension-like segments that do not exist', () => { + const files = new Set(['dist/app/index.js']) + + const resolved = resolveInternalImport( + '#app/missing.vue', + 'dist/index.js', + { '#app': './dist/app/index.js' }, + files, + ) + + expect(resolved).toBeNull() + }) + + it('strips quotes from internal specifiers before resolving', () => { + const files = new Set(['dist/app/nuxt.js']) + + const resolved = resolveInternalImport( + "'#app/nuxt'", + 'dist/index.js', + { '#app/nuxt': './dist/app/nuxt.js' }, + files, + ) + + expect(resolved?.path).toBe('dist/app/nuxt.js') + }) + + it('falls back to default import condition when import field is absent', () => { + const files = new Set(['dist/legacy.js']) + + const resolved = resolveInternalImport( + '#legacy', + 'dist/index.js', + { '#legacy': { default: './dist/legacy.js' } }, + files, + ) + + expect(resolved?.path).toBe('dist/legacy.js') + }) + + it('ignores non-string import map entries', () => { + const files = new Set(['dist/a.js']) + + const resolved = resolveInternalImport( + '#bad', + 'dist/index.js', + { '#bad': { import: 1 } as unknown as InternalImportTarget }, + files, + ) + + expect(resolved).toBeNull() + }) + + it('resolves #/ slash-variant specifier against a plain #app imports key', () => { + const files = new Set(['dist/app/components/Button.vue']) + + const resolved = resolveInternalImport( + '#/app/components/Button.vue', + 'dist/index.js', + { '#app': './dist/app/index.js' }, + files, + ) + + expect(resolved?.path).toBe('dist/app/components/Button.vue') + }) +}) + +describe('resolvePackageSelfImport', () => { + it('resolves the package root using the dot export', () => { + const files = new Set(['index.mjs']) + + const resolved = resolvePackageSelfImport( + 'empathic', + 'empathic', + { + '.': { import: './index.mjs' }, + }, + 'find.mjs', + files, + ) + + expect(resolved?.path).toBe('index.mjs') + }) + + it('resolves package self subpath imports using exports', () => { + const files = new Set(['find.mjs', 'walk.mjs']) + + const resolved = resolvePackageSelfImport( + 'empathic/walk', + 'empathic', + { + './walk': { import: './walk.mjs' }, + }, + 'find.mjs', + files, + ) + + expect(resolved?.path).toBe('walk.mjs') + }) + + it('resolves package self subpath imports to directory index files', () => { + const files = new Set(['walk/index.mjs']) + + const resolved = resolvePackageSelfImport( + 'empathic/walk', + 'empathic', + { + './walk': { import: './walk' }, + }, + 'find.mjs', + files, + ) + + expect(resolved?.path).toBe('walk/index.mjs') + }) + + it('returns null when the specifier is not for the current package', () => { + const files = new Set(['walk.mjs']) + + const resolved = resolvePackageSelfImport( + 'other-package/walk', + 'empathic', + { + './walk': { import: './walk.mjs' }, + }, + 'find.mjs', + files, + ) + + expect(resolved).toBeNull() + }) + + it('falls back to file-tree based self subpath resolution when exports are unavailable', () => { + const files = new Set(['find.mjs', 'walk.mjs']) + + const resolved = resolvePackageSelfImport( + 'empathic/walk', + 'empathic', + undefined, + 'find.mjs', + files, + ) + + expect(resolved?.path).toBe('walk.mjs') + }) + + it('returns null when neither exports nor fallback resolution can find a file', () => { + const files = new Set(['find.mjs']) + + const resolved = resolvePackageSelfImport( + 'empathic/missing', + 'empathic', + { + './missing': { import: './missing' }, + }, + 'find.mjs', + files, + ) + + expect(resolved).toBeNull() + }) + + it('uses the require export condition when import/default are absent', () => { + const files = new Set(['lib.node.cjs']) + + const resolved = resolvePackageSelfImport( + 'pkg/native', + 'pkg', + { './native': { require: './lib.node.cjs' } }, + 'index.js', + files, + ) + + expect(resolved?.path).toBe('lib.node.cjs') + }) + + it('uses the types export condition as a last resort', () => { + const files = new Set(['types.d.ts']) + + const resolved = resolvePackageSelfImport( + 'pkg/types', + 'pkg', + { './types': { types: './types.d.ts' } }, + 'index.d.ts', + files, + ) + + expect(resolved?.path).toBe('types.d.ts') + }) + + it('returns null when resolvePath rejects unsafe targets', () => { + const files = new Set(['secret.js']) + + const resolved = resolvePackageSelfImport( + 'pkg/leak', + 'pkg', + { './leak': { import: '../secret.js' } }, + 'index.js', + files, + ) + + expect(resolved).toBeNull() + }) + + it('strips quotes before normalizing self-import specifiers', () => { + const files = new Set(['walk.mjs']) + + const resolved = resolvePackageSelfImport( + "'empathic/walk'", + 'empathic', + { './walk': { import: './walk.mjs' } }, + 'find.mjs', + files, + ) + + expect(resolved?.path).toBe('walk.mjs') + }) }) diff --git a/test/unit/server/utils/readme.spec.ts b/test/unit/server/utils/readme.spec.ts index dacc2653b7..d24158d777 100644 --- a/test/unit/server/utils/readme.spec.ts +++ b/test/unit/server/utils/readme.spec.ts @@ -592,13 +592,13 @@ describe('HTML output', () => { }) describe('heading anchors (renderer.heading)', () => { - it('strips a full-line anchor wrapper and uses inner text for slug, toc, and permalink', async () => { + it('keeps the full-line anchor wrapper and places the link to the heading at the end', async () => { const markdown = '##
My Section' const result = await renderReadmeHtml(markdown, 'test-pkg') expect(result.toc).toEqual([{ text: 'My Section', depth: 2, id: 'user-content-my-section' }]) expect(result.html).toBe( - `

My Section

\n`, + `

My Section

\n`, ) }) @@ -610,7 +610,7 @@ describe('HTML output', () => { { text: 'See docs for more', depth: 3, id: 'user-content-see-docs-for-more' }, ]) expect(result.html).toBe( - `

See docs for more

\n`, + `

See docs for more

\n`, ) }) @@ -620,7 +620,7 @@ describe('HTML output', () => { expect(result.toc).toEqual([{ text: 'Guide: page', depth: 2, id: 'user-content-guide-page' }]) expect(result.html).toBe( - '

Guide: page

', + '

Guide: page

', ) }) }) diff --git a/test/unit/shared/utils/diff.spec.ts b/test/unit/shared/utils/diff.spec.ts new file mode 100644 index 0000000000..bdeecb2318 --- /dev/null +++ b/test/unit/shared/utils/diff.spec.ts @@ -0,0 +1,68 @@ +import { describe, expect, it } from 'vitest' +import { truncateDiffHunks } from '#shared/utils/diff' +import type { DiffHunk, DiffSkipBlock } from '#shared/types/compare' + +function createHunk(lineCount: number): DiffHunk { + return { + type: 'hunk', + content: '@@ -1,1 +1,1 @@', + oldStart: 1, + oldLines: lineCount, + newStart: 1, + newLines: lineCount, + lines: Array.from({ length: lineCount }, (_, index) => ({ + type: 'normal', + oldLineNumber: index + 1, + newLineNumber: index + 1, + content: [{ value: `line ${index + 1}`, type: 'normal' }], + })), + } +} + +describe('truncateDiffHunks', () => { + it('leaves hunks untouched when they fit within the line budget', () => { + const hunk = createHunk(2) + + const result = truncateDiffHunks([hunk], 3) + + expect(result.truncated).toBe(false) + expect(result.hunks).toEqual([hunk]) + }) + + it('truncates hunk lines when the line budget is exceeded', () => { + const result = truncateDiffHunks([createHunk(4)], 2) + + expect(result.truncated).toBe(true) + expect(result.hunks).toHaveLength(1) + expect(result.hunks[0]?.type).toBe('hunk') + expect((result.hunks[0] as DiffHunk).lines).toHaveLength(2) + }) + + it('does not count skip blocks against the line budget', () => { + const skip: DiffSkipBlock = { + type: 'skip', + count: 10, + content: '10 lines hidden', + } + + const result = truncateDiffHunks([skip, createHunk(2)], 1) + + expect(result.truncated).toBe(true) + expect(result.hunks[0]).toBe(skip) + expect((result.hunks[1] as DiffHunk).lines).toHaveLength(1) + }) + + it('does not append a skip block after the line budget is exhausted', () => { + const skip: DiffSkipBlock = { + type: 'skip', + count: 10, + content: '10 lines hidden', + } + const hunk = createHunk(1) + + const result = truncateDiffHunks([hunk, skip], 1) + + expect(result.truncated).toBe(true) + expect(result.hunks).toEqual([hunk]) + }) +}) diff --git a/test/unit/shared/utils/download-chart-last-label.spec.ts b/test/unit/shared/utils/download-chart-last-label.spec.ts new file mode 100644 index 0000000000..1923883816 --- /dev/null +++ b/test/unit/shared/utils/download-chart-last-label.spec.ts @@ -0,0 +1,294 @@ +import { describe, expect, it, vi } from 'vitest' +import { createLastDatapointLabelsSvg } from '#shared/utils/download-chart-last-label' + +const colors = { + foreground: '#000000', + background: '#FFFFFF', + fallbackSerieColor: '#999999', +} + +describe('createLastDatapointLabelsSvg', () => { + it('returns an empty string when there are no series', () => { + const result = createLastDatapointLabelsSvg({ + series: [], + drawingArea: { top: 10, height: 100 }, + colors, + formatValue: value => String(value), + isDarkMode: false, + }) + + expect(result).toBe('') + }) + + it('returns an empty string when no serie has plots', () => { + const result = createLastDatapointLabelsSvg({ + series: [{ color: '#FF0000' }, { color: '#00FF00', plots: [] }], + drawingArea: { top: 10, height: 100 }, + colors, + formatValue: value => String(value), + isDarkMode: false, + }) + + expect(result).toBe('') + }) + + it('renders regular labels when there is no collision', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 20, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 90, value: 20 }] }, + ], + drawingArea: { top: 0, height: 120 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain(' { + const result = createLastDatapointLabelsSvg({ + series: [{ plots: [{ x: 10, y: 20, value: 42 }] }], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + fontSize: 12, + labelOffset: 10, + }) + + expect(result).toContain('x="20"') + expect(result).toContain('font-size="12"') + expect(result).toContain('fill="#000000"') + expect(result).toContain('stroke="#FFFFFF"') + }) + + it('uses only the last plot of each serie', () => { + const formatValue = vi.fn((value: number) => `${value}`) + + const result = createLastDatapointLabelsSvg({ + series: [ + { + color: '#FF0000', + plots: [ + { x: 10, y: 10, value: 1 }, + { x: 50, y: 50, value: 99 }, + ], + }, + ], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue, + isDarkMode: false, + }) + + expect(formatValue).toHaveBeenCalledTimes(1) + expect(formatValue).toHaveBeenCalledWith(99) + expect(result).toContain('x="74"') + expect(result).toContain('y="50"') + expect(result).not.toContain('x="34"') + }) + + it('formats safe numeric values and falls back to zero for invalid values', () => { + const formatValue = vi.fn((value: number) => `value:${value}`) + + const result = createLastDatapointLabelsSvg({ + series: [{ plots: [{ x: 10, y: 20, value: Number.NaN }] }], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue, + isDarkMode: false, + }) + + expect(formatValue).toHaveBeenCalledWith(0) + expect(result).toContain('value:0') + }) + + it('renders collision labels as a compact non-overlapping label rack', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 50, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 55, value: 30 }] }, + { color: '#0000FF', plots: [{ x: 100, y: 60, value: 20 }] }, + ], + drawingArea: { top: 10, height: 120 }, + colors, + formatValue: value => `value-${value}`, + isDarkMode: false, + }) + + expect(result).toContain(' { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 50, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 55, value: 20 }] }, + ], + drawingArea: { top: 20, bottom: 120 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain('y="50"') + expect(result).toContain('y="80"') + }) + + it('keeps colliding labels close to their related points without overlapping', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 40, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 45, value: 20 }] }, + { color: '#0000FF', plots: [{ x: 100, y: 95, value: 30 }] }, + ], + drawingArea: { top: 0, height: 120 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain('y="40"') + expect(result).toContain('y="70"') + expect(result).toContain('y="100"') + }) + + it('shifts the label stack upward when it overflows the drawing area bottom', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 80, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 85, value: 20 }] }, + { color: '#0000FF', plots: [{ x: 100, y: 90, value: 30 }] }, + ], + drawingArea: { top: 0, height: 120 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain('y="45"') + expect(result).toContain('y="75"') + expect(result).toContain('y="105"') + }) + + it('uses dark-mode opacity in collision mode', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 50, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 50, value: 20 }] }, + ], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `${value}`, + isDarkMode: true, + }) + + expect(result).toContain('opacity="0.7"') + }) + + it('uses the fallback serie color when no color is provided', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { plots: [{ x: 100, y: 50, value: 10 }] }, + { plots: [{ x: 100, y: 50, value: 20 }] }, + ], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain('stroke="#999999"') + }) + + it('supports null plot values from SSR slot data', () => { + const result = createLastDatapointLabelsSvg({ + series: [{ plots: [{ x: 10, y: 20, value: null }] }], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `formatted:${value}`, + isDarkMode: false, + }) + + expect(result).toContain('formatted:0') + }) + + it('uses zero defaults when plot coordinates are nullish', () => { + const result = createLastDatapointLabelsSvg({ + series: [{ plots: [{ x: null, y: null, value: undefined }] }], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `value-${value}`, + isDarkMode: false, + }) + + expect(result).toContain('x="24"') + expect(result).toContain('y="0"') + expect(result).toContain('value-0') + }) + + it('uses zero drawing area height when neither height nor bottom is provided', () => { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 50, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 50, value: 20 }] }, + ], + drawingArea: { top: 20 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain('y="-45"') + expect(result).toContain('y="-15"') + }) + + it('renders a regular label when serie color is omitted', () => { + const result = createLastDatapointLabelsSvg({ + series: [{ plots: [{ x: 100, y: 50, value: 10 }] }], + drawingArea: { top: 0, height: 100 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + }) + + expect(result).toContain(' { + const result = createLastDatapointLabelsSvg({ + series: [ + { color: '#FF0000', plots: [{ x: 100, y: 50, value: 10 }] }, + { color: '#00FF00', plots: [{ x: 100, y: 50, value: 20 }] }, + ], + drawingArea: { top: 10, height: 110 }, + colors, + formatValue: value => `${value}`, + isDarkMode: false, + labelHeight: 20, + }) + + expect(result).toContain('y="50"') + expect(result).toContain('y="70"') + }) +}) diff --git a/test/unit/shared/utils/download-ranges.spec.ts b/test/unit/shared/utils/download-ranges.spec.ts new file mode 100644 index 0000000000..dbcb330f56 --- /dev/null +++ b/test/unit/shared/utils/download-ranges.spec.ts @@ -0,0 +1,134 @@ +import { describe, expect, it } from 'vitest' +import { + differenceInUtcDaysInclusive, + mergeDailyPoints, + splitIsoRangeIntoChunksInclusive, +} from '#shared/utils/download-ranges' + +describe('differenceInUtcDaysInclusive', () => { + it('returns 1 for the same start and end date', () => { + expect(differenceInUtcDaysInclusive('2026-05-31', '2026-05-31')).toBe(1) + }) + + it('counts both start and end dates inclusively', () => { + expect(differenceInUtcDaysInclusive('2026-05-01', '2026-05-31')).toBe(31) + }) + + it('handles ranges across month and year boundaries', () => { + expect(differenceInUtcDaysInclusive('2025-12-31', '2026-01-02')).toBe(3) + }) +}) + +describe('splitIsoRangeIntoChunksInclusive', () => { + it('returns a single chunk when total days is below the maximum', () => { + expect(splitIsoRangeIntoChunksInclusive('2026-05-01', '2026-05-10', 20)).toEqual([ + { + startIso: '2026-05-01', + endIso: '2026-05-10', + }, + ]) + }) + + it('returns a single chunk when total days equals the maximum', () => { + expect(splitIsoRangeIntoChunksInclusive('2026-05-01', '2026-05-10', 10)).toEqual([ + { + startIso: '2026-05-01', + endIso: '2026-05-10', + }, + ]) + }) + + it('splits a range into inclusive chunks', () => { + expect(splitIsoRangeIntoChunksInclusive('2026-05-01', '2026-05-10', 4)).toEqual([ + { + startIso: '2026-05-01', + endIso: '2026-05-04', + }, + { + startIso: '2026-05-05', + endIso: '2026-05-08', + }, + { + startIso: '2026-05-09', + endIso: '2026-05-10', + }, + ]) + }) + + it('splits ranges across month boundaries', () => { + expect(splitIsoRangeIntoChunksInclusive('2026-01-30', '2026-02-03', 2)).toEqual([ + { + startIso: '2026-01-30', + endIso: '2026-01-31', + }, + { + startIso: '2026-02-01', + endIso: '2026-02-02', + }, + { + startIso: '2026-02-03', + endIso: '2026-02-03', + }, + ]) + }) + + it('splits ranges across year boundaries', () => { + expect(splitIsoRangeIntoChunksInclusive('2025-12-30', '2026-01-02', 2)).toEqual([ + { + startIso: '2025-12-30', + endIso: '2025-12-31', + }, + { + startIso: '2026-01-01', + endIso: '2026-01-02', + }, + ]) + }) +}) + +describe('mergeDailyPoints', () => { + it('returns an empty array when there are no points', () => { + expect(mergeDailyPoints([])).toEqual([]) + }) + + it('sorts points by day', () => { + expect( + mergeDailyPoints([ + { day: '2026-05-03', value: 30 }, + { day: '2026-05-01', value: 10 }, + { day: '2026-05-02', value: 20 }, + ]), + ).toEqual([ + { day: '2026-05-01', value: 10 }, + { day: '2026-05-02', value: 20 }, + { day: '2026-05-03', value: 30 }, + ]) + }) + + it('merges duplicate days by summing their values', () => { + expect( + mergeDailyPoints([ + { day: '2026-05-02', value: 20 }, + { day: '2026-05-01', value: 10 }, + { day: '2026-05-02', value: 5 }, + { day: '2026-05-01', value: 15 }, + ]), + ).toEqual([ + { day: '2026-05-01', value: 25 }, + { day: '2026-05-02', value: 25 }, + ]) + }) + + it('preserves negative and zero values when merging', () => { + expect( + mergeDailyPoints([ + { day: '2026-05-01', value: 10 }, + { day: '2026-05-01', value: -5 }, + { day: '2026-05-02', value: 0 }, + ]), + ).toEqual([ + { day: '2026-05-01', value: 5 }, + { day: '2026-05-02', value: 0 }, + ]) + }) +}) diff --git a/test/unit/shared/utils/trends-chart.spec.ts b/test/unit/shared/utils/trends-chart.spec.ts new file mode 100644 index 0000000000..2f72a04acf --- /dev/null +++ b/test/unit/shared/utils/trends-chart.spec.ts @@ -0,0 +1,955 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { + buildNormalisedTrendsDataset, + buildTrendsChartConfig, + buildTrendsChartData, + drawTrendsEstimationLine, + drawTrendsLastDatapointLabel, + drawTrendsSvgPrintLegend, + generateWatermarkLogo, + getTrendsDatetimeFormatterOptions, + isDailyDataset, + isMonthlyDataset, + isWeeklyDataset, + isYearlyDataset, +} from '#shared/utils/trends-chart' + +const { + lightenOklchMock, + getFrameworkColorMock, + isListedFrameworkMock, + applyEllipsisMock, + applyDataPipelineMock, +} = vi.hoisted(() => ({ + lightenOklchMock: vi.fn(), + getFrameworkColorMock: vi.fn(), + isListedFrameworkMock: vi.fn(), + applyEllipsisMock: vi.fn(), + applyDataPipelineMock: vi.fn(), +})) + +vi.mock('~/utils/colors', () => ({ + OKLCH_NEUTRAL_FALLBACK: 'oklch-fallback', + lightenOklch: lightenOklchMock, +})) + +vi.mock('~/utils/frameworks', () => ({ + getFrameworkColor: getFrameworkColorMock, + isListedFramework: isListedFrameworkMock, +})) + +vi.mock('~/utils/charts', () => ({ + applyEllipsis: applyEllipsisMock, +})) + +vi.mock('~/utils/chart-data-prediction', () => ({ + DEFAULT_PREDICTION_POINTS: 12, + applyDataPipeline: applyDataPipelineMock, +})) + +const colors = { + bg: '#ffffff', + bgElevated: '#f8f8f8', + fg: '#111111', + fgMuted: '#666666', + fgSubtle: '#999999', + border: '#dddddd', +} + +const translate = (key: string, params?: Record) => { + if (!params) { + return key + } + + return `${key}:${JSON.stringify(params)}` +} + +const compactNumberFormatter = new Intl.NumberFormat('en', { + notation: 'compact', + maximumFractionDigits: 1, +}) + +function baseChartDataOptions() { + return { + packageNames: ['vue'], + isMultiPackageMode: false, + selectedMetric: 'downloads' as const, + selectedMetricLabel: 'Downloads', + selectedGranularity: 'daily' as const, + displayedGranularity: 'daily' as const, + singleEvolution: [], + colors, + isDarkMode: false, + chartFilter: { + averageWindow: 1, + smoothingTau: 0, + }, + t: translate, + compactNumberFormatter, + } +} + +function baseConfigOptions() { + return { + packageNames: ['vue'], + isMultiPackageMode: false, + selectedMetric: 'downloads' as const, + selectedMetricLabel: 'Downloads', + selectedGranularity: 'daily' as const, + displayedGranularity: 'daily' as const, + singleEvolution: [], + colors, + isDarkMode: false, + chartFilter: { + averageWindow: 1, + smoothingTau: 0, + }, + t: translate, + compactNumberFormatter, + dates: [1, 2], + isMobile: false, + pending: false, + locale: 'en', + chartHeight: 400, + } +} + +beforeEach(() => { + vi.clearAllMocks() + + lightenOklchMock.mockReturnValue('lightened-accent') + getFrameworkColorMock.mockReturnValue('#42b883') + isListedFrameworkMock.mockImplementation((packageName: string) => packageName === 'vue') + applyEllipsisMock.mockImplementation((value: string) => value) + applyDataPipelineMock.mockImplementation((series: number[]) => series) +}) + +describe('dataset guards', () => { + it('detects weekly datasets', () => { + expect( + isWeeklyDataset([ + { + weekKey: '2026-W01', + weekStart: '2026-01-01', + weekEnd: '2026-01-07', + timestampStart: 1, + timestampEnd: 2, + value: 10, + }, + ]), + ).toBe(true) + + expect(isWeeklyDataset([])).toBe(false) + expect(isWeeklyDataset(null)).toBe(false) + expect(isWeeklyDataset([{ value: 10 }])).toBe(false) + }) + + it('detects daily datasets', () => { + expect(isDailyDataset([{ day: '2026-01-01', timestamp: 1, value: 10 }])).toBe(true) + expect(isDailyDataset([])).toBe(false) + expect(isDailyDataset(null)).toBe(false) + expect(isDailyDataset([{ value: 10 }])).toBe(false) + }) + + it('detects monthly datasets', () => { + expect(isMonthlyDataset([{ month: '2026-01', timestamp: 1, value: 10 }])).toBe(true) + expect(isMonthlyDataset([])).toBe(false) + expect(isMonthlyDataset(null)).toBe(false) + expect(isMonthlyDataset([{ value: 10 }])).toBe(false) + }) + + it('detects yearly datasets', () => { + expect(isYearlyDataset([{ year: '2026', timestamp: 1, value: 10 }])).toBe(true) + expect(isYearlyDataset([])).toBe(false) + expect(isYearlyDataset(null)).toBe(false) + expect(isYearlyDataset([{ value: 10 }])).toBe(false) + }) +}) + +describe('buildTrendsChartData', () => { + it('formats a single daily dataset', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + singleEvolution: [ + { day: '2026-01-01', timestamp: 1, value: 10, hasAnomaly: true }, + { day: '2026-01-02', timestamp: 2, value: 20 }, + ], + accent: '#abcdef', + }) + + expect(result).toEqual({ + dataset: [ + expect.objectContaining({ + name: 'vue', + type: 'line', + series: [10, 20], + color: '#abcdef', + temperatureColors: undefined, + useArea: true, + dashIndices: [0], + }), + ], + dates: [1, 2], + }) + }) + + it('uses an empty series name when packageNames is empty in single-package mode', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: [], + singleEvolution: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + }) + + expect(result.dataset?.[0]?.name).toBe('') + expect(applyEllipsisMock).toHaveBeenCalledWith('', 32) + }) + + it('formats weekly, monthly, and yearly single datasets', () => { + expect( + buildTrendsChartData({ + ...baseChartDataOptions(), + selectedGranularity: 'weekly', + displayedGranularity: 'weekly', + singleEvolution: [ + { + weekKey: '2026-W01', + weekStart: '2026-01-01', + weekEnd: '2026-01-07', + timestampStart: 1, + timestampEnd: 2, + value: 10, + }, + ], + }).dates, + ).toEqual([2]) + + expect( + buildTrendsChartData({ + ...baseChartDataOptions(), + selectedGranularity: 'monthly', + displayedGranularity: 'monthly', + singleEvolution: [{ month: '2026-01', timestamp: 3, value: 10 }], + }).dates, + ).toEqual([3]) + + expect( + buildTrendsChartData({ + ...baseChartDataOptions(), + selectedGranularity: 'yearly', + displayedGranularity: 'yearly', + singleEvolution: [{ year: '2026', timestamp: 4, value: 10 }], + }).dates, + ).toEqual([4]) + }) + + it('returns null for an invalid single dataset', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + singleEvolution: [], + }) + + expect(result).toEqual({ + dataset: null, + dates: [], + }) + }) + + it('uses fallback accent and dark mode temperature colors', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + singleEvolution: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + colors: { ...colors, fgSubtle: undefined as never }, + isDarkMode: true, + }) + + expect(lightenOklchMock).toHaveBeenCalledWith('oklch-fallback', 0.618) + expect(result.dataset?.[0]).toMatchObject({ + color: 'oklch-fallback', + temperatureColors: ['lightened-accent', 'oklch-fallback'], + }) + }) + + it('extracts daily points in multi-package mode', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue', 'react'], + effectivePackageNamesForMetric: ['vue', 'react'], + isMultiPackageMode: true, + evolutionsByPackage: { + vue: [{ day: '2026-01-01', timestamp: 100, value: 10, hasAnomaly: true }], + react: [{ day: '2026-01-02', timestamp: 200, value: 20 }], + }, + }) + + expect(result.dates).toEqual([100, 200]) + expect(result.dataset).toEqual([ + expect.objectContaining({ + name: 'vue', + series: [10, 0], + dashIndices: [0], + color: '#42b883', + }), + expect.objectContaining({ + name: 'react', + series: [0, 20], + dashIndices: [], + }), + ]) + }) + + it('extracts monthly points in multi-package mode', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue', 'react'], + effectivePackageNamesForMetric: ['vue', 'react'], + isMultiPackageMode: true, + selectedGranularity: 'monthly', + displayedGranularity: 'monthly', + evolutionsByPackage: { + vue: [{ month: '2026-01', timestamp: 100, value: 10, hasAnomaly: true }], + react: [{ month: '2026-02', timestamp: 200, value: 20 }], + }, + }) + + expect(result.dates).toEqual([100, 200]) + expect(result.dataset).toEqual([ + expect.objectContaining({ + name: 'vue', + series: [10, 0], + dashIndices: [0], + }), + expect.objectContaining({ + name: 'react', + series: [0, 20], + dashIndices: [], + }), + ]) + }) + + it('extracts yearly points in multi-package mode', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue', 'react'], + effectivePackageNamesForMetric: ['vue', 'react'], + isMultiPackageMode: true, + selectedGranularity: 'yearly', + displayedGranularity: 'yearly', + evolutionsByPackage: { + vue: [{ year: '2025', timestamp: 100, value: 10, hasAnomaly: true }], + react: [{ year: '2026', timestamp: 200, value: 20 }], + }, + }) + + expect(result.dates).toEqual([100, 200]) + expect(result.dataset).toEqual([ + expect.objectContaining({ + name: 'vue', + series: [10, 0], + dashIndices: [0], + }), + expect.objectContaining({ + name: 'react', + series: [0, 20], + dashIndices: [], + }), + ]) + }) + + it('extracts weekly points in multi-package mode', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue', 'react'], + effectivePackageNamesForMetric: ['vue', 'react'], + isMultiPackageMode: true, + selectedGranularity: 'weekly', + displayedGranularity: 'weekly', + evolutionsByPackage: { + vue: [ + { + weekKey: '2026-W01', + weekStart: '2026-01-01', + weekEnd: '2026-01-07', + timestampStart: 100, + timestampEnd: 200, + value: 10, + hasAnomaly: true, + }, + ], + react: [ + { + weekKey: '2026-W02', + weekStart: '2026-01-08', + weekEnd: '2026-01-14', + timestampStart: 201, + timestampEnd: 300, + value: 20, + }, + ], + }, + }) + + expect(result.dates).toEqual([200, 300]) + expect(result.dataset).toEqual([ + expect.objectContaining({ + name: 'vue', + series: [10, 0], + dashIndices: [0], + }), + expect.objectContaining({ + name: 'react', + series: [0, 20], + dashIndices: [], + }), + ]) + }) + + it('falls back to packageNames when effectivePackageNamesForMetric is not provided', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue'], + isMultiPackageMode: true, + evolutionsByPackage: { + vue: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + }, + }) + + expect(result.dataset?.[0]?.name).toBe('vue') + }) + + it('falls back to an empty point list when a mapped package was not collected', () => { + const effectivePackageNamesForMetric = ['vue'] as unknown as string[] + + effectivePackageNamesForMetric.map = ((callback: (packageName: string) => unknown) => + ['vue', 'react'].map(callback)) as typeof effectivePackageNamesForMetric.map + + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue', 'react'], + effectivePackageNamesForMetric, + isMultiPackageMode: true, + evolutionsByPackage: { + vue: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + }, + }) + + expect(result.dataset).toEqual([ + expect.objectContaining({ + name: 'vue', + series: [10], + }), + expect.objectContaining({ + name: 'react', + series: [0], + }), + ]) + }) + + it('returns null for multi-package mode when no dates are available', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + isMultiPackageMode: true, + evolutionsByPackage: {}, + }) + + expect(result).toEqual({ + dataset: null, + dates: [], + }) + }) + + it('returns null for multi-package mode when extracted points are invalid', () => { + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue'], + isMultiPackageMode: true, + selectedGranularity: 'daily', + displayedGranularity: 'daily', + evolutionsByPackage: { + vue: [{ month: '2026-01', timestamp: 1, value: 10 }] as never, + }, + }) + + expect(result).toEqual({ + dataset: null, + dates: [], + }) + }) + + it('applies anomaly correction for downloads when enabled', () => { + const applyAnomalyCorrection = vi.fn(() => [{ day: '2026-01-01', timestamp: 1, value: 99 }]) + + const result = buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue'], + isMultiPackageMode: true, + evolutionsByPackage: { + vue: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + }, + useAnomalyCorrection: true, + applyAnomalyCorrection, + }) + + expect(applyAnomalyCorrection).toHaveBeenCalledWith({ + data: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + packageName: 'vue', + granularity: 'daily', + }) + expect(result.dataset?.[0]?.series).toEqual([99]) + }) + + it('does not apply anomaly correction for non-download metrics', () => { + const applyAnomalyCorrection = vi.fn() + + buildTrendsChartData({ + ...baseChartDataOptions(), + packageNames: ['vue'], + isMultiPackageMode: true, + selectedMetric: 'likes', + selectedMetricLabel: 'Likes', + evolutionsByPackage: { + vue: [{ day: '2026-01-01', timestamp: 1, value: 10 }], + }, + useAnomalyCorrection: true, + applyAnomalyCorrection, + }) + + expect(applyAnomalyCorrection).not.toHaveBeenCalled() + }) +}) + +describe('buildNormalisedTrendsDataset', () => { + it('returns an empty array for null dataset', () => { + expect( + buildNormalisedTrendsDataset({ + dataset: null, + dates: [], + granularity: 'daily', + selectedMetric: 'downloads', + chartFilter: { averageWindow: 1, smoothingTau: 0 }, + }), + ).toEqual([]) + }) + + it('normalizes number, object, and invalid values before applying the pipeline', () => { + applyDataPipelineMock.mockReturnValue([1, 2, 0]) + + const result = buildNormalisedTrendsDataset({ + dataset: [ + { + name: 'vue', + type: 'line', + series: [1, { x: 1, y: 2 }, 'bad'] as never, + }, + ], + dates: [10], + granularity: 'daily', + selectedMetric: 'downloads', + chartFilter: { averageWindow: 2, smoothingTau: 3 }, + endDateMs: 500, + }) + + expect(applyDataPipelineMock).toHaveBeenCalledWith( + [1, 2, 0], + { + averageWindow: 2, + smoothingTau: 3, + predictionPoints: 12, + }, + { + granularity: 'daily', + lastDateMs: 10, + referenceMs: 500, + isAbsoluteMetric: false, + }, + ) + + expect(result).toEqual([ + expect.objectContaining({ + series: [1, 2, 0], + dashIndices: [], + }), + ]) + }) + + it('uses Date.now when endDateMs is missing', () => { + const dateNowSpy = vi.spyOn(Date, 'now').mockReturnValue(999) + + buildNormalisedTrendsDataset({ + dataset: [{ name: 'vue', type: 'line', series: [1] }], + dates: [], + granularity: 'daily', + selectedMetric: 'downloads', + chartFilter: { averageWindow: 1, smoothingTau: 0, predictionPoints: 4 }, + }) + + expect(applyDataPipelineMock).toHaveBeenCalledWith( + [1], + expect.objectContaining({ + predictionPoints: 4, + }), + expect.objectContaining({ + lastDateMs: 0, + referenceMs: 999, + }), + ) + + dateNowSpy.mockRestore() + }) + + it('disables prediction points for weekly granularity', () => { + buildNormalisedTrendsDataset({ + dataset: [{ name: 'vue', type: 'line', series: [1], dashIndices: [0] }], + dates: [10], + granularity: 'weekly', + selectedMetric: 'contributors', + chartFilter: { averageWindow: 0, smoothingTau: 0, predictionPoints: 5 }, + endDateMs: 100, + }) + + expect(applyDataPipelineMock).toHaveBeenCalledWith( + [1], + { + averageWindow: 0, + smoothingTau: 0, + predictionPoints: 0, + }, + { + granularity: 'weekly', + lastDateMs: 10, + referenceMs: 100, + isAbsoluteMetric: true, + }, + ) + }) +}) + +describe('getTrendsDatetimeFormatterOptions', () => { + it('returns formatter options for each granularity', () => { + expect(getTrendsDatetimeFormatterOptions('daily')).toEqual({ + year: 'yyyy-MM-dd', + month: 'yyyy-MM-dd', + day: 'yyyy-MM-dd', + }) + + expect(getTrendsDatetimeFormatterOptions('weekly')).toEqual({ + year: 'yyyy-MM-dd', + month: 'yyyy-MM-dd', + day: 'yyyy-MM-dd', + }) + + expect(getTrendsDatetimeFormatterOptions('monthly')).toEqual({ + year: 'MMM yyyy', + month: 'MMM yyyy', + day: 'MMM yyyy', + }) + + expect(getTrendsDatetimeFormatterOptions('yearly')).toEqual({ + year: 'yyyy', + month: 'yyyy', + day: 'yyyy', + }) + }) +}) + +describe('buildTrendsChartConfig', () => { + it('builds a light desktop config with default tooltip behavior', () => { + const config = buildTrendsChartConfig(baseConfigOptions()) + + expect(config.theme).toBe('') + expect(config.chart?.height).toBe(400) + expect(config.chart?.padding?.bottom).toBe(64) + expect(config.chart?.grid?.labels?.fontSize).toBe(16) + expect(config.chart?.tooltip?.teleportTo).toBeUndefined() + expect(config.chart?.tooltip?.position).toBe('center') + expect(config.chart?.tooltip?.offsetY).toBe(-24) + expect(config.chart?.timeTag?.backgroundColor).toBe('#f8f8f8') + }) + + it('falls back to bg when bgElevated is not provided', () => { + const config = buildTrendsChartConfig({ + ...baseConfigOptions(), + colors: { + ...colors, + bgElevated: undefined as never, + }, + }) + + expect(config.chart?.timeTag?.backgroundColor).toBe(colors.bg) + }) + + it('builds a dark mobile yearly multi-package config', () => { + const config = buildTrendsChartConfig({ + ...baseConfigOptions(), + packageNames: ['vue', 'react'], + isMultiPackageMode: true, + selectedGranularity: 'yearly', + displayedGranularity: 'yearly', + isDarkMode: true, + dates: [1, 2], + isMobile: true, + pending: true, + locale: 'fr-FR', + chartHeight: 500, + inModal: true, + tooltipPosition: 'left', + }) + + expect(config.theme).toBe('dark') + expect(config.chart?.padding?.bottom).toBe(84) + expect(config.chart?.grid?.labels?.fontSize).toBe(24) + expect(config.chart?.grid?.labels?.color).toBe(colors.border) + expect(config.chart?.grid?.labels?.axis?.fontSize).toBe(32) + expect(config.chart?.tooltip?.teleportTo).toBe('#chart-modal') + expect(config.chart?.tooltip?.position).toBe('left') + expect(config.chart?.tooltip?.offsetY).toBeUndefined() + }) + + it('formats finite and non-finite y-axis values', () => { + const config = buildTrendsChartConfig(baseConfigOptions()) + + const formatter = config.chart?.grid?.labels?.yAxis?.formatter as (payload: { + value: number + }) => string + + expect(formatter({ value: 1200 })).toBe('1.2K') + expect(formatter({ value: Number.NaN })).toBe('0') + }) +}) + +describe('drawTrendsEstimationLine', () => { + it('returns an empty string when rendering is disabled or no data exists', () => { + expect( + drawTrendsEstimationLine({ + svg: {}, + colors, + shouldRender: false, + }), + ).toBe('') + + expect( + drawTrendsEstimationLine({ + svg: {}, + colors, + shouldRender: true, + }), + ).toBe('') + }) + + it('draws estimation lines from svg data', () => { + const result = drawTrendsEstimationLine({ + svg: { + data: [ + { + color: '#ff0000', + plots: [ + { x: 1, y: 2 }, + { x: 3, y: 4 }, + ], + }, + ], + }, + colors, + shouldRender: true, + }) + + expect(result).toContain('x1="1"') + expect(result).toContain('x2="3"') + expect(result).toContain('stroke="#ff0000"') + expect(result).toContain(' { + const result = drawTrendsEstimationLine({ + svg: { + series: [ + { + plots: [ + { x: 1, y: 2 }, + { x: 3, y: 4 }, + ], + }, + { + plots: [{ x: 1, y: 2 }], + }, + { + plots: null, + }, + ], + }, + colors, + shouldRender: true, + }) + + expect(result).toContain(`stroke="${colors.fg}"`) + }) + + it('skips estimation lines when previous or last plot is missing', () => { + const result = drawTrendsEstimationLine({ + svg: { + data: [ + { + color: '#ff0000', + plots: [{ x: 1, y: 2 }, undefined], + }, + { + color: '#00ff00', + plots: [null, { x: 3, y: 4 }], + }, + ], + }, + colors, + shouldRender: true, + }) + + expect(result).toBe('') + }) +}) + +describe('drawTrendsLastDatapointLabel', () => { + it('returns an empty string when no data exists', () => { + expect( + drawTrendsLastDatapointLabel({ + svg: {}, + colors, + compactNumberFormatter, + }), + ).toBe('') + }) + + it('draws last datapoint labels from svg data', () => { + const result = drawTrendsLastDatapointLabel({ + svg: { + data: [ + { + plots: [{ x: 1, y: 2, value: 1200 }], + }, + ], + }, + colors, + compactNumberFormatter, + }) + + expect(result).toContain('1.2K') + expect(result).toContain('x="13"') + }) + + it('draws last datapoint labels and falls back to zero for non-finite values', () => { + const result = drawTrendsLastDatapointLabel({ + svg: { + series: [ + { + plots: [{ x: 1, y: 2, value: 1200 }], + }, + { + plots: [{ x: 3, y: 4, value: Number.NaN }], + }, + { + plots: [], + }, + ], + }, + colors, + compactNumberFormatter, + }) + + expect(result).toContain('1.2K') + expect(result).toContain('0') + expect(result).toContain('x="13"') + }) +}) + +describe('drawTrendsSvgPrintLegend', () => { + it('returns an empty string when no data exists', () => { + expect( + drawTrendsSvgPrintLegend({ + svg: {}, + colors, + showEstimationLegend: false, + estimationLabel: 'Estimated', + }), + ).toBe('') + + expect( + drawTrendsSvgPrintLegend({ + svg: { + data: [], + series: [ + { + name: 'ignored', + color: '#000000', + }, + ], + }, + colors, + showEstimationLegend: false, + estimationLabel: 'Estimated', + }), + ).toBe('') + }) + + it('draws the print legend without estimation legend from data', () => { + const result = drawTrendsSvgPrintLegend({ + svg: { + drawingArea: { + left: 10, + top: 20, + }, + data: [ + { + name: 'vue', + color: '#42b883', + }, + ], + }, + colors, + showEstimationLegend: false, + estimationLabel: 'Estimated', + }) + + expect(result).toContain('vue') + expect(result).toContain('fill="#42b883"') + expect(result).not.toContain('Estimated') + }) + + it('draws the print legend with estimation legend using series fallback', () => { + const result = drawTrendsSvgPrintLegend({ + svg: { + drawingArea: { + left: 10, + top: 20, + }, + series: [ + { + name: 'vue', + color: '#42b883', + }, + ], + }, + colors, + showEstimationLegend: true, + estimationLabel: 'Estimated', + }) + + expect(result).toContain('vue') + expect(result).toContain('Estimated') + expect(result).toContain('stroke-dasharray="4"') + }) +}) + +describe('generateWatermarkLogo', () => { + it('generates an SVG watermark logo', () => { + const result = generateWatermarkLogo({ + x: 1, + y: 2, + width: 3, + height: 4, + fill: '#123456', + }) + + expect(result).toContain('x="1"') + expect(result).toContain('y="2"') + expect(result).toContain('width="3"') + expect(result).toContain('height="4"') + expect(result).toContain('fill="#123456"') + }) +}) diff --git a/uno.config.ts b/uno.config.ts index ddbbafb7a0..426b9dd40b 100644 --- a/uno.config.ts +++ b/uno.config.ts @@ -10,17 +10,7 @@ import { import { presetRtl } from './uno-preset-rtl' import { presetA11y } from './uno-preset-a11y' import { theme } from './uno.theme' - -const customIcons = { - 'agent-skills': - '', - 'tangled': - '', - 'vlt': - '', - 'a11y': - '', -} +import customIcons from './assets/media/custom-icons.json' export default defineConfig({ // og-image uses hardcoded classes we don't want bundled into main app @@ -33,6 +23,11 @@ export default defineConfig({ // Exclude OG image templates from the pipeline '**/OgImage/*.takumi.vue', ], + include: [ + /\.(vue|mdx|html)($|\?)/, + // git provider icons composable + '**/composables/useProviderIcon.ts', + ], }, }, presets: [ @@ -45,14 +40,16 @@ export default defineConfig({ warn: true, scale: 1.2, collections: { - custom: customIcons, + custom: Object.fromEntries( + Object.entries(customIcons).map(([key, { body }]) => [key, body]), + ), }, }), presetTypography(), // keep this preset last ...(process.env.CI ? [] : [presetRtl(), presetA11y()]), ].filter(Boolean), - transformers: [transformerDirectives(), transformerVariantGroup()], + transformers: [transformerDirectives({ enforce: 'pre' }), transformerVariantGroup()], theme, shortcuts: [ // Layout