Skip to content

Commit 08b9e0b

Browse files
committed
code-refator: generate element-id during spec parsing and avoid render time generation
1 parent 0e566ff commit 08b9e0b

9 files changed

+52
-54
lines changed

src/rapidoc.js

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import InfoStyles from '@/styles/info-styles';
2424
import CustomStyles from '@/styles/custom-styles';
2525
import { expandCollapseNavBarTag } from '@/templates/navbar-template';
2626
import {
27-
pathIsInSearch, invalidCharsRegEx, sleep, rapidocApiKey, advancedSearch, hasValidPathInUrlHash,
27+
pathIsInSearch, sleep, rapidocApiKey, advancedSearch, hasValidPathInUrlHash,
2828
} from '@/utils/common-utils';
2929
import ProcessSpec from '@/utils/spec-parser';
3030
import mainBodyTemplate from '@/templates/main-body-template';
@@ -435,7 +435,7 @@ export default class RapiDoc extends LitElement {
435435
await this.loadSpec(newVal);
436436
// If goto-path is provided then try to scroll there
437437
if (this.gotoPath) {
438-
this.scrollTo(this.gotoPath.replace(invalidCharsRegEx, '-').toLowerCase());
438+
this.scrollTo(this.gotoPath);
439439
}
440440
}, 0);
441441
}
@@ -610,17 +610,13 @@ export default class RapiDoc extends LitElement {
610610
this.selectedContentId = '';
611611
// If there is hash in url then check if hash belong to any of the path in spec
612612
if (window.location.hash) {
613-
this.selectedContentId = window.location.hash.substring(1).startsWith('overview--')
614-
? 'overview' : hasValidPathInUrlHash(this.resolvedSpec.tags)
615-
? window.location.hash.substring(1) : '';
613+
if ('top, overview, authentication, api-servers'.includes(window.location.hash.substring(1)) || hasValidPathInUrlHash(this.resolvedSpec.tags)) {
614+
this.selectedContentId = window.location.hash.substring(1);
615+
}
616616
}
617-
// If there is no matching hash to path, check if there is sufficient data to display overview otherwise just display first path from first tag
617+
// If there is no valid location-hash, check if there is sufficient data to display overview otherwise just display first path from first tag
618618
if (!this.selectedContentId) {
619-
if (this.showInfo === 'true' && (this.resolvedSpec.info?.description || this.resolvedSpec.info?.title)) {
620-
this.selectedContentId = 'overview';
621-
} else {
622-
this.selectedContentId = `${this.resolvedSpec.tags[0]?.paths[0]?.method}-${this.resolvedSpec.tags[0]?.paths[0]?.path}`;
623-
}
619+
this.selectedContentId = 'top';
624620
}
625621
// Set url back in address bar
626622
window.location.hash = `${this.selectedContentId}`;
@@ -650,33 +646,37 @@ export default class RapiDoc extends LitElement {
650646

651647
// Initiate IntersectionObserver and put it at the end of event loop, to allow loading all the child elements (must for larger specs)
652648
this.intersectionObserver.disconnect();
653-
if (this.renderStyle === 'read') {
654-
await sleep(100);
655-
this.observeExpandedContent(); // This will auto-highlight the selected nav
656-
} else if (this.renderStyle === 'focused') {
657-
await sleep(0);
658-
const newNavEl = this.shadowRoot.getElementById(`link-${this.selectedContentId}`);
659-
if (newNavEl) {
660-
newNavEl.classList.add('active');
661-
newNavEl.scrollIntoView({ behavior: 'auto', block: 'center' });
649+
if (window.location.hash) {
650+
if (this.renderStyle === 'read') {
651+
await sleep(100);
652+
this.observeExpandedContent(); // This will auto-highlight the selected nav-item in read-mode
653+
} else if (this.renderStyle === 'focused') {
654+
await sleep(0);
655+
const newNavEl = this.shadowRoot.getElementById(`link-${this.selectedContentId}`);
656+
if (newNavEl) {
657+
newNavEl.classList.add('active');
658+
newNavEl.scrollIntoView({ behavior: 'auto', block: 'center' });
659+
}
662660
}
663661
}
664662
// On first time Spec load, try to navigate to location hash if provided
665663
if (window.location.hash) {
666664
if (!this.gotoPath) {
667-
this.expandTreeToPath(window.location.hash, true, true);
665+
this.expandAndGotoOperation(window.location.hash, true, true);
668666
}
669667
}
670668
}
671669

672-
expandTreeToPath(pathInput, expandOperation = true, scrollToElement = true) {
670+
expandAndGotoOperation(elementId, expandOperation = true, scrollToElement = true) {
673671
// Expand full operation and tag
674-
if (pathInput.indexOf('#') === 0) pathInput = pathInput.substring(1);
672+
if (elementId.indexOf('#') === 0) {
673+
elementId = elementId.substring(1);
674+
}
675675
let path;
676676
this.resolvedSpec.tags.map((tag) => tag.paths.filter((v) => {
677-
const method = pathInput.match(new RegExp('(.*?)-'));
677+
const method = elementId.match(new RegExp('(.*?)-'));
678678
const methodType = (method && method.length === 2) ? method[1] : null;
679-
path = pathInput.match(new RegExp('/.*$'));
679+
path = elementId.match(new RegExp('/.*$'));
680680
const pathValue = (path && path.length === 1) ? path[0] : null;
681681

682682
if (methodType && pathValue && methodType === v.method && pathValue === v.path) {
@@ -689,7 +689,7 @@ export default class RapiDoc extends LitElement {
689689
if (scrollToElement) {
690690
// delay required, else we cant find element
691691
window.setTimeout(() => {
692-
const gotoEl = this.shadowRoot.getElementById(pathInput);
692+
const gotoEl = this.shadowRoot.getElementById(elementId);
693693
if (gotoEl) {
694694
gotoEl.scrollIntoView({ behavior: 'auto', block: 'start' });
695695
}
@@ -778,7 +778,7 @@ export default class RapiDoc extends LitElement {
778778
await sleep(0);
779779
const gotoEl = this.shadowRoot.getElementById(path);
780780
if (gotoEl) {
781-
this.expandTreeToPath(path, expandPath, true);
781+
this.expandAndGotoOperation(path, expandPath, true);
782782
const oldNavEl = this.shadowRoot.querySelector('.nav-bar-tag.active, .nav-bar-path.active, .nav-bar-info.active, .nav-bar-h1.active, .nav-bar-h2.active');
783783
const newNavEl = this.shadowRoot.getElementById(`link-${path}`);
784784
if (oldNavEl) {

src/templates/advance-search-template.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { html } from 'lit-html';
2-
import { invalidCharsRegEx } from '@/utils/common-utils';
32
import '@/components/dialog-box';
43

54
/* eslint-disable indent */
@@ -55,7 +54,7 @@ export default function searchByPropertiesModalTemplate() {
5554
this.matchPaths = ''; // clear quick filter if applied
5655
this.showAdvancedSearchDialog = false; // Hide Search Dialog
5756
this.requestUpdate();
58-
this.scrollTo(`${path.method}-${path.path.replace(invalidCharsRegEx, '-')}`);
57+
this.scrollTo(`${path.elementId}`);
5958
}
6059
}"
6160
>

src/templates/endpoint-template.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ import '@/components/api-response';
66
import codeSamplesTemplate from '@/templates/code-samples-template';
77
import callbackTemplate from '@/templates/callback-template';
88
import { pathSecurityTemplate } from '@/templates/security-scheme-template';
9-
import { pathIsInSearch, invalidCharsRegEx, rapidocApiKey } from '@/utils/common-utils';
9+
import { pathIsInSearch, rapidocApiKey } from '@/utils/common-utils';
1010

1111
function toggleExpand(path) {
1212
if (path.expanded) {
1313
path.expanded = false; // collapse
1414
window.history.replaceState(null, null, `${window.location.href.split('#')[0]}`);
1515
} else {
1616
path.expanded = true; // Expand
17-
const newHash = `#${path.method}-${path.path.replace(invalidCharsRegEx, '-')}`;
18-
const currentHash = window.location.hash;
19-
if (currentHash !== newHash) {
17+
const newHash = `#${path.elementId}`;
18+
if (window.location.hash !== newHash) {
2019
window.history.replaceState(null, null, `${window.location.href.split('#')[0]}${newHash}`);
2120
}
2221
}
@@ -138,7 +137,7 @@ export default function endpointTemplate() {
138137
<div class='regular-font section-gap section-tag ${tag.expanded ? 'expanded' : 'collapsed'}' >
139138
140139
<div class='section-tag-header' @click="${() => { tag.expanded = !tag.expanded; this.requestUpdate(); }}">
141-
<div id='${tag.name.replace(invalidCharsRegEx, '-')}' class="sub-title tag" style="color:var(--primary-color)">${tag.name}</div>
140+
<div id='${tag.elementId}' class="sub-title tag" style="color:var(--primary-color)">${tag.name}</div>
142141
</div>
143142
<div class='section-tag-body'>
144143
<div class="regular-font regular-font-size m-markdown" style="padding-bottom:12px">
@@ -150,7 +149,7 @@ export default function endpointTemplate() {
150149
}
151150
return true;
152151
}).map((path) => html`
153-
<div id='${path.method}-${path.path.replace(invalidCharsRegEx, '-')}' class='m-endpoint regular-font ${path.method} ${path.expanded ? 'expanded' : 'collapsed'}'>
152+
<div id='${path.elementId}' class='m-endpoint regular-font ${path.method} ${path.expanded ? 'expanded' : 'collapsed'}'>
154153
${endpointHeadTemplate.call(this, path)}
155154
${path.expanded ? endpointBodyTemplate.call(this, path) : ''}
156155
</div>`)

src/templates/expanded-endpoint-template.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { html } from 'lit-element';
22
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
33
import marked from 'marked';
4-
import { invalidCharsRegEx, rapidocApiKey } from '@/utils/common-utils';
4+
import { rapidocApiKey } from '@/utils/common-utils';
55
import { pathSecurityTemplate } from '@/templates/security-scheme-template';
66
import codeSamplesTemplate from '@/templates/code-samples-template';
77
import callbackTemplate from '@/templates/callback-template';
@@ -31,9 +31,9 @@ export function expandedEndpointBodyTemplate(path, tagName = '') {
3131
const codeSampleTabPanel = path.xCodeSamples ? codeSamplesTemplate.call(this, path.xCodeSamples) : '';
3232
return html`
3333
${this.renderStyle === 'read' ? html`<div class='divider'></div>` : ''}
34-
<div class='expanded-endpoint-body observe-me ${path.method} ${path.deprecated ? 'deprecated' : ''} ' id='${path.method}-${path.path.replace(invalidCharsRegEx, '-')}'>
34+
<div class='expanded-endpoint-body observe-me ${path.method} ${path.deprecated ? 'deprecated' : ''} ' id='${path.elementId}'>
3535
${this.renderStyle === 'focused' ? html`<h3 class="upper" style="font-weight:bold"> ${tagName} </h3>` : ''}
36-
${path.deprecated ? html`<div class="bold-text red-text" > DEPRECATED </div>` : ''}
36+
${path.deprecated ? html`<div class="bold-text red-text"> DEPRECATED </div>` : ''}
3737
${html`
3838
<h2 class = "${path.deprecated ? 'gray-text' : ''}">
3939
${path.summary || html`<span class='upper ${path.deprecated ? ' method-fg gray-text' : path.method} '> ${path.method}</span> ${path.path}`}
@@ -89,7 +89,7 @@ export function expandedEndpointBodyTemplate(path, tagName = '') {
8989
export default function expandedEndpointTemplate() {
9090
return html`
9191
${this.resolvedSpec.tags.map((tag) => html`
92-
<div id="tag--${tag.name.replace(invalidCharsRegEx, '-')}" class='regular-font section-gap--read-mode observe-me' style="border-top:1px solid var(--primary-color);">
92+
<div id="${tag.elementId}" class='regular-font section-gap--read-mode observe-me' style="border-top:1px solid var(--primary-color);">
9393
<div class="title tag">${tag.name}</div>
9494
<div class="regular-font-size">
9595
${unsafeHTML(`<div class='m-markdown regular-font'>${marked(tag.description ? tag.description : '')}</div>`)}

src/templates/focused-endpoint-template.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { html } from 'lit-element';
22
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
33
import marked from 'marked';
44
import { expandedEndpointBodyTemplate } from '@/templates/expanded-endpoint-template';
5-
import { invalidCharsRegEx } from '@/utils/common-utils';
65
import '@/components/api-request';
76
import '@/components/api-response';
87

98
/* eslint-disable indent */
109
function focusedTagBodyTemplate(tag) {
1110
return html`
12-
<h1 id="tag--${tag.name.replace(invalidCharsRegEx, '-')}">${tag.name}</h1>
11+
<h1 id="${tag.elementId}">${tag.name}</h1>
1312
${tag.description ? html`<div class="m-markdown"> ${unsafeHTML(marked(tag.description || ''))}</div>` : ''}
1413
`;
1514
}
@@ -28,12 +27,11 @@ export default function focusedEndpointTemplate() {
2827
selectedPathObj = {};
2928
selectedTagObj = {};
3029
} else if (itemToFocus.startsWith('tag--')) {
31-
const tag = itemToFocus.replace('tag--', '');
32-
selectedTagObj = this.resolvedSpec.tags.find((v) => v.name.replace(invalidCharsRegEx, '-') === tag);
30+
selectedTagObj = this.resolvedSpec.tags.find((v) => v.elementId === itemToFocus);
3331
} else {
3432
for (i = 0; i < this.resolvedSpec.tags.length; i += 1) {
3533
selectedTagObj = this.resolvedSpec.tags[i];
36-
selectedPathObj = this.resolvedSpec.tags[i].paths.find((v) => `${v.method}-${v.path.replace(invalidCharsRegEx, '-')}` === itemToFocus);
34+
selectedPathObj = this.resolvedSpec.tags[i].paths.find((v) => `${v.elementId}` === itemToFocus);
3735
if (selectedPathObj) {
3836
break;
3937
}

src/templates/main-body-template.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export default function mainBodyTemplate() {
9595
<!-- Advanced Search -->
9696
${this.allowAdvancedSearch === 'false' ? '' : advancedSearchTemplate.call(this)}
9797
98-
<div class="body">
98+
<div id='the-main-body' class="body">
9999
<!-- Side Nav -->
100100
${((this.renderStyle === 'read' || this.renderStyle === 'focused')
101101
&& this.showSideNav === 'true'

src/templates/navbar-template.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { html } from 'lit-element';
2-
import { pathIsInSearch, invalidCharsRegEx } from '@/utils/common-utils';
2+
import { pathIsInSearch } from '@/utils/common-utils';
33
import marked from 'marked';
44

55
export function expandCollapseNavBarTag(navLinkEl, action = 'toggle') {
@@ -121,8 +121,8 @@ export default function navbarTemplate() {
121121
<div class='nav-bar-tag-and-paths ${tag.expanded ? 'expanded' : 'collapsed'}'>
122122
<div
123123
class='nav-bar-tag'
124-
id="link-tag--${tag.name.replace(invalidCharsRegEx, '-')}"
125-
data-content-id='tag--${tag.name.replace(invalidCharsRegEx, '-')}'
124+
id="link-${tag.elementId}"
125+
data-content-id='${tag.elementId}'
126126
@click='${(e) => {
127127
this.scrollToEl(e);
128128
}}'
@@ -141,8 +141,8 @@ export default function navbarTemplate() {
141141
<div
142142
class='nav-bar-path
143143
${this.usePathInNavBar === 'true' ? 'small-font' : ''}'
144-
data-content-id='${p.method}-${p.path.replace(invalidCharsRegEx, '-')}'
145-
id='link-${p.method}-${p.path.replace(invalidCharsRegEx, '-')}'
144+
data-content-id='${p.elementId}'
145+
id='link-${p.elementId}'
146146
@click = '${(e) => this.scrollToEl(e)}'
147147
>
148148
<span style = "${p.deprecated ? 'filter:opacity(0.5)' : ''}">

src/utils/common-utils.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function debounce(fn, delay) {
1010
};
1111
}
1212

13-
export const invalidCharsRegEx = new RegExp(/[\s#:?&={}]/, 'g');
13+
export const invalidCharsRegEx = new RegExp(/[\s#:?&={}]/, 'g'); // used for generating valid html element ids by replacing the invalid chars with hyphen (-)
1414
export const rapidocApiKey = '_rapidoc_api_key';
1515

1616
export function sleep(ms) {
@@ -115,6 +115,5 @@ export function advancedSearch(searchVal, allSpecTags, searchOptions = []) {
115115
}
116116

117117
export function hasValidPathInUrlHash(tags) {
118-
const filterTags = tags.filter((tag) => tag.paths.filter((path) => window.location.hash.substring(1) === `${path.method}-${path.path.replace(invalidCharsRegEx, '-')}`).length > 0);
119-
return filterTags.length > 0;
118+
return tags.find((tag) => tag.paths.find((path) => window.location.hash.substring(1) === path.elementId));
120119
}

src/utils/spec-parser.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ function groupByTags(openApiSpec, sortTags = false, sortEndpointsBy) {
266266
const tags = openApiSpec.tags && Array.isArray(openApiSpec.tags)
267267
? openApiSpec.tags.map((v) => ({
268268
show: true,
269+
elementId: `tag--${v.name.replace(invalidCharsRegEx, '-')}`,
269270
name: v.name,
270271
description: v.description,
271272
paths: [],
@@ -311,9 +312,10 @@ function groupByTags(openApiSpec, sortTags = false, sortEndpointsBy) {
311312
if (!tagObj) {
312313
tagObj = {
313314
show: true,
315+
elementId: `tag--${tag.replace(invalidCharsRegEx, '-')}`,
314316
name: tag,
315-
paths: [],
316317
description: specTagsItem ? specTagsItem.description : '',
318+
paths: [],
317319
expanded: (specTagsItem ? specTagsItem['x-tag-expanded'] !== false : true),
318320
};
319321
tags.push(tagObj);
@@ -354,6 +356,7 @@ function groupByTags(openApiSpec, sortTags = false, sortEndpointsBy) {
354356
description: fullPath.description,
355357
path,
356358
operationId: fullPath.operationId,
359+
elementId: `${methodName}-${path.replace(invalidCharsRegEx, '-')}`,
357360
servers: fullPath.servers ? commonPathProp.servers.concat(fullPath.servers) : commonPathProp.servers,
358361
parameters: finalParameters,
359362
requestBody: fullPath.requestBody,

0 commit comments

Comments
 (0)