docusaurus-theme-openapi-docs 5.1.1 → 5.1.3
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.
|
@@ -254,6 +254,7 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
|
|
|
254
254
|
}),
|
|
255
255
|
anyOneSchema.type === "object" &&
|
|
256
256
|
!anyOneSchema.properties &&
|
|
257
|
+
!anyOneSchema.additionalProperties &&
|
|
257
258
|
!anyOneSchema.allOf &&
|
|
258
259
|
!anyOneSchema.oneOf &&
|
|
259
260
|
!anyOneSchema.anyOf &&
|
|
@@ -267,11 +268,23 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
|
|
|
267
268
|
}),
|
|
268
269
|
(anyOneSchema.type === "object" || !anyOneSchema.type) &&
|
|
269
270
|
anyOneSchema.properties &&
|
|
271
|
+
!anyOneSchema.oneOf &&
|
|
272
|
+
!anyOneSchema.anyOf &&
|
|
273
|
+
!anyOneSchema.allOf &&
|
|
270
274
|
react_1.default.createElement(Properties, {
|
|
271
275
|
schema: anyOneSchema,
|
|
272
276
|
schemaType: schemaType,
|
|
273
277
|
schemaPath: childSchemaPath,
|
|
274
278
|
}),
|
|
279
|
+
(anyOneSchema.type === "object" || !anyOneSchema.type) &&
|
|
280
|
+
anyOneSchema.additionalProperties &&
|
|
281
|
+
!anyOneSchema.oneOf &&
|
|
282
|
+
!anyOneSchema.anyOf &&
|
|
283
|
+
!anyOneSchema.allOf &&
|
|
284
|
+
react_1.default.createElement(AdditionalProperties, {
|
|
285
|
+
schema: anyOneSchema,
|
|
286
|
+
schemaType: schemaType,
|
|
287
|
+
}),
|
|
275
288
|
anyOneSchema.allOf &&
|
|
276
289
|
react_1.default.createElement(SchemaNode, {
|
|
277
290
|
schema: anyOneSchema,
|
|
@@ -996,7 +1009,11 @@ const SchemaNode = ({ schema: rawSchema, schemaType, schemaPath }) => {
|
|
|
996
1009
|
workingSchema = (0, normalize_1.mergeAllOf)(schema);
|
|
997
1010
|
}
|
|
998
1011
|
if (!workingSchema.discriminator && resolvedDiscriminator) {
|
|
999
|
-
|
|
1012
|
+
// Clone: getDiscriminator returns a nested branch's discriminator by
|
|
1013
|
+
// reference, and DiscriminatorNode mutates `.mapping` when inferring
|
|
1014
|
+
// variants. Without cloning, a branch that declares its own discriminator
|
|
1015
|
+
// gets a mapping pointing back to itself and recurses forever.
|
|
1016
|
+
workingSchema.discriminator = { ...resolvedDiscriminator };
|
|
1000
1017
|
}
|
|
1001
1018
|
if (workingSchema.discriminator) {
|
|
1002
1019
|
const { discriminator } = workingSchema;
|
|
@@ -140,6 +140,74 @@ describe("foldSiblingsIntoBranches", () => {
|
|
|
140
140
|
expect(result.items).toBeUndefined();
|
|
141
141
|
expect(result.oneOf).toHaveLength(1);
|
|
142
142
|
});
|
|
143
|
+
// Regression for #1548 (property duplication in nested anyOf-of-oneOf):
|
|
144
|
+
// when the outer schema is `{ properties, anyOf: [{oneOf:[...]}, ...] }`,
|
|
145
|
+
// fold merges the outer properties into each anyOf branch, giving each
|
|
146
|
+
// branch its own inner `oneOf` alongside merged properties. The AnyOneOf
|
|
147
|
+
// render layer then delegates the branch to SchemaNode, which folds again
|
|
148
|
+
// into each inner variant. If AnyOneOf were to *also* render the branch's
|
|
149
|
+
// properties directly at that outer level, the same fields would appear
|
|
150
|
+
// twice per selected inner variant tab — hence the check in Schema/index.tsx
|
|
151
|
+
// that skips <Properties> when the branch has a nested oneOf/anyOf/allOf.
|
|
152
|
+
it("folds outer properties into each anyOf branch when branches contain nested oneOf", () => {
|
|
153
|
+
const schema = {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {
|
|
156
|
+
name: { type: "string" },
|
|
157
|
+
default_value: { type: "string" },
|
|
158
|
+
},
|
|
159
|
+
anyOf: [
|
|
160
|
+
{
|
|
161
|
+
oneOf: [
|
|
162
|
+
{
|
|
163
|
+
title: "aggregate_group",
|
|
164
|
+
properties: {
|
|
165
|
+
aggregate_group: { type: "string" },
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
title: "tap",
|
|
170
|
+
properties: {
|
|
171
|
+
tap: { type: "object" },
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
oneOf: [
|
|
178
|
+
{
|
|
179
|
+
title: "folder",
|
|
180
|
+
properties: { folder: { type: "string" } },
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
title: "snippet",
|
|
184
|
+
properties: { snippet: { type: "string" } },
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
const outer = (0, normalize_1.foldSiblingsIntoBranches)(schema);
|
|
191
|
+
expect(outer.properties).toBeUndefined();
|
|
192
|
+
expect(outer.anyOf).toHaveLength(2);
|
|
193
|
+
for (const branch of outer.anyOf) {
|
|
194
|
+
// Each anyOf branch retains its own inner oneOf and picks up the
|
|
195
|
+
// merged outer properties as siblings — this is the shape that
|
|
196
|
+
// AnyOneOf must NOT render <Properties> for directly, because
|
|
197
|
+
// SchemaNode will fold them into the inner variants below.
|
|
198
|
+
expect(branch.oneOf).toBeDefined();
|
|
199
|
+
expect(branch.properties.name).toBeDefined();
|
|
200
|
+
expect(branch.properties.default_value).toBeDefined();
|
|
201
|
+
const inner = (0, normalize_1.foldSiblingsIntoBranches)(branch);
|
|
202
|
+
expect(inner.properties).toBeUndefined();
|
|
203
|
+
expect(inner.oneOf).toBeDefined();
|
|
204
|
+
for (const variant of inner.oneOf) {
|
|
205
|
+
// Merged outer properties appear exactly once — inside each variant.
|
|
206
|
+
expect(variant.properties.name).toBeDefined();
|
|
207
|
+
expect(variant.properties.default_value).toBeDefined();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
});
|
|
143
211
|
});
|
|
144
212
|
describe("getDiscriminator", () => {
|
|
145
213
|
it("returns direct discriminator", () => {
|
|
@@ -164,7 +164,7 @@ function parseCodeLinesFromContent(code, params) {
|
|
|
164
164
|
.filter((d) => d.block)
|
|
165
165
|
.map(({ className, block }) => [block.end, className])
|
|
166
166
|
);
|
|
167
|
-
for (let lineNumber = 0; lineNumber < lines.length;
|
|
167
|
+
for (let lineNumber = 0; lineNumber < lines.length;) {
|
|
168
168
|
const line = lines[lineNumber];
|
|
169
169
|
const match = line.match(directiveRegex);
|
|
170
170
|
if (!match) {
|
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": "5.1.
|
|
4
|
+
"version": "5.1.3",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/postman-collection": "^3.5.11",
|
|
39
39
|
"@types/react-modal": "^3.16.3",
|
|
40
40
|
"concurrently": "^10.0.3",
|
|
41
|
-
"docusaurus-plugin-openapi-docs": "^5.1.
|
|
41
|
+
"docusaurus-plugin-openapi-docs": "^5.1.3",
|
|
42
42
|
"docusaurus-plugin-sass": "^0.2.6",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.1"
|
|
44
44
|
},
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"crypto-js": "^4.2.0",
|
|
53
53
|
"file-saver": "^2.0.5",
|
|
54
54
|
"lodash": "^4.17.21",
|
|
55
|
-
"pako": "^
|
|
55
|
+
"pako": "^3.0.1",
|
|
56
56
|
"path-browserify": "^1.0.1",
|
|
57
57
|
"postman-code-generators": "^2.0.0",
|
|
58
58
|
"postman-collection": "^5.0.2",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"rehype-raw": "^7.0.0",
|
|
68
68
|
"remark-gfm": "4.0.1",
|
|
69
69
|
"sass": "^1.89.2",
|
|
70
|
-
"sass-loader": "^
|
|
70
|
+
"sass-loader": "^17.0.0",
|
|
71
71
|
"unist-util-visit": "^5.0.0",
|
|
72
72
|
"url": "^0.11.4",
|
|
73
73
|
"xml-formatter": "^3.6.6"
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"engines": {
|
|
83
83
|
"node": ">=14"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "d5af4f22e951712e084df8b7c513a1708e56d372"
|
|
86
86
|
}
|
|
@@ -236,6 +236,7 @@ const AnyOneOf: React.FC<SchemaProps> = ({
|
|
|
236
236
|
{/* Handle empty object as a primitive type */}
|
|
237
237
|
{anyOneSchema.type === "object" &&
|
|
238
238
|
!anyOneSchema.properties &&
|
|
239
|
+
!anyOneSchema.additionalProperties &&
|
|
239
240
|
!anyOneSchema.allOf &&
|
|
240
241
|
!anyOneSchema.oneOf &&
|
|
241
242
|
!anyOneSchema.anyOf && (
|
|
@@ -251,14 +252,33 @@ const AnyOneOf: React.FC<SchemaProps> = ({
|
|
|
251
252
|
|
|
252
253
|
{/* Handle actual object types with properties or nested schemas */}
|
|
253
254
|
{/* Note: In OpenAPI, properties implies type: object even if not explicitly set */}
|
|
255
|
+
{/* When the branch also has a nested oneOf/anyOf/allOf, skip
|
|
256
|
+
Properties here and delegate to SchemaNode below —
|
|
257
|
+
foldSiblingsIntoBranches will merge these properties into
|
|
258
|
+
each inner variant, so rendering them inline as well would
|
|
259
|
+
duplicate them per variant tab. See #1548. */}
|
|
254
260
|
{(anyOneSchema.type === "object" || !anyOneSchema.type) &&
|
|
255
|
-
anyOneSchema.properties &&
|
|
261
|
+
anyOneSchema.properties &&
|
|
262
|
+
!anyOneSchema.oneOf &&
|
|
263
|
+
!anyOneSchema.anyOf &&
|
|
264
|
+
!anyOneSchema.allOf && (
|
|
256
265
|
<Properties
|
|
257
266
|
schema={anyOneSchema}
|
|
258
267
|
schemaType={schemaType}
|
|
259
268
|
schemaPath={childSchemaPath}
|
|
260
269
|
/>
|
|
261
270
|
)}
|
|
271
|
+
{/* Render a map variant's `additionalProperties` */}
|
|
272
|
+
{(anyOneSchema.type === "object" || !anyOneSchema.type) &&
|
|
273
|
+
anyOneSchema.additionalProperties &&
|
|
274
|
+
!anyOneSchema.oneOf &&
|
|
275
|
+
!anyOneSchema.anyOf &&
|
|
276
|
+
!anyOneSchema.allOf && (
|
|
277
|
+
<AdditionalProperties
|
|
278
|
+
schema={anyOneSchema}
|
|
279
|
+
schemaType={schemaType}
|
|
280
|
+
/>
|
|
281
|
+
)}
|
|
262
282
|
{anyOneSchema.allOf && (
|
|
263
283
|
<SchemaNode
|
|
264
284
|
schema={anyOneSchema}
|
|
@@ -1100,7 +1120,11 @@ const SchemaNode: React.FC<SchemaProps> = ({
|
|
|
1100
1120
|
workingSchema = mergeAllOf(schema) as SchemaObject;
|
|
1101
1121
|
}
|
|
1102
1122
|
if (!workingSchema.discriminator && resolvedDiscriminator) {
|
|
1103
|
-
|
|
1123
|
+
// Clone: getDiscriminator returns a nested branch's discriminator by
|
|
1124
|
+
// reference, and DiscriminatorNode mutates `.mapping` when inferring
|
|
1125
|
+
// variants. Without cloning, a branch that declares its own discriminator
|
|
1126
|
+
// gets a mapping pointing back to itself and recurses forever.
|
|
1127
|
+
workingSchema.discriminator = { ...resolvedDiscriminator };
|
|
1104
1128
|
}
|
|
1105
1129
|
|
|
1106
1130
|
if (workingSchema.discriminator) {
|
|
@@ -1257,8 +1281,7 @@ const SchemaNode: React.FC<SchemaProps> = ({
|
|
|
1257
1281
|
export default SchemaNode;
|
|
1258
1282
|
|
|
1259
1283
|
type PrimitiveSchemaType =
|
|
1260
|
-
|
|
1261
|
-
| "null";
|
|
1284
|
+
Exclude<NonNullable<SchemaObject["type"]>, "object" | "array"> | "null";
|
|
1262
1285
|
|
|
1263
1286
|
const PRIMITIVE_TYPES: Record<PrimitiveSchemaType, true> = {
|
|
1264
1287
|
string: true,
|
|
@@ -158,6 +158,78 @@ describe("foldSiblingsIntoBranches", () => {
|
|
|
158
158
|
expect(result.items).toBeUndefined();
|
|
159
159
|
expect(result.oneOf).toHaveLength(1);
|
|
160
160
|
});
|
|
161
|
+
|
|
162
|
+
// Regression for #1548 (property duplication in nested anyOf-of-oneOf):
|
|
163
|
+
// when the outer schema is `{ properties, anyOf: [{oneOf:[...]}, ...] }`,
|
|
164
|
+
// fold merges the outer properties into each anyOf branch, giving each
|
|
165
|
+
// branch its own inner `oneOf` alongside merged properties. The AnyOneOf
|
|
166
|
+
// render layer then delegates the branch to SchemaNode, which folds again
|
|
167
|
+
// into each inner variant. If AnyOneOf were to *also* render the branch's
|
|
168
|
+
// properties directly at that outer level, the same fields would appear
|
|
169
|
+
// twice per selected inner variant tab — hence the check in Schema/index.tsx
|
|
170
|
+
// that skips <Properties> when the branch has a nested oneOf/anyOf/allOf.
|
|
171
|
+
it("folds outer properties into each anyOf branch when branches contain nested oneOf", () => {
|
|
172
|
+
const schema = {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
name: { type: "string" },
|
|
176
|
+
default_value: { type: "string" },
|
|
177
|
+
},
|
|
178
|
+
anyOf: [
|
|
179
|
+
{
|
|
180
|
+
oneOf: [
|
|
181
|
+
{
|
|
182
|
+
title: "aggregate_group",
|
|
183
|
+
properties: {
|
|
184
|
+
aggregate_group: { type: "string" },
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
title: "tap",
|
|
189
|
+
properties: {
|
|
190
|
+
tap: { type: "object" },
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
oneOf: [
|
|
197
|
+
{
|
|
198
|
+
title: "folder",
|
|
199
|
+
properties: { folder: { type: "string" } },
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
title: "snippet",
|
|
203
|
+
properties: { snippet: { type: "string" } },
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const outer = foldSiblingsIntoBranches(schema);
|
|
211
|
+
expect(outer.properties).toBeUndefined();
|
|
212
|
+
expect(outer.anyOf).toHaveLength(2);
|
|
213
|
+
|
|
214
|
+
for (const branch of outer.anyOf) {
|
|
215
|
+
// Each anyOf branch retains its own inner oneOf and picks up the
|
|
216
|
+
// merged outer properties as siblings — this is the shape that
|
|
217
|
+
// AnyOneOf must NOT render <Properties> for directly, because
|
|
218
|
+
// SchemaNode will fold them into the inner variants below.
|
|
219
|
+
expect(branch.oneOf).toBeDefined();
|
|
220
|
+
expect(branch.properties.name).toBeDefined();
|
|
221
|
+
expect(branch.properties.default_value).toBeDefined();
|
|
222
|
+
|
|
223
|
+
const inner = foldSiblingsIntoBranches(branch);
|
|
224
|
+
expect(inner.properties).toBeUndefined();
|
|
225
|
+
expect(inner.oneOf).toBeDefined();
|
|
226
|
+
for (const variant of inner.oneOf) {
|
|
227
|
+
// Merged outer properties appear exactly once — inside each variant.
|
|
228
|
+
expect(variant.properties.name).toBeDefined();
|
|
229
|
+
expect(variant.properties.default_value).toBeDefined();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
161
233
|
});
|
|
162
234
|
|
|
163
235
|
describe("getDiscriminator", () => {
|