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
@@ -0,0 +1,120 @@
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
+ import FormFileUpload from "@theme/ApiExplorer/FormFileUpload";
10
+ import FormSelect from "@theme/ApiExplorer/FormSelect";
11
+ import FormTextInput from "@theme/ApiExplorer/FormTextInput";
12
+ import LiveApp from "@theme/ApiExplorer/LiveEditor";
13
+ import { useTypedDispatch } from "@theme/ApiItem/hooks";
14
+ import { SchemaObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
15
+ import { clearFormBodyKey, setFileFormBody, setStringFormBody } from "../slice";
16
+ import FileArrayFormBodyItem from "../FileArrayFormBodyItem";
17
+
18
+ interface FormBodyItemProps {
19
+ schemaObject: SchemaObject;
20
+ id: string;
21
+ schema: SchemaObject;
22
+ }
23
+
24
+ export default function FormBodyItem({
25
+ schemaObject,
26
+ id,
27
+ schema,
28
+ }: FormBodyItemProps): React.JSX.Element {
29
+ const dispatch = useTypedDispatch();
30
+
31
+ if (
32
+ schemaObject.type === "array" &&
33
+ schemaObject.items?.format === "binary"
34
+ ) {
35
+ return (
36
+ <FileArrayFormBodyItem id={id} description={schemaObject.description} />
37
+ );
38
+ }
39
+
40
+ if (schemaObject.format === "binary") {
41
+ return (
42
+ <FormFileUpload
43
+ placeholder={schemaObject.description || id}
44
+ onChange={(file: any) => {
45
+ if (file === undefined) {
46
+ dispatch(clearFormBodyKey(id));
47
+ return;
48
+ }
49
+ dispatch(
50
+ setFileFormBody({
51
+ key: id,
52
+ value: {
53
+ src: `/path/to/${file.name}`,
54
+ content: file,
55
+ },
56
+ })
57
+ );
58
+ }}
59
+ />
60
+ );
61
+ }
62
+
63
+ if (
64
+ schemaObject.type === "object" &&
65
+ (schemaObject.example || schemaObject.examples)
66
+ ) {
67
+ const objectExample = JSON.stringify(
68
+ schemaObject.example ?? schemaObject.examples[0],
69
+ null,
70
+ 2
71
+ );
72
+
73
+ return (
74
+ <LiveApp
75
+ action={(code: string) =>
76
+ dispatch(setStringFormBody({ key: id, value: code }))
77
+ }
78
+ >
79
+ {objectExample}
80
+ </LiveApp>
81
+ );
82
+ }
83
+
84
+ if (
85
+ schemaObject.enum &&
86
+ schemaObject.enum.every((value) => typeof value === "string")
87
+ ) {
88
+ return (
89
+ <FormSelect
90
+ options={["---", ...schemaObject.enum]}
91
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
92
+ const val = e.target.value;
93
+ if (val === "---") {
94
+ dispatch(clearFormBodyKey(id));
95
+ } else {
96
+ dispatch(
97
+ setStringFormBody({
98
+ key: id,
99
+ value: val,
100
+ })
101
+ );
102
+ }
103
+ }}
104
+ />
105
+ );
106
+ }
107
+ // TODO: support all the other types.
108
+ return (
109
+ <FormTextInput
110
+ paramName={id}
111
+ isRequired={
112
+ Array.isArray(schema.required) && schema.required.includes(id)
113
+ }
114
+ placeholder={schemaObject.description || id}
115
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
116
+ dispatch(setStringFormBody({ key: id, value: e.target.value }));
117
+ }}
118
+ />
119
+ );
120
+ }
@@ -7,26 +7,22 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
11
+
10
12
  import json2xml from "@theme/ApiExplorer/Body/json2xml";
11
13
  import FormFileUpload from "@theme/ApiExplorer/FormFileUpload";
12
14
  import FormItem from "@theme/ApiExplorer/FormItem";
13
- import FormSelect from "@theme/ApiExplorer/FormSelect";
14
- import FormTextInput from "@theme/ApiExplorer/FormTextInput";
15
15
  import LiveApp from "@theme/ApiExplorer/LiveEditor";
16
16
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
17
17
  import Markdown from "@theme/Markdown";
18
18
  import SchemaTabs from "@theme/SchemaTabs";
19
19
  import TabItem from "@theme/TabItem";
20
+ import { OPENAPI_BODY, OPENAPI_REQUEST } from "@theme/translationIds";
20
21
  import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
21
22
  import format from "xml-formatter";
22
23
 
