Skip to content

Commit c4ea69d

Browse files
committed
add exmaples for schema property
1 parent bf1af5f commit c4ea69d

File tree

2 files changed

+121
-31
lines changed

2 files changed

+121
-31
lines changed

packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ interface Map<T> {
2121
}
2222

2323
export interface ExampleObject {
24-
summary?: string;
25-
description?: string;
24+
summary?: string | null;
25+
description?: string | null;
2626
value?: any;
27-
externalValue?: string;
27+
externalValue?: string | null;
2828
}
2929

3030
export interface Props {
3131
className: string;
3232
param: {
3333
description: string;
3434
example: any;
35-
examples: Map<ExampleObject>;
35+
examples: Map<ExampleObject> | any[];
3636
name: string;
3737
required: boolean;
3838
deprecated: boolean;
@@ -57,19 +57,14 @@ ${enumDescriptions
5757
};
5858

5959
function ParamsItem({ param, ...rest }: Props) {
60-
const {
61-
description,
62-
example,
63-
examples,
64-
name,
65-
required,
66-
deprecated,
67-
enumDescriptions,
68-
} = param;
60+
const { description, name, required, deprecated, enumDescriptions } = param;
6961

7062
let schema = param.schema;
7163
let defaultValue: string | undefined;
7264

65+
let examples = param.examples || schema?.examples;
66+
let example = param.example || schema?.example;
67+
7368
if (!schema) {
7469
schema = { type: "any" };
7570
}
@@ -144,32 +139,75 @@ function ParamsItem({ param, ...rest }: Props) {
144139
const renderExample = guard(toString(example), (example) => (
145140
<div>
146141
<strong>Example: </strong>
147-
{example}
142+
<code>{example}</code>
148143
</div>
149144
));
150145

146+
// Helper function to format example value
147+
const formatExample = (example: any) => {
148+
if (typeof example === "object" && example !== null) {
149+
return JSON.stringify(example);
150+
}
151+
return String(example);
152+
};
153+
154+
const renderExampleTabItem = (
155+
exampleName: string,
156+
exampleProperties: ExampleObject
157+
) => {
158+
return (
159+
// @ts-ignore
160+
<TabItem value={exampleName} label={exampleName}>
161+
{exampleProperties.summary && <p>{exampleProperties.summary}</p>}
162+
{exampleProperties.description && (
163+
<p>
164+
<strong>Description: </strong>
165+
<span>{exampleProperties.description}</span>
166+
</p>
167+
)}
168+
<p>
169+
<strong>Example: </strong>
170+
<code>{formatExample(exampleProperties.value)}</code>
171+
</p>
172+
</TabItem>
173+
);
174+
};
175+
151176
const renderExamples = guard(examples, (examples) => {
152-
const exampleEntries = Object.entries(examples);
177+
// Handle object-based examples (existing logic)
178+
let exampleEntries: [string, ExampleObject][];
179+
if (Array.isArray(examples)) {
180+
exampleEntries = examples.map((example, index) => [
181+
`Example ${index + 1}`,
182+
{ value: example, summary: null, description: null },
183+
]);
184+
} else {
185+
exampleEntries = Object.entries(examples);
186+
}
187+
188+
// If there's only one example, display it without tabs
189+
if (exampleEntries.length === 1) {
190+
const firstExample = exampleEntries[0][1];
191+
if (!firstExample) {
192+
return undefined;
193+
}
194+
return (
195+
<div>
196+
<strong>Example: </strong>
197+
<span>
198+
<code>{formatExample(firstExample.value)}</code>
199+
</span>
200+
</div>
201+
);
202+
}
203+
153204
return (
154205
<>
155206
<strong>Examples:</strong>
156207
<SchemaTabs>
157-
{exampleEntries.map(([exampleName, exampleProperties]) => (
158-
// @ts-ignore
159-
<TabItem value={exampleName} label={exampleName}>
160-
{exampleProperties.summary && <p>{exampleProperties.summary}</p>}
161-
{exampleProperties.description && (
162-
<p>
163-
<strong>Description: </strong>
164-
<span>{exampleProperties.description}</span>
165-
</p>
166-
)}
167-
<p>
168-
<strong>Example: </strong>
169-
<code>{exampleProperties.value}</code>
170-
</p>
171-
</TabItem>
172-
))}
208+
{exampleEntries.map(([exampleName, exampleProperties]) =>
209+
renderExampleTabItem(exampleName, exampleProperties)
210+
)}
173211
</SchemaTabs>
174212
</>
175213
);

packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import React, { ReactNode } from "react";
99

1010
import Markdown from "@theme/Markdown";
11+
import SchemaTabs from "@theme/SchemaTabs";
12+
import TabItem from "@theme/TabItem";
1113
import clsx from "clsx";
1214

1315
import { guard } from "../../markdown/utils";
@@ -63,6 +65,7 @@ export default function SchemaItem(props: Props) {
6365
let schemaDescription;
6466
let defaultValue: string | undefined;
6567
let example: string | undefined;
68+
let examples: string[] | undefined;
6669
let nullable;
6770
let enumDescriptions: [string, string][] = [];
6871
let constValue: string | undefined;
@@ -73,6 +76,7 @@ export default function SchemaItem(props: Props) {
7376
enumDescriptions = transformEnumDescriptions(schema["x-enumDescriptions"]);
7477
defaultValue = schema.default;
7578
example = schema.example;
79+
examples = schema.examples;
7680
nullable =
7781
schema.nullable ||
7882
(Array.isArray(schema.type) && schema.type.includes("null")); // support JSON Schema nullable
@@ -163,6 +167,53 @@ export default function SchemaItem(props: Props) {
163167
return undefined;
164168
}
165169

170+
// Helper function to format example value
171+
const formatExample = (example: any) => {
172+
if (typeof example === "object" && example !== null) {
173+
return JSON.stringify(example);
174+
}
175+
return String(example);
176+
};
177+
178+
function renderExamples() {
179+
if (examples && examples.length > 0) {
180+
// If there's only one example, display it without tabs
181+
if (examples.length === 1) {
182+
return (
183+
<div>
184+
<strong>Example: </strong>
185+
<span>
186+
<code>{formatExample(examples[0])}</code>
187+
</span>
188+
</div>
189+
);
190+
}
191+
192+
// Multiple examples - use tabs
193+
return (
194+
<div>
195+
<strong>Examples:</strong>
196+
<SchemaTabs>
197+
{examples.map((example, index) => (
198+
// @ts-ignore
199+
<TabItem
200+
value={`Example ${index + 1}`}
201+
label={`Example ${index + 1}`}
202+
key={`Example ${index + 1}`}
203+
>
204+
<p>
205+
<strong>Example: </strong>
206+
<code>{formatExample(example)}</code>
207+
</p>
208+
</TabItem>
209+
))}
210+
</SchemaTabs>
211+
</div>
212+
);
213+
}
214+
return undefined;
215+
}
216+
166217
function renderConstValue() {
167218
if (constValue !== undefined) {
168219
if (typeof constValue === "string") {
@@ -213,6 +264,7 @@ export default function SchemaItem(props: Props) {
213264
{renderConstValue()}
214265
{renderDefaultValue()}
215266
{renderExample()}
267+
{renderExamples()}
216268
{collapsibleSchemaContent ?? collapsibleSchemaContent}
217269
</div>
218270
);

0 commit comments

Comments
 (0)