openapi-explorer 2.1.656 → 2.1.659

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 (80) hide show
  1. package/dist/browser/openapi-explorer.min.js +2 -2
  2. package/dist/es/components/api-request.js +58 -140
  3. package/dist/es/components/api-response.js +9 -34
  4. package/dist/es/components/json-tree.js +4 -18
  5. package/dist/es/components/request-form-table.js +13 -36
  6. package/dist/es/components/schema-table.js +28 -42
  7. package/dist/es/components/schema-tree.js +31 -61
  8. package/dist/es/components/syntax-highlighter.js +7 -26
  9. package/dist/es/components/tag-input.js +2 -14
  10. package/dist/es/openapi-explorer-oauth-handler.js +0 -2
  11. package/dist/es/openapi-explorer.js +62 -174
  12. package/dist/es/react.js +4 -4
  13. package/dist/es/styles/input-styles.js +1 -1
  14. package/dist/es/styles/schema-styles.js +1 -1
  15. package/dist/es/templates/advance-search-template.js +1 -5
  16. package/dist/es/templates/callback-template.js +2 -2
  17. package/dist/es/templates/code-samples-template.js +1 -3
  18. package/dist/es/templates/components-template.js +41 -4
  19. package/dist/es/templates/endpoint-template.js +6 -17
  20. package/dist/es/templates/expanded-endpoint-template.js +4 -7
  21. package/dist/es/templates/focused-endpoint-template.js +0 -10
  22. package/dist/es/templates/mainBodyTemplate.js +3 -2
  23. package/dist/es/templates/navbar-template.js +9 -12
  24. package/dist/es/templates/overview-template.js +1 -1
  25. package/dist/es/templates/security-scheme-template.js +12 -73
  26. package/dist/es/templates/server-template.js +1 -8
  27. package/dist/es/utils/color-utils.js +2 -21
  28. package/dist/es/utils/common-utils.js +3 -20
  29. package/dist/es/utils/schema-utils.js +35 -132
  30. package/dist/es/utils/spec-parser.js +35 -120
  31. package/dist/es/utils/theme.js +3 -6
  32. package/dist/es/utils/xml/xml.js +1 -40
  33. package/dist/lib/components/api-request.js +58 -157
  34. package/dist/lib/components/api-response.js +9 -54
  35. package/dist/lib/components/json-tree.js +4 -27
  36. package/dist/lib/components/request-form-table.js +14 -42
  37. package/dist/lib/components/schema-table.js +28 -52
  38. package/dist/lib/components/schema-tree.js +31 -72
  39. package/dist/lib/components/syntax-highlighter.js +6 -49
  40. package/dist/lib/components/tag-input.js +2 -18
  41. package/dist/lib/languages/en.js +2 -3
  42. package/dist/lib/languages/fr.js +2 -3
  43. package/dist/lib/languages/index.js +0 -6
  44. package/dist/lib/openapi-explorer-oauth-handler.js +0 -6
  45. package/dist/lib/openapi-explorer.js +61 -197
  46. package/dist/lib/react.js +4 -5
  47. package/dist/lib/styles/advanced-search-styles.js +1 -5
  48. package/dist/lib/styles/api-request-styles.js +1 -5
  49. package/dist/lib/styles/border-styles.js +1 -5
  50. package/dist/lib/styles/endpoint-styles.js +1 -5
  51. package/dist/lib/styles/flex-styles.js +1 -5
  52. package/dist/lib/styles/font-styles.js +1 -5
  53. package/dist/lib/styles/info-styles.js +1 -5
  54. package/dist/lib/styles/input-styles.js +1 -5
  55. package/dist/lib/styles/key-frame-styles.js +1 -5
  56. package/dist/lib/styles/nav-styles.js +1 -5
  57. package/dist/lib/styles/prism-styles.js +1 -5
  58. package/dist/lib/styles/schema-styles.js +1 -5
  59. package/dist/lib/styles/tab-styles.js +1 -5
  60. package/dist/lib/styles/table-styles.js +1 -5
  61. package/dist/lib/styles/tag-input-styles.js +1 -5
  62. package/dist/lib/templates/advance-search-template.js +0 -6
  63. package/dist/lib/templates/callback-template.js +1 -3
  64. package/dist/lib/templates/code-samples-template.js +0 -4
  65. package/dist/lib/templates/components-template.js +43 -9
  66. package/dist/lib/templates/endpoint-template.js +6 -29
  67. package/dist/lib/templates/expanded-endpoint-template.js +3 -17
  68. package/dist/lib/templates/focused-endpoint-template.js +0 -19
  69. package/dist/lib/templates/mainBodyTemplate.js +2 -13
  70. package/dist/lib/templates/navbar-template.js +9 -20
  71. package/dist/lib/templates/overview-template.js +0 -5
  72. package/dist/lib/templates/security-scheme-template.js +12 -79
  73. package/dist/lib/templates/server-template.js +1 -12
  74. package/dist/lib/utils/color-utils.js +4 -25
  75. package/dist/lib/utils/common-utils.js +3 -33
  76. package/dist/lib/utils/schema-utils.js +33 -141
  77. package/dist/lib/utils/spec-parser.js +35 -128
  78. package/dist/lib/utils/theme.js +3 -16
  79. package/dist/lib/utils/xml/xml.js +1 -42
  80. package/package.json +2 -2
@@ -22,7 +22,6 @@ export default class ApiResponse extends LitElement {
22
22
  this.mimeResponsesForEachStatus = {};
23
23
  this.activeSchemaTab = 'model';
24
24
  }
