at://Press
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial commit: arcnode-blog with CI/CD

AT Protocol-powered blog at blog.arcnode.xyz with:
- Astro SSR + Docker deployment
- Draft/publish workflow
- Image upload via PDS blobs
- Side-by-side markdown preview
- Gitea Actions CI/CD with Matrix notifications

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Bryan Brooks 8ce9396e

+10644
+4
.dockerignore
··· 1 + node_modules 2 + dist 3 + .git 4 + .env
+21
.gitea/workflows/ci.yml
··· 1 + name: CI 2 + 3 + on: 4 + push: 5 + branches: [main] 6 + paths-ignore: ['*.md'] 7 + pull_request: 8 + branches: [main] 9 + 10 + jobs: 11 + test: 12 + name: Test 13 + runs-on: ubuntu-latest 14 + steps: 15 + - uses: actions/checkout@v4 16 + - uses: actions/setup-node@v4 17 + with: 18 + node-version: '22' 19 + - run: npm ci 20 + - run: npm test 21 + - run: npm run build
+91
.gitea/workflows/deploy.yml
··· 1 + name: Deploy Blog 2 + 3 + on: 4 + push: 5 + branches: [main] 6 + paths-ignore: ['*.md'] 7 + 8 + jobs: 9 + test: 10 + name: Test 11 + runs-on: ubuntu-latest 12 + steps: 13 + - uses: actions/checkout@v4 14 + - uses: actions/setup-node@v4 15 + with: 16 + node-version: '22' 17 + - run: npm ci 18 + - run: npm test 19 + - run: npm run build 20 + 21 + deploy: 22 + name: Build & Deploy 23 + runs-on: host 24 + needs: [test] 25 + steps: 26 + - name: Checkout code 27 + uses: actions/checkout@v4 28 + 29 + - name: Set short SHA 30 + id: sha 31 + run: echo "short=$(echo ${{ github.sha }} | cut -c1-7)" >> "$GITHUB_OUTPUT" 32 + 33 + - name: Notify build started 34 + env: 35 + COMMIT_MSG: ${{ github.event.head_commit.message }} 36 + run: | 37 + FIRST_LINE=$(echo "$COMMIT_MSG" | head -1) 38 + MSG=$(jq -n --arg body "🔨 arcnode-blog: build started @ ${{ steps.sha.outputs.short }} 39 + ├ Commit: $FIRST_LINE 40 + └ Triggered by: ${{ github.actor }}" '{msgtype: "m.text", body: $body}') 41 + curl -sf -X PUT \ 42 + "${{ secrets.MATRIX_HOMESERVER_URL }}/_matrix/client/v3/rooms/${{ secrets.MATRIX_CICD_ROOM_ID }}/send/m.room.message/cicd-$(date +%s)-$$" \ 43 + -H "Authorization: Bearer ${{ secrets.MATRIX_ACCESS_TOKEN }}" \ 44 + -H "Content-Type: application/json" \ 45 + -d "$MSG" || true 46 + 47 + - name: Sync source to deploy directory 48 + run: | 49 + rsync -a --delete \ 50 + --exclude node_modules --exclude .git --exclude dist \ 51 + --exclude tests --exclude test-results --exclude .astro \ 52 + ./ /opt/arcnode-blog/ 53 + 54 + - name: Build and restart container 55 + run: | 56 + cd /opt/arcnode-blog 57 + docker compose build --no-cache 58 + docker compose up -d 59 + 60 + - name: Health check 61 + run: | 62 + sleep 5 63 + for i in 1 2 3 4 5; do 64 + if curl -sf http://127.0.0.1:4000/ > /dev/null 2>&1; then 65 + echo "Health check passed" 66 + exit 0 67 + fi 68 + echo "Attempt $i failed, waiting..." 69 + sleep 3 70 + done 71 + echo "Health check failed after 5 attempts" 72 + exit 1 73 + 74 + - name: Notify result 75 + if: always() 76 + env: 77 + COMMIT_MSG: ${{ github.event.head_commit.message }} 78 + run: | 79 + if [ "${{ job.status }}" = "success" ]; then 80 + EMOJI="✅"; STATUS="deployed" 81 + else 82 + EMOJI="❌"; STATUS="FAILED" 83 + fi 84 + FIRST_LINE=$(echo "$COMMIT_MSG" | head -1) 85 + MSG=$(jq -n --arg body "${EMOJI} arcnode-blog: ${STATUS} @ ${{ steps.sha.outputs.short }} 86 + └ $FIRST_LINE" '{msgtype: "m.text", body: $body}') 87 + curl -sf -X PUT \ 88 + "${{ secrets.MATRIX_HOMESERVER_URL }}/_matrix/client/v3/rooms/${{ secrets.MATRIX_CICD_ROOM_ID }}/send/m.room.message/cicd-$(date +%s)-$$" \ 89 + -H "Authorization: Bearer ${{ secrets.MATRIX_ACCESS_TOKEN }}" \ 90 + -H "Content-Type: application/json" \ 91 + -d "$MSG" || true
+5
.gitignore
··· 1 + node_modules/ 2 + dist/ 3 + .astro/ 4 + test-results/ 5 + *.log
+20
Dockerfile
··· 1 + FROM node:22-alpine AS build 2 + WORKDIR /app 3 + COPY package.json package-lock.json* ./ 4 + RUN npm ci 5 + COPY . . 6 + RUN npm run build 7 + 8 + FROM node:22-alpine 9 + RUN addgroup -S blog && adduser -S blog -G blog 10 + WORKDIR /app 11 + COPY --from=build /app/package.json /app/package-lock.json* ./ 12 + RUN npm ci --omit=dev && npm cache clean --force 13 + COPY --from=build /app/dist ./dist 14 + USER blog 15 + ENV HOST=0.0.0.0 16 + ENV PORT=4000 17 + EXPOSE 4000 18 + HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ 19 + CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:4000/ || exit 1 20 + CMD ["node", "dist/server/entry.mjs"]
+11
astro.config.mjs
··· 1 + import { defineConfig } from "astro/config"; 2 + import node from "@astrojs/node"; 3 + import tailwindcss from "@tailwindcss/vite"; 4 + 5 + export default defineConfig({ 6 + output: "server", 7 + adapter: node({ mode: "standalone" }), 8 + vite: { 9 + plugins: [tailwindcss()], 10 + }, 11 + });
+12
docker-compose.yml
··· 1 + services: 2 + blog: 3 + build: . 4 + container_name: arcnode-blog 5 + restart: unless-stopped 6 + ports: 7 + - "0.0.0.0:4000:4000" 8 + environment: 9 + - HOST=0.0.0.0 10 + - PORT=4000 11 + - PDS_APP_PASSWORD=5wxb-dk6w-vuth-lgbp 12 + - ATAUTH_GATEWAY_URL=http://172.17.0.1:3100
+7268
package-lock.json
··· 1 + { 2 + "name": "arcnode-blog", 3 + "version": "1.0.0", 4 + "lockfileVersion": 3, 5 + "requires": true, 6 + "packages": { 7 + "": { 8 + "name": "arcnode-blog", 9 + "version": "1.0.0", 10 + "dependencies": { 11 + "@astrojs/node": "^9.1.0", 12 + "astro": "^5.7.0", 13 + "isomorphic-dompurify": "^3.0.0", 14 + "marked": "^17.0.0" 15 + }, 16 + "devDependencies": { 17 + "@playwright/test": "^1.58.2", 18 + "@tailwindcss/vite": "^4.1.0", 19 + "tailwindcss": "^4.1.0", 20 + "vitest": "^4.0.18" 21 + } 22 + }, 23 + "node_modules/@acemir/cssom": { 24 + "version": "0.9.31", 25 + "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", 26 + "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", 27 + "license": "MIT" 28 + }, 29 + "node_modules/@asamuzakjp/css-color": { 30 + "version": "5.0.1", 31 + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.0.1.tgz", 32 + "integrity": "sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==", 33 + "license": "MIT", 34 + "dependencies": { 35 + "@csstools/css-calc": "^3.1.1", 36 + "@csstools/css-color-parser": "^4.0.2", 37 + "@csstools/css-parser-algorithms": "^4.0.0", 38 + "@csstools/css-tokenizer": "^4.0.0", 39 + "lru-cache": "^11.2.6" 40 + }, 41 + "engines": { 42 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 43 + } 44 + }, 45 + "node_modules/@asamuzakjp/dom-selector": { 46 + "version": "6.8.1", 47 + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", 48 + "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", 49 + "license": "MIT", 50 + "dependencies": { 51 + "@asamuzakjp/nwsapi": "^2.3.9", 52 + "bidi-js": "^1.0.3", 53 + "css-tree": "^3.1.0", 54 + "is-potential-custom-element-name": "^1.0.1", 55 + "lru-cache": "^11.2.6" 56 + } 57 + }, 58 + "node_modules/@asamuzakjp/nwsapi": { 59 + "version": "2.3.9", 60 + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", 61 + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", 62 + "license": "MIT" 63 + }, 64 + "node_modules/@astrojs/compiler": { 65 + "version": "2.13.1", 66 + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz", 67 + "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==", 68 + "license": "MIT" 69 + }, 70 + "node_modules/@astrojs/internal-helpers": { 71 + "version": "0.7.5", 72 + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz", 73 + "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==", 74 + "license": "MIT" 75 + }, 76 + "node_modules/@astrojs/markdown-remark": { 77 + "version": "6.3.10", 78 + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.10.tgz", 79 + "integrity": "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==", 80 + "license": "MIT", 81 + "dependencies": { 82 + "@astrojs/internal-helpers": "0.7.5", 83 + "@astrojs/prism": "3.3.0", 84 + "github-slugger": "^2.0.0", 85 + "hast-util-from-html": "^2.0.3", 86 + "hast-util-to-text": "^4.0.2", 87 + "import-meta-resolve": "^4.2.0", 88 + "js-yaml": "^4.1.1", 89 + "mdast-util-definitions": "^6.0.0", 90 + "rehype-raw": "^7.0.0", 91 + "rehype-stringify": "^10.0.1", 92 + "remark-gfm": "^4.0.1", 93 + "remark-parse": "^11.0.0", 94 + "remark-rehype": "^11.1.2", 95 + "remark-smartypants": "^3.0.2", 96 + "shiki": "^3.19.0", 97 + "smol-toml": "^1.5.2", 98 + "unified": "^11.0.5", 99 + "unist-util-remove-position": "^5.0.0", 100 + "unist-util-visit": "^5.0.0", 101 + "unist-util-visit-parents": "^6.0.2", 102 + "vfile": "^6.0.3" 103 + } 104 + }, 105 + "node_modules/@astrojs/node": { 106 + "version": "9.5.4", 107 + "resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.5.4.tgz", 108 + "integrity": "sha512-AbPSZsMGu8hXPR2XxV79RaKy8h6wijhtoqZGeUf4OXg2w1mxXlx4VnIc1D+QvtsgauSz7P5PLhmvf6w/J41GJg==", 109 + "license": "MIT", 110 + "dependencies": { 111 + "@astrojs/internal-helpers": "0.7.5", 112 + "send": "^1.2.1", 113 + "server-destroy": "^1.0.1" 114 + }, 115 + "peerDependencies": { 116 + "astro": "^5.17.3" 117 + } 118 + }, 119 + "node_modules/@astrojs/prism": { 120 + "version": "3.3.0", 121 + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", 122 + "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", 123 + "license": "MIT", 124 + "dependencies": { 125 + "prismjs": "^1.30.0" 126 + }, 127 + "engines": { 128 + "node": "18.20.8 || ^20.3.0 || >=22.0.0" 129 + } 130 + }, 131 + "node_modules/@astrojs/telemetry": { 132 + "version": "3.3.0", 133 + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", 134 + "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", 135 + "license": "MIT", 136 + "dependencies": { 137 + "ci-info": "^4.2.0", 138 + "debug": "^4.4.0", 139 + "dlv": "^1.1.3", 140 + "dset": "^3.1.4", 141 + "is-docker": "^3.0.0", 142 + "is-wsl": "^3.1.0", 143 + "which-pm-runs": "^1.1.0" 144 + }, 145 + "engines": { 146 + "node": "18.20.8 || ^20.3.0 || >=22.0.0" 147 + } 148 + }, 149 + "node_modules/@babel/helper-string-parser": { 150 + "version": "7.27.1", 151 + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", 152 + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", 153 + "license": "MIT", 154 + "engines": { 155 + "node": ">=6.9.0" 156 + } 157 + }, 158 + "node_modules/@babel/helper-validator-identifier": { 159 + "version": "7.28.5", 160 + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", 161 + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", 162 + "license": "MIT", 163 + "engines": { 164 + "node": ">=6.9.0" 165 + } 166 + }, 167 + "node_modules/@babel/parser": { 168 + "version": "7.29.0", 169 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", 170 + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", 171 + "license": "MIT", 172 + "dependencies": { 173 + "@babel/types": "^7.29.0" 174 + }, 175 + "bin": { 176 + "parser": "bin/babel-parser.js" 177 + }, 178 + "engines": { 179 + "node": ">=6.0.0" 180 + } 181 + }, 182 + "node_modules/@babel/types": { 183 + "version": "7.29.0", 184 + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", 185 + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", 186 + "license": "MIT", 187 + "dependencies": { 188 + "@babel/helper-string-parser": "^7.27.1", 189 + "@babel/helper-validator-identifier": "^7.28.5" 190 + }, 191 + "engines": { 192 + "node": ">=6.9.0" 193 + } 194 + }, 195 + "node_modules/@bramus/specificity": { 196 + "version": "2.4.2", 197 + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", 198 + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", 199 + "license": "MIT", 200 + "dependencies": { 201 + "css-tree": "^3.0.0" 202 + }, 203 + "bin": { 204 + "specificity": "bin/cli.js" 205 + } 206 + }, 207 + "node_modules/@capsizecss/unpack": { 208 + "version": "4.0.0", 209 + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", 210 + "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", 211 + "license": "MIT", 212 + "dependencies": { 213 + "fontkitten": "^1.0.0" 214 + }, 215 + "engines": { 216 + "node": ">=18" 217 + } 218 + }, 219 + "node_modules/@csstools/color-helpers": { 220 + "version": "6.0.2", 221 + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", 222 + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", 223 + "funding": [ 224 + { 225 + "type": "github", 226 + "url": "https://github.com/sponsors/csstools" 227 + }, 228 + { 229 + "type": "opencollective", 230 + "url": "https://opencollective.com/csstools" 231 + } 232 + ], 233 + "license": "MIT-0", 234 + "engines": { 235 + "node": ">=20.19.0" 236 + } 237 + }, 238 + "node_modules/@csstools/css-calc": { 239 + "version": "3.1.1", 240 + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", 241 + "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", 242 + "funding": [ 243 + { 244 + "type": "github", 245 + "url": "https://github.com/sponsors/csstools" 246 + }, 247 + { 248 + "type": "opencollective", 249 + "url": "https://opencollective.com/csstools" 250 + } 251 + ], 252 + "license": "MIT", 253 + "engines": { 254 + "node": ">=20.19.0" 255 + }, 256 + "peerDependencies": { 257 + "@csstools/css-parser-algorithms": "^4.0.0", 258 + "@csstools/css-tokenizer": "^4.0.0" 259 + } 260 + }, 261 + "node_modules/@csstools/css-color-parser": { 262 + "version": "4.0.2", 263 + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz", 264 + "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==", 265 + "funding": [ 266 + { 267 + "type": "github", 268 + "url": "https://github.com/sponsors/csstools" 269 + }, 270 + { 271 + "type": "opencollective", 272 + "url": "https://opencollective.com/csstools" 273 + } 274 + ], 275 + "license": "MIT", 276 + "dependencies": { 277 + "@csstools/color-helpers": "^6.0.2", 278 + "@csstools/css-calc": "^3.1.1" 279 + }, 280 + "engines": { 281 + "node": ">=20.19.0" 282 + }, 283 + "peerDependencies": { 284 + "@csstools/css-parser-algorithms": "^4.0.0", 285 + "@csstools/css-tokenizer": "^4.0.0" 286 + } 287 + }, 288 + "node_modules/@csstools/css-parser-algorithms": { 289 + "version": "4.0.0", 290 + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", 291 + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", 292 + "funding": [ 293 + { 294 + "type": "github", 295 + "url": "https://github.com/sponsors/csstools" 296 + }, 297 + { 298 + "type": "opencollective", 299 + "url": "https://opencollective.com/csstools" 300 + } 301 + ], 302 + "license": "MIT", 303 + "engines": { 304 + "node": ">=20.19.0" 305 + }, 306 + "peerDependencies": { 307 + "@csstools/css-tokenizer": "^4.0.0" 308 + } 309 + }, 310 + "node_modules/@csstools/css-syntax-patches-for-csstree": { 311 + "version": "1.0.28", 312 + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.28.tgz", 313 + "integrity": "sha512-1NRf1CUBjnr3K7hu8BLxjQrKCxEe8FP/xmPTenAxCRZWVLbmGotkFvG9mfNpjA6k7Bw1bw4BilZq9cu19RA5pg==", 314 + "funding": [ 315 + { 316 + "type": "github", 317 + "url": "https://github.com/sponsors/csstools" 318 + }, 319 + { 320 + "type": "opencollective", 321 + "url": "https://opencollective.com/csstools" 322 + } 323 + ], 324 + "license": "MIT-0" 325 + }, 326 + "node_modules/@csstools/css-tokenizer": { 327 + "version": "4.0.0", 328 + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", 329 + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", 330 + "funding": [ 331 + { 332 + "type": "github", 333 + "url": "https://github.com/sponsors/csstools" 334 + }, 335 + { 336 + "type": "opencollective", 337 + "url": "https://opencollective.com/csstools" 338 + } 339 + ], 340 + "license": "MIT", 341 + "engines": { 342 + "node": ">=20.19.0" 343 + } 344 + }, 345 + "node_modules/@emnapi/runtime": { 346 + "version": "1.8.1", 347 + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", 348 + "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", 349 + "license": "MIT", 350 + "optional": true, 351 + "dependencies": { 352 + "tslib": "^2.4.0" 353 + } 354 + }, 355 + "node_modules/@esbuild/aix-ppc64": { 356 + "version": "0.27.3", 357 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", 358 + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", 359 + "cpu": [ 360 + "ppc64" 361 + ], 362 + "license": "MIT", 363 + "optional": true, 364 + "os": [ 365 + "aix" 366 + ], 367 + "engines": { 368 + "node": ">=18" 369 + } 370 + }, 371 + "node_modules/@esbuild/android-arm": { 372 + "version": "0.27.3", 373 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", 374 + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", 375 + "cpu": [ 376 + "arm" 377 + ], 378 + "license": "MIT", 379 + "optional": true, 380 + "os": [ 381 + "android" 382 + ], 383 + "engines": { 384 + "node": ">=18" 385 + } 386 + }, 387 + "node_modules/@esbuild/android-arm64": { 388 + "version": "0.27.3", 389 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", 390 + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", 391 + "cpu": [ 392 + "arm64" 393 + ], 394 + "license": "MIT", 395 + "optional": true, 396 + "os": [ 397 + "android" 398 + ], 399 + "engines": { 400 + "node": ">=18" 401 + } 402 + }, 403 + "node_modules/@esbuild/android-x64": { 404 + "version": "0.27.3", 405 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", 406 + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", 407 + "cpu": [ 408 + "x64" 409 + ], 410 + "license": "MIT", 411 + "optional": true, 412 + "os": [ 413 + "android" 414 + ], 415 + "engines": { 416 + "node": ">=18" 417 + } 418 + }, 419 + "node_modules/@esbuild/darwin-arm64": { 420 + "version": "0.27.3", 421 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", 422 + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", 423 + "cpu": [ 424 + "arm64" 425 + ], 426 + "license": "MIT", 427 + "optional": true, 428 + "os": [ 429 + "darwin" 430 + ], 431 + "engines": { 432 + "node": ">=18" 433 + } 434 + }, 435 + "node_modules/@esbuild/darwin-x64": { 436 + "version": "0.27.3", 437 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", 438 + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", 439 + "cpu": [ 440 + "x64" 441 + ], 442 + "license": "MIT", 443 + "optional": true, 444 + "os": [ 445 + "darwin" 446 + ], 447 + "engines": { 448 + "node": ">=18" 449 + } 450 + }, 451 + "node_modules/@esbuild/freebsd-arm64": { 452 + "version": "0.27.3", 453 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", 454 + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", 455 + "cpu": [ 456 + "arm64" 457 + ], 458 + "license": "MIT", 459 + "optional": true, 460 + "os": [ 461 + "freebsd" 462 + ], 463 + "engines": { 464 + "node": ">=18" 465 + } 466 + }, 467 + "node_modules/@esbuild/freebsd-x64": { 468 + "version": "0.27.3", 469 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", 470 + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", 471 + "cpu": [ 472 + "x64" 473 + ], 474 + "license": "MIT", 475 + "optional": true, 476 + "os": [ 477 + "freebsd" 478 + ], 479 + "engines": { 480 + "node": ">=18" 481 + } 482 + }, 483 + "node_modules/@esbuild/linux-arm": { 484 + "version": "0.27.3", 485 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", 486 + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", 487 + "cpu": [ 488 + "arm" 489 + ], 490 + "license": "MIT", 491 + "optional": true, 492 + "os": [ 493 + "linux" 494 + ], 495 + "engines": { 496 + "node": ">=18" 497 + } 498 + }, 499 + "node_modules/@esbuild/linux-arm64": { 500 + "version": "0.27.3", 501 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", 502 + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", 503 + "cpu": [ 504 + "arm64" 505 + ], 506 + "license": "MIT", 507 + "optional": true, 508 + "os": [ 509 + "linux" 510 + ], 511 + "engines": { 512 + "node": ">=18" 513 + } 514 + }, 515 + "node_modules/@esbuild/linux-ia32": { 516 + "version": "0.27.3", 517 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", 518 + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", 519 + "cpu": [ 520 + "ia32" 521 + ], 522 + "license": "MIT", 523 + "optional": true, 524 + "os": [ 525 + "linux" 526 + ], 527 + "engines": { 528 + "node": ">=18" 529 + } 530 + }, 531 + "node_modules/@esbuild/linux-loong64": { 532 + "version": "0.27.3", 533 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", 534 + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", 535 + "cpu": [ 536 + "loong64" 537 + ], 538 + "license": "MIT", 539 + "optional": true, 540 + "os": [ 541 + "linux" 542 + ], 543 + "engines": { 544 + "node": ">=18" 545 + } 546 + }, 547 + "node_modules/@esbuild/linux-mips64el": { 548 + "version": "0.27.3", 549 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", 550 + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", 551 + "cpu": [ 552 + "mips64el" 553 + ], 554 + "license": "MIT", 555 + "optional": true, 556 + "os": [ 557 + "linux" 558 + ], 559 + "engines": { 560 + "node": ">=18" 561 + } 562 + }, 563 + "node_modules/@esbuild/linux-ppc64": { 564 + "version": "0.27.3", 565 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", 566 + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", 567 + "cpu": [ 568 + "ppc64" 569 + ], 570 + "license": "MIT", 571 + "optional": true, 572 + "os": [ 573 + "linux" 574 + ], 575 + "engines": { 576 + "node": ">=18" 577 + } 578 + }, 579 + "node_modules/@esbuild/linux-riscv64": { 580 + "version": "0.27.3", 581 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", 582 + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", 583 + "cpu": [ 584 + "riscv64" 585 + ], 586 + "license": "MIT", 587 + "optional": true, 588 + "os": [ 589 + "linux" 590 + ], 591 + "engines": { 592 + "node": ">=18" 593 + } 594 + }, 595 + "node_modules/@esbuild/linux-s390x": { 596 + "version": "0.27.3", 597 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", 598 + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", 599 + "cpu": [ 600 + "s390x" 601 + ], 602 + "license": "MIT", 603 + "optional": true, 604 + "os": [ 605 + "linux" 606 + ], 607 + "engines": { 608 + "node": ">=18" 609 + } 610 + }, 611 + "node_modules/@esbuild/linux-x64": { 612 + "version": "0.27.3", 613 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", 614 + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", 615 + "cpu": [ 616 + "x64" 617 + ], 618 + "license": "MIT", 619 + "optional": true, 620 + "os": [ 621 + "linux" 622 + ], 623 + "engines": { 624 + "node": ">=18" 625 + } 626 + }, 627 + "node_modules/@esbuild/netbsd-arm64": { 628 + "version": "0.27.3", 629 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", 630 + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", 631 + "cpu": [ 632 + "arm64" 633 + ], 634 + "license": "MIT", 635 + "optional": true, 636 + "os": [ 637 + "netbsd" 638 + ], 639 + "engines": { 640 + "node": ">=18" 641 + } 642 + }, 643 + "node_modules/@esbuild/netbsd-x64": { 644 + "version": "0.27.3", 645 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", 646 + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", 647 + "cpu": [ 648 + "x64" 649 + ], 650 + "license": "MIT", 651 + "optional": true, 652 + "os": [ 653 + "netbsd" 654 + ], 655 + "engines": { 656 + "node": ">=18" 657 + } 658 + }, 659 + "node_modules/@esbuild/openbsd-arm64": { 660 + "version": "0.27.3", 661 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", 662 + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", 663 + "cpu": [ 664 + "arm64" 665 + ], 666 + "license": "MIT", 667 + "optional": true, 668 + "os": [ 669 + "openbsd" 670 + ], 671 + "engines": { 672 + "node": ">=18" 673 + } 674 + }, 675 + "node_modules/@esbuild/openbsd-x64": { 676 + "version": "0.27.3", 677 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", 678 + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", 679 + "cpu": [ 680 + "x64" 681 + ], 682 + "license": "MIT", 683 + "optional": true, 684 + "os": [ 685 + "openbsd" 686 + ], 687 + "engines": { 688 + "node": ">=18" 689 + } 690 + }, 691 + "node_modules/@esbuild/openharmony-arm64": { 692 + "version": "0.27.3", 693 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", 694 + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", 695 + "cpu": [ 696 + "arm64" 697 + ], 698 + "license": "MIT", 699 + "optional": true, 700 + "os": [ 701 + "openharmony" 702 + ], 703 + "engines": { 704 + "node": ">=18" 705 + } 706 + }, 707 + "node_modules/@esbuild/sunos-x64": { 708 + "version": "0.27.3", 709 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", 710 + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", 711 + "cpu": [ 712 + "x64" 713 + ], 714 + "license": "MIT", 715 + "optional": true, 716 + "os": [ 717 + "sunos" 718 + ], 719 + "engines": { 720 + "node": ">=18" 721 + } 722 + }, 723 + "node_modules/@esbuild/win32-arm64": { 724 + "version": "0.27.3", 725 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", 726 + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", 727 + "cpu": [ 728 + "arm64" 729 + ], 730 + "license": "MIT", 731 + "optional": true, 732 + "os": [ 733 + "win32" 734 + ], 735 + "engines": { 736 + "node": ">=18" 737 + } 738 + }, 739 + "node_modules/@esbuild/win32-ia32": { 740 + "version": "0.27.3", 741 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", 742 + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", 743 + "cpu": [ 744 + "ia32" 745 + ], 746 + "license": "MIT", 747 + "optional": true, 748 + "os": [ 749 + "win32" 750 + ], 751 + "engines": { 752 + "node": ">=18" 753 + } 754 + }, 755 + "node_modules/@esbuild/win32-x64": { 756 + "version": "0.27.3", 757 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", 758 + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", 759 + "cpu": [ 760 + "x64" 761 + ], 762 + "license": "MIT", 763 + "optional": true, 764 + "os": [ 765 + "win32" 766 + ], 767 + "engines": { 768 + "node": ">=18" 769 + } 770 + }, 771 + "node_modules/@exodus/bytes": { 772 + "version": "1.14.1", 773 + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", 774 + "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", 775 + "license": "MIT", 776 + "engines": { 777 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 778 + }, 779 + "peerDependencies": { 780 + "@noble/hashes": "^1.8.0 || ^2.0.0" 781 + }, 782 + "peerDependenciesMeta": { 783 + "@noble/hashes": { 784 + "optional": true 785 + } 786 + } 787 + }, 788 + "node_modules/@img/colour": { 789 + "version": "1.0.0", 790 + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", 791 + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", 792 + "license": "MIT", 793 + "optional": true, 794 + "engines": { 795 + "node": ">=18" 796 + } 797 + }, 798 + "node_modules/@img/sharp-darwin-arm64": { 799 + "version": "0.34.5", 800 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", 801 + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", 802 + "cpu": [ 803 + "arm64" 804 + ], 805 + "license": "Apache-2.0", 806 + "optional": true, 807 + "os": [ 808 + "darwin" 809 + ], 810 + "engines": { 811 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 812 + }, 813 + "funding": { 814 + "url": "https://opencollective.com/libvips" 815 + }, 816 + "optionalDependencies": { 817 + "@img/sharp-libvips-darwin-arm64": "1.2.4" 818 + } 819 + }, 820 + "node_modules/@img/sharp-darwin-x64": { 821 + "version": "0.34.5", 822 + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", 823 + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", 824 + "cpu": [ 825 + "x64" 826 + ], 827 + "license": "Apache-2.0", 828 + "optional": true, 829 + "os": [ 830 + "darwin" 831 + ], 832 + "engines": { 833 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 834 + }, 835 + "funding": { 836 + "url": "https://opencollective.com/libvips" 837 + }, 838 + "optionalDependencies": { 839 + "@img/sharp-libvips-darwin-x64": "1.2.4" 840 + } 841 + }, 842 + "node_modules/@img/sharp-libvips-darwin-arm64": { 843 + "version": "1.2.4", 844 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", 845 + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", 846 + "cpu": [ 847 + "arm64" 848 + ], 849 + "license": "LGPL-3.0-or-later", 850 + "optional": true, 851 + "os": [ 852 + "darwin" 853 + ], 854 + "funding": { 855 + "url": "https://opencollective.com/libvips" 856 + } 857 + }, 858 + "node_modules/@img/sharp-libvips-darwin-x64": { 859 + "version": "1.2.4", 860 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", 861 + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", 862 + "cpu": [ 863 + "x64" 864 + ], 865 + "license": "LGPL-3.0-or-later", 866 + "optional": true, 867 + "os": [ 868 + "darwin" 869 + ], 870 + "funding": { 871 + "url": "https://opencollective.com/libvips" 872 + } 873 + }, 874 + "node_modules/@img/sharp-libvips-linux-arm": { 875 + "version": "1.2.4", 876 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", 877 + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", 878 + "cpu": [ 879 + "arm" 880 + ], 881 + "license": "LGPL-3.0-or-later", 882 + "optional": true, 883 + "os": [ 884 + "linux" 885 + ], 886 + "funding": { 887 + "url": "https://opencollective.com/libvips" 888 + } 889 + }, 890 + "node_modules/@img/sharp-libvips-linux-arm64": { 891 + "version": "1.2.4", 892 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", 893 + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", 894 + "cpu": [ 895 + "arm64" 896 + ], 897 + "license": "LGPL-3.0-or-later", 898 + "optional": true, 899 + "os": [ 900 + "linux" 901 + ], 902 + "funding": { 903 + "url": "https://opencollective.com/libvips" 904 + } 905 + }, 906 + "node_modules/@img/sharp-libvips-linux-ppc64": { 907 + "version": "1.2.4", 908 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", 909 + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", 910 + "cpu": [ 911 + "ppc64" 912 + ], 913 + "license": "LGPL-3.0-or-later", 914 + "optional": true, 915 + "os": [ 916 + "linux" 917 + ], 918 + "funding": { 919 + "url": "https://opencollective.com/libvips" 920 + } 921 + }, 922 + "node_modules/@img/sharp-libvips-linux-riscv64": { 923 + "version": "1.2.4", 924 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", 925 + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", 926 + "cpu": [ 927 + "riscv64" 928 + ], 929 + "license": "LGPL-3.0-or-later", 930 + "optional": true, 931 + "os": [ 932 + "linux" 933 + ], 934 + "funding": { 935 + "url": "https://opencollective.com/libvips" 936 + } 937 + }, 938 + "node_modules/@img/sharp-libvips-linux-s390x": { 939 + "version": "1.2.4", 940 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", 941 + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", 942 + "cpu": [ 943 + "s390x" 944 + ], 945 + "license": "LGPL-3.0-or-later", 946 + "optional": true, 947 + "os": [ 948 + "linux" 949 + ], 950 + "funding": { 951 + "url": "https://opencollective.com/libvips" 952 + } 953 + }, 954 + "node_modules/@img/sharp-libvips-linux-x64": { 955 + "version": "1.2.4", 956 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", 957 + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", 958 + "cpu": [ 959 + "x64" 960 + ], 961 + "license": "LGPL-3.0-or-later", 962 + "optional": true, 963 + "os": [ 964 + "linux" 965 + ], 966 + "funding": { 967 + "url": "https://opencollective.com/libvips" 968 + } 969 + }, 970 + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { 971 + "version": "1.2.4", 972 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", 973 + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", 974 + "cpu": [ 975 + "arm64" 976 + ], 977 + "license": "LGPL-3.0-or-later", 978 + "optional": true, 979 + "os": [ 980 + "linux" 981 + ], 982 + "funding": { 983 + "url": "https://opencollective.com/libvips" 984 + } 985 + }, 986 + "node_modules/@img/sharp-libvips-linuxmusl-x64": { 987 + "version": "1.2.4", 988 + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", 989 + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", 990 + "cpu": [ 991 + "x64" 992 + ], 993 + "license": "LGPL-3.0-or-later", 994 + "optional": true, 995 + "os": [ 996 + "linux" 997 + ], 998 + "funding": { 999 + "url": "https://opencollective.com/libvips" 1000 + } 1001 + }, 1002 + "node_modules/@img/sharp-linux-arm": { 1003 + "version": "0.34.5", 1004 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", 1005 + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", 1006 + "cpu": [ 1007 + "arm" 1008 + ], 1009 + "license": "Apache-2.0", 1010 + "optional": true, 1011 + "os": [ 1012 + "linux" 1013 + ], 1014 + "engines": { 1015 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1016 + }, 1017 + "funding": { 1018 + "url": "https://opencollective.com/libvips" 1019 + }, 1020 + "optionalDependencies": { 1021 + "@img/sharp-libvips-linux-arm": "1.2.4" 1022 + } 1023 + }, 1024 + "node_modules/@img/sharp-linux-arm64": { 1025 + "version": "0.34.5", 1026 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", 1027 + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", 1028 + "cpu": [ 1029 + "arm64" 1030 + ], 1031 + "license": "Apache-2.0", 1032 + "optional": true, 1033 + "os": [ 1034 + "linux" 1035 + ], 1036 + "engines": { 1037 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1038 + }, 1039 + "funding": { 1040 + "url": "https://opencollective.com/libvips" 1041 + }, 1042 + "optionalDependencies": { 1043 + "@img/sharp-libvips-linux-arm64": "1.2.4" 1044 + } 1045 + }, 1046 + "node_modules/@img/sharp-linux-ppc64": { 1047 + "version": "0.34.5", 1048 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", 1049 + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", 1050 + "cpu": [ 1051 + "ppc64" 1052 + ], 1053 + "license": "Apache-2.0", 1054 + "optional": true, 1055 + "os": [ 1056 + "linux" 1057 + ], 1058 + "engines": { 1059 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1060 + }, 1061 + "funding": { 1062 + "url": "https://opencollective.com/libvips" 1063 + }, 1064 + "optionalDependencies": { 1065 + "@img/sharp-libvips-linux-ppc64": "1.2.4" 1066 + } 1067 + }, 1068 + "node_modules/@img/sharp-linux-riscv64": { 1069 + "version": "0.34.5", 1070 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", 1071 + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", 1072 + "cpu": [ 1073 + "riscv64" 1074 + ], 1075 + "license": "Apache-2.0", 1076 + "optional": true, 1077 + "os": [ 1078 + "linux" 1079 + ], 1080 + "engines": { 1081 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1082 + }, 1083 + "funding": { 1084 + "url": "https://opencollective.com/libvips" 1085 + }, 1086 + "optionalDependencies": { 1087 + "@img/sharp-libvips-linux-riscv64": "1.2.4" 1088 + } 1089 + }, 1090 + "node_modules/@img/sharp-linux-s390x": { 1091 + "version": "0.34.5", 1092 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", 1093 + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", 1094 + "cpu": [ 1095 + "s390x" 1096 + ], 1097 + "license": "Apache-2.0", 1098 + "optional": true, 1099 + "os": [ 1100 + "linux" 1101 + ], 1102 + "engines": { 1103 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1104 + }, 1105 + "funding": { 1106 + "url": "https://opencollective.com/libvips" 1107 + }, 1108 + "optionalDependencies": { 1109 + "@img/sharp-libvips-linux-s390x": "1.2.4" 1110 + } 1111 + }, 1112 + "node_modules/@img/sharp-linux-x64": { 1113 + "version": "0.34.5", 1114 + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", 1115 + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", 1116 + "cpu": [ 1117 + "x64" 1118 + ], 1119 + "license": "Apache-2.0", 1120 + "optional": true, 1121 + "os": [ 1122 + "linux" 1123 + ], 1124 + "engines": { 1125 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1126 + }, 1127 + "funding": { 1128 + "url": "https://opencollective.com/libvips" 1129 + }, 1130 + "optionalDependencies": { 1131 + "@img/sharp-libvips-linux-x64": "1.2.4" 1132 + } 1133 + }, 1134 + "node_modules/@img/sharp-linuxmusl-arm64": { 1135 + "version": "0.34.5", 1136 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", 1137 + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", 1138 + "cpu": [ 1139 + "arm64" 1140 + ], 1141 + "license": "Apache-2.0", 1142 + "optional": true, 1143 + "os": [ 1144 + "linux" 1145 + ], 1146 + "engines": { 1147 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1148 + }, 1149 + "funding": { 1150 + "url": "https://opencollective.com/libvips" 1151 + }, 1152 + "optionalDependencies": { 1153 + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" 1154 + } 1155 + }, 1156 + "node_modules/@img/sharp-linuxmusl-x64": { 1157 + "version": "0.34.5", 1158 + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", 1159 + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", 1160 + "cpu": [ 1161 + "x64" 1162 + ], 1163 + "license": "Apache-2.0", 1164 + "optional": true, 1165 + "os": [ 1166 + "linux" 1167 + ], 1168 + "engines": { 1169 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1170 + }, 1171 + "funding": { 1172 + "url": "https://opencollective.com/libvips" 1173 + }, 1174 + "optionalDependencies": { 1175 + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" 1176 + } 1177 + }, 1178 + "node_modules/@img/sharp-wasm32": { 1179 + "version": "0.34.5", 1180 + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", 1181 + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", 1182 + "cpu": [ 1183 + "wasm32" 1184 + ], 1185 + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", 1186 + "optional": true, 1187 + "dependencies": { 1188 + "@emnapi/runtime": "^1.7.0" 1189 + }, 1190 + "engines": { 1191 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1192 + }, 1193 + "funding": { 1194 + "url": "https://opencollective.com/libvips" 1195 + } 1196 + }, 1197 + "node_modules/@img/sharp-win32-arm64": { 1198 + "version": "0.34.5", 1199 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", 1200 + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", 1201 + "cpu": [ 1202 + "arm64" 1203 + ], 1204 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 1205 + "optional": true, 1206 + "os": [ 1207 + "win32" 1208 + ], 1209 + "engines": { 1210 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1211 + }, 1212 + "funding": { 1213 + "url": "https://opencollective.com/libvips" 1214 + } 1215 + }, 1216 + "node_modules/@img/sharp-win32-ia32": { 1217 + "version": "0.34.5", 1218 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", 1219 + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", 1220 + "cpu": [ 1221 + "ia32" 1222 + ], 1223 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 1224 + "optional": true, 1225 + "os": [ 1226 + "win32" 1227 + ], 1228 + "engines": { 1229 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1230 + }, 1231 + "funding": { 1232 + "url": "https://opencollective.com/libvips" 1233 + } 1234 + }, 1235 + "node_modules/@img/sharp-win32-x64": { 1236 + "version": "0.34.5", 1237 + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", 1238 + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", 1239 + "cpu": [ 1240 + "x64" 1241 + ], 1242 + "license": "Apache-2.0 AND LGPL-3.0-or-later", 1243 + "optional": true, 1244 + "os": [ 1245 + "win32" 1246 + ], 1247 + "engines": { 1248 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 1249 + }, 1250 + "funding": { 1251 + "url": "https://opencollective.com/libvips" 1252 + } 1253 + }, 1254 + "node_modules/@jridgewell/gen-mapping": { 1255 + "version": "0.3.13", 1256 + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", 1257 + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", 1258 + "dev": true, 1259 + "license": "MIT", 1260 + "dependencies": { 1261 + "@jridgewell/sourcemap-codec": "^1.5.0", 1262 + "@jridgewell/trace-mapping": "^0.3.24" 1263 + } 1264 + }, 1265 + "node_modules/@jridgewell/remapping": { 1266 + "version": "2.3.5", 1267 + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", 1268 + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", 1269 + "dev": true, 1270 + "license": "MIT", 1271 + "dependencies": { 1272 + "@jridgewell/gen-mapping": "^0.3.5", 1273 + "@jridgewell/trace-mapping": "^0.3.24" 1274 + } 1275 + }, 1276 + "node_modules/@jridgewell/resolve-uri": { 1277 + "version": "3.1.2", 1278 + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 1279 + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 1280 + "dev": true, 1281 + "license": "MIT", 1282 + "engines": { 1283 + "node": ">=6.0.0" 1284 + } 1285 + }, 1286 + "node_modules/@jridgewell/sourcemap-codec": { 1287 + "version": "1.5.5", 1288 + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", 1289 + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", 1290 + "license": "MIT" 1291 + }, 1292 + "node_modules/@jridgewell/trace-mapping": { 1293 + "version": "0.3.31", 1294 + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", 1295 + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", 1296 + "dev": true, 1297 + "license": "MIT", 1298 + "dependencies": { 1299 + "@jridgewell/resolve-uri": "^3.1.0", 1300 + "@jridgewell/sourcemap-codec": "^1.4.14" 1301 + } 1302 + }, 1303 + "node_modules/@oslojs/encoding": { 1304 + "version": "1.1.0", 1305 + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", 1306 + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", 1307 + "license": "MIT" 1308 + }, 1309 + "node_modules/@playwright/test": { 1310 + "version": "1.58.2", 1311 + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", 1312 + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", 1313 + "dev": true, 1314 + "license": "Apache-2.0", 1315 + "dependencies": { 1316 + "playwright": "1.58.2" 1317 + }, 1318 + "bin": { 1319 + "playwright": "cli.js" 1320 + }, 1321 + "engines": { 1322 + "node": ">=18" 1323 + } 1324 + }, 1325 + "node_modules/@rollup/pluginutils": { 1326 + "version": "5.3.0", 1327 + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", 1328 + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", 1329 + "license": "MIT", 1330 + "dependencies": { 1331 + "@types/estree": "^1.0.0", 1332 + "estree-walker": "^2.0.2", 1333 + "picomatch": "^4.0.2" 1334 + }, 1335 + "engines": { 1336 + "node": ">=14.0.0" 1337 + }, 1338 + "peerDependencies": { 1339 + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" 1340 + }, 1341 + "peerDependenciesMeta": { 1342 + "rollup": { 1343 + "optional": true 1344 + } 1345 + } 1346 + }, 1347 + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { 1348 + "version": "2.0.2", 1349 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 1350 + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 1351 + "license": "MIT" 1352 + }, 1353 + "node_modules/@rollup/rollup-android-arm-eabi": { 1354 + "version": "4.59.0", 1355 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", 1356 + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", 1357 + "cpu": [ 1358 + "arm" 1359 + ], 1360 + "license": "MIT", 1361 + "optional": true, 1362 + "os": [ 1363 + "android" 1364 + ] 1365 + }, 1366 + "node_modules/@rollup/rollup-android-arm64": { 1367 + "version": "4.59.0", 1368 + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", 1369 + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", 1370 + "cpu": [ 1371 + "arm64" 1372 + ], 1373 + "license": "MIT", 1374 + "optional": true, 1375 + "os": [ 1376 + "android" 1377 + ] 1378 + }, 1379 + "node_modules/@rollup/rollup-darwin-arm64": { 1380 + "version": "4.59.0", 1381 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", 1382 + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", 1383 + "cpu": [ 1384 + "arm64" 1385 + ], 1386 + "license": "MIT", 1387 + "optional": true, 1388 + "os": [ 1389 + "darwin" 1390 + ] 1391 + }, 1392 + "node_modules/@rollup/rollup-darwin-x64": { 1393 + "version": "4.59.0", 1394 + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", 1395 + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", 1396 + "cpu": [ 1397 + "x64" 1398 + ], 1399 + "license": "MIT", 1400 + "optional": true, 1401 + "os": [ 1402 + "darwin" 1403 + ] 1404 + }, 1405 + "node_modules/@rollup/rollup-freebsd-arm64": { 1406 + "version": "4.59.0", 1407 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", 1408 + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", 1409 + "cpu": [ 1410 + "arm64" 1411 + ], 1412 + "license": "MIT", 1413 + "optional": true, 1414 + "os": [ 1415 + "freebsd" 1416 + ] 1417 + }, 1418 + "node_modules/@rollup/rollup-freebsd-x64": { 1419 + "version": "4.59.0", 1420 + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", 1421 + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", 1422 + "cpu": [ 1423 + "x64" 1424 + ], 1425 + "license": "MIT", 1426 + "optional": true, 1427 + "os": [ 1428 + "freebsd" 1429 + ] 1430 + }, 1431 + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 1432 + "version": "4.59.0", 1433 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", 1434 + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", 1435 + "cpu": [ 1436 + "arm" 1437 + ], 1438 + "license": "MIT", 1439 + "optional": true, 1440 + "os": [ 1441 + "linux" 1442 + ] 1443 + }, 1444 + "node_modules/@rollup/rollup-linux-arm-musleabihf": { 1445 + "version": "4.59.0", 1446 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", 1447 + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", 1448 + "cpu": [ 1449 + "arm" 1450 + ], 1451 + "license": "MIT", 1452 + "optional": true, 1453 + "os": [ 1454 + "linux" 1455 + ] 1456 + }, 1457 + "node_modules/@rollup/rollup-linux-arm64-gnu": { 1458 + "version": "4.59.0", 1459 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", 1460 + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", 1461 + "cpu": [ 1462 + "arm64" 1463 + ], 1464 + "license": "MIT", 1465 + "optional": true, 1466 + "os": [ 1467 + "linux" 1468 + ] 1469 + }, 1470 + "node_modules/@rollup/rollup-linux-arm64-musl": { 1471 + "version": "4.59.0", 1472 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", 1473 + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", 1474 + "cpu": [ 1475 + "arm64" 1476 + ], 1477 + "license": "MIT", 1478 + "optional": true, 1479 + "os": [ 1480 + "linux" 1481 + ] 1482 + }, 1483 + "node_modules/@rollup/rollup-linux-loong64-gnu": { 1484 + "version": "4.59.0", 1485 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", 1486 + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", 1487 + "cpu": [ 1488 + "loong64" 1489 + ], 1490 + "license": "MIT", 1491 + "optional": true, 1492 + "os": [ 1493 + "linux" 1494 + ] 1495 + }, 1496 + "node_modules/@rollup/rollup-linux-loong64-musl": { 1497 + "version": "4.59.0", 1498 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", 1499 + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", 1500 + "cpu": [ 1501 + "loong64" 1502 + ], 1503 + "license": "MIT", 1504 + "optional": true, 1505 + "os": [ 1506 + "linux" 1507 + ] 1508 + }, 1509 + "node_modules/@rollup/rollup-linux-ppc64-gnu": { 1510 + "version": "4.59.0", 1511 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", 1512 + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", 1513 + "cpu": [ 1514 + "ppc64" 1515 + ], 1516 + "license": "MIT", 1517 + "optional": true, 1518 + "os": [ 1519 + "linux" 1520 + ] 1521 + }, 1522 + "node_modules/@rollup/rollup-linux-ppc64-musl": { 1523 + "version": "4.59.0", 1524 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", 1525 + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", 1526 + "cpu": [ 1527 + "ppc64" 1528 + ], 1529 + "license": "MIT", 1530 + "optional": true, 1531 + "os": [ 1532 + "linux" 1533 + ] 1534 + }, 1535 + "node_modules/@rollup/rollup-linux-riscv64-gnu": { 1536 + "version": "4.59.0", 1537 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", 1538 + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", 1539 + "cpu": [ 1540 + "riscv64" 1541 + ], 1542 + "license": "MIT", 1543 + "optional": true, 1544 + "os": [ 1545 + "linux" 1546 + ] 1547 + }, 1548 + "node_modules/@rollup/rollup-linux-riscv64-musl": { 1549 + "version": "4.59.0", 1550 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", 1551 + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", 1552 + "cpu": [ 1553 + "riscv64" 1554 + ], 1555 + "license": "MIT", 1556 + "optional": true, 1557 + "os": [ 1558 + "linux" 1559 + ] 1560 + }, 1561 + "node_modules/@rollup/rollup-linux-s390x-gnu": { 1562 + "version": "4.59.0", 1563 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", 1564 + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", 1565 + "cpu": [ 1566 + "s390x" 1567 + ], 1568 + "license": "MIT", 1569 + "optional": true, 1570 + "os": [ 1571 + "linux" 1572 + ] 1573 + }, 1574 + "node_modules/@rollup/rollup-linux-x64-gnu": { 1575 + "version": "4.59.0", 1576 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", 1577 + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", 1578 + "cpu": [ 1579 + "x64" 1580 + ], 1581 + "license": "MIT", 1582 + "optional": true, 1583 + "os": [ 1584 + "linux" 1585 + ] 1586 + }, 1587 + "node_modules/@rollup/rollup-linux-x64-musl": { 1588 + "version": "4.59.0", 1589 + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", 1590 + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", 1591 + "cpu": [ 1592 + "x64" 1593 + ], 1594 + "license": "MIT", 1595 + "optional": true, 1596 + "os": [ 1597 + "linux" 1598 + ] 1599 + }, 1600 + "node_modules/@rollup/rollup-openbsd-x64": { 1601 + "version": "4.59.0", 1602 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", 1603 + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", 1604 + "cpu": [ 1605 + "x64" 1606 + ], 1607 + "license": "MIT", 1608 + "optional": true, 1609 + "os": [ 1610 + "openbsd" 1611 + ] 1612 + }, 1613 + "node_modules/@rollup/rollup-openharmony-arm64": { 1614 + "version": "4.59.0", 1615 + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", 1616 + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", 1617 + "cpu": [ 1618 + "arm64" 1619 + ], 1620 + "license": "MIT", 1621 + "optional": true, 1622 + "os": [ 1623 + "openharmony" 1624 + ] 1625 + }, 1626 + "node_modules/@rollup/rollup-win32-arm64-msvc": { 1627 + "version": "4.59.0", 1628 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", 1629 + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", 1630 + "cpu": [ 1631 + "arm64" 1632 + ], 1633 + "license": "MIT", 1634 + "optional": true, 1635 + "os": [ 1636 + "win32" 1637 + ] 1638 + }, 1639 + "node_modules/@rollup/rollup-win32-ia32-msvc": { 1640 + "version": "4.59.0", 1641 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", 1642 + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", 1643 + "cpu": [ 1644 + "ia32" 1645 + ], 1646 + "license": "MIT", 1647 + "optional": true, 1648 + "os": [ 1649 + "win32" 1650 + ] 1651 + }, 1652 + "node_modules/@rollup/rollup-win32-x64-gnu": { 1653 + "version": "4.59.0", 1654 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", 1655 + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", 1656 + "cpu": [ 1657 + "x64" 1658 + ], 1659 + "license": "MIT", 1660 + "optional": true, 1661 + "os": [ 1662 + "win32" 1663 + ] 1664 + }, 1665 + "node_modules/@rollup/rollup-win32-x64-msvc": { 1666 + "version": "4.59.0", 1667 + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", 1668 + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", 1669 + "cpu": [ 1670 + "x64" 1671 + ], 1672 + "license": "MIT", 1673 + "optional": true, 1674 + "os": [ 1675 + "win32" 1676 + ] 1677 + }, 1678 + "node_modules/@shikijs/core": { 1679 + "version": "3.23.0", 1680 + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", 1681 + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", 1682 + "license": "MIT", 1683 + "dependencies": { 1684 + "@shikijs/types": "3.23.0", 1685 + "@shikijs/vscode-textmate": "^10.0.2", 1686 + "@types/hast": "^3.0.4", 1687 + "hast-util-to-html": "^9.0.5" 1688 + } 1689 + }, 1690 + "node_modules/@shikijs/engine-javascript": { 1691 + "version": "3.23.0", 1692 + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", 1693 + "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", 1694 + "license": "MIT", 1695 + "dependencies": { 1696 + "@shikijs/types": "3.23.0", 1697 + "@shikijs/vscode-textmate": "^10.0.2", 1698 + "oniguruma-to-es": "^4.3.4" 1699 + } 1700 + }, 1701 + "node_modules/@shikijs/engine-oniguruma": { 1702 + "version": "3.23.0", 1703 + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", 1704 + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", 1705 + "license": "MIT", 1706 + "dependencies": { 1707 + "@shikijs/types": "3.23.0", 1708 + "@shikijs/vscode-textmate": "^10.0.2" 1709 + } 1710 + }, 1711 + "node_modules/@shikijs/langs": { 1712 + "version": "3.23.0", 1713 + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", 1714 + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", 1715 + "license": "MIT", 1716 + "dependencies": { 1717 + "@shikijs/types": "3.23.0" 1718 + } 1719 + }, 1720 + "node_modules/@shikijs/themes": { 1721 + "version": "3.23.0", 1722 + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", 1723 + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", 1724 + "license": "MIT", 1725 + "dependencies": { 1726 + "@shikijs/types": "3.23.0" 1727 + } 1728 + }, 1729 + "node_modules/@shikijs/types": { 1730 + "version": "3.23.0", 1731 + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", 1732 + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", 1733 + "license": "MIT", 1734 + "dependencies": { 1735 + "@shikijs/vscode-textmate": "^10.0.2", 1736 + "@types/hast": "^3.0.4" 1737 + } 1738 + }, 1739 + "node_modules/@shikijs/vscode-textmate": { 1740 + "version": "10.0.2", 1741 + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", 1742 + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", 1743 + "license": "MIT" 1744 + }, 1745 + "node_modules/@standard-schema/spec": { 1746 + "version": "1.1.0", 1747 + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", 1748 + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", 1749 + "dev": true, 1750 + "license": "MIT" 1751 + }, 1752 + "node_modules/@tailwindcss/node": { 1753 + "version": "4.2.1", 1754 + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", 1755 + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", 1756 + "dev": true, 1757 + "license": "MIT", 1758 + "dependencies": { 1759 + "@jridgewell/remapping": "^2.3.5", 1760 + "enhanced-resolve": "^5.19.0", 1761 + "jiti": "^2.6.1", 1762 + "lightningcss": "1.31.1", 1763 + "magic-string": "^0.30.21", 1764 + "source-map-js": "^1.2.1", 1765 + "tailwindcss": "4.2.1" 1766 + } 1767 + }, 1768 + "node_modules/@tailwindcss/oxide": { 1769 + "version": "4.2.1", 1770 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", 1771 + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", 1772 + "dev": true, 1773 + "license": "MIT", 1774 + "engines": { 1775 + "node": ">= 20" 1776 + }, 1777 + "optionalDependencies": { 1778 + "@tailwindcss/oxide-android-arm64": "4.2.1", 1779 + "@tailwindcss/oxide-darwin-arm64": "4.2.1", 1780 + "@tailwindcss/oxide-darwin-x64": "4.2.1", 1781 + "@tailwindcss/oxide-freebsd-x64": "4.2.1", 1782 + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", 1783 + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", 1784 + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", 1785 + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", 1786 + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", 1787 + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", 1788 + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", 1789 + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" 1790 + } 1791 + }, 1792 + "node_modules/@tailwindcss/oxide-android-arm64": { 1793 + "version": "4.2.1", 1794 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", 1795 + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", 1796 + "cpu": [ 1797 + "arm64" 1798 + ], 1799 + "dev": true, 1800 + "license": "MIT", 1801 + "optional": true, 1802 + "os": [ 1803 + "android" 1804 + ], 1805 + "engines": { 1806 + "node": ">= 20" 1807 + } 1808 + }, 1809 + "node_modules/@tailwindcss/oxide-darwin-arm64": { 1810 + "version": "4.2.1", 1811 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", 1812 + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", 1813 + "cpu": [ 1814 + "arm64" 1815 + ], 1816 + "dev": true, 1817 + "license": "MIT", 1818 + "optional": true, 1819 + "os": [ 1820 + "darwin" 1821 + ], 1822 + "engines": { 1823 + "node": ">= 20" 1824 + } 1825 + }, 1826 + "node_modules/@tailwindcss/oxide-darwin-x64": { 1827 + "version": "4.2.1", 1828 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", 1829 + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", 1830 + "cpu": [ 1831 + "x64" 1832 + ], 1833 + "dev": true, 1834 + "license": "MIT", 1835 + "optional": true, 1836 + "os": [ 1837 + "darwin" 1838 + ], 1839 + "engines": { 1840 + "node": ">= 20" 1841 + } 1842 + }, 1843 + "node_modules/@tailwindcss/oxide-freebsd-x64": { 1844 + "version": "4.2.1", 1845 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", 1846 + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", 1847 + "cpu": [ 1848 + "x64" 1849 + ], 1850 + "dev": true, 1851 + "license": "MIT", 1852 + "optional": true, 1853 + "os": [ 1854 + "freebsd" 1855 + ], 1856 + "engines": { 1857 + "node": ">= 20" 1858 + } 1859 + }, 1860 + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { 1861 + "version": "4.2.1", 1862 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", 1863 + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", 1864 + "cpu": [ 1865 + "arm" 1866 + ], 1867 + "dev": true, 1868 + "license": "MIT", 1869 + "optional": true, 1870 + "os": [ 1871 + "linux" 1872 + ], 1873 + "engines": { 1874 + "node": ">= 20" 1875 + } 1876 + }, 1877 + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { 1878 + "version": "4.2.1", 1879 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", 1880 + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", 1881 + "cpu": [ 1882 + "arm64" 1883 + ], 1884 + "dev": true, 1885 + "license": "MIT", 1886 + "optional": true, 1887 + "os": [ 1888 + "linux" 1889 + ], 1890 + "engines": { 1891 + "node": ">= 20" 1892 + } 1893 + }, 1894 + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { 1895 + "version": "4.2.1", 1896 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", 1897 + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", 1898 + "cpu": [ 1899 + "arm64" 1900 + ], 1901 + "dev": true, 1902 + "license": "MIT", 1903 + "optional": true, 1904 + "os": [ 1905 + "linux" 1906 + ], 1907 + "engines": { 1908 + "node": ">= 20" 1909 + } 1910 + }, 1911 + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { 1912 + "version": "4.2.1", 1913 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", 1914 + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", 1915 + "cpu": [ 1916 + "x64" 1917 + ], 1918 + "dev": true, 1919 + "license": "MIT", 1920 + "optional": true, 1921 + "os": [ 1922 + "linux" 1923 + ], 1924 + "engines": { 1925 + "node": ">= 20" 1926 + } 1927 + }, 1928 + "node_modules/@tailwindcss/oxide-linux-x64-musl": { 1929 + "version": "4.2.1", 1930 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", 1931 + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", 1932 + "cpu": [ 1933 + "x64" 1934 + ], 1935 + "dev": true, 1936 + "license": "MIT", 1937 + "optional": true, 1938 + "os": [ 1939 + "linux" 1940 + ], 1941 + "engines": { 1942 + "node": ">= 20" 1943 + } 1944 + }, 1945 + "node_modules/@tailwindcss/oxide-wasm32-wasi": { 1946 + "version": "4.2.1", 1947 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", 1948 + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", 1949 + "bundleDependencies": [ 1950 + "@napi-rs/wasm-runtime", 1951 + "@emnapi/core", 1952 + "@emnapi/runtime", 1953 + "@tybys/wasm-util", 1954 + "@emnapi/wasi-threads", 1955 + "tslib" 1956 + ], 1957 + "cpu": [ 1958 + "wasm32" 1959 + ], 1960 + "dev": true, 1961 + "license": "MIT", 1962 + "optional": true, 1963 + "dependencies": { 1964 + "@emnapi/core": "^1.8.1", 1965 + "@emnapi/runtime": "^1.8.1", 1966 + "@emnapi/wasi-threads": "^1.1.0", 1967 + "@napi-rs/wasm-runtime": "^1.1.1", 1968 + "@tybys/wasm-util": "^0.10.1", 1969 + "tslib": "^2.8.1" 1970 + }, 1971 + "engines": { 1972 + "node": ">=14.0.0" 1973 + } 1974 + }, 1975 + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { 1976 + "version": "4.2.1", 1977 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", 1978 + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", 1979 + "cpu": [ 1980 + "arm64" 1981 + ], 1982 + "dev": true, 1983 + "license": "MIT", 1984 + "optional": true, 1985 + "os": [ 1986 + "win32" 1987 + ], 1988 + "engines": { 1989 + "node": ">= 20" 1990 + } 1991 + }, 1992 + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { 1993 + "version": "4.2.1", 1994 + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", 1995 + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", 1996 + "cpu": [ 1997 + "x64" 1998 + ], 1999 + "dev": true, 2000 + "license": "MIT", 2001 + "optional": true, 2002 + "os": [ 2003 + "win32" 2004 + ], 2005 + "engines": { 2006 + "node": ">= 20" 2007 + } 2008 + }, 2009 + "node_modules/@tailwindcss/vite": { 2010 + "version": "4.2.1", 2011 + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz", 2012 + "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==", 2013 + "dev": true, 2014 + "license": "MIT", 2015 + "dependencies": { 2016 + "@tailwindcss/node": "4.2.1", 2017 + "@tailwindcss/oxide": "4.2.1", 2018 + "tailwindcss": "4.2.1" 2019 + }, 2020 + "peerDependencies": { 2021 + "vite": "^5.2.0 || ^6 || ^7" 2022 + } 2023 + }, 2024 + "node_modules/@types/chai": { 2025 + "version": "5.2.3", 2026 + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", 2027 + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", 2028 + "dev": true, 2029 + "license": "MIT", 2030 + "dependencies": { 2031 + "@types/deep-eql": "*", 2032 + "assertion-error": "^2.0.1" 2033 + } 2034 + }, 2035 + "node_modules/@types/debug": { 2036 + "version": "4.1.12", 2037 + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", 2038 + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", 2039 + "license": "MIT", 2040 + "dependencies": { 2041 + "@types/ms": "*" 2042 + } 2043 + }, 2044 + "node_modules/@types/deep-eql": { 2045 + "version": "4.0.2", 2046 + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", 2047 + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", 2048 + "dev": true, 2049 + "license": "MIT" 2050 + }, 2051 + "node_modules/@types/estree": { 2052 + "version": "1.0.8", 2053 + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 2054 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 2055 + "license": "MIT" 2056 + }, 2057 + "node_modules/@types/hast": { 2058 + "version": "3.0.4", 2059 + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", 2060 + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", 2061 + "license": "MIT", 2062 + "dependencies": { 2063 + "@types/unist": "*" 2064 + } 2065 + }, 2066 + "node_modules/@types/mdast": { 2067 + "version": "4.0.4", 2068 + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", 2069 + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", 2070 + "license": "MIT", 2071 + "dependencies": { 2072 + "@types/unist": "*" 2073 + } 2074 + }, 2075 + "node_modules/@types/ms": { 2076 + "version": "2.1.0", 2077 + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", 2078 + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", 2079 + "license": "MIT" 2080 + }, 2081 + "node_modules/@types/nlcst": { 2082 + "version": "2.0.3", 2083 + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", 2084 + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", 2085 + "license": "MIT", 2086 + "dependencies": { 2087 + "@types/unist": "*" 2088 + } 2089 + }, 2090 + "node_modules/@types/trusted-types": { 2091 + "version": "2.0.7", 2092 + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", 2093 + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", 2094 + "license": "MIT", 2095 + "optional": true 2096 + }, 2097 + "node_modules/@types/unist": { 2098 + "version": "3.0.3", 2099 + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", 2100 + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", 2101 + "license": "MIT" 2102 + }, 2103 + "node_modules/@ungap/structured-clone": { 2104 + "version": "1.3.0", 2105 + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", 2106 + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", 2107 + "license": "ISC" 2108 + }, 2109 + "node_modules/@vitest/expect": { 2110 + "version": "4.0.18", 2111 + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", 2112 + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", 2113 + "dev": true, 2114 + "license": "MIT", 2115 + "dependencies": { 2116 + "@standard-schema/spec": "^1.0.0", 2117 + "@types/chai": "^5.2.2", 2118 + "@vitest/spy": "4.0.18", 2119 + "@vitest/utils": "4.0.18", 2120 + "chai": "^6.2.1", 2121 + "tinyrainbow": "^3.0.3" 2122 + }, 2123 + "funding": { 2124 + "url": "https://opencollective.com/vitest" 2125 + } 2126 + }, 2127 + "node_modules/@vitest/mocker": { 2128 + "version": "4.0.18", 2129 + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", 2130 + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", 2131 + "dev": true, 2132 + "license": "MIT", 2133 + "dependencies": { 2134 + "@vitest/spy": "4.0.18", 2135 + "estree-walker": "^3.0.3", 2136 + "magic-string": "^0.30.21" 2137 + }, 2138 + "funding": { 2139 + "url": "https://opencollective.com/vitest" 2140 + }, 2141 + "peerDependencies": { 2142 + "msw": "^2.4.9", 2143 + "vite": "^6.0.0 || ^7.0.0-0" 2144 + }, 2145 + "peerDependenciesMeta": { 2146 + "msw": { 2147 + "optional": true 2148 + }, 2149 + "vite": { 2150 + "optional": true 2151 + } 2152 + } 2153 + }, 2154 + "node_modules/@vitest/pretty-format": { 2155 + "version": "4.0.18", 2156 + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", 2157 + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", 2158 + "dev": true, 2159 + "license": "MIT", 2160 + "dependencies": { 2161 + "tinyrainbow": "^3.0.3" 2162 + }, 2163 + "funding": { 2164 + "url": "https://opencollective.com/vitest" 2165 + } 2166 + }, 2167 + "node_modules/@vitest/runner": { 2168 + "version": "4.0.18", 2169 + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", 2170 + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", 2171 + "dev": true, 2172 + "license": "MIT", 2173 + "dependencies": { 2174 + "@vitest/utils": "4.0.18", 2175 + "pathe": "^2.0.3" 2176 + }, 2177 + "funding": { 2178 + "url": "https://opencollective.com/vitest" 2179 + } 2180 + }, 2181 + "node_modules/@vitest/snapshot": { 2182 + "version": "4.0.18", 2183 + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", 2184 + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", 2185 + "dev": true, 2186 + "license": "MIT", 2187 + "dependencies": { 2188 + "@vitest/pretty-format": "4.0.18", 2189 + "magic-string": "^0.30.21", 2190 + "pathe": "^2.0.3" 2191 + }, 2192 + "funding": { 2193 + "url": "https://opencollective.com/vitest" 2194 + } 2195 + }, 2196 + "node_modules/@vitest/spy": { 2197 + "version": "4.0.18", 2198 + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", 2199 + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", 2200 + "dev": true, 2201 + "license": "MIT", 2202 + "funding": { 2203 + "url": "https://opencollective.com/vitest" 2204 + } 2205 + }, 2206 + "node_modules/@vitest/utils": { 2207 + "version": "4.0.18", 2208 + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", 2209 + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", 2210 + "dev": true, 2211 + "license": "MIT", 2212 + "dependencies": { 2213 + "@vitest/pretty-format": "4.0.18", 2214 + "tinyrainbow": "^3.0.3" 2215 + }, 2216 + "funding": { 2217 + "url": "https://opencollective.com/vitest" 2218 + } 2219 + }, 2220 + "node_modules/acorn": { 2221 + "version": "8.16.0", 2222 + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", 2223 + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", 2224 + "license": "MIT", 2225 + "bin": { 2226 + "acorn": "bin/acorn" 2227 + }, 2228 + "engines": { 2229 + "node": ">=0.4.0" 2230 + } 2231 + }, 2232 + "node_modules/agent-base": { 2233 + "version": "7.1.4", 2234 + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", 2235 + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", 2236 + "license": "MIT", 2237 + "engines": { 2238 + "node": ">= 14" 2239 + } 2240 + }, 2241 + "node_modules/ansi-align": { 2242 + "version": "3.0.1", 2243 + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", 2244 + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", 2245 + "license": "ISC", 2246 + "dependencies": { 2247 + "string-width": "^4.1.0" 2248 + } 2249 + }, 2250 + "node_modules/ansi-align/node_modules/ansi-regex": { 2251 + "version": "5.0.1", 2252 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 2253 + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 2254 + "license": "MIT", 2255 + "engines": { 2256 + "node": ">=8" 2257 + } 2258 + }, 2259 + "node_modules/ansi-align/node_modules/emoji-regex": { 2260 + "version": "8.0.0", 2261 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 2262 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 2263 + "license": "MIT" 2264 + }, 2265 + "node_modules/ansi-align/node_modules/string-width": { 2266 + "version": "4.2.3", 2267 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2268 + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2269 + "license": "MIT", 2270 + "dependencies": { 2271 + "emoji-regex": "^8.0.0", 2272 + "is-fullwidth-code-point": "^3.0.0", 2273 + "strip-ansi": "^6.0.1" 2274 + }, 2275 + "engines": { 2276 + "node": ">=8" 2277 + } 2278 + }, 2279 + "node_modules/ansi-align/node_modules/strip-ansi": { 2280 + "version": "6.0.1", 2281 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2282 + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2283 + "license": "MIT", 2284 + "dependencies": { 2285 + "ansi-regex": "^5.0.1" 2286 + }, 2287 + "engines": { 2288 + "node": ">=8" 2289 + } 2290 + }, 2291 + "node_modules/ansi-regex": { 2292 + "version": "6.2.2", 2293 + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", 2294 + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", 2295 + "license": "MIT", 2296 + "engines": { 2297 + "node": ">=12" 2298 + }, 2299 + "funding": { 2300 + "url": "https://github.com/chalk/ansi-regex?sponsor=1" 2301 + } 2302 + }, 2303 + "node_modules/ansi-styles": { 2304 + "version": "6.2.3", 2305 + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", 2306 + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", 2307 + "license": "MIT", 2308 + "engines": { 2309 + "node": ">=12" 2310 + }, 2311 + "funding": { 2312 + "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2313 + } 2314 + }, 2315 + "node_modules/anymatch": { 2316 + "version": "3.1.3", 2317 + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 2318 + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 2319 + "license": "ISC", 2320 + "dependencies": { 2321 + "normalize-path": "^3.0.0", 2322 + "picomatch": "^2.0.4" 2323 + }, 2324 + "engines": { 2325 + "node": ">= 8" 2326 + } 2327 + }, 2328 + "node_modules/anymatch/node_modules/picomatch": { 2329 + "version": "2.3.1", 2330 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2331 + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2332 + "license": "MIT", 2333 + "engines": { 2334 + "node": ">=8.6" 2335 + }, 2336 + "funding": { 2337 + "url": "https://github.com/sponsors/jonschlinkert" 2338 + } 2339 + }, 2340 + "node_modules/argparse": { 2341 + "version": "2.0.1", 2342 + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 2343 + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 2344 + "license": "Python-2.0" 2345 + }, 2346 + "node_modules/aria-query": { 2347 + "version": "5.3.2", 2348 + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", 2349 + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", 2350 + "license": "Apache-2.0", 2351 + "engines": { 2352 + "node": ">= 0.4" 2353 + } 2354 + }, 2355 + "node_modules/array-iterate": { 2356 + "version": "2.0.1", 2357 + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", 2358 + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", 2359 + "license": "MIT", 2360 + "funding": { 2361 + "type": "github", 2362 + "url": "https://github.com/sponsors/wooorm" 2363 + } 2364 + }, 2365 + "node_modules/assertion-error": { 2366 + "version": "2.0.1", 2367 + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 2368 + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 2369 + "dev": true, 2370 + "license": "MIT", 2371 + "engines": { 2372 + "node": ">=12" 2373 + } 2374 + }, 2375 + "node_modules/astro": { 2376 + "version": "5.18.0", 2377 + "resolved": "https://registry.npmjs.org/astro/-/astro-5.18.0.tgz", 2378 + "integrity": "sha512-CHiohwJIS4L0G6/IzE1Fx3dgWqXBCXus/od0eGUfxrZJD2um2pE7ehclMmgL/fXqbU7NfE1Ze2pq34h2QaA6iQ==", 2379 + "license": "MIT", 2380 + "dependencies": { 2381 + "@astrojs/compiler": "^2.13.0", 2382 + "@astrojs/internal-helpers": "0.7.5", 2383 + "@astrojs/markdown-remark": "6.3.10", 2384 + "@astrojs/telemetry": "3.3.0", 2385 + "@capsizecss/unpack": "^4.0.0", 2386 + "@oslojs/encoding": "^1.1.0", 2387 + "@rollup/pluginutils": "^5.3.0", 2388 + "acorn": "^8.15.0", 2389 + "aria-query": "^5.3.2", 2390 + "axobject-query": "^4.1.0", 2391 + "boxen": "8.0.1", 2392 + "ci-info": "^4.3.1", 2393 + "clsx": "^2.1.1", 2394 + "common-ancestor-path": "^1.0.1", 2395 + "cookie": "^1.1.1", 2396 + "cssesc": "^3.0.0", 2397 + "debug": "^4.4.3", 2398 + "deterministic-object-hash": "^2.0.2", 2399 + "devalue": "^5.6.2", 2400 + "diff": "^8.0.3", 2401 + "dlv": "^1.1.3", 2402 + "dset": "^3.1.4", 2403 + "es-module-lexer": "^1.7.0", 2404 + "esbuild": "^0.27.3", 2405 + "estree-walker": "^3.0.3", 2406 + "flattie": "^1.1.1", 2407 + "fontace": "~0.4.0", 2408 + "github-slugger": "^2.0.0", 2409 + "html-escaper": "3.0.3", 2410 + "http-cache-semantics": "^4.2.0", 2411 + "import-meta-resolve": "^4.2.0", 2412 + "js-yaml": "^4.1.1", 2413 + "magic-string": "^0.30.21", 2414 + "magicast": "^0.5.1", 2415 + "mrmime": "^2.0.1", 2416 + "neotraverse": "^0.6.18", 2417 + "p-limit": "^6.2.0", 2418 + "p-queue": "^8.1.1", 2419 + "package-manager-detector": "^1.6.0", 2420 + "piccolore": "^0.1.3", 2421 + "picomatch": "^4.0.3", 2422 + "prompts": "^2.4.2", 2423 + "rehype": "^13.0.2", 2424 + "semver": "^7.7.3", 2425 + "shiki": "^3.21.0", 2426 + "smol-toml": "^1.6.0", 2427 + "svgo": "^4.0.0", 2428 + "tinyexec": "^1.0.2", 2429 + "tinyglobby": "^0.2.15", 2430 + "tsconfck": "^3.1.6", 2431 + "ultrahtml": "^1.6.0", 2432 + "unifont": "~0.7.3", 2433 + "unist-util-visit": "^5.0.0", 2434 + "unstorage": "^1.17.4", 2435 + "vfile": "^6.0.3", 2436 + "vite": "^6.4.1", 2437 + "vitefu": "^1.1.1", 2438 + "xxhash-wasm": "^1.1.0", 2439 + "yargs-parser": "^21.1.1", 2440 + "yocto-spinner": "^0.2.3", 2441 + "zod": "^3.25.76", 2442 + "zod-to-json-schema": "^3.25.1", 2443 + "zod-to-ts": "^1.2.0" 2444 + }, 2445 + "bin": { 2446 + "astro": "astro.js" 2447 + }, 2448 + "engines": { 2449 + "node": "18.20.8 || ^20.3.0 || >=22.0.0", 2450 + "npm": ">=9.6.5", 2451 + "pnpm": ">=7.1.0" 2452 + }, 2453 + "funding": { 2454 + "type": "opencollective", 2455 + "url": "https://opencollective.com/astrodotbuild" 2456 + }, 2457 + "optionalDependencies": { 2458 + "sharp": "^0.34.0" 2459 + } 2460 + }, 2461 + "node_modules/astro/node_modules/@esbuild/aix-ppc64": { 2462 + "version": "0.25.12", 2463 + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", 2464 + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", 2465 + "cpu": [ 2466 + "ppc64" 2467 + ], 2468 + "license": "MIT", 2469 + "optional": true, 2470 + "os": [ 2471 + "aix" 2472 + ], 2473 + "engines": { 2474 + "node": ">=18" 2475 + } 2476 + }, 2477 + "node_modules/astro/node_modules/@esbuild/android-arm": { 2478 + "version": "0.25.12", 2479 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", 2480 + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", 2481 + "cpu": [ 2482 + "arm" 2483 + ], 2484 + "license": "MIT", 2485 + "optional": true, 2486 + "os": [ 2487 + "android" 2488 + ], 2489 + "engines": { 2490 + "node": ">=18" 2491 + } 2492 + }, 2493 + "node_modules/astro/node_modules/@esbuild/android-arm64": { 2494 + "version": "0.25.12", 2495 + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", 2496 + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", 2497 + "cpu": [ 2498 + "arm64" 2499 + ], 2500 + "license": "MIT", 2501 + "optional": true, 2502 + "os": [ 2503 + "android" 2504 + ], 2505 + "engines": { 2506 + "node": ">=18" 2507 + } 2508 + }, 2509 + "node_modules/astro/node_modules/@esbuild/android-x64": { 2510 + "version": "0.25.12", 2511 + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", 2512 + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", 2513 + "cpu": [ 2514 + "x64" 2515 + ], 2516 + "license": "MIT", 2517 + "optional": true, 2518 + "os": [ 2519 + "android" 2520 + ], 2521 + "engines": { 2522 + "node": ">=18" 2523 + } 2524 + }, 2525 + "node_modules/astro/node_modules/@esbuild/darwin-arm64": { 2526 + "version": "0.25.12", 2527 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", 2528 + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", 2529 + "cpu": [ 2530 + "arm64" 2531 + ], 2532 + "license": "MIT", 2533 + "optional": true, 2534 + "os": [ 2535 + "darwin" 2536 + ], 2537 + "engines": { 2538 + "node": ">=18" 2539 + } 2540 + }, 2541 + "node_modules/astro/node_modules/@esbuild/darwin-x64": { 2542 + "version": "0.25.12", 2543 + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", 2544 + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", 2545 + "cpu": [ 2546 + "x64" 2547 + ], 2548 + "license": "MIT", 2549 + "optional": true, 2550 + "os": [ 2551 + "darwin" 2552 + ], 2553 + "engines": { 2554 + "node": ">=18" 2555 + } 2556 + }, 2557 + "node_modules/astro/node_modules/@esbuild/freebsd-arm64": { 2558 + "version": "0.25.12", 2559 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", 2560 + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", 2561 + "cpu": [ 2562 + "arm64" 2563 + ], 2564 + "license": "MIT", 2565 + "optional": true, 2566 + "os": [ 2567 + "freebsd" 2568 + ], 2569 + "engines": { 2570 + "node": ">=18" 2571 + } 2572 + }, 2573 + "node_modules/astro/node_modules/@esbuild/freebsd-x64": { 2574 + "version": "0.25.12", 2575 + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", 2576 + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", 2577 + "cpu": [ 2578 + "x64" 2579 + ], 2580 + "license": "MIT", 2581 + "optional": true, 2582 + "os": [ 2583 + "freebsd" 2584 + ], 2585 + "engines": { 2586 + "node": ">=18" 2587 + } 2588 + }, 2589 + "node_modules/astro/node_modules/@esbuild/linux-arm": { 2590 + "version": "0.25.12", 2591 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", 2592 + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", 2593 + "cpu": [ 2594 + "arm" 2595 + ], 2596 + "license": "MIT", 2597 + "optional": true, 2598 + "os": [ 2599 + "linux" 2600 + ], 2601 + "engines": { 2602 + "node": ">=18" 2603 + } 2604 + }, 2605 + "node_modules/astro/node_modules/@esbuild/linux-arm64": { 2606 + "version": "0.25.12", 2607 + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", 2608 + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", 2609 + "cpu": [ 2610 + "arm64" 2611 + ], 2612 + "license": "MIT", 2613 + "optional": true, 2614 + "os": [ 2615 + "linux" 2616 + ], 2617 + "engines": { 2618 + "node": ">=18" 2619 + } 2620 + }, 2621 + "node_modules/astro/node_modules/@esbuild/linux-ia32": { 2622 + "version": "0.25.12", 2623 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", 2624 + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", 2625 + "cpu": [ 2626 + "ia32" 2627 + ], 2628 + "license": "MIT", 2629 + "optional": true, 2630 + "os": [ 2631 + "linux" 2632 + ], 2633 + "engines": { 2634 + "node": ">=18" 2635 + } 2636 + }, 2637 + "node_modules/astro/node_modules/@esbuild/linux-loong64": { 2638 + "version": "0.25.12", 2639 + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", 2640 + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", 2641 + "cpu": [ 2642 + "loong64" 2643 + ], 2644 + "license": "MIT", 2645 + "optional": true, 2646 + "os": [ 2647 + "linux" 2648 + ], 2649 + "engines": { 2650 + "node": ">=18" 2651 + } 2652 + }, 2653 + "node_modules/astro/node_modules/@esbuild/linux-mips64el": { 2654 + "version": "0.25.12", 2655 + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", 2656 + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", 2657 + "cpu": [ 2658 + "mips64el" 2659 + ], 2660 + "license": "MIT", 2661 + "optional": true, 2662 + "os": [ 2663 + "linux" 2664 + ], 2665 + "engines": { 2666 + "node": ">=18" 2667 + } 2668 + }, 2669 + "node_modules/astro/node_modules/@esbuild/linux-ppc64": { 2670 + "version": "0.25.12", 2671 + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", 2672 + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", 2673 + "cpu": [ 2674 + "ppc64" 2675 + ], 2676 + "license": "MIT", 2677 + "optional": true, 2678 + "os": [ 2679 + "linux" 2680 + ], 2681 + "engines": { 2682 + "node": ">=18" 2683 + } 2684 + }, 2685 + "node_modules/astro/node_modules/@esbuild/linux-riscv64": { 2686 + "version": "0.25.12", 2687 + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", 2688 + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", 2689 + "cpu": [ 2690 + "riscv64" 2691 + ], 2692 + "license": "MIT", 2693 + "optional": true, 2694 + "os": [ 2695 + "linux" 2696 + ], 2697 + "engines": { 2698 + "node": ">=18" 2699 + } 2700 + }, 2701 + "node_modules/astro/node_modules/@esbuild/linux-s390x": { 2702 + "version": "0.25.12", 2703 + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", 2704 + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", 2705 + "cpu": [ 2706 + "s390x" 2707 + ], 2708 + "license": "MIT", 2709 + "optional": true, 2710 + "os": [ 2711 + "linux" 2712 + ], 2713 + "engines": { 2714 + "node": ">=18" 2715 + } 2716 + }, 2717 + "node_modules/astro/node_modules/@esbuild/linux-x64": { 2718 + "version": "0.25.12", 2719 + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", 2720 + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", 2721 + "cpu": [ 2722 + "x64" 2723 + ], 2724 + "license": "MIT", 2725 + "optional": true, 2726 + "os": [ 2727 + "linux" 2728 + ], 2729 + "engines": { 2730 + "node": ">=18" 2731 + } 2732 + }, 2733 + "node_modules/astro/node_modules/@esbuild/netbsd-arm64": { 2734 + "version": "0.25.12", 2735 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", 2736 + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", 2737 + "cpu": [ 2738 + "arm64" 2739 + ], 2740 + "license": "MIT", 2741 + "optional": true, 2742 + "os": [ 2743 + "netbsd" 2744 + ], 2745 + "engines": { 2746 + "node": ">=18" 2747 + } 2748 + }, 2749 + "node_modules/astro/node_modules/@esbuild/netbsd-x64": { 2750 + "version": "0.25.12", 2751 + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", 2752 + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", 2753 + "cpu": [ 2754 + "x64" 2755 + ], 2756 + "license": "MIT", 2757 + "optional": true, 2758 + "os": [ 2759 + "netbsd" 2760 + ], 2761 + "engines": { 2762 + "node": ">=18" 2763 + } 2764 + }, 2765 + "node_modules/astro/node_modules/@esbuild/openbsd-arm64": { 2766 + "version": "0.25.12", 2767 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", 2768 + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", 2769 + "cpu": [ 2770 + "arm64" 2771 + ], 2772 + "license": "MIT", 2773 + "optional": true, 2774 + "os": [ 2775 + "openbsd" 2776 + ], 2777 + "engines": { 2778 + "node": ">=18" 2779 + } 2780 + }, 2781 + "node_modules/astro/node_modules/@esbuild/openbsd-x64": { 2782 + "version": "0.25.12", 2783 + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", 2784 + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", 2785 + "cpu": [ 2786 + "x64" 2787 + ], 2788 + "license": "MIT", 2789 + "optional": true, 2790 + "os": [ 2791 + "openbsd" 2792 + ], 2793 + "engines": { 2794 + "node": ">=18" 2795 + } 2796 + }, 2797 + "node_modules/astro/node_modules/@esbuild/openharmony-arm64": { 2798 + "version": "0.25.12", 2799 + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", 2800 + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", 2801 + "cpu": [ 2802 + "arm64" 2803 + ], 2804 + "license": "MIT", 2805 + "optional": true, 2806 + "os": [ 2807 + "openharmony" 2808 + ], 2809 + "engines": { 2810 + "node": ">=18" 2811 + } 2812 + }, 2813 + "node_modules/astro/node_modules/@esbuild/sunos-x64": { 2814 + "version": "0.25.12", 2815 + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", 2816 + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", 2817 + "cpu": [ 2818 + "x64" 2819 + ], 2820 + "license": "MIT", 2821 + "optional": true, 2822 + "os": [ 2823 + "sunos" 2824 + ], 2825 + "engines": { 2826 + "node": ">=18" 2827 + } 2828 + }, 2829 + "node_modules/astro/node_modules/@esbuild/win32-arm64": { 2830 + "version": "0.25.12", 2831 + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", 2832 + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", 2833 + "cpu": [ 2834 + "arm64" 2835 + ], 2836 + "license": "MIT", 2837 + "optional": true, 2838 + "os": [ 2839 + "win32" 2840 + ], 2841 + "engines": { 2842 + "node": ">=18" 2843 + } 2844 + }, 2845 + "node_modules/astro/node_modules/@esbuild/win32-ia32": { 2846 + "version": "0.25.12", 2847 + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", 2848 + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", 2849 + "cpu": [ 2850 + "ia32" 2851 + ], 2852 + "license": "MIT", 2853 + "optional": true, 2854 + "os": [ 2855 + "win32" 2856 + ], 2857 + "engines": { 2858 + "node": ">=18" 2859 + } 2860 + }, 2861 + "node_modules/astro/node_modules/@esbuild/win32-x64": { 2862 + "version": "0.25.12", 2863 + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", 2864 + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", 2865 + "cpu": [ 2866 + "x64" 2867 + ], 2868 + "license": "MIT", 2869 + "optional": true, 2870 + "os": [ 2871 + "win32" 2872 + ], 2873 + "engines": { 2874 + "node": ">=18" 2875 + } 2876 + }, 2877 + "node_modules/astro/node_modules/vite": { 2878 + "version": "6.4.1", 2879 + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", 2880 + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", 2881 + "license": "MIT", 2882 + "dependencies": { 2883 + "esbuild": "^0.25.0", 2884 + "fdir": "^6.4.4", 2885 + "picomatch": "^4.0.2", 2886 + "postcss": "^8.5.3", 2887 + "rollup": "^4.34.9", 2888 + "tinyglobby": "^0.2.13" 2889 + }, 2890 + "bin": { 2891 + "vite": "bin/vite.js" 2892 + }, 2893 + "engines": { 2894 + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 2895 + }, 2896 + "funding": { 2897 + "url": "https://github.com/vitejs/vite?sponsor=1" 2898 + }, 2899 + "optionalDependencies": { 2900 + "fsevents": "~2.3.3" 2901 + }, 2902 + "peerDependencies": { 2903 + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 2904 + "jiti": ">=1.21.0", 2905 + "less": "*", 2906 + "lightningcss": "^1.21.0", 2907 + "sass": "*", 2908 + "sass-embedded": "*", 2909 + "stylus": "*", 2910 + "sugarss": "*", 2911 + "terser": "^5.16.0", 2912 + "tsx": "^4.8.1", 2913 + "yaml": "^2.4.2" 2914 + }, 2915 + "peerDependenciesMeta": { 2916 + "@types/node": { 2917 + "optional": true 2918 + }, 2919 + "jiti": { 2920 + "optional": true 2921 + }, 2922 + "less": { 2923 + "optional": true 2924 + }, 2925 + "lightningcss": { 2926 + "optional": true 2927 + }, 2928 + "sass": { 2929 + "optional": true 2930 + }, 2931 + "sass-embedded": { 2932 + "optional": true 2933 + }, 2934 + "stylus": { 2935 + "optional": true 2936 + }, 2937 + "sugarss": { 2938 + "optional": true 2939 + }, 2940 + "terser": { 2941 + "optional": true 2942 + }, 2943 + "tsx": { 2944 + "optional": true 2945 + }, 2946 + "yaml": { 2947 + "optional": true 2948 + } 2949 + } 2950 + }, 2951 + "node_modules/astro/node_modules/vite/node_modules/esbuild": { 2952 + "version": "0.25.12", 2953 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", 2954 + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", 2955 + "hasInstallScript": true, 2956 + "license": "MIT", 2957 + "bin": { 2958 + "esbuild": "bin/esbuild" 2959 + }, 2960 + "engines": { 2961 + "node": ">=18" 2962 + }, 2963 + "optionalDependencies": { 2964 + "@esbuild/aix-ppc64": "0.25.12", 2965 + "@esbuild/android-arm": "0.25.12", 2966 + "@esbuild/android-arm64": "0.25.12", 2967 + "@esbuild/android-x64": "0.25.12", 2968 + "@esbuild/darwin-arm64": "0.25.12", 2969 + "@esbuild/darwin-x64": "0.25.12", 2970 + "@esbuild/freebsd-arm64": "0.25.12", 2971 + "@esbuild/freebsd-x64": "0.25.12", 2972 + "@esbuild/linux-arm": "0.25.12", 2973 + "@esbuild/linux-arm64": "0.25.12", 2974 + "@esbuild/linux-ia32": "0.25.12", 2975 + "@esbuild/linux-loong64": "0.25.12", 2976 + "@esbuild/linux-mips64el": "0.25.12", 2977 + "@esbuild/linux-ppc64": "0.25.12", 2978 + "@esbuild/linux-riscv64": "0.25.12", 2979 + "@esbuild/linux-s390x": "0.25.12", 2980 + "@esbuild/linux-x64": "0.25.12", 2981 + "@esbuild/netbsd-arm64": "0.25.12", 2982 + "@esbuild/netbsd-x64": "0.25.12", 2983 + "@esbuild/openbsd-arm64": "0.25.12", 2984 + "@esbuild/openbsd-x64": "0.25.12", 2985 + "@esbuild/openharmony-arm64": "0.25.12", 2986 + "@esbuild/sunos-x64": "0.25.12", 2987 + "@esbuild/win32-arm64": "0.25.12", 2988 + "@esbuild/win32-ia32": "0.25.12", 2989 + "@esbuild/win32-x64": "0.25.12" 2990 + } 2991 + }, 2992 + "node_modules/axobject-query": { 2993 + "version": "4.1.0", 2994 + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", 2995 + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", 2996 + "license": "Apache-2.0", 2997 + "engines": { 2998 + "node": ">= 0.4" 2999 + } 3000 + }, 3001 + "node_modules/bail": { 3002 + "version": "2.0.2", 3003 + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", 3004 + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", 3005 + "license": "MIT", 3006 + "funding": { 3007 + "type": "github", 3008 + "url": "https://github.com/sponsors/wooorm" 3009 + } 3010 + }, 3011 + "node_modules/base-64": { 3012 + "version": "1.0.0", 3013 + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", 3014 + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", 3015 + "license": "MIT" 3016 + }, 3017 + "node_modules/bidi-js": { 3018 + "version": "1.0.3", 3019 + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", 3020 + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", 3021 + "license": "MIT", 3022 + "dependencies": { 3023 + "require-from-string": "^2.0.2" 3024 + } 3025 + }, 3026 + "node_modules/boolbase": { 3027 + "version": "1.0.0", 3028 + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 3029 + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", 3030 + "license": "ISC" 3031 + }, 3032 + "node_modules/boxen": { 3033 + "version": "8.0.1", 3034 + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", 3035 + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", 3036 + "license": "MIT", 3037 + "dependencies": { 3038 + "ansi-align": "^3.0.1", 3039 + "camelcase": "^8.0.0", 3040 + "chalk": "^5.3.0", 3041 + "cli-boxes": "^3.0.0", 3042 + "string-width": "^7.2.0", 3043 + "type-fest": "^4.21.0", 3044 + "widest-line": "^5.0.0", 3045 + "wrap-ansi": "^9.0.0" 3046 + }, 3047 + "engines": { 3048 + "node": ">=18" 3049 + }, 3050 + "funding": { 3051 + "url": "https://github.com/sponsors/sindresorhus" 3052 + } 3053 + }, 3054 + "node_modules/camelcase": { 3055 + "version": "8.0.0", 3056 + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", 3057 + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", 3058 + "license": "MIT", 3059 + "engines": { 3060 + "node": ">=16" 3061 + }, 3062 + "funding": { 3063 + "url": "https://github.com/sponsors/sindresorhus" 3064 + } 3065 + }, 3066 + "node_modules/ccount": { 3067 + "version": "2.0.1", 3068 + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", 3069 + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", 3070 + "license": "MIT", 3071 + "funding": { 3072 + "type": "github", 3073 + "url": "https://github.com/sponsors/wooorm" 3074 + } 3075 + }, 3076 + "node_modules/chai": { 3077 + "version": "6.2.2", 3078 + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", 3079 + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", 3080 + "dev": true, 3081 + "license": "MIT", 3082 + "engines": { 3083 + "node": ">=18" 3084 + } 3085 + }, 3086 + "node_modules/chalk": { 3087 + "version": "5.6.2", 3088 + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", 3089 + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", 3090 + "license": "MIT", 3091 + "engines": { 3092 + "node": "^12.17.0 || ^14.13 || >=16.0.0" 3093 + }, 3094 + "funding": { 3095 + "url": "https://github.com/chalk/chalk?sponsor=1" 3096 + } 3097 + }, 3098 + "node_modules/character-entities": { 3099 + "version": "2.0.2", 3100 + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", 3101 + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", 3102 + "license": "MIT", 3103 + "funding": { 3104 + "type": "github", 3105 + "url": "https://github.com/sponsors/wooorm" 3106 + } 3107 + }, 3108 + "node_modules/character-entities-html4": { 3109 + "version": "2.1.0", 3110 + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", 3111 + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", 3112 + "license": "MIT", 3113 + "funding": { 3114 + "type": "github", 3115 + "url": "https://github.com/sponsors/wooorm" 3116 + } 3117 + }, 3118 + "node_modules/character-entities-legacy": { 3119 + "version": "3.0.0", 3120 + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", 3121 + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", 3122 + "license": "MIT", 3123 + "funding": { 3124 + "type": "github", 3125 + "url": "https://github.com/sponsors/wooorm" 3126 + } 3127 + }, 3128 + "node_modules/chokidar": { 3129 + "version": "5.0.0", 3130 + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", 3131 + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", 3132 + "license": "MIT", 3133 + "dependencies": { 3134 + "readdirp": "^5.0.0" 3135 + }, 3136 + "engines": { 3137 + "node": ">= 20.19.0" 3138 + }, 3139 + "funding": { 3140 + "url": "https://paulmillr.com/funding/" 3141 + } 3142 + }, 3143 + "node_modules/ci-info": { 3144 + "version": "4.4.0", 3145 + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", 3146 + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", 3147 + "funding": [ 3148 + { 3149 + "type": "github", 3150 + "url": "https://github.com/sponsors/sibiraj-s" 3151 + } 3152 + ], 3153 + "license": "MIT", 3154 + "engines": { 3155 + "node": ">=8" 3156 + } 3157 + }, 3158 + "node_modules/cli-boxes": { 3159 + "version": "3.0.0", 3160 + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", 3161 + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", 3162 + "license": "MIT", 3163 + "engines": { 3164 + "node": ">=10" 3165 + }, 3166 + "funding": { 3167 + "url": "https://github.com/sponsors/sindresorhus" 3168 + } 3169 + }, 3170 + "node_modules/clsx": { 3171 + "version": "2.1.1", 3172 + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", 3173 + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", 3174 + "license": "MIT", 3175 + "engines": { 3176 + "node": ">=6" 3177 + } 3178 + }, 3179 + "node_modules/comma-separated-tokens": { 3180 + "version": "2.0.3", 3181 + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", 3182 + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", 3183 + "license": "MIT", 3184 + "funding": { 3185 + "type": "github", 3186 + "url": "https://github.com/sponsors/wooorm" 3187 + } 3188 + }, 3189 + "node_modules/commander": { 3190 + "version": "11.1.0", 3191 + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", 3192 + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", 3193 + "license": "MIT", 3194 + "engines": { 3195 + "node": ">=16" 3196 + } 3197 + }, 3198 + "node_modules/common-ancestor-path": { 3199 + "version": "1.0.1", 3200 + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", 3201 + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", 3202 + "license": "ISC" 3203 + }, 3204 + "node_modules/cookie": { 3205 + "version": "1.1.1", 3206 + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", 3207 + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", 3208 + "license": "MIT", 3209 + "engines": { 3210 + "node": ">=18" 3211 + }, 3212 + "funding": { 3213 + "type": "opencollective", 3214 + "url": "https://opencollective.com/express" 3215 + } 3216 + }, 3217 + "node_modules/cookie-es": { 3218 + "version": "1.2.2", 3219 + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", 3220 + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", 3221 + "license": "MIT" 3222 + }, 3223 + "node_modules/crossws": { 3224 + "version": "0.3.5", 3225 + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", 3226 + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", 3227 + "license": "MIT", 3228 + "dependencies": { 3229 + "uncrypto": "^0.1.3" 3230 + } 3231 + }, 3232 + "node_modules/css-select": { 3233 + "version": "5.2.2", 3234 + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", 3235 + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", 3236 + "license": "BSD-2-Clause", 3237 + "dependencies": { 3238 + "boolbase": "^1.0.0", 3239 + "css-what": "^6.1.0", 3240 + "domhandler": "^5.0.2", 3241 + "domutils": "^3.0.1", 3242 + "nth-check": "^2.0.1" 3243 + }, 3244 + "funding": { 3245 + "url": "https://github.com/sponsors/fb55" 3246 + } 3247 + }, 3248 + "node_modules/css-tree": { 3249 + "version": "3.1.0", 3250 + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", 3251 + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", 3252 + "license": "MIT", 3253 + "dependencies": { 3254 + "mdn-data": "2.12.2", 3255 + "source-map-js": "^1.0.1" 3256 + }, 3257 + "engines": { 3258 + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" 3259 + } 3260 + }, 3261 + "node_modules/css-what": { 3262 + "version": "6.2.2", 3263 + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", 3264 + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", 3265 + "license": "BSD-2-Clause", 3266 + "engines": { 3267 + "node": ">= 6" 3268 + }, 3269 + "funding": { 3270 + "url": "https://github.com/sponsors/fb55" 3271 + } 3272 + }, 3273 + "node_modules/cssesc": { 3274 + "version": "3.0.0", 3275 + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 3276 + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", 3277 + "license": "MIT", 3278 + "bin": { 3279 + "cssesc": "bin/cssesc" 3280 + }, 3281 + "engines": { 3282 + "node": ">=4" 3283 + } 3284 + }, 3285 + "node_modules/csso": { 3286 + "version": "5.0.5", 3287 + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", 3288 + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", 3289 + "license": "MIT", 3290 + "dependencies": { 3291 + "css-tree": "~2.2.0" 3292 + }, 3293 + "engines": { 3294 + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", 3295 + "npm": ">=7.0.0" 3296 + } 3297 + }, 3298 + "node_modules/csso/node_modules/css-tree": { 3299 + "version": "2.2.1", 3300 + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", 3301 + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", 3302 + "license": "MIT", 3303 + "dependencies": { 3304 + "mdn-data": "2.0.28", 3305 + "source-map-js": "^1.0.1" 3306 + }, 3307 + "engines": { 3308 + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", 3309 + "npm": ">=7.0.0" 3310 + } 3311 + }, 3312 + "node_modules/csso/node_modules/mdn-data": { 3313 + "version": "2.0.28", 3314 + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", 3315 + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", 3316 + "license": "CC0-1.0" 3317 + }, 3318 + "node_modules/cssstyle": { 3319 + "version": "6.1.0", 3320 + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.1.0.tgz", 3321 + "integrity": "sha512-Ml4fP2UT2K3CUBQnVlbdV/8aFDdlY69E+YnwJM+3VUWl08S3J8c8aRuJqCkD9Py8DHZ7zNNvsfKl8psocHZEFg==", 3322 + "license": "MIT", 3323 + "dependencies": { 3324 + "@asamuzakjp/css-color": "^5.0.0", 3325 + "@csstools/css-syntax-patches-for-csstree": "^1.0.28", 3326 + "css-tree": "^3.1.0", 3327 + "lru-cache": "^11.2.6" 3328 + }, 3329 + "engines": { 3330 + "node": ">=20" 3331 + } 3332 + }, 3333 + "node_modules/data-urls": { 3334 + "version": "7.0.0", 3335 + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", 3336 + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", 3337 + "license": "MIT", 3338 + "dependencies": { 3339 + "whatwg-mimetype": "^5.0.0", 3340 + "whatwg-url": "^16.0.0" 3341 + }, 3342 + "engines": { 3343 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 3344 + } 3345 + }, 3346 + "node_modules/debug": { 3347 + "version": "4.4.3", 3348 + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", 3349 + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", 3350 + "license": "MIT", 3351 + "dependencies": { 3352 + "ms": "^2.1.3" 3353 + }, 3354 + "engines": { 3355 + "node": ">=6.0" 3356 + }, 3357 + "peerDependenciesMeta": { 3358 + "supports-color": { 3359 + "optional": true 3360 + } 3361 + } 3362 + }, 3363 + "node_modules/decimal.js": { 3364 + "version": "10.6.0", 3365 + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", 3366 + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", 3367 + "license": "MIT" 3368 + }, 3369 + "node_modules/decode-named-character-reference": { 3370 + "version": "1.3.0", 3371 + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", 3372 + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", 3373 + "license": "MIT", 3374 + "dependencies": { 3375 + "character-entities": "^2.0.0" 3376 + }, 3377 + "funding": { 3378 + "type": "github", 3379 + "url": "https://github.com/sponsors/wooorm" 3380 + } 3381 + }, 3382 + "node_modules/defu": { 3383 + "version": "6.1.4", 3384 + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", 3385 + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", 3386 + "license": "MIT" 3387 + }, 3388 + "node_modules/depd": { 3389 + "version": "2.0.0", 3390 + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 3391 + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 3392 + "license": "MIT", 3393 + "engines": { 3394 + "node": ">= 0.8" 3395 + } 3396 + }, 3397 + "node_modules/dequal": { 3398 + "version": "2.0.3", 3399 + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", 3400 + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", 3401 + "license": "MIT", 3402 + "engines": { 3403 + "node": ">=6" 3404 + } 3405 + }, 3406 + "node_modules/destr": { 3407 + "version": "2.0.5", 3408 + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", 3409 + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", 3410 + "license": "MIT" 3411 + }, 3412 + "node_modules/detect-libc": { 3413 + "version": "2.1.2", 3414 + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", 3415 + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", 3416 + "devOptional": true, 3417 + "license": "Apache-2.0", 3418 + "engines": { 3419 + "node": ">=8" 3420 + } 3421 + }, 3422 + "node_modules/deterministic-object-hash": { 3423 + "version": "2.0.2", 3424 + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", 3425 + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", 3426 + "license": "MIT", 3427 + "dependencies": { 3428 + "base-64": "^1.0.0" 3429 + }, 3430 + "engines": { 3431 + "node": ">=18" 3432 + } 3433 + }, 3434 + "node_modules/devalue": { 3435 + "version": "5.6.3", 3436 + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz", 3437 + "integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==", 3438 + "license": "MIT" 3439 + }, 3440 + "node_modules/devlop": { 3441 + "version": "1.1.0", 3442 + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", 3443 + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", 3444 + "license": "MIT", 3445 + "dependencies": { 3446 + "dequal": "^2.0.0" 3447 + }, 3448 + "funding": { 3449 + "type": "github", 3450 + "url": "https://github.com/sponsors/wooorm" 3451 + } 3452 + }, 3453 + "node_modules/diff": { 3454 + "version": "8.0.3", 3455 + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", 3456 + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", 3457 + "license": "BSD-3-Clause", 3458 + "engines": { 3459 + "node": ">=0.3.1" 3460 + } 3461 + }, 3462 + "node_modules/dlv": { 3463 + "version": "1.1.3", 3464 + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 3465 + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", 3466 + "license": "MIT" 3467 + }, 3468 + "node_modules/dom-serializer": { 3469 + "version": "2.0.0", 3470 + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 3471 + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 3472 + "license": "MIT", 3473 + "dependencies": { 3474 + "domelementtype": "^2.3.0", 3475 + "domhandler": "^5.0.2", 3476 + "entities": "^4.2.0" 3477 + }, 3478 + "funding": { 3479 + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" 3480 + } 3481 + }, 3482 + "node_modules/dom-serializer/node_modules/entities": { 3483 + "version": "4.5.0", 3484 + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 3485 + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 3486 + "license": "BSD-2-Clause", 3487 + "engines": { 3488 + "node": ">=0.12" 3489 + }, 3490 + "funding": { 3491 + "url": "https://github.com/fb55/entities?sponsor=1" 3492 + } 3493 + }, 3494 + "node_modules/domelementtype": { 3495 + "version": "2.3.0", 3496 + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 3497 + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", 3498 + "funding": [ 3499 + { 3500 + "type": "github", 3501 + "url": "https://github.com/sponsors/fb55" 3502 + } 3503 + ], 3504 + "license": "BSD-2-Clause" 3505 + }, 3506 + "node_modules/domhandler": { 3507 + "version": "5.0.3", 3508 + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 3509 + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 3510 + "license": "BSD-2-Clause", 3511 + "dependencies": { 3512 + "domelementtype": "^2.3.0" 3513 + }, 3514 + "engines": { 3515 + "node": ">= 4" 3516 + }, 3517 + "funding": { 3518 + "url": "https://github.com/fb55/domhandler?sponsor=1" 3519 + } 3520 + }, 3521 + "node_modules/dompurify": { 3522 + "version": "3.3.1", 3523 + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", 3524 + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", 3525 + "license": "(MPL-2.0 OR Apache-2.0)", 3526 + "optionalDependencies": { 3527 + "@types/trusted-types": "^2.0.7" 3528 + } 3529 + }, 3530 + "node_modules/domutils": { 3531 + "version": "3.2.2", 3532 + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", 3533 + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", 3534 + "license": "BSD-2-Clause", 3535 + "dependencies": { 3536 + "dom-serializer": "^2.0.0", 3537 + "domelementtype": "^2.3.0", 3538 + "domhandler": "^5.0.3" 3539 + }, 3540 + "funding": { 3541 + "url": "https://github.com/fb55/domutils?sponsor=1" 3542 + } 3543 + }, 3544 + "node_modules/dset": { 3545 + "version": "3.1.4", 3546 + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", 3547 + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", 3548 + "license": "MIT", 3549 + "engines": { 3550 + "node": ">=4" 3551 + } 3552 + }, 3553 + "node_modules/ee-first": { 3554 + "version": "1.1.1", 3555 + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 3556 + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 3557 + "license": "MIT" 3558 + }, 3559 + "node_modules/emoji-regex": { 3560 + "version": "10.6.0", 3561 + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", 3562 + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", 3563 + "license": "MIT" 3564 + }, 3565 + "node_modules/encodeurl": { 3566 + "version": "2.0.0", 3567 + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 3568 + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 3569 + "license": "MIT", 3570 + "engines": { 3571 + "node": ">= 0.8" 3572 + } 3573 + }, 3574 + "node_modules/enhanced-resolve": { 3575 + "version": "5.20.0", 3576 + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", 3577 + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", 3578 + "dev": true, 3579 + "license": "MIT", 3580 + "dependencies": { 3581 + "graceful-fs": "^4.2.4", 3582 + "tapable": "^2.3.0" 3583 + }, 3584 + "engines": { 3585 + "node": ">=10.13.0" 3586 + } 3587 + }, 3588 + "node_modules/entities": { 3589 + "version": "6.0.1", 3590 + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", 3591 + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", 3592 + "license": "BSD-2-Clause", 3593 + "engines": { 3594 + "node": ">=0.12" 3595 + }, 3596 + "funding": { 3597 + "url": "https://github.com/fb55/entities?sponsor=1" 3598 + } 3599 + }, 3600 + "node_modules/es-module-lexer": { 3601 + "version": "1.7.0", 3602 + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", 3603 + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", 3604 + "license": "MIT" 3605 + }, 3606 + "node_modules/esbuild": { 3607 + "version": "0.27.3", 3608 + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", 3609 + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", 3610 + "hasInstallScript": true, 3611 + "license": "MIT", 3612 + "bin": { 3613 + "esbuild": "bin/esbuild" 3614 + }, 3615 + "engines": { 3616 + "node": ">=18" 3617 + }, 3618 + "optionalDependencies": { 3619 + "@esbuild/aix-ppc64": "0.27.3", 3620 + "@esbuild/android-arm": "0.27.3", 3621 + "@esbuild/android-arm64": "0.27.3", 3622 + "@esbuild/android-x64": "0.27.3", 3623 + "@esbuild/darwin-arm64": "0.27.3", 3624 + "@esbuild/darwin-x64": "0.27.3", 3625 + "@esbuild/freebsd-arm64": "0.27.3", 3626 + "@esbuild/freebsd-x64": "0.27.3", 3627 + "@esbuild/linux-arm": "0.27.3", 3628 + "@esbuild/linux-arm64": "0.27.3", 3629 + "@esbuild/linux-ia32": "0.27.3", 3630 + "@esbuild/linux-loong64": "0.27.3", 3631 + "@esbuild/linux-mips64el": "0.27.3", 3632 + "@esbuild/linux-ppc64": "0.27.3", 3633 + "@esbuild/linux-riscv64": "0.27.3", 3634 + "@esbuild/linux-s390x": "0.27.3", 3635 + "@esbuild/linux-x64": "0.27.3", 3636 + "@esbuild/netbsd-arm64": "0.27.3", 3637 + "@esbuild/netbsd-x64": "0.27.3", 3638 + "@esbuild/openbsd-arm64": "0.27.3", 3639 + "@esbuild/openbsd-x64": "0.27.3", 3640 + "@esbuild/openharmony-arm64": "0.27.3", 3641 + "@esbuild/sunos-x64": "0.27.3", 3642 + "@esbuild/win32-arm64": "0.27.3", 3643 + "@esbuild/win32-ia32": "0.27.3", 3644 + "@esbuild/win32-x64": "0.27.3" 3645 + } 3646 + }, 3647 + "node_modules/escape-html": { 3648 + "version": "1.0.3", 3649 + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 3650 + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 3651 + "license": "MIT" 3652 + }, 3653 + "node_modules/escape-string-regexp": { 3654 + "version": "5.0.0", 3655 + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", 3656 + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", 3657 + "license": "MIT", 3658 + "engines": { 3659 + "node": ">=12" 3660 + }, 3661 + "funding": { 3662 + "url": "https://github.com/sponsors/sindresorhus" 3663 + } 3664 + }, 3665 + "node_modules/estree-walker": { 3666 + "version": "3.0.3", 3667 + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 3668 + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 3669 + "license": "MIT", 3670 + "dependencies": { 3671 + "@types/estree": "^1.0.0" 3672 + } 3673 + }, 3674 + "node_modules/etag": { 3675 + "version": "1.8.1", 3676 + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 3677 + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 3678 + "license": "MIT", 3679 + "engines": { 3680 + "node": ">= 0.6" 3681 + } 3682 + }, 3683 + "node_modules/eventemitter3": { 3684 + "version": "5.0.4", 3685 + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", 3686 + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", 3687 + "license": "MIT" 3688 + }, 3689 + "node_modules/expect-type": { 3690 + "version": "1.3.0", 3691 + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", 3692 + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", 3693 + "dev": true, 3694 + "license": "Apache-2.0", 3695 + "engines": { 3696 + "node": ">=12.0.0" 3697 + } 3698 + }, 3699 + "node_modules/extend": { 3700 + "version": "3.0.2", 3701 + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 3702 + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 3703 + "license": "MIT" 3704 + }, 3705 + "node_modules/fdir": { 3706 + "version": "6.5.0", 3707 + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", 3708 + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", 3709 + "license": "MIT", 3710 + "engines": { 3711 + "node": ">=12.0.0" 3712 + }, 3713 + "peerDependencies": { 3714 + "picomatch": "^3 || ^4" 3715 + }, 3716 + "peerDependenciesMeta": { 3717 + "picomatch": { 3718 + "optional": true 3719 + } 3720 + } 3721 + }, 3722 + "node_modules/flattie": { 3723 + "version": "1.1.1", 3724 + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", 3725 + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", 3726 + "license": "MIT", 3727 + "engines": { 3728 + "node": ">=8" 3729 + } 3730 + }, 3731 + "node_modules/fontace": { 3732 + "version": "0.4.1", 3733 + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", 3734 + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", 3735 + "license": "MIT", 3736 + "dependencies": { 3737 + "fontkitten": "^1.0.2" 3738 + } 3739 + }, 3740 + "node_modules/fontkitten": { 3741 + "version": "1.0.2", 3742 + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.2.tgz", 3743 + "integrity": "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q==", 3744 + "license": "MIT", 3745 + "dependencies": { 3746 + "tiny-inflate": "^1.0.3" 3747 + }, 3748 + "engines": { 3749 + "node": ">=20" 3750 + } 3751 + }, 3752 + "node_modules/fresh": { 3753 + "version": "2.0.0", 3754 + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 3755 + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 3756 + "license": "MIT", 3757 + "engines": { 3758 + "node": ">= 0.8" 3759 + } 3760 + }, 3761 + "node_modules/fsevents": { 3762 + "version": "2.3.3", 3763 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 3764 + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 3765 + "hasInstallScript": true, 3766 + "license": "MIT", 3767 + "optional": true, 3768 + "os": [ 3769 + "darwin" 3770 + ], 3771 + "engines": { 3772 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 3773 + } 3774 + }, 3775 + "node_modules/get-east-asian-width": { 3776 + "version": "1.5.0", 3777 + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", 3778 + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", 3779 + "license": "MIT", 3780 + "engines": { 3781 + "node": ">=18" 3782 + }, 3783 + "funding": { 3784 + "url": "https://github.com/sponsors/sindresorhus" 3785 + } 3786 + }, 3787 + "node_modules/github-slugger": { 3788 + "version": "2.0.0", 3789 + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", 3790 + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", 3791 + "license": "ISC" 3792 + }, 3793 + "node_modules/graceful-fs": { 3794 + "version": "4.2.11", 3795 + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 3796 + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 3797 + "dev": true, 3798 + "license": "ISC" 3799 + }, 3800 + "node_modules/h3": { 3801 + "version": "1.15.5", 3802 + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", 3803 + "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", 3804 + "license": "MIT", 3805 + "dependencies": { 3806 + "cookie-es": "^1.2.2", 3807 + "crossws": "^0.3.5", 3808 + "defu": "^6.1.4", 3809 + "destr": "^2.0.5", 3810 + "iron-webcrypto": "^1.2.1", 3811 + "node-mock-http": "^1.0.4", 3812 + "radix3": "^1.1.2", 3813 + "ufo": "^1.6.3", 3814 + "uncrypto": "^0.1.3" 3815 + } 3816 + }, 3817 + "node_modules/hast-util-from-html": { 3818 + "version": "2.0.3", 3819 + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", 3820 + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", 3821 + "license": "MIT", 3822 + "dependencies": { 3823 + "@types/hast": "^3.0.0", 3824 + "devlop": "^1.1.0", 3825 + "hast-util-from-parse5": "^8.0.0", 3826 + "parse5": "^7.0.0", 3827 + "vfile": "^6.0.0", 3828 + "vfile-message": "^4.0.0" 3829 + }, 3830 + "funding": { 3831 + "type": "opencollective", 3832 + "url": "https://opencollective.com/unified" 3833 + } 3834 + }, 3835 + "node_modules/hast-util-from-parse5": { 3836 + "version": "8.0.3", 3837 + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", 3838 + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", 3839 + "license": "MIT", 3840 + "dependencies": { 3841 + "@types/hast": "^3.0.0", 3842 + "@types/unist": "^3.0.0", 3843 + "devlop": "^1.0.0", 3844 + "hastscript": "^9.0.0", 3845 + "property-information": "^7.0.0", 3846 + "vfile": "^6.0.0", 3847 + "vfile-location": "^5.0.0", 3848 + "web-namespaces": "^2.0.0" 3849 + }, 3850 + "funding": { 3851 + "type": "opencollective", 3852 + "url": "https://opencollective.com/unified" 3853 + } 3854 + }, 3855 + "node_modules/hast-util-is-element": { 3856 + "version": "3.0.0", 3857 + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", 3858 + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", 3859 + "license": "MIT", 3860 + "dependencies": { 3861 + "@types/hast": "^3.0.0" 3862 + }, 3863 + "funding": { 3864 + "type": "opencollective", 3865 + "url": "https://opencollective.com/unified" 3866 + } 3867 + }, 3868 + "node_modules/hast-util-parse-selector": { 3869 + "version": "4.0.0", 3870 + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", 3871 + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", 3872 + "license": "MIT", 3873 + "dependencies": { 3874 + "@types/hast": "^3.0.0" 3875 + }, 3876 + "funding": { 3877 + "type": "opencollective", 3878 + "url": "https://opencollective.com/unified" 3879 + } 3880 + }, 3881 + "node_modules/hast-util-raw": { 3882 + "version": "9.1.0", 3883 + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", 3884 + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", 3885 + "license": "MIT", 3886 + "dependencies": { 3887 + "@types/hast": "^3.0.0", 3888 + "@types/unist": "^3.0.0", 3889 + "@ungap/structured-clone": "^1.0.0", 3890 + "hast-util-from-parse5": "^8.0.0", 3891 + "hast-util-to-parse5": "^8.0.0", 3892 + "html-void-elements": "^3.0.0", 3893 + "mdast-util-to-hast": "^13.0.0", 3894 + "parse5": "^7.0.0", 3895 + "unist-util-position": "^5.0.0", 3896 + "unist-util-visit": "^5.0.0", 3897 + "vfile": "^6.0.0", 3898 + "web-namespaces": "^2.0.0", 3899 + "zwitch": "^2.0.0" 3900 + }, 3901 + "funding": { 3902 + "type": "opencollective", 3903 + "url": "https://opencollective.com/unified" 3904 + } 3905 + }, 3906 + "node_modules/hast-util-to-html": { 3907 + "version": "9.0.5", 3908 + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", 3909 + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", 3910 + "license": "MIT", 3911 + "dependencies": { 3912 + "@types/hast": "^3.0.0", 3913 + "@types/unist": "^3.0.0", 3914 + "ccount": "^2.0.0", 3915 + "comma-separated-tokens": "^2.0.0", 3916 + "hast-util-whitespace": "^3.0.0", 3917 + "html-void-elements": "^3.0.0", 3918 + "mdast-util-to-hast": "^13.0.0", 3919 + "property-information": "^7.0.0", 3920 + "space-separated-tokens": "^2.0.0", 3921 + "stringify-entities": "^4.0.0", 3922 + "zwitch": "^2.0.4" 3923 + }, 3924 + "funding": { 3925 + "type": "opencollective", 3926 + "url": "https://opencollective.com/unified" 3927 + } 3928 + }, 3929 + "node_modules/hast-util-to-parse5": { 3930 + "version": "8.0.1", 3931 + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", 3932 + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", 3933 + "license": "MIT", 3934 + "dependencies": { 3935 + "@types/hast": "^3.0.0", 3936 + "comma-separated-tokens": "^2.0.0", 3937 + "devlop": "^1.0.0", 3938 + "property-information": "^7.0.0", 3939 + "space-separated-tokens": "^2.0.0", 3940 + "web-namespaces": "^2.0.0", 3941 + "zwitch": "^2.0.0" 3942 + }, 3943 + "funding": { 3944 + "type": "opencollective", 3945 + "url": "https://opencollective.com/unified" 3946 + } 3947 + }, 3948 + "node_modules/hast-util-to-text": { 3949 + "version": "4.0.2", 3950 + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", 3951 + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", 3952 + "license": "MIT", 3953 + "dependencies": { 3954 + "@types/hast": "^3.0.0", 3955 + "@types/unist": "^3.0.0", 3956 + "hast-util-is-element": "^3.0.0", 3957 + "unist-util-find-after": "^5.0.0" 3958 + }, 3959 + "funding": { 3960 + "type": "opencollective", 3961 + "url": "https://opencollective.com/unified" 3962 + } 3963 + }, 3964 + "node_modules/hast-util-whitespace": { 3965 + "version": "3.0.0", 3966 + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", 3967 + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", 3968 + "license": "MIT", 3969 + "dependencies": { 3970 + "@types/hast": "^3.0.0" 3971 + }, 3972 + "funding": { 3973 + "type": "opencollective", 3974 + "url": "https://opencollective.com/unified" 3975 + } 3976 + }, 3977 + "node_modules/hastscript": { 3978 + "version": "9.0.1", 3979 + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", 3980 + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", 3981 + "license": "MIT", 3982 + "dependencies": { 3983 + "@types/hast": "^3.0.0", 3984 + "comma-separated-tokens": "^2.0.0", 3985 + "hast-util-parse-selector": "^4.0.0", 3986 + "property-information": "^7.0.0", 3987 + "space-separated-tokens": "^2.0.0" 3988 + }, 3989 + "funding": { 3990 + "type": "opencollective", 3991 + "url": "https://opencollective.com/unified" 3992 + } 3993 + }, 3994 + "node_modules/html-encoding-sniffer": { 3995 + "version": "6.0.0", 3996 + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", 3997 + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", 3998 + "license": "MIT", 3999 + "dependencies": { 4000 + "@exodus/bytes": "^1.6.0" 4001 + }, 4002 + "engines": { 4003 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 4004 + } 4005 + }, 4006 + "node_modules/html-escaper": { 4007 + "version": "3.0.3", 4008 + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", 4009 + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", 4010 + "license": "MIT" 4011 + }, 4012 + "node_modules/html-void-elements": { 4013 + "version": "3.0.0", 4014 + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", 4015 + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", 4016 + "license": "MIT", 4017 + "funding": { 4018 + "type": "github", 4019 + "url": "https://github.com/sponsors/wooorm" 4020 + } 4021 + }, 4022 + "node_modules/http-cache-semantics": { 4023 + "version": "4.2.0", 4024 + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", 4025 + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", 4026 + "license": "BSD-2-Clause" 4027 + }, 4028 + "node_modules/http-errors": { 4029 + "version": "2.0.1", 4030 + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", 4031 + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", 4032 + "license": "MIT", 4033 + "dependencies": { 4034 + "depd": "~2.0.0", 4035 + "inherits": "~2.0.4", 4036 + "setprototypeof": "~1.2.0", 4037 + "statuses": "~2.0.2", 4038 + "toidentifier": "~1.0.1" 4039 + }, 4040 + "engines": { 4041 + "node": ">= 0.8" 4042 + }, 4043 + "funding": { 4044 + "type": "opencollective", 4045 + "url": "https://opencollective.com/express" 4046 + } 4047 + }, 4048 + "node_modules/http-proxy-agent": { 4049 + "version": "7.0.2", 4050 + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", 4051 + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", 4052 + "license": "MIT", 4053 + "dependencies": { 4054 + "agent-base": "^7.1.0", 4055 + "debug": "^4.3.4" 4056 + }, 4057 + "engines": { 4058 + "node": ">= 14" 4059 + } 4060 + }, 4061 + "node_modules/https-proxy-agent": { 4062 + "version": "7.0.6", 4063 + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", 4064 + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", 4065 + "license": "MIT", 4066 + "dependencies": { 4067 + "agent-base": "^7.1.2", 4068 + "debug": "4" 4069 + }, 4070 + "engines": { 4071 + "node": ">= 14" 4072 + } 4073 + }, 4074 + "node_modules/import-meta-resolve": { 4075 + "version": "4.2.0", 4076 + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", 4077 + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", 4078 + "license": "MIT", 4079 + "funding": { 4080 + "type": "github", 4081 + "url": "https://github.com/sponsors/wooorm" 4082 + } 4083 + }, 4084 + "node_modules/inherits": { 4085 + "version": "2.0.4", 4086 + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 4087 + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 4088 + "license": "ISC" 4089 + }, 4090 + "node_modules/iron-webcrypto": { 4091 + "version": "1.2.1", 4092 + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", 4093 + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", 4094 + "license": "MIT", 4095 + "funding": { 4096 + "url": "https://github.com/sponsors/brc-dd" 4097 + } 4098 + }, 4099 + "node_modules/is-docker": { 4100 + "version": "3.0.0", 4101 + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", 4102 + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", 4103 + "license": "MIT", 4104 + "bin": { 4105 + "is-docker": "cli.js" 4106 + }, 4107 + "engines": { 4108 + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 4109 + }, 4110 + "funding": { 4111 + "url": "https://github.com/sponsors/sindresorhus" 4112 + } 4113 + }, 4114 + "node_modules/is-fullwidth-code-point": { 4115 + "version": "3.0.0", 4116 + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 4117 + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 4118 + "license": "MIT", 4119 + "engines": { 4120 + "node": ">=8" 4121 + } 4122 + }, 4123 + "node_modules/is-inside-container": { 4124 + "version": "1.0.0", 4125 + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", 4126 + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", 4127 + "license": "MIT", 4128 + "dependencies": { 4129 + "is-docker": "^3.0.0" 4130 + }, 4131 + "bin": { 4132 + "is-inside-container": "cli.js" 4133 + }, 4134 + "engines": { 4135 + "node": ">=14.16" 4136 + }, 4137 + "funding": { 4138 + "url": "https://github.com/sponsors/sindresorhus" 4139 + } 4140 + }, 4141 + "node_modules/is-plain-obj": { 4142 + "version": "4.1.0", 4143 + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", 4144 + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", 4145 + "license": "MIT", 4146 + "engines": { 4147 + "node": ">=12" 4148 + }, 4149 + "funding": { 4150 + "url": "https://github.com/sponsors/sindresorhus" 4151 + } 4152 + }, 4153 + "node_modules/is-potential-custom-element-name": { 4154 + "version": "1.0.1", 4155 + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", 4156 + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", 4157 + "license": "MIT" 4158 + }, 4159 + "node_modules/is-wsl": { 4160 + "version": "3.1.1", 4161 + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", 4162 + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", 4163 + "license": "MIT", 4164 + "dependencies": { 4165 + "is-inside-container": "^1.0.0" 4166 + }, 4167 + "engines": { 4168 + "node": ">=16" 4169 + }, 4170 + "funding": { 4171 + "url": "https://github.com/sponsors/sindresorhus" 4172 + } 4173 + }, 4174 + "node_modules/isomorphic-dompurify": { 4175 + "version": "3.0.0", 4176 + "resolved": "https://registry.npmjs.org/isomorphic-dompurify/-/isomorphic-dompurify-3.0.0.tgz", 4177 + "integrity": "sha512-5K+MYP7Nrg74+Bi+QmQGzQ/FgEOyVHWsN8MuJy5wYQxxBRxPnWsD25Tjjt5FWYhan3OQ+vNLubyNJH9dfG03lQ==", 4178 + "license": "MIT", 4179 + "dependencies": { 4180 + "dompurify": "^3.3.1", 4181 + "jsdom": "^28.0.0" 4182 + }, 4183 + "engines": { 4184 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 4185 + } 4186 + }, 4187 + "node_modules/jiti": { 4188 + "version": "2.6.1", 4189 + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", 4190 + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", 4191 + "devOptional": true, 4192 + "license": "MIT", 4193 + "bin": { 4194 + "jiti": "lib/jiti-cli.mjs" 4195 + } 4196 + }, 4197 + "node_modules/js-yaml": { 4198 + "version": "4.1.1", 4199 + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", 4200 + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", 4201 + "license": "MIT", 4202 + "dependencies": { 4203 + "argparse": "^2.0.1" 4204 + }, 4205 + "bin": { 4206 + "js-yaml": "bin/js-yaml.js" 4207 + } 4208 + }, 4209 + "node_modules/jsdom": { 4210 + "version": "28.1.0", 4211 + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", 4212 + "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", 4213 + "license": "MIT", 4214 + "dependencies": { 4215 + "@acemir/cssom": "^0.9.31", 4216 + "@asamuzakjp/dom-selector": "^6.8.1", 4217 + "@bramus/specificity": "^2.4.2", 4218 + "@exodus/bytes": "^1.11.0", 4219 + "cssstyle": "^6.0.1", 4220 + "data-urls": "^7.0.0", 4221 + "decimal.js": "^10.6.0", 4222 + "html-encoding-sniffer": "^6.0.0", 4223 + "http-proxy-agent": "^7.0.2", 4224 + "https-proxy-agent": "^7.0.6", 4225 + "is-potential-custom-element-name": "^1.0.1", 4226 + "parse5": "^8.0.0", 4227 + "saxes": "^6.0.0", 4228 + "symbol-tree": "^3.2.4", 4229 + "tough-cookie": "^6.0.0", 4230 + "undici": "^7.21.0", 4231 + "w3c-xmlserializer": "^5.0.0", 4232 + "webidl-conversions": "^8.0.1", 4233 + "whatwg-mimetype": "^5.0.0", 4234 + "whatwg-url": "^16.0.0", 4235 + "xml-name-validator": "^5.0.0" 4236 + }, 4237 + "engines": { 4238 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 4239 + }, 4240 + "peerDependencies": { 4241 + "canvas": "^3.0.0" 4242 + }, 4243 + "peerDependenciesMeta": { 4244 + "canvas": { 4245 + "optional": true 4246 + } 4247 + } 4248 + }, 4249 + "node_modules/jsdom/node_modules/parse5": { 4250 + "version": "8.0.0", 4251 + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", 4252 + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", 4253 + "license": "MIT", 4254 + "dependencies": { 4255 + "entities": "^6.0.0" 4256 + }, 4257 + "funding": { 4258 + "url": "https://github.com/inikulin/parse5?sponsor=1" 4259 + } 4260 + }, 4261 + "node_modules/kleur": { 4262 + "version": "3.0.3", 4263 + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 4264 + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", 4265 + "license": "MIT", 4266 + "engines": { 4267 + "node": ">=6" 4268 + } 4269 + }, 4270 + "node_modules/lightningcss": { 4271 + "version": "1.31.1", 4272 + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", 4273 + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", 4274 + "devOptional": true, 4275 + "license": "MPL-2.0", 4276 + "dependencies": { 4277 + "detect-libc": "^2.0.3" 4278 + }, 4279 + "engines": { 4280 + "node": ">= 12.0.0" 4281 + }, 4282 + "funding": { 4283 + "type": "opencollective", 4284 + "url": "https://opencollective.com/parcel" 4285 + }, 4286 + "optionalDependencies": { 4287 + "lightningcss-android-arm64": "1.31.1", 4288 + "lightningcss-darwin-arm64": "1.31.1", 4289 + "lightningcss-darwin-x64": "1.31.1", 4290 + "lightningcss-freebsd-x64": "1.31.1", 4291 + "lightningcss-linux-arm-gnueabihf": "1.31.1", 4292 + "lightningcss-linux-arm64-gnu": "1.31.1", 4293 + "lightningcss-linux-arm64-musl": "1.31.1", 4294 + "lightningcss-linux-x64-gnu": "1.31.1", 4295 + "lightningcss-linux-x64-musl": "1.31.1", 4296 + "lightningcss-win32-arm64-msvc": "1.31.1", 4297 + "lightningcss-win32-x64-msvc": "1.31.1" 4298 + } 4299 + }, 4300 + "node_modules/lightningcss-android-arm64": { 4301 + "version": "1.31.1", 4302 + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", 4303 + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", 4304 + "cpu": [ 4305 + "arm64" 4306 + ], 4307 + "dev": true, 4308 + "license": "MPL-2.0", 4309 + "optional": true, 4310 + "os": [ 4311 + "android" 4312 + ], 4313 + "engines": { 4314 + "node": ">= 12.0.0" 4315 + }, 4316 + "funding": { 4317 + "type": "opencollective", 4318 + "url": "https://opencollective.com/parcel" 4319 + } 4320 + }, 4321 + "node_modules/lightningcss-darwin-arm64": { 4322 + "version": "1.31.1", 4323 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", 4324 + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", 4325 + "cpu": [ 4326 + "arm64" 4327 + ], 4328 + "dev": true, 4329 + "license": "MPL-2.0", 4330 + "optional": true, 4331 + "os": [ 4332 + "darwin" 4333 + ], 4334 + "engines": { 4335 + "node": ">= 12.0.0" 4336 + }, 4337 + "funding": { 4338 + "type": "opencollective", 4339 + "url": "https://opencollective.com/parcel" 4340 + } 4341 + }, 4342 + "node_modules/lightningcss-darwin-x64": { 4343 + "version": "1.31.1", 4344 + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", 4345 + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", 4346 + "cpu": [ 4347 + "x64" 4348 + ], 4349 + "dev": true, 4350 + "license": "MPL-2.0", 4351 + "optional": true, 4352 + "os": [ 4353 + "darwin" 4354 + ], 4355 + "engines": { 4356 + "node": ">= 12.0.0" 4357 + }, 4358 + "funding": { 4359 + "type": "opencollective", 4360 + "url": "https://opencollective.com/parcel" 4361 + } 4362 + }, 4363 + "node_modules/lightningcss-freebsd-x64": { 4364 + "version": "1.31.1", 4365 + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", 4366 + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", 4367 + "cpu": [ 4368 + "x64" 4369 + ], 4370 + "dev": true, 4371 + "license": "MPL-2.0", 4372 + "optional": true, 4373 + "os": [ 4374 + "freebsd" 4375 + ], 4376 + "engines": { 4377 + "node": ">= 12.0.0" 4378 + }, 4379 + "funding": { 4380 + "type": "opencollective", 4381 + "url": "https://opencollective.com/parcel" 4382 + } 4383 + }, 4384 + "node_modules/lightningcss-linux-arm-gnueabihf": { 4385 + "version": "1.31.1", 4386 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", 4387 + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", 4388 + "cpu": [ 4389 + "arm" 4390 + ], 4391 + "dev": true, 4392 + "license": "MPL-2.0", 4393 + "optional": true, 4394 + "os": [ 4395 + "linux" 4396 + ], 4397 + "engines": { 4398 + "node": ">= 12.0.0" 4399 + }, 4400 + "funding": { 4401 + "type": "opencollective", 4402 + "url": "https://opencollective.com/parcel" 4403 + } 4404 + }, 4405 + "node_modules/lightningcss-linux-arm64-gnu": { 4406 + "version": "1.31.1", 4407 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", 4408 + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", 4409 + "cpu": [ 4410 + "arm64" 4411 + ], 4412 + "dev": true, 4413 + "license": "MPL-2.0", 4414 + "optional": true, 4415 + "os": [ 4416 + "linux" 4417 + ], 4418 + "engines": { 4419 + "node": ">= 12.0.0" 4420 + }, 4421 + "funding": { 4422 + "type": "opencollective", 4423 + "url": "https://opencollective.com/parcel" 4424 + } 4425 + }, 4426 + "node_modules/lightningcss-linux-arm64-musl": { 4427 + "version": "1.31.1", 4428 + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", 4429 + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", 4430 + "cpu": [ 4431 + "arm64" 4432 + ], 4433 + "dev": true, 4434 + "license": "MPL-2.0", 4435 + "optional": true, 4436 + "os": [ 4437 + "linux" 4438 + ], 4439 + "engines": { 4440 + "node": ">= 12.0.0" 4441 + }, 4442 + "funding": { 4443 + "type": "opencollective", 4444 + "url": "https://opencollective.com/parcel" 4445 + } 4446 + }, 4447 + "node_modules/lightningcss-linux-x64-gnu": { 4448 + "version": "1.31.1", 4449 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", 4450 + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", 4451 + "cpu": [ 4452 + "x64" 4453 + ], 4454 + "dev": true, 4455 + "license": "MPL-2.0", 4456 + "optional": true, 4457 + "os": [ 4458 + "linux" 4459 + ], 4460 + "engines": { 4461 + "node": ">= 12.0.0" 4462 + }, 4463 + "funding": { 4464 + "type": "opencollective", 4465 + "url": "https://opencollective.com/parcel" 4466 + } 4467 + }, 4468 + "node_modules/lightningcss-linux-x64-musl": { 4469 + "version": "1.31.1", 4470 + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", 4471 + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", 4472 + "cpu": [ 4473 + "x64" 4474 + ], 4475 + "dev": true, 4476 + "license": "MPL-2.0", 4477 + "optional": true, 4478 + "os": [ 4479 + "linux" 4480 + ], 4481 + "engines": { 4482 + "node": ">= 12.0.0" 4483 + }, 4484 + "funding": { 4485 + "type": "opencollective", 4486 + "url": "https://opencollective.com/parcel" 4487 + } 4488 + }, 4489 + "node_modules/lightningcss-win32-arm64-msvc": { 4490 + "version": "1.31.1", 4491 + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", 4492 + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", 4493 + "cpu": [ 4494 + "arm64" 4495 + ], 4496 + "dev": true, 4497 + "license": "MPL-2.0", 4498 + "optional": true, 4499 + "os": [ 4500 + "win32" 4501 + ], 4502 + "engines": { 4503 + "node": ">= 12.0.0" 4504 + }, 4505 + "funding": { 4506 + "type": "opencollective", 4507 + "url": "https://opencollective.com/parcel" 4508 + } 4509 + }, 4510 + "node_modules/lightningcss-win32-x64-msvc": { 4511 + "version": "1.31.1", 4512 + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", 4513 + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", 4514 + "cpu": [ 4515 + "x64" 4516 + ], 4517 + "dev": true, 4518 + "license": "MPL-2.0", 4519 + "optional": true, 4520 + "os": [ 4521 + "win32" 4522 + ], 4523 + "engines": { 4524 + "node": ">= 12.0.0" 4525 + }, 4526 + "funding": { 4527 + "type": "opencollective", 4528 + "url": "https://opencollective.com/parcel" 4529 + } 4530 + }, 4531 + "node_modules/longest-streak": { 4532 + "version": "3.1.0", 4533 + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", 4534 + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", 4535 + "license": "MIT", 4536 + "funding": { 4537 + "type": "github", 4538 + "url": "https://github.com/sponsors/wooorm" 4539 + } 4540 + }, 4541 + "node_modules/lru-cache": { 4542 + "version": "11.2.6", 4543 + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", 4544 + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", 4545 + "license": "BlueOak-1.0.0", 4546 + "engines": { 4547 + "node": "20 || >=22" 4548 + } 4549 + }, 4550 + "node_modules/magic-string": { 4551 + "version": "0.30.21", 4552 + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", 4553 + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", 4554 + "license": "MIT", 4555 + "dependencies": { 4556 + "@jridgewell/sourcemap-codec": "^1.5.5" 4557 + } 4558 + }, 4559 + "node_modules/magicast": { 4560 + "version": "0.5.2", 4561 + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", 4562 + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", 4563 + "license": "MIT", 4564 + "dependencies": { 4565 + "@babel/parser": "^7.29.0", 4566 + "@babel/types": "^7.29.0", 4567 + "source-map-js": "^1.2.1" 4568 + } 4569 + }, 4570 + "node_modules/markdown-table": { 4571 + "version": "3.0.4", 4572 + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", 4573 + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", 4574 + "license": "MIT", 4575 + "funding": { 4576 + "type": "github", 4577 + "url": "https://github.com/sponsors/wooorm" 4578 + } 4579 + }, 4580 + "node_modules/marked": { 4581 + "version": "17.0.3", 4582 + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.3.tgz", 4583 + "integrity": "sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==", 4584 + "license": "MIT", 4585 + "bin": { 4586 + "marked": "bin/marked.js" 4587 + }, 4588 + "engines": { 4589 + "node": ">= 20" 4590 + } 4591 + }, 4592 + "node_modules/mdast-util-definitions": { 4593 + "version": "6.0.0", 4594 + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", 4595 + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", 4596 + "license": "MIT", 4597 + "dependencies": { 4598 + "@types/mdast": "^4.0.0", 4599 + "@types/unist": "^3.0.0", 4600 + "unist-util-visit": "^5.0.0" 4601 + }, 4602 + "funding": { 4603 + "type": "opencollective", 4604 + "url": "https://opencollective.com/unified" 4605 + } 4606 + }, 4607 + "node_modules/mdast-util-find-and-replace": { 4608 + "version": "3.0.2", 4609 + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", 4610 + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", 4611 + "license": "MIT", 4612 + "dependencies": { 4613 + "@types/mdast": "^4.0.0", 4614 + "escape-string-regexp": "^5.0.0", 4615 + "unist-util-is": "^6.0.0", 4616 + "unist-util-visit-parents": "^6.0.0" 4617 + }, 4618 + "funding": { 4619 + "type": "opencollective", 4620 + "url": "https://opencollective.com/unified" 4621 + } 4622 + }, 4623 + "node_modules/mdast-util-from-markdown": { 4624 + "version": "2.0.3", 4625 + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", 4626 + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", 4627 + "license": "MIT", 4628 + "dependencies": { 4629 + "@types/mdast": "^4.0.0", 4630 + "@types/unist": "^3.0.0", 4631 + "decode-named-character-reference": "^1.0.0", 4632 + "devlop": "^1.0.0", 4633 + "mdast-util-to-string": "^4.0.0", 4634 + "micromark": "^4.0.0", 4635 + "micromark-util-decode-numeric-character-reference": "^2.0.0", 4636 + "micromark-util-decode-string": "^2.0.0", 4637 + "micromark-util-normalize-identifier": "^2.0.0", 4638 + "micromark-util-symbol": "^2.0.0", 4639 + "micromark-util-types": "^2.0.0", 4640 + "unist-util-stringify-position": "^4.0.0" 4641 + }, 4642 + "funding": { 4643 + "type": "opencollective", 4644 + "url": "https://opencollective.com/unified" 4645 + } 4646 + }, 4647 + "node_modules/mdast-util-gfm": { 4648 + "version": "3.1.0", 4649 + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", 4650 + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", 4651 + "license": "MIT", 4652 + "dependencies": { 4653 + "mdast-util-from-markdown": "^2.0.0", 4654 + "mdast-util-gfm-autolink-literal": "^2.0.0", 4655 + "mdast-util-gfm-footnote": "^2.0.0", 4656 + "mdast-util-gfm-strikethrough": "^2.0.0", 4657 + "mdast-util-gfm-table": "^2.0.0", 4658 + "mdast-util-gfm-task-list-item": "^2.0.0", 4659 + "mdast-util-to-markdown": "^2.0.0" 4660 + }, 4661 + "funding": { 4662 + "type": "opencollective", 4663 + "url": "https://opencollective.com/unified" 4664 + } 4665 + }, 4666 + "node_modules/mdast-util-gfm-autolink-literal": { 4667 + "version": "2.0.1", 4668 + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", 4669 + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", 4670 + "license": "MIT", 4671 + "dependencies": { 4672 + "@types/mdast": "^4.0.0", 4673 + "ccount": "^2.0.0", 4674 + "devlop": "^1.0.0", 4675 + "mdast-util-find-and-replace": "^3.0.0", 4676 + "micromark-util-character": "^2.0.0" 4677 + }, 4678 + "funding": { 4679 + "type": "opencollective", 4680 + "url": "https://opencollective.com/unified" 4681 + } 4682 + }, 4683 + "node_modules/mdast-util-gfm-footnote": { 4684 + "version": "2.1.0", 4685 + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", 4686 + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", 4687 + "license": "MIT", 4688 + "dependencies": { 4689 + "@types/mdast": "^4.0.0", 4690 + "devlop": "^1.1.0", 4691 + "mdast-util-from-markdown": "^2.0.0", 4692 + "mdast-util-to-markdown": "^2.0.0", 4693 + "micromark-util-normalize-identifier": "^2.0.0" 4694 + }, 4695 + "funding": { 4696 + "type": "opencollective", 4697 + "url": "https://opencollective.com/unified" 4698 + } 4699 + }, 4700 + "node_modules/mdast-util-gfm-strikethrough": { 4701 + "version": "2.0.0", 4702 + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", 4703 + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", 4704 + "license": "MIT", 4705 + "dependencies": { 4706 + "@types/mdast": "^4.0.0", 4707 + "mdast-util-from-markdown": "^2.0.0", 4708 + "mdast-util-to-markdown": "^2.0.0" 4709 + }, 4710 + "funding": { 4711 + "type": "opencollective", 4712 + "url": "https://opencollective.com/unified" 4713 + } 4714 + }, 4715 + "node_modules/mdast-util-gfm-table": { 4716 + "version": "2.0.0", 4717 + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", 4718 + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", 4719 + "license": "MIT", 4720 + "dependencies": { 4721 + "@types/mdast": "^4.0.0", 4722 + "devlop": "^1.0.0", 4723 + "markdown-table": "^3.0.0", 4724 + "mdast-util-from-markdown": "^2.0.0", 4725 + "mdast-util-to-markdown": "^2.0.0" 4726 + }, 4727 + "funding": { 4728 + "type": "opencollective", 4729 + "url": "https://opencollective.com/unified" 4730 + } 4731 + }, 4732 + "node_modules/mdast-util-gfm-task-list-item": { 4733 + "version": "2.0.0", 4734 + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", 4735 + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", 4736 + "license": "MIT", 4737 + "dependencies": { 4738 + "@types/mdast": "^4.0.0", 4739 + "devlop": "^1.0.0", 4740 + "mdast-util-from-markdown": "^2.0.0", 4741 + "mdast-util-to-markdown": "^2.0.0" 4742 + }, 4743 + "funding": { 4744 + "type": "opencollective", 4745 + "url": "https://opencollective.com/unified" 4746 + } 4747 + }, 4748 + "node_modules/mdast-util-phrasing": { 4749 + "version": "4.1.0", 4750 + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", 4751 + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", 4752 + "license": "MIT", 4753 + "dependencies": { 4754 + "@types/mdast": "^4.0.0", 4755 + "unist-util-is": "^6.0.0" 4756 + }, 4757 + "funding": { 4758 + "type": "opencollective", 4759 + "url": "https://opencollective.com/unified" 4760 + } 4761 + }, 4762 + "node_modules/mdast-util-to-hast": { 4763 + "version": "13.2.1", 4764 + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", 4765 + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", 4766 + "license": "MIT", 4767 + "dependencies": { 4768 + "@types/hast": "^3.0.0", 4769 + "@types/mdast": "^4.0.0", 4770 + "@ungap/structured-clone": "^1.0.0", 4771 + "devlop": "^1.0.0", 4772 + "micromark-util-sanitize-uri": "^2.0.0", 4773 + "trim-lines": "^3.0.0", 4774 + "unist-util-position": "^5.0.0", 4775 + "unist-util-visit": "^5.0.0", 4776 + "vfile": "^6.0.0" 4777 + }, 4778 + "funding": { 4779 + "type": "opencollective", 4780 + "url": "https://opencollective.com/unified" 4781 + } 4782 + }, 4783 + "node_modules/mdast-util-to-markdown": { 4784 + "version": "2.1.2", 4785 + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", 4786 + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", 4787 + "license": "MIT", 4788 + "dependencies": { 4789 + "@types/mdast": "^4.0.0", 4790 + "@types/unist": "^3.0.0", 4791 + "longest-streak": "^3.0.0", 4792 + "mdast-util-phrasing": "^4.0.0", 4793 + "mdast-util-to-string": "^4.0.0", 4794 + "micromark-util-classify-character": "^2.0.0", 4795 + "micromark-util-decode-string": "^2.0.0", 4796 + "unist-util-visit": "^5.0.0", 4797 + "zwitch": "^2.0.0" 4798 + }, 4799 + "funding": { 4800 + "type": "opencollective", 4801 + "url": "https://opencollective.com/unified" 4802 + } 4803 + }, 4804 + "node_modules/mdast-util-to-string": { 4805 + "version": "4.0.0", 4806 + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", 4807 + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", 4808 + "license": "MIT", 4809 + "dependencies": { 4810 + "@types/mdast": "^4.0.0" 4811 + }, 4812 + "funding": { 4813 + "type": "opencollective", 4814 + "url": "https://opencollective.com/unified" 4815 + } 4816 + }, 4817 + "node_modules/mdn-data": { 4818 + "version": "2.12.2", 4819 + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", 4820 + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", 4821 + "license": "CC0-1.0" 4822 + }, 4823 + "node_modules/micromark": { 4824 + "version": "4.0.2", 4825 + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", 4826 + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", 4827 + "funding": [ 4828 + { 4829 + "type": "GitHub Sponsors", 4830 + "url": "https://github.com/sponsors/unifiedjs" 4831 + }, 4832 + { 4833 + "type": "OpenCollective", 4834 + "url": "https://opencollective.com/unified" 4835 + } 4836 + ], 4837 + "license": "MIT", 4838 + "dependencies": { 4839 + "@types/debug": "^4.0.0", 4840 + "debug": "^4.0.0", 4841 + "decode-named-character-reference": "^1.0.0", 4842 + "devlop": "^1.0.0", 4843 + "micromark-core-commonmark": "^2.0.0", 4844 + "micromark-factory-space": "^2.0.0", 4845 + "micromark-util-character": "^2.0.0", 4846 + "micromark-util-chunked": "^2.0.0", 4847 + "micromark-util-combine-extensions": "^2.0.0", 4848 + "micromark-util-decode-numeric-character-reference": "^2.0.0", 4849 + "micromark-util-encode": "^2.0.0", 4850 + "micromark-util-normalize-identifier": "^2.0.0", 4851 + "micromark-util-resolve-all": "^2.0.0", 4852 + "micromark-util-sanitize-uri": "^2.0.0", 4853 + "micromark-util-subtokenize": "^2.0.0", 4854 + "micromark-util-symbol": "^2.0.0", 4855 + "micromark-util-types": "^2.0.0" 4856 + } 4857 + }, 4858 + "node_modules/micromark-core-commonmark": { 4859 + "version": "2.0.3", 4860 + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", 4861 + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", 4862 + "funding": [ 4863 + { 4864 + "type": "GitHub Sponsors", 4865 + "url": "https://github.com/sponsors/unifiedjs" 4866 + }, 4867 + { 4868 + "type": "OpenCollective", 4869 + "url": "https://opencollective.com/unified" 4870 + } 4871 + ], 4872 + "license": "MIT", 4873 + "dependencies": { 4874 + "decode-named-character-reference": "^1.0.0", 4875 + "devlop": "^1.0.0", 4876 + "micromark-factory-destination": "^2.0.0", 4877 + "micromark-factory-label": "^2.0.0", 4878 + "micromark-factory-space": "^2.0.0", 4879 + "micromark-factory-title": "^2.0.0", 4880 + "micromark-factory-whitespace": "^2.0.0", 4881 + "micromark-util-character": "^2.0.0", 4882 + "micromark-util-chunked": "^2.0.0", 4883 + "micromark-util-classify-character": "^2.0.0", 4884 + "micromark-util-html-tag-name": "^2.0.0", 4885 + "micromark-util-normalize-identifier": "^2.0.0", 4886 + "micromark-util-resolve-all": "^2.0.0", 4887 + "micromark-util-subtokenize": "^2.0.0", 4888 + "micromark-util-symbol": "^2.0.0", 4889 + "micromark-util-types": "^2.0.0" 4890 + } 4891 + }, 4892 + "node_modules/micromark-extension-gfm": { 4893 + "version": "3.0.0", 4894 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", 4895 + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", 4896 + "license": "MIT", 4897 + "dependencies": { 4898 + "micromark-extension-gfm-autolink-literal": "^2.0.0", 4899 + "micromark-extension-gfm-footnote": "^2.0.0", 4900 + "micromark-extension-gfm-strikethrough": "^2.0.0", 4901 + "micromark-extension-gfm-table": "^2.0.0", 4902 + "micromark-extension-gfm-tagfilter": "^2.0.0", 4903 + "micromark-extension-gfm-task-list-item": "^2.0.0", 4904 + "micromark-util-combine-extensions": "^2.0.0", 4905 + "micromark-util-types": "^2.0.0" 4906 + }, 4907 + "funding": { 4908 + "type": "opencollective", 4909 + "url": "https://opencollective.com/unified" 4910 + } 4911 + }, 4912 + "node_modules/micromark-extension-gfm-autolink-literal": { 4913 + "version": "2.1.0", 4914 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", 4915 + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", 4916 + "license": "MIT", 4917 + "dependencies": { 4918 + "micromark-util-character": "^2.0.0", 4919 + "micromark-util-sanitize-uri": "^2.0.0", 4920 + "micromark-util-symbol": "^2.0.0", 4921 + "micromark-util-types": "^2.0.0" 4922 + }, 4923 + "funding": { 4924 + "type": "opencollective", 4925 + "url": "https://opencollective.com/unified" 4926 + } 4927 + }, 4928 + "node_modules/micromark-extension-gfm-footnote": { 4929 + "version": "2.1.0", 4930 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", 4931 + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", 4932 + "license": "MIT", 4933 + "dependencies": { 4934 + "devlop": "^1.0.0", 4935 + "micromark-core-commonmark": "^2.0.0", 4936 + "micromark-factory-space": "^2.0.0", 4937 + "micromark-util-character": "^2.0.0", 4938 + "micromark-util-normalize-identifier": "^2.0.0", 4939 + "micromark-util-sanitize-uri": "^2.0.0", 4940 + "micromark-util-symbol": "^2.0.0", 4941 + "micromark-util-types": "^2.0.0" 4942 + }, 4943 + "funding": { 4944 + "type": "opencollective", 4945 + "url": "https://opencollective.com/unified" 4946 + } 4947 + }, 4948 + "node_modules/micromark-extension-gfm-strikethrough": { 4949 + "version": "2.1.0", 4950 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", 4951 + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", 4952 + "license": "MIT", 4953 + "dependencies": { 4954 + "devlop": "^1.0.0", 4955 + "micromark-util-chunked": "^2.0.0", 4956 + "micromark-util-classify-character": "^2.0.0", 4957 + "micromark-util-resolve-all": "^2.0.0", 4958 + "micromark-util-symbol": "^2.0.0", 4959 + "micromark-util-types": "^2.0.0" 4960 + }, 4961 + "funding": { 4962 + "type": "opencollective", 4963 + "url": "https://opencollective.com/unified" 4964 + } 4965 + }, 4966 + "node_modules/micromark-extension-gfm-table": { 4967 + "version": "2.1.1", 4968 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", 4969 + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", 4970 + "license": "MIT", 4971 + "dependencies": { 4972 + "devlop": "^1.0.0", 4973 + "micromark-factory-space": "^2.0.0", 4974 + "micromark-util-character": "^2.0.0", 4975 + "micromark-util-symbol": "^2.0.0", 4976 + "micromark-util-types": "^2.0.0" 4977 + }, 4978 + "funding": { 4979 + "type": "opencollective", 4980 + "url": "https://opencollective.com/unified" 4981 + } 4982 + }, 4983 + "node_modules/micromark-extension-gfm-tagfilter": { 4984 + "version": "2.0.0", 4985 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", 4986 + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", 4987 + "license": "MIT", 4988 + "dependencies": { 4989 + "micromark-util-types": "^2.0.0" 4990 + }, 4991 + "funding": { 4992 + "type": "opencollective", 4993 + "url": "https://opencollective.com/unified" 4994 + } 4995 + }, 4996 + "node_modules/micromark-extension-gfm-task-list-item": { 4997 + "version": "2.1.0", 4998 + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", 4999 + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", 5000 + "license": "MIT", 5001 + "dependencies": { 5002 + "devlop": "^1.0.0", 5003 + "micromark-factory-space": "^2.0.0", 5004 + "micromark-util-character": "^2.0.0", 5005 + "micromark-util-symbol": "^2.0.0", 5006 + "micromark-util-types": "^2.0.0" 5007 + }, 5008 + "funding": { 5009 + "type": "opencollective", 5010 + "url": "https://opencollective.com/unified" 5011 + } 5012 + }, 5013 + "node_modules/micromark-factory-destination": { 5014 + "version": "2.0.1", 5015 + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", 5016 + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", 5017 + "funding": [ 5018 + { 5019 + "type": "GitHub Sponsors", 5020 + "url": "https://github.com/sponsors/unifiedjs" 5021 + }, 5022 + { 5023 + "type": "OpenCollective", 5024 + "url": "https://opencollective.com/unified" 5025 + } 5026 + ], 5027 + "license": "MIT", 5028 + "dependencies": { 5029 + "micromark-util-character": "^2.0.0", 5030 + "micromark-util-symbol": "^2.0.0", 5031 + "micromark-util-types": "^2.0.0" 5032 + } 5033 + }, 5034 + "node_modules/micromark-factory-label": { 5035 + "version": "2.0.1", 5036 + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", 5037 + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", 5038 + "funding": [ 5039 + { 5040 + "type": "GitHub Sponsors", 5041 + "url": "https://github.com/sponsors/unifiedjs" 5042 + }, 5043 + { 5044 + "type": "OpenCollective", 5045 + "url": "https://opencollective.com/unified" 5046 + } 5047 + ], 5048 + "license": "MIT", 5049 + "dependencies": { 5050 + "devlop": "^1.0.0", 5051 + "micromark-util-character": "^2.0.0", 5052 + "micromark-util-symbol": "^2.0.0", 5053 + "micromark-util-types": "^2.0.0" 5054 + } 5055 + }, 5056 + "node_modules/micromark-factory-space": { 5057 + "version": "2.0.1", 5058 + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", 5059 + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", 5060 + "funding": [ 5061 + { 5062 + "type": "GitHub Sponsors", 5063 + "url": "https://github.com/sponsors/unifiedjs" 5064 + }, 5065 + { 5066 + "type": "OpenCollective", 5067 + "url": "https://opencollective.com/unified" 5068 + } 5069 + ], 5070 + "license": "MIT", 5071 + "dependencies": { 5072 + "micromark-util-character": "^2.0.0", 5073 + "micromark-util-types": "^2.0.0" 5074 + } 5075 + }, 5076 + "node_modules/micromark-factory-title": { 5077 + "version": "2.0.1", 5078 + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", 5079 + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", 5080 + "funding": [ 5081 + { 5082 + "type": "GitHub Sponsors", 5083 + "url": "https://github.com/sponsors/unifiedjs" 5084 + }, 5085 + { 5086 + "type": "OpenCollective", 5087 + "url": "https://opencollective.com/unified" 5088 + } 5089 + ], 5090 + "license": "MIT", 5091 + "dependencies": { 5092 + "micromark-factory-space": "^2.0.0", 5093 + "micromark-util-character": "^2.0.0", 5094 + "micromark-util-symbol": "^2.0.0", 5095 + "micromark-util-types": "^2.0.0" 5096 + } 5097 + }, 5098 + "node_modules/micromark-factory-whitespace": { 5099 + "version": "2.0.1", 5100 + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", 5101 + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", 5102 + "funding": [ 5103 + { 5104 + "type": "GitHub Sponsors", 5105 + "url": "https://github.com/sponsors/unifiedjs" 5106 + }, 5107 + { 5108 + "type": "OpenCollective", 5109 + "url": "https://opencollective.com/unified" 5110 + } 5111 + ], 5112 + "license": "MIT", 5113 + "dependencies": { 5114 + "micromark-factory-space": "^2.0.0", 5115 + "micromark-util-character": "^2.0.0", 5116 + "micromark-util-symbol": "^2.0.0", 5117 + "micromark-util-types": "^2.0.0" 5118 + } 5119 + }, 5120 + "node_modules/micromark-util-character": { 5121 + "version": "2.1.1", 5122 + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", 5123 + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", 5124 + "funding": [ 5125 + { 5126 + "type": "GitHub Sponsors", 5127 + "url": "https://github.com/sponsors/unifiedjs" 5128 + }, 5129 + { 5130 + "type": "OpenCollective", 5131 + "url": "https://opencollective.com/unified" 5132 + } 5133 + ], 5134 + "license": "MIT", 5135 + "dependencies": { 5136 + "micromark-util-symbol": "^2.0.0", 5137 + "micromark-util-types": "^2.0.0" 5138 + } 5139 + }, 5140 + "node_modules/micromark-util-chunked": { 5141 + "version": "2.0.1", 5142 + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", 5143 + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", 5144 + "funding": [ 5145 + { 5146 + "type": "GitHub Sponsors", 5147 + "url": "https://github.com/sponsors/unifiedjs" 5148 + }, 5149 + { 5150 + "type": "OpenCollective", 5151 + "url": "https://opencollective.com/unified" 5152 + } 5153 + ], 5154 + "license": "MIT", 5155 + "dependencies": { 5156 + "micromark-util-symbol": "^2.0.0" 5157 + } 5158 + }, 5159 + "node_modules/micromark-util-classify-character": { 5160 + "version": "2.0.1", 5161 + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", 5162 + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", 5163 + "funding": [ 5164 + { 5165 + "type": "GitHub Sponsors", 5166 + "url": "https://github.com/sponsors/unifiedjs" 5167 + }, 5168 + { 5169 + "type": "OpenCollective", 5170 + "url": "https://opencollective.com/unified" 5171 + } 5172 + ], 5173 + "license": "MIT", 5174 + "dependencies": { 5175 + "micromark-util-character": "^2.0.0", 5176 + "micromark-util-symbol": "^2.0.0", 5177 + "micromark-util-types": "^2.0.0" 5178 + } 5179 + }, 5180 + "node_modules/micromark-util-combine-extensions": { 5181 + "version": "2.0.1", 5182 + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", 5183 + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", 5184 + "funding": [ 5185 + { 5186 + "type": "GitHub Sponsors", 5187 + "url": "https://github.com/sponsors/unifiedjs" 5188 + }, 5189 + { 5190 + "type": "OpenCollective", 5191 + "url": "https://opencollective.com/unified" 5192 + } 5193 + ], 5194 + "license": "MIT", 5195 + "dependencies": { 5196 + "micromark-util-chunked": "^2.0.0", 5197 + "micromark-util-types": "^2.0.0" 5198 + } 5199 + }, 5200 + "node_modules/micromark-util-decode-numeric-character-reference": { 5201 + "version": "2.0.2", 5202 + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", 5203 + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", 5204 + "funding": [ 5205 + { 5206 + "type": "GitHub Sponsors", 5207 + "url": "https://github.com/sponsors/unifiedjs" 5208 + }, 5209 + { 5210 + "type": "OpenCollective", 5211 + "url": "https://opencollective.com/unified" 5212 + } 5213 + ], 5214 + "license": "MIT", 5215 + "dependencies": { 5216 + "micromark-util-symbol": "^2.0.0" 5217 + } 5218 + }, 5219 + "node_modules/micromark-util-decode-string": { 5220 + "version": "2.0.1", 5221 + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", 5222 + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", 5223 + "funding": [ 5224 + { 5225 + "type": "GitHub Sponsors", 5226 + "url": "https://github.com/sponsors/unifiedjs" 5227 + }, 5228 + { 5229 + "type": "OpenCollective", 5230 + "url": "https://opencollective.com/unified" 5231 + } 5232 + ], 5233 + "license": "MIT", 5234 + "dependencies": { 5235 + "decode-named-character-reference": "^1.0.0", 5236 + "micromark-util-character": "^2.0.0", 5237 + "micromark-util-decode-numeric-character-reference": "^2.0.0", 5238 + "micromark-util-symbol": "^2.0.0" 5239 + } 5240 + }, 5241 + "node_modules/micromark-util-encode": { 5242 + "version": "2.0.1", 5243 + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", 5244 + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", 5245 + "funding": [ 5246 + { 5247 + "type": "GitHub Sponsors", 5248 + "url": "https://github.com/sponsors/unifiedjs" 5249 + }, 5250 + { 5251 + "type": "OpenCollective", 5252 + "url": "https://opencollective.com/unified" 5253 + } 5254 + ], 5255 + "license": "MIT" 5256 + }, 5257 + "node_modules/micromark-util-html-tag-name": { 5258 + "version": "2.0.1", 5259 + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", 5260 + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", 5261 + "funding": [ 5262 + { 5263 + "type": "GitHub Sponsors", 5264 + "url": "https://github.com/sponsors/unifiedjs" 5265 + }, 5266 + { 5267 + "type": "OpenCollective", 5268 + "url": "https://opencollective.com/unified" 5269 + } 5270 + ], 5271 + "license": "MIT" 5272 + }, 5273 + "node_modules/micromark-util-normalize-identifier": { 5274 + "version": "2.0.1", 5275 + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", 5276 + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", 5277 + "funding": [ 5278 + { 5279 + "type": "GitHub Sponsors", 5280 + "url": "https://github.com/sponsors/unifiedjs" 5281 + }, 5282 + { 5283 + "type": "OpenCollective", 5284 + "url": "https://opencollective.com/unified" 5285 + } 5286 + ], 5287 + "license": "MIT", 5288 + "dependencies": { 5289 + "micromark-util-symbol": "^2.0.0" 5290 + } 5291 + }, 5292 + "node_modules/micromark-util-resolve-all": { 5293 + "version": "2.0.1", 5294 + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", 5295 + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", 5296 + "funding": [ 5297 + { 5298 + "type": "GitHub Sponsors", 5299 + "url": "https://github.com/sponsors/unifiedjs" 5300 + }, 5301 + { 5302 + "type": "OpenCollective", 5303 + "url": "https://opencollective.com/unified" 5304 + } 5305 + ], 5306 + "license": "MIT", 5307 + "dependencies": { 5308 + "micromark-util-types": "^2.0.0" 5309 + } 5310 + }, 5311 + "node_modules/micromark-util-sanitize-uri": { 5312 + "version": "2.0.1", 5313 + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", 5314 + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", 5315 + "funding": [ 5316 + { 5317 + "type": "GitHub Sponsors", 5318 + "url": "https://github.com/sponsors/unifiedjs" 5319 + }, 5320 + { 5321 + "type": "OpenCollective", 5322 + "url": "https://opencollective.com/unified" 5323 + } 5324 + ], 5325 + "license": "MIT", 5326 + "dependencies": { 5327 + "micromark-util-character": "^2.0.0", 5328 + "micromark-util-encode": "^2.0.0", 5329 + "micromark-util-symbol": "^2.0.0" 5330 + } 5331 + }, 5332 + "node_modules/micromark-util-subtokenize": { 5333 + "version": "2.1.0", 5334 + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", 5335 + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", 5336 + "funding": [ 5337 + { 5338 + "type": "GitHub Sponsors", 5339 + "url": "https://github.com/sponsors/unifiedjs" 5340 + }, 5341 + { 5342 + "type": "OpenCollective", 5343 + "url": "https://opencollective.com/unified" 5344 + } 5345 + ], 5346 + "license": "MIT", 5347 + "dependencies": { 5348 + "devlop": "^1.0.0", 5349 + "micromark-util-chunked": "^2.0.0", 5350 + "micromark-util-symbol": "^2.0.0", 5351 + "micromark-util-types": "^2.0.0" 5352 + } 5353 + }, 5354 + "node_modules/micromark-util-symbol": { 5355 + "version": "2.0.1", 5356 + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", 5357 + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", 5358 + "funding": [ 5359 + { 5360 + "type": "GitHub Sponsors", 5361 + "url": "https://github.com/sponsors/unifiedjs" 5362 + }, 5363 + { 5364 + "type": "OpenCollective", 5365 + "url": "https://opencollective.com/unified" 5366 + } 5367 + ], 5368 + "license": "MIT" 5369 + }, 5370 + "node_modules/micromark-util-types": { 5371 + "version": "2.0.2", 5372 + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", 5373 + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", 5374 + "funding": [ 5375 + { 5376 + "type": "GitHub Sponsors", 5377 + "url": "https://github.com/sponsors/unifiedjs" 5378 + }, 5379 + { 5380 + "type": "OpenCollective", 5381 + "url": "https://opencollective.com/unified" 5382 + } 5383 + ], 5384 + "license": "MIT" 5385 + }, 5386 + "node_modules/mime-db": { 5387 + "version": "1.54.0", 5388 + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 5389 + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 5390 + "license": "MIT", 5391 + "engines": { 5392 + "node": ">= 0.6" 5393 + } 5394 + }, 5395 + "node_modules/mime-types": { 5396 + "version": "3.0.2", 5397 + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", 5398 + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", 5399 + "license": "MIT", 5400 + "dependencies": { 5401 + "mime-db": "^1.54.0" 5402 + }, 5403 + "engines": { 5404 + "node": ">=18" 5405 + }, 5406 + "funding": { 5407 + "type": "opencollective", 5408 + "url": "https://opencollective.com/express" 5409 + } 5410 + }, 5411 + "node_modules/mrmime": { 5412 + "version": "2.0.1", 5413 + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", 5414 + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", 5415 + "license": "MIT", 5416 + "engines": { 5417 + "node": ">=10" 5418 + } 5419 + }, 5420 + "node_modules/ms": { 5421 + "version": "2.1.3", 5422 + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 5423 + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 5424 + "license": "MIT" 5425 + }, 5426 + "node_modules/nanoid": { 5427 + "version": "3.3.11", 5428 + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 5429 + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 5430 + "funding": [ 5431 + { 5432 + "type": "github", 5433 + "url": "https://github.com/sponsors/ai" 5434 + } 5435 + ], 5436 + "license": "MIT", 5437 + "bin": { 5438 + "nanoid": "bin/nanoid.cjs" 5439 + }, 5440 + "engines": { 5441 + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 5442 + } 5443 + }, 5444 + "node_modules/neotraverse": { 5445 + "version": "0.6.18", 5446 + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", 5447 + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", 5448 + "license": "MIT", 5449 + "engines": { 5450 + "node": ">= 10" 5451 + } 5452 + }, 5453 + "node_modules/nlcst-to-string": { 5454 + "version": "4.0.0", 5455 + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", 5456 + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", 5457 + "license": "MIT", 5458 + "dependencies": { 5459 + "@types/nlcst": "^2.0.0" 5460 + }, 5461 + "funding": { 5462 + "type": "opencollective", 5463 + "url": "https://opencollective.com/unified" 5464 + } 5465 + }, 5466 + "node_modules/node-fetch-native": { 5467 + "version": "1.6.7", 5468 + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", 5469 + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", 5470 + "license": "MIT" 5471 + }, 5472 + "node_modules/node-mock-http": { 5473 + "version": "1.0.4", 5474 + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", 5475 + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", 5476 + "license": "MIT" 5477 + }, 5478 + "node_modules/normalize-path": { 5479 + "version": "3.0.0", 5480 + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 5481 + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 5482 + "license": "MIT", 5483 + "engines": { 5484 + "node": ">=0.10.0" 5485 + } 5486 + }, 5487 + "node_modules/nth-check": { 5488 + "version": "2.1.1", 5489 + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 5490 + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 5491 + "license": "BSD-2-Clause", 5492 + "dependencies": { 5493 + "boolbase": "^1.0.0" 5494 + }, 5495 + "funding": { 5496 + "url": "https://github.com/fb55/nth-check?sponsor=1" 5497 + } 5498 + }, 5499 + "node_modules/obug": { 5500 + "version": "2.1.1", 5501 + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", 5502 + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", 5503 + "dev": true, 5504 + "funding": [ 5505 + "https://github.com/sponsors/sxzz", 5506 + "https://opencollective.com/debug" 5507 + ], 5508 + "license": "MIT" 5509 + }, 5510 + "node_modules/ofetch": { 5511 + "version": "1.5.1", 5512 + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", 5513 + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", 5514 + "license": "MIT", 5515 + "dependencies": { 5516 + "destr": "^2.0.5", 5517 + "node-fetch-native": "^1.6.7", 5518 + "ufo": "^1.6.1" 5519 + } 5520 + }, 5521 + "node_modules/ohash": { 5522 + "version": "2.0.11", 5523 + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 5524 + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 5525 + "license": "MIT" 5526 + }, 5527 + "node_modules/on-finished": { 5528 + "version": "2.4.1", 5529 + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 5530 + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 5531 + "license": "MIT", 5532 + "dependencies": { 5533 + "ee-first": "1.1.1" 5534 + }, 5535 + "engines": { 5536 + "node": ">= 0.8" 5537 + } 5538 + }, 5539 + "node_modules/oniguruma-parser": { 5540 + "version": "0.12.1", 5541 + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", 5542 + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", 5543 + "license": "MIT" 5544 + }, 5545 + "node_modules/oniguruma-to-es": { 5546 + "version": "4.3.4", 5547 + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", 5548 + "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", 5549 + "license": "MIT", 5550 + "dependencies": { 5551 + "oniguruma-parser": "^0.12.1", 5552 + "regex": "^6.0.1", 5553 + "regex-recursion": "^6.0.2" 5554 + } 5555 + }, 5556 + "node_modules/p-limit": { 5557 + "version": "6.2.0", 5558 + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", 5559 + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", 5560 + "license": "MIT", 5561 + "dependencies": { 5562 + "yocto-queue": "^1.1.1" 5563 + }, 5564 + "engines": { 5565 + "node": ">=18" 5566 + }, 5567 + "funding": { 5568 + "url": "https://github.com/sponsors/sindresorhus" 5569 + } 5570 + }, 5571 + "node_modules/p-queue": { 5572 + "version": "8.1.1", 5573 + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", 5574 + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", 5575 + "license": "MIT", 5576 + "dependencies": { 5577 + "eventemitter3": "^5.0.1", 5578 + "p-timeout": "^6.1.2" 5579 + }, 5580 + "engines": { 5581 + "node": ">=18" 5582 + }, 5583 + "funding": { 5584 + "url": "https://github.com/sponsors/sindresorhus" 5585 + } 5586 + }, 5587 + "node_modules/p-timeout": { 5588 + "version": "6.1.4", 5589 + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", 5590 + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", 5591 + "license": "MIT", 5592 + "engines": { 5593 + "node": ">=14.16" 5594 + }, 5595 + "funding": { 5596 + "url": "https://github.com/sponsors/sindresorhus" 5597 + } 5598 + }, 5599 + "node_modules/package-manager-detector": { 5600 + "version": "1.6.0", 5601 + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", 5602 + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", 5603 + "license": "MIT" 5604 + }, 5605 + "node_modules/parse-latin": { 5606 + "version": "7.0.0", 5607 + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", 5608 + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", 5609 + "license": "MIT", 5610 + "dependencies": { 5611 + "@types/nlcst": "^2.0.0", 5612 + "@types/unist": "^3.0.0", 5613 + "nlcst-to-string": "^4.0.0", 5614 + "unist-util-modify-children": "^4.0.0", 5615 + "unist-util-visit-children": "^3.0.0", 5616 + "vfile": "^6.0.0" 5617 + }, 5618 + "funding": { 5619 + "type": "github", 5620 + "url": "https://github.com/sponsors/wooorm" 5621 + } 5622 + }, 5623 + "node_modules/parse5": { 5624 + "version": "7.3.0", 5625 + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", 5626 + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", 5627 + "license": "MIT", 5628 + "dependencies": { 5629 + "entities": "^6.0.0" 5630 + }, 5631 + "funding": { 5632 + "url": "https://github.com/inikulin/parse5?sponsor=1" 5633 + } 5634 + }, 5635 + "node_modules/pathe": { 5636 + "version": "2.0.3", 5637 + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 5638 + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 5639 + "dev": true, 5640 + "license": "MIT" 5641 + }, 5642 + "node_modules/piccolore": { 5643 + "version": "0.1.3", 5644 + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", 5645 + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", 5646 + "license": "ISC" 5647 + }, 5648 + "node_modules/picocolors": { 5649 + "version": "1.1.1", 5650 + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 5651 + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 5652 + "license": "ISC" 5653 + }, 5654 + "node_modules/picomatch": { 5655 + "version": "4.0.3", 5656 + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 5657 + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 5658 + "license": "MIT", 5659 + "engines": { 5660 + "node": ">=12" 5661 + }, 5662 + "funding": { 5663 + "url": "https://github.com/sponsors/jonschlinkert" 5664 + } 5665 + }, 5666 + "node_modules/playwright": { 5667 + "version": "1.58.2", 5668 + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", 5669 + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", 5670 + "dev": true, 5671 + "license": "Apache-2.0", 5672 + "dependencies": { 5673 + "playwright-core": "1.58.2" 5674 + }, 5675 + "bin": { 5676 + "playwright": "cli.js" 5677 + }, 5678 + "engines": { 5679 + "node": ">=18" 5680 + }, 5681 + "optionalDependencies": { 5682 + "fsevents": "2.3.2" 5683 + } 5684 + }, 5685 + "node_modules/playwright-core": { 5686 + "version": "1.58.2", 5687 + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", 5688 + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", 5689 + "dev": true, 5690 + "license": "Apache-2.0", 5691 + "bin": { 5692 + "playwright-core": "cli.js" 5693 + }, 5694 + "engines": { 5695 + "node": ">=18" 5696 + } 5697 + }, 5698 + "node_modules/playwright/node_modules/fsevents": { 5699 + "version": "2.3.2", 5700 + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 5701 + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 5702 + "dev": true, 5703 + "hasInstallScript": true, 5704 + "license": "MIT", 5705 + "optional": true, 5706 + "os": [ 5707 + "darwin" 5708 + ], 5709 + "engines": { 5710 + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 5711 + } 5712 + }, 5713 + "node_modules/postcss": { 5714 + "version": "8.5.6", 5715 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 5716 + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 5717 + "funding": [ 5718 + { 5719 + "type": "opencollective", 5720 + "url": "https://opencollective.com/postcss/" 5721 + }, 5722 + { 5723 + "type": "tidelift", 5724 + "url": "https://tidelift.com/funding/github/npm/postcss" 5725 + }, 5726 + { 5727 + "type": "github", 5728 + "url": "https://github.com/sponsors/ai" 5729 + } 5730 + ], 5731 + "license": "MIT", 5732 + "dependencies": { 5733 + "nanoid": "^3.3.11", 5734 + "picocolors": "^1.1.1", 5735 + "source-map-js": "^1.2.1" 5736 + }, 5737 + "engines": { 5738 + "node": "^10 || ^12 || >=14" 5739 + } 5740 + }, 5741 + "node_modules/prismjs": { 5742 + "version": "1.30.0", 5743 + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", 5744 + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", 5745 + "license": "MIT", 5746 + "engines": { 5747 + "node": ">=6" 5748 + } 5749 + }, 5750 + "node_modules/prompts": { 5751 + "version": "2.4.2", 5752 + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", 5753 + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", 5754 + "license": "MIT", 5755 + "dependencies": { 5756 + "kleur": "^3.0.3", 5757 + "sisteransi": "^1.0.5" 5758 + }, 5759 + "engines": { 5760 + "node": ">= 6" 5761 + } 5762 + }, 5763 + "node_modules/property-information": { 5764 + "version": "7.1.0", 5765 + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", 5766 + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", 5767 + "license": "MIT", 5768 + "funding": { 5769 + "type": "github", 5770 + "url": "https://github.com/sponsors/wooorm" 5771 + } 5772 + }, 5773 + "node_modules/punycode": { 5774 + "version": "2.3.1", 5775 + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 5776 + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 5777 + "license": "MIT", 5778 + "engines": { 5779 + "node": ">=6" 5780 + } 5781 + }, 5782 + "node_modules/radix3": { 5783 + "version": "1.1.2", 5784 + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", 5785 + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", 5786 + "license": "MIT" 5787 + }, 5788 + "node_modules/range-parser": { 5789 + "version": "1.2.1", 5790 + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 5791 + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 5792 + "license": "MIT", 5793 + "engines": { 5794 + "node": ">= 0.6" 5795 + } 5796 + }, 5797 + "node_modules/readdirp": { 5798 + "version": "5.0.0", 5799 + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", 5800 + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", 5801 + "license": "MIT", 5802 + "engines": { 5803 + "node": ">= 20.19.0" 5804 + }, 5805 + "funding": { 5806 + "type": "individual", 5807 + "url": "https://paulmillr.com/funding/" 5808 + } 5809 + }, 5810 + "node_modules/regex": { 5811 + "version": "6.1.0", 5812 + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", 5813 + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", 5814 + "license": "MIT", 5815 + "dependencies": { 5816 + "regex-utilities": "^2.3.0" 5817 + } 5818 + }, 5819 + "node_modules/regex-recursion": { 5820 + "version": "6.0.2", 5821 + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", 5822 + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", 5823 + "license": "MIT", 5824 + "dependencies": { 5825 + "regex-utilities": "^2.3.0" 5826 + } 5827 + }, 5828 + "node_modules/regex-utilities": { 5829 + "version": "2.3.0", 5830 + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", 5831 + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", 5832 + "license": "MIT" 5833 + }, 5834 + "node_modules/rehype": { 5835 + "version": "13.0.2", 5836 + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", 5837 + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", 5838 + "license": "MIT", 5839 + "dependencies": { 5840 + "@types/hast": "^3.0.0", 5841 + "rehype-parse": "^9.0.0", 5842 + "rehype-stringify": "^10.0.0", 5843 + "unified": "^11.0.0" 5844 + }, 5845 + "funding": { 5846 + "type": "opencollective", 5847 + "url": "https://opencollective.com/unified" 5848 + } 5849 + }, 5850 + "node_modules/rehype-parse": { 5851 + "version": "9.0.1", 5852 + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", 5853 + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", 5854 + "license": "MIT", 5855 + "dependencies": { 5856 + "@types/hast": "^3.0.0", 5857 + "hast-util-from-html": "^2.0.0", 5858 + "unified": "^11.0.0" 5859 + }, 5860 + "funding": { 5861 + "type": "opencollective", 5862 + "url": "https://opencollective.com/unified" 5863 + } 5864 + }, 5865 + "node_modules/rehype-raw": { 5866 + "version": "7.0.0", 5867 + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", 5868 + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", 5869 + "license": "MIT", 5870 + "dependencies": { 5871 + "@types/hast": "^3.0.0", 5872 + "hast-util-raw": "^9.0.0", 5873 + "vfile": "^6.0.0" 5874 + }, 5875 + "funding": { 5876 + "type": "opencollective", 5877 + "url": "https://opencollective.com/unified" 5878 + } 5879 + }, 5880 + "node_modules/rehype-stringify": { 5881 + "version": "10.0.1", 5882 + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", 5883 + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", 5884 + "license": "MIT", 5885 + "dependencies": { 5886 + "@types/hast": "^3.0.0", 5887 + "hast-util-to-html": "^9.0.0", 5888 + "unified": "^11.0.0" 5889 + }, 5890 + "funding": { 5891 + "type": "opencollective", 5892 + "url": "https://opencollective.com/unified" 5893 + } 5894 + }, 5895 + "node_modules/remark-gfm": { 5896 + "version": "4.0.1", 5897 + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", 5898 + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", 5899 + "license": "MIT", 5900 + "dependencies": { 5901 + "@types/mdast": "^4.0.0", 5902 + "mdast-util-gfm": "^3.0.0", 5903 + "micromark-extension-gfm": "^3.0.0", 5904 + "remark-parse": "^11.0.0", 5905 + "remark-stringify": "^11.0.0", 5906 + "unified": "^11.0.0" 5907 + }, 5908 + "funding": { 5909 + "type": "opencollective", 5910 + "url": "https://opencollective.com/unified" 5911 + } 5912 + }, 5913 + "node_modules/remark-parse": { 5914 + "version": "11.0.0", 5915 + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", 5916 + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", 5917 + "license": "MIT", 5918 + "dependencies": { 5919 + "@types/mdast": "^4.0.0", 5920 + "mdast-util-from-markdown": "^2.0.0", 5921 + "micromark-util-types": "^2.0.0", 5922 + "unified": "^11.0.0" 5923 + }, 5924 + "funding": { 5925 + "type": "opencollective", 5926 + "url": "https://opencollective.com/unified" 5927 + } 5928 + }, 5929 + "node_modules/remark-rehype": { 5930 + "version": "11.1.2", 5931 + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", 5932 + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", 5933 + "license": "MIT", 5934 + "dependencies": { 5935 + "@types/hast": "^3.0.0", 5936 + "@types/mdast": "^4.0.0", 5937 + "mdast-util-to-hast": "^13.0.0", 5938 + "unified": "^11.0.0", 5939 + "vfile": "^6.0.0" 5940 + }, 5941 + "funding": { 5942 + "type": "opencollective", 5943 + "url": "https://opencollective.com/unified" 5944 + } 5945 + }, 5946 + "node_modules/remark-smartypants": { 5947 + "version": "3.0.2", 5948 + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", 5949 + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", 5950 + "license": "MIT", 5951 + "dependencies": { 5952 + "retext": "^9.0.0", 5953 + "retext-smartypants": "^6.0.0", 5954 + "unified": "^11.0.4", 5955 + "unist-util-visit": "^5.0.0" 5956 + }, 5957 + "engines": { 5958 + "node": ">=16.0.0" 5959 + } 5960 + }, 5961 + "node_modules/remark-stringify": { 5962 + "version": "11.0.0", 5963 + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", 5964 + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", 5965 + "license": "MIT", 5966 + "dependencies": { 5967 + "@types/mdast": "^4.0.0", 5968 + "mdast-util-to-markdown": "^2.0.0", 5969 + "unified": "^11.0.0" 5970 + }, 5971 + "funding": { 5972 + "type": "opencollective", 5973 + "url": "https://opencollective.com/unified" 5974 + } 5975 + }, 5976 + "node_modules/require-from-string": { 5977 + "version": "2.0.2", 5978 + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 5979 + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 5980 + "license": "MIT", 5981 + "engines": { 5982 + "node": ">=0.10.0" 5983 + } 5984 + }, 5985 + "node_modules/retext": { 5986 + "version": "9.0.0", 5987 + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", 5988 + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", 5989 + "license": "MIT", 5990 + "dependencies": { 5991 + "@types/nlcst": "^2.0.0", 5992 + "retext-latin": "^4.0.0", 5993 + "retext-stringify": "^4.0.0", 5994 + "unified": "^11.0.0" 5995 + }, 5996 + "funding": { 5997 + "type": "opencollective", 5998 + "url": "https://opencollective.com/unified" 5999 + } 6000 + }, 6001 + "node_modules/retext-latin": { 6002 + "version": "4.0.0", 6003 + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", 6004 + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", 6005 + "license": "MIT", 6006 + "dependencies": { 6007 + "@types/nlcst": "^2.0.0", 6008 + "parse-latin": "^7.0.0", 6009 + "unified": "^11.0.0" 6010 + }, 6011 + "funding": { 6012 + "type": "opencollective", 6013 + "url": "https://opencollective.com/unified" 6014 + } 6015 + }, 6016 + "node_modules/retext-smartypants": { 6017 + "version": "6.2.0", 6018 + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", 6019 + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", 6020 + "license": "MIT", 6021 + "dependencies": { 6022 + "@types/nlcst": "^2.0.0", 6023 + "nlcst-to-string": "^4.0.0", 6024 + "unist-util-visit": "^5.0.0" 6025 + }, 6026 + "funding": { 6027 + "type": "opencollective", 6028 + "url": "https://opencollective.com/unified" 6029 + } 6030 + }, 6031 + "node_modules/retext-stringify": { 6032 + "version": "4.0.0", 6033 + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", 6034 + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", 6035 + "license": "MIT", 6036 + "dependencies": { 6037 + "@types/nlcst": "^2.0.0", 6038 + "nlcst-to-string": "^4.0.0", 6039 + "unified": "^11.0.0" 6040 + }, 6041 + "funding": { 6042 + "type": "opencollective", 6043 + "url": "https://opencollective.com/unified" 6044 + } 6045 + }, 6046 + "node_modules/rollup": { 6047 + "version": "4.59.0", 6048 + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", 6049 + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", 6050 + "license": "MIT", 6051 + "dependencies": { 6052 + "@types/estree": "1.0.8" 6053 + }, 6054 + "bin": { 6055 + "rollup": "dist/bin/rollup" 6056 + }, 6057 + "engines": { 6058 + "node": ">=18.0.0", 6059 + "npm": ">=8.0.0" 6060 + }, 6061 + "optionalDependencies": { 6062 + "@rollup/rollup-android-arm-eabi": "4.59.0", 6063 + "@rollup/rollup-android-arm64": "4.59.0", 6064 + "@rollup/rollup-darwin-arm64": "4.59.0", 6065 + "@rollup/rollup-darwin-x64": "4.59.0", 6066 + "@rollup/rollup-freebsd-arm64": "4.59.0", 6067 + "@rollup/rollup-freebsd-x64": "4.59.0", 6068 + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", 6069 + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", 6070 + "@rollup/rollup-linux-arm64-gnu": "4.59.0", 6071 + "@rollup/rollup-linux-arm64-musl": "4.59.0", 6072 + "@rollup/rollup-linux-loong64-gnu": "4.59.0", 6073 + "@rollup/rollup-linux-loong64-musl": "4.59.0", 6074 + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", 6075 + "@rollup/rollup-linux-ppc64-musl": "4.59.0", 6076 + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", 6077 + "@rollup/rollup-linux-riscv64-musl": "4.59.0", 6078 + "@rollup/rollup-linux-s390x-gnu": "4.59.0", 6079 + "@rollup/rollup-linux-x64-gnu": "4.59.0", 6080 + "@rollup/rollup-linux-x64-musl": "4.59.0", 6081 + "@rollup/rollup-openbsd-x64": "4.59.0", 6082 + "@rollup/rollup-openharmony-arm64": "4.59.0", 6083 + "@rollup/rollup-win32-arm64-msvc": "4.59.0", 6084 + "@rollup/rollup-win32-ia32-msvc": "4.59.0", 6085 + "@rollup/rollup-win32-x64-gnu": "4.59.0", 6086 + "@rollup/rollup-win32-x64-msvc": "4.59.0", 6087 + "fsevents": "~2.3.2" 6088 + } 6089 + }, 6090 + "node_modules/sax": { 6091 + "version": "1.4.4", 6092 + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", 6093 + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", 6094 + "license": "BlueOak-1.0.0", 6095 + "engines": { 6096 + "node": ">=11.0.0" 6097 + } 6098 + }, 6099 + "node_modules/saxes": { 6100 + "version": "6.0.0", 6101 + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", 6102 + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", 6103 + "license": "ISC", 6104 + "dependencies": { 6105 + "xmlchars": "^2.2.0" 6106 + }, 6107 + "engines": { 6108 + "node": ">=v12.22.7" 6109 + } 6110 + }, 6111 + "node_modules/semver": { 6112 + "version": "7.7.4", 6113 + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", 6114 + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", 6115 + "license": "ISC", 6116 + "bin": { 6117 + "semver": "bin/semver.js" 6118 + }, 6119 + "engines": { 6120 + "node": ">=10" 6121 + } 6122 + }, 6123 + "node_modules/send": { 6124 + "version": "1.2.1", 6125 + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", 6126 + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", 6127 + "license": "MIT", 6128 + "dependencies": { 6129 + "debug": "^4.4.3", 6130 + "encodeurl": "^2.0.0", 6131 + "escape-html": "^1.0.3", 6132 + "etag": "^1.8.1", 6133 + "fresh": "^2.0.0", 6134 + "http-errors": "^2.0.1", 6135 + "mime-types": "^3.0.2", 6136 + "ms": "^2.1.3", 6137 + "on-finished": "^2.4.1", 6138 + "range-parser": "^1.2.1", 6139 + "statuses": "^2.0.2" 6140 + }, 6141 + "engines": { 6142 + "node": ">= 18" 6143 + }, 6144 + "funding": { 6145 + "type": "opencollective", 6146 + "url": "https://opencollective.com/express" 6147 + } 6148 + }, 6149 + "node_modules/server-destroy": { 6150 + "version": "1.0.1", 6151 + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", 6152 + "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==", 6153 + "license": "ISC" 6154 + }, 6155 + "node_modules/setprototypeof": { 6156 + "version": "1.2.0", 6157 + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 6158 + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 6159 + "license": "ISC" 6160 + }, 6161 + "node_modules/sharp": { 6162 + "version": "0.34.5", 6163 + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", 6164 + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", 6165 + "hasInstallScript": true, 6166 + "license": "Apache-2.0", 6167 + "optional": true, 6168 + "dependencies": { 6169 + "@img/colour": "^1.0.0", 6170 + "detect-libc": "^2.1.2", 6171 + "semver": "^7.7.3" 6172 + }, 6173 + "engines": { 6174 + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 6175 + }, 6176 + "funding": { 6177 + "url": "https://opencollective.com/libvips" 6178 + }, 6179 + "optionalDependencies": { 6180 + "@img/sharp-darwin-arm64": "0.34.5", 6181 + "@img/sharp-darwin-x64": "0.34.5", 6182 + "@img/sharp-libvips-darwin-arm64": "1.2.4", 6183 + "@img/sharp-libvips-darwin-x64": "1.2.4", 6184 + "@img/sharp-libvips-linux-arm": "1.2.4", 6185 + "@img/sharp-libvips-linux-arm64": "1.2.4", 6186 + "@img/sharp-libvips-linux-ppc64": "1.2.4", 6187 + "@img/sharp-libvips-linux-riscv64": "1.2.4", 6188 + "@img/sharp-libvips-linux-s390x": "1.2.4", 6189 + "@img/sharp-libvips-linux-x64": "1.2.4", 6190 + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", 6191 + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", 6192 + "@img/sharp-linux-arm": "0.34.5", 6193 + "@img/sharp-linux-arm64": "0.34.5", 6194 + "@img/sharp-linux-ppc64": "0.34.5", 6195 + "@img/sharp-linux-riscv64": "0.34.5", 6196 + "@img/sharp-linux-s390x": "0.34.5", 6197 + "@img/sharp-linux-x64": "0.34.5", 6198 + "@img/sharp-linuxmusl-arm64": "0.34.5", 6199 + "@img/sharp-linuxmusl-x64": "0.34.5", 6200 + "@img/sharp-wasm32": "0.34.5", 6201 + "@img/sharp-win32-arm64": "0.34.5", 6202 + "@img/sharp-win32-ia32": "0.34.5", 6203 + "@img/sharp-win32-x64": "0.34.5" 6204 + } 6205 + }, 6206 + "node_modules/shiki": { 6207 + "version": "3.23.0", 6208 + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", 6209 + "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", 6210 + "license": "MIT", 6211 + "dependencies": { 6212 + "@shikijs/core": "3.23.0", 6213 + "@shikijs/engine-javascript": "3.23.0", 6214 + "@shikijs/engine-oniguruma": "3.23.0", 6215 + "@shikijs/langs": "3.23.0", 6216 + "@shikijs/themes": "3.23.0", 6217 + "@shikijs/types": "3.23.0", 6218 + "@shikijs/vscode-textmate": "^10.0.2", 6219 + "@types/hast": "^3.0.4" 6220 + } 6221 + }, 6222 + "node_modules/siginfo": { 6223 + "version": "2.0.0", 6224 + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 6225 + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 6226 + "dev": true, 6227 + "license": "ISC" 6228 + }, 6229 + "node_modules/sisteransi": { 6230 + "version": "1.0.5", 6231 + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 6232 + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", 6233 + "license": "MIT" 6234 + }, 6235 + "node_modules/smol-toml": { 6236 + "version": "1.6.0", 6237 + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", 6238 + "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", 6239 + "license": "BSD-3-Clause", 6240 + "engines": { 6241 + "node": ">= 18" 6242 + }, 6243 + "funding": { 6244 + "url": "https://github.com/sponsors/cyyynthia" 6245 + } 6246 + }, 6247 + "node_modules/source-map-js": { 6248 + "version": "1.2.1", 6249 + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 6250 + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 6251 + "license": "BSD-3-Clause", 6252 + "engines": { 6253 + "node": ">=0.10.0" 6254 + } 6255 + }, 6256 + "node_modules/space-separated-tokens": { 6257 + "version": "2.0.2", 6258 + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", 6259 + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", 6260 + "license": "MIT", 6261 + "funding": { 6262 + "type": "github", 6263 + "url": "https://github.com/sponsors/wooorm" 6264 + } 6265 + }, 6266 + "node_modules/stackback": { 6267 + "version": "0.0.2", 6268 + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 6269 + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 6270 + "dev": true, 6271 + "license": "MIT" 6272 + }, 6273 + "node_modules/statuses": { 6274 + "version": "2.0.2", 6275 + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", 6276 + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", 6277 + "license": "MIT", 6278 + "engines": { 6279 + "node": ">= 0.8" 6280 + } 6281 + }, 6282 + "node_modules/std-env": { 6283 + "version": "3.10.0", 6284 + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", 6285 + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", 6286 + "dev": true, 6287 + "license": "MIT" 6288 + }, 6289 + "node_modules/string-width": { 6290 + "version": "7.2.0", 6291 + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", 6292 + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", 6293 + "license": "MIT", 6294 + "dependencies": { 6295 + "emoji-regex": "^10.3.0", 6296 + "get-east-asian-width": "^1.0.0", 6297 + "strip-ansi": "^7.1.0" 6298 + }, 6299 + "engines": { 6300 + "node": ">=18" 6301 + }, 6302 + "funding": { 6303 + "url": "https://github.com/sponsors/sindresorhus" 6304 + } 6305 + }, 6306 + "node_modules/stringify-entities": { 6307 + "version": "4.0.4", 6308 + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", 6309 + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", 6310 + "license": "MIT", 6311 + "dependencies": { 6312 + "character-entities-html4": "^2.0.0", 6313 + "character-entities-legacy": "^3.0.0" 6314 + }, 6315 + "funding": { 6316 + "type": "github", 6317 + "url": "https://github.com/sponsors/wooorm" 6318 + } 6319 + }, 6320 + "node_modules/strip-ansi": { 6321 + "version": "7.2.0", 6322 + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", 6323 + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", 6324 + "license": "MIT", 6325 + "dependencies": { 6326 + "ansi-regex": "^6.2.2" 6327 + }, 6328 + "engines": { 6329 + "node": ">=12" 6330 + }, 6331 + "funding": { 6332 + "url": "https://github.com/chalk/strip-ansi?sponsor=1" 6333 + } 6334 + }, 6335 + "node_modules/svgo": { 6336 + "version": "4.0.0", 6337 + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", 6338 + "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", 6339 + "license": "MIT", 6340 + "dependencies": { 6341 + "commander": "^11.1.0", 6342 + "css-select": "^5.1.0", 6343 + "css-tree": "^3.0.1", 6344 + "css-what": "^6.1.0", 6345 + "csso": "^5.0.5", 6346 + "picocolors": "^1.1.1", 6347 + "sax": "^1.4.1" 6348 + }, 6349 + "bin": { 6350 + "svgo": "bin/svgo.js" 6351 + }, 6352 + "engines": { 6353 + "node": ">=16" 6354 + }, 6355 + "funding": { 6356 + "type": "opencollective", 6357 + "url": "https://opencollective.com/svgo" 6358 + } 6359 + }, 6360 + "node_modules/symbol-tree": { 6361 + "version": "3.2.4", 6362 + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", 6363 + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", 6364 + "license": "MIT" 6365 + }, 6366 + "node_modules/tailwindcss": { 6367 + "version": "4.2.1", 6368 + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", 6369 + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", 6370 + "dev": true, 6371 + "license": "MIT" 6372 + }, 6373 + "node_modules/tapable": { 6374 + "version": "2.3.0", 6375 + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", 6376 + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", 6377 + "dev": true, 6378 + "license": "MIT", 6379 + "engines": { 6380 + "node": ">=6" 6381 + }, 6382 + "funding": { 6383 + "type": "opencollective", 6384 + "url": "https://opencollective.com/webpack" 6385 + } 6386 + }, 6387 + "node_modules/tiny-inflate": { 6388 + "version": "1.0.3", 6389 + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", 6390 + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", 6391 + "license": "MIT" 6392 + }, 6393 + "node_modules/tinybench": { 6394 + "version": "2.9.0", 6395 + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 6396 + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 6397 + "dev": true, 6398 + "license": "MIT" 6399 + }, 6400 + "node_modules/tinyexec": { 6401 + "version": "1.0.2", 6402 + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", 6403 + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", 6404 + "license": "MIT", 6405 + "engines": { 6406 + "node": ">=18" 6407 + } 6408 + }, 6409 + "node_modules/tinyglobby": { 6410 + "version": "0.2.15", 6411 + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", 6412 + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", 6413 + "license": "MIT", 6414 + "dependencies": { 6415 + "fdir": "^6.5.0", 6416 + "picomatch": "^4.0.3" 6417 + }, 6418 + "engines": { 6419 + "node": ">=12.0.0" 6420 + }, 6421 + "funding": { 6422 + "url": "https://github.com/sponsors/SuperchupuDev" 6423 + } 6424 + }, 6425 + "node_modules/tinyrainbow": { 6426 + "version": "3.0.3", 6427 + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", 6428 + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", 6429 + "dev": true, 6430 + "license": "MIT", 6431 + "engines": { 6432 + "node": ">=14.0.0" 6433 + } 6434 + }, 6435 + "node_modules/tldts": { 6436 + "version": "7.0.23", 6437 + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", 6438 + "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", 6439 + "license": "MIT", 6440 + "dependencies": { 6441 + "tldts-core": "^7.0.23" 6442 + }, 6443 + "bin": { 6444 + "tldts": "bin/cli.js" 6445 + } 6446 + }, 6447 + "node_modules/tldts-core": { 6448 + "version": "7.0.23", 6449 + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", 6450 + "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", 6451 + "license": "MIT" 6452 + }, 6453 + "node_modules/toidentifier": { 6454 + "version": "1.0.1", 6455 + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 6456 + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 6457 + "license": "MIT", 6458 + "engines": { 6459 + "node": ">=0.6" 6460 + } 6461 + }, 6462 + "node_modules/tough-cookie": { 6463 + "version": "6.0.0", 6464 + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", 6465 + "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", 6466 + "license": "BSD-3-Clause", 6467 + "dependencies": { 6468 + "tldts": "^7.0.5" 6469 + }, 6470 + "engines": { 6471 + "node": ">=16" 6472 + } 6473 + }, 6474 + "node_modules/tr46": { 6475 + "version": "6.0.0", 6476 + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", 6477 + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", 6478 + "license": "MIT", 6479 + "dependencies": { 6480 + "punycode": "^2.3.1" 6481 + }, 6482 + "engines": { 6483 + "node": ">=20" 6484 + } 6485 + }, 6486 + "node_modules/trim-lines": { 6487 + "version": "3.0.1", 6488 + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", 6489 + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", 6490 + "license": "MIT", 6491 + "funding": { 6492 + "type": "github", 6493 + "url": "https://github.com/sponsors/wooorm" 6494 + } 6495 + }, 6496 + "node_modules/trough": { 6497 + "version": "2.2.0", 6498 + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", 6499 + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", 6500 + "license": "MIT", 6501 + "funding": { 6502 + "type": "github", 6503 + "url": "https://github.com/sponsors/wooorm" 6504 + } 6505 + }, 6506 + "node_modules/tsconfck": { 6507 + "version": "3.1.6", 6508 + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", 6509 + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", 6510 + "license": "MIT", 6511 + "bin": { 6512 + "tsconfck": "bin/tsconfck.js" 6513 + }, 6514 + "engines": { 6515 + "node": "^18 || >=20" 6516 + }, 6517 + "peerDependencies": { 6518 + "typescript": "^5.0.0" 6519 + }, 6520 + "peerDependenciesMeta": { 6521 + "typescript": { 6522 + "optional": true 6523 + } 6524 + } 6525 + }, 6526 + "node_modules/tslib": { 6527 + "version": "2.8.1", 6528 + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", 6529 + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", 6530 + "license": "0BSD", 6531 + "optional": true 6532 + }, 6533 + "node_modules/type-fest": { 6534 + "version": "4.41.0", 6535 + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", 6536 + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", 6537 + "license": "(MIT OR CC0-1.0)", 6538 + "engines": { 6539 + "node": ">=16" 6540 + }, 6541 + "funding": { 6542 + "url": "https://github.com/sponsors/sindresorhus" 6543 + } 6544 + }, 6545 + "node_modules/typescript": { 6546 + "version": "5.9.3", 6547 + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", 6548 + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", 6549 + "license": "Apache-2.0", 6550 + "peer": true, 6551 + "bin": { 6552 + "tsc": "bin/tsc", 6553 + "tsserver": "bin/tsserver" 6554 + }, 6555 + "engines": { 6556 + "node": ">=14.17" 6557 + } 6558 + }, 6559 + "node_modules/ufo": { 6560 + "version": "1.6.3", 6561 + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", 6562 + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", 6563 + "license": "MIT" 6564 + }, 6565 + "node_modules/ultrahtml": { 6566 + "version": "1.6.0", 6567 + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", 6568 + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", 6569 + "license": "MIT" 6570 + }, 6571 + "node_modules/uncrypto": { 6572 + "version": "0.1.3", 6573 + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", 6574 + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", 6575 + "license": "MIT" 6576 + }, 6577 + "node_modules/undici": { 6578 + "version": "7.22.0", 6579 + "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", 6580 + "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", 6581 + "license": "MIT", 6582 + "engines": { 6583 + "node": ">=20.18.1" 6584 + } 6585 + }, 6586 + "node_modules/unified": { 6587 + "version": "11.0.5", 6588 + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", 6589 + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", 6590 + "license": "MIT", 6591 + "dependencies": { 6592 + "@types/unist": "^3.0.0", 6593 + "bail": "^2.0.0", 6594 + "devlop": "^1.0.0", 6595 + "extend": "^3.0.0", 6596 + "is-plain-obj": "^4.0.0", 6597 + "trough": "^2.0.0", 6598 + "vfile": "^6.0.0" 6599 + }, 6600 + "funding": { 6601 + "type": "opencollective", 6602 + "url": "https://opencollective.com/unified" 6603 + } 6604 + }, 6605 + "node_modules/unifont": { 6606 + "version": "0.7.4", 6607 + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", 6608 + "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", 6609 + "license": "MIT", 6610 + "dependencies": { 6611 + "css-tree": "^3.1.0", 6612 + "ofetch": "^1.5.1", 6613 + "ohash": "^2.0.11" 6614 + } 6615 + }, 6616 + "node_modules/unist-util-find-after": { 6617 + "version": "5.0.0", 6618 + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", 6619 + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", 6620 + "license": "MIT", 6621 + "dependencies": { 6622 + "@types/unist": "^3.0.0", 6623 + "unist-util-is": "^6.0.0" 6624 + }, 6625 + "funding": { 6626 + "type": "opencollective", 6627 + "url": "https://opencollective.com/unified" 6628 + } 6629 + }, 6630 + "node_modules/unist-util-is": { 6631 + "version": "6.0.1", 6632 + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", 6633 + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", 6634 + "license": "MIT", 6635 + "dependencies": { 6636 + "@types/unist": "^3.0.0" 6637 + }, 6638 + "funding": { 6639 + "type": "opencollective", 6640 + "url": "https://opencollective.com/unified" 6641 + } 6642 + }, 6643 + "node_modules/unist-util-modify-children": { 6644 + "version": "4.0.0", 6645 + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", 6646 + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", 6647 + "license": "MIT", 6648 + "dependencies": { 6649 + "@types/unist": "^3.0.0", 6650 + "array-iterate": "^2.0.0" 6651 + }, 6652 + "funding": { 6653 + "type": "opencollective", 6654 + "url": "https://opencollective.com/unified" 6655 + } 6656 + }, 6657 + "node_modules/unist-util-position": { 6658 + "version": "5.0.0", 6659 + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", 6660 + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", 6661 + "license": "MIT", 6662 + "dependencies": { 6663 + "@types/unist": "^3.0.0" 6664 + }, 6665 + "funding": { 6666 + "type": "opencollective", 6667 + "url": "https://opencollective.com/unified" 6668 + } 6669 + }, 6670 + "node_modules/unist-util-remove-position": { 6671 + "version": "5.0.0", 6672 + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", 6673 + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", 6674 + "license": "MIT", 6675 + "dependencies": { 6676 + "@types/unist": "^3.0.0", 6677 + "unist-util-visit": "^5.0.0" 6678 + }, 6679 + "funding": { 6680 + "type": "opencollective", 6681 + "url": "https://opencollective.com/unified" 6682 + } 6683 + }, 6684 + "node_modules/unist-util-stringify-position": { 6685 + "version": "4.0.0", 6686 + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", 6687 + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", 6688 + "license": "MIT", 6689 + "dependencies": { 6690 + "@types/unist": "^3.0.0" 6691 + }, 6692 + "funding": { 6693 + "type": "opencollective", 6694 + "url": "https://opencollective.com/unified" 6695 + } 6696 + }, 6697 + "node_modules/unist-util-visit": { 6698 + "version": "5.1.0", 6699 + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", 6700 + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", 6701 + "license": "MIT", 6702 + "dependencies": { 6703 + "@types/unist": "^3.0.0", 6704 + "unist-util-is": "^6.0.0", 6705 + "unist-util-visit-parents": "^6.0.0" 6706 + }, 6707 + "funding": { 6708 + "type": "opencollective", 6709 + "url": "https://opencollective.com/unified" 6710 + } 6711 + }, 6712 + "node_modules/unist-util-visit-children": { 6713 + "version": "3.0.0", 6714 + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", 6715 + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", 6716 + "license": "MIT", 6717 + "dependencies": { 6718 + "@types/unist": "^3.0.0" 6719 + }, 6720 + "funding": { 6721 + "type": "opencollective", 6722 + "url": "https://opencollective.com/unified" 6723 + } 6724 + }, 6725 + "node_modules/unist-util-visit-parents": { 6726 + "version": "6.0.2", 6727 + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", 6728 + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", 6729 + "license": "MIT", 6730 + "dependencies": { 6731 + "@types/unist": "^3.0.0", 6732 + "unist-util-is": "^6.0.0" 6733 + }, 6734 + "funding": { 6735 + "type": "opencollective", 6736 + "url": "https://opencollective.com/unified" 6737 + } 6738 + }, 6739 + "node_modules/unstorage": { 6740 + "version": "1.17.4", 6741 + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz", 6742 + "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==", 6743 + "license": "MIT", 6744 + "dependencies": { 6745 + "anymatch": "^3.1.3", 6746 + "chokidar": "^5.0.0", 6747 + "destr": "^2.0.5", 6748 + "h3": "^1.15.5", 6749 + "lru-cache": "^11.2.0", 6750 + "node-fetch-native": "^1.6.7", 6751 + "ofetch": "^1.5.1", 6752 + "ufo": "^1.6.3" 6753 + }, 6754 + "peerDependencies": { 6755 + "@azure/app-configuration": "^1.8.0", 6756 + "@azure/cosmos": "^4.2.0", 6757 + "@azure/data-tables": "^13.3.0", 6758 + "@azure/identity": "^4.6.0", 6759 + "@azure/keyvault-secrets": "^4.9.0", 6760 + "@azure/storage-blob": "^12.26.0", 6761 + "@capacitor/preferences": "^6 || ^7 || ^8", 6762 + "@deno/kv": ">=0.9.0", 6763 + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", 6764 + "@planetscale/database": "^1.19.0", 6765 + "@upstash/redis": "^1.34.3", 6766 + "@vercel/blob": ">=0.27.1", 6767 + "@vercel/functions": "^2.2.12 || ^3.0.0", 6768 + "@vercel/kv": "^1 || ^2 || ^3", 6769 + "aws4fetch": "^1.0.20", 6770 + "db0": ">=0.2.1", 6771 + "idb-keyval": "^6.2.1", 6772 + "ioredis": "^5.4.2", 6773 + "uploadthing": "^7.4.4" 6774 + }, 6775 + "peerDependenciesMeta": { 6776 + "@azure/app-configuration": { 6777 + "optional": true 6778 + }, 6779 + "@azure/cosmos": { 6780 + "optional": true 6781 + }, 6782 + "@azure/data-tables": { 6783 + "optional": true 6784 + }, 6785 + "@azure/identity": { 6786 + "optional": true 6787 + }, 6788 + "@azure/keyvault-secrets": { 6789 + "optional": true 6790 + }, 6791 + "@azure/storage-blob": { 6792 + "optional": true 6793 + }, 6794 + "@capacitor/preferences": { 6795 + "optional": true 6796 + }, 6797 + "@deno/kv": { 6798 + "optional": true 6799 + }, 6800 + "@netlify/blobs": { 6801 + "optional": true 6802 + }, 6803 + "@planetscale/database": { 6804 + "optional": true 6805 + }, 6806 + "@upstash/redis": { 6807 + "optional": true 6808 + }, 6809 + "@vercel/blob": { 6810 + "optional": true 6811 + }, 6812 + "@vercel/functions": { 6813 + "optional": true 6814 + }, 6815 + "@vercel/kv": { 6816 + "optional": true 6817 + }, 6818 + "aws4fetch": { 6819 + "optional": true 6820 + }, 6821 + "db0": { 6822 + "optional": true 6823 + }, 6824 + "idb-keyval": { 6825 + "optional": true 6826 + }, 6827 + "ioredis": { 6828 + "optional": true 6829 + }, 6830 + "uploadthing": { 6831 + "optional": true 6832 + } 6833 + } 6834 + }, 6835 + "node_modules/vfile": { 6836 + "version": "6.0.3", 6837 + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", 6838 + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", 6839 + "license": "MIT", 6840 + "dependencies": { 6841 + "@types/unist": "^3.0.0", 6842 + "vfile-message": "^4.0.0" 6843 + }, 6844 + "funding": { 6845 + "type": "opencollective", 6846 + "url": "https://opencollective.com/unified" 6847 + } 6848 + }, 6849 + "node_modules/vfile-location": { 6850 + "version": "5.0.3", 6851 + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", 6852 + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", 6853 + "license": "MIT", 6854 + "dependencies": { 6855 + "@types/unist": "^3.0.0", 6856 + "vfile": "^6.0.0" 6857 + }, 6858 + "funding": { 6859 + "type": "opencollective", 6860 + "url": "https://opencollective.com/unified" 6861 + } 6862 + }, 6863 + "node_modules/vfile-message": { 6864 + "version": "4.0.3", 6865 + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", 6866 + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", 6867 + "license": "MIT", 6868 + "dependencies": { 6869 + "@types/unist": "^3.0.0", 6870 + "unist-util-stringify-position": "^4.0.0" 6871 + }, 6872 + "funding": { 6873 + "type": "opencollective", 6874 + "url": "https://opencollective.com/unified" 6875 + } 6876 + }, 6877 + "node_modules/vite": { 6878 + "version": "7.3.1", 6879 + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", 6880 + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", 6881 + "devOptional": true, 6882 + "license": "MIT", 6883 + "dependencies": { 6884 + "esbuild": "^0.27.0", 6885 + "fdir": "^6.5.0", 6886 + "picomatch": "^4.0.3", 6887 + "postcss": "^8.5.6", 6888 + "rollup": "^4.43.0", 6889 + "tinyglobby": "^0.2.15" 6890 + }, 6891 + "bin": { 6892 + "vite": "bin/vite.js" 6893 + }, 6894 + "engines": { 6895 + "node": "^20.19.0 || >=22.12.0" 6896 + }, 6897 + "funding": { 6898 + "url": "https://github.com/vitejs/vite?sponsor=1" 6899 + }, 6900 + "optionalDependencies": { 6901 + "fsevents": "~2.3.3" 6902 + }, 6903 + "peerDependencies": { 6904 + "@types/node": "^20.19.0 || >=22.12.0", 6905 + "jiti": ">=1.21.0", 6906 + "less": "^4.0.0", 6907 + "lightningcss": "^1.21.0", 6908 + "sass": "^1.70.0", 6909 + "sass-embedded": "^1.70.0", 6910 + "stylus": ">=0.54.8", 6911 + "sugarss": "^5.0.0", 6912 + "terser": "^5.16.0", 6913 + "tsx": "^4.8.1", 6914 + "yaml": "^2.4.2" 6915 + }, 6916 + "peerDependenciesMeta": { 6917 + "@types/node": { 6918 + "optional": true 6919 + }, 6920 + "jiti": { 6921 + "optional": true 6922 + }, 6923 + "less": { 6924 + "optional": true 6925 + }, 6926 + "lightningcss": { 6927 + "optional": true 6928 + }, 6929 + "sass": { 6930 + "optional": true 6931 + }, 6932 + "sass-embedded": { 6933 + "optional": true 6934 + }, 6935 + "stylus": { 6936 + "optional": true 6937 + }, 6938 + "sugarss": { 6939 + "optional": true 6940 + }, 6941 + "terser": { 6942 + "optional": true 6943 + }, 6944 + "tsx": { 6945 + "optional": true 6946 + }, 6947 + "yaml": { 6948 + "optional": true 6949 + } 6950 + } 6951 + }, 6952 + "node_modules/vitefu": { 6953 + "version": "1.1.2", 6954 + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz", 6955 + "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==", 6956 + "license": "MIT", 6957 + "workspaces": [ 6958 + "tests/deps/*", 6959 + "tests/projects/*", 6960 + "tests/projects/workspace/packages/*" 6961 + ], 6962 + "peerDependencies": { 6963 + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" 6964 + }, 6965 + "peerDependenciesMeta": { 6966 + "vite": { 6967 + "optional": true 6968 + } 6969 + } 6970 + }, 6971 + "node_modules/vitest": { 6972 + "version": "4.0.18", 6973 + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", 6974 + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", 6975 + "dev": true, 6976 + "license": "MIT", 6977 + "dependencies": { 6978 + "@vitest/expect": "4.0.18", 6979 + "@vitest/mocker": "4.0.18", 6980 + "@vitest/pretty-format": "4.0.18", 6981 + "@vitest/runner": "4.0.18", 6982 + "@vitest/snapshot": "4.0.18", 6983 + "@vitest/spy": "4.0.18", 6984 + "@vitest/utils": "4.0.18", 6985 + "es-module-lexer": "^1.7.0", 6986 + "expect-type": "^1.2.2", 6987 + "magic-string": "^0.30.21", 6988 + "obug": "^2.1.1", 6989 + "pathe": "^2.0.3", 6990 + "picomatch": "^4.0.3", 6991 + "std-env": "^3.10.0", 6992 + "tinybench": "^2.9.0", 6993 + "tinyexec": "^1.0.2", 6994 + "tinyglobby": "^0.2.15", 6995 + "tinyrainbow": "^3.0.3", 6996 + "vite": "^6.0.0 || ^7.0.0", 6997 + "why-is-node-running": "^2.3.0" 6998 + }, 6999 + "bin": { 7000 + "vitest": "vitest.mjs" 7001 + }, 7002 + "engines": { 7003 + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" 7004 + }, 7005 + "funding": { 7006 + "url": "https://opencollective.com/vitest" 7007 + }, 7008 + "peerDependencies": { 7009 + "@edge-runtime/vm": "*", 7010 + "@opentelemetry/api": "^1.9.0", 7011 + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", 7012 + "@vitest/browser-playwright": "4.0.18", 7013 + "@vitest/browser-preview": "4.0.18", 7014 + "@vitest/browser-webdriverio": "4.0.18", 7015 + "@vitest/ui": "4.0.18", 7016 + "happy-dom": "*", 7017 + "jsdom": "*" 7018 + }, 7019 + "peerDependenciesMeta": { 7020 + "@edge-runtime/vm": { 7021 + "optional": true 7022 + }, 7023 + "@opentelemetry/api": { 7024 + "optional": true 7025 + }, 7026 + "@types/node": { 7027 + "optional": true 7028 + }, 7029 + "@vitest/browser-playwright": { 7030 + "optional": true 7031 + }, 7032 + "@vitest/browser-preview": { 7033 + "optional": true 7034 + }, 7035 + "@vitest/browser-webdriverio": { 7036 + "optional": true 7037 + }, 7038 + "@vitest/ui": { 7039 + "optional": true 7040 + }, 7041 + "happy-dom": { 7042 + "optional": true 7043 + }, 7044 + "jsdom": { 7045 + "optional": true 7046 + } 7047 + } 7048 + }, 7049 + "node_modules/w3c-xmlserializer": { 7050 + "version": "5.0.0", 7051 + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", 7052 + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", 7053 + "license": "MIT", 7054 + "dependencies": { 7055 + "xml-name-validator": "^5.0.0" 7056 + }, 7057 + "engines": { 7058 + "node": ">=18" 7059 + } 7060 + }, 7061 + "node_modules/web-namespaces": { 7062 + "version": "2.0.1", 7063 + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", 7064 + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", 7065 + "license": "MIT", 7066 + "funding": { 7067 + "type": "github", 7068 + "url": "https://github.com/sponsors/wooorm" 7069 + } 7070 + }, 7071 + "node_modules/webidl-conversions": { 7072 + "version": "8.0.1", 7073 + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", 7074 + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", 7075 + "license": "BSD-2-Clause", 7076 + "engines": { 7077 + "node": ">=20" 7078 + } 7079 + }, 7080 + "node_modules/whatwg-mimetype": { 7081 + "version": "5.0.0", 7082 + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", 7083 + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", 7084 + "license": "MIT", 7085 + "engines": { 7086 + "node": ">=20" 7087 + } 7088 + }, 7089 + "node_modules/whatwg-url": { 7090 + "version": "16.0.1", 7091 + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", 7092 + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", 7093 + "license": "MIT", 7094 + "dependencies": { 7095 + "@exodus/bytes": "^1.11.0", 7096 + "tr46": "^6.0.0", 7097 + "webidl-conversions": "^8.0.1" 7098 + }, 7099 + "engines": { 7100 + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" 7101 + } 7102 + }, 7103 + "node_modules/which-pm-runs": { 7104 + "version": "1.1.0", 7105 + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", 7106 + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", 7107 + "license": "MIT", 7108 + "engines": { 7109 + "node": ">=4" 7110 + } 7111 + }, 7112 + "node_modules/why-is-node-running": { 7113 + "version": "2.3.0", 7114 + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 7115 + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 7116 + "dev": true, 7117 + "license": "MIT", 7118 + "dependencies": { 7119 + "siginfo": "^2.0.0", 7120 + "stackback": "0.0.2" 7121 + }, 7122 + "bin": { 7123 + "why-is-node-running": "cli.js" 7124 + }, 7125 + "engines": { 7126 + "node": ">=8" 7127 + } 7128 + }, 7129 + "node_modules/widest-line": { 7130 + "version": "5.0.0", 7131 + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", 7132 + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", 7133 + "license": "MIT", 7134 + "dependencies": { 7135 + "string-width": "^7.0.0" 7136 + }, 7137 + "engines": { 7138 + "node": ">=18" 7139 + }, 7140 + "funding": { 7141 + "url": "https://github.com/sponsors/sindresorhus" 7142 + } 7143 + }, 7144 + "node_modules/wrap-ansi": { 7145 + "version": "9.0.2", 7146 + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", 7147 + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", 7148 + "license": "MIT", 7149 + "dependencies": { 7150 + "ansi-styles": "^6.2.1", 7151 + "string-width": "^7.0.0", 7152 + "strip-ansi": "^7.1.0" 7153 + }, 7154 + "engines": { 7155 + "node": ">=18" 7156 + }, 7157 + "funding": { 7158 + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 7159 + } 7160 + }, 7161 + "node_modules/xml-name-validator": { 7162 + "version": "5.0.0", 7163 + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", 7164 + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", 7165 + "license": "Apache-2.0", 7166 + "engines": { 7167 + "node": ">=18" 7168 + } 7169 + }, 7170 + "node_modules/xmlchars": { 7171 + "version": "2.2.0", 7172 + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", 7173 + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", 7174 + "license": "MIT" 7175 + }, 7176 + "node_modules/xxhash-wasm": { 7177 + "version": "1.1.0", 7178 + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", 7179 + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", 7180 + "license": "MIT" 7181 + }, 7182 + "node_modules/yargs-parser": { 7183 + "version": "21.1.1", 7184 + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 7185 + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 7186 + "license": "ISC", 7187 + "engines": { 7188 + "node": ">=12" 7189 + } 7190 + }, 7191 + "node_modules/yocto-queue": { 7192 + "version": "1.2.2", 7193 + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", 7194 + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", 7195 + "license": "MIT", 7196 + "engines": { 7197 + "node": ">=12.20" 7198 + }, 7199 + "funding": { 7200 + "url": "https://github.com/sponsors/sindresorhus" 7201 + } 7202 + }, 7203 + "node_modules/yocto-spinner": { 7204 + "version": "0.2.3", 7205 + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", 7206 + "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", 7207 + "license": "MIT", 7208 + "dependencies": { 7209 + "yoctocolors": "^2.1.1" 7210 + }, 7211 + "engines": { 7212 + "node": ">=18.19" 7213 + }, 7214 + "funding": { 7215 + "url": "https://github.com/sponsors/sindresorhus" 7216 + } 7217 + }, 7218 + "node_modules/yoctocolors": { 7219 + "version": "2.1.2", 7220 + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", 7221 + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", 7222 + "license": "MIT", 7223 + "engines": { 7224 + "node": ">=18" 7225 + }, 7226 + "funding": { 7227 + "url": "https://github.com/sponsors/sindresorhus" 7228 + } 7229 + }, 7230 + "node_modules/zod": { 7231 + "version": "3.25.76", 7232 + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", 7233 + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", 7234 + "license": "MIT", 7235 + "funding": { 7236 + "url": "https://github.com/sponsors/colinhacks" 7237 + } 7238 + }, 7239 + "node_modules/zod-to-json-schema": { 7240 + "version": "3.25.1", 7241 + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", 7242 + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", 7243 + "license": "ISC", 7244 + "peerDependencies": { 7245 + "zod": "^3.25 || ^4" 7246 + } 7247 + }, 7248 + "node_modules/zod-to-ts": { 7249 + "version": "1.2.0", 7250 + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", 7251 + "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", 7252 + "peerDependencies": { 7253 + "typescript": "^4.9.4 || ^5.0.2", 7254 + "zod": "^3" 7255 + } 7256 + }, 7257 + "node_modules/zwitch": { 7258 + "version": "2.0.4", 7259 + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", 7260 + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", 7261 + "license": "MIT", 7262 + "funding": { 7263 + "type": "github", 7264 + "url": "https://github.com/sponsors/wooorm" 7265 + } 7266 + } 7267 + } 7268 + }
+27
package.json
··· 1 + { 2 + "name": "arcnode-blog", 3 + "type": "module", 4 + "version": "1.0.0", 5 + "private": true, 6 + "scripts": { 7 + "dev": "astro dev", 8 + "build": "astro build", 9 + "preview": "astro preview", 10 + "start": "node dist/server/entry.mjs", 11 + "test": "vitest run", 12 + "test:watch": "vitest", 13 + "test:e2e": "playwright test" 14 + }, 15 + "dependencies": { 16 + "@astrojs/node": "^9.1.0", 17 + "astro": "^5.7.0", 18 + "isomorphic-dompurify": "^3.0.0", 19 + "marked": "^17.0.0" 20 + }, 21 + "devDependencies": { 22 + "@playwright/test": "^1.58.2", 23 + "@tailwindcss/vite": "^4.1.0", 24 + "tailwindcss": "^4.1.0", 25 + "vitest": "^4.0.18" 26 + } 27 + }
+18
playwright.config.ts
··· 1 + import { defineConfig } from "@playwright/test"; 2 + 3 + export default defineConfig({ 4 + testDir: "tests/e2e", 5 + timeout: 30_000, 6 + use: { 7 + baseURL: "https://blog.arcnode.xyz", 8 + extraHTTPHeaders: { 9 + // No auth headers needed for public pages 10 + }, 11 + }, 12 + projects: [ 13 + { 14 + name: "chromium", 15 + use: { browserName: "chromium" }, 16 + }, 17 + ], 18 + });
+70
src/layouts/Base.astro
··· 1 + --- 2 + import "../styles/global.css"; 3 + import { BLOG_URL, HANDLE } from "../lib/constants"; 4 + 5 + interface Props { 6 + title: string; 7 + description?: string; 8 + wide?: boolean; 9 + } 10 + 11 + const { title, description = "Writing by bkb", wide = false } = Astro.props; 12 + const canonicalUrl = new URL(Astro.url.pathname, BLOG_URL); 13 + --- 14 + 15 + <!doctype html> 16 + <html lang="en"> 17 + <head> 18 + <meta charset="UTF-8" /> 19 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 20 + <meta name="description" content={description} /> 21 + <meta name="theme-color" content="#d9ccb4" /> 22 + <link rel="canonical" href={canonicalUrl.toString()} /> 23 + <link rel="alternate" type="application/rss+xml" title="bkb — writing" href="/rss.xml" /> 24 + <meta property="og:title" content={title} /> 25 + <meta property="og:description" content={description} /> 26 + <meta property="og:type" content="article" /> 27 + <meta property="og:url" content={canonicalUrl.toString()} /> 28 + <title>{title}</title> 29 + </head> 30 + <body class="bg-paper text-ink min-h-screen"> 31 + <header class="border-b border-border"> 32 + <nav class="max-w-2xl mx-auto px-4 sm:px-6 py-4 sm:py-5 flex items-center justify-between"> 33 + <a href="/" class="font-serif text-xl font-bold tracking-tight text-ink-bright hover:text-accent transition-colors"> 34 + bkb 35 + </a> 36 + <div class="flex items-center gap-4 sm:gap-5 text-sm text-muted"> 37 + <a href="/write" class="hover:text-accent transition-colors">write</a> 38 + <a 39 + href={`https://bsky.app/profile/${HANDLE}`} 40 + target="_blank" 41 + rel="noopener" 42 + class="hover:text-ink transition-colors" 43 + > 44 + bluesky 45 + </a> 46 + <a 47 + href="/rss.xml" 48 + class="hover:text-ink transition-colors" 49 + > 50 + rss 51 + </a> 52 + </div> 53 + </nav> 54 + </header> 55 + 56 + <main class={`mx-auto px-4 sm:px-6 py-8 sm:py-12 ${wide ? 'max-w-6xl' : 'max-w-2xl'}`}> 57 + <slot /> 58 + </main> 59 + 60 + <footer class="border-t border-border mt-16"> 61 + <div class="max-w-2xl mx-auto px-4 sm:px-6 py-8 text-center text-sm text-muted"> 62 + <p> 63 + powered by <a href="https://atproto.com" target="_blank" rel="noopener" class="text-accent/70 hover:text-accent transition-colors">AT Protocol</a> 64 + <span class="text-border-light mx-2">&middot;</span> 65 + served from <a href="https://arcnode.xyz" class="text-accent/70 hover:text-accent transition-colors">arcnode.xyz</a> 66 + </p> 67 + </div> 68 + </footer> 69 + </body> 70 + </html>
+63
src/lib/api.ts
··· 1 + import type { AstroCookies } from "astro"; 2 + import { isOwner } from "./auth"; 3 + import { BLOG_URL, PDS_URL, DID } from "./constants"; 4 + 5 + export function checkOrigin(request: Request): Response | null { 6 + const origin = request.headers.get("origin"); 7 + if (origin && origin !== BLOG_URL) { 8 + return new Response(JSON.stringify({ error: "Forbidden" }), { status: 403 }); 9 + } 10 + return null; 11 + } 12 + 13 + export function checkAuth(cookies: AstroCookies): Response | null { 14 + const sessionDid = cookies.get("session_did")?.value; 15 + if (!sessionDid || !isOwner(sessionDid)) { 16 + return new Response(JSON.stringify({ error: "Not authorized" }), { status: 403 }); 17 + } 18 + return null; 19 + } 20 + 21 + export async function parseJsonBody( 22 + request: Request 23 + ): Promise<[Record<string, unknown>, null] | [null, Response]> { 24 + try { 25 + const body = await request.json(); 26 + return [body as Record<string, unknown>, null]; 27 + } catch { 28 + return [ 29 + null, 30 + new Response(JSON.stringify({ error: "Invalid JSON body" }), { status: 400 }), 31 + ]; 32 + } 33 + } 34 + 35 + export async function createPdsSession(): Promise<[string, null] | [null, Response]> { 36 + const pdsPassword = process.env.PDS_APP_PASSWORD; 37 + if (!pdsPassword) { 38 + return [ 39 + null, 40 + new Response(JSON.stringify({ error: "PDS credentials not configured" }), { status: 500 }), 41 + ]; 42 + } 43 + 44 + const sessionRes = await fetch( 45 + `${PDS_URL}/xrpc/com.atproto.server.createSession`, 46 + { 47 + method: "POST", 48 + headers: { "Content-Type": "application/json" }, 49 + body: JSON.stringify({ identifier: DID, password: pdsPassword }), 50 + } 51 + ); 52 + 53 + if (!sessionRes.ok) { 54 + console.error("PDS createSession failed:", sessionRes.status); 55 + return [ 56 + null, 57 + new Response(JSON.stringify({ error: "PDS auth failed" }), { status: 500 }), 58 + ]; 59 + } 60 + 61 + const session = (await sessionRes.json()) as { accessJwt: string }; 62 + return [session.accessJwt, null]; 63 + }
+51
src/lib/auth.ts
··· 1 + import { DID, BLOG_URL } from "./constants"; 2 + 3 + const GATEWAY_URL = 4 + process.env.ATAUTH_GATEWAY_URL || "https://apricot.workingtitle.zip"; 5 + const ATAUTH_PUBLIC_URL = 6 + process.env.ATAUTH_PUBLIC_URL || "https://apricot.workingtitle.zip"; 7 + 8 + export interface ProxyUser { 9 + did: string; 10 + handle: string; 11 + } 12 + 13 + export function getLoginUrl(): string { 14 + return `${ATAUTH_PUBLIC_URL}/auth/proxy/login?rd=${encodeURIComponent(`${BLOG_URL}/write`)}`; 15 + } 16 + 17 + export async function verifyProxyTicket( 18 + ticket: string 19 + ): Promise<ProxyUser | null> { 20 + try { 21 + const verifyUrl = `${GATEWAY_URL}/auth/verify`; 22 + const originalUrl = `${BLOG_URL}/write?_atauth_ticket=${encodeURIComponent(ticket)}`; 23 + 24 + const res = await fetch(verifyUrl, { 25 + headers: { 26 + "X-Original-URL": originalUrl, 27 + "X-Forwarded-Proto": "https", 28 + "X-Forwarded-Host": new URL(BLOG_URL).host, 29 + }, 30 + }); 31 + 32 + if (res.status !== 200) return null; 33 + 34 + const did = res.headers.get("x-auth-did"); 35 + const handle = res.headers.get("x-auth-handle"); 36 + if (!did || !handle) return null; 37 + 38 + // Validate handle format (alphanumeric, dots, hyphens) 39 + if (!/^[a-zA-Z0-9.-]+$/.test(handle)) return null; 40 + 41 + return { did, handle }; 42 + } catch { 43 + return null; 44 + } 45 + } 46 + 47 + export function isOwner(did: string): boolean { 48 + return did === DID; 49 + } 50 + 51 + export { GATEWAY_URL, ATAUTH_PUBLIC_URL };
+5
src/lib/constants.ts
··· 1 + export const BLOG_URL = "https://blog.arcnode.xyz"; 2 + export const PDS_URL = "https://arcnode.xyz"; 3 + export const DID = "did:plc:k23ujfuppr3hr4pxvtaz7jro"; 4 + export const HANDLE = "bkb.arcnode.xyz"; 5 + export const BLOG_COLLECTION = "com.whtwnd.blog.entry";
+345
src/lib/pds.ts
··· 1 + import { PDS_URL, DID, HANDLE, BLOG_COLLECTION } from "./constants"; 2 + 3 + const RKEY_REGEX = /^[a-zA-Z0-9._~-]{1,512}$/; 4 + 5 + export function isValidRkey(rkey: string): boolean { 6 + return RKEY_REGEX.test(rkey); 7 + } 8 + 9 + export interface AtBlob { 10 + $type: "blob"; 11 + ref: { $link: string }; 12 + mimeType: string; 13 + size: number; 14 + } 15 + 16 + export interface BlogEntry { 17 + uri: string; 18 + cid: string; 19 + rkey: string; 20 + title: string; 21 + content: string; 22 + createdAt: string; 23 + visibility: string; 24 + theme?: string; 25 + blobs?: AtBlob[]; 26 + } 27 + 28 + export interface AuthorProfile { 29 + displayName: string; 30 + description: string; 31 + avatarUrl: string | null; 32 + bannerUrl: string | null; 33 + } 34 + 35 + interface ListRecordsResponse { 36 + records: Array<{ 37 + uri: string; 38 + cid: string; 39 + value: Record<string, unknown>; 40 + }>; 41 + cursor?: string; 42 + } 43 + 44 + // --- Cache layer --- 45 + 46 + interface CacheEntry<T> { 47 + data: T; 48 + expiresAt: number; 49 + } 50 + 51 + const PROFILE_TTL = 3600_000; // 1 hour 52 + const ENTRIES_TTL = 300_000; // 5 minutes 53 + const ENTRY_TTL = 600_000; // 10 minutes 54 + const MAX_ENTRY_CACHE = 200; 55 + 56 + let profileCache: CacheEntry<AuthorProfile> | null = null; 57 + let entriesCache: CacheEntry<BlogEntry[]> | null = null; 58 + const entryCache = new Map<string, CacheEntry<BlogEntry>>(); 59 + 60 + function isFresh<T>(entry: CacheEntry<T> | null | undefined): entry is CacheEntry<T> { 61 + return entry != null && Date.now() < entry.expiresAt; 62 + } 63 + 64 + export function invalidateCache(): void { 65 + profileCache = null; 66 + entriesCache = null; 67 + entryCache.clear(); 68 + } 69 + 70 + export function invalidateEntry(rkey: string): void { 71 + entryCache.delete(rkey); 72 + entriesCache = null; 73 + } 74 + 75 + // --- Helpers --- 76 + 77 + function extractRkey(uri: string): string { 78 + return uri.split("/").pop() || ""; 79 + } 80 + 81 + export function blobUrl(did: string, cid: string): string { 82 + return `${PDS_URL}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`; 83 + } 84 + 85 + function parseBlobsFromValue(val: Record<string, unknown>): AtBlob[] | undefined { 86 + if (!Array.isArray(val.blobs)) return undefined; 87 + return val.blobs.filter( 88 + (b: unknown) => { 89 + const blob = b as Record<string, unknown>; 90 + return ( 91 + blob?.$type === "blob" && 92 + typeof (blob?.ref as Record<string, unknown>)?.$link === "string" && 93 + typeof blob?.mimeType === "string" && 94 + typeof blob?.size === "number" 95 + ); 96 + } 97 + ) as AtBlob[]; 98 + } 99 + 100 + const FALLBACK_PROFILE: AuthorProfile = { 101 + displayName: HANDLE, 102 + description: "", 103 + avatarUrl: null, 104 + bannerUrl: null, 105 + }; 106 + 107 + // --- Data fetching --- 108 + 109 + export async function getProfile(): Promise<AuthorProfile> { 110 + if (isFresh(profileCache)) return profileCache.data; 111 + 112 + try { 113 + const res = await fetch( 114 + `${PDS_URL}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=app.bsky.actor.profile&limit=1` 115 + ); 116 + if (!res.ok) { 117 + console.error("PDS profile fetch failed:", res.status); 118 + return profileCache?.data ?? FALLBACK_PROFILE; 119 + } 120 + const data = (await res.json()) as ListRecordsResponse; 121 + const record = data.records[0]?.value as Record<string, unknown> | undefined; 122 + 123 + if (!record) { 124 + return profileCache?.data ?? FALLBACK_PROFILE; 125 + } 126 + 127 + const avatar = record.avatar as { ref?: { $link?: string } } | undefined; 128 + const banner = record.banner as { ref?: { $link?: string } } | undefined; 129 + 130 + const profile: AuthorProfile = { 131 + displayName: (record.displayName as string) || HANDLE, 132 + description: (record.description as string) || "", 133 + avatarUrl: avatar?.ref?.$link ? blobUrl(DID, avatar.ref.$link) : null, 134 + bannerUrl: banner?.ref?.$link ? blobUrl(DID, banner.ref.$link) : null, 135 + }; 136 + 137 + profileCache = { data: profile, expiresAt: Date.now() + PROFILE_TTL }; 138 + return profile; 139 + } catch (err) { 140 + console.error("Failed to fetch profile:", err); 141 + return profileCache?.data ?? FALLBACK_PROFILE; 142 + } 143 + } 144 + 145 + export async function getBlogEntries(): Promise<BlogEntry[]> { 146 + if (isFresh(entriesCache)) return entriesCache.data; 147 + 148 + const entries: BlogEntry[] = []; 149 + let cursor: string | undefined; 150 + 151 + try { 152 + do { 153 + const params = new URLSearchParams({ 154 + repo: DID, 155 + collection: BLOG_COLLECTION, 156 + limit: "100", 157 + }); 158 + if (cursor) params.set("cursor", cursor); 159 + 160 + const res = await fetch( 161 + `${PDS_URL}/xrpc/com.atproto.repo.listRecords?${params}` 162 + ); 163 + if (!res.ok) { 164 + console.error("PDS listRecords failed:", res.status); 165 + break; 166 + } 167 + const data = (await res.json()) as ListRecordsResponse; 168 + 169 + for (const record of data.records) { 170 + const val = record.value as Record<string, unknown>; 171 + if (val.visibility !== "public") continue; 172 + 173 + entries.push({ 174 + uri: record.uri, 175 + cid: record.cid, 176 + rkey: extractRkey(record.uri), 177 + title: (val.title as string) || "Untitled", 178 + content: val.content as string, 179 + createdAt: val.createdAt as string, 180 + visibility: val.visibility as string, 181 + theme: val.theme as string | undefined, 182 + blobs: parseBlobsFromValue(val), 183 + }); 184 + } 185 + 186 + cursor = data.cursor; 187 + } while (cursor && entries.length < 500); 188 + } catch (err) { 189 + console.error("Failed to fetch blog entries:", err); 190 + if (entriesCache?.data) return entriesCache.data; 191 + } 192 + 193 + entries.sort( 194 + (a, b) => 195 + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() 196 + ); 197 + 198 + if (entries.length > 0) { 199 + entriesCache = { data: entries, expiresAt: Date.now() + ENTRIES_TTL }; 200 + } 201 + 202 + return entries; 203 + } 204 + 205 + export async function getBlogEntry(rkey: string): Promise<BlogEntry | null> { 206 + const cached = entryCache.get(rkey); 207 + if (isFresh(cached)) return cached.data; 208 + 209 + try { 210 + const res = await fetch( 211 + `${PDS_URL}/xrpc/com.atproto.repo.getRecord?repo=${DID}&collection=${BLOG_COLLECTION}&rkey=${rkey}` 212 + ); 213 + 214 + if (!res.ok) { 215 + if (res.status === 404) { 216 + entryCache.delete(rkey); // Deleted post — evict from cache 217 + return null; 218 + } 219 + return cached?.data ?? null; // Non-404 error — serve stale if available 220 + } 221 + 222 + const data = (await res.json()) as { 223 + uri: string; 224 + cid: string; 225 + value: Record<string, unknown>; 226 + }; 227 + const val = data.value; 228 + 229 + if (val.visibility !== "public") { 230 + entryCache.delete(rkey); // No longer public — evict from cache 231 + return null; 232 + } 233 + 234 + const entry: BlogEntry = { 235 + uri: data.uri, 236 + cid: data.cid, 237 + rkey, 238 + title: (val.title as string) || "Untitled", 239 + content: val.content as string, 240 + createdAt: val.createdAt as string, 241 + visibility: val.visibility as string, 242 + theme: val.theme as string | undefined, 243 + blobs: parseBlobsFromValue(val), 244 + }; 245 + 246 + // Enforce cache size limit 247 + if (entryCache.size >= MAX_ENTRY_CACHE) { 248 + const firstKey = entryCache.keys().next().value; 249 + if (firstKey) entryCache.delete(firstKey); 250 + } 251 + 252 + entryCache.set(rkey, { data: entry, expiresAt: Date.now() + ENTRY_TTL }); 253 + return entry; 254 + } catch { 255 + return cached?.data ?? null; // Network error — serve stale if available 256 + } 257 + } 258 + 259 + // --- Draft / raw access (no cache, owner-only) --- 260 + 261 + export async function getDraftEntries(): Promise<BlogEntry[]> { 262 + const entries: BlogEntry[] = []; 263 + let cursor: string | undefined; 264 + 265 + try { 266 + do { 267 + const params = new URLSearchParams({ 268 + repo: DID, 269 + collection: BLOG_COLLECTION, 270 + limit: "100", 271 + }); 272 + if (cursor) params.set("cursor", cursor); 273 + 274 + const res = await fetch( 275 + `${PDS_URL}/xrpc/com.atproto.repo.listRecords?${params}` 276 + ); 277 + if (!res.ok) break; 278 + const data = (await res.json()) as ListRecordsResponse; 279 + 280 + for (const record of data.records) { 281 + const val = record.value as Record<string, unknown>; 282 + if (val.visibility !== "author") continue; 283 + 284 + entries.push({ 285 + uri: record.uri, 286 + cid: record.cid, 287 + rkey: extractRkey(record.uri), 288 + title: (val.title as string) || "Untitled", 289 + content: val.content as string, 290 + createdAt: val.createdAt as string, 291 + visibility: val.visibility as string, 292 + theme: val.theme as string | undefined, 293 + blobs: parseBlobsFromValue(val), 294 + }); 295 + } 296 + 297 + cursor = data.cursor; 298 + } while (cursor && entries.length < 100); 299 + } catch (err) { 300 + console.error("Failed to fetch draft entries:", err); 301 + } 302 + 303 + entries.sort( 304 + (a, b) => 305 + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() 306 + ); 307 + 308 + return entries; 309 + } 310 + 311 + export async function getRawBlogEntry( 312 + rkey: string 313 + ): Promise<BlogEntry | null> { 314 + try { 315 + const res = await fetch( 316 + `${PDS_URL}/xrpc/com.atproto.repo.getRecord?repo=${DID}&collection=${BLOG_COLLECTION}&rkey=${rkey}` 317 + ); 318 + 319 + if (!res.ok) return null; 320 + 321 + const data = (await res.json()) as { 322 + uri: string; 323 + cid: string; 324 + value: Record<string, unknown>; 325 + }; 326 + const val = data.value; 327 + 328 + return { 329 + uri: data.uri, 330 + cid: data.cid, 331 + rkey, 332 + title: (val.title as string) || "Untitled", 333 + content: val.content as string, 334 + createdAt: val.createdAt as string, 335 + visibility: (val.visibility as string) || "public", 336 + theme: val.theme as string | undefined, 337 + blobs: parseBlobsFromValue(val), 338 + }; 339 + } catch { 340 + return null; 341 + } 342 + } 343 + 344 + // Re-export constants for backward compatibility 345 + export { HANDLE, DID, PDS_URL } from "./constants";
+30
src/lib/utils.ts
··· 1 + export function formatDate(iso: string, opts?: { weekday?: boolean }): string { 2 + const options: Intl.DateTimeFormatOptions = { 3 + year: "numeric", 4 + month: "long", 5 + day: "numeric", 6 + }; 7 + if (opts?.weekday) options.weekday = "long"; 8 + return new Date(iso).toLocaleDateString("en-US", options); 9 + } 10 + 11 + export function excerpt(content: string, maxLen = 160): string { 12 + const plain = content 13 + .replace(/^#{1,6}\s+/gm, "") 14 + .replace(/\*{1,2}([^*]+)\*{1,2}/g, "$1") 15 + .replace(/`([^`]+)`/g, "$1") 16 + .replace(/~~~[\s\S]*?~~~/g, "") 17 + .replace(/\n+/g, " ") 18 + .trim(); 19 + if (plain.length <= maxLen) return plain; 20 + return plain.slice(0, maxLen).replace(/\s+\S*$/, "") + "\u2026"; 21 + } 22 + 23 + export function escapeXml(s: string): string { 24 + return s 25 + .replace(/&/g, "&amp;") 26 + .replace(/</g, "&lt;") 27 + .replace(/>/g, "&gt;") 28 + .replace(/"/g, "&quot;") 29 + .replace(/'/g, "&apos;"); 30 + }
+13
src/middleware.ts
··· 1 + import { defineMiddleware } from "astro:middleware"; 2 + 3 + export const onRequest = defineMiddleware(async (_context, next) => { 4 + const response = await next(); 5 + response.headers.set( 6 + "Content-Security-Policy", 7 + "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https://arcnode.xyz https://*.bsky.network; connect-src 'self'; frame-ancestors 'none'" 8 + ); 9 + response.headers.set("X-Content-Type-Options", "nosniff"); 10 + response.headers.set("X-Frame-Options", "DENY"); 11 + response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin"); 12 + return response; 13 + });
+224
src/pages/[rkey].astro
··· 1 + --- 2 + import Base from "../layouts/Base.astro"; 3 + import { getBlogEntry, getRawBlogEntry, isValidRkey } from "../lib/pds"; 4 + import { HANDLE, PDS_URL, DID, BLOG_COLLECTION } from "../lib/constants"; 5 + import { formatDate } from "../lib/utils"; 6 + import { isOwner } from "../lib/auth"; 7 + import { marked } from "marked"; 8 + import DOMPurify from "isomorphic-dompurify"; 9 + 10 + const renderer = new marked.Renderer(); 11 + renderer.link = ({ href, title, text }) => { 12 + const titleAttr = title ? ` title="${title}"` : ""; 13 + return `<a href="${href}" target="_blank" rel="noopener noreferrer"${titleAttr}>${text}</a>`; 14 + }; 15 + marked.use({ renderer }); 16 + 17 + const { rkey } = Astro.params; 18 + 19 + if (!rkey || !isValidRkey(rkey)) { 20 + return new Response("Not found", { status: 404 }); 21 + } 22 + 23 + // Auth check before fetching — owner can see drafts 24 + const sessionDid = Astro.cookies.get("session_did")?.value; 25 + const isAuthor = sessionDid ? isOwner(sessionDid) : false; 26 + 27 + const entry = isAuthor 28 + ? await getRawBlogEntry(rkey) 29 + : await getBlogEntry(rkey); 30 + 31 + if (!entry) { 32 + return new Response("Not found", { status: 404 }); 33 + } 34 + 35 + const isDraft = entry.visibility !== "public"; 36 + 37 + const rawHtml = await marked.parse(entry.content); 38 + const html = DOMPurify.sanitize(rawHtml, { 39 + ADD_ATTR: ["target"], 40 + }); 41 + 42 + // Pass entry data to client script for visibility toggle 43 + const entryData = { 44 + rkey, 45 + title: entry.title, 46 + content: entry.content, 47 + createdAt: entry.createdAt, 48 + visibility: entry.visibility, 49 + blobs: entry.blobs ?? [], 50 + }; 51 + --- 52 + 53 + <Base title={`${entry.title} — bkb`} description={entry.content.slice(0, 155)}> 54 + <article class="fade-in"> 55 + {isDraft && isAuthor && ( 56 + <div class="mb-6 px-4 py-3 bg-accent/10 border border-accent/30 rounded-lg text-sm font-mono text-accent"> 57 + draft — only visible to you 58 + </div> 59 + )} 60 + 61 + <header class="mb-10"> 62 + <time 63 + datetime={entry.createdAt} 64 + class="text-xs font-mono text-muted uppercase tracking-wider" 65 + > 66 + {formatDate(entry.createdAt, { weekday: true })} 67 + </time> 68 + <h1 class="font-serif text-2xl sm:text-3xl md:text-4xl font-bold mt-2 leading-tight text-ink-bright"> 69 + {entry.title} 70 + </h1> 71 + </header> 72 + 73 + <div class="prose fade-in-delay" set:html={html} /> 74 + 75 + <footer class="mt-16 pt-8 border-t border-border"> 76 + <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-4 text-sm text-muted"> 77 + <div class="font-serif"> 78 + <span>by </span> 79 + <a 80 + href={`https://bsky.app/profile/${HANDLE}`} 81 + target="_blank" 82 + rel="noopener" 83 + class="text-accent hover:text-accent-light transition-colors" 84 + > 85 + @{HANDLE} 86 + </a> 87 + </div> 88 + <div class="flex items-center gap-4 text-xs font-mono"> 89 + <a 90 + href={`${PDS_URL}/xrpc/com.atproto.repo.getRecord?repo=${DID}&collection=${BLOG_COLLECTION}&rkey=${rkey}`} 91 + target="_blank" 92 + rel="noopener" 93 + class="hover:text-ink transition-colors" 94 + > 95 + view record 96 + </a> 97 + <span class="text-border-light">|</span> 98 + <a href="/" class="hover:text-ink transition-colors">all posts</a> 99 + {isAuthor && ( 100 + <> 101 + <span class="text-border-light">|</span> 102 + <a 103 + href={`/write?edit=${rkey}`} 104 + class="hover:text-ink transition-colors" 105 + > 106 + edit 107 + </a> 108 + <span class="text-border-light">|</span> 109 + {isDraft ? ( 110 + <button 111 + id="visibility-btn" 112 + class="text-accent hover:text-accent-light transition-colors cursor-pointer" 113 + > 114 + publish 115 + </button> 116 + ) : ( 117 + <button 118 + id="visibility-btn" 119 + class="text-muted hover:text-ink transition-colors cursor-pointer" 120 + > 121 + unpublish 122 + </button> 123 + )} 124 + <span class="text-border-light">|</span> 125 + <button 126 + id="delete-btn" 127 + data-rkey={rkey} 128 + class="text-red-700/60 hover:text-red-700 transition-colors cursor-pointer" 129 + > 130 + delete 131 + </button> 132 + </> 133 + )} 134 + </div> 135 + </div> 136 + </footer> 137 + </article> 138 + </Base> 139 + 140 + {isAuthor && ( 141 + <script define:vars={{ entryData }}> 142 + window.__entryData = entryData; 143 + </script> 144 + <script> 145 + const entry = (window as any).__entryData; 146 + 147 + // Visibility toggle (publish/unpublish) 148 + const visibilityBtn = document.getElementById("visibility-btn"); 149 + if (visibilityBtn && entry) { 150 + const isDraft = entry.visibility !== "public"; 151 + visibilityBtn.addEventListener("click", async () => { 152 + const action = isDraft ? "Publish" : "Unpublish"; 153 + const confirmMsg = isDraft 154 + ? "Publish this draft? It will become visible to everyone." 155 + : "Unpublish this post? It will become a draft."; 156 + if (!confirm(confirmMsg)) return; 157 + 158 + const newVisibility = isDraft ? "public" : "author"; 159 + visibilityBtn.textContent = isDraft ? "publishing..." : "unpublishing..."; 160 + 161 + try { 162 + const res = await fetch("/api/update", { 163 + method: "POST", 164 + headers: { "Content-Type": "application/json" }, 165 + body: JSON.stringify({ 166 + rkey: entry.rkey, 167 + title: entry.title, 168 + content: entry.content, 169 + createdAt: entry.createdAt, 170 + visibility: newVisibility, 171 + blobs: entry.blobs || [], 172 + }), 173 + }); 174 + 175 + const data = await res.json(); 176 + if (data.success) { 177 + if (newVisibility === "author") { 178 + window.location.href = "/write"; 179 + } else { 180 + window.location.reload(); 181 + } 182 + } else { 183 + alert(data.error || `${action} failed`); 184 + visibilityBtn.textContent = isDraft ? "publish" : "unpublish"; 185 + } 186 + } catch { 187 + alert("Network error"); 188 + visibilityBtn.textContent = isDraft ? "publish" : "unpublish"; 189 + } 190 + }); 191 + } 192 + 193 + // Delete 194 + const deleteBtn = document.getElementById("delete-btn"); 195 + if (deleteBtn) { 196 + deleteBtn.addEventListener("click", async () => { 197 + if (!confirm("Delete this post? This cannot be undone.")) return; 198 + 199 + const rkey = deleteBtn.dataset.rkey; 200 + deleteBtn.textContent = "deleting..."; 201 + 202 + try { 203 + const res = await fetch("/api/delete", { 204 + method: "POST", 205 + headers: { "Content-Type": "application/json" }, 206 + body: JSON.stringify({ rkey }), 207 + }); 208 + 209 + const data = await res.json(); 210 + 211 + if (data.success) { 212 + window.location.href = "/"; 213 + } else { 214 + alert(data.error || "Delete failed"); 215 + deleteBtn.textContent = "delete"; 216 + } 217 + } catch { 218 + alert("Network error"); 219 + deleteBtn.textContent = "delete"; 220 + } 221 + }); 222 + } 223 + </script> 224 + )}
+53
src/pages/api/delete.ts
··· 1 + import type { APIRoute } from "astro"; 2 + import { checkOrigin, checkAuth, parseJsonBody, createPdsSession } from "../../lib/api"; 3 + import { isValidRkey, invalidateEntry } from "../../lib/pds"; 4 + import { PDS_URL, DID, BLOG_COLLECTION } from "../../lib/constants"; 5 + 6 + export const POST: APIRoute = async ({ request, cookies }) => { 7 + const originErr = checkOrigin(request); 8 + if (originErr) return originErr; 9 + 10 + const authErr = checkAuth(cookies); 11 + if (authErr) return authErr; 12 + 13 + const [body, parseErr] = await parseJsonBody(request); 14 + if (parseErr) return parseErr; 15 + 16 + const rkey = typeof body.rkey === "string" ? body.rkey : ""; 17 + 18 + if (!rkey || !isValidRkey(rkey)) { 19 + return new Response(JSON.stringify({ error: "Invalid rkey" }), { status: 400 }); 20 + } 21 + 22 + const [accessJwt, sessionErr] = await createPdsSession(); 23 + if (sessionErr) return sessionErr; 24 + 25 + const deleteRes = await fetch( 26 + `${PDS_URL}/xrpc/com.atproto.repo.deleteRecord`, 27 + { 28 + method: "POST", 29 + headers: { 30 + "Content-Type": "application/json", 31 + Authorization: `Bearer ${accessJwt}`, 32 + }, 33 + body: JSON.stringify({ 34 + repo: DID, 35 + collection: BLOG_COLLECTION, 36 + rkey, 37 + }), 38 + } 39 + ); 40 + 41 + if (!deleteRes.ok) { 42 + const err = await deleteRes.text(); 43 + console.error("PDS deleteRecord failed:", err); 44 + return new Response( 45 + JSON.stringify({ error: "Failed to delete entry" }), 46 + { status: 500 } 47 + ); 48 + } 49 + 50 + invalidateEntry(rkey); 51 + 52 + return new Response(JSON.stringify({ success: true })); 53 + };
+7
src/pages/api/logout.ts
··· 1 + import type { APIRoute } from "astro"; 2 + 3 + export const GET: APIRoute = async ({ cookies, redirect }) => { 4 + cookies.delete("session_did", { path: "/" }); 5 + cookies.delete("session_handle", { path: "/" }); 6 + return redirect("/", 303); 7 + };
+79
src/pages/api/publish.ts
··· 1 + import type { APIRoute } from "astro"; 2 + import { checkOrigin, checkAuth, parseJsonBody, createPdsSession } from "../../lib/api"; 3 + import { invalidateCache } from "../../lib/pds"; 4 + import { PDS_URL, DID, BLOG_COLLECTION } from "../../lib/constants"; 5 + 6 + const MAX_TITLE_LENGTH = 300; 7 + const MAX_CONTENT_LENGTH = 100_000; 8 + 9 + export const POST: APIRoute = async ({ request, cookies }) => { 10 + const originErr = checkOrigin(request); 11 + if (originErr) return originErr; 12 + 13 + const authErr = checkAuth(cookies); 14 + if (authErr) return authErr; 15 + 16 + const [body, parseErr] = await parseJsonBody(request); 17 + if (parseErr) return parseErr; 18 + 19 + const title = typeof body.title === "string" ? body.title.trim() : ""; 20 + const content = typeof body.content === "string" ? body.content.trim() : ""; 21 + 22 + if (!title || title.length > MAX_TITLE_LENGTH) { 23 + return new Response( 24 + JSON.stringify({ error: `Title is required and must be under ${MAX_TITLE_LENGTH} characters` }), 25 + { status: 400 } 26 + ); 27 + } 28 + 29 + if (!content || content.length > MAX_CONTENT_LENGTH) { 30 + return new Response( 31 + JSON.stringify({ error: `Content is required and must be under ${MAX_CONTENT_LENGTH} characters` }), 32 + { status: 400 } 33 + ); 34 + } 35 + 36 + const blobs = Array.isArray(body.blobs) ? body.blobs : []; 37 + 38 + const [accessJwt, sessionErr] = await createPdsSession(); 39 + if (sessionErr) return sessionErr; 40 + 41 + const createRes = await fetch( 42 + `${PDS_URL}/xrpc/com.atproto.repo.createRecord`, 43 + { 44 + method: "POST", 45 + headers: { 46 + "Content-Type": "application/json", 47 + Authorization: `Bearer ${accessJwt}`, 48 + }, 49 + body: JSON.stringify({ 50 + repo: DID, 51 + collection: BLOG_COLLECTION, 52 + record: { 53 + $type: BLOG_COLLECTION, 54 + title, 55 + content, 56 + createdAt: new Date().toISOString(), 57 + visibility: body.visibility === "author" ? "author" : "public", 58 + ...(blobs.length > 0 && { blobs }), 59 + }, 60 + }), 61 + } 62 + ); 63 + 64 + if (!createRes.ok) { 65 + const err = await createRes.text(); 66 + console.error("PDS createRecord failed:", err); 67 + return new Response( 68 + JSON.stringify({ error: "Failed to create entry" }), 69 + { status: 500 } 70 + ); 71 + } 72 + 73 + const record = (await createRes.json()) as { uri: string; cid: string }; 74 + const rkey = record.uri.split("/").pop(); 75 + 76 + invalidateCache(); 77 + 78 + return new Response(JSON.stringify({ success: true, rkey })); 79 + };
+92
src/pages/api/update.ts
··· 1 + import type { APIRoute } from "astro"; 2 + import { checkOrigin, checkAuth, parseJsonBody, createPdsSession } from "../../lib/api"; 3 + import { isValidRkey, invalidateEntry } from "../../lib/pds"; 4 + import { PDS_URL, DID, BLOG_COLLECTION } from "../../lib/constants"; 5 + 6 + const MAX_TITLE_LENGTH = 300; 7 + const MAX_CONTENT_LENGTH = 100_000; 8 + const VALID_VISIBILITY = ["public", "author"]; 9 + 10 + export const POST: APIRoute = async ({ request, cookies }) => { 11 + const originErr = checkOrigin(request); 12 + if (originErr) return originErr; 13 + 14 + const authErr = checkAuth(cookies); 15 + if (authErr) return authErr; 16 + 17 + const [body, parseErr] = await parseJsonBody(request); 18 + if (parseErr) return parseErr; 19 + 20 + const rkey = typeof body.rkey === "string" ? body.rkey : ""; 21 + const title = typeof body.title === "string" ? body.title.trim() : ""; 22 + const content = typeof body.content === "string" ? body.content.trim() : ""; 23 + const visibility = typeof body.visibility === "string" ? body.visibility : ""; 24 + const createdAt = typeof body.createdAt === "string" ? body.createdAt : new Date().toISOString(); 25 + 26 + if (!rkey || !isValidRkey(rkey)) { 27 + return new Response(JSON.stringify({ error: "Invalid rkey" }), { status: 400 }); 28 + } 29 + 30 + if (!title || title.length > MAX_TITLE_LENGTH) { 31 + return new Response( 32 + JSON.stringify({ error: `Title is required and must be under ${MAX_TITLE_LENGTH} characters` }), 33 + { status: 400 } 34 + ); 35 + } 36 + 37 + if (!content || content.length > MAX_CONTENT_LENGTH) { 38 + return new Response( 39 + JSON.stringify({ error: `Content is required and must be under ${MAX_CONTENT_LENGTH} characters` }), 40 + { status: 400 } 41 + ); 42 + } 43 + 44 + if (!VALID_VISIBILITY.includes(visibility)) { 45 + return new Response( 46 + JSON.stringify({ error: "Visibility must be 'public' or 'author'" }), 47 + { status: 400 } 48 + ); 49 + } 50 + 51 + const blobs = Array.isArray(body.blobs) ? body.blobs : []; 52 + 53 + const [accessJwt, sessionErr] = await createPdsSession(); 54 + if (sessionErr) return sessionErr; 55 + 56 + const putRes = await fetch( 57 + `${PDS_URL}/xrpc/com.atproto.repo.putRecord`, 58 + { 59 + method: "POST", 60 + headers: { 61 + "Content-Type": "application/json", 62 + Authorization: `Bearer ${accessJwt}`, 63 + }, 64 + body: JSON.stringify({ 65 + repo: DID, 66 + collection: BLOG_COLLECTION, 67 + rkey, 68 + record: { 69 + $type: BLOG_COLLECTION, 70 + title, 71 + content, 72 + createdAt, 73 + visibility, 74 + ...(blobs.length > 0 && { blobs }), 75 + }, 76 + }), 77 + } 78 + ); 79 + 80 + if (!putRes.ok) { 81 + const err = await putRes.text(); 82 + console.error("PDS putRecord failed:", err); 83 + return new Response( 84 + JSON.stringify({ error: "Failed to update entry" }), 85 + { status: 500 } 86 + ); 87 + } 88 + 89 + invalidateEntry(rkey); 90 + 91 + return new Response(JSON.stringify({ success: true, rkey })); 92 + };
+82
src/pages/api/upload-image.ts
··· 1 + import type { APIRoute } from "astro"; 2 + import { checkOrigin, checkAuth, createPdsSession } from "../../lib/api"; 3 + import { blobUrl } from "../../lib/pds"; 4 + import { PDS_URL, DID } from "../../lib/constants"; 5 + 6 + const MAX_SIZE = 5 * 1024 * 1024; // 5 MB 7 + const ALLOWED_TYPES = new Set(["image/png", "image/jpeg", "image/webp"]); 8 + 9 + export const POST: APIRoute = async ({ request, cookies }) => { 10 + const originErr = checkOrigin(request); 11 + if (originErr) return originErr; 12 + 13 + const authErr = checkAuth(cookies); 14 + if (authErr) return authErr; 15 + 16 + let formData: FormData; 17 + try { 18 + formData = await request.formData(); 19 + } catch { 20 + return new Response( 21 + JSON.stringify({ error: "Invalid form data" }), 22 + { status: 400 } 23 + ); 24 + } 25 + 26 + const file = formData.get("file"); 27 + 28 + if (!(file instanceof File)) { 29 + return new Response( 30 + JSON.stringify({ error: "No file provided" }), 31 + { status: 400 } 32 + ); 33 + } 34 + 35 + if (!ALLOWED_TYPES.has(file.type)) { 36 + return new Response( 37 + JSON.stringify({ error: "Only PNG, JPEG, and WebP images are accepted" }), 38 + { status: 400 } 39 + ); 40 + } 41 + 42 + if (file.size > MAX_SIZE) { 43 + return new Response( 44 + JSON.stringify({ error: "Image must be under 5 MB" }), 45 + { status: 400 } 46 + ); 47 + } 48 + 49 + const [accessJwt, sessionErr] = await createPdsSession(); 50 + if (sessionErr) return sessionErr; 51 + 52 + const bytes = await file.arrayBuffer(); 53 + 54 + const uploadRes = await fetch( 55 + `${PDS_URL}/xrpc/com.atproto.repo.uploadBlob`, 56 + { 57 + method: "POST", 58 + headers: { 59 + "Content-Type": file.type, 60 + Authorization: `Bearer ${accessJwt}`, 61 + }, 62 + body: bytes, 63 + } 64 + ); 65 + 66 + if (!uploadRes.ok) { 67 + const err = await uploadRes.text(); 68 + console.error("PDS uploadBlob failed:", err); 69 + return new Response( 70 + JSON.stringify({ error: "Failed to upload image" }), 71 + { status: 500 } 72 + ); 73 + } 74 + 75 + const { blob } = (await uploadRes.json()) as { 76 + blob: { $type: "blob"; ref: { $link: string }; mimeType: string; size: number }; 77 + }; 78 + 79 + const url = blobUrl(DID, blob.ref.$link); 80 + 81 + return new Response(JSON.stringify({ blob, url })); 82 + };
+57
src/pages/index.astro
··· 1 + --- 2 + import Base from "../layouts/Base.astro"; 3 + import { getBlogEntries, getProfile } from "../lib/pds"; 4 + import { HANDLE } from "../lib/constants"; 5 + import { formatDate, excerpt } from "../lib/utils"; 6 + 7 + const profile = await getProfile(); 8 + const entries = await getBlogEntries(); 9 + --- 10 + 11 + <Base title="bkb — writing" description={profile.description || "Writing by bkb on the AT Protocol"}> 12 + <div class="mb-14 fade-in"> 13 + <div class="flex items-center gap-4 mb-5"> 14 + {profile.avatarUrl && ( 15 + <img 16 + src={profile.avatarUrl} 17 + alt={profile.displayName} 18 + class="w-12 h-12 sm:w-14 sm:h-14 rounded-full object-cover ring-1 ring-border-light" 19 + /> 20 + )} 21 + <div> 22 + <h1 class="font-serif text-xl sm:text-2xl font-bold text-ink-bright">{profile.displayName}</h1> 23 + <p class="text-sm text-muted">@{HANDLE}</p> 24 + </div> 25 + </div> 26 + {profile.description && ( 27 + <p class="text-muted text-sm whitespace-pre-line leading-relaxed">{profile.description}</p> 28 + )} 29 + </div> 30 + 31 + {entries.length === 0 ? ( 32 + <p class="text-muted italic font-serif fade-in-delay">No entries yet.</p> 33 + ) : ( 34 + <div class="space-y-1 fade-in-delay"> 35 + {entries.map((entry) => ( 36 + <article> 37 + <a href={`/${entry.rkey}`} class="group block py-4 sm:py-5 -mx-3 sm:-mx-4 px-3 sm:px-4 rounded-lg hover:bg-paper-raised transition-colors"> 38 + <div class="flex flex-col sm:flex-row sm:items-baseline sm:justify-between gap-1 sm:gap-4"> 39 + <h2 class="font-serif text-base sm:text-lg font-semibold text-ink-bright group-hover:text-accent transition-colors"> 40 + {entry.title} 41 + </h2> 42 + <time 43 + datetime={entry.createdAt} 44 + class="text-xs font-mono text-muted shrink-0" 45 + > 46 + {formatDate(entry.createdAt)} 47 + </time> 48 + </div> 49 + <p class="text-muted text-sm leading-relaxed mt-1.5 font-serif"> 50 + {excerpt(entry.content)} 51 + </p> 52 + </a> 53 + </article> 54 + ))} 55 + </div> 56 + )} 57 + </Base>
+43
src/pages/rss.xml.ts
··· 1 + import type { APIRoute } from "astro"; 2 + import { getBlogEntries, getProfile } from "../lib/pds"; 3 + import { BLOG_URL, HANDLE } from "../lib/constants"; 4 + import { escapeXml, excerpt } from "../lib/utils"; 5 + 6 + export const GET: APIRoute = async () => { 7 + const [entries, profile] = await Promise.all([ 8 + getBlogEntries(), 9 + getProfile(), 10 + ]); 11 + 12 + const items = entries.slice(0, 20).map((entry) => { 13 + const pubDate = new Date(entry.createdAt).toUTCString(); 14 + const desc = excerpt(entry.content, 300); 15 + 16 + return ` <item> 17 + <title>${escapeXml(entry.title)}</title> 18 + <link>${BLOG_URL}/${escapeXml(entry.rkey)}</link> 19 + <guid isPermaLink="true">${BLOG_URL}/${escapeXml(entry.rkey)}</guid> 20 + <pubDate>${pubDate}</pubDate> 21 + <description>${escapeXml(desc)}</description> 22 + </item>`; 23 + }); 24 + 25 + const xml = `<?xml version="1.0" encoding="UTF-8"?> 26 + <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> 27 + <channel> 28 + <title>${escapeXml(profile.displayName)} — writing</title> 29 + <link>${BLOG_URL}</link> 30 + <description>${escapeXml(profile.description || `Writing by @${HANDLE}`)}</description> 31 + <language>en</language> 32 + <atom:link href="${BLOG_URL}/rss.xml" rel="self" type="application/rss+xml" /> 33 + ${items.join("\n")} 34 + </channel> 35 + </rss>`; 36 + 37 + return new Response(xml, { 38 + headers: { 39 + "Content-Type": "application/rss+xml; charset=utf-8", 40 + "Cache-Control": "public, max-age=3600", 41 + }, 42 + }); 43 + };
+435
src/pages/write.astro
··· 1 + --- 2 + import Base from "../layouts/Base.astro"; 3 + import { verifyProxyTicket, isOwner, getLoginUrl } from "../lib/auth"; 4 + import { getDraftEntries, getRawBlogEntry, type BlogEntry } from "../lib/pds"; 5 + import { formatDate } from "../lib/utils"; 6 + 7 + let authed = false; 8 + let handle = ""; 9 + 10 + // Check for proxy ticket in URL (redirect from atauth) 11 + const ticket = Astro.url.searchParams.get("_atauth_ticket"); 12 + if (ticket) { 13 + const user = await verifyProxyTicket(ticket); 14 + if (user && isOwner(user.did)) { 15 + Astro.cookies.set("session_did", user.did, { 16 + httpOnly: true, 17 + secure: true, 18 + sameSite: "lax", 19 + path: "/", 20 + maxAge: 86400 * 7, 21 + }); 22 + Astro.cookies.set("session_handle", user.handle, { 23 + httpOnly: true, 24 + secure: true, 25 + sameSite: "lax", 26 + path: "/", 27 + maxAge: 86400 * 7, 28 + }); 29 + return Astro.redirect("/write"); 30 + } 31 + } 32 + 33 + // Check existing session cookie 34 + const sessionDid = Astro.cookies.get("session_did")?.value; 35 + const sessionHandle = Astro.cookies.get("session_handle")?.value; 36 + if (sessionDid && sessionHandle && isOwner(sessionDid)) { 37 + authed = true; 38 + handle = sessionHandle; 39 + } 40 + 41 + const loginUrl = getLoginUrl(); 42 + 43 + // Load drafts and optional edit entry 44 + let drafts: BlogEntry[] = []; 45 + let editEntry: BlogEntry | null = null; 46 + const editRkey = Astro.url.searchParams.get("edit"); 47 + 48 + if (authed) { 49 + drafts = await getDraftEntries(); 50 + if (editRkey) { 51 + editEntry = await getRawBlogEntry(editRkey); 52 + } 53 + } 54 + 55 + const isEditing = editEntry !== null; 56 + const pageTitle = isEditing ? "Edit entry" : "New entry"; 57 + const editBlobs = editEntry?.blobs ?? []; 58 + --- 59 + 60 + <Base title={`${pageTitle} — bkb`} description="Compose a blog entry" wide={authed}> 61 + {!authed ? ( 62 + <div class="py-16 text-center fade-in max-w-2xl mx-auto"> 63 + <h1 class="font-serif text-2xl font-bold text-ink-bright mb-4">Sign in to write</h1> 64 + <p class="text-muted font-serif mb-8">Authenticate with your AT Protocol identity.</p> 65 + <a 66 + href={loginUrl} 67 + class="inline-block px-6 py-3 bg-accent/10 border border-accent/30 text-accent font-serif rounded-lg hover:bg-accent/20 transition-colors" 68 + > 69 + Sign in with AT Protocol 70 + </a> 71 + </div> 72 + ) : ( 73 + <div class="fade-in"> 74 + <div class="flex items-center justify-between mb-8"> 75 + <h1 class="font-serif text-2xl font-bold text-ink-bright">{pageTitle}</h1> 76 + <div class="flex items-center gap-3"> 77 + <span class="text-xs font-mono text-muted hidden sm:inline">@{handle}</span> 78 + <a 79 + href="/api/logout" 80 + class="text-xs font-mono text-muted hover:text-accent transition-colors" 81 + > 82 + sign out 83 + </a> 84 + </div> 85 + </div> 86 + 87 + {drafts.length > 0 && !isEditing && ( 88 + <div class="mb-10 pb-8 border-b border-border"> 89 + <h2 class="font-serif text-lg font-semibold text-ink-bright mb-4">Drafts</h2> 90 + <div class="space-y-1"> 91 + {drafts.map((draft) => ( 92 + <a 93 + href={`/write?edit=${draft.rkey}`} 94 + class="group flex items-baseline justify-between py-2 px-3 -mx-3 rounded-lg hover:bg-paper-raised transition-colors" 95 + > 96 + <span class="font-serif text-ink-bright group-hover:text-accent transition-colors truncate mr-4"> 97 + {draft.title} 98 + </span> 99 + <time class="text-xs font-mono text-muted shrink-0"> 100 + {formatDate(draft.createdAt)} 101 + </time> 102 + </a> 103 + ))} 104 + </div> 105 + </div> 106 + )} 107 + 108 + <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> 109 + <!-- Editor column --> 110 + <div> 111 + <form 112 + id="editor-form" 113 + class="space-y-5" 114 + data-rkey={editEntry?.rkey || ""} 115 + data-created-at={editEntry?.createdAt || ""} 116 + data-visibility={editEntry?.visibility || ""} 117 + > 118 + <div> 119 + <input 120 + type="text" 121 + id="title-input" 122 + placeholder="Title" 123 + required 124 + value={editEntry?.title || ""} 125 + class="w-full px-4 py-3 bg-paper-dim border border-border rounded-lg text-ink-bright font-serif text-lg sm:text-xl focus:outline-none focus:border-accent placeholder:text-muted transition-colors" 126 + /> 127 + </div> 128 + <div class="flex items-center gap-2 text-sm"> 129 + <label 130 + id="image-upload-label" 131 + class="cursor-pointer px-3 py-1.5 text-muted hover:text-ink border border-border rounded-lg hover:border-border-light transition-colors inline-flex items-center gap-1.5" 132 + > 133 + <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"> 134 + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 135 + d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/> 136 + </svg> 137 + image 138 + <input 139 + type="file" 140 + id="image-input" 141 + accept="image/png,image/jpeg,image/webp" 142 + class="hidden" 143 + /> 144 + </label> 145 + <span id="upload-status" class="text-xs text-muted"></span> 146 + </div> 147 + <div> 148 + <textarea 149 + id="content-input" 150 + placeholder="Write in markdown..." 151 + rows="20" 152 + required 153 + class="editor-textarea w-full px-4 py-3" 154 + >{editEntry?.content || ""}</textarea> 155 + </div> 156 + <div class="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3"> 157 + <p class="text-xs text-muted font-mono">markdown supported</p> 158 + <div class="flex items-center gap-3 w-full sm:w-auto"> 159 + <button 160 + type="button" 161 + id="preview-btn" 162 + class="flex-1 sm:flex-none px-4 py-2.5 sm:py-2 text-sm text-muted hover:text-ink border border-border rounded-lg hover:border-border-light transition-colors md:hidden" 163 + > 164 + preview 165 + </button> 166 + <button 167 + type="button" 168 + id="draft-btn" 169 + class="flex-1 sm:flex-none px-4 py-2.5 sm:py-2 text-sm text-muted hover:text-ink border border-border rounded-lg hover:border-border-light transition-colors" 170 + > 171 + save draft 172 + </button> 173 + <button 174 + type="submit" 175 + id="publish-btn" 176 + class="flex-1 sm:flex-none px-6 py-2.5 sm:py-2 bg-accent/10 border border-accent/30 text-accent font-serif rounded-lg hover:bg-accent/20 transition-colors" 177 + > 178 + publish 179 + </button> 180 + </div> 181 + </div> 182 + </form> 183 + 184 + <p id="editor-status" class="text-sm mt-4 hidden"></p> 185 + </div> 186 + 187 + <!-- Desktop preview column --> 188 + <div id="desktop-preview" class="hidden md:block"> 189 + <p class="text-xs font-mono text-muted uppercase tracking-wider mb-4">Preview</p> 190 + <div id="desktop-preview-content" class="prose"></div> 191 + </div> 192 + </div> 193 + 194 + <!-- Mobile preview (toggle) --> 195 + <div id="mobile-preview" class="md:hidden hidden mt-8 pt-8 border-t border-border"> 196 + <p class="text-xs font-mono text-muted uppercase tracking-wider mb-4">Preview</p> 197 + <div id="mobile-preview-content" class="prose"></div> 198 + </div> 199 + </div> 200 + )} 201 + </Base> 202 + 203 + {authed && ( 204 + <script define:vars={{ editBlobs }}> 205 + window.__editBlobs = editBlobs; 206 + </script> 207 + )} 208 + 209 + <script> 210 + const editorForm = document.getElementById("editor-form") as HTMLFormElement | null; 211 + if (editorForm) { 212 + const titleInput = document.getElementById("title-input") as HTMLInputElement; 213 + const contentInput = document.getElementById("content-input") as HTMLTextAreaElement; 214 + const publishBtn = document.getElementById("publish-btn") as HTMLButtonElement; 215 + const draftBtn = document.getElementById("draft-btn") as HTMLButtonElement; 216 + const statusEl = document.getElementById("editor-status")!; 217 + const previewBtn = document.getElementById("preview-btn"); 218 + const desktopPreviewContent = document.getElementById("desktop-preview-content"); 219 + const mobilePreview = document.getElementById("mobile-preview"); 220 + const mobilePreviewContent = document.getElementById("mobile-preview-content"); 221 + const imageInput = document.getElementById("image-input") as HTMLInputElement; 222 + const uploadStatus = document.getElementById("upload-status")!; 223 + 224 + const editRkey = editorForm.dataset.rkey || ""; 225 + const editCreatedAt = editorForm.dataset.createdAt || ""; 226 + const isEditing = editRkey.length > 0; 227 + 228 + // --- Blob tracking --- 229 + let uploadedBlobs: any[] = (window as any).__editBlobs || []; 230 + 231 + // --- Image upload --- 232 + imageInput.addEventListener("change", async () => { 233 + const file = imageInput.files?.[0]; 234 + if (!file) return; 235 + 236 + if (file.size > 5 * 1024 * 1024) { 237 + uploadStatus.textContent = "Image must be under 5 MB"; 238 + uploadStatus.className = "text-xs text-red-400"; 239 + return; 240 + } 241 + 242 + uploadStatus.textContent = "uploading..."; 243 + uploadStatus.className = "text-xs text-muted"; 244 + 245 + const formData = new FormData(); 246 + formData.append("file", file); 247 + 248 + try { 249 + const res = await fetch("/api/upload-image", { 250 + method: "POST", 251 + body: formData, 252 + }); 253 + 254 + const data = await res.json(); 255 + 256 + if (res.ok && data.blob && data.url) { 257 + uploadedBlobs.push(data.blob); 258 + 259 + const alt = file.name.replace(/\.[^.]+$/, ""); 260 + const markdown = `![${alt}](${data.url})`; 261 + insertAtCursor(contentInput, markdown); 262 + 263 + uploadStatus.textContent = ""; 264 + uploadStatus.className = "text-xs text-muted"; 265 + } else { 266 + uploadStatus.textContent = data.error || "Upload failed"; 267 + uploadStatus.className = "text-xs text-red-400"; 268 + } 269 + } catch { 270 + uploadStatus.textContent = "Network error"; 271 + uploadStatus.className = "text-xs text-red-400"; 272 + } 273 + 274 + imageInput.value = ""; 275 + }); 276 + 277 + function insertAtCursor(textarea: HTMLTextAreaElement, text: string) { 278 + const start = textarea.selectionStart; 279 + const end = textarea.selectionEnd; 280 + const before = textarea.value.substring(0, start); 281 + const after = textarea.value.substring(end); 282 + 283 + const needNewlineBefore = before.length > 0 && !before.endsWith("\n"); 284 + const needNewlineAfter = after.length > 0 && !after.startsWith("\n"); 285 + 286 + const insert = 287 + (needNewlineBefore ? "\n\n" : "") + 288 + text + 289 + (needNewlineAfter ? "\n\n" : ""); 290 + 291 + textarea.value = before + insert + after; 292 + const newPos = start + insert.length; 293 + textarea.selectionStart = textarea.selectionEnd = newPos; 294 + textarea.focus(); 295 + textarea.dispatchEvent(new Event("input")); 296 + } 297 + 298 + // --- Save entry --- 299 + async function saveEntry(visibility: "public" | "author") { 300 + const btn = visibility === "public" ? publishBtn : draftBtn; 301 + const label = visibility === "public" ? "publish" : "save draft"; 302 + btn.disabled = true; 303 + btn.textContent = visibility === "public" ? "publishing..." : "saving..."; 304 + statusEl.classList.add("hidden"); 305 + 306 + const endpoint = isEditing ? "/api/update" : "/api/publish"; 307 + const payload: Record<string, unknown> = { 308 + title: titleInput.value, 309 + content: contentInput.value, 310 + visibility, 311 + blobs: uploadedBlobs, 312 + }; 313 + if (isEditing) { 314 + payload.rkey = editRkey; 315 + payload.createdAt = editCreatedAt; 316 + } 317 + 318 + try { 319 + const res = await fetch(endpoint, { 320 + method: "POST", 321 + headers: { "Content-Type": "application/json" }, 322 + body: JSON.stringify(payload), 323 + }); 324 + 325 + const data = await res.json(); 326 + 327 + if (data.success) { 328 + if (visibility === "public") { 329 + window.location.href = `/${data.rkey}`; 330 + } else { 331 + window.location.href = "/write"; 332 + } 333 + } else { 334 + statusEl.textContent = data.error || `${label} failed`; 335 + statusEl.className = "text-red-400 text-sm mt-4"; 336 + btn.disabled = false; 337 + btn.textContent = label; 338 + } 339 + } catch { 340 + statusEl.textContent = "Network error"; 341 + statusEl.className = "text-red-400 text-sm mt-4"; 342 + btn.disabled = false; 343 + btn.textContent = label; 344 + } 345 + } 346 + 347 + editorForm.addEventListener("submit", (e) => { 348 + e.preventDefault(); 349 + saveEntry("public"); 350 + }); 351 + 352 + draftBtn.addEventListener("click", () => { 353 + if (!titleInput.value.trim() || !contentInput.value.trim()) { 354 + statusEl.textContent = "Title and content are required"; 355 + statusEl.className = "text-red-400 text-sm mt-4"; 356 + return; 357 + } 358 + saveEntry("author"); 359 + }); 360 + 361 + // --- Preview rendering --- 362 + function escapeHtml(s: string): string { 363 + const div = document.createElement("div"); 364 + div.textContent = s; 365 + return div.innerHTML; 366 + } 367 + 368 + function renderPreview(): string { 369 + const md = escapeHtml(contentInput.value); 370 + const html = md 371 + .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1" />') 372 + .replace(/^### (.+)$/gm, '<h3>$1</h3>') 373 + .replace(/^## (.+)$/gm, '<h2>$1</h2>') 374 + .replace(/^# (.+)$/gm, '<h1>$1</h1>') 375 + .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>') 376 + .replace(/\*(.+?)\*/g, '<em>$1</em>') 377 + .replace(/`(.+?)`/g, '<code>$1</code>') 378 + .replace(/(https?:\/\/[^\s<]+)/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>') 379 + .replace(/\n\n/g, '</p><p>') 380 + .replace(/\n/g, '<br>'); 381 + return `<p>${html}</p>`; 382 + } 383 + 384 + // Desktop: live preview with debounce 385 + let previewTimer: number; 386 + function updateDesktopPreview() { 387 + if (desktopPreviewContent) { 388 + desktopPreviewContent.innerHTML = renderPreview(); 389 + } 390 + } 391 + 392 + contentInput.addEventListener("input", () => { 393 + clearTimeout(previewTimer); 394 + previewTimer = window.setTimeout(updateDesktopPreview, 150); 395 + }); 396 + 397 + // Initial desktop preview 398 + updateDesktopPreview(); 399 + 400 + // Mobile: toggle preview 401 + if (previewBtn && mobilePreview && mobilePreviewContent) { 402 + previewBtn.addEventListener("click", () => { 403 + if (mobilePreview.classList.contains("hidden")) { 404 + mobilePreviewContent.innerHTML = renderPreview(); 405 + mobilePreview.classList.remove("hidden"); 406 + previewBtn.textContent = "edit"; 407 + } else { 408 + mobilePreview.classList.add("hidden"); 409 + previewBtn.textContent = "preview"; 410 + } 411 + }); 412 + } 413 + } 414 + </script> 415 + 416 + <style is:global> 417 + .editor-textarea { 418 + font-family: var(--font-mono); 419 + font-size: 0.9375rem; 420 + line-height: 1.7; 421 + background: var(--color-paper-dim); 422 + color: var(--color-ink); 423 + border: 1px solid var(--color-border); 424 + border-radius: 0.5rem; 425 + resize: vertical; 426 + transition: border-color 0.2s; 427 + } 428 + .editor-textarea:focus { 429 + outline: none; 430 + border-color: var(--color-accent); 431 + } 432 + .editor-textarea::placeholder { 433 + color: var(--color-muted); 434 + } 435 + </style>
+186
src/styles/global.css
··· 1 + @import "tailwindcss"; 2 + 3 + @theme { 4 + --color-ink: #3d3329; 5 + --color-ink-bright: #1a1410; 6 + --color-ink-dim: #6b5d4f; 7 + --color-paper: #d9ccb4; 8 + --color-paper-raised: #cfc1a7; 9 + --color-paper-dim: #d3c5ab; 10 + --color-accent: #7a3b10; 11 + --color-accent-light: #904d22; 12 + --color-muted: #7d6a56; 13 + --color-border: #bfb196; 14 + --color-border-light: #c9bca3; 15 + --font-serif: "Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif; 16 + --font-mono: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace; 17 + } 18 + 19 + html { 20 + scroll-behavior: smooth; 21 + -webkit-font-smoothing: antialiased; 22 + } 23 + 24 + body { 25 + background-image: 26 + /* bright warm highlights — bleached spots where sun hit */ 27 + radial-gradient(ellipse at 25% 15%, rgba(240, 225, 180, 0.7) 0%, transparent 30%), 28 + radial-gradient(ellipse at 70% 5%, rgba(235, 218, 170, 0.5) 0%, transparent 25%), 29 + /* golden amber pool — warm light spill */ 30 + radial-gradient(ellipse at 60% 50%, rgba(200, 165, 100, 0.35) 0%, transparent 35%), 31 + /* cool gray-brown patches — aged/stained areas */ 32 + radial-gradient(ellipse at 10% 70%, rgba(120, 105, 80, 0.3) 0%, transparent 30%), 33 + radial-gradient(ellipse at 85% 80%, rgba(130, 112, 85, 0.25) 0%, transparent 28%), 34 + radial-gradient(ellipse at 45% 90%, rgba(115, 100, 75, 0.2) 0%, transparent 35%), 35 + /* deep shadow wells — foxing and water damage */ 36 + radial-gradient(circle at 15% 50%, rgba(90, 75, 55, 0.2) 0%, transparent 20%), 37 + radial-gradient(circle at 80% 35%, rgba(95, 80, 58, 0.15) 0%, transparent 18%), 38 + /* strong vignette — burned edges */ 39 + radial-gradient(ellipse at 50% 50%, transparent 30%, rgba(100, 85, 60, 0.4) 100%); 40 + } 41 + 42 + /* Fade-in animation */ 43 + @keyframes fadeIn { 44 + from { opacity: 0; transform: translateY(4px); } 45 + to { opacity: 1; transform: translateY(0); } 46 + } 47 + 48 + .fade-in { 49 + animation: fadeIn 0.4s ease-out both; 50 + } 51 + 52 + .fade-in-delay { 53 + animation: fadeIn 0.4s ease-out 0.1s both; 54 + } 55 + 56 + /* Markdown content styles */ 57 + .prose h1 { 58 + font-family: var(--font-serif); 59 + font-size: 2.25rem; 60 + font-weight: 700; 61 + line-height: 1.2; 62 + margin-bottom: 1.5rem; 63 + color: var(--color-ink-bright); 64 + } 65 + 66 + .prose h2 { 67 + font-family: var(--font-serif); 68 + font-size: 1.5rem; 69 + font-weight: 600; 70 + line-height: 1.3; 71 + margin-top: 2.5rem; 72 + margin-bottom: 1rem; 73 + color: var(--color-ink-bright); 74 + } 75 + 76 + .prose h3 { 77 + font-family: var(--font-serif); 78 + font-size: 1.25rem; 79 + font-weight: 600; 80 + margin-top: 2rem; 81 + margin-bottom: 0.75rem; 82 + color: var(--color-ink-bright); 83 + } 84 + 85 + .prose p { 86 + font-family: var(--font-serif); 87 + font-size: 1.0625rem; 88 + line-height: 1.8; 89 + margin-bottom: 1.25rem; 90 + color: var(--color-ink); 91 + } 92 + 93 + @media (min-width: 640px) { 94 + .prose p { 95 + font-size: 1.125rem; 96 + } 97 + } 98 + 99 + .prose a { 100 + color: var(--color-accent); 101 + text-decoration: underline; 102 + text-decoration-color: rgba(122, 59, 16, 0.3); 103 + text-underline-offset: 3px; 104 + transition: text-decoration-color 0.2s; 105 + } 106 + 107 + .prose a:hover { 108 + text-decoration-color: var(--color-accent); 109 + } 110 + 111 + .prose blockquote { 112 + border-left: 2px solid var(--color-accent); 113 + padding-left: 1.25rem; 114 + margin: 1.5rem 0; 115 + font-style: italic; 116 + color: var(--color-ink-dim); 117 + } 118 + 119 + .prose ul, .prose ol { 120 + font-family: var(--font-serif); 121 + font-size: 1.0625rem; 122 + line-height: 1.8; 123 + margin-bottom: 1.25rem; 124 + padding-left: 1.5rem; 125 + color: var(--color-ink); 126 + } 127 + 128 + @media (min-width: 640px) { 129 + .prose ul, .prose ol { 130 + font-size: 1.125rem; 131 + } 132 + } 133 + 134 + .prose li { 135 + margin-bottom: 0.25rem; 136 + } 137 + 138 + .prose pre { 139 + background: var(--color-paper-dim); 140 + color: var(--color-ink); 141 + padding: 1.25rem; 142 + border-radius: 0.5rem; 143 + border: 1px solid var(--color-border); 144 + overflow-x: auto; 145 + -webkit-overflow-scrolling: touch; 146 + font-family: var(--font-mono); 147 + font-size: 0.875rem; 148 + line-height: 1.6; 149 + margin: 1.5rem 0; 150 + } 151 + 152 + .prose code { 153 + font-family: var(--font-mono); 154 + font-size: 0.875em; 155 + background: var(--color-paper-raised); 156 + padding: 0.15rem 0.4rem; 157 + border-radius: 0.25rem; 158 + color: var(--color-accent); 159 + } 160 + 161 + .prose pre code { 162 + background: none; 163 + padding: 0; 164 + color: inherit; 165 + } 166 + 167 + .prose strong { 168 + font-weight: 700; 169 + color: var(--color-ink-bright); 170 + } 171 + 172 + .prose em { 173 + font-style: italic; 174 + } 175 + 176 + .prose hr { 177 + border: none; 178 + border-top: 1px solid var(--color-border); 179 + margin: 2.5rem 0; 180 + } 181 + 182 + .prose img { 183 + max-width: 100%; 184 + border-radius: 0.5rem; 185 + margin: 1.5rem 0; 186 + }
+185
tests/e2e/blog.spec.ts
··· 1 + import { test, expect } from "@playwright/test"; 2 + 3 + test.describe("Blog public pages", () => { 4 + test("homepage loads and shows blog title", async ({ page }) => { 5 + await page.goto("/"); 6 + await expect(page).toHaveTitle(/bkb/); 7 + await expect(page.locator("header a").first()).toBeVisible(); 8 + }); 9 + 10 + test("homepage shows blog entries or empty state", async ({ page }) => { 11 + await page.goto("/"); 12 + const entries = page.locator("article"); 13 + const emptyState = page.locator("text=No entries yet"); 14 + // Either entries exist or empty state shows 15 + const hasEntries = (await entries.count()) > 0; 16 + const isEmpty = await emptyState.isVisible().catch(() => false); 17 + expect(hasEntries || isEmpty).toBe(true); 18 + }); 19 + 20 + test("homepage has profile section with avatar", async ({ page }) => { 21 + await page.goto("/"); 22 + const avatar = page.locator("img[alt]").first(); 23 + await expect(avatar).toBeVisible(); 24 + }); 25 + 26 + test("navigation links are present", async ({ page }) => { 27 + await page.goto("/"); 28 + await expect(page.locator('nav a[href="/write"]')).toBeVisible(); 29 + await expect(page.locator('nav a[href="/rss.xml"]')).toBeVisible(); 30 + await expect(page.locator('nav a[href*="bsky.app"]')).toBeVisible(); 31 + }); 32 + 33 + test("clicking a post navigates to post page", async ({ page }) => { 34 + await page.goto("/"); 35 + const firstPost = page.locator("article a").first(); 36 + if (await firstPost.isVisible()) { 37 + const href = await firstPost.getAttribute("href"); 38 + await firstPost.click(); 39 + await page.waitForURL(`**${href}`); 40 + await expect(page.locator("article h1")).toBeVisible(); 41 + } 42 + }); 43 + 44 + test("post page shows title, date, content, and footer", async ({ page }) => { 45 + await page.goto("/"); 46 + const firstPost = page.locator("article a").first(); 47 + if (await firstPost.isVisible()) { 48 + await firstPost.click(); 49 + await expect(page.locator("article header time")).toBeVisible(); 50 + await expect(page.locator("article h1")).toBeVisible(); 51 + await expect(page.locator(".prose")).toBeVisible(); 52 + await expect(page.locator("article footer")).toBeVisible(); 53 + await expect(page.locator('text=view record')).toBeVisible(); 54 + await expect(page.locator('text=all posts')).toBeVisible(); 55 + } 56 + }); 57 + 58 + test("post page 'all posts' link navigates home", async ({ page }) => { 59 + await page.goto("/"); 60 + const firstPost = page.locator("article a").first(); 61 + if (await firstPost.isVisible()) { 62 + await firstPost.click(); 63 + await page.locator('a:text("all posts")').click(); 64 + await page.waitForURL("/"); 65 + } 66 + }); 67 + }); 68 + 69 + test.describe("RSS feed", () => { 70 + test("returns valid XML with correct content-type", async ({ request }) => { 71 + const res = await request.get("/rss.xml"); 72 + expect(res.status()).toBe(200); 73 + expect(res.headers()["content-type"]).toContain("application/rss+xml"); 74 + 75 + const body = await res.text(); 76 + expect(body).toContain('<?xml version="1.0"'); 77 + expect(body).toContain("<rss"); 78 + expect(body).toContain("<channel>"); 79 + expect(body).toContain("<title>"); 80 + }); 81 + 82 + test("RSS feed contains entry items", async ({ request }) => { 83 + const res = await request.get("/rss.xml"); 84 + const body = await res.text(); 85 + // Should have at least one item if blog has posts 86 + if (body.includes("<item>")) { 87 + expect(body).toContain("<link>"); 88 + expect(body).toContain("<guid"); 89 + expect(body).toContain("<pubDate>"); 90 + } 91 + }); 92 + }); 93 + 94 + test.describe("Write page (unauthenticated)", () => { 95 + test("shows sign-in prompt when not authenticated", async ({ page }) => { 96 + await page.goto("/write"); 97 + await expect(page.locator("text=Sign in to write")).toBeVisible(); 98 + await expect(page.locator('a:text("Sign in with AT Protocol")')).toBeVisible(); 99 + }); 100 + 101 + test("sign-in link points to atauth", async ({ page }) => { 102 + await page.goto("/write"); 103 + const signIn = page.locator('a:text("Sign in with AT Protocol")'); 104 + const href = await signIn.getAttribute("href"); 105 + expect(href).toContain("/auth/proxy/login"); 106 + expect(href).toContain("rd="); 107 + }); 108 + 109 + test("does not show editor when unauthenticated", async ({ page }) => { 110 + await page.goto("/write"); 111 + await expect(page.locator("#editor-form")).not.toBeVisible(); 112 + }); 113 + }); 114 + 115 + test.describe("API endpoints (unauthenticated)", () => { 116 + test("POST /api/publish returns 403 without session", async ({ request }) => { 117 + const res = await request.post("/api/publish", { 118 + data: { title: "Test", content: "Test content" }, 119 + }); 120 + expect(res.status()).toBe(403); 121 + const body = await res.json(); 122 + expect(body.error).toContain("Not authorized"); 123 + }); 124 + 125 + test("POST /api/delete returns 403 without session", async ({ request }) => { 126 + const res = await request.post("/api/delete", { 127 + data: { rkey: "test123" }, 128 + }); 129 + expect(res.status()).toBe(403); 130 + const body = await res.json(); 131 + expect(body.error).toContain("Not authorized"); 132 + }); 133 + 134 + test("GET /api/logout redirects to home", async ({ request }) => { 135 + const res = await request.get("/api/logout", { 136 + maxRedirects: 0, 137 + }); 138 + // 303 redirect to / 139 + expect([303, 302]).toContain(res.status()); 140 + expect(res.headers()["location"]).toBe("/"); 141 + }); 142 + }); 143 + 144 + test.describe("404 handling", () => { 145 + test("returns 404 for nonexistent post", async ({ request }) => { 146 + const res = await request.get("/nonexistent-rkey-99999"); 147 + expect(res.status()).toBe(404); 148 + }); 149 + }); 150 + 151 + test.describe("Mobile responsiveness", () => { 152 + test.use({ viewport: { width: 375, height: 812 } }); 153 + 154 + test("homepage renders properly on mobile", async ({ page }) => { 155 + await page.goto("/"); 156 + await expect(page.locator("nav")).toBeVisible(); 157 + await expect(page.locator("header a").first()).toBeVisible(); 158 + // Nav links should still be visible 159 + await expect(page.locator('nav a[href="/write"]')).toBeVisible(); 160 + }); 161 + 162 + test("post page is readable on mobile", async ({ page }) => { 163 + await page.goto("/"); 164 + const firstPost = page.locator("article a").first(); 165 + if (await firstPost.isVisible()) { 166 + await firstPost.click(); 167 + await expect(page.locator("article h1")).toBeVisible(); 168 + await expect(page.locator(".prose")).toBeVisible(); 169 + // Content should not overflow horizontally 170 + const prose = page.locator(".prose"); 171 + const box = await prose.boundingBox(); 172 + if (box) { 173 + expect(box.width).toBeLessThanOrEqual(375); 174 + } 175 + } 176 + }); 177 + }); 178 + 179 + test.describe("Footer", () => { 180 + test("footer shows AT Protocol and arcnode links", async ({ page }) => { 181 + await page.goto("/"); 182 + await expect(page.locator('footer a[href="https://atproto.com"]')).toBeVisible(); 183 + await expect(page.locator('footer a[href="https://arcnode.xyz"]')).toBeVisible(); 184 + }); 185 + });
+132
tests/unit/auth.test.ts
··· 1 + import { describe, it, expect, vi, beforeEach } from "vitest"; 2 + import { isOwner, getLoginUrl, verifyProxyTicket } from "../../src/lib/auth"; 3 + import { DID } from "../../src/lib/constants"; 4 + 5 + describe("auth", () => { 6 + describe("isOwner", () => { 7 + it("returns true for the allowed DID", () => { 8 + expect(isOwner(DID)).toBe(true); 9 + }); 10 + 11 + it("returns false for a different DID", () => { 12 + expect(isOwner("did:plc:someone-else")).toBe(false); 13 + }); 14 + 15 + it("returns false for empty string", () => { 16 + expect(isOwner("")).toBe(false); 17 + }); 18 + }); 19 + 20 + describe("getLoginUrl", () => { 21 + it("returns a URL pointing to atauth proxy login", () => { 22 + const url = getLoginUrl(); 23 + expect(url).toContain("/auth/proxy/login"); 24 + expect(url).toContain("rd="); 25 + }); 26 + 27 + it("includes encoded redirect to /write", () => { 28 + const url = getLoginUrl(); 29 + expect(url).toContain(encodeURIComponent("https://blog.arcnode.xyz/write")); 30 + }); 31 + }); 32 + 33 + describe("verifyProxyTicket", () => { 34 + beforeEach(() => { 35 + vi.restoreAllMocks(); 36 + }); 37 + 38 + it("returns user when gateway returns 200 with DID headers", async () => { 39 + const headers = new Headers(); 40 + headers.set("x-auth-did", "did:plc:test123"); 41 + headers.set("x-auth-handle", "test.handle"); 42 + 43 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 44 + new Response(null, { status: 200, headers }) 45 + ); 46 + 47 + const result = await verifyProxyTicket("valid-ticket"); 48 + expect(result).toEqual({ did: "did:plc:test123", handle: "test.handle" }); 49 + }); 50 + 51 + it("returns null when gateway returns non-200", async () => { 52 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 53 + new Response(null, { status: 401 }) 54 + ); 55 + 56 + const result = await verifyProxyTicket("bad-ticket"); 57 + expect(result).toBeNull(); 58 + }); 59 + 60 + it("returns null when DID header is missing", async () => { 61 + const headers = new Headers(); 62 + headers.set("x-auth-handle", "test.handle"); 63 + 64 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 65 + new Response(null, { status: 200, headers }) 66 + ); 67 + 68 + const result = await verifyProxyTicket("no-did-ticket"); 69 + expect(result).toBeNull(); 70 + }); 71 + 72 + it("returns null when handle header is missing", async () => { 73 + const headers = new Headers(); 74 + headers.set("x-auth-did", "did:plc:test123"); 75 + 76 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 77 + new Response(null, { status: 200, headers }) 78 + ); 79 + 80 + const result = await verifyProxyTicket("no-handle-ticket"); 81 + expect(result).toBeNull(); 82 + }); 83 + 84 + it("returns null on network error", async () => { 85 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("Network error")); 86 + 87 + const result = await verifyProxyTicket("error-ticket"); 88 + expect(result).toBeNull(); 89 + }); 90 + 91 + it("returns null when handle contains invalid characters", async () => { 92 + const headers = new Headers(); 93 + headers.set("x-auth-did", "did:plc:test123"); 94 + headers.set("x-auth-handle", '<script>alert("xss")</script>'); 95 + 96 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 97 + new Response(null, { status: 200, headers }) 98 + ); 99 + 100 + const result = await verifyProxyTicket("bad-handle-ticket"); 101 + expect(result).toBeNull(); 102 + }); 103 + 104 + it("accepts valid handle format", async () => { 105 + const headers = new Headers(); 106 + headers.set("x-auth-did", "did:plc:test123"); 107 + headers.set("x-auth-handle", "user.bsky.social"); 108 + 109 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 110 + new Response(null, { status: 200, headers }) 111 + ); 112 + 113 + const result = await verifyProxyTicket("valid-handle-ticket"); 114 + expect(result).toEqual({ did: "did:plc:test123", handle: "user.bsky.social" }); 115 + }); 116 + 117 + it("sends correct headers to gateway", async () => { 118 + const fetchSpy = vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 119 + new Response(null, { status: 401 }) 120 + ); 121 + 122 + await verifyProxyTicket("test-ticket"); 123 + 124 + expect(fetchSpy).toHaveBeenCalledOnce(); 125 + const [url, opts] = fetchSpy.mock.calls[0]; 126 + expect(String(url)).toContain("/auth/verify"); 127 + expect(opts?.headers).toHaveProperty("X-Original-URL"); 128 + expect(opts?.headers).toHaveProperty("X-Forwarded-Proto", "https"); 129 + expect(opts?.headers).toHaveProperty("X-Forwarded-Host", "blog.arcnode.xyz"); 130 + }); 131 + }); 132 + });
+869
tests/unit/pds.test.ts
··· 1 + import { describe, it, expect, vi, beforeEach } from "vitest"; 2 + import { getProfile, getBlogEntries, getBlogEntry, getDraftEntries, getRawBlogEntry, isValidRkey, invalidateCache, invalidateEntry, blobUrl, HANDLE, DID, PDS_URL } from "../../src/lib/pds"; 3 + 4 + function mockFetch(responses: Array<{ ok?: boolean; status?: number; body: unknown }>) { 5 + const mock = vi.spyOn(globalThis, "fetch"); 6 + for (const r of responses) { 7 + mock.mockResolvedValueOnce( 8 + new Response(JSON.stringify(r.body), { 9 + status: r.status ?? 200, 10 + headers: { "Content-Type": "application/json" }, 11 + }) 12 + ); 13 + } 14 + return mock; 15 + } 16 + 17 + describe("pds", () => { 18 + beforeEach(() => { 19 + vi.restoreAllMocks(); 20 + invalidateCache(); 21 + }); 22 + 23 + describe("isValidRkey", () => { 24 + it("accepts valid alphanumeric rkeys", () => { 25 + expect(isValidRkey("3abc123")).toBe(true); 26 + expect(isValidRkey("abc-def")).toBe(true); 27 + expect(isValidRkey("abc_def")).toBe(true); 28 + expect(isValidRkey("abc.def")).toBe(true); 29 + expect(isValidRkey("abc~def")).toBe(true); 30 + }); 31 + 32 + it("rejects empty string", () => { 33 + expect(isValidRkey("")).toBe(false); 34 + }); 35 + 36 + it("rejects strings with query injection characters", () => { 37 + expect(isValidRkey("abc&repo=evil")).toBe(false); 38 + expect(isValidRkey("abc?foo=bar")).toBe(false); 39 + expect(isValidRkey("abc/def")).toBe(false); 40 + expect(isValidRkey("abc<script>")).toBe(false); 41 + }); 42 + 43 + it("rejects strings over 512 chars", () => { 44 + expect(isValidRkey("a".repeat(512))).toBe(true); 45 + expect(isValidRkey("a".repeat(513))).toBe(false); 46 + }); 47 + }); 48 + 49 + describe("constants", () => { 50 + it("exports expected HANDLE", () => { 51 + expect(HANDLE).toBe("bkb.arcnode.xyz"); 52 + }); 53 + 54 + it("exports expected DID", () => { 55 + expect(DID).toBe("did:plc:k23ujfuppr3hr4pxvtaz7jro"); 56 + }); 57 + 58 + it("exports expected PDS_URL", () => { 59 + expect(PDS_URL).toBe("https://arcnode.xyz"); 60 + }); 61 + }); 62 + 63 + describe("getProfile", () => { 64 + it("returns profile data from PDS", async () => { 65 + mockFetch([{ 66 + body: { 67 + records: [{ 68 + uri: "at://did:plc:test/app.bsky.actor.profile/self", 69 + cid: "cid123", 70 + value: { 71 + displayName: "Test User", 72 + description: "A bio", 73 + avatar: { ref: { $link: "bafkreiabc" } }, 74 + banner: { ref: { $link: "bafkreibanner" } }, 75 + }, 76 + }], 77 + }, 78 + }]); 79 + 80 + const profile = await getProfile(); 81 + expect(profile.displayName).toBe("Test User"); 82 + expect(profile.description).toBe("A bio"); 83 + expect(profile.avatarUrl).toContain("bafkreiabc"); 84 + expect(profile.bannerUrl).toContain("bafkreibanner"); 85 + }); 86 + 87 + it("returns fallback when no profile record exists", async () => { 88 + mockFetch([{ body: { records: [] } }]); 89 + 90 + const profile = await getProfile(); 91 + expect(profile.displayName).toBe(HANDLE); 92 + expect(profile.description).toBe(""); 93 + expect(profile.avatarUrl).toBeNull(); 94 + expect(profile.bannerUrl).toBeNull(); 95 + }); 96 + 97 + it("returns fallback on PDS fetch error", async () => { 98 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("connection refused")); 99 + 100 + const profile = await getProfile(); 101 + expect(profile.displayName).toBe(HANDLE); 102 + expect(profile.description).toBe(""); 103 + }); 104 + 105 + it("returns fallback on non-200 PDS response", async () => { 106 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 107 + new Response("Internal error", { status: 500 }) 108 + ); 109 + 110 + const profile = await getProfile(); 111 + expect(profile.displayName).toBe(HANDLE); 112 + }); 113 + 114 + it("returns null avatar when blob ref missing", async () => { 115 + mockFetch([{ 116 + body: { 117 + records: [{ 118 + uri: "at://did:plc:test/app.bsky.actor.profile/self", 119 + cid: "cid123", 120 + value: { 121 + displayName: "No Avatar", 122 + description: "No pic", 123 + }, 124 + }], 125 + }, 126 + }]); 127 + 128 + const profile = await getProfile(); 129 + expect(profile.avatarUrl).toBeNull(); 130 + expect(profile.bannerUrl).toBeNull(); 131 + }); 132 + }); 133 + 134 + describe("getBlogEntries", () => { 135 + it("returns public entries sorted newest first", async () => { 136 + mockFetch([{ 137 + body: { 138 + records: [ 139 + { 140 + uri: `at://${DID}/com.whtwnd.blog.entry/older`, 141 + cid: "cid1", 142 + value: { 143 + title: "Older Post", 144 + content: "Content 1", 145 + createdAt: "2025-01-01T00:00:00Z", 146 + visibility: "public", 147 + }, 148 + }, 149 + { 150 + uri: `at://${DID}/com.whtwnd.blog.entry/newer`, 151 + cid: "cid2", 152 + value: { 153 + title: "Newer Post", 154 + content: "Content 2", 155 + createdAt: "2025-06-01T00:00:00Z", 156 + visibility: "public", 157 + }, 158 + }, 159 + ], 160 + }, 161 + }]); 162 + 163 + const entries = await getBlogEntries(); 164 + expect(entries).toHaveLength(2); 165 + expect(entries[0].title).toBe("Newer Post"); 166 + expect(entries[1].title).toBe("Older Post"); 167 + }); 168 + 169 + it("filters out non-public entries", async () => { 170 + mockFetch([{ 171 + body: { 172 + records: [ 173 + { 174 + uri: `at://${DID}/com.whtwnd.blog.entry/pub`, 175 + cid: "cid1", 176 + value: { 177 + title: "Public", 178 + content: "C", 179 + createdAt: "2025-01-01T00:00:00Z", 180 + visibility: "public", 181 + }, 182 + }, 183 + { 184 + uri: `at://${DID}/com.whtwnd.blog.entry/draft`, 185 + cid: "cid2", 186 + value: { 187 + title: "Draft", 188 + content: "C", 189 + createdAt: "2025-01-02T00:00:00Z", 190 + visibility: "author", 191 + }, 192 + }, 193 + ], 194 + }, 195 + }]); 196 + 197 + const entries = await getBlogEntries(); 198 + expect(entries).toHaveLength(1); 199 + expect(entries[0].title).toBe("Public"); 200 + }); 201 + 202 + it("extracts rkey from URI", async () => { 203 + mockFetch([{ 204 + body: { 205 + records: [{ 206 + uri: `at://${DID}/com.whtwnd.blog.entry/3abc123`, 207 + cid: "cid1", 208 + value: { 209 + title: "Test", 210 + content: "C", 211 + createdAt: "2025-01-01T00:00:00Z", 212 + visibility: "public", 213 + }, 214 + }], 215 + }, 216 + }]); 217 + 218 + const entries = await getBlogEntries(); 219 + expect(entries[0].rkey).toBe("3abc123"); 220 + }); 221 + 222 + it("paginates through multiple pages", async () => { 223 + mockFetch([ 224 + { 225 + body: { 226 + records: [{ 227 + uri: `at://${DID}/com.whtwnd.blog.entry/page1`, 228 + cid: "cid1", 229 + value: { 230 + title: "Page 1", 231 + content: "C", 232 + createdAt: "2025-01-01T00:00:00Z", 233 + visibility: "public", 234 + }, 235 + }], 236 + cursor: "next-page", 237 + }, 238 + }, 239 + { 240 + body: { 241 + records: [{ 242 + uri: `at://${DID}/com.whtwnd.blog.entry/page2`, 243 + cid: "cid2", 244 + value: { 245 + title: "Page 2", 246 + content: "C", 247 + createdAt: "2025-01-02T00:00:00Z", 248 + visibility: "public", 249 + }, 250 + }], 251 + }, 252 + }, 253 + ]); 254 + 255 + const entries = await getBlogEntries(); 256 + expect(entries).toHaveLength(2); 257 + }); 258 + 259 + it("returns empty array on PDS fetch error", async () => { 260 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("network error")); 261 + 262 + const entries = await getBlogEntries(); 263 + expect(entries).toEqual([]); 264 + }); 265 + 266 + it("returns empty array on non-200 PDS response", async () => { 267 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 268 + new Response("error", { status: 503 }) 269 + ); 270 + 271 + const entries = await getBlogEntries(); 272 + expect(entries).toEqual([]); 273 + }); 274 + 275 + it("defaults title to Untitled when missing", async () => { 276 + mockFetch([{ 277 + body: { 278 + records: [{ 279 + uri: `at://${DID}/com.whtwnd.blog.entry/notitle`, 280 + cid: "cid1", 281 + value: { 282 + content: "No title here", 283 + createdAt: "2025-01-01T00:00:00Z", 284 + visibility: "public", 285 + }, 286 + }], 287 + }, 288 + }]); 289 + 290 + const entries = await getBlogEntries(); 291 + expect(entries[0].title).toBe("Untitled"); 292 + }); 293 + }); 294 + 295 + describe("getBlogEntry", () => { 296 + it("returns a single entry by rkey", async () => { 297 + mockFetch([{ 298 + body: { 299 + uri: `at://${DID}/com.whtwnd.blog.entry/abc123`, 300 + cid: "cid1", 301 + value: { 302 + title: "My Post", 303 + content: "Hello world", 304 + createdAt: "2025-01-01T00:00:00Z", 305 + visibility: "public", 306 + }, 307 + }, 308 + }]); 309 + 310 + const entry = await getBlogEntry("abc123"); 311 + expect(entry).not.toBeNull(); 312 + expect(entry!.title).toBe("My Post"); 313 + expect(entry!.rkey).toBe("abc123"); 314 + }); 315 + 316 + it("returns null for non-public entry", async () => { 317 + mockFetch([{ 318 + body: { 319 + uri: `at://${DID}/com.whtwnd.blog.entry/private`, 320 + cid: "cid1", 321 + value: { 322 + title: "Private", 323 + content: "Secret", 324 + createdAt: "2025-01-01T00:00:00Z", 325 + visibility: "author", 326 + }, 327 + }, 328 + }]); 329 + 330 + const entry = await getBlogEntry("private"); 331 + expect(entry).toBeNull(); 332 + }); 333 + 334 + it("returns null when record not found", async () => { 335 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 336 + new Response("Not found", { status: 404 }) 337 + ); 338 + 339 + const entry = await getBlogEntry("missing"); 340 + expect(entry).toBeNull(); 341 + }); 342 + 343 + it("returns null on network error", async () => { 344 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("timeout")); 345 + 346 + const entry = await getBlogEntry("error"); 347 + expect(entry).toBeNull(); 348 + }); 349 + }); 350 + 351 + describe("cache behavior", () => { 352 + it("serves cached profile on second call without re-fetching", async () => { 353 + const fetchSpy = mockFetch([{ 354 + body: { 355 + records: [{ 356 + uri: "at://did:plc:test/app.bsky.actor.profile/self", 357 + cid: "cid123", 358 + value: { displayName: "Cached User", description: "Bio" }, 359 + }], 360 + }, 361 + }]); 362 + 363 + const first = await getProfile(); 364 + const second = await getProfile(); 365 + expect(first.displayName).toBe("Cached User"); 366 + expect(second.displayName).toBe("Cached User"); 367 + expect(fetchSpy).toHaveBeenCalledTimes(1); 368 + }); 369 + 370 + it("serves cached entries on second call without re-fetching", async () => { 371 + const fetchSpy = mockFetch([{ 372 + body: { 373 + records: [{ 374 + uri: `at://${DID}/com.whtwnd.blog.entry/cached`, 375 + cid: "cid1", 376 + value: { 377 + title: "Cached", 378 + content: "C", 379 + createdAt: "2025-01-01T00:00:00Z", 380 + visibility: "public", 381 + }, 382 + }], 383 + }, 384 + }]); 385 + 386 + const first = await getBlogEntries(); 387 + const second = await getBlogEntries(); 388 + expect(first).toHaveLength(1); 389 + expect(second).toHaveLength(1); 390 + expect(fetchSpy).toHaveBeenCalledTimes(1); 391 + }); 392 + 393 + it("serves cached single entry on second call without re-fetching", async () => { 394 + const fetchSpy = mockFetch([{ 395 + body: { 396 + uri: `at://${DID}/com.whtwnd.blog.entry/single`, 397 + cid: "cid1", 398 + value: { 399 + title: "Single", 400 + content: "C", 401 + createdAt: "2025-01-01T00:00:00Z", 402 + visibility: "public", 403 + }, 404 + }, 405 + }]); 406 + 407 + const first = await getBlogEntry("single"); 408 + const second = await getBlogEntry("single"); 409 + expect(first!.title).toBe("Single"); 410 + expect(second!.title).toBe("Single"); 411 + expect(fetchSpy).toHaveBeenCalledTimes(1); 412 + }); 413 + 414 + it("invalidateCache clears all caches", async () => { 415 + mockFetch([ 416 + { 417 + body: { 418 + records: [{ 419 + uri: "at://did:plc:test/app.bsky.actor.profile/self", 420 + cid: "cid1", 421 + value: { displayName: "First", description: "" }, 422 + }], 423 + }, 424 + }, 425 + { 426 + body: { 427 + records: [{ 428 + uri: "at://did:plc:test/app.bsky.actor.profile/self", 429 + cid: "cid2", 430 + value: { displayName: "Second", description: "" }, 431 + }], 432 + }, 433 + }, 434 + ]); 435 + 436 + const first = await getProfile(); 437 + expect(first.displayName).toBe("First"); 438 + 439 + invalidateCache(); 440 + 441 + const second = await getProfile(); 442 + expect(second.displayName).toBe("Second"); 443 + }); 444 + 445 + it("invalidateEntry clears specific entry and entries list", async () => { 446 + mockFetch([ 447 + { 448 + body: { 449 + uri: `at://${DID}/com.whtwnd.blog.entry/inv`, 450 + cid: "cid1", 451 + value: { 452 + title: "Original", 453 + content: "C", 454 + createdAt: "2025-01-01T00:00:00Z", 455 + visibility: "public", 456 + }, 457 + }, 458 + }, 459 + { 460 + body: { 461 + uri: `at://${DID}/com.whtwnd.blog.entry/inv`, 462 + cid: "cid2", 463 + value: { 464 + title: "Updated", 465 + content: "C", 466 + createdAt: "2025-01-01T00:00:00Z", 467 + visibility: "public", 468 + }, 469 + }, 470 + }, 471 + ]); 472 + 473 + const first = await getBlogEntry("inv"); 474 + expect(first!.title).toBe("Original"); 475 + 476 + invalidateEntry("inv"); 477 + 478 + const second = await getBlogEntry("inv"); 479 + expect(second!.title).toBe("Updated"); 480 + }); 481 + 482 + it("evicts entry from cache when visibility changes to author", async () => { 483 + mockFetch([ 484 + { 485 + body: { 486 + uri: `at://${DID}/com.whtwnd.blog.entry/vis`, 487 + cid: "cid1", 488 + value: { 489 + title: "Was Public", 490 + content: "C", 491 + createdAt: "2025-01-01T00:00:00Z", 492 + visibility: "public", 493 + }, 494 + }, 495 + }, 496 + ]); 497 + 498 + const first = await getBlogEntry("vis"); 499 + expect(first!.title).toBe("Was Public"); 500 + 501 + // Now the entry was changed to author visibility 502 + mockFetch([{ 503 + body: { 504 + uri: `at://${DID}/com.whtwnd.blog.entry/vis`, 505 + cid: "cid2", 506 + value: { 507 + title: "Was Public", 508 + content: "C", 509 + createdAt: "2025-01-01T00:00:00Z", 510 + visibility: "author", 511 + }, 512 + }, 513 + }]); 514 + 515 + invalidateEntry("vis"); 516 + const second = await getBlogEntry("vis"); 517 + expect(second).toBeNull(); // getBlogEntry filters non-public 518 + }); 519 + 520 + it("evicts from cache on PDS 404 (deleted post)", async () => { 521 + mockFetch([ 522 + { 523 + body: { 524 + uri: `at://${DID}/com.whtwnd.blog.entry/del`, 525 + cid: "cid1", 526 + value: { 527 + title: "Soon Deleted", 528 + content: "C", 529 + createdAt: "2025-01-01T00:00:00Z", 530 + visibility: "public", 531 + }, 532 + }, 533 + }, 534 + ]); 535 + 536 + const first = await getBlogEntry("del"); 537 + expect(first!.title).toBe("Soon Deleted"); 538 + 539 + // Mock 404 for the deleted post 540 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 541 + new Response("Not found", { status: 404 }) 542 + ); 543 + 544 + invalidateEntry("del"); 545 + const second = await getBlogEntry("del"); 546 + expect(second).toBeNull(); 547 + }); 548 + }); 549 + 550 + describe("getDraftEntries", () => { 551 + it("returns only author-visibility entries", async () => { 552 + mockFetch([{ 553 + body: { 554 + records: [ 555 + { 556 + uri: `at://${DID}/com.whtwnd.blog.entry/pub`, 557 + cid: "cid1", 558 + value: { 559 + title: "Public Post", 560 + content: "C", 561 + createdAt: "2025-01-01T00:00:00Z", 562 + visibility: "public", 563 + }, 564 + }, 565 + { 566 + uri: `at://${DID}/com.whtwnd.blog.entry/draft1`, 567 + cid: "cid2", 568 + value: { 569 + title: "My Draft", 570 + content: "WIP", 571 + createdAt: "2025-06-01T00:00:00Z", 572 + visibility: "author", 573 + }, 574 + }, 575 + ], 576 + }, 577 + }]); 578 + 579 + const drafts = await getDraftEntries(); 580 + expect(drafts).toHaveLength(1); 581 + expect(drafts[0].title).toBe("My Draft"); 582 + expect(drafts[0].visibility).toBe("author"); 583 + }); 584 + 585 + it("returns empty array when no drafts exist", async () => { 586 + mockFetch([{ 587 + body: { 588 + records: [ 589 + { 590 + uri: `at://${DID}/com.whtwnd.blog.entry/pub`, 591 + cid: "cid1", 592 + value: { 593 + title: "Public", 594 + content: "C", 595 + createdAt: "2025-01-01T00:00:00Z", 596 + visibility: "public", 597 + }, 598 + }, 599 + ], 600 + }, 601 + }]); 602 + 603 + const drafts = await getDraftEntries(); 604 + expect(drafts).toEqual([]); 605 + }); 606 + 607 + it("returns empty array on fetch error", async () => { 608 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("network error")); 609 + 610 + const drafts = await getDraftEntries(); 611 + expect(drafts).toEqual([]); 612 + }); 613 + 614 + it("sorts drafts newest first", async () => { 615 + mockFetch([{ 616 + body: { 617 + records: [ 618 + { 619 + uri: `at://${DID}/com.whtwnd.blog.entry/older`, 620 + cid: "cid1", 621 + value: { 622 + title: "Older Draft", 623 + content: "C", 624 + createdAt: "2025-01-01T00:00:00Z", 625 + visibility: "author", 626 + }, 627 + }, 628 + { 629 + uri: `at://${DID}/com.whtwnd.blog.entry/newer`, 630 + cid: "cid2", 631 + value: { 632 + title: "Newer Draft", 633 + content: "C", 634 + createdAt: "2025-06-01T00:00:00Z", 635 + visibility: "author", 636 + }, 637 + }, 638 + ], 639 + }, 640 + }]); 641 + 642 + const drafts = await getDraftEntries(); 643 + expect(drafts[0].title).toBe("Newer Draft"); 644 + expect(drafts[1].title).toBe("Older Draft"); 645 + }); 646 + }); 647 + 648 + describe("getRawBlogEntry", () => { 649 + it("returns entry regardless of visibility", async () => { 650 + mockFetch([{ 651 + body: { 652 + uri: `at://${DID}/com.whtwnd.blog.entry/draft`, 653 + cid: "cid1", 654 + value: { 655 + title: "Draft Post", 656 + content: "WIP content", 657 + createdAt: "2025-01-01T00:00:00Z", 658 + visibility: "author", 659 + }, 660 + }, 661 + }]); 662 + 663 + const entry = await getRawBlogEntry("draft"); 664 + expect(entry).not.toBeNull(); 665 + expect(entry!.title).toBe("Draft Post"); 666 + expect(entry!.visibility).toBe("author"); 667 + }); 668 + 669 + it("returns public entries too", async () => { 670 + mockFetch([{ 671 + body: { 672 + uri: `at://${DID}/com.whtwnd.blog.entry/pub`, 673 + cid: "cid1", 674 + value: { 675 + title: "Public Post", 676 + content: "Content", 677 + createdAt: "2025-01-01T00:00:00Z", 678 + visibility: "public", 679 + }, 680 + }, 681 + }]); 682 + 683 + const entry = await getRawBlogEntry("pub"); 684 + expect(entry).not.toBeNull(); 685 + expect(entry!.visibility).toBe("public"); 686 + }); 687 + 688 + it("returns null on 404", async () => { 689 + vi.spyOn(globalThis, "fetch").mockResolvedValueOnce( 690 + new Response("Not found", { status: 404 }) 691 + ); 692 + 693 + const entry = await getRawBlogEntry("missing"); 694 + expect(entry).toBeNull(); 695 + }); 696 + 697 + it("returns null on network error", async () => { 698 + vi.spyOn(globalThis, "fetch").mockRejectedValueOnce(new Error("timeout")); 699 + 700 + const entry = await getRawBlogEntry("error"); 701 + expect(entry).toBeNull(); 702 + }); 703 + 704 + it("defaults visibility to public when missing", async () => { 705 + mockFetch([{ 706 + body: { 707 + uri: `at://${DID}/com.whtwnd.blog.entry/novis`, 708 + cid: "cid1", 709 + value: { 710 + title: "No Visibility", 711 + content: "C", 712 + createdAt: "2025-01-01T00:00:00Z", 713 + }, 714 + }, 715 + }]); 716 + 717 + const entry = await getRawBlogEntry("novis"); 718 + expect(entry!.visibility).toBe("public"); 719 + }); 720 + }); 721 + 722 + describe("blobUrl", () => { 723 + it("constructs correct getBlob URL", () => { 724 + const url = blobUrl("did:plc:abc123", "bafkreiexample"); 725 + expect(url).toBe(`${PDS_URL}/xrpc/com.atproto.sync.getBlob?did=did:plc:abc123&cid=bafkreiexample`); 726 + }); 727 + }); 728 + 729 + describe("blob parsing", () => { 730 + const validBlob = { 731 + $type: "blob", 732 + ref: { $link: "bafkreitest123" }, 733 + mimeType: "image/png", 734 + size: 12345, 735 + }; 736 + 737 + it("parses valid blobs from entry records", async () => { 738 + mockFetch([{ 739 + body: { 740 + uri: `at://${DID}/com.whtwnd.blog.entry/withblob`, 741 + cid: "cid1", 742 + value: { 743 + title: "Post with Image", 744 + content: "![img](url)", 745 + createdAt: "2025-01-01T00:00:00Z", 746 + visibility: "public", 747 + blobs: [validBlob], 748 + }, 749 + }, 750 + }]); 751 + 752 + const entry = await getBlogEntry("withblob"); 753 + expect(entry).not.toBeNull(); 754 + expect(entry!.blobs).toHaveLength(1); 755 + expect(entry!.blobs![0].ref.$link).toBe("bafkreitest123"); 756 + expect(entry!.blobs![0].mimeType).toBe("image/png"); 757 + }); 758 + 759 + it("returns undefined blobs when field is missing", async () => { 760 + mockFetch([{ 761 + body: { 762 + uri: `at://${DID}/com.whtwnd.blog.entry/noblob`, 763 + cid: "cid1", 764 + value: { 765 + title: "No Blobs", 766 + content: "Text only", 767 + createdAt: "2025-01-01T00:00:00Z", 768 + visibility: "public", 769 + }, 770 + }, 771 + }]); 772 + 773 + const entry = await getBlogEntry("noblob"); 774 + expect(entry).not.toBeNull(); 775 + expect(entry!.blobs).toBeUndefined(); 776 + }); 777 + 778 + it("filters out malformed blobs", async () => { 779 + mockFetch([{ 780 + body: { 781 + uri: `at://${DID}/com.whtwnd.blog.entry/badblob`, 782 + cid: "cid1", 783 + value: { 784 + title: "Bad Blobs", 785 + content: "C", 786 + createdAt: "2025-01-01T00:00:00Z", 787 + visibility: "public", 788 + blobs: [ 789 + validBlob, 790 + { $type: "blob", ref: "not-an-object", mimeType: "image/png", size: 100 }, 791 + { $type: "not-blob", ref: { $link: "cid" }, mimeType: "image/png", size: 100 }, 792 + { $type: "blob", ref: { $link: "cid" }, mimeType: 123, size: 100 }, 793 + null, 794 + ], 795 + }, 796 + }, 797 + }]); 798 + 799 + const entry = await getBlogEntry("badblob"); 800 + expect(entry).not.toBeNull(); 801 + expect(entry!.blobs).toHaveLength(1); 802 + expect(entry!.blobs![0].ref.$link).toBe("bafkreitest123"); 803 + }); 804 + 805 + it("parses blobs in getRawBlogEntry", async () => { 806 + mockFetch([{ 807 + body: { 808 + uri: `at://${DID}/com.whtwnd.blog.entry/rawblob`, 809 + cid: "cid1", 810 + value: { 811 + title: "Raw with Blob", 812 + content: "C", 813 + createdAt: "2025-01-01T00:00:00Z", 814 + visibility: "author", 815 + blobs: [validBlob], 816 + }, 817 + }, 818 + }]); 819 + 820 + const entry = await getRawBlogEntry("rawblob"); 821 + expect(entry).not.toBeNull(); 822 + expect(entry!.blobs).toHaveLength(1); 823 + }); 824 + 825 + it("parses blobs in getDraftEntries", async () => { 826 + mockFetch([{ 827 + body: { 828 + records: [{ 829 + uri: `at://${DID}/com.whtwnd.blog.entry/draftblob`, 830 + cid: "cid1", 831 + value: { 832 + title: "Draft with Blob", 833 + content: "C", 834 + createdAt: "2025-01-01T00:00:00Z", 835 + visibility: "author", 836 + blobs: [validBlob], 837 + }, 838 + }], 839 + }, 840 + }]); 841 + 842 + const drafts = await getDraftEntries(); 843 + expect(drafts).toHaveLength(1); 844 + expect(drafts[0].blobs).toHaveLength(1); 845 + }); 846 + 847 + it("parses blobs in getBlogEntries", async () => { 848 + mockFetch([{ 849 + body: { 850 + records: [{ 851 + uri: `at://${DID}/com.whtwnd.blog.entry/listblob`, 852 + cid: "cid1", 853 + value: { 854 + title: "Listed with Blob", 855 + content: "C", 856 + createdAt: "2025-01-01T00:00:00Z", 857 + visibility: "public", 858 + blobs: [validBlob], 859 + }, 860 + }], 861 + }, 862 + }]); 863 + 864 + const entries = await getBlogEntries(); 865 + expect(entries).toHaveLength(1); 866 + expect(entries[0].blobs).toHaveLength(1); 867 + }); 868 + }); 869 + });
+38
tests/unit/rss.test.ts
··· 1 + import { describe, it, expect } from "vitest"; 2 + import { escapeXml } from "../../src/lib/utils"; 3 + 4 + describe("RSS feed utilities", () => { 5 + describe("escapeXml", () => { 6 + it("escapes ampersands", () => { 7 + expect(escapeXml("foo & bar")).toBe("foo &amp; bar"); 8 + }); 9 + 10 + it("escapes angle brackets", () => { 11 + expect(escapeXml("<script>alert('xss')</script>")).toBe( 12 + "&lt;script&gt;alert(&apos;xss&apos;)&lt;/script&gt;" 13 + ); 14 + }); 15 + 16 + it("escapes quotes", () => { 17 + expect(escapeXml('He said "hello"')).toBe("He said &quot;hello&quot;"); 18 + }); 19 + 20 + it("escapes single quotes", () => { 21 + expect(escapeXml("it's")).toBe("it&apos;s"); 22 + }); 23 + 24 + it("handles empty string", () => { 25 + expect(escapeXml("")).toBe(""); 26 + }); 27 + 28 + it("handles string with no special characters", () => { 29 + expect(escapeXml("plain text")).toBe("plain text"); 30 + }); 31 + 32 + it("escapes multiple special chars in sequence", () => { 33 + expect(escapeXml("a&b<c>d\"e'f")).toBe( 34 + "a&amp;b&lt;c&gt;d&quot;e&apos;f" 35 + ); 36 + }); 37 + }); 38 + });
+96
tests/unit/utils.test.ts
··· 1 + import { describe, it, expect } from "vitest"; 2 + import { formatDate, excerpt, escapeXml } from "../../src/lib/utils"; 3 + 4 + describe("utils", () => { 5 + describe("formatDate", () => { 6 + it("formats ISO date to readable string", () => { 7 + const result = formatDate("2025-06-15T12:00:00Z"); 8 + expect(result).toContain("June"); 9 + expect(result).toContain("15"); 10 + expect(result).toContain("2025"); 11 + }); 12 + 13 + it("includes weekday when option set", () => { 14 + const result = formatDate("2025-06-15T12:00:00Z", { weekday: true }); 15 + expect(result).toContain("Sunday"); 16 + }); 17 + 18 + it("omits weekday by default", () => { 19 + const result = formatDate("2025-06-15T12:00:00Z"); 20 + expect(result).not.toContain("Sunday"); 21 + }); 22 + }); 23 + 24 + describe("excerpt", () => { 25 + it("returns short content as-is", () => { 26 + expect(excerpt("Hello world")).toBe("Hello world"); 27 + }); 28 + 29 + it("truncates long content with ellipsis", () => { 30 + const long = "word ".repeat(50); 31 + const result = excerpt(long, 40); 32 + expect(result.length).toBeLessThanOrEqual(41); // 40 + ellipsis char 33 + expect(result).toMatch(/\u2026$/); 34 + }); 35 + 36 + it("strips markdown headings", () => { 37 + expect(excerpt("# Title\nBody text")).toBe("Title Body text"); 38 + }); 39 + 40 + it("strips bold markdown", () => { 41 + expect(excerpt("Some **bold** text")).toBe("Some bold text"); 42 + }); 43 + 44 + it("strips italic markdown", () => { 45 + expect(excerpt("Some *italic* text")).toBe("Some italic text"); 46 + }); 47 + 48 + it("strips inline code", () => { 49 + expect(excerpt("Use `const x = 1` here")).toBe("Use const x = 1 here"); 50 + }); 51 + 52 + it("strips fenced code blocks", () => { 53 + expect(excerpt("Before\n~~~\ncode\n~~~\nAfter")).toBe("Before After"); 54 + }); 55 + 56 + it("collapses newlines to spaces", () => { 57 + expect(excerpt("Line 1\n\nLine 2\nLine 3")).toBe("Line 1 Line 2 Line 3"); 58 + }); 59 + 60 + it("uses default maxLen of 160", () => { 61 + const long = "a ".repeat(200); 62 + const result = excerpt(long); 63 + expect(result.length).toBeLessThanOrEqual(161); 64 + }); 65 + 66 + it("handles empty string", () => { 67 + expect(excerpt("")).toBe(""); 68 + }); 69 + }); 70 + 71 + describe("escapeXml", () => { 72 + it("escapes ampersands", () => { 73 + expect(escapeXml("foo & bar")).toBe("foo &amp; bar"); 74 + }); 75 + 76 + it("escapes angle brackets", () => { 77 + expect(escapeXml("<script>")).toBe("&lt;script&gt;"); 78 + }); 79 + 80 + it("escapes double quotes", () => { 81 + expect(escapeXml('He said "hi"')).toBe("He said &quot;hi&quot;"); 82 + }); 83 + 84 + it("escapes single quotes", () => { 85 + expect(escapeXml("it's")).toBe("it&apos;s"); 86 + }); 87 + 88 + it("handles empty string", () => { 89 + expect(escapeXml("")).toBe(""); 90 + }); 91 + 92 + it("handles string with no special characters", () => { 93 + expect(escapeXml("plain text")).toBe("plain text"); 94 + }); 95 + }); 96 + });
+3
tsconfig.json
··· 1 + { 2 + "extends": "astro/tsconfigs/strict" 3 + }
+9
vitest.config.ts
··· 1 + import { defineConfig } from "vitest/config"; 2 + 3 + export default defineConfig({ 4 + test: { 5 + globals: true, 6 + environment: "node", 7 + include: ["tests/unit/**/*.test.ts"], 8 + }, 9 + });