Skip to content

Commit bf1af5f

Browse files
committed
refactor: add BaseSchemaComponent
1 parent cd478ed commit bf1af5f

File tree

5 files changed

+165
-259
lines changed

5 files changed

+165
-259
lines changed

demo/examples/tests/examples.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ paths:
5757
example2:
5858
summary: "name example 2"
5959
description: "name example 2 description"
60-
value: "Jane Doe"
60+
value: "Jane Smith"
6161
responses:
6262
"204":
6363
description: no content
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/* ============================================================================
2+
* Copyright (c) Palo Alto Networks
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
* ========================================================================== */
7+
8+
import React from "react";
9+
10+
import BrowserOnly from "@docusaurus/BrowserOnly";
11+
import Details from "@theme/Details";
12+
import {
13+
ExampleFromSchema,
14+
MimeExample,
15+
MimeExamples,
16+
SchemaExample,
17+
SchemaExamples,
18+
} from "@theme/Examples";
19+
import Markdown from "@theme/Markdown";
20+
import MimeTabs from "@theme/MimeTabs";
21+
import SchemaNode from "@theme/Schema";
22+
import SchemaTabs from "@theme/SchemaTabs";
23+
import SkeletonLoader from "@theme/SkeletonLoader";
24+
import TabItem from "@theme/TabItem";
25+
import { MediaTypeObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types";
26+
27+
interface Props {
28+
style?: React.CSSProperties;
29+
title: string;
30+
body: {
31+
content?: {
32+
[key: string]: MediaTypeObject;
33+
};
34+
description?: string;
35+
required?: string[] | boolean;
36+
};
37+
schemaType: "request" | "response";
38+
}
39+
40+
const BaseSchemaComponent: React.FC<Props> = ({
41+
title,
42+
body,
43+
style,
44+
schemaType,
45+
}) => {
46+
if (
47+
body === undefined ||
48+
body.content === undefined ||
49+
Object.keys(body).length === 0 ||
50+
Object.keys(body.content).length === 0
51+
) {
52+
return null;
53+
}
54+
55+
const mimeTypes = Object.keys(body.content);
56+
if (mimeTypes && mimeTypes.length) {
57+
return (
58+
<MimeTabs className="openapi-tabs__mime" schemaType={schemaType}>
59+
{mimeTypes.map((mimeType: any) => {
60+
const mimeExamples = body.content![mimeType].examples;
61+
const mimeExample = body.content![mimeType].example;
62+
const schemaExamples = body.content![mimeType].schema?.examples;
63+
const schemaExample = body.content![mimeType].schema?.example;
64+
const firstBody = body.content![mimeType].schema;
65+
66+
if (
67+
firstBody === undefined ||
68+
(firstBody.properties &&
69+
Object.keys(firstBody.properties).length === 0)
70+
) {
71+
return null;
72+
}
73+
74+
if (firstBody) {
75+
const tabTitle = "Schema";
76+
return (
77+
// @ts-ignore
78+
<TabItem key={mimeType} label={mimeType} value={mimeType}>
79+
<SchemaTabs className="openapi-tabs__schema">
80+
{/* @ts-ignore */}
81+
<TabItem key={tabTitle} label={tabTitle} value={tabTitle}>
82+
<Details
83+
className="openapi-markdown__details mime"
84+
data-collapsed={false}
85+
open={true}
86+
style={style}
87+
summary={
88+
<>
89+
<summary>
90+
<strong className="openapi-markdown__details-summary-header-body">
91+
{title}
92+
{body.required && (
93+
<strong className="openapi-schema__required">
94+
required
95+
</strong>
96+
)}
97+
</strong>
98+
</summary>
99+
</>
100+
}
101+
>
102+
<div style={{ textAlign: "left", marginLeft: "1rem" }}>
103+
{body.description && (
104+
<div
105+
style={{ marginTop: "1rem", marginBottom: "1rem" }}
106+
>
107+
<Markdown>{body.description}</Markdown>
108+
</div>
109+
)}
110+
</div>
111+
<ul style={{ marginLeft: "1rem" }}>
112+
<SchemaNode
113+
schema={firstBody}
114+
schemaType={schemaType}
115+
/>
116+
</ul>
117+
</Details>
118+
</TabItem>
119+
{firstBody &&
120+
ExampleFromSchema({
121+
schema: firstBody,
122+
mimeType,
123+
context: { type: schemaType },
124+
})}
125+
126+
{mimeExamples &&
127+
MimeExamples({ examples: mimeExamples, mimeType })}
128+
129+
{mimeExample &&
130+
MimeExample({ example: mimeExample, mimeType })}
131+
132+
{schemaExamples &&
133+
SchemaExamples({ examples: schemaExamples, mimeType })}
134+
135+
{schemaExample &&
136+
SchemaExample({ example: schemaExample, mimeType })}
137+
</SchemaTabs>
138+
</TabItem>
139+
);
140+
}
141+
return null;
142+
})}
143+
</MimeTabs>
144+
);
145+
}
146+
return null;
147+
};
148+
149+
const BaseSchema: React.FC<Props> = (props) => {
150+
return (
151+
<BrowserOnly fallback={<SkeletonLoader size="sm" />}>
152+
{() => {
153+
return <BaseSchemaComponent {...props} />;
154+
}}
155+
</BrowserOnly>
156+
);
157+
};
158+
159+
export default BaseSchema;

packages/docusaurus-theme-openapi-docs/src/theme/Markdown/Details/_Details.scss

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,7 @@
2424
/* Top-Level Details Caret Styling */
2525
.openapi-left-panel__container > .openapi-markdown__details > summary::before,
2626
.openapi-markdown__details.mime > summary::before {
27-
top: 0.1rem;
28-
}
29-
30-
.openapi-markdown__details.response > summary::before {
31-
top: 0.25rem; /* TODO: figure out why this is necessary */
27+
top: 0.25rem;
3228
}
3329
/* End of Top-Level Details Caret Styling */
3430

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

Lines changed: 2 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,7 @@
77

88
import React from "react";
99

10-
import BrowserOnly from "@docusaurus/BrowserOnly";
11-
import Details from "@theme/Details";
12-
import {
13-
ExampleFromSchema,
14-
MimeExample,
15-
MimeExamples,
16-
SchemaExample,
17-
SchemaExamples,
18-
} from "@theme/Examples";
19-
import Markdown from "@theme/Markdown";
20-
import MimeTabs from "@theme/MimeTabs"; // Assume these components exist
21-
import SchemaNode from "@theme/Schema";
22-
import SchemaTabs from "@theme/SchemaTabs";
23-
import SkeletonLoader from "@theme/SkeletonLoader";
24-
import TabItem from "@theme/TabItem";
10+
import BaseSchema from "@theme/BaseSchema";
2511
import { MediaTypeObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types";
2612

2713
interface Props {
@@ -36,114 +22,8 @@ interface Props {
3622
};
3723
}
3824

39-
const RequestSchemaComponent: React.FC<Props> = ({ title, body, style }) => {
40-
if (
41-
body === undefined ||
42-
body.content === undefined ||
43-
Object.keys(body).length === 0 ||
44-
Object.keys(body.content).length === 0
45-
) {
46-
return null;
47-
}
48-
49-
const SchemaTitle = "Schema";
50-
const mimeTypes = Object.keys(body.content);
51-
if (mimeTypes && mimeTypes.length) {
52-
return (
53-
<MimeTabs className="openapi-tabs__mime" schemaType="request">
54-
{mimeTypes.map((mimeType) => {
55-
const mimeExamples = body.content![mimeType].examples;
56-
const mimeExample = body.content![mimeType].example;
57-
const schemaExamples = body.content![mimeType].schema?.examples;
58-
const schemaExample = body.content![mimeType].schema?.example;
59-
60-
const firstBody = body.content![mimeType].schema;
61-
if (
62-
firstBody === undefined ||
63-
(firstBody.properties &&
64-
Object.keys(firstBody.properties).length === 0)
65-
) {
66-
return null;
67-
}
68-
return (
69-
// @ts-ignore
70-
<TabItem key={mimeType} label={mimeType} value={mimeType}>
71-
<SchemaTabs className="openapi-tabs__schema">
72-
{/* @ts-ignore */}
73-
<TabItem
74-
key={SchemaTitle}
75-
label={SchemaTitle}
76-
value={SchemaTitle}
77-
>
78-
<Details
79-
className="openapi-markdown__details mime"
80-
data-collapsed={false}
81-
open={true}
82-
style={style}
83-
summary={
84-
<>
85-
<summary>
86-
<h3 className="openapi-markdown__details-summary-header-body">
87-
{title}
88-
{body.required && (
89-
<strong className="openapi-schema__required">
90-
required
91-
</strong>
92-
)}
93-
</h3>
94-
</summary>
95-
</>
96-
}
97-
>
98-
<div style={{ textAlign: "left", marginLeft: "1rem" }}>
99-
{body.description && (
100-
<div
101-
style={{ marginTop: "1rem", marginBottom: "1rem" }}
102-
>
103-
<Markdown>{body.description}</Markdown>
104-
</div>
105-
)}
106-
</div>
107-
<ul style={{ marginLeft: "1rem" }}>
108-
<SchemaNode schema={firstBody} schemaType="request" />
109-
</ul>
110-
</Details>
111-
</TabItem>
112-
{firstBody &&
113-
ExampleFromSchema({
114-
schema: firstBody,
115-
mimeType,
116-
context: { type: "request" },
117-
})}
118-
119-
{mimeExamples &&
120-
MimeExamples({ examples: mimeExamples, mimeType })}
121-
122-
{mimeExample && MimeExample({ example: mimeExample, mimeType })}
123-
124-
{schemaExamples &&
125-
SchemaExamples({ examples: schemaExamples, mimeType })}
126-
127-
{schemaExample &&
128-
SchemaExample({ example: schemaExample, mimeType })}
129-
</SchemaTabs>
130-
</TabItem>
131-
);
132-
})}
133-
</MimeTabs>
134-
);
135-
}
136-
return null;
137-
};
138-
13925
const RequestSchema: React.FC<Props> = (props) => {
140-
return (
141-
<BrowserOnly fallback={<SkeletonLoader size="sm" />}>
142-
{() => {
143-
return <RequestSchemaComponent {...props} />;
144-
}}
145-
</BrowserOnly>
146-
);
26+
return <BaseSchema {...props} schemaType="request" />;
14727
};
14828

14929
export default RequestSchema;

0 commit comments

Comments
 (0)