Skip to content

Commit 5c082df

Browse files
committed
Fix example and description missing
1 parent 1eca1f7 commit 5c082df

File tree

2 files changed

+67
-36
lines changed

2 files changed

+67
-36
lines changed

packages/react-openapi/src/OpenAPISchema.tsx

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import { InteractiveSection } from './InteractiveSection';
66
import { Markdown } from './Markdown';
77
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
88
import { OpenAPISchemaName } from './OpenAPISchemaName';
9-
import { stringifyOpenAPI } from './stringifyOpenAPI';
109
import type { OpenAPIClientContext } from './types';
11-
import { checkIsReference, resolveDescription } from './utils';
10+
import { checkIsReference, resolveDescription, resolveFirstExample } from './utils';
1211

1312
type CircularRefsIds = Map<OpenAPIV3.SchemaObject, string>;
1413

@@ -269,28 +268,19 @@ export function OpenAPISchemaEnum(props: { enumValues: any[] }) {
269268
);
270269
}
271270

272-
export function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry) {
273-
const { schema, propertyName, required } = props;
274-
275-
const shouldDisplayExample = (schema: OpenAPIV3.SchemaObject): boolean => {
276-
return (
277-
(typeof schema.example === 'string' && !!schema.example) ||
278-
typeof schema.example === 'number' ||
279-
typeof schema.example === 'boolean' ||
280-
(Array.isArray(schema.example) && schema.example.length > 0) ||
281-
(typeof schema.example === 'object' &&
282-
schema.example !== null &&
283-
Object.keys(schema.example).length > 0)
284-
);
285-
};
271+
export function OpenAPISchemaPresentation(
272+
props: OpenAPISchemaPropertyEntry & { showType?: boolean }
273+
) {
274+
const { schema, propertyName, required, showType = true } = props;
286275

287276
const description = resolveDescription(schema);
277+
const example = resolveFirstExample(schema);
288278

289279
return (
290280
<div className="openapi-schema-presentation">
291281
<OpenAPISchemaName
292282
schema={schema}
293-
type={getSchemaTitle(schema)}
283+
type={showType ? getSchemaTitle(schema) : undefined}
294284
propertyName={propertyName}
295285
required={required}
296286
/>
@@ -305,9 +295,9 @@ export function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry) {
305295
{description ? (
306296
<Markdown source={description} className="openapi-schema-description" />
307297
) : null}
308-
{shouldDisplayExample(schema) ? (
298+
{example ? (
309299
<div className="openapi-schema-example">
310-
Example: <code>{formatExample(schema.example)}</code>
300+
Example: <code>{example}</code>
311301
</div>
312302
) : null}
313303
{schema.pattern ? (
@@ -325,7 +315,9 @@ export function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry) {
325315
/**
326316
* Get the sub-properties of a schema.
327317
*/
328-
function getSchemaProperties(schema: OpenAPIV3.SchemaObject): null | OpenAPISchemaPropertyEntry[] {
318+
export function getSchemaProperties(
319+
schema: OpenAPIV3.SchemaObject
320+
): null | OpenAPISchemaPropertyEntry[] {
329321
// check array AND schema.items as this is sometimes null despite what the type indicates
330322
if (schema.type === 'array' && !!schema.items) {
331323
const items = schema.items;
@@ -485,16 +477,3 @@ function getDisclosureLabel(schema: OpenAPIV3.SchemaObject): string | undefined
485477

486478
return schema.title;
487479
}
488-
489-
function formatExample(example: any): string {
490-
if (typeof example === 'string') {
491-
return example
492-
.replace(/\n/g, ' ') // Replace newlines with spaces
493-
.replace(/\s+/g, ' ') // Collapse multiple spaces/newlines into a single space
494-
.replace(/([\{\}:,])\s+/g, '$1 ') // Ensure a space after {, }, :, and ,
495-
.replace(/\s+([\{\}:,])/g, ' $1') // Ensure a space before {, }, :, and ,
496-
.trim();
497-
}
498-
499-
return stringifyOpenAPI(example);
500-
}

packages/react-openapi/src/utils.ts

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AnyObject, OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2+
import { stringifyOpenAPI } from './stringifyOpenAPI';
23

34
export function checkIsReference(
45
input: unknown
@@ -10,11 +11,23 @@ export function createStateKey(key: string, scope?: string) {
1011
return scope ? `${scope}_${key}` : key;
1112
}
1213

14+
function hasDescription(object: AnyObject) {
15+
if (Array.isArray(object)) {
16+
return object.some(hasDescription);
17+
}
18+
19+
return 'description' in object || 'x-gitbook-description-html' in object;
20+
}
21+
1322
/**
1423
* Resolve the description of an object.
1524
*/
1625
export function resolveDescription(object: OpenAPIV3.SchemaObject | AnyObject) {
17-
if ('items' in object && object.items) {
26+
if ('items' in object && typeof object.items === 'object' && hasDescription(object.items)) {
27+
if (Array.isArray(object.items)) {
28+
return resolveDescription(object.items[0]);
29+
}
30+
1831
return resolveDescription(object.items);
1932
}
2033

@@ -50,9 +63,20 @@ export function resolveFirstExample(object: AnyObject) {
5063
return object.examples[firstKey];
5164
}
5265
}
53-
if ('example' in object && object.example !== undefined) {
54-
return object.example;
66+
67+
// Resolve top level example first
68+
if (shouldDisplayExample(object)) {
69+
return formatExample(object.example);
70+
}
71+
72+
// Resolve example from items if any
73+
if (object.items && typeof object.items === 'object') {
74+
if (Array.isArray(object.items)) {
75+
return formatExample(object.items[0].example);
76+
}
77+
return formatExample(object.items.example);
5578
}
79+
5680
return undefined;
5781
}
5882

@@ -98,3 +122,31 @@ export function parameterToProperty(
98122
required: parameter.required,
99123
};
100124
}
125+
126+
/**
127+
* Format the example of a schema.
128+
*/
129+
function formatExample(example: unknown): string {
130+
if (typeof example === 'string') {
131+
return example
132+
.replace(/\n/g, ' ') // Replace newlines with spaces
133+
.replace(/\s+/g, ' ') // Collapse multiple spaces/newlines into a single space
134+
.replace(/([\{\}:,])\s+/g, '$1 ') // Ensure a space after {, }, :, and ,
135+
.replace(/\s+([\{\}:,])/g, ' $1') // Ensure a space before {, }, :, and ,
136+
.trim();
137+
}
138+
139+
return stringifyOpenAPI(example);
140+
}
141+
142+
function shouldDisplayExample(schema: OpenAPIV3.SchemaObject): boolean {
143+
return (
144+
(typeof schema.example === 'string' && !!schema.example) ||
145+
typeof schema.example === 'number' ||
146+
typeof schema.example === 'boolean' ||
147+
(Array.isArray(schema.example) && schema.example.length > 0) ||
148+
(typeof schema.example === 'object' &&
149+
schema.example !== null &&
150+
Object.keys(schema.example).length > 0)
151+
);
152+
}

0 commit comments

Comments
 (0)