rapidoc 9.3.6 → 9.3.8

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 (44) hide show
  1. package/.eslintrc +9 -1
  2. package/dist/index.html +1010 -6
  3. package/dist/index.html.gz +0 -0
  4. package/dist/rapidoc-min.js +444 -428
  5. package/dist/rapidoc-min.js.LICENSE.txt +1 -8
  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 +576 -373
  11. package/dist/report.html +2 -2
  12. package/index.html +1006 -209
  13. package/{index1.html → index_bak.html} +13 -6
  14. package/jsconfig.json +1 -1
  15. package/package.json +8 -8
  16. package/src/components/api-request.js +144 -100
  17. package/src/components/api-response.js +12 -13
  18. package/src/components/json-tree.js +1 -1
  19. package/src/components/schema-table.js +16 -6
  20. package/src/components/schema-tree.js +15 -10
  21. package/src/json-schema-viewer.js +7 -2
  22. package/src/rapidoc-mini.js +22 -4
  23. package/src/rapidoc.js +35 -19
  24. package/src/styles/border-styles.js +2 -2
  25. package/src/styles/endpoint-styles.js +13 -10
  26. package/src/styles/flex-styles.js +1 -1
  27. package/src/styles/font-styles.js +13 -13
  28. package/src/styles/input-styles.js +8 -3
  29. package/src/styles/nav-styles.js +1 -1
  30. package/src/styles/schema-styles.js +12 -9
  31. package/src/templates/advance-search-template.js +2 -1
  32. package/src/templates/callback-template.js +3 -1
  33. package/src/templates/code-samples-template.js +3 -3
  34. package/src/templates/endpoint-template.js +33 -28
  35. package/src/templates/expanded-endpoint-template.js +7 -3
  36. package/src/templates/json-schema-viewer-template.js +3 -3
  37. package/src/templates/logo-template.js +1 -1
  38. package/src/templates/main-body-template.js +6 -17
  39. package/src/templates/navbar-template.js +6 -6
  40. package/src/templates/security-scheme-template.js +14 -10
  41. package/src/utils/common-utils.js +5 -9
  42. package/src/utils/schema-utils.js +65 -16
  43. package/src/utils/spec-parser.js +77 -7
  44. package/src/utils/theme.js +4 -6
@@ -120,18 +120,67 @@ export function getTypeInfo(schema) {
120
120
  return info;
121
121
  }
122
122
 
