rapidoc 9.3.2 → 9.3.4

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 (47) hide show
  1. package/.github/workflow/words.yaml +22 -0
  2. package/dist/index.html +1 -1
  3. package/dist/index.html.gz +0 -0
  4. package/dist/rapidoc-min.js +857 -738
  5. package/dist/rapidoc-min.js.LICENSE.txt +9 -10
  6. package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
  7. package/dist/rapidoc-min.js.gz +0 -0
  8. package/dist/rapidoc-min.js.map +1 -1
  9. package/dist/rapidoc-min.js.map.gz +0 -0
  10. package/dist/rapidoc.js +9341 -25092
  11. package/dist/report.html +5 -4
  12. package/index.html +2 -3
  13. package/package.json +20 -19
  14. package/src/components/api-request.js +344 -154
  15. package/src/components/api-response.js +16 -12
  16. package/src/components/json-tree.js +17 -12
  17. package/src/components/schema-table.js +50 -42
  18. package/src/components/schema-tree.js +56 -53
  19. package/src/components/tag-input.js +7 -4
  20. package/src/json-schema-viewer.js +1 -2
  21. package/src/rapidoc-mini.js +1 -3
  22. package/src/rapidoc.js +112 -45
  23. package/src/styles/endpoint-styles.js +1 -1
  24. package/src/styles/font-styles.js +1 -1
  25. package/src/styles/info-styles.js +2 -1
  26. package/src/styles/input-styles.js +2 -16
  27. package/src/styles/nav-styles.js +57 -10
  28. package/src/styles/schema-styles.js +27 -15
  29. package/src/styles/tab-styles.js +1 -0
  30. package/src/templates/callback-template.js +6 -7
  31. package/src/templates/code-samples-template.js +1 -0
  32. package/src/templates/components-template.js +3 -5
  33. package/src/templates/endpoint-template.js +41 -27
  34. package/src/templates/expanded-endpoint-template.js +63 -13
  35. package/src/templates/focused-endpoint-template.js +4 -1
  36. package/src/templates/header-template.js +2 -2
  37. package/src/templates/json-schema-viewer-template.js +2 -1
  38. package/src/templates/main-body-template.js +19 -18
  39. package/src/templates/navbar-template.js +98 -81
  40. package/src/templates/overview-template.js +1 -1
  41. package/src/templates/security-scheme-template.js +48 -25
  42. package/src/templates/server-template.js +1 -1
  43. package/src/utils/common-utils.js +2 -5
  44. package/src/utils/schema-utils.js +208 -83
  45. package/src/utils/spec-parser.js +1 -0
  46. package/src/utils/theme.js +11 -5
  47. package/webpack.config.js +2 -1
@@ -1,3 +1,23 @@
1
+ // Takes a value as input and provides a printable string to replresent null values, spaces, blankstring etc
2
+ export function getPrintableVal(val) {
3
+ if (val === undefined) {
4
+ return '';
5
+ }
6
+ if (val === null) {
7
+ return 'null';
8
+ }
9
+ if (val === '') {
10
+ return '∅';
11
+ }
12
+ if (typeof val === 'boolean' || typeof val === 'number') {
13
+ return `${val}`;
14
+ }
15
+ if (Array.isArray(val)) {
16
+ return val.map((v) => (v === null ? 'null' : v === '' ? '∅' : v.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '')).join(', ');
17
+ }
18
+ return val.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '';
19
+ }
20
+
1
21
  /* Generates an schema object containing type and constraint info */