25
-
26
25
  static get properties() {
27
26
  return {
28
27
  callback: {
@@ -37,11 +36,9 @@ export default class ApiResponse extends LitElement {
37
36
  includeNulls: {
38
37
  type: Boolean,
39
38
  attribute: 'display-nulls',
40
-
41
39
  converter(value) {
42
40
  return value === 'true';
43
41
  }
44
-
45
42
  },
46
43
  schemaStyle: {
47
44
  type: String,
@@ -73,46 +70,37 @@ export default class ApiResponse extends LitElement {
73
70
  }
74
71
  };
75
72
  }
76
-
77
73
  static finalizeStyles() {
78
74
  return [SchemaStyles, FontStyles, FlexStyles, TabStyles, TableStyles, InputStyles, BorderStyles, PrismStyles, css`.resp-head{vertical-align:middle;padding:16px 0 8px}.resp-head.divider{border-top:1px solid var(--border-color);margin-top:10px}.resp-status{font-weight:700;font-size:calc(var(--font-size-small) + 1px)}.resp-descr{font-size:calc(var(--font-size-small) + 1px)}.top-gap{margin-top:16px}.example-panel{font-size:var(--font-size-small);margin:0}.generic-tree{background:var(--bg2,#333);color:var(--fg,#fff)}.example-panel.generic-tree{margin-top:8px}pre.generic-tree{border:none;padding:8px 10px 10px}.example-panel select{margin-left:8px;padding-top:8px;min-width:100px;max-width:100%}.example-panel .example{padding:0 12px}.focused-mode,.read-mode{padding-top:24px;margin-top:12px;border-top:1px dashed var(--border-color)}`];
79
75
  }
80
-
81
76
  render() {
82
77
  return html` <div class="col regular-font response-panel ${this.renderStyle}-mode"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}"> ${this.callback === 'true' ? 'CALLBACK RESPONSE' : getI18nText('operations.response')} </div> <div> ${this.responseTemplate()} <div> </div> </div></div>`;
83
78
  }
84
-
85
79
  resetSelection() {
86
80
  this.selectedStatus = '';
87
81
  this.selectedMimeType = '';
88
82
  }
89
- /* eslint-disable indent */
90
-
91
83
 
84
+ /* eslint-disable indent */
92
85
  responseTemplate() {
93
86
  if (!this.responses) {
94
87
  return '';
95
88
  }
96
-
97
89
  for (const statusCode in this.responses) {
98
90
  if (!this.selectedStatus) {
99
91
  this.selectedStatus = statusCode;
100
92
  }
101
-
102
93
  const allMimeResp = {};
103
-
104
94
  for (const mimeResp in this.responses[statusCode] && this.responses[statusCode].content) {
105
95
  const mimeRespObj = this.responses[statusCode].content[mimeResp];
106
-
107
96
  if (!this.selectedMimeType) {
108
97
  this.selectedMimeType = mimeResp;
109
- } // Generate Schema
110
-
111
-
98
+ }
99
+ // Generate Schema
112
100
  const schemaTree = schemaInObjectNotation(mimeRespObj.schema, {
113
101
  includeNulls: this.includeNulls
114
- }); // Generate Example
115
-
102
+ });
103
+ // Generate Example
116
104
  const respExamples = generateExample(mimeRespObj.examples || '', mimeRespObj.example || '', mimeRespObj.schema, mimeResp, true, false, mimeResp.includes('json') ? 'json' : 'text');
117
105
  allMimeResp[mimeResp] = {
118
106
  description: this.responses[statusCode].description,
@@ -120,26 +108,21 @@ export default class ApiResponse extends LitElement {
120
108
  selectedExample: respExamples[0] && respExamples[0].exampleId || '',
121
109
  schemaTree
122
110
  };
123
- } // Headers for each response status
124
-
125
-
111
+ }
112
+ // Headers for each response status
126
113
  const tempHeaders = [];
127
-
128
114
  for (const key in this.responses[statusCode] && this.responses[statusCode].headers) {
129
115
  tempHeaders.push({
130
116
  name: key,
131
117
  ...this.responses[statusCode].headers[key]
132
118
  });
133
119
  }
134
-
135
120
  this.headersForEachRespStatus[statusCode] = tempHeaders;
136
121
  this.mimeResponsesForEachStatus[statusCode] = allMimeResp;
137
122
  }
138
-
139
123
  return html`<div class="row" style="flex-wrap:wrap"> ${Object.keys(this.responses).map(respStatus => html` ${respStatus === '$$ref' // Swagger-Client parser creates '$$ref' object if JSON references are used to create responses - this should be ignored
140
124
  ? '' : html` <button @click="${() => {
141
125
  this.selectedStatus = respStatus;
142
-
143
126
  if (this.responses[respStatus].content && Object.keys(this.responses[respStatus].content)[0]) {
144
127
  this.selectedMimeType = Object.keys(this.responses[respStatus].content)[0];
145
128
  } else {
@@ -151,20 +134,17 @@ export default class ApiResponse extends LitElement {
151
134
  }
152
135
  }}"> <button class="tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" data-tab="model">${getI18nText('operations.model')}</button> <button class="tab-btn ${this.activeSchemaTab !== 'model' ? 'active' : ''}" data-tab="body">${getI18nText('operations.example')}</button> <div style="flex:1"></div> ${Object.keys(this.mimeResponsesForEachStatus[status]).length === 1 ? html`<span class="small-font-size gray-text" style="align-self:center;margin-top:8px"> ${Object.keys(this.mimeResponsesForEachStatus[status])[0]} </span>` : html`${this.mimeTypeDropdownTemplate(Object.keys(this.mimeResponsesForEachStatus[status]))}`} </div> ${this.activeSchemaTab === 'body' ? html`<div class="tab-content col" style="flex:1"> ${this.mimeExampleTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>` : html`<div class="tab-content col" style="flex:1"> ${this.mimeSchemaTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} </div>`} </div> `}</div>`)} `;
153
136
  }
154
-
155
137
  responseHeaderListTemplate(respHeaders) {
156
138
  return html` <div style="padding:16px 0 8px 0" class="resp-headers small-font-size bold-text">${getI18nText('operations.response-headers')}</div> <table role="presentation" style="border-collapse:collapse;margin-bottom:16px;border:1px solid var(--border-color);border-radius:var(--border-radius)" class="small-font-size mono-font"> ${respHeaders.map(v => {
157
139
  const typeData = getTypeInfo(v.schema);
158
140
  return html` <tr> <td style="padding:8px;vertical-align:baseline;min-width:160px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${v.name || ''} </td> <td class="${(typeData === null || typeData === void 0 ? void 0 : typeData.cssType) || ''}" style="padding:4px;vertical-align:baseline;min-width:100px;padding:0 5px;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(typeData === null || typeData === void 0 ? void 0 : typeData.format) || (typeData === null || typeData === void 0 ? void 0 : typeData.type) || ''} </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> <div class="m-markdown-small regular-font">${unsafeHTML(marked(v.description || ''))}</div> </td> <td style="padding:8px;vertical-align:baseline;border-top:1px solid var(--light-border-color);text-overflow:ellipsis"> ${(typeData === null || typeData === void 0 ? void 0 : typeData.example) || ''} </td> </tr> `;
159
141
  })} </table>`;
160
142
  }
161
-
162
143
  mimeTypeDropdownTemplate(mimeTypes) {
163
144
  return html` <select aria-label="mime type" @change="${e => {
164
145
  this.selectedMimeType = e.target.value;
165
146
  }}" style="margin-bottom:-1px;z-index:1"> ${mimeTypes.map(mimeType => html`<option value="${mimeType}" ?selected="${mimeType === this.selectedMimeType}"> ${mimeType} </option>`)} </select>`;
166
147
  }
167
-
168
148
  onSelectExample(e) {
169
149
  const exampleContainerEl = e.target.closest('.example-panel');
170
150
  const exampleEls = [...exampleContainerEl.querySelectorAll('.example')];
@@ -172,27 +152,22 @@ export default class ApiResponse extends LitElement {
172
152
  v.style.display = v.dataset.example === e.target.value ? 'block' : 'none';
173
153
  });
174
154
  }
