docusaurus-theme-openapi-docs 4.7.0 → 5.0.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 (148) hide show
  1. package/lib/index.js +2 -0
  2. package/lib/markdown/schema.js +63 -9
  3. package/lib/theme/ApiExplorer/Accept/index.js +2 -1
  4. package/lib/theme/ApiExplorer/Authorization/index.js +12 -18
  5. package/lib/theme/ApiExplorer/Authorization/slice.d.ts +1 -1
  6. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.js +0 -4
  7. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +6 -2
  8. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +191 -38
  9. package/lib/theme/ApiExplorer/Body/index.d.ts +1 -1
  10. package/lib/theme/ApiExplorer/Body/index.js +86 -15
  11. package/lib/theme/ApiExplorer/Body/resolveSchemaWithSelections.d.ts +1 -1
  12. package/lib/theme/ApiExplorer/Body/slice.d.ts +136 -544
  13. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
  14. package/lib/theme/ApiExplorer/CodeSnippets/index.js +4 -0
  15. package/lib/theme/ApiExplorer/CodeTabs/index.js +15 -16
  16. package/lib/theme/ApiExplorer/ContentType/index.js +7 -2
  17. package/lib/theme/ApiExplorer/EncodingSelection/slice.d.ts +17 -0
  18. package/lib/theme/ApiExplorer/EncodingSelection/slice.js +29 -0
  19. package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.d.ts +12 -0
  20. package/lib/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.js +39 -0
  21. package/lib/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
  22. package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -4
  23. package/lib/theme/ApiExplorer/FormItem/index.js +2 -26
  24. package/lib/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
  25. package/lib/theme/ApiExplorer/FormLabel/index.d.ts +9 -0
  26. package/lib/theme/ApiExplorer/FormLabel/index.js +50 -0
  27. package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +4 -1
  28. package/lib/theme/ApiExplorer/FormMultiSelect/index.js +97 -19
  29. package/lib/theme/ApiExplorer/FormSelect/index.d.ts +6 -1
  30. package/lib/theme/ApiExplorer/FormSelect/index.js +96 -15
  31. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +4 -1
  32. package/lib/theme/ApiExplorer/FormTextInput/index.js +71 -1
  33. package/lib/theme/ApiExplorer/MethodEndpoint/index.js +28 -0
  34. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +4 -1
  35. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +11 -3
  36. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +4 -1
  37. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +4 -1
  38. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +4 -1
  39. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +6 -2
  40. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +4 -1
  41. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +6 -2
  42. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +4 -1
  43. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +8 -3
  44. package/lib/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
  45. package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +10 -0
  46. package/lib/theme/ApiExplorer/ParamOptions/index.js +55 -5
  47. package/lib/theme/ApiExplorer/ParamOptions/slice.d.ts +1 -1
  48. package/lib/theme/ApiExplorer/Request/_Request.scss +11 -0
  49. package/lib/theme/ApiExplorer/Request/index.d.ts +1 -1
  50. package/lib/theme/ApiExplorer/Request/index.js +19 -5
  51. package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +3 -1
  52. package/lib/theme/ApiExplorer/Request/makeRequest.js +19 -3
  53. package/lib/theme/ApiExplorer/Response/_Response.scss +11 -0
  54. package/lib/theme/ApiExplorer/Response/index.d.ts +1 -1
  55. package/lib/theme/ApiExplorer/Response/index.js +98 -12
  56. package/lib/theme/ApiExplorer/SecuritySchemes/index.js +2 -2
  57. package/lib/theme/ApiExplorer/Server/index.d.ts +4 -1
  58. package/lib/theme/ApiExplorer/Server/index.js +6 -3
  59. package/lib/theme/ApiExplorer/Server/slice.d.ts +1 -1
  60. package/lib/theme/ApiExplorer/buildPostmanRequest.d.ts +5 -2
  61. package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -5
  62. package/lib/theme/ApiExplorer/index.d.ts +1 -1
  63. package/lib/theme/ApiExplorer/index.js +1 -0
  64. package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +2 -0
  65. package/lib/theme/ApiItem/hooks.d.ts +1 -0
  66. package/lib/theme/ApiItem/index.js +2 -1
  67. package/lib/theme/ApiItem/store.d.ts +6 -0
  68. package/lib/theme/ApiItem/store.js +11 -7
  69. package/lib/theme/ApiTabs/index.js +10 -11
  70. package/lib/theme/DiscriminatorTabs/index.js +10 -11
  71. package/lib/theme/MimeTabs/index.js +10 -11
  72. package/lib/theme/OperationTabs/index.js +10 -11
  73. package/lib/theme/ParamsDetails/index.js +2 -2
  74. package/lib/theme/ParamsItem/index.js +27 -0
  75. package/lib/theme/RequestSchema/index.d.ts +1 -1
  76. package/lib/theme/RequestSchema/index.js +174 -111
  77. package/lib/theme/ResponseHeaders/index.js +0 -1
  78. package/lib/theme/ResponseSchema/index.d.ts +1 -1
  79. package/lib/theme/Schema/index.d.ts +1 -1
  80. package/lib/theme/Schema/index.js +91 -23
  81. package/lib/theme/SchemaItem/index.js +6 -1
  82. package/lib/theme/SchemaTabs/index.d.ts +1 -1
  83. package/lib/theme/SchemaTabs/index.js +31 -12
  84. package/lib/theme/StatusCodes/index.d.ts +1 -1
  85. package/lib/theme/styles.scss +1 -0
  86. package/lib/theme/translationIds.d.ts +3 -0
  87. package/lib/theme/translationIds.js +3 -0
  88. package/package.json +9 -8
  89. package/src/index.ts +2 -0
  90. package/src/markdown/schema.ts +69 -13
  91. package/src/theme/ApiExplorer/Accept/index.tsx +2 -1
  92. package/src/theme/ApiExplorer/Authorization/index.tsx +27 -33
  93. package/src/theme/ApiExplorer/Authorization/slice.ts +1 -1
  94. package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +2 -5
  95. package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +119 -39
  96. package/src/theme/ApiExplorer/Body/index.tsx +88 -21
  97. package/src/theme/ApiExplorer/Body/resolveSchemaWithSelections.ts +1 -1
  98. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +9 -1
  99. package/src/theme/ApiExplorer/CodeTabs/index.tsx +19 -19
  100. package/src/theme/ApiExplorer/ContentType/index.tsx +7 -4
  101. package/src/theme/ApiExplorer/EncodingSelection/slice.ts +31 -0
  102. package/src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts +43 -0
  103. package/src/theme/ApiExplorer/FormItem/_FormItem.scss +0 -5
  104. package/src/theme/ApiExplorer/FormItem/index.tsx +2 -17
  105. package/src/theme/ApiExplorer/FormLabel/_FormLabel.scss +4 -0
  106. package/src/theme/ApiExplorer/FormLabel/index.tsx +43 -0
  107. package/src/theme/ApiExplorer/FormMultiSelect/index.tsx +40 -20
  108. package/src/theme/ApiExplorer/FormSelect/index.tsx +41 -15
  109. package/src/theme/ApiExplorer/FormTextInput/index.tsx +15 -1
  110. package/src/theme/ApiExplorer/MethodEndpoint/index.tsx +21 -0
  111. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +13 -2
  112. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -1
  113. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +14 -2
  114. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +14 -2
  115. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +16 -3
  116. package/src/theme/ApiExplorer/ParamOptions/_ParamOptions.scss +0 -9
  117. package/src/theme/ApiExplorer/ParamOptions/index.tsx +97 -11
  118. package/src/theme/ApiExplorer/ParamOptions/slice.ts +1 -1
  119. package/src/theme/ApiExplorer/Request/_Request.scss +11 -0
  120. package/src/theme/ApiExplorer/Request/index.tsx +22 -10
  121. package/src/theme/ApiExplorer/Request/makeRequest.ts +19 -3
  122. package/src/theme/ApiExplorer/Response/_Response.scss +11 -0
  123. package/src/theme/ApiExplorer/Response/index.tsx +37 -17
  124. package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +2 -3
  125. package/src/theme/ApiExplorer/Server/index.tsx +10 -3
  126. package/src/theme/ApiExplorer/Server/slice.ts +1 -1
  127. package/src/theme/ApiExplorer/buildPostmanRequest.ts +53 -6
  128. package/src/theme/ApiExplorer/index.tsx +2 -1
  129. package/src/theme/ApiItem/index.tsx +3 -2
  130. package/src/theme/ApiItem/store.ts +2 -0
  131. package/src/theme/ApiTabs/index.tsx +14 -19
  132. package/src/theme/DiscriminatorTabs/index.tsx +14 -19
  133. package/src/theme/MimeTabs/index.tsx +15 -19
  134. package/src/theme/OperationTabs/index.tsx +14 -19
  135. package/src/theme/ParamsDetails/index.tsx +2 -3
  136. package/src/theme/ParamsItem/index.tsx +25 -0
  137. package/src/theme/RequestSchema/index.tsx +144 -87
  138. package/src/theme/ResponseHeaders/index.tsx +1 -2
  139. package/src/theme/ResponseSchema/index.tsx +1 -1
  140. package/src/theme/Schema/index.tsx +112 -27
  141. package/src/theme/SchemaItem/index.tsx +6 -1
  142. package/src/theme/SchemaTabs/index.tsx +42 -21
  143. package/src/theme/StatusCodes/index.tsx +1 -1
  144. package/src/theme/styles.scss +1 -0
  145. package/src/theme/translationIds.ts +3 -0
  146. package/src/theme-classic.d.ts +25 -1
  147. package/src/types.d.ts +15 -52
  148. package/tsconfig.tsbuildinfo +1 -1
