rapidoc 9.2.0 → 9.3.3

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 (45) hide show
  1. package/.github/FUNDING.yml +13 -0
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +13 -6
  4. package/dist/index.html +1 -1
  5. package/dist/index.html.gz +0 -0
  6. package/dist/rapidoc-min.js +472 -353
  7. package/dist/rapidoc-min.js.LICENSE.txt +9 -11
  8. package/dist/rapidoc-min.js.LICENSE.txt.gz +0 -0
  9. package/dist/rapidoc-min.js.gz +0 -0
  10. package/dist/rapidoc-min.js.map +1 -1
  11. package/dist/rapidoc-min.js.map.gz +0 -0
  12. package/dist/rapidoc.js +1839 -3420
  13. package/dist/report.html +2 -2
  14. package/index.html +6 -5
  15. package/package.json +22 -20
  16. package/src/components/api-request.js +184 -85
  17. package/src/components/api-response.js +8 -4
  18. package/src/components/json-tree.js +13 -2
  19. package/src/components/schema-table.js +40 -18
  20. package/src/components/schema-tree.js +41 -12
  21. package/src/json-schema-viewer.js +1 -2
  22. package/src/rapidoc-mini.js +23 -0
  23. package/src/rapidoc.js +54 -17
  24. package/src/styles/endpoint-styles.js +9 -9
  25. package/src/styles/font-styles.js +1 -1
  26. package/src/styles/nav-styles.js +3 -1
  27. package/src/styles/schema-styles.js +3 -1
  28. package/src/styles/tab-styles.js +1 -0
  29. package/src/templates/callback-template.js +8 -4
  30. package/src/templates/components-template.js +2 -0
  31. package/src/templates/endpoint-template.js +20 -15
  32. package/src/templates/expanded-endpoint-template.js +76 -71
  33. package/src/templates/header-template.js +1 -1
  34. package/src/templates/json-schema-viewer-template.js +1 -1
  35. package/src/templates/main-body-template.js +1 -1
  36. package/src/templates/navbar-template.js +21 -8
  37. package/src/templates/overview-template.js +1 -1
  38. package/src/templates/security-scheme-template.js +30 -20
  39. package/src/templates/server-template.js +2 -2
  40. package/src/utils/common-utils.js +1 -4
  41. package/src/utils/schema-utils.js +96 -57
  42. package/src/utils/spec-parser.js +1 -1
  43. package/src/utils/theme.js +13 -6
  44. package/webpack.config.js +1 -1
  45. package/.vscode/settings.json +0 -12
@@ -3,6 +3,7 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js'; // eslint-disable-li
3
3
  import { guard } from 'lit/directives/guard.js'; // eslint-disable-line import/extensions
4
4
  import { live } from 'lit/directives/live.js'; // eslint-disable-line import/extensions
5
5
  import { marked } from 'marked';
6
+ import formatXml from 'xml-but-prettier';
6
7
  import Prism from 'prismjs';
7
8
  import TableStyles from '~/styles/table-styles';
8
9
  import FlexStyles from '~/styles/flex-styles';
@@ -12,8 +13,15 @@ import BorderStyles from '~/styles/border-styles';
12
13
  import TabStyles from '~/styles/tab-styles';
13
14
  import PrismStyles from '~/styles/prism-styles';
14
15
  import CustomStyles from '~/styles/custom-styles';
15
- import { copyToClipboard, prettyXml, downloadResource, viewResource } from '~/utils/common-utils';
16
- import { schemaInObjectNotation, getTypeInfo, generateExample, normalizeExamples, getSchemaFromParam, json2xml, nestExampleIfPresent } from '~/utils/schema-utils';
16
+ import { copyToClipboard, downloadResource, viewResource } from '~/utils/common-utils';
17
+ import { schemaInObjectNotation,
18
+ getTypeInfo,
19
+ generateExample,
20
+ normalizeExamples,
21
+ getSchemaFromParam,
22
+ json2xml,
23
+ nestExampleIfPresent,
24
+ anyExampleWithSummaryOrDescription } from '~/utils/schema-utils';
17
25
  import '~/components/json-tree';
18
26
  import '~/components/schema-tree';
19
27
  import '~/components/tag-input';