175
-
176
155
  mimeExampleTemplate(mimeRespDetails) {
177
156
  if (!mimeRespDetails) {
178
157
  return html` <pre style="color:var(--red)" class="example-panel border-top"> No example provided </pre> `;
179
158
  }
180
-
181
159
  return html` ${mimeRespDetails.examples.length === 1 ? html` ${mimeRespDetails.examples[0].exampleSummary && mimeRespDetails.examples[0].exampleSummary.length > 80 ? html`<div style="padding:4px 0"> ${mimeRespDetails.examples[0].exampleSummary} </div>` : ''} ${mimeRespDetails.examples[0].exampleDescription ? html`<div class="m-markdown-small" style="padding:4px 0"> ${unsafeHTML(marked(mimeRespDetails.examples[0].exampleDescription || ''))} </div>` : ''} <syntax-highlighter class="example-panel generic-tree border-top pad-top-8" mime-type="${mimeRespDetails.examples[0].exampleType}" .content="${mimeRespDetails.examples[0].exampleValue}">` : html` <span class="example-panel generic-tree ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}"> <select aria-label="response body example" @change="${e => this.onSelectExample(e)}"> ${mimeRespDetails.examples.map(v => html`<option value="${v.exampleId}" ?selected="${v.exampleId === mimeRespDetails.selectedExample}"> ${!v.exampleSummary || v.exampleSummary.length > 80 ? v.exampleId : v.exampleSummary} </option>`)} </select> ${mimeRespDetails.examples.map(v => html` <div class="example" data-example="${v.exampleId}" style="display:${v.exampleId === mimeRespDetails.selectedExample ? 'block' : 'none'}"> ${v.exampleSummary && v.exampleSummary.length > 80 ? html`<div style="padding:4px 0"> ${v.exampleSummary} </div>` : ''} ${v.exampleDescription && v.exampleDescription !== v.exampleSummary ? html`<div class="m-markdown-small" style="padding:4px 0"> ${unsafeHTML(marked(v.exampleDescription || ''))} </div>` : ''} <syntax-highlighter mime-type="${v.exampleType}" .content="${v.exampleValue}"> </div> `)} </span> `} `;
182
160
  }
183
-
184
161
  mimeSchemaTemplate(mimeRespDetails) {
185
162
  if (!mimeRespDetails) {
186
163
  return html` <pre style="color:var(--red)" class="${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top'}"> Schema not found</pre> `;
187
164
  }
188
-
189
165
  return html` ${this.schemaStyle === 'table' ? html` <schema-table render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}"> </schema-table> ` : html` <schema-tree render-style="${this.renderStyle}" .data="${mimeRespDetails.schemaTree}" class="example-panel ${this.renderStyle === 'read' ? 'border pad-8-16' : 'pad-top-8'}" schema-expand-level="${this.schemaExpandLevel}" schema-hide-read-only="false" schema-hide-write-only="${this.schemaHideWriteOnly}"> </schema-tree>`}`;
190
166
  }
191
167
  /* eslint-enable indent */
168
+ }
192
169
 
193
-
194
- } // Register the element with the browser
195
-
170
+ // Register the element with the browser
196
171
  if (!customElements.get('openapi-explorer')) {
197
172
  customElements.define('api-response', ApiResponse);
198
173
  }
@@ -15,68 +15,54 @@ export default class JsonTree extends LitElement {
15
15
  }
16
16
  };
17
17
  }
18
+
18
19
  /**
19
20
  * @param {Map<string, object>} changedProperties Changed Properties
20
21
  */
21
-
22
-
23
22
  update(changedProperties) {
24
23
  if (changedProperties.has('data')) {
25
24
  this.interactive = false;
26
25
  }
27
-
28
26
  super.update(changedProperties);
29
27
  }
30
-
31
28
  updated() {
32
29
  this.interactive = true; // Note: interactive is not a reactive property
33
30
  }
34
-
35
31
  static finalizeStyles() {
36
32
  return [FontStyles, BorderStyles, InputStyles, KeyFrameStyles, css`:host{display:flex}.json-tree{background:var(--bg2);padding:12px;min-height:30px;font-family:var(--font-mono);font-size:var(--font-size-small);overflow:hidden;word-break:break-all;flex:1;line-height:calc(var(--font-size-small) + 6px)}.open-bracket{display:inline-block;padding:0 20px 0 0;cursor:pointer;border:1px solid transparent;border-radius:3px}.collapsed.open-bracket{padding-right:0}.tree>.open-bracket{margin-left:-2px}.open-bracket:hover{color:var(--primary-color);background-color:var(--hover-color);border:1px solid var(--border-color)}.inside-bracket-wrapper{overflow:hidden}.tree:not(.interactive) .inside-bracket-wrapper{animation-duration:0s!important}.open-bracket:not(.collapsed)+.inside-bracket-wrapper{animation:linear .2s expand-height}.open-bracket.collapsed+.inside-bracket-wrapper{animation:linear .2s collapse-height;max-height:0}.inside-bracket{padding-left:16px;border-left:1px dotted var(--border-color)}.string{color:var(--green)}.number{color:var(--blue)}.null{color:var(--red)}.boolean{color:var(--orange)}.toolbar{display:none}.tree .toolbar{display:flex;justify-content:space-between;width:100%}.tree .item{border-bottom:1px dotted transparent}.toolbar-item{cursor:pointer;flex-shrink:0}.tree .toolbar .toolbar-item{display:none}.inside-bracket.xxx-of{padding:5px 0;border-style:dotted;border-width:0 0 1px 0;border-color:var(--primary-color)}.schema-root-type.xxx-of{display:none}.toolbar-item:first-of-type{margin:0 2px 0 0}@media only screen and (min-width:576px){.key-descr{display:block}.tree .toolbar .toolbar-item{display:block}.toolbar{display:flex}}.toolbar-backup{position:absolute;right:6px;display:flex;align-items:center}`];
37
33
  }
38
- /* eslint-disable indent */
39
-
40
34
 
35
+ /* eslint-disable indent */
41
36
  render() {
42
37
  return html` <div class="json-tree tree ${this.interactive ? 'interactive' : ''}"> ${this.generateTree(this.data, true)} </div> `;
43
38
  }
44
-
45
39
  generateTree(data, isLast = false) {
46
40
  if (data === null) {
47
41
  return html`<div class="null" style="display:inline">null</div>`;
48
42
  }
49
-
50
43
  if (typeof data === 'object' && data instanceof Date === false) {
51
44
  const detailType = Array.isArray(data) ? 'array' : 'pure_object';
52
-
53
45
  if (Object.keys(data).length === 0) {
54
46
  return html`${Array.isArray(data) ? '[ ],' : '{ },'}`;
55
47
  }
56
-
57
48
  return html` <div class="open-bracket ${detailType === 'array' ? 'array' : 'object'}" @click="${this.toggleExpand}"> ${detailType === 'array' ? '[' : '{'}</div> <div class="inside-bracket-wrapper"> <div class="inside-bracket"> ${Object.keys(data).map((key, i, a) => html` <div class="item"> ${detailType === 'pure_object' ? html`"${key}":` : ''} ${this.generateTree(data[key], i === a.length - 1)} </div>`)} </div> <div class="close-bracket">${detailType === 'array' ? ']' : '}'}${isLast ? '' : ','}</div> </div> `;
58
49
  }
59
-
60
50
  return typeof data === 'string' || data instanceof Date ? html`<span class="${typeof data}">"${data}"</span>${isLast ? '' : ','}` : html`<span class="${typeof data}">${data}</span>${isLast ? '' : ','}`;
61
51
  }
