docusaurus-theme-openapi-docs 5.0.2 → 5.1.1
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.
- package/lib/markdown/schema.js +38 -15
- package/lib/markdown/schema.test.d.ts +1 -0
- package/lib/markdown/schema.test.js +86 -0
- package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +4 -2
- package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +9 -6
- package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/Authorization/index.js +9 -10
- package/lib/theme/ApiExplorer/Body/index.js +4 -5
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +96 -61
- package/lib/theme/ApiExplorer/CodeSnippets/languages.js +12 -1
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.d.ts +1 -0
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.js +102 -0
- package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/CodeTabs/index.js +6 -5
- package/lib/theme/ApiExplorer/Export/index.js +9 -2
- package/lib/theme/ApiExplorer/FormFileUpload/index.js +1 -2
- package/lib/theme/ApiExplorer/FormLabel/index.js +1 -2
- package/lib/theme/ApiExplorer/FormTextInput/index.js +1 -2
- package/lib/theme/ApiExplorer/LiveEditor/index.js +1 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +5 -3
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +75 -4
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +1 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +67 -4
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +65 -1
- package/lib/theme/ApiExplorer/ParamOptions/index.js +2 -3
- package/lib/theme/ApiExplorer/Request/index.js +17 -18
- package/lib/theme/ApiExplorer/Response/index.js +54 -12
- package/lib/theme/ApiExplorer/SecuritySchemes/index.js +57 -50
- package/lib/theme/ApiExplorer/Server/index.js +2 -3
- package/lib/theme/ApiItem/index.js +59 -33
- package/lib/theme/ApiTabs/index.d.ts +1 -1
- package/lib/theme/ApiTabs/index.js +7 -7
- package/lib/theme/DiscriminatorTabs/index.d.ts +1 -1
- package/lib/theme/DiscriminatorTabs/index.js +6 -5
- package/lib/theme/Example/index.js +3 -4
- package/lib/theme/MimeTabs/index.d.ts +1 -1
- package/lib/theme/MimeTabs/index.js +6 -5
- package/lib/theme/OperationTabs/index.d.ts +1 -1
- package/lib/theme/OperationTabs/index.js +6 -5
- package/lib/theme/ParamsDetails/index.js +1 -2
- package/lib/theme/ParamsItem/index.js +7 -8
- package/lib/theme/RequestSchema/index.js +57 -57
- package/lib/theme/ResponseExamples/index.js +3 -4
- package/lib/theme/ResponseSchema/index.js +26 -24
- package/lib/theme/Schema/index.js +148 -110
- package/lib/theme/Schema/normalize.d.ts +41 -0
- package/lib/theme/Schema/normalize.js +210 -0
- package/lib/theme/Schema/normalize.test.d.ts +1 -0
- package/lib/theme/Schema/normalize.test.js +271 -0
- package/lib/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
- package/lib/theme/SchemaExpansion/context.d.ts +24 -0
- package/lib/theme/SchemaExpansion/context.js +187 -0
- package/lib/theme/SchemaExpansion/index.d.ts +4 -0
- package/lib/theme/SchemaExpansion/index.js +314 -0
- package/lib/theme/SchemaItem/index.js +9 -10
- package/lib/theme/SchemaTabs/index.d.ts +1 -1
- package/lib/theme/SchemaTabs/index.js +6 -5
- package/lib/theme/StatusCodes/index.js +2 -4
- package/lib/theme/TabItem/index.d.ts +5 -0
- package/lib/theme/TabItem/index.js +51 -0
- package/lib/theme/TabItem/styles.module.css +3 -0
- package/lib/theme/Tabs/index.d.ts +5 -0
- package/lib/theme/Tabs/index.js +148 -0
- package/lib/theme/Tabs/styles.module.css +7 -0
- package/lib/theme/styles.scss +1 -0
- package/lib/theme/translationIds.d.ts +1 -93
- package/lib/theme/translationIds.js +0 -109
- package/lib/theme/utils/codeBlockUtils.d.ts +28 -0
- package/lib/theme/utils/codeBlockUtils.js +223 -0
- package/lib/theme/utils/reactUtils.d.ts +1 -0
- package/lib/theme/utils/reactUtils.js +23 -0
- package/lib/theme/utils/scrollUtils.d.ts +7 -0
- package/lib/theme/utils/scrollUtils.js +175 -0
- package/lib/theme/utils/tabsUtils.d.ts +47 -0
- package/lib/theme/utils/tabsUtils.js +299 -0
- package/lib/theme/utils/useCodeWordWrap.d.ts +8 -0
- package/lib/theme/utils/useCodeWordWrap.js +84 -0
- package/lib/theme/utils/useMutationObserver.d.ts +3 -0
- package/lib/theme/utils/useMutationObserver.js +34 -0
- package/package.json +4 -4
- package/src/markdown/schema.test.ts +102 -0
- package/src/markdown/schema.ts +42 -15
- package/src/theme/ApiExplorer/ApiCodeBlock/Container/index.tsx +2 -1
- package/src/theme/ApiExplorer/ApiCodeBlock/Content/String.tsx +8 -7
- package/src/theme/ApiExplorer/ApiCodeBlock/Line/index.tsx +1 -1
- package/src/theme/ApiExplorer/ApiCodeBlock/index.tsx +1 -1
- package/src/theme/ApiExplorer/Authorization/index.tsx +9 -10
- package/src/theme/ApiExplorer/Body/index.tsx +7 -5
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +103 -59
- package/src/theme/ApiExplorer/CodeSnippets/languages.test.ts +109 -0
- package/src/theme/ApiExplorer/CodeSnippets/languages.ts +13 -1
- package/src/theme/ApiExplorer/CodeTabs/index.tsx +5 -5
- package/src/theme/ApiExplorer/Export/index.tsx +6 -2
- package/src/theme/ApiExplorer/FormFileUpload/index.tsx +1 -2
- package/src/theme/ApiExplorer/FormLabel/index.tsx +1 -2
- package/src/theme/ApiExplorer/FormTextInput/index.tsx +1 -2
- package/src/theme/ApiExplorer/LiveEditor/index.tsx +1 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +5 -3
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +20 -4
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +1 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +15 -4
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +11 -1
- package/src/theme/ApiExplorer/ParamOptions/index.tsx +2 -3
- package/src/theme/ApiExplorer/Request/index.tsx +23 -18
- package/src/theme/ApiExplorer/Response/index.tsx +63 -9
- package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +60 -52
- package/src/theme/ApiExplorer/Server/index.tsx +8 -3
- package/src/theme/ApiItem/index.tsx +43 -21
- package/src/theme/ApiTabs/index.tsx +8 -8
- package/src/theme/DiscriminatorTabs/index.tsx +6 -5
- package/src/theme/Example/index.tsx +3 -4
- package/src/theme/MimeTabs/index.tsx +9 -8
- package/src/theme/OperationTabs/index.tsx +5 -4
- package/src/theme/ParamsDetails/index.tsx +1 -2
- package/src/theme/ParamsItem/index.tsx +13 -8
- package/src/theme/RequestSchema/index.tsx +38 -40
- package/src/theme/ResponseExamples/index.tsx +3 -4
- package/src/theme/ResponseSchema/index.tsx +16 -17
- package/src/theme/Schema/index.tsx +154 -121
- package/src/theme/Schema/normalize.test.ts +288 -0
- package/src/theme/Schema/normalize.ts +224 -0
- package/src/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
- package/src/theme/SchemaExpansion/context.tsx +154 -0
- package/src/theme/SchemaExpansion/index.tsx +236 -0
- package/src/theme/SchemaItem/index.tsx +18 -10
- package/src/theme/SchemaTabs/index.tsx +6 -5
- package/src/theme/StatusCodes/index.tsx +2 -3
- package/src/theme/TabItem/index.tsx +61 -0
- package/src/theme/TabItem/styles.module.css +3 -0
- package/src/theme/Tabs/index.tsx +164 -0
- package/src/theme/Tabs/styles.module.css +7 -0
- package/src/theme/styles.scss +1 -0
- package/src/theme/translationIds.ts +37 -106
- package/src/theme/utils/codeBlockUtils.ts +296 -0
- package/src/theme/utils/reactUtils.ts +22 -0
- package/src/theme/utils/scrollUtils.tsx +153 -0
- package/src/theme/utils/tabsUtils.tsx +329 -0
- package/src/theme/utils/useCodeWordWrap.ts +110 -0
- package/src/theme/utils/useMutationObserver.ts +43 -0
- package/src/theme-classic.d.ts +0 -96
- package/src/types.d.ts +27 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -19,10 +19,10 @@ const Markdown_1 = __importDefault(require("@theme/Markdown"));
|
|
|
19
19
|
const MimeTabs_1 = __importDefault(require("@theme/MimeTabs")); // Assume these components exist
|
|
20
20
|
const ResponseExamples_1 = require("@theme/ResponseExamples");
|
|
21
21
|
const Schema_1 = __importDefault(require("@theme/Schema"));
|
|
22
|
+
const SchemaExpansion_1 = __importDefault(require("@theme/SchemaExpansion"));
|
|
22
23
|
const SchemaTabs_1 = __importDefault(require("@theme/SchemaTabs"));
|
|
23
24
|
const SkeletonLoader_1 = __importDefault(require("@theme/SkeletonLoader"));
|
|
24
25
|
const TabItem_1 = __importDefault(require("@theme/TabItem"));
|
|
25
|
-
const translationIds_1 = require("@theme/translationIds");
|
|
26
26
|
const ResponseSchemaComponent = ({ title, body, style }) => {
|
|
27
27
|
if (
|
|
28
28
|
body === undefined ||
|
|
@@ -57,7 +57,7 @@ const ResponseSchemaComponent = ({ title, body, style }) => {
|
|
|
57
57
|
"div",
|
|
58
58
|
null,
|
|
59
59
|
(0, Translate_1.translate)({
|
|
60
|
-
id:
|
|
60
|
+
id: "theme.openapi.schema.noSchema",
|
|
61
61
|
message: "No schema",
|
|
62
62
|
})
|
|
63
63
|
)
|
|
@@ -83,29 +83,31 @@ const ResponseSchemaComponent = ({ title, body, style }) => {
|
|
|
83
83
|
open: true,
|
|
84
84
|
style: style,
|
|
85
85
|
summary: react_1.default.createElement(
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
"summary",
|
|
87
|
+
{
|
|
88
|
+
className:
|
|
89
|
+
"openapi-markdown__details-summary--with-control",
|
|
90
|
+
},
|
|
88
91
|
react_1.default.createElement(
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
)
|
|
92
|
+
"strong",
|
|
93
|
+
{
|
|
94
|
+
className:
|
|
95
|
+
"openapi-markdown__details-summary-response",
|
|
96
|
+
},
|
|
97
|
+
title,
|
|
98
|
+
body.required === true &&
|
|
99
|
+
react_1.default.createElement(
|
|
100
|
+
"span",
|
|
101
|
+
{ className: "openapi-schema__required" },
|
|
102
|
+
(0, Translate_1.translate)({
|
|
103
|
+
id: "theme.openapi.schemaItem.required",
|
|
104
|
+
message: "required",
|
|
105
|
+
})
|
|
106
|
+
)
|
|
107
|
+
),
|
|
108
|
+
react_1.default.createElement(
|
|
109
|
+
SchemaExpansion_1.default,
|
|
110
|
+
null
|
|
109
111
|
)
|
|
110
112
|
),
|
|
111
113
|
},
|
|
@@ -77,85 +77,14 @@ const DiscriminatorTabs_1 = __importDefault(
|
|
|
77
77
|
require("@theme/DiscriminatorTabs")
|
|
78
78
|
);
|
|
79
79
|
const Markdown_1 = __importDefault(require("@theme/Markdown"));
|
|
80
|
+
const normalize_1 = require("@theme/Schema/normalize");
|
|
81
|
+
const SchemaExpansion_1 = require("@theme/SchemaExpansion");
|
|
80
82
|
const SchemaItem_1 = __importDefault(require("@theme/SchemaItem"));
|
|
81
83
|
const SchemaTabs_1 = __importDefault(require("@theme/SchemaTabs"));
|
|
82
84
|
const TabItem_1 = __importDefault(require("@theme/TabItem"));
|
|
83
|
-
const translationIds_1 = require("@theme/translationIds");
|
|
84
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
85
|
-
const allof_merge_1 = require("allof-merge");
|
|
86
85
|
const clsx_1 = __importDefault(require("clsx"));
|
|
87
86
|
const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
|
|
88
87
|
const schema_1 = require("../../markdown/schema");
|
|
89
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
90
|
-
// const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
|
|
91
|
-
const mergeAllOf = (allOf) => {
|
|
92
|
-
const onMergeError = (msg) => {
|
|
93
|
-
console.warn(msg);
|
|
94
|
-
};
|
|
95
|
-
const mergedSchemas = (0, allof_merge_1.merge)(allOf, { onMergeError });
|
|
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;
|
|
158
|
-
};
|
|
159
88
|
// Renders string as markdown, useful for descriptions and qualifiers
|
|
160
89
|
const MarkdownWrapper = ({ text }) => {
|
|
161
90
|
return react_1.default.createElement(
|
|
@@ -199,7 +128,7 @@ const Summary = ({ name, schemaName, schema, required }) => {
|
|
|
199
128
|
"span",
|
|
200
129
|
{ className: "openapi-schema__nullable" },
|
|
201
130
|
(0, Translate_1.translate)({
|
|
202
|
-
id:
|
|
131
|
+
id: "theme.openapi.schemaItem.nullable",
|
|
203
132
|
message: "nullable",
|
|
204
133
|
})
|
|
205
134
|
),
|
|
@@ -208,7 +137,7 @@ const Summary = ({ name, schemaName, schema, required }) => {
|
|
|
208
137
|
"span",
|
|
209
138
|
{ className: "openapi-schema__required" },
|
|
210
139
|
(0, Translate_1.translate)({
|
|
211
|
-
id:
|
|
140
|
+
id: "theme.openapi.schemaItem.required",
|
|
212
141
|
message: "required",
|
|
213
142
|
})
|
|
214
143
|
),
|
|
@@ -217,7 +146,7 @@ const Summary = ({ name, schemaName, schema, required }) => {
|
|
|
217
146
|
"span",
|
|
218
147
|
{ className: "openapi-schema__deprecated" },
|
|
219
148
|
(0, Translate_1.translate)({
|
|
220
|
-
id:
|
|
149
|
+
id: "theme.openapi.schemaItem.deprecated",
|
|
221
150
|
message: "deprecated",
|
|
222
151
|
})
|
|
223
152
|
)
|
|
@@ -234,11 +163,11 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
|
|
|
234
163
|
}
|
|
235
164
|
const type = schema.oneOf
|
|
236
165
|
? (0, Translate_1.translate)({
|
|
237
|
-
id:
|
|
166
|
+
id: "theme.openapi.schemaItem.oneOf",
|
|
238
167
|
message: "oneOf",
|
|
239
168
|
})
|
|
240
169
|
: (0, Translate_1.translate)({
|
|
241
|
-
id:
|
|
170
|
+
id: "theme.openapi.schemaItem.anyOf",
|
|
242
171
|
message: "anyOf",
|
|
243
172
|
});
|
|
244
173
|
// Generate a unique ID for this anyOf/oneOf to prevent tab value collisions
|
|
@@ -285,12 +214,12 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
|
|
|
285
214
|
if (!label) {
|
|
286
215
|
if (anyOneSchema.oneOf) {
|
|
287
216
|
label = (0, Translate_1.translate)({
|
|
288
|
-
id:
|
|
217
|
+
id: "theme.openapi.schemaItem.oneOf",
|
|
289
218
|
message: "oneOf",
|
|
290
219
|
});
|
|
291
220
|
} else if (anyOneSchema.anyOf) {
|
|
292
221
|
label = (0, Translate_1.translate)({
|
|
293
|
-
id:
|
|
222
|
+
id: "theme.openapi.schemaItem.anyOf",
|
|
294
223
|
message: "anyOf",
|
|
295
224
|
});
|
|
296
225
|
} else {
|
|
@@ -306,6 +235,14 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
|
|
|
306
235
|
react_1.default.createElement(
|
|
307
236
|
TabItem_1.default,
|
|
308
237
|
{ key: index, label: label, value: `${uniqueId}-${index}-item` },
|
|
238
|
+
anyOneSchema.description &&
|
|
239
|
+
react_1.default.createElement(
|
|
240
|
+
"div",
|
|
241
|
+
{ style: { marginLeft: "1rem" } },
|
|
242
|
+
react_1.default.createElement(MarkdownWrapper, {
|
|
243
|
+
text: anyOneSchema.description,
|
|
244
|
+
})
|
|
245
|
+
),
|
|
309
246
|
(isPrimitive(anyOneSchema) || anyOneSchema.const) &&
|
|
310
247
|
react_1.default.createElement(SchemaItem_1.default, {
|
|
311
248
|
collapsible: false,
|
|
@@ -459,7 +396,7 @@ const PropertyDiscriminator = ({
|
|
|
459
396
|
"span",
|
|
460
397
|
{ className: "openapi-schema__required" },
|
|
461
398
|
(0, Translate_1.translate)({
|
|
462
|
-
id:
|
|
399
|
+
id: "theme.openapi.schemaItem.required",
|
|
463
400
|
message: "required",
|
|
464
401
|
})
|
|
465
402
|
)
|
|
@@ -484,6 +421,14 @@ const PropertyDiscriminator = ({
|
|
|
484
421
|
react_1.default.createElement(
|
|
485
422
|
TabItem_1.default,
|
|
486
423
|
{ key: index, label: key, value: `${index}-item-discriminator` },
|
|
424
|
+
discriminator.mapping[key]?.description &&
|
|
425
|
+
react_1.default.createElement(
|
|
426
|
+
"div",
|
|
427
|
+
{ style: { marginLeft: "1rem" } },
|
|
428
|
+
react_1.default.createElement(MarkdownWrapper, {
|
|
429
|
+
text: discriminator.mapping[key].description,
|
|
430
|
+
})
|
|
431
|
+
),
|
|
487
432
|
react_1.default.createElement(SchemaNode, {
|
|
488
433
|
schema: discriminator.mapping[key],
|
|
489
434
|
schemaType: schemaType,
|
|
@@ -513,11 +458,13 @@ const PropertyDiscriminator = ({
|
|
|
513
458
|
const DiscriminatorNode = ({ discriminator, schema, schemaType }) => {
|
|
514
459
|
let discriminatedSchemas = {};
|
|
515
460
|
let inferredMapping = {};
|
|
516
|
-
// Search for the discriminator property in the schema, including nested
|
|
461
|
+
// Search for the discriminator property in the schema, including nested
|
|
462
|
+
// structures. Cached recursive lookup replaces the O(subtree) findProperty
|
|
463
|
+
// walk that caused #1525's O(N^2) render cost.
|
|
517
464
|
const discriminatorProperty =
|
|
518
|
-
|
|
465
|
+
(0, normalize_1.findPropertyDeep)(schema, discriminator.propertyName) ?? {};
|
|
519
466
|
if (schema.allOf) {
|
|
520
|
-
const mergedSchemas = mergeAllOf(schema);
|
|
467
|
+
const mergedSchemas = (0, normalize_1.mergeAllOf)(schema);
|
|
521
468
|
if (mergedSchemas.oneOf || mergedSchemas.anyOf) {
|
|
522
469
|
discriminatedSchemas = mergedSchemas.oneOf || mergedSchemas.anyOf;
|
|
523
470
|
}
|
|
@@ -537,7 +484,7 @@ const DiscriminatorNode = ({ discriminator, schema, schemaType }) => {
|
|
|
537
484
|
// Handle discriminated schema with allOf
|
|
538
485
|
let mergedSubSchema = {};
|
|
539
486
|
if (subSchema.allOf) {
|
|
540
|
-
mergedSubSchema = mergeAllOf(subSchema);
|
|
487
|
+
mergedSubSchema = (0, normalize_1.mergeAllOf)(subSchema);
|
|
541
488
|
}
|
|
542
489
|
const subProperties = subSchema.properties || mergedSubSchema.properties;
|
|
543
490
|
// Add a safeguard check to avoid referencing subProperties if it's undefined
|
|
@@ -578,6 +525,17 @@ const DiscriminatorNode = ({ discriminator, schema, schemaType }) => {
|
|
|
578
525
|
const AdditionalProperties = ({ schema, schemaType }) => {
|
|
579
526
|
const additionalProperties = schema.additionalProperties;
|
|
580
527
|
if (!additionalProperties) return null;
|
|
528
|
+
if ((0, normalize_1.isCircularMarker)(additionalProperties)) {
|
|
529
|
+
return react_1.default.createElement(SchemaItem_1.default, {
|
|
530
|
+
name: "property name*",
|
|
531
|
+
required: false,
|
|
532
|
+
schemaName: additionalProperties,
|
|
533
|
+
schema: additionalProperties,
|
|
534
|
+
collapsible: false,
|
|
535
|
+
discriminator: false,
|
|
536
|
+
children: null,
|
|
537
|
+
});
|
|
538
|
+
}
|
|
581
539
|
// Handle free-form objects
|
|
582
540
|
if (
|
|
583
541
|
additionalProperties === true ||
|
|
@@ -644,13 +602,18 @@ const SchemaNodeDetails = ({
|
|
|
644
602
|
schemaType,
|
|
645
603
|
schemaPath,
|
|
646
604
|
}) => {
|
|
605
|
+
const depth = (0, SchemaExpansion_1.useSchemaDepth)();
|
|
606
|
+
const { level } = (0, SchemaExpansion_1.useSchemaExpansion)();
|
|
607
|
+
const defaultOpen = depth < level;
|
|
647
608
|
return react_1.default.createElement(
|
|
648
609
|
SchemaItem_1.default,
|
|
649
610
|
{ collapsible: true },
|
|
650
611
|
react_1.default.createElement(
|
|
651
612
|
Details_1.default,
|
|
652
613
|
{
|
|
614
|
+
key: `level-${level}`,
|
|
653
615
|
className: "openapi-markdown__details",
|
|
616
|
+
open: defaultOpen,
|
|
654
617
|
summary: react_1.default.createElement(Summary, {
|
|
655
618
|
name: name,
|
|
656
619
|
schemaName: schemaName,
|
|
@@ -669,20 +632,40 @@ const SchemaNodeDetails = ({
|
|
|
669
632
|
react_1.default.createElement(MarkdownWrapper, {
|
|
670
633
|
text: (0, schema_1.getQualifierMessage)(schema),
|
|
671
634
|
}),
|
|
672
|
-
react_1.default.createElement(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
635
|
+
react_1.default.createElement(
|
|
636
|
+
SchemaExpansion_1.SchemaDepthProvider,
|
|
637
|
+
{ depth: depth + 1 },
|
|
638
|
+
react_1.default.createElement(SchemaNode, {
|
|
639
|
+
schema: schema,
|
|
640
|
+
schemaType: schemaType,
|
|
641
|
+
schemaPath: schemaPath,
|
|
642
|
+
})
|
|
643
|
+
)
|
|
677
644
|
)
|
|
678
645
|
)
|
|
679
646
|
);
|
|
680
647
|
};
|
|
681
648
|
const Items = ({ schema, schemaType, schemaPath }) => {
|
|
649
|
+
if ((0, normalize_1.isCircularMarker)(schema.items)) {
|
|
650
|
+
return react_1.default.createElement(
|
|
651
|
+
"div",
|
|
652
|
+
{ style: { marginLeft: ".5rem" } },
|
|
653
|
+
react_1.default.createElement(ArrayBrackets_1.OpeningArrayBracket, null),
|
|
654
|
+
react_1.default.createElement(SchemaItem_1.default, {
|
|
655
|
+
collapsible: false,
|
|
656
|
+
name: "",
|
|
657
|
+
schemaName: schema.items,
|
|
658
|
+
schema: schema.items,
|
|
659
|
+
discriminator: false,
|
|
660
|
+
children: null,
|
|
661
|
+
}),
|
|
662
|
+
react_1.default.createElement(ArrayBrackets_1.ClosingArrayBracket, null)
|
|
663
|
+
);
|
|
664
|
+
}
|
|
682
665
|
// Process schema.items to handle allOf merging
|
|
683
666
|
let itemsSchema = schema.items;
|
|
684
667
|
if (schema.items?.allOf) {
|
|
685
|
-
itemsSchema = mergeAllOf(schema.items);
|
|
668
|
+
itemsSchema = (0, normalize_1.mergeAllOf)(schema.items);
|
|
686
669
|
}
|
|
687
670
|
// Handle complex schemas with multiple schema types
|
|
688
671
|
const hasOneOfAnyOf = itemsSchema?.oneOf || itemsSchema?.anyOf;
|
|
@@ -691,17 +674,25 @@ const Items = ({ schema, schemaType, schemaPath }) => {
|
|
|
691
674
|
// Build the items schema path
|
|
692
675
|
const itemsSchemaPath = schemaPath ? `${schemaPath}.items` : undefined;
|
|
693
676
|
if (hasOneOfAnyOf || hasProperties || hasAdditionalProperties) {
|
|
677
|
+
// Fold sibling properties into each oneOf/anyOf branch to avoid duplicate
|
|
678
|
+
// property rendering. See issue #1218.
|
|
679
|
+
const renderSchema =
|
|
680
|
+
hasOneOfAnyOf && hasProperties
|
|
681
|
+
? (0, normalize_1.foldSiblingsIntoBranches)(itemsSchema)
|
|
682
|
+
: itemsSchema;
|
|
683
|
+
const renderHasProperties =
|
|
684
|
+
hasOneOfAnyOf && hasProperties ? false : hasProperties;
|
|
694
685
|
return react_1.default.createElement(
|
|
695
686
|
react_1.default.Fragment,
|
|
696
687
|
null,
|
|
697
688
|
react_1.default.createElement(ArrayBrackets_1.OpeningArrayBracket, null),
|
|
698
689
|
hasOneOfAnyOf &&
|
|
699
690
|
react_1.default.createElement(AnyOneOf, {
|
|
700
|
-
schema:
|
|
691
|
+
schema: renderSchema,
|
|
701
692
|
schemaType: schemaType,
|
|
702
693
|
schemaPath: itemsSchemaPath,
|
|
703
694
|
}),
|
|
704
|
-
|
|
695
|
+
renderHasProperties &&
|
|
705
696
|
react_1.default.createElement(Properties, {
|
|
706
697
|
schema: itemsSchema,
|
|
707
698
|
schemaType: schemaType,
|
|
@@ -771,6 +762,17 @@ const SchemaEdge = ({
|
|
|
771
762
|
) {
|
|
772
763
|
return null;
|
|
773
764
|
}
|
|
765
|
+
if ((0, normalize_1.isCircularMarker)(schema)) {
|
|
766
|
+
return react_1.default.createElement(SchemaItem_1.default, {
|
|
767
|
+
collapsible: false,
|
|
768
|
+
name: name,
|
|
769
|
+
required: Array.isArray(required) ? required.includes(name) : required,
|
|
770
|
+
schemaName: schema,
|
|
771
|
+
schema: schema,
|
|
772
|
+
discriminator: false,
|
|
773
|
+
children: null,
|
|
774
|
+
});
|
|
775
|
+
}
|
|
774
776
|
const schemaName = (0, schema_1.getSchemaName)(schema);
|
|
775
777
|
if (discriminator && discriminator.propertyName === name) {
|
|
776
778
|
return react_1.default.createElement(PropertyDiscriminator, {
|
|
@@ -838,6 +840,17 @@ const SchemaEdge = ({
|
|
|
838
840
|
schemaPath: schemaPath,
|
|
839
841
|
});
|
|
840
842
|
}
|
|
843
|
+
if ((0, normalize_1.isCircularMarker)(schema.items)) {
|
|
844
|
+
return react_1.default.createElement(SchemaNodeDetails, {
|
|
845
|
+
name: name,
|
|
846
|
+
schemaName: schemaName,
|
|
847
|
+
required: required,
|
|
848
|
+
nullable: schema.nullable,
|
|
849
|
+
schema: schema,
|
|
850
|
+
schemaType: schemaType,
|
|
851
|
+
schemaPath: schemaPath,
|
|
852
|
+
});
|
|
853
|
+
}
|
|
841
854
|
if (schema.allOf) {
|
|
842
855
|
// handle circular properties
|
|
843
856
|
if (
|
|
@@ -856,7 +869,7 @@ const SchemaEdge = ({
|
|
|
856
869
|
children: null,
|
|
857
870
|
});
|
|
858
871
|
}
|
|
859
|
-
const mergedSchemas = mergeAllOf(schema);
|
|
872
|
+
const mergedSchemas = (0, normalize_1.mergeAllOf)(schema);
|
|
860
873
|
if (
|
|
861
874
|
(schemaType === "request" && mergedSchemas.readOnly) ||
|
|
862
875
|
(schemaType === "response" && mergedSchemas.writeOnly)
|
|
@@ -918,22 +931,32 @@ const SchemaEdge = ({
|
|
|
918
931
|
});
|
|
919
932
|
};
|
|
920
933
|
function renderChildren(schema, schemaType, schemaPath) {
|
|
934
|
+
// Fold sibling properties into each oneOf/anyOf branch to avoid duplicate
|
|
935
|
+
// property rendering. See issue #1218.
|
|
936
|
+
const hasOneOfAnyOf = !!(schema.oneOf || schema.anyOf);
|
|
937
|
+
const hasProperties = !!schema.properties;
|
|
938
|
+
const folded =
|
|
939
|
+
hasOneOfAnyOf && hasProperties
|
|
940
|
+
? (0, normalize_1.foldSiblingsIntoBranches)(schema)
|
|
941
|
+
: schema;
|
|
942
|
+
const renderProperties =
|
|
943
|
+
hasOneOfAnyOf && hasProperties ? false : hasProperties;
|
|
921
944
|
return react_1.default.createElement(
|
|
922
945
|
react_1.default.Fragment,
|
|
923
946
|
null,
|
|
924
|
-
|
|
947
|
+
folded.oneOf &&
|
|
925
948
|
react_1.default.createElement(AnyOneOf, {
|
|
926
|
-
schema:
|
|
949
|
+
schema: folded,
|
|
927
950
|
schemaType: schemaType,
|
|
928
951
|
schemaPath: schemaPath,
|
|
929
952
|
}),
|
|
930
|
-
|
|
953
|
+
folded.anyOf &&
|
|
931
954
|
react_1.default.createElement(AnyOneOf, {
|
|
932
|
-
schema:
|
|
955
|
+
schema: folded,
|
|
933
956
|
schemaType: schemaType,
|
|
934
957
|
schemaPath: schemaPath,
|
|
935
958
|
}),
|
|
936
|
-
|
|
959
|
+
renderProperties &&
|
|
937
960
|
react_1.default.createElement(Properties, {
|
|
938
961
|
schema: schema,
|
|
939
962
|
schemaType: schemaType,
|
|
@@ -952,7 +975,11 @@ function renderChildren(schema, schemaType, schemaPath) {
|
|
|
952
975
|
})
|
|
953
976
|
);
|
|
954
977
|
}
|
|
955
|
-
const SchemaNode = ({ schema, schemaType, schemaPath }) => {
|
|
978
|
+
const SchemaNode = ({ schema: rawSchema, schemaType, schemaPath }) => {
|
|
979
|
+
const schema = (0, react_1.useMemo)(
|
|
980
|
+
() => (0, normalize_1.normalizeSchema)(rawSchema),
|
|
981
|
+
[rawSchema]
|
|
982
|
+
);
|
|
956
983
|
if (
|
|
957
984
|
(schemaType === "request" && schema.readOnly) ||
|
|
958
985
|
(schemaType === "response" && schema.writeOnly)
|
|
@@ -960,12 +987,13 @@ const SchemaNode = ({ schema, schemaType, schemaPath }) => {
|
|
|
960
987
|
return null;
|
|
961
988
|
}
|
|
962
989
|
// Resolve discriminator recursively so nested oneOf/anyOf/allOf compositions
|
|
963
|
-
// can still render discriminator tabs.
|
|
990
|
+
// can still render discriminator tabs. Cached via getDiscriminator so per-
|
|
991
|
+
// render cost is O(1) amortized (see #1525).
|
|
964
992
|
let workingSchema = schema;
|
|
965
993
|
const resolvedDiscriminator =
|
|
966
|
-
schema.discriminator ??
|
|
994
|
+
schema.discriminator ?? (0, normalize_1.getDiscriminator)(schema);
|
|
967
995
|
if (schema.allOf && !schema.discriminator && resolvedDiscriminator) {
|
|
968
|
-
workingSchema = mergeAllOf(schema);
|
|
996
|
+
workingSchema = (0, normalize_1.mergeAllOf)(schema);
|
|
969
997
|
}
|
|
970
998
|
if (!workingSchema.discriminator && resolvedDiscriminator) {
|
|
971
999
|
workingSchema.discriminator = resolvedDiscriminator;
|
|
@@ -985,7 +1013,7 @@ const SchemaNode = ({ schema, schemaType, schemaPath }) => {
|
|
|
985
1013
|
const hasMultipleChoices = oneOfItems.length > 1;
|
|
986
1014
|
if (hasMultipleChoices) {
|
|
987
1015
|
// Render each oneOf/anyOf constraint first, then shared properties
|
|
988
|
-
const mergedSchemas = mergeAllOf(schema);
|
|
1016
|
+
const mergedSchemas = (0, normalize_1.mergeAllOf)(schema);
|
|
989
1017
|
if (
|
|
990
1018
|
(schemaType === "request" && mergedSchemas.readOnly) ||
|
|
991
1019
|
(schemaType === "response" && mergedSchemas.writeOnly)
|
|
@@ -1027,29 +1055,39 @@ const SchemaNode = ({ schema, schemaType, schemaPath }) => {
|
|
|
1027
1055
|
);
|
|
1028
1056
|
}
|
|
1029
1057
|
// For other allOf cases, use standard merge behavior
|
|
1030
|
-
const mergedSchemas = mergeAllOf(schema);
|
|
1058
|
+
const mergedSchemas = (0, normalize_1.mergeAllOf)(schema);
|
|
1031
1059
|
if (
|
|
1032
1060
|
(schemaType === "request" && mergedSchemas.readOnly) ||
|
|
1033
1061
|
(schemaType === "response" && mergedSchemas.writeOnly)
|
|
1034
1062
|
) {
|
|
1035
1063
|
return null;
|
|
1036
1064
|
}
|
|
1065
|
+
// Fold sibling properties into each oneOf/anyOf branch to avoid duplicate
|
|
1066
|
+
// property rendering. See issue #1218.
|
|
1067
|
+
const hasOneOfAnyOf = !!(mergedSchemas.oneOf || mergedSchemas.anyOf);
|
|
1068
|
+
const hasProperties = !!mergedSchemas.properties;
|
|
1069
|
+
const folded =
|
|
1070
|
+
hasOneOfAnyOf && hasProperties
|
|
1071
|
+
? (0, normalize_1.foldSiblingsIntoBranches)(mergedSchemas)
|
|
1072
|
+
: mergedSchemas;
|
|
1073
|
+
const renderProperties =
|
|
1074
|
+
hasOneOfAnyOf && hasProperties ? false : hasProperties;
|
|
1037
1075
|
return react_1.default.createElement(
|
|
1038
1076
|
"div",
|
|
1039
1077
|
null,
|
|
1040
|
-
|
|
1078
|
+
folded.oneOf &&
|
|
1041
1079
|
react_1.default.createElement(AnyOneOf, {
|
|
1042
|
-
schema:
|
|
1080
|
+
schema: folded,
|
|
1043
1081
|
schemaType: schemaType,
|
|
1044
1082
|
schemaPath: schemaPath,
|
|
1045
1083
|
}),
|
|
1046
|
-
|
|
1084
|
+
folded.anyOf &&
|
|
1047
1085
|
react_1.default.createElement(AnyOneOf, {
|
|
1048
|
-
schema:
|
|
1086
|
+
schema: folded,
|
|
1049
1087
|
schemaType: schemaType,
|
|
1050
1088
|
schemaPath: schemaPath,
|
|
1051
1089
|
}),
|
|
1052
|
-
|
|
1090
|
+
renderProperties &&
|
|
1053
1091
|
react_1.default.createElement(Properties, {
|
|
1054
1092
|
schema: mergedSchemas,
|
|
1055
1093
|
schemaType: schemaType,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export declare function isCircularMarker(value: unknown): value is string;
|
|
2
|
+
export declare function mergeAllOf(schema: any): any;
|
|
3
|
+
/**
|
|
4
|
+
* Fold sibling fields into each oneOf/anyOf branch via allOf-merge so each
|
|
5
|
+
* branch is self-contained. See #1218.
|
|
6
|
+
*
|
|
7
|
+
* Skipped when a discriminator is present: DiscriminatorNode already renders
|
|
8
|
+
* sibling properties at the top level, and folding would duplicate the
|
|
9
|
+
* discriminator metadata into each branch (causing nested DiscriminatorNode
|
|
10
|
+
* renders inside tabs — see #1525 follow-up).
|
|
11
|
+
*
|
|
12
|
+
* Called by normalizeSchema after allOf resolution. Uses mergeAllOf internally
|
|
13
|
+
* to compose `{ allOf: [siblings, branch] }` per branch — the WeakMap caches
|
|
14
|
+
* in stripConflictingAdditionalProps prevent redundant work on shared subtrees.
|
|
15
|
+
*/
|
|
16
|
+
export declare function foldSiblingsIntoBranches(schema: any): any;
|
|
17
|
+
export declare function getDiscriminator(schema: any): any | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Cached recursive property lookup. Searches schema.properties first, then
|
|
20
|
+
* into oneOf/anyOf/allOf branches. Returns O(1) on repeated calls with the
|
|
21
|
+
* same (schema, propertyName) pair — replaces the O(subtree) findProperty
|
|
22
|
+
* walk that caused #1525's O(N^2) render cost.
|
|
23
|
+
*/
|
|
24
|
+
export declare function findPropertyDeep(schema: any, propertyName: string): any | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Identity-stable schema pass-through. Returns the input as-is so SchemaNode
|
|
27
|
+
* useMemo dependencies stay stable across renders.
|
|
28
|
+
*
|
|
29
|
+
* Earlier iterations of this function eagerly merged allOf and folded
|
|
30
|
+
* siblings into oneOf/anyOf branches, but those operations need to stay
|
|
31
|
+
* conditional inside SchemaNode and DiscriminatorNode — eager versions
|
|
32
|
+
* caused cartesian product expansion (allOf with multiple oneOfs) and
|
|
33
|
+
* double-folding regressions. The render-time helpers below
|
|
34
|
+
* (mergeAllOf, foldSiblingsIntoBranches) are still cached via the WeakMap
|
|
35
|
+
* inside stripConflictingAdditionalProps, so per-render cost stays bounded.
|
|
36
|
+
*
|
|
37
|
+
* The perf win for #1525 comes from getDiscriminator's WeakMap cache
|
|
38
|
+
* replacing the O(subtree) findDiscriminator walk, not from eager
|
|
39
|
+
* normalization here.
|
|
40
|
+
*/
|
|
41
|
+
export declare function normalizeSchema(schema: any): any;
|