docusaurus-theme-openapi-docs 4.5.0 → 4.6.0

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 (119) hide show
  1. package/lib/markdown/schema.js +9 -1
  2. package/lib/theme/ApiExplorer/Accept/slice.d.ts +5 -2
  3. package/lib/theme/ApiExplorer/Authorization/index.js +50 -9
  4. package/lib/theme/ApiExplorer/Authorization/slice.d.ts +145 -3
  5. package/lib/theme/ApiExplorer/Authorization/slice.js +3 -1
  6. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.d.ts +7 -0
  7. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.js +126 -0
  8. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +9 -0
  9. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +110 -0
  10. package/lib/theme/ApiExplorer/Body/index.js +94 -100
  11. package/lib/theme/ApiExplorer/Body/slice.d.ts +1056 -11
  12. package/lib/theme/ApiExplorer/Body/slice.js +22 -2
  13. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
  14. package/lib/theme/ApiExplorer/CodeSnippets/index.js +37 -26
  15. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  16. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +3 -3
  17. package/lib/theme/ApiExplorer/CodeTabs/index.js +2 -2
  18. package/lib/theme/ApiExplorer/ContentType/slice.d.ts +5 -2
  19. package/lib/theme/ApiExplorer/FormFileUpload/index.js +6 -1
  20. package/lib/theme/ApiExplorer/FormItem/index.js +6 -1
  21. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +2 -0
  22. package/lib/theme/ApiExplorer/FormTextInput/index.js +8 -1
  23. package/lib/theme/ApiExplorer/LiveEditor/index.js +11 -4
  24. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +15 -5
  25. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +11 -3
  26. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +12 -4
  27. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +11 -2
  28. package/lib/theme/ApiExplorer/ParamOptions/index.js +11 -1
  29. package/lib/theme/ApiExplorer/ParamOptions/slice.d.ts +0 -4
  30. package/lib/theme/ApiExplorer/ParamOptions/slice.js +4 -4
  31. package/lib/theme/ApiExplorer/Request/index.js +110 -17
  32. package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +7 -1
  33. package/lib/theme/ApiExplorer/Request/makeRequest.js +94 -24
  34. package/lib/theme/ApiExplorer/Response/index.js +34 -14
  35. package/lib/theme/ApiExplorer/Response/slice.d.ts +31 -7
  36. package/lib/theme/ApiExplorer/SecuritySchemes/index.js +208 -69
  37. package/lib/theme/ApiExplorer/Server/index.js +16 -2
  38. package/lib/theme/ApiExplorer/Server/slice.d.ts +49 -3
  39. package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -57
  40. package/lib/theme/ApiExplorer/index.js +11 -1
  41. package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +19 -0
  42. package/lib/theme/ApiExplorer/{persistanceMiddleware.js → persistenceMiddleware.js} +16 -9
  43. package/lib/theme/ApiExplorer/storage-utils.d.ts +2 -2
  44. package/lib/theme/ApiExplorer/storage-utils.js +3 -3
  45. package/lib/theme/ApiItem/Layout/index.d.ts +1 -1
  46. package/lib/theme/ApiItem/hooks.d.ts +9 -9
  47. package/lib/theme/ApiItem/index.js +12 -8
  48. package/lib/theme/ApiItem/store.d.ts +55 -43
  49. package/lib/theme/ApiTabs/index.js +6 -1
  50. package/lib/theme/Example/_Example.scss +11 -0
  51. package/lib/theme/Example/index.d.ts +24 -0
  52. package/lib/theme/Example/index.js +170 -0
  53. package/lib/theme/ParamsDetails/index.js +9 -1
  54. package/lib/theme/ParamsItem/index.d.ts +1 -1
  55. package/lib/theme/ParamsItem/index.js +43 -74
  56. package/lib/theme/RequestSchema/index.js +18 -4
  57. package/lib/theme/ResponseExamples/index.js +23 -3
  58. package/lib/theme/ResponseSchema/index.js +97 -82
  59. package/lib/theme/Schema/index.js +106 -23
  60. package/lib/theme/SchemaItem/index.js +64 -36
  61. package/lib/theme/SchemaTabs/index.js +4 -1
  62. package/lib/theme/StatusCodes/index.js +11 -2
  63. package/lib/theme/styles.scss +5 -0
  64. package/lib/theme/translationIds.d.ts +90 -0
  65. package/lib/theme/translationIds.js +114 -0
  66. package/lib/types.d.ts +9 -1
  67. package/package.json +28 -28
  68. package/src/markdown/schema.ts +11 -1
  69. package/src/theme/ApiExplorer/Authorization/index.tsx +51 -10
  70. package/src/theme/ApiExplorer/Authorization/slice.ts +1 -1
  71. package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +77 -0
  72. package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +120 -0
  73. package/src/theme/ApiExplorer/Body/index.tsx +87 -107
  74. package/src/theme/ApiExplorer/Body/json2xml.d.ts +8 -0
  75. package/src/theme/ApiExplorer/Body/slice.ts +40 -1
  76. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +43 -29
  77. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  78. package/src/theme/ApiExplorer/CodeTabs/index.tsx +6 -5
  79. package/src/theme/ApiExplorer/ContentType/index.tsx +1 -1
  80. package/src/theme/ApiExplorer/FormFileUpload/index.tsx +6 -1
  81. package/src/theme/ApiExplorer/FormItem/index.tsx +8 -1
  82. package/src/theme/ApiExplorer/FormTextInput/index.tsx +10 -1
  83. package/src/theme/ApiExplorer/LiveEditor/index.tsx +11 -4
  84. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +16 -6
  85. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -4
  86. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +12 -4
  87. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +12 -3
  88. package/src/theme/ApiExplorer/ParamOptions/index.tsx +10 -2
  89. package/src/theme/ApiExplorer/ParamOptions/slice.ts +1 -1
  90. package/src/theme/ApiExplorer/Request/index.tsx +108 -17
  91. package/src/theme/ApiExplorer/Request/makeRequest.ts +106 -25
  92. package/src/theme/ApiExplorer/Response/index.tsx +30 -8
  93. package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +157 -69
  94. package/src/theme/ApiExplorer/Server/index.tsx +12 -4
  95. package/src/theme/ApiExplorer/buildPostmanRequest.ts +47 -63
  96. package/src/theme/ApiExplorer/index.tsx +10 -1
  97. package/src/theme/ApiExplorer/{persistanceMiddleware.ts → persistenceMiddleware.ts} +23 -13
  98. package/src/theme/ApiExplorer/storage-utils.ts +4 -4
  99. package/src/theme/ApiItem/Layout/index.tsx +1 -1
  100. package/src/theme/ApiItem/index.tsx +12 -7
  101. package/src/theme/ApiTabs/index.tsx +6 -1
  102. package/src/theme/Example/_Example.scss +11 -0
  103. package/src/theme/Example/index.tsx +168 -0
  104. package/src/theme/Markdown/index.d.ts +8 -0
  105. package/src/theme/ParamsDetails/index.tsx +10 -1
  106. package/src/theme/ParamsItem/index.tsx +38 -54
  107. package/src/theme/RequestSchema/index.tsx +19 -4
  108. package/src/theme/ResponseExamples/index.tsx +23 -3
  109. package/src/theme/ResponseSchema/index.tsx +73 -61
  110. package/src/theme/Schema/index.tsx +128 -33
  111. package/src/theme/SchemaItem/index.tsx +51 -33
  112. package/src/theme/SchemaTabs/index.tsx +4 -1
  113. package/src/theme/StatusCodes/index.tsx +13 -2
  114. package/src/theme/styles.scss +5 -0
  115. package/src/theme/translationIds.ts +111 -0
  116. package/src/theme-openapi.d.ts +7 -275
  117. package/src/types.ts +9 -1
  118. package/tsconfig.tsbuildinfo +1 -1
  119. package/lib/theme/ApiExplorer/persistanceMiddleware.d.ts +0 -3