2
22
  export function getTypeInfo(schema) {
3
23
  if (!schema) {
@@ -13,12 +33,14 @@ export function getTypeInfo(schema) {
13
33
  dataType = `{recursive: ${schemaNode}} `;
14
34
  } else if (schema.type) {
15
35
  dataType = Array.isArray(schema.type) ? schema.type.join(schema.length === 2 ? ' or ' : '┃') : schema.type;
16
- if (schema.format || schema.enum) {
17
- dataType = dataType.replace('string', schema.enum ? 'enum' : schema.format);
36
+ if (schema.format || schema.enum || schema.const) {
37
+ dataType = dataType.replace('string', schema.enum ? 'enum' : schema.const ? 'const' : schema.format);
18
38
  }
19
39
  if (schema.nullable) {
20
40
  dataType += '┃null';
21
41
  }
42
+ } else if (schema.const) {
43
+ dataType = 'const';
22
44
  } else if (Object.keys(schema).length === 0) {
23
45
  dataType = 'any';
24
46
  } else {
@@ -32,7 +54,7 @@ export function getTypeInfo(schema) {
32
54
  readOrWriteOnly: (schema.readOnly ? '🆁' : schema.writeOnly ? '🆆' : ''),
33
55
  deprecated: schema.deprecated ? '❌' : '',
34
56
  examples: schema.examples || schema.example,
35
- default: schema.default != null ? `${schema.default}` : '',
57
+ default: getPrintableVal(schema.default),
36
58
  description: schema.description || '',
37
59
  constrain: '',
38
60
  allowedValues: '',
@@ -45,16 +67,24 @@ export function getTypeInfo(schema) {
45
67
  } else if (info.type === '{missing-type-info}' || info.type === 'any') {
46
68
  info.description = info.description || '';
47
69
  }
48
-
49
70
  // Set Allowed Values
50
- info.allowedValues = Array.isArray(schema.enum) ? schema.enum.join('┃') : '';
71
+ info.allowedValues = schema.const
72
+ ? schema.const
73
+ : Array.isArray(schema.enum)
74
+ ? schema.enum.map((v) => (getPrintableVal(v))).join('┃')
75
+ : '';
76
+
51
77
  if (dataType === 'array' && schema.items) {
52
78
  const arrayItemType = schema.items?.type;
53
- const arrayItemDefault = schema.items?.default !== undefined ? schema.items.default : '';
79
+ const arrayItemDefault = getPrintableVal(schema.items.default);
54
80
 
55
81
  info.arrayType = `${schema.type} of ${Array.isArray(arrayItemType) ? arrayItemType.join('') : arrayItemType}`;
56
82
  info.default = arrayItemDefault;
57
- info.allowedValues = Array.isArray(schema.items?.enum) ? schema.items.enum.join('┃') : '';
83
+ info.allowedValues = schema.items.const
84
+ ? schema.const
85
+ : Array.isArray(schema.items?.enum)
86
+ ? schema.items.enum.map((v) => (getPrintableVal(v))).join('┃')
87
+ : '';
58
88
  }
59
89
  if (dataType.match(/integer|number/g)) {
60
90
  if (schema.minimum !== undefined || schema.exclusiveMinimum !== undefined) {
@@ -80,49 +110,88 @@ export function getTypeInfo(schema) {
80
110
  info.html = `${info.type}~|~${info.readOrWriteOnly}~|~${info.constrain}~|~${info.default}~|~${info.allowedValues}~|~${info.pattern}~|~${info.description}~|~${schema.title || ''}~|~${info.deprecated ? 'deprecated' : ''}`;
81
111
  return info;
82
112
  }
113
+
83
114
  export function nestExampleIfPresent(example) {
115
+ if (typeof example === 'boolean' || typeof example === 'number') {
116
+ return {
117
+ Example: { value: `${example}` },
118
+ };
119
+ }
120
+ if (example === '') {
121
+ return {
122
+ Example: { value: '' },
123
+ };
124
+ }
84
125
  return example ? { Example: { value: example } } : example;
85
126
  }
127
+
128
+ /**
129
+ * Normalize example object in the following format (List of object which is used to render example links and fill the input boxes)
130
+ * [{
131
+ * exampleVal : 'value to be rendered on the input control (text-box)',
132
+ * exampleList : [
133
+ * value : '',
134
+ * printableValue: '',
135
+ * summary : '',
136
+ * description : ''
137
+ * ]
138
+ * }]
139
+ * */
86
140
  export function normalizeExamples(examples, dataType = 'string') {
87
- let exampleVal;
88
- let exampleList;
89
- if (examples) {
90
- if (examples.constructor === Object) {
91
- const exampleValAndDescr = Object.values(examples);
92
- exampleVal = exampleValAndDescr.length > 0
93
- ? typeof exampleValAndDescr[0].value === 'boolean' || typeof exampleValAndDescr[0].value === 'number'
94
- ? exampleValAndDescr[0].value.toString()
95
- : exampleValAndDescr[0].value
96
- : '';
97
- exampleList = Object.values(examples).map((v) => ({
98
- value: typeof v.value === 'boolean' || typeof v.value === 'number' ? v.value.toString() : v.value,
99
- description: v.description || v.summary || v.value,
141
+ if (!examples) {
142
+ return {
143
+ exampleVal: '',
144
+ exampleList: [],
145
+ };
146
+ }
147
+ if (examples.constructor === Object) {
148
+ const exampleList = Object.values(examples)
149
+ .filter((v) => (v['x-example-show-value'] !== false))
150
+ .map((v) => ({
151
+ value: (typeof v.value === 'boolean' || typeof v.value === 'number' ? `${v.value}` : (v.value || '')),
152
+ printableValue: getPrintableVal(v.value),
153
+ summary: v.summary || '',
154
+ description: v.description || '',
100
155
  }));
101
- } else {
102
- // This is non standard way to provide example but will support for now
103
- if (!Array.isArray(examples)) {
104
- examples = examples ? [examples] : [];
105
- }
106
- if (examples.length > 0) {
107
- if (dataType === 'array') {
108
- [exampleVal] = examples;
109
- exampleList = examples.map((v) => ({ value: v, description: Array.isArray(v) ? v.join(' , ') : v }));
110
- } else {
111
- exampleVal = examples[0].toString();
112
- exampleList = examples.map((v) => ({ value: v.toString(), description: v }));
113
- }
114
- }
115
- }
156
+ const exampleVal = exampleList.length > 0
157
+ ? exampleList[0].value.toString()
158
+ : '';
159
+ return { exampleVal, exampleList };
160
+ }
161
+
162
+ // This is non-standard way to provide example but will support for now
163
+ if (!Array.isArray(examples)) {
164
+ examples = examples ? [examples] : [];
165
+ }
166
+
167
+ if (examples.length === 0) {
116
168
  return {
117
- exampleVal,
118
- exampleList,
169
+ exampleVal: '',
170
+ exampleList: [],
119
171
  };
120
172
  }
121
- return {
122
- exampleVal: '',
123
- exampleList: [],
124
- };
173
+
174
+ if (dataType === 'array') {
175
+ const [exampleVal] = examples;
176
+ const exampleList = examples.map((v) => ({
177
+ value: v,
178
+ printableValue: getPrintableVal(v),
179
+ }));
180
+ return { exampleVal, exampleList };
181
+ }
182
+
183
+ const exampleVal = examples[0].toString();
184
+ const exampleList = examples.map((v) => ({
185
+ value: v.toString(),
186
+ printableValue: getPrintableVal(v),
187
+ }));
188
+ return { exampleVal, exampleList };
125
189
  }
190
+
191
+ export function anyExampleWithSummaryOrDescription(examples) {
192
+ return examples.some((x) => x.summary?.length > 0 || x.description?.length > 0);
193
+ }
194
+
126
195
  export function getSampleValueByType(schemaObj) {
127
196
  const example = schemaObj.examples
128
197
  ? schemaObj.examples[0]
@@ -132,6 +201,17 @@ export function getSampleValueByType(schemaObj) {
132
201
  if (example === '') { return ''; }
133
202
  if (example === null) { return null; }
134
203
  if (example === 0) { return 0; }
204
+ if (example === false) { return false; }
205
+ if (example instanceof Date) {
206
+ switch (schemaObj.format.toLowerCase()) {
207
+ case 'date':
208
+ return example.toISOString().split('T')[0];
209
+ case 'time':
210
+ return example.toISOString().split('T')[1];
211
+ default:
212
+ return example.toISOString();
213
+ }
214
+ }
135
215
  if (example) { return example; }
136
216
 
137
217
  if (Object.keys(schemaObj).length === 0) {
@@ -141,6 +221,12 @@ export function getSampleValueByType(schemaObj) {
141
221
  // Indicates a Circular ref
142
222
  return schemaObj.$ref;
143
223
  }
224
+ if (schemaObj.const === false || schemaObj.const === 0 || schemaObj.const === null || schemaObj.const === '') {
225
+ return schemaObj.const;
226
+ }
227
+ if (schemaObj.const) {
228
+ return schemaObj.const;
229
+ }
144
230
  const typeValue = Array.isArray(schemaObj.type) ? schemaObj.type[0] : schemaObj.type;
145
231
  if (!typeValue) {
146
232
  return '?';
@@ -166,6 +252,7 @@ export function getSampleValueByType(schemaObj) {
166
252
  if (typeValue.match(/^null/g)) { return null; }
167
253
  if (typeValue.match(/^string/g)) {
168
254
  if (schemaObj.enum) { return schemaObj.enum[0]; }
255
+ if (schemaObj.const) { return schemaObj.const; }
169
256
  if (schemaObj.pattern) { return schemaObj.pattern; }
170
257
  if (schemaObj.format) {
171
258
  const u = `${Date.now().toString(16)}${Math.random().toString(16)}0`.repeat(16);
@@ -221,9 +308,9 @@ json2xml- TestCase
221
308
  <root>
222
309
  <prop1>simple</prop1>
223
310
  <prop2>
224
- <0> a </0>
225
- <1> b </1>
226
- <2> c </2>
311
+ <0>a</0>
312
+ <1>b</1>
313
+ <2>c</2>
227
314
  </prop2>
228
315
  <prop3>
229
316
  <ob1>val-1</ob1>
@@ -238,12 +325,22 @@ export function json2xml(obj, level = 1) {
238
325
  return `\n${indent}${obj.toString()}`;
239
326
  }
240
327
  for (const prop in obj) {
328
+ const tagNameOrProp = (obj[prop]['::XML_TAG'] || prop);
329
+ let tagName = '';
241
330
  if (Array.isArray(obj[prop])) {
242
- xmlText = `${xmlText}\n${indent}<${prop}> ${json2xml(obj[prop], level + 1)}\n${indent}</${prop}>`;
331
+ tagName = tagNameOrProp[0]['::XML_TAG'] || `${prop}`;
332
+ } else {
333
+ tagName = tagNameOrProp;
334
+ }
335
+ if (prop.startsWith('::')) {
336
+ continue;
337
+ }
338
+ if (Array.isArray(obj[prop])) {
339
+ xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
243
340
  } else if (typeof obj[prop] === 'object') {
244
- xmlText = `${xmlText}\n${indent}<${prop}> ${json2xml(obj[prop], level + 1)}\n${indent}</${prop}>`;
341
+ xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
245
342
  } else {
246
- xmlText = `${xmlText}\n${indent}<${prop}> ${obj[prop].toString()} </${prop}>`;
343
+ xmlText = `${xmlText}\n${indent}<${tagName}>${obj[prop].toString()}</${tagName}>`;
247
344
  }
248
345
  }
249
346
  return xmlText;
@@ -259,6 +356,12 @@ function addSchemaInfoToExample(schema, obj) {
259
356
  if (schema.description) {
260
357
  obj['::DESCRIPTION'] = schema.description;
261
358
  }
359
+ if (schema.xml?.name) {
360
+ obj['::XML_TAG'] = schema.xml?.name;
361
+ }
362
+ if (schema.xml?.wrapped) {
363
+ obj['::XML_WRAP'] = schema.xml?.wrapped.toString();
364
+ }
262
365
  }
263
366
 
264
367
  function removeTitlesAndDescriptions(obj) {
@@ -267,6 +370,8 @@ function removeTitlesAndDescriptions(obj) {
267
370
  }
268
371
  delete obj['::TITLE'];
269
372
  delete obj['::DESCRIPTION'];
373
+ delete obj['::XML_TAG'];
374
+ delete obj['::XML_WRAP'];
270
375
  for (const k in obj) {
271
376
  removeTitlesAndDescriptions(obj[k]);
272
377
  }
@@ -305,11 +410,10 @@ export function schemaToSampleObj(schema, config = { }) {
305
410
  if (!schema) {
306
411
  return;
307
412
  }
308
-
309
413
  if (schema.allOf) {
310
414
  const objWithAllProps = {};
311
415
 
312
- if (schema.allOf.length === 1 && !schema.allOf[0].properties && !schema.allOf[0].items) {
416
+ if (schema.allOf.length === 1 && !schema.allOf[0]?.properties && !schema.allOf[0]?.items) {
313
417
  // If allOf has single item and the type is not an object or array, then its a primitive
314
418
  if (schema.allOf[0].$ref) {
315
419
  return '{ }';
@@ -342,7 +446,11 @@ export function schemaToSampleObj(schema, config = { }) {
342
446
  const objWithSchemaProps = {};
343
447
  if (schema.properties) {
344
448
  for (const propertyName in schema.properties) {
345
- objWithSchemaProps[propertyName] = getSampleValueByType(schema.properties[propertyName]);
449
+ if (schema.properties[propertyName].properties || schema.properties[propertyName].properties?.items) {
450
+ objWithSchemaProps[propertyName] = schemaToSampleObj(schema.properties[propertyName], config);
451
+ } else {
452
+ objWithSchemaProps[propertyName] = getSampleValueByType(schema.properties[propertyName]);
453
+ }
346
454
  }
347
455
  }
348
456
 
@@ -456,11 +564,21 @@ export function schemaToSampleObj(schema, config = { }) {
456
564
  addPropertyExampleToObjectExamples([schema.properties[propertyName].items.example], obj, propertyName);
457
565
  } else {
458
566
  const itemSamples = schemaToSampleObj(schema.properties[propertyName].items, config);
459
- const arraySamples = [];
460
- for (const key in itemSamples) {
461
- arraySamples[key] = [itemSamples[key]];
567
+ if (config.useXmlTagForProp) {
568
+ const xmlTagName = schema.properties[propertyName].xml?.name || propertyName;
569
+ if (schema.properties[propertyName].xml?.wrapped) {
570
+ const wrappedItemSample = JSON.parse(`{ "${xmlTagName}" : { "${xmlTagName}" : ${JSON.stringify(itemSamples['example-0'])} } }`);
571
+ obj = mergePropertyExamples(obj, xmlTagName, wrappedItemSample);
572
+ } else {
573
+ obj = mergePropertyExamples(obj, xmlTagName, itemSamples);
574
+ }
575
+ } else {
576
+ const arraySamples = [];
577
+ for (const key in itemSamples) {
578
+ arraySamples[key] = [itemSamples[key]];
579
+ }
580
+ obj = mergePropertyExamples(obj, propertyName, arraySamples);
462
581
  }
463
- obj = mergePropertyExamples(obj, propertyName, arraySamples);
464
582
  }
465
583
  continue;
466
584
  }
@@ -492,26 +610,29 @@ export function schemaToSampleObj(schema, config = { }) {
492
610
  }
493
611
 
494
612
  function generateMarkdownForArrayAndObjectDescription(schema, level = 0) {
495
- let markdown = '';
613
+ let markdown = ((schema.description || schema.title) && (schema.minItems || schema.maxItems)) ? '<span class="descr-expand-toggle">➔</span>' : '';
496
614
  if (schema.title) {
497
- markdown = `**${schema.title}:** `;
498
- }
499
- if (schema.description) {
500
- markdown = `${markdown} ${schema.description} ${schema.minItems || schema.maxItems ? '<span class="more-content">⤵</span><br/>' : ''}`;
615
+ if (schema.description) {
616
+ markdown = `${markdown} <b>${schema.title}:</b> ${schema.description}<br/>`;
617
+ } else {
618
+ markdown = `${markdown} ${schema.title}<br/>`;
619
+ }
620
+ } else if (schema.description) {
621
+ markdown = `${markdown} ${schema.description}<br/>`;
501
622
  }
502
623
  if (schema.minItems) {
503
- markdown = `${markdown} **Min Items:** ${schema.minItems}`;
624
+ markdown = `${markdown} <b>Min Items:</b> ${schema.minItems}`;
504
625
  }
505
626
  if (schema.maxItems) {
506
- markdown = `${markdown} **Max Items:** ${schema.maxItems}`;
627
+ markdown = `${markdown} <b>Max Items:</b> ${schema.maxItems}`;
507
628
  }
508
629
  if (level > 0 && schema.items?.description) {
509
630
  let itemsMarkdown = '';
510
631
  if (schema.items.minProperties) {
511
- itemsMarkdown = `**Min Properties:** ${schema.items.minProperties}`;
632
+ itemsMarkdown = `<b>Min Properties:</b> ${schema.items.minProperties}`;
512
633
  }
513
634
  if (schema.items.maxProperties) {
514
- itemsMarkdown = `${itemsMarkdown} **Max Properties:** ${schema.items.maxProperties}`;
635
+ itemsMarkdown = `${itemsMarkdown} <b>Max Properties:</b> ${schema.items.maxProperties}`;
515
636
  }
516
637
  markdown = `${markdown} ⮕ ${itemsMarkdown} [ ${schema.items.description} ] `;
517
638
  }
@@ -576,11 +697,13 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
576
697
  if (v.type === 'object' || v.properties || v.allOf || v.anyOf || v.oneOf) {
577
698
  const partialObj = schemaInObjectNotation(v, {});
578
699
  objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
700
+ objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
579
701
  objWithAnyOfProps['::type'] = 'xxx-of-option';
580
702
  } else if (v.type === 'array' || v.items) {
581
703
  // This else-if block never seems to get executed
582
704
  const partialObj = schemaInObjectNotation(v, {});
583
705
  objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
706
+ objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
584
707
  objWithAnyOfProps['::type'] = 'xxx-of-array';
585
708
  } else {
586
709
  const prop = `::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`;
@@ -589,7 +712,8 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
589
712
  }
590
713
  });
591
714
  obj[(schema.anyOf ? `::ANY~OF ${suffix}` : `::ONE~OF ${suffix}`)] = objWithAnyOfProps;
592
- obj['::type'] = 'xxx-of';
715
+ // obj['::type'] = 'object';
716
+ obj['::type'] = 'object';
593
717
  } else if (Array.isArray(schema.type)) {
594
718
  // When a property has multiple types, then check further if any of the types are array or object, if yes then modify the schema using one-of
595
719
  // Clone the schema - as it will be modified to replace multi-data-types with one-of;
@@ -619,7 +743,7 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
619
743
  }
620
744
  }
621
745
  if (complexTypes.length > 0) {
622
- obj['::type'] = 'xxx-of';
746
+ obj['::type'] = 'object';
623
747
  const multiTypeOptions = {
624
748
  '::type': 'xxx-of-option',
625
749
  };
@@ -664,6 +788,9 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
664
788
  obj['::title'] = schema.title || '';
665
789
  obj['::description'] = generateMarkdownForArrayAndObjectDescription(schema, level);
666
790
  obj['::type'] = 'object';
791
+ if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
792
+ obj['::dataTypeLabel'] = 'object or null';
793
+ }
667
794
  obj['::deprecated'] = schema.deprecated || false;
668
795
  obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
669
796
  for (const key in schema.properties) {
@@ -673,13 +800,19 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
673
800
  obj[key] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
674
801
  }
675
802
  }
803
+ for (const key in schema.patternProperties) {
804
+ obj[`[pattern: ${key}]`] = schemaInObjectNotation(schema.patternProperties[key], obj, (level + 1));
805
+ }
676
806
  if (schema.additionalProperties) {
677
- obj['<any-key>'] = schemaInObjectNotation(schema.additionalProperties, {});
807
+ obj['[any-key]'] = schemaInObjectNotation(schema.additionalProperties, {});
678
808
  }
679
809
  } else if (schema.type === 'array' || schema.items) { // If Array
680
810
  obj['::title'] = schema.title || '';
681
811
  obj['::description'] = generateMarkdownForArrayAndObjectDescription(schema, level);
682
812
  obj['::type'] = 'array';
813
+ if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
814
+ obj['::dataTypeLabel'] = 'array or null';
815
+ }
683
816
  obj['::deprecated'] = schema.deprecated || false;
684
817
  obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
685
818
  if (schema.items?.items) {
@@ -712,7 +845,8 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
712
845
  egContent = examples[eg].value;
713
846
  if (typeof examples[eg].value === 'string') {
714
847
  try {
715
- const fixedJsonString = examples[eg].value.replace((/([\w]+)(:)/g), '"$1"$2').replace((/'/g), '"');
848
+ // const fixedJsonString = examples[eg].value.replace((/([\w]+)(:)/g), '"$1"$2').replace((/'/g), '"');
849
+ const fixedJsonString = examples[eg].value;
716
850
  egContent = JSON.parse(fixedJsonString);
717
851
  egFormat = 'json';
718
852
  } catch (err) {
@@ -770,7 +904,8 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
770
904
  // If schema-level examples are not provided or includeGeneratedExample === true then generate one based on the schema field types
771
905
  if (finalExamples.length === 0 || includeGeneratedExample === true) {
772
906
  if (schema) {
773
- if (schema.example) { // Note: schema.examples (plurals) is not allowed as per spec
907
+ if (schema.example) {
908
+ // Note: Deprecated: The 'example' property has been deprecated in 3.1.0 in favor of the JSON Schema 'examples' keyword
774
909
  finalExamples.push({
775
910
  exampleId: 'Example',
776
911
  exampleSummary: '',
@@ -785,22 +920,13 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
785
920
  let exampleFormat = '';
786
921
  let exampleValue = '';
787
922
  if (mimeType?.toLowerCase().includes('xml')) {
788
- xmlRootStart = (schema.xml && schema.xml.name) ? `<${schema.xml.name}>` : '<root>';
789
- xmlRootEnd = (schema.xml && schema.xml.name) ? `</${schema.xml.name}>` : '</root>';
923
+ xmlRootStart = schema.xml?.name ? `<${schema.xml.name} ${schema.xml.namespace ? `xmlns="${schema.xml.namespace}"` : ''}>` : '<root>';
924
+ xmlRootEnd = schema.xml?.name ? `</${schema.xml.name}>` : '</root>';
790
925
  exampleFormat = 'text';
791
926
  } else {
792
927
  exampleFormat = outputType;
793
928
  }
794
-
795
- const samples = schemaToSampleObj(
796
- schema,
797
- {
798
- includeReadOnly,
799
- includeWriteOnly,
800
- deprecated: true,
801
- },
802
- );
803
-
929
+ const samples = schemaToSampleObj(schema, { includeReadOnly, includeWriteOnly, deprecated: true, useXmlTagForProp: mimeType?.toLowerCase().includes('xml') });
804
930
  let i = 0;
805
931
  for (const samplesKey in samples) {
806
932
  if (!samples[samplesKey]) {
@@ -808,11 +934,10 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
808
934
  }
809
935
  const summary = samples[samplesKey]['::TITLE'] || `Example ${++i}`;
810
936
  const description = samples[samplesKey]['::DESCRIPTION'] || '';
811
- removeTitlesAndDescriptions(samples[samplesKey]);
812
-
813
937
  if (mimeType?.toLowerCase().includes('xml')) {
814
- exampleValue = `${xmlRootStart}${json2xml(samples[samplesKey])}\n${xmlRootEnd}`;
938
+ exampleValue = `<?xml version="1.0" encoding="UTF-8"?>\n${xmlRootStart}${json2xml(samples[samplesKey], 1)}\n${xmlRootEnd}`;
815
939
  } else {
940
+ removeTitlesAndDescriptions(samples[samplesKey]);
816
941
  exampleValue = outputType === 'text' ? JSON.stringify(samples[samplesKey], null, 2) : samples[samplesKey];
817
942
  }
818
943
 
@@ -347,6 +347,7 @@ function groupByTags(openApiSpec, sortEndpointsBy, generateMissingTags = false,
347
347
  expandedAtLeastOnce: false,
348
348
  summary: (pathOrHookObj.summary || ''),
349
349
  description: (pathOrHookObj.description || ''),
350
+ externalDocs: pathOrHookObj.externalDocs,
350
351
  shortSummary,
351
352
  method: methodName,
352
353
  path: pathOrHookName,
@@ -7,7 +7,7 @@ export default function setTheme(baseTheme, theme = {}) {
7
7
  // Common Theme colors
8
8
  const primaryColor = theme.primaryColor ? theme.primaryColor : baseTheme === 'dark' ? '#f76b39' : '#ff591e';
9
9
  const primaryColorInvert = ColorUtils.color.invert(primaryColor);
10
- const primaryColorTrans = ColorUtils.color.opacity(primaryColor, '0.8');
10
+ const primaryColorTrans = ColorUtils.color.opacity(primaryColor, '0.4');
11
11
 
12
12
  // Dark and Light Theme colors
13
13
  if (baseTheme === 'dark') {
@@ -31,6 +31,8 @@ export default function setTheme(baseTheme, theme = {}) {
31
31
  const navHoverBgColor = theme.navHoverBgColor ? theme.navHoverBgColor : ColorUtils.color.brightness(navBgColor, -15);
32
32
  const navHoverTextColor = theme.navHoverTextColor ? theme.navHoverTextColor : ColorUtils.color.invert(navBgColor);
33
33
  const navAccentColor = theme.navAccentColor ? theme.navAccentColor : ColorUtils.color.brightness(primaryColor, 25);
34
+ const navAccentTextColor = theme.navAccentTextColor ? theme.navAccenttextColor : ColorUtils.color.invert(navAccentColor);
35
+
34
36
  const overlayBg = 'rgba(80, 80, 80, 0.4)';
35
37
 
36
38
  newTheme = {
@@ -54,7 +56,7 @@ export default function setTheme(baseTheme, theme = {}) {
54
56
  navHoverBgColor,
55
57
  navHoverTextColor,
56
58
  navAccentColor,
57
-
59
+ navAccentTextColor,
58
60
  headerColor,
59
61
  headerColorInvert: ColorUtils.color.invert(headerColor),
60
62
  headerColorDarker: ColorUtils.color.brightness(headerColor, -20),
@@ -123,6 +125,7 @@ export default function setTheme(baseTheme, theme = {}) {
123
125
  const navHoverBgColor = theme.navHoverBgColor ? theme.navHoverBgColor : ColorUtils.color.brightness(navBgColor, -15);
124
126
  const navHoverTextColor = theme.navHoverTextColor ? theme.navHoverTextColor : ColorUtils.color.invert(navBgColor);
125
127
  const navAccentColor = theme.navAccentColor ? theme.navAccentColor : ColorUtils.color.brightness(primaryColor, 25);
128
+ const navAccentTextColor = theme.navAccentTextColor ? theme.navAccenttextColor : ColorUtils.color.invert(navAccentColor);
126
129
  const overlayBg = 'rgba(0, 0, 0, 0.4)';
127
130
 
128
131
  newTheme = {
@@ -146,7 +149,7 @@ export default function setTheme(baseTheme, theme = {}) {
146
149
  navHoverBgColor,
147
150
  navHoverTextColor,
148
151
  navAccentColor,
149
-
152
+ navAccentTextColor,
150
153
  headerColor,
151
154
  headerColorInvert: ColorUtils.color.invert(headerColor),
152
155
  headerColorDarker: ColorUtils.color.brightness(headerColor, -20),
@@ -206,11 +209,13 @@ export default function setTheme(baseTheme, theme = {}) {
206
209
  : '7px 16px 7px 10px')};
207
210
 
208
211
  --resp-area-height: ${this.responseAreaHeight};
209
- --font-size-small: ${this.fontSize === 'default' ? '12px' : (this.fontSize === 'large' ? '13px' : '14px')};
210
- --font-size-mono: ${this.fontSize === 'default' ? '13px' : (this.fontSize === 'large' ? '14px' : '15px')};
212
+ --font-size-small: ${this.fontSize === 'default' ? '12px' : (this.fontSize === 'large' ? '13px' : '14px')};
213
+ --font-size-mono: ${this.fontSize === 'default' ? '13px' : (this.fontSize === 'large' ? '14px' : '15px')};
211
214
  --font-size-regular: ${this.fontSize === 'default' ? '14px' : (this.fontSize === 'large' ? '15px' : '16px')};
212
215
  --dialog-z-index: 1000;
213
216
 
217
+ --focus-shadow: 0 0 0 1px transparent, 0 0 0 3px ${newTheme.primaryColorTrans};
218
+
214
219
  /* Theme specific styles */
215
220
  --bg:${newTheme.bg1};
216
221
  --bg2:${newTheme.bg2};
@@ -259,6 +264,7 @@ export default function setTheme(baseTheme, theme = {}) {
259
264
  --nav-hover-bg-color:${newTheme.navHoverBgColor};
260
265
  --nav-hover-text-color:${newTheme.navHoverTextColor};
261
266
  --nav-accent-color:${newTheme.navAccentColor};
267
+ --nav-accent-text-color:${newTheme.navAccentTextColor};
262
268
 
263
269
  /* Nav API Method Colors*/
264
270
  --nav-get-color:${newTheme.blue};
package/webpack.config.js CHANGED
@@ -31,7 +31,8 @@ const rapidocBanner = `
31
31
  * License: MIT
32
32
  * Repo : https://github.com/rapi-doc/RapiDoc
33
33
  * Author : Mrinmoy Majumdar
34
- *`;
34
+ */
35
+ `;
35
36
 
36
37
  const commonPlugins = [
37
38
  new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }),