mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-20 17:43:24 +00:00
Support for x-enumDescriptions and x-gitbook-enum (#3066)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
'@gitbook/openapi-parser': patch
|
||||||
|
'@gitbook/react-openapi': patch
|
||||||
|
'gitbook': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Support for x-enumDescriptions and x-gitbook-enum
|
||||||
@@ -244,7 +244,11 @@
|
|||||||
|
|
||||||
/* Schema Enum */
|
/* Schema Enum */
|
||||||
.openapi-schema-enum {
|
.openapi-schema-enum {
|
||||||
@apply flex flex-row text-sm leading-relaxed flex-wrap text-tint;
|
@apply flex flex-row text-sm leading-relaxed gap-2 flex-wrap text-tint;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openapi-schema-enum-list {
|
||||||
|
@apply flex flex-row gap-1.5 items-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.openapi-schema-enum-value {
|
.openapi-schema-enum-value {
|
||||||
@@ -693,3 +697,7 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.openapi-copy-button {
|
||||||
|
@apply hover:brightness-95;
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,6 +47,21 @@ export interface OpenAPICustomOperationProperties {
|
|||||||
* Description in Document format.
|
* Description in Document format.
|
||||||
*/
|
*/
|
||||||
'x-gitbook-description-document'?: object;
|
'x-gitbook-description-document'?: object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enums with name and description
|
||||||
|
*/
|
||||||
|
'x-enumDescriptions'?: object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enums with name and description
|
||||||
|
*/
|
||||||
|
'x-gitbook-enum'?: {
|
||||||
|
[key: string]: {
|
||||||
|
description?: string;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,10 +6,16 @@ import { Button, type ButtonProps, Tooltip, TooltipTrigger } from 'react-aria-co
|
|||||||
export function OpenAPICopyButton(
|
export function OpenAPICopyButton(
|
||||||
props: ButtonProps & {
|
props: ButtonProps & {
|
||||||
value: string;
|
value: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
label?: string;
|
||||||
|
/**
|
||||||
|
* Whether to show a tooltip.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
withTooltip?: boolean;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const { value } = props;
|
const { value, label, children, onPress, className, withTooltip = true } = props;
|
||||||
const { children, onPress, className } = props;
|
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
@@ -21,12 +27,19 @@ export function OpenAPICopyButton(
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setCopied(false);
|
setCopied(false);
|
||||||
|
setIsOpen(false);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} closeDelay={200} delay={200}>
|
<TooltipTrigger
|
||||||
|
isOpen={isOpen}
|
||||||
|
onOpenChange={setIsOpen}
|
||||||
|
isDisabled={!withTooltip}
|
||||||
|
closeDelay={200}
|
||||||
|
delay={200}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
preventFocusOnPress
|
preventFocusOnPress
|
||||||
@@ -47,7 +60,7 @@ export function OpenAPICopyButton(
|
|||||||
offset={4}
|
offset={4}
|
||||||
className="openapi-tooltip"
|
className="openapi-tooltip"
|
||||||
>
|
>
|
||||||
{copied ? 'Copied' : 'Copy to clipboard'}{' '}
|
{copied ? 'Copied' : label || 'Copy to clipboard'}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
// This component does not use any client feature but we don't want to
|
// This component does not use any client feature but we don't want to
|
||||||
// render it server-side because it has recursion.
|
// render it server-side because it has recursion.
|
||||||
|
|
||||||
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
import type { OpenAPICustomOperationProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
|
||||||
import { useId } from 'react';
|
import { useId } from 'react';
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { Markdown } from './Markdown';
|
import { Markdown } from './Markdown';
|
||||||
|
import { OpenAPICopyButton } from './OpenAPICopyButton';
|
||||||
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
|
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
|
||||||
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
||||||
import { retrocycle } from './decycle';
|
import { retrocycle } from './decycle';
|
||||||
@@ -236,20 +237,59 @@ function OpenAPISchemaCircularRef(props: { id: string; schema: OpenAPIV3.SchemaO
|
|||||||
/**
|
/**
|
||||||
* Render the enum value for a schema.
|
* Render the enum value for a schema.
|
||||||
*/
|
*/
|
||||||
function OpenAPISchemaEnum(props: { enumValues: any[] }) {
|
function OpenAPISchemaEnum(props: {
|
||||||
const { enumValues } = props;
|
schema: OpenAPIV3.SchemaObject & OpenAPICustomOperationProperties;
|
||||||
|
}) {
|
||||||
|
const { schema } = props;
|
||||||
|
|
||||||
|
const enumValues = (() => {
|
||||||
|
// Render x-gitbook-enum first, as it has a different format
|
||||||
|
if (schema['x-gitbook-enum']) {
|
||||||
|
return Object.entries(schema['x-gitbook-enum']).map(([name, { description }]) => {
|
||||||
|
return {
|
||||||
|
value: name,
|
||||||
|
description,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema['x-enumDescriptions']) {
|
||||||
|
return Object.entries(schema['x-enumDescriptions']).map(([value, description]) => {
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
description,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema.enum?.map((value) => {
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
description: undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
if (!enumValues?.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="openapi-schema-enum">
|
<div className="openapi-schema-enum">
|
||||||
<span>
|
<span>Available options:</span>
|
||||||
Options:{' '}
|
<div className="openapi-schema-enum-list">
|
||||||
{enumValues.map((value, index) => (
|
{enumValues.map((item, index) => (
|
||||||
<span key={index} className="openapi-schema-enum-value">
|
<span key={index} className="openapi-schema-enum-value">
|
||||||
<code>{`${value}`}</code>
|
<OpenAPICopyButton
|
||||||
{index < enumValues.length - 1 ? ', ' : ''}
|
value={item.value}
|
||||||
|
label={item.description}
|
||||||
|
withTooltip={!!item.description}
|
||||||
|
>
|
||||||
|
<code>{`${item.value}`}</code>
|
||||||
|
</OpenAPICopyButton>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -294,9 +334,7 @@ function OpenAPISchemaPresentation(props: { property: OpenAPISchemaPropertyEntry
|
|||||||
Pattern: <code>{schema.pattern}</code>
|
Pattern: <code>{schema.pattern}</code>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{schema.enum && schema.enum.length > 0 ? (
|
<OpenAPISchemaEnum schema={schema} />
|
||||||
<OpenAPISchemaEnum enumValues={schema.enum} />
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -421,7 +459,7 @@ function getSchemaTitle(schema: OpenAPIV3.SchemaObject): string {
|
|||||||
// Otherwise try to infer a nice title
|
// Otherwise try to infer a nice title
|
||||||
let type = 'any';
|
let type = 'any';
|
||||||
|
|
||||||
if (schema.enum) {
|
if (schema.enum || schema['x-enumDescriptions'] || schema['x-gitbook-enum']) {
|
||||||
type = `${schema.type} · enum`;
|
type = `${schema.type} · enum`;
|
||||||
// check array AND schema.items as this is sometimes null despite what the type indicates
|
// check array AND schema.items as this is sometimes null despite what the type indicates
|
||||||
} else if (schema.type === 'array' && !!schema.items) {
|
} else if (schema.type === 'array' && !!schema.items) {
|
||||||
|
|||||||
Reference in New Issue
Block a user