@@ -8,17 +8,83 @@
8
8
  import { Body } from "@theme/ApiExplorer/Body/slice";
9
9
  import * as sdk from "postman-collection";
10
10
 
11
+ // Custom error types for better error handling
12
+ export type RequestErrorType =
13
+ | "timeout"
14
+ | "network"
15
+ | "cors"
16
+ | "abort"
17
+ | "unknown";
18
+
19
+ export class RequestError extends Error {
20
+ type: RequestErrorType;
21
+ originalError?: Error;
22
+
23
+ constructor(type: RequestErrorType, message: string, originalError?: Error) {
24
+ super(message);
25
+ this.name = "RequestError";
26
+ this.type = type;
27
+ this.originalError = originalError;
28
+ }
29
+ }
30
+
31
+ const DEFAULT_REQUEST_TIMEOUT = 30000; // 30 seconds
32
+
11
33
  function fetchWithtimeout(
12
34
  url: string,
13
35
  options: RequestInit,
14
- timeout = 5000
15
- ): any {
16
- return Promise.race([
17
- fetch(url, options),
18
- new Promise((_, reject) =>
19
- setTimeout(() => reject(new Error("Request timed out")), timeout)
20
- ),
21
- ]);
36
+ timeout = DEFAULT_REQUEST_TIMEOUT
37
+ ): Promise<Response> {
38
+ const controller = new AbortController();
39
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
40
+
41
+ return fetch(url, {
42
+ ...options,
43
+ signal: controller.signal,
44
+ })
45
+ .then((response) => {
46
+ clearTimeout(timeoutId);
47
+ return response;
48
+ })
49
+ .catch((error) => {
50
+ clearTimeout(timeoutId);
51
+
52
+ // Check if it was an abort due to timeout
53
+ if (error.name === "AbortError") {
54
+ throw new RequestError(
55
+ "timeout",
56
+ "The request timed out waiting for the server to respond. Please try again. If the issue persists, try using a different client (e.g., curl) with a longer timeout.",
57
+ error
58
+ );
59
+ }
60
+
61
+ // Check for network errors (offline, DNS failure, etc.)
62
+ if (error instanceof TypeError && error.message === "Failed to fetch") {
63
+ // This could be CORS, network failure, or the server being unreachable
64
+ throw new RequestError(
65
+ "network",
66
+ "Unable to reach the server. Please check your network connection and verify the server URL is correct. If the server is running, this may be a CORS issue.",
67
+ error
68
+ );
69
+ }
70
+
71
+ // Handle other TypeErrors that might indicate CORS issues
72
+ if (error instanceof TypeError) {
73
+ throw new RequestError(
74
+ "cors",
75
+ "The request was blocked, possibly due to CORS restrictions. Ensure the server allows requests from this origin, or try using a proxy.",
76
+ error
77
+ );
78
+ }
79
+
80
+ // Generic error fallback
81
+ throw new RequestError(
82
+ "unknown",
83
+ error.message ||
84
+ "An unexpected error occurred while making the request.",
85
+ error
86
+ );
87
+ });
22
88
  }
