Skip to content

Commit c1c58eb

Browse files
authored
Render OpenAPISchemas block (#2959)
1 parent eec3eed commit c1c58eb

File tree

11 files changed

+337
-39
lines changed

11 files changed

+337
-39
lines changed

packages/gitbook/src/components/DocumentView/Block.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { IntegrationBlock } from './Integration';
2525
import { List } from './List';
2626
import { ListItem } from './ListItem';
2727
import { BlockMath } from './Math';
28-
import { OpenAPI } from './OpenAPI';
28+
import { OpenAPIOperation, OpenAPISchemas } from './OpenAPI';
2929
import { Paragraph } from './Paragraph';
3030
import { Quote } from './Quote';
3131
import { ReusableContent } from './ReusableContent';
@@ -82,9 +82,9 @@ export function Block<T extends DocumentBlock>(props: BlockProps<T>) {
8282
return <Table {...props} block={block} />;
8383
case 'swagger':
8484
case 'openapi-operation':
85-
return <OpenAPI {...props} block={block} />;
85+
return <OpenAPIOperation {...props} block={block} />;
8686
case 'openapi-schemas':
87-
return <></>;
87+
return <OpenAPISchemas {...props} block={block} />;
8888
case 'embed':
8989
return <Embed {...props} block={block} />;
9090
case 'blockquote':

packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx renamed to packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { JSONDocument } from '@gitbook/api';
22
import { Icon } from '@gitbook/icons';
3-
import { OpenAPIOperation } from '@gitbook/react-openapi';
3+
import { OpenAPIOperation as BaseOpenAPIOperation } from '@gitbook/react-openapi';
44

55
import { resolveOpenAPIOperationBlock } from '@/lib/openapi/resolveOpenAPIOperationBlock';
66
import { tcls } from '@/lib/tailwind';
@@ -12,21 +12,21 @@ import { Heading } from '../Heading';
1212

1313
import './scalar.css';
1414
import './style.css';
15-
import type { AnyOpenAPIBlock } from '@/lib/openapi/types';
15+
import type { AnyOpenAPIOperationsBlock } from '@/lib/openapi/types';
1616

1717
/**
1818
* Render an openapi block or an openapi-operation block.
1919
*/
20-
export async function OpenAPI(props: BlockProps<AnyOpenAPIBlock>) {
20+
export async function OpenAPIOperation(props: BlockProps<AnyOpenAPIOperationsBlock>) {
2121
const { style } = props;
2222
return (
2323
<div className={tcls('flex w-full', style, 'max-w-full')}>
24-
<OpenAPIBody {...props} />
24+
<OpenAPIOperationBody {...props} />
2525
</div>
2626
);
2727
}
2828

29-
async function OpenAPIBody(props: BlockProps<AnyOpenAPIBlock>) {
29+
async function OpenAPIOperationBody(props: BlockProps<AnyOpenAPIOperationsBlock>) {
3030
const { block, context } = props;
3131

3232
if (!context.contentContext) {
@@ -53,7 +53,7 @@ async function OpenAPIBody(props: BlockProps<AnyOpenAPIBlock>) {
5353
}
5454

5555
return (
56-
<OpenAPIOperation
56+
<BaseOpenAPIOperation
5757
data={data}
5858
context={{
5959
specUrl,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { resolveOpenAPISchemasBlock } from '@/lib/openapi/resolveOpenAPISchemasBlock';
2+
import { tcls } from '@/lib/tailwind';
3+
import { Icon } from '@gitbook/icons';
4+
import { OpenAPISchemas as BaseOpenAPISchemas } from '@gitbook/react-openapi';
5+
6+
import type { BlockProps } from '../Block';
7+
8+
import './scalar.css';
9+
import './style.css';
10+
import type { OpenAPISchemasBlock } from '@/lib/openapi/types';
11+
12+
/**
13+
* Render an openapi-schemas block.
14+
*/
15+
export async function OpenAPISchemas(props: BlockProps<OpenAPISchemasBlock>) {
16+
const { style } = props;
17+
return (
18+
<div className={tcls('flex w-full', style, 'max-w-full')}>
19+
<OpenAPISchemasBody {...props} />
20+
</div>
21+
);
22+
}
23+
24+
async function OpenAPISchemasBody(props: BlockProps<OpenAPISchemasBlock>) {
25+
const { block, context } = props;
26+
27+
if (!context.contentContext) {
28+
return null;
29+
}
30+
31+
const { data, specUrl, error } = await resolveOpenAPISchemasBlock({
32+
block,
33+
context: context.contentContext,
34+
});
35+
36+
if (error) {
37+
return (
38+
<div className="hidden">
39+
<p>
40+
Error with {specUrl}: {error.message}
41+
</p>
42+
</div>
43+
);
44+
}
45+
46+
if (!data || !specUrl) {
47+
return null;
48+
}
49+
50+
return (
51+
<BaseOpenAPISchemas
52+
data={data}
53+
context={{
54+
specUrl,
55+
icons: {
56+
chevronDown: <Icon icon="chevron-down" />,
57+
chevronRight: <Icon icon="chevron-right" />,
58+
plus: <Icon icon="plus" />,
59+
},
60+
defaultInteractiveOpened: context.mode === 'print',
61+
id: block.meta?.id,
62+
blockKey: block.key,
63+
}}
64+
className="openapi-block"
65+
/>
66+
);
67+
}
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export * from './OpenAPI';
1+
export * from './OpenAPIOperation';
2+
export * from './OpenAPISchemas';

packages/gitbook/src/lib/openapi/fetch.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
import { parseOpenAPI } from '@gitbook/openapi-parser';
22

33
import { type CacheFunctionOptions, cache, noCacheFetchOptions } from '@/lib/cache';
4-
import type { ResolveOpenAPIBlockArgs } from '@/lib/openapi/types';
4+
import type {
5+
AnyOpenAPIOperationsBlock,
6+
OpenAPISchemasBlock,
7+
ResolveOpenAPIBlockArgs,
8+
} from '@/lib/openapi/types';
59
import { assert } from 'ts-essentials';
610
import { resolveContentRef } from '../references';
711
import { isV2 } from '../v2';
812
import { enrichFilesystem } from './enrich';
913
import type { FetchOpenAPIFilesystemResult } from './types';
1014

15+
type AnyOpenAPIBlock = AnyOpenAPIOperationsBlock | OpenAPISchemasBlock;
16+
1117
/**
1218
* Fetch OpenAPI block.
1319
*/
1420
export async function fetchOpenAPIFilesystem(
15-
args: ResolveOpenAPIBlockArgs
21+
args: ResolveOpenAPIBlockArgs<AnyOpenAPIBlock>
1622
): Promise<FetchOpenAPIFilesystemResult> {
1723
const { context, block } = args;
1824

packages/gitbook/src/lib/openapi/resolveOpenAPIOperationBlock.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
import { fetchOpenAPIFilesystem } from '@/lib/openapi/fetch';
22
import { OpenAPIParseError } from '@gitbook/openapi-parser';
33
import { type OpenAPIOperationData, resolveOpenAPIOperation } from '@gitbook/react-openapi';
4-
import type { AnyOpenAPIBlock, ResolveOpenAPIBlockArgs, ResolveOpenAPIBlockResult } from './types';
4+
import type {
5+
AnyOpenAPIOperationsBlock,
6+
ResolveOpenAPIBlockArgs,
7+
ResolveOpenAPIBlockResult,
8+
} from './types';
59

610
type ResolveOpenAPIOperationBlockResult = ResolveOpenAPIBlockResult<OpenAPIOperationData>;
711

8-
const weakmap = new WeakMap<AnyOpenAPIBlock, Promise<ResolveOpenAPIOperationBlockResult>>();
12+
const weakmap = new WeakMap<
13+
AnyOpenAPIOperationsBlock,
14+
Promise<ResolveOpenAPIOperationBlockResult>
15+
>();
916

1017
/**
1118
* Cache the result of resolving an OpenAPI block.
1219
* It is important because the resolve is called in sections and in the block itself.
1320
*/
1421
export function resolveOpenAPIOperationBlock(
15-
args: ResolveOpenAPIBlockArgs
22+
args: ResolveOpenAPIBlockArgs<AnyOpenAPIOperationsBlock>
1623
): Promise<ResolveOpenAPIOperationBlockResult> {
1724
if (weakmap.has(args.block)) {
1825
return weakmap.get(args.block)!;
@@ -27,7 +34,7 @@ export function resolveOpenAPIOperationBlock(
2734
* Resolve OpenAPI operation block.
2835
*/
2936
async function baseResolveOpenAPIOperationBlock(
30-
args: ResolveOpenAPIBlockArgs
37+
args: ResolveOpenAPIBlockArgs<AnyOpenAPIOperationsBlock>
3138
): Promise<ResolveOpenAPIOperationBlockResult> {
3239
const { context, block } = args;
3340
if (!block.data.path || !block.data.method) {

packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
1-
import { fetchOpenAPIFilesystem } from '@/lib/openapi/fetch';
2-
import type { ResolveOpenAPIBlockResult } from '@/lib/openapi/types';
31
import { OpenAPIParseError } from '@gitbook/openapi-parser';
42
import { type OpenAPISchemasData, resolveOpenAPISchemas } from '@gitbook/react-openapi';
5-
import type { AnyOpenAPIBlock, ResolveOpenAPIBlockArgs } from './types';
3+
import { fetchOpenAPIFilesystem } from './fetch';
4+
import type {
5+
OpenAPISchemasBlock,
6+
ResolveOpenAPIBlockArgs,
7+
ResolveOpenAPIBlockResult,
8+
} from './types';
69

710
type ResolveOpenAPISchemasBlockResult = ResolveOpenAPIBlockResult<OpenAPISchemasData>;
811

9-
const weakmap = new WeakMap<AnyOpenAPIBlock, Promise<ResolveOpenAPISchemasBlockResult>>();
12+
const weakmap = new WeakMap<OpenAPISchemasBlock, Promise<ResolveOpenAPISchemasBlockResult>>();
1013

1114
/**
1215
* Cache the result of resolving an OpenAPI block.
1316
* It is important because the resolve is called in sections and in the block itself.
1417
*/
1518
export function resolveOpenAPISchemasBlock(
16-
args: ResolveOpenAPIBlockArgs
19+
args: ResolveOpenAPIBlockArgs<OpenAPISchemasBlock>
1720
): Promise<ResolveOpenAPISchemasBlockResult> {
1821
if (weakmap.has(args.block)) {
1922
return weakmap.get(args.block)!;
@@ -28,10 +31,10 @@ export function resolveOpenAPISchemasBlock(
2831
* Resolve OpenAPI schemas block.
2932
*/
3033
async function baseResolveOpenAPISchemasBlock(
31-
args: ResolveOpenAPIBlockArgs
34+
args: ResolveOpenAPIBlockArgs<OpenAPISchemasBlock>
3235
): Promise<ResolveOpenAPISchemasBlockResult> {
3336
const { context, block } = args;
34-
if (!block.data.path || !block.data.method) {
37+
if (!block.data.schemas || !block.data.schemas.length) {
3538
return { data: null, specUrl: null };
3639
}
3740

@@ -42,7 +45,9 @@ async function baseResolveOpenAPISchemasBlock(
4245
return { data: null, specUrl: null };
4346
}
4447

45-
const data = await resolveOpenAPISchemas(filesystem);
48+
const data = await resolveOpenAPISchemas(filesystem, {
49+
schemas: block.data.schemas,
50+
});
4651

4752
return { data, specUrl };
4853
} catch (error) {

packages/gitbook/src/lib/openapi/types.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
import type { DocumentBlockOpenAPI, DocumentBlockOpenAPIOperation } from '@gitbook/api';
1+
import type {
2+
DocumentBlockOpenAPI,
3+
DocumentBlockOpenAPIOperation,
4+
DocumentBlockOpenAPISchemas,
5+
} from '@gitbook/api';
26
import type { Filesystem, OpenAPIParseError, OpenAPIV3xDocument } from '@gitbook/openapi-parser';
37
import type { GitBookAnyContext } from '@v2/lib/context';
48

5-
//!!TODO: Add DocumentBlockOpenAPISchemas when available in @gitbook/api
6-
export type AnyOpenAPIBlock = DocumentBlockOpenAPI | DocumentBlockOpenAPIOperation;
9+
/**
10+
* Type for both OpenAPI & OpenAPIOperation block
11+
*/
12+
export type AnyOpenAPIOperationsBlock = DocumentBlockOpenAPI | DocumentBlockOpenAPIOperation;
13+
14+
/**
15+
* Type for OpenAPI Schemas block
16+
*/
17+
export type OpenAPISchemasBlock = DocumentBlockOpenAPISchemas;
718

819
/**
920
* Arguments for resolving OpenAPI block.
1021
*/
11-
export type ResolveOpenAPIBlockArgs = {
12-
block: AnyOpenAPIBlock;
22+
export type ResolveOpenAPIBlockArgs<T> = {
23+
block: T;
1324
context: GitBookAnyContext;
1425
};
1526

packages/react-openapi/src/schemas/OpenAPISchemas.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ import { OpenAPIRootSchema } from '../OpenAPISchema';
44
import { Section, SectionBody } from '../StaticSection';
55
import type { OpenAPIClientContext, OpenAPIContextProps, OpenAPISchemasData } from '../types';
66

7+
type OpenAPISchemasContextProps = Omit<
8+
OpenAPIContextProps,
9+
'renderCodeBlock' | 'renderHeading' | 'renderDocument'
10+
>;
11+
712
/**
813
* Display OpenAPI Schemas.
914
*/
1015
export function OpenAPISchemas(props: {
1116
className?: string;
1217
data: OpenAPISchemasData;
13-
context: OpenAPIContextProps;
18+
context: OpenAPISchemasContextProps;
1419
}) {
1520
const { className, data, context } = props;
1621
const { schemas } = data;

0 commit comments

Comments
 (0)