docusaurus-plugin-generate-schema-docs 1.8.0 → 1.8.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.
@@ -54,6 +54,53 @@ describe('buildExampleModel', () => {
54
54
  );
55
55
  });
56
56
 
57
+ it('builds distinct conditional examples for required-only branches', () => {
58
+ const model = buildExampleModel({
59
+ type: 'object',
60
+ properties: {
61
+ platform: {
62
+ type: 'string',
63
+ examples: ['ios'],
64
+ },
65
+ att_status: {
66
+ type: 'string',
67
+ examples: ['authorized'],
68
+ },
69
+ ad_personalization_enabled: {
70
+ type: 'boolean',
71
+ examples: [true],
72
+ },
73
+ },
74
+ if: {
75
+ properties: {
76
+ platform: {
77
+ const: 'ios',
78
+ },
79
+ },
80
+ required: ['platform'],
81
+ },
82
+ then: {
83
+ required: ['att_status'],
84
+ },
85
+ else: {
86
+ required: ['ad_personalization_enabled'],
87
+ },
88
+ });
89
+ const conditionalGroup = model.variantGroups.find(
90
+ (group) => group.property === 'conditional',
91
+ );
92
+
93
+ expect(conditionalGroup).toBeDefined();
94
+ expect(conditionalGroup.options[0].example).toEqual({
95
+ platform: 'ios',
96
+ att_status: 'authorized',
97
+ });
98
+ expect(conditionalGroup.options[1].example).toEqual({
99
+ platform: 'ios',
100
+ ad_personalization_enabled: true,
101
+ });
102
+ });
103
+
57
104
  it('uses configured dataLayerName in snippets', () => {
58
105
  const schema = {
59
106
  type: 'object',
@@ -278,6 +278,47 @@ describe('schemaToTableData', () => {
278
278
  expect(conditionalRow.branches[0].title).toBe('Then');
279
279
  });
280
280
 
281
+ it('materializes required-only branch rows from parent properties', () => {
282
+ const schema = {
283
+ type: 'object',
284
+ properties: {
285
+ platform: { type: 'string' },
286
+ att_status: { type: 'string' },
287
+ ad_personalization_enabled: { type: 'boolean' },
288
+ },
289
+ required: ['platform'],
290
+ if: {
291
+ properties: {
292
+ platform: { const: 'ios' },
293
+ },
294
+ required: ['platform'],
295
+ },
296
+ then: {
297
+ required: ['att_status'],
298
+ },
299
+ else: {
300
+ required: ['ad_personalization_enabled'],
301
+ },
302
+ };
303
+
304
+ const tableData = schemaToTableData(schema);
305
+ const conditionalRow = tableData.find((r) => r.type === 'conditional');
306
+ const thenBranch = conditionalRow.branches.find(
307
+ (b) => b.title === 'Then',
308
+ );
309
+ const elseBranch = conditionalRow.branches.find(
310
+ (b) => b.title === 'Else',
311
+ );
312
+
313
+ expect(thenBranch.rows).toHaveLength(1);
314
+ expect(thenBranch.rows[0].name).toBe('att_status');
315
+ expect(thenBranch.rows[0].required).toBe(true);
316
+
317
+ expect(elseBranch.rows).toHaveLength(1);
318
+ expect(elseBranch.rows[0].name).toBe('ad_personalization_enabled');
319
+ expect(elseBranch.rows[0].required).toBe(true);
320
+ });
321
+
281
322
  it('renders regular properties alongside conditional rows', () => {
282
323
  const tableData = schemaToTableData(conditionalEventSchema);
283
324
  const propRows = tableData.filter((r) => r.type === 'property');
@@ -63,18 +63,61 @@ const generateExampleForChoice = (rootSchema, path, option) => {
63
63
  }
64
64
  };
65
65
 
66
+ const pruneSiblingConditionalProperties = (
67
+ mergedSchema,
68
+ activeBranchSchema,
69
+ inactiveBranchSchema,
70
+ baseRequired = [],
71
+ ) => {
72
+ const branchesOnlyAdjustRequired =
73
+ !activeBranchSchema?.properties && !inactiveBranchSchema?.properties;
74
+
75
+ if (
76
+ !mergedSchema?.properties ||
77
+ !branchesOnlyAdjustRequired ||
78
+ !Array.isArray(inactiveBranchSchema?.required)
79
+ ) {
80
+ return mergedSchema;
81
+ }
82
+
83
+ const activeRequired = new Set(activeBranchSchema?.required || []);
84
+ const protectedRequired = new Set(baseRequired);
85
+
86
+ inactiveBranchSchema.required.forEach((name) => {
87
+ if (activeRequired.has(name) || protectedRequired.has(name)) {
88
+ return;
89
+ }
90
+
91
+ delete mergedSchema.properties[name];
92
+ if (Array.isArray(mergedSchema.required)) {
93
+ mergedSchema.required = mergedSchema.required.filter(
94
+ (requiredName) => requiredName !== name,
95
+ );
96
+ }
97
+ });
98
+
99
+ return mergedSchema;
100
+ };
101
+
66
102
  const generateConditionalExample = (rootSchema, path, branch) => {
67
103
  const schemaVariant = JSON.parse(JSON.stringify(rootSchema));
104
+ const siblingBranch = branch === 'then' ? 'else' : 'then';
68
105
 
69
106
  if (path.length === 0) {
70
107
  const branchSchema = schemaVariant[branch];
108
+ const siblingBranchSchema = schemaVariant[siblingBranch];
109
+ const baseRequired = schemaVariant.required || [];
71
110
  delete schemaVariant.if;
72
111
  delete schemaVariant.then;
73
112
  delete schemaVariant.else;
74
113
  if (branchSchema) {
75
- return buildExampleFromSchema(
114
+ const merged = pruneSiblingConditionalProperties(
76
115
  mergeJsonSchema({ allOf: [schemaVariant, branchSchema] }),
116
+ branchSchema,
117
+ siblingBranchSchema,
118
+ baseRequired,
77
119
  );
120
+ return buildExampleFromSchema(merged);
78
121
  }
79
122
  return buildExampleFromSchema(schemaVariant);
80
123
  }
@@ -84,11 +127,18 @@ const generateConditionalExample = (rootSchema, path, branch) => {
84
127
  target = target[segment];
85
128
  }
86
129
  const branchSchema = target[branch];
130
+ const siblingBranchSchema = target[siblingBranch];
131
+ const baseRequired = target.required || [];
87
132
  delete target.if;
88
133
  delete target.then;
89
134
  delete target.else;
90
135
  if (branchSchema) {
91
- const merged = mergeJsonSchema({ allOf: [target, branchSchema] });
136
+ const merged = pruneSiblingConditionalProperties(
137
+ mergeJsonSchema({ allOf: [target, branchSchema] }),
138
+ branchSchema,
139
+ siblingBranchSchema,
140
+ baseRequired,
141
+ );
92
142
  Object.keys(target).forEach((k) => delete target[k]);
93
143
  Object.assign(target, merged);
94
144
  }
@@ -11,6 +11,36 @@ function computeOwnBracket(level, parentGroupBrackets) {
11
11
  return { level, bracketIndex };
12
12
  }
13
13
 
14
+ function materializeConditionalBranchSchema(branchSchema, parentSchema) {
15
+ if (
16
+ !branchSchema ||
17
+ branchSchema.properties ||
18
+ branchSchema.oneOf ||
19
+ branchSchema.anyOf ||
20
+ branchSchema.if ||
21
+ !Array.isArray(branchSchema.required) ||
22
+ !parentSchema?.properties
23
+ ) {
24
+ return branchSchema;
25
+ }
26
+
27
+ const branchProperties = Object.fromEntries(
28
+ branchSchema.required
29
+ .filter((name) => parentSchema.properties[name])
30
+ .map((name) => [name, parentSchema.properties[name]]),
31
+ );
32
+
33
+ if (Object.keys(branchProperties).length === 0) {
34
+ return branchSchema;
35
+ }
36
+
37
+ return {
38
+ ...branchSchema,
39
+ type: 'object',
40
+ properties: branchProperties,
41
+ };
42
+ }
43
+
14
44
  function processOptions(
15
45
  choices,
16
46
  level,
@@ -144,11 +174,15 @@ export function schemaToTableData(
144
174
  // Then is NOT the last branch if Else exists — use innerContinuingLevels
145
175
  // to keep the parent line flowing. If Then IS the last branch, use original.
146
176
  const thenLevels = hasElse ? innerContinuingLevels : continuingLevels;
177
+ const thenSchema = materializeConditionalBranchSchema(
178
+ subSchema.then,
179
+ subSchema,
180
+ );
147
181
  branches.push({
148
182
  title: 'Then',
149
183
  description: subSchema.then.description,
150
184
  rows: schemaToTableData(
151
- subSchema.then,
185
+ thenSchema,
152
186
  currentLevel,
153
187
  currentPath,
154
188
  thenLevels,
@@ -160,11 +194,15 @@ export function schemaToTableData(
160
194
  }
161
195
  if (hasElse) {
162
196
  // Else is always the last branch — use original continuingLevels
197
+ const elseSchema = materializeConditionalBranchSchema(
198
+ subSchema.else,
199
+ subSchema,
200
+ );
163
201
  branches.push({
164
202
  title: 'Else',
165
203
  description: subSchema.else.description,
166
204
  rows: schemaToTableData(
167
- subSchema.else,
205
+ elseSchema,
168
206
  currentLevel,
169
207
  currentPath,
170
208
  continuingLevels,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-plugin-generate-schema-docs",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Docusaurus plugin to generate documentation from JSON schemas.",
5
5
  "main": "index.js",
6
6
  "license": "MIT",