23
89
 
24
90
  async function loadImage(content: Blob): Promise<string | ArrayBuffer | null> {
@@ -47,7 +113,8 @@ async function loadImage(content: Blob): Promise<string | ArrayBuffer | null> {
47
113
  async function makeRequest(
48
114
  request: sdk.Request,
49
115
  proxy: string | undefined,
50
- _body: Body
116
+ _body: Body,
117
+ timeout: number = DEFAULT_REQUEST_TIMEOUT
51
118
  ) {
52
119
  const headers = request.toJSON().header;
53
120
 
@@ -194,7 +261,8 @@ async function makeRequest(
194
261
  finalUrl = normalizedProxy + request.url.toString();
195
262
  }
196
263
 
197
- return fetchWithtimeout(finalUrl, requestOptions).then((response: any) => {
264
+ try {
265
+ const response = await fetchWithtimeout(finalUrl, requestOptions, timeout);
198
266
  const contentType = response.headers.get("content-type");
199
267
  let fileExtension = "";
200
268
 
@@ -224,32 +292,45 @@ async function makeRequest(
224
292
  }
225
293
 
226
294
  if (fileExtension) {
227
- return response.blob().then((blob: any) => {
228
- const url = window.URL.createObjectURL(blob);
295
+ const blob = await response.blob();
296
+ const url = window.URL.createObjectURL(blob);
229
297
 
230
- const link = document.createElement("a");
231
- link.href = url;
232
- // Now the file name includes the extension
233
- link.setAttribute("download", `file${fileExtension}`);
298
+ const link = document.createElement("a");
299
+ link.href = url;
300
+ // Now the file name includes the extension
301
+ link.setAttribute("download", `file${fileExtension}`);
234
302
 
235
- // These two lines are necessary to make the link click in Firefox
236
- link.style.display = "none";
237
- document.body.appendChild(link);
303
+ // These two lines are necessary to make the link click in Firefox
304
+ link.style.display = "none";
305
+ document.body.appendChild(link);
238
306
 
239
- link.click();
307
+ link.click();
240
308
 
241
- // After link is clicked, it's safe to remove it.
242
- setTimeout(() => document.body.removeChild(link), 0);
309
+ // After link is clicked, it's safe to remove it.
310
+ setTimeout(() => document.body.removeChild(link), 0);
243
311
 
244
- return response;
245
- });
312
+ return response;
246
313
  } else {
247
314
  return response;
248
315
  }
249
316
  }
250
317
 
251
318
  return response;
252
- });
319
+ } catch (error) {
320
+ // Re-throw RequestError instances as-is
321
+ if (error instanceof RequestError) {
322
+ throw error;
323
+ }
324
+
325
+ // Wrap unexpected errors
326
+ throw new RequestError(
327
+ "unknown",
328
+ error instanceof Error
329
+ ? error.message
330
+ : "An unexpected error occurred while processing the response.",
331
+ error instanceof Error ? error : undefined
332
+ );
333
+ }
253
334
  }
254
335
 
255
336
  export default makeRequest;
@@ -9,12 +9,16 @@ import React from "react";
9
9
 
10
10
  import { useDoc } from "@docusaurus/plugin-content-docs/client";
11
11
  import { usePrismTheme } from "@docusaurus/theme-common";
12
+ import { translate } from "@docusaurus/Translate";
13
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
12
14
  import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock";
13
15
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
14
16
  import SchemaTabs from "@theme/SchemaTabs";
15
17
  import TabItem from "@theme/TabItem";
18
+ import { OPENAPI_RESPONSE } from "@theme/translationIds";
16
19
  import clsx from "clsx";
17
20
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
21
+ import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
18
22
 
19
23
  import { clearResponse, clearCode, clearHeaders } from "./slice";
20
24
 
@@ -40,7 +44,11 @@ function formatXml(xml: string) {
40
44
 
41
45
  function Response({ item }: { item: ApiItem }) {
42
46
  const metadata = useDoc();
47
+ const { siteConfig } = useDocusaurusContext();
48
+ const themeConfig = siteConfig.themeConfig as ThemeConfig;
43
49
  const hideSendButton = metadata.frontMatter.hide_send_button;
50
+ const proxy =
51
+ metadata.frontMatter.proxy ?? themeConfig.api?.proxy;
44
52
  const prismTheme = usePrismTheme();
45
53
  const code = useTypedSelector((state: any) => state.response.code);
46
54
  const headers = useTypedSelector((state: any) => state.response.headers);
@@ -55,7 +63,7 @@ function Response({ item }: { item: ApiItem }) {
55
63
  ? "openapi-response__dot--success"
56
64
  : "openapi-response__dot--info");
57
65
 
58
- if (!item.servers || hideSendButton) {
66
+ if ((!item.servers && !proxy) || hideSendButton) {
59
67
  return null;
60
68
  }
61
69
 
@@ -74,7 +82,9 @@ function Response({ item }: { item: ApiItem }) {
74
82
  return (
75
83
  <div className="openapi-explorer__response-container">
76
84
  <div className="openapi-explorer__response-title-container">
77
- <span className="openapi-explorer__response-title">Response</span>
85
+ <span className="openapi-explorer__response-title">
86
+ {translate({ id: OPENAPI_RESPONSE.TITLE, message: "Response" })}
87
+ </span>
78
88
  <span
79
89
  className="openapi-explorer__response-clear-btn"
80
90
  onClick={() => {
@@ -83,7 +93,7 @@ function Response({ item }: { item: ApiItem }) {
83
93
  dispatch(clearHeaders());
84
94
  }}
85
95
  >
86
- Clear
96
+ {translate({ id: OPENAPI_RESPONSE.CLEAR, message: "Clear" })}
87
97
  </span>
88
98
  </div>
89
99
  <div
@@ -117,14 +127,23 @@ function Response({ item }: { item: ApiItem }) {
117
127
  >
118
128
  {prettyResponse || (
119
129
  <p className="openapi-explorer__response-placeholder-message">
120
- Click the <code>Send API Request</code> button above and see
121
- the response here!
130
+ {translate({
131
+ id: OPENAPI_RESPONSE.PLACEHOLDER,
132
+ message:
133
+ "Click the <code>Send API Request</code> button above and see the response here!",
134
+ })}
122
135
  </p>
123
136
  )}
124
137
  </ApiCodeBlock>
125
138
  </TabItem>
126
139
  {/* @ts-ignore */}
127
- <TabItem label="Headers" value="headers">
140
+ <TabItem
141
+ label={translate({
142
+ id: OPENAPI_RESPONSE.HEADERS_TAB,
143
+ message: "Headers",
144
+ })}
145
+ value="headers"
146
+ >
128
147
  {/* @ts-ignore */}
129
148
  <ApiCodeBlock
130
149
  className="openapi-explorer__code-block openapi-response__status-headers"
@@ -145,8 +164,11 @@ function Response({ item }: { item: ApiItem }) {
145
164
  </div>
146
165
  ) : (
147
166
  <p className="openapi-explorer__response-placeholder-message">
148
- Click the <code>Send API Request</code> button above and see the
149
- response here!
167
+ {translate({
168
+ id: OPENAPI_RESPONSE.PLACEHOLDER,
169
+ message:
170
+ "Click the <code>Send API Request</code> button above and see the response here!",
171
+ })}
150
172
  </p>
151
173
  )}
152
174
  </div>
@@ -7,6 +7,9 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
11
+ import { OPENAPI_SECURITY_SCHEMES } from "@theme/translationIds";
12
+
10
13
  import Link from "@docusaurus/Link";
11
14
  import { useTypedSelector } from "@theme/ApiItem/hooks";
12
15
 
@@ -22,6 +25,41 @@ function SecuritySchemes(props: any) {
22
25
  }
23
26
 
24
27
  const selectedAuth = options[selected];
28
+
29
+ const keyTranslations: Record<string, { id: string; message: string }> = {
30
+ description: {
31
+ id: OPENAPI_SECURITY_SCHEMES.DESCRIPTION,
32
+ message: "description:",
33
+ },
34
+ scheme: {
35
+ id: OPENAPI_SECURITY_SCHEMES.SCHEME,
36
+ message: "scheme:",
37
+ },
38
+ bearerFormat: {
39
+ id: OPENAPI_SECURITY_SCHEMES.BEARER_FORMAT,
40
+ message: "bearerFormat:",
41
+ },
42
+ openIdConnectUrl: {
43
+ id: OPENAPI_SECURITY_SCHEMES.OPEN_ID_CONNECT_URL,
44
+ message: "openIdConnectUrl:",
45
+ },
46
+ };
47
+
48
+ const renderRest = (rest: Record<string, any>) =>
49
+ Object.keys(rest).map((k) => {
50
+ const translation = keyTranslations[k];
51
+ const label = translation
52
+ ? translate({ id: translation.id, message: translation.message })
53
+ : `${k}:`;
54
+ return (
55
+ <span key={k}>
56
+ <strong>{label} </strong>
57
+ {typeof rest[k] === "object"
58
+ ? JSON.stringify(rest[k], null, 2)
59
+ : String(rest[k])}
60
+ </span>
61
+ );
62
+ });
25
63
  return (
26
64
  <details className="openapi-security__details" open={false}>
27
65
  <summary className="openapi-security__summary-container">
@@ -48,31 +86,37 @@ function SecuritySchemes(props: any) {
48
86
  }}
49
87
  >
50
88
  <span>
51
- <strong>name:</strong>{" "}
89
+ <strong>
90
+ {translate({
91
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
92
+ message: "name:",
93
+ })}
94
+ </strong>{" "}
52
95
  <Link to={infoAuthPath}>{name ?? key}</Link>
53
96
  </span>
54
97
  <span>
55
- <strong>type: </strong>
98
+ <strong>
99
+ {translate({
100
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
101
+ message: "type:",
102
+ })}
103
+ </strong>{" "}
56
104
  {type}
57
105
  </span>
58
106
  {scopes && scopes.length > 0 && (
59
107
  <span>
60
- <strong>scopes: </strong>
108
+ <strong>
109
+ {translate({
110
+ id: OPENAPI_SECURITY_SCHEMES.SCOPES,
111
+ message: "scopes:",
112
+ })}
113
+ </strong>{" "}
61
114
  <code>
62
115
  {auth.scopes.length > 0 ? auth.scopes.toString() : "[]"}
63
116
  </code>
64
117
  </span>
65
118
  )}
66
- {Object.keys(rest).map((k, i) => {
67
- return (
68
- <span key={k}>
69
- <strong>{k}: </strong>
70
- {typeof rest[k] === "object"
71
- ? JSON.stringify(rest[k], null, 2)
72
- : String(rest[k])}
73
- </span>
74
- );
75
- })}
119
+ {renderRest(rest)}
76
120
  </pre>
77
121
  </React.Fragment>
78
122
  );
@@ -89,31 +133,37 @@ function SecuritySchemes(props: any) {
89
133
  }}
90
134
  >
91
135
  <span>
92
- <strong>name:</strong>{" "}
136
+ <strong>
137
+ {translate({
138
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
139
+ message: "name:",
140
+ })}
141
+ </strong>{" "}
93
142
  <Link to={infoAuthPath}>{name ?? key}</Link>
94
143
  </span>
95
144
  <span>
96
- <strong>type: </strong>
145
+ <strong>
146
+ {translate({
147
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
148
+ message: "type:",
149
+ })}
150
+ </strong>{" "}
97
151
  {type}
98
152
  </span>
99
153
  {scopes && scopes.length > 0 && (
100
154
  <span>
101
- <strong>scopes: </strong>
155
+ <strong>
156
+ {translate({
157
+ id: OPENAPI_SECURITY_SCHEMES.SCOPES,
158
+ message: "scopes:",
159
+ })}
160
+ </strong>{" "}
102
161
  <code>
103
162
  {auth.scopes.length > 0 ? auth.scopes.toString() : "[]"}
104
163
  </code>
105
164
  </span>
106
165
  )}
107
- {Object.keys(rest).map((k, i) => {
108
- return (
109
- <span key={k}>
110
- <strong>{k}: </strong>
111
- {typeof rest[k] === "object"
112
- ? JSON.stringify(rest[k], null, 2)
113
- : String(rest[k])}
114
- </span>
115
- );
116
- })}
166
+ {renderRest(rest)}
117
167
  </pre>
118
168
  </React.Fragment>
119
169
  );
@@ -128,15 +178,30 @@ function SecuritySchemes(props: any) {
128
178
  }}
129
179
  >
130
180
  <span>
131
- <strong>name:</strong>{" "}
181
+ <strong>
182
+ {translate({
183
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
184
+ message: "name:",
185
+ })}
186
+ </strong>{" "}
132
187
  <Link to={infoAuthPath}>{auth.name ?? auth.key}</Link>
133
188
  </span>
134
189
  <span>
135
- <strong>type: </strong>
190
+ <strong>
191
+ {translate({
192
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
193
+ message: "type:",
194
+ })}
195
+ </strong>{" "}
136
196
  {auth.type}
137
197
  </span>
138
198
  <span>
139
- <strong>in: </strong>
199
+ <strong>
200
+ {translate({
201
+ id: OPENAPI_SECURITY_SCHEMES.IN,
202
+ message: "in:",
203
+ })}
204
+ </strong>{" "}
140
205
  {auth.in}
141
206
  </span>
142
207
  </pre>
@@ -156,31 +221,37 @@ function SecuritySchemes(props: any) {
156
221
  }}
157
222
  >
158
223
  <span>
159
- <strong>name:</strong>{" "}
224
+ <strong>
225
+ {translate({
226
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
227
+ message: "name:",
228
+ })}
229
+ </strong>{" "}
160
230
  <Link to={infoAuthPath}>{name ?? key}</Link>
161
231
  </span>
162
232
  <span>
163
- <strong>type: </strong>
233
+ <strong>
234
+ {translate({
235
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
236
+ message: "type:",
237
+ })}
238
+ </strong>{" "}
164
239
  {type}
165
240
  </span>
166
241
  {scopes && scopes.length > 0 && (
167
242
  <span>
168
- <strong>scopes: </strong>
243
+ <strong>
244
+ {translate({
245
+ id: OPENAPI_SECURITY_SCHEMES.SCOPES,
246
+ message: "scopes:",
247
+ })}
248
+ </strong>{" "}
169
249
  <code>
170
250
  {auth.scopes.length > 0 ? auth.scopes.toString() : "[]"}
171
251
  </code>
172
252
  </span>
173
253
  )}
174
- {Object.keys(rest).map((k, i) => {
175
- return (
176
- <span key={k}>
177
- <strong>{k}: </strong>
178
- {typeof rest[k] === "object"
179
- ? JSON.stringify(rest[k], null, 2)
180
- : String(rest[k])}
181
- </span>
182
- );
183
- })}
254
+ {renderRest(rest)}
184
255
  </pre>
185
256
  </React.Fragment>
186
257
  );
@@ -198,35 +269,46 @@ function SecuritySchemes(props: any) {
198
269
  }}
