openapi-explorer 0.8.291 → 0.8.294
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/dist/openapi-explorer.min.js +5 -5
- package/dist/openapi-explorer.min.js.LICENSE.txt +1 -1
- package/dist/openapi-explorer.min.js.LICENSE.txt.gz +0 -0
- package/dist/openapi-explorer.min.js.gz +0 -0
- package/dist/openapi-explorer.min.js.map +1 -1
- package/dist/openapi-explorer.min.js.map.gz +0 -0
- package/dist/report.html +2 -2
- package/package.json +1 -1
- package/src/components/api-request.js +4 -4
- package/src/components/api-response.js +3 -3
- package/src/openapi-explorer.js +4 -7
- package/src/styles/nav-styles.js +15 -14
- package/src/templates/focused-endpoint-template.js +1 -17
- package/src/templates/navbar-template.js +55 -49
- package/src/templates/security-scheme-template.js +2 -2
- package/src/templates/server-template.js +1 -1
- package/src/utils/spec-parser.js +7 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openapi-explorer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.294",
|
|
4
4
|
"description": "OpenAPI Explorer - API viewer with dynamically generated components, documentation, and interaction console",
|
|
5
5
|
"author": "Rhosys Developers <developers@rhosys.ch>",
|
|
6
6
|
"repository": {
|
|
@@ -245,7 +245,7 @@ export default class ApiRequest extends LitElement {
|
|
|
245
245
|
return html`
|
|
246
246
|
<div class="table-title top-gap">${title}${paramType === 'path' ? html`<span style='color:var(--red);'>*</span>` : ''}</div>
|
|
247
247
|
<div style="display:block; overflow-x:auto; max-width:100%;">
|
|
248
|
-
<table class="m-table" style="width:100%; word-break:break-word;">
|
|
248
|
+
<table role="presentation" class="m-table" style="width:100%; word-break:break-word;">
|
|
249
249
|
${tableRows}
|
|
250
250
|
</table>
|
|
251
251
|
</div>`;
|
|
@@ -313,7 +313,7 @@ export default class ApiRequest extends LitElement {
|
|
|
313
313
|
reqBodyTypeSelectorHtml = requestBodyTypes.length === 1
|
|
314
314
|
? ''
|
|
315
315
|
: html`
|
|
316
|
-
<select style="min-width:100px; max-width:100%; margin-bottom:-1px;" @change = '${(e) => this.onMimeTypeChange(e)}'>
|
|
316
|
+
<select aria-label="mime type" style="min-width:100px; max-width:100%; margin-bottom:-1px;" @change = '${(e) => this.onMimeTypeChange(e)}'>
|
|
317
317
|
${requestBodyTypes.map((reqBody) => html`
|
|
318
318
|
<option value = '${reqBody.mimeType}' ?selected = '${reqBody.mimeType === this.selectedRequestBodyType}'>
|
|
319
319
|
${reqBody.mimeType}
|
|
@@ -348,7 +348,7 @@ export default class ApiRequest extends LitElement {
|
|
|
348
348
|
${reqBodyExamples.length === 1
|
|
349
349
|
? ''
|
|
350
350
|
: html`
|
|
351
|
-
<select style="min-width:100px; max-width:100%; margin-bottom:-1px;" @change='${(e) => this.onSelectExample(e)}'>
|
|
351
|
+
<select aria-label='request body example' style="min-width:100px; max-width:100%; margin-bottom:-1px;" @change='${(e) => this.onSelectExample(e)}'>
|
|
352
352
|
${reqBodyExamples.map((v) => html`<option value="${v.exampleId}" ?selected=${v.exampleId === this.selectedRequestBodyExample} >
|
|
353
353
|
${v.exampleSummary.length > 80 ? v.exampleId : v.exampleSummary ? v.exampleSummary : v.exampleId}
|
|
354
354
|
</option>`)}
|
|
@@ -683,7 +683,7 @@ export default class ApiRequest extends LitElement {
|
|
|
683
683
|
}`);
|
|
684
684
|
}
|
|
685
685
|
return html`
|
|
686
|
-
<table style="width:100%;" class="m-table">
|
|
686
|
+
<table role="presentation" style="width:100%;" class="m-table">
|
|
687
687
|
${formDataTableRows}
|
|
688
688
|
</table>
|
|
689
689
|
`;
|
|
@@ -216,7 +216,7 @@ export default class ApiResponse extends LitElement {
|
|
|
216
216
|
responseHeaderListTemplate(respHeaders) {
|
|
217
217
|
return html`
|
|
218
218
|
<div style="padding:16px 0 8px 0" class="resp-headers small-font-size bold-text">RESPONSE HEADERS</div>
|
|
219
|
-
<table style="border-collapse: collapse; margin-bottom:16px; border:1px solid var(--border-color); border-radius: var(--border-radius)" class="small-font-size mono-font">
|
|
219
|
+
<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">
|
|
220
220
|
${respHeaders.map((v) => html`
|
|
221
221
|
<tr>
|
|
222
222
|
<td style="padding:8px; vertical-align: baseline; min-width:120px; border-top: 1px solid var(--light-border-color); text-overflow: ellipsis;">
|
|
@@ -238,7 +238,7 @@ export default class ApiResponse extends LitElement {
|
|
|
238
238
|
|
|
239
239
|
mimeTypeDropdownTemplate(mimeTypes) {
|
|
240
240
|
return html`
|
|
241
|
-
<select @change="${(e) => { this.selectedMimeType = e.target.value; }}" style='margin-bottom: -1px; z-index:1'>
|
|
241
|
+
<select aria-label='mime type' @change="${(e) => { this.selectedMimeType = e.target.value; }}" style='margin-bottom: -1px; z-index:1'>
|
|
242
242
|
${mimeTypes.map((mimeType) => html`<option value='${mimeType}' ?selected = '${mimeType === this.selectedMimeType}'> ${mimeType} </option>`)}
|
|
243
243
|
</select>`;
|
|
244
244
|
}
|
|
@@ -276,7 +276,7 @@ export default class ApiResponse extends LitElement {
|
|
|
276
276
|
}`
|
|
277
277
|
: html`
|
|
278
278
|
<span class = 'example-panel generic-tree ${this.renderStyle === 'read' ? 'border pad-8-16' : 'border-top pad-top-8'}'>
|
|
279
|
-
<select @change='${(e) => this.onSelectExample(e)}'>
|
|
279
|
+
<select aria-label='response body example' @change='${(e) => this.onSelectExample(e)}'>
|
|
280
280
|
${mimeRespDetails.examples.map((v) => html`<option value="${v.exampleId}" ?selected=${v.exampleId === mimeRespDetails.selectedExample} >
|
|
281
281
|
${v.exampleSummary.length > 80 ? v.exampleId : v.exampleSummary}
|
|
282
282
|
</option>`)}
|
package/src/openapi-explorer.js
CHANGED
|
@@ -65,7 +65,6 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
65
65
|
defaultSchemaTab: { type: String, attribute: 'default-schema-tab' },
|
|
66
66
|
responseAreaHeight: { type: String, attribute: 'response-area-height' },
|
|
67
67
|
fillRequestWithDefault: { type: String, attribute: 'fill-defaults' },
|
|
68
|
-
onNavTagClick: { type: String, attribute: 'on-nav-tag-click' },
|
|
69
68
|
|
|
70
69
|
// Schema Styles
|
|
71
70
|
schemaStyle: { type: String, attribute: 'schema-style' },
|
|
@@ -379,7 +378,6 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
379
378
|
this.schemaHideReadOnly = ['post', 'put', 'patch'].join(',');
|
|
380
379
|
this.schemaHideWriteOnly = true;
|
|
381
380
|
if (!this.fillRequestWithDefault || !'true, false,'.includes(`${this.fillRequestWithDefault},`)) { this.fillRequestWithDefault = 'true'; }
|
|
382
|
-
if (!this.onNavTagClick || !'expand-collapse, show-description,'.includes(`${this.onNavTagClick},`)) { this.onNavTagClick = 'expand-collapse'; }
|
|
383
381
|
if (!this.responseAreaHeight) {
|
|
384
382
|
this.responseAreaHeight = '300px';
|
|
385
383
|
}
|
|
@@ -510,16 +508,15 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
510
508
|
this.resolvedSpec = null;
|
|
511
509
|
this.loading = true;
|
|
512
510
|
this.loadFailed = false;
|
|
513
|
-
const
|
|
514
|
-
if (!this.serverUrl && isServerUrl) {
|
|
515
|
-
this.serverUrl = new URL(specUrlOrObject).origin;
|
|
516
|
-
}
|
|
517
|
-
const spec = await ProcessSpec(isServerUrl, specUrlOrObject, this.serverUrl);
|
|
511
|
+
const spec = await ProcessSpec(specUrlOrObject, this.serverUrl);
|
|
518
512
|
this.loading = false;
|
|
519
513
|
if (spec === undefined || spec === null) {
|
|
520
514
|
console.error('Unable to resolve the API spec. '); // eslint-disable-line no-console
|
|
521
515
|
return;
|
|
522
516
|
}
|
|
517
|
+
if (!this.serverUrl) {
|
|
518
|
+
this.serverUrl = spec.servers[0].url;
|
|
519
|
+
}
|
|
523
520
|
this.afterSpecParsedAndValidated(spec);
|
|
524
521
|
} catch (err) {
|
|
525
522
|
this.loading = false;
|
package/src/styles/nav-styles.js
CHANGED
|
@@ -29,14 +29,11 @@ export default css`
|
|
|
29
29
|
justify-content: space-between;
|
|
30
30
|
flex-direction: row;
|
|
31
31
|
}
|
|
32
|
-
.nav-bar.read .nav-bar-tag-icon {
|
|
33
|
-
display:none;
|
|
34
|
-
}
|
|
35
32
|
|
|
36
33
|
.nav-bar-tag-icon {
|
|
34
|
+
font-size: 16px;
|
|
35
|
+
padding-right: 1px;
|
|
37
36
|
color: var(--nav-text-color);
|
|
38
|
-
font-size: 20px;
|
|
39
|
-
margin-right: -16px;
|
|
40
37
|
}
|
|
41
38
|
.nav-bar-tag-icon:hover {
|
|
42
39
|
color:var(--nav-hover-text-color);
|
|
@@ -44,15 +41,15 @@ export default css`
|
|
|
44
41
|
.nav-bar.focused .nav-bar-tag-and-paths.collapsed .nav-bar-paths-under-tag {
|
|
45
42
|
display:none;
|
|
46
43
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
text-align: center;
|
|
51
|
-
display: inline-block;
|
|
44
|
+
|
|
45
|
+
.nav-bar-tag-and-paths.collapsed .nav-bar-tag-icon.collapse-button-arrow {
|
|
46
|
+
display: none;
|
|
52
47
|
}
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
|
|
49
|
+
.nav-bar-tag-and-paths.expanded .nav-bar-tag-icon.expand-button-arrow {
|
|
50
|
+
display: none;
|
|
55
51
|
}
|
|
52
|
+
|
|
56
53
|
.nav-bar.focused, .nav-scroll {
|
|
57
54
|
border-top: 1px solid var(--secondary-color);
|
|
58
55
|
}
|
|
@@ -71,7 +68,7 @@ export default css`
|
|
|
71
68
|
color: var(--secondary-color);
|
|
72
69
|
border-left:4px solid transparent;
|
|
73
70
|
font-weight:bold;
|
|
74
|
-
padding: 15px
|
|
71
|
+
padding: 15px 15px 15px 10px;
|
|
75
72
|
text-transform: capitalize;
|
|
76
73
|
}
|
|
77
74
|
|
|
@@ -108,9 +105,13 @@ export default css`
|
|
|
108
105
|
font-size: var(--font-size-small);
|
|
109
106
|
color: var(--nav-text-color);
|
|
110
107
|
padding: 15px 15px 5px 5px;
|
|
111
|
-
filter:opacity(0.5);
|
|
112
108
|
font-weight:bold;
|
|
113
109
|
border-bottom: 1px solid var(--nav-text-color);
|
|
110
|
+
background: var(--nav-bg-color);
|
|
111
|
+
}
|
|
112
|
+
.sticky-scroll-element {
|
|
113
|
+
position: sticky;
|
|
114
|
+
top: 0;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
.nav-bar-h2 {margin-left:12px;}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
|
-
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
|
3
|
-
import { marked } from 'marked';
|
|
4
2
|
import { expandedEndpointBodyTemplate } from './expanded-endpoint-template';
|
|
5
3
|
import '../components/api-request';
|
|
6
4
|
import '../components/api-response';
|
|
@@ -31,21 +29,7 @@ function defaultContentTemplate() {
|
|
|
31
29
|
|
|
32
30
|
/* eslint-disable indent */
|
|
33
31
|
function focusedTagBodyTemplate(tag) {
|
|
34
|
-
return html
|
|
35
|
-
<h1 id="${tag.elementId}">${tag.name}</h1>
|
|
36
|
-
${this.onNavTagClick === 'show-description' && tag.description
|
|
37
|
-
? html`
|
|
38
|
-
<div class="m-markdown">
|
|
39
|
-
${
|
|
40
|
-
unsafeHTML(`
|
|
41
|
-
<div class="m-markdown regular-font">
|
|
42
|
-
${marked(tag.description || '')}
|
|
43
|
-
</div>`)
|
|
44
|
-
}
|
|
45
|
-
</div>`
|
|
46
|
-
: ''
|
|
47
|
-
}
|
|
48
|
-
`;
|
|
32
|
+
return html`<h1 id="${tag.elementId}">${tag.name}</h1>`;
|
|
49
33
|
}
|
|
50
34
|
|
|
51
35
|
export default function focusedEndpointTemplate() {
|
|
@@ -8,32 +8,44 @@ export function expandCollapseNavBarTag(navLinkEl, action = 'toggle') {
|
|
|
8
8
|
if (expand) {
|
|
9
9
|
tagAndPathEl.classList.remove('collapsed');
|
|
10
10
|
tagAndPathEl.classList.add('expanded');
|
|
11
|
-
|
|
12
|
-
tagAndPathEl.classList.remove('expanded');
|
|
13
|
-
tagAndPathEl.classList.add('collapsed');
|
|
11
|
+
return;
|
|
14
12
|
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (action === 'expand-all') {
|
|
21
|
-
elList.map((el) => {
|
|
22
|
-
expandCollapseNavBarTag(el, 'expand');
|
|
23
|
-
});
|
|
24
|
-
} else {
|
|
25
|
-
elList.map((el) => {
|
|
26
|
-
expandCollapseNavBarTag(el, 'collapse');
|
|
27
|
-
});
|
|
14
|
+
tagAndPathEl.classList.remove('expanded');
|
|
15
|
+
tagAndPathEl.classList.add('collapsed');
|
|
28
16
|
}
|
|
29
17
|
}
|
|
30
18
|
|
|
31
|
-
function onExpandCollapse(e) {
|
|
19
|
+
function onExpandCollapse(tagId, e) {
|
|
20
|
+
const tag = this.resolvedSpec.tags.find(t => t.elementId === tagId);
|
|
21
|
+
if (!tag) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
32
24
|
expandCollapseNavBarTag(e.target, 'toggle');
|
|
25
|
+
tag.expanded = !tag.expanded;
|
|
26
|
+
|
|
27
|
+
if (this.resolvedSpec.tags.some(t => t.expanded)) {
|
|
28
|
+
this.operationsCollapsed = false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (this.resolvedSpec.tags.every(t => !t.expanded)) {
|
|
32
|
+
this.operationsCollapsed = true;
|
|
33
|
+
}
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
function
|
|
36
|
-
|
|
36
|
+
export function expandCollapseAll(e, action = 'expand-all') {
|
|
37
|
+
const navEl = e.target.closest('.nav-scroll');
|
|
38
|
+
|
|
39
|
+
const elList = [...navEl.querySelectorAll('.nav-bar-tag-and-paths')];
|
|
40
|
+
if (action === 'expand-all') {
|
|
41
|
+
elList.map((el) => { expandCollapseNavBarTag(el, 'expand'); });
|
|
42
|
+
this.resolvedSpec.tags.forEach(t => { t.expanded = true; });
|
|
43
|
+
this.operationsCollapsed = false;
|
|
44
|
+
} else {
|
|
45
|
+
elList.map((el) => { expandCollapseNavBarTag(el, 'collapse'); });
|
|
46
|
+
this.resolvedSpec.tags.forEach(t => { t.expanded = false; });
|
|
47
|
+
this.operationsCollapsed = true;
|
|
48
|
+
}
|
|
37
49
|
}
|
|
38
50
|
|
|
39
51
|
/* eslint-disable indent */
|
|
@@ -96,17 +108,19 @@ export default function navbarTemplate() {
|
|
|
96
108
|
<slot name="nav-section" class="custom-nav-section" data-content-id='section' @click = '${(e) => this.scrollToEventTarget(e, false)}'></slot>
|
|
97
109
|
|
|
98
110
|
<slot name="operations-header">
|
|
99
|
-
<div
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
<div class="sticky-scroll-element">
|
|
112
|
+
<div id='link-paths' class='nav-bar-section' part="navbar-operations-header">
|
|
113
|
+
<div class='nav-bar-section-title'>OPERATIONS</div>
|
|
114
|
+
<div style="display:flex; margin-left:10px;">
|
|
115
|
+
${this.renderStyle === 'focused' && this.resolvedSpec.tags.length > 1
|
|
116
|
+
? html`
|
|
117
|
+
${this.operationsCollapsed
|
|
118
|
+
? html`<div @click="${(e) => { expandCollapseAll.call(this, e, 'expand-all'); }}" style="font-size: 16px; transform: rotate(0deg); cursor: pointer;">▸</div>`
|
|
119
|
+
: html`<div @click="${(e) => { expandCollapseAll.call(this, e, 'collapse-all'); }}" style="font-size: 16px; transform: rotate(90deg); cursor: pointer;">▸</div>`
|
|
120
|
+
}`
|
|
121
|
+
: ''
|
|
122
|
+
}
|
|
123
|
+
</div>
|
|
110
124
|
</div>
|
|
111
125
|
</div>
|
|
112
126
|
</slot>
|
|
@@ -118,25 +132,15 @@ export default function navbarTemplate() {
|
|
|
118
132
|
<slot name="nav-${tag.elementId}">
|
|
119
133
|
<div class='nav-bar-tag-and-paths ${tag.expanded ? 'expanded' : 'collapsed'}'>
|
|
120
134
|
${tag.name === 'General ⦂'
|
|
121
|
-
? html
|
|
135
|
+
? html``
|
|
122
136
|
: html`
|
|
123
|
-
<div
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
} else {
|
|
131
|
-
this.scrollToEventTarget(e, false);
|
|
132
|
-
}
|
|
133
|
-
}}'>
|
|
134
|
-
<div>${tag.name}</div>
|
|
135
|
-
<div class="nav-bar-tag-icon" @click="${(e) => {
|
|
136
|
-
if (this.renderStyle === 'focused' && this.onNavTagClick === 'show-description') {
|
|
137
|
-
onExpandCollapse.call(this, e);
|
|
138
|
-
}
|
|
139
|
-
}}">
|
|
137
|
+
<div class='nav-bar-tag' id="link-${tag.elementId}" data-content-id='${tag.elementId}'
|
|
138
|
+
@click='${(e) => { onExpandCollapse.call(this, tag.elementId, e); }}'>
|
|
139
|
+
|
|
140
|
+
<div style="display: flex; justify-content: space-between; width: 100%;">
|
|
141
|
+
<div>${tag.name}</div>
|
|
142
|
+
<div class="nav-bar-tag-icon expand-button-arrow">▸</div>
|
|
143
|
+
<div class="nav-bar-tag-icon collapse-button-arrow">▾</div>
|
|
140
144
|
</div>
|
|
141
145
|
</div>
|
|
142
146
|
`
|
|
@@ -170,8 +174,10 @@ export default function navbarTemplate() {
|
|
|
170
174
|
<!-- COMPONENTS -->
|
|
171
175
|
${this.resolvedSpec.components && this.showComponents === 'true'
|
|
172
176
|
? html`
|
|
173
|
-
<div
|
|
174
|
-
<div class='nav-bar-section
|
|
177
|
+
<div class="sticky-scroll-element">
|
|
178
|
+
<div id='link-components' class='nav-bar-section'>
|
|
179
|
+
<div class='nav-bar-section-title'>COMPONENTS</div>
|
|
180
|
+
</div>
|
|
175
181
|
</div>
|
|
176
182
|
${this.resolvedSpec.components.map((component) => (component.subComponents.length
|
|
177
183
|
? html`
|
|
@@ -270,7 +270,7 @@ function oAuthFlowTemplate(flowName, securityObj, authFlow) {
|
|
|
270
270
|
${flowName === 'clientCredentials'
|
|
271
271
|
? html`
|
|
272
272
|
<input type="password" part="textbox textbox-auth-client-secret" value = "" placeholder="Client Secret" spellcheck="false" class="oauth-client-secret" style = "margin:0 5px;">
|
|
273
|
-
<select style="margin-right:5px;" class="oauth-send-client-secret-in">
|
|
273
|
+
<select aria-label='oauth client secret location' style="margin-right:5px;" class="oauth-send-client-secret-in">
|
|
274
274
|
<option value = 'header' selected> Authorization Header </option>
|
|
275
275
|
<option value = 'request-body'> Request Body </option>
|
|
276
276
|
</select>`
|
|
@@ -314,7 +314,7 @@ export default function securitySchemeTemplate() {
|
|
|
314
314
|
</div>
|
|
315
315
|
${schemes.length > 0
|
|
316
316
|
? html`
|
|
317
|
-
<table class='m-table' style
|
|
317
|
+
<table role="presentation" class='m-table' style="width:100%">
|
|
318
318
|
${schemes.map((v) => html`
|
|
319
319
|
<tr>
|
|
320
320
|
<td style="max-width:500px; overflow-wrap: break-word;">
|
|
@@ -26,7 +26,7 @@ function serverVarsTemplate() {
|
|
|
26
26
|
return this.selectedServer && this.selectedServer.variables
|
|
27
27
|
? html`
|
|
28
28
|
<div class="table-title"> SERVER VARIABLES</div>
|
|
29
|
-
<table class='m-table'>
|
|
29
|
+
<table role="presentation" class='m-table'>
|
|
30
30
|
${Object.entries(this.selectedServer.variables).map((kv) => html`
|
|
31
31
|
<tr>
|
|
32
32
|
<td style="vertical-align: middle;" >${kv[0]}</td>
|
package/src/utils/spec-parser.js
CHANGED
|
@@ -3,7 +3,8 @@ import { marked } from 'marked';
|
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
4
|
import { invalidCharsRegEx } from './common-utils';
|
|
5
5
|
|
|
6
|
-
export default async function ProcessSpec(
|
|
6
|
+
export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
7
|
+
const inputSpecIsAUrl = typeof specUrlOrObject === 'string' && specUrlOrObject.match(/^http/);
|
|
7
8
|
let specMeta;
|
|
8
9
|
|
|
9
10
|
// Dynamically resolve non yaml or json files and insert their descriptions where necessary
|
|
@@ -14,7 +15,7 @@ export default async function ProcessSpec(requiresLookup, specUrlOrObject, serve
|
|
|
14
15
|
return val;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
if (
|
|
18
|
+
if (inputSpecIsAUrl) {
|
|
18
19
|
specMeta = await SwaggerClient({ allowMetaPatches: false, url: specUrlOrObject, responseInterceptor });
|
|
19
20
|
} else if (typeof specUrlOrObject === 'string') {
|
|
20
21
|
specMeta = await SwaggerClient({ allowMetaPatches: false, spec: yaml.load(specUrlOrObject), responseInterceptor });
|
|
@@ -71,7 +72,7 @@ export default async function ProcessSpec(requiresLookup, specUrlOrObject, serve
|
|
|
71
72
|
|
|
72
73
|
// Servers
|
|
73
74
|
let servers = [];
|
|
74
|
-
if (
|
|
75
|
+
if (Array.isArray(jsonParsedSpec.servers) && jsonParsedSpec.servers.length) {
|
|
75
76
|
jsonParsedSpec.servers.forEach((v) => {
|
|
76
77
|
let computedUrl = v.url.trim();
|
|
77
78
|
if (!(computedUrl.startsWith('http') || computedUrl.startsWith('//') || computedUrl.startsWith('{'))) {
|
|
@@ -90,11 +91,13 @@ export default async function ProcessSpec(requiresLookup, specUrlOrObject, serve
|
|
|
90
91
|
}
|
|
91
92
|
v.computedUrl = computedUrl;
|
|
92
93
|
});
|
|
93
|
-
if (serverUrl) {
|
|
94
|
+
if (serverUrl && !jsonParsedSpec.servers.some(s => s.url === serverUrl || s.computedUrl === serverUrl)) {
|
|
94
95
|
jsonParsedSpec.servers.push({ url: serverUrl, computedUrl: serverUrl });
|
|
95
96
|
}
|
|
96
97
|
} else if (serverUrl) {
|
|
97
98
|
jsonParsedSpec.servers = [{ url: serverUrl, computedUrl: serverUrl }];
|
|
99
|
+
} else if (inputSpecIsAUrl) {
|
|
100
|
+
jsonParsedSpec.servers = [{ url: new URL(specUrlOrObject).origin, computedUrl: new URL(specUrlOrObject).origin }];
|
|
98
101
|
} else if (window.location.origin.startsWith('http')) {
|
|
99
102
|
jsonParsedSpec.servers = [{ url: window.location.origin, computedUrl: window.location.origin }];
|
|
100
103
|
} else {
|