diff --git a/.changeset/green-moles-camp.md b/.changeset/green-moles-camp.md new file mode 100644 index 000000000..b0596261a --- /dev/null +++ b/.changeset/green-moles-camp.md @@ -0,0 +1,5 @@ +--- +'@gitbook/react-openapi': patch +--- + +Fix display of OpenAPI header description diff --git a/packages/react-openapi/src/OpenAPIResponse.tsx b/packages/react-openapi/src/OpenAPIResponse.tsx index f72b9ed75..0d3e36c39 100644 --- a/packages/react-openapi/src/OpenAPIResponse.tsx +++ b/packages/react-openapi/src/OpenAPIResponse.tsx @@ -1,6 +1,6 @@ import type { OpenAPIV3 } from '@gitbook/openapi-parser'; import { OpenAPISchemaProperties } from './OpenAPISchema'; -import { resolveDescription } from './utils'; +import { parameterToProperty, resolveDescription } from './utils'; import type { OpenAPIClientContext } from './types'; import { OpenAPIDisclosure } from './OpenAPIDisclosure'; @@ -27,13 +27,11 @@ export function OpenAPIResponse(props: { return (
{headers.length > 0 ? ( - + ({ - propertyName: name, - schema: header.schema ?? {}, - required: header.required, - }))} + properties={headers.map(([name, header]) => { + return parameterToProperty({ name, ...header }); + })} context={context} /> @@ -41,11 +39,7 @@ export function OpenAPIResponse(props: {
diff --git a/packages/react-openapi/src/OpenAPISchema.tsx b/packages/react-openapi/src/OpenAPISchema.tsx index bc2693661..d364a96af 100644 --- a/packages/react-openapi/src/OpenAPISchema.tsx +++ b/packages/react-openapi/src/OpenAPISchema.tsx @@ -13,8 +13,8 @@ import { OpenAPIDisclosure } from './OpenAPIDisclosure'; type CircularRefsIds = Map; export interface OpenAPISchemaPropertyEntry { - propertyName?: string; - required?: boolean; + propertyName?: string | undefined; + required?: boolean | undefined; schema: OpenAPIV3.SchemaObject; } @@ -47,7 +47,7 @@ export function OpenAPISchemaProperty( ? null : getSchemaAlternatives(schema, new Set(circularRefs.keys())); - if ((properties && !!properties.length) || schema.type === 'object') { + if ((properties && properties.length > 0) || schema.type === 'object') { return ( diff --git a/packages/react-openapi/src/OpenAPISpec.tsx b/packages/react-openapi/src/OpenAPISpec.tsx index c4a2571ed..29b43846b 100644 --- a/packages/react-openapi/src/OpenAPISpec.tsx +++ b/packages/react-openapi/src/OpenAPISpec.tsx @@ -8,7 +8,7 @@ import { OpenAPIResponses } from './OpenAPIResponses'; import { OpenAPISchemaProperties } from './OpenAPISchema'; import { OpenAPISecurities } from './OpenAPISecurities'; import type { OpenAPIClientContext, OpenAPIOperationData } from './types'; -import { resolveDescription } from './utils'; +import { parameterToProperty } from './utils'; /** * Client component to render the spec for the request and response. @@ -38,22 +38,7 @@ export function OpenAPISpec(props: { data: OpenAPIOperationData; context: OpenAP header={group.label} > { - const description = resolveDescription(parameter); - return { - propertyName: parameter.name, - schema: { - // Description of the parameter is defined at the parameter level - // we use display it if the schema doesn't override it - description: description, - example: parameter.example, - // Deprecated can be defined at the parameter level - deprecated: parameter.deprecated, - ...(parameter.schema ?? {}), - }, - required: parameter.required, - }; - })} + properties={group.parameters.map(parameterToProperty)} context={context} /> diff --git a/packages/react-openapi/src/utils.ts b/packages/react-openapi/src/utils.ts index c3a45a578..6bebf2f58 100644 --- a/packages/react-openapi/src/utils.ts +++ b/packages/react-openapi/src/utils.ts @@ -1,6 +1,8 @@ -import type { AnyObject, OpenAPIV3 } from '@gitbook/openapi-parser'; +import type { AnyObject, OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser'; -export function checkIsReference(input: unknown): input is OpenAPIV3.ReferenceObject { +export function checkIsReference( + input: unknown, +): input is OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject { return typeof input === 'object' && !!input && '$ref' in input; } @@ -19,3 +21,76 @@ export function resolveDescription(object: AnyObject) { ? object.description : undefined; } + +/** + * Extract descriptions from an object. + */ +export function extractDescriptions(object: AnyObject) { + return { + description: object.description, + ['x-gitbook-description-html']: + 'x-gitbook-description-html' in object + ? object['x-gitbook-description-html'] + : undefined, + }; +} + +/** + * Resolve the first example from an object. + */ +export function resolveFirstExample(object: AnyObject) { + if ('examples' in object && typeof object.examples === 'object' && object.examples) { + const keys = Object.keys(object.examples); + const firstKey = keys[0]; + if (firstKey && object.examples[firstKey]) { + return object.examples[firstKey]; + } + } + if ('example' in object && object.example !== undefined) { + return object.example; + } + return undefined; +} + +/** + * Resolve the schema of a parameter. + * Extract the description, example and deprecated from parameter. + */ +export function resolveParameterSchema( + parameter: OpenAPIV3.ParameterBaseObject, +): OpenAPIV3.SchemaObject { + const schema = checkIsReference(parameter.schema) ? undefined : parameter.schema; + return { + // Description of the parameter is defined at the parameter level + // we use display it if the schema doesn't override it + ...extractDescriptions(parameter), + example: resolveFirstExample(parameter), + // Deprecated can be defined at the parameter level + deprecated: parameter.deprecated, + ...schema, + }; +} + +/** + * Transform a parameter object to a property object. + */ +export function parameterToProperty( + parameter: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject, +): { + propertyName: string | undefined; + schema: OpenAPIV3.SchemaObject; + required: boolean | undefined; +} { + if (checkIsReference(parameter)) { + return { + propertyName: parameter.$ref ?? 'Unknown ref', + schema: {}, + required: undefined, + }; + } + return { + propertyName: parameter.name, + schema: resolveParameterSchema(parameter), + required: parameter.required, + }; +}