docusaurus-theme-openapi-docs 4.5.1 → 4.7.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 (133) hide show
  1. package/lib/markdown/schema.js +14 -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 +322 -193
  11. package/lib/theme/ApiExplorer/Body/resolveSchemaWithSelections.d.ts +13 -0
  12. package/lib/theme/ApiExplorer/Body/resolveSchemaWithSelections.js +133 -0
  13. package/lib/theme/ApiExplorer/Body/slice.d.ts +1056 -11
  14. package/lib/theme/ApiExplorer/Body/slice.js +22 -2
  15. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
  16. package/lib/theme/ApiExplorer/CodeSnippets/index.js +37 -26
  17. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  18. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +3 -3
  19. package/lib/theme/ApiExplorer/CodeTabs/index.js +2 -2
  20. package/lib/theme/ApiExplorer/ContentType/slice.d.ts +5 -2
  21. package/lib/theme/ApiExplorer/FormFileUpload/index.js +6 -1
  22. package/lib/theme/ApiExplorer/FormItem/index.js +6 -1
  23. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +2 -0
  24. package/lib/theme/ApiExplorer/FormTextInput/index.js +8 -1
  25. package/lib/theme/ApiExplorer/LiveEditor/index.js +11 -4
  26. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +15 -5
  27. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +11 -3
  28. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +12 -4
  29. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +11 -2
  30. package/lib/theme/ApiExplorer/ParamOptions/index.js +11 -1
  31. package/lib/theme/ApiExplorer/ParamOptions/slice.d.ts +0 -4
  32. package/lib/theme/ApiExplorer/ParamOptions/slice.js +4 -4
  33. package/lib/theme/ApiExplorer/Request/index.js +110 -17
  34. package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +7 -1
  35. package/lib/theme/ApiExplorer/Request/makeRequest.js +94 -24
  36. package/lib/theme/ApiExplorer/Response/index.js +34 -14
  37. package/lib/theme/ApiExplorer/Response/slice.d.ts +31 -7
  38. package/lib/theme/ApiExplorer/SchemaSelection/index.d.ts +2 -0
  39. package/lib/theme/ApiExplorer/SchemaSelection/index.js +36 -0
  40. package/lib/theme/ApiExplorer/SchemaSelection/slice.d.ts +37 -0
  41. package/lib/theme/ApiExplorer/SchemaSelection/slice.js +39 -0
  42. package/lib/theme/ApiExplorer/SecuritySchemes/index.js +208 -69
  43. package/lib/theme/ApiExplorer/Server/index.js +16 -2
  44. package/lib/theme/ApiExplorer/Server/slice.d.ts +49 -3
  45. package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -57
  46. package/lib/theme/ApiExplorer/index.js +4 -0
  47. package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +21 -0
  48. package/lib/theme/ApiExplorer/{persistanceMiddleware.js → persistenceMiddleware.js} +16 -9
  49. package/lib/theme/ApiExplorer/storage-utils.d.ts +2 -2
  50. package/lib/theme/ApiExplorer/storage-utils.js +3 -3
  51. package/lib/theme/ApiItem/Layout/index.d.ts +1 -1
  52. package/lib/theme/ApiItem/hooks.d.ts +10 -9
  53. package/lib/theme/ApiItem/index.js +13 -8
  54. package/lib/theme/ApiItem/store.d.ts +61 -43
  55. package/lib/theme/ApiItem/store.js +6 -2
  56. package/lib/theme/ApiTabs/index.js +6 -1
  57. package/lib/theme/Example/_Example.scss +11 -0
  58. package/lib/theme/Example/index.d.ts +24 -0
  59. package/lib/theme/Example/index.js +170 -0
  60. package/lib/theme/ParamsDetails/index.js +9 -1
  61. package/lib/theme/ParamsItem/index.d.ts +1 -1
  62. package/lib/theme/ParamsItem/index.js +43 -74
  63. package/lib/theme/RequestSchema/index.js +68 -48
  64. package/lib/theme/ResponseExamples/index.js +23 -3
  65. package/lib/theme/ResponseSchema/index.js +97 -82
  66. package/lib/theme/Schema/index.d.ts +6 -0
  67. package/lib/theme/Schema/index.js +240 -31
  68. package/lib/theme/SchemaItem/index.js +64 -36
  69. package/lib/theme/SchemaTabs/index.d.ts +8 -1
  70. package/lib/theme/SchemaTabs/index.js +14 -2
  71. package/lib/theme/StatusCodes/index.d.ts +1 -1
  72. package/lib/theme/StatusCodes/index.js +11 -2
  73. package/lib/theme/styles.scss +15 -0
  74. package/lib/theme/translationIds.d.ts +90 -0
  75. package/lib/theme/translationIds.js +114 -0
  76. package/package.json +28 -28
  77. package/src/markdown/schema.ts +17 -1
  78. package/src/theme/ApiExplorer/Authorization/index.tsx +51 -10
  79. package/src/theme/ApiExplorer/Authorization/slice.ts +1 -1
  80. package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +77 -0
  81. package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +120 -0
  82. package/src/theme/ApiExplorer/Body/index.tsx +262 -198
  83. package/{lib/types.js → src/theme/ApiExplorer/Body/json2xml.d.ts} +2 -2
  84. package/src/theme/ApiExplorer/Body/resolveSchemaWithSelections.ts +155 -0
  85. package/src/theme/ApiExplorer/Body/slice.ts +40 -1
  86. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +43 -29
  87. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  88. package/src/theme/ApiExplorer/CodeTabs/index.tsx +6 -5
  89. package/src/theme/ApiExplorer/ContentType/index.tsx +1 -1
  90. package/src/theme/ApiExplorer/FormFileUpload/index.tsx +6 -1
  91. package/src/theme/ApiExplorer/FormItem/index.tsx +8 -1
  92. package/src/theme/ApiExplorer/FormTextInput/index.tsx +10 -1
  93. package/src/theme/ApiExplorer/LiveEditor/index.tsx +11 -4
  94. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +16 -6
  95. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -4
  96. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +12 -4
  97. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +12 -3
  98. package/src/theme/ApiExplorer/ParamOptions/index.tsx +10 -2
  99. package/src/theme/ApiExplorer/ParamOptions/slice.ts +1 -1
  100. package/src/theme/ApiExplorer/Request/index.tsx +108 -17
  101. package/src/theme/ApiExplorer/Request/makeRequest.ts +106 -25
  102. package/src/theme/ApiExplorer/Response/index.tsx +30 -8
  103. package/src/theme/ApiExplorer/SchemaSelection/index.ts +13 -0
  104. package/src/theme/ApiExplorer/SchemaSelection/slice.ts +46 -0
  105. package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +157 -69
  106. package/src/theme/ApiExplorer/Server/index.tsx +12 -4
  107. package/src/theme/ApiExplorer/buildPostmanRequest.ts +47 -63
  108. package/src/theme/ApiExplorer/index.tsx +5 -0
  109. package/src/theme/ApiExplorer/{persistanceMiddleware.ts → persistenceMiddleware.ts} +23 -13
  110. package/src/theme/ApiExplorer/storage-utils.ts +4 -4
  111. package/src/theme/ApiItem/Layout/index.tsx +1 -1
  112. package/src/theme/ApiItem/index.tsx +13 -7
  113. package/src/theme/ApiItem/store.ts +2 -0
  114. package/src/theme/ApiTabs/index.tsx +6 -1
  115. package/src/theme/Example/_Example.scss +11 -0
  116. package/src/theme/Example/index.tsx +168 -0
  117. package/src/theme/Markdown/index.d.ts +8 -0
  118. package/src/theme/ParamsDetails/index.tsx +10 -1
  119. package/src/theme/ParamsItem/index.tsx +38 -54
  120. package/src/theme/RequestSchema/index.tsx +60 -35
  121. package/src/theme/ResponseExamples/index.tsx +23 -3
  122. package/src/theme/ResponseSchema/index.tsx +73 -61
  123. package/src/theme/Schema/index.tsx +307 -55
  124. package/src/theme/SchemaItem/index.tsx +51 -33
  125. package/src/theme/SchemaTabs/index.tsx +19 -5
  126. package/src/theme/StatusCodes/index.tsx +13 -3
  127. package/src/theme/styles.scss +15 -0
  128. package/src/theme/translationIds.ts +111 -0
  129. package/src/theme-openapi.d.ts +7 -275
  130. package/src/{types.ts → types.d.ts} +9 -1
  131. package/tsconfig.tsbuildinfo +1 -1
  132. package/lib/theme/ApiExplorer/persistanceMiddleware.d.ts +0 -3
  133. package/lib/types.d.ts +0 -46
