@gitbook/react-openapi 1.5.1 → 1.5.2

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/InteractiveSection.js +59 -0
  3. package/dist/Markdown.js +10 -0
  4. package/dist/OpenAPICodeSample.js +219 -0
  5. package/dist/OpenAPICodeSampleInteractive.js +66 -0
  6. package/dist/OpenAPICodeSampleSelector.js +45 -0
  7. package/dist/OpenAPICopyButton.js +39 -0
  8. package/dist/OpenAPIDisclosure.js +30 -0
  9. package/dist/OpenAPIDisclosureGroup.js +75 -0
  10. package/dist/OpenAPIExample.js +41 -0
  11. package/dist/OpenAPIMediaType.js +58 -0
  12. package/dist/OpenAPIOperation.d.ts +15 -0
  13. package/dist/OpenAPIOperation.js +30 -0
  14. package/dist/OpenAPIOperationContext.d.ts +20 -0
  15. package/dist/OpenAPIOperationContext.js +30 -0
  16. package/dist/OpenAPIPath.js +51 -0
  17. package/dist/OpenAPIPrefillContextProvider.d.ts +26 -0
  18. package/dist/OpenAPIPrefillContextProvider.js +25 -0
  19. package/dist/OpenAPIRequestBody.js +28 -0
  20. package/dist/OpenAPIRequestBodyHeaderType.js +23 -0
  21. package/dist/OpenAPIResponse.js +39 -0
  22. package/dist/OpenAPIResponseExample.js +75 -0
  23. package/dist/OpenAPIResponseExampleContent.js +61 -0
  24. package/dist/OpenAPIResponses.js +61 -0
  25. package/dist/OpenAPISchema.js +373 -0
  26. package/dist/OpenAPISchemaName.js +45 -0
  27. package/dist/OpenAPISchemaServer.js +13 -0
  28. package/dist/OpenAPISecurities.js +124 -0
  29. package/dist/OpenAPISelect.js +45 -0
  30. package/dist/OpenAPISpec.js +73 -0
  31. package/dist/OpenAPIWebhook.d.ts +15 -0
  32. package/dist/OpenAPIWebhook.js +28 -0
  33. package/dist/OpenAPIWebhookExample.js +40 -0
  34. package/dist/ScalarApiButton.js +87 -0
  35. package/dist/StaticSection.js +37 -0
  36. package/dist/code-samples.js +275 -0
  37. package/dist/common/OpenAPIColumnSpec.js +23 -0
  38. package/dist/common/OpenAPIOperationDescription.js +18 -0
  39. package/dist/common/OpenAPIStability.js +17 -0
  40. package/dist/common/OpenAPISummary.js +27 -0
  41. package/dist/contentTypeChecks.js +34 -0
  42. package/dist/context.d.ts +71 -0
  43. package/dist/context.js +29 -0
  44. package/dist/decycle.js +41 -0
  45. package/dist/dereference.js +24 -0
  46. package/dist/generateSchemaExample.js +198 -0
  47. package/dist/getDisclosureLabel.js +17 -0
  48. package/dist/getOrCreateStoreByKey.js +22 -0
  49. package/dist/index.d.ts +11 -662
  50. package/dist/index.js +9 -3871
  51. package/dist/json2xml.js +12 -0
  52. package/dist/resolveOpenAPIOperation.d.ts +15 -0
  53. package/dist/resolveOpenAPIOperation.js +102 -0
  54. package/dist/resolveOpenAPIWebhook.d.ts +15 -0
  55. package/dist/resolveOpenAPIWebhook.js +52 -0
  56. package/dist/schemas/OpenAPISchemaItem.js +26 -0
  57. package/dist/schemas/OpenAPISchemas.d.ts +19 -0
  58. package/dist/schemas/OpenAPISchemas.js +57 -0
  59. package/dist/schemas/resolveOpenAPISchemas.d.ts +15 -0
  60. package/dist/schemas/resolveOpenAPISchemas.js +17 -0
  61. package/dist/stringifyOpenAPI.js +14 -0
  62. package/dist/translate.js +43 -0
  63. package/dist/translations/de.js +48 -0
  64. package/dist/translations/en.d.ts +47 -0
  65. package/dist/translations/en.js +48 -0
  66. package/dist/translations/es.js +48 -0
  67. package/dist/translations/fr.js +48 -0
  68. package/dist/translations/index.d.ts +408 -0
  69. package/dist/translations/index.js +31 -0
  70. package/dist/translations/ja.js +48 -0
  71. package/dist/translations/nl.js +48 -0
  72. package/dist/translations/no.js +48 -0
  73. package/dist/translations/pt-br.js +48 -0
  74. package/dist/translations/types.d.ts +7 -0
  75. package/dist/translations/zh.js +48 -0
  76. package/dist/types.d.ts +37 -0
  77. package/dist/util/example.js +84 -0
  78. package/dist/util/server.js +38 -0
  79. package/dist/util/tryit-prefill.js +143 -0
  80. package/dist/utils.js +163 -0
  81. package/package.json +10 -7
