openapi-explorer 0.8.294 → 0.8.297

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openapi-explorer",
3
- "version": "0.8.294",
3
+ "version": "0.8.297",
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": {
@@ -515,7 +515,7 @@ export default class OpenApiExplorer extends LitElement {
515
515
  return;
516
516
  }
517
517
  if (!this.serverUrl) {
518
- this.serverUrl = spec.servers[0].url;
518
+ this.serverUrl = spec.servers[0].computedUrl || spec.servers[0].url;
519
519
  }
520
520
  this.afterSpecParsedAndValidated(spec);
521
521
  } catch (err) {
@@ -558,62 +558,45 @@ export default class OpenApiExplorer extends LitElement {
558
558
  this.resolvedSpec = spec;
559
559
  this.selectedServer = this.resolvedSpec.servers.find((s) => s.url === this.serverUrl || !this.serverUrl);
560
560
  this.dispatchEvent(new CustomEvent('spec-loaded', { detail: spec }));
561
+ // Wait for 10 milliseconds to account for any changes to the spec via spec-loaded
562
+ await sleep(10);
561
563
  this.requestUpdate();
562
564
 
563
565
  // Initiate IntersectionObserver and put it at the end of event loop, to allow loading all the child elements (must for larger specs)
564
566
  this.intersectionObserver.disconnect();
565
- if (this.renderStyle === 'read') {
566
- await sleep(100);
567
- this.observeExpandedContent(); // This will auto-highlight the selected nav-item in read-mode
567
+
568
+ if (this.renderStyle === 'focused') {
569
+ const defaultElementId = this.showInfo ? 'overview' : this.resolvedSpec.tags && this.resolvedSpec.tags[0] && this.resolvedSpec.tags[0].paths[0];
570
+ this.scrollTo(this.explorerLocation || defaultElementId);
568
571
  }
569
572
 
570
- // On first time Spec load, try to navigate to location hash if provided
571
- const locationHash = this.explorerLocation;
572
- if (locationHash) {
573
- if (this.renderStyle === 'view') {
574
- this.expandAndGotoOperation(locationHash, true, true);
575
- } else if (this.renderStyle === 'focused') {
576
- this.scrollTo(locationHash);
577
- }
578
- } else if (this.renderStyle === 'focused') {
579
- const defaultElementId = this.showInfo ? 'overview' : this.resolvedSpec.tags[0] && this.resolvedSpec.tags[0].paths[0];
580
- this.scrollTo(defaultElementId);
573
+ if (this.renderStyle === 'view' && this.explorerLocation) {
574
+ this.expandAndGotoOperation(this.explorerLocation);
581
575
  }
582
576
  }
583
577
 
584
- expandAndGotoOperation(elementId, scrollToElement = true) {
578
+ expandAndGotoOperation(elementId) {
585
579
  // Expand full operation and tag
586
- let isExpandingNeeded = true;
587
- const tmpElementId = elementId.indexOf('#') === -1 ? elementId : elementId.substring(1);
588
- if (tmpElementId.startsWith('overview') || tmpElementId === 'servers' || tmpElementId === 'auth') {
589
- isExpandingNeeded = false;
590
- } else {
591
- for (let i = 0; i < this.resolvedSpec.tags && this.resolvedSpec.tags.length; i++) {
592
- const tag = this.resolvedSpec.tags[i];
593
- const path = tag.paths && tag.paths.find((p) => p.elementId === elementId);
594
- if (path) {
595
- if (path.expanded && tag.expanded) {
596
- isExpandingNeeded = false;
597
- } else {
598
- path.expanded = true;
599
- tag.expanded = true;
600
- }
601
- }
602
- }
580
+ let isExpandingNeeded = false;
581
+
582
+ const tag = this.resolvedSpec.tags.find(t => t.paths && t.paths.find(p => p.elementId === elementId));
583
+ const path = tag && tag.paths && tag.paths.find((p) => p.elementId === elementId);
584
+ if (path && (!path.expanded || !tag.expanded)) {
585
+ isExpandingNeeded = true;
586
+ path.expanded = true;
587
+ tag.expanded = true;
588
+ this.requestUpdate();
603
589
  }
604
- if (scrollToElement) {
605
- // requestUpdate() and delay required, else we cant find element
606
- if (isExpandingNeeded) {
607
- this.requestUpdate();
590
+
591
+ // requestUpdate() and delay required, else we cant find element because it won't exist immediately
592
+ const tmpElementId = elementId.indexOf('#') === -1 ? elementId : elementId.substring(1);
593
+ window.setTimeout(() => {
594
+ const gotoEl = this.shadowRoot.getElementById(tmpElementId);
595
+ if (gotoEl) {
596
+ gotoEl.scrollIntoView({ behavior: 'auto', block: 'start' });
597
+ replaceState(tmpElementId);
608
598
  }
609
- window.setTimeout(() => {
610
- const gotoEl = this.shadowRoot.getElementById(tmpElementId);
611
- if (gotoEl) {
612
- gotoEl.scrollIntoView({ behavior: 'auto', block: 'start' });
613
- replaceState(tmpElementId);
614
- }
615
- }, isExpandingNeeded ? 150 : 0);
616
- }
599
+ }, isExpandingNeeded ? 150 : 0);
617
600
  }
618
601
 
619
602
  isValidTopId(id) {
@@ -696,28 +679,26 @@ export default class OpenApiExplorer extends LitElement {
696
679
  repeatedElementIndex = assignedNodes && [].findIndex.call(assignedNodes, (slot) => slot === event.target);
697
680
  }
698
681
  this.isIntersectionObserverActive = false;
699
- this.scrollTo(navEl.dataset.contentId, true, scrollNavItemToView, repeatedElementIndex);
682
+ this.scrollTo(navEl.dataset.contentId, scrollNavItemToView, repeatedElementIndex);
700
683
  setTimeout(() => {
701
684
  this.isIntersectionObserverActive = true;
702
685
  }, 300);
703
686
  }
704
687
 
705
688
  // Public Method (scrolls to a given path and highlights the left-nav selection)
706
- async scrollTo(elementId, expandPath = true, scrollNavItemToView = true, repeatedElementIndex) {
689
+ async scrollTo(elementId, scrollNavItemToView = true, repeatedElementIndex) {
707
690
  if (!this.resolvedSpec) {
708
691
  return;
709
692
  }
710
693
 
711
694
  if (this.renderStyle === 'view') {
712
- this.expandAndGotoOperation(elementId, expandPath, true);
695
+ this.expandAndGotoOperation(elementId);
713
696
  return;
714
697
  }
715
698
 
716
- if (this.renderStyle === 'focused') {
717
- // explorerLocation will get validated in the focused-endpoint-template
718
- this.explorerLocation = elementId;
719
- await sleep(0);
720
- }
699
+ // explorerLocation will get validated in the focused-endpoint-template
700
+ this.explorerLocation = elementId;
701
+ await sleep(0);
721
702
 
722
703
  const contentEl = this.shadowRoot.getElementById(elementId);
723
704
  if (!contentEl) {
@@ -725,22 +706,20 @@ export default class OpenApiExplorer extends LitElement {
725
706
  }
726
707
 
727
708
  // For focused APIs, always scroll to the top of the component
728
- if (this.renderStyle === 'focused' && !elementId.match('cmp--')) {
709
+ if (!elementId.match('cmp--')) {
729
710
  this.shadowRoot.getElementById('operations-root').scrollIntoView({ behavior: 'auto', block: 'start' });
730
711
  } else {
731
712
  contentEl.scrollIntoView({ behavior: 'auto', block: 'start' });
732
713
  }
733
714
 
734
715
  // for focused style it is important to reset request-body-selection and response selection which maintains the state for in case of multiple req-body or multiple response mime-type
735
- if (this.renderStyle === 'focused') {
736
- const requestEl = this.shadowRoot.querySelector('api-request');
737
- if (requestEl) {
738
- requestEl.resetRequestBodySelection();
739
- }
740
- const responseEl = this.shadowRoot.querySelector('api-response');
741
- if (responseEl) {
742
- responseEl.resetSelection();
743
- }
716
+ const requestEl = this.shadowRoot.querySelector('api-request');
717
+ if (requestEl) {
718
+ requestEl.resetRequestBodySelection();
719
+ }
720
+ const responseEl = this.shadowRoot.querySelector('api-response');
721
+ if (responseEl) {
722
+ responseEl.resetSelection();
744
723
  }
745
724
 
746
725
  // Update Location Hash
@@ -772,7 +751,7 @@ export default class OpenApiExplorer extends LitElement {
772
751
  node.classList.remove('active');
773
752
  });
774
753
  newNavEl.classList.add('active'); // must add the class after scrolling
775
- // this.requestUpdate();
754
+ this.requestUpdate();
776
755
  }
777
756
 
778
757
  // Event handler for Advanced Search text-inputs and checkboxes
@@ -68,8 +68,7 @@ export default css`
68
68
  color: var(--secondary-color);
69
69
  border-left:4px solid transparent;
70
70
  font-weight:bold;
71
- padding: 15px 15px 15px 10px;
72
- text-transform: capitalize;
71
+ padding: 15px 15px 15px 10px;
73
72
  }
74
73
 
75
74
  .nav-bar-components,
@@ -14,7 +14,7 @@ function toggleExpand(path) {
14
14
  replaceState(null);
15
15
  } else {
16
16
  path.expanded = true; // Expand
17
- if (path.elementId === getCurrentElement()) {
17
+ if (path.elementId !== getCurrentElement()) {
18
18
  replaceState(path.elementId);
19
19
  }
20
20
  }
@@ -6,7 +6,6 @@ import componentsTemplate from './components-template';
6
6
  import overviewTemplate from './overview-template';
7
7
  import serverTemplate from './server-template';
8
8
  import securitySchemeTemplate from './security-scheme-template';
9
- import { expandCollapseNavBarTag } from './navbar-template';
10
9
 
11
10
  function wrapFocusedTemplate(templateToWrap) {
12
11
  return html`
@@ -71,9 +70,6 @@ export default function focusedEndpointTemplate() {
71
70
  }
72
71
  }
73
72
  if (selectedPathObj) {
74
- // In focused mode we must expand the nav-bar tag element if it is collapsed
75
- const newNavEl = this.shadowRoot.getElementById(`link-${focusElId}`);
76
- expandCollapseNavBarTag(newNavEl, 'expand');
77
73
  focusedTemplate = wrapFocusedTemplate.call(this, expandedEndpointBodyTemplate.call(this, selectedPathObj, selectedTagObj.name));
78
74
  } else {
79
75
  // if explorerLocation is not found then show the default content (overview or first-path)
@@ -1,7 +1,6 @@
1
1
  import { html } from 'lit-element';
2
2
 
3
3
  // Templates
4
- import expandedEndpointTemplate from './expanded-endpoint-template';
5
4
  import focusedEndpointTemplate from './focused-endpoint-template';
6
5
  import overviewTemplate from './overview-template';
7
6
  import endpointTemplate from './endpoint-template';
@@ -61,11 +60,7 @@ export default function responsiveViewMainBodyTemplate() {
61
60
  class='observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}'>
62
61
  <slot name="custom-section"></slot>
63
62
  </section>
64
- ${this.renderStyle === 'read'
65
- ? expandedEndpointTemplate.call(this)
66
- : endpointTemplate.call(this)
67
- }
68
- `
63
+ ${endpointTemplate.call(this)}`
69
64
  }
70
65
  </div>
71
66
  `
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
4
4
  import { invalidCharsRegEx } from './common-utils';
5
5
 
6
6
  export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
7
- const inputSpecIsAUrl = typeof specUrlOrObject === 'string' && specUrlOrObject.match(/^http/);
7
+ const inputSpecIsAUrl = typeof specUrlOrObject === 'string' && specUrlOrObject.match(/^http/) || typeof specUrlOrObject === 'object' && typeof specUrlOrObject.href === 'string';
8
8
  let specMeta;
9
9
 
10
10
  // Dynamically resolve non yaml or json files and insert their descriptions where necessary
@@ -16,7 +16,7 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
16
16
  }
17
17
 
18
18
  if (inputSpecIsAUrl) {
19
- specMeta = await SwaggerClient({ allowMetaPatches: false, url: specUrlOrObject, responseInterceptor });
19
+ specMeta = await SwaggerClient({ allowMetaPatches: false, url: specUrlOrObject.toString(), responseInterceptor });
20
20
  } else if (typeof specUrlOrObject === 'string') {
21
21
  specMeta = await SwaggerClient({ allowMetaPatches: false, spec: yaml.load(specUrlOrObject), responseInterceptor });
22
22
  } else {