@@ -0,0 +1,155 @@
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 { SchemaObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
9
+ import merge from "lodash/merge";
10
+
11
+ export interface SchemaSelections {
12
+ [schemaPath: string]: number;
13
+ }
14
+
15
+ /**
16
+ * Resolves a schema by replacing anyOf/oneOf with the selected option based on user selections.
17
+ *
18
+ * @param schema - The original schema object
19
+ * @param selections - Map of schema paths to selected indices
20
+ * @param basePath - The base path for this schema (used for looking up selections)
21
+ * @returns A new schema with anyOf/oneOf resolved to selected options
22
+ */
23
+ export function resolveSchemaWithSelections(
24
+ schema: SchemaObject | undefined,
25
+ selections: SchemaSelections,
26
+ basePath: string = "requestBody"
27
+ ): SchemaObject | undefined {
28
+ if (!schema) {
29
+ return schema;
30
+ }
31
+
32
+ // Deep clone to avoid mutating the original schema
33
+ const schemaCopy = JSON.parse(JSON.stringify(schema)) as SchemaObject;
34
+
35
+ return resolveSchemaRecursive(schemaCopy, selections, basePath);
36
+ }
37
+
38
+ function resolveSchemaRecursive(
39
+ schema: SchemaObject,
40
+ selections: SchemaSelections,
41
+ currentPath: string
42
+ ): SchemaObject {
43
+ // Handle oneOf
44
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
45
+ const selectedIndex = selections[currentPath] ?? 0;
46
+ const selectedSchema = schema.oneOf[selectedIndex] as SchemaObject;
47
+
48
+ if (selectedSchema) {
49
+ // If there are shared properties, merge them with the selected schema
50
+ if (schema.properties) {
51
+ const mergedSchema = merge({}, schema, selectedSchema);
52
+ delete mergedSchema.oneOf;
53
+
54
+ // Continue resolving nested schemas in the merged result
55
+ return resolveSchemaRecursive(
56
+ mergedSchema,
57
+ selections,
58
+ `${currentPath}.${selectedIndex}`
59
+ );
60
+ }
61
+
62
+ // No shared properties, just use the selected schema
63
+ // Continue resolving in case there are nested anyOf/oneOf
64
+ return resolveSchemaRecursive(
65
+ selectedSchema,
66
+ selections,
67
+ `${currentPath}.${selectedIndex}`
68
+ );
69
+ }
70
+ }
71
+
72
+ // Handle anyOf
73
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
74
+ const selectedIndex = selections[currentPath] ?? 0;
75
+ const selectedSchema = schema.anyOf[selectedIndex] as SchemaObject;
76
+
77
+ if (selectedSchema) {
78
+ // If there are shared properties, merge them with the selected schema
79
+ if (schema.properties) {
80
+ const mergedSchema = merge({}, schema, selectedSchema);
81
+ delete mergedSchema.anyOf;
82
+
83
+ // Continue resolving nested schemas in the merged result
84
+ return resolveSchemaRecursive(
85
+ mergedSchema,
86
+ selections,
87
+ `${currentPath}.${selectedIndex}`
88
+ );
89
+ }
90
+
91
+ // No shared properties, just use the selected schema
92
+ // Continue resolving in case there are nested anyOf/oneOf
93
+ return resolveSchemaRecursive(
94
+ selectedSchema,
95
+ selections,
96
+ `${currentPath}.${selectedIndex}`
97
+ );
98
+ }
99
+ }
100
+
101
+ // Handle allOf - merge all schemas and continue resolving
102
+ if (schema.allOf && Array.isArray(schema.allOf)) {
103
+ // Process each allOf item, resolving any anyOf/oneOf within them
104
+ const resolvedItems = schema.allOf.map((item, index) => {
105
+ return resolveSchemaRecursive(
106
+ item as SchemaObject,
107
+ selections,
108
+ `${currentPath}.allOf.${index}`
109
+ );
110
+ });
111
+
112
+ // Merge all resolved items
113
+ const mergedSchema = resolvedItems.reduce(
114
+ (acc, item) => merge(acc, item),
115
+ {} as SchemaObject
116
+ );
117
+
118
+ // Preserve any top-level properties from the original schema
119
+ if (schema.properties) {
120
+ mergedSchema.properties = merge(
121
+ {},
122
+ mergedSchema.properties,
123
+ schema.properties
124
+ );
125
+ }
126
+
127
+ return mergedSchema;
128
+ }
129
+
130
+ // Handle object properties recursively
131
+ if (schema.properties) {
132
+ const resolvedProperties: { [key: string]: SchemaObject } = {};
133
+
134
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
135
+ resolvedProperties[propName] = resolveSchemaRecursive(
136
+ propSchema as SchemaObject,
137
+ selections,
138
+ `${currentPath}.${propName}`
139
+ );
140
+ }
141
+
142
+ schema.properties = resolvedProperties;
143
+ }
144
+
145
+ // Handle array items recursively
146
+ if (schema.items) {
147
+ schema.items = resolveSchemaRecursive(
148
+ schema.items as SchemaObject,
149
+ selections,
150
+ `${currentPath}.items`
151
+ );
152
+ }
153
+
154
+ return schema;
155
+ }
@@ -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
  </>