@@ -84,8 +84,8 @@ const translationIds_1 = require("@theme/translationIds");
84
84
  // eslint-disable-next-line import/no-extraneous-dependencies
85
85
  const allof_merge_1 = require("allof-merge");
86
86
  const clsx_1 = __importDefault(require("clsx"));
87
- const schema_1 = require("docusaurus-plugin-openapi-docs/lib/markdown/schema");
88
87
  const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
88
+ const schema_1 = require("../../markdown/schema");
89
89
  // eslint-disable-next-line import/no-extraneous-dependencies
90
90
  // const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
91
91
  const mergeAllOf = (allOf) => {
@@ -93,7 +93,68 @@ const mergeAllOf = (allOf) => {
93
93
  console.warn(msg);
94
94
  };
95
95
  const mergedSchemas = (0, allof_merge_1.merge)(allOf, { onMergeError });
96
- return mergedSchemas;
96
+ return mergedSchemas ?? {};
97
+ };
98
+ /**
99
+ * Recursively searches for a property in a schema, including nested
100
+ * oneOf, anyOf, and allOf structures. This is needed for discriminators
101
+ * where the property definition may be in a nested schema.
102
+ */
103
+ const findProperty = (schema, propertyName) => {
104
+ // Check direct properties first
105
+ if (schema.properties?.[propertyName]) {
106
+ return schema.properties[propertyName];
107
+ }
108
+ // Search in oneOf schemas
109
+ if (schema.oneOf) {
110
+ for (const subschema of schema.oneOf) {
111
+ const found = findProperty(subschema, propertyName);
112
+ if (found) return found;
113
+ }
114
+ }
115
+ // Search in anyOf schemas
116
+ if (schema.anyOf) {
117
+ for (const subschema of schema.anyOf) {
118
+ const found = findProperty(subschema, propertyName);
119
+ if (found) return found;
120
+ }
121
+ }
122
+ // Search in allOf schemas
123
+ if (schema.allOf) {
124
+ for (const subschema of schema.allOf) {
125
+ const found = findProperty(subschema, propertyName);
126
+ if (found) return found;
127
+ }
128
+ }
129
+ return undefined;
130
+ };
131
+ /**
132
+ * Recursively searches for a discriminator in a schema, including nested
133
+ * oneOf, anyOf, and allOf structures.
134
+ */
135
+ const findDiscriminator = (schema) => {
136
+ if (schema.discriminator) {
137
+ return schema.discriminator;
138
+ }
139
+ if (schema.oneOf) {
140
+ for (const subschema of schema.oneOf) {
141
+ const found = findDiscriminator(subschema);
142
+ if (found) return found;
143
+ }
144
+ }
145
+ if (schema.anyOf) {
146
+ for (const subschema of schema.anyOf) {
147
+ const found = findDiscriminator(subschema);
148
+ if (found) return found;
149
+ }
150
+ }
151
+ if (schema.allOf) {
152
+ for (const subschema of schema.allOf) {
153
+ const found = findDiscriminator(subschema);
154
+ if (found) return found;
155
+ }
156
+ }
157
+ return undefined;
97
158
  };
