mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-10-28 07:57:02 +00:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc49a3d899 | |||
| db880d647f | |||
| 6f888387b4 | |||
| 0dd9a65cae | |||
| f39ad015b4 | |||
| a1438cb678 | |||
| 97a5dd3138 | |||
| 6f2cab2f07 | |||
| be6329a64a | |||
| 967b65300d | |||
| 581ceb2b3f | |||
| 9ad5951afc | |||
| 58c4cb2f9e | |||
| ac3643001c | |||
| dd8c53da9a | |||
| e149e618fb | |||
| 39d2828af9 | |||
| 321e07d9fd | |||
| a36a939aef | |||
| c75151e2dc | |||
| aa3357a57d | |||
| de53946896 | |||
| d06bedbbe1 | |||
| d51204148e | |||
| 319761a39e | |||
| 7fbf01a348 | |||
| c22490bd80 | |||
| 860fd6d02e | |||
| c43c524804 | |||
| 66bb938d85 | |||
| 0e6d928496 | |||
| f07982d9f8 | |||
| b92ecfad58 | |||
| 416bde70bc | |||
| 580f7ade15 | |||
| cdffd7c47b | |||
| 5a959cf041 | |||
| 31466546a2 | |||
| 90ead98eaa | |||
| 65e9cb9d5c | |||
| e59076a074 | |||
| 653920dec9 | |||
| 23cedd2d8b | |||
| 70c4182fd8 | |||
| b62b101065 | |||
| b9c929beeb | |||
| 2b6c593289 | |||
| c0b339e406 | |||
| da485f5144 | |||
| 139a8050a5 | |||
| da7b369ffd | |||
| 432da64919 | |||
| 7d0b422200 | |||
| fb90eb0acc |
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix security issue with injection of "javacript:` url in the back button of PDFs
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Implement retry logic for the DO cache to prevent when revalidating content.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix OpenAPISchemas description padding
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@gitbook/colors": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Desaturate text colors by decreasing chroma for the last steps of the color scale
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/react-openapi': patch
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve OpenAPI schema style
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/openapi-parser': patch
|
||||||
|
'@gitbook/react-openapi': patch
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Remove stable from x-stability
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve the error message returned by the revalidate endpoint.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Do not set cookie to identify visitor for insights when disabled.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@gitbook/react-openapi": patch
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improve OpenAPI schemas block ungrouped style. Classnames have changed, please refer to this PR to update GBX.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@gitbook/react-openapi": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Hide deprecated properties in examples
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"gitbook": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Better error handling in cache revalidation.
|
||||||
@@ -19,6 +19,12 @@ inputs:
|
|||||||
deploy:
|
deploy:
|
||||||
description: 'Deploy as main version for all traffic instead of uploading versions'
|
description: 'Deploy as main version for all traffic instead of uploading versions'
|
||||||
required: true
|
required: true
|
||||||
|
commitTag:
|
||||||
|
description: 'Commit branch to associate with the deployment'
|
||||||
|
required: true
|
||||||
|
commitMessage:
|
||||||
|
description: 'Commit message to associate with the deployment'
|
||||||
|
required: true
|
||||||
outputs:
|
outputs:
|
||||||
deployment-url:
|
deployment-url:
|
||||||
description: "Deployment URL"
|
description: "Deployment URL"
|
||||||
@@ -53,6 +59,8 @@ runs:
|
|||||||
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
|
GITBOOK_FONTS_URL: ${{ inputs.opItem }}/GITBOOK_FONTS_URL
|
||||||
- name: Build worker
|
- name: Build worker
|
||||||
run: bun run turbo build:v2:cloudflare
|
run: bun run turbo build:v2:cloudflare
|
||||||
|
env:
|
||||||
|
GITBOOK_RUNTIME: cloudflare
|
||||||
shell: bash
|
shell: bash
|
||||||
- id: deploy
|
- id: deploy
|
||||||
name: Deploy to Cloudflare
|
name: Deploy to Cloudflare
|
||||||
@@ -63,7 +71,7 @@ runs:
|
|||||||
workingDirectory: ./
|
workingDirectory: ./
|
||||||
wranglerVersion: '3.112.0'
|
wranglerVersion: '3.112.0'
|
||||||
environment: ${{ inputs.environment }}
|
environment: ${{ inputs.environment }}
|
||||||
command: ${{ fromJSON(inputs.deploy) == true && 'deploy' || 'versions upload' }} --config ./packages/gitbook-v2/wrangler.toml
|
command: ${{ inputs.deploy == 'true' && 'deploy' || format('versions upload --tag {0} --message "{1}"', inputs.commitTag, inputs.commitMessage) }} --config ./packages/gitbook-v2/wrangler.jsonc
|
||||||
- name: Outputs
|
- name: Outputs
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ runs:
|
|||||||
env:
|
env:
|
||||||
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
|
VERCEL_ORG_ID: ${{ inputs.vercelOrg }}
|
||||||
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
|
VERCEL_PROJECT_ID: ${{ inputs.vercelProject }}
|
||||||
|
GITBOOK_RUNTIME: vercel
|
||||||
- name: Deploy Project Artifacts to Vercel
|
- name: Deploy Project Artifacts to Vercel
|
||||||
id: deploy
|
id: deploy
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ jobs:
|
|||||||
run: bun run turbo gitbook#build:cloudflare
|
run: bun run turbo gitbook#build:cloudflare
|
||||||
env:
|
env:
|
||||||
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ secrets.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY }}
|
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ secrets.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY }}
|
||||||
|
GITBOOK_RUNTIME: cloudflare
|
||||||
- id: deploy
|
- id: deploy
|
||||||
name: Deploy to Cloudflare
|
name: Deploy to Cloudflare
|
||||||
uses: cloudflare/wrangler-action@v3.14.0
|
uses: cloudflare/wrangler-action@v3.14.0
|
||||||
@@ -95,6 +96,8 @@ jobs:
|
|||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
opItem: op://gitbook-open/2c-preview
|
opItem: op://gitbook-open/2c-preview
|
||||||
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||||
|
commitTag: ${{ github.ref == 'refs/heads/main' && 'main' || format('pr{0}', github.event.pull_request.number) }}
|
||||||
|
commitMessage: ${{ github.sha }}
|
||||||
- name: Outputs
|
- name: Outputs
|
||||||
run: |
|
run: |
|
||||||
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Deploy staging
|
- name: Deploy
|
||||||
id: deploy
|
id: deploy
|
||||||
uses: ./.github/composite/deploy-vercel
|
uses: ./.github/composite/deploy-vercel
|
||||||
with:
|
with:
|
||||||
@@ -48,6 +48,8 @@ jobs:
|
|||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
opItem: op://gitbook-open/2c-production
|
opItem: op://gitbook-open/2c-production
|
||||||
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||||
|
commitTag: main
|
||||||
|
commitMessage: ${{ github.sha }}
|
||||||
- name: Outputs
|
- name: Outputs
|
||||||
run: |
|
run: |
|
||||||
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Deploy staging
|
- name: Deploy
|
||||||
id: deploy
|
id: deploy
|
||||||
uses: ./.github/composite/deploy-vercel
|
uses: ./.github/composite/deploy-vercel
|
||||||
with:
|
with:
|
||||||
@@ -48,6 +48,8 @@ jobs:
|
|||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
opItem: op://gitbook-open/2c-staging
|
opItem: op://gitbook-open/2c-staging
|
||||||
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
opServiceAccount: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||||
|
commitTag: main
|
||||||
|
commitMessage: ${{ github.sha }}
|
||||||
- name: Outputs
|
- name: Outputs
|
||||||
run: |
|
run: |
|
||||||
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
echo "URL: ${{ steps.deploy.outputs.deployment-url }}"
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
"packages/colors": {
|
"packages/colors": {
|
||||||
"name": "@gitbook/colors",
|
"name": "@gitbook/colors",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
},
|
},
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
},
|
},
|
||||||
"packages/gitbook": {
|
"packages/gitbook": {
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "0.8.2",
|
"version": "0.9.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "*",
|
"@gitbook/api": "*",
|
||||||
"@gitbook/cache-do": "workspace:*",
|
"@gitbook/cache-do": "workspace:*",
|
||||||
@@ -64,15 +64,15 @@
|
|||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.3",
|
"@radix-ui/react-navigation-menu": "^1.2.3",
|
||||||
"@radix-ui/react-popover": "^1.0.7",
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@sindresorhus/fnv1a": "^3.1.0",
|
"@sindresorhus/fnv1a": "^3.1.0",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@upstash/redis": "^1.27.1",
|
"ai": "^4.2.2",
|
||||||
"ai": "^4.1.46",
|
|
||||||
"ajv": "^8.12.0",
|
|
||||||
"assert-never": "^1.2.1",
|
"assert-never": "^1.2.1",
|
||||||
"bun-types": "^1.1.20",
|
"bun-types": "^1.1.20",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
|
"event-iterator": "^2.0.0",
|
||||||
"framer-motion": "^10.16.14",
|
"framer-motion": "^10.16.14",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jsontoxml": "^1.0.1",
|
"jsontoxml": "^1.0.1",
|
||||||
@@ -81,13 +81,14 @@
|
|||||||
"mathjax": "^3.2.2",
|
"mathjax": "^3.2.2",
|
||||||
"mdast-util-to-markdown": "^2.1.2",
|
"mdast-util-to-markdown": "^2.1.2",
|
||||||
"memoizee": "^0.4.17",
|
"memoizee": "^0.4.17",
|
||||||
"next": "14.2.25",
|
"next": "14.2.26",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"nuqs": "^2.2.3",
|
"nuqs": "^2.2.3",
|
||||||
"object-hash": "^3.0.0",
|
"object-hash": "^3.0.0",
|
||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"p-map": "^7.0.0",
|
"p-map": "^7.0.0",
|
||||||
"parse-cache-control": "^1.0.1",
|
"parse-cache-control": "^1.0.1",
|
||||||
|
"partial-json": "^0.1.7",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-hotkeys-hook": "^4.4.1",
|
"react-hotkeys-hook": "^4.4.1",
|
||||||
@@ -104,6 +105,9 @@
|
|||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
"url-join": "^5.0.0",
|
"url-join": "^5.0.0",
|
||||||
"usehooks-ts": "^3.1.0",
|
"usehooks-ts": "^3.1.0",
|
||||||
|
"zod": "^3.24.2",
|
||||||
|
"zod-to-json-schema": "^3.24.5",
|
||||||
|
"zustand": "^5.0.3",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@argos-ci/playwright": "^4.3.0",
|
"@argos-ci/playwright": "^4.3.0",
|
||||||
@@ -136,14 +140,13 @@
|
|||||||
},
|
},
|
||||||
"packages/gitbook-v2": {
|
"packages/gitbook-v2": {
|
||||||
"name": "gitbook-v2",
|
"name": "gitbook-v2",
|
||||||
"version": "0.2.2",
|
"version": "0.2.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "*",
|
"@gitbook/api": "*",
|
||||||
"@gitbook/cache-tags": "workspace:*",
|
"@gitbook/cache-tags": "workspace:*",
|
||||||
"@sindresorhus/fnv1a": "^3.1.0",
|
"@sindresorhus/fnv1a": "^3.1.0",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"next": "^15.2.3",
|
"next": "canary",
|
||||||
"p-memoize": "^7.1.1",
|
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"rison": "^0.1.1",
|
"rison": "^0.1.1",
|
||||||
@@ -151,7 +154,7 @@
|
|||||||
"warn-once": "^0.1.1",
|
"warn-once": "^0.1.1",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@opennextjs/cloudflare": "^0.5.10",
|
"@opennextjs/cloudflare": "^1.0.0-beta.0",
|
||||||
"@types/rison": "^0.0.9",
|
"@types/rison": "^0.0.9",
|
||||||
"gitbook": "*",
|
"gitbook": "*",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
@@ -180,7 +183,7 @@
|
|||||||
},
|
},
|
||||||
"packages/openapi-parser": {
|
"packages/openapi-parser": {
|
||||||
"name": "@gitbook/openapi-parser",
|
"name": "@gitbook/openapi-parser",
|
||||||
"version": "2.1.1",
|
"version": "2.1.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scalar/openapi-parser": "^0.10.10",
|
"@scalar/openapi-parser": "^0.10.10",
|
||||||
"@scalar/openapi-types": "^0.1.9",
|
"@scalar/openapi-types": "^0.1.9",
|
||||||
@@ -234,7 +237,7 @@
|
|||||||
},
|
},
|
||||||
"packages/react-openapi": {
|
"packages/react-openapi": {
|
||||||
"name": "@gitbook/react-openapi",
|
"name": "@gitbook/react-openapi",
|
||||||
"version": "1.1.6",
|
"version": "1.1.9",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/openapi-parser": "workspace:*",
|
"@gitbook/openapi-parser": "workspace:*",
|
||||||
"@scalar/api-client-react": "^1.2.5",
|
"@scalar/api-client-react": "^1.2.5",
|
||||||
@@ -262,18 +265,18 @@
|
|||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@codemirror/state": "6.4.1",
|
"@codemirror/state": "6.4.1",
|
||||||
"@gitbook/api": "0.106.0",
|
"@gitbook/api": "0.108.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ai-sdk/provider": ["@ai-sdk/provider@1.0.9", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA=="],
|
"@ai-sdk/provider": ["@ai-sdk/provider@1.1.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-0M+qjp+clUD0R1E5eWQFhxEvWLNaOtGQRUaBn8CUABnSKredagq92hUS9VjOzGsTm37xLfpaxl97AVtbeOsHew=="],
|
||||||
|
|
||||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.1.10", "", { "dependencies": { "@ai-sdk/provider": "1.0.9", "eventsource-parser": "^3.0.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q=="],
|
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.4", "", { "dependencies": { "@ai-sdk/provider": "1.1.0", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-13sEGBxB6kgaMPGOgCLYibF6r8iv8mgjhuToFrOTU09bBxbFQd8ZoARarCfJN6VomCUbUvMKwjTBLb1vQnN+WA=="],
|
||||||
|
|
||||||
"@ai-sdk/react": ["@ai-sdk/react@1.1.19", "", { "dependencies": { "@ai-sdk/provider-utils": "2.1.10", "@ai-sdk/ui-utils": "1.1.16", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-zqSOWmJxpB45ZrwZ04+Q7Uo3xeGM0tva2eUYz2T4gv9Yk6MQAfOBA6+scsKg8CyIuUy4M4/C4pCY3eWQf7sfQg=="],
|
"@ai-sdk/react": ["@ai-sdk/react@1.2.6", "", { "dependencies": { "@ai-sdk/provider-utils": "2.2.4", "@ai-sdk/ui-utils": "1.2.5", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["zod"] }, "sha512-5BFChNbcYtcY9MBStcDev7WZRHf0NpTrk8yfSoedWctB3jfWkFd1HECBvdc8w3mUQshF2MumLHtAhRO7IFtGGQ=="],
|
||||||
|
|
||||||
"@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.1.16", "", { "dependencies": { "@ai-sdk/provider": "1.0.9", "@ai-sdk/provider-utils": "2.1.10", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.0.0" }, "optionalPeers": ["zod"] }, "sha512-jfblR2yZVISmNK2zyNzJZFtkgX57WDAUQXcmn3XUBJyo8LFsADu+/vYMn5AOyBi9qJT0RBk11PEtIxIqvByw3Q=="],
|
"@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.2.5", "", { "dependencies": { "@ai-sdk/provider": "1.1.0", "@ai-sdk/provider-utils": "2.2.4", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-XDgqnJcaCkDez7qolvk+PDbs/ceJvgkNkxkOlc9uDWqxfDJxtvCZ+14MP/1qr4IBwGIgKVHzMDYDXvqVhSWLzg=="],
|
||||||
|
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
@@ -287,25 +290,25 @@
|
|||||||
|
|
||||||
"@argos-ci/util": ["@argos-ci/util@2.3.0", "", {}, "sha512-tkxnCpaj7yN9nCFzo9MX0FJ5YjUepEOGYfdvF8COQqp+EdY1qubOPpc4Z0l1B60BlC8YtjQv/oRxHSh1XzxWFg=="],
|
"@argos-ci/util": ["@argos-ci/util@2.3.0", "", {}, "sha512-tkxnCpaj7yN9nCFzo9MX0FJ5YjUepEOGYfdvF8COQqp+EdY1qubOPpc4Z0l1B60BlC8YtjQv/oRxHSh1XzxWFg=="],
|
||||||
|
|
||||||
"@ast-grep/napi": ["@ast-grep/napi@0.34.3", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.34.3", "@ast-grep/napi-darwin-x64": "0.34.3", "@ast-grep/napi-linux-arm64-gnu": "0.34.3", "@ast-grep/napi-linux-arm64-musl": "0.34.3", "@ast-grep/napi-linux-x64-gnu": "0.34.3", "@ast-grep/napi-linux-x64-musl": "0.34.3", "@ast-grep/napi-win32-arm64-msvc": "0.34.3", "@ast-grep/napi-win32-ia32-msvc": "0.34.3", "@ast-grep/napi-win32-x64-msvc": "0.34.3" } }, "sha512-2yrnMrUw3NVm9hf+YKO+BOY3Aci/qau2vDo0lGtA7qGMma18XPUIOTdzm601k5gPHo4MfxPPZLoe9QdTUviANg=="],
|
"@ast-grep/napi": ["@ast-grep/napi@0.35.0", "", { "optionalDependencies": { "@ast-grep/napi-darwin-arm64": "0.35.0", "@ast-grep/napi-darwin-x64": "0.35.0", "@ast-grep/napi-linux-arm64-gnu": "0.35.0", "@ast-grep/napi-linux-arm64-musl": "0.35.0", "@ast-grep/napi-linux-x64-gnu": "0.35.0", "@ast-grep/napi-linux-x64-musl": "0.35.0", "@ast-grep/napi-win32-arm64-msvc": "0.35.0", "@ast-grep/napi-win32-ia32-msvc": "0.35.0", "@ast-grep/napi-win32-x64-msvc": "0.35.0" } }, "sha512-3ucaaSxV6fxXoqHrE/rxAvP1THnDdY5jNzGlnvx+JvnY9C/dSRKc0jlRMRz59N3El572+/yNRUUpAV1T9aBJug=="],
|
||||||
|
|
||||||
"@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.34.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0a8dS+mOP5TYRX3YDiejL1WXWoWga3wpMYZGSs6Ni+SlH1WEO8zyUHe/1z6jNWH8VMHfH9FSCy6+YaPTpiurCA=="],
|
"@ast-grep/napi-darwin-arm64": ["@ast-grep/napi-darwin-arm64@0.35.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-T+MN4Oinc+sXjXCIHzfxDDWY7r2pKgPxM6zVeVlkMTrJV2mJtyKYBIS+CABhRM6kflps2T2I6l4DGaKV/8Ym9w=="],
|
||||||
|
|
||||||
"@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.34.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-n70ha95Fk187B8tgnvR+ZW429EAs/rXktD0839Mdm2+fWjD+JSdB3SADzOGo2cKhuLpLOKnsvfF/bmu+C/p0YQ=="],
|
"@ast-grep/napi-darwin-x64": ["@ast-grep/napi-darwin-x64@0.35.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-pEYiN6JI1HY2uWhMYJ9+3yIMyVYKuYdFzeD+dL7odA3qzK0o9N9AM3/NOt4ynU2EhufaWCJr0P5NoQ636qN6MQ=="],
|
||||||
|
|
||||||
"@ast-grep/napi-linux-arm64-gnu": ["@ast-grep/napi-linux-arm64-gnu@0.34.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-2LBUvMVkBcO/CJ4ItgZ1MOSqDq2fRmhiLwFxIYjhjG7Rz+4ZNdRY+d7Sl596g0BChB4ffNv+M5HS8uUBuUax1w=="],
|
"@ast-grep/napi-linux-arm64-gnu": ["@ast-grep/napi-linux-arm64-gnu@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-NBuzQngABGKz7lhG08IQb+7nPqUx81Ol37xmS3ZhVSdSgM0mtp93rCbgFTkJcAFE8IMfCHQSg7G4g0Iotz4ABQ=="],
|
||||||
|
|
||||||
"@ast-grep/napi-linux-arm64-musl": ["@ast-grep/napi-linux-arm64-musl@0.34.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-vlX4mOyVO1Oy2CdOIFi7HBPwMKzOyLdBpRCcu7pArBOQJkpJ2eS5GR5qSW15f7KPLTkUMpJq7juLz/rP6Rc79Q=="],
|
"@ast-grep/napi-linux-arm64-musl": ["@ast-grep/napi-linux-arm64-musl@0.35.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1EcvHPwyWpCL/96LuItBYGfeI5FaMTRvL+dHbO/hL5q1npqbb5qn+ppJwtNOjTPz8tayvgggxVk9T4C2O7taYA=="],
|
||||||
|
|
||||||
"@ast-grep/napi-linux-x64-gnu": ["@ast-grep/napi-linux-x64-gnu@0.34.3", "", { "os": "linux", "cpu": "x64" }, "sha512-F9TwAfZT/vjjxoPH9Fk8/PTNB95Hm2V/rtva+xMCxkTnhaSh0swM+ku3vavkZ4rwk+LfKPAY37pifEVWg4JPNQ=="],
|
"@ast-grep/napi-linux-x64-gnu": ["@ast-grep/napi-linux-x64-gnu@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-FDzNdlqmQnsiWXhnLxusw5AOfEcEM+5xtmrnAf3SBRFr86JyWD9qsynnFYC2pnP9hlMfifNH2TTmMpyGJW49Xw=="],
|
||||||
|
|
||||||
"@ast-grep/napi-linux-x64-musl": ["@ast-grep/napi-linux-x64-musl@0.34.3", "", { "os": "linux", "cpu": "x64" }, "sha512-2W0ZYsRxdVnwJ/BfnCOSKgfcZ2UFf5I+vF5aMmeAOplOg7vlFHb8XHSa4GqO0MoBfFTGKTH76bKwxLz8d38y1Q=="],
|
"@ast-grep/napi-linux-x64-musl": ["@ast-grep/napi-linux-x64-musl@0.35.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wlmndjfBafT8u5p4DBnoRQyoCSGNuVSz7rT3TqhvlHcPzUouRWMn95epU9B1LNLyjXvr9xHeRjSktyCN28w57Q=="],
|
||||||
|
|
||||||
"@ast-grep/napi-win32-arm64-msvc": ["@ast-grep/napi-win32-arm64-msvc@0.34.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-XRWHlZnO77dEjC7IM5aQRTBC/hc/08Hdl18baJL7smG2dYGJKonUA7BQns6Vt2i63sOEghclkDw6Pq0PD60dbw=="],
|
"@ast-grep/napi-win32-arm64-msvc": ["@ast-grep/napi-win32-arm64-msvc@0.35.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-gkhJeYc4rrZLX2icLxalPikTLMR57DuIYLwLr9g+StHYXIsGHrbfrE6Nnbdd8Izfs34ArFCrcwdaMrGlvOPSeg=="],
|
||||||
|
|
||||||
"@ast-grep/napi-win32-ia32-msvc": ["@ast-grep/napi-win32-ia32-msvc@0.34.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-0jR3QIkuasSrEvsaGtsgMEvgEY8FVe4pemuW77hUOH/mhO4vxFOWny7w4kUaBxQkzJ5z3lbXVoqO4Uv9rpJsRA=="],
|
"@ast-grep/napi-win32-ia32-msvc": ["@ast-grep/napi-win32-ia32-msvc@0.35.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-OdUuRa3chHCZ65y+qALfkUjz0W0Eg21YZ9TyPquV5why07M6HAK38mmYGzLxFH6294SvRQhs+FA/rAfbKeH0jA=="],
|
||||||
|
|
||||||
"@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.34.3", "", { "os": "win32", "cpu": "x64" }, "sha512-OY1Cswkz+0bRZgt9sLjzgyA+y0X164UFjwf5WTYpbCTPUlwdpJP6L7FqJNRMemzQp0qQwwRR7ejpBUF4o/V0Aw=="],
|
"@ast-grep/napi-win32-x64-msvc": ["@ast-grep/napi-win32-x64-msvc@0.35.0", "", { "os": "win32", "cpu": "x64" }, "sha512-pcQRUHqbroTN1oQ56V982a7IZTUUySQYWa2KEyksiifHGuBuitlzcyzFGjT96ThcqD9XW0UVJMvpoF2Qjh006Q=="],
|
||||||
|
|
||||||
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
||||||
|
|
||||||
@@ -623,7 +626,7 @@
|
|||||||
|
|
||||||
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="],
|
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="],
|
||||||
|
|
||||||
"@gitbook/api": ["@gitbook/api@0.106.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-2qA/w18JwHe2fwR2A45q1pEdCZArxqUloegfNibu0xngDhea+iKTXSBrN94wD6Lwkh7cqBp9MvtxC+YMz3hx1g=="],
|
"@gitbook/api": ["@gitbook/api@0.108.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-OytauuT3IMf0zl6rBvIacQ7YphzNhpuNAvEVQbysCGo3BhGYD1xv+vXVmtkAGUnFEAclw2fg2VjWPt3sOlQsAg=="],
|
||||||
|
|
||||||
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
|
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
|
||||||
|
|
||||||
@@ -751,25 +754,25 @@
|
|||||||
|
|
||||||
"@msgpack/msgpack": ["@msgpack/msgpack@3.0.0-beta2", "", {}, "sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw=="],
|
"@msgpack/msgpack": ["@msgpack/msgpack@3.0.0-beta2", "", {}, "sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw=="],
|
||||||
|
|
||||||
"@next/env": ["@next/env@14.2.25", "", {}, "sha512-JnzQ2cExDeG7FxJwqAksZ3aqVJrHjFwZQAEJ9gQZSoEhIow7SNoKZzju/AwQ+PLIR4NY8V0rhcVozx/2izDO0w=="],
|
"@next/env": ["@next/env@14.2.26", "", {}, "sha512-vO//GJ/YBco+H7xdQhzJxF7ub3SUwft76jwaeOyVVQFHCi5DCnkP16WHB+JBylo4vOKPoZBlR94Z8xBxNBdNJA=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@14.2.25", "", { "os": "darwin", "cpu": "arm64" }, "sha512-09clWInF1YRd6le00vt750s3m7SEYNehz9C4PUcSu3bAdCTpjIV4aTYQZ25Ehrr83VR1rZeqtKUPWSI7GfuKZQ=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@14.2.26", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zDJY8gsKEseGAxG+C2hTMT0w9Nk9N1Sk1qV7vXYz9MEiyRoF5ogQX2+vplyUMIfygnjn9/A04I6yrUTRTuRiyQ=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@14.2.25", "", { "os": "darwin", "cpu": "x64" }, "sha512-V+iYM/QR+aYeJl3/FWWU/7Ix4b07ovsQ5IbkwgUK29pTHmq+5UxeDr7/dphvtXEq5pLB/PucfcBNh9KZ8vWbug=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@14.2.26", "", { "os": "darwin", "cpu": "x64" }, "sha512-U0adH5ryLfmTDkahLwG9sUQG2L0a9rYux8crQeC92rPhi3jGQEY47nByQHrVrt3prZigadwj/2HZ1LUUimuSbg=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@14.2.25", "", { "os": "linux", "cpu": "arm64" }, "sha512-LFnV2899PJZAIEHQ4IMmZIgL0FBieh5keMnriMY1cK7ompR+JUd24xeTtKkcaw8QmxmEdhoE5Mu9dPSuDBgtTg=="],
|
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@14.2.26", "", { "os": "linux", "cpu": "arm64" }, "sha512-SINMl1I7UhfHGM7SoRiw0AbwnLEMUnJ/3XXVmhyptzriHbWvPPbbm0OEVG24uUKhuS1t0nvN/DBvm5kz6ZIqpg=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@14.2.25", "", { "os": "linux", "cpu": "arm64" }, "sha512-QC5y5PPTmtqFExcKWKYgUNkHeHE/z3lUsu83di488nyP0ZzQ3Yse2G6TCxz6nNsQwgAx1BehAJTZez+UQxzLfw=="],
|
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@14.2.26", "", { "os": "linux", "cpu": "arm64" }, "sha512-s6JaezoyJK2DxrwHWxLWtJKlqKqTdi/zaYigDXUJ/gmx/72CrzdVZfMvUc6VqnZ7YEvRijvYo+0o4Z9DencduA=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@14.2.25", "", { "os": "linux", "cpu": "x64" }, "sha512-y6/ML4b9eQ2D/56wqatTJN5/JR8/xdObU2Fb1RBidnrr450HLCKr6IJZbPqbv7NXmje61UyxjF5kvSajvjye5w=="],
|
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@14.2.26", "", { "os": "linux", "cpu": "x64" }, "sha512-FEXeUQi8/pLr/XI0hKbe0tgbLmHFRhgXOUiPScz2hk0hSmbGiU8aUqVslj/6C6KA38RzXnWoJXo4FMo6aBxjzg=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@14.2.25", "", { "os": "linux", "cpu": "x64" }, "sha512-sPX0TSXHGUOZFvv96GoBXpB3w4emMqKeMgemrSxI7A6l55VBJp/RKYLwZIB9JxSqYPApqiREaIIap+wWq0RU8w=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@14.2.26", "", { "os": "linux", "cpu": "x64" }, "sha512-BUsomaO4d2DuXhXhgQCVt2jjX4B4/Thts8nDoIruEJkhE5ifeQFtvW5c9JkdOtYvE5p2G0hcwQ0UbRaQmQwaVg=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@14.2.25", "", { "os": "win32", "cpu": "arm64" }, "sha512-ReO9S5hkA1DU2cFCsGoOEp7WJkhFzNbU/3VUF6XxNGUCQChyug6hZdYL/istQgfT/GWE6PNIg9cm784OI4ddxQ=="],
|
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@14.2.26", "", { "os": "win32", "cpu": "arm64" }, "sha512-5auwsMVzT7wbB2CZXQxDctpWbdEnEW/e66DyXO1DcgHxIyhP06awu+rHKshZE+lPLIGiwtjo7bsyeuubewwxMw=="],
|
||||||
|
|
||||||
"@next/swc-win32-ia32-msvc": ["@next/swc-win32-ia32-msvc@14.2.25", "", { "os": "win32", "cpu": "ia32" }, "sha512-DZ/gc0o9neuCDyD5IumyTGHVun2dCox5TfPQI/BJTYwpSNYM3CZDI4i6TOdjeq1JMo+Ug4kPSMuZdwsycwFbAw=="],
|
"@next/swc-win32-ia32-msvc": ["@next/swc-win32-ia32-msvc@14.2.26", "", { "os": "win32", "cpu": "ia32" }, "sha512-GQWg/Vbz9zUGi9X80lOeGsz1rMH/MtFO/XqigDznhhhTfDlDoynCM6982mPCbSlxJ/aveZcKtTlwfAjwhyxDpg=="],
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@14.2.25", "", { "os": "win32", "cpu": "x64" }, "sha512-KSznmS6eFjQ9RJ1nEc66kJvtGIL1iZMYmGEXsZPh2YtnLtqrgdVvKXJY2ScjjoFnG6nGLyPFR0UiEvDwVah4Tw=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@14.2.26", "", { "os": "win32", "cpu": "x64" }, "sha512-2rdB3T1/Gp7bv1eQTTm9d1Y1sv9UuJ2LAwOE0Pe2prHKe32UNscj7YS13fRB37d0GAiGNR+Y7ZcW8YjDI8Ns0w=="],
|
||||||
|
|
||||||
"@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="],
|
"@noble/ciphers": ["@noble/ciphers@1.2.1", "", {}, "sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA=="],
|
||||||
|
|
||||||
@@ -789,9 +792,9 @@
|
|||||||
|
|
||||||
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
|
||||||
|
|
||||||
"@opennextjs/aws": ["@opennextjs/aws@https://pkg.pr.new/@opennextjs/aws@756", { "dependencies": { "@aws-sdk/client-cloudfront": "3.398.0", "@aws-sdk/client-dynamodb": "^3.398.0", "@aws-sdk/client-lambda": "^3.398.0", "@aws-sdk/client-s3": "^3.398.0", "@aws-sdk/client-sqs": "^3.398.0", "@node-minify/core": "^8.0.6", "@node-minify/terser": "^8.0.6", "@tsconfig/node18": "^1.0.1", "aws4fetch": "^1.0.18", "chalk": "^5.3.0", "esbuild": "0.19.2", "express": "5.0.1", "path-to-regexp": "^6.3.0", "urlpattern-polyfill": "^10.0.0" }, "bin": { "open-next": "./dist/index.js" } }],
|
"@opennextjs/aws": ["@opennextjs/aws@3.5.4", "", { "dependencies": { "@ast-grep/napi": "^0.35.0", "@aws-sdk/client-cloudfront": "3.398.0", "@aws-sdk/client-dynamodb": "^3.398.0", "@aws-sdk/client-lambda": "^3.398.0", "@aws-sdk/client-s3": "^3.398.0", "@aws-sdk/client-sqs": "^3.398.0", "@node-minify/core": "^8.0.6", "@node-minify/terser": "^8.0.6", "@tsconfig/node18": "^1.0.1", "aws4fetch": "^1.0.18", "chalk": "^5.3.0", "esbuild": "0.19.2", "express": "5.0.1", "path-to-regexp": "^6.3.0", "urlpattern-polyfill": "^10.0.0", "yaml": "^2.7.0" }, "bin": { "open-next": "dist/index.js" } }, "sha512-QPCTcJ95p0pHUVDjjiB9MGRbOKotaq1Dl9WrmS6/dJt6vb6zdavKFBYdT/WQsTn5wj2RqInim7t6Xc5x+wAO6Q=="],
|
||||||
|
|
||||||
"@opennextjs/cloudflare": ["@opennextjs/cloudflare@0.5.10", "", { "dependencies": { "@ast-grep/napi": "^0.34.1", "@dotenvx/dotenvx": "1.31.0", "@opennextjs/aws": "https://pkg.pr.new/@opennextjs/aws@756", "enquirer": "^2.4.1", "glob": "^11.0.0", "yaml": "^2.7.0" }, "peerDependencies": { "wrangler": "^3.111.0" }, "bin": { "opennextjs-cloudflare": "dist/cli/index.js" } }, "sha512-L/D472YT5OW1LwpFtD/aVXHJYcVPbFVX7XdphlUjCR4+2osSQIDnsuNgfDRydHMDJZMKxeZDc251ZBzUVKpCqw=="],
|
"@opennextjs/cloudflare": ["@opennextjs/cloudflare@1.0.0-beta.0", "", { "dependencies": { "@dotenvx/dotenvx": "1.31.0", "@opennextjs/aws": "3.5.4", "enquirer": "^2.4.1", "glob": "^11.0.0" }, "peerDependencies": { "wrangler": "^3.114.3 || ^4.7.0" }, "bin": { "opennextjs-cloudflare": "dist/cli/index.js" } }, "sha512-hBYUs/v5MHkXqZnKn9rrXnjlf/dgUOhMoaqPHcrc8eS24GC7AFuQvDH1a4v7y54xzF2/rOJVYaq6RcbDQAve+A=="],
|
||||||
|
|
||||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||||
|
|
||||||
@@ -837,6 +840,8 @@
|
|||||||
|
|
||||||
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw=="],
|
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.1.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-popper": "1.2.2", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-visually-hidden": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YAA2cu48EkJZdAMHC0dqo9kialOcRStbtiY4nJPaht7Ptrhcvpo+eDChaM6BIs8kL6a8Z5l5poiqLnXcNduOkA=="],
|
||||||
|
|
||||||
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="],
|
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="],
|
||||||
|
|
||||||
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="],
|
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="],
|
||||||
@@ -1315,8 +1320,6 @@
|
|||||||
|
|
||||||
"@unhead/schema": ["@unhead/schema@1.11.14", "", { "dependencies": { "hookable": "^5.5.3", "zhead": "^2.2.4" } }, "sha512-V9W9u5tF1/+TiLqxu+Qvh1ShoMDkPEwHoEo4DKdDG6ko7YlbzFfDxV6el9JwCren45U/4Vy/4Xi7j8OH02wsiA=="],
|
"@unhead/schema": ["@unhead/schema@1.11.14", "", { "dependencies": { "hookable": "^5.5.3", "zhead": "^2.2.4" } }, "sha512-V9W9u5tF1/+TiLqxu+Qvh1ShoMDkPEwHoEo4DKdDG6ko7YlbzFfDxV6el9JwCren45U/4Vy/4Xi7j8OH02wsiA=="],
|
||||||
|
|
||||||
"@upstash/redis": ["@upstash/redis@1.34.3", "", { "dependencies": { "crypto-js": "^4.2.0" } }, "sha512-VT25TyODGy/8ljl7GADnJoMmtmJ1F8d84UXfGonRRF8fWYJz7+2J6GzW+a6ETGtk4OyuRTt7FRSvFG5GvrfSdQ=="],
|
|
||||||
|
|
||||||
"@vercel/build-utils": ["@vercel/build-utils@9.0.1", "", {}, "sha512-pG/izEqA0AGyqQj6QBfGoTOKU9FPG18sYw9qpncEq00uA+J4Ly4e8ssNbENsXtnXqkMjeoS3c5ncR3jT0bOyiA=="],
|
"@vercel/build-utils": ["@vercel/build-utils@9.0.1", "", {}, "sha512-pG/izEqA0AGyqQj6QBfGoTOKU9FPG18sYw9qpncEq00uA+J4Ly4e8ssNbENsXtnXqkMjeoS3c5ncR3jT0bOyiA=="],
|
||||||
|
|
||||||
"@vercel/error-utils": ["@vercel/error-utils@2.0.3", "", {}, "sha512-CqC01WZxbLUxoiVdh9B/poPbNpY9U+tO1N9oWHwTl5YAZxcqXmmWJ8KNMFItJCUUWdY3J3xv8LvAuQv2KZ5YdQ=="],
|
"@vercel/error-utils": ["@vercel/error-utils@2.0.3", "", {}, "sha512-CqC01WZxbLUxoiVdh9B/poPbNpY9U+tO1N9oWHwTl5YAZxcqXmmWJ8KNMFItJCUUWdY3J3xv8LvAuQv2KZ5YdQ=="],
|
||||||
@@ -1393,7 +1396,7 @@
|
|||||||
|
|
||||||
"agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
|
"agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
|
||||||
|
|
||||||
"ai": ["ai@4.1.47", "", { "dependencies": { "@ai-sdk/provider": "1.0.9", "@ai-sdk/provider-utils": "2.1.10", "@ai-sdk/react": "1.1.19", "@ai-sdk/ui-utils": "1.1.16", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.0.0" }, "optionalPeers": ["react", "zod"] }, "sha512-9UZ8Mkv1HlprCJfQ0Kq+rgKbfkrkDtJjslr1WOHBRzvC70jDJJYp8r0Qq4vlF7zs9VBkGyy8Rhm5zQJJIUjvgw=="],
|
"ai": ["ai@4.3.0", "", { "dependencies": { "@ai-sdk/provider": "1.1.0", "@ai-sdk/provider-utils": "2.2.4", "@ai-sdk/react": "1.2.6", "@ai-sdk/ui-utils": "1.2.5", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["react"] }, "sha512-PxyQYKhWaU3LiZEpeKRaekVonZIbWdKAwgnqm0CSAxy1MFufmYEC5SM5Mc9uiK2DoHcbAL3d1jyaQ2fSDAJL8w=="],
|
||||||
|
|
||||||
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
|
||||||
|
|
||||||
@@ -1585,8 +1588,6 @@
|
|||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="],
|
"cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="],
|
||||||
|
|
||||||
"crypto-js": ["crypto-js@4.2.0", "", {}, "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="],
|
|
||||||
|
|
||||||
"crypto-random-string": ["crypto-random-string@2.0.0", "", {}, "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="],
|
"crypto-random-string": ["crypto-random-string@2.0.0", "", {}, "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="],
|
||||||
|
|
||||||
"css-functions-list": ["css-functions-list@3.2.3", "", {}, "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA=="],
|
"css-functions-list": ["css-functions-list@3.2.3", "", {}, "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA=="],
|
||||||
@@ -2281,7 +2282,7 @@
|
|||||||
|
|
||||||
"mime-types": ["mime-types@3.0.0", "", { "dependencies": { "mime-db": "^1.53.0" } }, "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w=="],
|
"mime-types": ["mime-types@3.0.0", "", { "dependencies": { "mime-db": "^1.53.0" } }, "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w=="],
|
||||||
|
|
||||||
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||||
|
|
||||||
"mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
|
"mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
|
||||||
|
|
||||||
@@ -2319,7 +2320,7 @@
|
|||||||
|
|
||||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||||
|
|
||||||
"next": ["next@14.2.25", "", { "dependencies": { "@next/env": "14.2.25", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "graceful-fs": "^4.2.11", "postcss": "8.4.31", "styled-jsx": "5.1.1" }, "optionalDependencies": { "@next/swc-darwin-arm64": "14.2.25", "@next/swc-darwin-x64": "14.2.25", "@next/swc-linux-arm64-gnu": "14.2.25", "@next/swc-linux-arm64-musl": "14.2.25", "@next/swc-linux-x64-gnu": "14.2.25", "@next/swc-linux-x64-musl": "14.2.25", "@next/swc-win32-arm64-msvc": "14.2.25", "@next/swc-win32-ia32-msvc": "14.2.25", "@next/swc-win32-x64-msvc": "14.2.25" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-N5M7xMc4wSb4IkPvEV5X2BRRXUmhVHNyaXwEM86+voXthSZz8ZiRyQW4p9mwAoAPIm6OzuVZtn7idgEJeAJN3Q=="],
|
"next": ["next@14.2.26", "", { "dependencies": { "@next/env": "14.2.26", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "graceful-fs": "^4.2.11", "postcss": "8.4.31", "styled-jsx": "5.1.1" }, "optionalDependencies": { "@next/swc-darwin-arm64": "14.2.26", "@next/swc-darwin-x64": "14.2.26", "@next/swc-linux-arm64-gnu": "14.2.26", "@next/swc-linux-arm64-musl": "14.2.26", "@next/swc-linux-x64-gnu": "14.2.26", "@next/swc-linux-x64-musl": "14.2.26", "@next/swc-win32-arm64-msvc": "14.2.26", "@next/swc-win32-ia32-msvc": "14.2.26", "@next/swc-win32-x64-msvc": "14.2.26" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-b81XSLihMwCfwiUVRRja3LphLo4uBBMZEzBBWMaISbKTwOmq3wPknIETy/8000tr7Gq4WmbuFYPS7jOYIf+ZJw=="],
|
||||||
|
|
||||||
"next-themes": ["next-themes@0.2.1", "", { "peerDependencies": { "next": "*", "react": "*", "react-dom": "*" } }, "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A=="],
|
"next-themes": ["next-themes@0.2.1", "", { "peerDependencies": { "next": "*", "react": "*", "react-dom": "*" } }, "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A=="],
|
||||||
|
|
||||||
@@ -2393,8 +2394,6 @@
|
|||||||
|
|
||||||
"p-map": ["p-map@7.0.2", "", {}, "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q=="],
|
"p-map": ["p-map@7.0.2", "", {}, "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q=="],
|
||||||
|
|
||||||
"p-memoize": ["p-memoize@7.1.1", "", { "dependencies": { "mimic-fn": "^4.0.0", "type-fest": "^3.0.0" } }, "sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA=="],
|
|
||||||
|
|
||||||
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
|
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
|
||||||
|
|
||||||
"package-json": ["package-json@6.5.0", "", { "dependencies": { "got": "^9.6.0", "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" } }, "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ=="],
|
"package-json": ["package-json@6.5.0", "", { "dependencies": { "got": "^9.6.0", "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" } }, "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ=="],
|
||||||
@@ -2417,6 +2416,8 @@
|
|||||||
|
|
||||||
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
"parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
|
||||||
|
|
||||||
|
"partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="],
|
||||||
|
|
||||||
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
|
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
|
||||||
|
|
||||||
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
|
||||||
@@ -2805,7 +2806,7 @@
|
|||||||
|
|
||||||
"type": ["type@2.7.3", "", {}, "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="],
|
"type": ["type@2.7.3", "", {}, "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="],
|
||||||
|
|
||||||
"type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="],
|
"type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
|
||||||
|
|
||||||
"type-is": ["type-is@2.0.0", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw=="],
|
"type-is": ["type-is@2.0.0", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw=="],
|
||||||
|
|
||||||
@@ -2949,9 +2950,9 @@
|
|||||||
|
|
||||||
"zhead": ["zhead@2.2.4", "", {}, "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag=="],
|
"zhead": ["zhead@2.2.4", "", {}, "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag=="],
|
||||||
|
|
||||||
"zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
|
||||||
|
|
||||||
"zod-to-json-schema": ["zod-to-json-schema@3.24.3", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A=="],
|
"zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="],
|
||||||
|
|
||||||
"zustand": ["zustand@5.0.3", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg=="],
|
"zustand": ["zustand@5.0.3", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg=="],
|
||||||
|
|
||||||
@@ -3679,6 +3680,24 @@
|
|||||||
|
|
||||||
"@radix-ui/react-popper/@radix-ui/react-context": ["@radix-ui/react-context@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A=="],
|
"@radix-ui/react-popper/@radix-ui/react-context": ["@radix-ui/react-context@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.2", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q=="],
|
||||||
|
|
||||||
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="],
|
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.1", "", { "dependencies": { "@radix-ui/react-slot": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg=="],
|
||||||
|
|
||||||
"@react-aria/focus/clsx": ["clsx@2.0.0", "", {}, "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="],
|
"@react-aria/focus/clsx": ["clsx@2.0.0", "", {}, "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q=="],
|
||||||
@@ -3689,12 +3708,20 @@
|
|||||||
|
|
||||||
"@scalar/api-client/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="],
|
"@scalar/api-client/pretty-ms": ["pretty-ms@8.0.0", "", { "dependencies": { "parse-ms": "^3.0.0" } }, "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q=="],
|
||||||
|
|
||||||
|
"@scalar/api-client/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||||
|
|
||||||
"@scalar/code-highlight/remark-gfm": ["remark-gfm@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA=="],
|
"@scalar/code-highlight/remark-gfm": ["remark-gfm@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA=="],
|
||||||
|
|
||||||
"@scalar/oas-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
|
"@scalar/oas-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
|
||||||
|
|
||||||
|
"@scalar/oas-utils/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||||
|
|
||||||
"@scalar/object-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
|
"@scalar/object-utils/flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="],
|
||||||
|
|
||||||
|
"@scalar/types/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||||
|
|
||||||
|
"@scalar/use-hooks/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||||
|
|
||||||
"@shikijs/core/hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
"@shikijs/core/hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
|
||||||
|
|
||||||
"@smithy/abort-controller/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@smithy/abort-controller/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
@@ -3995,7 +4022,7 @@
|
|||||||
|
|
||||||
"gaxios/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"gaxios/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||||
|
|
||||||
"gitbook-v2/next": ["next@15.2.3", "", { "dependencies": { "@next/env": "15.2.3", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.2.3", "@next/swc-darwin-x64": "15.2.3", "@next/swc-linux-arm64-gnu": "15.2.3", "@next/swc-linux-arm64-musl": "15.2.3", "@next/swc-linux-x64-gnu": "15.2.3", "@next/swc-linux-x64-musl": "15.2.3", "@next/swc-win32-arm64-msvc": "15.2.3", "@next/swc-win32-x64-msvc": "15.2.3", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-x6eDkZxk2rPpu46E1ZVUWIBhYCLszmUY6fvHBFcbzJ9dD+qRX6vcHusaqqDlnY+VngKzKbAiG2iRCkPbmi8f7w=="],
|
"gitbook-v2/next": ["next@15.3.0-canary.37", "", { "dependencies": { "@next/env": "15.3.0-canary.37", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.3.0-canary.37", "@next/swc-darwin-x64": "15.3.0-canary.37", "@next/swc-linux-arm64-gnu": "15.3.0-canary.37", "@next/swc-linux-arm64-musl": "15.3.0-canary.37", "@next/swc-linux-x64-gnu": "15.3.0-canary.37", "@next/swc-linux-x64-musl": "15.3.0-canary.37", "@next/swc-win32-arm64-msvc": "15.3.0-canary.37", "@next/swc-win32-x64-msvc": "15.3.0-canary.37", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-K9BJZoFYnp+WqR7jYSCzrBJHOwTXJOED964z0En7qszrjF2HXfa24W2bFAMBwK56JD+h4lUyhpbgBoDiDN+vnA=="],
|
||||||
|
|
||||||
"global-dirs/ini": ["ini@1.3.7", "", {}, "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="],
|
"global-dirs/ini": ["ini@1.3.7", "", {}, "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="],
|
||||||
|
|
||||||
@@ -4045,8 +4072,6 @@
|
|||||||
|
|
||||||
"mdast-util-gfm-task-list-item/mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="],
|
"mdast-util-gfm-task-list-item/mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ=="],
|
||||||
|
|
||||||
"meow/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
|
|
||||||
|
|
||||||
"micro/arg": ["arg@4.1.0", "", {}, "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="],
|
"micro/arg": ["arg@4.1.0", "", {}, "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="],
|
||||||
|
|
||||||
"micro/content-type": ["content-type@1.0.4", "", {}, "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="],
|
"micro/content-type": ["content-type@1.0.4", "", {}, "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="],
|
||||||
@@ -4075,8 +4100,6 @@
|
|||||||
|
|
||||||
"normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
"normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
||||||
|
|
||||||
"onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
|
||||||
|
|
||||||
"p-filter/p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="],
|
"p-filter/p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="],
|
||||||
|
|
||||||
"package-json/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"package-json/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
@@ -4623,6 +4646,8 @@
|
|||||||
|
|
||||||
"@cloudflare/next-on-pages/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
"@cloudflare/next-on-pages/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
|
||||||
|
|
||||||
|
"@cloudflare/next-on-pages/miniflare/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
|
||||||
|
|
||||||
"@codemirror/lang-json/@codemirror/language/@codemirror/view": ["@codemirror/view@6.34.1", "", { "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ=="],
|
"@codemirror/lang-json/@codemirror/language/@codemirror/view": ["@codemirror/view@6.34.1", "", { "dependencies": { "@codemirror/state": "^6.4.0", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ=="],
|
||||||
|
|
||||||
"@codemirror/lang-json/@codemirror/language/@lezer/common": ["@lezer/common@1.2.2", "", {}, "sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw=="],
|
"@codemirror/lang-json/@codemirror/language/@lezer/common": ["@lezer/common@1.2.2", "", {}, "sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw=="],
|
||||||
@@ -4701,6 +4726,8 @@
|
|||||||
|
|
||||||
"@radix-ui/react-navigation-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
"@radix-ui/react-navigation-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-tooltip/@radix-ui/react-popper/@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg=="],
|
||||||
|
|
||||||
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
"@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.1", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g=="],
|
||||||
|
|
||||||
"@scalar/api-client/pretty-ms/parse-ms": ["parse-ms@3.0.0", "", {}, "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw=="],
|
"@scalar/api-client/pretty-ms/parse-ms": ["parse-ms@3.0.0", "", {}, "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw=="],
|
||||||
@@ -4863,23 +4890,23 @@
|
|||||||
|
|
||||||
"gaxios/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
"gaxios/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/env": ["@next/env@15.2.3", "", {}, "sha512-a26KnbW9DFEUsSxAxKBORR/uD9THoYoKbkpFywMN/AFvboTt94b8+g/07T8J6ACsdLag8/PDU60ov4rPxRAixw=="],
|
"gitbook-v2/next/@next/env": ["@next/env@15.3.0-canary.37", "", {}, "sha512-NoG8pEk34zpIphk7vSTZ6zs3rj33jtxWO5E2o+bCE8gjFQunChNnRWP1OPo2cATmnc64aJKcvdX5uOuEtAvoUw=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-uaBhA8aLbXLqwjnsHSkxs353WrRgQgiFjduDpc7YXEU0B54IKx3vU+cxQlYwPCyC8uYEEX7THhtQQsfHnvv8dw=="],
|
"gitbook-v2/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.0-canary.37", "", { "os": "darwin", "cpu": "arm64" }, "sha512-H+gorYP1jSJCmPDpTlQIyLS6GXkA6WZ74H7lxHeXWdAWyP7zv/MmxuhPmsD/RFzYEwZNDSk9jVFpYcOvfWK1Hw=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-pVwKvJ4Zk7h+4hwhqOUuMx7Ib02u3gDX3HXPKIShBi9JlYllI0nU6TWLbPT94dt7FSi6mSBhfc2JrHViwqbOdw=="],
|
"gitbook-v2/next/@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.0-canary.37", "", { "os": "darwin", "cpu": "x64" }, "sha512-zul0GsE7SGga8DdBWHRYzdQC5WST1RMmVJRxutvqCqcm7R/GosIzibrEFE5AkW7XMh6bZCO71r4zKPehTuWFcg=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-50ibWdn2RuFFkOEUmo9NCcQbbV9ViQOrUfG48zHBCONciHjaUKtHcYFiCwBVuzD08fzvzkWuuZkd4AqbvKO7UQ=="],
|
"gitbook-v2/next/@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.3.0-canary.37", "", { "os": "linux", "cpu": "arm64" }, "sha512-ucAOG0sMG2MkNbGTFAI0qncbkci0VE34xjwcpxUT7LUv/rWG83oVOcxcGY5xVbz9V6MpPCxr62FV3I5h6t+w0w=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-2gAPA7P652D3HzR4cLyAuVYwYqjG0mt/3pHSWTCyKZq/N/dJcUAEoNQMyUmwTZWCJRKofB+JPuDVP2aD8w2J6Q=="],
|
"gitbook-v2/next/@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.3.0-canary.37", "", { "os": "linux", "cpu": "arm64" }, "sha512-hVnST5YroTumu1y+UB4HXN2mbmTs5VWqsr8KmQonAc7+Uu9hvjSb79cpCD5B97h0TBb34Z2vr90hN9w0Q06PFA=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ODSKvrdMgAJOVU4qElflYy1KSZRM3M45JVbeZu42TINCMG3anp7YCBn80RkISV6bhzKwcUqLBAmOiWkaGtBA9w=="],
|
"gitbook-v2/next/@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.0-canary.37", "", { "os": "linux", "cpu": "x64" }, "sha512-p7ArUaiTRm5pSqHg60UtJbZUzsOU90idibVRPgnXd+0Kec7n6TClE3pWcIFow9by0bpSi6kmbNmkHf61i0Kerw=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ZR9kLwCWrlYxwEoytqPi1jhPd1TlsSJWAc+H/CJHmHkf2nD92MQpSRIURR1iNgA/kuFSdxB8xIPt4p/T78kwsg=="],
|
"gitbook-v2/next/@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.0-canary.37", "", { "os": "linux", "cpu": "x64" }, "sha512-Egi3swoN3pbseJ3oRGFYs94ICEjmzmY+exWfNlpycjBMWp1m/QzIcIxHTdz2/Lqe5SNGVMrJ8uEDNAD2knqgvw=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-+G2FrDcfm2YDbhDiObDU/qPriWeiz/9cRR0yMWJeTLGGX6/x8oryO3tt7HhodA1vZ8r2ddJPCjtLcpaVl7TE2Q=="],
|
"gitbook-v2/next/@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.3.0-canary.37", "", { "os": "win32", "cpu": "arm64" }, "sha512-gOE0lBeS/ztrSHnXimEp9D5OOTN86moSfMgC05ei/UJSFyT7YEZa4FRYRDzctNEilRJC2DBnxjEpeD+JhDuf6A=="],
|
||||||
|
|
||||||
"gitbook-v2/next/@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-gHYS9tc+G2W0ZC8rBL+H6RdtXIyk40uLiaos0yj5US85FNhbFEndMA2nW3z47nzOWiSvXTZ5kBClc3rD0zJg0w=="],
|
"gitbook-v2/next/@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.0-canary.37", "", { "os": "win32", "cpu": "x64" }, "sha512-J/SjJYN1Nj/olRC0ykfDNKKoxJss4a3Zf340UeyHbmbqeKHvGbT/H0QFMx+3DT+Sqar3PqbyZBLbxpE/QYct1w=="],
|
||||||
|
|
||||||
"gitbook-v2/next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
"gitbook-v2/next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -7,12 +7,12 @@
|
|||||||
"turbo": "^2.4.4",
|
"turbo": "^2.4.4",
|
||||||
"vercel": "^39.3.0"
|
"vercel": "^39.3.0"
|
||||||
},
|
},
|
||||||
"packageManager": "bun@1.2.5",
|
"packageManager": "bun@1.2.8",
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@codemirror/state": "6.4.1",
|
"@codemirror/state": "6.4.1",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"@gitbook/api": "0.106.0"
|
"@gitbook/api": "0.108.0"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
# @gitbook/colors
|
# @gitbook/colors
|
||||||
|
|
||||||
|
## 0.3.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- fb90eb0: Reduce chroma of first color scale step
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"default": "./dist/index.js"
|
"default": "./dist/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.5.3"
|
"typescript": "^5.5.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ export function colorScale(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chromaRatio = index < 8 ? (index + 1) * 0.05 : 1;
|
const chromaRatio = index === 8 || index === 9 ? 1 : index * 0.05;
|
||||||
|
|
||||||
const shade = {
|
const shade = {
|
||||||
L: targetL, // Blend lightness
|
L: targetL, // Blend lightness
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ const nextConfig = {
|
|||||||
// This is needed to throw "forbidden" when the api token expired during revalidation
|
// This is needed to throw "forbidden" when the api token expired during revalidation
|
||||||
authInterrupts: true,
|
authInterrupts: true,
|
||||||
|
|
||||||
// This is needed to use 'use cache'
|
// We don't use 'use cache' as it's not supported in OpenNext yet
|
||||||
useCache: true,
|
// and instead we scope `unstable_cache` to the parameters of the function
|
||||||
|
useCache: false,
|
||||||
|
|
||||||
// Content is fully static, we can cache it in the session memory cache for a long time
|
// Content is fully static, we can cache it in the session memory cache for a long time
|
||||||
staleTimes: {
|
staleTimes: {
|
||||||
@@ -34,6 +35,7 @@ const nextConfig = {
|
|||||||
GITBOOK_SECRET: process.env.GITBOOK_SECRET,
|
GITBOOK_SECRET: process.env.GITBOOK_SECRET,
|
||||||
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: process.env.GITBOOK_IMAGE_RESIZE_SIGNING_KEY,
|
GITBOOK_IMAGE_RESIZE_SIGNING_KEY: process.env.GITBOOK_IMAGE_RESIZE_SIGNING_KEY,
|
||||||
GITBOOK_FONTS_URL: process.env.GITBOOK_FONTS_URL,
|
GITBOOK_FONTS_URL: process.env.GITBOOK_FONTS_URL,
|
||||||
|
GITBOOK_RUNTIME: process.env.GITBOOK_RUNTIME,
|
||||||
|
|
||||||
// Next.js envs
|
// Next.js envs
|
||||||
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY,
|
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY,
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
||||||
import d1TagCache from '@opennextjs/cloudflare/d1-tag-cache';
|
import kvIncrementalCache from '@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache';
|
||||||
import kvIncrementalCache from '@opennextjs/cloudflare/kv-cache';
|
import doQueue from '@opennextjs/cloudflare/overrides/queue/do-queue';
|
||||||
import memoryQueue from '@opennextjs/cloudflare/memory-queue';
|
import doShardedTagCache from '@opennextjs/cloudflare/overrides/tag-cache/do-sharded-tag-cache';
|
||||||
|
|
||||||
export default defineCloudflareConfig({
|
export default defineCloudflareConfig({
|
||||||
incrementalCache: kvIncrementalCache,
|
incrementalCache: kvIncrementalCache,
|
||||||
queue: memoryQueue,
|
tagCache: doShardedTagCache({
|
||||||
tagCache: d1TagCache,
|
baseShardSize: 12,
|
||||||
|
regionalCache: true,
|
||||||
|
shardReplication: {
|
||||||
|
numberOfSoftReplicas: 2,
|
||||||
|
numberOfHardReplicas: 1,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
queue: doQueue,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "^15.2.3",
|
"next": "canary",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"@gitbook/api": "*",
|
"@gitbook/api": "*",
|
||||||
@@ -12,12 +12,11 @@
|
|||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
"warn-once": "^0.1.1",
|
"warn-once": "^0.1.1",
|
||||||
"rison": "^0.1.1",
|
"rison": "^0.1.1",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0"
|
||||||
"p-memoize": "^7.1.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gitbook": "*",
|
"gitbook": "*",
|
||||||
"@opennextjs/cloudflare": "^0.5.10",
|
"@opennextjs/cloudflare": "^1.0.0-beta.0",
|
||||||
"@types/rison": "^0.0.9",
|
"@types/rison": "^0.0.9",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.0",
|
||||||
"postcss": "^8"
|
"postcss": "^8"
|
||||||
@@ -28,7 +27,7 @@
|
|||||||
"build": "next build",
|
"build": "next build",
|
||||||
"build:v2": "next build",
|
"build:v2": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"build:v2:cloudflare": "opennextjs-cloudflare",
|
"build:v2:cloudflare": "opennextjs-cloudflare build",
|
||||||
"dev:v2:cloudflare": "wrangler dev --port 8771",
|
"dev:v2:cloudflare": "wrangler dev --port 8771",
|
||||||
"unit": "bun test",
|
"unit": "bun test",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
|
|||||||
+1
-11
@@ -3,10 +3,9 @@ import {
|
|||||||
generateSitePageMetadata,
|
generateSitePageMetadata,
|
||||||
generateSitePageViewport,
|
generateSitePageViewport,
|
||||||
} from '@/components/SitePage';
|
} from '@/components/SitePage';
|
||||||
import { getCacheTag } from '@gitbook/cache-tags';
|
|
||||||
import { type RouteParams, getPagePathFromParams, getStaticSiteContext } from '@v2/app/utils';
|
import { type RouteParams, getPagePathFromParams, getStaticSiteContext } from '@v2/app/utils';
|
||||||
|
|
||||||
import type { Metadata, Viewport } from 'next';
|
import type { Metadata, Viewport } from 'next';
|
||||||
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
|
||||||
|
|
||||||
export const dynamic = 'force-static';
|
export const dynamic = 'force-static';
|
||||||
|
|
||||||
@@ -15,19 +14,10 @@ type PageProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function Page(props: PageProps) {
|
export default async function Page(props: PageProps) {
|
||||||
'use cache';
|
|
||||||
|
|
||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
const { context } = await getStaticSiteContext(params);
|
const { context } = await getStaticSiteContext(params);
|
||||||
const pathname = getPagePathFromParams(params);
|
const pathname = getPagePathFromParams(params);
|
||||||
|
|
||||||
cacheTag(
|
|
||||||
getCacheTag({
|
|
||||||
tag: 'site',
|
|
||||||
site: context.site.id,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return <SitePage context={context} pageParams={{ pathname }} />;
|
return <SitePage context={context} pageParams={{ pathname }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ import {
|
|||||||
generateSiteLayoutMetadata,
|
generateSiteLayoutMetadata,
|
||||||
generateSiteLayoutViewport,
|
generateSiteLayoutViewport,
|
||||||
} from '@/components/SiteLayout';
|
} from '@/components/SiteLayout';
|
||||||
import { getCacheTag } from '@gitbook/cache-tags';
|
|
||||||
import { type RouteLayoutParams, getStaticSiteContext } from '@v2/app/utils';
|
import { type RouteLayoutParams, getStaticSiteContext } from '@v2/app/utils';
|
||||||
import { GITBOOK_DISABLE_TRACKING } from '@v2/lib/env';
|
import { GITBOOK_DISABLE_TRACKING } from '@v2/lib/env';
|
||||||
import { unstable_cacheTag as cacheTag } from 'next/cache';
|
|
||||||
|
|
||||||
interface SiteStaticLayoutProps {
|
interface SiteStaticLayoutProps {
|
||||||
params: Promise<RouteLayoutParams>;
|
params: Promise<RouteLayoutParams>;
|
||||||
@@ -17,17 +15,8 @@ export default async function SiteStaticLayout({
|
|||||||
params,
|
params,
|
||||||
children,
|
children,
|
||||||
}: React.PropsWithChildren<SiteStaticLayoutProps>) {
|
}: React.PropsWithChildren<SiteStaticLayoutProps>) {
|
||||||
'use cache';
|
|
||||||
|
|
||||||
const { context, visitorAuthClaims } = await getStaticSiteContext(await params);
|
const { context, visitorAuthClaims } = await getStaticSiteContext(await params);
|
||||||
|
|
||||||
cacheTag(
|
|
||||||
getCacheTag({
|
|
||||||
tag: 'site',
|
|
||||||
site: context.site.id,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CustomizationRootLayout customization={context.customization}>
|
<CustomizationRootLayout customization={context.customization}>
|
||||||
<SiteLayout
|
<SiteLayout
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
import { getCloudflareContext as getCloudflareContextOpenNext } from '@opennextjs/cloudflare';
|
||||||
|
import { GITBOOK_RUNTIME } from '../env';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Cloudflare context or null when not running in Cloudflare.
|
||||||
|
*/
|
||||||
|
export function getCloudflareContext() {
|
||||||
|
if (GITBOOK_RUNTIME !== 'cloudflare') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCloudflareContextOpenNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an object representing the current request.
|
||||||
|
*/
|
||||||
|
export function getCloudflareRequestGlobal() {
|
||||||
|
const context = getCloudflareContext();
|
||||||
|
if (!context) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.cf;
|
||||||
|
}
|
||||||
@@ -1,39 +1,52 @@
|
|||||||
import { describe, expect, it, mock } from 'bun:test';
|
import { describe, expect, it, mock } from 'bun:test';
|
||||||
import { memoize } from './memoize';
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
import { withCacheKey, withoutConcurrentExecution } from './memoize';
|
||||||
|
|
||||||
describe('memoize', () => {
|
describe('withoutConcurrentExecution', () => {
|
||||||
it('should memoize the function', async () => {
|
it('should memoize the function based on the cache key', async () => {
|
||||||
const fn = mock(async () => Math.random());
|
|
||||||
const memoized = memoize(fn);
|
|
||||||
expect(await memoized()).toBe(await memoized());
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should memoize the function with different arguments', async () => {
|
|
||||||
const fn = mock(async (a: number, b: number) => a + b);
|
const fn = mock(async (a: number, b: number) => a + b);
|
||||||
const memoized = memoize(fn);
|
const memoized = withoutConcurrentExecution(() => null, fn);
|
||||||
expect(await memoized(1, 2)).toBe(await memoized(1, 2));
|
|
||||||
expect(fn.mock.calls.length).toBe(1);
|
const p1 = memoized('c1', 1, 2);
|
||||||
expect(await memoized(1, 2)).not.toBe(await memoized(2, 3));
|
const p2 = memoized('c1', 1, 2);
|
||||||
|
const p3 = memoized('c3', 2, 3);
|
||||||
|
|
||||||
|
expect(await p1).toBe(await p2);
|
||||||
|
expect(await p1).not.toBe(await p3);
|
||||||
expect(fn.mock.calls.length).toBe(2);
|
expect(fn.mock.calls.length).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should memoize a function complex object', async () => {
|
it('should support caching per request', async () => {
|
||||||
const fn = mock(async (a: { foo: string; bar: number }) => a.foo + a.bar);
|
|
||||||
const memoized = memoize(fn);
|
|
||||||
expect(await memoized({ foo: 'foo', bar: 1 })).toBe(await memoized({ foo: 'foo', bar: 1 }));
|
|
||||||
expect(fn.mock.calls.length).toBe(1);
|
|
||||||
expect(await memoized({ foo: 'foo', bar: 1 })).not.toBe(
|
|
||||||
await memoized({ foo: 'foo', bar: 2 })
|
|
||||||
);
|
|
||||||
expect(fn.mock.calls.length).toBe(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should wrap concurrent async calls', async () => {
|
|
||||||
const fn = mock(async () => Math.random());
|
const fn = mock(async () => Math.random());
|
||||||
const memoized = memoize(fn);
|
|
||||||
const promise1 = memoized();
|
const request1 = { id: 'request1' };
|
||||||
const promise2 = memoized();
|
const request2 = { id: 'request2' };
|
||||||
|
|
||||||
|
const requestContext = new AsyncLocalStorage<{ id: string }>();
|
||||||
|
|
||||||
|
const memoized = withoutConcurrentExecution(() => requestContext.getStore(), fn);
|
||||||
|
|
||||||
|
// Both in the same request
|
||||||
|
const promise1 = requestContext.run(request1, () => memoized('c1'));
|
||||||
|
const promise2 = requestContext.run(request1, () => memoized('c1'));
|
||||||
|
|
||||||
|
// In a different request
|
||||||
|
const promise3 = requestContext.run(request2, () => memoized('c1'));
|
||||||
|
|
||||||
expect(await promise1).toBe(await promise2);
|
expect(await promise1).toBe(await promise2);
|
||||||
|
expect(await promise1).not.toBe(await promise3);
|
||||||
|
expect(fn.mock.calls.length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('withCacheKey', () => {
|
||||||
|
it('should wrap the function by passing the cache key', async () => {
|
||||||
|
const fn = mock(
|
||||||
|
async (cacheKey: string, arg: { a: number; b: number }, c: number) =>
|
||||||
|
`${cacheKey}, result=${arg.a + arg.b + c}`
|
||||||
|
);
|
||||||
|
const memoized = withCacheKey(fn);
|
||||||
|
expect(await memoized({ a: 1, b: 2 }, 4)).toBe('[[["a",1],["b",2]],4], result=7');
|
||||||
expect(fn.mock.calls.length).toBe(1);
|
expect(fn.mock.calls.length).toBe(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,17 +1,61 @@
|
|||||||
import pMemoize from 'p-memoize';
|
/**
|
||||||
|
* Wrap a function by preventing concurrent executions of the same function.
|
||||||
|
* With a logic to work per-request in Cloudflare Workers.
|
||||||
|
*/
|
||||||
|
export function withoutConcurrentExecution<ArgsType extends any[], ReturnType>(
|
||||||
|
getGlobalContext: () => object | null | undefined,
|
||||||
|
wrapped: (...args: ArgsType) => Promise<ReturnType>
|
||||||
|
): (cacheKey: string, ...args: ArgsType) => Promise<ReturnType> {
|
||||||
|
const globalPromiseCache = new WeakMap<object, Map<string, Promise<ReturnType>>>();
|
||||||
|
|
||||||
|
return (key: string, ...args: ArgsType) => {
|
||||||
|
const globalContext = getGlobalContext() ?? globalThis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache storage that is scoped to the current request when executed in Cloudflare Workers,
|
||||||
|
* to avoid "Cannot perform I/O on behalf of a different request" errors.
|
||||||
|
*/
|
||||||
|
const promiseCache =
|
||||||
|
globalPromiseCache.get(globalContext) ?? new Map<string, Promise<ReturnType>>();
|
||||||
|
globalPromiseCache.set(globalContext, promiseCache);
|
||||||
|
|
||||||
|
const concurrent = promiseCache.get(key);
|
||||||
|
if (concurrent) {
|
||||||
|
return concurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const promise = (async () => {
|
||||||
|
try {
|
||||||
|
const result = await wrapped(...args);
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
promiseCache.delete(key);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
promiseCache.set(key, promise);
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We wrap 'use cache' calls in a p-memoize function to avoid
|
* Wrap a function by passing it a cache key that is computed from the function arguments.
|
||||||
* executing the function multiple times when doing concurrent calls.
|
|
||||||
*
|
|
||||||
* Hopefully one day this can be done directly by 'use cache'.
|
|
||||||
*/
|
*/
|
||||||
export function memoize<F extends (...args: any[]) => any>(f: F): F {
|
export function withCacheKey<ArgsType extends any[], ReturnType>(
|
||||||
return pMemoize(f, {
|
wrapped: (cacheKey: string, ...args: ArgsType) => Promise<ReturnType>
|
||||||
cacheKey: (args) => {
|
): (...args: ArgsType) => Promise<ReturnType> {
|
||||||
return JSON.stringify(deepSortValue(args));
|
return (...args: ArgsType) => {
|
||||||
},
|
const cacheKey = getCacheKey(args);
|
||||||
});
|
return wrapped(cacheKey, ...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a cache key from the function arguments.
|
||||||
|
*/
|
||||||
|
function getCacheKey(args: any[]) {
|
||||||
|
return JSON.stringify(deepSortValue(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
function deepSortValue(value: unknown): unknown {
|
function deepSortValue(value: unknown): unknown {
|
||||||
|
|||||||
@@ -179,4 +179,15 @@ export interface GitBookDataFetcher {
|
|||||||
integrationName: string;
|
integrationName: string;
|
||||||
request: api.RenderIntegrationUI;
|
request: api.RenderIntegrationUI;
|
||||||
}): Promise<DataFetcherResponse<api.ContentKitRenderOutput>>;
|
}): Promise<DataFetcherResponse<api.ContentKitRenderOutput>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream an AI response.
|
||||||
|
*/
|
||||||
|
streamAIResponse(params: {
|
||||||
|
organizationId: string;
|
||||||
|
siteId: string;
|
||||||
|
input: api.AIMessageInput[];
|
||||||
|
output: api.AIOutputFormat;
|
||||||
|
model: api.AIModel;
|
||||||
|
}): AsyncGenerator<api.AIStreamResponse, void, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -6,6 +6,14 @@ import 'server-only';
|
|||||||
* and not from the `process.env` object.
|
* and not from the `process.env` object.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime environment.
|
||||||
|
*/
|
||||||
|
export const GITBOOK_RUNTIME = (process.env.GITBOOK_RUNTIME ?? 'unknown') as
|
||||||
|
| 'vercel'
|
||||||
|
| 'cloudflare'
|
||||||
|
| 'unknown';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main host on which GitBook is running.
|
* Main host on which GitBook is running.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ export async function verifyImageSignature(
|
|||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const generator = IMAGE_SIGNATURE_FUNCTIONS[version];
|
const generator = IMAGE_SIGNATURE_FUNCTIONS[version];
|
||||||
const generated = await generator(input);
|
const generated = await generator(input);
|
||||||
|
|
||||||
|
// biome-ignore lint/suspicious/noConsole: we want to log the signature comparison
|
||||||
|
console.log(
|
||||||
|
`comparing image signature for "${input.url}" on identifier "${input.imagesContextId}": "${generated}" (expected) === "${signature}" (actual)`
|
||||||
|
);
|
||||||
return generated === signature;
|
return generated === signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +70,9 @@ const generateSignatureV2: SignFn = async (input) => {
|
|||||||
]
|
]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join(':');
|
.join(':');
|
||||||
return fnv1a(all, { utf8Buffer: fnv1aUtf8Buffer }).toString(16);
|
|
||||||
|
const signature = fnv1a(all, { utf8Buffer: fnv1aUtf8Buffer }).toString(16);
|
||||||
|
return signature;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reused buffer for FNV-1a hashing in the v1 algorithm
|
// Reused buffer for FNV-1a hashing in the v1 algorithm
|
||||||
|
|||||||
@@ -167,6 +167,23 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) {
|
|||||||
// (customization override, theme, etc)
|
// (customization override, theme, etc)
|
||||||
let routeType: 'dynamic' | 'static' = 'static';
|
let routeType: 'dynamic' | 'static' = 'static';
|
||||||
|
|
||||||
|
// We pick only stable data from the siteURL data to prevent re-rendering of
|
||||||
|
// the root layout when changing pages..
|
||||||
|
const stableSiteURLData: SiteURLData = {
|
||||||
|
site: siteURLData.site,
|
||||||
|
siteSection: siteURLData.siteSection,
|
||||||
|
siteSpace: siteURLData.siteSpace,
|
||||||
|
siteBasePath: siteURLData.siteBasePath,
|
||||||
|
basePath: siteURLData.basePath,
|
||||||
|
space: siteURLData.space,
|
||||||
|
organization: siteURLData.organization,
|
||||||
|
changeRequest: siteURLData.changeRequest,
|
||||||
|
revision: siteURLData.revision,
|
||||||
|
shareKey: siteURLData.shareKey,
|
||||||
|
apiToken: siteURLData.apiToken,
|
||||||
|
imagesContextId: imagesContextId,
|
||||||
|
};
|
||||||
|
|
||||||
const requestHeaders = new Headers(request.headers);
|
const requestHeaders = new Headers(request.headers);
|
||||||
requestHeaders.set(MiddlewareHeaders.RouteType, routeType);
|
requestHeaders.set(MiddlewareHeaders.RouteType, routeType);
|
||||||
requestHeaders.set(MiddlewareHeaders.URLMode, mode);
|
requestHeaders.set(MiddlewareHeaders.URLMode, mode);
|
||||||
@@ -174,7 +191,7 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) {
|
|||||||
MiddlewareHeaders.SiteURL,
|
MiddlewareHeaders.SiteURL,
|
||||||
`${siteCanonicalURL.origin}${siteURLData.basePath}`
|
`${siteCanonicalURL.origin}${siteURLData.basePath}`
|
||||||
);
|
);
|
||||||
requestHeaders.set(MiddlewareHeaders.SiteURLData, JSON.stringify(siteURLData));
|
requestHeaders.set(MiddlewareHeaders.SiteURLData, JSON.stringify(stableSiteURLData));
|
||||||
|
|
||||||
// Preview of customization/theme
|
// Preview of customization/theme
|
||||||
const customization = siteRequestURL.searchParams.get('customization');
|
const customization = siteRequestURL.searchParams.get('customization');
|
||||||
@@ -204,23 +221,6 @@ async function serveSiteRoutes(requestURL: URL, request: NextRequest) {
|
|||||||
);
|
);
|
||||||
routeType = routeTypeFromPathname ?? routeType;
|
routeType = routeTypeFromPathname ?? routeType;
|
||||||
|
|
||||||
// We pick only stable data from the siteURL data to prevent re-rendering of
|
|
||||||
// the root layout when changing pages..
|
|
||||||
const stableSiteURLData: SiteURLData = {
|
|
||||||
site: siteURLData.site,
|
|
||||||
siteSection: siteURLData.siteSection,
|
|
||||||
siteSpace: siteURLData.siteSpace,
|
|
||||||
siteBasePath: siteURLData.siteBasePath,
|
|
||||||
basePath: siteURLData.basePath,
|
|
||||||
space: siteURLData.space,
|
|
||||||
organization: siteURLData.organization,
|
|
||||||
changeRequest: siteURLData.changeRequest,
|
|
||||||
revision: siteURLData.revision,
|
|
||||||
shareKey: siteURLData.shareKey,
|
|
||||||
apiToken: siteURLData.apiToken,
|
|
||||||
imagesContextId: imagesContextId,
|
|
||||||
};
|
|
||||||
|
|
||||||
const route = [
|
const route = [
|
||||||
'sites',
|
'sites',
|
||||||
routeType,
|
routeType,
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
"main": ".open-next/worker.js",
|
||||||
|
"name": "gitbook-open-v2",
|
||||||
|
"compatibility_date": "2025-03-11",
|
||||||
|
"compatibility_flags": ["nodejs_compat", "allow_importable_env"],
|
||||||
|
"assets": {
|
||||||
|
"directory": ".open-next/assets",
|
||||||
|
"binding": "ASSETS"
|
||||||
|
},
|
||||||
|
"observability": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"durable_objects": {
|
||||||
|
"bindings": [
|
||||||
|
{
|
||||||
|
"name": "NEXT_CACHE_DO_QUEUE",
|
||||||
|
"class_name": "DOQueueHandler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "NEXT_TAG_CACHE_DO_SHARDED",
|
||||||
|
"class_name": "DOShardedTagCache"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"migrations": [
|
||||||
|
{
|
||||||
|
"tag": "v1",
|
||||||
|
"new_sqlite_classes": ["DOQueueHandler", "DOShardedTagCache"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"preview": {
|
||||||
|
"kv_namespaces": [
|
||||||
|
{
|
||||||
|
// gitbook-open-v2-cache-preview
|
||||||
|
"binding": "NEXT_INC_CACHE_KV",
|
||||||
|
"id": "b7dd9cf58bf2458f84812a2d83b3760c"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"d1_databases": [
|
||||||
|
{
|
||||||
|
"binding": "NEXT_CACHE_D1",
|
||||||
|
"database_id": "f59ddb40-ad72-4312-9395-0ac6a129af8e",
|
||||||
|
"database_name": "gitbook-open-v2-tags-preview"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"binding": "WORKER_SELF_REFERENCE",
|
||||||
|
"service": "gitbook-open-v2-preview"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binding": "GITBOOK_API",
|
||||||
|
"service": "gitbook-x-prod-api-cache"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"staging": {
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"pattern": "open-2c.gitbook-staging.com/*",
|
||||||
|
"zone_name": "gitbook-staging.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "static-2c.gitbook-staging.com/*",
|
||||||
|
"zone_name": "gitbook-staging.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kv_namespaces": [
|
||||||
|
{
|
||||||
|
// gitbook-open-v2-cache-staging
|
||||||
|
"binding": "NEXT_INC_CACHE_KV",
|
||||||
|
"id": "a446e25f12b741afb185f1e5b4474f0a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"d1_databases": [
|
||||||
|
{
|
||||||
|
"binding": "NEXT_CACHE_D1",
|
||||||
|
"database_id": "9df62e39-1f35-4066-83aa-e9b8ed3ac8d5",
|
||||||
|
"database_name": "gitbook-open-v2-tags-staging"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"binding": "WORKER_SELF_REFERENCE",
|
||||||
|
"service": "gitbook-open-v2-staging"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binding": "GITBOOK_API",
|
||||||
|
"service": "gitbook-x-staging-api-cache"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tail_consumers": [
|
||||||
|
{
|
||||||
|
"service": "gitbook-x-staging-tail"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"pattern": "open-2c.gitbook.com/*",
|
||||||
|
"zone_name": "gitbook.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "static-2c.gitbook.com/*",
|
||||||
|
"zone_name": "gitbook.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kv_namespaces": [
|
||||||
|
{
|
||||||
|
// gitbook-open-v2-cache-production
|
||||||
|
"binding": "NEXT_INC_CACHE_KV",
|
||||||
|
"id": "72379746280d4e79acf24440eea950dc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"d1_databases": [
|
||||||
|
{
|
||||||
|
"binding": "NEXT_CACHE_D1",
|
||||||
|
"database_id": "a6f16fce-5f45-43a9-89a4-7b83ddf25b77",
|
||||||
|
"database_name": "gitbook-open-v2-tags-production"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": [
|
||||||
|
{
|
||||||
|
"binding": "WORKER_SELF_REFERENCE",
|
||||||
|
"service": "gitbook-open-v2-production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"binding": "GITBOOK_API",
|
||||||
|
"service": "gitbook-x-prod-api-cache"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tail_consumers": [
|
||||||
|
{
|
||||||
|
"service": "gitbook-x-prod-tail"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
main = ".open-next/worker.js"
|
|
||||||
name = "gitbook-open-v2"
|
|
||||||
compatibility_date = "2025-03-11"
|
|
||||||
compatibility_flags = ["nodejs_compat", "allow_importable_env"]
|
|
||||||
assets = { directory = ".open-next/assets", binding = "ASSETS" }
|
|
||||||
observability = { enabled = true }
|
|
||||||
|
|
||||||
[env.preview]
|
|
||||||
kv_namespaces = [
|
|
||||||
{ binding = "NEXT_CACHE_WORKERS_KV", id = "b7dd9cf58bf2458f84812a2d83b3760c" } # gitbook-open-v2-cache-preview
|
|
||||||
]
|
|
||||||
d1_databases = [
|
|
||||||
{ binding = "NEXT_CACHE_D1", database_id = "f59ddb40-ad72-4312-9395-0ac6a129af8e", database_name = "gitbook-open-v2-tags-preview" }
|
|
||||||
]
|
|
||||||
services = [
|
|
||||||
{ binding = "NEXT_CACHE_REVALIDATION_WORKER", service = "gitbook-open-v2-preview" },
|
|
||||||
{ binding = "GITBOOK_API", service = "gitbook-x-prod-api-cache" }
|
|
||||||
]
|
|
||||||
|
|
||||||
[env.staging]
|
|
||||||
routes = [
|
|
||||||
{ pattern = "open-2c.gitbook-staging.com/*", zone_name = "gitbook-staging.com" },
|
|
||||||
{ pattern = "static-2c.gitbook-staging.com/*", zone_name = "gitbook-staging.com" }
|
|
||||||
]
|
|
||||||
kv_namespaces = [
|
|
||||||
{ binding = "NEXT_CACHE_WORKERS_KV", id = "a446e25f12b741afb185f1e5b4474f0a" } # gitbook-open-v2-cache-staging
|
|
||||||
]
|
|
||||||
d1_databases = [
|
|
||||||
{ binding = "NEXT_CACHE_D1", database_id = "9df62e39-1f35-4066-83aa-e9b8ed3ac8d5", database_name = "gitbook-open-v2-tags-staging" }
|
|
||||||
]
|
|
||||||
services = [
|
|
||||||
{ binding = "NEXT_CACHE_REVALIDATION_WORKER", service = "gitbook-open-v2-staging" },
|
|
||||||
{ binding = "GITBOOK_API", service = "gitbook-x-staging-api-cache" }
|
|
||||||
]
|
|
||||||
|
|
||||||
[env.production]
|
|
||||||
routes = [
|
|
||||||
{ pattern = "open-2c.gitbook.com/*", zone_name = "gitbook.com" },
|
|
||||||
{ pattern = "static-2c.gitbook.com/*", zone_name = "gitbook.com" }
|
|
||||||
]
|
|
||||||
kv_namespaces = [
|
|
||||||
{ binding = "NEXT_CACHE_WORKERS_KV", id = "72379746280d4e79acf24440eea950dc" } # gitbook-open-v2-cache-production
|
|
||||||
]
|
|
||||||
d1_databases = [
|
|
||||||
{ binding = "NEXT_CACHE_D1", database_id = "a6f16fce-5f45-43a9-89a4-7b83ddf25b77", database_name = "gitbook-open-v2-tags-production" }
|
|
||||||
]
|
|
||||||
services = [
|
|
||||||
{ binding = "NEXT_CACHE_REVALIDATION_WORKER", service = "gitbook-open-v2-production" },
|
|
||||||
{ binding = "GITBOOK_API", service = "gitbook-x-prod-api-cache" }
|
|
||||||
]
|
|
||||||
@@ -1,5 +1,27 @@
|
|||||||
# gitbook
|
# gitbook
|
||||||
|
|
||||||
|
## 0.9.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- da7b369: Fix missing headers in OpenAPIResponses
|
||||||
|
- 139a805: Fix OpenAPI enum display
|
||||||
|
- Updated dependencies [da7b369]
|
||||||
|
- Updated dependencies [da485f5]
|
||||||
|
- Updated dependencies [139a805]
|
||||||
|
- @gitbook/react-openapi@1.1.9
|
||||||
|
|
||||||
|
## 0.9.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- fb90eb0: Limit tinted background on bold theme to sites with filled sidebar
|
||||||
|
- 7d0b422: Handle grouped OpenAPISchemas
|
||||||
|
- Updated dependencies [7d0b422]
|
||||||
|
- Updated dependencies [fb90eb0]
|
||||||
|
- @gitbook/react-openapi@1.1.8
|
||||||
|
- @gitbook/colors@0.3.1
|
||||||
|
|
||||||
## 0.9.0
|
## 0.9.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -92,11 +92,6 @@ const testCases: TestsCase[] = [
|
|||||||
contentBaseURL: 'https://book.character.ai',
|
contentBaseURL: 'https://book.character.ai',
|
||||||
tests: [{ name: 'Home', url: '/', run: waitForCookiesDialog }],
|
tests: [{ name: 'Home', url: '/', run: waitForCookiesDialog }],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'docs.tradeonnova.io',
|
|
||||||
contentBaseURL: 'https://docs.tradeonnova.io',
|
|
||||||
tests: [{ name: 'Home', url: '/' }],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'azcoiner.gitbook.io',
|
name: 'azcoiner.gitbook.io',
|
||||||
contentBaseURL: 'https://azcoiner.gitbook.io',
|
contentBaseURL: 'https://azcoiner.gitbook.io',
|
||||||
|
|||||||
@@ -276,6 +276,9 @@ export function getCustomizationURL(partial: DeepPartial<SiteCustomizationSettin
|
|||||||
internationalization: {
|
internationalization: {
|
||||||
locale: CustomizationLocale.En,
|
locale: CustomizationLocale.En,
|
||||||
},
|
},
|
||||||
|
insights: {
|
||||||
|
trackingCookie: true,
|
||||||
|
},
|
||||||
favicon: {},
|
favicon: {},
|
||||||
header: {
|
header: {
|
||||||
preset: CustomizationHeaderPreset.Default,
|
preset: CustomizationHeaderPreset.Default,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ module.exports = {
|
|||||||
GITBOOK_ICONS_URL: process.env.GITBOOK_ICONS_URL,
|
GITBOOK_ICONS_URL: process.env.GITBOOK_ICONS_URL,
|
||||||
GITBOOK_ICONS_TOKEN: process.env.GITBOOK_ICONS_TOKEN,
|
GITBOOK_ICONS_TOKEN: process.env.GITBOOK_ICONS_TOKEN,
|
||||||
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY,
|
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: process.env.NEXT_SERVER_ACTIONS_ENCRYPTION_KEY,
|
||||||
|
GITBOOK_RUNTIME: process.env.GITBOOK_RUNTIME,
|
||||||
},
|
},
|
||||||
|
|
||||||
webpack(config) {
|
webpack(config) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "0.9.0",
|
"version": "0.9.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "env-cmd --silent -f ../../.env.local next dev",
|
"dev": "env-cmd --silent -f ../../.env.local next dev",
|
||||||
@@ -29,12 +29,11 @@
|
|||||||
"@radix-ui/react-checkbox": "^1.0.4",
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.3",
|
"@radix-ui/react-navigation-menu": "^1.2.3",
|
||||||
"@radix-ui/react-popover": "^1.0.7",
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@sindresorhus/fnv1a": "^3.1.0",
|
"@sindresorhus/fnv1a": "^3.1.0",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@upstash/redis": "^1.27.1",
|
"ai": "^4.2.2",
|
||||||
"ai": "^4.1.46",
|
|
||||||
"ajv": "^8.12.0",
|
|
||||||
"assert-never": "^1.2.1",
|
"assert-never": "^1.2.1",
|
||||||
"bun-types": "^1.1.20",
|
"bun-types": "^1.1.20",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
@@ -46,7 +45,7 @@
|
|||||||
"mathjax": "^3.2.2",
|
"mathjax": "^3.2.2",
|
||||||
"mdast-util-to-markdown": "^2.1.2",
|
"mdast-util-to-markdown": "^2.1.2",
|
||||||
"memoizee": "^0.4.17",
|
"memoizee": "^0.4.17",
|
||||||
"next": "14.2.25",
|
"next": "14.2.26",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"nuqs": "^2.2.3",
|
"nuqs": "^2.2.3",
|
||||||
"object-hash": "^3.0.0",
|
"object-hash": "^3.0.0",
|
||||||
@@ -68,7 +67,12 @@
|
|||||||
"tailwind-shades": "^1.1.2",
|
"tailwind-shades": "^1.1.2",
|
||||||
"unified": "^11.0.5",
|
"unified": "^11.0.5",
|
||||||
"url-join": "^5.0.0",
|
"url-join": "^5.0.0",
|
||||||
"usehooks-ts": "^3.1.0"
|
"usehooks-ts": "^3.1.0",
|
||||||
|
"zod": "^3.24.2",
|
||||||
|
"zod-to-json-schema": "^3.24.5",
|
||||||
|
"event-iterator": "^2.0.0",
|
||||||
|
"partial-json": "^0.1.7",
|
||||||
|
"zustand": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@argos-ci/playwright": "^4.3.0",
|
"@argos-ci/playwright": "^4.3.0",
|
||||||
|
|||||||
@@ -14,7 +14,15 @@ interface JsonBody {
|
|||||||
* The body should be a JSON with { tags: string[] }
|
* The body should be a JSON with { tags: string[] }
|
||||||
*/
|
*/
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
const json = (await req.json()) as JsonBody;
|
let json: JsonBody;
|
||||||
|
|
||||||
|
try {
|
||||||
|
json = await req.json();
|
||||||
|
} catch (err) {
|
||||||
|
return NextResponse.json({
|
||||||
|
error: `invalid json body: ${err}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!json.tags || !Array.isArray(json.tags)) {
|
if (!json.tags || !Array.isArray(json.tags)) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
@@ -25,10 +33,18 @@ export async function POST(req: NextRequest) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await revalidateTags(json.tags);
|
try {
|
||||||
|
const result = await revalidateTags(json.tags);
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
success: true,
|
success: true,
|
||||||
stats: result.stats,
|
stats: result.stats,
|
||||||
});
|
});
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: `${err}`,
|
||||||
|
},
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ import { useScrollPage } from '@/components/hooks';
|
|||||||
export function PageClientLayout(props: { withSections?: boolean }) {
|
export function PageClientLayout(props: { withSections?: boolean }) {
|
||||||
// We use this hook in the page layout to ensure the elements for the blocks
|
// We use this hook in the page layout to ensure the elements for the blocks
|
||||||
// are rendered before we scroll to a hash or to the top of the page
|
// are rendered before we scroll to a hash or to the top of the page
|
||||||
useScrollPage({ scrollMarginTop: props.withSections ? 50 : undefined });
|
useScrollPage({ scrollMarginTop: props.withSections ? 48 : undefined });
|
||||||
|
|
||||||
useStripFallbackQueryParam();
|
useStripFallbackQueryParam();
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Button } from '@/components/primitives/Button';
|
import { Button } from '@/components/primitives/Button';
|
||||||
import { t, useLanguage } from '@/intl/client';
|
import { t, tString, useLanguage } from '@/intl/client';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
export default function ErrorPage(props: {
|
export default function ErrorPage(props: {
|
||||||
@@ -35,9 +35,8 @@ export default function ErrorPage(props: {
|
|||||||
}}
|
}}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
label={tString(language, 'unexpected_error_retry')}
|
||||||
{t(language, 'unexpected_error_retry')}
|
/>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
'use client';
|
||||||
|
import { useLanguage } from '@/intl/client';
|
||||||
|
import { t } from '@/intl/translate';
|
||||||
|
import { Icon } from '@gitbook/icons';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { useVisitedPages } from '../Insights';
|
||||||
|
import { usePageContext } from '../PageContext';
|
||||||
|
import { Loading } from '../primitives';
|
||||||
|
import { streamLinkPageSummary } from './server-actions/streamLinkPageSummary';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Summarise a page's content for use in a link preview
|
||||||
|
*/
|
||||||
|
export function AIPageLinkSummary(props: {
|
||||||
|
targetSpaceId: string;
|
||||||
|
targetPageId: string;
|
||||||
|
linkPreview?: string;
|
||||||
|
linkTitle?: string;
|
||||||
|
showTrademark: boolean;
|
||||||
|
}) {
|
||||||
|
const { targetSpaceId, targetPageId, linkPreview, linkTitle, showTrademark = true } = props;
|
||||||
|
|
||||||
|
const currentPage = usePageContext();
|
||||||
|
|
||||||
|
const language = useLanguage();
|
||||||
|
const visitedPages = useVisitedPages((state) => state.pages);
|
||||||
|
const [highlight, setHighlight] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let canceled = false;
|
||||||
|
|
||||||
|
setHighlight('');
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const stream = await streamLinkPageSummary({
|
||||||
|
currentSpaceId: currentPage.spaceId,
|
||||||
|
currentPageId: currentPage.pageId,
|
||||||
|
currentPageTitle: currentPage.title,
|
||||||
|
targetSpaceId,
|
||||||
|
targetPageId,
|
||||||
|
linkPreview,
|
||||||
|
linkTitle,
|
||||||
|
visitedPages,
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const highlight of stream) {
|
||||||
|
if (canceled) return;
|
||||||
|
setHighlight(highlight ?? '');
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
canceled = true;
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
currentPage.pageId,
|
||||||
|
currentPage.spaceId,
|
||||||
|
currentPage.title,
|
||||||
|
targetSpaceId,
|
||||||
|
targetPageId,
|
||||||
|
linkPreview,
|
||||||
|
linkTitle,
|
||||||
|
visitedPages,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const shimmerBlocks = [
|
||||||
|
'w-[20%] [animation-delay:-1s]',
|
||||||
|
'w-[35%] [animation-delay:-0.8s]',
|
||||||
|
'w-[25%] [animation-delay:-0.6s]',
|
||||||
|
'w-[10%] [animation-delay:-0.4s]',
|
||||||
|
'w-[40%] [animation-delay:-0.2s]',
|
||||||
|
'w-[30%] [animation-delay:0s]',
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="flex w-screen items-center gap-1 font-semibold text-tint text-xs uppercase leading-tight tracking-wide">
|
||||||
|
{showTrademark ? (
|
||||||
|
<Loading className="size-4" busy={!highlight || highlight.length === 0} />
|
||||||
|
) : (
|
||||||
|
<Icon icon="sparkle" className="size-3" />
|
||||||
|
)}
|
||||||
|
<h6 className="text-tint">{t(language, 'link_tooltip_ai_summary')}</h6>
|
||||||
|
</div>
|
||||||
|
{highlight.length > 0 ? (
|
||||||
|
<p className="animate-fadeIn">{highlight}</p>
|
||||||
|
) : (
|
||||||
|
<div className="mt-2 flex flex-wrap gap-2">
|
||||||
|
{shimmerBlocks.map((block, index) => (
|
||||||
|
<div
|
||||||
|
key={`${index}-${block}`}
|
||||||
|
className={`${block} h-4 animate-pulse rounded straight-corners:rounded-none bg-tint-active`}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{highlight.length > 0 ? (
|
||||||
|
<div className="animate-fadeIn text-tint-subtle text-xs">
|
||||||
|
{t(language, 'link_tooltip_ai_summary_description')}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './AIPageLinkSummary';
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
'use server';
|
||||||
|
import { type AIMessageInput, AIModel, type AIStreamResponse } from '@gitbook/api';
|
||||||
|
import type { GitBookBaseContext } from '@v2/lib/context';
|
||||||
|
import { EventIterator } from 'event-iterator';
|
||||||
|
import type { MaybePromise } from 'p-map';
|
||||||
|
import * as partialJson from 'partial-json';
|
||||||
|
import type { DeepPartial } from 'ts-essentials';
|
||||||
|
import type { z } from 'zod';
|
||||||
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest value from a stream and the response id.
|
||||||
|
*/
|
||||||
|
export async function generate<T>(
|
||||||
|
promise: MaybePromise<{
|
||||||
|
stream: EventIterator<T>;
|
||||||
|
response: Promise<{ responseId: string }>;
|
||||||
|
}>
|
||||||
|
) {
|
||||||
|
const input = await promise;
|
||||||
|
let value: T | undefined;
|
||||||
|
|
||||||
|
for await (const event of input.stream) {
|
||||||
|
value = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { responseId } = await input.response;
|
||||||
|
return {
|
||||||
|
responseId,
|
||||||
|
value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream the generation of an object using the AI.
|
||||||
|
*/
|
||||||
|
export async function streamGenerateObject<T>(
|
||||||
|
context: GitBookBaseContext,
|
||||||
|
{
|
||||||
|
organizationId,
|
||||||
|
siteId,
|
||||||
|
}: {
|
||||||
|
organizationId: string;
|
||||||
|
siteId: string;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
schema,
|
||||||
|
messages,
|
||||||
|
model = AIModel.Fast,
|
||||||
|
}: {
|
||||||
|
schema: z.ZodSchema<T>;
|
||||||
|
messages: AIMessageInput[];
|
||||||
|
model?: AIModel;
|
||||||
|
previousResponseId?: string;
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
const rawStream = context.dataFetcher.streamAIResponse({
|
||||||
|
organizationId,
|
||||||
|
siteId,
|
||||||
|
input: messages,
|
||||||
|
output: {
|
||||||
|
type: 'object',
|
||||||
|
schema: zodToJsonSchema(schema),
|
||||||
|
},
|
||||||
|
model,
|
||||||
|
});
|
||||||
|
|
||||||
|
let json = '';
|
||||||
|
return parseResponse<DeepPartial<T>>(rawStream, (event) => {
|
||||||
|
if (event.type === 'response_object') {
|
||||||
|
json += event.jsonChunk;
|
||||||
|
|
||||||
|
const parsed = partialJson.parse(json, partialJson.ALL);
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a stream from the API to extract the responseId.
|
||||||
|
*/
|
||||||
|
function parseResponse<T>(
|
||||||
|
responseStream: EventIterator<AIStreamResponse>,
|
||||||
|
parse: (response: AIStreamResponse) => T | undefined
|
||||||
|
): {
|
||||||
|
stream: EventIterator<T>;
|
||||||
|
response: Promise<{ responseId: string }>;
|
||||||
|
} {
|
||||||
|
let resolveResponse: (value: { responseId: string }) => void;
|
||||||
|
const response = new Promise<{ responseId: string }>((resolve) => {
|
||||||
|
resolveResponse = resolve;
|
||||||
|
});
|
||||||
|
|
||||||
|
const stream = new EventIterator<T>((queue) => {
|
||||||
|
(async () => {
|
||||||
|
let foundResponse = false;
|
||||||
|
|
||||||
|
for await (const event of responseStream) {
|
||||||
|
if (event.type === 'response_finish') {
|
||||||
|
foundResponse = true;
|
||||||
|
resolveResponse({ responseId: event.responseId });
|
||||||
|
} else {
|
||||||
|
const parsed = parse(event);
|
||||||
|
if (parsed !== undefined) {
|
||||||
|
queue.push(parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundResponse) {
|
||||||
|
throw new Error('No response found');
|
||||||
|
}
|
||||||
|
})().then(
|
||||||
|
() => {
|
||||||
|
queue.stop();
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
queue.fail(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return { stream, response };
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './streamLinkPageSummary';
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
'use server';
|
||||||
|
import { filterOutNullable } from '@/lib/typescript';
|
||||||
|
import { getV1BaseContext } from '@/lib/v1';
|
||||||
|
import { isV2 } from '@/lib/v2';
|
||||||
|
import { AIMessageRole } from '@gitbook/api';
|
||||||
|
import { getSiteURLDataFromMiddleware } from '@v2/lib/middleware';
|
||||||
|
import { getServerActionBaseContext } from '@v2/lib/server-actions';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { streamGenerateObject } from './api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a summary of a page, in the context of another page
|
||||||
|
*/
|
||||||
|
export async function* streamLinkPageSummary({
|
||||||
|
currentSpaceId,
|
||||||
|
currentPageId,
|
||||||
|
targetSpaceId,
|
||||||
|
targetPageId,
|
||||||
|
linkPreview,
|
||||||
|
linkTitle,
|
||||||
|
visitedPages,
|
||||||
|
}: {
|
||||||
|
currentSpaceId: string;
|
||||||
|
currentPageId: string;
|
||||||
|
currentPageTitle: string;
|
||||||
|
targetSpaceId: string;
|
||||||
|
targetPageId: string;
|
||||||
|
linkPreview?: string;
|
||||||
|
linkTitle?: string;
|
||||||
|
visitedPages?: Array<{ spaceId: string; pageId: string }>;
|
||||||
|
}) {
|
||||||
|
const baseContext = isV2() ? await getServerActionBaseContext() : await getV1BaseContext();
|
||||||
|
const siteURLData = await getSiteURLDataFromMiddleware();
|
||||||
|
|
||||||
|
const { stream } = await streamGenerateObject(
|
||||||
|
baseContext,
|
||||||
|
{
|
||||||
|
organizationId: siteURLData.organization,
|
||||||
|
siteId: siteURLData.site,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
schema: z.object({
|
||||||
|
highlight: z
|
||||||
|
.string()
|
||||||
|
.describe('The reason why the user should read the target page.'),
|
||||||
|
// questions: z.array(z.string().describe('The questions to sea')).max(3),
|
||||||
|
}),
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `# 1. Role
|
||||||
|
You are a contextual fact extractor. Your job is to find the exact fact from the linked page that directly answers the implied question in the current paragraph.
|
||||||
|
|
||||||
|
# 2. Task
|
||||||
|
Extract a contextually-relevant fact that:
|
||||||
|
- Directly answers the specific need or question implied by the link's placement
|
||||||
|
- States a capability, limitation, or specification from the target page
|
||||||
|
- Connects precisely to the user's current paragraph or sentence
|
||||||
|
- Completes the user's understanding based on what they're currently reading
|
||||||
|
|
||||||
|
# 3. Instructions
|
||||||
|
1. First, identify the exact need, question, or gap in the current paragraph where the link appears
|
||||||
|
2. Find the specific fact in the target page that addresses this exact contextual need
|
||||||
|
3. Ensure the fact relates directly to the context of the paragraph containing the link
|
||||||
|
4. Avoid ALL instructional language including words like "use", "click", "select", "create"
|
||||||
|
5. Keep it under 30 words, factual and declarative about what EXISTS or IS TRUE`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `# 4. Current page
|
||||||
|
The content of the current page is:`,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
type: 'page' as const,
|
||||||
|
spaceId: currentSpaceId,
|
||||||
|
pageId: currentPageId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
...(visitedPages
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: '# 5. Previous pages',
|
||||||
|
},
|
||||||
|
...visitedPages.map(({ spaceId, pageId }) => ({
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `## Page ${pageId}`,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
type: 'page' as const,
|
||||||
|
spaceId,
|
||||||
|
pageId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `# 6. Target page
|
||||||
|
The content of the target page is:`,
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
type: 'page' as const,
|
||||||
|
spaceId: targetSpaceId,
|
||||||
|
pageId: targetPageId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `# 7. Link preview
|
||||||
|
The content of the link preview is:
|
||||||
|
> ${linkPreview}
|
||||||
|
> Page ID: ${targetPageId}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: AIMessageRole.Developer,
|
||||||
|
content: `# 8. Guidelines & Examples
|
||||||
|
ALWAYS:
|
||||||
|
- ALWAYS choose facts that directly fulfill the contextual need where the link appears
|
||||||
|
- ALWAYS connect target page information specifically to the current paragraph context
|
||||||
|
- ALWAYS focus on the gap in knowledge that the link is meant to fill
|
||||||
|
- ALWAYS consider user's navigation history to ensure contextual continuity
|
||||||
|
- ALWAYS use action verbs like "click", "select", "use", "create", "enable"
|
||||||
|
|
||||||
|
NEVER:
|
||||||
|
- NEVER include ANY unspecifc language like "learn", "how to", "discover", etc. State the fact directly.
|
||||||
|
- NEVER select general facts unrelated to the specific link context
|
||||||
|
- NEVER ignore the specific context where the link appears
|
||||||
|
- NEVER repeat the same fact in different words
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
Current paragraph: "When organizing content, headings are limited to 3 levels. For more advanced editing, you can use (multiple select)[/multiple-select] to move multiple blocks at once."
|
||||||
|
Preview: "Multiple Select: Select multiple content blocks at once."
|
||||||
|
✓ "Shift selects content between two points, useful for reorganizing your current heading structure."
|
||||||
|
✗ "Shift and Ctrl/Cmd keys are the modifiers for selecting multiple blocks."
|
||||||
|
|
||||||
|
Current paragraph: "Most changes can be published directly, but for major revisions, if you want others to review changes before publishing, create a (change request)[/change-requests]."
|
||||||
|
Preview: "Change Requests: Collaborative content editing workflow."
|
||||||
|
✓ "Each reviewer's approval is tracked separately, with specific change highlighting for your major revisions."
|
||||||
|
✗ "Each reviewer receives an email notification and can approve or request changes."
|
||||||
|
|
||||||
|
Current paragraph: "Your team mentioned issues with conflicting edits. Need to collaborate in real-time? You can use (live edit mode)[/live-edit]."
|
||||||
|
Preview: "Live Edit: Real-time collaborative editing."
|
||||||
|
✓ "Teams with GitHub repositories (like yours) cannot use this feature due to sync limitations."
|
||||||
|
✗ "Incompatible with GitHub/GitLab sync and requires specific visibility settings."`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: AIMessageRole.User,
|
||||||
|
content: `I'm considering reading the link titled "${linkTitle}" pointing to page ${targetPageId}. Why should I read it? Relate it to the paragraph I'm currently reading.`,
|
||||||
|
},
|
||||||
|
].filter(filterOutNullable),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
for await (const value of stream) {
|
||||||
|
const highlight = value.highlight;
|
||||||
|
if (!highlight) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield highlight;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,9 +97,8 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onUpdateState(true);
|
onUpdateState(true);
|
||||||
}}
|
}}
|
||||||
>
|
label={tString(language, 'cookies_accept')}
|
||||||
{t(language, 'cookies_accept')}
|
/>
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -107,9 +106,8 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onUpdateState(false);
|
onUpdateState(false);
|
||||||
}}
|
}}
|
||||||
>
|
label={tString(language, 'cookies_reject')}
|
||||||
{t(language, 'cookies_reject')}
|
/>
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,15 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
|
|||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
id={id}
|
id={id}
|
||||||
className={tcls(textStyle.textSize, 'heading', 'group', 'relative', 'grid', style)}
|
className={tcls(
|
||||||
|
textStyle.textSize,
|
||||||
|
'heading',
|
||||||
|
'group',
|
||||||
|
'relative',
|
||||||
|
'grid',
|
||||||
|
'scroll-m-12',
|
||||||
|
style
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={tcls(
|
className={tcls(
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ const HINT_STYLES: {
|
|||||||
'[&_.can-override-text]:text-neutral-strong',
|
'[&_.can-override-text]:text-neutral-strong',
|
||||||
],
|
],
|
||||||
container:
|
container:
|
||||||
'bg-info border-info theme-muted-tint:bg-info-solid/2 theme-bold-tint:bg-info-solid/2',
|
'bg-info border-info theme-muted-tint:bg-info-solid/2 [html.sidebar-filled.theme-bold.tint_&]:bg-info-solid/2',
|
||||||
containerWithHeader: 'border-info-solid bg-info-subtle',
|
containerWithHeader: 'border-info-solid bg-info-subtle',
|
||||||
},
|
},
|
||||||
warning: {
|
warning: {
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
import { type DocumentInlineLink, SiteInsightsLinkPosition } from '@gitbook/api';
|
import { type DocumentInlineLink, SiteInsightsLinkPosition } from '@gitbook/api';
|
||||||
|
|
||||||
import { resolveContentRef } from '@/lib/references';
|
import { resolveContentRef } from '@/lib/references';
|
||||||
|
import { Icon } from '@gitbook/icons';
|
||||||
import { StyledLink } from '../primitives';
|
import { StyledLink } from '../primitives';
|
||||||
import type { InlineProps } from './Inline';
|
import type { InlineProps } from './Inline';
|
||||||
|
import { InlineLinkTooltip } from './InlineLinkTooltip';
|
||||||
import { Inlines } from './Inlines';
|
import { Inlines } from './Inlines';
|
||||||
|
|
||||||
export async function InlineLink(props: InlineProps<DocumentInlineLink>) {
|
export async function InlineLink(props: InlineProps<DocumentInlineLink>) {
|
||||||
const { inline, document, context, ancestorInlines } = props;
|
const { inline, document, context, ancestorInlines } = props;
|
||||||
|
|
||||||
const resolved = context.contentContext
|
const resolved = context.contentContext
|
||||||
? await resolveContentRef(inline.data.ref, context.contentContext)
|
? await resolveContentRef(inline.data.ref, context.contentContext, {
|
||||||
|
resolveAnchorText: true,
|
||||||
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!resolved) {
|
if (!context.contentContext || !resolved) {
|
||||||
return (
|
return (
|
||||||
<span title="Broken link" className="underline">
|
<span title="Broken link" className="underline">
|
||||||
<Inlines
|
<Inlines
|
||||||
@@ -25,24 +28,33 @@ export async function InlineLink(props: InlineProps<DocumentInlineLink>) {
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const isExternal = inline.data.ref.kind === 'url';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledLink
|
<InlineLinkTooltip inline={inline} context={context.contentContext} resolved={resolved}>
|
||||||
href={resolved.href}
|
<StyledLink
|
||||||
insights={{
|
href={resolved.href}
|
||||||
type: 'link_click',
|
insights={{
|
||||||
link: {
|
type: 'link_click',
|
||||||
target: inline.data.ref,
|
link: {
|
||||||
position: SiteInsightsLinkPosition.Content,
|
target: inline.data.ref,
|
||||||
},
|
position: SiteInsightsLinkPosition.Content,
|
||||||
}}
|
},
|
||||||
>
|
}}
|
||||||
<Inlines
|
>
|
||||||
context={context}
|
<Inlines
|
||||||
document={document}
|
context={context}
|
||||||
nodes={inline.nodes}
|
document={document}
|
||||||
ancestorInlines={[...ancestorInlines, inline]}
|
nodes={inline.nodes}
|
||||||
/>
|
ancestorInlines={[...ancestorInlines, inline]}
|
||||||
</StyledLink>
|
/>
|
||||||
|
{isExternal ? (
|
||||||
|
<Icon
|
||||||
|
icon="arrow-up-right"
|
||||||
|
className="ml-0.5 inline size-3 links-accent:text-tint-subtle"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</StyledLink>
|
||||||
|
</InlineLinkTooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
import type { DocumentInlineLink } from '@gitbook/api';
|
||||||
|
|
||||||
|
import type { ResolvedContentRef } from '@/lib/references';
|
||||||
|
|
||||||
|
import { getSpaceLanguage } from '@/intl/server';
|
||||||
|
import { tString } from '@/intl/translate';
|
||||||
|
import { languages } from '@/intl/translations';
|
||||||
|
import { getNodeText } from '@/lib/document';
|
||||||
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
import { Icon } from '@gitbook/icons';
|
||||||
|
import * as Tooltip from '@radix-ui/react-tooltip';
|
||||||
|
import type { GitBookAnyContext } from '@v2/lib/context';
|
||||||
|
import { Fragment } from 'react';
|
||||||
|
import { AIPageLinkSummary } from '../Adaptive/AIPageLinkSummary';
|
||||||
|
import { Button, StyledLink } from '../primitives';
|
||||||
|
|
||||||
|
export async function InlineLinkTooltip(props: {
|
||||||
|
inline: DocumentInlineLink;
|
||||||
|
context: GitBookAnyContext;
|
||||||
|
children: React.ReactNode;
|
||||||
|
resolved: ResolvedContentRef;
|
||||||
|
}) {
|
||||||
|
const { inline, context, resolved, children } = props;
|
||||||
|
|
||||||
|
let breadcrumbs = resolved.ancestors;
|
||||||
|
const language =
|
||||||
|
'customization' in context ? getSpaceLanguage(context.customization) : languages.en;
|
||||||
|
const isExternal = inline.data.ref.kind === 'url';
|
||||||
|
const isSamePage = inline.data.ref.kind === 'anchor' && inline.data.ref.page === undefined;
|
||||||
|
if (isExternal) {
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
label: tString(language, 'link_tooltip_external_link'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (isSamePage) {
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
label: tString(language, 'link_tooltip_page_anchor'),
|
||||||
|
icon: <Icon icon="arrow-down-short-wide" className="size-3" />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
resolved.subText = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasAISummary =
|
||||||
|
!isExternal &&
|
||||||
|
!isSamePage &&
|
||||||
|
'customization' in context &&
|
||||||
|
context.customization.ai?.pageLinkSummaries.enabled &&
|
||||||
|
(inline.data.ref.kind === 'page' || inline.data.ref.kind === 'anchor');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip.Provider delayDuration={200}>
|
||||||
|
<Tooltip.Root>
|
||||||
|
<Tooltip.Trigger asChild>{children}</Tooltip.Trigger>
|
||||||
|
<Tooltip.Portal>
|
||||||
|
<Tooltip.Content className="z-40 w-screen max-w-md animate-present px-4 sm:w-auto">
|
||||||
|
<div className="overflow-hidden rounded-md straight-corners:rounded-none shadow-lg shadow-tint-12/4 ring-1 ring-tint-subtle dark:shadow-tint-1 ">
|
||||||
|
<div className="bg-tint-base p-4">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{breadcrumbs && breadcrumbs.length > 0 ? (
|
||||||
|
<div className="mb-1 flex grow flex-wrap items-center gap-x-2 gap-y-0.5 font-semibold text-tint text-xs uppercase leading-tight tracking-wide">
|
||||||
|
{breadcrumbs.map((crumb, index) => {
|
||||||
|
const Tag = crumb.href ? StyledLink : 'div';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Fragment key={crumb.label}>
|
||||||
|
{index !== 0 ? (
|
||||||
|
<Icon
|
||||||
|
icon="chevron-right"
|
||||||
|
className="size-3 text-tint-subtle"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<Tag
|
||||||
|
className={tcls(
|
||||||
|
'flex gap-1',
|
||||||
|
crumb.href &&
|
||||||
|
'links-default:text-tint no-underline hover:underline contrast-more:underline contrast-more:decoration-current'
|
||||||
|
)}
|
||||||
|
href={crumb.href ?? '#'}
|
||||||
|
>
|
||||||
|
{crumb.icon ? (
|
||||||
|
<span className="mt-0.5 text-tint-subtle empty:hidden">
|
||||||
|
{crumb.icon}
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
{crumb.label}
|
||||||
|
</Tag>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div
|
||||||
|
className={tcls(
|
||||||
|
'flex gap-2 leading-snug',
|
||||||
|
isExternal && 'text-sm [overflow-wrap:anywhere]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{resolved.icon ? (
|
||||||
|
<div className="mt-1 text-tint-subtle empty:hidden">
|
||||||
|
{resolved.icon}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<h5 className="font-semibold">{resolved.text}</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{!isSamePage && resolved.href ? (
|
||||||
|
<Button
|
||||||
|
className={tcls(
|
||||||
|
'-mx-2 -my-2 ml-auto',
|
||||||
|
breadcrumbs?.length === 0
|
||||||
|
? 'place-self-center'
|
||||||
|
: null
|
||||||
|
)}
|
||||||
|
variant="blank"
|
||||||
|
href={resolved.href}
|
||||||
|
target="_blank"
|
||||||
|
label={tString(language, 'open_in_new_tab')}
|
||||||
|
size="small"
|
||||||
|
icon="arrow-up-right-from-square"
|
||||||
|
iconOnly={true}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
{resolved.subText ? (
|
||||||
|
<p className="mt-1 text-sm text-tint">{resolved.subText}</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{hasAISummary && 'page' in context && 'page' in inline.data.ref ? (
|
||||||
|
<div className="border-tint-subtle border-t bg-tint p-4">
|
||||||
|
<AIPageLinkSummary
|
||||||
|
targetPageId={
|
||||||
|
resolved.page?.id ??
|
||||||
|
inline.data.ref.page ??
|
||||||
|
context.page.id
|
||||||
|
}
|
||||||
|
targetSpaceId={inline.data.ref.space ?? context.space.id}
|
||||||
|
linkTitle={getNodeText(inline)}
|
||||||
|
linkPreview={`**${resolved.text}**: ${resolved.subText}`}
|
||||||
|
showTrademark={
|
||||||
|
'customization' in context &&
|
||||||
|
context.customization.trademark.enabled
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<Tooltip.Arrow className={hasAISummary ? 'fill-tint-3' : 'fill-tint-1'} />
|
||||||
|
</Tooltip.Content>
|
||||||
|
</Tooltip.Portal>
|
||||||
|
</Tooltip.Root>
|
||||||
|
</Tooltip.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,18 +1,14 @@
|
|||||||
import type { JSONDocument } from '@gitbook/api';
|
|
||||||
import { Icon } from '@gitbook/icons';
|
|
||||||
import { OpenAPIOperation as BaseOpenAPIOperation } from '@gitbook/react-openapi';
|
import { OpenAPIOperation as BaseOpenAPIOperation } from '@gitbook/react-openapi';
|
||||||
|
|
||||||
import { resolveOpenAPIOperationBlock } from '@/lib/openapi/resolveOpenAPIOperationBlock';
|
import { resolveOpenAPIOperationBlock } from '@/lib/openapi/resolveOpenAPIOperationBlock';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
import type { BlockProps } from '../Block';
|
import type { BlockProps } from '../Block';
|
||||||
import { PlainCodeBlock } from '../CodeBlock';
|
|
||||||
import { DocumentView } from '../DocumentView';
|
|
||||||
import { Heading } from '../Heading';
|
|
||||||
|
|
||||||
import './scalar.css';
|
import './scalar.css';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import type { AnyOpenAPIOperationsBlock } from '@/lib/openapi/types';
|
import type { AnyOpenAPIOperationsBlock } from '@/lib/openapi/types';
|
||||||
|
import { getOpenAPIContext } from './context';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render an openapi block or an openapi-operation block.
|
* Render an openapi block or an openapi-operation block.
|
||||||
@@ -55,56 +51,7 @@ async function OpenAPIOperationBody(props: BlockProps<AnyOpenAPIOperationsBlock>
|
|||||||
return (
|
return (
|
||||||
<BaseOpenAPIOperation
|
<BaseOpenAPIOperation
|
||||||
data={data}
|
data={data}
|
||||||
context={{
|
context={getOpenAPIContext({ props, specUrl })}
|
||||||
specUrl,
|
|
||||||
icons: {
|
|
||||||
chevronDown: <Icon icon="chevron-down" />,
|
|
||||||
chevronRight: <Icon icon="chevron-right" />,
|
|
||||||
plus: <Icon icon="plus" />,
|
|
||||||
},
|
|
||||||
renderCodeBlock: (codeProps) => <PlainCodeBlock {...codeProps} />,
|
|
||||||
renderDocument: (documentProps) => (
|
|
||||||
<DocumentView
|
|
||||||
document={documentProps.document as JSONDocument}
|
|
||||||
context={props.context}
|
|
||||||
style="space-y-6"
|
|
||||||
blockStyle="max-w-full"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
renderHeading: (headingProps) => (
|
|
||||||
<Heading
|
|
||||||
document={props.document}
|
|
||||||
ancestorBlocks={props.ancestorBlocks}
|
|
||||||
isEstimatedOffscreen={props.isEstimatedOffscreen}
|
|
||||||
context={props.context}
|
|
||||||
style={tcls([
|
|
||||||
headingProps.deprecated ? 'line-through' : undefined,
|
|
||||||
headingProps.deprecated || !!headingProps.stability
|
|
||||||
? '[&>div]:mt-0'
|
|
||||||
: undefined,
|
|
||||||
])}
|
|
||||||
block={{
|
|
||||||
object: 'block',
|
|
||||||
key: `${block.key}-heading`,
|
|
||||||
meta: block.meta,
|
|
||||||
data: {},
|
|
||||||
type: 'heading-2',
|
|
||||||
nodes: [
|
|
||||||
{
|
|
||||||
key: `${block.key}-heading-text`,
|
|
||||||
object: 'text',
|
|
||||||
leaves: [
|
|
||||||
{ text: headingProps.title, object: 'leaf', marks: [] },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
defaultInteractiveOpened: context.mode === 'print',
|
|
||||||
id: block.meta?.id,
|
|
||||||
blockKey: block.key,
|
|
||||||
}}
|
|
||||||
className="openapi-block"
|
className="openapi-block"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { resolveOpenAPISchemasBlock } from '@/lib/openapi/resolveOpenAPISchemasBlock';
|
import { resolveOpenAPISchemasBlock } from '@/lib/openapi/resolveOpenAPISchemasBlock';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
import { Icon } from '@gitbook/icons';
|
|
||||||
import { OpenAPISchemas as BaseOpenAPISchemas } from '@gitbook/react-openapi';
|
import { OpenAPISchemas as BaseOpenAPISchemas } from '@gitbook/react-openapi';
|
||||||
|
|
||||||
import type { BlockProps } from '../Block';
|
import type { BlockProps } from '../Block';
|
||||||
@@ -8,6 +7,7 @@ import type { BlockProps } from '../Block';
|
|||||||
import './scalar.css';
|
import './scalar.css';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
import type { OpenAPISchemasBlock } from '@/lib/openapi/types';
|
import type { OpenAPISchemasBlock } from '@/lib/openapi/types';
|
||||||
|
import { getOpenAPIContext } from './context';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render an openapi-schemas block.
|
* Render an openapi-schemas block.
|
||||||
@@ -49,18 +49,9 @@ async function OpenAPISchemasBody(props: BlockProps<OpenAPISchemasBlock>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseOpenAPISchemas
|
<BaseOpenAPISchemas
|
||||||
data={data}
|
schemas={data.schemas}
|
||||||
context={{
|
grouped={block.data.grouped}
|
||||||
specUrl,
|
context={getOpenAPIContext({ props, specUrl })}
|
||||||
icons: {
|
|
||||||
chevronDown: <Icon icon="chevron-down" />,
|
|
||||||
chevronRight: <Icon icon="chevron-right" />,
|
|
||||||
plus: <Icon icon="plus" />,
|
|
||||||
},
|
|
||||||
defaultInteractiveOpened: context.mode === 'print',
|
|
||||||
id: block.meta?.id,
|
|
||||||
blockKey: block.key,
|
|
||||||
}}
|
|
||||||
className="openapi-block"
|
className="openapi-block"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { JSONDocument } from '@gitbook/api';
|
||||||
|
import { Icon } from '@gitbook/icons';
|
||||||
|
import type { OpenAPIContext } from '@gitbook/react-openapi';
|
||||||
|
|
||||||
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
|
import type { BlockProps } from '../Block';
|
||||||
|
import { PlainCodeBlock } from '../CodeBlock';
|
||||||
|
import { DocumentView } from '../DocumentView';
|
||||||
|
import { Heading } from '../Heading';
|
||||||
|
|
||||||
|
import './scalar.css';
|
||||||
|
import './style.css';
|
||||||
|
import type { AnyOpenAPIOperationsBlock, OpenAPISchemasBlock } from '@/lib/openapi/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the OpenAPI context to render a block.
|
||||||
|
*/
|
||||||
|
export function getOpenAPIContext(args: {
|
||||||
|
props: BlockProps<AnyOpenAPIOperationsBlock | OpenAPISchemasBlock>;
|
||||||
|
specUrl: string;
|
||||||
|
}): OpenAPIContext {
|
||||||
|
const { props, specUrl } = args;
|
||||||
|
const { block } = props;
|
||||||
|
return {
|
||||||
|
specUrl,
|
||||||
|
icons: {
|
||||||
|
chevronDown: <Icon icon="chevron-down" />,
|
||||||
|
chevronRight: <Icon icon="chevron-right" />,
|
||||||
|
plus: <Icon icon="plus" />,
|
||||||
|
},
|
||||||
|
renderCodeBlock: (codeProps) => <PlainCodeBlock {...codeProps} />,
|
||||||
|
renderDocument: (documentProps) => (
|
||||||
|
<DocumentView
|
||||||
|
document={documentProps.document as JSONDocument}
|
||||||
|
context={props.context}
|
||||||
|
style="space-y-6"
|
||||||
|
blockStyle="max-w-full"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
renderHeading: (headingProps) => (
|
||||||
|
<Heading
|
||||||
|
document={props.document}
|
||||||
|
ancestorBlocks={props.ancestorBlocks}
|
||||||
|
isEstimatedOffscreen={props.isEstimatedOffscreen}
|
||||||
|
context={props.context}
|
||||||
|
style={tcls([
|
||||||
|
headingProps.deprecated ? 'line-through' : undefined,
|
||||||
|
headingProps.deprecated || !!headingProps.stability
|
||||||
|
? '[&>div]:mt-0'
|
||||||
|
: undefined,
|
||||||
|
])}
|
||||||
|
block={{
|
||||||
|
object: 'block',
|
||||||
|
key: `${block.key}-heading`,
|
||||||
|
meta: block.meta,
|
||||||
|
data: {},
|
||||||
|
type: 'heading-2',
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
key: `${block.key}-heading-text`,
|
||||||
|
object: 'text',
|
||||||
|
leaves: [{ text: headingProps.title, object: 'leaf', marks: [] }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
defaultInteractiveOpened: props.context.mode === 'print',
|
||||||
|
id: block.meta?.id,
|
||||||
|
blockKey: block.key,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
/* Layout Components */
|
/* Layout Components */
|
||||||
.openapi-operation {
|
.openapi-operation,
|
||||||
|
.openapi-schemas {
|
||||||
@apply flex-1 flex flex-col gap-8 mb-14 min-w-0;
|
@apply flex-1 flex flex-col gap-8 mb-14 min-w-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.openapi-summary {
|
.openapi-summary {
|
||||||
@apply flex flex-col items-start justify-start gap-3;
|
@apply flex flex-col items-start justify-start gap-3 scroll-m-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-summary-tags {
|
.openapi-summary-tags {
|
||||||
@@ -29,10 +30,6 @@
|
|||||||
@apply py-0.5 px-1.5 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-sm leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
@apply py-0.5 px-1.5 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-sm leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-stability-stable {
|
|
||||||
@apply text-green-600 dark:text-green-300 bg-green-50 dark:bg-green-900/6 ring-green-500/5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.openapi-stability-alpha {
|
.openapi-stability-alpha {
|
||||||
@apply text-amber-700 dark:text-amber-300 bg-amber-50 dark:bg-amber-900/6 ring-amber-500/5;
|
@apply text-amber-700 dark:text-amber-300 bg-amber-50 dark:bg-amber-900/6 ring-amber-500/5;
|
||||||
}
|
}
|
||||||
@@ -155,6 +152,14 @@
|
|||||||
/* unstyled */
|
/* unstyled */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.openapi-schema-root-description.openapi-markdown {
|
||||||
|
@apply prose-sm text-balance mt-1.5 !text-[0.813rem] text-tint overflow-hidden !font-normal select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openapi-section-schemas > .openapi-section-body > .openapi-schema-root-description {
|
||||||
|
@apply px-2.5 pt-1 !text-sm;
|
||||||
|
}
|
||||||
|
|
||||||
.openapi-schema-properties {
|
.openapi-schema-properties {
|
||||||
@apply flex flex-col;
|
@apply flex flex-col;
|
||||||
}
|
}
|
||||||
@@ -203,7 +208,7 @@
|
|||||||
.openapi-schema-name {
|
.openapi-schema-name {
|
||||||
/* To make double click on the property name select only the name,
|
/* To make double click on the property name select only the name,
|
||||||
we disable selection on the parent and re-enable it on the children. */
|
we disable selection on the parent and re-enable it on the children. */
|
||||||
@apply select-none flex gap-x-2.5 items-baseline text-sm flex-wrap;
|
@apply select-none text-sm text-balance *:whitespace-nowrap flex flex-wrap gap-y-1.5 gap-x-2.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-name .openapi-deprecated {
|
.openapi-schema-name .openapi-deprecated {
|
||||||
@@ -265,15 +270,11 @@
|
|||||||
|
|
||||||
/* Schema Enum */
|
/* Schema Enum */
|
||||||
.openapi-schema-enum {
|
.openapi-schema-enum {
|
||||||
@apply flex flex-row text-sm leading-relaxed gap-2 flex-wrap text-tint;
|
@apply text-sm leading-relaxed max-w-full text-tint;
|
||||||
}
|
|
||||||
|
|
||||||
.openapi-schema-enum-list {
|
|
||||||
@apply flex flex-row gap-1.5 items-center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-enum-value {
|
.openapi-schema-enum-value {
|
||||||
@apply text-sm;
|
@apply text-sm mr-1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-enum-value:first-child {
|
.openapi-schema-enum-value:first-child {
|
||||||
@@ -286,7 +287,7 @@
|
|||||||
|
|
||||||
/* Schema Description */
|
/* Schema Description */
|
||||||
.openapi-schema-description.openapi-markdown {
|
.openapi-schema-description.openapi-markdown {
|
||||||
@apply prose-sm text-tint overflow-hidden !font-normal select-text prose-strong:font-semibold prose-strong:text-inherit;
|
@apply prose-sm text-tint overflow-hidden text-pretty !font-normal select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-description.openapi-markdown pre:has(code) {
|
.openapi-schema-description.openapi-markdown pre:has(code) {
|
||||||
@@ -306,13 +307,15 @@
|
|||||||
|
|
||||||
/* Schema Examples */
|
/* Schema Examples */
|
||||||
.openapi-schema-example,
|
.openapi-schema-example,
|
||||||
.openapi-schema-pattern {
|
.openapi-schema-pattern,
|
||||||
|
.openapi-schema-default {
|
||||||
@apply prose-sm text-tint;
|
@apply prose-sm text-tint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-example code,
|
.openapi-schema-example code,
|
||||||
.openapi-schema-pattern code,
|
.openapi-schema-pattern code,
|
||||||
.openapi-schema-enum-value code {
|
.openapi-schema-enum-value code,
|
||||||
|
.openapi-schema-default code {
|
||||||
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-xs leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-xs leading-[calc(max(1.20em,1.25rem))] before:!content-none after:!content-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +329,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.openapi-securities-description.openapi-markdown {
|
.openapi-securities-description.openapi-markdown {
|
||||||
@apply prose-sm text-tint !font-normal select-text prose-strong:font-semibold prose-strong:text-inherit;
|
@apply prose-sm text-tint !font-normal select-text text-pretty prose-strong:font-semibold prose-strong:text-inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-securities-label {
|
.openapi-securities-label {
|
||||||
@@ -352,7 +355,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.openapi-requestbody-description.openapi-markdown {
|
.openapi-requestbody-description.openapi-markdown {
|
||||||
@apply prose-sm text-tint !font-normal select-text prose-strong:font-semibold prose-strong:text-inherit;
|
@apply prose-sm text-tint !font-normal text-pretty select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responses */
|
/* Responses */
|
||||||
@@ -369,7 +372,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.openapi-response-description.openapi-markdown {
|
.openapi-response-description.openapi-markdown {
|
||||||
@apply text-left prose-sm text-[0.813rem] h-auto relative leading-[1.125rem] text-tint !font-normal truncate select-text prose-strong:font-semibold prose-strong:text-inherit;
|
@apply text-left prose-sm text-[0.813rem] text-pretty h-auto relative leading-[1.125rem] text-tint !font-normal truncate select-text prose-strong:font-semibold prose-strong:text-inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-response-description.openapi-markdown::-webkit-scrollbar {
|
.openapi-response-description.openapi-markdown::-webkit-scrollbar {
|
||||||
@@ -485,12 +488,30 @@
|
|||||||
@apply flex flex-row items-center py-2 px-3 justify-end border-t border-tint-subtle;
|
@apply flex flex-row items-center py-2 px-3 justify-end border-t border-tint-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Response Example */
|
/* Panel */
|
||||||
.openapi-response-example {
|
.openapi-panel {
|
||||||
@apply border rounded bg-tint border-tint-subtle;
|
@apply border rounded bg-tint border-tint-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-response-example-empty {
|
.openapi-panel-heading {
|
||||||
|
@apply font-medium px-4 py-2 text-xs uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openapi-panel-body {
|
||||||
|
@apply relative;
|
||||||
|
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openapi-panel-footer {
|
||||||
|
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openapi-panel-footer .openapi-markdown {
|
||||||
|
@apply text-[0.813rem] text-tint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Example */
|
||||||
|
.openapi-example-empty {
|
||||||
@apply relative text-tint bg-tint min-h-20 flex flex-col justify-center items-center;
|
@apply relative text-tint bg-tint min-h-20 flex flex-col justify-center items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,15 +582,6 @@
|
|||||||
|
|
||||||
.openapi-tabs-panel {
|
.openapi-tabs-panel {
|
||||||
@apply flex-1 text-sm relative focus-visible:outline-none;
|
@apply flex-1 text-sm relative focus-visible:outline-none;
|
||||||
@apply before:w-full before:h-px before:absolute before:bg-tint-6 before:-top-px before:z-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.openapi-tabs-footer {
|
|
||||||
@apply px-3 py-2 pt-2.5 border-t border-tint-subtle text-[0.813rem] text-tint;
|
|
||||||
}
|
|
||||||
|
|
||||||
.openapi-tabs-footer .openapi-markdown {
|
|
||||||
@apply text-[0.813rem] text-tint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disclosure group */
|
/* Disclosure group */
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export async function RecordColumnValue<Tag extends React.ElementType = 'div'>(
|
|||||||
key={index}
|
key={index}
|
||||||
href={ref.href}
|
href={ref.href}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
style={['flex', 'flex-row', 'items-center', 'gap-2']}
|
className="flex flex-row items-center gap-2"
|
||||||
insights={
|
insights={
|
||||||
ref.file
|
ref.file
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
|
|||||||
|
|
||||||
'bg-tint-base/9',
|
'bg-tint-base/9',
|
||||||
'theme-muted:bg-tint-subtle/9',
|
'theme-muted:bg-tint-subtle/9',
|
||||||
'theme-bold-tint:bg-tint-subtle/9',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle/9',
|
||||||
'theme-gradient:bg-gradient-primary',
|
'theme-gradient:bg-gradient-primary',
|
||||||
'theme-gradient-tint:bg-gradient-tint',
|
'theme-gradient-tint:bg-gradient-tint',
|
||||||
'contrast-more:bg-tint-base',
|
'contrast-more:bg-tint-base',
|
||||||
|
|||||||
@@ -142,10 +142,9 @@ function HeaderItemButton(
|
|||||||
position: SiteInsightsLinkPosition.Header,
|
position: SiteInsightsLinkPosition.Header,
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
label={title}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
/>
|
||||||
{title}
|
|
||||||
</Button>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { useDebounceCallback, useEventCallback } from 'usehooks-ts';
|
|||||||
import type { VisitorAuthClaims } from '@/lib/adaptive';
|
import type { VisitorAuthClaims } from '@/lib/adaptive';
|
||||||
import { getAllBrowserCookiesMap } from '@/lib/browser-cookies';
|
import { getAllBrowserCookiesMap } from '@/lib/browser-cookies';
|
||||||
import { getSession } from './sessions';
|
import { getSession } from './sessions';
|
||||||
|
import { useVisitedPages } from './useVisitedPages';
|
||||||
import { getVisitorId } from './visitorId';
|
import { getVisitorId } from './visitorId';
|
||||||
|
|
||||||
export type InsightsEventName = api.SiteInsightsEvent['type'];
|
export type InsightsEventName = api.SiteInsightsEvent['type'];
|
||||||
@@ -63,9 +64,19 @@ type TrackEventCallback = <EventName extends InsightsEventName>(
|
|||||||
const InsightsContext = React.createContext<TrackEventCallback>(() => {});
|
const InsightsContext = React.createContext<TrackEventCallback>(() => {});
|
||||||
|
|
||||||
interface InsightsProviderProps extends InsightsEventContext {
|
interface InsightsProviderProps extends InsightsEventContext {
|
||||||
|
/** If true, the events will be sent to the server. */
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|
||||||
|
/** If true, the visitor cookie tracking will be used */
|
||||||
|
visitorCookieTrackingEnabled: boolean;
|
||||||
|
|
||||||
|
/** The URL of the app. */
|
||||||
appURL: string;
|
appURL: string;
|
||||||
|
|
||||||
|
/** The host of the API. */
|
||||||
apiHost: string;
|
apiHost: string;
|
||||||
|
|
||||||
|
/** The children of the provider. */
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +84,9 @@ interface InsightsProviderProps extends InsightsEventContext {
|
|||||||
* Wrap the content of the app with the InsightsProvider to track events.
|
* Wrap the content of the app with the InsightsProvider to track events.
|
||||||
*/
|
*/
|
||||||
export function InsightsProvider(props: InsightsProviderProps) {
|
export function InsightsProvider(props: InsightsProviderProps) {
|
||||||
const { enabled, appURL, apiHost, children, ...context } = props;
|
const { enabled, appURL, apiHost, children, visitorCookieTrackingEnabled, ...context } = props;
|
||||||
|
|
||||||
|
const addVisitedPage = useVisitedPages((state) => state.addPage);
|
||||||
const visitorIdRef = React.useRef<string | null>(null);
|
const visitorIdRef = React.useRef<string | null>(null);
|
||||||
const eventsRef = React.useRef<{
|
const eventsRef = React.useRef<{
|
||||||
[pathname: string]:
|
[pathname: string]:
|
||||||
@@ -124,6 +136,14 @@ export function InsightsProvider(props: InsightsProviderProps) {
|
|||||||
...eventsForPathname,
|
...eventsForPathname,
|
||||||
events: [],
|
events: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Mark the page as visited in our local state
|
||||||
|
if (eventsForPathname.pageContext.pageId) {
|
||||||
|
addVisitedPage({
|
||||||
|
spaceId: context.spaceId,
|
||||||
|
pageId: eventsForPathname.pageContext.pageId,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allEvents.length > 0) {
|
if (allEvents.length > 0) {
|
||||||
@@ -140,7 +160,8 @@ export function InsightsProvider(props: InsightsProviderProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const flushBatchedEvents = useDebounceCallback(async () => {
|
const flushBatchedEvents = useDebounceCallback(async () => {
|
||||||
const visitorId = visitorIdRef.current ?? (await getVisitorId(appURL));
|
const visitorId =
|
||||||
|
visitorIdRef.current ?? (await getVisitorId(appURL, visitorCookieTrackingEnabled));
|
||||||
visitorIdRef.current = visitorId;
|
visitorIdRef.current = visitorId;
|
||||||
|
|
||||||
flushEventsSync();
|
flushEventsSync();
|
||||||
@@ -184,7 +205,7 @@ export function InsightsProvider(props: InsightsProviderProps) {
|
|||||||
* Get the visitor ID and store it in a ref.
|
* Get the visitor ID and store it in a ref.
|
||||||
*/
|
*/
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
getVisitorId(appURL).then((visitorId) => {
|
getVisitorId(appURL, visitorCookieTrackingEnabled).then((visitorId) => {
|
||||||
visitorIdRef.current = visitorId;
|
visitorIdRef.current = visitorId;
|
||||||
// When the page is unloaded, flush all events, but only if the visitor ID is set
|
// When the page is unloaded, flush all events, but only if the visitor ID is set
|
||||||
window.addEventListener('beforeunload', flushEventsSync);
|
window.addEventListener('beforeunload', flushEventsSync);
|
||||||
@@ -192,7 +213,7 @@ export function InsightsProvider(props: InsightsProviderProps) {
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('beforeunload', flushEventsSync);
|
window.removeEventListener('beforeunload', flushEventsSync);
|
||||||
};
|
};
|
||||||
}, [flushEventsSync, appURL]);
|
}, [flushEventsSync, appURL, visitorCookieTrackingEnabled]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InsightsContext.Provider value={trackEvent}>
|
<InsightsContext.Provider value={trackEvent}>
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ export * from './InsightsProvider';
|
|||||||
export * from './visitorId';
|
export * from './visitorId';
|
||||||
export * from './cookies';
|
export * from './cookies';
|
||||||
export * from './TrackPageViewEvent';
|
export * from './TrackPageViewEvent';
|
||||||
|
export * from './useVisitedPages';
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
type VisitedPage = {
|
||||||
|
spaceId: string;
|
||||||
|
pageId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store for the pages that have been visited in the current session.
|
||||||
|
*/
|
||||||
|
export const useVisitedPages = create<{
|
||||||
|
pages: VisitedPage[];
|
||||||
|
addPage: (page: VisitedPage) => void;
|
||||||
|
}>((set) => ({
|
||||||
|
pages: [],
|
||||||
|
addPage: (page) =>
|
||||||
|
set((state) => {
|
||||||
|
const lastPage = state.pages[state.pages.length - 1];
|
||||||
|
if (lastPage && lastPage.spaceId === page.spaceId && lastPage.pageId === page.pageId) {
|
||||||
|
return { pages: state.pages };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { pages: [...state.pages, page] };
|
||||||
|
}),
|
||||||
|
}));
|
||||||
@@ -13,10 +13,13 @@ let pendingVisitorId: Promise<string> | null = null;
|
|||||||
/**
|
/**
|
||||||
* Return the current visitor identifier.
|
* Return the current visitor identifier.
|
||||||
*/
|
*/
|
||||||
export async function getVisitorId(appURL: string): Promise<string> {
|
export async function getVisitorId(
|
||||||
|
appURL: string,
|
||||||
|
visitorCookieTrackingEnabled: boolean
|
||||||
|
): Promise<string> {
|
||||||
if (!visitorId) {
|
if (!visitorId) {
|
||||||
if (!pendingVisitorId) {
|
if (!pendingVisitorId) {
|
||||||
pendingVisitorId = fetchVisitorID(appURL).finally(() => {
|
pendingVisitorId = fetchVisitorID(appURL, visitorCookieTrackingEnabled).finally(() => {
|
||||||
pendingVisitorId = null;
|
pendingVisitorId = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -30,10 +33,13 @@ export async function getVisitorId(appURL: string): Promise<string> {
|
|||||||
/**
|
/**
|
||||||
* Propose a visitor identifier to the GitBook.com server and get the devideId back.
|
* Propose a visitor identifier to the GitBook.com server and get the devideId back.
|
||||||
*/
|
*/
|
||||||
async function fetchVisitorID(appURL: string): Promise<string> {
|
async function fetchVisitorID(
|
||||||
|
appURL: string,
|
||||||
|
visitorCookieTrackingEnabled: boolean
|
||||||
|
): Promise<string> {
|
||||||
const withoutCookies = isCookiesTrackingDisabled();
|
const withoutCookies = isCookiesTrackingDisabled();
|
||||||
|
|
||||||
if (withoutCookies) {
|
if (withoutCookies || !visitorCookieTrackingEnabled) {
|
||||||
return generateRandomId();
|
return generateRandomId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { TrademarkLink } from '@/components/TableOfContents/Trademark';
|
|||||||
import type { PolymorphicComponentProp } from '@/components/utils/types';
|
import type { PolymorphicComponentProp } from '@/components/utils/types';
|
||||||
import { getSpaceLanguage } from '@/intl/server';
|
import { getSpaceLanguage } from '@/intl/server';
|
||||||
import { tString } from '@/intl/translate';
|
import { tString } from '@/intl/translate';
|
||||||
import { getPagePDFContainerId } from '@/lib/links';
|
|
||||||
import { resolvePageId } from '@/lib/pages';
|
import { resolvePageId } from '@/lib/pages';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
import { defaultCustomization } from '@/lib/utils';
|
import { defaultCustomization } from '@/lib/utils';
|
||||||
@@ -29,6 +28,7 @@ import { type PDFSearchParams, getPDFSearchParams } from './urls';
|
|||||||
import { PageControlButtons } from './PageControlButtons';
|
import { PageControlButtons } from './PageControlButtons';
|
||||||
import { PrintButton } from './PrintButton';
|
import { PrintButton } from './PrintButton';
|
||||||
import './pdf.css';
|
import './pdf.css';
|
||||||
|
import { sanitizeGitBookAppURL } from '@/lib/app';
|
||||||
|
|
||||||
const DEFAULT_LIMIT = 100;
|
const DEFAULT_LIMIT = 100;
|
||||||
|
|
||||||
@@ -92,7 +92,10 @@ export async function PDFPage(props: {
|
|||||||
<div className={tcls('fixed', 'left-12', 'top-12', 'print:hidden', 'z-50')}>
|
<div className={tcls('fixed', 'left-12', 'top-12', 'print:hidden', 'z-50')}>
|
||||||
<a
|
<a
|
||||||
title={tString(language, 'pdf_goback')}
|
title={tString(language, 'pdf_goback')}
|
||||||
href={pdfParams.back ?? linker.toAbsoluteURL(linker.toPathInSpace(''))}
|
href={
|
||||||
|
(pdfParams.back ? sanitizeGitBookAppURL(pdfParams.back) : null) ??
|
||||||
|
linker.toAbsoluteURL(linker.toPathInSpace(''))
|
||||||
|
}
|
||||||
className={tcls(
|
className={tcls(
|
||||||
'flex',
|
'flex',
|
||||||
'flex-row',
|
'flex-row',
|
||||||
@@ -353,3 +356,13 @@ function selectPages(
|
|||||||
});
|
});
|
||||||
return limitTo(allPages);
|
return limitTo(allPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the HTML ID for the container of a page or a given anchor in it.
|
||||||
|
*/
|
||||||
|
function getPagePDFContainerId(
|
||||||
|
page: RevisionPageDocument | RevisionPageGroup,
|
||||||
|
anchor?: string
|
||||||
|
): string {
|
||||||
|
return `pdf-page-${page.id}${anchor ? `-${anchor}` : ''}`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { useScrollActiveId } from '@/components/hooks';
|
import { useScrollActiveId } from '@/components/hooks';
|
||||||
import { Button } from '@/components/primitives';
|
import { Button } from '@/components/primitives';
|
||||||
import { t, useLanguage } from '@/intl/client';
|
import { t, tString, useLanguage } from '@/intl/client';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
import { type PDFSearchParams, getPDFURLSearchParams } from './urls';
|
import { type PDFSearchParams, getPDFURLSearchParams } from './urls';
|
||||||
|
|
||||||
@@ -58,9 +58,8 @@ export function PageControlButtons(props: {
|
|||||||
only: true,
|
only: true,
|
||||||
}).toString()}`}
|
}).toString()}`}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
>
|
label={tString(language, 'pdf_mode_only_page')}
|
||||||
{t(language, 'pdf_mode_only_page')}
|
/>
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
href={`?${getPDFURLSearchParams({
|
href={`?${getPDFURLSearchParams({
|
||||||
@@ -69,9 +68,8 @@ export function PageControlButtons(props: {
|
|||||||
only: false,
|
only: false,
|
||||||
}).toString()}`}
|
}).toString()}`}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
>
|
label={tString(language, 'pdf_mode_all')}
|
||||||
{t(language, 'pdf_mode_all')}
|
/>
|
||||||
</Button>
|
|
||||||
|
|
||||||
{trademark ? <div className={tcls('mt-5')}>{trademark}</div> : null}
|
{trademark ? <div className={tcls('mt-5')}>{trademark}</div> : null}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export function PageAside(props: {
|
|||||||
) : null}
|
) : null}
|
||||||
<div
|
<div
|
||||||
className={tcls(
|
className={tcls(
|
||||||
'sticky bottom-0 z-10 mt-auto flex flex-col bg-tint-base theme-bold-tint:bg-tint-subtle theme-gradient-tint:bg-gradient-tint theme-gradient:bg-gradient-primary theme-muted:bg-tint-subtle pb-4 page-api-block:xl:max-2xl:hidden page-api-block:xl:max-2xl:pb-0 page-api-block:xl:max-2xl:group-hover/aside:flex',
|
'sticky bottom-0 z-10 mt-auto flex flex-col bg-tint-base theme-gradient-tint:bg-gradient-tint theme-gradient:bg-gradient-primary theme-muted:bg-tint-subtle pb-4 page-api-block:xl:max-2xl:hidden page-api-block:xl:max-2xl:pb-0 page-api-block:xl:max-2xl:group-hover/aside:flex [html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||||
'page-api-block:xl:max-2xl:bg-transparent'
|
'page-api-block:xl:max-2xl:bg-transparent'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export function ScrollSectionsList(props: { sections: DocumentSection[] }) {
|
|||||||
|
|
||||||
'hover:bg-primary-hover',
|
'hover:bg-primary-hover',
|
||||||
'theme-muted:hover:bg-primary-active',
|
'theme-muted:hover:bg-primary-active',
|
||||||
'theme-bold-tint:hover:bg-primary-active',
|
'[html.sidebar-filled.theme-bold.tint_&]:hover:bg-primary-active',
|
||||||
'theme-gradient:hover:bg-primary-active',
|
'theme-gradient:hover:bg-primary-active',
|
||||||
|
|
||||||
'tint:font-semibold',
|
'tint:font-semibold',
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { t } from '@/intl/translate';
|
|||||||
import { hasFullWidthBlock, isNodeEmpty } from '@/lib/document';
|
import { hasFullWidthBlock, isNodeEmpty } from '@/lib/document';
|
||||||
import type { AncestorRevisionPage } from '@/lib/pages';
|
import type { AncestorRevisionPage } from '@/lib/pages';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
import { DocumentView, DocumentViewSkeleton } from '../DocumentView';
|
import { DocumentView, DocumentViewSkeleton } from '../DocumentView';
|
||||||
import { TrackPageViewEvent } from '../Insights';
|
import { TrackPageViewEvent } from '../Insights';
|
||||||
import { PageFeedbackForm } from '../PageFeedback';
|
import { PageFeedbackForm } from '../PageFeedback';
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import type { RevisionPageDocument, RevisionPageDocumentCover } from '@gitbook/api';
|
import type { RevisionPageDocument, RevisionPageDocumentCover } from '@gitbook/api';
|
||||||
import type { GitBookSiteContext } from '@v2/lib/context';
|
import type { GitBookSiteContext } from '@v2/lib/context';
|
||||||
|
import type { StaticImageData } from 'next/image';
|
||||||
|
|
||||||
import { Image, type ImageSize } from '@/components/utils';
|
import { Image, type ImageSize } from '@/components/utils';
|
||||||
import { resolveContentRef } from '@/lib/references';
|
import { resolveContentRef } from '@/lib/references';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
import defaultPageCover from './default-page-cover.svg';
|
import defaultPageCoverSVG from './default-page-cover.svg';
|
||||||
|
|
||||||
|
const defaultPageCover = defaultPageCoverSVG as StaticImageData;
|
||||||
const PAGE_COVER_SIZE: ImageSize = { width: 1990, height: 480 };
|
const PAGE_COVER_SIZE: ImageSize = { width: 1990, height: 480 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export async function PageHeader(props: {
|
|||||||
>
|
>
|
||||||
{ancestors.length > 0 && (
|
{ancestors.length > 0 && (
|
||||||
<nav>
|
<nav>
|
||||||
<ol className={tcls('flex', 'flex-wrap', 'items-center', 'gap-2')}>
|
<ol className={tcls('flex', 'flex-wrap', 'items-center', 'gap-2', 'text-tint')}>
|
||||||
{ancestors.map((breadcrumb, index) => {
|
{ancestors.map((breadcrumb, index) => {
|
||||||
const href = linker.toPathForPage({ pages, page: breadcrumb });
|
const href = linker.toPathForPage({ pages, page: breadcrumb });
|
||||||
return (
|
return (
|
||||||
@@ -35,7 +35,7 @@ export async function PageHeader(props: {
|
|||||||
<li key={breadcrumb.id}>
|
<li key={breadcrumb.id}>
|
||||||
<StyledLink
|
<StyledLink
|
||||||
href={href}
|
href={href}
|
||||||
style={tcls(
|
className={tcls(
|
||||||
'no-underline',
|
'no-underline',
|
||||||
'hover:underline',
|
'hover:underline',
|
||||||
'text-xs',
|
'text-xs',
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export type PageContextType = {
|
||||||
|
pageId: string;
|
||||||
|
spaceId: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PageContext = React.createContext<PageContextType | null>(null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client side context provider to pass information about the current page.
|
||||||
|
*/
|
||||||
|
export function PageContextProvider(props: PageContextType & { children: React.ReactNode }) {
|
||||||
|
const { pageId, spaceId, title, children } = props;
|
||||||
|
|
||||||
|
const value = React.useMemo(() => ({ pageId, spaceId, title }), [pageId, spaceId, title]);
|
||||||
|
|
||||||
|
return <PageContext.Provider value={value}>{children}</PageContext.Provider>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to use the page context.
|
||||||
|
*/
|
||||||
|
export function usePageContext() {
|
||||||
|
const context = React.useContext(PageContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('usePageContext must be used within a PageContextProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './PageContext';
|
||||||
@@ -106,9 +106,8 @@ export function PageFeedbackForm(props: {
|
|||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() => onSubmitComment(rating, comment)}
|
onClick={() => onSubmitComment(rating, comment)}
|
||||||
>
|
label={tString(languages, 'submit')}
|
||||||
{t(languages, 'submit')}
|
/>
|
||||||
</Button>
|
|
||||||
{comment.length > MAX_COMMENT_LENGTH * 0.8 ? (
|
{comment.length > MAX_COMMENT_LENGTH * 0.8 ? (
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
|
|||||||
@@ -153,9 +153,9 @@ export async function CustomizationRootLayout(props: {
|
|||||||
</head>
|
</head>
|
||||||
<body
|
<body
|
||||||
className={tcls(
|
className={tcls(
|
||||||
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||||
'bg-tint-base',
|
'bg-tint-base',
|
||||||
'theme-muted:bg-tint-subtle',
|
'theme-muted:bg-tint-subtle',
|
||||||
'theme-bold-tint:bg-tint-subtle',
|
|
||||||
|
|
||||||
'theme-gradient:bg-gradient-primary',
|
'theme-gradient:bg-gradient-primary',
|
||||||
'theme-gradient-tint:bg-gradient-tint'
|
'theme-gradient-tint:bg-gradient-tint'
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { useScrollPage } from '@/components/hooks';
|
|||||||
export function PageClientLayout(props: { withSections?: boolean }) {
|
export function PageClientLayout(props: { withSections?: boolean }) {
|
||||||
// We use this hook in the page layout to ensure the elements for the blocks
|
// We use this hook in the page layout to ensure the elements for the blocks
|
||||||
// are rendered before we scroll to a hash or to the top of the page
|
// are rendered before we scroll to a hash or to the top of the page
|
||||||
useScrollPage({ scrollMarginTop: props.withSections ? 50 : undefined });
|
useScrollPage({ scrollMarginTop: props.withSections ? 48 : undefined });
|
||||||
|
|
||||||
useStripFallbackQueryParam();
|
useStripFallbackQueryParam();
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -11,12 +11,10 @@ import { getPagePath } from '@/lib/pages';
|
|||||||
import { isPageIndexable, isSiteIndexable } from '@/lib/seo';
|
import { isPageIndexable, isSiteIndexable } from '@/lib/seo';
|
||||||
|
|
||||||
import { getResizedImageURL } from '@v2/lib/images';
|
import { getResizedImageURL } from '@v2/lib/images';
|
||||||
|
import { PageContextProvider } from '../PageContext';
|
||||||
import { PageClientLayout } from './PageClientLayout';
|
import { PageClientLayout } from './PageClientLayout';
|
||||||
import { type PagePathParams, fetchPageData, getPathnameParam } from './fetch';
|
import { type PagePathParams, fetchPageData, getPathnameParam } from './fetch';
|
||||||
|
|
||||||
export const runtime = 'edge';
|
|
||||||
export const dynamic = 'force-dynamic';
|
|
||||||
|
|
||||||
export type SitePageProps = {
|
export type SitePageProps = {
|
||||||
context: GitBookSiteContext;
|
context: GitBookSiteContext;
|
||||||
pageParams: PagePathParams;
|
pageParams: PagePathParams;
|
||||||
@@ -67,7 +65,7 @@ export async function SitePage(props: SitePageProps) {
|
|||||||
const document = await getPageDocument(context.dataFetcher, context.space, page);
|
const document = await getPageDocument(context.dataFetcher, context.space, page);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageContextProvider pageId={page.id} spaceId={context.space.id} title={page.title}>
|
||||||
{withFullPageCover && page.cover ? (
|
{withFullPageCover && page.cover ? (
|
||||||
<PageCover as="full" page={page} cover={page.cover} context={context} />
|
<PageCover as="full" page={page} cover={page.cover} context={context} />
|
||||||
) : null}
|
) : null}
|
||||||
@@ -92,7 +90,7 @@ export async function SitePage(props: SitePageProps) {
|
|||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
<PageClientLayout withSections={withSections} />
|
<PageClientLayout withSections={withSections} />
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</>
|
</PageContextProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export function SiteSectionList(props: { sections: ClientSiteSections; className
|
|||||||
<nav
|
<nav
|
||||||
aria-label="Sections"
|
aria-label="Sections"
|
||||||
className={tcls(
|
className={tcls(
|
||||||
'-mx-5 before:contents[] relative border-tint-subtle border-b from-transparent sidebar-filled:to-tint-subtle theme-bold-tint:to-tint-subtle theme-muted:to-tint-subtle to-tint-base text-sm text-tint before:pointer-events-none before:absolute before:right-2 before:bottom-0 before:left-0 before:h-12 before:bg-gradient-to-b [html.sidebar-filled.theme-bold.tint_&]:to-tint-base [html.sidebar-filled.theme-muted_&]:to-tint-base',
|
'-mx-5 before:contents[] relative border-tint-subtle border-b from-transparent sidebar-filled:to-tint-subtle theme-muted:to-tint-subtle to-tint-base text-sm text-tint before:pointer-events-none before:absolute before:right-2 before:bottom-0 before:left-0 before:h-12 before:bg-gradient-to-b [html.sidebar-filled.theme-bold.tint_&]:to-tint-base [html.sidebar-filled.theme-bold.tint_&]:to-tint-subtle [html.sidebar-filled.theme-muted_&]:to-tint-base',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export function SpaceLayout(props: {
|
|||||||
revisionId={context.revisionId}
|
revisionId={context.revisionId}
|
||||||
spaceId={context.space.id}
|
spaceId={context.space.id}
|
||||||
visitorAuthClaims={visitorAuthClaims}
|
visitorAuthClaims={visitorAuthClaims}
|
||||||
|
visitorCookieTrackingEnabled={context.customization.insights?.trackingCookie}
|
||||||
>
|
>
|
||||||
<Announcement context={context} />
|
<Announcement context={context} />
|
||||||
<Header withTopHeader={withTopHeader} context={context} />
|
<Header withTopHeader={withTopHeader} context={context} />
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function PageGroupItem(props: {
|
|||||||
'bg-tint-base',
|
'bg-tint-base',
|
||||||
'sidebar-filled:bg-tint-subtle',
|
'sidebar-filled:bg-tint-subtle',
|
||||||
'theme-muted:bg-tint-subtle',
|
'theme-muted:bg-tint-subtle',
|
||||||
'theme-bold-tint:bg-tint-subtle',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||||
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
|
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
|
||||||
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
|
||||||
'[html.sidebar-default.theme-gradient_&]:bg-gradient-primary',
|
'[html.sidebar-default.theme-gradient_&]:bg-gradient-primary',
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ export function TableOfContents(props: {
|
|||||||
|
|
||||||
'sidebar-filled:bg-tint-subtle',
|
'sidebar-filled:bg-tint-subtle',
|
||||||
'theme-muted:bg-tint-subtle',
|
'theme-muted:bg-tint-subtle',
|
||||||
'theme-bold-tint:bg-tint-subtle',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
|
||||||
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
|
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
|
||||||
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
|
||||||
'page-no-toc:!bg-transparent',
|
'page-no-toc:!bg-transparent',
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export function Trademark(props: {
|
|||||||
'before:to-tint-base',
|
'before:to-tint-base',
|
||||||
'sidebar-filled:before:to-tint-subtle',
|
'sidebar-filled:before:to-tint-subtle',
|
||||||
'theme-muted:before:to-tint-subtle',
|
'theme-muted:before:to-tint-subtle',
|
||||||
'theme-bold-tint:before:to-tint-subtle',
|
'[html.sidebar-filled.theme-bold.tint_&]:before:to-tint-subtle',
|
||||||
'[html.sidebar-filled.theme-muted_&]:before:to-tint-base',
|
'[html.sidebar-filled.theme-muted_&]:before:to-tint-base',
|
||||||
'[html.sidebar-filled.theme-bold.tint_&]:before:to-tint-base',
|
'[html.sidebar-filled.theme-bold.tint_&]:before:to-tint-base',
|
||||||
'page-no-toc:before:!to-transparent'
|
'page-no-toc:before:!to-transparent'
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function ThemeButton(props: {
|
|||||||
active && [
|
active && [
|
||||||
'bg-primary',
|
'bg-primary',
|
||||||
'theme-muted:bg-primary-hover',
|
'theme-muted:bg-primary-hover',
|
||||||
'theme-bold-tint:bg-primary-hover',
|
'[html.sidebar-filled.theme-bold.tint_&]:bg-primary-hover',
|
||||||
'hover:bg-primary',
|
'hover:bg-primary',
|
||||||
'text-primary-strong',
|
'text-primary-strong',
|
||||||
'contrast-more:text-primary-strong',
|
'contrast-more:text-primary-strong',
|
||||||
|
|||||||
@@ -1,62 +1,80 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import type { HTMLAttributes } from 'react';
|
import type { HTMLAttributeAnchorTarget, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
|
import { Icon, type IconName } from '@gitbook/icons';
|
||||||
import { Link, type LinkInsightsProps } from './Link';
|
import { Link, type LinkInsightsProps } from './Link';
|
||||||
|
|
||||||
type ButtonProps = {
|
type ButtonProps = {
|
||||||
href?: string;
|
href?: string;
|
||||||
variant?: 'primary' | 'secondary';
|
variant?: 'primary' | 'secondary' | 'blank';
|
||||||
|
icon?: IconName;
|
||||||
|
iconOnly?: boolean;
|
||||||
size?: 'default' | 'medium' | 'small';
|
size?: 'default' | 'medium' | 'small';
|
||||||
className?: ClassValue;
|
className?: ClassValue;
|
||||||
|
label?: string;
|
||||||
} & LinkInsightsProps &
|
} & LinkInsightsProps &
|
||||||
HTMLAttributes<HTMLElement>;
|
HTMLAttributes<HTMLElement>;
|
||||||
|
|
||||||
|
const variantClasses = {
|
||||||
|
primary: [
|
||||||
|
'bg-primary-solid',
|
||||||
|
'text-contrast-primary-solid',
|
||||||
|
'hover:bg-primary-solid-hover',
|
||||||
|
'hover:text-contrast-primary-solid-hover',
|
||||||
|
'ring-0',
|
||||||
|
'contrast-more:ring-1',
|
||||||
|
],
|
||||||
|
blank: [
|
||||||
|
'bg-transparent',
|
||||||
|
'text-tint',
|
||||||
|
'ring-0',
|
||||||
|
'shadow-none',
|
||||||
|
'hover:bg-primary-hover',
|
||||||
|
'hover:text-primary',
|
||||||
|
'hover:scale-1',
|
||||||
|
'hover:shadow-none',
|
||||||
|
'contrast-more:bg-tint-subtle',
|
||||||
|
],
|
||||||
|
secondary: [
|
||||||
|
'bg-tint',
|
||||||
|
'text-tint',
|
||||||
|
'hover:bg-tint-hover',
|
||||||
|
'hover:text-primary',
|
||||||
|
'contrast-more:bg-tint-subtle',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
export function Button({
|
export function Button({
|
||||||
href,
|
href,
|
||||||
children,
|
|
||||||
variant = 'primary',
|
variant = 'primary',
|
||||||
size = 'default',
|
size = 'default',
|
||||||
className,
|
className,
|
||||||
insights,
|
insights,
|
||||||
|
target,
|
||||||
|
label,
|
||||||
|
icon,
|
||||||
|
iconOnly = false,
|
||||||
...rest
|
...rest
|
||||||
}: ButtonProps) {
|
}: ButtonProps & { target?: HTMLAttributeAnchorTarget }) {
|
||||||
const variantClasses =
|
|
||||||
variant === 'primary'
|
|
||||||
? //PRIMARY
|
|
||||||
[
|
|
||||||
'bg-primary-solid',
|
|
||||||
'text-contrast-primary-solid',
|
|
||||||
'hover:bg-primary-solid-hover',
|
|
||||||
'hover:text-contrast-primary-solid-hover',
|
|
||||||
'ring-0',
|
|
||||||
'contrast-more:ring-1',
|
|
||||||
]
|
|
||||||
: // SECONDARY
|
|
||||||
[
|
|
||||||
'bg-tint',
|
|
||||||
'text-tint',
|
|
||||||
'hover:bg-tint-hover',
|
|
||||||
'hover:text-primary',
|
|
||||||
'contrast-more:bg-tint-subtle',
|
|
||||||
];
|
|
||||||
|
|
||||||
const sizes = {
|
const sizes = {
|
||||||
default: ['text-base', 'px-4', 'py-2'],
|
default: ['text-base', 'px-4', 'py-2'],
|
||||||
medium: ['text-sm', 'px-3', 'py-1.5'],
|
medium: ['text-sm', 'px-3', 'py-1.5'],
|
||||||
small: ['text-xs', 'px-3 py-2'],
|
small: ['text-xs', 'py-2', iconOnly ? 'px-2' : 'px-3'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const sizeClasses = sizes[size] || sizes.default;
|
const sizeClasses = sizes[size] || sizes.default;
|
||||||
|
|
||||||
const domClassName = tcls(
|
const domClassName = tcls(
|
||||||
'button',
|
'button',
|
||||||
'inline-block',
|
'inline-flex',
|
||||||
|
'items-center',
|
||||||
|
'gap-2',
|
||||||
'rounded-md',
|
'rounded-md',
|
||||||
'straight-corners:rounded-none',
|
'straight-corners:rounded-none',
|
||||||
'place-self-start',
|
// 'place-self-start',
|
||||||
|
|
||||||
'ring-1',
|
'ring-1',
|
||||||
'ring-tint',
|
'ring-tint',
|
||||||
@@ -79,22 +97,31 @@ export function Button({
|
|||||||
'grow-0',
|
'grow-0',
|
||||||
'shrink-0',
|
'shrink-0',
|
||||||
'truncate',
|
'truncate',
|
||||||
variantClasses,
|
variantClasses[variant],
|
||||||
sizeClasses,
|
sizeClasses,
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
return (
|
return (
|
||||||
<Link href={href} className={domClassName} insights={insights} {...rest}>
|
<Link
|
||||||
{children}
|
href={href}
|
||||||
|
className={domClassName}
|
||||||
|
insights={insights}
|
||||||
|
aria-label={label}
|
||||||
|
target={target}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{icon ? <Icon icon={icon} className={tcls('size-[1em]')} /> : null}
|
||||||
|
{iconOnly ? null : label}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button type="button" className={domClassName} {...rest}>
|
<button type="button" className={domClassName} aria-label={label} {...rest}>
|
||||||
{children}
|
{icon ? <Icon icon={icon} className={tcls('size-[1em]')} /> : null}
|
||||||
|
{iconOnly ? null : label}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import type { SVGProps } from 'react';
|
|||||||
|
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
export const Loading = (props: Partial<SVGProps<SVGSVGElement>>) => {
|
export const Loading = ({
|
||||||
|
busy = true,
|
||||||
|
...props
|
||||||
|
}: { busy?: boolean } & SVGProps<SVGSVGElement>) => {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width="100%"
|
width="100%"
|
||||||
@@ -14,7 +17,11 @@ export const Loading = (props: Partial<SVGProps<SVGSVGElement>>) => {
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
className={tcls('animate-[pathLoading_2s_ease_infinite_forwards]')}
|
className={tcls(
|
||||||
|
busy
|
||||||
|
? 'animate-[pathLoading_2s_ease_infinite_forwards]'
|
||||||
|
: 'animate-[pathLoading_2s_ease_forwards]'
|
||||||
|
)}
|
||||||
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
pathLength="100"
|
pathLength="100"
|
||||||
@@ -27,7 +34,8 @@ export const Loading = (props: Partial<SVGProps<SVGSVGElement>>) => {
|
|||||||
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
d="M6 59.5V56.291C6 45.8865 11.5194 36.263 20.5 31.0091V31.0091L60.9857 7.32407C63.4452 5.88525 66.4843 5.86317 68.9643 7.26611L116 33.8734L70.4183 60.2148C67.9468 61.6431 64.9014 61.6462 62.4269 60.223L29.9772 41.5592C19.3106 35.4242 6 43.1236 6 55.4288V64.8776C6 73.4486 10.5708 81.3691 17.9918 85.6575L54.59 106.807C62.0198 111.1 71.1766 111.1 78.6064 106.807L116.364 84.9874C120.074 82.8432 122.36 78.883 122.36 74.5975V59.2647C122.36 57.7248 120.692 56.7626 119.359 57.5331L72.6023 84.5529C68.8874 86.6996 64.309 86.6996 60.5941 84.5529L26 64.5617"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
pathLength="100"
|
pathLength="100"
|
||||||
strokeOpacity="0.24"
|
strokeOpacity={busy ? 0.24 : 1}
|
||||||
|
className="transition-opacity duration-1000"
|
||||||
fill="none"
|
fill="none"
|
||||||
strokeWidth="11"
|
strokeWidth="11"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ export const linkStyles = [
|
|||||||
/**
|
/**
|
||||||
* Styled version of Link component.
|
* Styled version of Link component.
|
||||||
*/
|
*/
|
||||||
export function StyledLink(props: Omit<LinkProps, 'style'> & { style?: ClassValue }) {
|
export function StyledLink(props: Omit<LinkProps, 'style'> & { className?: ClassValue }) {
|
||||||
const { style, ...rest } = props;
|
const { className, ...rest } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link {...rest} className={tcls(linkStyles, style)}>
|
<Link {...rest} className={tcls(linkStyles, className)}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ function ZoomImageModal(props: {
|
|||||||
)}
|
)}
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<Icon icon="compress-wide" className={tcls('size-5')} />
|
<Icon icon="close" className={tcls('size-5')} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ export const de = {
|
|||||||
'Das PDF konnte für ${1} Seiten nicht generiert werden, Generierung wurde bei ${2} gestoppt.',
|
'Das PDF konnte für ${1} Seiten nicht generiert werden, Generierung wurde bei ${2} gestoppt.',
|
||||||
pdf_limit_reached_continue: 'Mit ${1} weiteren Seiten erweitern.',
|
pdf_limit_reached_continue: 'Mit ${1} weiteren Seiten erweitern.',
|
||||||
more: 'Mehr',
|
more: 'Mehr',
|
||||||
|
link_tooltip_external_link: 'Externe Verlinkung zu',
|
||||||
|
link_tooltip_page_anchor: 'Zum Abschnitt springen',
|
||||||
|
link_tooltip_ai_summary: 'Seitenhighlight',
|
||||||
|
link_tooltip_ai_summary_description: 'Basierend auf Ihrem Kontext. Kann Fehler enthalten.',
|
||||||
|
open_in_new_tab: 'In neuem Tab öffnen',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,4 +56,9 @@ export const en = {
|
|||||||
pdf_limit_reached: "Couldn't generate the PDF for ${1} pages, generation stopped at ${2}.",
|
pdf_limit_reached: "Couldn't generate the PDF for ${1} pages, generation stopped at ${2}.",
|
||||||
pdf_limit_reached_continue: 'Extend with ${1} more pages.',
|
pdf_limit_reached_continue: 'Extend with ${1} more pages.',
|
||||||
more: 'More',
|
more: 'More',
|
||||||
|
link_tooltip_external_link: 'External link to',
|
||||||
|
link_tooltip_page_anchor: 'Jump to section',
|
||||||
|
link_tooltip_ai_summary: 'Page highlight',
|
||||||
|
link_tooltip_ai_summary_description: 'Based on your context. May contain mistakes.',
|
||||||
|
open_in_new_tab: 'Open in new tab',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,4 +60,9 @@ export const es: TranslationLanguage = {
|
|||||||
'No se pudo generar el PDF para ${1} páginas, la generación se detuvo en ${2}.',
|
'No se pudo generar el PDF para ${1} páginas, la generación se detuvo en ${2}.',
|
||||||
pdf_limit_reached_continue: 'Extender con ${1} páginas más.',
|
pdf_limit_reached_continue: 'Extender con ${1} páginas más.',
|
||||||
more: 'Más',
|
more: 'Más',
|
||||||
|
link_tooltip_external_link: 'Enlace externo a',
|
||||||
|
link_tooltip_page_anchor: 'Saltar a la sección',
|
||||||
|
link_tooltip_ai_summary: 'Resumen de la página',
|
||||||
|
link_tooltip_ai_summary_description: 'Basado en tu contexto. Puede contener errores.',
|
||||||
|
open_in_new_tab: 'Abrir en una nueva pestaña',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ export const fr: TranslationLanguage = {
|
|||||||
pdf_limit_reached: 'Impossible de générer le PDF pour ${1} pages, génération arrêtée à ${2}.',
|
pdf_limit_reached: 'Impossible de générer le PDF pour ${1} pages, génération arrêtée à ${2}.',
|
||||||
pdf_limit_reached_continue: 'Étendre avec ${1} pages supplémentaires.',
|
pdf_limit_reached_continue: 'Étendre avec ${1} pages supplémentaires.',
|
||||||
more: 'Plus',
|
more: 'Plus',
|
||||||
|
link_tooltip_external_link: 'Lien externe à',
|
||||||
|
link_tooltip_page_anchor: 'Sauter à la section',
|
||||||
|
link_tooltip_ai_summary: 'Résumé de la page',
|
||||||
|
link_tooltip_ai_summary_description: 'Basé sur votre contexte. Peut contenir des erreurs.',
|
||||||
|
open_in_new_tab: 'Ouvrir dans un nouvel onglet',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,4 +58,10 @@ export const ja: TranslationLanguage = {
|
|||||||
pdf_limit_reached: '${1}ページのPDFを生成できませんでした、${2}で生成が停止しました。',
|
pdf_limit_reached: '${1}ページのPDFを生成できませんでした、${2}で生成が停止しました。',
|
||||||
pdf_limit_reached_continue: 'さらに${1}ページで拡張',
|
pdf_limit_reached_continue: 'さらに${1}ページで拡張',
|
||||||
more: '詳細',
|
more: '詳細',
|
||||||
|
link_tooltip_external_link: '外部リンク先',
|
||||||
|
link_tooltip_page_anchor: 'ページ内リンク先',
|
||||||
|
link_tooltip_ai_summary: 'ページのハイライト',
|
||||||
|
link_tooltip_ai_summary_description:
|
||||||
|
'あなたのコンテキストに基づいています。間違いが含まれる可能性があります。',
|
||||||
|
open_in_new_tab: '新しいタブで開く',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ export const nl: TranslationLanguage = {
|
|||||||
pdf_limit_reached: "Kon de PDF niet genereren voor ${1} pagina's, generatie gestopt bij ${2}.",
|
pdf_limit_reached: "Kon de PDF niet genereren voor ${1} pagina's, generatie gestopt bij ${2}.",
|
||||||
pdf_limit_reached_continue: 'Verleng met ${1} extra pagina’s.',
|
pdf_limit_reached_continue: 'Verleng met ${1} extra pagina’s.',
|
||||||
more: 'Meer',
|
more: 'Meer',
|
||||||
|
link_tooltip_external_link: 'Externe link naar',
|
||||||
|
link_tooltip_page_anchor: 'Spring naar sectie',
|
||||||
|
link_tooltip_ai_summary: 'Pagina-samenvatting',
|
||||||
|
link_tooltip_ai_summary_description: 'Gebaseerd op je context. Kan fouten bevatten.',
|
||||||
|
open_in_new_tab: 'Open in nieuw tabblad',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ export const no: TranslationLanguage = {
|
|||||||
pdf_limit_reached: 'Kunne ikke generere PDF for ${1} sider, generering stoppet ved ${2}.',
|
pdf_limit_reached: 'Kunne ikke generere PDF for ${1} sider, generering stoppet ved ${2}.',
|
||||||
pdf_limit_reached_continue: 'Utvid med ${1} flere sider.',
|
pdf_limit_reached_continue: 'Utvid med ${1} flere sider.',
|
||||||
more: 'Mer',
|
more: 'Mer',
|
||||||
|
link_tooltip_external_link: 'Ekstern lenke til',
|
||||||
|
link_tooltip_page_anchor: 'Hopp til seksjon',
|
||||||
|
link_tooltip_ai_summary: 'Sidesammendrag',
|
||||||
|
link_tooltip_ai_summary_description: 'Basert på din kontekst. Kan inneholde feil.',
|
||||||
|
open_in_new_tab: 'Åpne i ny fane',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ export const pt_br = {
|
|||||||
'Não foi possível gerar o PDF para ${1} páginas, generation stopped at ${2}.',
|
'Não foi possível gerar o PDF para ${1} páginas, generation stopped at ${2}.',
|
||||||
pdf_limit_reached_continue: 'Extender com mais ${1} páginas.',
|
pdf_limit_reached_continue: 'Extender com mais ${1} páginas.',
|
||||||
more: 'Mais',
|
more: 'Mais',
|
||||||
|
link_tooltip_external_link: 'Link externo para',
|
||||||
|
link_tooltip_page_anchor: 'Pular para a seção',
|
||||||
|
link_tooltip_ai_summary: 'Resumo da página',
|
||||||
|
link_tooltip_ai_summary_description: 'Baseado no seu contexto. Pode conter erros.',
|
||||||
|
open_in_new_tab: 'Abrir em uma nova guia',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,4 +56,9 @@ export const zh: TranslationLanguage = {
|
|||||||
pdf_limit_reached: '无法为${1}页生成 PDF,生成在${2}页时停止。',
|
pdf_limit_reached: '无法为${1}页生成 PDF,生成在${2}页时停止。',
|
||||||
pdf_limit_reached_continue: '使用${1}页进行扩展。',
|
pdf_limit_reached_continue: '使用${1}页进行扩展。',
|
||||||
more: '更多',
|
more: '更多',
|
||||||
|
link_tooltip_external_link: '外部链接到',
|
||||||
|
link_tooltip_page_anchor: '跳转到页面',
|
||||||
|
link_tooltip_ai_summary: '页面要点',
|
||||||
|
link_tooltip_ai_summary_description: '基于您的上下文。可能包含错误。',
|
||||||
|
open_in_new_tab: '在新标签页中打开',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { GITBOOK_APP_URL } from '@v2/lib/env';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an absolute href in the GitBook application.
|
||||||
|
*/
|
||||||
|
export function getGitBookAppHref(pathname: string): string {
|
||||||
|
const appUrl = new URL(GITBOOK_APP_URL);
|
||||||
|
appUrl.pathname = pathname;
|
||||||
|
|
||||||
|
return appUrl.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize a URL to be a valid GitBook.com app URL.
|
||||||
|
*/
|
||||||
|
export function sanitizeGitBookAppURL(input: string): string | null {
|
||||||
|
if (!URL.canParse(input)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(input);
|
||||||
|
if (url.origin !== GITBOOK_APP_URL) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
+51
-1
@@ -64,7 +64,10 @@ export const cloudflareDOCache: CacheBackend = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keys = await stub.purge();
|
const keys = await retryOnDurableObjectError(async () => {
|
||||||
|
return await stub.purge();
|
||||||
|
});
|
||||||
|
|
||||||
keys.forEach((key) => {
|
keys.forEach((key) => {
|
||||||
entries.push({ key, tag });
|
entries.push({ key, tag });
|
||||||
});
|
});
|
||||||
@@ -99,3 +102,50 @@ async function getStub(tag: string): Promise<CacheObjectStub | null> {
|
|||||||
|
|
||||||
return stub;
|
return stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retry an operation on a Durable Object if it fails with a retriable error.
|
||||||
|
* It will retry up to 4 times with an exponential backoff.
|
||||||
|
*/
|
||||||
|
export async function retryOnDurableObjectError<T>(
|
||||||
|
operation: () => T | Promise<T>,
|
||||||
|
attemptsLeft = 4,
|
||||||
|
delay = 50
|
||||||
|
): Promise<T> {
|
||||||
|
if (attemptsLeft <= 0) {
|
||||||
|
return operation();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await operation();
|
||||||
|
} catch (error) {
|
||||||
|
if (!shouldRetryError(error)) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attemptsLeft > 0) {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
|
return retryOnDurableObjectError(operation, attemptsLeft - 1, delay * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const RETRIABLE_ERROR_MESSAGES = new Set([
|
||||||
|
'Cannot resolve Durable Object due to transient issue on remote node.',
|
||||||
|
'internal error',
|
||||||
|
`Durable Object's isolate exceeded its memory limit and was reset.`,
|
||||||
|
'cannot access storage because object has moved to a different machine',
|
||||||
|
'Durable Object reset because its code was updated.',
|
||||||
|
"The Durable Object's code has been updated, this version can no longer access storage.",
|
||||||
|
// https://developers.cloudflare.com/workers/observability/errors/#runtime-errors
|
||||||
|
'Network connection lost.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an error should be retried based on its error message.
|
||||||
|
*/
|
||||||
|
function shouldRetryError(error: unknown): boolean {
|
||||||
|
return error instanceof Error && RETRIABLE_ERROR_MESSAGES.has(error.message);
|
||||||
|
}
|
||||||
|
|||||||
+19
-11
@@ -36,18 +36,25 @@ export async function revalidateTags(tags: string[]): Promise<{
|
|||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
cacheBackends.map(async (backend, backendIndex) => {
|
cacheBackends.map(async (backend, backendIndex) => {
|
||||||
const { entries: addedEntries } = await backend.revalidateTags(tags);
|
try {
|
||||||
|
const { entries: addedEntries } = await backend.revalidateTags(tags);
|
||||||
|
|
||||||
addedEntries.forEach(({ key, tag }) => {
|
addedEntries.forEach(({ key, tag }) => {
|
||||||
stats[key] = stats[key] ?? {
|
stats[key] = stats[key] ?? {
|
||||||
tag,
|
tag,
|
||||||
backends: {},
|
backends: {},
|
||||||
};
|
};
|
||||||
stats[key].backends[backend.name] = { set: true };
|
stats[key].backends[backend.name] = { set: true };
|
||||||
|
|
||||||
entries.set(key, { tag, key });
|
entries.set(key, { tag, key });
|
||||||
keysByBackend.set(backendIndex, [...(keysByBackend.get(backendIndex) ?? []), key]);
|
keysByBackend.set(backendIndex, [
|
||||||
});
|
...(keysByBackend.get(backendIndex) ?? []),
|
||||||
|
key,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`error revalidating tags on backend ${backend.name}: ${err}`);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -71,7 +78,8 @@ export async function revalidateTags(tags: string[]): Promise<{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw error;
|
|
||||||
|
throw new Error(`error deleting entries on backend ${backend.name}: ${error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user