@@ -7,6 +7,9 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
11
+ import { OPENAPI_SCHEMA_ITEM } from "@theme/translationIds";
12
+
10
13
  import clsx from "clsx";
11
14
 
12
15
  export interface Props {
@@ -24,7 +27,11 @@ function FormItem({ label, type, required, children, className }: Props) {
24
27
  <label className="openapi-explorer__form-item-label">{label}</label>
25
28
  )}
26
29
  {type && <span style={{ opacity: 0.6 }}> — {type}</span>}
27
- {required && <span className="openapi-schema__required">required</span>}
30
+ {required && (
31
+ <span className="openapi-schema__required">
32
+ {translate({ id: OPENAPI_SCHEMA_ITEM.REQUIRED, message: "required" })}
33
+ </span>
34
+ )}
28
35
  <div>{children}</div>
29
36
  </div>
30
37
  );
@@ -8,7 +8,9 @@
8
8
  // @ts-nocheck
9
9
  import React from "react";
10
10
 
11
+ import { translate } from "@docusaurus/Translate";
11
12
  import { ErrorMessage } from "@hookform/error-message";
13
+ import { OPENAPI_FORM } from "@theme/translationIds";
12
14
  import clsx from "clsx";
13
15
  import { useFormContext } from "react-hook-form";