@@ -46,6 +54,7 @@ export default class ApiRequest extends LitElement {
46
54
  parser: { type: Object },
47
55
  accept: { type: String },
48
56
  callback: { type: String },
57
+ webhook: { type: String },
49
58
  responseMessage: { type: String, attribute: false },
50
59
  responseText: { type: String, attribute: false },
51
60
  responseHeaders: { type: String, attribute: false },
@@ -68,6 +77,7 @@ export default class ApiRequest extends LitElement {
68
77
  schemaDescriptionExpanded: { type: String, attribute: 'schema-description-expanded' },
69
78
  allowSchemaDescriptionExpandToggle: { type: String, attribute: 'allow-schema-description-expand-toggle' },
70
79
  schemaHideReadOnly: { type: String, attribute: 'schema-hide-read-only' },
80
+ schemaHideWriteOnly: { type: String, attribute: 'schema-hide-write-only' },
71
81
  fetchCredentials: { type: String, attribute: 'fetch-credentials' },
72
82
 
73
83
  // properties for internal tracking
@@ -98,12 +108,12 @@ export default class ApiRequest extends LitElement {
98
108
  text-align: right;
99
109
  line-height: var(--font-size-small);
100
110
  }
101
- .param-name{
111
+ .param-name {
102
112
  color: var(--fg);
103
113
  font-family: var(--font-mono);
104
114
  }
105
115
  .param-name.deprecated {
106
- text-decoration: line-through;
116
+ color: var(--red);
107
117
  }
108
118
  .param-type{
109
119
  color: var(--light-fg);
@@ -192,18 +202,19 @@ export default class ApiRequest extends LitElement {
192
202
  ${this.callback === 'true' ? 'CALLBACK REQUEST' : 'REQUEST'}
193
203
  </div>
194
204
  <div>
195
- ${guard([this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('path'))}
196
- ${guard([this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('query'))}
205
+ ${guard([this.method, this.path, this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('path'))}
206
+ ${guard([this.method, this.path, this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('query'))}
197
207
  ${this.requestBodyTemplate()}
198
- ${guard([this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('header'))}
199
- ${guard([this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('cookie'))}
208
+ ${guard([this.method, this.path, this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('header'))}
209
+ ${guard([this.method, this.path, this.allowTry, this.parameters, this.activeParameterSchemaTabs], () => this.inputParametersTemplate('cookie'))}
200
210
  ${this.allowTry === 'false' ? '' : html`${this.apiCallTemplate()}`}
201
211
  </div>
202
212
  </div>
203
213
  `;
204
214
  }
205
215
 
206
- updated(changedProperties) {
216
+ /*
217
+ async updated(changedProperties) {
207
218
  // In focused mode after rendering the request component, update the text-areas(which contains examples) using
208
219
  // the original values from hidden textareas
209
220
  // This is done coz, user may update the dom by editing the textarea's and once the DOM is updated externally change detection wont happen, therefore update the values manually
@@ -211,46 +222,98 @@ export default class ApiRequest extends LitElement {
211
222
  if (changedProperties.size === 1 && changedProperties.has('activeSchemaTab')) {
212
223
  // dont update example as only tabs is switched
213
224
  } else {
214
- const exampleTextAreaEls = [...this.shadowRoot.querySelectorAll('textarea[data-ptype="form-data"]')];
215
- exampleTextAreaEls.forEach((el) => {
216
- const origExampleEl = this.shadowRoot.querySelector(`textarea[data-pname='hidden-${el.dataset.pname}']`);
217
- if (origExampleEl) {
218
- el.value = origExampleEl.value;
219
- }
220
- });
225
+ this.requestUpdate();
221
226
  }
222
227
  }
223
228
  }
229
+ */
224
230
 
225
- /* eslint-disable indent */
231
+ async saveExampleState() {
232
+ if (this.renderStyle === 'focused') {
233
+ const reqBodyTextAreaEls = [...this.shadowRoot.querySelectorAll('textarea.request-body-param-user-input')];
234
+ reqBodyTextAreaEls.forEach((el) => {
235
+ el.dataset.user_example = el.value;
236
+ });
237
+ const exampleTextAreaEls = [...this.shadowRoot.querySelectorAll('textarea[data-ptype="form-data"]')];
238
+ exampleTextAreaEls.forEach((el) => {
239
+ el.dataset.user_example = el.value;
240
+ });
241
+ this.requestUpdate();
242
+ }
243
+ }
226
244
 
227
- exampleListTemplate(paramName, paramType, exampleList = []) {
245
+ async updateExamplesFromDataAttr() {
246
+ // In focused mode after rendering the request component, update the text-areas(which contains examples) using
247
+ // the original values from hidden textareas
248
+ // This is done coz, user may update the dom by editing the textarea's and once the DOM is updated externally change detection wont happen, therefore update the values manually
249
+ if (this.renderStyle === 'focused') {
250
+ const reqBodyTextAreaEls = [...this.shadowRoot.querySelectorAll('textarea.request-body-param-user-input')];
251
+ reqBodyTextAreaEls.forEach((el) => {
252
+ el.value = el.dataset.user_example || el.dataset.example;
253
+ });
254
+ const exampleTextAreaEls = [...this.shadowRoot.querySelectorAll('textarea[data-ptype="form-data"]')];
255
+ exampleTextAreaEls.forEach((el) => {
256
+ el.value = el.dataset.user_example || el.dataset.example;
257
+ });
258
+ this.requestUpdate();
259
+ }
260
+ }
261
+
262
+ renderExample(example, paramType, paramName) {
228
263
  return html`
229
- ${(exampleList.length > 0
230
- ? html`<span style="font-weight:bold">Example: </span>
231
- ${exampleList.map((v, i) => html`
232
- ${i === 0 ? '' : '┃'}
233
- ${paramType === 'array' ? '[' : ''}
234
- <a part="anchor anchor-param-example" class = "${this.allowTry === 'true' ? '' : 'inactive-link'}"
235
- data-example-type="${paramType === 'array' ? paramType : 'string'}"
236
- data-example = "${v.value && Array.isArray(v.value) ? (v.value?.join('~|~')) : (v.value || '')}"
237
- @click="${(e) => {
238
- const inputEl = e.target.closest('table').querySelector(`[data-pname="${paramName}"]`);
239
- if (inputEl) {
240
- if (e.target.dataset.exampleType === 'array') {
241
- inputEl.value = e.target.dataset.example.split('~|~');
242
- } else {
243
- inputEl.value = e.target.dataset.example;
244
- }
245
- }
246
- }
247
- }"
248
- >${v.value && Array.isArray(v.value) ? (v.value?.join(', ')) : (v.value || '')}</a>
249
- ${paramType === 'array' ? '] ' : ''}
264
+ ${paramType === 'array' ? '[' : ''}
265
+ <a
266
+ part="anchor anchor-param-example"
267
+ class="${this.allowTry === 'true' ? '' : 'inactive-link'}"
268
+ data-example-type="${paramType === 'array' ? paramType : 'string'}"
269
+ data-example="${example.value && Array.isArray(example.value) ? example.value?.join('~|~') : example.value || ''}"
270
+ @click="${(e) => {
271
+ const inputEl = e.target.closest('table').querySelector(`[data-pname="${paramName}"]`);
272
+ if (inputEl) {
273
+ if (e.target.dataset.exampleType === 'array') {
274
+ inputEl.value = e.target.dataset.example.split('~|~');
275
+ } else {
276
+ inputEl.value = e.target.dataset.example;
277
+ }
278
+ }
279
+ }
280
+ }"
281
+ >
282
+ ${example.value && Array.isArray(example.value) ? example.value?.join(', ') : example.value || '∅'}
283
+ </a>
284
+ ${paramType === 'array' ? '] ' : ''}
285
+ `;
286
+ }
287
+
288
+ renderShortFormatExamples(examples, paramType, paramName) {
289
+ return html`${examples.map((x, i) => html`
290
+ ${i === 0 ? '' : '┃'}
291
+ ${this.renderExample(x, paramType, paramName)}`)}`;
292
+ }
293
+
294
+ renderLongFormatExamples(exampleList, paramType, paramName) {
295
+ return html` <ul style="list-style-type: disclosure-closed;">
296
+ ${exampleList.map((v) => html`
297
+ <li>
298
+ ${this.renderExample(v, paramType, paramName)}
299
+ ${v.summary?.length > 0 ? html`<span>&lpar;${v.summary}&rpar;</span>` : ''}
300
+ ${v.description?.length > 0 ? html`<p>${unsafeHTML(marked(v.description))}</p>` : ''}
301
+ </li>
250
302
  `)}
251
- `
252
- : ''
253
- )}`;
303
+ </ul>`;
304
+ }
305
+
306
+ /* eslint-disable indent */
307
+
308
+ exampleListTemplate(paramName, paramType, exampleList = []) {
309
+ return html` ${exampleList.length > 0
310
+ ? html`<span style="font-weight:bold">Examples: </span>
311
+ ${
312
+ anyExampleWithSummaryOrDescription(exampleList)
313
+ ? this.renderLongFormatExamples(exampleList, paramType, paramName)
314
+ : this.renderShortFormatExamples(exampleList, paramType, paramName)
315
+ }`
316
+ : ''}`;
254
317
  }
255
318
 
256
319
  inputParametersTemplate(paramType) {
@@ -298,7 +361,6 @@ export default class ApiRequest extends LitElement {
298
361
  paramAllowReserved = param.allowReserved;
299
362
  }
300
363
  }
301
-
302
364
  // openapi 3.1.0 spec based examples (which must be Object(string : { value:any, summary?: string, description?: string})
303
365
  const example = normalizeExamples(
304
366
  (param.examples
@@ -316,7 +378,8 @@ export default class ApiRequest extends LitElement {
316
378
  serializeStyle || 'json',
317
379
  '',
318
380
  '',
319
- true,
381
+ this.callback === 'true' || this.webhook === 'true' ? true : false, // eslint-disable-line no-unneeded-ternary
382
+ this.callback === 'true' || this.webhook === 'true' ? false : true, // eslint-disable-line no-unneeded-ternary
320
383
  true,
321
384
  'text',
322
385
  false,
@@ -324,10 +387,12 @@ export default class ApiRequest extends LitElement {
324
387
  }
325
388
  const labelColWidth = 'read focused'.includes(this.renderStyle) ? '200px' : '160px';
326
389
  tableRows.push(html`
327
- <tr>
390
+ <tr title="${param.deprecated ? 'Deprecated' : ''}">
328
391
  <td rowspan="${this.allowTry === 'true' ? '1' : '2'}" style="width:${labelColWidth}; min-width:100px;">
329
- <div class="param-name">
330
- ${param.required ? html`<span style='color:var(--red)'>*</span>` : ''}${param.name}
392
+ <div class="param-name ${param.deprecated ? 'deprecated' : ''}" >
393
+ ${param.deprecated ? html`<span style='color:var(--red);'>✗</span>` : ''}
394
+ ${param.required ? html`<span style='color:var(--red)'>*</span>` : ''}
395
+ ${param.name}
331
396
  </div>
332
397
  <div class="param-type">
333
398
  ${paramSchema.type === 'array'
@@ -338,7 +403,7 @@ export default class ApiRequest extends LitElement {
338
403
  </td>
339
404
  ${this.allowTry === 'true'
340
405
  ? html`
341
- <td style="min-width:100px;">
406
+ <td style="min-width:100px;" colspan="${paramSchema.default || paramSchema.constrain || paramSchema.allowedValues || paramSchema.pattern ? '1' : '2'}">
342
407
  ${paramSchema.type === 'array'
343
408
  ? html`
344
409
  <tag-input class="request-param"
@@ -349,9 +414,13 @@ export default class ApiRequest extends LitElement {
349
414
  data-param-serialize-style = "${paramStyle}"
350
415
  data-param-serialize-explode = "${paramExplode}"
351
416
  data-param-allow-reserved = "${paramAllowReserved}"
417
+ data-x-fill-example = "${param['x-fill-example'] || 'yes'}"
352
418
  data-array = "true"
353
419
  placeholder = "add-multiple &#x21a9;"
354
- .value = "${Array.isArray(example.exampleVal) ? example.exampleVal : example.exampleVal}"
420
+ .value="${param['x-fill-example'] === 'no'
421
+ ? []
422
+ : live(this.fillRequestFieldsWithExample === 'true' ? Array.isArray(example.exampleVal) ? example.exampleVal : [example.exampleVal] : [])
423
+ }"
355
424
  >
356
425
  </tag-input>`
357
426
  : paramSchema.type === 'object'
@@ -378,13 +447,14 @@ export default class ApiRequest extends LitElement {
378
447
  data-param-serialize-style = "${paramStyle}"
379
448
  data-param-serialize-explode = "${paramExplode}"
380
449
  data-param-allow-reserved = "${paramAllowReserved}"
450
+ data-x-fill-example = "${param['x-fill-example'] || 'yes'}"
381
451
  spellcheck = "false"
382
- .textContent = "${this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : ''}"
452
+ .textContent="${param['x-fill-example'] === 'no' ? '' : live(this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : '')}"
383
453
  style = "resize:vertical; width:100%; height: ${'read focused'.includes(this.renderStyle) ? '180px' : '120px'};"
384
454
  ></textarea>
385
455
  </div>`
386
456
  : html`
387
- <div class="tab-content col">
457
+ <div class="tab-content col">
388
458
  <schema-tree
389
459
  class = 'json'
390
460
  style = 'display: block'
@@ -393,7 +463,10 @@ export default class ApiRequest extends LitElement {
393
463
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
394
464
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
395
465
  schema-hide-read-only = "${this.schemaHideReadOnly.includes(this.method)}"
396
- schema-hide-write-only = "false"
466
+ schema-hide-write-only = "${this.schemaHideWriteOnly.includes(this.method)}"
467
+ exportparts = "btn:btn, btn-fill:btn-fill, btn-outline:btn-outline, btn-try:btn-try, btn-clear:btn-clear, btn-clear-resp:btn-clear-resp,
468
+ file-input:file-input, textbox:textbox, textbox-param:textbox-param, textarea:textarea, textarea-param:textarea-param,
469
+ anchor:anchor, anchor-param-example:anchor-param-example"
397
470
  > </schema-tree>
398
471
  </div>`
399
472
  }
@@ -406,8 +479,9 @@ export default class ApiRequest extends LitElement {
406
479
  data-pname="${param.name}"
407
480
  data-example="${Array.isArray(example.exampleVal) ? example.exampleVal.join('~|~') : example.exampleVal}"
408
481
  data-param-allow-reserved = "${paramAllowReserved}"
482
+ data-x-fill-example = "${param['x-fill-example'] || 'yes'}"
409
483
  data-array="false"
410
- .value="${live(this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : '')}"
484
+ .value="${param['x-fill-example'] === 'no' ? '' : live(this.fillRequestFieldsWithExample === 'true' ? example.exampleVal : '')}"
411
485
  />`
412
486
  }
413
487
  </td>`
@@ -440,12 +514,12 @@ export default class ApiRequest extends LitElement {
440
514
  }`)}
441
515
  </div>
442
516
  </td>`
443
- : ''
517
+ : html`<td></td>`
444
518
  }
445
519
  </tr>
446
520
  <tr>
447
521
  ${this.allowTry === 'true' ? html`<td style="border:none"> </td>` : ''}
448
- <td colspan="2" style="border:none;">
522
+ <td colspan="2" style="border:none">
449
523
  <span class="m-markdown-small">${unsafeHTML(marked(param.description || ''))}</span>
450
524
  ${this.exampleListTemplate.call(this, param.name, paramSchema.type, example.exampleList)}
451
525
  </td>
@@ -462,9 +536,16 @@ export default class ApiRequest extends LitElement {
462
536
  </div>`;
463
537
  }
464
538
 
465
- resetRequestBodySelection() {
539
+ // This method is called before navigation change in focusd mode
540
+ async beforerNavigationFocusedMode() {
541
+ // this.saveExampleState();
542
+ }
543
+
544
+ // This method is called after navigation change in focusd mode
545
+ async afterNavigationFocusedMode() {
466
546
  this.selectedRequestBodyType = '';
467
547
  this.selectedRequestBodyExample = '';
548
+ this.updateExamplesFromDataAttr();
468
549
  this.clearResponseData();
469
550
  }
470
551
 
@@ -546,8 +627,8 @@ export default class ApiRequest extends LitElement {
546
627
  reqBody.mimeType,
547
628
  reqBody.examples,
548
629
  reqBody.example,
549
- false,
550
- true,
630
+ this.callback === 'true' || this.webhook === 'true' ? true : false, // eslint-disable-line no-unneeded-ternary
631
+ this.callback === 'true' || this.webhook === 'true' ? false : true, // eslint-disable-line no-unneeded-ternary
551
632
  'text',
552
633
  false,
553
634
  );
@@ -605,8 +686,8 @@ export default class ApiRequest extends LitElement {
605
686
  reqBody.mimeType,
606
687
  reqBody.examples,
607
688
  reqBody.example,
608
- false,
609
- true,
689
+ this.callback === 'true' || this.webhook === 'true' ? true : false, // eslint-disable-line no-unneeded-ternary
690
+ this.callback === 'true' || this.webhook === 'true' ? false : true, // eslint-disable-line no-unneeded-ternary
610
691
  'text',
611
692
  false,
612
693
  );
@@ -637,8 +718,9 @@ export default class ApiRequest extends LitElement {
637
718
  schema-expand-level = "${this.schemaExpandLevel}"
638
719
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
639
720
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
640
- schema-hide-read-only = "${this.schemaHideReadOnly.includes(this.method)}"
641
- schema-hide-write-only = "false"
721
+ schema-hide-read-only = "${this.schemaHideReadOnly}"
722
+ schema-hide-write-only = "${this.schemaHideWriteOnly}"
723
+ exportparts = "schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
642
724
  > </schema-table>
643
725
  `;
644
726
  } else if (this.schemaStyle === 'tree') {
@@ -651,8 +733,9 @@ export default class ApiRequest extends LitElement {
651
733
  schema-expand-level = "${this.schemaExpandLevel}"
652
734
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
653
735
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
654
- schema-hide-read-only = "true"
655
- schema-hide-write-only = "false"
736
+ schema-hide-read-only = "${this.schemaHideReadOnly}"
737
+ schema-hide-write-only = "${this.schemaHideWriteOnly}"
738
+ exportparts = "schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
656
739
  > </schema-tree>
657
740
  `;
658
741
  }
@@ -676,10 +759,8 @@ export default class ApiRequest extends LitElement {
676
759
  <button class="tab-btn ${this.activeSchemaTab === 'example' ? 'active' : ''}" data-tab = 'example'>EXAMPLE</button>
677
760
  <button class="tab-btn ${this.activeSchemaTab !== 'example' ? 'active' : ''}" data-tab = 'schema'>SCHEMA</button>
678
761
  </div>
679
- ${this.activeSchemaTab === 'example'
680
- ? html`<div class="tab-content col"> ${reqBodyExampleHtml}</div>`
681
- : html`<div class="tab-content col"> ${reqBodySchemaHtml}</div>`
682
- }
762
+ ${html`<div class="tab-content col" style="display:${this.activeSchemaTab === 'example' ? 'block' : 'none'};"> ${reqBodyExampleHtml}</div>`}
763
+ ${html`<div class="tab-content col" style="display:${this.activeSchemaTab === 'example' ? 'none' : 'block'};"> ${reqBodySchemaHtml}</div>`}
683
764
  </div>`
684
765
  : html`
685
766
  ${reqBodyFileInputHtml}
@@ -697,8 +778,8 @@ export default class ApiRequest extends LitElement {
697
778
  'json',
698
779
  fieldSchema.examples,
699
780
  fieldSchema.example,
700
- false,
701
- true,
781
+ this.callback === 'true' || this.webhook === 'true' ? true : false, // eslint-disable-line no-unneeded-ternary
782
+ this.callback === 'true' || this.webhook === 'true' ? false : true, // eslint-disable-line no-unneeded-ternary
702
783
  'text',
703
784
  false,
704
785
  );
@@ -740,8 +821,6 @@ export default class ApiRequest extends LitElement {
740
821
  .textContent = "${this.fillRequestFieldsWithExample === 'true' ? formdataPartExample[0].exampleValue : ''}"
741
822
  spellcheck = "false"
742
823
  ></textarea>
743
- <!-- This textarea(hidden) is to store the original example value, in focused mode on navbar change it is used to update the example text -->
744
- <textarea data-pname = "hidden-${fieldName}" data-ptype = "${mimeType.includes('form-urlencode') ? 'hidden-form-urlencode' : 'hidden-form-data'}" class="is-hidden" style="display:none">${formdataPartExample[0].exampleValue}</textarea>
745
824
  </div>`
746
825
  }
747
826
  ${html`
@@ -772,7 +851,7 @@ export default class ApiRequest extends LitElement {
772
851
  const labelColWidth = 'read focused'.includes(this.renderStyle) ? '200px' : '160px';
773
852
  const example = normalizeExamples((paramSchema.examples || paramSchema.example), paramSchema.type);
774
853
  formDataTableRows.push(html`
775
- <tr>
854
+ <tr title="${fieldSchema.deprecated ? 'Deprecated' : ''}">
776
855
  <td style="width:${labelColWidth}; min-width:100px;">
777
856
  <div class="param-name ${fieldSchema.deprecated ? 'deprecated' : ''}">
778
857
  ${fieldName}${(schema.required?.includes(fieldName) || fieldSchema.required) ? html`<span style='color:var(--red);'>*</span>` : ''}
@@ -907,7 +986,24 @@ export default class ApiRequest extends LitElement {
907
986
  }
908
987
 
909
988
  apiResponseTabTemplate() {
910
- const responseFormat = this.responseHeaders.includes('json') ? 'json' : (this.responseHeaders.includes('html') || this.responseHeaders.includes('xml')) ? 'html' : '';
989
+ let responseFormat = '';
990
+ let responseContent = '';
991
+ if (!this.responseIsBlob) {
992
+ if (this.responseHeaders.includes('application/x-ndjson')) {
993
+ responseFormat = 'json';
994
+ const prismLines = this.responseText.split('\n').map((q) => Prism.highlight(q, Prism.languages[responseFormat], responseFormat)).join('\n');
995
+ responseContent = html`<code>${unsafeHTML(prismLines)}</code>`;
996
+ } else if (this.responseHeaders.includes('json')) {
997
+ responseFormat = 'json';
998
+ responseContent = html`<code>${unsafeHTML(Prism.highlight(this.responseText, Prism.languages[responseFormat], responseFormat))}</code>`;
999
+ } else if (this.responseHeaders.includes('html') || this.responseHeaders.includes('xml')) {
1000
+ responseFormat = 'html';
1001
+ responseContent = html`<code>${unsafeHTML(Prism.highlight(this.responseText, Prism.languages[responseFormat], responseFormat))}</code>`;
1002
+ } else {
1003
+ responseFormat = 'text';
1004
+ responseContent = html`<code>${this.responseText}</code>`;
1005
+ }
1006
+ }
911
1007
  return html`
912
1008
  <div class="row" style="font-size:var(--font-size-small); margin:5px 0">
913
1009
  <div class="response-message ${this.responseStatus}">Response Status: ${this.responseMessage}</div>
@@ -935,19 +1031,16 @@ export default class ApiRequest extends LitElement {
935
1031
  }
936
1032
  </div>`
937
1033
  : html`
938
- <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'};" >
1034
+ <div class="tab-content col m-markdown" style="flex:1; display:${this.activeResponseTab === 'response' ? 'flex' : 'none'};" >
939
1035
  <button class="toolbar-btn" style="position:absolute; top:12px; right:8px" @click='${(e) => { copyToClipboard(this.responseText, e); }}' part="btn btn-fill"> Copy </button>
940
- <pre style="white-space:pre; max-height:400px; overflow:auto">${responseFormat
941
- ? html`<code>${unsafeHTML(Prism.highlight(this.responseText, Prism.languages[responseFormat], responseFormat))}</code>`
942
- : `${this.responseText}`
943
- }</pre>
1036
+ <pre style="white-space:pre; min-height:50px; height:var(--resp-area-height, 400px); resize:vertical; overflow:auto">${responseContent}</pre>
944
1037
  </div>`
945
1038
  }
946
- <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'};" >
1039
+ <div class="tab-content col m-markdown" style="flex:1; display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'};" >
947
1040
  <button class="toolbar-btn" style = "position:absolute; top:12px; right:8px" @click='${(e) => { copyToClipboard(this.responseHeaders, e); }}' part="btn btn-fill"> Copy </button>
948
1041
  <pre style="white-space:pre"><code>${unsafeHTML(Prism.highlight(this.responseHeaders, Prism.languages.css, 'css'))}</code></pre>
949
1042
  </div>
950
- <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'curl' ? 'flex' : 'none'};">
1043
+ <div class="tab-content col m-markdown" style="flex:1; display:${this.activeResponseTab === 'curl' ? 'flex' : 'none'};">
951
1044
  <button class="toolbar-btn" style = "position:absolute; top:12px; right:8px" @click='${(e) => { copyToClipboard(this.curlSyntax.replace(/\\$/, ''), e); }}' part="btn btn-fill"> Copy </button>
952
1045
  <pre style="white-space:pre"><code>${unsafeHTML(Prism.highlight(this.curlSyntax.trim().replace(/\\$/, ''), Prism.languages.shell, 'shell'))}</code></pre>
953
1046
  </div>
@@ -1340,6 +1433,9 @@ export default class ApiRequest extends LitElement {
1340
1433
  let respJson;
1341
1434
  let respText;
1342
1435
  tryBtnEl.disabled = true;
1436
+ this.responseText = '⌛';
1437
+ this.responseMessage = '';
1438
+ this.requestUpdate();
1343
1439
  const startTime = performance.now();
1344
1440
  fetchResponse = await fetch(fetchRequest, { signal });
1345
1441
  const endTime = performance.now();
@@ -1357,7 +1453,9 @@ export default class ApiRequest extends LitElement {
1357
1453
  if (respEmpty) {
1358
1454
  this.responseText = '';
1359
1455
  } else if (contentType) {
1360
- if (contentType.includes('json')) {
1456
+ if (contentType === 'application/x-ndjson') {
1457
+ this.responseText = await fetchResponse.text();
1458
+ } else if (contentType.includes('json')) {
1361
1459
  if ((/charset=[^"']+/).test(contentType)) {
1362
1460
  const encoding = contentType.split('charset=')[1];
1363
1461
  const buffer = await fetchResponse.arrayBuffer();
@@ -1386,13 +1484,14 @@ export default class ApiRequest extends LitElement {
1386
1484
  } else {
1387
1485
  respText = await fetchResponse.text();
1388
1486
  if (contentType.includes('xml')) {
1389
- this.responseText = prettyXml(respText);
1487
+ this.responseText = formatXml(respText, { textNodesOnSameLine: true, indentor: ' ' });
1488
+ } else {
1489
+ this.responseText = respText;
1390
1490
  }
1391
- this.responseText = respText;
1392
1491
  }
1393
1492
  if (this.responseIsBlob) {
1394
1493
  const contentDisposition = fetchResponse.headers.get('content-disposition');
1395
- this.respContentDisposition = contentDisposition ? contentDisposition.split('filename=')[1].replace(/\\"/g, '') : 'filename';
1494
+ this.respContentDisposition = contentDisposition ? contentDisposition.split('filename=')[1].replace(/"|'/g, '') : 'filename';
1396
1495
  respBlob = await fetchResponse.blob();
1397
1496
  this.responseBlobUrl = URL.createObjectURL(respBlob);
1398
1497
  }
@@ -24,6 +24,7 @@ export default class ApiResponse extends LitElement {
24
24
  static get properties() {
25
25
  return {
26
26
  callback: { type: String },
27
+ webhook: { type: String },
27
28
  responses: { type: Object },
28
29
  parser: { type: Object },
29
30
  schemaStyle: { type: String, attribute: 'schema-style' },
@@ -34,6 +35,7 @@ export default class ApiResponse extends LitElement {
34
35
  schemaExpandLevel: { type: Number, attribute: 'schema-expand-level' },
35
36
  schemaDescriptionExpanded: { type: String, attribute: 'schema-description-expanded' },
36
37
  allowSchemaDescriptionExpandToggle: { type: String, attribute: 'allow-schema-description-expand-toggle' },
38
+ schemaHideReadOnly: { type: String, attribute: 'schema-hide-read-only' },
37
39
  schemaHideWriteOnly: { type: String, attribute: 'schema-hide-write-only' },
38
40
  };
39
41
  }
@@ -118,8 +120,8 @@ export default class ApiResponse extends LitElement {
118
120
  mimeResp,
119
121
  mimeRespObj.examples,
120
122
  mimeRespObj.example,
121
- true,
122
- false,
123
+ this.callback === 'true' || this.webhook === 'true' ? false : true, // eslint-disable-line no-unneeded-ternary
124
+ this.callback === 'true' || this.webhook === 'true' ? true : false, // eslint-disable-line no-unneeded-ternary
123
125
  mimeResp.includes('json') ? 'json' : 'text',
124
126
  );
125
127
  allMimeResp[mimeResp] = {
@@ -309,8 +311,9 @@ export default class ApiResponse extends LitElement {
309
311
  schema-expand-level = "${this.schemaExpandLevel}"
310
312
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
311
313
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
312
- schema-hide-read-only = "false"
314
+ schema-hide-read-only = "${this.schemaHideReadOnly}"
313
315
  schema-hide-write-only = "${this.schemaHideWriteOnly}"
316
+ exportparts = "schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
314
317
  > </schema-tree> `
315
318
  : html`
316
319
  <schema-tree
@@ -319,8 +322,9 @@ export default class ApiResponse extends LitElement {
319
322
  schema-expand-level = "${this.schemaExpandLevel}"
320
323
  schema-description-expanded = "${this.schemaDescriptionExpanded}"
321
324
  allow-schema-description-expand-toggle = "${this.allowSchemaDescriptionExpandToggle}",
322
- schema-hide-read-only = "false"
325
+ schema-hide-read-only = "${this.schemaHideReadOnly}"
323
326
  schema-hide-write-only = "${this.schemaHideWriteOnly}"
327
+ exportparts = "schema-description:schema-description, schema-multiline-toggle:schema-multiline-toggle"
324
328
  > </schema-tree>`
325
329
  }`;
326
330
  }
@@ -35,18 +35,29 @@ export default class JsonTree extends LitElement {
35
35
  text-align: left;
36
36
  }
37
37
 
38
- .open-bracket{
38
+ .open-bracket {
39
39
  display:inline-block;
40
40
  padding: 0 20px 0 0;
41
41
  cursor:pointer;
42
42
  border: 1px solid transparent;
43
43
  border-radius:3px;
44
44
  }
45
- .open-bracket:hover{
45
+ .close-bracket {
46
+ border: 1px solid transparent;
47
+ border-radius:3px;
48
+ display:inline-block;
49
+ }
50
+ .open-bracket:hover {
46
51
  color:var(--primary-color);
47
52
  background-color:var(--hover-color);
48
53
  border: 1px solid var(--border-color);
49
54
  }
55
+ .open-bracket.expanded:hover ~ .inside-bracket {
56
+ border-left: 1px solid var(--fg3);
57
+ }
58
+ .open-bracket.expanded:hover ~ .close-bracket {
59
+ color:var(--primary-color);
60
+ }
50
61
  .inside-bracket{
51
62
  padding-left:12px;
52
63
  border-left:1px dotted var(--border-color);