docusaurus-theme-openapi-docs 0.0.0-1334 → 0.0.0-1338

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.
@@ -267,6 +267,9 @@ const AnyOneOf = ({ schema, schemaType, schemaPath }) => {
267
267
  }),
268
268
  (anyOneSchema.type === "object" || !anyOneSchema.type) &&
269
269
  anyOneSchema.properties &&
270
+ !anyOneSchema.oneOf &&
271
+ !anyOneSchema.anyOf &&
272
+ !anyOneSchema.allOf &&
270
273
  react_1.default.createElement(Properties, {
271
274
  schema: anyOneSchema,
272
275
  schemaType: schemaType,
@@ -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", () => {
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": "0.0.0-1334",
4
+ "version": "0.0.0-1338",
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": "0.0.0-1334",
41
+ "docusaurus-plugin-openapi-docs": "0.0.0-1338",
42
42
  "docusaurus-plugin-sass": "^0.2.6",
43
43
  "eslint-plugin-prettier": "^5.5.1"
44
44
  },
@@ -82,5 +82,5 @@
82
82
  "engines": {
83
83
  "node": ">=14"
84
84
  },
85
- "gitHead": "4c2d938073c8558fc9e7cba0b58c5b948787e24e"
85
+ "gitHead": "f1317997381b86f0344148111bb5ed9266cae94f"
86
86
  }
@@ -251,8 +251,16 @@ const AnyOneOf: React.FC<SchemaProps> = ({
251
251
 
252
252
  {/* Handle actual object types with properties or nested schemas */}
253
253
  {/* Note: In OpenAPI, properties implies type: object even if not explicitly set */}
254
+ {/* When the branch also has a nested oneOf/anyOf/allOf, skip
255
+ Properties here and delegate to SchemaNode below —
256
+ foldSiblingsIntoBranches will merge these properties into
257
+ each inner variant, so rendering them inline as well would
258
+ duplicate them per variant tab. See #1548. */}
254
259
  {(anyOneSchema.type === "object" || !anyOneSchema.type) &&
255
- anyOneSchema.properties && (
260
+ anyOneSchema.properties &&
261
+ !anyOneSchema.oneOf &&
262
+ !anyOneSchema.anyOf &&
263
+ !anyOneSchema.allOf && (
256
264
  <Properties
257
265
  schema={anyOneSchema}
258
266
  schemaType={schemaType}
@@ -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", () => {