98
159
  // Renders string as markdown, useful for descriptions and qualifiers
99
160
  const MarkdownWrapper = ({ text }) => {
@@ -165,6 +226,12 @@ const Summary = ({ name, schemaName, schema, required }) => {
165
226
  };
166
227
  const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
167
228
  const key = schema.oneOf ? "oneOf" : "anyOf";
229
+ const schemaArray = schema[key];
230
+ // Empty oneOf/anyOf arrays are valid in OpenAPI specs but would cause the
231
+ // Tabs component to throw "requires at least one TabItem". Return null instead.
232
+ if (!schemaArray || !Array.isArray(schemaArray) || schemaArray.length === 0) {
233
+ return null;
234
+ }
168
235
  const type = schema.oneOf
169
236
  ? (0, Translate_1.translate)({
170
237
  id: translationIds_1.OPENAPI_SCHEMA_ITEM.ONE_OF,
@@ -244,9 +311,6 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
244
311
  collapsible: false,
245
312
  name: undefined,
246
313
  schemaName: computedSchemaName,
247
- qualifierMessage: (0, schema_1.getQualifierMessage)(
248
- anyOneSchema
249
- ),
250
314
  schema: anyOneSchema,
251
315
  discriminator: false,
252
316
  children: null,
@@ -260,9 +324,6 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
260
324
  collapsible: false,
261
325
  name: undefined,
262
326
  schemaName: computedSchemaName,
263
- qualifierMessage: (0, schema_1.getQualifierMessage)(
264
- anyOneSchema
265
- ),
266
327
  schema: anyOneSchema,
267
328
  discriminator: false,
268
329
  children: null,
@@ -321,12 +382,16 @@ const Properties = ({ schema, schemaType, schemaPath }) => {
321
382
  discriminator["mapping"] = inferredMapping;
322
383
  }
323
384
  if (Object.keys(schema.properties).length === 0) {
385
+ // Hide placeholder only for discriminator cleanup artifacts; preserve
386
+ // empty object rendering for schemas that intentionally define no properties.
387
+ if (discriminator) {
388
+ return null;
389
+ }
324
390
  return react_1.default.createElement(SchemaItem_1.default, {
325
391
  collapsible: false,
326
392
  name: "",
327
393
  required: false,
328
394
  schemaName: "object",
329
- qualifierMessage: undefined,
330
395
  schema: {},
331
396
  });
332
397
  }
@@ -448,10 +513,9 @@ const PropertyDiscriminator = ({
448
513
  const DiscriminatorNode = ({ discriminator, schema, schemaType }) => {
449
514
  let discriminatedSchemas = {};
450
515
  let inferredMapping = {};
451
- // default to empty object if no parent-level properties exist
452
- const discriminatorProperty = schema.properties
453
- ? schema.properties[discriminator.propertyName]
454
- : {};
516
+ // Search for the discriminator property in the schema, including nested structures
517
+ const discriminatorProperty =
518
+ findProperty(schema, discriminator.propertyName) ?? {};
455
519
  if (schema.allOf) {
456
520
  const mergedSchemas = mergeAllOf(schema);
457
521
  if (mergedSchemas.oneOf || mergedSchemas.anyOf) {
@@ -523,7 +587,6 @@ const AdditionalProperties = ({ schema, schemaType }) => {
523
587
  name: "property name*",
524
588
  required: false,
525
589
  schemaName: "any",
526
- qualifierMessage: (0, schema_1.getQualifierMessage)(schema),
527
590
  schema: schema,
528
591
  collapsible: false,
529
592
  discriminator: false,
@@ -564,7 +627,6 @@ const AdditionalProperties = ({ schema, schemaType }) => {
564
627
  name: "property name*",
565
628
  required: false,
566
629
  schemaName: schemaName,
567
- qualifierMessage: (0, schema_1.getQualifierMessage)(schema),
568
630
  schema: additionalProperties,
569
631
  collapsible: false,
570
632
  discriminator: false,
@@ -669,7 +731,6 @@ const Items = ({ schema, schemaType, schemaPath }) => {
669
731
  collapsible: false,
670
732
  name: "", // No name for array items
671
733
  schemaName: (0, schema_1.getSchemaName)(itemsSchema),
672
- qualifierMessage: (0, schema_1.getQualifierMessage)(itemsSchema),
673
734
  schema: itemsSchema,
674
735
  discriminator: false,
675
736
  children: null,
@@ -790,7 +851,6 @@ const SchemaEdge = ({
790
851
  name: name,
791
852
  required: Array.isArray(required) ? required.includes(name) : required,
792
853
  schemaName: schema.allOf[0],
793
- qualifierMessage: undefined,
794
854
  schema: schema.allOf[0],
795
855
  discriminator: false,
796
856
  children: null,
@@ -842,7 +902,6 @@ const SchemaEdge = ({
842
902
  name: name,
843
903
  required: Array.isArray(required) ? required.includes(name) : required,
844
904
  schemaName: mergedSchemaName,
845
- qualifierMessage: (0, schema_1.getQualifierMessage)(mergedSchemas),
846
905
  schema: mergedSchemas,
847
906
  discriminator: false,
848
907
  children: null,
@@ -853,7 +912,6 @@ const SchemaEdge = ({
853
912
  name: name,
854
913
  required: Array.isArray(required) ? required.includes(name) : required,
855
914
  schemaName: schemaName,
856
- qualifierMessage: (0, schema_1.getQualifierMessage)(schema),
857
915
  schema: schema,
858
916
  discriminator: false,
859
917
  children: null,
@@ -901,11 +959,22 @@ const SchemaNode = ({ schema, schemaType, schemaPath }) => {
901
959
  ) {
902
960
  return null;
903
961
  }
904
- if (schema.discriminator) {
905
- const { discriminator } = schema;
962
+ // Resolve discriminator recursively so nested oneOf/anyOf/allOf compositions
963
+ // can still render discriminator tabs.
964
+ let workingSchema = schema;
965
+ const resolvedDiscriminator =
966
+ schema.discriminator ?? findDiscriminator(schema);
967
+ if (schema.allOf && !schema.discriminator && resolvedDiscriminator) {
968
+ workingSchema = mergeAllOf(schema);
969
+ }
970
+ if (!workingSchema.discriminator && resolvedDiscriminator) {
971
+ workingSchema.discriminator = resolvedDiscriminator;
972
+ }
973
+ if (workingSchema.discriminator) {
974
+ const { discriminator } = workingSchema;
906
975
  return react_1.default.createElement(DiscriminatorNode, {
907
976
  discriminator: discriminator,
908
- schema: schema,
977
+ schema: workingSchema,
909
978
  schemaType: schemaType,
910
979
  });
911
980
  }
@@ -1010,7 +1079,6 @@ const SchemaNode = ({ schema, schemaType, schemaPath }) => {
1010
1079
  name: schema.type,
1011
1080
  required: Boolean(schema.required),
1012
1081
  schemaName: schemaName,
1013
- qualifierMessage: (0, schema_1.getQualifierMessage)(schema),
1014
1082
  schema: schema,
1015
1083
  discriminator: false,
1016
1084
  children: null,
@@ -18,6 +18,7 @@ const Example_1 = require("@theme/Example");
18
18
  const Markdown_1 = __importDefault(require("@theme/Markdown"));
19
19
  const translationIds_1 = require("@theme/translationIds");
20
20
  const clsx_1 = __importDefault(require("clsx"));
21
+ const schema_1 = require("../../markdown/schema");
21
22
  const utils_1 = require("../../markdown/utils");
22
23
  const transformEnumDescriptions = (enumDescriptions) => {
23
24
  if (enumDescriptions) {
@@ -127,8 +128,12 @@ function SchemaItem(props) {
127
128
  react_1.default.createElement(Markdown_1.default, null, description)
128
129
  )
129
130
  );
131
+ // Generate qualifierMessage from schema if not provided
132
+ const effectiveQualifierMessage =
133
+ qualifierMessage ??
134
+ (schema ? (0, schema_1.getQualifierMessage)(schema) : undefined);
130
135
  const renderQualifierMessage = (0, utils_1.guard)(
131
- qualifierMessage,
136
+ effectiveQualifierMessage,
132
137
  (message) =>
133
138
  react_1.default.createElement(
134
139
  react_1.default.Fragment,
@@ -7,4 +7,4 @@ export interface SchemaTabsProps extends TabProps {
7
7
  */
8
8
  onChange?: (index: number) => void;
9
9
  }
10
- export default function SchemaTabs(props: SchemaTabsProps): React.JSX.Element;
10
+ export default function SchemaTabs(props: SchemaTabsProps): React.JSX.Element | null;
@@ -233,25 +233,44 @@ function TabContent({ lazy, children, selectedValue }) {
233
233
  return react_1.default.createElement(
234
234
  "div",
235
235
  { className: "margin-top--md" },
236
- childTabs.map((tabItem, i) =>
237
- (0, react_1.cloneElement)(tabItem, {
238
- key: i,
239
- hidden: tabItem.props.value !== selectedValue,
240
- })
241
- )
236
+ childTabs
242
237
  );
243
238
  }
244
239
  function TabsComponent(props) {
245
- const tabs = (0, internal_1.useTabs)(props);
240
+ const tabs = (0, internal_1.useTabsContextValue)(props);
246
241
  return react_1.default.createElement(
247
- "div",
248
- { className: "openapi-tabs__schema-container" },
249
- react_1.default.createElement(TabList, { ...props, ...tabs }),
250
- react_1.default.createElement(TabContent, { ...props, ...tabs })
242
+ internal_1.TabsProvider,
243
+ { value: tabs },
244
+ react_1.default.createElement(
245
+ "div",
246
+ { className: "openapi-tabs__schema-container" },
247
+ react_1.default.createElement(TabList, { ...props, ...tabs }),
248
+ react_1.default.createElement(TabContent, { ...props, ...tabs })
249
+ )
251
250
  );
252
251
  }
253
252
  function SchemaTabs(props) {
254
253
  const isBrowser = (0, useIsBrowser_1.default)();
254
+ const children = Array.isArray(props.children)
255
+ ? props.children.filter(Boolean)
256
+ : props.children
257
+ ? [props.children]
258
+ : [];
259
+ if (children.length === 0) {
260
+ return null;
261
+ }
262
+ let sanitizedChildren;
263
+ try {
264
+ sanitizedChildren = (0, internal_1.sanitizeTabsChildren)(children);
265
+ } catch {
266
+ return null;
267
+ }
268
+ if (
269
+ !sanitizedChildren ||
270
+ (Array.isArray(sanitizedChildren) && sanitizedChildren.length === 0)
271
+ ) {
272
+ return null;
273
+ }
255
274
  return react_1.default.createElement(
256
275
  TabsComponent,
257
276
  // Remount tabs after hydration
@@ -262,6 +281,6 @@ function SchemaTabs(props) {
262
281
  key: String(isBrowser),
263
282
  ...props,
264
283
  },
265
- (0, internal_1.sanitizeTabsChildren)(props.children)
284
+ sanitizedChildren
266
285
  );
267
286
  }
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
2
+ import type { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
3
3
  interface Props {
4
4
  id?: string;
5
5
  label?: string;
@@ -9,6 +9,7 @@
9
9
  @use "./ApiExplorer/FloatingButton/FloatingButton";
10
10
  @use "./ApiExplorer/FormFileUpload/FormFileUpload";
11
11
  @use "./ApiExplorer/FormItem/FormItem";
12
+ @use "./ApiExplorer/FormLabel/FormLabel";
12
13
  @use "./ApiExplorer/FormMultiSelect/FormMultiSelect";
13
14
  @use "./ApiExplorer/FormSelect/FormSelect";
14
15
  @use "./ApiExplorer/FormTextInput/FormTextInput";
@@ -60,6 +60,8 @@ export declare const OPENAPI_SCHEMA: {
60
60
  NO_SCHEMA: string;
61
61
  };
62
62
  export declare const OPENAPI_SCHEMA_ITEM: {
63
+ CHARACTERS: string;
64
+ NON_EMPTY: string;
63
65
  REQUIRED: string;
64
66
  DEPRECATED: string;
65
67
  NULLABLE: string;
@@ -71,6 +73,7 @@ export declare const OPENAPI_SCHEMA_ITEM: {
71
73
  ENUM_VALUE: string;
72
74
  ENUM_DESCRIPTION: string;
73
75
  POSSIBLE_VALUES: string;
76
+ EXPRESSION: string;
74
77
  ONE_OF: string;
75
78
  ANY_OF: string;
76
79
  };
@@ -84,6 +84,8 @@ exports.OPENAPI_SCHEMA = {
84
84
  NO_SCHEMA: "theme.openapi.schema.noSchema",
85
85
  };
86
86
  exports.OPENAPI_SCHEMA_ITEM = {
87
+ CHARACTERS: "theme.openapi.schemaItem.characters",
88
+ NON_EMPTY: "theme.openapi.schemaItem.nonEmpty",
87
89
  REQUIRED: "theme.openapi.schemaItem.required",
88
90
  DEPRECATED: "theme.openapi.schemaItem.deprecated",
89
91
  NULLABLE: "theme.openapi.schemaItem.nullable",
@@ -95,6 +97,7 @@ exports.OPENAPI_SCHEMA_ITEM = {
95
97
  ENUM_VALUE: "theme.openapi.schemaItem.enumValue",
96
98
  ENUM_DESCRIPTION: "theme.openapi.schemaItem.enumDescription",
97
99
  POSSIBLE_VALUES: "theme.openapi.schemaItem.possibleValues",
100
+ EXPRESSION: "theme.openapi.schemaItem.expression",
98
101
  ONE_OF: "theme.openapi.schemaItem.oneOf",
99
102
  ANY_OF: "theme.openapi.schemaItem.anyOf",
100
103
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "4.7.0",
4
+ "version": "5.0.0",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -28,9 +28,9 @@
28
28
  "watch": "concurrently --names \"lib,lib-next,tsc\" --kill-others \"yarn babel:lib --watch\" \"yarn babel:lib-next --watch\" \"yarn tsc --watch\""
29
29
  },
30
30
  "devDependencies": {
31
- "@docusaurus/theme-classic": "^3.5.0",
32
- "@docusaurus/theme-common": "^3.5.0",
33
- "@docusaurus/types": "^3.5.0",
31
+ "@docusaurus/theme-classic": "^3.10.0",
32
+ "@docusaurus/theme-common": "^3.10.0",
33
+ "@docusaurus/types": "^3.10.0",
34
34
  "@types/crypto-js": "^4.2.2",
35
35
  "@types/file-saver": "^2.0.7",
36
36
  "@types/lodash": "^4.17.20",
@@ -38,7 +38,7 @@
38
38
  "@types/postman-collection": "^3.5.11",
39
39
  "@types/react-modal": "^3.16.3",
40
40
  "concurrently": "^9.2.0",
41
- "docusaurus-plugin-openapi-docs": "^4.7.0",
41
+ "docusaurus-plugin-openapi-docs": "^5.0.0",
42
42
  "docusaurus-plugin-sass": "^0.2.6",
43
43
  "eslint-plugin-prettier": "^5.5.1"
44
44
  },
@@ -53,6 +53,7 @@
53
53
  "file-saver": "^2.0.5",
54
54
  "lodash": "^4.17.21",
55
55
  "pako": "^2.1.0",
56
+ "path-browserify": "^1.0.1",
56
57
  "postman-code-generators": "^2.0.0",
57
58
  "postman-collection": "^5.0.2",
58
59
  "prism-react-renderer": "^2.4.1",
@@ -72,8 +73,8 @@
72
73
  "xml-formatter": "^3.6.6"
73
74
  },
74
75
  "peerDependencies": {
75
- "@docusaurus/theme-common": "^3.5.0",
76
- "docusaurus-plugin-openapi-docs": "^4.0.0",
76
+ "@docusaurus/theme-common": "^3.10.0",
77
+ "docusaurus-plugin-openapi-docs": "^5.0.0",
77
78
  "docusaurus-plugin-sass": "^0.2.3",
78
79
  "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0",
79
80
  "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -81,5 +82,5 @@
81
82
  "engines": {
82
83
  "node": ">=14"
83
84
  },
84
- "gitHead": "f5829b8e478b0ee76344ba31edd67efdfea18990"
85
+ "gitHead": "516bd48c628fb16b7fe90d8f996168ab75ce5562"
85
86
  }
package/src/index.ts CHANGED
@@ -42,6 +42,7 @@ export default function docusaurusThemeOpenAPI(): Plugin<void> {
42
42
  resolve: {
43
43
  fallback: {
44
44
  buffer: require.resolve("buffer/"),
45
+ path: require.resolve("path-browserify"),
45
46
  },
46
47
  },
47
48
  plugins: [
@@ -71,6 +72,7 @@ export default function docusaurusThemeOpenAPI(): Plugin<void> {
71
72
  resolve: {
72
73
  fallback: {
73
74
  buffer: require.resolve("buffer/"),
75
+ path: require.resolve("path-browserify"),
74
76
  },
75
77
  },
76
78
  plugins: [
@@ -10,6 +10,44 @@ import { translate } from "@docusaurus/Translate";
10
10
  import { OPENAPI_SCHEMA_ITEM } from "../theme/translationIds";
11
11
  import { SchemaObject } from "../types";
12
12
 
13
+ /**
14
+ * Extracts enum values from a schema, including when wrapped in allOf.
15
+ */
16
+ function getEnumFromSchema(schema: SchemaObject): any[] | undefined {
17
+ if (schema.enum) {
18
+ return schema.enum;
19
+ }
20
+
21
+ if (schema.allOf && Array.isArray(schema.allOf)) {
22
+ for (const item of schema.allOf) {
23
+ if (item.enum) {
24
+ return item.enum;
25
+ }
26
+ }
27
+ }
28
+
29
+ return undefined;
30
+ }
31
+
32
+ /**
33
+ * Extracts the type from a schema, including when wrapped in allOf.
34
+ */
35
+ function getTypeFromSchema(schema: SchemaObject): string | undefined {
36
+ if (schema.type) {
37
+ return schema.type as string;
38
+ }
39
+
40
+ if (schema.allOf && Array.isArray(schema.allOf)) {
41
+ for (const item of schema.allOf) {
42
+ if (item.type) {
43
+ return item.type as string;
44
+ }
45
+ }
46
+ }
47
+
48
+ return undefined;
49
+ }
50
+
13
51
  function prettyName(schema: SchemaObject, circular?: boolean) {
14
52
  // Handle enum-only schemas (valid in JSON Schema)
15
53
  // When enum is present without explicit type, treat as string
@@ -28,6 +66,12 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
28
66
  return schema.allOf[0];
29
67
  }
30
68
  }
69
+ // Check if allOf contains an enum - if so, return the type from allOf
70
+ const enumFromAllOf = getEnumFromSchema(schema);
71
+ if (enumFromAllOf) {
72
+ const typeFromAllOf = getTypeFromSchema(schema);
73
+ return typeFromAllOf ?? "string";
74
+ }
31
75
  return "object";
32
76
  }
33
77
 
@@ -92,11 +136,11 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
92
136
 
93
137
  let qualifierGroups = [];
94
138
 
95
- if (schema.items && schema.items.enum) {
96
- if (schema.items.enum) {
97
- qualifierGroups.push(
98
- `[${schema.items.enum.map((e) => `\`${e}\``).join(", ")}]`
99
- );
139
+ // Check for enum in array items (directly or inside allOf)
140
+ if (schema.items) {
141
+ const itemsEnum = getEnumFromSchema(schema.items as SchemaObject);
142
+ if (itemsEnum) {
143
+ qualifierGroups.push(`[${itemsEnum.map((e) => `\`${e}\``).join(", ")}]`);
100
144
  }
101
145
  }
102
146
 
@@ -104,14 +148,22 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
104
148
  let lengthQualifier = "";
105
149
  let minLength;
106
150
  let maxLength;
151
+ const charactersMessage = translate({
152
+ id: OPENAPI_SCHEMA_ITEM.CHARACTERS,
153
+ message: "characters",
154
+ });
155
+ const nonEmptyMessage = translate({
156
+ id: OPENAPI_SCHEMA_ITEM.NON_EMPTY,
157
+ message: "non-empty",
158
+ });
107
159
  if (schema.minLength && schema.minLength > 1) {
108
- minLength = `\`>= ${schema.minLength} characters\``;
160
+ minLength = `\`>= ${schema.minLength} ${charactersMessage}\``;
109
161
  }
110
162
  if (schema.minLength && schema.minLength === 1) {
111
- minLength = `\`non-empty\``;
163
+ minLength = `\`${nonEmptyMessage}\``;
112
164
  }
113
165
  if (schema.maxLength) {
114
- maxLength = `\`<= ${schema.maxLength} characters\``;
166
+ maxLength = `\`<= ${schema.maxLength} ${charactersMessage}\``;
115
167
  }
116
168
 
117
169
  if (minLength && !maxLength) {
@@ -165,9 +217,11 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
165
217
  }
166
218
 
167
219
  if (schema.pattern) {
168
- qualifierGroups.push(
169
- `Value must match regular expression \`${schema.pattern}\``
170
- );
220
+ const expressionMessage = translate({
221
+ id: OPENAPI_SCHEMA_ITEM.EXPRESSION,
222
+ message: "Value must match regular expression",
223
+ });
224
+ qualifierGroups.push(`${expressionMessage} \`${schema.pattern}\``);
171
225
  }
172
226
 
173
227
  // Check if discriminator mapping
@@ -177,8 +231,10 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
177
231
  qualifierGroups.push(`[${values.map((e) => `\`${e}\``).join(", ")}]`);
178
232
  }
179
233
 
180
- if (schema.enum) {
181
- qualifierGroups.push(`[${schema.enum.map((e) => `\`${e}\``).join(", ")}]`);
234
+ // Check for enum directly on schema or inside allOf
235
+ const schemaEnum = getEnumFromSchema(schema);
236
+ if (schemaEnum) {
237
+ qualifierGroups.push(`[${schemaEnum.map((e) => `\`${e}\``).join(", ")}]`);
182
238
  }
183
239
 
184
240
  if (schema.minItems) {
@@ -23,8 +23,9 @@ function Accept() {
23
23
  }
24
24
 
25
25
  return (
26
- <FormItem label="Accept">
26
+ <FormItem>
27
27
  <FormSelect
28
+ label="Accept"
28
29
  value={value}
29
30
  options={options}
30
31
  onChange={(e: any) => dispatch(setAccept(e.target.value))}