23
- import {
24
- clearFormBodyKey,
25
- clearRawBody,
26
- setFileFormBody,
27
- setFileRawBody,
28
- setStringFormBody,
29
- } from "./slice";
24
+ import { clearRawBody, setFileRawBody, setStringRawBody } from "./slice";
25
+ import FormBodyItem from "./FormBodyItem";
30
26
 
31
27
  export interface Props {
32
28
  jsonRequestBodyExample: string;
@@ -93,12 +89,17 @@ function Body({
93
89
  const schema = requestBodyMetadata?.content?.[contentType]?.schema;
94
90
  const example = requestBodyMetadata?.content?.[contentType]?.example;
95
91
  const examples = requestBodyMetadata?.content?.[contentType]?.examples;
92
+ // OpenAPI 3.1 / JSON Schema: schema.examples is an array of example values
93
+ const schemaExamples = schema?.examples as any[] | undefined;
96
94
 
97
95
  if (schema?.format === "binary") {
98
96
  return (
99
97
  <FormItem>
100
98
  <FormFileUpload
101
- placeholder={schema.description || "Body"}
99
+ placeholder={
100
+ schema.description ||
101
+ translate({ id: OPENAPI_REQUEST.BODY_TITLE, message: "Body" })
102
+ }
102
103
  onChange={(file: any) => {
103
104
  if (file === undefined) {
104
105
  dispatch(clearRawBody());
@@ -122,96 +123,23 @@ function Body({
122
123
  ) {
123
124
  return (
124
125
  <FormItem className="openapi-explorer__form-item-body-container">
125
- <div>
126
- {Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
127
- if (val.format === "binary") {
128
- return (
129
- <FormItem
130
- key={key}
131
- label={key}
132
- required={
133
- Array.isArray(schema.required) &&
134
- schema.required.includes(key)
135
- }
136
- >
137
- <FormFileUpload
138
- placeholder={val.description || key}
139
- onChange={(file: any) => {
140
- if (file === undefined) {
141
- dispatch(clearFormBodyKey(key));
142
- return;
143
- }
144
- dispatch(
145
- setFileFormBody({
146
- key: key,
147
- value: {
148
- src: `/path/to/${file.name}`,
149
- content: file,
150
- },
151
- })
152
- );
153
- }}
154
- />
155
- </FormItem>
156
- );
157
- }
158
-
159
- if (val.enum) {
160
- return (
161
- <FormItem
162
- key={key}
163
- label={key}
164
- required={
165
- Array.isArray(schema.required) &&
166
- schema.required.includes(key)
167
- }
168
- >
169
- <FormSelect
170
- options={["---", ...val.enum]}
171
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
172
- const val = e.target.value;
173
- if (val === "---") {
174
- dispatch(clearFormBodyKey(key));
175
- } else {
176
- dispatch(
177
- setStringFormBody({
178
- key: key,
179
- value: val,
180
- })
181
- );
182
- }
183
- }}
184
- />
185
- </FormItem>
186
- );
187
- }
188
- // TODO: support all the other types.
189
- return (
190
- <FormItem
191
- key={key}
192
- label={key}
193
- required={
194
- Array.isArray(schema.required) &&
195
- schema.required.includes(key)
196
- }
197
- >
198
- <FormTextInput
199
- paramName={key}
200
- isRequired={
201
- Array.isArray(schema.required) &&
202
- schema.required.includes(key)
203
- }
204
- placeholder={val.description || key}
205
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
206
- dispatch(
207
- setStringFormBody({ key: key, value: e.target.value })
208
- );
209
- }}
210
- />
211
- </FormItem>
212
- );
213
- })}
214
- </div>
126
+ {Object.entries(schema.properties ?? {}).map(([key, val]: any) => {
127
+ return (
128
+ <FormItem
129
+ key={key}
130
+ label={key}
131
+ required={
132
+ Array.isArray(schema.required) && schema.required.includes(key)
133
+ }
134
+ >
135
+ <FormBodyItem
136
+ schemaObject={val}
137
+ id={key}
138
+ schema={schema}
139
+ ></FormBodyItem>
140
+ </FormItem>
141
+ );
142
+ })}
215
143
  </FormItem>
216
144
  );
217
145
  }
@@ -248,6 +176,17 @@ function Body({
248
176
  });
249
177
  }
250
178
  }
179
+ // OpenAPI 3.1: schema.examples is an array of example values
180
+ if (schemaExamples && Array.isArray(schemaExamples)) {
181
+ schemaExamples.forEach((schemaExample, index) => {
182
+ const body = JSON.stringify(schemaExample, null, 2);
183
+ examplesBodies.push({
184
+ label: `Example ${index + 1}`,
185
+ body,
186
+ summary: undefined,
187
+ });
188
+ });
189
+ }
251
190
  language = "json";
252
191
  }
