diff --git a/.dockerignore b/.dockerignore index e511441e..61b6416c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,3 +2,6 @@ build/* Dockerfile .dockerignore node_modules/* +website/node_modules +website/dist +website/.astro diff --git a/.github/workflows/deploy-viewer.yml b/.github/workflows/deploy-viewer.yml new file mode 100644 index 00000000..963ee68c --- /dev/null +++ b/.github/workflows/deploy-viewer.yml @@ -0,0 +1,92 @@ +name: viewer/deploy + +# Publishes the Slim viewer to https://slim-app.web.app, built against the IDC +# public proxy. The website's "Open in Slim" links point here. +on: + push: + branches: [master] + paths: + - "src/**" + - "public/**" + - "index.html" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - "vite.config.ts" + - "tsconfig*.json" + - "scripts/**" + - ".github/workflows/deploy-viewer.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: deploy-viewer-${{ github.ref }} + cancel-in-progress: true + +jobs: + deploy: + name: "Deploy the viewer" + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Setup pnpm + uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 24 + cache: pnpm + + # A git-hosted dicom-microscopy-viewer runs a nested install that ignores + # this workspace's allowBuilds. + - name: Allow dependency build scripts + run: pnpm config set strict-dep-builds false --global + + - name: Install dependencies + # Install without lifecycle scripts, then rebuild only the packages that + # need prepare (dicom-microscopy-viewer dist/). + run: | + set -euo pipefail + pnpm install --frozen-lockfile --ignore-scripts + pnpm rebuild dicom-microscopy-viewer core-js-pure + if [ ! -f "node_modules/dicom-microscopy-viewer/dist/dynamic-import/dicomMicroscopyViewer.min.js" ]; then + (cd node_modules/dicom-microscopy-viewer && pnpm run build) + fi + + - name: Require preview DICOMweb URL + env: + SLIM_PREVIEW_DICOMWEB_URL: ${{ secrets.SLIM_PREVIEW_DICOMWEB_URL }} + run: | + if [ -z "${SLIM_PREVIEW_DICOMWEB_URL}" ]; then + echo "::error::Set Actions secret SLIM_PREVIEW_DICOMWEB_URL (the IDC proxy, read by public/config/preview.js)." + exit 1 + fi + + - name: Build + env: + REACT_APP_CONFIG: preview + PUBLIC_URL: / + SLIM_PREVIEW_DICOMWEB_URL: ${{ secrets.SLIM_PREVIEW_DICOMWEB_URL }} + run: pnpm run build + + # The Firebase CLI skips gitignored directories, and the build output is + # gitignored, so the deploy runs from a copy outside the checkout. + - name: Stage the deploy + run: | + mkdir -p "$RUNNER_TEMP/viewer" + cp -R build "$RUNNER_TEMP/viewer/build" + jq '.hosting.site = "slim-app"' firebase.json > "$RUNNER_TEMP/viewer/firebase.json" + + - name: Deploy to Firebase + uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0 + with: + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_SLIM }}" + projectId: slim-website + entryPoint: ${{ runner.temp }}/viewer + channelId: live diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml new file mode 100644 index 00000000..50cc03ee --- /dev/null +++ b/.github/workflows/deploy-website.yml @@ -0,0 +1,123 @@ +name: website/deploy + +on: + # feat/slim-modern-redesign is included while the website PR is stacked on the + # redesign branch; it can be dropped once the site is merged to master. + pull_request: + branches: [master, feat/slim-modern-redesign] + paths: + - "website/**" + - "src/styles/tokens.css" + - "src/components/ui/**" + - "src/components/slim/**" + - "docs/CHANGELOG.md" + - "CITATION.cff" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - ".github/workflows/deploy-website.yml" + push: + branches: [master, feat/slim-modern-redesign] + paths: + - "website/**" + - "src/styles/tokens.css" + - "src/components/ui/**" + - "src/components/slim/**" + - "docs/CHANGELOG.md" + - "CITATION.cff" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" + - ".github/workflows/deploy-website.yml" + workflow_dispatch: + +concurrency: + group: deploy-website-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +env: + SITE_URL: https://slim-website.web.app + +jobs: + build: + name: "Check and build the website" + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Setup pnpm + uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 24 + cache: pnpm + + - name: Install dependencies + # The site needs no dependency build scripts, and skipping them avoids + # building dicom-microscopy-viewer, which only the app uses. + run: pnpm install --frozen-lockfile --ignore-scripts --filter slim-website... + + - name: Check + run: pnpm --filter slim-website run check + + - name: Test + run: pnpm --filter slim-website run test + + - name: Build + run: pnpm --filter slim-website run build + + - name: Upload site + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: website-dist + path: website/dist + retention-days: 7 + + deploy: + name: "Deploy to Firebase" + needs: build + # Forked PRs cannot access the Firebase service account secret, so skip them. + if: > + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + checks: write + pull-requests: write + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Download site + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: website-dist + path: website/dist + + - name: Deploy preview + if: github.event_name == 'pull_request' + uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0 + with: + repoToken: "${{ secrets.GITHUB_TOKEN }}" + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_SLIM }}" + projectId: slim-website + entryPoint: website + channelId: website-pr-${{ github.event.pull_request.number }} + + - name: Deploy to live + if: github.event_name != 'pull_request' + uses: FirebaseExtended/action-hosting-deploy@500ac625ca2dd40cbd15f7659af953801858032a # v0.11.0 + with: + repoToken: "${{ secrets.GITHUB_TOKEN }}" + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_SLIM }}" + projectId: slim-website + entryPoint: website + channelId: live diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 23e7ebe9..eeb649a6 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -51,3 +51,13 @@ jobs: - name: Test run: pnpm run test + + # The website shares tokens and components with the app, so app changes can break it + - name: Website check + run: pnpm --filter slim-website run check + + - name: Website test + run: pnpm --filter slim-website run test + + - name: Website build + run: pnpm --filter slim-website run build diff --git a/.github/workflows/website-idc-examples.yml b/.github/workflows/website-idc-examples.yml new file mode 100644 index 00000000..2426f281 --- /dev/null +++ b/.github/workflows/website-idc-examples.yml @@ -0,0 +1,58 @@ +name: website/verify-idc-examples + +# The support matrix on the website links to public IDC series. IDC releases +# can retire or replace series, so check weekly that every link still resolves +# on the IDC proxy, and open an issue when one breaks or a new type appears. + +on: + schedule: + - cron: "17 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + verify: + name: "Verify IDC examples" + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Setup Node.js + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: 24 + + - name: Verify examples against IDC + id: verify + # The script only uses Node built-ins, so no install is needed + env: + IDC_REPORT_PATH: ${{ runner.temp }}/idc-examples-report.md + run: node website/scripts/find-idc-examples.mjs --verify + + - name: Open or update an issue + if: failure() && steps.verify.outcome == 'failure' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPORT_PATH: ${{ runner.temp }}/idc-examples-report.md + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + TITLE="Website: IDC examples in the support matrix need attention" + { + if [ -f "${REPORT_PATH}" ]; then cat "${REPORT_PATH}"; else echo "The check failed before writing a report."; fi + echo + echo "Run \`pnpm --filter slim-website find-idc-examples\` to pick new examples, then commit \`website/src/data/idc-examples.json\`." + echo + echo "Workflow run: ${RUN_URL}" + } > "${RUNNER_TEMP}/issue-body.md" + EXISTING=$(gh issue list --state open --search "in:title \"${TITLE}\"" --json number --jq '.[0].number // empty') + if [ -n "${EXISTING}" ]; then + gh issue comment "${EXISTING}" --body-file "${RUNNER_TEMP}/issue-body.md" + else + gh issue create --title "${TITLE}" --body-file "${RUNNER_TEMP}/issue-body.md" + fi diff --git a/biome.json b/biome.json index fe9c6da2..626169f2 100644 --- a/biome.json +++ b/biome.json @@ -6,7 +6,11 @@ "useIgnoreFile": true }, "files": { - "includes": ["src/**/*.{ts,tsx,js,jsx}", "!src/__mocks__"] + "includes": [ + "src/**/*.{ts,tsx,js,jsx}", + "!src/__mocks__", + "website/**/*.{ts,tsx,mjs}" + ] }, "formatter": { "enabled": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d502f692..09ce92e1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,16 +142,16 @@ importers: version: 2.4.16 '@rolldown/plugin-babel': specifier: ^0.2.4 - version: 0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + version: 0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) '@tailwindcss/vite': specifier: 4.3.3 - version: 4.3.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + version: 4.3.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) '@testing-library/dom': specifier: ^10.4.2 version: 10.4.2 '@testing-library/jest-dom': specifier: ^7.0.1 - version: 7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0))) + version: 7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))) '@testing-library/react': specifier: ^16.3.3 version: 16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) @@ -181,7 +181,7 @@ importers: version: 8.3.4 '@vitejs/plugin-react': specifier: ^6.1.1 - version: 6.1.2(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + version: 6.1.2(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))(babel-plugin-react-compiler@1.0.0)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) babel-plugin-react-compiler: specifier: ^1.0.0 version: 1.0.0 @@ -205,13 +205,83 @@ importers: version: 7.0.2 vite: specifier: ^8.3.1 - version: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + version: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) vite-plugin-static-copy: specifier: ^4.1.1 - version: 4.1.1(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + version: 4.1.1(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) vitest: specifier: ^5.0.3 - version: 5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + version: 5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) + + website: + dependencies: + '@astrojs/mdx': + specifier: ^8.0.2 + version: 8.0.3(@astrojs/markdown-satteri@0.4.3)(astro@7.3.8(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) + '@astrojs/react': + specifier: ^7.0.0 + version: 7.0.1(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))(@types/node@24.19.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(babel-plugin-react-compiler@1.0.0)(jiti@2.7.0)(less@4.6.4)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(terser@5.48.0)(yaml@2.9.1) + '@astrojs/rss': + specifier: ^4.0.19 + version: 4.0.19 + '@astrojs/sitemap': + specifier: ^3.7.4 + version: 3.7.4 + '@fontsource/ibm-plex-mono': + specifier: ^5.3.0 + version: 5.3.0 + '@fontsource/ibm-plex-sans': + specifier: ^5.3.0 + version: 5.3.0 + '@radix-ui/react-slot': + specifier: ^1.3.3 + version: 1.4.0(@types/react@19.3.0)(react@19.3.0) + '@tailwindcss/vite': + specifier: 4.3.3 + version: 4.3.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) + astro: + specifier: ^7.3.5 + version: 7.3.8(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + lucide-react: + specifier: ^1.49.0 + version: 1.54.0(@types/react@19.3.0)(react@19.3.0) + react: + specifier: ^19.3.0 + version: 19.3.0 + react-dom: + specifier: ^19.3.0 + version: 19.3.0(react@19.3.0) + tailwind-merge: + specifier: ^3.7.0 + version: 3.7.0 + tailwindcss: + specifier: 4.3.3 + version: 4.3.3 + yaml: + specifier: ^2.9.1 + version: 2.9.1 + devDependencies: + '@astrojs/check': + specifier: ^0.9.10 + version: 0.9.10(@emnapi/runtime@1.11.3)(prettier@3.9.10)(typescript@5.9.3) + '@types/react': + specifier: ^19.2.0 + version: 19.3.0 + '@types/react-dom': + specifier: ^19.2.0 + version: 19.3.0(@types/react@19.3.0) + playwright: + specifier: ~1.57.0 + version: 1.57.0 + typescript: + specifier: ^5.9.3 + version: 5.9.3 packages: @@ -226,6 +296,146 @@ packages: resolution: {integrity: sha512-YnVzxDxLaqL0t7Q4wfcgHZjg55Wm6y5EaO7Bhu3q9J7wq/8iw3PhsnWiOQhYekx4VexnbkgWpTT6n+QIV7kczw==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + '@astrojs/astro2tsx@0.1.2': + resolution: {integrity: sha512-Uj/M9zbrhu5cIZEvWAGTbQJRKSxXWJ/E59BZwt7F+chrKhbfttW+9rkS/l+1QxoJP1KU3UnpM62M7yszfAI0WA==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@astrojs/check@0.9.10': + resolution: {integrity: sha512-zgx/UQMozdjOa3bOxjgeCFdtpE3c9rRX6xHwa+2QXvy8z8Akifu2AtubHyv/zzC2znO8dl8fFWL4K+Ba9kS8HQ==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 || ^6.0.0 + + '@astrojs/compiler-binding-android-arm64@0.5.1': + resolution: {integrity: sha512-nMb2nMIJtcWLNH+fV75Enmi+jp4tIOYOfsv4XtpgdOWkqc9P4uSSdK5u1xb340AzrXo5V18SxLl/nc3vcqtamQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@astrojs/compiler-binding-darwin-arm64@0.5.1': + resolution: {integrity: sha512-5k4+nZ/WRt+dcVow4z7rBuI7iv9A58h/uQ91YJe1PrTivbcCkq3u2Ynx/AZJwII4CsZawBCeGpojkFjutZBhBQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@astrojs/compiler-binding-darwin-x64@0.5.1': + resolution: {integrity: sha512-0Buw+YST9Ff2EqQyhRMQujuFq/dijLw3zXWhsvI0dJ2pGrT38iVoxTEca2eBX/PfhlwkVWSRJEKO5gMqKHyeHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@astrojs/compiler-binding-linux-arm64-gnu@0.5.1': + resolution: {integrity: sha512-x5LRpyCoMKuu3INr18cn42YhwSOaRpp9b5Ny3eJJ/sWVeejC16Zeshu1JlvlSmEZACLeWxU5JM0RX6T6nI+YyA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-arm64-musl@0.5.1': + resolution: {integrity: sha512-mL7tQEuDk3rGfaKmrO63nw6WBy1TPVioQGmVyjcAr+C+a/k3SVMYBytNSMqH9mZPT/Swj30JaZ2N842Z1NnOEQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-linux-x64-gnu@0.5.1': + resolution: {integrity: sha512-uLGc9jtxwiDe4cQyhNPQim4ECiB/YzbWlXssfLAv8r374kArfTwBHjwR2+j+XVyF71yCx5mF9YNRclRqdNBgeg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@astrojs/compiler-binding-linux-x64-musl@0.5.1': + resolution: {integrity: sha512-G0cywinaQUc8v1MrytvYKUX7svTDMmYtOCZfxjwKPbJi59zIqM+Ll0rWgO0GQWLZH3XoPYo19ZwlP3Xt9ep9YA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@astrojs/compiler-binding-wasm32-wasi@0.5.1': + resolution: {integrity: sha512-yMhLL8asmLydoAdnEZxAw6eLfNDs3YJl6jqn0pjPt6zrb2U5qIDLnii4/twThpIFODKkQ6YDpBRTOz/vSfZCxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@astrojs/compiler-binding-win32-arm64-msvc@0.5.1': + resolution: {integrity: sha512-aClIG6poFt3Wf/bZykrEAX2nAnKvBHW6RXiKUa69QjBtWH0/FOlOAjnFcxRNlhej2AMWNYFx0o+LGjwMcH8P7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@astrojs/compiler-binding-win32-x64-msvc@0.5.1': + resolution: {integrity: sha512-/E6uBCagY70YpWqssBC+/FuniNSloeQPRgj7l3LDWiqjxIyTLnIgX1sTt18FU7jrigetpSnC9cHAM6b6IxSgPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@astrojs/compiler-binding@0.5.1': + resolution: {integrity: sha512-oczyolLUl9mNrtuBuNjuvn5thpHrFLXAHAWGTRg0JDHQ8cGVsVeFekOu2uSoQGgainJIi+A3/9m0DyYwz3Nlnw==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@astrojs/compiler-rs@0.5.1': + resolution: {integrity: sha512-1k1acnX7DepIiea9U9/Y+d1hdAFfylu1ZQQkkYgRSwBOBAsXInolyZuh/2tax+83vu/A+hOYP6P3+265RvMTvw==} + engines: {node: '>=22.12.0'} + + '@astrojs/internal-helpers@0.12.0': + resolution: {integrity: sha512-pKPuwCDtO0L7zgmt1JGd9X4Aes1+0SX3IEBSqBNPHsScYdPMlfmed3Y7DTbXyF7E+8ylnb563o/0OzGQPOFehw==} + + '@astrojs/language-server@2.17.2': + resolution: {integrity: sha512-WzqCBYo0RtKrkPLPMnTz2+UOQPosaFhoG/PvoSyPIgBU0BKeS6qeaYv7Rscq7P1LxJdoN0VosQF2h2TZTsIGHg==} + hasBin: true + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true + + '@astrojs/markdown-satteri@0.4.3': + resolution: {integrity: sha512-PFbEHPnwUlLvpXd7RXrrKM+j12akF4bG+DSuNuoN+3eiwjOwp4HaPi+QQdbkBV7QEYXmzyKca50OJsmGxhNIUA==} + + '@astrojs/mdx@8.0.3': + resolution: {integrity: sha512-SmwnVrGZSohDG0B9LXiAPbR6fe9TOumli9Vw/9zo815xGTeB1T3Fqt6HEClmBsVwIKFg/ccos4TgjZAedvg7zA==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@astrojs/markdown-remark': ^7.3.0 + '@astrojs/markdown-satteri': ^0.4.0 + astro: ^7.2.10 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: true + + '@astrojs/prism@4.0.2': + resolution: {integrity: sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==} + engines: {node: '>=22.12.0'} + + '@astrojs/react@7.0.1': + resolution: {integrity: sha512-ggKxfvq5KHDveZd/3TGbxvdA4O0ClwMG0eiSJh92dpHJxqfGjRudOqKW2SLFTmKfZAJD+hV+soPgT9WJArO0dQ==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@types/react': ^17.0.50 || ^18.0.21 || ^19.0.0 + '@types/react-dom': ^17.0.17 || ^18.0.6 || ^19.0.0 + oxc-transform-react: ^0.145.0 + react: ^17.0.2 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.2 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + oxc-transform-react: + optional: true + + '@astrojs/rss@4.0.19': + resolution: {integrity: sha512-e+z5wYeYtffQdHQO8c2tkSd2JEBdAuRXJV4ZEU5IxkYeE6e39woDd7nw1PH1Kk2tEYNCYuKdylnnbhGmt61awA==} + + '@astrojs/sitemap@3.7.4': + resolution: {integrity: sha512-LbKNC24bdUWcQf/pThB6qLlSqHojxGjZDURIzFocY8rlWnAn2t74nnhnK6S5x0NHriHoAduLEpVjRykmeGiVvA==} + + '@astrojs/telemetry@3.3.3': + resolution: {integrity: sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@astrojs/yaml2ts@0.2.4': + resolution: {integrity: sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A==} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -377,6 +587,67 @@ packages: resolution: {integrity: sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==} hasBin: true + '@bruits/satteri-darwin-arm64@0.10.5': + resolution: {integrity: sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA==} + cpu: [arm64] + os: [darwin] + + '@bruits/satteri-darwin-x64@0.10.5': + resolution: {integrity: sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q==} + cpu: [x64] + os: [darwin] + + '@bruits/satteri-linux-arm64-gnu@0.10.5': + resolution: {integrity: sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-arm64-musl@0.10.5': + resolution: {integrity: sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@bruits/satteri-linux-x64-gnu@0.10.5': + resolution: {integrity: sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-linux-x64-musl@0.10.5': + resolution: {integrity: sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@bruits/satteri-wasm32-wasi@0.10.5': + resolution: {integrity: sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@bruits/satteri-win32-arm64-msvc@0.10.5': + resolution: {integrity: sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw==} + cpu: [arm64] + os: [win32] + + '@bruits/satteri-win32-x64-msvc@0.10.5': + resolution: {integrity: sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ==} + cpu: [x64] + os: [win32] + + '@capsizecss/unpack@4.0.1': + resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==} + engines: {node: '>=18'} + + '@clack/core@1.5.1': + resolution: {integrity: sha512-iHTrHA8MtVuLl2TfZySmcKv1qO2PoyC9Z7pfSDozEuV5vtY3/wcOPKJXlqJ5Oq2Cx5DDGQGAMVx6HZfRRoVEbQ==} + engines: {node: '>= 20.12.0'} + + '@clack/prompts@1.8.1': + resolution: {integrity: sha512-dlT1m5e/0yUL0kRNcQn7yGLVThkgbB0Ga/1AmfDDC/8ik6AIiSf2QLQO2zPYvefsHP0aFgxO93cVLCCfDp7kzQ==} + engines: {node: '>= 20.12.0'} + '@cornerstonejs/codec-charls@1.2.7': resolution: {integrity: sha512-kNfQ7J8LIrfQUbt56fPJ0SEvevLlAAbsLHjqPS4DUDWVSuAHb5Fn0cMIV/U0SYkJRJqKvzyLJYF1hl7/xQGqLQ==, tarball: https://registry.npmjs.org/@cornerstonejs/codec-charls/-/codec-charls-1.2.7.tgz} engines: {node: '>=0.14'} @@ -429,6 +700,45 @@ packages: resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==} engines: {node: '>=20.19.0'} + '@emmetio/abbreviation@2.3.3': + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + + '@emmetio/css-abbreviation@2.1.8': + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + + '@emmetio/css-parser@0.4.1': + resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==} + + '@emmetio/html-matcher@1.3.0': + resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==} + + '@emmetio/scanner@1.0.4': + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + + '@emmetio/stream-reader-utils@0.1.0': + resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==} + + '@emmetio/stream-reader@2.2.0': + resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} + + '@emnapi/core@1.11.3': + resolution: {integrity: sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==} + + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/runtime@1.11.3': + resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + + '@emnapi/wasi-threads@1.2.3': + resolution: {integrity: sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==} + '@exodus/bytes@1.16.0': resolution: {integrity: sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -463,6 +773,168 @@ packages: resolution: {integrity: sha512-gHRHIct+5kyTqONASiuGgjlZVEaawpwqSxfBbltLwhTVYedcA7hs0TPYJk3uR1P5RvvC2fC1lPJ0c8jhkGxtNA==} engines: {node: '>=0.14'} + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.35.5': + resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.35.5': + resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.5': + resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==} + engines: {node: '>=20.9.0'} + os: [freebsd] + + '@img/sharp-libvips-darwin-arm64@1.3.4': + resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.3.4': + resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.3.4': + resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.3.4': + resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.3.4': + resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.3.4': + resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.3.4': + resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.3.4': + resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.35.5': + resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.35.5': + resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.35.5': + resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.35.5': + resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.35.5': + resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.35.5': + resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.35.5': + resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.35.5': + resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.35.5': + resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.5': + resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.5': + resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.5': + resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.35.5': + resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -485,6 +957,20 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@napi-rs/wasm-runtime@1.2.4': + resolution: {integrity: sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 + + '@napi-rs/wasm-runtime@1.2.5': + resolution: {integrity: sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 + '@noble/curves@2.4.0': resolution: {integrity: sha512-P4/62zrgfH33CneE3Dn4WhJVA22YUU0eR51wKIan4NVRvwsA0YnPTwWGpNbpuacSujmSFLvyzpyuR30+fbq2Ew==} engines: {node: '>= 20.19.0'} @@ -493,6 +979,12 @@ packages: resolution: {integrity: sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==} engines: {node: '>= 20.19.0'} + '@nodable/entities@3.1.0': + resolution: {integrity: sha512-LsS/DjHr+uDM647Gru/cA8+J3a3HfhttwCKLyuoyN7yXTFCxKBtSgMQBvrW9yNPa2/zDRUNuGPaH5QUFoa4arQ==} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oxc-project/types@0.153.0': resolution: {integrity: sha512-jSNrRIyvPVLL5E1z/tS5zLAprosGz/FuI1PWwEOz59j3E4TTTzSpqKb/RDGqJhhW0QHYISGXxq582wGx6T11Tw==} @@ -1013,6 +1505,37 @@ packages: '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@shikijs/core@4.5.0': + resolution: {integrity: sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==} + engines: {node: '>=20'} + + '@shikijs/engine-javascript@4.5.0': + resolution: {integrity: sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==} + engines: {node: '>=20'} + + '@shikijs/engine-oniguruma@4.5.0': + resolution: {integrity: sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==} + engines: {node: '>=20'} + + '@shikijs/langs@4.5.0': + resolution: {integrity: sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==} + engines: {node: '>=20'} + + '@shikijs/primitive@4.5.0': + resolution: {integrity: sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==} + engines: {node: '>=20'} + + '@shikijs/themes@4.5.0': + resolution: {integrity: sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==} + engines: {node: '>=20'} + + '@shikijs/types@4.5.0': + resolution: {integrity: sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==} + engines: {node: '>=20'} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@tailwindcss/node@4.3.3': resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} @@ -1147,6 +1670,9 @@ packages: '@types/react-dom': optional: true + '@tybys/wasm-util@0.10.4': + resolution: {integrity: sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -1171,12 +1697,24 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + '@types/lodash@4.17.24': resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + '@types/node@24.19.2': resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} @@ -1194,6 +1732,12 @@ packages: '@types/retry@0.12.5': resolution: {integrity: sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==} + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/uuid@8.3.4': resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} @@ -1317,6 +1861,9 @@ packages: cpu: [x64] os: [win32] + '@ungap/structured-clone@1.4.0': + resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==} + '@vitejs/plugin-react@6.1.2': resolution: {integrity: sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1347,6 +1894,32 @@ packages: '@vitest/spy@5.0.3': resolution: {integrity: sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==} + '@volar/kit@2.4.28': + resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==} + peerDependencies: + typescript: '*' + + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} + + '@volar/language-server@2.4.28': + resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==} + + '@volar/language-service@2.4.28': + resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==} + + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} + + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} + + '@vscode/emmet-helper@2.11.0': + resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==} + + '@vscode/l10n@0.0.18': + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + '@zarrita/storage@0.2.0': resolution: {integrity: sha512-855ZXqtnds7spnT8vNvD+MXa3QExP1m2GqShe8yt7uZXHnQLgJHgkpVwFjE1B0KDDRO0ki09hmk6OboTaIfPsQ==} @@ -1359,10 +1932,38 @@ packages: resolution: {integrity: sha512-Xwrja8nx9e5o2N1my4DsKCeKpdrnACyr1wtbPxBDgGzKzKyE9kRtBFA8mWldI+RVlD7CBZNWY/wQ2+ydwOR6kQ==} engines: {node: '>=14.0'} + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-i18n@4.2.0: + resolution: {integrity: sha512-v/ei2UkCEeuKNXh8RToiFsUclmU+G57LO1Oo22OagNMENIw+Yb8eMwvHu7Vn9fmkjJyv6XclhJ8TbuigSglPkg==} + peerDependencies: + ajv: ^8.0.0-beta.0 + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + am-i-vibing@0.5.0: + resolution: {integrity: sha512-KLcsDhqf1XRrJmJr+9I/C0EX2K+sGrAGZFgkmd84c8TJO9zJBu+/kFInjazu1KfJWFhWDKdRWkpBzEs7s35DVA==} + hasBin: true + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} @@ -1371,6 +1972,12 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + anynum@1.0.1: + resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + aria-hidden@1.2.6: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} @@ -1394,9 +2001,23 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + astro@7.3.8: + resolution: {integrity: sha512-LHzDHSaV+YzZiR3EFndDYTLLeNeuMtP1qX1FLcCNUUHOCqTTIWPczy2UV3zpA5VqvJe5cWZolqM9Z8JFqR2i9w==} + engines: {node: '>=22.12.0', npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + peerDependencies: + '@astrojs/markdown-remark': ^7.3.0 + peerDependenciesMeta: + '@astrojs/markdown-remark': + optional: true + async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + babel-plugin-polyfill-corejs2@0.4.17: resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} peerDependencies: @@ -1415,6 +2036,9 @@ packages: babel-plugin-react-compiler@1.0.0: resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==} + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -1430,6 +2054,9 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + brace-expansion@1.1.21: resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} @@ -1448,27 +2075,70 @@ packages: caniuse-lite@1.0.30001812: resolution: {integrity: sha512-qN+QNNBr93TCmFrmte0bBCjSDMuRvt78VlHT99qIGPszm4QsqCX8lnyWUFkHi8B7ZBAPq8SH+UqyXNy/odMdng==} + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@6.3.0: resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==} engines: {node: '>=18'} + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + 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'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colormap@2.3.2: resolution: {integrity: sha512-jDOjaoEEmA9AgA11B/jCSAvYE95r3wRoAyTf3LEHGiUVlNHJaL1mRkf5AyLSpQBVGfTEPwGEqCIzL+kgr2WgNA==} + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + common-ancestor-path@2.0.0: + resolution: {integrity: sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==} + engines: {node: '>= 18'} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -1481,9 +2151,16 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + cookie-es@3.1.1: resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + cookie@2.0.1: + resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} + engines: {node: '>=22'} + copy-anything@3.0.5: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} @@ -1494,13 +2171,31 @@ packages: core-js-pure@3.49.0: resolution: {integrity: sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==} + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + css-tree@3.2.1: resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + css.escape@1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -1527,10 +2222,16 @@ packages: decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + detect-browser@5.3.0: resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} @@ -1541,6 +2242,12 @@ packages: detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + devalue@5.9.4: + resolution: {integrity: sha512-sPAT4pztbu6586/hrhOnMKS17IJrvg12mXiSPSS3W5qDeN2RGgvZ0diZCm31dBbnevfVmujNO3IM2wrS4Y2Rhg==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dicom-microscopy-viewer@0.48.27: resolution: {integrity: sha512-Y/5q/AOgqYirT9mzfdAUQwi2bPdY/TOG5ouLbP1KGgtpEsfWelAVlagtovB15Gh7585kZ9XWR6fGnBAmwNE9Cg==} @@ -1550,12 +2257,33 @@ packages: dicomweb-client@0.11.3: resolution: {integrity: sha512-7t1Rc/01fyFnKlQeNPW9Pvxvmsx8R/BgB2n7BxTuWirRFwlTC5upEeLeS3vO72P+n6/SQZ3+5ij0bgaWDHQG/A==} + diff@9.0.0: + resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} + engines: {node: '>=0.3.1'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + earcut@3.0.2: resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} @@ -1565,10 +2293,22 @@ packages: email-addresses@5.0.0: resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} + emmet@2.4.11: + resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + enhanced-resolve@5.26.0: resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} engines: {node: '>=10.13.0'} + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + entities@8.1.0: resolution: {integrity: sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==} engines: {node: '>=20.19.0'} @@ -1584,6 +2324,9 @@ packages: es-module-lexer@2.3.2: resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + es-module-lexer@3.0.3: + resolution: {integrity: sha512-yWGe1O/j+almnV4hOYrmZo8u58JdnmXEMneRQAYkWtqSiT86yoMIEKF4rpqEDj52tbYl3xceBD3DQIBwcsC9Pw==} + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1598,10 +2341,38 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + expect-type@1.4.0: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-string-truncated-width@3.0.3: + resolution: {integrity: sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==} + + fast-string-width@3.0.2: + resolution: {integrity: sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==} + + fast-uri@3.1.8: + resolution: {integrity: sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==} + + fast-wrap-ansi@0.2.2: + resolution: {integrity: sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==} + + fast-xml-builder@1.3.1: + resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==} + + fast-xml-parser@5.11.2: + resolution: {integrity: sha512-R9iDuNrQYeQut46cn2r2wHKn4HYzVDvDm5J1wW+koZewykv0yuO2HChTYeZtrULyHIDM9cj9TUXloCsueCQUog==} + hasBin: true + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1634,10 +2405,25 @@ packages: resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} engines: {node: '>=8'} + find-proc@0.2.0: + resolution: {integrity: sha512-a6h2nTrgB3g5Wrn4au9Ux4kMk7IJtyF6oA8uGn+mk3weLZssUtc1cp6meHIzzuW2o1srrBAxzkmXLbqjRkgB6w==} + engines: {node: ^20.19.0 || >=22.12.0} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + fontace@0.4.1: + resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==} + + fontkitten@1.0.3: + resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==} + engines: {node: '>=20'} + fraction.js@4.3.4: resolution: {integrity: sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==} @@ -1648,6 +2434,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1664,15 +2455,30 @@ packages: resolution: {integrity: sha512-OWcL9S9+yDZ6iAlXMt32T1iwUApJM8UiD47xbm6ZP1h33d10fqkPs14EG/ttT5EnefpZSx3G15iDFC5FxUNUwA==} engines: {node: '>=10.19'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.7.0: + resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==} + engines: {node: '>=18'} + get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-tsconfig@5.0.0-beta.6: + resolution: {integrity: sha512-X6fBC0pmImC70gvX2zm56go9hx0MyoGVdG0tUCkg/D+Xnh5TJsOZ7iDbOdI3PvmtrDxnu1YdDufpK2QJX1Meqw==} + engines: {node: '>=20.20.0'} + gh-pages@5.0.0: resolution: {integrity: sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==} engines: {node: '>=10'} hasBin: true + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + gl-matrix@3.4.4: resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==} @@ -1691,14 +2497,32 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + h3@1.15.11: + resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + hasown@2.0.4: resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + html-encoding-sniffer@7.0.0: resolution: {integrity: sha512-UikN5yr7xsCDAq87Or5or0PAlD3HJJOKVzM05az588WnpDJ4Ux7a2A53Qi6gofGg2/EtvF/H4hCi/TXfCW4Y6w==} engines: {node: ^22.13.0 || >=24.0.0} + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + http-cache-semantics@4.3.0: + resolution: {integrity: sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==} + husky@9.1.7: resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} @@ -1731,6 +2555,9 @@ packages: iota-array@1.0.0: resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -1742,10 +2569,19 @@ packages: resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} + is-docker@4.0.0: + resolution: {integrity: sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==} + engines: {node: '>=20'} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1754,9 +2590,16 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-unsafe@2.0.2: + resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==} + is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} @@ -1785,11 +2628,20 @@ packages: engines: {node: '>=6'} hasBin: true + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true + jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} @@ -1797,6 +2649,10 @@ packages: resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} engines: {node: '>=18'} + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + lerc@3.0.0: resolution: {integrity: sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==} @@ -2000,6 +2856,9 @@ packages: magic-string@1.4.3: resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==} + magicast@0.5.5: + resolution: {integrity: sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -2009,8 +2868,29 @@ packages: engines: {node: '>= 14'} hasBin: true - mdn-data@2.27.1: - resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.3: + resolution: {integrity: sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==} mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} @@ -2024,9 +2904,16 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + nanoid@3.3.19: resolution: {integrity: sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2040,6 +2927,19 @@ packages: engines: {node: '>= 4.4.x'} hasBin: true + neotraverse@1.0.1: + resolution: {integrity: sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-mock-http@1.0.5: + resolution: {integrity: sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==} + node-releases@2.0.57: resolution: {integrity: sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==} engines: {node: '>=18'} @@ -2048,6 +2948,9 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + nth-check@2.0.1: + resolution: {integrity: sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==} + numcodecs@0.3.2: resolution: {integrity: sha512-6YSPnmZgg0P87jnNhi3s+FVLOcIn3y+1CTIgUulA3IdASzK9fJM87sUFkpyA+be9GibGRaST2wCgkD+6U+fWKw==} @@ -2059,6 +2962,16 @@ packages: resolution: {integrity: sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==} engines: {node: '>=12.20.0'} + obug@3.0.0: + resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==} + engines: {node: '>=12.20.0'} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + ohash@2.0.12: + resolution: {integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==} + oidc-client-ts@3.5.0: resolution: {integrity: sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A==} engines: {node: '>=18'} @@ -2069,10 +2982,20 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} + p-limit@7.3.3: + resolution: {integrity: sha512-SKgVvDU5TNIxQ4r30U75BNLC6a+6GOEjngrk/ysM5+Zu3oJuk1SC5ApzIzY/7PjCEjoVPMWJ0zho/4QUiEB7TQ==} + engines: {node: '>=20'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -2081,10 +3004,21 @@ packages: resolution: {integrity: sha512-HaSJ9hNZOxTUSATfB48Qi7U2+GF1eECjI39nkeLmCWQrSOYr1z4NepR0rpWiZO77pYwUWU2cJ5NIgsmoFCsYDQ==} engines: {node: '>=18'} + p-queue@9.3.3: + resolution: {integrity: sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA==} + engines: {node: '>=20'} + + p-timeout@7.0.2: + resolution: {integrity: sha512-prbX4Z3YszrFNgH+MW5Zoeq3baXrMtP/MQnFeET90UB/GtGcGDQ5Usg9OCy6ETjTTntOw1SL2z9fMPUppN3Guw==} + engines: {node: '>=20'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-manager-detector@1.9.0: + resolution: {integrity: sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==} + pako@2.1.0: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} @@ -2098,10 +3032,17 @@ packages: parse5@8.0.1: resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-expression-matcher@1.6.2: + resolution: {integrity: sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==} + engines: {node: '>=14.0.0'} + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -2113,6 +3054,9 @@ packages: resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} hasBin: true + piccolore@0.1.3: + resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -2144,14 +3088,40 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + playwright-core@1.57.0: + resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.57.0: + resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==} + engines: {node: '>=18'} + hasBin: true + postcss@8.5.25: resolution: {integrity: sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==} engines: {node: ^10 || ^12 || >=14} + prettier@3.9.10: + resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==} + engines: {node: '>=14'} + hasBin: true + pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + process-ancestry@0.1.0: + resolution: {integrity: sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg==} + engines: {node: '>=18.0.0'} + + property-information@7.2.0: + resolution: {integrity: sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==} + protocol-buffers-schema@3.6.1: resolution: {integrity: sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==} @@ -2169,6 +3139,9 @@ packages: quickselect@3.0.0: resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==} + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + rbush@4.0.1: resolution: {integrity: sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==} @@ -2237,6 +3210,14 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} + engines: {node: '>= 20.19.0'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -2244,10 +3225,28 @@ packages: reference-spec-reader@0.2.0: resolution: {integrity: sha512-q0mfCi5yZSSHXpCyxjgQeaORq3tvDsxDyzaadA/5+AbAUwRyRuuTh0aRQuE/vAOt/qzzxidJ5iDeu1cLHaNBlQ==} + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + request-light@0.5.8: + resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==} + + request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve-protobuf-schema@2.1.0: resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} @@ -2256,6 +3255,9 @@ packages: engines: {node: '>= 0.4'} hasBin: true + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} + retry@0.13.1: resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} engines: {node: '>= 4'} @@ -2268,6 +3270,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + satteri@0.10.5: + resolution: {integrity: sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ==} + sax@1.6.0: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} @@ -2287,6 +3292,31 @@ packages: engines: {node: '>=10'} hasBin: true + sharp@0.35.5: + resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==} + engines: {node: '>=20.9.0'} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + shiki@4.5.0: + resolution: {integrity: sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==} + engines: {node: '>=20'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@9.0.1: + resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==} + engines: {node: '>=20.19.5', npm: '>=10.8.2'} + hasBin: true + + smol-toml@1.9.1: + resolution: {integrity: sha512-j7WyPdf0CJoutMzMoPLF/bVXHtKZIT9Rb4eGeEbWw8X2t5oirjPgpL+OpaENZrILYaXqYwnVH+qgUwVbl+pUJQ==} + engines: {node: '>= 18'} + source-map-js@1.2.2: resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} @@ -2298,9 +3328,39 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + std-env@4.3.0: resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string-width@8.3.0: + resolution: {integrity: sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==} + engines: {node: '>=20'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -2309,10 +3369,18 @@ packages: resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} engines: {node: '>=0.10.0'} + strnum@2.5.1: + resolution: {integrity: sha512-UM4nTLWzQiDBseVxUGxN0wJzIk0UU89Qi7pKXz9qISo+lhviJikTuikBsK/oFRlpvYHvSdz0TVoLyQ+sEpYwxA==} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svgo@2.8.4: + resolution: {integrity: sha512-2GJ4h3rl13qYTdwllaK6QlL8tG+UrM8626V2Ylcd/yBUv2Y/EwLsYisVV6UDCRmlk+C74G8nMpxJCk0RWPdDCw==} + engines: {node: '>=10.13.0'} + hasBin: true + tailwind-merge@3.7.0: resolution: {integrity: sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA==} @@ -2331,10 +3399,17 @@ packages: tiny-emitter@2.1.0: resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tinybench@6.2.1: resolution: {integrity: sha512-IAbQaPJIIdhVxi0mqy9lez1wEwje0UQf9F1vwtbelEG5Nbgn0nPOxCvU+mNeNS9gyJTAhrHp74CbUaSynQpZcQ==} engines: {node: '>=20.0.0'} + tinyclip@1.0.3: + resolution: {integrity: sha512-nTv2raKFMzGG6JJp0lpNDsRPdfFE6UHlu2rVEjXo8vkx1ZS3LW2CVXqIaLu8xZlu+6tbFs9V58Qc/Jmk/Ii7wA==} + engines: {node: ^16.14.0 || >= 17.3.0} + tinyexec@1.3.1: resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} engines: {node: '>=18'} @@ -2362,10 +3437,16 @@ packages: resolution: {integrity: sha512-BcDSDW+SIGWVOns1Zm6Yg91q9AEj7eaID0QDY9oIqJD1A8dscNwMcl9Sms2DeuWCNov1X0/oXanHGYQBSLwZsg==} engines: {node: ^22.14.0 || >=24.0.0} + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + trim-repeated@1.0.0: resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} engines: {node: '>=0.10.0'} + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -2376,11 +3457,31 @@ packages: resolution: {integrity: sha512-VwaXim9Gp1bngi/q3do8hgttYn2uC3MoT/gfuMWylnj1IeZBUAyPddHZlo1K05BDoj8DYPpMdiHqH1dDYdJf2A==} engines: {node: '>= 18'} + typesafe-path@0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + + typescript-auto-import-cache@0.3.6: + resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} hasBin: true + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + ultrahtml@1.7.0: + resolution: {integrity: sha512-2xRd0VHoAQE4M+vF/DvFFB7pUV0ZxTW1TLi7lHQWnF/Sb5TPeEUV/l+hxcNnGO00ZXGnR0voCMmYRKQf+rvJ2g==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} @@ -2388,10 +3489,93 @@ packages: resolution: {integrity: sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==} engines: {node: '>=22.19.0'} + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unifont@0.7.5: + resolution: {integrity: sha512-ULe/Cs+ZIsq+dcFofNkhqielCrUJnb5mr+Yc4EBM2VlL+6OZR6+cjtI2mT1bJvRBrVncqHAbLURxmPLcCXzWMg==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + unstorage@1.17.5: + resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + unzipit@2.0.0: resolution: {integrity: sha512-DVeVIWUZCAQPNzm5sB0hpsG1GygTTdBnzNtYYEpInkttx5evkyqRgZi6rTczoySqp8hO5jHVKzrH0f23X8FZLg==} engines: {node: '>=18'} @@ -2432,6 +3616,16 @@ packages: deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true + verkit@0.5.0: + resolution: {integrity: sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==} + engines: {node: '>=18.12.0'} + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + vite-plugin-static-copy@4.1.1: resolution: {integrity: sha512-GrlA8YklrAfSyxJ4M3fdQLOo9oNkp56IM9FYgX/WtEgeIFkPwhu4wzpufBCIuNKCa6Fn77FkRdYxkHqV0FwjAw==} engines: {node: ^22.0.0 || >=24.0.0} @@ -2481,6 +3675,14 @@ packages: yaml: optional: true + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@5.0.3: resolution: {integrity: sha512-xMw97S3rjdtj5dkVat7jCsqWBpvchs3RlpQctUqwJD0KkERk40vz2fJ77lDwW/Vzh/pk18eItYAzkodhSes3jQ==} engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} @@ -2522,6 +3724,108 @@ packages: jsdom: optional: true + volar-service-css@0.0.71: + resolution: {integrity: sha512-wRRFt9BpjMKCazcgOh67MSjUjiWUCAh99DyYSDIOTuxaRjEtDC7PpB0k1Y1wbJIW/pVtMUSVbpPo3UGSm0Byxw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-emmet@0.0.71: + resolution: {integrity: sha512-zqjzt6bN95e3CUstBm0PBFAJnrfz0ZAARka87fart46/gNCLLuP3Vujy8V/J8HEziTFLnfkgIASLFYPUhonJcA==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-html@0.0.71: + resolution: {integrity: sha512-e8tHPhgQ7ooLfudAEIku+kgd9pWkq3SSz8RbnQDI1+Eb8wbenkLGHqoirLqz5ORLV6wIMr2Iv08RWBG5eOcgpw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-prettier@0.0.71: + resolution: {integrity: sha512-Rz7JVH3qD108UCdmIEiZvOBNljMt2nLFdbN8AXcDfn7xD9F5I2aCIsDVqBbXw21PsnxG0b7MfwtNF+zPS/NKUg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + + volar-service-typescript-twoslash-queries@0.0.71: + resolution: {integrity: sha512-9K2k72s4n7rV9s4bX0MyjbX9iBribvKZbBJKuEmTCZfeWJXs6Yh7bGpY4eoc7UufAjvpheBqwyZCOIPBvxCv0A==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-typescript@0.0.71: + resolution: {integrity: sha512-yTtM/BVT6hoyEYnDtaCyAtNhdNeS/mhTTABlBOdw3NNiRBUin3IznFJpgfjer4c6RYopiPjjQjc9VFhxVl1mLw==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-yaml@0.0.71: + resolution: {integrity: sha512-qYGWGuVpUTnZGu5P/CR4KLK4aIR8RrcVnmfZ2eRcj9q/I8VZCoC5yy9FtEvfNvnDp4MU17yhdJcvpQPIqhJS2Q==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + vscode-css-languageservice@6.3.10: + resolution: {integrity: sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==} + + vscode-html-languageservice@5.6.2: + resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==} + + vscode-json-languageservice@4.1.8: + resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==} + engines: {npm: '>=7.0.0'} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-jsonrpc@9.0.3: + resolution: {integrity: sha512-qETYf9PCl1lVfwR+oBmMfc4vP2nqLNA35ABxorw3j06+xlKRgDVxbLgKm4Y/xPL0YWdeDjLoI4ImICIT3nB0zQ==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-protocol@3.18.4: + resolution: {integrity: sha512-CCXbyr99dafRJzJH/0Ryk7ly5T8XPmSR0//OuF2w4m+9JiOin7zcAT5iET8GRE7Z9taFBejb3GbM0a0mbjdbrg==} + + vscode-languageserver-textdocument@1.0.15: + resolution: {integrity: sha512-Gsfr9S8LU3S6885cS+NaleasJ0n3V5y/SOTqHCifQiXWFw3G9w9/YItDfwHrlCz+dSZWWZ8ilYVMcJe7Sz7Sxw==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver-types@3.18.4: + resolution: {integrity: sha512-nQsacoiijvl0fRf2q28uFDrAVwRhdCa3QveiF7/CX0r18mLR5FU/1WskSsCKOjmEbtteKUnY8x8Yzxop+k0zwg==} + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + + vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + + vscode-uri@3.2.0: + resolution: {integrity: sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==} + w3c-xmlserializer@6.0.0: resolution: {integrity: sha512-4Nsy8K5Tr6SPDH9jhKJOHf7ChDrc1zufZTVSF7x72hwuEXBqxqk9G6cK+K2NRUtB3iELRJqjXb4JPDMBjMTl2Q==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} @@ -2546,6 +3850,10 @@ packages: engines: {node: '>=20.11'} hasBin: true + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -2553,24 +3861,67 @@ packages: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} + xml-naming@0.3.0: + resolution: {integrity: sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==} + engines: {node: '>=16.0.0'} + xml-utils@1.10.2: resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==} xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml-language-server@1.23.0: + resolution: {integrity: sha512-3qVyCOexLCWw06PQa5kRPwvMWMZ/eZeCRWUvgD6a0OkqL/4iCnxy2WumbWifa937Uo5xhyWJ0uxlU39ljhNh7A==} + hasBin: true + + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.2.0: + resolution: {integrity: sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + zarrita@0.7.3: resolution: {integrity: sha512-wChTQ1Ox75INoQCzKAfLWAfB70JJ4KjdW8Sz5x4ZWrFB4Dw+YZdnxHTL0xSdsrB9EmKSeK7fS1Y+I2ibhfGbkw==} + zod@4.6.5: + resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} + zstddec@0.2.0: resolution: {integrity: sha512-oyPnDa1X5c13+Y7mA/FDMNJrn4S8UNBe0KCqtDmor40Re7ALrPN6npFwyYVRRh+PqozZQdeg23QtbcamZnG5rA==} + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + snapshots: '@adobe/css-tools@4.5.0': {} @@ -2585,10 +3936,183 @@ snapshots: '@asamuzakjp/dom-selector@9.2.4': dependencies: - bidi-js: 1.1.0 - css-tree: 3.2.1 - is-potential-custom-element-name: 1.0.1 - lru-cache: 11.5.3 + bidi-js: 1.1.0 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.3 + + '@astrojs/astro2tsx@0.1.2(@emnapi/runtime@1.11.3)': + dependencies: + '@emnapi/core': 1.11.3 + '@napi-rs/wasm-runtime': 1.2.4(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) + transitivePeerDependencies: + - '@emnapi/runtime' + + '@astrojs/check@0.9.10(@emnapi/runtime@1.11.3)(prettier@3.9.10)(typescript@5.9.3)': + dependencies: + '@astrojs/language-server': 2.17.2(@emnapi/runtime@1.11.3)(prettier@3.9.10)(typescript@5.9.3) + chokidar: 4.0.3 + kleur: 4.1.5 + typescript: 5.9.3 + yargs: 18.2.0 + transitivePeerDependencies: + - '@emnapi/runtime' + - prettier + - prettier-plugin-astro + + '@astrojs/compiler-binding-android-arm64@0.5.1': + optional: true + + '@astrojs/compiler-binding-darwin-arm64@0.5.1': + optional: true + + '@astrojs/compiler-binding-darwin-x64@0.5.1': + optional: true + + '@astrojs/compiler-binding-linux-arm64-gnu@0.5.1': + optional: true + + '@astrojs/compiler-binding-linux-arm64-musl@0.5.1': + optional: true + + '@astrojs/compiler-binding-linux-x64-gnu@0.5.1': + optional: true + + '@astrojs/compiler-binding-linux-x64-musl@0.5.1': + optional: true + + '@astrojs/compiler-binding-wasm32-wasi@0.5.1': + dependencies: + '@emnapi/core': 1.11.3 + '@emnapi/runtime': 1.11.3 + '@napi-rs/wasm-runtime': 1.2.5(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3) + optional: true + + '@astrojs/compiler-binding-win32-arm64-msvc@0.5.1': + optional: true + + '@astrojs/compiler-binding-win32-x64-msvc@0.5.1': + optional: true + + '@astrojs/compiler-binding@0.5.1': + optionalDependencies: + '@astrojs/compiler-binding-android-arm64': 0.5.1 + '@astrojs/compiler-binding-darwin-arm64': 0.5.1 + '@astrojs/compiler-binding-darwin-x64': 0.5.1 + '@astrojs/compiler-binding-linux-arm64-gnu': 0.5.1 + '@astrojs/compiler-binding-linux-arm64-musl': 0.5.1 + '@astrojs/compiler-binding-linux-x64-gnu': 0.5.1 + '@astrojs/compiler-binding-linux-x64-musl': 0.5.1 + '@astrojs/compiler-binding-wasm32-wasi': 0.5.1 + '@astrojs/compiler-binding-win32-arm64-msvc': 0.5.1 + '@astrojs/compiler-binding-win32-x64-msvc': 0.5.1 + + '@astrojs/compiler-rs@0.5.1': + dependencies: + '@astrojs/compiler-binding': 0.5.1 + + '@astrojs/internal-helpers@0.12.0': + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + picomatch: 4.0.7 + retext-smartypants: 6.2.0 + shiki: 4.5.0 + smol-toml: 1.9.1 + unified: 11.0.5 + yaml: 2.9.1 + + '@astrojs/language-server@2.17.2(@emnapi/runtime@1.11.3)(prettier@3.9.10)(typescript@5.9.3)': + dependencies: + '@astrojs/astro2tsx': 0.1.2(@emnapi/runtime@1.11.3) + '@astrojs/yaml2ts': 0.2.4 + '@volar/kit': 2.4.28(typescript@5.9.3) + '@volar/language-core': 2.4.28 + '@volar/language-server': 2.4.28 + '@volar/language-service': 2.4.28 + muggle-string: 0.4.1 + tinyglobby: 0.2.17 + volar-service-css: 0.0.71(@volar/language-service@2.4.28) + volar-service-emmet: 0.0.71(@volar/language-service@2.4.28) + volar-service-html: 0.0.71(@volar/language-service@2.4.28) + volar-service-prettier: 0.0.71(@volar/language-service@2.4.28)(prettier@3.9.10) + volar-service-typescript: 0.0.71(@volar/language-service@2.4.28) + volar-service-typescript-twoslash-queries: 0.0.71(@volar/language-service@2.4.28) + volar-service-yaml: 0.0.71(@volar/language-service@2.4.28) + vscode-html-languageservice: 5.6.2 + vscode-uri: 3.2.0 + optionalDependencies: + prettier: 3.9.10 + transitivePeerDependencies: + - '@emnapi/runtime' + - typescript + + '@astrojs/markdown-satteri@0.4.3': + dependencies: + '@astrojs/internal-helpers': 0.12.0 + '@astrojs/prism': 4.0.2 + github-slugger: 2.0.0 + satteri: 0.10.5 + + '@astrojs/mdx@8.0.3(@astrojs/markdown-satteri@0.4.3)(astro@7.3.8(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))': + dependencies: + '@astrojs/internal-helpers': 0.12.0 + '@astrojs/markdown-satteri': 0.4.3 + astro: 7.3.8(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) + es-module-lexer: 3.0.3 + + '@astrojs/prism@4.0.2': + dependencies: + prismjs: 1.30.0 + + '@astrojs/react@7.0.1(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))(@types/node@24.19.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(babel-plugin-react-compiler@1.0.0)(jiti@2.7.0)(less@4.6.4)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(terser@5.48.0)(yaml@2.9.1)': + dependencies: + '@astrojs/internal-helpers': 0.12.0 + '@types/react': 19.3.0 + '@types/react-dom': 19.3.0(@types/react@19.3.0) + '@vitejs/plugin-react': 6.1.2(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))(babel-plugin-react-compiler@1.0.0)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) + devalue: 5.9.4 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + ultrahtml: 1.7.0 + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) + transitivePeerDependencies: + - '@rolldown/plugin-babel' + - '@types/node' + - '@vitejs/devtools' + - babel-plugin-react-compiler + - esbuild + - jiti + - less + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + '@astrojs/rss@4.0.19': + dependencies: + fast-xml-parser: 5.11.2 + piccolore: 0.1.3 + zod: 4.6.5 + + '@astrojs/sitemap@3.7.4': + dependencies: + sitemap: 9.0.1 + zod: 4.6.5 + + '@astrojs/telemetry@3.3.3': + dependencies: + ci-info: 4.4.0 + dset: 3.1.4 + is-docker: 4.0.0 + package-manager-detector: 1.9.0 + + '@astrojs/yaml2ts@0.2.4': + dependencies: + yaml: 2.9.1 '@babel/code-frame@7.29.7': dependencies: @@ -2763,6 +4287,53 @@ snapshots: dependencies: css-tree: 3.2.1 + '@bruits/satteri-darwin-arm64@0.10.5': + optional: true + + '@bruits/satteri-darwin-x64@0.10.5': + optional: true + + '@bruits/satteri-linux-arm64-gnu@0.10.5': + optional: true + + '@bruits/satteri-linux-arm64-musl@0.10.5': + optional: true + + '@bruits/satteri-linux-x64-gnu@0.10.5': + optional: true + + '@bruits/satteri-linux-x64-musl@0.10.5': + optional: true + + '@bruits/satteri-wasm32-wasi@0.10.5': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.2.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true + + '@bruits/satteri-win32-arm64-msvc@0.10.5': + optional: true + + '@bruits/satteri-win32-x64-msvc@0.10.5': + optional: true + + '@capsizecss/unpack@4.0.1': + dependencies: + fontkitten: 1.0.3 + + '@clack/core@1.5.1': + dependencies: + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + + '@clack/prompts@1.8.1': + dependencies: + '@clack/core': 1.5.1 + fast-string-width: 3.0.2 + fast-wrap-ansi: 0.2.2 + sisteransi: 1.0.5 + '@cornerstonejs/codec-charls@1.2.7': {} '@cornerstonejs/codec-libjpeg-turbo-8bit@1.2.8': {} @@ -2795,6 +4366,58 @@ snapshots: '@csstools/css-tokenizer@4.0.2': {} + '@emmetio/abbreviation@2.3.3': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-abbreviation@2.1.8': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-parser@0.4.1': + dependencies: + '@emmetio/stream-reader': 2.2.0 + '@emmetio/stream-reader-utils': 0.1.0 + + '@emmetio/html-matcher@1.3.0': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/scanner@1.0.4': {} + + '@emmetio/stream-reader-utils@0.1.0': {} + + '@emmetio/stream-reader@2.2.0': {} + + '@emnapi/core@1.11.1': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + + '@emnapi/core@1.11.3': + dependencies: + '@emnapi/wasi-threads': 1.2.3 + tslib: 2.8.1 + + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.3': + dependencies: + tslib: 2.8.1 + '@exodus/bytes@1.16.0(@noble/hashes@2.4.0)': optionalDependencies: '@noble/hashes': 2.4.0 @@ -2822,6 +4445,113 @@ snapshots: '@imagingdatacommons/dicomicc@0.2.3': {} + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.4 + optional: true + + '@img/sharp-darwin-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.4 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.3.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + optional: true + + '@img/sharp-linux-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.4 + optional: true + + '@img/sharp-linux-arm@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.4 + optional: true + + '@img/sharp-linux-ppc64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.4 + optional: true + + '@img/sharp-linux-riscv64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.4 + optional: true + + '@img/sharp-linux-s390x@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.4 + optional: true + + '@img/sharp-linux-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + optional: true + + '@img/sharp-wasm32@0.35.5': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-win32-arm64@0.35.5': + optional: true + + '@img/sharp-win32-ia32@0.35.5': + optional: true + + '@img/sharp-win32-x64@0.35.5': + optional: true + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2849,12 +4579,36 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@napi-rs/wasm-runtime@1.2.4(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3)': + dependencies: + '@emnapi/core': 1.11.3 + '@emnapi/runtime': 1.11.3 + '@tybys/wasm-util': 0.10.4 + + '@napi-rs/wasm-runtime@1.2.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + dependencies: + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.4 + optional: true + + '@napi-rs/wasm-runtime@1.2.5(@emnapi/core@1.11.3)(@emnapi/runtime@1.11.3)': + dependencies: + '@emnapi/core': 1.11.3 + '@emnapi/runtime': 1.11.3 + '@tybys/wasm-util': 0.10.4 + optional: true + '@noble/curves@2.4.0': dependencies: '@noble/hashes': 2.4.0 '@noble/hashes@2.4.0': {} + '@nodable/entities@3.1.0': {} + + '@oslojs/encoding@1.1.0': {} + '@oxc-project/types@0.153.0': {} '@petamoriken/float16@3.9.3': {} @@ -3326,7 +5080,7 @@ snapshots: '@rolldown/binding-win32-x64-msvc@1.2.13': optional: true - '@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0))': + '@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))': dependencies: '@babel/core': 7.29.7 picomatch: 4.0.7 @@ -3334,10 +5088,50 @@ snapshots: optionalDependencies: '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) '@babel/runtime': 7.29.7 - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) '@rolldown/pluginutils@1.0.1': {} + '@shikijs/core@4.5.0': + dependencies: + '@shikijs/primitive': 4.5.0 + '@shikijs/types': 4.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@4.5.0': + dependencies: + '@shikijs/types': 4.5.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@4.5.0': + dependencies: + '@shikijs/types': 4.5.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@4.5.0': + dependencies: + '@shikijs/types': 4.5.0 + + '@shikijs/primitive@4.5.0': + dependencies: + '@shikijs/types': 4.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/themes@4.5.0': + dependencies: + '@shikijs/types': 4.5.0 + + '@shikijs/types@4.5.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + '@shikijs/vscode-textmate@10.0.2': {} + '@tailwindcss/node@4.3.3': dependencies: '@jridgewell/remapping': 2.3.5 @@ -3399,12 +5193,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 - '@tailwindcss/vite@4.3.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0))': + '@tailwindcss/vite@4.3.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))': dependencies: '@tailwindcss/node': 4.3.3 '@tailwindcss/oxide': 4.3.3 tailwindcss: 4.3.3 - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) '@tanstack/react-table@8.20.5(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: @@ -3425,7 +5219,7 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 - '@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)))': + '@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))': dependencies: '@adobe/css-tools': 4.5.0 '@testing-library/dom': 10.4.2 @@ -3435,7 +5229,7 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 optionalDependencies: - vitest: 5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + vitest: 5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) '@testing-library/react@16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': dependencies: @@ -3447,6 +5241,10 @@ snapshots: '@types/react': 19.3.0 '@types/react-dom': 19.3.0(@types/react@19.3.0) + '@tybys/wasm-util@0.10.4': + dependencies: + tslib: 2.8.1 + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -3479,10 +5277,26 @@ snapshots: '@types/deep-eql@4.0.2': {} + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.9 + '@types/estree@1.0.9': {} + '@types/hast@3.0.5': + dependencies: + '@types/unist': 3.0.3 + '@types/lodash@4.17.24': {} + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + '@types/node@24.19.2': dependencies: undici-types: 7.24.6 @@ -3499,6 +5313,12 @@ snapshots: '@types/retry@0.12.5': {} + '@types/sax@1.2.7': + dependencies: + '@types/node': 24.19.2 + + '@types/unist@3.0.3': {} + '@types/uuid@8.3.4': {} '@typescript/typescript-aix-ppc64@7.0.2': @@ -3561,25 +5381,77 @@ snapshots: '@typescript/typescript-win32-x64@7.0.2': optional: true - '@vitejs/plugin-react@6.1.2(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)))(babel-plugin-react-compiler@1.0.0)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0))': + '@ungap/structured-clone@1.4.0': {} + + '@vitejs/plugin-react@6.1.2(@rolldown/plugin-babel@0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)))(babel-plugin-react-compiler@1.0.0)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))': dependencies: '@rolldown/pluginutils': 1.0.1 - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) optionalDependencies: - '@rolldown/plugin-babel': 0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + '@rolldown/plugin-babel': 0.2.4(@babel/core@7.29.7)(@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7))(@babel/runtime@7.29.7)(rolldown@1.2.13)(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) babel-plugin-react-compiler: 1.0.0 - '@vitest/mocker@5.0.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0))': + '@vitest/mocker@5.0.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1))': dependencies: '@jridgewell/trace-mapping': 0.3.31 '@vitest/spy': 5.0.3 estree-walker: 3.0.3 magic-string: 1.4.3 optionalDependencies: - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) '@vitest/spy@5.0.3': {} + '@volar/kit@2.4.28(typescript@5.9.3)': + dependencies: + '@volar/language-service': 2.4.28 + '@volar/typescript': 2.4.28 + typesafe-path: 0.2.2 + typescript: 5.9.3 + vscode-languageserver-textdocument: 1.0.15 + vscode-uri: 3.2.0 + + '@volar/language-core@2.4.28': + dependencies: + '@volar/source-map': 2.4.28 + + '@volar/language-server@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + '@volar/language-service': 2.4.28 + '@volar/typescript': 2.4.28 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.18.4 + vscode-languageserver-textdocument: 1.0.15 + vscode-uri: 3.2.0 + + '@volar/language-service@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + vscode-languageserver-protocol: 3.18.4 + vscode-languageserver-textdocument: 1.0.15 + vscode-uri: 3.2.0 + + '@volar/source-map@2.4.28': {} + + '@volar/typescript@2.4.28': + dependencies: + '@volar/language-core': 2.4.28 + path-browserify: 1.0.1 + vscode-uri: 3.2.0 + + '@vscode/emmet-helper@2.11.0': + dependencies: + emmet: 2.4.11 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.15 + vscode-languageserver-types: 3.18.4 + vscode-uri: 3.2.0 + + '@vscode/l10n@0.0.18': {} + '@zarrita/storage@0.2.0': dependencies: reference-spec-reader: 0.2.0 @@ -3590,8 +5462,33 @@ snapshots: adm-zip@0.6.1: {} + ajv-draft-04@1.0.0(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv-i18n@4.2.0(ajv@8.20.0): + dependencies: + ajv: 8.20.0 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.8 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + am-i-vibing@0.5.0: + dependencies: + process-ancestry: 0.1.0 + ansi-regex@5.0.1: {} + ansi-regex@6.4.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + ansi-styles@5.2.0: {} anymatch@3.1.3: @@ -3599,6 +5496,10 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.2 + anynum@1.0.1: {} + + arg@5.0.2: {} + aria-hidden@1.2.6: dependencies: tslib: 2.8.1 @@ -3617,8 +5518,99 @@ snapshots: assertion-error@2.0.1: {} + astro@7.3.8(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1): + dependencies: + '@astrojs/compiler-rs': 0.5.1 + '@astrojs/internal-helpers': 0.12.0 + '@astrojs/markdown-satteri': 0.4.3 + '@astrojs/telemetry': 3.3.3 + '@capsizecss/unpack': 4.0.1 + '@clack/prompts': 1.8.1 + '@oslojs/encoding': 1.1.0 + am-i-vibing: 0.5.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + ci-info: 4.4.0 + clsx: 2.1.1 + common-ancestor-path: 2.0.0 + cookie: 2.0.1 + devalue: 5.9.4 + diff: 9.0.0 + dset: 3.1.4 + es-module-lexer: 3.0.3 + find-proc: 0.2.0 + flattie: 1.1.1 + fontace: 0.4.1 + get-tsconfig: 5.0.0-beta.6 + github-slugger: 2.0.0 + html-escaper: 3.0.3 + http-cache-semantics: 4.3.0 + jsonc-parser: 3.3.1 + magic-string: 1.4.3 + magicast: 0.5.5 + mrmime: 2.0.1 + neotraverse: 1.0.1 + obug: 3.0.0 + p-limit: 7.3.3 + p-queue: 9.3.3 + package-manager-detector: 1.9.0 + piccolore: 0.1.3 + picomatch: 4.0.7 + rolldown: 1.2.13 + shiki: 4.5.0 + smol-toml: 1.9.1 + svgo: 2.8.4 + tinyclip: 1.0.3 + tinyexec: 1.3.1 + tinyglobby: 0.2.17 + ultrahtml: 1.7.0 + unifont: 0.7.5 + unstorage: 1.17.5 + verkit: 0.5.0 + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) + vitefu: 1.1.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) + xxhash-wasm: 1.1.0 + yargs-parser: 22.0.0 + zod: 4.6.5 + optionalDependencies: + sharp: 0.35.5(@types/node@24.19.2) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - '@vitejs/devtools' + - aws4fetch + - db0 + - esbuild + - idb-keyval + - ioredis + - jiti + - less + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - uploadthing + - yaml + async@3.2.6: {} + axobject-query@4.1.0: {} + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7): dependencies: '@babel/compat-data': 7.29.7 @@ -3650,6 +5642,8 @@ snapshots: dependencies: '@babel/types': 7.29.7 + bail@2.0.2: {} + balanced-match@1.0.2: {} baseline-browser-mapping@2.11.26: {} @@ -3660,6 +5654,8 @@ snapshots: binary-extensions@2.3.0: {} + boolbase@1.0.0: {} + brace-expansion@1.1.21: dependencies: balanced-match: 1.0.2 @@ -3682,8 +5678,14 @@ snapshots: caniuse-lite@1.0.30001812: {} + ccount@2.0.1: {} + chai@6.3.0: {} + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -3696,18 +5698,46 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chokidar@5.0.0: + dependencies: + readdirp: 5.1.1 + + ci-info@4.4.0: {} + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 + cliui@9.0.1: + dependencies: + string-width: 7.2.0 + strip-ansi: 7.2.0 + wrap-ansi: 7.0.0 + clsx@2.1.1: {} + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + colormap@2.3.2: dependencies: lerp: 1.0.3 + comma-separated-tokens@2.0.3: {} + commander@2.20.3: {} + commander@7.2.0: {} + + common-ancestor-path@2.0.0: {} + commondir@1.0.1: {} complex.js@2.4.3: {} @@ -3716,8 +5746,12 @@ snapshots: convert-source-map@2.0.0: {} + cookie-es@1.2.3: {} + cookie-es@3.1.1: {} + cookie@2.0.1: {} + copy-anything@3.0.5: dependencies: is-what: 4.1.16 @@ -3730,13 +5764,36 @@ snapshots: core-js-pure@3.49.0: {} + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.0.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + css-tree@3.2.1: dependencies: mdn-data: 2.27.1 source-map-js: 1.2.2 + css-what@6.2.2: {} + css.escape@1.5.1: {} + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + csstype@3.2.3: {} data-urls@8.0.0(@noble/hashes@2.4.0): @@ -3772,14 +5829,24 @@ snapshots: decimal.js@10.6.0: {} + defu@6.1.7: {} + dequal@2.0.3: {} + destr@2.0.5: {} + detect-browser@5.3.0: {} detect-libc@2.1.2: {} detect-node-es@1.1.0: {} + devalue@5.9.4: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + dicom-microscopy-viewer@0.48.27: dependencies: '@cornerstonejs/codec-charls': 1.2.7 @@ -3795,13 +5862,35 @@ snapshots: ol: 10.9.0 uuid: 9.0.1 - dicomweb-client@0.10.3: {} + dicomweb-client@0.10.3: {} + + dicomweb-client@0.11.3: {} + + diff@9.0.0: {} + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@2.3.0: {} - dicomweb-client@0.11.3: {} + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 - dom-accessibility-api@0.5.16: {} + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 - dom-accessibility-api@0.6.3: {} + dset@3.1.4: {} earcut@3.0.2: {} @@ -3809,11 +5898,22 @@ snapshots: email-addresses@5.0.0: {} + emmet@2.4.11: + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + enhanced-resolve@5.26.0: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 + entities@2.2.0: {} + entities@8.1.0: {} errno@0.1.8: @@ -3826,6 +5926,8 @@ snapshots: es-module-lexer@2.3.2: {} + es-module-lexer@3.0.3: {} + escalade@3.2.0: {} escape-latex@1.2.0: {} @@ -3836,8 +5938,40 @@ snapshots: dependencies: '@types/estree': 1.0.9 + eventemitter3@5.0.4: {} + expect-type@1.4.0: {} + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-string-truncated-width@3.0.3: {} + + fast-string-width@3.0.2: + dependencies: + fast-string-truncated-width: 3.0.3 + + fast-uri@3.1.8: {} + + fast-wrap-ansi@0.2.2: + dependencies: + fast-string-width: 3.0.2 + + fast-xml-builder@1.3.1: + dependencies: + path-expression-matcher: 1.6.2 + xml-naming: 0.3.0 + + fast-xml-parser@5.11.2: + dependencies: + '@nodable/entities': 3.1.0 + fast-xml-builder: 1.3.1 + is-unsafe: 2.0.2 + path-expression-matcher: 1.6.2 + strnum: 2.5.1 + xml-naming: 0.3.0 + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -3864,11 +5998,23 @@ snapshots: make-dir: 3.1.0 pkg-dir: 4.2.0 + find-proc@0.2.0: {} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 + flattie@1.1.1: {} + + fontace@0.4.1: + dependencies: + fontkitten: 1.0.3 + + fontkitten@1.0.3: + dependencies: + tiny-inflate: 1.0.3 + fraction.js@4.3.4: {} fs-extra@8.1.0: @@ -3879,6 +6025,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -3898,8 +6047,16 @@ snapshots: xml-utils: 1.10.2 zstddec: 0.2.0 + get-caller-file@2.0.5: {} + + get-east-asian-width@1.7.0: {} + get-nonce@1.0.1: {} + get-tsconfig@5.0.0-beta.6: + dependencies: + resolve-pkg-maps: 1.0.0 + gh-pages@5.0.0: dependencies: async: 3.2.6 @@ -3910,6 +6067,8 @@ snapshots: fs-extra: 8.1.0 globby: 6.1.0 + github-slugger@2.0.0: {} + gl-matrix@3.4.4: {} glob-parent@5.1.2: @@ -3935,17 +6094,53 @@ snapshots: graceful-fs@4.2.11: {} + h3@1.15.11: + dependencies: + cookie-es: 1.2.3 + crossws: 0.3.5 + defu: 6.1.7 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.5 + radix3: 1.1.2 + ufo: 1.6.4 + uncrypto: 0.1.3 + hasown@2.0.4: dependencies: function-bind: 1.1.2 optional: true + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.5 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.2.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.5 + html-encoding-sniffer@7.0.0(@noble/hashes@2.4.0): dependencies: '@exodus/bytes': 1.16.0(@noble/hashes@2.4.0) transitivePeerDependencies: - '@noble/hashes' + html-escaper@3.0.3: {} + + html-void-elements@3.0.0: {} + + http-cache-semantics@4.3.0: {} + husky@9.1.7: {} iconv-lite@0.6.3: @@ -3971,6 +6166,8 @@ snapshots: iota-array@1.0.0: {} + iron-webcrypto@1.2.1: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -3982,16 +6179,24 @@ snapshots: hasown: 2.0.4 optional: true + is-docker@4.0.0: {} + is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-number@7.0.0: {} + is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-unsafe@2.0.2: {} + is-what@4.1.16: optional: true @@ -4028,14 +6233,22 @@ snapshots: jsesc@3.1.0: {} + json-schema-traverse@1.0.0: {} + json5@2.2.3: {} + jsonc-parser@2.3.1: {} + + jsonc-parser@3.3.1: {} + jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 jwt-decode@4.0.0: {} + kleur@4.1.5: {} + lerc@3.0.0: {} lerp@1.0.3: {} @@ -4189,6 +6402,12 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.6.0 + magicast@0.5.5: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + source-map-js: 1.2.2 + make-dir@3.1.0: dependencies: semver: 7.5.2 @@ -4205,8 +6424,39 @@ snapshots: tiny-emitter: 2.1.0 typed-function: 4.2.2 + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.4.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdn-data@2.0.14: {} + mdn-data@2.27.1: {} + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.3 + + micromark-util-encode@2.0.1: {} + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.3: {} + mime@1.6.0: optional: true @@ -4216,8 +6466,12 @@ snapshots: dependencies: brace-expansion: 1.1.21 + mrmime@2.0.1: {} + ms@2.1.3: {} + muggle-string@0.4.1: {} + nanoid@3.3.19: {} ndarray@1.0.19: @@ -4231,10 +6485,24 @@ snapshots: sax: 1.6.0 optional: true + neotraverse@1.0.1: {} + + nlcst-to-string@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + + node-fetch-native@1.6.7: {} + + node-mock-http@1.0.5: {} + node-releases@2.0.57: {} normalize-path@3.0.0: {} + nth-check@2.0.1: + dependencies: + boolbase: 1.0.0 + numcodecs@0.3.2: dependencies: fflate: 0.8.3 @@ -4243,6 +6511,16 @@ snapshots: obug@2.2.1: {} + obug@3.0.0: {} + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.4 + + ohash@2.0.12: {} + oidc-client-ts@3.5.0: dependencies: jwt-decode: 4.0.0 @@ -4260,18 +6538,39 @@ snapshots: dependencies: wrappy: 1.0.2 + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + p-limit@2.3.0: dependencies: p-try: 2.2.0 + p-limit@7.3.3: + dependencies: + yocto-queue: 1.2.2 + p-locate@4.1.0: dependencies: p-limit: 2.3.0 p-map@7.1.0: {} + p-queue@9.3.3: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.2 + + p-timeout@7.0.2: {} + p-try@2.2.0: {} + package-manager-detector@1.9.0: {} + pako@2.1.0: {} parse-headers@2.0.6: {} @@ -4283,8 +6582,12 @@ snapshots: dependencies: entities: 8.1.0 + path-browserify@1.0.1: {} + path-exists@4.0.0: {} + path-expression-matcher@1.6.2: {} + path-is-absolute@1.0.1: {} path-parse@1.0.7: @@ -4294,6 +6597,8 @@ snapshots: dependencies: resolve-protobuf-schema: 2.1.0 + piccolore@0.1.3: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -4314,18 +6619,34 @@ snapshots: dependencies: find-up: 4.1.0 + playwright-core@1.57.0: {} + + playwright@1.57.0: + dependencies: + playwright-core: 1.57.0 + optionalDependencies: + fsevents: 2.3.2 + postcss@8.5.25: dependencies: nanoid: 3.3.19 picocolors: 1.1.1 source-map-js: 1.2.2 + prettier@3.9.10: {} + pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 ansi-styles: 5.2.0 react-is: 17.0.2 + prismjs@1.30.0: {} + + process-ancestry@0.1.0: {} + + property-information@7.2.0: {} + protocol-buffers-schema@3.6.1: {} prr@1.0.1: @@ -4337,6 +6658,8 @@ snapshots: quickselect@3.0.0: {} + radix3@1.1.2: {} + rbush@4.0.1: dependencies: quickselect: 3.0.0 @@ -4395,6 +6718,10 @@ snapshots: dependencies: picomatch: 2.3.2 + readdirp@4.1.2: {} + + readdirp@5.1.1: {} + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -4402,8 +6729,24 @@ snapshots: reference-spec-reader@0.2.0: {} + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + request-light@0.5.8: {} + + request-light@0.7.0: {} + require-from-string@2.0.2: {} + resolve-pkg-maps@1.0.0: {} + resolve-protobuf-schema@2.1.0: dependencies: protocol-buffers-schema: 3.6.1 @@ -4416,6 +6759,12 @@ snapshots: supports-preserve-symlinks-flag: 1.0.0 optional: true + retext-smartypants@6.2.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.1.0 + retry@0.13.1: {} rolldown@1.2.13: @@ -4442,8 +6791,24 @@ snapshots: safer-buffer@2.1.2: optional: true - sax@1.6.0: - optional: true + satteri@0.10.5: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.5 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + optionalDependencies: + '@bruits/satteri-darwin-arm64': 0.10.5 + '@bruits/satteri-darwin-x64': 0.10.5 + '@bruits/satteri-linux-arm64-gnu': 0.10.5 + '@bruits/satteri-linux-arm64-musl': 0.10.5 + '@bruits/satteri-linux-x64-gnu': 0.10.5 + '@bruits/satteri-linux-x64-musl': 0.10.5 + '@bruits/satteri-wasm32-wasi': 0.10.5 + '@bruits/satteri-win32-arm64-msvc': 0.10.5 + '@bruits/satteri-win32-x64-msvc': 0.10.5 + + sax@1.6.0: {} saxes@6.0.0: dependencies: @@ -4457,6 +6822,62 @@ snapshots: dependencies: lru-cache: 6.0.0 + sharp@0.35.5(@types/node@24.19.2): + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.5.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.5 + '@img/sharp-darwin-x64': 0.35.5 + '@img/sharp-freebsd-wasm32': 0.35.5 + '@img/sharp-libvips-darwin-arm64': 1.3.4 + '@img/sharp-libvips-darwin-x64': 1.3.4 + '@img/sharp-libvips-linux-arm': 1.3.4 + '@img/sharp-libvips-linux-arm64': 1.3.4 + '@img/sharp-libvips-linux-ppc64': 1.3.4 + '@img/sharp-libvips-linux-riscv64': 1.3.4 + '@img/sharp-libvips-linux-s390x': 1.3.4 + '@img/sharp-libvips-linux-x64': 1.3.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + '@img/sharp-linux-arm': 0.35.5 + '@img/sharp-linux-arm64': 0.35.5 + '@img/sharp-linux-ppc64': 0.35.5 + '@img/sharp-linux-riscv64': 0.35.5 + '@img/sharp-linux-s390x': 0.35.5 + '@img/sharp-linux-x64': 0.35.5 + '@img/sharp-linuxmusl-arm64': 0.35.5 + '@img/sharp-linuxmusl-x64': 0.35.5 + '@img/sharp-webcontainers-wasm32': 0.35.5 + '@img/sharp-win32-arm64': 0.35.5 + '@img/sharp-win32-ia32': 0.35.5 + '@img/sharp-win32-x64': 0.35.5 + '@types/node': 24.19.2 + optional: true + + shiki@4.5.0: + dependencies: + '@shikijs/core': 4.5.0 + '@shikijs/engine-javascript': 4.5.0 + '@shikijs/engine-oniguruma': 4.5.0 + '@shikijs/langs': 4.5.0 + '@shikijs/themes': 4.5.0 + '@shikijs/types': 4.5.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.5 + + sisteransi@1.0.5: {} + + sitemap@9.0.1: + dependencies: + '@types/node': 24.19.2 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + + smol-toml@1.9.1: {} + source-map-js@1.2.2: {} source-map-support@0.5.21: @@ -4465,11 +6886,44 @@ snapshots: source-map: 0.6.1 optional: true - source-map@0.6.1: - optional: true + source-map@0.6.1: {} + + space-separated-tokens@2.0.2: {} + + stable@0.1.8: {} std-env@4.3.0: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 + + string-width@8.3.0: + dependencies: + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.4.0 + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -4478,9 +6932,23 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 + strnum@2.5.1: + dependencies: + anynum: 1.0.1 + supports-preserve-symlinks-flag@1.0.0: optional: true + svgo@2.8.4: + dependencies: + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + sax: 1.6.0 + stable: 0.1.8 + tailwind-merge@3.7.0: {} tailwindcss@4.3.3: {} @@ -4497,8 +6965,12 @@ snapshots: tiny-emitter@2.1.0: {} + tiny-inflate@1.0.3: {} + tinybench@6.2.1: {} + tinyclip@1.0.3: {} + tinyexec@1.3.1: {} tinyglobby@0.2.17: @@ -4524,16 +6996,28 @@ snapshots: dependencies: punycode: 2.3.1 + trim-lines@3.0.1: {} + trim-repeated@1.0.0: dependencies: escape-string-regexp: 1.0.5 + trough@2.2.0: {} + tslib@2.8.1: {} tw-animate-css@1.4.0: {} typed-function@4.2.2: {} + typesafe-path@0.2.2: {} + + typescript-auto-import-cache@0.3.6: + dependencies: + semver: 7.5.2 + + typescript@5.9.3: {} + typescript@7.0.2: optionalDependencies: '@typescript/typescript-aix-ppc64': 7.0.2 @@ -4557,12 +7041,68 @@ snapshots: '@typescript/typescript-win32-arm64': 7.0.2 '@typescript/typescript-win32-x64': 7.0.2 + ufo@1.6.4: {} + + ultrahtml@1.7.0: {} + + uncrypto@0.1.3: {} + undici-types@7.24.6: {} undici@8.11.2: {} + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unifont@0.7.5: + dependencies: + css-tree: 3.2.1 + ohash: 2.0.12 + undici: 8.11.2 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + universalify@0.1.2: {} + unstorage@1.17.5: + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.11 + lru-cache: 11.5.3 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.4 + unzipit@2.0.0: {} update-browserslist-db@1.2.3(browserslist@4.28.7): @@ -4590,15 +7130,27 @@ snapshots: uuid@9.0.1: {} - vite-plugin-static-copy@4.1.1(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)): + verkit@0.5.0: {} + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite-plugin-static-copy@4.1.1(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)): dependencies: chokidar: 3.6.0 p-map: 7.1.0 picocolors: 1.1.1 tinyglobby: 0.2.17 - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) - vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0): + vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1): dependencies: lightningcss: 1.33.0 picomatch: 4.0.7 @@ -4611,11 +7163,16 @@ snapshots: jiti: 2.7.0 less: 4.6.4 terser: 5.48.0 + yaml: 2.9.1 + + vitefu@1.1.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)): + optionalDependencies: + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) - vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)): + vitest@5.0.3(@types/node@24.19.2)(jsdom@30.1.2(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)): dependencies: '@types/chai': 5.2.3 - '@vitest/mocker': 5.0.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)) + '@vitest/mocker': 5.0.3(vite@8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1)) chai: 6.3.0 es-module-lexer: 2.3.2 expect-type: 1.4.0 @@ -4626,7 +7183,7 @@ snapshots: tinybench: 6.2.1 tinyexec: 1.3.1 tinyglobby: 0.2.17 - vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0) + vite: 8.3.4(@types/node@24.19.2)(jiti@2.7.0)(less@4.6.4)(terser@5.48.0)(yaml@2.9.1) why-is-node-running: 3.2.1 optionalDependencies: '@types/node': 24.19.2 @@ -4634,6 +7191,112 @@ snapshots: transitivePeerDependencies: - msw + volar-service-css@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-css-languageservice: 6.3.10 + vscode-languageserver-textdocument: 1.0.15 + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-emmet@0.0.71(@volar/language-service@2.4.28): + dependencies: + '@emmetio/css-parser': 0.4.1 + '@emmetio/html-matcher': 1.3.0 + '@vscode/emmet-helper': 2.11.0 + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-html@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-html-languageservice: 5.6.2 + vscode-languageserver-textdocument: 1.0.15 + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-prettier@0.0.71(@volar/language-service@2.4.28)(prettier@3.9.10): + dependencies: + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + prettier: 3.9.10 + + volar-service-typescript-twoslash-queries@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-typescript@0.0.71(@volar/language-service@2.4.28): + dependencies: + path-browserify: 1.0.1 + semver: 7.5.2 + typescript-auto-import-cache: 0.3.6 + vscode-languageserver-textdocument: 1.0.15 + vscode-nls: 5.2.0 + vscode-uri: 3.2.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + volar-service-yaml@0.0.71(@volar/language-service@2.4.28): + dependencies: + vscode-uri: 3.2.0 + yaml-language-server: 1.23.0 + optionalDependencies: + '@volar/language-service': 2.4.28 + + vscode-css-languageservice@6.3.10: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.15 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.2.0 + + vscode-html-languageservice@5.6.2: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.15 + vscode-languageserver-types: 3.18.4 + vscode-uri: 3.2.0 + + vscode-json-languageservice@4.1.8: + dependencies: + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.15 + vscode-languageserver-types: 3.18.4 + vscode-nls: 5.2.0 + vscode-uri: 3.2.0 + + vscode-jsonrpc@8.2.0: {} + + vscode-jsonrpc@9.0.3: {} + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-protocol@3.18.4: + dependencies: + vscode-jsonrpc: 9.0.3 + vscode-languageserver-types: 3.18.4 + + vscode-languageserver-textdocument@1.0.15: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver-types@3.18.4: {} + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-nls@5.2.0: {} + + vscode-uri@3.2.0: {} + w3c-xmlserializer@6.0.0: dependencies: xml-name-validator: 5.0.0 @@ -4654,21 +7317,69 @@ snapshots: why-is-node-running@3.2.1: {} + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrappy@1.0.2: {} xml-name-validator@5.0.0: {} + xml-naming@0.3.0: {} + xml-utils@1.10.2: {} xmlchars@2.2.0: {} + xxhash-wasm@1.1.0: {} + + y18n@5.0.8: {} + yallist@3.1.1: {} yallist@4.0.0: {} + yaml-language-server@1.23.0: + dependencies: + '@vscode/l10n': 0.0.18 + ajv: 8.20.0 + ajv-draft-04: 1.0.0(ajv@8.20.0) + ajv-i18n: 4.2.0(ajv@8.20.0) + prettier: 3.9.10 + request-light: 0.5.8 + vscode-json-languageservice: 4.1.8 + vscode-languageserver: 9.0.1 + vscode-languageserver-textdocument: 1.0.15 + vscode-languageserver-types: 3.18.4 + vscode-uri: 3.2.0 + yaml: 2.8.3 + + yaml@2.8.3: {} + + yaml@2.9.1: {} + + yargs-parser@22.0.0: {} + + yargs@18.2.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 8.3.0 + y18n: 5.0.8 + yargs-parser: 22.0.0 + + yocto-queue@1.2.2: {} + zarrita@0.7.3: dependencies: '@zarrita/storage': 0.2.0 numcodecs: 0.3.2 + zod@4.6.5: {} + zstddec@0.2.0: {} + + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4f899842..c8b616fd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,7 @@ +packages: + - '.' + - website + shamefullyHoist: true strictPeerDependencies: false @@ -6,6 +10,7 @@ allowBuilds: core-js: true core-js-pure: true dicom-microscopy-viewer: true + esbuild: true overrides: '@types/d3-dispatch': 3.0.6 diff --git a/src/styles/globals.css b/src/styles/globals.css index 65dd4791..976d5117 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,230 +1,7 @@ @import 'tailwindcss'; @import 'tw-animate-css'; -@custom-variant dark (&:where(.dark, .dark *)); - -/* - * Design tokens for utilities. Colours and shadows read the light/dark - * variables defined in the base layer below, so `.dark` switches them at - * runtime. Custom keys must also be registered in src/lib/utils.ts so - * tailwind-merge resolves conflicts between them. - */ -@theme { - --color-app: rgb(var(--app)); - --color-panel: rgb(var(--panel)); - --color-subtle: rgb(var(--subtle)); - --color-selected: rgb(var(--selected)); - - --color-ink: rgb(var(--ink)); - --color-ink-body: rgb(var(--ink-body)); - --color-ink-secondary: rgb(var(--ink-secondary)); - --color-ink-muted: rgb(var(--ink-muted)); - --color-ink-faint: rgb(var(--ink-faint)); - --color-ink-fainter: rgb(var(--ink-fainter)); - - --color-line: rgb(var(--line)); - --color-line-soft: rgb(var(--line-soft)); - --color-line-row: rgb(var(--line-row)); - --color-line-input: rgb(var(--line-input)); - --color-line-hover: rgb(var(--line-hover)); - - --color-chip: rgb(var(--chip)); - --color-chip-foreground: rgb(var(--chip-foreground)); - - --color-segmented: rgb(var(--segmented)); - --color-segmented-active: rgb(var(--segmented-active)); - - --color-switch-off: rgb(var(--switch-off)); - - --color-viewport: rgb(var(--viewport)); - --color-viewport-fluorescence: rgb(var(--viewport-fluorescence)); - - --color-overlay-card: rgb(var(--overlay-card)); - --color-scrim: rgb(var(--scrim)); - - --color-syntax-boolean: rgb(var(--syntax-boolean)); - --color-syntax-string: rgb(var(--syntax-string)); - - --color-ring: rgb(var(--primary)); - /* Logo tile background; matches public/favicon.svg in both themes */ - --color-brand: rgb(var(--brand)); - - --color-primary: rgb(var(--primary)); - --color-primary-hover: rgb(var(--primary-hover)); - --color-primary-soft: rgb(var(--primary-soft)); - --color-primary-foreground: rgb(var(--primary-foreground)); - - --color-destructive: rgb(var(--destructive)); - --color-destructive-text: rgb(var(--destructive-text)); - --color-destructive-soft: rgb(var(--destructive-soft)); - --color-destructive-hover: rgb(var(--destructive-hover)); - --color-destructive-foreground: rgb(var(--destructive-foreground)); - - --color-success: rgb(var(--success)); - - --color-warning: rgb(var(--warning)); - --color-warning-soft: rgb(var(--warning-soft)); - --color-warning-text: rgb(var(--warning-text)); - - --radius-lg: var(--radius); - --radius-md: calc(var(--radius) - 2px); - --radius-sm: calc(var(--radius) - 4px); - /* Cards, menus and option tiles */ - --radius-card: 10px; - /* Icon tiles in dialog headers */ - --radius-tile: 9px; - - /* Tinted with the segmented track colour, not --shadow-color */ - --shadow-segmented: 0 1px 2px rgb(var(--segmented)); - --shadow-tool: 0 1px 2px rgb(var(--shadow-color) / 0.14); - --shadow-overlay: 0 2px 8px rgb(var(--shadow-color) / 0.08); - --shadow-menu: 0 12px 32px rgb(var(--shadow-color) / 0.14); - --shadow-modal: 0 24px 64px rgb(var(--shadow-color) / 0.22); - --shadow-selected-ring: 0 0 0 3px rgb(var(--primary) / 0.12); - - --font-sans: - 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', - Roboto, 'Helvetica Neue', Arial, sans-serif; - --font-mono: - 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - monospace; - - /* - * Design type scale in px; sizes only, line height stays inherited. - * `_` stands for the dot in class names: `--text-11_5` is `text-11.5`. - */ - --text-11: 11px; - --text-11_5: 11.5px; - --text-12: 12px; - --text-12_5: 12.5px; - --text-13: 13px; - - /* Default control height (buttons, inputs, icon tiles) */ - --spacing-control: 34px; - - --width-sidebar: 288px; - --width-sidebar-right: 320px; - - --height-header: 52px; - --height-toolbar: 40px; - --height-footer: 28px; -} - -@layer base { - /* - * Slim v2 design tokens, stored as RGB triplets so plain CSS can add alpha - * (`rgb(var(--primary) / 0.08)`); utilities use the `--color-*` theme keys. - */ - :root { - --app: 242 244 247; /* #f2f4f7 */ - --panel: 255 255 255; /* #ffffff */ - --subtle: 247 249 251; /* #f7f9fb */ - --selected: 244 247 253; /* #f4f7fd */ - - --ink: 15 26 42; /* #0f1a2a */ - --ink-body: 42 53 70; /* #2a3546 */ - --ink-secondary: 74 85 102; /* #4a5566 */ - --ink-muted: 107 118 134; /* #6b7686 */ - --ink-faint: 138 148 163; /* #8a94a3 */ - --ink-fainter: 160 169 182; /* #a0a9b6 */ - - --line: 228 232 238; /* #e4e8ee */ - --line-soft: 238 241 245; /* #eef1f5 */ - --line-row: 240 242 246; /* #f0f2f6 */ - --line-input: 217 222 230; /* #d9dee6 */ - --line-hover: 185 199 228; /* #b9c7e4 */ - - --chip: 238 242 248; /* #eef2f8 */ - --chip-foreground: 52 66 90; /* #34425a */ - --segmented: 233 236 241; /* #e9ecf1 */ - --segmented-active: 255 255 255; /* #ffffff */ - --switch-off: 201 208 218; /* #c9d0da */ - - --primary: 31 90 209; /* #1f5ad1 */ - --primary-hover: 23 71 168; /* #1747a8 */ - --primary-soft: 234 240 252; /* #eaf0fc */ - --primary-foreground: 255 255 255; - - --success: 31 157 107; /* #1f9d6b */ - --success-foreground: 255 255 255; - --warning: 217 138 31; /* #d98a1f */ - --warning-soft: 252 241 222; /* #fcf1de */ - --warning-text: 138 86 12; /* #8a560c */ - --warning-foreground: 255 255 255; - --destructive: 217 69 59; /* #d9453b */ - --destructive-text: 184 53 44; /* #b8352c */ - --destructive-soft: 251 233 231; /* #fbe9e7 */ - --destructive-hover: 253 241 240; /* #fdf1f0 */ - --destructive-foreground: 255 255 255; - - --viewport: 251 249 250; /* #fbf9fa */ - --viewport-fluorescence: 11 16 32; /* #0b1020 */ - --overlay-card: 255 255 255; - --scrim: 15 26 42; - --stripe-a: 245 247 250; /* #f5f7fa */ - --stripe-b: 238 241 245; /* #eef1f5 */ - - --shadow-color: 15 26 42; - - /* Logo tile; same in both themes, matches public/favicon.svg */ - --brand: 61 79 107; /* #3d4f6b */ - - /* Value colors in the Preferences > Configuration tree */ - --syntax-boolean: 122 75 209; /* #7a4bd1 */ - --syntax-string: 29 122 85; /* #1d7a55 */ - - --radius: 8px; - } - - .dark { - --app: 12 17 25; /* #0c1119 */ - --panel: 21 27 38; /* #151b26 */ - --subtle: 17 23 34; /* #111722 */ - --selected: 24 35 58; /* #18233a */ - - --ink: 232 237 245; /* #e8edf5 */ - --ink-body: 201 210 223; /* #c9d2df */ - --ink-secondary: 167 177 194; /* #a7b1c2 */ - --ink-muted: 139 151 170; /* #8b97aa */ - --ink-faint: 111 123 142; /* #6f7b8e */ - --ink-fainter: 93 104 120; /* #5d6878 */ - - --line: 38 48 65; /* #263041 */ - --line-soft: 29 37 50; /* #1d2532 */ - --line-row: 29 37 50; /* #1d2532 */ - --line-input: 52 64 84; /* #344054 */ - --line-hover: 59 79 117; /* #3b4f75 */ - - --chip: 31 40 56; /* #1f2838 */ - --chip-foreground: 201 210 223; /* #c9d2df */ - --segmented: 34 43 58; /* #222b3a */ - --segmented-active: 38 48 65; /* #263041 */ - --switch-off: 52 64 84; /* #344054 */ - - --primary: 74 134 245; /* #4a86f5 */ - --primary-hover: 120 166 255; /* #78a6ff */ - --primary-soft: 23 40 74; /* #17284a */ - --primary-foreground: 255 255 255; - - --warning-soft: 58 42 18; - --warning-text: 240 180 90; - --destructive-text: 240 120 110; - --destructive-soft: 60 26 26; - --destructive-hover: 44 24 28; - - --viewport: 10 14 21; /* #0a0e15 */ - --viewport-fluorescence: 5 7 11; /* #05070b */ - --overlay-card: 21 27 38; - --scrim: 0 0 0; - --stripe-a: 24 31 43; - --stripe-b: 29 37 50; - - --shadow-color: 0 0 0; - - --syntax-boolean: 169 139 240; /* #a98bf0 */ - --syntax-string: 79 195 154; /* #4fc39a */ - } -} +@import './tokens.css'; @layer base { * { diff --git a/src/styles/tokens.css b/src/styles/tokens.css new file mode 100644 index 00000000..2b8bab6e --- /dev/null +++ b/src/styles/tokens.css @@ -0,0 +1,229 @@ +/* + * Slim v2 design tokens, shared by the app (src/styles/globals.css) and the + * website (website/src/styles/site.css). Import after 'tailwindcss'. + */ + +@custom-variant dark (&:where(.dark, .dark *)); + +/* + * Design tokens for utilities. Colours and shadows read the light/dark + * variables defined in the base layer below, so `.dark` switches them at + * runtime. Custom keys must also be registered in src/lib/utils.ts so + * tailwind-merge resolves conflicts between them. + */ +@theme { + --color-app: rgb(var(--app)); + --color-panel: rgb(var(--panel)); + --color-subtle: rgb(var(--subtle)); + --color-selected: rgb(var(--selected)); + + --color-ink: rgb(var(--ink)); + --color-ink-body: rgb(var(--ink-body)); + --color-ink-secondary: rgb(var(--ink-secondary)); + --color-ink-muted: rgb(var(--ink-muted)); + --color-ink-faint: rgb(var(--ink-faint)); + --color-ink-fainter: rgb(var(--ink-fainter)); + + --color-line: rgb(var(--line)); + --color-line-soft: rgb(var(--line-soft)); + --color-line-row: rgb(var(--line-row)); + --color-line-input: rgb(var(--line-input)); + --color-line-hover: rgb(var(--line-hover)); + + --color-chip: rgb(var(--chip)); + --color-chip-foreground: rgb(var(--chip-foreground)); + + --color-segmented: rgb(var(--segmented)); + --color-segmented-active: rgb(var(--segmented-active)); + + --color-switch-off: rgb(var(--switch-off)); + + --color-viewport: rgb(var(--viewport)); + --color-viewport-fluorescence: rgb(var(--viewport-fluorescence)); + + --color-overlay-card: rgb(var(--overlay-card)); + --color-scrim: rgb(var(--scrim)); + + --color-syntax-boolean: rgb(var(--syntax-boolean)); + --color-syntax-string: rgb(var(--syntax-string)); + + --color-ring: rgb(var(--primary)); + /* Logo tile background; matches public/favicon.svg in both themes */ + --color-brand: rgb(var(--brand)); + + --color-primary: rgb(var(--primary)); + --color-primary-hover: rgb(var(--primary-hover)); + --color-primary-soft: rgb(var(--primary-soft)); + --color-primary-foreground: rgb(var(--primary-foreground)); + + --color-destructive: rgb(var(--destructive)); + --color-destructive-text: rgb(var(--destructive-text)); + --color-destructive-soft: rgb(var(--destructive-soft)); + --color-destructive-hover: rgb(var(--destructive-hover)); + --color-destructive-foreground: rgb(var(--destructive-foreground)); + + --color-success: rgb(var(--success)); + + --color-warning: rgb(var(--warning)); + --color-warning-soft: rgb(var(--warning-soft)); + --color-warning-text: rgb(var(--warning-text)); + + --radius-lg: var(--radius); + --radius-md: calc(var(--radius) - 2px); + --radius-sm: calc(var(--radius) - 4px); + /* Cards, menus and option tiles */ + --radius-card: 10px; + /* Icon tiles in dialog headers */ + --radius-tile: 9px; + + /* Tinted with the segmented track colour, not --shadow-color */ + --shadow-segmented: 0 1px 2px rgb(var(--segmented)); + --shadow-tool: 0 1px 2px rgb(var(--shadow-color) / 0.14); + --shadow-overlay: 0 2px 8px rgb(var(--shadow-color) / 0.08); + --shadow-menu: 0 12px 32px rgb(var(--shadow-color) / 0.14); + --shadow-modal: 0 24px 64px rgb(var(--shadow-color) / 0.22); + --shadow-selected-ring: 0 0 0 3px rgb(var(--primary) / 0.12); + + --font-sans: + 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', + Roboto, 'Helvetica Neue', Arial, sans-serif; + --font-mono: + 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + monospace; + + /* + * Design type scale in px; sizes only, line height stays inherited. + * `_` stands for the dot in class names: `--text-11_5` is `text-11.5`. + */ + --text-11: 11px; + --text-11_5: 11.5px; + --text-12: 12px; + --text-12_5: 12.5px; + --text-13: 13px; + + /* Default control height (buttons, inputs, icon tiles) */ + --spacing-control: 34px; + + --width-sidebar: 288px; + --width-sidebar-right: 320px; + + --height-header: 52px; + --height-toolbar: 40px; + --height-footer: 28px; +} + +@layer base { + /* + * Slim v2 design tokens, stored as RGB triplets so plain CSS can add alpha + * (`rgb(var(--primary) / 0.08)`); utilities use the `--color-*` theme keys. + */ + :root { + --app: 242 244 247; /* #f2f4f7 */ + --panel: 255 255 255; /* #ffffff */ + --subtle: 247 249 251; /* #f7f9fb */ + --selected: 244 247 253; /* #f4f7fd */ + + --ink: 15 26 42; /* #0f1a2a */ + --ink-body: 42 53 70; /* #2a3546 */ + --ink-secondary: 74 85 102; /* #4a5566 */ + --ink-muted: 107 118 134; /* #6b7686 */ + --ink-faint: 138 148 163; /* #8a94a3 */ + --ink-fainter: 160 169 182; /* #a0a9b6 */ + + --line: 228 232 238; /* #e4e8ee */ + --line-soft: 238 241 245; /* #eef1f5 */ + --line-row: 240 242 246; /* #f0f2f6 */ + --line-input: 217 222 230; /* #d9dee6 */ + --line-hover: 185 199 228; /* #b9c7e4 */ + + --chip: 238 242 248; /* #eef2f8 */ + --chip-foreground: 52 66 90; /* #34425a */ + --segmented: 233 236 241; /* #e9ecf1 */ + --segmented-active: 255 255 255; /* #ffffff */ + --switch-off: 201 208 218; /* #c9d0da */ + + --primary: 31 90 209; /* #1f5ad1 */ + --primary-hover: 23 71 168; /* #1747a8 */ + --primary-soft: 234 240 252; /* #eaf0fc */ + --primary-foreground: 255 255 255; + + --success: 31 157 107; /* #1f9d6b */ + --success-foreground: 255 255 255; + --warning: 217 138 31; /* #d98a1f */ + --warning-soft: 252 241 222; /* #fcf1de */ + --warning-text: 138 86 12; /* #8a560c */ + --warning-foreground: 255 255 255; + --destructive: 217 69 59; /* #d9453b */ + --destructive-text: 184 53 44; /* #b8352c */ + --destructive-soft: 251 233 231; /* #fbe9e7 */ + --destructive-hover: 253 241 240; /* #fdf1f0 */ + --destructive-foreground: 255 255 255; + + --viewport: 251 249 250; /* #fbf9fa */ + --viewport-fluorescence: 11 16 32; /* #0b1020 */ + --overlay-card: 255 255 255; + --scrim: 15 26 42; + --stripe-a: 245 247 250; /* #f5f7fa */ + --stripe-b: 238 241 245; /* #eef1f5 */ + + --shadow-color: 15 26 42; + + /* Logo tile; same in both themes, matches public/favicon.svg */ + --brand: 61 79 107; /* #3d4f6b */ + + /* Value colors in the Preferences > Configuration tree */ + --syntax-boolean: 122 75 209; /* #7a4bd1 */ + --syntax-string: 29 122 85; /* #1d7a55 */ + + --radius: 8px; + } + + .dark { + --app: 12 17 25; /* #0c1119 */ + --panel: 21 27 38; /* #151b26 */ + --subtle: 17 23 34; /* #111722 */ + --selected: 24 35 58; /* #18233a */ + + --ink: 232 237 245; /* #e8edf5 */ + --ink-body: 201 210 223; /* #c9d2df */ + --ink-secondary: 167 177 194; /* #a7b1c2 */ + --ink-muted: 139 151 170; /* #8b97aa */ + --ink-faint: 111 123 142; /* #6f7b8e */ + --ink-fainter: 93 104 120; /* #5d6878 */ + + --line: 38 48 65; /* #263041 */ + --line-soft: 29 37 50; /* #1d2532 */ + --line-row: 29 37 50; /* #1d2532 */ + --line-input: 52 64 84; /* #344054 */ + --line-hover: 59 79 117; /* #3b4f75 */ + + --chip: 31 40 56; /* #1f2838 */ + --chip-foreground: 201 210 223; /* #c9d2df */ + --segmented: 34 43 58; /* #222b3a */ + --segmented-active: 38 48 65; /* #263041 */ + --switch-off: 52 64 84; /* #344054 */ + + --primary: 74 134 245; /* #4a86f5 */ + --primary-hover: 120 166 255; /* #78a6ff */ + --primary-soft: 23 40 74; /* #17284a */ + --primary-foreground: 255 255 255; + + --warning-soft: 58 42 18; + --warning-text: 240 180 90; + --destructive-text: 240 120 110; + --destructive-soft: 60 26 26; + --destructive-hover: 44 24 28; + + --viewport: 10 14 21; /* #0a0e15 */ + --viewport-fluorescence: 5 7 11; /* #05070b */ + --overlay-card: 21 27 38; + --scrim: 0 0 0; + --stripe-a: 24 31 43; + --stripe-b: 29 37 50; + + --shadow-color: 0 0 0; + + --syntax-boolean: 169 139 240; /* #a98bf0 */ + --syntax-string: 79 195 154; /* #4fc39a */ + } +} diff --git a/vite.config.ts b/vite.config.ts index 2152ba17..fad60811 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,7 +5,7 @@ import tailwindcss from '@tailwindcss/vite' import react, { reactCompilerPreset } from '@vitejs/plugin-react' import { loadEnv, normalizePath, type Plugin } from 'vite' import { viteStaticCopy } from 'vite-plugin-static-copy' -import { defineConfig } from 'vitest/config' +import { configDefaults, defineConfig } from 'vitest/config' import { resolveSlimEnv, slimEnvScript } from './scripts/slimEnv.mjs' @@ -177,6 +177,8 @@ export default defineConfig(({ mode }) => { environmentOptions: { jsdom: { url: 'http://localhost/' } }, globals: true, setupFiles: ['src/setupTests.tsx'], + /** The website package runs its own tests with node:test */ + exclude: [...configDefaults.exclude, 'website/**'], /** Matches the CRA Jest preset, which reset mocks before each test */ mockReset: true, }, diff --git a/website/.firebaserc b/website/.firebaserc new file mode 100644 index 00000000..525bd3f3 --- /dev/null +++ b/website/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "slim-website" + } +} diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 00000000..8ad6fb34 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.astro/ +.firebase/ +firebase-debug.log diff --git a/website/README.md b/website/README.md new file mode 100644 index 00000000..55b5d5c6 --- /dev/null +++ b/website/README.md @@ -0,0 +1,73 @@ +# Slim website + +The marketing and documentation site for Slim, built with [Astro](https://astro.build) as a static site. It is a pnpm workspace package inside the Slim repository and reuses the app's design tokens (`src/styles/tokens.css`), button and logo components, so the site and the viewer share one visual language. Dark is the default theme, and light is one click away. + +## Develop + +From the repository root: + +```bash +pnpm install +pnpm --filter slim-website dev # http://localhost:4321 +``` + +| Command | Purpose | +| --- | --- | +| `pnpm --filter slim-website build` | Static build into `website/dist` | +| `pnpm --filter slim-website check` | Type-check Astro, TypeScript and content schemas | +| `pnpm --filter slim-website test` | Unit tests (changelog parsing, citation, assets, no raw colors) | +| `pnpm --filter slim-website find-idc-examples` | Re-pick public IDC examples for the support matrix | +| `pnpm --filter slim-website verify-idc-examples` | Check the examples still resolve on the IDC proxy | +| `pnpm --filter slim-website capture-screenshots` | Re-capture app screenshots, thumbnails and the social card | + +Set `PUBLIC_SLIM_DEMO_URL` to point the "Open in Slim" links at another Slim deployment. The default is the deployment that serves the IDC public proxy. + +## Content + +| What | Where | +| --- | --- | +| Feature sections | `src/content/features/*.md` | +| Showcase entries | `src/content/showcase/*.md` | +| Release highlights | `src/content/releases/*.mdx` | +| Changelog | Read from `docs/CHANGELOG.md` at build time, one page per version | +| DICOM support matrix | `src/data/matrix.ts` | +| IDC examples | `src/data/idc-examples.json`, generated by `scripts/find-idc-examples.mjs` | +| Citation | Read from `CITATION.cff` at build time | +| IDC logo | `public/brand/nci-idc.svg` (official NCI lockup, from the IDC portal) and `nci-idc-reverse.svg` (white wordmark for the dark theme), shown by `src/components/IdcLogo.astro` | + +The IDC logo appears in the home hero, the "Developed and supported by" section on the home page, the about page, the footer and the social card. It links to IDC's page in the [Cancer Research Data Commons](https://datacommons.cancer.gov/repository/imaging-data-commons). Logos keep their own brand colors and live in `public/`, outside the token rule below. + +Colors must come from the shared tokens. A test fails if `website/src` contains hex or `rgb()` literals; the only exception is the `theme-color` meta values in `src/data/theme.ts`, which a second test keeps in sync with the `--app` token. + +## Screenshots + +Screenshots show the real app on public IDC data. Run the app against the IDC proxy, then capture: + +```bash +REACT_APP_CONFIG=preview \ +SLIM_PREVIEW_DICOMWEB_URL=https://proxy.imaging.datacommons.cancer.gov/current/viewer-only-no-downloads-see-tinyurl-dot-com-slash-3j3d9jyp/dicomWeb \ +pnpm start --port 3100 + +SLIM_APP_URL=http://localhost:3100 pnpm --filter slim-website capture-screenshots +``` + +To regenerate only the social card (`public/og.png`), which needs no running app, use `pnpm --filter slim-website capture-screenshots --only=og`. + +The script uses the installed Google Chrome. Set `PLAYWRIGHT_CHANNEL=` to use Playwright's bundled Chromium instead (`pnpm exec playwright install chromium`). + +## Deploy + +The site is hosted on Firebase Hosting in the `slim-website` project, at . `website/firebase.json` targets that project's default site, so the app's root `firebase.json` is unaffected. + +The same project hosts the Slim viewer the site links to, at (the `slim-app` Hosting site). It is built with `REACT_APP_CONFIG=preview`, so it reads studies from the IDC public proxy. `.github/workflows/deploy-viewer.yml` republishes it on every push to `master` that changes the app. Like the website deploy, it needs the `FIREBASE_SERVICE_ACCOUNT_SLIM` secret, plus `SLIM_PREVIEW_DICOMWEB_URL` set to the IDC proxy URL. + +`.github/workflows/deploy-website.yml` deploys every pull request that touches the site to a preview channel and comments the URL, and deploys `master` (and `feat/slim-modern-redesign`, while the site is stacked on the redesign branch) to the live channel. It authenticates with the `FIREBASE_SERVICE_ACCOUNT_SLIM` secret, a service account key from the `slim-website` project with the Firebase Hosting Admin role. A custom domain can be connected later in the Firebase console; update `SITE_URL` in the workflow when it is. + +To deploy by hand, from `website/`: + +```bash +pnpm --filter slim-website build +firebase deploy --only hosting --project slim-website +``` + +A weekly workflow, `.github/workflows/website-idc-examples.yml`, checks that every example in the support matrix still resolves on the IDC proxy and opens an issue when one breaks or a new IDC release changes the picture. diff --git a/website/astro.config.mjs b/website/astro.config.mjs new file mode 100644 index 00000000..e88024c6 --- /dev/null +++ b/website/astro.config.mjs @@ -0,0 +1,32 @@ +import { fileURLToPath } from 'node:url' +import mdx from '@astrojs/mdx' +import react from '@astrojs/react' +import sitemap from '@astrojs/sitemap' +import tailwindcss from '@tailwindcss/vite' +import { defineConfig } from 'astro/config' + +const slimSrc = fileURLToPath(new URL('../src', import.meta.url)) + +export default defineConfig({ + site: process.env.SITE_URL ?? 'https://slim-website.web.app', + output: 'static', + trailingSlash: 'ignore', + build: { + format: 'directory', + }, + integrations: [react(), mdx(), sitemap()], + vite: { + plugins: [tailwindcss()], + resolve: { + alias: { + '@slim': slimSrc, + }, + }, + server: { + fs: { + /** Shared tokens and UI primitives live in the app's src/ */ + allow: ['..'], + }, + }, + }, +}) diff --git a/website/firebase.json b/website/firebase.json new file mode 100644 index 00000000..69f473f4 --- /dev/null +++ b/website/firebase.json @@ -0,0 +1,26 @@ +{ + "hosting": { + "site": "slim-website", + "public": "dist", + "cleanUrls": true, + "trailingSlash": true, + "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], + "headers": [ + { + "source": "/_astro/**", + "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }] + }, + { + "source": "**/*.@(webp|png|svg|ico|woff2)", + "headers": [{ "key": "Cache-Control", "value": "public, max-age=86400" }] + }, + { + "source": "**", + "headers": [ + { "key": "X-Content-Type-Options", "value": "nosniff" }, + { "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" } + ] + } + ] + } +} diff --git a/website/package.json b/website/package.json new file mode 100644 index 00000000..f931ebc7 --- /dev/null +++ b/website/package.json @@ -0,0 +1,44 @@ +{ + "name": "slim-website", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "Marketing website for Slim, the DICOM slide microscopy viewer", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro build", + "preview": "astro preview", + "check": "astro check", + "test": "node --test \"tests/*.test.mjs\"", + "find-idc-examples": "node scripts/find-idc-examples.mjs", + "verify-idc-examples": "node scripts/find-idc-examples.mjs --verify", + "capture-screenshots": "node scripts/capture-screenshots.mjs" + }, + "dependencies": { + "@astrojs/mdx": "^8.0.2", + "@astrojs/react": "^7.0.0", + "@astrojs/rss": "^4.0.19", + "@astrojs/sitemap": "^3.7.4", + "@fontsource/ibm-plex-mono": "^5.3.0", + "@fontsource/ibm-plex-sans": "^5.3.0", + "@radix-ui/react-slot": "^1.3.3", + "@tailwindcss/vite": "4.3.3", + "astro": "^7.3.5", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^1.49.0", + "react": "^19.3.0", + "react-dom": "^19.3.0", + "tailwind-merge": "^3.7.0", + "tailwindcss": "4.3.3", + "yaml": "^2.9.1" + }, + "devDependencies": { + "@astrojs/check": "^0.9.10", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "playwright": "~1.57.0", + "typescript": "^5.9.3" + } +} diff --git a/website/public/brand/nci-idc-reverse.svg b/website/public/brand/nci-idc-reverse.svg new file mode 100644 index 00000000..353422aa --- /dev/null +++ b/website/public/brand/nci-idc-reverse.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/public/brand/nci-idc.svg b/website/public/brand/nci-idc.svg new file mode 100644 index 00000000..c50bc0a0 --- /dev/null +++ b/website/public/brand/nci-idc.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/public/examples/ann.webp b/website/public/examples/ann.webp new file mode 100644 index 00000000..79f20bcd Binary files /dev/null and b/website/public/examples/ann.webp differ diff --git a/website/public/examples/brightfield.webp b/website/public/examples/brightfield.webp new file mode 100644 index 00000000..facb96b7 Binary files /dev/null and b/website/public/examples/brightfield.webp differ diff --git a/website/public/examples/fluorescence.webp b/website/public/examples/fluorescence.webp new file mode 100644 index 00000000..fe4de3ea Binary files /dev/null and b/website/public/examples/fluorescence.webp differ diff --git a/website/public/examples/pmap.webp b/website/public/examples/pmap.webp new file mode 100644 index 00000000..588ce0bb Binary files /dev/null and b/website/public/examples/pmap.webp differ diff --git a/website/public/examples/presentation-state.webp b/website/public/examples/presentation-state.webp new file mode 100644 index 00000000..670c56ee Binary files /dev/null and b/website/public/examples/presentation-state.webp differ diff --git a/website/public/examples/seg-binary.webp b/website/public/examples/seg-binary.webp new file mode 100644 index 00000000..8a085f9d Binary files /dev/null and b/website/public/examples/seg-binary.webp differ diff --git a/website/public/examples/seg-fractional.webp b/website/public/examples/seg-fractional.webp new file mode 100644 index 00000000..c6405874 Binary files /dev/null and b/website/public/examples/seg-fractional.webp differ diff --git a/website/public/examples/sr.webp b/website/public/examples/sr.webp new file mode 100644 index 00000000..de8d389e Binary files /dev/null and b/website/public/examples/sr.webp differ diff --git a/website/public/favicon.ico b/website/public/favicon.ico new file mode 100644 index 00000000..ed8d8f8d Binary files /dev/null and b/website/public/favicon.ico differ diff --git a/website/public/favicon.svg b/website/public/favicon.svg new file mode 100644 index 00000000..3f3ccb6a --- /dev/null +++ b/website/public/favicon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/website/public/logo192.png b/website/public/logo192.png new file mode 100644 index 00000000..59f52404 Binary files /dev/null and b/website/public/logo192.png differ diff --git a/website/public/og.png b/website/public/og.png new file mode 100644 index 00000000..86aeea9b Binary files /dev/null and b/website/public/og.png differ diff --git a/website/public/screenshots/annotations-dark.webp b/website/public/screenshots/annotations-dark.webp new file mode 100644 index 00000000..f6c5d847 Binary files /dev/null and b/website/public/screenshots/annotations-dark.webp differ diff --git a/website/public/screenshots/annotations-light.webp b/website/public/screenshots/annotations-light.webp new file mode 100644 index 00000000..22ba253b Binary files /dev/null and b/website/public/screenshots/annotations-light.webp differ diff --git a/website/public/screenshots/draw-dark.webp b/website/public/screenshots/draw-dark.webp new file mode 100644 index 00000000..03bd852a Binary files /dev/null and b/website/public/screenshots/draw-dark.webp differ diff --git a/website/public/screenshots/draw-light.webp b/website/public/screenshots/draw-light.webp new file mode 100644 index 00000000..58c6cf10 Binary files /dev/null and b/website/public/screenshots/draw-light.webp differ diff --git a/website/public/screenshots/fluorescence-dark.webp b/website/public/screenshots/fluorescence-dark.webp new file mode 100644 index 00000000..bf05c2a7 Binary files /dev/null and b/website/public/screenshots/fluorescence-dark.webp differ diff --git a/website/public/screenshots/fluorescence-light.webp b/website/public/screenshots/fluorescence-light.webp new file mode 100644 index 00000000..8fefcc10 Binary files /dev/null and b/website/public/screenshots/fluorescence-light.webp differ diff --git a/website/public/screenshots/preferences-dark.webp b/website/public/screenshots/preferences-dark.webp new file mode 100644 index 00000000..53d79ffc Binary files /dev/null and b/website/public/screenshots/preferences-dark.webp differ diff --git a/website/public/screenshots/preferences-light.webp b/website/public/screenshots/preferences-light.webp new file mode 100644 index 00000000..5184591b Binary files /dev/null and b/website/public/screenshots/preferences-light.webp differ diff --git a/website/public/screenshots/segmentation-dark.webp b/website/public/screenshots/segmentation-dark.webp new file mode 100644 index 00000000..60125bbd Binary files /dev/null and b/website/public/screenshots/segmentation-dark.webp differ diff --git a/website/public/screenshots/segmentation-light.webp b/website/public/screenshots/segmentation-light.webp new file mode 100644 index 00000000..21a4910a Binary files /dev/null and b/website/public/screenshots/segmentation-light.webp differ diff --git a/website/public/screenshots/server-dark.webp b/website/public/screenshots/server-dark.webp new file mode 100644 index 00000000..9919191b Binary files /dev/null and b/website/public/screenshots/server-dark.webp differ diff --git a/website/public/screenshots/server-light.webp b/website/public/screenshots/server-light.webp new file mode 100644 index 00000000..d628cbe4 Binary files /dev/null and b/website/public/screenshots/server-light.webp differ diff --git a/website/public/screenshots/viewer-dark.webp b/website/public/screenshots/viewer-dark.webp new file mode 100644 index 00000000..d4ccc712 Binary files /dev/null and b/website/public/screenshots/viewer-dark.webp differ diff --git a/website/public/screenshots/viewer-light.webp b/website/public/screenshots/viewer-light.webp new file mode 100644 index 00000000..b065b842 Binary files /dev/null and b/website/public/screenshots/viewer-light.webp differ diff --git a/website/public/screenshots/worklist-dark.webp b/website/public/screenshots/worklist-dark.webp new file mode 100644 index 00000000..b2c59b8d Binary files /dev/null and b/website/public/screenshots/worklist-dark.webp differ diff --git a/website/public/screenshots/worklist-light.webp b/website/public/screenshots/worklist-light.webp new file mode 100644 index 00000000..9b371070 Binary files /dev/null and b/website/public/screenshots/worklist-light.webp differ diff --git a/website/scripts/capture-screenshots.mjs b/website/scripts/capture-screenshots.mjs new file mode 100644 index 00000000..c0a05d5b --- /dev/null +++ b/website/scripts/capture-screenshots.mjs @@ -0,0 +1,345 @@ +#!/usr/bin/env node +/** + * Captures the screenshots the website shows, from a running Slim app that + * loads data from the IDC public proxy: + * + * REACT_APP_CONFIG=preview SLIM_PREVIEW_DICOMWEB_URL= pnpm start --port 3100 + * SLIM_APP_URL=http://localhost:3100 pnpm --filter slim-website capture-screenshots + * + * Writes public/screenshots/{name}-{dark,light}.webp (1440x900), + * public/examples/{id}.webp thumbnails, and public/og.png (1200x630). + * + * Flags: --only=viewer,worklist --skip-examples --skip-og + * --only=og renders just the social card, which needs no running app. + * Env: SLIM_APP_URL, PLAYWRIGHT_CHANNEL (default "chrome"; "" for bundled Chromium) + */ +import { mkdir, readFile, writeFile } from 'node:fs/promises' +import { createRequire } from 'node:module' +import { chromium } from 'playwright' + +const require = createRequire(import.meta.url) +const root = new URL('..', import.meta.url) +const appUrl = (process.env.SLIM_APP_URL ?? 'http://localhost:3100').replace( + /\/+$/, + '', +) +const channel = process.env.PLAYWRIGHT_CHANNEL ?? 'chrome' + +const args = new Map( + process.argv.slice(2).map((arg) => { + const [key, value = 'true'] = arg.replace(/^--/, '').split('=') + return [key, value] + }), +) +const only = args.get('only')?.split(',') + +const VIEWPORT = { width: 1440, height: 900 } +const THEMES = ['dark', 'light'] +const LOAD_TIMEOUT = 120_000 + +const { examples } = JSON.parse( + await readFile(new URL('src/data/idc-examples.json', root), 'utf8'), +) +const byId = new Map( + examples.filter((example) => example.available).map((e) => [e.id, e]), +) + +function viewerPath(id) { + const example = byId.get(id) + if (!example) + throw new Error(`No available example "${id}" in idc-examples.json`) + const path = `/studies/${example.studyInstanceUID}/series/${example.seriesInstanceUID}` + return example.stateInstanceUID + ? `${path}?state=${example.stateInstanceUID}` + : path +} + +/** + * Waits until no loading indicator is visible, then gives tiles a moment to + * settle. The indicators fade out but stay in the DOM, so only visible ones count. + */ +async function waitForApp(page) { + await page.waitForFunction( + () => { + const loading = /Loading (studies|study|slide)/ + const visibleIndicator = [...document.querySelectorAll('body *')].some( + (element) => + [...element.childNodes].some( + (node) => + node.nodeType === Node.TEXT_NODE && + loading.test(node.textContent ?? ''), + ) && + element.checkVisibility({ + opacityProperty: true, + visibilityProperty: true, + }), + ) + return document.body.innerText.length > 0 && !visibleIndicator + }, + undefined, + { timeout: LOAD_TIMEOUT, polling: 500 }, + ) + await page + .waitForLoadState('networkidle', { timeout: 20_000 }) + .catch(() => {}) + await page.waitForTimeout(2500) +} + +async function openDialog(page, buttonName, menuItem) { + await page.getByRole('button', { name: buttonName }).first().click() + if (menuItem) + await page.getByRole('menuitem', { name: menuItem }).first().click() + await page.getByRole('dialog').first().waitFor({ timeout: 15_000 }) + await page.waitForTimeout(600) +} + +const SHOTS = [ + { name: 'worklist', path: '/?contains=ann' }, + { name: 'viewer', path: viewerPath('brightfield'), example: 'brightfield' }, + { name: 'annotations', path: viewerPath('ann'), example: 'ann' }, + { + name: 'segmentation', + path: viewerPath('seg-fractional'), + example: 'seg-fractional', + }, + { + name: 'fluorescence', + path: viewerPath('fluorescence'), + example: 'fluorescence', + }, + { name: 'draw', path: viewerPath('sr'), example: 'sr' }, + { + name: 'server', + path: '/', + action: (page) => openDialog(page, 'Select server'), + }, + { + name: 'preferences', + path: '/', + action: (page) => openDialog(page, /Guest|Not signed in/, 'Preferences'), + }, +] + +/** Encodes a PNG as WebP (optionally resized) with the browser's canvas encoder */ +async function toWebp(encoder, png, { width, height, quality = 0.84 } = {}) { + const dataUrl = await encoder.evaluate( + async ({ src, width, height, quality }) => { + const image = new Image() + image.src = src + await image.decode() + const canvas = document.createElement('canvas') + canvas.width = width ?? image.naturalWidth + canvas.height = height ?? image.naturalHeight + const context = canvas.getContext('2d') + context.imageSmoothingQuality = 'high' + context.drawImage(image, 0, 0, canvas.width, canvas.height) + return canvas.toDataURL('image/webp', quality) + }, + { + src: `data:image/png;base64,${png.toString('base64')}`, + width, + height, + quality, + }, + ) + return Buffer.from(dataUrl.split(',')[1], 'base64') +} + +/** The largest OpenLayers viewport on the page is the slide; the others are the overview */ +async function slideClip(page) { + return page.evaluate(() => { + const boxes = [...document.querySelectorAll('.ol-viewport')] + .map((element) => element.getBoundingClientRect()) + .filter((box) => box.width > 0 && box.height > 0) + .sort((a, b) => b.width * b.height - a.width * a.height) + const box = boxes[0] + if (!box) return undefined + return { x: box.x, y: box.y, width: box.width, height: box.height } + }) +} + +/** Crops the slide viewport to 16:10 around its centre */ +function centredClip(clip) { + const ratio = 16 / 10 + let { width, height } = clip + if (width / height > ratio) width = height * ratio + else height = width / ratio + return { + x: Math.round(clip.x + (clip.width - width) / 2), + y: Math.round(clip.y + (clip.height - height) / 2), + width: Math.round(width), + height: Math.round(height), + } +} + +async function newThemedPage(browser, theme) { + const context = await browser.newContext({ + viewport: VIEWPORT, + deviceScaleFactor: 1, + colorScheme: theme, + reducedMotion: 'reduce', + }) + await context.addInitScript((value) => { + window.localStorage.setItem('slim-theme', value) + }, theme) + return context.newPage() +} + +async function capture() { + /** Headless Chrome only offers WebGL, which the slide renderer needs, through SwiftShader */ + const browser = await chromium.launch({ + ...(channel ? { channel } : {}), + args: [ + '--enable-unsafe-swiftshader', + '--use-angle=swiftshader', + '--ignore-gpu-blocklist', + ], + }) + const encoder = await (await browser.newContext()).newPage() + const screenshotsDir = new URL('public/screenshots/', root) + const examplesDir = new URL('public/examples/', root) + await mkdir(screenshotsDir, { recursive: true }) + await mkdir(examplesDir, { recursive: true }) + + const thumbnails = new Set() + const saveThumbnail = async (page, id) => { + const clip = await slideClip(page) + if (!clip) return + const png = await page.screenshot({ clip: centredClip(clip) }) + await writeFile( + new URL(`${id}.webp`, examplesDir), + await toWebp(encoder, png, { width: 640, height: 400 }), + ) + thumbnails.add(id) + console.log(` examples/${id}.webp`) + } + + const shots = only ? SHOTS.filter((shot) => only.includes(shot.name)) : SHOTS + for (const shot of shots) { + for (const theme of THEMES) { + const page = await newThemedPage(browser, theme) + try { + await page.goto(`${appUrl}${shot.path}`, { + waitUntil: 'domcontentloaded', + }) + await waitForApp(page) + if (shot.action) await shot.action(page) + const png = await page.screenshot() + await writeFile( + new URL(`${shot.name}-${theme}.webp`, screenshotsDir), + await toWebp(encoder, png), + ) + console.log(` screenshots/${shot.name}-${theme}.webp`) + if (theme === 'dark' && shot.example && !args.has('skip-examples')) { + await saveThumbnail(page, shot.example) + } + } catch (error) { + console.error(` ✗ ${shot.name} (${theme}): ${error.message}`) + process.exitCode = 1 + } finally { + await page.context().close() + } + } + } + + if (!args.has('skip-examples') && !only) { + for (const id of byId.keys()) { + if (thumbnails.has(id)) continue + const page = await newThemedPage(browser, 'dark') + try { + await page.goto(`${appUrl}${viewerPath(id)}`, { + waitUntil: 'domcontentloaded', + }) + await waitForApp(page) + await saveThumbnail(page, id) + } catch (error) { + console.error(` ✗ examples/${id}: ${error.message}`) + process.exitCode = 1 + } finally { + await page.context().close() + } + } + } + + if (!args.has('skip-og')) await renderOgImage(browser) + await browser.close() +} + +/** Social card: brand tokens from the shared stylesheet, plus the dark viewer screenshot */ +async function renderOgImage(browser) { + const tokens = await readFile( + new URL('../src/styles/tokens.css', root), + 'utf8', + ) + const darkBlock = tokens.slice(tokens.indexOf('.dark {')) + const darkVars = darkBlock + .slice(0, darkBlock.indexOf('}')) + .replace('.dark {', '') + const font = (weight) => + readFile( + require.resolve( + `@fontsource/ibm-plex-sans/files/ibm-plex-sans-latin-${weight}-normal.woff2`, + ), + ).then((buffer) => buffer.toString('base64')) + const [regular, semibold, logo, idcLogo, viewer] = await Promise.all([ + font(400), + font(600), + readFile(new URL('public/favicon.svg', root)).then((buffer) => + buffer.toString('base64'), + ), + readFile(new URL('public/brand/nci-idc-reverse.svg', root)).then((buffer) => + buffer.toString('base64'), + ), + readFile(new URL('public/screenshots/viewer-dark.webp', root)).then( + (buffer) => buffer.toString('base64'), + ), + ]) + + const html = ` +
+
+
Slim
+

The web viewer for DICOM slide microscopy

+

Open source, zero footprint, DICOMweb native.

+
+
+ Developed and supported by + +
+
+ ` + + const page = await ( + await browser.newContext({ viewport: { width: 1200, height: 630 } }) + ).newPage() + await page.setContent(html, { waitUntil: 'load' }) + await page.evaluate(() => document.fonts.ready) + await writeFile( + new URL('public/og.png', root), + await page.screenshot({ type: 'png' }), + ) + console.log(' og.png') + await page.context().close() +} + +await capture() diff --git a/website/scripts/find-idc-examples.mjs b/website/scripts/find-idc-examples.mjs new file mode 100644 index 00000000..0e22e61e --- /dev/null +++ b/website/scripts/find-idc-examples.mjs @@ -0,0 +1,399 @@ +#!/usr/bin/env node +/** + * Picks one public IDC example per row of the DICOM support matrix and writes + * src/data/idc-examples.json. Uses the IDC REST API (POST /v3/sql), the + * no-install path of github.com/ImagingDataCommons/imaging-data-commons-skill, + * and checks every UID on the IDC public DICOMweb proxy. + * + * node scripts/find-idc-examples.mjs curate and write the JSON + * node scripts/find-idc-examples.mjs --verify re-check the committed JSON + * + * --verify exits 1 when an example stops resolving or a row without an + * example (Labelmap) gains public data, and writes a Markdown report to + * $IDC_REPORT_PATH when set. + */ +import { readFile, writeFile } from 'node:fs/promises' + +const API = 'https://api.imaging.datacommons.cancer.gov/v3' +const PROXY = + process.env.IDC_PROXY_URL ?? + 'https://proxy.imaging.datacommons.cancer.gov/current/viewer-only-no-downloads-see-tinyurl-dot-com-slash-3j3d9jyp/dicomWeb' +const OUTPUT = new URL('../src/data/idc-examples.json', import.meta.url) + +const SOP = { + wsi: '1.2.840.10008.5.1.4.1.1.77.1.6', + sr3d: '1.2.840.10008.5.1.4.1.1.88.34', + seg: '1.2.840.10008.5.1.4.1.1.66.4', + labelmap: '1.2.840.10008.5.1.4.1.1.66.7', + ann: '1.2.840.10008.5.1.4.1.1.91.1', + pmap: '1.2.840.10008.5.1.4.1.1.30', + abps: '1.2.840.10008.5.1.4.1.1.11.8', +} + +/** Derived objects open via their own series: Slim loads the referenced slide */ +const SLIDE_SIZE = 'src.series_size_MB BETWEEN 80 AND 400' + +/** + * One row per matrix entry. `preferred` UIDs come from the README or a + * previous curation run; `fallback` SQL is used when they no longer resolve. + */ +const ROWS = [ + { + id: 'brightfield', + caption: 'H&E brightfield slide', + preferred: { + series: '1.3.6.1.4.1.5962.99.1.208792987.352384958.1640886332827.2.0', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM sm_index s + JOIN index i ON i.SeriesInstanceUID = s.SeriesInstanceUID + WHERE array_to_string(s.staining_usingSubstance_CodeMeaning, ',') LIKE '%eosin%' + AND i.license_short_name LIKE 'CC BY%' AND i.series_size_MB BETWEEN 80 AND 400 + ORDER BY i.series_size_MB DESC LIMIT 1`, + }, + { + id: 'fluorescence', + caption: 'Cyclic immunofluorescence (t-CyCIF), multiplexed channels', + preferred: { + series: '1.3.6.1.4.1.5962.99.1.2339926922.537408935.1655902368650.4.0', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM sm_index s + JOIN index i ON i.SeriesInstanceUID = s.SeriesInstanceUID + WHERE s.illuminationType_CodeMeaning ILIKE '%fluorescence%' + AND i.license_short_name LIKE 'CC BY%' + ORDER BY i.series_size_MB LIMIT 1`, + }, + { + id: 'sr', + caption: 'Expert region annotations stored as Comprehensive 3D SR', + preferred: { + series: + '1.2.826.0.1.3680043.10.511.3.65352168153070950281170547035589843', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM index i + WHERE i.SOPClassUID = '${SOP.sr3d}' AND i.license_short_name LIKE 'CC BY%' + AND i.StudyInstanceUID IN (SELECT StudyInstanceUID FROM index WHERE Modality = 'SM') + LIMIT 1`, + }, + { + id: 'ann', + caption: 'AI nuclei outlines as Microscopy Bulk Simple Annotations', + preferred: { + series: + '1.2.826.0.1.3680043.10.511.3.65930042075829390210508226259517515', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM ann_index a + JOIN index i ON i.SeriesInstanceUID = a.SeriesInstanceUID + JOIN index src ON src.SeriesInstanceUID = a.referenced_SeriesInstanceUID + WHERE i.license_short_name LIKE 'CC BY%' AND ${SLIDE_SIZE} + ORDER BY i.series_size_MB LIMIT 1`, + }, + { + id: 'seg-binary', + caption: 'AI nuclei segmentation, binary DICOM SEG', + preferred: { + series: + '1.2.826.0.1.3680043.10.511.3.76624010831157291367936127061121081', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM seg_index seg + JOIN index i ON i.SeriesInstanceUID = seg.SeriesInstanceUID + JOIN index src ON src.SeriesInstanceUID = seg.segmented_SeriesInstanceUID + WHERE src.Modality = 'SM' AND seg.SegmentationType = 'BINARY' + AND i.license_short_name LIKE 'CC BY%' AND ${SLIDE_SIZE} + AND i.series_size_MB BETWEEN 5 AND 200 + ORDER BY i.series_size_MB DESC LIMIT 1`, + }, + { + id: 'seg-fractional', + caption: 'Tumor-infiltrating lymphocyte map, fractional DICOM SEG', + preferred: { + series: + '1.2.826.0.1.3680043.10.511.3.80872271169752522514101601468878519', + }, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM seg_index seg + JOIN index i ON i.SeriesInstanceUID = seg.SeriesInstanceUID + JOIN index src ON src.SeriesInstanceUID = seg.segmented_SeriesInstanceUID + WHERE src.Modality = 'SM' AND seg.SegmentationType = 'FRACTIONAL' + AND i.license_short_name LIKE 'CC BY%' AND ${SLIDE_SIZE} + ORDER BY src.series_size_MB DESC LIMIT 1`, + }, + { + id: 'labelmap', + caption: 'Multi-class label map segmentation', + preferred: null, + fallback: `SELECT i.StudyInstanceUID, i.SeriesInstanceUID FROM index i + WHERE i.SOPClassUID = '${SOP.labelmap}' + AND i.StudyInstanceUID IN (SELECT StudyInstanceUID FROM index WHERE Modality = 'SM') + ORDER BY i.license_short_name LIKE 'CC BY%' DESC LIMIT 1`, + }, + { + id: 'pmap', + caption: 'Glioma aggressiveness score map, DICOM Parametric Map', + preferred: { + series: + '1.2.826.0.1.3680043.10.511.3.57569487572611978100487359450084020', + }, + fallback: `SELECT pm.StudyInstanceUID, pm.SeriesInstanceUID FROM index pm + JOIN index sm ON sm.StudyInstanceUID = pm.StudyInstanceUID AND sm.Modality = 'SM' + WHERE pm.SOPClassUID = '${SOP.pmap}' AND pm.license_short_name LIKE 'CC BY%' + GROUP BY 1, 2 HAVING max(sm.series_size_MB) BETWEEN 100 AND 400 + ORDER BY count(sm.SeriesInstanceUID) LIMIT 1`, + }, + { + id: 'presentation-state', + caption: 't-CyCIF slide with a saved Advanced Blending Presentation State', + preferred: { + series: '1.3.6.1.4.1.5962.99.1.2344794501.795090168.1655907236229.4.0', + stateSeries: + '1.2.826.0.1.3680043.10.511.3.91342853824883143715411628225851002', + stateInstance: + '1.2.826.0.1.3680043.10.511.3.79630386778396943986328353882008803', + }, + fallback: `SELECT sm.StudyInstanceUID, sm.SeriesInstanceUID, pr.SeriesInstanceUID AS stateSeries + FROM index pr JOIN index sm ON sm.StudyInstanceUID = pr.StudyInstanceUID AND sm.Modality = 'SM' + WHERE pr.SOPClassUID = '${SOP.abps}' AND pr.license_short_name LIKE 'CC BY%' + ORDER BY sm.series_size_MB LIMIT 1`, + }, +] + +async function sql(query, maxRows = 50) { + const response = await fetch(`${API}/sql`, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ sql: query, max_rows: maxRows }), + }) + if (!response.ok) { + throw new Error( + `IDC SQL failed (${response.status}): ${await response.text()}`, + ) + } + return (await response.json()).rows ?? [] +} + +async function qido(path) { + const response = await fetch(`${PROXY}${path}`, { + headers: { accept: 'application/dicom+json' }, + }) + if (response.status === 204) return [] + if (!response.ok) throw new Error(`QIDO ${path} failed (${response.status})`) + return response.json() +} + +const tagValue = (dataset, tag) => dataset?.[tag]?.Value?.[0] + +async function seriesMetadata(seriesUIDs) { + const list = seriesUIDs.map((uid) => `'${uid}'`).join(',') + const rows = + await sql(`SELECT collection_id, StudyInstanceUID, SeriesInstanceUID, Modality, + SOPClassUID, sop_class_name, license_short_name, round(series_size_MB, 1) AS size_mb, + SeriesDescription, source_DOI + FROM index WHERE SeriesInstanceUID IN (${list})`) + return new Map(rows.map((row) => [row.SeriesInstanceUID, row])) +} + +async function collectionName(collectionId) { + const response = await fetch(`${API}/collections/${collectionId}`) + if (!response.ok) return collectionId + return (await response.json()).collection_name ?? collectionId +} + +async function existsOnProxy(studyUID, seriesUID) { + const results = await qido( + `/studies/${studyUID}/series?SeriesInstanceUID=${seriesUID}`, + ) + return results.length === 1 +} + +async function annotationSummary(seriesUID) { + const rows = + await sql(`SELECT AnnotationGroupLabel, NumberOfAnnotations, GraphicType, AlgorithmName + FROM ann_group_index WHERE SeriesInstanceUID = '${seriesUID}'`) + if (rows.length === 0) return undefined + const total = rows.reduce( + (sum, row) => sum + Number(row.NumberOfAnnotations), + 0, + ) + return `${total.toLocaleString('en-US')} ${rows[0].GraphicType.toLowerCase()} annotations (${rows + .map((row) => row.AnnotationGroupLabel) + .join(', ')})` +} + +async function segmentationSummary(seriesUID) { + const rows = + await sql(`SELECT SegmentationType, total_segments, AlgorithmName, + SegmentedPropertyType_CodeMeanings AS types + FROM seg_index WHERE SeriesInstanceUID = '${seriesUID}'`) + const row = rows[0] + if (!row) return undefined + return `${row.AlgorithmName ?? 'Segmentation'}: ${row.types?.join(', ') ?? ''}`.trim() +} + +async function presentationStateInstance( + studyUID, + stateSeries, + preferredInstance, +) { + const instances = await qido( + `/studies/${studyUID}/series/${stateSeries}/instances`, + ) + const uids = instances.map((instance) => tagValue(instance, '00080018')) + if (preferredInstance && uids.includes(preferredInstance)) + return preferredInstance + return uids[0] +} + +async function resolveRow(row) { + let target = row.preferred + if (target) { + const metadata = await seriesMetadata([target.series]) + if (!metadata.has(target.series)) target = null + } + if (!target) { + const [found] = await sql(row.fallback, 1) + if (!found) return { id: row.id, caption: row.caption, available: false } + target = { series: found.SeriesInstanceUID, stateSeries: found.stateSeries } + } + + const metadata = await seriesMetadata([target.series]) + const series = metadata.get(target.series) + const study = series.StudyInstanceUID + + if (!(await existsOnProxy(study, target.series))) { + throw new Error( + `${row.id}: series ${target.series} does not resolve on the proxy`, + ) + } + + /** @type {Record} */ + const example = { + id: row.id, + caption: row.caption, + available: true, + collection: series.collection_id, + collectionName: await collectionName(series.collection_id), + modality: series.Modality, + sopClassUID: series.SOPClassUID, + sopClassName: series.sop_class_name, + license: series.license_short_name, + sizeMB: series.size_mb, + sourceDOI: series.source_DOI ?? null, + studyInstanceUID: study, + seriesInstanceUID: target.series, + } + + if (series.Modality === 'ANN') + example.detail = await annotationSummary(target.series) + if (series.Modality === 'SEG') + example.detail = await segmentationSummary(target.series) + if (series.SeriesDescription) + example.seriesDescription = series.SeriesDescription + + if (target.stateSeries) { + example.stateSeriesInstanceUID = target.stateSeries + example.stateInstanceUID = await presentationStateInstance( + study, + target.stateSeries, + target.stateInstance, + ) + if (!example.stateInstanceUID) { + throw new Error( + `${row.id}: no instances in presentation state series ${target.stateSeries}`, + ) + } + } + + return example +} + +async function curate() { + const [version] = await fetch(`${API}/version`).then((response) => + response.json().then((v) => [v]), + ) + const examples = [] + for (const row of ROWS) { + process.stdout.write(`${row.id} ... `) + const example = await resolveRow(row) + examples.push(example) + console.log( + example.available + ? `${example.collection} ${example.seriesInstanceUID}` + : 'no public example', + ) + } + const data = { + generatedAt: new Date().toISOString().slice(0, 10), + idcVersion: version.idc_version, + proxy: PROXY, + examples, + } + await writeFile(OUTPUT, `${JSON.stringify(data, null, 2)}\n`) + console.log( + `\nWrote ${examples.length} examples for IDC ${version.idc_version}`, + ) +} + +async function verify() { + const data = JSON.parse(await readFile(OUTPUT, 'utf8')) + const problems = [] + const news = [] + + for (const example of data.examples) { + if (example.available) { + const ok = await existsOnProxy( + example.studyInstanceUID, + example.seriesInstanceUID, + ).catch(() => false) + if (!ok) + problems.push( + `\`${example.id}\`: series ${example.seriesInstanceUID} no longer resolves`, + ) + if (example.stateInstanceUID) { + const instance = await presentationStateInstance( + example.studyInstanceUID, + example.stateSeriesInstanceUID, + example.stateInstanceUID, + ).catch(() => undefined) + if (instance !== example.stateInstanceUID) { + problems.push( + `\`${example.id}\`: presentation state ${example.stateInstanceUID} is missing`, + ) + } + } + } else { + const row = ROWS.find((candidate) => candidate.id === example.id) + const [found] = row ? await sql(row.fallback, 1) : [] + if (found) + news.push( + `\`${example.id}\`: public data now available (${found.SeriesInstanceUID})`, + ) + } + console.log(`${example.id}: checked`) + } + + const lines = [] + if (problems.length) + lines.push('### Broken examples', '', ...problems.map((p) => `- ${p}`), '') + if (news.length) + lines.push( + '### New examples available', + '', + ...news.map((n) => `- ${n}`), + '', + ) + if (lines.length) { + lines.push( + 'Run `pnpm --filter slim-website find-idc-examples` and commit the result.', + ) + } + const report = lines.join('\n') + + if (process.env.IDC_REPORT_PATH) + await writeFile(process.env.IDC_REPORT_PATH, report) + if (report) { + console.error(`\n${report}`) + process.exitCode = 1 + } else { + console.log(`\nAll ${data.examples.length} examples are current.`) + } +} + +await (process.argv.includes('--verify') ? verify() : curate()) diff --git a/website/src/components/CitationCopy.astro b/website/src/components/CitationCopy.astro new file mode 100644 index 00000000..52fb110f --- /dev/null +++ b/website/src/components/CitationCopy.astro @@ -0,0 +1,38 @@ +--- +import { parse } from 'yaml' +import cffSource from '../../../CITATION.cff?raw' +import { type Cff, formatCitation } from '../lib/citation' +import CopyButton from './CopyButton.tsx' +import Tabs from './Tabs.astro' + +const citation = formatCitation(parse(cffSource) as Cff) +--- + +
+
+

{citation.title}

+

{citation.authors}

+

+ {citation.journal} + {citation.year} · + doi:{citation.doi} +

+
+ +
+
{citation.bibtex}
+
+ +
+
+
+

+ {citation.apa} +

+
+ +
+
+
+
diff --git a/website/src/components/CodeBlock.astro b/website/src/components/CodeBlock.astro new file mode 100644 index 00000000..6ed8da8e --- /dev/null +++ b/website/src/components/CodeBlock.astro @@ -0,0 +1,18 @@ +--- +import CopyButton from './CopyButton.tsx' + +interface Props { + code: string + title?: string +} + +const { code, title } = Astro.props +--- + +
+
+ {title ?? 'Shell'} + +
+
{code}
+
diff --git a/website/src/components/CopyButton.tsx b/website/src/components/CopyButton.tsx new file mode 100644 index 00000000..d8c5fce6 --- /dev/null +++ b/website/src/components/CopyButton.tsx @@ -0,0 +1,42 @@ +import { Check, Copy } from 'lucide-react' +import { useEffect, useState } from 'react' + +interface CopyButtonProps { + text: string + label?: string +} + +export default function CopyButton({ text, label = 'Copy' }: CopyButtonProps) { + const [copied, setCopied] = useState(false) + + useEffect(() => { + if (!copied) return + const timer = window.setTimeout(() => setCopied(false), 1800) + return () => window.clearTimeout(timer) + }, [copied]) + + const copy = async (): Promise => { + try { + await navigator.clipboard.writeText(text) + setCopied(true) + } catch { + /** Clipboard access can be refused; the text stays selectable */ + setCopied(false) + } + } + + return ( + + ) +} diff --git a/website/src/components/ExampleCard.astro b/website/src/components/ExampleCard.astro new file mode 100644 index 00000000..ada91db4 --- /dev/null +++ b/website/src/components/ExampleCard.astro @@ -0,0 +1,49 @@ +--- +import { ArrowUpRight } from 'lucide-react' +import { collectionUrl, exampleUrl, type IdcExample } from '../lib/examples' + +interface Props { + example: IdcExample +} + +const { example } = Astro.props +const href = exampleUrl(example) +--- + +
  • +
    + +
    +
    +

    {example.sopClassName?.replace(/ Storage$/, '')}

    +

    + + {example.caption} + (opens in the demo) + +

    + {example.detail &&

    {example.detail}

    } +
    + + {example.collectionName} + + + Open in Slim + +
    +
    +
  • diff --git a/website/src/components/FeatureSection.astro b/website/src/components/FeatureSection.astro new file mode 100644 index 00000000..8e384a36 --- /dev/null +++ b/website/src/components/FeatureSection.astro @@ -0,0 +1,53 @@ +--- +import { Check } from 'lucide-react' +import type { CollectionEntry } from 'astro:content' +import { render } from 'astro:content' +import { featureAnchor } from '../lib/content' +import Icon from './Icon.astro' +import OpenInSlim from './OpenInSlim.astro' +import Screenshot from './Screenshot.astro' + +interface Props { + feature: CollectionEntry<'features'> + reverse?: boolean +} + +const { feature, reverse = false } = Astro.props +const { Content } = await render(feature) +const { title, eyebrow, summary, icon, bullets, screenshot, example } = feature.data +--- + +
    +
    +

    + + {eyebrow} +

    +

    {title}

    +

    {summary}

    +
    + +
    + { + bullets.length > 0 && ( +
      + {bullets.map((bullet) => ( +
    • +
    • + ))} +
    + ) + } + +
    + { + screenshot && ( + + ) + } +
    diff --git a/website/src/components/Footer.astro b/website/src/components/Footer.astro new file mode 100644 index 00000000..1973111f --- /dev/null +++ b/website/src/components/Footer.astro @@ -0,0 +1,98 @@ +--- +import { demoUrl, site } from '../data/site' +import IdcLogo from './IdcLogo.astro' +import Logo from './Logo.astro' + +const columns = [ + { + title: 'Product', + links: [ + { href: '/features/', label: 'Features' }, + { href: '/features/#support-matrix', label: 'DICOM support' }, + { href: '/showcase/', label: 'Showcase' }, + { href: '/release-notes/', label: 'Release notes' }, + { href: demoUrl, label: 'Live demo', external: true }, + ], + }, + { + title: 'Resources', + links: [ + { href: '/docs/', label: 'Documentation' }, + { href: site.links.configuration, label: 'Configuration', external: true }, + { href: site.links.conformance, label: 'Conformance statement', external: true }, + { href: site.links.wiki, label: 'Wiki', external: true }, + { href: '/rss.xml', label: 'RSS feed' }, + ], + }, + { + title: 'Community', + links: [ + { href: site.links.github, label: 'GitHub', external: true }, + { href: site.links.issues, label: 'Issues', external: true }, + { href: site.links.idcForum, label: 'IDC forum', external: true }, + { href: site.links.contributing, label: 'Contributing', external: true }, + ], + }, + { + title: 'Project', + links: [ + { href: '/about/', label: 'About' }, + { href: '/about/#cite', label: 'Cite Slim' }, + { href: '/support/', label: 'Support' }, + { href: site.links.license, label: 'License', external: true }, + ], + }, +] +--- + +
    +
    +
    + +

    + Interoperable web-based DICOM slide microscopy viewer and annotation tool. +

    +
    +

    Developed and supported by

    + + + +
    +
    + { + columns.map((column) => ( +
    +

    {column.title}

    + +
    + )) + } +
    +
    +
    +

    Released under the Apache 2.0 license.

    +

    + Built on dicom-microscopy-viewer and DICOMweb. +

    +
    +
    +
    diff --git a/website/src/components/GithubMark.astro b/website/src/components/GithubMark.astro new file mode 100644 index 00000000..a88d027b --- /dev/null +++ b/website/src/components/GithubMark.astro @@ -0,0 +1,14 @@ +--- +/** GitHub's mark; lucide dropped brand icons in v1 */ +interface Props { + class?: string +} + +const { class: className } = Astro.props +--- + + diff --git a/website/src/components/Header.astro b/website/src/components/Header.astro new file mode 100644 index 00000000..fd2049a2 --- /dev/null +++ b/website/src/components/Header.astro @@ -0,0 +1,91 @@ +--- +import { ArrowUpRight, Menu, X } from 'lucide-react' +import { buttonVariants } from '@slim/components/ui/button' +import { demoUrl, site } from '../data/site' +import GithubMark from './GithubMark.astro' +import Logo from './Logo.astro' +import ThemeToggle from './ThemeToggle.astro' + +const path = Astro.url.pathname +const isActive = (href: string): boolean => path === href || path.startsWith(href) +--- + +
    + Skip to content +
    + + + + +
    + + + + + + +
    + + + +
    +
    +
    +
    diff --git a/website/src/components/Icon.astro b/website/src/components/Icon.astro new file mode 100644 index 00000000..d309bbf6 --- /dev/null +++ b/website/src/components/Icon.astro @@ -0,0 +1,36 @@ +--- +import { + Layers, + ListFilter, + Microscope, + Network, + PanelsTopLeft, + PenTool, + Shapes, + SlidersHorizontal, + type LucideIcon, +} from 'lucide-react' + +/** Icons that content files may name in their `icon` field */ +const icons: Record = { + Layers, + ListFilter, + Microscope, + Network, + PanelsTopLeft, + PenTool, + Shapes, + SlidersHorizontal, +} + +interface Props { + name: string + class?: string +} + +const { name, class: className } = Astro.props +const Component = icons[name] +if (!Component) throw new Error(`Unknown icon "${name}". Add it to Icon.astro.`) +--- + +