199
270
  >
200
271
  <span>
201
- <strong>name:</strong>{" "}
272
+ <strong>
273
+ {translate({
274
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
275
+ message: "name:",
276
+ })}
277
+ </strong>{" "}
202
278
  <Link to={infoAuthPath}>{name ?? key}</Link>
203
279
  </span>
204
280
  <span>
205
- <strong>type: </strong>
281
+ <strong>
282
+ {translate({
283
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
284
+ message: "type:",
285
+ })}
286
+ </strong>{" "}
206
287
  {type}
207
288
  </span>
208
289
  {scopes && scopes.length > 0 && (
209
290
  <span>
210
- <strong>scopes: </strong>
291
+ <strong>
292
+ {translate({
293
+ id: OPENAPI_SECURITY_SCHEMES.SCOPES,
294
+ message: "scopes:",
295
+ })}
296
+ </strong>{" "}
211
297
  <code>
212
298
  {auth.scopes.length > 0 ? auth.scopes.toString() : "[]"}
213
299
  </code>
214
300
  </span>
215
301
  )}
216
- {Object.keys(rest).map((k, i) => {
217
- return (
218
- <span key={k}>
219
- <strong>{k}: </strong>
220
- {typeof rest[k] === "object"
221
- ? JSON.stringify(rest[k], null, 2)
222
- : String(rest[k])}
223
- </span>
224
- );
225
- })}
302
+ {renderRest(rest)}
226
303
  {flows && (
227
304
  <span>
228
305
  <code>
229
- <strong>flows: </strong>
306
+ <strong>
307
+ {translate({
308
+ id: OPENAPI_SECURITY_SCHEMES.FLOWS,
309
+ message: "flows:",
310
+ })}
311
+ </strong>{" "}
230
312
  {JSON.stringify(flows, null, 2)}
231
313
  </code>
232
314
  </span>
@@ -248,31 +330,37 @@ function SecuritySchemes(props: any) {
248
330
  }}
249
331
  >
250
332
  <span>
251
- <strong>name:</strong>{" "}
333
+ <strong>
334
+ {translate({
335
+ id: OPENAPI_SECURITY_SCHEMES.NAME,
336
+ message: "name:",
337
+ })}
338
+ </strong>{" "}
252
339
  <Link to={infoAuthPath}>{name ?? key}</Link>
253
340
  </span>
254
341
  <span>
255
- <strong>type: </strong>
342
+ <strong>
343
+ {translate({
344
+ id: OPENAPI_SECURITY_SCHEMES.TYPE,
345
+ message: "type:",
346
+ })}
347
+ </strong>{" "}
256
348
  {type}
257
349
  </span>
258
350
  {scopes && scopes.length > 0 && (
259
351
  <span>
260
- <strong>scopes: </strong>
352
+ <strong>
353
+ {translate({
354
+ id: OPENAPI_SECURITY_SCHEMES.SCOPES,
355
+ message: "scopes:",
356
+ })}
357
+ </strong>{" "}
261
358
  <code>
262
359
  {auth.scopes.length > 0 ? auth.scopes.toString() : "[]"}
263
360
  </code>
264
361
  </span>
265
362
  )}
266
- {Object.keys(rest).map((k, i) => {
267
- return (
268
- <span key={k}>
269
- <strong>{k}: </strong>
270
- {typeof rest[k] === "object"
271
- ? JSON.stringify(rest[k], null, 2)
272
- : String(rest[k])}
273
- </span>
274
- );
275
- })}
363
+ {renderRest(rest)}
276
364
  </pre>
277
365
  </React.Fragment>
278
366
  );