62
52
  /* eslint-enable indent */
63
53
 
64
-
65
54
  toggleExpand(e) {
66
55
  const openBracketEl = e.target;
67
56
  openBracketEl.classList.toggle('collapsed');
68
-
69
57
  if (openBracketEl.classList.contains('collapsed')) {
70
58
  e.target.innerHTML = e.target.classList.contains('array') ? '[...]' : '{...}';
71
59
  } else {
72
60
  e.target.innerHTML = e.target.classList.contains('array') ? '[' : '{';
73
61
  }
74
-
75
62
  this.requestUpdate();
76
63
  }
77
-
78
- } // Register the element with the browser
79
-
64
+ }
65
+ // Register the element with the browser
80
66
  if (!customElements.get('openapi-explorer')) {
81
67
  customElements.define('json-tree', JsonTree);
82
68
  }
@@ -5,22 +5,17 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
5
5
  import { isPatternProperty } from '../utils/schema-utils.js';
6
6
  import { map } from 'lit/directives/map.js';
7
7
  import { range } from 'lit/directives/range.js';
8
-
9
8
  function generateFormRows(data, options, dataType = 'object', key = '', description = '', schemaLevel = 0) {
10
9
  const newSchemaLevel = data['::type'] && data['::type'].startsWith('xxx-of') ? schemaLevel : schemaLevel + 1;
11
-
12
10
  if (!data) {
13
11
  return null;
14
12
  }
15
-
16
13
  if (Object.keys(data).length === 0) {
17
14
  return null;
18
15
  }
19
-
20
16
  let rawKeyLabel = '';
21
17
  let keyDescr = '';
22
18
  let isOneOfLabel = false;
23
-
24
19
  if (key.startsWith('::ONE~OF') || key.startsWith('::ANY~OF')) {
25
20
  rawKeyLabel = key.replace('::', '').replace('~', ' ');
26
21
  isOneOfLabel = true;
@@ -31,22 +26,21 @@ function generateFormRows(data, options, dataType = 'object', key = '', descript
31
26
  } else {
32
27
  rawKeyLabel = key;
33
28
  }
34
-
35
29
  const keyLabel = rawKeyLabel.replace(/[*]$/, '');
36
30
  const isRequired = rawKeyLabel.endsWith('*');
37
-
38
31
  if (typeof data === 'object') {
39
32
  const flags = data['::flags'] || {};
40
-
41
33
  if (flags['🆁']) {
42
34
  return undefined;
43
35
  }
44
-
45
36
  const displayLine = [description].filter(v => v).join(' ');
46
- return html` ${newSchemaLevel >= 0 && key ? html` <tr class="complex-object-display ${data['::type']}" data-obj="${keyLabel}"> <td class="key ${data['::deprecated'] ? 'deprecated' : ''}"> <div style="display:flex;align-items:center"> ${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' || key.startsWith('::OPTION') ? html`<span class="xxx-of-key">${keyLabel}</span><span class="${isOneOfLabel ? 'xxx-of-key' : 'xxx-of-descr'}">${keyDescr}</span>` : isRequired ? html`<span class="key-label requiredStar" style="display:inline-block" title="Required">${keyLabel}</span>` : html`<span class="key-label" style="display:inline-block">${keyLabel === '::props' ? '' : keyLabel}</span>`} </div> </td> <td> </td> <td class="key-descr m-markdown-small">${unsafeHTML(marked(displayLine))}</td> </tr>` : html`${data['::type'] === 'array' && dataType === 'array' ? html`<tr><td> ${dataType} </td> </tr>` : ''}`} ${Array.isArray(data) && data[0] ? html`${generateFormRows.call(this, data[0], options, 'xxx-of-option', '::ARRAY~OF', '', newSchemaLevel)}` : html`${Object.keys(data).map(dataKey => !['::metadata', '::title', '::description', '::type', '::props', '::deprecated', '::array-type', '::dataTypeLabel', '::flags'].includes(dataKey) || data[dataKey]['::type'] === 'array' && data[dataKey]['::type'] === 'object' ? html`${generateFormRows.call(this, data[dataKey]['::type'] === 'array' ? data[dataKey]['::props'] : data[dataKey], options, data[dataKey]['::type'], dataKey, data[dataKey]['::description'], newSchemaLevel)}` : '')}`}`;
47
- } // For Primitive Data types
48
-
37
+ return html` ${newSchemaLevel >= 0 && key ? html` <tr class="complex-object-display ${data['::type']}" data-obj="${keyLabel}"> <td class="key ${data['::deprecated'] ? 'deprecated' : ''}"> <div style="display:flex;align-items:center"> ${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' || key.startsWith('::OPTION') ? html`<span class="xxx-of-key">${keyLabel}</span><span class="${isOneOfLabel ? 'xxx-of-key' : 'xxx-of-descr'}">${keyDescr}</span>` : isRequired ? html`<span class="key-label requiredStar" style="display:inline-block" title="Required">${keyLabel}</span>` : html`<span class="key-label" style="display:inline-block">${keyLabel === '::props' ? '' : keyLabel}</span>`} </div> </td> <td> </td> <td class="key-descr m-markdown-small">${unsafeHTML(marked(displayLine))}</td> </tr>` : html`${data['::type'] === 'array' && dataType === 'array' ? html`<tr><td> ${dataType} </td> </tr>` : ''}`} ${Array.isArray(data) && data[0] ? html`${generateFormRows.call(this, data[0], options, 'xxx-of-option', '::ARRAY~OF', '', newSchemaLevel)}` : html`${Object.keys(data).map(dataKey => {
38
+ var _data$dataKey;
39
+ return !['::metadata', '::title', '::description', '::type', '::link', '::props', '::deprecated', '::array-type', '::dataTypeLabel', '::flags'].includes(dataKey) || (_data$dataKey = data[dataKey]) !== null && _data$dataKey !== void 0 && _data$dataKey['::type'] && !data[dataKey]['::type'].includes('xxx-of') ? html`${generateFormRows.call(this, data[dataKey]['::type'] === 'array' ? data[dataKey]['::props'] : data[dataKey], options, data[dataKey]['::type'], dataKey, data[dataKey]['::description'], newSchemaLevel)}` : '';
40
+ })}`}`;
41
+ }
49
42
 
43
+ // For Primitive Data types
50
44
  const parsedData = JSON.parse(data);
51
45
  return generatePrimitiveRow.call(this, parsedData, {
52
46
  key,
@@ -58,10 +52,8 @@ function generateFormRows(data, options, dataType = 'object', key = '', descript
58
52
  options
59
53
  });
60
54
  }