253
192
 
@@ -293,6 +232,26 @@ function Body({
293
232
  });
294
233
  }
295
234
  }
235
+ // OpenAPI 3.1: schema.examples is an array of example values
236
+ if (schemaExamples && Array.isArray(schemaExamples)) {
237
+ schemaExamples.forEach((schemaExample, index) => {
238
+ let formattedXmlBody;
239
+ try {
240
+ formattedXmlBody = format(json2xml(schemaExample, ""), {
241
+ indentation: " ",
242
+ lineSeparator: "\n",
243
+ collapseContent: true,
244
+ });
245
+ } catch {
246
+ formattedXmlBody = json2xml(schemaExample);
247
+ }
248
+ examplesBodies.push({
249
+ label: `Example ${index + 1}`,
250
+ body: formattedXmlBody,
251
+ summary: undefined,
252
+ });
253
+ });
254
+ }
296
255
  language = "xml";
297
256
  }
298
257
 
@@ -302,11 +261,18 @@ function Body({
302
261
  <SchemaTabs className="openapi-tabs__schema" lazy>
303
262
  {/* @ts-ignore */}
304
263
  <TabItem
305
- label="Example (from schema)"
264
+ label={translate({
265
+ id: OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
266
+ message: "Example (from schema)",
267
+ })}
306
268
  value="Example (from schema)"
307
269
  default
308
270
  >
309
- <LiveApp action={dispatch} language={language} required={required}>
271
+ <LiveApp
272
+ action={(code: string) => dispatch(setStringRawBody(code))}
273
+ language={language}
274
+ required={required}
275
+ >
310
276
  {defaultBody}
311
277
  </LiveApp>
312
278
  </TabItem>
@@ -315,7 +281,7 @@ function Body({
315
281
  {example.summary && <Markdown>{example.summary}</Markdown>}
316
282
  {exampleBody && (
317
283
  <LiveApp
318
- action={dispatch}
284
+ action={(code: string) => dispatch(setStringRawBody(code))}
319
285
  language={language}
320
286
  required={required}
321
287
  >
@@ -334,11 +300,18 @@ function Body({
334
300
  <SchemaTabs className="openapi-tabs__schema" lazy>
335
301
  {/* @ts-ignore */}
336
302
  <TabItem
337
- label="Example (from schema)"
303
+ label={translate({
304
+ id: OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
305
+ message: "Example (from schema)",
306
+ })}
338
307
  value="Example (from schema)"
339
308
  default
340
309
  >
341
- <LiveApp action={dispatch} language={language} required={required}>
310
+ <LiveApp
311
+ action={(code: string) => dispatch(setStringRawBody(code))}
312
+ language={language}
313
+ required={required}
314
+ >
342
315
  {defaultBody}
343
316
  </LiveApp>
344
317
  </TabItem>
@@ -352,7 +325,10 @@ function Body({
352
325
  >
353
326
  {example.summary && <Markdown>{example.summary}</Markdown>}
354
327
  {example.body && (
355
- <LiveApp action={dispatch} language={language}>
328
+ <LiveApp
329
+ action={(code: string) => dispatch(setStringRawBody(code))}
330
+ language={language}
331
+ >
356
332
  {example.body}
357
333
  </LiveApp>
358
334
  )}
@@ -366,7 +342,11 @@ function Body({
366
342
 
367
343
  return (
368
344
  <FormItem>
369
- <LiveApp action={dispatch} language={language} required={required}>
345
+ <LiveApp
346
+ action={(code: string) => dispatch(setStringRawBody(code))}
347
+ language={language}
348
+ required={required}
349
+ >
370
350
  {defaultBody}
371
351
  </LiveApp>
372
352
  </FormItem>
@@ -0,0 +1,8 @@
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
+ export default function json2xml(input: any, indent?: any): any;
@@ -15,12 +15,24 @@ export interface FileContent {
15
15
  };
16
16
  }
17
17
 
18
+ export interface FileArrayContent {
19
+ type: "file[]";
20
+ value: {
21
+ src: string;
22
+ content: Blob;
23
+ }[];
24
+ }
25
+
18
26
  export interface StringContent {
19
27
  type: "string";
20
28
  value?: string;
21
29
  }
22
30
 
23
- export type Content = FileContent | StringContent | undefined;
31
+ export type Content =
32
+ | FileContent
33
+ | FileArrayContent
34
+ | StringContent
35
+ | undefined;
24
36
 
25
37
  export interface FormBody {
26
38
  type: "form";
@@ -118,6 +130,32 @@ export const slice = createSlice({
118
130
  };
119
131
  return state;
120
132
  },
133
+ setFileArrayFormBody: (
134
+ state,
135
+ action: PayloadAction<{
136
+ key: string;
137
+ value: FileArrayContent["value"];
138
+ }>
139
+ ) => {
140
+ if (state?.type !== "form") {
141
+ return {
142
+ type: "form",
143
+ content: {
144
+ [action.payload.key]: {
145
+ type: "file[]",
146
+ value: action.payload.value,
147
+ },
148
+ },
149
+ };
150
+ }
151
+
152
+ state.content[action.payload.key] = {
153
+ type: "file[]",
154
+ value: action.payload.value,
155
+ };
156
+
157
+ return state;
158
+ },
121
159
  },
122
160
  });
123
161
 
@@ -128,6 +166,7 @@ export const {
128
166
  clearFormBodyKey,
129
167
  setStringFormBody,
130
168
  setFileFormBody,
169
+ setFileArrayFormBody,
131
170
  } = slice.actions;
132
171
 
133
172
  export default slice.reducer;
@@ -29,6 +29,7 @@ export const languageSet: Language[] = generateLanguageSet();
29
29
  export interface Props {
30
30
  postman: sdk.Request;
31
31
  codeSamples: CodeSample[];
32
+ maskCredentials?: boolean;
32
33
  }
33
34
 
34
35
  function CodeTab({ children, hidden, className }: any): React.JSX.Element {
@@ -39,7 +40,11 @@ function CodeTab({ children, hidden, className }: any): React.JSX.Element {
39
40
  );
40
41
  }
41
42
 
42
- function CodeSnippets({ postman, codeSamples }: Props) {
43
+ function CodeSnippets({
44
+ postman,
45
+ codeSamples,
46
+ maskCredentials: propMaskCredentials,
47
+ }: Props) {
43
48
  const { siteConfig } = useDocusaurusContext();
44
49
 
45
50
  const contentType = useTypedSelector((state: any) => state.contentType.value);
@@ -53,33 +58,42 @@ function CodeSnippets({ postman, codeSamples }: Props) {
53
58
  const headerParams = useTypedSelector((state: any) => state.params.header);
54
59
 
55
60
  const auth = useTypedSelector((state: any) => state.auth);
56
- const clonedAuth = cloneDeep(auth);
57
- let placeholder: string;
58
61
 
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
- }
62
+ // Check if credential masking is enabled (default: true)
63
+ const maskCredentials = propMaskCredentials ?? true;
72
64
 
73
- return obj;
74
- }
65
+ // Clone Auth if maskCredentials is not false
66
+ const cleanedAuth = maskCredentials
67
+ ? (() => {
68
+ const clonedAuth = cloneDeep(auth);
69
+ let placeholder: string;
75
70
 
76
- // scrub credentials from code snippets
77
- const cleanedAuth = {
78
- ...clonedAuth,
79
- data: cleanCredentials(clonedAuth.data),
80
- };
71
+ function cleanCredentials(obj: any) {
72
+ for (const key in obj) {
73
+ if (typeof obj[key] === "object" && obj[key] !== null) {
74
+ // use name as placeholder if exists
75
+ const comboAuthId = Object.keys(obj).join(" and ");
76
+ const authOptions =
77
+ clonedAuth?.options?.[key] ??
78
+ clonedAuth?.options?.[comboAuthId];
79
+ placeholder = authOptions?.find((opt: any) => opt.key === key)?.name;
80
+ obj[key] = cleanCredentials(obj[key]);
81
+ } else {
82
+ obj[key] = `<${placeholder ?? key}>`;
83
+ }
84
+ }
81
85
 
82
- // Create a Postman request object using cleanedAuth
86
+ return obj;
87
+ }
88
+
89
+ return {
90
+ ...clonedAuth,
91
+ data: cleanCredentials(clonedAuth.data),
92
+ };
93
+ })()
94
+ : auth;
95
+
96
+ // Create a Postman request object using cleanedAuth or original auth
83
97
  const cleanedPostmanRequest = buildPostmanRequest(postman, {
84
98
  queryParams,
85
99
  pathParams,
@@ -127,9 +141,9 @@ function CodeSnippets({ postman, codeSamples }: Props) {
127
141
  return defaultLang[0] ?? mergedLangs[0];
128
142
  });
129
143
  const [codeText, setCodeText] = useState<string>("");
130
- const [codeSampleCodeText, setCodeSampleCodeText] = useState<
131
- string | (() => string)
132
- >(() => getCodeSampleSourceFromLanguage(language));
144
+ const [codeSampleCodeText, setCodeSampleCodeText] = useState<string>(() =>
145
+ getCodeSampleSourceFromLanguage(language)
146
+ );
133
147
 
134
148
  useEffect(() => {
135
149
  if (language && !!language.sample) {
@@ -259,7 +273,7 @@ function CodeSnippets({ postman, codeSamples }: Props) {
259
273
  setSelectedSample: setSelectedSample,
260
274
  }}
261
275
  includeSample={true}
262
- currentLanguage={lang.language}
276
+ currentLanguage={lang}
263
277
  defaultValue={selectedSample}
264
278
  languageSet={mergedLangs}
265
279
  lazy
@@ -300,7 +314,7 @@ function CodeSnippets({ postman, codeSamples }: Props) {
300
314
  setSelectedVariant: setSelectedVariant,
301
315
  }}
302
316
  includeVariant={true}
303
- currentLanguage={lang.language}
317
+ currentLanguage={lang}
304
318
  defaultValue={selectedVariant}
305
319
  languageSet={mergedLangs}
306
320
  lazy
@@ -197,7 +197,11 @@ body[class="ReactModal__Body--open"] {
197
197
  }
198
198
 
199
199
  &.active {
200
- box-shadow: 0 0 0 3px var(--openapi-code-tab-shadow-color-curl);
200
+ box-shadow: 0 0 0 3px
201
+ var(
202
+ --openapi-code-tab-shadow-color-curl,
203
+ var(--openapi-code-tab-shadow-color-bash)
204
+ );
201
205
  border-color: var(--ifm-color-danger);
202
206
  }
203
207
  }
@@ -15,16 +15,17 @@ import {
15
15
  } from "@docusaurus/theme-common/internal";
16
16
  import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
17
17
  import useIsBrowser from "@docusaurus/useIsBrowser";
18
- import { Language } from "@theme/ApiExplorer/CodeSnippets";
19
18
  import clsx from "clsx";
20
19
 
20
+ import { Language } from "../CodeSnippets/code-snippets-types";
21
+
21
22
  export interface Props {
22
23
  action: {
23
24
  [key: string]: React.Dispatch<any>;
24
25
  };
25
- currentLanguage: Language;
26
+ currentLanguage?: Language;
26
27
  languageSet: Language[];
27
- includeVariant: boolean;
28
+ includeVariant?: boolean;
28
29
  }
29
30
 
30
31
  export interface CodeTabsProps extends Props, TabProps {
@@ -94,13 +95,13 @@ function TabList({
94
95
  let newLanguage: Language;
95
96
  if (currentLanguage && includeVariant) {
96
97
  newLanguage = languageSet.filter(
97
- (lang: Language) => lang.language === currentLanguage
98
+ (lang: Language) => lang.language === currentLanguage.language
98
99
  )[0];
99
100
  newLanguage.variant = newTabValue;
100
101
  action.setSelectedVariant(newTabValue.toLowerCase());
101
102
  } else if (currentLanguage && includeSample) {
102
103
  newLanguage = languageSet.filter(
103
- (lang: Language) => lang.language === currentLanguage
104
+ (lang: Language) => lang.language === currentLanguage.language
104
105
  )[0];
105
106
  newLanguage.sample = newTabValue;
106
107
  action.setSelectedSample(newTabValue);
@@ -27,7 +27,7 @@ function ContentType() {
27
27
  <FormSelect
28
28
  value={value}
29
29
  options={options}
30
- onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
30
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
31
31
  dispatch(setContentType(e.target.value))
32
32
  }
33
33
  />
@@ -7,7 +7,9 @@
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";
12
+ import { OPENAPI_FORM_FILE_UPLOAD } from "@theme/translationIds";
11
13
  import MagicDropzone from "react-magic-dropzone";
12
14
 
13
15
  type PreviewFile = { preview: string } & File;
@@ -102,7 +104,10 @@ function FormFileUpload({ placeholder, onChange }: Props) {
102
104
  setAndNotifyFile(undefined);
103
105
  }}
104
106
  >
105
- Clear
107
+ {translate({
108
+ id: OPENAPI_FORM_FILE_UPLOAD.CLEAR_BUTTON,
109
+ message: "Clear",
110
+ })}
106
111
  </button>
107
112
  <RenderPreview file={file} />
108
113
  </>