@@ -7,11 +7,13 @@
7
7
 
8
8
  import React, { useState } from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import FloatingButton from "@theme/ApiExplorer/FloatingButton";
11
12
  import FormItem from "@theme/ApiExplorer/FormItem";
12
13
  import FormSelect from "@theme/ApiExplorer/FormSelect";
13
14
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
14
15
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
16
+ import { OPENAPI_SERVER } from "@theme/translationIds";
15
17
 
16
18
  import { setServer, setServerVariable } from "./slice";
17
19
 
@@ -57,7 +59,10 @@ function Server() {
57
59
  }
58
60
  }
59
61
  return (
60
- <FloatingButton onClick={() => setIsEditing(true)} label="Edit">
62
+ <FloatingButton
63
+ onClick={() => setIsEditing(true)}
64
+ label={translate({ id: OPENAPI_SERVER.EDIT_BUTTON, message: "Edit" })}
65
+ >
61
66
  <FormItem>
62
67
  <span className="openapi-explorer__server-url" title={url}>
63
68
  {url}
@@ -68,11 +73,14 @@ function Server() {
68
73
  }
69
74
  return (
70
75
  <div className="openapi-explorer__server-container">
71
- <FloatingButton onClick={() => setIsEditing(false)} label="Hide">
76
+ <FloatingButton
77
+ onClick={() => setIsEditing(false)}
78
+ label={translate({ id: OPENAPI_SERVER.HIDE_BUTTON, message: "Hide" })}
79
+ >
72
80
  <FormItem>
73
81
  <FormSelect
74
82
  options={options.map((s: any) => s.url)}
75
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
83
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
76
84
  dispatch(
77
85
  setServer(
78
86
  JSON.stringify(
@@ -94,7 +102,7 @@ function Server() {
94
102
  <FormItem label={key}>
95
103
  <FormSelect
96
104
  options={value.variables[key].enum}
97
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
105
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
98
106
  dispatch(
99
107
  setServerVariable(
100
108
  JSON.stringify({ key, value: e.target.value })