123
- export function nestExampleIfPresent(example) {
124
- if (typeof example === 'boolean' || typeof example === 'number') {
125
- return {
126
- Example: { value: `${example}` },
127
- };
128
- }
129
- if (example === '') {
130
- return {
131
- Example: { value: '' },
132
- };
123
+ /**
124
+ *
125
+ * @param {*} ex if the value
126
+ * - Is an Object with 'value' property like
127
+ * { 'value': 'example_val1', 'description': 'some description' }
128
+ * Returns >>>
129
+ * {
130
+ * 'Example': { 'value' : 'example_val1', 'description': 'some description' },
131
+ * }
132
+ * - Is an object where each key represents a valid example object (i,e has a value property)
133
+ * {
134
+ * 'example1': { 'value' : 'example_val1', 'description': 'some description' },
135
+ * 'example2': { 'value' : 'example_val2', 'description': 'some other description' },
136
+ * 'invalid': { 'description': 'invalid example object without any value property' }
137
+ * }
138
+ * Returns >>>
139
+ * {
140
+ * 'example1': { 'value' : 'example_val1', 'description': 'some description' },
141
+ * 'example2': { 'value' : 'example_val2', 'description': 'some other description' }
142
+ * }
143
+ * if none of the keys represents an object with 'value' property then return undefined
144
+ * - Is an array of premitive values
145
+ * ['example_val1', 'example_val2']
146
+ * Returns >>>
147
+ * {
148
+ * 'Example1': {value:'value1'}
149
+ * 'Example2': {value:'value2'}
150
+ * }
151
+ * - Is a premitive value
152
+ * 'example_val1'
153
+ * Returns >>>
154
+ * {
155
+ * 'Example': { 'value': 'example_val1' }
156
+ * }
157
+ * - Is undefined
158
+ * returns undefined
159
+ * @returns
160
+ */
161
+
162
+ export function standardizeExample(ex) {
163
+ if (typeof ex === 'object' && !Array.isArray(ex)) {
164
+ if (ex.value !== undefined) {
165
+ // Case 1: Single object with 'value' property
166
+ return { Example: { ...ex } };
167
+ }
168
+ // Case 2: Object where each key is an object with a 'value' property
169
+ const filteredEntries = Object.entries(ex).filter(([_, obj]) => obj.value !== undefined); // eslint-disable-line
170
+ // If no valid entries found, return JSON.stringify of the input
171
+ if (filteredEntries.length === 0) {
172
+ return undefined;
173
+ }
174
+ return Object.fromEntries(filteredEntries);
175
+ } if (Array.isArray(ex)) {
176
+ // Case 3: Array of primitive values
177
+ return ex.reduce((acc, value, index) => {
178
+ acc[`Example${index + 1}`] = { value };
179
+ return acc;
180
+ }, {});
133
181
  }
134
- return example ? { Example: { value: example } } : example;
182
+ // Case 4: Single primitive value
183
+ return ex ? { Example: { value: ex } } : undefined;
135
184
  }
136
185
 
137
186
  /**
@@ -268,7 +317,7 @@ export function getSampleValueByType(schemaObj) {
268
317
  if (schemaObj.pattern) {
269
318
  try {
270
319
  return new RandExp(schemaObj.pattern).gen();
271
- } catch (error) {
320
+ } catch {
272
321
  return schemaObj.pattern;
273
322
  }
274
323
  }
@@ -297,7 +346,7 @@ export function getSampleValueByType(schemaObj) {
297
346
  case 'ipv6':
298
347
  return '2001:0db8:5b96:0000:0000:426f:8e17:642a';
299
348
  case 'uuid':
300
- return [u.substr(0, 8), u.substr(8, 4), `4000-8${u.substr(13, 3)}`, u.substr(16, 12)].join('-');
349
+ return [u.substring(0, 8), u.substring(8, 12), `4000-8${u.substring(13, 16)}`, u.substring(16, 28)].join('-');
301
350
  case 'byte':
302
351
  return 'ZXhhbXBsZQ=='; // 'example' base64 encoded. See https://spec.openapis.org/oas/v3.0.0#data-types
303
352
  default:
@@ -857,7 +906,7 @@ export function schemaInObjectNotation(schema, obj, level = 0, suffix = '') {
857
906
  }
858
907
 
859
908
  /* Create Example object */
860
- export function generateExample(schema, mimeType, examples = '', example = '', includeReadOnly = true, includeWriteOnly = true, outputType = 'json', includeGeneratedExample = false) {
909
+ export function generateExample(schema, mimeType, examples = {}, example = {}, includeReadOnly = true, includeWriteOnly = true, outputType = 'json', includeGeneratedExample = false) {
861
910
  const finalExamples = [];
862
911
  // First check if examples is provided
863
912
  if (examples) {
@@ -876,7 +925,7 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
876
925
  const fixedJsonString = examples[eg].value;
877
926
  egContent = JSON.parse(fixedJsonString);
878
927
  egFormat = 'json';
879
- } catch (err) {
928
+ } catch {
880
929
  egFormat = 'text';
881
930
  egContent = examples[eg].value;
882
931
  }
@@ -910,7 +959,7 @@ export function generateExample(schema, mimeType, examples = '', example = '', i
910
959
  try {
911
960
  egContent = JSON.parse(example);
912
961
  egFormat = 'json';
913
- } catch (err) {
962
+ } catch {
914
963
  egFormat = 'text';
915
964
  egContent = example;
916
965
  }
@@ -3,8 +3,22 @@ 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, sortSchemas = false, sortEndpointsBy = '', attrApiKey = '', attrApiKeyLocation = '', attrApiKeyValue = '', serverUrl = '') {
6
+ export default async function ProcessSpec(
7
+ specUrl,
8
+ generateMissingTags = false,
9
+ sortTags = false,
10
+ sortSchemas = false,
11
+ sortEndpointsBy = '',
12
+ attrApiKey = '',
13
+ attrApiKeyLocation = '',
14
+ attrApiKeyValue = '',
15
+ serverUrl = '',
16
+ matchPaths = '',
17
+ matchType = '',
18
+ removeEndpointsWithBadgeLabelAs = '',
19
+ ) {
7
20
  let jsonParsedSpec;
21
+
8
22
  try {
9
23
  this.requestUpdate(); // important to show the initial loader
10
24
  let specMeta;
@@ -15,7 +29,7 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
15
29
  }
16
30
  await sleep(0); // important to show the initial loader (allows for rendering updates)
17
31
 
18
- // If JSON Schema Viewer
32
+ // If JSON Schema Viewer
19
33
  if (specMeta.resolvedSpec?.jsonSchemaViewer && specMeta.resolvedSpec?.schemaAndExamples) {
20
34
  this.dispatchEvent(new CustomEvent('before-render', { detail: { spec: specMeta.resolvedSpec } }));
21
35
  const schemaAndExamples = Object.entries(specMeta.resolvedSpec.schemaAndExamples).map((v) => ({ show: true, expanded: true, selectedExample: null, name: v[0], elementId: v[0].replace(invalidCharsRegEx, '-'), ...v[1] }));
@@ -27,8 +41,10 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
27
41
  };
28
42
  return parsedSpec;
29
43
  }
44
+
45
+ // If RapiDoc or RapiDocMini
30
46
  if (specMeta.spec && (specMeta.spec.components || specMeta.spec.info || specMeta.spec.servers || specMeta.spec.tags || specMeta.spec.paths)) {
31
- jsonParsedSpec = specMeta.spec;
47
+ jsonParsedSpec = filterPaths(specMeta.spec, matchPaths, matchType, removeEndpointsWithBadgeLabelAs);
32
48
  this.dispatchEvent(new CustomEvent('before-render', { detail: { spec: jsonParsedSpec } }));
33
49
  } else {
34
50
  console.info('RapiDoc: %c There was an issue while parsing the spec %o ', 'color:orangered', specMeta); // eslint-disable-line no-console
@@ -112,7 +128,7 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
112
128
 
113
129
  // Servers
114
130
  let servers = [];
115
- if (jsonParsedSpec.servers && Array.isArray(jsonParsedSpec.servers)) {
131
+ if (jsonParsedSpec.servers && Array.isArray(jsonParsedSpec.servers) && jsonParsedSpec.servers.length > 0) {
116
132
  jsonParsedSpec.servers.forEach((v) => {
117
133
  let computedUrl = v.url.trim();
118
134
  if (!(computedUrl.startsWith('http') || computedUrl.startsWith('//') || computedUrl.startsWith('{'))) {
@@ -141,7 +157,7 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
141
157
  } else {
142
158
  jsonParsedSpec.servers = [{ url: 'http://localhost', computedUrl: 'http://localhost' }];
143
159
  }
144
- servers = jsonParsedSpec.servers;
160
+ servers = jsonParsedSpec.servers; // eslint-disable-line prefer-destructuring
145
161
  const parsedSpec = {
146
162
  specLoadError: false,
147
163
  isSpecLoading: false,
@@ -156,6 +172,60 @@ export default async function ProcessSpec(specUrl, generateMissingTags = false,
156
172
  return parsedSpec;
157
173
  }
158
174
 
175
+ function filterPaths(openApiObject, matchPaths = '', matchType = '', removeEndpointsWithBadgeLabelAs = '') {
176
+ const filteredPaths = {};
177
+
178
+ // Convert the removePathsWithBadgeLabeledAs to an array if provided
179
+ const labelsToRemove = removeEndpointsWithBadgeLabelAs.split(',').map((label) => label.trim().toLowerCase()).filter(Boolean);
180
+
181
+ // Helper function to check if a path should be included based on matchPaths
182
+ function pathMatches(pathsKey, httpMethod) {
183
+ if (!matchPaths) {
184
+ return true; // If no matchPaths provided, include everything
185
+ }
186
+ const fullPath = `${httpMethod} ${pathsKey}`.toLowerCase(); // Construct "method path" string
187
+ if (matchType === 'regex') {
188
+ const regex = new RegExp(matchPaths, 'i');
189
+ return regex.test(matchPaths.toLowerCase());
190
+ }
191
+ return fullPath.includes(matchPaths.toLowerCase());
192
+ }
193
+
194
+ // Helper function to check if the badges contain any label that needs to be removed
195
+ function containsLabelToRemove(badges) {
196
+ return badges.some((badge) => labelsToRemove.includes(badge?.label.toLowerCase()));
197
+ }
198
+
199
+ // Loop through the paths in the openApiObject
200
+ Object.entries(openApiObject.paths).forEach(([pathsKey, methods]) => {
201
+ const filteredMethods = {};
202
+
203
+ Object.entries(methods).forEach(([httpMethod, methodDetails]) => {
204
+ const badges = methodDetails['x-badges'];
205
+
206
+ // Filter by matchPaths
207
+ if (pathMatches(pathsKey, httpMethod)) {
208
+ if (badges && Array.isArray(badges)) {
209
+ // Filter out based on removePathsWithBadgeLabeledAs
210
+ if (!containsLabelToRemove(badges)) {
211
+ filteredMethods[httpMethod] = methodDetails;
212
+ }
213
+ } else {
214
+ // No badges present, include the method
215
+ filteredMethods[httpMethod] = methodDetails;
216
+ }
217
+ }
218
+ });
219
+
220
+ if (Object.keys(filteredMethods).length > 0) {
221
+ filteredPaths[pathsKey] = filteredMethods;
222
+ }
223
+ });
224
+
225
+ openApiObject.paths = filteredPaths;
226
+ return openApiObject;
227
+ }
228
+
159
229
  function getHeadersFromMarkdown(markdownContent) {
160
230
  const tokens = marked.lexer(markdownContent);
161
231
  const headers = tokens.filter((v) => v.type === 'heading' && v.depth <= 2);
@@ -245,7 +315,7 @@ function getComponents(openApiSpec, sortSchemas = false) {
245
315
 
246
316
  function groupByTags(openApiSpec, sortEndpointsBy, generateMissingTags = false, sortTags = false) {
247
317
  const supportedMethods = ['get', 'put', 'post', 'delete', 'patch', 'head', 'options']; // this is also used for ordering endpoints by methods
248
- const tags = openApiSpec.tags && Array.isArray(openApiSpec.tags)
318
+ const tags = openApiSpec.tags && Array.isArray(openApiSpec.tags) && openApiSpec.tags.length > 0
249
319
  ? openApiSpec.tags.map((v) => ({
250
320
  show: true,
251
321
  elementId: `tag--${v.name.replace(invalidCharsRegEx, '-')}`,
@@ -286,7 +356,7 @@ function groupByTags(openApiSpec, sortEndpointsBy, generateMissingTags = false,
286
356
  pathTags.push(pathOrHookNameKey);
287
357
  } else {
288
358
  // firstWordEndIndex -= 1;
289
- pathTags.push(pathOrHookNameKey.substr(0, firstWordEndIndex));
359
+ pathTags.push(pathOrHookNameKey.substring(0, firstWordEndIndex));
290
360
  }
291
361
  } else {
292
362
  pathTags.push('General ⦂');
@@ -21,8 +21,8 @@ export default function setTheme(baseTheme, theme = {}) {
21
21
  const fg3 = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, -20); // or #aaa
22
22
  const lightFg = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, -65); // or #777
23
23
  const inlineCodeFg = theme.inlineCodeFg ? theme.inlineCodeFg : '#aaa';
24
- const selectionBg = '#bbb';
25
- const selectionFg = '#eee';
24
+ const selectionBg = fg2;
25
+ const selectionFg = bg2;
26
26
 
27
27
  const headerColor = theme.headerColor ? theme.headerColor : ColorUtils.color.brightness(bg1, 10);
28
28
 
@@ -107,10 +107,8 @@ export default function setTheme(baseTheme, theme = {}) {
107
107
  const fg3 = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, 30); // or #666
108
108
  const lightFg = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, 70); // or #999
109
109
  const inlineCodeFg = theme.inlineCodeFg ? theme.inlineCodeFg : 'brown';
110
-
111
- const selectionBg = '#444';
112
- const selectionFg = '#eee';
113
-
110
+ const selectionBg = fg2;
111
+ const selectionFg = bg2;
114
112
  const headerColor = theme.headerColor ? theme.headerColor : ColorUtils.color.brightness(bg1, -180);
115
113
 
116
114
  /*