rapidoc 9.3.3 → 9.3.5
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/.github/workflow/words.yaml +22 -0
- package/README.md +2 -7
- package/dist/index.html +1 -1
- package/dist/index.html.gz +0 -0
- package/dist/rapidoc-min.js +858 -748
- package/dist/rapidoc-min.js.LICENSE.txt +14 -9
- package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
- package/dist/rapidoc-min.js.gz +0 -0
- package/dist/rapidoc-min.js.map +1 -1
- package/dist/rapidoc-min.js.map.gz +0 -0
- package/dist/rapidoc.js +11948 -32008
- package/dist/report.html +6 -5
- package/index.html +2 -1
- package/package.json +25 -24
- package/src/components/api-request.js +266 -122
- package/src/components/api-response.js +11 -10
- package/src/components/json-tree.js +17 -12
- package/src/components/schema-table.js +58 -49
- package/src/components/schema-tree.js +60 -56
- package/src/components/tag-input.js +7 -4
- package/src/json-schema-viewer.js +2 -1
- package/src/rapidoc-mini.js +1 -1
- package/src/rapidoc.js +108 -35
- package/src/styles/endpoint-styles.js +1 -1
- package/src/styles/info-styles.js +2 -1
- package/src/styles/input-styles.js +2 -16
- package/src/styles/nav-styles.js +57 -10
- package/src/styles/schema-styles.js +27 -15
- package/src/styles/tab-styles.js +1 -0
- package/src/templates/advance-search-template.js +3 -3
- package/src/templates/callback-template.js +3 -3
- package/src/templates/code-samples-template.js +1 -0
- package/src/templates/components-template.js +3 -5
- package/src/templates/endpoint-template.js +39 -26
- package/src/templates/expanded-endpoint-template.js +58 -9
- package/src/templates/focused-endpoint-template.js +5 -2
- package/src/templates/header-template.js +2 -2
- package/src/templates/json-schema-viewer-template.js +2 -1
- package/src/templates/main-body-template.js +19 -18
- package/src/templates/navbar-template.js +99 -82
- package/src/templates/overview-template.js +1 -1
- package/src/templates/security-scheme-template.js +51 -27
- package/src/templates/server-template.js +1 -1
- package/src/utils/common-utils.js +2 -2
- package/src/utils/schema-utils.js +192 -67
- package/src/utils/spec-parser.js +9 -3
- package/src/utils/theme.js +9 -3
- package/webpack.config.js +2 -1
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
import RandExp from 'randexp';
|
|
2
|
+
|
|
3
|
+
// Make RandExp determinist
|
|
4
|
+
RandExp.prototype.randInt = (from) => from;
|
|
5
|
+
|
|
6
|
+
// Takes a value as input and provides a printable string to replresent null values, spaces, blankstring etc
|
|
7
|
+
export function getPrintableVal(val) {
|
|
8
|
+
if (val === undefined) {
|
|
9
|
+
return '';
|
|
10
|
+
}
|
|
11
|
+
if (val === null) {
|
|
12
|
+
return 'null';
|
|
13
|
+
}
|
|
14
|
+
if (val === '') {
|
|
15
|
+
return '∅';
|
|
16
|
+
}
|
|
17
|
+
if (typeof val === 'boolean' || typeof val === 'number') {
|
|
18
|
+
return `${val}`;
|
|
19
|
+
}
|
|
20
|
+
if (Array.isArray(val)) {
|
|
21
|
+
return val.map((v) => (v === null ? 'null' : v === '' ? '∅' : v.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '')).join(', ');
|
|
22
|
+
}
|
|
23
|
+
if (typeof val === 'object') {
|
|
24
|
+
const keys = Object.keys(val);
|
|
25
|
+
return `{ ${keys[0]}:${val[keys[0]]}${keys.length > 1 ? ',' : ''} ... }`;
|
|
26
|
+
}
|
|
27
|
+
return val.toString().replace(/^ +| +$/g, (m) => '●'.repeat(m.length)) || '';
|
|
28
|
+
}
|
|
29
|
+
|
|
1
30
|
/* Generates an schema object containing type and constraint info */
|
|
2
31
|
export function getTypeInfo(schema) {
|
|
3
32
|
if (!schema) {
|
|
@@ -13,12 +42,14 @@ export function getTypeInfo(schema) {
|
|
|
13
42
|
dataType = `{recursive: ${schemaNode}} `;
|
|
14
43
|
} else if (schema.type) {
|
|
15
44
|
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);
|
|
45
|
+
if (schema.format || schema.enum || schema.const) {
|
|
46
|
+
dataType = dataType.replace('string', schema.enum ? 'enum' : schema.const ? 'const' : schema.format);
|
|
18
47
|
}
|
|
19
48
|
if (schema.nullable) {
|
|
20
49
|
dataType += '┃null';
|
|
21
50
|
}
|
|
51
|
+
} else if (schema.const) {
|
|
52
|
+
dataType = 'const';
|
|
22
53
|
} else if (Object.keys(schema).length === 0) {
|
|
23
54
|
dataType = 'any';
|
|
24
55
|
} else {
|
|
@@ -32,7 +63,7 @@ export function getTypeInfo(schema) {
|
|
|
32
63
|
readOrWriteOnly: (schema.readOnly ? '🆁' : schema.writeOnly ? '🆆' : ''),
|
|
33
64
|
deprecated: schema.deprecated ? '❌' : '',
|
|
34
65
|
examples: schema.examples || schema.example,
|
|
35
|
-
default: schema.default
|
|
66
|
+
default: getPrintableVal(schema.default),
|
|
36
67
|
description: schema.description || '',
|
|
37
68
|
constrain: '',
|
|
38
69
|
allowedValues: '',
|
|
@@ -45,16 +76,24 @@ export function getTypeInfo(schema) {
|
|
|
45
76
|
} else if (info.type === '{missing-type-info}' || info.type === 'any') {
|
|
46
77
|
info.description = info.description || '';
|
|
47
78
|
}
|
|
48
|
-
|
|
49
79
|
// Set Allowed Values
|
|
50
|
-
info.allowedValues =
|
|
80
|
+
info.allowedValues = schema.const
|
|
81
|
+
? schema.const
|
|
82
|
+
: Array.isArray(schema.enum)
|
|
83
|
+
? schema.enum.map((v) => (getPrintableVal(v))).join('┃')
|
|
84
|
+
: '';
|
|
85
|
+
|
|
51
86
|
if (dataType === 'array' && schema.items) {
|
|
52
87
|
const arrayItemType = schema.items?.type;
|
|
53
|
-
const arrayItemDefault = schema.items
|
|
88
|
+
const arrayItemDefault = getPrintableVal(schema.items.default);
|
|
54
89
|
|
|
55
90
|
info.arrayType = `${schema.type} of ${Array.isArray(arrayItemType) ? arrayItemType.join('') : arrayItemType}`;
|
|
56
91
|
info.default = arrayItemDefault;
|
|
57
|
-
info.allowedValues =
|
|
92
|
+
info.allowedValues = schema.items.const
|
|
93
|
+
? schema.const
|
|
94
|
+
: Array.isArray(schema.items?.enum)
|
|
95
|
+
? schema.items.enum.map((v) => (getPrintableVal(v))).join('┃')
|
|
96
|
+
: '';
|
|
58
97
|
}
|
|
59
98
|
if (dataType.match(/integer|number/g)) {
|
|
60
99
|
if (schema.minimum !== undefined || schema.exclusiveMinimum !== undefined) {
|
|
@@ -80,8 +119,9 @@ export function getTypeInfo(schema) {
|
|
|
80
119
|
info.html = `${info.type}~|~${info.readOrWriteOnly}~|~${info.constrain}~|~${info.default}~|~${info.allowedValues}~|~${info.pattern}~|~${info.description}~|~${schema.title || ''}~|~${info.deprecated ? 'deprecated' : ''}`;
|
|
81
120
|
return info;
|
|
82
121
|
}
|
|
122
|
+
|
|
83
123
|
export function nestExampleIfPresent(example) {
|
|
84
|
-
if (typeof example === 'boolean') {
|
|
124
|
+
if (typeof example === 'boolean' || typeof example === 'number') {
|
|
85
125
|
return {
|
|
86
126
|
Example: { value: `${example}` },
|
|
87
127
|
};
|
|
@@ -94,6 +134,18 @@ export function nestExampleIfPresent(example) {
|
|
|
94
134
|
return example ? { Example: { value: example } } : example;
|
|
95
135
|
}
|
|
96
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Normalize example object in the following format (List of object which is used to render example links and fill the input boxes)
|
|
139
|
+
* [{
|
|
140
|
+
* exampleVal : 'value to be rendered on the input control (text-box)',
|
|
141
|
+
* exampleList : [
|
|
142
|
+
* value : '',
|
|
143
|
+
* printableValue: '',
|
|
144
|
+
* summary : '',
|
|
145
|
+
* description : ''
|
|
146
|
+
* ]
|
|
147
|
+
* }]
|
|
148
|
+
* */
|
|
97
149
|
export function normalizeExamples(examples, dataType = 'string') {
|
|
98
150
|
if (!examples) {
|
|
99
151
|
return {
|
|
@@ -101,19 +153,18 @@ export function normalizeExamples(examples, dataType = 'string') {
|
|
|
101
153
|
exampleList: [],
|
|
102
154
|
};
|
|
103
155
|
}
|
|
104
|
-
|
|
105
156
|
if (examples.constructor === Object) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
?
|
|
110
|
-
:
|
|
157
|
+
const exampleList = Object.values(examples)
|
|
158
|
+
.filter((v) => (v['x-example-show-value'] !== false))
|
|
159
|
+
.map((v) => ({
|
|
160
|
+
value: (typeof v.value === 'boolean' || typeof v.value === 'number' ? `${v.value}` : (v.value || '')),
|
|
161
|
+
printableValue: getPrintableVal(v.value),
|
|
162
|
+
summary: v.summary || '',
|
|
163
|
+
description: v.description || '',
|
|
164
|
+
}));
|
|
165
|
+
const exampleVal = exampleList.length > 0
|
|
166
|
+
? exampleList[0].value
|
|
111
167
|
: '';
|
|
112
|
-
const exampleList = Object.values(examples).map((v) => ({
|
|
113
|
-
value: typeof v.value === 'boolean' || typeof v.value === 'number' ? v.value.toString() : v.value,
|
|
114
|
-
summary: v.summary,
|
|
115
|
-
description: v.description,
|
|
116
|
-
}));
|
|
117
168
|
return { exampleVal, exampleList };
|
|
118
169
|
}
|
|
119
170
|
|
|
@@ -131,12 +182,18 @@ export function normalizeExamples(examples, dataType = 'string') {
|
|
|
131
182
|
|
|
132
183
|
if (dataType === 'array') {
|
|
133
184
|
const [exampleVal] = examples;
|
|
134
|
-
const exampleList = examples.map((v) => ({
|
|
185
|
+
const exampleList = examples.map((v) => ({
|
|
186
|
+
value: v,
|
|
187
|
+
printableValue: getPrintableVal(v),
|
|
188
|
+
}));
|
|
135
189
|
return { exampleVal, exampleList };
|
|
136
190
|
}
|
|
137
191
|
|
|
138
192
|
const exampleVal = examples[0].toString();
|
|
139
|
-
const exampleList = examples.map((v) => ({
|
|
193
|
+
const exampleList = examples.map((v) => ({
|
|
194
|
+
value: v.toString(),
|
|
195
|
+
printableValue: getPrintableVal(v),
|
|
196
|
+
}));
|
|
140
197
|
return { exampleVal, exampleList };
|
|
141
198
|
}
|
|
142
199
|
|
|
@@ -153,6 +210,17 @@ export function getSampleValueByType(schemaObj) {
|
|
|
153
210
|
if (example === '') { return ''; }
|
|
154
211
|
if (example === null) { return null; }
|
|
155
212
|
if (example === 0) { return 0; }
|
|
213
|
+
if (example === false) { return false; }
|
|
214
|
+
if (example instanceof Date) {
|
|
215
|
+
switch (schemaObj.format.toLowerCase()) {
|
|
216
|
+
case 'date':
|
|
217
|
+
return example.toISOString().split('T')[0];
|
|
218
|
+
case 'time':
|
|
219
|
+
return example.toISOString().split('T')[1];
|
|
220
|
+
default:
|
|
221
|
+
return example.toISOString();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
156
224
|
if (example) { return example; }
|
|
157
225
|
|
|
158
226
|
if (Object.keys(schemaObj).length === 0) {
|
|
@@ -160,11 +228,20 @@ export function getSampleValueByType(schemaObj) {
|
|
|
160
228
|
}
|
|
161
229
|
if (schemaObj.$ref) {
|
|
162
230
|
// Indicates a Circular ref
|
|
163
|
-
return
|
|
231
|
+
return {};
|
|
232
|
+
}
|
|
233
|
+
if (schemaObj.const === false || schemaObj.const === 0 || schemaObj.const === null || schemaObj.const === '') {
|
|
234
|
+
return schemaObj.const;
|
|
235
|
+
}
|
|
236
|
+
if (schemaObj.const) {
|
|
237
|
+
return schemaObj.const;
|
|
238
|
+
}
|
|
239
|
+
if (schemaObj.default) {
|
|
240
|
+
return schemaObj.default;
|
|
164
241
|
}
|
|
165
242
|
const typeValue = Array.isArray(schemaObj.type) ? schemaObj.type[0] : schemaObj.type;
|
|
166
243
|
if (!typeValue) {
|
|
167
|
-
return
|
|
244
|
+
return null;
|
|
168
245
|
}
|
|
169
246
|
if (typeValue.match(/^integer|^number/g)) {
|
|
170
247
|
const multipleOf = Number.isNaN(Number(schemaObj.multipleOf)) ? undefined : Number(schemaObj.multipleOf);
|
|
@@ -187,7 +264,14 @@ export function getSampleValueByType(schemaObj) {
|
|
|
187
264
|
if (typeValue.match(/^null/g)) { return null; }
|
|
188
265
|
if (typeValue.match(/^string/g)) {
|
|
189
266
|
if (schemaObj.enum) { return schemaObj.enum[0]; }
|
|
190
|
-
if (schemaObj.
|
|
267
|
+
if (schemaObj.const) { return schemaObj.const; }
|
|
268
|
+
if (schemaObj.pattern) {
|
|
269
|
+
try {
|
|
270
|
+
return new RandExp(schemaObj.pattern).gen();
|
|
271
|
+
} catch (error) {
|
|
272
|
+
return schemaObj.pattern;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
191
275
|
if (schemaObj.format) {
|
|
192
276
|
const u = `${Date.now().toString(16)}${Math.random().toString(16)}0`.repeat(16);
|
|
193
277
|
switch (schemaObj.format.toLowerCase()) {
|
|
@@ -214,6 +298,8 @@ export function getSampleValueByType(schemaObj) {
|
|
|
214
298
|
return '2001:0db8:5b96:0000:0000:426f:8e17:642a';
|
|
215
299
|
case 'uuid':
|
|
216
300
|
return [u.substr(0, 8), u.substr(8, 4), `4000-8${u.substr(13, 3)}`, u.substr(16, 12)].join('-');
|
|
301
|
+
case 'byte':
|
|
302
|
+
return 'ZXhhbXBsZQ=='; // 'example' base64 encoded. See https://spec.openapis.org/oas/v3.0.0#data-types
|
|
217
303
|
default:
|
|
218
304
|
return '';
|
|
219
305
|
}
|
|
@@ -225,7 +311,7 @@ export function getSampleValueByType(schemaObj) {
|
|
|
225
311
|
}
|
|
226
312
|
}
|
|
227
313
|
// If type cannot be determined
|
|
228
|
-
return
|
|
314
|
+
return null;
|
|
229
315
|
}
|
|
230
316
|
|
|
231
317
|
/*
|
|
@@ -242,9 +328,9 @@ json2xml- TestCase
|
|
|
242
328
|
<root>
|
|
243
329
|
<prop1>simple</prop1>
|
|
244
330
|
<prop2>
|
|
245
|
-
<0>
|
|
246
|
-
<1>
|
|
247
|
-
<2>
|
|
331
|
+
<0>a</0>
|
|
332
|
+
<1>b</1>
|
|
333
|
+
<2>c</2>
|
|
248
334
|
</prop2>
|
|
249
335
|
<prop3>
|
|
250
336
|
<ob1>val-1</ob1>
|
|
@@ -259,12 +345,22 @@ export function json2xml(obj, level = 1) {
|
|
|
259
345
|
return `\n${indent}${obj.toString()}`;
|
|
260
346
|
}
|
|
261
347
|
for (const prop in obj) {
|
|
348
|
+
const tagNameOrProp = (obj[prop]['::XML_TAG'] || prop);
|
|
349
|
+
let tagName = '';
|
|
262
350
|
if (Array.isArray(obj[prop])) {
|
|
263
|
-
|
|
351
|
+
tagName = tagNameOrProp[0]['::XML_TAG'] || `${prop}`;
|
|
352
|
+
} else {
|
|
353
|
+
tagName = tagNameOrProp;
|
|
354
|
+
}
|
|
355
|
+
if (prop.startsWith('::')) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (Array.isArray(obj[prop])) {
|
|
359
|
+
xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
|
|
264
360
|
} else if (typeof obj[prop] === 'object') {
|
|
265
|
-
xmlText = `${xmlText}\n${indent}<${
|
|
361
|
+
xmlText = `${xmlText}\n${indent}<${tagName}>${json2xml(obj[prop], level + 1)}\n${indent}</${tagName}>`;
|
|
266
362
|
} else {
|
|
267
|
-
xmlText = `${xmlText}\n${indent}<${
|
|
363
|
+
xmlText = `${xmlText}\n${indent}<${tagName}>${obj[prop].toString()}</${tagName}>`;
|
|
268
364
|
}
|
|
269
365
|
}
|
|
270
366
|
return xmlText;
|
|
@@ -280,6 +376,12 @@ function addSchemaInfoToExample(schema, obj) {
|
|
|
280
376
|
if (schema.description) {
|
|
281
377
|
obj['::DESCRIPTION'] = schema.description;
|
|
282
378
|
}
|
|
379
|
+
if (schema.xml?.name) {
|
|
380
|
+
obj['::XML_TAG'] = schema.xml?.name;
|
|
381
|
+
}
|
|
382
|
+
if (schema.xml?.wrapped) {
|
|
383
|
+
obj['::XML_WRAP'] = schema.xml?.wrapped.toString();
|
|
384
|
+
}
|
|
283
385
|
}
|
|
284
386
|
|
|
285
387
|
function removeTitlesAndDescriptions(obj) {
|
|
@@ -288,6 +390,8 @@ function removeTitlesAndDescriptions(obj) {
|
|
|
288
390
|
}
|
|
289
391
|
delete obj['::TITLE'];
|
|
290
392
|
delete obj['::DESCRIPTION'];
|
|
393
|
+
delete obj['::XML_TAG'];
|
|
394
|
+
delete obj['::XML_WRAP'];
|
|
291
395
|
for (const k in obj) {
|
|
292
396
|
removeTitlesAndDescriptions(obj[k]);
|
|
293
397
|
}
|
|
@@ -326,11 +430,10 @@ export function schemaToSampleObj(schema, config = { }) {
|
|
|
326
430
|
if (!schema) {
|
|
327
431
|
return;
|
|
328
432
|
}
|
|
329
|
-
|
|
330
433
|
if (schema.allOf) {
|
|
331
434
|
const objWithAllProps = {};
|
|
332
435
|
|
|
333
|
-
if (schema.allOf.length === 1 && !schema.allOf[0]
|
|
436
|
+
if (schema.allOf.length === 1 && !schema.allOf[0]?.properties && !schema.allOf[0]?.items) {
|
|
334
437
|
// If allOf has single item and the type is not an object or array, then its a primitive
|
|
335
438
|
if (schema.allOf[0].$ref) {
|
|
336
439
|
return '{ }';
|
|
@@ -363,7 +466,11 @@ export function schemaToSampleObj(schema, config = { }) {
|
|
|
363
466
|
const objWithSchemaProps = {};
|
|
364
467
|
if (schema.properties) {
|
|
365
468
|
for (const propertyName in schema.properties) {
|
|
366
|
-
|
|
469
|
+
if (schema.properties[propertyName].properties || schema.properties[propertyName].properties?.items) {
|
|
470
|
+
objWithSchemaProps[propertyName] = schemaToSampleObj(schema.properties[propertyName], config);
|
|
471
|
+
} else {
|
|
472
|
+
objWithSchemaProps[propertyName] = getSampleValueByType(schema.properties[propertyName]);
|
|
473
|
+
}
|
|
367
474
|
}
|
|
368
475
|
}
|
|
369
476
|
|
|
@@ -477,16 +584,31 @@ export function schemaToSampleObj(schema, config = { }) {
|
|
|
477
584
|
addPropertyExampleToObjectExamples([schema.properties[propertyName].items.example], obj, propertyName);
|
|
478
585
|
} else {
|
|
479
586
|
const itemSamples = schemaToSampleObj(schema.properties[propertyName].items, config);
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
587
|
+
if (config.useXmlTagForProp) {
|
|
588
|
+
const xmlTagName = schema.properties[propertyName].xml?.name || propertyName;
|
|
589
|
+
if (schema.properties[propertyName].xml?.wrapped) {
|
|
590
|
+
const wrappedItemSample = JSON.parse(`{ "${xmlTagName}" : { "${xmlTagName}" : ${JSON.stringify(itemSamples['example-0'])} } }`);
|
|
591
|
+
obj = mergePropertyExamples(obj, xmlTagName, wrappedItemSample);
|
|
592
|
+
} else {
|
|
593
|
+
obj = mergePropertyExamples(obj, xmlTagName, itemSamples);
|
|
594
|
+
}
|
|
595
|
+
} else {
|
|
596
|
+
const arraySamples = [];
|
|
597
|
+
for (const key in itemSamples) {
|
|
598
|
+
arraySamples[key] = [itemSamples[key]];
|
|
599
|
+
}
|
|
600
|
+
obj = mergePropertyExamples(obj, propertyName, arraySamples);
|
|
483
601
|
}
|
|
484
|
-
obj = mergePropertyExamples(obj, propertyName, arraySamples);
|
|
485
602
|
}
|
|
486
603
|
continue;
|
|
487
604
|
}
|
|
488
605
|
obj = mergePropertyExamples(obj, propertyName, schemaToSampleObj(schema.properties[propertyName], config));
|
|
489
606
|
}
|
|
607
|
+
if (typeof schema.additionalProperties === 'object') {
|
|
608
|
+
const propertyName = schema.additionalProperties['x-additionalPropertiesName'] || 'property';
|
|
609
|
+
obj = mergePropertyExamples(obj, `${propertyName}1`, schemaToSampleObj(schema.additionalProperties, config));
|
|
610
|
+
obj = mergePropertyExamples(obj, `${propertyName}2`, schemaToSampleObj(schema.additionalProperties, config));
|
|
611
|
+
}
|
|
490
612
|
}
|
|
491
613
|
} else if (schema.type === 'array' || schema.items) {
|
|
492
614
|
if (schema.items || schema.example) {
|
|
@@ -513,26 +635,29 @@ export function schemaToSampleObj(schema, config = { }) {
|
|
|
513
635
|
}
|
|
514
636
|
|
|
515
637
|
function generateMarkdownForArrayAndObjectDescription(schema, level = 0) {
|
|
516
|
-
let markdown = '';
|
|
638
|
+
let markdown = ((schema.description || schema.title) && (schema.minItems || schema.maxItems)) ? '<span class="descr-expand-toggle">➔</span>' : '';
|
|
517
639
|
if (schema.title) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
640
|
+
if (schema.description) {
|
|
641
|
+
markdown = `${markdown} <b>${schema.title}:</b> ${schema.description}<br/>`;
|
|
642
|
+
} else {
|
|
643
|
+
markdown = `${markdown} ${schema.title}<br/>`;
|
|
644
|
+
}
|
|
645
|
+
} else if (schema.description) {
|
|
646
|
+
markdown = `${markdown} ${schema.description}<br/>`;
|
|
522
647
|
}
|
|
523
648
|
if (schema.minItems) {
|
|
524
|
-
markdown = `${markdown}
|
|
649
|
+
markdown = `${markdown} <b>Min Items:</b> ${schema.minItems}`;
|
|
525
650
|
}
|
|
526
651
|
if (schema.maxItems) {
|
|
527
|
-
markdown = `${markdown}
|
|
652
|
+
markdown = `${markdown} <b>Max Items:</b> ${schema.maxItems}`;
|
|
528
653
|
}
|
|
529
654
|
if (level > 0 && schema.items?.description) {
|
|
530
655
|
let itemsMarkdown = '';
|
|
531
656
|
if (schema.items.minProperties) {
|
|
532
|
-
itemsMarkdown =
|
|
657
|
+
itemsMarkdown = `<b>Min Properties:</b> ${schema.items.minProperties}`;
|
|
533
658
|
}
|
|
534
659
|
if (schema.items.maxProperties) {
|
|
535
|
-
itemsMarkdown = `${itemsMarkdown}
|
|
660
|
+
itemsMarkdown = `${itemsMarkdown} <b>Max Properties:</b> ${schema.items.maxProperties}`;
|
|
536
661
|
}
|
|
537
662
|
markdown = `${markdown} ⮕ ${itemsMarkdown} [ ${schema.items.description} ] `;
|
|
538
663
|
}
|
|
@@ -597,11 +722,13 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
597
722
|
if (v.type === 'object' || v.properties || v.allOf || v.anyOf || v.oneOf) {
|
|
598
723
|
const partialObj = schemaInObjectNotation(v, {});
|
|
599
724
|
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
|
|
725
|
+
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
|
|
600
726
|
objWithAnyOfProps['::type'] = 'xxx-of-option';
|
|
601
727
|
} else if (v.type === 'array' || v.items) {
|
|
602
728
|
// This else-if block never seems to get executed
|
|
603
729
|
const partialObj = schemaInObjectNotation(v, {});
|
|
604
730
|
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`] = partialObj;
|
|
731
|
+
objWithAnyOfProps[`::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`]['::readwrite'] = ''; // xxx-options cannot be read or write only
|
|
605
732
|
objWithAnyOfProps['::type'] = 'xxx-of-array';
|
|
606
733
|
} else {
|
|
607
734
|
const prop = `::OPTION~${index + 1}${v.title ? `~${v.title}` : ''}`;
|
|
@@ -610,7 +737,8 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
610
737
|
}
|
|
611
738
|
});
|
|
612
739
|
obj[(schema.anyOf ? `::ANY~OF ${suffix}` : `::ONE~OF ${suffix}`)] = objWithAnyOfProps;
|
|
613
|
-
obj['::type'] = '
|
|
740
|
+
// obj['::type'] = 'object';
|
|
741
|
+
obj['::type'] = 'object';
|
|
614
742
|
} else if (Array.isArray(schema.type)) {
|
|
615
743
|
// 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
|
|
616
744
|
// Clone the schema - as it will be modified to replace multi-data-types with one-of;
|
|
@@ -640,7 +768,7 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
640
768
|
}
|
|
641
769
|
}
|
|
642
770
|
if (complexTypes.length > 0) {
|
|
643
|
-
obj['::type'] = '
|
|
771
|
+
obj['::type'] = 'object';
|
|
644
772
|
const multiTypeOptions = {
|
|
645
773
|
'::type': 'xxx-of-option',
|
|
646
774
|
};
|
|
@@ -687,6 +815,7 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
687
815
|
obj['::type'] = 'object';
|
|
688
816
|
if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
|
|
689
817
|
obj['::dataTypeLabel'] = 'object or null';
|
|
818
|
+
obj['::nullable'] = true;
|
|
690
819
|
}
|
|
691
820
|
obj['::deprecated'] = schema.deprecated || false;
|
|
692
821
|
obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
|
|
@@ -697,8 +826,11 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
697
826
|
obj[key] = schemaInObjectNotation(schema.properties[key], {}, (level + 1));
|
|
698
827
|
}
|
|
699
828
|
}
|
|
829
|
+
for (const key in schema.patternProperties) {
|
|
830
|
+
obj[`[pattern: ${key}]`] = schemaInObjectNotation(schema.patternProperties[key], obj, (level + 1));
|
|
831
|
+
}
|
|
700
832
|
if (schema.additionalProperties) {
|
|
701
|
-
obj['
|
|
833
|
+
obj['[any-key]'] = schemaInObjectNotation(schema.additionalProperties, {});
|
|
702
834
|
}
|
|
703
835
|
} else if (schema.type === 'array' || schema.items) { // If Array
|
|
704
836
|
obj['::title'] = schema.title || '';
|
|
@@ -706,6 +838,7 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
|
|
|
706
838
|
obj['::type'] = 'array';
|
|
707
839
|
if ((Array.isArray(schema.type) && schema.type.includes('null')) || schema.nullable) {
|
|
708
840
|
obj['::dataTypeLabel'] = 'array or null';
|
|
841
|
+
obj['::nullable'] = true;
|
|
709
842
|
}
|
|
710
843
|
obj['::deprecated'] = schema.deprecated || false;
|
|
711
844
|
obj['::readwrite'] = schema.readOnly ? 'readonly' : schema.writeOnly ? 'writeonly' : '';
|
|
@@ -739,7 +872,8 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
|
|
|
739
872
|
egContent = examples[eg].value;
|
|
740
873
|
if (typeof examples[eg].value === 'string') {
|
|
741
874
|
try {
|
|
742
|
-
const fixedJsonString = examples[eg].value.replace((/([\w]+)(:)/g), '"$1"$2').replace((/'/g), '"');
|
|
875
|
+
// const fixedJsonString = examples[eg].value.replace((/([\w]+)(:)/g), '"$1"$2').replace((/'/g), '"');
|
|
876
|
+
const fixedJsonString = examples[eg].value;
|
|
743
877
|
egContent = JSON.parse(fixedJsonString);
|
|
744
878
|
egFormat = 'json';
|
|
745
879
|
} catch (err) {
|
|
@@ -797,7 +931,8 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
|
|
|
797
931
|
// If schema-level examples are not provided or includeGeneratedExample === true then generate one based on the schema field types
|
|
798
932
|
if (finalExamples.length === 0 || includeGeneratedExample === true) {
|
|
799
933
|
if (schema) {
|
|
800
|
-
if (schema.example) {
|
|
934
|
+
if (schema.example) {
|
|
935
|
+
// Note: Deprecated: The 'example' property has been deprecated in 3.1.0 in favor of the JSON Schema 'examples' keyword
|
|
801
936
|
finalExamples.push({
|
|
802
937
|
exampleId: 'Example',
|
|
803
938
|
exampleSummary: '',
|
|
@@ -812,22 +947,13 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
|
|
|
812
947
|
let exampleFormat = '';
|
|
813
948
|
let exampleValue = '';
|
|
814
949
|
if (mimeType?.toLowerCase().includes('xml')) {
|
|
815
|
-
xmlRootStart =
|
|
816
|
-
xmlRootEnd =
|
|
950
|
+
xmlRootStart = schema.xml?.name ? `<${schema.xml.name} ${schema.xml.namespace ? `xmlns="${schema.xml.namespace}"` : ''}>` : '<root>';
|
|
951
|
+
xmlRootEnd = schema.xml?.name ? `</${schema.xml.name}>` : '</root>';
|
|
817
952
|
exampleFormat = 'text';
|
|
818
953
|
} else {
|
|
819
954
|
exampleFormat = outputType;
|
|
820
955
|
}
|
|
821
|
-
|
|
822
|
-
const samples = schemaToSampleObj(
|
|
823
|
-
schema,
|
|
824
|
-
{
|
|
825
|
-
includeReadOnly,
|
|
826
|
-
includeWriteOnly,
|
|
827
|
-
deprecated: true,
|
|
828
|
-
},
|
|
829
|
-
);
|
|
830
|
-
|
|
956
|
+
const samples = schemaToSampleObj(schema, { includeReadOnly, includeWriteOnly, deprecated: true, useXmlTagForProp: mimeType?.toLowerCase().includes('xml') });
|
|
831
957
|
let i = 0;
|
|
832
958
|
for (const samplesKey in samples) {
|
|
833
959
|
if (!samples[samplesKey]) {
|
|
@@ -835,11 +961,10 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
|
|
|
835
961
|
}
|
|
836
962
|
const summary = samples[samplesKey]['::TITLE'] || `Example ${++i}`;
|
|
837
963
|
const description = samples[samplesKey]['::DESCRIPTION'] || '';
|
|
838
|
-
removeTitlesAndDescriptions(samples[samplesKey]);
|
|
839
|
-
|
|
840
964
|
if (mimeType?.toLowerCase().includes('xml')) {
|
|
841
|
-
exampleValue =
|
|
965
|
+
exampleValue = `<?xml version="1.0" encoding="UTF-8"?>\n${xmlRootStart}${json2xml(samples[samplesKey], 1)}\n${xmlRootEnd}`;
|
|
842
966
|
} else {
|
|
967
|
+
removeTitlesAndDescriptions(samples[samplesKey]);
|
|
843
968
|
exampleValue = outputType === 'text' ? JSON.stringify(samples[samplesKey], null, 2) : samples[samplesKey];
|
|
844
969
|
}
|
|
845
970
|
|
package/src/utils/spec-parser.js
CHANGED
|
@@ -3,7 +3,7 @@ import OpenApiParser from '@apitools/openapi-parser';
|
|
|
3
3
|
import { marked } from 'marked';
|
|
4
4
|
import { invalidCharsRegEx, rapidocApiKey, sleep } from '~/utils/common-utils';
|
|
5
5
|
|
|
6
|
-
export default async function ProcessSpec(specUrl, generateMissingTags = false, sortTags = false, sortEndpointsBy = '', attrApiKey = '', attrApiKeyLocation = '', attrApiKeyValue = '', serverUrl = '') {
|
|
6
|
+
export default async function ProcessSpec(specUrl, generateMissingTags = false, sortTags = false, sortSchemas = false, sortEndpointsBy = '', attrApiKey = '', attrApiKeyLocation = '', attrApiKeyValue = '', serverUrl = '') {
|
|
7
7
|
let jsonParsedSpec;
|
|
8
8
|
try {
|
|
9
9
|
this.requestUpdate(); // important to show the initial loader
|
|
@@ -53,7 +53,7 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
|
|
|
53
53
|
const tags = groupByTags(jsonParsedSpec, sortEndpointsBy, generateMissingTags, sortTags);
|
|
54
54
|
|
|
55
55
|
// Components
|
|
56
|
-
const components = getComponents(jsonParsedSpec);
|
|
56
|
+
const components = getComponents(jsonParsedSpec, sortSchemas);
|
|
57
57
|
|
|
58
58
|
// Info Description Headers
|
|
59
59
|
const infoDescriptionHeaders = jsonParsedSpec.info?.description ? getHeadersFromMarkdown(jsonParsedSpec.info.description) : [];
|
|
@@ -162,7 +162,7 @@ function getHeadersFromMarkdown(markdownContent) {
|
|
|
162
162
|
return headers || [];
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
function getComponents(openApiSpec) {
|
|
165
|
+
function getComponents(openApiSpec, sortSchemas = false) {
|
|
166
166
|
if (!openApiSpec.components) {
|
|
167
167
|
return [];
|
|
168
168
|
}
|
|
@@ -184,6 +184,10 @@ function getComponents(openApiSpec) {
|
|
|
184
184
|
|
|
185
185
|
switch (component) {
|
|
186
186
|
case 'schemas':
|
|
187
|
+
if (sortSchemas) {
|
|
188
|
+
subComponents.sort((c1, c2) => c1.name.localeCompare(c2.name));
|
|
189
|
+
}
|
|
190
|
+
|
|
187
191
|
cmpName = 'Schemas';
|
|
188
192
|
cmpDescription = 'Schemas allows the definition of input and output data types. These types can be objects, but also primitives and arrays.';
|
|
189
193
|
break;
|
|
@@ -246,6 +250,7 @@ function groupByTags(openApiSpec, sortEndpointsBy, generateMissingTags = false,
|
|
|
246
250
|
show: true,
|
|
247
251
|
elementId: `tag--${v.name.replace(invalidCharsRegEx, '-')}`,
|
|
248
252
|
name: v.name,
|
|
253
|
+
displayName: v['x-displayName'] || v.name,
|
|
249
254
|
description: v.description || '',
|
|
250
255
|
headers: v.description ? getHeadersFromMarkdown(v.description) : [],
|
|
251
256
|
paths: [],
|
|
@@ -347,6 +352,7 @@ function groupByTags(openApiSpec, sortEndpointsBy, generateMissingTags = false,
|
|
|
347
352
|
expandedAtLeastOnce: false,
|
|
348
353
|
summary: (pathOrHookObj.summary || ''),
|
|
349
354
|
description: (pathOrHookObj.description || ''),
|
|
355
|
+
externalDocs: pathOrHookObj.externalDocs,
|
|
350
356
|
shortSummary,
|
|
351
357
|
method: methodName,
|
|
352
358
|
path: pathOrHookName,
|
package/src/utils/theme.js
CHANGED
|
@@ -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.
|
|
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),
|
|
@@ -211,6 +214,8 @@ export default function setTheme(baseTheme, theme = {}) {
|
|
|
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