61
-
62
55
  function generatePrimitiveRow(rowData, parentRecursionOptions) {
63
56
  var _this$duplicatedRowsB;
64
-
65
57
  const {
66
58
  type,
67
59
  format,
@@ -84,54 +76,42 @@ function generatePrimitiveRow(rowData, parentRecursionOptions) {
84
76
  isRequired,
85
77
  options
86
78
  } = parentRecursionOptions;
87
-
88
79
  if (readOrWriteOnly === '🆁') {
89
80
  return undefined;
90
81
  }
91
-
92
82
  const elementId = this.elementId || `${this.method}-${this.path}`;
93
83
  const duplicateRowGeneratorKey = `${elementId}-${key}`;
94
-
95
84
  const rowGenerator = e => {
96
85
  var _e$target$dataset, _e$target$dataset2;
97
-
98
86
  if (((_e$target$dataset = e.target.dataset) === null || _e$target$dataset === void 0 ? void 0 : _e$target$dataset.ptype) !== 'pattern-property-key' && !isPatternProperty((_e$target$dataset2 = e.target.dataset) === null || _e$target$dataset2 === void 0 ? void 0 : _e$target$dataset2.pname)) {
99
87
  return;
100
- } // If the row key has a value then add another row
101
-
102
-
88
+ }
89
+ // If the row key has a value then add another row
103
90
  const patternPropertyKeyEls = [...this.querySelectorAll("[data-ptype='pattern-property-key']")];
104
- const patternPropertyInputEls = [...this.querySelectorAll("[data-ptype='form-input']")].filter(el => isPatternProperty(el.dataset.pname)); // If there is still some row that either has an empty key or an empty value, then skip adding a new row
105
-
91
+ const patternPropertyInputEls = [...this.querySelectorAll("[data-ptype='form-input']")].filter(el => isPatternProperty(el.dataset.pname));
92
+ // If there is still some row that either has an empty key or an empty value, then skip adding a new row
106
93
  if (patternPropertyKeyEls.some((keyElement, index) => !keyElement.value || !patternPropertyInputEls[index].value)) {
107
94
  return;
108
95
  }
109
-
110
96
  if (e.target.value) {
111
97
  this.duplicatedRowsByKey[duplicateRowGeneratorKey] = (this.duplicatedRowsByKey[duplicateRowGeneratorKey] || 1) + 1;
112
98
  this.requestUpdate();
113
99
  }
114
100
  };
115
-
116
101
  return map(range(((_this$duplicatedRowsB = this.duplicatedRowsByKey) === null || _this$duplicatedRowsB === void 0 ? void 0 : _this$duplicatedRowsB[duplicateRowGeneratorKey]) || 1), () => html` <tr> ${inputFieldKeyLabel.call(this, key.startsWith('::OPTION'), keyLabel, keyDescr, dataType, deprecated, isRequired, schemaTitle, format || type, rowGenerator)} ${dataType === 'array' ? getArrayFormField.call(this, keyLabel, example, defaultValue, format, rowGenerator) : ''} ${dataType !== 'array' ? getPrimitiveFormField.call(this, keyLabel, example, defaultValue, format, options, rowGenerator) : ''} <td> ${description ? html`<div class="param-description">${unsafeHTML(marked(description))}</div>` : ''} ${defaultValue || constraints || allowedValues || pattern ? html` <div class="param-constraint"> ${pattern ? html`<span style="font-weight:700">Pattern: </span>${pattern}<br>` : ''} ${constraints.length ? html`<span style="font-weight:700">Constraints: </span>${constraints.join(', ')}<br>` : ''} ${allowedValues === null || allowedValues === void 0 ? void 0 : allowedValues.split('┃').filter(v => v !== '').map((v, i) => html` ${i > 0 ? '|' : html`<span style="font-weight:700">Allowed: </span>`} ${html` <a part="anchor anchor-param-constraint" data-type="${type === 'array' ? type : 'string'}" data-enum="${v.trim()}" @click="${e => {
117
102
  const inputEl = e.target.closest('table').querySelector(`[data-pname="${keyLabel}"]`);
118
-
119
103
  if (inputEl) {
120
104
  inputEl.value = e.target.dataset.type === 'array' ? [e.target.dataset.enum] : e.target.dataset.enum;
121
105
  }
122
-
123
106
  this.computeCurlSyntax();
124
107
  }}"> ${v} </a>`}`)} </div>` : ''} </td> </tr> ${schemaDescription || example ? html`<tr class="form-parameter-description"> <td> </td> <td colspan="2" style="margin-top:0;padding:0 5px 8px 5px"> <span class="m-markdown-small">${unsafeHTML(marked(schemaDescription || ''))}</span> ${example ? html`<span> <span style="font-weight:700"> Example: </span> ${type === 'array' ? '[ ' : ''} <a part="anchor anchor-param-example" data-example-type="${type === 'array' ? type : 'string'}" data-example="${Array.isArray(example) && example.join('~|~') || example || ''}" @click="${e => {
125
108
  const inputEl = e.target.closest('table').querySelector(`[data-pname="${keyLabel}"]`);
126
-
127
109
  if (inputEl) {
128
110
  inputEl.value = e.target.dataset.exampleType === 'array' ? e.target.dataset.example.split('~|~') : e.target.dataset.example;
129
111
  }
130
-
131
112
  this.computeCurlSyntax();
132
113
  }}"> ${type === 'array' ? example.join(', ') : example} </a> ${type === 'array' ? '] ' : ''} </span>` : ''} </td> </tr>` : ''}`);
133
114
  }
134
-
135
115
  function inputFieldKeyLabel(isOption, keyLabel, keyDescription, dataType, deprecated, isRequired, schemaTitle, format, rowGenerator) {
136
116
  if (isPatternProperty(keyLabel)) {
137
117
  return html` <td style="width:160px;min-width:100px"> <div class="param-name ${deprecated ? 'deprecated' : ''}"> <input placeholder="${keyLabel}" @input="${e => {
@@ -139,9 +119,10 @@ function inputFieldKeyLabel(isOption, keyLabel, keyDescription, dataType, deprec
139
119
  this.computeCurlSyntax();
140
120
  }}" .value="${''}" spellcheck="false" type="${format === 'binary' ? 'file' : format === 'password' ? 'password' : 'text'}" part="textbox textbox-param" style="width:100%" data-ptype="pattern-property-key" data-pname="${keyLabel}" data-default="${''}" data-array="false"> </div></td>`;
141
121
  }
142
-
143
122
  return html` <td style="width:160px;min-width:100px"> <div class="param-name ${deprecated ? 'deprecated' : ''}"> ${!deprecated && isRequired ? html`<span class="key-label">${keyLabel}</span><span style="color:var(--red)">*</span>` : isOption ? html`<span class="xxx-of-key">${keyLabel}</span><span class="xxx-of-descr">${keyDescription}</span>` : html`${keyLabel ? html`<span class="key-label"> ${keyLabel}</span>` : html`<span class="xxx-of-descr">${schemaTitle}</span>`}`} </div> <div class="param-type"> ${dataType === 'array' ? html`[<span>${format}</span>]` : `${format}`} </div> </td>`;
144
- } // function getObjectFormField(keyLabel, example, defaultValue, format, options) {
123
+ }
124
+
125
+ // function getObjectFormField(keyLabel, example, defaultValue, format, options) {
145
126
  // return html`
146
127
  // <td>
