Skip to content

Commit 813b2af

Browse files
authored
Support for x-enumDescriptions and x-gitbook-enum (#3066)
1 parent 6f71da8 commit 813b2af

File tree

5 files changed

+99
-18
lines changed

5 files changed

+99
-18
lines changed

.changeset/tame-colts-know.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@gitbook/openapi-parser': patch
3+
'@gitbook/react-openapi': patch
4+
'gitbook': patch
5+
---
6+
7+
Support for x-enumDescriptions and x-gitbook-enum

packages/gitbook/src/components/DocumentView/OpenAPI/style.css

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,11 @@
244244

245245
/* Schema Enum */
246246
.openapi-schema-enum {
247-
@apply flex flex-row text-sm leading-relaxed flex-wrap text-tint;
247+
@apply flex flex-row text-sm leading-relaxed gap-2 flex-wrap text-tint;
248+
}
249+
250+
.openapi-schema-enum-list {
251+
@apply flex flex-row gap-1.5 items-center;
248252
}
249253

250254
.openapi-schema-enum-value {
@@ -693,3 +697,7 @@
693697
opacity: 0;
694698
}
695699
}
700+
701+
.openapi-copy-button {
702+
@apply hover:brightness-95;
703+
}

packages/openapi-parser/src/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,21 @@ export interface OpenAPICustomOperationProperties {
4747
* Description in Document format.
4848
*/
4949
'x-gitbook-description-document'?: object;
50+
51+
/**
52+
* Enums with name and description
53+
*/
54+
'x-enumDescriptions'?: object;
55+
56+
/**
57+
* Enums with name and description
58+
*/
59+
'x-gitbook-enum'?: {
60+
[key: string]: {
61+
description?: string;
62+
name?: string;
63+
};
64+
};
5065
}
5166

5267
/**

packages/react-openapi/src/OpenAPICopyButton.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ import { Button, type ButtonProps, Tooltip, TooltipTrigger } from 'react-aria-co
66
export function OpenAPICopyButton(
77
props: ButtonProps & {
88
value: string;
9+
children: React.ReactNode;
10+
label?: string;
11+
/**
12+
* Whether to show a tooltip.
13+
* @default true
14+
*/
15+
withTooltip?: boolean;
916
}
1017
) {
11-
const { value } = props;
12-
const { children, onPress, className } = props;
18+
const { value, label, children, onPress, className, withTooltip = true } = props;
1319
const [copied, setCopied] = useState(false);
1420
const [isOpen, setIsOpen] = useState(false);
1521

@@ -21,12 +27,19 @@ export function OpenAPICopyButton(
2127

2228
setTimeout(() => {
2329
setCopied(false);
30+
setIsOpen(false);
2431
}, 2000);
2532
});
2633
};
2734

2835
return (
29-
<TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} closeDelay={200} delay={200}>
36+
<TooltipTrigger
37+
isOpen={isOpen}
38+
onOpenChange={setIsOpen}
39+
isDisabled={!withTooltip}
40+
closeDelay={200}
41+
delay={200}
42+
>
3043
<Button
3144
type="button"
3245
preventFocusOnPress
@@ -47,7 +60,7 @@ export function OpenAPICopyButton(
4760
offset={4}
4861
className="openapi-tooltip"
4962
>
50-
{copied ? 'Copied' : 'Copy to clipboard'}{' '}
63+
{copied ? 'Copied' : label || 'Copy to clipboard'}
5164
</Tooltip>
5265
</TooltipTrigger>
5366
);

packages/react-openapi/src/OpenAPISchema.tsx

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// This component does not use any client feature but we don't want to
33
// render it server-side because it has recursion.
44

5-
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
5+
import type { OpenAPICustomOperationProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
66
import { useId } from 'react';
77

88
import clsx from 'clsx';
99
import { Markdown } from './Markdown';
10+
import { OpenAPICopyButton } from './OpenAPICopyButton';
1011
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
1112
import { OpenAPISchemaName } from './OpenAPISchemaName';
1213
import { retrocycle } from './decycle';
@@ -236,20 +237,59 @@ function OpenAPISchemaCircularRef(props: { id: string; schema: OpenAPIV3.SchemaO
236237
/**
237238
* Render the enum value for a schema.
238239
*/
239-
function OpenAPISchemaEnum(props: { enumValues: any[] }) {
240-
const { enumValues } = props;
240+
function OpenAPISchemaEnum(props: {
241+
schema: OpenAPIV3.SchemaObject & OpenAPICustomOperationProperties;
242+
}) {
243+
const { schema } = props;
244+
245+
const enumValues = (() => {
246+
// Render x-gitbook-enum first, as it has a different format
247+
if (schema['x-gitbook-enum']) {
248+
return Object.entries(schema['x-gitbook-enum']).map(([name, { description }]) => {
249+
return {
250+
value: name,
251+
description,
252+
};
253+
});
254+
}
255+
256+
if (schema['x-enumDescriptions']) {
257+
return Object.entries(schema['x-enumDescriptions']).map(([value, description]) => {
258+
return {
259+
value,
260+
description,
261+
};
262+
});
263+
}
264+
265+
return schema.enum?.map((value) => {
266+
return {
267+
value,
268+
description: undefined,
269+
};
270+
});
271+
})();
272+
273+
if (!enumValues?.length) {
274+
return null;
275+
}
241276

242277
return (
243278
<div className="openapi-schema-enum">
244-
<span>
245-
Options:{' '}
246-
{enumValues.map((value, index) => (
279+
<span>Available options:</span>
280+
<div className="openapi-schema-enum-list">
281+
{enumValues.map((item, index) => (
247282
<span key={index} className="openapi-schema-enum-value">
248-
<code>{`${value}`}</code>
249-
{index < enumValues.length - 1 ? ', ' : ''}
283+
<OpenAPICopyButton
284+
value={item.value}
285+
label={item.description}
286+
withTooltip={!!item.description}
287+
>
288+
<code>{`${item.value}`}</code>
289+
</OpenAPICopyButton>
250290
</span>
251291
))}
252-
</span>
292+
</div>
253293
</div>
254294
);
255295
}
@@ -294,9 +334,7 @@ function OpenAPISchemaPresentation(props: { property: OpenAPISchemaPropertyEntry
294334
Pattern: <code>{schema.pattern}</code>
295335
</div>
296336
) : null}
297-
{schema.enum && schema.enum.length > 0 ? (
298-
<OpenAPISchemaEnum enumValues={schema.enum} />
299-
) : null}
337+
<OpenAPISchemaEnum schema={schema} />
300338
</div>
301339
);
302340
}
@@ -421,7 +459,7 @@ function getSchemaTitle(schema: OpenAPIV3.SchemaObject): string {
421459
// Otherwise try to infer a nice title
422460
let type = 'any';
423461

424-
if (schema.enum) {
462+
if (schema.enum || schema['x-enumDescriptions'] || schema['x-gitbook-enum']) {
425463
type = `${schema.type} · enum`;
426464
// check array AND schema.items as this is sometimes null despite what the type indicates
427465
} else if (schema.type === 'array' && !!schema.items) {

0 commit comments

Comments
 (0)