14
16
 
@@ -17,6 +19,8 @@ export interface Props {
17
19
  placeholder?: string;
18
20
  password?: boolean;
19
21
  onChange?: React.ChangeEventHandler<HTMLInputElement>;
22
+ paramName?: string;
23
+ isRequired?: boolean;
20
24
  }
21
25
 
22
26
  function FormTextInput({
@@ -41,7 +45,12 @@ function FormTextInput({
41
45
  {paramName ? (
42
46
  <input
43
47
  {...register(paramName, {
44
- required: isRequired ? "This field is required" : false,
48
+ required: isRequired
49
+ ? translate({
50
+ id: OPENAPI_FORM.FIELD_REQUIRED,
51
+ message: "This field is required",
52
+ })
53
+ : false,
45
54
  })}
46
55
  className={clsx("openapi-explorer__form-item-input", {
47
56
  error: showErrorMessage,
@@ -8,9 +8,10 @@
8
8
  import React, { type JSX, useEffect, useState } from "react";
9
9
 
10
10
  import { usePrismTheme } from "@docusaurus/theme-common";
11
+ import { translate } from "@docusaurus/Translate";
11
12
  import useIsBrowser from "@docusaurus/useIsBrowser";
12
13
  import { ErrorMessage } from "@hookform/error-message";
13
- import { setStringRawBody } from "@theme/ApiExplorer/Body/slice";
14
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
15
  import clsx from "clsx";
15
16
  import { Controller, useFormContext } from "react-hook-form";
16
17
  import { LiveProvider, LiveEditor, withLive } from "react-live";
@@ -54,8 +55,8 @@ function App({
54
55
  const [code, setCode] = React.useState(children.replace(/\n$/, ""));
55
56
 
56
57
  useEffect(() => {
57
- action(setStringRawBody(code));
58
- }, [action, code]);
58
+ action(code);
59
+ }, [code]);
59
60
 
60
61
  const {
61
62
  control,
@@ -85,7 +86,13 @@ function App({
85
86
  <Controller
86
87
  control={control}
87
88
  rules={{
88
- required: isRequired && !code ? "This field is required" : false,
89
+ required:
90
+ isRequired && !code
91
+ ? translate({
92
+ id: OPENAPI_FORM.FIELD_REQUIRED,
93
+ message: "This field is required",
94
+ })
95
+ : false,
89
96
  }}
90
97
  name="requestBody"
91
98
  render={({ field: { onChange, name } }) => (
@@ -7,12 +7,14 @@
7
7
 
8
8
  import React, { useEffect, useState } from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import { nanoid } from "@reduxjs/toolkit";
12
13
  import FormSelect from "@theme/ApiExplorer/FormSelect";
13
14
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
14
15
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
15
16
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
17
+ import { OPENAPI_FORM } from "@theme/translationIds";
16
18
  import { Controller, useFormContext } from "react-hook-form";
17
19
 
18
20
  export interface ParamProps {
@@ -30,7 +32,7 @@ function ArrayItem({
30
32
  return (
31
33
  <FormSelect
32
34
  options={["---", "true", "false"]}
33
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
35
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
34
36
  const val = e.target.value;
35
37
  onChange(val === "---" ? undefined : val);
36
38
  }}
@@ -87,15 +89,16 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
87
89
  }, [items]);
88
90
 
89
91
  useEffect(() => {
90
- if (param.schema?.example?.length > 0) {
91
- const examplesWithIds = param.schema.example.map((item: any) => ({
92
+ const example = param.schema?.example;
93
+ if (Array.isArray(example) && example.length > 0) {
94
+ const examplesWithIds = example.map((item: any) => ({
92
95
  id: nanoid(),
93
96
  value: item.toString(),
94
97
  }));
95
98
 
96
99
  setItems(examplesWithIds);
97
100
  }
98
- }, [param.schema.example, param.schema.length]);
101
+ }, [param.schema?.example]);
99
102
 
100
103
  function handleDeleteItem(itemToDelete: { id: string }) {
101
104
  return () => {
@@ -121,9 +124,16 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
121
124
  <>
122
125
  <Controller
123
126
  control={control}
124
- rules={{ required: param.required ? "This field is required" : false }}
127
+ rules={{
128
+ required: param.required
129
+ ? translate({
130
+ id: OPENAPI_FORM.FIELD_REQUIRED,
131
+ message: "This field is required",
132
+ })
133
+ : false,
134
+ }}
125
135
  name="paramArray"
126
- render={({ field: { onChange, name } }) => (
136
+ render={({ field: { onChange } }) => (
127
137
  <>
128
138
  {items.map((item) => (
129
139
  <div key={item.id} style={{ display: "flex" }}>
@@ -7,10 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import FormSelect from "@theme/ApiExplorer/FormSelect";
12
13
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
13
14
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
15
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
16
  import { Controller, useFormContext } from "react-hook-form";
15
17
 
16
18
  export interface ParamProps {
@@ -31,13 +33,19 @@ export default function ParamBooleanFormItem({ param }: ParamProps) {
31
33
  <>
32
34
  <Controller
33
35
  control={control}
34
- rules={{ required: param.required ? "This field is required" : false }}
36
+ rules={{
37
+ required: param.required
38
+ ? translate({
39
+ id: OPENAPI_FORM.FIELD_REQUIRED,
40
+ message: "This field is required",
41
+ })
42
+ : false,
43
+ }}
35
44
  name="paramBoolean"
36
- render={({ field: { onChange, name } }) => (
45
+ render={({ field: { onChange } }) => (
37
46
  <FormSelect
38
- name={name}
39
47
  options={["---", "true", "false"]}
40
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
48
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
41
49
  const val = e.target.value;
42
50
  dispatch(
43
51
  setParam({
@@ -7,10 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import FormMultiSelect from "@theme/ApiExplorer/FormMultiSelect";
12
13
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
13
14
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
15
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
16
  import { Controller, useFormContext } from "react-hook-form";
15
17
 
16
18
  export interface ParamProps {
@@ -61,14 +63,20 @@ export default function ParamMultiSelectFormItem({ param }: ParamProps) {
61
63
  <>
62
64
  <Controller
63
65
  control={control}
64
- rules={{ required: param.required ? "This field is required" : false }}
66
+ rules={{
67
+ required: param.required
68
+ ? translate({
69
+ id: OPENAPI_FORM.FIELD_REQUIRED,
70
+ message: "This field is required",
71
+ })
72
+ : false,
73
+ }}
65
74
  name="paramMultiSelect"
66
- render={({ field: { onChange, name } }) => (
75
+ render={({ field: { onChange } }) => (
67
76
  <FormMultiSelect
68
77
  options={options as string[]}
69
- name={name}
70
78
  onChange={(e: any) => handleChange(e, onChange)}
71
- showErrors={showErrorMessage}
79
+ showErrors={!!showErrorMessage}
72
80
  />
73
81
  )}
74
82
  />