rapidoc 9.1.0 → 9.1.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 (67) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/index.html.gz +0 -0
  3. package/dist/rapidoc-min.js +2 -5
  4. package/dist/rapidoc-min.js.LICENSE.txt +17 -1
  5. package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
  6. package/dist/rapidoc-min.js.gz +0 -0
  7. package/dist/report.html +6 -5
  8. package/docker/Dockerfile +5 -5
  9. package/docs/api.html +48 -40
  10. package/docs/examples/auth-test1.html +113 -0
  11. package/docs/examples/auth.html +37 -34
  12. package/docs/examples/badges.html +1 -1
  13. package/docs/examples/dynamic-query-params.html +1 -0
  14. package/docs/examples/mongo.html +33 -0
  15. package/docs/examples/readwrite.html +40 -0
  16. package/docs/examples/slots.html +7 -0
  17. package/docs/examples.html +3 -2
  18. package/docs/index.html +2 -2
  19. package/docs/list.html +15 -3
  20. package/docs/quickstart.html +1 -1
  21. package/docs/rapidoc-min.js +2 -5
  22. package/docs/rapidoc-mini.html +20 -20
  23. package/docs/specs/auth-test1.yaml +35 -0
  24. package/docs/specs/auth.yaml +2 -2
  25. package/docs/specs/code-highlight.yaml +1 -1
  26. package/docs/specs/data-types.yaml +0 -1
  27. package/docs/specs/dynamic-query-params.yaml +41 -0
  28. package/docs/specs/examples.yaml +11 -0
  29. package/docs/specs/mongo.yaml +78 -0
  30. package/docs/specs/multipart-formdata.yaml +3 -0
  31. package/docs/specs/petstore_extended.yaml +1 -1
  32. package/docs/specs/readwrite.yaml +90 -0
  33. package/docs/specs/server.yaml +4 -4
  34. package/docs/specs/temp.json +24 -105
  35. package/docs/specs/temp.yaml +20 -282
  36. package/docs/welcome.html +3 -3
  37. package/index.html +11 -6
  38. package/package.json +22 -21
  39. package/src/components/api-request.js +105 -63
  40. package/src/components/api-response.js +10 -10
  41. package/src/components/json-tree.js +2 -1
  42. package/src/components/schema-table.js +51 -14
  43. package/src/components/schema-tree.js +59 -18
  44. package/src/components/tag-input.js +8 -1
  45. package/src/index.js +2 -1
  46. package/src/json-schema-viewer.js +341 -0
  47. package/src/rapidoc-mini.js +5 -1
  48. package/src/rapidoc.js +11 -7
  49. package/src/styles/font-styles.js +3 -2
  50. package/src/styles/nav-styles.js +2 -2
  51. package/src/templates/components-template.js +9 -10
  52. package/src/templates/endpoint-template.js +1 -1
  53. package/src/templates/expanded-endpoint-template.js +1 -1
  54. package/src/templates/focused-endpoint-template.js +1 -1
  55. package/src/templates/header-template.js +1 -1
  56. package/src/templates/json-schema-viewer-template.js +184 -0
  57. package/src/templates/main-body-template.js +4 -1
  58. package/src/templates/navbar-template.js +3 -3
  59. package/src/templates/overview-template.js +6 -3
  60. package/src/templates/security-scheme-template.js +78 -38
  61. package/src/templates/server-template.js +1 -1
  62. package/src/utils/common-utils.js +2 -1
  63. package/src/utils/schema-utils.js +24 -19
  64. package/src/utils/spec-parser.js +24 -3
  65. package/webpack.config.js +1 -12
  66. package/dist/rapidoc-min.js.map +0 -1
  67. package/dist/rapidoc-min.js.map.gz +0 -0
@@ -1,9 +1,10 @@
1
1
  import { LitElement, html, css } from 'lit-element';
2
- import marked from 'marked';
2
+ import { marked } from 'marked';
3
3
  import Prism from 'prismjs';
4
4
 
5
5
  import { unsafeHTML } from 'lit-html/directives/unsafe-html';
