mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-14 06:35:17 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 404c8df073 | |||
| 05e1d8cd96 | |||
| 9f0de74caa | |||
| a820739bd2 |
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Remove unused search api method from gitbook/api/lib
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/react-openapi': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Hide x-gitbook-\* symbols in OpenAPI blocks
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add support for new OpenAPI ref
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/react-openapi': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix ID not set when there is no operation summary
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"packages/colors": {
|
"packages/colors": {
|
||||||
"name": "@gitbook/colors",
|
"name": "@gitbook/colors",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
},
|
},
|
||||||
@@ -38,9 +38,9 @@
|
|||||||
},
|
},
|
||||||
"packages/gitbook": {
|
"packages/gitbook": {
|
||||||
"name": "gitbook",
|
"name": "gitbook",
|
||||||
"version": "0.6.1",
|
"version": "0.6.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "^0.93.0",
|
"@gitbook/api": "^0.95.0",
|
||||||
"@gitbook/cache-do": "workspace:*",
|
"@gitbook/cache-do": "workspace:*",
|
||||||
"@gitbook/colors": "workspace:*",
|
"@gitbook/colors": "workspace:*",
|
||||||
"@gitbook/emoji-codepoints": "workspace:*",
|
"@gitbook/emoji-codepoints": "workspace:*",
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
},
|
},
|
||||||
"packages/openapi-parser": {
|
"packages/openapi-parser": {
|
||||||
"name": "@gitbook/openapi-parser",
|
"name": "@gitbook/openapi-parser",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@scalar/openapi-parser": "^0.10.4",
|
"@scalar/openapi-parser": "^0.10.4",
|
||||||
"@scalar/openapi-types": "^0.1.6",
|
"@scalar/openapi-types": "^0.1.6",
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
},
|
},
|
||||||
"packages/react-openapi": {
|
"packages/react-openapi": {
|
||||||
"name": "@gitbook/react-openapi",
|
"name": "@gitbook/react-openapi",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/openapi-parser": "workspace:*",
|
"@gitbook/openapi-parser": "workspace:*",
|
||||||
"@scalar/api-client-react": "1.0.87",
|
"@scalar/api-client-react": "1.0.87",
|
||||||
@@ -4651,6 +4651,8 @@
|
|||||||
|
|
||||||
"gaxios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
"gaxios/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||||
|
|
||||||
|
"gitbook/@gitbook/api": ["@gitbook/api@0.95.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-9KAbt27Ile6cqAch7QEbiJHALQHojYlhsPzilgdQ5wpHgLwsrd7Smd58A3/8bWBKq4KV0vP4rh3oYhIw+LlWFw=="],
|
||||||
|
|
||||||
"gitbook-v2/next": ["next@15.2.0-canary.45", "", { "dependencies": { "@next/env": "15.2.0-canary.45", "@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.0-canary.45", "@next/swc-darwin-x64": "15.2.0-canary.45", "@next/swc-linux-arm64-gnu": "15.2.0-canary.45", "@next/swc-linux-arm64-musl": "15.2.0-canary.45", "@next/swc-linux-x64-gnu": "15.2.0-canary.45", "@next/swc-linux-x64-musl": "15.2.0-canary.45", "@next/swc-win32-arm64-msvc": "15.2.0-canary.45", "@next/swc-win32-x64-msvc": "15.2.0-canary.45", "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-UsneTQn9tntbiAaXpvoXhhsTBb58Q2XIs2Dfka+qWA8motBz0ZvW297YHLxhdur4xN0IJvknnZKl5Bs7wAGlOg=="],
|
"gitbook-v2/next": ["next@15.2.0-canary.45", "", { "dependencies": { "@next/env": "15.2.0-canary.45", "@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.0-canary.45", "@next/swc-darwin-x64": "15.2.0-canary.45", "@next/swc-linux-arm64-gnu": "15.2.0-canary.45", "@next/swc-linux-arm64-musl": "15.2.0-canary.45", "@next/swc-linux-x64-gnu": "15.2.0-canary.45", "@next/swc-linux-x64-musl": "15.2.0-canary.45", "@next/swc-win32-arm64-msvc": "15.2.0-canary.45", "@next/swc-win32-x64-msvc": "15.2.0-canary.45", "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-UsneTQn9tntbiAaXpvoXhhsTBb58Q2XIs2Dfka+qWA8motBz0ZvW297YHLxhdur4xN0IJvknnZKl5Bs7wAGlOg=="],
|
||||||
|
|
||||||
"glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="],
|
"glob/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="],
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static/icons && rm -rf ./public/~gitbook/static/math"
|
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static/icons && rm -rf ./public/~gitbook/static/math"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gitbook/api": "^0.93.0",
|
"@gitbook/api": "^0.95.0",
|
||||||
"@gitbook/cache-do": "workspace:*",
|
"@gitbook/cache-do": "workspace:*",
|
||||||
"@gitbook/colors": "workspace:*",
|
"@gitbook/colors": "workspace:*",
|
||||||
"@gitbook/emoji-codepoints": "workspace:*",
|
"@gitbook/emoji-codepoints": "workspace:*",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Icon } from '@gitbook/icons';
|
|||||||
import { OpenAPIOperation } from '@gitbook/react-openapi';
|
import { OpenAPIOperation } from '@gitbook/react-openapi';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { fetchOpenAPIBlock } from '@/lib/openapi/fetch';
|
import { resolveOpenAPIBlock } from '@/lib/openapi/fetch';
|
||||||
import { tcls } from '@/lib/tailwind';
|
import { tcls } from '@/lib/tailwind';
|
||||||
|
|
||||||
import { BlockProps } from '../Block';
|
import { BlockProps } from '../Block';
|
||||||
@@ -27,13 +27,17 @@ export async function OpenAPI(props: BlockProps<DocumentBlockOpenAPI>) {
|
|||||||
|
|
||||||
async function OpenAPIBody(props: BlockProps<DocumentBlockOpenAPI>) {
|
async function OpenAPIBody(props: BlockProps<DocumentBlockOpenAPI>) {
|
||||||
const { block, context } = props;
|
const { block, context } = props;
|
||||||
const { data, specUrl, error } = await fetchOpenAPIBlock(block, context.resolveContentRef);
|
|
||||||
|
const { data, specUrl, error } = await resolveOpenAPIBlock({
|
||||||
|
block,
|
||||||
|
context: { resolveContentRef: context.resolveContentRef },
|
||||||
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
<div className={tcls('hidden')}>
|
<div className="hidden">
|
||||||
<p>
|
<p>
|
||||||
Error with {error.rootURL}: {error.message}
|
Error with {specUrl}: {error.message}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -208,6 +208,42 @@ export const getUserById = cache({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest version of an OpenAPI spec by its slug.
|
||||||
|
*/
|
||||||
|
export const getLatestOpenAPISpecVersionContent = cache({
|
||||||
|
name: 'api.getLatestOpenApiSpecVersionContent',
|
||||||
|
tag: (organization, openAPISpec) =>
|
||||||
|
getAPICacheTag({
|
||||||
|
tag: 'openapi',
|
||||||
|
organization,
|
||||||
|
openAPISpec,
|
||||||
|
}),
|
||||||
|
get: async (organizationId: string, slug: string, options: CacheFunctionOptions) => {
|
||||||
|
try {
|
||||||
|
const apiCtx = await api();
|
||||||
|
const response = await apiCtx.client.orgs.getLatestOpenApiSpecVersionContent(
|
||||||
|
organizationId,
|
||||||
|
slug,
|
||||||
|
{
|
||||||
|
...noCacheFetchOptions,
|
||||||
|
signal: options.signal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return cacheResponse(response, { revalidateBefore: 60 * 60 });
|
||||||
|
} catch (error) {
|
||||||
|
if (checkHasErrorCode(error, 404)) {
|
||||||
|
return {
|
||||||
|
revalidateBefore: 5,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a URL to the content to render.
|
* Resolve a URL to the content to render.
|
||||||
*/
|
*/
|
||||||
@@ -1066,55 +1102,6 @@ export async function getSpaceContentData(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Search content in a space.
|
|
||||||
*/
|
|
||||||
export const searchSpaceContent = cache({
|
|
||||||
name: 'api.searchSpaceContent',
|
|
||||||
tag: (spaceId) => getAPICacheTag({ tag: 'space', space: spaceId }),
|
|
||||||
getKeySuffix: getAPIContextId,
|
|
||||||
get: async (
|
|
||||||
spaceId: string,
|
|
||||||
/** The revision ID is used as a cache bust key, to avoid revalidating lot of cache entries by tags */
|
|
||||||
revisionId: string,
|
|
||||||
query: string,
|
|
||||||
options: CacheFunctionOptions,
|
|
||||||
) => {
|
|
||||||
const apiCtx = await api();
|
|
||||||
const response = await apiCtx.client.spaces.searchSpaceContent(
|
|
||||||
spaceId,
|
|
||||||
{ query },
|
|
||||||
{
|
|
||||||
...noCacheFetchOptions,
|
|
||||||
signal: options.signal,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return cacheResponse(response);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search content accross all spaces in a parent (site or collection).
|
|
||||||
*/
|
|
||||||
export const searchParentContent = cache({
|
|
||||||
name: 'api.searchParentContent',
|
|
||||||
tag: (spaceId) => getAPICacheTag({ tag: 'space', space: spaceId }),
|
|
||||||
getKeySuffix: getAPIContextId,
|
|
||||||
get: async (parentId: string, query: string, options: CacheFunctionOptions) => {
|
|
||||||
const apiCtx = await api();
|
|
||||||
const response = await apiCtx.client.search.searchContent(
|
|
||||||
{ query },
|
|
||||||
{
|
|
||||||
...noCacheFetchOptions,
|
|
||||||
signal: options.signal,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return cacheResponse(response, {
|
|
||||||
ttl: 60 * 60,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search content in a Site or specific SiteSpaces.
|
* Search content in a Site or specific SiteSpaces.
|
||||||
*/
|
*/
|
||||||
@@ -1275,6 +1262,12 @@ export function getAPICacheTag(
|
|||||||
| {
|
| {
|
||||||
tag: 'site';
|
tag: 'site';
|
||||||
site: string;
|
site: string;
|
||||||
|
}
|
||||||
|
// All data related to an OpenAPI spec
|
||||||
|
| {
|
||||||
|
tag: 'openapi';
|
||||||
|
organization: string;
|
||||||
|
openAPISpec: string;
|
||||||
},
|
},
|
||||||
): string {
|
): string {
|
||||||
switch (spec.tag) {
|
switch (spec.tag) {
|
||||||
@@ -1298,6 +1291,8 @@ export function getAPICacheTag(
|
|||||||
return `site:${spec.site}`;
|
return `site:${spec.site}`;
|
||||||
case 'integration':
|
case 'integration':
|
||||||
return `integration:${spec.integration}`;
|
return `integration:${spec.integration}`;
|
||||||
|
case 'openapi':
|
||||||
|
return `organization:${spec.organization}:openapi:${spec.openAPISpec}`;
|
||||||
default:
|
default:
|
||||||
assertNever(spec);
|
assertNever(spec);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { JSONDocument, ContentRef } from '@gitbook/api';
|
import { JSONDocument, ContentRef } from '@gitbook/api';
|
||||||
|
|
||||||
import { getNodeText } from './document';
|
import { getNodeText } from './document';
|
||||||
import { fetchOpenAPIBlock } from './openapi/fetch';
|
import { resolveOpenAPIBlock } from './openapi/fetch';
|
||||||
import { ResolvedContentRef } from './references';
|
import { ResolvedContentRef } from './references';
|
||||||
|
|
||||||
export interface DocumentSection {
|
export interface DocumentSection {
|
||||||
@@ -38,7 +38,10 @@ export async function getDocumentSections(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (block.type === 'swagger' && block.meta?.id) {
|
if (block.type === 'swagger' && block.meta?.id) {
|
||||||
const { data: operation } = await fetchOpenAPIBlock(block, resolveContentRef);
|
const { data: operation } = await resolveOpenAPIBlock({
|
||||||
|
block,
|
||||||
|
context: { resolveContentRef },
|
||||||
|
});
|
||||||
if (operation) {
|
if (operation) {
|
||||||
sections.push({
|
sections.push({
|
||||||
id: block.meta.id,
|
id: block.meta.id,
|
||||||
|
|||||||
@@ -7,23 +7,48 @@ import { cache, noCacheFetchOptions, CacheFunctionOptions } from '@/lib/cache';
|
|||||||
import { enrichFilesystem } from './enrich';
|
import { enrichFilesystem } from './enrich';
|
||||||
import { ResolvedContentRef } from '../references';
|
import { ResolvedContentRef } from '../references';
|
||||||
|
|
||||||
|
const weakmap = new WeakMap<DocumentBlockOpenAPI, ResolveOpenAPIBlockResult>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch an OpenAPI specification for an operation.
|
* Cache the result of resolving an OpenAPI block.
|
||||||
|
* It is important because the resolve is called in sections and in the block itself.
|
||||||
*/
|
*/
|
||||||
export async function fetchOpenAPIBlock(
|
export function resolveOpenAPIBlock(args: ResolveOpenAPIBlockArgs): ResolveOpenAPIBlockResult {
|
||||||
block: DocumentBlockOpenAPI,
|
if (weakmap.has(args.block)) {
|
||||||
resolveContentRef: (ref: ContentRef) => Promise<ResolvedContentRef | null>,
|
return weakmap.get(args.block)!;
|
||||||
): Promise<
|
}
|
||||||
| { data: OpenAPIOperationData | null; specUrl: string | null; error?: undefined }
|
|
||||||
|
const result = baseResolveOpenAPIBlock(args);
|
||||||
|
weakmap.set(args.block, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResolveOpenAPIBlockArgs = {
|
||||||
|
block: DocumentBlockOpenAPI;
|
||||||
|
context: { resolveContentRef: (ref: ContentRef) => Promise<ResolvedContentRef | null> };
|
||||||
|
};
|
||||||
|
type ResolveOpenAPIBlockResult = Promise<
|
||||||
|
| { error?: undefined; data: OpenAPIOperationData | null; specUrl: string | null }
|
||||||
| { error: OpenAPIParseError; data?: undefined; specUrl?: undefined }
|
| { error: OpenAPIParseError; data?: undefined; specUrl?: undefined }
|
||||||
> {
|
>;
|
||||||
const resolved = block.data.ref ? await resolveContentRef(block.data.ref) : null;
|
/**
|
||||||
if (!resolved || !block.data.path || !block.data.method) {
|
* Resolve OpenAPI block.
|
||||||
|
*/
|
||||||
|
async function baseResolveOpenAPIBlock(args: ResolveOpenAPIBlockArgs): ResolveOpenAPIBlockResult {
|
||||||
|
const { context, block } = args;
|
||||||
|
if (!block.data.path || !block.data.method) {
|
||||||
|
return { data: null, specUrl: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolved = block.data.ref ? await context.resolveContentRef(block.data.ref) : null;
|
||||||
|
|
||||||
|
if (!resolved) {
|
||||||
return { data: null, specUrl: null };
|
return { data: null, specUrl: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const filesystem = await fetchFilesystem(resolved.href);
|
const filesystem = resolved.openAPIFilesystem ?? (await fetchFilesystem(resolved.href));
|
||||||
|
|
||||||
const data = await resolveOpenAPIOperation(filesystem, {
|
const data = await resolveOpenAPIOperation(filesystem, {
|
||||||
path: block.data.path,
|
path: block.data.path,
|
||||||
method: block.data.method,
|
method: block.data.method,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
SiteSpace,
|
SiteSpace,
|
||||||
Space,
|
Space,
|
||||||
} from '@gitbook/api';
|
} from '@gitbook/api';
|
||||||
|
import type { Filesystem } from '@gitbook/openapi-parser';
|
||||||
import assertNever from 'assert-never';
|
import assertNever from 'assert-never';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
@@ -17,6 +18,8 @@ import {
|
|||||||
SpaceContentPointer,
|
SpaceContentPointer,
|
||||||
getCollection,
|
getCollection,
|
||||||
getDocument,
|
getDocument,
|
||||||
|
getLatestOpenAPISpecVersion,
|
||||||
|
getLatestOpenAPISpecVersionContent,
|
||||||
getPageDocument,
|
getPageDocument,
|
||||||
getPublishedContentSite,
|
getPublishedContentSite,
|
||||||
getReusableContent,
|
getReusableContent,
|
||||||
@@ -50,6 +53,8 @@ export interface ResolvedContentRef {
|
|||||||
file?: RevisionFile;
|
file?: RevisionFile;
|
||||||
/** Resolved reusable content, if the ref points to reusable content on a revision. */
|
/** Resolved reusable content, if the ref points to reusable content on a revision. */
|
||||||
reusableContent?: RevisionReusableContent;
|
reusableContent?: RevisionReusableContent;
|
||||||
|
/** Resolve OpenAPI spec filesystem. */
|
||||||
|
openAPIFilesystem?: Filesystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ContentRefContext extends PageHrefContext {
|
export interface ContentRefContext extends PageHrefContext {
|
||||||
@@ -272,6 +277,27 @@ export async function resolveContentRef(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'openapi': {
|
||||||
|
if (!siteContext) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { organizationId } = siteContext;
|
||||||
|
const openAPISpecVersionContent = await getLatestOpenAPISpecVersionContent(
|
||||||
|
organizationId,
|
||||||
|
contentRef.spec,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!openAPISpecVersionContent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
href: openAPISpecVersionContent.url,
|
||||||
|
text: contentRef.spec,
|
||||||
|
active: false,
|
||||||
|
openAPIFilesystem: openAPISpecVersionContent.filesystem as Filesystem,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assertNever(contentRef);
|
assertNever(contentRef);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function OpenAPIOperation(props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx('openapi-operation', className)}>
|
<div className={clsx('openapi-operation', className)}>
|
||||||
<div className="openapi-summary">
|
<div className="openapi-summary" id={operation.summary ? undefined : context.id}>
|
||||||
{operation.summary
|
{operation.summary
|
||||||
? context.renderHeading({
|
? context.renderHeading({
|
||||||
deprecated: operation.deprecated ?? false,
|
deprecated: operation.deprecated ?? false,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { checkIsReference, createStateKey, resolveDescription } from './utils';
|
|||||||
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
||||||
import { InteractiveSection } from './InteractiveSection';
|
import { InteractiveSection } from './InteractiveSection';
|
||||||
import { json2xml } from './json2xml';
|
import { json2xml } from './json2xml';
|
||||||
|
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display an example of the response content.
|
* Display an example of the response content.
|
||||||
@@ -226,7 +227,7 @@ function stringifyExample(args: { example: OpenAPIV3.ExampleObject; xml: boolean
|
|||||||
return json2xml(example.value);
|
return json2xml(example.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(example.value, null, 2);
|
return stringifyOpenAPI(example.value, null, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
* Stringify an OpenAPI object. Same API as JSON.stringify.
|
* Stringify an OpenAPI object. Same API as JSON.stringify.
|
||||||
*/
|
*/
|
||||||
export function stringifyOpenAPI(body: unknown, transformer?: null, indent?: number): string {
|
export function stringifyOpenAPI(body: unknown, _?: null, indent?: number): string {
|
||||||
return JSON.stringify(body, transformer, indent);
|
return JSON.stringify(
|
||||||
|
body,
|
||||||
|
(key, value) => {
|
||||||
|
// Ignore internal keys
|
||||||
|
if (key.startsWith('x-gitbook-')) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
indent,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user