mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-26 04:07:07 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1fdce020f | |||
| 84e01f255e | |||
| a007604ab1 | |||
| 3076e96061 | |||
| a3741dd65f | |||
| 07085a5b89 | |||
| 36600bc0c7 | |||
| 5b7488b066 |
+1
-1
@@ -10,7 +10,7 @@ Invalidate cache can be done at two levels using tags:
|
||||
To invalidate and refetch the data cache, you can execute a POST request to `/~/gitbook/revalidate`:
|
||||
|
||||
```bash
|
||||
curl --location --request POST 'https://gitbook/mycompany.com/~gitbook/revalidate' \
|
||||
curl --location --request POST 'https://gitbook.mycompany.com/~gitbook/revalidate' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{"tags": ["space.id"]}'
|
||||
```
|
||||
|
||||
@@ -149,3 +149,37 @@ it('should parse Swagger 2.0', async () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve a ref with whitespace', async () => {
|
||||
const resolved = await fetchOpenAPIOperation(
|
||||
{
|
||||
url: ' https://petstore3.swagger.io/api/v3/openapi.json',
|
||||
method: 'put',
|
||||
path: '/pet',
|
||||
},
|
||||
fetcher,
|
||||
);
|
||||
|
||||
expect(resolved).toMatchObject({
|
||||
servers: [
|
||||
{
|
||||
url: '/api/v3',
|
||||
},
|
||||
],
|
||||
operation: {
|
||||
tags: ['pet'],
|
||||
summary: 'Update an existing pet',
|
||||
description: 'Update an existing pet by Id',
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
required: ['name', 'photoUrls'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CustomizationThemeMode } from '@gitbook/api';
|
||||
import { Metadata, Viewport } from 'next';
|
||||
import { headers } from 'next/headers';
|
||||
import React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
@@ -47,7 +48,10 @@ export default async function ContentLayout(props: { children: React.ReactNode }
|
||||
return (
|
||||
<ClientContexts
|
||||
nonce={nonce}
|
||||
forcedTheme={customization.themes.toggeable ? undefined : customization.themes.default}
|
||||
forcedTheme={
|
||||
getQueryStringTheme() ??
|
||||
(customization.themes.toggeable ? undefined : customization.themes.default)
|
||||
}
|
||||
>
|
||||
<SpaceLayout
|
||||
space={space}
|
||||
@@ -124,3 +128,18 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
robots: shouldIndexSpace({ space, collection }) ? 'index, follow' : 'noindex, nofollow',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For preview, the theme can be set via query string (?theme=light).
|
||||
*/
|
||||
function getQueryStringTheme() {
|
||||
const headersList = headers();
|
||||
const queryStringTheme = headersList.get('x-gitbook-theme');
|
||||
if (!queryStringTheme) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return queryStringTheme === 'light'
|
||||
? CustomizationThemeMode.Light
|
||||
: CustomizationThemeMode.Dark;
|
||||
}
|
||||
|
||||
@@ -33,10 +33,7 @@ export async function RecordCard(
|
||||
'z-0',
|
||||
'relative',
|
||||
'grid',
|
||||
'grid-cols-[40%,_1fr]',
|
||||
'bg-light',
|
||||
'min-[432px]:grid-cols-none',
|
||||
'min-[432px]:grid-rows-[auto,1fr]',
|
||||
'w-[calc(100%+2px)]',
|
||||
'h-[calc(100%+2px)]',
|
||||
'inset-[-1px]',
|
||||
@@ -44,6 +41,14 @@ export async function RecordCard(
|
||||
'straight-corners:rounded-none',
|
||||
'overflow-hidden',
|
||||
'dark:bg-dark',
|
||||
cover
|
||||
? [
|
||||
// On mobile, the cover is displayed on the left with 40% of the width
|
||||
'grid-cols-[40%,_1fr]',
|
||||
'min-[432px]:grid-cols-none',
|
||||
'min-[432px]:grid-rows-[auto,1fr]',
|
||||
]
|
||||
: null,
|
||||
)}
|
||||
>
|
||||
{cover ? (
|
||||
|
||||
@@ -69,7 +69,9 @@ async function fetchVisitorID(): Promise<string> {
|
||||
* Accept or reject cookies.
|
||||
*/
|
||||
export function setCookiesTracking(enabled: boolean) {
|
||||
cookies.set(GRANTED_COOKIE, enabled ? 'yes' : 'no');
|
||||
cookies.set(GRANTED_COOKIE, enabled ? 'yes' : 'no', {
|
||||
expires: 365,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-6
@@ -326,7 +326,7 @@ interface GetRevisionOptions {
|
||||
* Get a revision by its ID.
|
||||
*/
|
||||
export const getRevision = cache(
|
||||
'api.getRevision',
|
||||
'api.getRevision.v2',
|
||||
async (
|
||||
spaceId: string,
|
||||
revisionId: string,
|
||||
@@ -359,7 +359,7 @@ export const getRevision = cache(
|
||||
* Get all the pages in a revision of a space.
|
||||
*/
|
||||
export const getRevisionPages = cache(
|
||||
'api.getRevisionPages.v3',
|
||||
'api.getRevisionPages.v4',
|
||||
async (
|
||||
spaceId: string,
|
||||
revisionId: string,
|
||||
@@ -392,7 +392,7 @@ export const getRevisionPages = cache(
|
||||
* Get a revision page by its path
|
||||
*/
|
||||
export const getRevisionPageByPath = cache(
|
||||
'api.getRevisionPageByPath.v2',
|
||||
'api.getRevisionPageByPath.v3',
|
||||
async (
|
||||
spaceId: string,
|
||||
revisionId: string,
|
||||
@@ -434,7 +434,7 @@ export const getRevisionPageByPath = cache(
|
||||
* It should not be used directly, use `getRevisionFile` instead.
|
||||
*/
|
||||
const getRevisionFileById = cache(
|
||||
'api.getRevisionFile.v2',
|
||||
'api.getRevisionFile.v3',
|
||||
async (spaceId: string, revisionId: string, fileId: string, options: CacheFunctionOptions) => {
|
||||
try {
|
||||
const response = await (async () => {
|
||||
@@ -468,7 +468,7 @@ const getRevisionFileById = cache(
|
||||
* It should not be used directly, use `getRevisionFile` instead.
|
||||
*/
|
||||
const getRevisionAllFiles = cache(
|
||||
'api.getRevisionAllFiles',
|
||||
'api.getRevisionAllFiles.v2',
|
||||
async (spaceId: string, revisionId: string, options: CacheFunctionOptions) => {
|
||||
const response = await getAll(
|
||||
(params) =>
|
||||
@@ -558,7 +558,7 @@ export const getRevisionFile = batch<[string, string, string], RevisionFile | nu
|
||||
* Get a document by its ID.
|
||||
*/
|
||||
export const getDocument = cache(
|
||||
'api.getDocument',
|
||||
'api.getDocument.v2',
|
||||
async (spaceId: string, documentId: string, options: CacheFunctionOptions) => {
|
||||
const response = await api().spaces.getDocumentById(
|
||||
spaceId,
|
||||
|
||||
Vendored
+1
@@ -126,6 +126,7 @@ export function cache<Args extends any[], Result>(
|
||||
// Try the memory backend, independently of the other backends as it doesn't have a network cost
|
||||
const memoryEntry = await memoryCache.get(key);
|
||||
if (memoryEntry) {
|
||||
console.log(`${key} memcache ${Date.now()} setAt=${memoryEntry.meta.setAt} expiresAt=${memoryEntry.meta.expiresAt} revalidatesAt=${memoryEntry.meta.revalidatesAt}`)
|
||||
span.setAttribute('memory', true);
|
||||
result = [memoryEntry, 'memory'] as const;
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -185,7 +185,7 @@ export async function resizeImage(
|
||||
return response;
|
||||
}
|
||||
|
||||
return fetch(input, {
|
||||
return fetch(parsed, {
|
||||
// @ts-ignore
|
||||
cf: {
|
||||
image: resizeOptions,
|
||||
|
||||
+7
-2
@@ -50,13 +50,18 @@ export async function fetchOpenAPIBlock(
|
||||
|
||||
const fetcher: OpenAPIFetcher = {
|
||||
fetch: cache('openapi.fetch', async (url: string, options: CacheFunctionOptions) => {
|
||||
const response = await fetch(url, {
|
||||
// Wrap the raw string to prevent invalid URLs from being passed to fetch.
|
||||
// This can happen if the URL has whitespace, which is currently handled differently by Cloudflare's implementation of fetch:
|
||||
// https://github.com/cloudflare/workerd/issues/1957
|
||||
const response = await fetch(new URL(url), {
|
||||
...noCacheFetchOptions,
|
||||
signal: options.signal,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch OpenAPI file: ${response.statusText}`);
|
||||
throw new Error(
|
||||
`Failed to fetch OpenAPI file: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
|
||||
@@ -196,6 +196,11 @@ export async function middleware(request: NextRequest) {
|
||||
headers.set('x-gitbook-customization', customization);
|
||||
}
|
||||
|
||||
const theme = url.searchParams.get('theme');
|
||||
if (theme) {
|
||||
headers.set('x-gitbook-theme', theme);
|
||||
}
|
||||
|
||||
if (apiEndpoint) {
|
||||
headers.set('x-gitbook-api', apiEndpoint);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user