147
128
  // <div class="tab-panel row" style="min-height:300px; border-left: 6px solid var(--light-border-color); align-items: stretch;">
@@ -164,7 +145,6 @@ function inputFieldKeyLabel(isOption, keyLabel, keyDescription, dataType, deprec
164
145
  // </td>`;
165
146
  // }
166
147
 
167
-
168
148
  function getArrayFormField(keyLabel, example, defaultValue, format, rowGenerator) {
169
149
  if (format === 'binary') {
170
150
  return html`<td style="min-width:100px"> <div class="file-input-container col" style="align-items:flex-end" @click="${e => this.onAddRemoveFileInput(e, keyLabel)}"> <div class="input-set row"> <input @input="${e => {
@@ -172,20 +152,17 @@ function getArrayFormField(keyLabel, example, defaultValue, format, rowGenerator
172
152
  this.computeCurlSyntax();
173
153
  }}" type="file" part="file-input" class="file-input" data-pname="${keyLabel}" data-ptype="form-input" data-array="false" data-file-array="true"> <button class="file-input-remove-btn"> &#x2715; </button> </div> <button class="m-btn primary file-input-add-btn" part="btn btn-fill" style="margin:2px 25px 0 0;padding:2px 6px">ADD</button> </div> </td>`;
174
154
  }
175
-
176
155
  return html`<td style="min-width:100px"> <tag-input @change="${e => {
177
156
  rowGenerator(e);
178
157
  this.computeCurlSyntax();
179
158
  }}" style="width:100%" data-ptype="form-input" data-pname="${keyLabel}" data-default="${defaultValue || ''}" data-array="true" placeholder="${(Array.isArray(example) ? example[0] : example) || defaultValue || 'add-multiple ↩'}" .value="${defaultValue || ''}"></tag-input> </td>`;
180
159
  }
181
-
182
160
  function getPrimitiveFormField(keyLabel, example, defaultValue, format, options, rowGenerator) {
183
161
  return html`<td style="min-width:100px"> <input placeholder="${example || defaultValue || ''}" @input="${e => {
184
162
  rowGenerator(e);
185
163
  this.computeCurlSyntax();
186
164
  }}" .value="${options.fillRequestWithDefault && defaultValue || ''}" spellcheck="false" type="${format === 'binary' ? 'file' : format === 'password' ? 'password' : 'text'}" part="textbox textbox-param" style="width:100%" data-ptype="form-input" data-pname="${keyLabel}" data-default="${defaultValue || ''}" data-array="false"> </td>`;
187
165
  }
188
-
189
166
  export default function getRequestFormTable(data, mimeType) {
190
167
  const options = {
191
168
  mimeType: mimeType,
@@ -26,69 +26,63 @@ export default class SchemaTable extends LitElement {
26
26
  }
27
27
  };
28
28
  }
29
-
30
29
  connectedCallback() {
31
30
  super.connectedCallback();
32
-
33
31
  if (!this.schemaExpandLevel || this.schemaExpandLevel < 1) {
34
32
  this.schemaExpandLevel = 99999;
35
33
  }
36
-
37
34
  if (!this.schemaHideReadOnly || !'true false'.includes(this.schemaHideReadOnly)) {
38
35
  this.schemaHideReadOnly = 'true';
39
36
  }
40
-
41
37
  if (!this.schemaHideWriteOnly || !'true false'.includes(this.schemaHideWriteOnly)) {
42
38
  this.schemaHideWriteOnly = 'true';
43
39
  }
44
40
  }
41
+
45
42
  /**
46
43
  * @param {Map<string, object>} changedProperties Changed Properties
47
44
  */
48
-
49
-
50
45
  update(changedProperties) {
51
46
  if (changedProperties.has('data')) {
52
47
  this.interactive = false;
53
48
  }
54
-
55
49
  super.update(changedProperties);
56
50
  }
57
-
58
51
  updated() {
59
52
  this.interactive = true; // Note: interactive is not a reactive property
60
53
  }
61
-
62
54
  static finalizeStyles() {
63
55
  return [FontStyles, KeyFrameStyles, SchemaStyles, css`.table{font-size:var(--font-size-small);text-align:left;line-height:calc(var(--font-size-small) + 6px)}.table .tr{width:calc(100% - 5px);padding:0 0 0 5px;border-bottom:1px dotted var(--light-border-color)}.table .td{padding:4px 0}.table .key{width:240px}.requiredStar::after{content:'*';color:var(--red);font-size:larger}.key.deprecated .key-label{text-decoration:line-through}.table .key-type{white-space:normal;width:150px}.key-type{display:flex}.key-type>.attributes{margin:.0625rem 0 0 .25rem}.obj-toggle{display:inline-flex;margin-left:-.8rem;margin-right:.8rem;color:var(--primary-color);cursor:pointer;font-size:calc(var(--font-size-small) + 4px);font-family:var(--font-mono);background-clip:border-box}.tr+.object-body{overflow:hidden}.table:not(.interactive) .object-body{animation-duration:0s!important}.tr:not(.collapsed)+.object-body{animation:linear .2s expand-height}.tr.collapsed+.object-body{animation:linear .2s collapse-height;max-height:0}.obj-toggle{transition:transform .1s ease}.tr.collapsed .obj-toggle{transform:rotate(-90deg)}`];
64
56
  }
65
- /* eslint-disable indent */
66
-
67
57
 
58
+ /* eslint-disable indent */
68
59
  render() {
69
- return html` ${this.data && this.data['::description'] ? html`<span class="m-markdown" style="padding-bottom:8px"> ${unsafeHTML(marked(this.data['::description'] || ''))}</span>` : ''} <div class="table ${this.interactive ? 'interactive' : ''}"> <div style="border:1px solid var(--light-border-color)"> <div style="display:flex;background-color:var(--bg2);padding:8px 4px;border-bottom:1px solid var(--light-border-color)"> <div class="key" style="font-family:var(--font-regular);font-weight:700;color:var(--fg);padding-left:${firstColumnInitialPadding}px"> Field </div> <div class="key-type" style="font-family:var(--font-regular);font-weight:700;color:var(--fg)"> Type </div> <div class="key-descr" style="font-family:var(--font-regular);font-weight:700;color:var(--fg)"> Description </div> </div> ${this.data ? html`${this.generateTree(this.data['::type'] === 'array' ? this.data['::props'] : this.data, this.data['::type'])}` : ''} </div> </div> `;
60
+ var _this$data, _this$data2;
61
+ const displayLine = [(_this$data = this.data) === null || _this$data === void 0 ? void 0 : _this$data['::title'], (_this$data2 = this.data) === null || _this$data2 === void 0 ? void 0 : _this$data2['::description']].filter(d => d).join(' - ');
62
+ return html` ${displayLine ? html`<span class="m-markdown" style="padding-bottom:8px"> ${unsafeHTML(marked(displayLine))}</span>` : ''} <div class="table ${this.interactive ? 'interactive' : ''}"> <div style="border:1px solid var(--light-border-color)"> <div style="display:flex;background-color:var(--bg2);padding:8px 4px;border-bottom:1px solid var(--light-border-color)"> <div class="key" style="font-family:var(--font-regular);font-weight:700;color:var(--fg);padding-left:${firstColumnInitialPadding}px"> Field </div> <div class="key-type" style="font-family:var(--font-regular);font-weight:700;color:var(--fg)"> Type </div> <div class="key-descr" style="font-family:var(--font-regular);font-weight:700;color:var(--fg)"> Description </div> </div> ${this.data ? html`${this.generateTree(this.data['::type'] === 'array' ? this.data['::props'] : this.data, this.data['::type'])}` : ''} </div> </div> `;
63
+ }
64
+ scrollToSchemaComponentByName(componentName) {
65
+ this.dispatchEvent(new CustomEvent('scrollToSchemaComponentByName', {
66
+ bubbles: true,
67
+ composed: true,
68
+ detail: componentName
69
+ }));
70
70
  }
71
-
72
71
  generateTree(data, dataType = 'object', key = '', title = '', description = '', schemaLevel = 0, indentLevel = 0) {
73
72
  var _keyLabel;
74
-
75
73
  const newSchemaLevel = data['::type'] && data['::type'].startsWith('xxx-of') ? schemaLevel : schemaLevel + 1;
76
- const newIndentLevel = dataType === 'xxx-of-option' || data['::type'] === 'xxx-of-option' || key.startsWith('::OPTION') ? indentLevel : indentLevel + 1; // 16px space indentation at each level, start the first one at 32px to align with the field hr key row object
77
-
74
+ const newIndentLevel = dataType === 'xxx-of-option' || data['::type'] === 'xxx-of-option' || key.startsWith('::OPTION') ? indentLevel : indentLevel + 1;
75
+ // 16px space indentation at each level, start the first one at 32px to align with the field hr key row object
78
76
  const leftPadding = Math.max(firstColumnInitialPadding, tablePadding * newIndentLevel);
79
-
80
77
  if (!data) {
81
78
  return html`<div class="null" style="display:inline">null</div>`;
82
79
  }
83
-
84
80
  if (Object.keys(data).length === 0) {
85
81
  return html`<span class="td key object" style="padding-left:${leftPadding}px">${key}</span>`;
86
82
  }
87
-
88
83
  let keyLabel = '';
89
84
  let keyDescr = '';
90
85
  let isOneOfLabel = false;
91
-
92
86
  if (key.startsWith('::ONE~OF') || key.startsWith('::ANY~OF')) {
93
87
  keyLabel = key.replace('::', '').replace('~', ' ');
94
88
  isOneOfLabel = true;
@@ -99,43 +93,41 @@ export default class SchemaTable extends LitElement {
99
93
  } else {
100
94
  keyLabel = key;
101
95
  }
102
-
103
96
  let detailObjType = '';
104
-
97
+ let displaySchemaLink = false;
105
98
  if ((data['::type'] || '').includes('xxx-of')) {
106
99
  detailObjType = '';
107
- } else if (data['::type'] === 'object') {
108
- if (dataType === 'array') {
109
- detailObjType = `[${keyLabel.replace(/(s|Collection|List)[*]?$/i, '')}]`; // Array of Object
110
- } else {
111
- detailObjType = 'object'; // Object
112
- }
113
100
  } else if (data['::type'] === 'array') {
114
101
  if (dataType === 'array') {
115
102
  detailObjType = 'array of array'; // Array of array
116
103
  } else {
117
104
  detailObjType = 'array';
118
105
  }
106
+ } else if (data['::type']) {
107
+ displaySchemaLink = data['::link'];
108
+ if (dataType === 'array') {
109
+ detailObjType = data['::link'] || keyLabel.replace(/(s|Collection|List)[*]?$/i, ''); // Array of Object
110
+ } else {
111
+ detailObjType = data['::link'] || data['::type'];
112
+ }
119
113
  }
120
-
121
114
  if (typeof data === 'object') {
122
115
  var _data$Metadata, _data$Metadata$constr;
123
-
124
116
  const flags = data['::flags'] || {};
125
-
126
117
  if (flags['🆁'] && this.schemaHideReadOnly === 'true') {
127
118
  return undefined;
128
119
  }
129
-
130
120
  if (flags['🆆'] && this.schemaHideWriteOnly === 'true') {
131
121
  return undefined;
132
122
  }
133
-
134
123
  const displayLine = [title && `**${title}${description ? ':' : ''}**`, description].filter(v => v).join(' ');
135
- return html` ${newSchemaLevel >= 0 && key ? html` <div class="tr ${newSchemaLevel <= this.schemaExpandLevel ? '' : 'collapsed'} ${data['::type']}" data-obj="${keyLabel}"> <div class="td no-select key ${data['::deprecated'] ? 'deprecated' : ''}" style="padding-left:${leftPadding}px;cursor:pointer" @click="${e => this.toggleObjectExpand(e, keyLabel)}"> <div style="display:flex;align-items:center"> ${keyLabel || keyDescr ? html`<div class="obj-toggle" data-obj="${keyLabel}">▾</div>` : ''} ${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' || key.startsWith('::OPTION') ? html`<span class="xxx-of-key" style="margin-left:-6px">${keyLabel}</span><span class="${isOneOfLabel ? 'xxx-of-key' : 'xxx-of-descr'}">${keyDescr}</span>` : keyLabel.endsWith('*') ? html`<span class="key-label requiredStar" style="display:inline-block;margin-left:-6px" title="Required"> ${keyLabel.substring(0, keyLabel.length - 1)}</span>` : html`<span class="key-label" style="display:inline-block;margin-left:-6px">${keyLabel === '::props' ? '' : keyLabel}</span>`} </div> </div> <div class="td key-type"> <div>${(data['::type'] || '').includes('xxx-of') ? '' : detailObjType}</div> <div class="attributes" title="${flags['🆁'] && 'Read only attribute' || flags['🆆'] && 'Write only attribute' || ''}">${flags['🆁'] || flags['🆆'] || ''}</div> </div> <div class="td key-descr"> <span class="m-markdown-small">${unsafeHTML(marked(displayLine))}</span> ${(_data$Metadata = data['::metadata']) !== null && _data$Metadata !== void 0 && (_data$Metadata$constr = _data$Metadata.constraints) !== null && _data$Metadata$constr !== void 0 && _data$Metadata$constr.length ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Constraints: </span>${data['::metadata'].constraints.join(', ')}</div><br>` : ''} </div> </div>` : html` ${data['::type'] === 'array' && dataType === 'array' ? html`<div class="tr"> <div class="td"> ${dataType} </div> </div>` : ''} `} <div class="object-body"> ${Array.isArray(data) && data[0] ? html`${this.generateTree(data[0], 'xxx-of-option', '::ARRAY~OF', data[0]['::title'], data[0]['::description'], newSchemaLevel, newIndentLevel)}` : html` ${Object.keys(data).map(dataKey => !['::metadata', '::title', '::description', '::type', '::props', '::deprecated', '::array-type', '::dataTypeLabel', '::flags'].includes(dataKey) || data[dataKey]['::type'] === 'array' && data[dataKey]['::type'] === 'object' ? html`${this.generateTree(data[dataKey]['::type'] === 'array' ? data[dataKey]['::props'] : data[dataKey], data[dataKey]['::type'], dataKey, data[dataKey]['::title'], data[dataKey]['::description'], newSchemaLevel, newIndentLevel)}` : '')}`} <div> </div></div>`;
136
- } // For Primitive Data types
137
-
124
+ return html` ${newSchemaLevel >= 0 && key ? html` <div class="tr ${newSchemaLevel <= this.schemaExpandLevel ? '' : 'collapsed'} ${data['::type']}" data-obj="${keyLabel}"> <div class="td no-select key ${data['::deprecated'] ? 'deprecated' : ''}" style="padding-left:${leftPadding}px;cursor:pointer" @click="${e => this.toggleObjectExpand(e, keyLabel)}"> <div style="display:flex;align-items:center"> ${keyLabel || keyDescr ? html`<div class="obj-toggle" data-obj="${keyLabel}">▾</div>` : ''} ${data['::type'] === 'xxx-of-option' || data['::type'] === 'xxx-of-array' || key.startsWith('::OPTION') ? html`<span class="xxx-of-key" style="margin-left:-6px">${keyLabel}</span><span class="${isOneOfLabel ? 'xxx-of-key' : 'xxx-of-descr'}">${keyDescr}</span>` : keyLabel.endsWith('*') ? html`<span class="key-label requiredStar" style="display:inline-block;margin-left:-6px" title="Required"> ${keyLabel.substring(0, keyLabel.length - 1)}</span>` : html`<span class="key-label" style="display:inline-block;margin-left:-6px">${keyLabel === '::props' ? '' : keyLabel}</span>`} </div> </div> <div class="td key-type"> ${displaySchemaLink ? html`<div class="schema-link" style="overflow:hidden;text-overflow:ellipsis" @click="${() => this.scrollToSchemaComponentByName(displaySchemaLink)}"> ${dataType === 'array' ? '[' : ''}<span style="color:var(--primary)">${detailObjType}</span>${dataType === 'array' ? ']' : ''} </div>` : html`<div>${(data['::type'] || '').includes('xxx-of') ? '' : detailObjType}</div>`} <div class="attributes" title="${flags['🆁'] && 'Read only attribute' || flags['🆆'] && 'Write only attribute' || ''}">${flags['🆁'] || flags['🆆'] || ''}</div> </div> <div class="td key-descr"> <span class="m-markdown-small">${unsafeHTML(marked(displayLine))}</span> ${(_data$Metadata = data['::metadata']) !== null && _data$Metadata !== void 0 && (_data$Metadata$constr = _data$Metadata.constraints) !== null && _data$Metadata$constr !== void 0 && _data$Metadata$constr.length ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Constraints: </span>${data['::metadata'].constraints.join(', ')}</div><br>` : ''} </div> </div>` : html` ${data['::type'] === 'array' && dataType === 'array' ? html`<div class="tr"> <div class="td"> ${dataType} </div> </div>` : ''} `} <div class="object-body"> ${Array.isArray(data) && data[0] ? html`${this.generateTree(data[0], 'xxx-of-option', '::ARRAY~OF', data[0]['::title'], data[0]['::description'], newSchemaLevel, newIndentLevel)}` : html` ${Object.keys(data).map(dataKey => {
125
+ var _data$dataKey;
126
+ return !['::metadata', '::title', '::description', '::type', '::link', '::props', '::deprecated', '::array-type', '::dataTypeLabel', '::flags'].includes(dataKey) || (_data$dataKey = data[dataKey]) !== null && _data$dataKey !== void 0 && _data$dataKey['::type'] && !data[dataKey]['::type'].includes('xxx-of') ? html`${this.generateTree(data[dataKey]['::type'] === 'array' ? data[dataKey]['::props'] : data[dataKey], data[dataKey]['::type'], dataKey, data[dataKey]['::title'], data[dataKey]['::description'], newSchemaLevel, newIndentLevel)}` : '';
127
+ })}`} <div> </div></div>`;
128
+ }
138
129
 
130
+ // For Primitive Data types
139
131
  const {
140
132
  type,
141
133
  cssType,
@@ -150,27 +142,21 @@ export default class SchemaTable extends LitElement {
150
142
  schemaTitle,
151
143
  deprecated
152
144
  } = JSON.parse(data);
153
-
154
145
  if (readOrWriteOnly === '🆁' && this.schemaHideReadOnly === 'true') {
155
146
  return undefined;
156
147
  }
157
-
158
148
  if (readOrWriteOnly === '🆆' && this.schemaHideWriteOnly === 'true') {
159
149
  return undefined;
160
150
  }
161
-
162
151
  return html` <div class="tr"> <div class="td key ${deprecated ? 'deprecated' : ''}" style="padding-left:${leftPadding}px"> ${(_keyLabel = keyLabel) !== null && _keyLabel !== void 0 && _keyLabel.endsWith('*') ? html`<span class="key-label requiredStar" title="Required">${keyLabel.substring(0, keyLabel.length - 1)}</span>` : key.startsWith('::OPTION') ? html`<span class="xxx-of-key">${keyLabel}</span><span class="xxx-of-descr">${keyDescr}</span>` : html`${keyLabel ? html`<span class="key-label"> ${keyLabel}</span>` : html`<span class="xxx-of-descr">${schemaTitle}</span>`}`} </div> <div class="td key-type"> <div>${dataType === 'array' ? '[' : ''}<span class="${cssType}">${format || type}</span>${dataType === 'array' ? ']' : ''}</div> <div class="attributes ${cssType}" style="font-family:var(--font-mono)" title="${readOrWriteOnly === '🆁' && 'Read only attribute' || readOrWriteOnly === '🆆' && 'Write only attribute' || ''}">${readOrWriteOnly}</div> </div> <div class="td key-descr"> <span class="m-markdown-small" style="vertical-align:middle"> ${unsafeHTML(marked(`${`${schemaTitle || title ? `**${schemaTitle || title}${schemaDescription || description ? ':' : ''}**` : ''} ${schemaDescription || description}` || ''}`))} </span> ${constraints.length ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Constraints: </span>${constraints.join(', ')}</div><br>` : ''} ${defaultValue ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Default: </span>${defaultValue}</div><br>` : ''} ${allowedValues ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Allowed: </span>${allowedValues}</div><br>` : ''} ${pattern ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Pattern: </span>${pattern}</div><br>` : ''} ${example ? html`<div style="display:inline-block;line-break:anywhere;margin-right:8px"><span class="bold-text">Example: </span>${example}</div><br>` : ''} </div> </div> `;
163
152
  }
164
153
  /* eslint-enable indent */
165
154
 
166
-
167
155
  toggleObjectExpand(e) {
168
156
  const rowEl = e.target.closest('.tr');
169
157
  rowEl.classList.toggle('collapsed');
170
158
  }
171
-
172
159
  }
173
-
174
160
  if (!customElements.get('openapi-explorer')) {
175
161
  customElements.define('schema-table', SchemaTable);
176
162
  }