6
- // import { live } from 'lit-html/directives/live';
6
+ import { guard } from 'lit-html/directives/guard';
7
+ import { live } from 'lit-html/directives/live';
7
8
  import TableStyles from '~/styles/table-styles';
8
9
  import FlexStyles from '~/styles/flex-styles';
9
10
  import InputStyles from '~/styles/input-styles';
@@ -102,6 +103,9 @@ export default class ApiRequest extends LitElement {
102
103
  color: var(--fg);
103
104
  font-family: var(--font-mono);
104
105
  }
106
+ .param-name.deprecated {
107
+ text-decoration: line-through;
108
+ }
105
109
  .param-type{
106
110
  color: var(--light-fg);
107
111
  font-family: var(--font-regular);
@@ -189,11 +193,11 @@ export default class ApiRequest extends LitElement {
189
193
  ${this.callback === 'true' ? 'CALLBACK REQUEST' : 'REQUEST'}
190
194
  </div>
191
195
  <div>
192
- ${this.inputParametersTemplate('path')}
193
- ${this.inputParametersTemplate('query')}
196
+ ${guard([this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('path'))}
197
+ ${guard([this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('query'))}
194
198
  ${this.requestBodyTemplate()}
195
- ${this.inputParametersTemplate('header')}
196
- ${this.inputParametersTemplate('cookie')}
199
+ ${guard([this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('header'))}
200
+ ${guard([this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('cookie'))}
197
201
  ${this.allowTry === 'false' ? '' : html`${this.apiCallTemplate()}`}
198
202
  </div>
199
203
  </div>
@@ -242,7 +246,7 @@ export default class ApiRequest extends LitElement {
242
246
  }
243
247
  }
244
248
  }"
245
- >${v.description || v.summary || v.value}</a>
249
+ >${v.value && Array.isArray(v.value) ? (v.value?.join(', ')) : (v.value || '')}</a>
246
250
  ${paramType === 'array' ? '] ' : ''}
247
251
  `)}
248
252
  `
@@ -281,6 +285,7 @@ export default class ApiRequest extends LitElement {
281
285
  // let exampleList = [];
282
286
  let paramStyle = 'form';
283
287
  let paramExplode = true;
288
+ let paramAllowReserved = false;
284
289
  if (paramType === 'query') {
285
290
  if (param.style && 'form spaceDelimited pipeDelimited'.includes(param.style)) {
286
291
  paramStyle = param.style;
@@ -290,6 +295,9 @@ export default class ApiRequest extends LitElement {
290
295
  if (typeof param.explode === 'boolean') {
291
296
  paramExplode = param.explode;
292
297
  }
298
+ if (typeof param.allowReserved === 'boolean') {
299
+ paramAllowReserved = param.allowReserved;
300
+ }
293
301
  }
294
302
 
295
303
  // openapi 3.1.0 spec based examples (which must be Object(string : { value:any, summary?: string, description?: string})
@@ -305,13 +313,14 @@ export default class ApiRequest extends LitElement {
305
313
  );
306
314
  if (!example.exampleVal && paramSchema.type === 'object') {
307
315
  example.exampleVal = generateExample(
316
+ declaredParamSchema,
317
+ serializeStyle || 'json',
308
318
  '',
309
319
  '',
310
- declaredParamSchema,
311
- serializeStyle,
312
320
  true,
313
321
  true,
314
322
  'text',
323
+ false,
315
324
  )[0].exampleValue;
316
325
  }
317
326
  const labelColWidth = 'read focused'.includes(this.renderStyle) ? '200px' : '160px';
@@ -340,6 +349,7 @@ export default class ApiRequest extends LitElement {
340
349
  data-example = "${Array.isArray(example.exampleVal) ? example.exampleVal.join('~|~') : example.exampleVal}"
341
350
  data-param-serialize-style = "${paramStyle}"
342
351
  data-param-serialize-explode = "${paramExplode}"
352
+ data-param-allow-reserved = "${paramAllowReserved}"
343
353
  data-array = "true"
344
354
  placeholder = "add-multiple &#x21a9;"
345
355
  .value = "${Array.isArray(example.exampleVal) ? example.exampleVal : example.exampleVal}"
@@ -368,6 +378,7 @@ export default class ApiRequest extends LitElement {
368
378
  data-example = "${example.exampleVal}"
369
379
  data-param-serialize-style = "${paramStyle}"
370
380
  data-param-serialize-explode = "${paramExplode}"
381
+ data-param-allow-reserved = "${paramAllowReserved}"
371
382
  spellcheck = "false"
372
383
  .textContent = "${this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : ''}"
373
384
  style = "resize:vertical; width:100%; height: ${'read focused'.includes(this.renderStyle) ? '180px' : '120px'};"
@@ -383,7 +394,7 @@ export default class ApiRequest extends LitElement {
383
394
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
384
395
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
385
396
  schema-hide-read-only = "${this.schemaHideReadOnly.includes(this.method)}"
386
- schema-hide-write-only = false
397
+ schema-hide-write-only = "false"
387
398
  > </schema-tree>
388
399
  </div>`
389
400
  }
@@ -395,8 +406,9 @@ export default class ApiRequest extends LitElement {
395
406
  data-ptype="${paramType}"
396
407
  data-pname="${param.name}"
397
408
  data-example="${Array.isArray(example.exampleVal) ? example.exampleVal.join('~|~') : example.exampleVal}"
409
+ data-param-allow-reserved = "${paramAllowReserved}"
398
410
  data-array="false"
399
- .value="${this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : ''}"
411
+ .value="${live(this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : '')}"
400
412
  />`
401
413
  }
402
414
  </td>`
@@ -531,13 +543,14 @@ export default class ApiRequest extends LitElement {
531
543
  // Generate Example
532
544
  if (reqBody.mimeType === this.selectedRequestBodyType) {
533
545
  reqBodyExamples = generateExample(
534
- reqBody.examples,
535
- reqBody.example,
536
546
  reqBody.schema,
537
547
  reqBody.mimeType,
548
+ reqBody.examples,
549
+ reqBody.example,
538
550
  false,
539
551
  true,
540
552
  'text',
553
+ false,
541
554
  );
542
555
  if (!this.selectedRequestBodyExample) {
543
556
  this.selectedRequestBodyExample = (reqBodyExamples.length > 0 ? reqBodyExamples[0].exampleId : '');
@@ -579,9 +592,7 @@ export default class ApiRequest extends LitElement {
579
592
  data-example-format = "${v.exampleFormat}"
580
593
  style="width:100%; resize:vertical;"
581
594
  .textContent = "${this.fillRequestFieldsWithExample === 'true' ? (v.exampleFormat === 'text' ? v.exampleValue : JSON.stringify(v.exampleValue, null, 2)) : ''}"
582
- >
583
- </textarea>
584
-
595
+ ></textarea>
585
596
  </div>
586
597
  `)}
587
598
 
@@ -591,19 +602,20 @@ export default class ApiRequest extends LitElement {
591
602
  } else if (this.selectedRequestBodyType.includes('form-urlencoded') || this.selectedRequestBodyType.includes('form-data')) {
592
603
  if (reqBody.mimeType === this.selectedRequestBodyType) {
593
604
  const ex = generateExample(
594
- reqBody.examples,
595
- reqBody.example,
596
605
  reqBody.schema,
597
606
  reqBody.mimeType,
607
+ reqBody.examples,
608
+ reqBody.example,
598
609
  false,
599
610
  true,
600
611
  'text',
612
+ false,
601
613
  );
602
614
  if (reqBody.schema) {
603
615
  reqBodyFormHtml = this.formDataTemplate(reqBody.schema, reqBody.mimeType, (ex[0] ? ex[0].exampleValue : ''));
604
616
  }
605
617
  }
606
- } else if ((RegExp('^audio/|^image/|^video/|^font/|tar$|zip$|7z$|rtf$|msword$|excel$|/pdf$|/octet-stream$').test(this.selectedRequestBodyType))) {
618
+ } else if ((/^audio\/|^image\/|^video\/|^font\/|tar$|zip$|7z$|rtf$|msword$|excel$|\/pdf$|\/octet-stream$/.test(this.selectedRequestBodyType))) {
607
619
  if (reqBody.mimeType === this.selectedRequestBodyType) {
608
620
  reqBodyFileInputHtml = html`
609
621
  <div class = "small-font-size bold-text row">
@@ -627,21 +639,21 @@ export default class ApiRequest extends LitElement {
627
639
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
628
640
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
629
641
  schema-hide-read-only = "${this.schemaHideReadOnly.includes(this.method)}"
630
- schema-hide-write-only = false
642
+ schema-hide-write-only = "false"
631
643
  > </schema-table>
632
644
  `;
633
645
  } else if (this.schemaStyle === 'tree') {
634
646
  reqBodySchemaHtml = html`
635
647
  ${reqBodySchemaHtml}
636
648
  <schema-tree
637
- class = '${reqBody.mimeType.substring(reqBody.mimeType.indexOf('/') + 1)}'
638
- style = 'display: ${this.selectedRequestBodyType === reqBody.mimeType ? 'block' : 'none'};'
639
- .data = '${schemaAsObj}'
649
+ class = "${reqBody.mimeType.substring(reqBody.mimeType.indexOf('/') + 1)}"
650
+ style = "display: ${this.selectedRequestBodyType === reqBody.mimeType ? 'block' : 'none'};"
651
+ .data = "${schemaAsObj}"
640
652
  schema-expand-level = "${this.schemaExpandLevel}"
641
653
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
642
654
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
643
- schema-hide-read-only = "${this.schemaHideReadOnly.includes(this.method)}"
644
- schema-hide-write-only = false
655
+ schema-hide-read-only = "true"
656
+ schema-hide-write-only = "false"
645
657
  > </schema-tree>
646
658
  `;
647
659
  }
@@ -682,13 +694,14 @@ export default class ApiRequest extends LitElement {
682
694
  // This template is used when form-data param should be send as a object (application/json, application/xml)
683
695
  const formdataPartSchema = schemaInObjectNotation(fieldSchema, {});
684
696
  const formdataPartExample = generateExample(
685
- fieldSchema.examples,
686
- fieldSchema.example,
687
697
  fieldSchema,
688
698
  'json',
699
+ fieldSchema.examples,
700
+ fieldSchema.example,
689
701
  false,
690
702
  true,
691
703
  'text',
704
+ false,
692
705
  );
693
706
 
694
707
  return html`
@@ -762,11 +775,8 @@ export default class ApiRequest extends LitElement {
762
775
  formDataTableRows.push(html`
763
776
  <tr>
764
777
  <td style="width:${labelColWidth}; min-width:100px;">
765
- <div class="param-name">
766
- ${fieldSchema.required
767
- ? html`<span style='color:var(--red);'>*</span>${fieldName}`
768
- : html`${fieldName}`
769
- }
778
+ <div class="param-name ${fieldSchema.deprecated ? 'deprecated' : ''}">
779
+ ${fieldName}${(schema.required?.includes(fieldName) || fieldSchema.required) ? html`<span style='color:var(--red);'>*</span>` : ''}
770
780
  </div>
771
781
  <div class="param-type">${paramSchema.type}</div>
772
782
  </td>
@@ -931,8 +941,7 @@ export default class ApiRequest extends LitElement {
931
941
  <pre style="white-space:pre; max-height:400px; overflow:auto">${responseFormat
932
942
  ? html`<code>${unsafeHTML(Prism.highlight(this.responseText, Prism.languages[responseFormat], responseFormat))}</code>`
933
943
  : `${this.responseText}`
934
- }
935
- </pre>
944
+ }</pre>
936
945
  </div>`
937
946
  }
938
947
  <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'};" >
@@ -1053,7 +1062,6 @@ export default class ApiRequest extends LitElement {
1053
1062
  fetchUrl = this.path;
1054
1063
  const fetchOptions = {
1055
1064
  method: this.method.toUpperCase(),
1056
- headers: {},
1057
1065
  };
1058
1066
  // Generate URL using Path Params
1059
1067
  pathParamEls.map((el) => {
@@ -1061,12 +1069,17 @@ export default class ApiRequest extends LitElement {
1061
1069
  });
1062
1070
 
1063
1071
  // Query Params
1064
- const urlQueryParam = new URLSearchParams();
1072
+ const urlQueryParamsMap = new Map();
1073
+ const queryParamsWithReservedCharsAllowed = [];
1065
1074
  if (queryParamEls.length > 0) {
1066
1075
  queryParamEls.forEach((el) => {
1076
+ const queryParam = new URLSearchParams();
1077
+ if (el.dataset.paramAllowReserved === 'true') {
1078
+ queryParamsWithReservedCharsAllowed.push(el.dataset.pname);
1079
+ }
1067
1080
  if (el.dataset.array === 'false') {
1068
1081
  if (el.value !== '') {
1069
- urlQueryParam.append(el.dataset.pname, el.value);
1082
+ queryParam.append(el.dataset.pname, el.value);
1070
1083
  }
1071
1084
  } else {
1072
1085
  const paramSerializeStyle = el.dataset.paramSerializeStyle;
@@ -1075,64 +1088,88 @@ export default class ApiRequest extends LitElement {
1075
1088
  vals = Array.isArray(vals) ? vals.filter((v) => v !== '') : [];
1076
1089
  if (vals.length > 0) {
1077
1090
  if (paramSerializeStyle === 'spaceDelimited') {
1078
- urlQueryParam.append(el.dataset.pname, vals.join(' ').replace(/^\s|\s$/g, ''));
1091
+ queryParam.append(el.dataset.pname, vals.join(' ').replace(/^\s|\s$/g, ''));
1079
1092
  } else if (paramSerializeStyle === 'pipeDelimited') {
1080
- urlQueryParam.append(el.dataset.pname, vals.join('|').replace(/^\||\|$/g, ''));
1093
+ queryParam.append(el.dataset.pname, vals.join('|').replace(/^\||\|$/g, ''));
1081
1094
  } else {
1082
1095
  if (paramSerializeExplode === 'true') { // eslint-disable-line no-lonely-if
1083
- vals.forEach((v) => { urlQueryParam.append(el.dataset.pname, v); });
1096
+ vals.forEach((v) => { queryParam.append(el.dataset.pname, v); });
1084
1097
  } else {
1085
- urlQueryParam.append(el.dataset.pname, vals.join(',').replace(/^,|,$/g, ''));
1098
+ queryParam.append(el.dataset.pname, vals.join(',').replace(/^,|,$/g, ''));
1086
1099
  }
1087
1100
  }
1088
1101
  }
1089
1102
  }
1103
+ if (queryParam.toString()) {
1104
+ urlQueryParamsMap.set(el.dataset.pname, queryParam);
1105
+ }
1090
1106
  });
1091
1107
  }
1092
1108
 
1093
1109
  // Query Params (Dynamic - create from JSON)
1094
1110
  if (queryParamObjTypeEls.length > 0) {
1095
1111
  queryParamObjTypeEls.map((el) => {
1112
+ const queryParam = new URLSearchParams();
1096
1113
  try {
1097
1114
  let queryParamObj = {};
1098
1115
  const paramSerializeStyle = el.dataset.paramSerializeStyle;
1099
1116
  const paramSerializeExplode = el.dataset.paramSerializeExplode;
1100
1117
  queryParamObj = Object.assign(queryParamObj, JSON.parse(el.value.replace(/\s+/g, ' ')));
1118
+ if (el.dataset.paramAllowReserved === 'true') {
1119
+ queryParamsWithReservedCharsAllowed.push(el.dataset.pname);
1120
+ }
1101
1121
  if ('json xml'.includes(paramSerializeStyle)) {
1102
1122
  if (paramSerializeStyle === 'json') {
1103
- urlQueryParam.append(el.dataset.pname, JSON.stringify(queryParamObj));
1123
+ queryParam.append(el.dataset.pname, JSON.stringify(queryParamObj));
1104
1124
  } else if (paramSerializeStyle === 'xml') {
1105
- urlQueryParam.append(el.dataset.pname, json2xml(queryParamObj));
1125
+ queryParam.append(el.dataset.pname, json2xml(queryParamObj));
1106
1126
  }
1107
1127
  } else {
1108
1128
  for (const key in queryParamObj) {
1109
1129
  if (typeof queryParamObj[key] === 'object') {
1110
1130
  if (Array.isArray(queryParamObj[key])) {
1111
1131
  if (paramSerializeStyle === 'spaceDelimited') {
1112
- urlQueryParam.append(key, queryParamObj[key].join(' '));
1132
+ queryParam.append(key, queryParamObj[key].join(' '));
1113
1133
  } else if (paramSerializeStyle === 'pipeDelimited') {
1114
- urlQueryParam.append(key, queryParamObj[key].join('|'));
1134
+ queryParam.append(key, queryParamObj[key].join('|'));
1115
1135
  } else {
1116
1136
  if (paramSerializeExplode === 'true') { // eslint-disable-line no-lonely-if
1117
1137
  queryParamObj[key].forEach((v) => {
1118
- urlQueryParam.append(key, v);
1138
+ queryParam.append(key, v);
1119
1139
  });
1120
1140
  } else {
1121
- urlQueryParam.append(key, queryParamObj[key]);
1141
+ queryParam.append(key, queryParamObj[key]);
1122
1142
  }
1123
1143
  }
1124
1144
  }
1125
1145
  } else {
1126
- urlQueryParam.append(key, queryParamObj[key]);
1146
+ queryParam.append(key, queryParamObj[key]);
1127
1147
  }
1128
1148
  }
1129
1149
  }
1130
1150
  } catch (err) {
1131
1151
  console.log('RapiDoc: unable to parse %s into object', el.value); // eslint-disable-line no-console
1132
1152
  }
1153
+ if (queryParam.toString()) {
1154
+ urlQueryParamsMap.set(el.dataset.pname, queryParam);
1155
+ }
1156
+ });
1157
+ }
1158
+ let urlQueryParamString = '';
1159
+ if (urlQueryParamsMap.size) {
1160
+ urlQueryParamString = '?';
1161
+ urlQueryParamsMap.forEach((val, pname) => {
1162
+ if (queryParamsWithReservedCharsAllowed.includes(pname)) {
1163
+ urlQueryParamString += `${pname}=`;
1164
+ urlQueryParamString += val.getAll(pname).join(`&${pname}=`);
1165
+ urlQueryParamString += '&';
1166
+ } else {
1167
+ urlQueryParamString += `${val.toString()}&`;
1168
+ }
1133
1169
  });
1170
+ urlQueryParamString = urlQueryParamString.slice(0, -1);
1134
1171
  }
1135
- fetchUrl = `${fetchUrl}${urlQueryParam.toString() ? '?' : ''}${urlQueryParam.toString()}`;
1172
+ fetchUrl = `${fetchUrl}${urlQueryParamString}`;
1136
1173
 
1137
1174
  // Add authentication Query-Param if provided
1138
1175
  this.api_keys
@@ -1150,13 +1187,13 @@ export default class ApiRequest extends LitElement {
1150
1187
  curlUrl = fetchUrl;
1151
1188
  }
1152
1189
  curl = `curl -X ${this.method.toUpperCase()} "${curlUrl}" \\\n`;
1153
-
1190
+ const reqHeaders = new Headers();
1154
1191
  if (acceptHeader) {
1155
1192
  // Uses the acceptHeader from Response panel
1156
- fetchOptions.headers.Accept = acceptHeader;
1193
+ reqHeaders.append('Accept', acceptHeader);
1157
1194
  curlHeaders += ` -H "Accept: ${acceptHeader}" \\\n`;
1158
1195
  } else if (this.accept) {
1159
- fetchOptions.headers.Accept = this.accept;
1196
+ reqHeaders.append('Accept', this.accept);
1160
1197
  curlHeaders += ` -H "Accept: ${this.accept}" \\\n`;
1161
1198
  }
1162
1199
 
@@ -1164,14 +1201,14 @@ export default class ApiRequest extends LitElement {
1164
1201
  this.api_keys
1165
1202
  .filter((v) => (v.in === 'header'))
1166
1203
  .forEach((v) => {
1167
- fetchOptions.headers[v.name] = v.finalKeyValue;
1204
+ reqHeaders.append(v.name, v.finalKeyValue);
1168
1205
  curlHeaders += ` -H "${v.name}: ${v.finalKeyValue}" \\\n`;
1169
1206
  });
1170
1207
 
1171
1208
  // Add Header Params
1172
1209
  headerParamEls.map((el) => {
1173
1210
  if (el.value) {
1174
- fetchOptions.headers[el.dataset.pname] = el.value;
1211
+ reqHeaders.append(el.dataset.pname, el.value);
1175
1212
  curlHeaders += ` -H "${el.dataset.pname}: ${el.value}" \\\n`;
1176
1213
  }
1177
1214
  });
@@ -1243,7 +1280,7 @@ export default class ApiRequest extends LitElement {
1243
1280
  }
1244
1281
  });
1245
1282
  fetchOptions.body = formDataParams;
1246
- } else if ((RegExp('^audio/|^image/|^video/|^font/|tar$|zip$|7z$|rtf$|msword$|excel$|/pdf$|/octet-stream$').test(requestBodyType))) {
1283
+ } else if (/^audio\/|^image\/|^video\/|^font\/|tar$|zip$|7z$|rtf$|msword$|excel$|\/pdf$|\/octet-stream$/.test(requestBodyType)) {
1247
1284
  const bodyParamFileEl = requestPanelEl.querySelector('.request-body-param-file');
1248
1285
  if (bodyParamFileEl?.files[0]) {
1249
1286
  fetchOptions.body = bodyParamFileEl.files[0];
@@ -1253,18 +1290,22 @@ export default class ApiRequest extends LitElement {
1253
1290
  const exampleTextAreaEl = requestPanelEl.querySelector('.request-body-param-user-input');
1254
1291
  if (exampleTextAreaEl?.value) {
1255
1292
  fetchOptions.body = exampleTextAreaEl.value;
1256
- // curlData = ` -d ${JSON.stringify(exampleTextAreaEl.value.replace(/(\r\n|\n|\r)/gm, '')).replace(/\\"/g, "'")} \\ \n`;
1257
- try {
1258
- curlData = ` -d '${JSON.stringify(JSON.parse(exampleTextAreaEl.value))}' \\\n`;
1259
- } catch (err) {
1260
- curlData = ` -d '${exampleTextAreaEl.value.replace(/(\r\n|\n|\r)/gm, '')}' \\\n`;
1293
+ if (requestBodyType.includes('json')) {
1294
+ try {
1295
+ curlData = ` -d '${JSON.stringify(JSON.parse(exampleTextAreaEl.value))}' \\\n`;
1296
+ } catch (err) {
1297
+ // Ignore.
1298
+ }
1299
+ }
1300
+ if (!curlData) {
1301
+ curlData = ` -d '${exampleTextAreaEl.value.replace(/'/g, '\'"\'"\'')}' \\\n`;
1261
1302
  }
1262
1303
  }
1263
1304
  }
1264
1305
  // Common for all request-body
1265
1306
  if (!requestBodyType.includes('form-data')) {
1266
1307
  // For multipart/form-data dont set the content-type to allow creation of browser generated part boundaries
1267
- fetchOptions.headers['Content-Type'] = requestBodyType;
1308
+ reqHeaders.append('Content-Type', requestBodyType);
1268
1309
  }
1269
1310
  curlHeaders += ` -H "Content-Type: ${requestBodyType}" \\\n`;
1270
1311
  }
@@ -1283,6 +1324,7 @@ export default class ApiRequest extends LitElement {
1283
1324
  if (this.fetchCredentials) {
1284
1325
  fetchOptions.credentials = this.fetchCredentials;
1285
1326
  }
1327
+ fetchOptions.headers = reqHeaders;
1286
1328
  const fetchRequest = new Request(fetchUrl, fetchOptions);
1287
1329
  this.dispatchEvent(new CustomEvent('before-try', {
1288
1330
  bubbles: true,
@@ -1336,10 +1378,10 @@ export default class ApiRequest extends LitElement {
1336
1378
  this.responseText = JSON.stringify(respJson, null, 2);
1337
1379
  }
1338
1380
  // eslint-disable-next-line no-useless-escape
1339
- } else if (RegExp('^font/|tar$|zip$|7z$|rtf$|msword$|excel$|/pdf$|/octet-stream$|^application\/vnd\.').test(contentType)) {
1381
+ } else if (/^font\/|tar$|zip$|7z$|rtf$|msword$|excel$|\/pdf$|\/octet-stream$|^application\/vnd\./.test(contentType)) {
1340
1382
  this.responseIsBlob = true;
1341
1383
  this.responseBlobType = 'download';
1342
- } else if (RegExp('^audio|^image|^video').test(contentType)) {
1384
+ } else if (/^audio|^image|^video/.test(contentType)) {
1343
1385
  this.responseIsBlob = true;
1344
1386
  this.responseBlobType = 'view';
1345
1387
  } else {
@@ -1,5 +1,5 @@
1
1
  import { LitElement, html, css } from 'lit-element';
2
- import marked from 'marked';
2
+ import { marked } from 'marked';
3
3
  import { unsafeHTML } from 'lit-html/directives/unsafe-html';
4
4
  import { schemaInObjectNotation, generateExample } from '~/utils/schema-utils';
5
5
  import FontStyles from '~/styles/font-styles';
@@ -114,10 +114,10 @@ export default class ApiResponse extends LitElement {
114
114
  const schemaTree = schemaInObjectNotation(mimeRespObj.schema, {});
115
115
  // Generate Example
116
116
  const respExamples = generateExample(
117
- mimeRespObj.examples,
118
- mimeRespObj.example,
119
117
  mimeRespObj.schema,
120
118
  mimeResp,
119
+ mimeRespObj.examples,
120
+ mimeRespObj.example,
121
121
  true,
122
122
  false,
123
123
  mimeResp.includes('json') ? 'json' : 'text',
@@ -302,23 +302,23 @@ export default class ApiResponse extends LitElement {
302
302
  ${this.schemaStyle === 'table'
303
303
  ? html`
304
304
  <schema-table
305
- render-style = '${this.renderStyle}'
306
- .data = '${mimeRespDetails.schemaTree}'
305
+ render-style = "${this.renderStyle}"
306
+ .data = "${mimeRespDetails.schemaTree}"
307
307
  schema-expand-level = "${this.schemaExpandLevel}"
308
308
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
309
309
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
310
- schema-hide-read-only = false
311
- schema-hide-write-only = ${this.schemaHideWriteOnly}
310
+ schema-hide-read-only = "false"
311
+ schema-hide-write-only = "${this.schemaHideWriteOnly}"
312
312
  > </schema-tree> `
313
313
  : html`
314
314
  <schema-tree
315
- render-style = '${this.renderStyle}'
315
+ render-style = "${this.renderStyle}"
316
316
  .data = '${mimeRespDetails.schemaTree}'
317
317
  schema-expand-level = "${this.schemaExpandLevel}"
318
318
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
319
319
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
320
- schema-hide-read-only = false
321
- schema-hide-write-only = ${this.schemaHideWriteOnly}
320
+ schema-hide-read-only = "false"
321
+ schema-hide-write-only = "${this.schemaHideWriteOnly}"
322
322
  > </schema-tree>`
323
323
  }`;
324
324
  }
@@ -23,6 +23,7 @@ export default class JsonTree extends LitElement {
23
23
  display:flex;
24
24
  }
25
25
  .json-tree {
26
+ position: relative;
26
27
  font-family: var(--font-mono);
27
28
  font-size: var(--font-size-small);
28
29
  display:inline-block;
@@ -98,7 +99,7 @@ export default class JsonTree extends LitElement {
98
99
  <div class="inside-bracket">
99
100
  ${Object.keys(data).map((key, i, a) => html`
100
101
  <div class="item">
101
- ${detailType === 'pure_object' ? html`${key}:` : ''}
102
+ ${detailType === 'pure_object' ? html`"${key}":` : ''}
102
103
  ${this.generateTree(data[key], i === (a.length - 1))}
103
104
  </div>`)
104
105
  }