@@ -0,0 +1,15 @@
1
+ import { OpenAPIContextInput } from "./context.js";
2
+ import { OpenAPIWebhookData } from "./types.js";
3
+ import * as react0 from "react";
4
+
5
+ //#region src/OpenAPIWebhook.d.ts
6
+ /**
7
+ * Display an interactive OpenAPI webhook.
8
+ */
9
+ declare function OpenAPIWebhook(props: {
10
+ className?: string;
11
+ data: OpenAPIWebhookData;
12
+ context: OpenAPIContextInput;
13
+ }): react0.JSX.Element;
14
+ //#endregion
15
+ export { OpenAPIWebhook };
@@ -0,0 +1,28 @@
1
+ import { resolveOpenAPIContext } from "./context.js";
2
+ import { OpenAPIColumnSpec } from "./common/OpenAPIColumnSpec.js";
3
+ import { OpenAPISummary } from "./common/OpenAPISummary.js";
4
+ import { OpenAPIWebhookExample } from "./OpenAPIWebhookExample.js";
5
+ import clsx from "classnames";
6
+
7
+ //#region src/OpenAPIWebhook.tsx
8
+ /**
9
+ * Display an interactive OpenAPI webhook.
10
+ */
11
+ function OpenAPIWebhook(props) {
12
+ const { className, data, context: contextInput } = props;
13
+ const context = resolveOpenAPIContext(contextInput);
14
+ return <div className={clsx("openapi-webhook", className)}>
15
+ <OpenAPISummary data={data} context={context} />
16
+ <div className="openapi-columns">
17
+ <OpenAPIColumnSpec data={data} context={context} />
18
+ <div className="openapi-column-preview">
19
+ <div className="openapi-column-preview-body">
20
+ <OpenAPIWebhookExample data={data} context={context} />
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </div>;
25
+ }
26
+
27
+ //#endregion
28
+ export { OpenAPIWebhook };
@@ -0,0 +1,40 @@
1
+ import { OpenAPIEmptyExample } from "./OpenAPIExample.js";
2
+ import { createStateKey } from "./utils.js";
3
+ import { getOpenAPIClientContext } from "./context.js";
4
+ import { getExamples } from "./util/example.js";
5
+ import { OpenAPIMediaTypeContent } from "./OpenAPIMediaType.js";
6
+
7
+ //#region src/OpenAPIWebhookExample.tsx
8
+ function OpenAPIWebhookExample(props) {
9
+ const { data, context } = props;
10
+ const { operation } = data;
11
+ const items = (() => {
12
+ if (!operation.requestBody) return [];
13
+ return Object.entries(operation.requestBody.content).map(([key, value]) => {
14
+ if (!value?.schema) return {
15
+ key,
16
+ label: key,
17
+ body: <OpenAPIEmptyExample context={context} />
18
+ };
19
+ return {
20
+ key,
21
+ label: key,
22
+ body: <></>,
23
+ examples: getExamples({
24
+ mediaTypeObject: value,
25
+ mediaType: key,
26
+ context
27
+ })
28
+ };
29
+ });
30
+ })();
31
+ return <div className="openapi-panel">
32
+ <h4 className="openapi-panel-heading">Payload</h4>
33
+ <div className="openapi-panel-body">
34
+ <OpenAPIMediaTypeContent selectIcon={context.icons.chevronDown} stateKey={createStateKey("request-body-media-type", context.blockKey)} items={items} context={getOpenAPIClientContext(context)} />
35
+ </div>
36
+ </div>;
37
+ }
38
+
39
+ //#endregion
40
+ export { OpenAPIWebhookExample };
@@ -0,0 +1,87 @@
1
+ 'use client';
2
+
3
+
4
+ import { t } from "./translate.js";
5
+ import { useOpenAPIOperationContext } from "./OpenAPIOperationContext.js";
6
+ import { useOpenAPIPrefillContext } from "./OpenAPIPrefillContextProvider.js";
7
+ import { resolveTryItPrefillForOperation } from "./util/tryit-prefill.js";
8
+ import { Suspense, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
9
+ import { ApiClientModalProvider, useApiClientModal } from "@scalar/api-client-react";
10
+ import { createPortal } from "react-dom";
11
+
12
+ //#region src/ScalarApiButton.tsx
13
+ /**
14
+ * Button which launches the Scalar API Client
15
+ */
16
+ function ScalarApiButton(props) {
17
+ const { method, path, securities, servers, specUrl, context } = props;
18
+ const [isOpen, setIsOpen] = useState(false);
19
+ const controllerRef = useRef(null);
20
+ return <div className="scalar scalar-activate">
21
+ <button className="scalar-activate-button button" onClick={() => {
22
+ controllerRef.current?.openClient?.();
23
+ setIsOpen(true);
24
+ }}>
25
+ {t(context.translation, "test_it")}
26
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 12" fill="currentColor">
27
+ <path stroke="currentColor" strokeWidth="1.5" d="M1 10.05V1.43c0-.2.2-.31.37-.22l7.26 4.08c.17.1.17.33.01.43l-7.26 4.54a.25.25 0 0 1-.38-.21Z" />
28
+ </svg>
29
+ </button>
30
+
31
+ {isOpen && createPortal(<Suspense fallback={null}>
32
+ <ScalarModal controllerRef={controllerRef} method={method} path={path} securities={securities} servers={servers} specUrl={specUrl} />
33
+ </Suspense>, document.body)}
34
+ </div>;
35
+ }
36
+ function ScalarModal(props) {
37
+ const { method, path, securities, servers, specUrl, controllerRef } = props;
38
+ const prefillInputContext = useOpenAPIPrefillContext()();
39
+ const prefillConfig = resolveTryItPrefillForOperation({
40
+ operation: {
41
+ securities,
42
+ servers
43
+ },
44
+ prefillInputContext
45
+ });
46
+ return <ApiClientModalProvider configuration={{
47
+ url: specUrl,
48
+ ...prefillConfig
49
+ }} initialRequest={{
50
+ method,
51
+ path
52
+ }}>
53
+ <ScalarModalController method={method} path={path} controllerRef={controllerRef} />
54
+ </ApiClientModalProvider>;
55
+ }
56
+ function ScalarModalController(props) {
57
+ const { method, path, controllerRef } = props;
58
+ const openScalarClient = useApiClientModal()?.open;
59
+ const { onOpenClient: trackClientOpening } = useOpenAPIOperationContext();
60
+ const openClient = useMemo(() => {
61
+ if (openScalarClient) return () => {
62
+ openScalarClient({
63
+ method,
64
+ path,
65
+ _source: "gitbook"
66
+ });
67
+ trackClientOpening({
68
+ method,
69
+ path
70
+ });
71
+ };
72
+ return null;
73
+ }, [
74
+ openScalarClient,
75
+ method,
76
+ path,
77
+ trackClientOpening
78
+ ]);
79
+ useImperativeHandle(controllerRef, () => ({ openClient: openClient ? () => openClient() : void 0 }), [openClient]);
80
+ useEffect(() => {
81
+ openClient?.();
82
+ }, [openClient]);
83
+ return null;
84
+ }
85
+
86
+ //#endregion
87
+ export { ScalarApiButton };
@@ -0,0 +1,37 @@
1
+ import clsx from "classnames";
2
+ import { forwardRef } from "react";
3
+
4
+ //#region src/StaticSection.tsx
5
+ function Section(props) {
6
+ return <div {...props} className={clsx("openapi-section", props.className)} />;
7
+ }
8
+ function SectionHeader(props) {
9
+ return <div {...props} className={clsx("openapi-section-header", props.className ? `${props.className}-header` : void 0)} />;
10
+ }
11
+ function SectionHeaderContent(props) {
12
+ return <div {...props} className={clsx("openapi-section-header-content", props.className && `${props.className}-header-content`)} />;
13
+ }
14
+ const SectionBody = forwardRef(function SectionBody$1(props, ref) {
15
+ return <div ref={ref} {...props} className={clsx("openapi-section-body", props.className && `${props.className}-body`)} />;
16
+ });
17
+ function SectionFooter(props) {
18
+ return <div {...props} className={clsx("openapi-section-footer", props.className && `${props.className}-footer`)} />;
19
+ }
20
+ function SectionFooterContent(props) {
21
+ return <div {...props} className={clsx("openapi-section-footer-content", props.className && `${props.className}-footer-content`)} />;
22
+ }
23
+ function StaticSection(props) {
24
+ const { className, header, children, footer } = props;
25
+ return <Section className={className}>
26
+ {header ? <SectionHeader className={className}>
27
+ <SectionHeaderContent className={className}>{header}</SectionHeaderContent>
28
+ </SectionHeader> : null}
29
+ <SectionBody className={className}>{children}</SectionBody>
30
+ {footer ? <SectionFooter className={className}>
31
+ <SectionFooterContent className={className}>{footer}</SectionFooterContent>
32
+ </SectionFooter> : null}
33
+ </Section>;
34
+ }
35
+
36
+ //#endregion
37
+ export { Section, SectionBody, SectionHeader, SectionHeaderContent, StaticSection };
@@ -0,0 +1,275 @@
1
+ import { json2xml } from "./json2xml.js";
2
+ import { stringifyOpenAPI } from "./stringifyOpenAPI.js";
3
+ import { isCSV, isFormData, isFormUrlEncoded, isGraphQL, isJSON, isPDF, isPlainObject, isText, isXML, isYAML } from "./contentTypeChecks.js";
4
+ import yaml from "js-yaml";
5
+
6
+ //#region src/code-samples.ts
7
+ const codeSampleGenerators = [
8
+ {
9
+ id: "http",
10
+ label: "HTTP",
11
+ syntax: "http",
12
+ generate: ({ method, url: { origin, path }, headers = {}, body }) => {
13
+ if (body) {
14
+ const bodyContent = body ? stringifyOpenAPI(body) : "";
15
+ const encoder = new TextEncoder();
16
+ const bodyString$1 = BodyGenerators.getHTTPBody(body, headers);
17
+ if (bodyString$1) body = bodyString$1;
18
+ headers = {
19
+ ...headers,
20
+ "Content-Length": encoder.encode(bodyContent).length.toString()
21
+ };
22
+ }
23
+ if (!headers.hasOwnProperty("Accept")) headers.Accept = "*/*";
24
+ const headerString = headers ? `${Object.entries(headers).map(([key, value]) => key.toLowerCase() !== "host" ? `${key}: ${value}` : "").join("\n")}\n` : "";
25
+ const bodyString = body ? `\n${body}` : "";
26
+ return `${method.toUpperCase()} ${decodeURI(path)} HTTP/1.1
27
+ Host: ${origin.replaceAll(/https*:\/\//g, "")}
28
+ ${headerString}${bodyString}`;
29
+ }
30
+ },
31
+ {
32
+ id: "curl",
33
+ label: "cURL",
34
+ syntax: "bash",
35
+ generate: ({ method, url: { origin, path }, headers, body }) => {
36
+ const separator = " \\\n";
37
+ const lines = ["curl -L"];
38
+ if (method.toUpperCase() !== "GET") lines.push(`--request ${method.toUpperCase()}`);
39
+ lines.push(`--url '${origin}${path}'`);
40
+ if (body) {
41
+ const bodyContent = BodyGenerators.getCurlBody(body, headers);
42
+ if (bodyContent) {
43
+ body = bodyContent.body;
44
+ headers = bodyContent.headers;
45
+ }
46
+ }
47
+ if (headers && Object.keys(headers).length > 0) Object.entries(headers).forEach(([key, value]) => {
48
+ lines.push(`--header '${key}: ${value}'`);
49
+ });
50
+ if (body) if (Array.isArray(body)) lines.push(...body);
51
+ else lines.push(body);
52
+ return lines.map((line, index) => index > 0 ? indent(line, 2) : line).join(separator);
53
+ }
54
+ },
55
+ {
56
+ id: "javascript",
57
+ label: "JavaScript",
58
+ syntax: "javascript",
59
+ generate: ({ method, url: { origin, path }, headers, body }) => {
60
+ let code = "";
61
+ if (body) {
62
+ const lines = BodyGenerators.getJavaScriptBody(body, headers);
63
+ if (lines) {
64
+ code += lines.code;
65
+ body = lines.body;
66
+ headers = lines.headers;
67
+ }
68
+ }
69
+ code += `const response = await fetch('${origin}${path}', {
70
+ method: '${method.toUpperCase()}',\n`;
71
+ if (headers && Object.keys(headers).length > 0) code += indent(`headers: ${stringifyOpenAPI(headers, null, 2)},\n`, 4);
72
+ if (body) code += indent(`body: ${body}\n`, 4);
73
+ code += "});\n\n";
74
+ code += "const data = await response.json();";
75
+ return code;
76
+ }
77
+ },
78
+ {
79
+ id: "python",
80
+ label: "Python",
81
+ syntax: "python",
82
+ generate: ({ method, url: { origin, path }, headers, body }) => {
83
+ const contentType = headers?.["Content-Type"];
84
+ let code = `${isJSON(contentType) ? "import json\n" : ""}import requests\n\n`;
85
+ if (body) {
86
+ const lines = BodyGenerators.getPythonBody(body, headers);
87
+ if (lines) {
88
+ code += lines.code;
89
+ body = lines.body;
90
+ headers = lines.headers;
91
+ }
92
+ }
93
+ code += `response = requests.${method.toLowerCase()}(\n`;
94
+ code += indent(`"${origin}${path}",\n`, 4);
95
+ if (headers && Object.keys(headers).length > 0) code += indent(`headers=${stringifyOpenAPI(headers)},\n`, 4);
96
+ if (body) if (body === "files") code += indent(`files=${body}\n`, 4);
97
+ else if (isJSON(contentType)) code += indent(`data=json.dumps(${body})\n`, 4);
98
+ else code += indent(`data=${body}\n`, 4);
99
+ code += ")\n\n";
100
+ code += "data = response.json()";
101
+ return code;
102
+ }
103
+ }
104
+ ];
105
+ function indent(code, spaces) {
106
+ const indent$1 = " ".repeat(spaces);
107
+ return code.split("\n").map((line) => line ? indent$1 + line : "").join("\n");
108
+ }
109
+ function parseHostAndPath(url) {
110
+ try {
111
+ const urlObj = new URL(url);
112
+ const path = urlObj.pathname || "/";
113
+ return {
114
+ host: urlObj.host,
115
+ path
116
+ };
117
+ } catch (_e) {
118
+ const splitted = url.split("//");
119
+ const parts = (splitted[1] ? splitted[1] : url).split("/");
120
+ return {
121
+ host: parts.shift(),
122
+ path: `/${parts.join("/")}`
123
+ };
124
+ }
125
+ }
126
+ const BodyGenerators = {
127
+ getCurlBody(body, headers) {
128
+ if (!body || !headers) return void 0;
129
+ const headersCopy = { ...headers };
130
+ const contentType = headersCopy["Content-Type"] || "";
131
+ if (isFormData(contentType)) body = isPlainObject(body) ? Object.entries(body).map(([key, value]) => `--form '${key}=${String(value)}'`) : `--form 'file=@${body}'`;
132
+ else if (isFormUrlEncoded(contentType)) body = isPlainObject(body) ? `--data '${Object.entries(body).map(([key, value]) => `${key}=${String(value)}`).join("&")}'` : String(body);
133
+ else if (isText(contentType)) body = `--data '${String(body).replace(/"/g, "")}'`;
134
+ else if (isXML(contentType)) body = `--data-binary $'${convertBodyToXML(body)}'`;
135
+ else if (isCSV(contentType)) body = `--data-binary $'${stringifyOpenAPI(body).replace(/"/g, "").replace(/\\n/g, "\n")}'`;
136
+ else if (isGraphQL(contentType)) {
137
+ body = `--data '${stringifyOpenAPI(body)}'`;
138
+ headersCopy["Content-Type"] = "application/json";
139
+ } else if (isPDF(contentType)) body = `--data-binary '@${String(body)}'`;
140
+ else if (isYAML(contentType)) body = `--data-binary $'${yaml.dump(body).replace(/'/g, "").replace(/\\n/g, "\n")}'`;
141
+ else body = `--data '${stringifyOpenAPI(body, null, 2).replace(/\\n/g, "\n")}'`;
142
+ return {
143
+ body,
144
+ headers: headersCopy
145
+ };
146
+ },
147
+ getJavaScriptBody: (body, headers) => {
148
+ if (!body || !headers) return;
149
+ let code = "";
150
+ const headersCopy = { ...headers };
151
+ const contentType = headersCopy["Content-Type"] || "";
152
+ if (isFormData(contentType)) {
153
+ code += "const formData = new FormData();\n\n";
154
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
155
+ code += `formData.append("${key}", "${String(value)}");\n`;
156
+ });
157
+ else if (typeof body === "string") code += `formData.append("file", "${body}");\n`;
158
+ code += "\n";
159
+ body = "formData";
160
+ } else if (isFormUrlEncoded(contentType)) {
161
+ code += "const params = new URLSearchParams();\n\n";
162
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
163
+ code += `params.append("${key}", "${String(value)}");\n`;
164
+ });
165
+ code += "\n";
166
+ body = "params.toString()";
167
+ } else if (isGraphQL(contentType)) if (isPlainObject(body)) {
168
+ Object.entries(body).forEach(([key, value]) => {
169
+ code += `const ${key} = \`\n${indent(String(value), 4)}\`;\n\n`;
170
+ });
171
+ body = `JSON.stringify({ ${Object.keys(body).join(", ")} })`;
172
+ headersCopy["Content-Type"] = "application/json";
173
+ } else {
174
+ code += `const query = \`\n${indent(String(body), 4)}\`;\n\n`;
175
+ body = "JSON.stringify(query)";
176
+ }
177
+ else if (isCSV(contentType)) {
178
+ code += "const csv = `\n";
179
+ code += indent(String(body), 4);
180
+ code += "`;\n\n";
181
+ body = "csv";
182
+ } else if (isPDF(contentType)) {
183
+ code += "const formData = new FormData();\n\n";
184
+ code += `formData.append("file", "${body}");\n\n`;
185
+ body = "formData";
186
+ } else if (isXML(contentType)) {
187
+ code += "const xml = `\n";
188
+ code += indent(convertBodyToXML(body), 4);
189
+ code += "`;\n\n";
190
+ body = "xml";
191
+ } else if (isYAML(contentType)) {
192
+ code += `const yamlBody = \`\n${indent(yaml.dump(body), 4)}\`;\n\n`;
193
+ body = "yamlBody";
194
+ } else if (isText(contentType)) body = stringifyOpenAPI(body, null, 2);
195
+ else body = `JSON.stringify(${stringifyOpenAPI(body, null, 2)})`;
196
+ return {
197
+ body,
198
+ code,
199
+ headers: headersCopy
200
+ };
201
+ },
202
+ getPythonBody: (body, headers) => {
203
+ if (!body || !headers) return;
204
+ let code = "";
205
+ const contentType = headers["Content-Type"] || "";
206
+ if (isFormData(contentType)) {
207
+ code += "files = {\n";
208
+ if (isPlainObject(body)) Object.entries(body).forEach(([key, value]) => {
209
+ code += `${indent(`"${key}": "${String(value)}",`, 4)}\n`;
210
+ });
211
+ code += "}\n\n";
212
+ body = "files";
213
+ } else if (isPDF(contentType)) {
214
+ code += "files = {\n";
215
+ code += `${indent(`"file": "${body}",`, 4)}\n`;
216
+ code += "}\n\n";
217
+ body = "files";
218
+ } else if (isXML(contentType)) body = JSON.stringify(convertBodyToXML(body));
219
+ else if (isYAML(contentType)) {
220
+ code += `yamlBody = \"\"\"\n${indent(yaml.dump(body), 4)}\"\"\"\n\n`;
221
+ body = "yamlBody";
222
+ } else body = stringifyOpenAPI(body, (_key, value) => {
223
+ switch (value) {
224
+ case true: return "$$__TRUE__$$";
225
+ case false: return "$$__FALSE__$$";
226
+ case null: return "$$__NULL__$$";
227
+ default: return value;
228
+ }
229
+ }, 2).replaceAll("\"$$__TRUE__$$\"", "True").replaceAll("\"$$__FALSE__$$\"", "False").replaceAll("\"$$__NULL__$$\"", "None");
230
+ return {
231
+ body,
232
+ code,
233
+ headers
234
+ };
235
+ },
236
+ getHTTPBody: (body, headers) => {
237
+ if (!body || !headers) return void 0;
238
+ const contentType = headers["Content-Type"] || "";
239
+ const typeHandlers = {
240
+ pdf: () => `${stringifyOpenAPI(body, null, 2)}`,
241
+ formUrlEncoded: () => {
242
+ return `"${(isPlainObject(body) ? Object.entries(body).map(([key, value]) => `${key}=${stringifyOpenAPI(value)}`).join("&") : stringifyOpenAPI(body)).replace(/"/g, "'")}"`;
243
+ },
244
+ text: () => `"${String(body)}"`,
245
+ xml: () => {
246
+ return `"${convertBodyToXML(body)}"`;
247
+ },
248
+ yaml: () => `"${yaml.dump(body).replace(/"/g, "\\\"")}"`,
249
+ csv: () => `"${stringifyOpenAPI(body).replace(/"/g, "")}"`,
250
+ default: () => `${stringifyOpenAPI(body, null, 2)}`
251
+ };
252
+ if (isPDF(contentType)) return typeHandlers.pdf();
253
+ if (isFormUrlEncoded(contentType)) return typeHandlers.formUrlEncoded();
254
+ if (isText(contentType)) return typeHandlers.text();
255
+ if (isXML(contentType)) return typeHandlers.xml();
256
+ if (isYAML(contentType)) return typeHandlers.yaml();
257
+ if (isCSV(contentType)) return typeHandlers.csv();
258
+ return typeHandlers.default();
259
+ }
260
+ };
261
+ /**
262
+ * Converts a body to XML format
263
+ */
264
+ function convertBodyToXML(body) {
265
+ if (typeof body === "string" && body.trim().startsWith("<")) return body;
266
+ if (typeof body !== "object" || body === null) try {
267
+ body = JSON.parse(body);
268
+ } catch {
269
+ return body;
270
+ }
271
+ return json2xml(body).replace(/"/g, "").replace(/\\n/g, "\n").replace(/\\t/g, " ");
272
+ }
273
+
274
+ //#endregion
275
+ export { codeSampleGenerators, parseHostAndPath };
@@ -0,0 +1,23 @@
1
+ import { t } from "../translate.js";
2
+ import { getOpenAPIClientContext } from "../context.js";
3
+ import { OpenAPISpec } from "../OpenAPISpec.js";
4
+ import { OpenAPIOperationDescription } from "./OpenAPIOperationDescription.js";
5
+
6
+ //#region src/common/OpenAPIColumnSpec.tsx
7
+ function OpenAPIColumnSpec(props) {
8
+ const { data, context } = props;
9
+ const { operation } = data;
10
+ const clientContext = getOpenAPIClientContext(context);
11
+ return <div className="openapi-column-spec">
12
+ {operation["x-deprecated-sunset"] ? <div className="openapi-deprecated-sunset openapi-description openapi-markdown">
13
+ {t(context.translation, "deprecated_and_sunset_on", [<span key="date" className="openapi-deprecated-sunset-date">
14
+ {operation["x-deprecated-sunset"]}
15
+ </span>])}
16
+ </div> : null}
17
+ <OpenAPIOperationDescription operation={operation} context={context} />
18
+ <OpenAPISpec data={data} context={clientContext} />
19
+ </div>;
20
+ }
21
+
22
+ //#endregion
23
+ export { OpenAPIColumnSpec };
@@ -0,0 +1,18 @@
1
+ import { Markdown } from "../Markdown.js";
2
+ import { resolveDescription } from "../utils.js";
3
+
4
+ //#region src/common/OpenAPIOperationDescription.tsx
5
+ function OpenAPIOperationDescription(props) {
6
+ const { operation } = props;
7
+ if (operation["x-gitbook-description-document"]) return <div className="openapi-intro">
8
+ {props.context.renderDocument({ document: operation["x-gitbook-description-document"] })}
9
+ </div>;
10
+ const description = resolveDescription(operation);
11
+ if (!description) return null;
12
+ return <div className="openapi-intro">
13
+ <Markdown className="openapi-description" source={description} />
14
+ </div>;
15
+ }
16
+
17
+ //#endregion
18
+ export { OpenAPIOperationDescription };
@@ -0,0 +1,17 @@
1
+ //#region src/common/OpenAPIStability.tsx
2
+ const stabilityEnum = {
3
+ experimental: "Experimental",
4
+ alpha: "Alpha",
5
+ beta: "Beta"
6
+ };
7
+ function OpenAPIStability(props) {
8
+ const { stability } = props;
9
+ const foundStability = stabilityEnum[stability];
10
+ if (!foundStability) return null;
11
+ return <div className={`openapi-stability openapi-stability-${foundStability.toLowerCase()}`}>
12
+ {foundStability}
13
+ </div>;
14
+ }
15
+
16
+ //#endregion
17
+ export { OpenAPIStability };
@@ -0,0 +1,27 @@
1
+ import { OpenAPIPath } from "../OpenAPIPath.js";
2
+ import { OpenAPIStability } from "./OpenAPIStability.js";
3
+
4
+ //#region src/common/OpenAPISummary.tsx
5
+ function OpenAPISummary(props) {
6
+ const { data, context } = props;
7
+ const { operation } = data;
8
+ const title = (() => {
9
+ if (operation.summary) return operation.summary;
10
+ if ("name" in data) return data.name;
11
+ })();
12
+ return <div className="openapi-summary" id={operation.summary ? void 0 : context.id}>
13
+ {(operation.deprecated || operation["x-stability"]) && <div className="openapi-summary-tags">
14
+ {operation.deprecated && <div className="openapi-deprecated">Deprecated</div>}
15
+ {operation["x-stability"] && <OpenAPIStability stability={operation["x-stability"]} />}
16
+ </div>}
17
+ {title ? context.renderHeading({
18
+ deprecated: operation.deprecated ?? false,
19
+ stability: operation["x-stability"],
20
+ title
21
+ }) : null}
22
+ {"path" in data ? <OpenAPIPath data={data} context={context} /> : null}
23
+ </div>;
24
+ }
25
+
26
+ //#endregion
27
+ export { OpenAPISummary };
@@ -0,0 +1,34 @@
1
+ //#region src/contentTypeChecks.ts
2
+ function isJSON(contentType) {
3
+ return contentType?.toLowerCase().includes("application/json") || false;
4
+ }
5
+ function isXML(contentType) {
6
+ return contentType?.toLowerCase().includes("application/xml") || false;
7
+ }
8
+ function isYAML(contentType) {
9
+ return contentType?.toLowerCase().includes("application/yaml") || false;
10
+ }
11
+ function isGraphQL(contentType) {
12
+ return contentType?.toLowerCase().includes("application/graphql") || false;
13
+ }
14
+ function isCSV(contentType) {
15
+ return contentType?.toLowerCase().includes("text/csv") || false;
16
+ }
17
+ function isPDF(contentType) {
18
+ return contentType?.toLowerCase().includes("application/pdf") || false;
19
+ }
20
+ function isText(contentType) {
21
+ return contentType?.toLowerCase().includes("text/plain") || false;
22
+ }
23
+ function isFormUrlEncoded(contentType) {
24
+ return contentType?.toLowerCase().includes("application/x-www-form-urlencoded") || false;
25
+ }
26
+ function isFormData(contentType) {
27
+ return !!contentType && contentType.toLowerCase().includes("multipart/form-data");
28
+ }
29
+ function isPlainObject(value) {
30
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31
+ }
32
+
33
+ //#endregion
34
+ export { isCSV, isFormData, isFormUrlEncoded, isGraphQL, isJSON, isPDF, isPlainObject, isText, isXML, isYAML };
@@ -0,0 +1,71 @@
1
+ import { Translation } from "./translations/types.js";
2
+ import { TranslationLocale } from "./translations/index.js";
3
+
4
+ //#region src/context.d.ts
5
+ interface OpenAPIClientContext {
6
+ /**
7
+ * The translation language to use.
8
+ */
9
+ translation: Translation;
10
+ /**
11
+ * Icons used in the block.
12
+ */
13
+ icons: {
14
+ chevronDown: React.ReactNode;
15
+ chevronRight: React.ReactNode;
16
+ plus: React.ReactNode;
17
+ };
18
+ /**
19
+ * Force all sections to be opened by default.
20
+ * @default false
21
+ */
22
+ defaultInteractiveOpened?: boolean;
23
+ /**
24
+ * The key of the block
25
+ */
26
+ blockKey?: string;
27
+ /**
28
+ * Optional id attached to the heading and used as an anchor.
29
+ */
30
+ id?: string;
31
+ /**
32
+ * Mark the context as a client context.
33
+ */
34
+ $$isClientContext$$: true;
35
+ }
36
+ interface OpenAPIContext extends Omit<OpenAPIClientContext, '$$isClientContext$$'> {
37
+ /**
38
+ * Render a code block.
39
+ */
40
+ renderCodeBlock: (props: {
41
+ code: string;
42
+ syntax: string;
43
+ }) => React.ReactNode;
44
+ /**
45
+ * Render the heading of the operation.
46
+ */
47
+ renderHeading: (props: {
48
+ deprecated: boolean;
49
+ title: string;
50
+ stability?: string;
51
+ }) => React.ReactNode;
52
+ /**
53
+ * Render the document of the operation.
54
+ */
55
+ renderDocument: (props: {
56
+ document: object;
57
+ }) => React.ReactNode;
58
+ /**
59
+ * Specification URL.
60
+ */
61
+ specUrl: string;
62
+ }
63
+ interface OpenAPIContextInput extends Omit<OpenAPIContext, 'translation'> {
64
+ /**
65
+ * The translation language to use.
66
+ * @default 'en'
67
+ */
68
+ locale?: TranslationLocale | undefined;
69
+ }
70
+ //#endregion
71
+ export { OpenAPIContextInput };