docusaurus-theme-openapi-docs 4.2.0 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/theme/ApiExplorer/ApiCodeBlock/Line/_Line.scss +0 -12
- package/lib/theme/ApiExplorer/Authorization/index.js +3 -0
- package/lib/theme/ApiExplorer/Body/index.js +11 -2
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +41 -45
- package/lib/theme/ApiExplorer/buildPostmanRequest.js +1 -1
- package/lib/theme/Markdown/Details/_Details.scss +5 -2
- package/lib/theme/Markdown/index.js +160 -18
- package/lib/theme/ParamsItem/index.js +7 -48
- package/lib/theme/RequestSchema/index.js +11 -3
- package/lib/theme/ResponseExamples/index.d.ts +9 -39
- package/lib/theme/ResponseExamples/index.js +3 -99
- package/lib/theme/ResponseHeaders/index.d.ts +13 -0
- package/lib/theme/ResponseHeaders/index.js +39 -0
- package/lib/theme/ResponseSchema/index.js +4 -2
- package/lib/theme/Schema/index.js +29 -21
- package/lib/theme/SchemaItem/index.js +7 -41
- package/lib/theme/StatusCodes/index.js +10 -7
- package/package.json +10 -6
- package/src/theme/ApiExplorer/ApiCodeBlock/Line/_Line.scss +0 -12
- package/src/theme/ApiExplorer/Authorization/index.tsx +3 -0
- package/src/theme/ApiExplorer/Body/index.tsx +3 -2
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +45 -47
- package/src/theme/ApiExplorer/buildPostmanRequest.ts +1 -1
- package/src/theme/Markdown/Details/_Details.scss +5 -2
- package/src/theme/Markdown/index.js +160 -18
- package/src/theme/ParamsItem/index.tsx +6 -36
- package/src/theme/RequestSchema/index.tsx +3 -3
- package/src/theme/ResponseExamples/index.tsx +24 -122
- package/src/theme/ResponseHeaders/index.tsx +49 -0
- package/src/theme/ResponseSchema/index.tsx +2 -2
- package/src/theme/Schema/index.tsx +29 -22
- package/src/theme/SchemaItem/index.tsx +11 -35
- package/src/theme/StatusCodes/index.tsx +3 -3
|
@@ -5,13 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
-
/* ============================================================================
|
|
9
|
-
* Copyright (c) Palo Alto Networks
|
|
10
|
-
*
|
|
11
|
-
* This source code is licensed under the MIT license found in the
|
|
12
|
-
* LICENSE file in the root directory of this source tree.
|
|
13
|
-
* ========================================================================== */
|
|
14
|
-
|
|
15
8
|
import React, { useState, useEffect } from "react";
|
|
16
9
|
|
|
17
10
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
@@ -19,6 +12,7 @@ import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock";
|
|
|
19
12
|
import buildPostmanRequest from "@theme/ApiExplorer/buildPostmanRequest";
|
|
20
13
|
import CodeTabs from "@theme/ApiExplorer/CodeTabs";
|
|
21
14
|
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
15
|
+
import cloneDeep from "lodash/cloneDeep";
|
|
22
16
|
import codegen from "postman-code-generators";
|
|
23
17
|
import sdk from "postman-collection";
|
|
24
18
|
|
|
@@ -59,6 +53,44 @@ function CodeSnippets({ postman, codeSamples }: Props) {
|
|
|
59
53
|
const headerParams = useTypedSelector((state: any) => state.params.header);
|
|
60
54
|
|
|
61
55
|
const auth = useTypedSelector((state: any) => state.auth);
|
|
56
|
+
const clonedAuth = cloneDeep(auth);
|
|
57
|
+
let placeholder: string;
|
|
58
|
+
|
|
59
|
+
function cleanCredentials(obj: any) {
|
|
60
|
+
for (const key in obj) {
|
|
61
|
+
if (typeof obj[key] === "object" && obj[key] !== null) {
|
|
62
|
+
// use name as placeholder if exists
|
|
63
|
+
const comboAuthId = Object.keys(obj).join(" and ");
|
|
64
|
+
const authOptions =
|
|
65
|
+
clonedAuth?.options?.[key] ?? clonedAuth?.options?.[comboAuthId];
|
|
66
|
+
placeholder = authOptions?.[0]?.name;
|
|
67
|
+
obj[key] = cleanCredentials(obj[key]);
|
|
68
|
+
} else {
|
|
69
|
+
obj[key] = `<${placeholder ?? key}>`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return obj;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// scrub credentials from code snippets
|
|
77
|
+
const cleanedAuth = {
|
|
78
|
+
...clonedAuth,
|
|
79
|
+
data: cleanCredentials(clonedAuth.data),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Create a Postman request object using cleanedAuth
|
|
83
|
+
const cleanedPostmanRequest = buildPostmanRequest(postman, {
|
|
84
|
+
queryParams,
|
|
85
|
+
pathParams,
|
|
86
|
+
cookieParams,
|
|
87
|
+
contentType,
|
|
88
|
+
accept,
|
|
89
|
+
headerParams,
|
|
90
|
+
body,
|
|
91
|
+
server,
|
|
92
|
+
auth: cleanedAuth,
|
|
93
|
+
});
|
|
62
94
|
|
|
63
95
|
// User-defined languages array
|
|
64
96
|
// Can override languageSet, change order of langs, override options and variants
|
|
@@ -105,21 +137,10 @@ function CodeSnippets({ postman, codeSamples }: Props) {
|
|
|
105
137
|
}
|
|
106
138
|
|
|
107
139
|
if (language && !!language.options) {
|
|
108
|
-
const postmanRequest = buildPostmanRequest(postman, {
|
|
109
|
-
queryParams,
|
|
110
|
-
pathParams,
|
|
111
|
-
cookieParams,
|
|
112
|
-
contentType,
|
|
113
|
-
accept,
|
|
114
|
-
headerParams,
|
|
115
|
-
body,
|
|
116
|
-
server,
|
|
117
|
-
auth,
|
|
118
|
-
});
|
|
119
140
|
codegen.convert(
|
|
120
141
|
language.language,
|
|
121
142
|
language.variant,
|
|
122
|
-
|
|
143
|
+
cleanedPostmanRequest,
|
|
123
144
|
language.options,
|
|
124
145
|
(error: any, snippet: string) => {
|
|
125
146
|
if (error) {
|
|
@@ -137,22 +158,10 @@ function CodeSnippets({ postman, codeSamples }: Props) {
|
|
|
137
158
|
// This allows users to define only the minimal properties necessary in languageTabs
|
|
138
159
|
// User-defined properties should override languageSet properties
|
|
139
160
|
const mergedLanguage = { ...langSource[0], ...language };
|
|
140
|
-
const postmanRequest = buildPostmanRequest(postman, {
|
|
141
|
-
queryParams,
|
|
142
|
-
pathParams,
|
|
143
|
-
cookieParams,
|
|
144
|
-
contentType,
|
|
145
|
-
accept,
|
|
146
|
-
headerParams,
|
|
147
|
-
body,
|
|
148
|
-
server,
|
|
149
|
-
auth,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
161
|
codegen.convert(
|
|
153
162
|
mergedLanguage.language,
|
|
154
163
|
mergedLanguage.variant,
|
|
155
|
-
|
|
164
|
+
cleanedPostmanRequest,
|
|
156
165
|
mergedLanguage.options,
|
|
157
166
|
(error: any, snippet: string) => {
|
|
158
167
|
if (error) {
|
|
@@ -175,27 +184,16 @@ function CodeSnippets({ postman, codeSamples }: Props) {
|
|
|
175
184
|
postman,
|
|
176
185
|
queryParams,
|
|
177
186
|
server,
|
|
178
|
-
|
|
187
|
+
cleanedPostmanRequest,
|
|
179
188
|
mergedLangs,
|
|
180
189
|
]);
|
|
181
|
-
// no dependencies was
|
|
190
|
+
// no dependencies was intentionally set for this particular hook. it's safe as long as if conditions are set
|
|
182
191
|
useEffect(function onSelectedVariantUpdate() {
|
|
183
192
|
if (selectedVariant && selectedVariant !== language?.variant) {
|
|
184
|
-
const postmanRequest = buildPostmanRequest(postman, {
|
|
185
|
-
queryParams,
|
|
186
|
-
pathParams,
|
|
187
|
-
cookieParams,
|
|
188
|
-
contentType,
|
|
189
|
-
accept,
|
|
190
|
-
headerParams,
|
|
191
|
-
body,
|
|
192
|
-
server,
|
|
193
|
-
auth,
|
|
194
|
-
});
|
|
195
193
|
codegen.convert(
|
|
196
194
|
language.language,
|
|
197
195
|
selectedVariant,
|
|
198
|
-
|
|
196
|
+
cleanedPostmanRequest,
|
|
199
197
|
language.options,
|
|
200
198
|
(error: any, snippet: string) => {
|
|
201
199
|
if (error) {
|
|
@@ -207,7 +205,7 @@ function CodeSnippets({ postman, codeSamples }: Props) {
|
|
|
207
205
|
}
|
|
208
206
|
});
|
|
209
207
|
|
|
210
|
-
// no dependencies was
|
|
208
|
+
// no dependencies was intentionally set for this particular hook. it's safe as long as if conditions are set
|
|
211
209
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
212
210
|
useEffect(function onSelectedSampleUpdate() {
|
|
213
211
|
if (
|
|
@@ -23,10 +23,13 @@
|
|
|
23
23
|
|
|
24
24
|
/* Top-Level Details Caret Styling */
|
|
25
25
|
.openapi-left-panel__container > .openapi-markdown__details > summary::before,
|
|
26
|
-
.openapi-markdown__details.mime > summary::before
|
|
27
|
-
.openapi-markdown__details.response > summary::before {
|
|
26
|
+
.openapi-markdown__details.mime > summary::before {
|
|
28
27
|
top: 0.1rem;
|
|
29
28
|
}
|
|
29
|
+
|
|
30
|
+
.openapi-markdown__details.response > summary::before {
|
|
31
|
+
top: 0.25rem; /* TODO: figure out why this is necessary */
|
|
32
|
+
}
|
|
30
33
|
/* End of Top-Level Details Caret Styling */
|
|
31
34
|
|
|
32
35
|
.openapi-markdown__details {
|
|
@@ -7,30 +7,172 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
|
+
import Admonition from "@theme/Admonition";
|
|
10
11
|
import CodeBlock from "@theme/CodeBlock";
|
|
11
12
|
import ReactMarkdown from "react-markdown";
|
|
12
13
|
import rehypeRaw from "rehype-raw";
|
|
14
|
+
import remarkGfm from "remark-gfm";
|
|
15
|
+
|
|
16
|
+
function remarkAdmonition() {
|
|
17
|
+
return (tree) => {
|
|
18
|
+
const openingTagRegex = /^:::(\w+)(?:\[(.*?)\])?\s*$/;
|
|
19
|
+
const closingTagRegex = /^:::\s*$/;
|
|
20
|
+
const textOnlyAdmonition = /^:::(\w+)(?:\[(.*?)\])?\s*([\s\S]*?)\s*:::$/;
|
|
21
|
+
|
|
22
|
+
const nodes = [];
|
|
23
|
+
let bufferedChildren = [];
|
|
24
|
+
|
|
25
|
+
let insideAdmonition = false;
|
|
26
|
+
let type = null;
|
|
27
|
+
let title = null;
|
|
28
|
+
|
|
29
|
+
tree.children.forEach((node) => {
|
|
30
|
+
if (
|
|
31
|
+
node.type === "paragraph" &&
|
|
32
|
+
node.children.length === 1 &&
|
|
33
|
+
node.children[0].type === "text"
|
|
34
|
+
) {
|
|
35
|
+
const text = node.children[0].value.trim();
|
|
36
|
+
const openingMatch = text.match(openingTagRegex);
|
|
37
|
+
const closingMatch = text.match(closingTagRegex);
|
|
38
|
+
const textOnlyAdmonitionMatch = text.match(textOnlyAdmonition);
|
|
39
|
+
|
|
40
|
+
if (textOnlyAdmonitionMatch) {
|
|
41
|
+
const type = textOnlyAdmonitionMatch[1];
|
|
42
|
+
const title = textOnlyAdmonitionMatch[2]
|
|
43
|
+
? textOnlyAdmonitionMatch[2]?.trim()
|
|
44
|
+
: undefined;
|
|
45
|
+
const content = textOnlyAdmonitionMatch[3];
|
|
46
|
+
|
|
47
|
+
const admonitionNode = {
|
|
48
|
+
type: "admonition",
|
|
49
|
+
data: {
|
|
50
|
+
hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component
|
|
51
|
+
hProperties: {
|
|
52
|
+
type, // Passed as a prop to the Admonition component
|
|
53
|
+
title,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
children: [
|
|
57
|
+
{
|
|
58
|
+
type: "text",
|
|
59
|
+
value: content?.trim(), // Trim leading/trailing whitespace
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
nodes.push(admonitionNode);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (openingMatch) {
|
|
68
|
+
type = openingMatch[1];
|
|
69
|
+
title = openingMatch[2] || type;
|
|
70
|
+
insideAdmonition = true;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (closingMatch && insideAdmonition) {
|
|
75
|
+
nodes.push({
|
|
76
|
+
type: "admonition",
|
|
77
|
+
data: {
|
|
78
|
+
hName: "Admonition",
|
|
79
|
+
hProperties: { type: type, title: title },
|
|
80
|
+
},
|
|
81
|
+
children: bufferedChildren,
|
|
82
|
+
});
|
|
83
|
+
bufferedChildren = [];
|
|
84
|
+
insideAdmonition = false;
|
|
85
|
+
type = null;
|
|
86
|
+
title = null;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (insideAdmonition) {
|
|
92
|
+
bufferedChildren.push(node);
|
|
93
|
+
} else {
|
|
94
|
+
nodes.push(node);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (bufferedChildren.length > 0 && type) {
|
|
99
|
+
nodes.push({
|
|
100
|
+
type: "admonition",
|
|
101
|
+
data: {
|
|
102
|
+
hName: "Admonition",
|
|
103
|
+
hProperties: { type: type, title: title },
|
|
104
|
+
},
|
|
105
|
+
children: bufferedChildren,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
tree.children = nodes;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function convertAstToHtmlStr(ast) {
|
|
113
|
+
if (!ast || !Array.isArray(ast)) {
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const convertNode = (node) => {
|
|
118
|
+
switch (node.type) {
|
|
119
|
+
case "text":
|
|
120
|
+
return node.value;
|
|
121
|
+
case "element":
|
|
122
|
+
const { tagName, properties, children } = node;
|
|
123
|
+
|
|
124
|
+
// Convert attributes to a string
|
|
125
|
+
const attrs = properties
|
|
126
|
+
? Object.entries(properties)
|
|
127
|
+
.map(([key, value]) => `${key}="${value}"`)
|
|
128
|
+
.join(" ")
|
|
129
|
+
: "";
|
|
130
|
+
|
|
131
|
+
// Convert children to HTML
|
|
132
|
+
const childrenHtml = children ? children.map(convertNode).join("") : "";
|
|
133
|
+
|
|
134
|
+
return `<${tagName} ${attrs}>${childrenHtml}</${tagName}>`;
|
|
135
|
+
default:
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return ast.map(convertNode).join("");
|
|
141
|
+
}
|
|
13
142
|
|
|
14
143
|
function Markdown({ children }) {
|
|
15
144
|
return (
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
145
|
+
<ReactMarkdown
|
|
146
|
+
rehypePlugins={[rehypeRaw]}
|
|
147
|
+
remarkPlugins={[remarkGfm, remarkAdmonition]}
|
|
148
|
+
components={{
|
|
149
|
+
pre: (props) => <div {...props} />,
|
|
150
|
+
code({ node, inline, className, children, ...props }) {
|
|
151
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
152
|
+
return match ? (
|
|
153
|
+
<CodeBlock className={className} language={match[1]} {...props}>
|
|
154
|
+
{children}
|
|
155
|
+
</CodeBlock>
|
|
156
|
+
) : (
|
|
157
|
+
<code className={className} {...props}>
|
|
158
|
+
{children}
|
|
159
|
+
</code>
|
|
160
|
+
);
|
|
161
|
+
},
|
|
162
|
+
admonition: ({ node, ...props }) => {
|
|
163
|
+
const type = node.data?.hProperties?.type || "note";
|
|
164
|
+
const title = node.data?.hProperties?.title || type;
|
|
165
|
+
const content = convertAstToHtmlStr(node.children);
|
|
166
|
+
return (
|
|
167
|
+
<Admonition type={type} title={title} {...props}>
|
|
168
|
+
<div dangerouslySetInnerHTML={{ __html: content }} />
|
|
169
|
+
</Admonition>
|
|
170
|
+
);
|
|
171
|
+
},
|
|
172
|
+
}}
|
|
173
|
+
>
|
|
174
|
+
{children}
|
|
175
|
+
</ReactMarkdown>
|
|
34
176
|
);
|
|
35
177
|
}
|
|
36
178
|
|
|
@@ -7,16 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import Markdown from "@theme/Markdown";
|
|
11
11
|
import SchemaTabs from "@theme/SchemaTabs";
|
|
12
12
|
import TabItem from "@theme/TabItem";
|
|
13
13
|
/* eslint-disable import/no-extraneous-dependencies*/
|
|
14
14
|
import clsx from "clsx";
|
|
15
|
-
import ReactMarkdown from "react-markdown";
|
|
16
|
-
import rehypeRaw from "rehype-raw";
|
|
17
|
-
import remarkGfm from "remark-gfm";
|
|
18
15
|
|
|
19
|
-
import { createDescription } from "../../markdown/createDescription";
|
|
20
16
|
import { getQualifierMessage, getSchemaName } from "../../markdown/schema";
|
|
21
17
|
import { guard, toString } from "../../markdown/utils";
|
|
22
18
|
|
|
@@ -97,34 +93,12 @@ function ParamsItem({ param, ...rest }: Props) {
|
|
|
97
93
|
<span className="openapi-schema__deprecated">deprecated</span>
|
|
98
94
|
));
|
|
99
95
|
|
|
100
|
-
const
|
|
101
|
-
<
|
|
102
|
-
<ReactMarkdown
|
|
103
|
-
children={createDescription(message)}
|
|
104
|
-
rehypePlugins={[rehypeRaw]}
|
|
105
|
-
/>
|
|
106
|
-
</div>
|
|
96
|
+
const renderQualifier = guard(getQualifierMessage(schema), (qualifier) => (
|
|
97
|
+
<Markdown>{qualifier}</Markdown>
|
|
107
98
|
));
|
|
108
99
|
|
|
109
100
|
const renderDescription = guard(description, (description) => (
|
|
110
|
-
|
|
111
|
-
<ReactMarkdown
|
|
112
|
-
children={createDescription(description)}
|
|
113
|
-
components={{
|
|
114
|
-
pre: "div",
|
|
115
|
-
code({ node, inline, className, children, ...props }) {
|
|
116
|
-
const match = /language-(\w+)/.exec(className || "");
|
|
117
|
-
if (inline) return <code>{children}</code>;
|
|
118
|
-
return !inline && match ? (
|
|
119
|
-
<CodeBlock className={className}>{children}</CodeBlock>
|
|
120
|
-
) : (
|
|
121
|
-
<CodeBlock>{children}</CodeBlock>
|
|
122
|
-
);
|
|
123
|
-
},
|
|
124
|
-
}}
|
|
125
|
-
rehypePlugins={[rehypeRaw]}
|
|
126
|
-
/>
|
|
127
|
-
</>
|
|
101
|
+
<Markdown>{description}</Markdown>
|
|
128
102
|
));
|
|
129
103
|
|
|
130
104
|
const renderEnumDescriptions = guard(
|
|
@@ -132,11 +106,7 @@ function ParamsItem({ param, ...rest }: Props) {
|
|
|
132
106
|
(value) => {
|
|
133
107
|
return (
|
|
134
108
|
<div style={{ marginTop: ".5rem" }}>
|
|
135
|
-
<
|
|
136
|
-
rehypePlugins={[rehypeRaw]}
|
|
137
|
-
remarkPlugins={[remarkGfm]}
|
|
138
|
-
children={value}
|
|
139
|
-
/>
|
|
109
|
+
<Markdown>{value}</Markdown>
|
|
140
110
|
</div>
|
|
141
111
|
);
|
|
142
112
|
}
|
|
@@ -217,7 +187,7 @@ function ParamsItem({ param, ...rest }: Props) {
|
|
|
217
187
|
{renderSchemaRequired}
|
|
218
188
|
{renderDeprecated}
|
|
219
189
|
</span>
|
|
220
|
-
{
|
|
190
|
+
{renderQualifier}
|
|
221
191
|
{renderDescription}
|
|
222
192
|
{renderEnumDescriptions}
|
|
223
193
|
{renderDefaultValue()}
|
|
@@ -9,11 +9,11 @@ import React, { Suspense } from "react";
|
|
|
9
9
|
|
|
10
10
|
import BrowserOnly from "@docusaurus/BrowserOnly";
|
|
11
11
|
import Details from "@theme/Details";
|
|
12
|
+
import Markdown from "@theme/Markdown";
|
|
12
13
|
import MimeTabs from "@theme/MimeTabs"; // Assume these components exist
|
|
13
14
|
import SchemaNode from "@theme/Schema";
|
|
14
15
|
import SkeletonLoader from "@theme/SkeletonLoader";
|
|
15
16
|
import TabItem from "@theme/TabItem";
|
|
16
|
-
import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription";
|
|
17
17
|
import { MediaTypeObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types";
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
@@ -78,7 +78,7 @@ const RequestSchemaComponent: React.FC<Props> = ({ title, body, style }) => {
|
|
|
78
78
|
<div style={{ textAlign: "left", marginLeft: "1rem" }}>
|
|
79
79
|
{body.description && (
|
|
80
80
|
<div style={{ marginTop: "1rem", marginBottom: "1rem" }}>
|
|
81
|
-
{
|
|
81
|
+
<Markdown>{body.description}</Markdown>
|
|
82
82
|
</div>
|
|
83
83
|
)}
|
|
84
84
|
</div>
|
|
@@ -131,7 +131,7 @@ const RequestSchemaComponent: React.FC<Props> = ({ title, body, style }) => {
|
|
|
131
131
|
<div style={{ textAlign: "left", marginLeft: "1rem" }}>
|
|
132
132
|
{body.description && (
|
|
133
133
|
<div style={{ marginTop: "1rem", marginBottom: "1rem" }}>
|
|
134
|
-
{
|
|
134
|
+
<Markdown>{body.description}</Markdown>
|
|
135
135
|
</div>
|
|
136
136
|
)}
|
|
137
137
|
</div>
|
|
@@ -7,14 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import Markdown from "@theme/Markdown";
|
|
11
11
|
import ResponseSamples from "@theme/ResponseSamples";
|
|
12
12
|
import TabItem from "@theme/TabItem";
|
|
13
|
-
import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription";
|
|
14
13
|
import { sampleResponseFromSchema } from "docusaurus-plugin-openapi-docs/lib/openapi/createResponseExample";
|
|
15
14
|
import format from "xml-formatter";
|
|
16
15
|
|
|
17
|
-
// Utility function
|
|
18
16
|
export function json2xml(o: Record<string, any>, tab: string): string {
|
|
19
17
|
const toXml = (v: any, name: string, ind: string): string => {
|
|
20
18
|
let xml = "";
|
|
@@ -52,120 +50,14 @@ export function json2xml(o: Record<string, any>, tab: string): string {
|
|
|
52
50
|
return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
interface
|
|
56
|
-
in: string;
|
|
57
|
-
name: string;
|
|
58
|
-
schema?: {
|
|
59
|
-
type?: string;
|
|
60
|
-
items?: Record<string, any>;
|
|
61
|
-
};
|
|
62
|
-
enumDescriptions?: [string, string][];
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
interface ResponseHeaderProps {
|
|
66
|
-
description?: string;
|
|
67
|
-
example?: string;
|
|
68
|
-
schema?: {
|
|
69
|
-
type?: string;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
interface ResponseExampleProps {
|
|
74
|
-
value: any;
|
|
75
|
-
summary?: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
interface Props {
|
|
79
|
-
parameters?: ParameterProps[];
|
|
80
|
-
type: string;
|
|
81
|
-
responseHeaders?: Record<string, ResponseHeaderProps>;
|
|
82
|
-
responseExamples?: Record<string, ResponseExampleProps>;
|
|
83
|
-
responseExample?: any;
|
|
84
|
-
schema?: any;
|
|
85
|
-
mimeType: string;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// React components
|
|
89
|
-
export const ParamsDetails: React.FC<Props> = ({ parameters, type }) => {
|
|
90
|
-
const params = parameters?.filter((param) => param?.in === type);
|
|
91
|
-
|
|
92
|
-
if (!params || params.length === 0) {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<details
|
|
98
|
-
className="openapi-markdown__details"
|
|
99
|
-
data-collapsed={false}
|
|
100
|
-
open={true}
|
|
101
|
-
style={{ marginBottom: "1rem" }}
|
|
102
|
-
>
|
|
103
|
-
<summary>
|
|
104
|
-
<h3 className="openapi-markdown__details-summary-header-params">
|
|
105
|
-
{`${type.charAt(0).toUpperCase() + type.slice(1)} Parameters`}
|
|
106
|
-
</h3>
|
|
107
|
-
</summary>
|
|
108
|
-
<div>
|
|
109
|
-
<ul>
|
|
110
|
-
{params.map((param, index) => (
|
|
111
|
-
<ParamsItem
|
|
112
|
-
key={index}
|
|
113
|
-
className="paramsItem"
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
param={{
|
|
116
|
-
...param,
|
|
117
|
-
enumDescriptions: Object.entries(
|
|
118
|
-
param?.schema?.items?.["x-enumDescriptions"] ?? {}
|
|
119
|
-
),
|
|
120
|
-
}}
|
|
121
|
-
/>
|
|
122
|
-
))}
|
|
123
|
-
</ul>
|
|
124
|
-
</div>
|
|
125
|
-
</details>
|
|
126
|
-
);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
export const ResponseHeaders: React.FC<{
|
|
130
|
-
responseHeaders?: Record<string, ResponseHeaderProps>;
|
|
131
|
-
}> = ({ responseHeaders }) => {
|
|
132
|
-
if (!responseHeaders) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<ul style={{ marginLeft: "1rem" }}>
|
|
138
|
-
{Object.entries(responseHeaders).map(([headerName, headerObj]) => {
|
|
139
|
-
const { description, example, schema } = headerObj;
|
|
140
|
-
const type = schema?.type ?? "any";
|
|
141
|
-
|
|
142
|
-
return (
|
|
143
|
-
<li className="schemaItem" key={headerName}>
|
|
144
|
-
<details>
|
|
145
|
-
<summary>
|
|
146
|
-
<strong>{headerName}</strong>
|
|
147
|
-
{type && <span style={{ opacity: "0.6" }}> {type}</span>}
|
|
148
|
-
</summary>
|
|
149
|
-
<div>
|
|
150
|
-
{description && (
|
|
151
|
-
<div style={{ marginTop: ".5rem", marginBottom: ".5rem" }}>
|
|
152
|
-
{example && `Example: ${example}`}
|
|
153
|
-
{createDescription(description)}
|
|
154
|
-
</div>
|
|
155
|
-
)}
|
|
156
|
-
</div>
|
|
157
|
-
</details>
|
|
158
|
-
</li>
|
|
159
|
-
);
|
|
160
|
-
})}
|
|
161
|
-
</ul>
|
|
162
|
-
);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
export const ResponseExamples: React.FC<{
|
|
53
|
+
interface ResponseExamplesProps {
|
|
166
54
|
responseExamples: any;
|
|
167
55
|
mimeType: string;
|
|
168
|
-
}
|
|
56
|
+
}
|
|
57
|
+
export const ResponseExamples: React.FC<ResponseExamplesProps> = ({
|
|
58
|
+
responseExamples,
|
|
59
|
+
mimeType,
|
|
60
|
+
}): any => {
|
|
169
61
|
let language = "shell";
|
|
170
62
|
if (mimeType.endsWith("json")) language = "json";
|
|
171
63
|
if (mimeType.endsWith("xml")) language = "xml";
|
|
@@ -182,9 +74,9 @@ export const ResponseExamples: React.FC<{
|
|
|
182
74
|
// @ts-ignore
|
|
183
75
|
<TabItem label={exampleName} value={exampleName} key={exampleName}>
|
|
184
76
|
{exampleValue.summary && (
|
|
185
|
-
<
|
|
77
|
+
<Markdown className="openapi-example__summary">
|
|
186
78
|
{exampleValue.summary}
|
|
187
|
-
</
|
|
79
|
+
</Markdown>
|
|
188
80
|
)}
|
|
189
81
|
<ResponseSamples
|
|
190
82
|
responseExample={responseExample}
|
|
@@ -198,10 +90,15 @@ export const ResponseExamples: React.FC<{
|
|
|
198
90
|
return examplesArray;
|
|
199
91
|
};
|
|
200
92
|
|
|
201
|
-
|
|
93
|
+
interface ResponseExampleProps {
|
|
202
94
|
responseExample: any;
|
|
203
95
|
mimeType: string;
|
|
204
|
-
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const ResponseExample: React.FC<ResponseExampleProps> = ({
|
|
99
|
+
responseExample,
|
|
100
|
+
mimeType,
|
|
101
|
+
}) => {
|
|
205
102
|
let language = "shell";
|
|
206
103
|
if (mimeType.endsWith("json")) {
|
|
207
104
|
language = "json";
|
|
@@ -219,16 +116,21 @@ export const ResponseExample: React.FC<{
|
|
|
219
116
|
// @ts-ignore
|
|
220
117
|
<TabItem label="Example" value="Example">
|
|
221
118
|
{responseExample.summary && (
|
|
222
|
-
<
|
|
119
|
+
<Markdown className="openapi-example__summary">
|
|
223
120
|
{responseExample.summary}
|
|
224
|
-
</
|
|
121
|
+
</Markdown>
|
|
225
122
|
)}
|
|
226
123
|
<ResponseSamples responseExample={exampleContent} language={language} />
|
|
227
124
|
</TabItem>
|
|
228
125
|
);
|
|
229
126
|
};
|
|
230
127
|
|
|
231
|
-
|
|
128
|
+
interface ExampleFromSchemaProps {
|
|
129
|
+
schema: any;
|
|
130
|
+
mimeType: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const ExampleFromSchema: React.FC<ExampleFromSchemaProps> = ({
|
|
232
134
|
schema,
|
|
233
135
|
mimeType,
|
|
234
136
|
}) => {
|