@salesforcedevs/docs-components 0.56.2-seo-test10 → 0.56.2

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.
@@ -3,7 +3,7 @@ import { noCase } from "no-case";
3
3
  import { sentenceCase } from "sentence-case";
4
4
  import qs from "query-string";
5
5
  import { AmfModelParser } from "./utils";
6
- import { normalizeBoolean } from "dxUtils/normalizers";
6
+ import { RouteMeta } from "./route-meta";
7
7
  import type {
8
8
  AmfConfig,
9
9
  AmfMetadataTopic,
@@ -14,46 +14,94 @@ import type {
14
14
  TopicModel,
15
15
  ReferenceVersion,
16
16
  ReferenceSetConfig,
17
- AmfMetaTopicType,
18
- RouteMeta,
19
- ParsedMarkdownTopic
17
+ AmfMetaTopicType
20
18
  } from "./types";
21
19
 
22
- import {
23
- NAVIGATION_ITEMS,
24
- URL_CONFIG,
25
- REFERENCE_TYPES,
26
- oldReferenceIdNewReferenceIdMap
27
- } from "./constants";
20
+ const NAVIGATION_ITEMS = [
21
+ {
22
+ label: "Summary",
23
+ name: "summary",
24
+ childrenPropertyName: undefined,
25
+ type: "summary"
26
+ },
27
+ {
28
+ label: "Endpoints",
29
+ name: "endpoints",
30
+ childrenPropertyName: "endpoints",
31
+ type: "endpoint"
32
+ },
33
+ {
34
+ label: "Documentation",
35
+ name: "documentation",
36
+ childrenPropertyName: "docs",
37
+ type: "documentation"
38
+ },
39
+ {
40
+ label: "Types",
41
+ name: "types",
42
+ childrenPropertyName: "types",
43
+ type: "type"
44
+ },
45
+ {
46
+ label: "Security",
47
+ name: "security",
48
+ childrenPropertyName: "security",
49
+ type: "security"
50
+ }
51
+ ];
52
+
53
+ const URL_CONFIG = {
54
+ summary: {
55
+ urlIdentifer: "label"
56
+ },
57
+ endpoint: {
58
+ urlIdentifer: "path"
59
+ },
60
+ method: {
61
+ urlIdentifer: "label"
62
+ },
63
+ documentation: {
64
+ urlIdentifer: "label"
65
+ },
66
+ type: {
67
+ urlIdentifer: "label",
68
+ prefix: "type:"
69
+ },
70
+ security: {
71
+ urlIdentifer: "label",
72
+ prefix: "security:"
73
+ }
74
+ };
75
+
76
+ const urlHashToMetaRedirectMap = {
77
+ "commerce-api-assignments:Summary": "assignments:Summary",
78
+ "commerce-api-campaigns:Summary": "campaigns:Summary",
79
+ "commerce-api-catalogs:Summary": "catalogs:Summary",
80
+ "cdn-zones:Summary": "cdn-api-process-apis:Summary",
81
+ "inventory-impex:Summary": "impex:Summary",
82
+ "inventory-reservations:Summary": "inventory-reservation-service:Summary",
83
+ "shopper-login-and-api-access-service:Summary": "shopper-login:Summary",
84
+ "shopper-login-and-api-access-service-admin:Summary": "slas-admin:Summary",
85
+ "einstein-recommendations:Summary": "einstein-api-quick-start-guide:Summary"
86
+ };
28
87
 
29
88
  export default class AmfReference extends LightningElement {
30
- @api breadcrumbs?: string | null | undefined = null;
31
- @api sidebarHeader!: string;
89
+ @api breadcrumbs?: string = null;
90
+ @api sidebarHeader: string;
32
91
  @api coveoOrganizationId!: string;
33
92
  @api coveoPublicAccessToken!: string;
34
93
  @api coveoAdvancedQueryConfig!: string;
35
94
  @api coveoSearchHub!: string;
36
95
  @api useOldSidebar?: boolean = false;
37
- @api tocTitle?: string;
38
- @api tocOptions?: string;
39
- @track navigation = [];
40
- @track versions: Array<ReferenceVersion> = [];
41
96
 
42
97
  // Update this to update what component gets rendered in the content block
43
98
  @track
44
- protected topicModel!: TopicModel;
99
+ protected topicModel: TopicModel;
45
100
 
46
101
  get isVersionEnabled(): boolean {
47
102
  return !!this._referenceSetConfig?.versions?.length;
48
103
  }
49
104
 
50
- /**
51
- * Gives if the currently selected reference is spec based or not
52
- */
53
- get showSpecBasedReference(): boolean {
54
- return this.isSpecBasedReference(this._currentReferenceId);
55
- }
56
-
57
105
  @api
58
106
  get referenceSetConfig(): ReferenceSetConfig {
59
107
  return this._referenceSetConfig;
@@ -74,42 +122,22 @@ export default class AmfReference extends LightningElement {
74
122
  this._referenceSetConfig = refConfig;
75
123
  } catch (e) {
76
124
  this._referenceSetConfig = {
77
- refList: [],
78
- versions: []
125
+ refList: []
79
126
  };
80
127
  }
81
128
 
82
- this._amfConfigList = this._referenceSetConfig.refList || [];
83
-
84
- this._amfConfigList.forEach((amfConfig) => {
85
- this._amfConfigMap.set(amfConfig.id, amfConfig);
86
- });
87
-
88
- if (this._amfConfigList.length > 0) {
89
- this._currentReferenceId =
90
- this._referenceSetConfig.refId || this._amfConfigList[0].id;
91
- }
92
-
93
129
  if (this.isVersionEnabled) {
94
130
  const selectedVersion = this.getSelectedVersion();
95
-
96
- /**
97
- * If current selected is markdown based reference,
98
- * We will assign versions once the selected item url is updated
99
- */
100
- if (this.isSpecBasedReference(this._currentReferenceId)) {
101
- this.versions = this.getVersions();
102
- }
131
+ this.versionToRefMap = this._referenceSetConfig.versionToRefMap;
132
+ // if version is not available, then show empty - this will be the default behaviour
133
+ this._amfConfig = this.versionToRefMap[selectedVersion.id] || [];
134
+ this.versions = this._referenceSetConfig.versions;
103
135
  this.selectedVersion = selectedVersion;
104
- }
105
-
106
- // This is to check if the url is hash based and redirect if needed
107
- const redirectUrl = this.getHashBasedRedirectUrl();
108
- if (redirectUrl) {
109
- window.location.href = redirectUrl;
110
136
  } else {
111
- this.updateAmfConfigInView();
137
+ this._amfConfig = this._referenceSetConfig.refList;
112
138
  }
139
+
140
+ this.updateAmfConfigInView();
113
141
  }
114
142
 
115
143
  @api
@@ -124,51 +152,53 @@ export default class AmfReference extends LightningElement {
124
152
  }
125
153
  }
126
154
 
127
- @api
128
- get expandChildren() {
129
- return this._expandChildren;
130
- }
131
-
132
- set expandChildren(value) {
133
- this._expandChildren = normalizeBoolean(value);
134
- }
135
-
136
155
  // model
137
- protected _amfConfigList: AmfConfig[] = [];
138
- protected _amfConfigMap: Map<string, AmfConfig> = new Map();
139
- protected _referenceSetConfig!: ReferenceSetConfig;
156
+ protected _amfConfig: AmfConfig[] = [];
157
+ protected _referenceSetConfig: ReferenceSetConfig;
140
158
  protected _currentReferenceId = "";
141
159
 
142
- protected parentReferenceUrls = [];
143
160
  protected amfMap: Record<string, AmfModelRecord> = {};
144
161
  protected amfFetchPromiseMap = {};
145
162
  protected metadata: { [key: string]: AmfMetadataTopic } = {};
146
- protected selectedTopic?: AmfMetaTopicType = undefined;
163
+ protected selectedTopic: AmfMetaTopicType = undefined;
164
+ protected navigation = [];
147
165
  protected selectedSidebarValue = undefined;
148
-
149
- protected selectedVersion: ReferenceVersion | null = null;
166
+ protected versions: Array<ReferenceVersion> = [];
167
+ protected selectedVersion: ReferenceVersion = null;
150
168
 
151
169
  private hasRendered = false;
170
+ private navAmfOrder = [];
171
+
172
+ private versionToRefMap: Map<string, Array<AmfConfig>>;
152
173
 
153
174
  private isParentLevelDocPhaseEnabled = false;
154
- private selectedReferenceDocPhase?: string | null = null;
155
- private _expandChildren?: boolean = false;
175
+ private selectedReferenceDocPhase?: string = null;
156
176
 
157
177
  /**
158
- * Key for storing the currently selected reference url. This will be used to save the
159
- * previously selected reference url and restoring it when changing between reference versions.
178
+ * Key for storing the currently selected reference meta query param. This will be used to save the
179
+ * previously selected reference meta and restoring it when changing between reference versions.
160
180
  */
161
- private readonly docsReferenceUrlSessionKey: string = "docsReferenceUrl";
181
+ private readonly docsReferenceMetaSessionKey: string = "docsReferenceMeta";
162
182
 
163
183
  _boundOnApiNavigationChanged;
164
184
  _boundUpdateSelectedItemFromUrlQuery;
165
185
 
186
+ get amfConfigMapped(): AmfConfig[] {
187
+ return this._amfConfig.map((config) => {
188
+ return config.id in this.amfMap
189
+ ? Object.assign(config, this.amfMap[config.id])
190
+ : config;
191
+ });
192
+ }
193
+
166
194
  constructor() {
167
195
  super();
168
- this._boundOnApiNavigationChanged =
169
- this.onApiNavigationChanged.bind(this);
170
- this._boundUpdateSelectedItemFromUrlQuery =
171
- this.updateSelectedItemFromUrlQuery.bind(this);
196
+ this._boundOnApiNavigationChanged = this.onApiNavigationChanged.bind(
197
+ this
198
+ );
199
+ this._boundUpdateSelectedItemFromUrlQuery = this.updateSelectedItemFromUrlQuery.bind(
200
+ this
201
+ );
172
202
  }
173
203
 
174
204
  connectedCallback(): void {
@@ -196,7 +226,7 @@ export default class AmfReference extends LightningElement {
196
226
  renderedCallback(): void {
197
227
  if (!this.hasRendered) {
198
228
  this.hasRendered = true;
199
- if (this._amfConfigList && this._amfConfigList.length) {
229
+ if (this._amfConfig && this._amfConfig.length) {
200
230
  // If amfConfig has a value and length, it is assumed that fetch
201
231
  // has already been called and promises stored.
202
232
  this.updateView();
@@ -204,108 +234,6 @@ export default class AmfReference extends LightningElement {
204
234
  }
205
235
  }
206
236
 
207
- /**
208
- * Check if the URL hash to see whether this is one we want to redirect
209
- * See GUS W-10718771 for references where we want hash-based redirects
210
- * Return if we needs to redirect url to updated url
211
- */
212
- private getHashBasedRedirectUrl(): string | undefined {
213
- const { hash } = window.location;
214
- let hashBasedRedirectUrl = "";
215
- if (hash) {
216
- const strippedHash = hash.startsWith("#") ? hash.slice(1) : hash;
217
- const strippedHashItems = strippedHash
218
- ? strippedHash.split(":")
219
- : [];
220
- if (strippedHashItems.length) {
221
- const referenceId = strippedHashItems[0];
222
- const meta = strippedHashItems[1];
223
- const updatedReferenceId =
224
- oldReferenceIdNewReferenceIdMap[referenceId];
225
- const newReferenceId = updatedReferenceId || referenceId;
226
- const referenceItemConfig =
227
- this.getAmfConfigWithId(newReferenceId);
228
- if (referenceItemConfig) {
229
- hashBasedRedirectUrl = `${referenceItemConfig.href}?meta=${meta}`;
230
- }
231
- }
232
- }
233
- return hashBasedRedirectUrl;
234
- }
235
-
236
- /**
237
- * @param referenceId
238
- * @returns AMFConfig with given reference Id
239
- */
240
- private getAmfConfigWithId(referenceId: string): AmfConfig | undefined {
241
- return this._amfConfigMap.get(referenceId);
242
- }
243
-
244
- /**
245
- * @param referenceId
246
- * @returns if the reference is spec based one or not with given referenceId.
247
- */
248
- private isSpecBasedReference(referenceId: string): boolean {
249
- const selectedReference = this.getAmfConfigWithId(referenceId);
250
- return selectedReference
251
- ? selectedReference.referenceType !== REFERENCE_TYPES.markdown
252
- : false;
253
- }
254
-
255
- /*
256
- * Refactor below method when sidebar allows sending extraData along with the name for each item.
257
- * See if we can refactor the below method using regex.
258
- */
259
-
260
- /**
261
- * @param url
262
- * @returns reference Id from url path / selected sidebar item.
263
- */
264
- private getReferenceIdFromUrl(url: string): string {
265
- let referenceId = "";
266
- const urlItems = url.split("/references/");
267
- if (urlItems.length > 1) {
268
- const rightSidePart = urlItems[1];
269
-
270
- //This covers urls like "/project-name/references/reference-id/..."
271
- const slashSeparatorItems = rightSidePart.split("/");
272
-
273
- //This covers urls like "/project-name/references/reference-id?meta=Summary"
274
- const querySeparatorItems = slashSeparatorItems[0].split("?");
275
-
276
- referenceId = querySeparatorItems[0];
277
- }
278
-
279
- return referenceId;
280
- }
281
-
282
- /**
283
- * @returns versions to be shown in the dropdown
284
- * For markdown based specs, Adds selected markdown topic url to same references
285
- */
286
- private getVersions(): Array<ReferenceVersion> {
287
- const allVersions = this._referenceSetConfig.versions;
288
- if (!this.isSpecBasedReference(this._currentReferenceId)) {
289
- const currentRefMeta = this.getMarkdownReferenceMeta(
290
- window.location.href
291
- );
292
- if (currentRefMeta) {
293
- for (let i = 0; i < allVersions.length; i++) {
294
- const versionItem = allVersions[i];
295
- const referenceLink = versionItem.link.href;
296
- const referenceId =
297
- this.getReferenceIdFromUrl(referenceLink);
298
- if (this._currentReferenceId === referenceId) {
299
- // This is to navigate to respective topic in the changed version
300
- versionItem.link.href = `${referenceLink}/${currentRefMeta}`;
301
- allVersions[i] = versionItem;
302
- }
303
- }
304
- }
305
- }
306
- return allVersions;
307
- }
308
-
309
237
  /**
310
238
  * Returns the selected version or the first available version.
311
239
  */
@@ -319,9 +247,9 @@ export default class AmfReference extends LightningElement {
319
247
  }
320
248
 
321
249
  private updateAmfConfigInView(): void {
322
- if (this._amfConfigList && this._amfConfigList.length) {
250
+ if (this._amfConfig && this._amfConfig.length) {
323
251
  // fetch AMF Json as soon as config is set
324
- this.populateReferenceItems();
252
+ this.fetchAllAmf();
325
253
  // update() must be called after renderedCallback.
326
254
  if (this.hasRendered) {
327
255
  this.updateView();
@@ -341,69 +269,17 @@ export default class AmfReference extends LightningElement {
341
269
  }
342
270
 
343
271
  /**
344
- * Returns whether current location is project root path like ../example-project/references
345
- */
346
- private isProjectRootPath(): boolean {
347
- return this.getReferenceIdFromUrl(window.location.href) === "";
348
- }
349
-
350
- /**
351
- * Returns whether given url is parent reference path like ../example-project/references/reference-id
272
+ * Calls the fetch for each AMF in the config.
273
+ * Stores each fetch promise for handling after renderCallback.
352
274
  */
353
- private isParentReferencePath(urlPath: string): boolean {
354
- if (!urlPath) {
355
- return false;
356
- }
357
- const parentReferenceIndex = this.parentReferenceUrls.findIndex(
358
- (referenceUrl: string) => {
359
- return urlPath.endsWith(referenceUrl);
360
- }
361
- );
362
- return parentReferenceIndex !== -1;
363
- }
364
-
365
- /**
366
- * Populates reference Items from amfConfigList and assigns it to navigation for sidebar
367
- */
368
- private populateReferenceItems(): void {
369
- const navAmfOrder = [];
370
- for (const [index, amfConfig] of this._amfConfigList.entries()) {
371
- let navItemChildren = [];
372
- let isChildrenLoading = false;
373
- if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
374
- if (amfConfig.isSelected) {
375
- const amfPromise = this.fetchAmf(amfConfig).then(
376
- (amfJson) => {
377
- this.updateModel(amfConfig.id, amfJson);
378
- this.assignNavigationItemsFromAmf(amfConfig, index);
379
- }
380
- );
381
- this.amfFetchPromiseMap[amfConfig.id] = amfPromise;
382
- }
383
- isChildrenLoading = true;
384
- } else {
385
- navItemChildren = amfConfig.topic.children;
386
- }
387
- // store nav items for each spec in order
388
- navAmfOrder[index] = {
389
- label: amfConfig.title,
390
- name: amfConfig.href,
391
- isExpanded:
392
- amfConfig.isSelected ||
393
- this.isExpandChildrenEnabled(amfConfig.id),
394
- children: navItemChildren,
395
- isChildrenLoading
396
- };
397
- this.parentReferenceUrls.push(amfConfig.href);
275
+ private fetchAllAmf(): void {
276
+ for (const [i, amfConfig] of this._amfConfig.entries()) {
277
+ const p = this.fetchAmf(amfConfig).then((amfJson) => {
278
+ this.updateModel(amfConfig.id, amfJson);
279
+ this.assignNavigationItemsFromAmf(amfConfig.id, i);
280
+ });
281
+ this.amfFetchPromiseMap[amfConfig.id] = p;
398
282
  }
399
- this.navigation = navAmfOrder;
400
- }
401
-
402
- /**
403
- * Returns a boolean indicating whether the children should be expanded or not.
404
- */
405
- private isExpandChildrenEnabled(referenceId: string): boolean {
406
- return this.expandChildren && this._currentReferenceId === referenceId;
407
283
  }
408
284
 
409
285
  /**
@@ -435,7 +311,7 @@ export default class AmfReference extends LightningElement {
435
311
 
436
312
  /**
437
313
  * Transforms a list of model data for endpoints into corresponding
438
- * navigation list items that are compatible with dx-sidebar.
314
+ * navigation list items that is compatible with dx-sidebar.
439
315
  * Compatible with transforming AMF data parsed from both RAML and OAS spec.
440
316
  * Transforms a flat list of endpoints into a nested list based on indentation level
441
317
  * for RAML spec.
@@ -443,7 +319,6 @@ export default class AmfReference extends LightningElement {
443
319
  * @returns {array<Object>} List of navigation items
444
320
  */
445
321
  private assignEndpointNavItems(
446
- parentReferencePath: string,
447
322
  referenceId: string,
448
323
  items: ParsedTopicModel[]
449
324
  ): NavItem[] {
@@ -451,37 +326,22 @@ export default class AmfReference extends LightningElement {
451
326
 
452
327
  items.forEach((item) => {
453
328
  item.methods?.forEach((method) => {
454
- const title =
455
- this.getTitleForLabel(method.label) || method.method;
456
- const meta = this.addToMetadata(
457
- parentReferencePath,
458
- referenceId,
459
- "method",
460
- method,
461
- title
462
- );
329
+ const meta = this.addToMetadata(referenceId, "method", method);
463
330
  methodList.push(
464
331
  Object.assign(method, {
465
- name: this.getReferencePathWithMeta(
466
- parentReferencePath,
467
- meta
468
- ),
469
- label: title
332
+ name: this.getReferencePathWithMeta(meta),
333
+ label:
334
+ this.getTitleForLabel(method.label) || method.method
470
335
  })
471
336
  );
472
337
  });
473
338
  });
339
+
474
340
  return methodList;
475
341
  }
476
342
 
477
- /**
478
- * Gives URL path for reference items, Which can be used to push to the history
479
- */
480
- private getReferencePathWithMeta(
481
- parentReferencePath: string,
482
- meta: string
483
- ): string {
484
- return meta ? `${parentReferencePath}?meta=${meta}` : "";
343
+ private getReferencePathWithMeta(meta: string): string {
344
+ return meta ? `${window.location.pathname}?meta=${meta}` : "";
485
345
  }
486
346
 
487
347
  /**
@@ -491,15 +351,12 @@ export default class AmfReference extends LightningElement {
491
351
  * The 'endpoint' nav item may have nested children.
492
352
  */
493
353
  private assignNavigationItemsFromAmf(
494
- amfConfig: AmfConfig,
354
+ referenceId: string,
495
355
  amfIdx: number
496
356
  ): void {
497
- const referenceId = amfConfig.id;
498
- const parentReferencePath = amfConfig.href;
499
357
  const model = this.amfMap[referenceId].parser.parsedModel;
500
358
 
501
359
  const children = [];
502
- const expandChildren = this.isExpandChildrenEnabled(referenceId);
503
360
 
504
361
  NAVIGATION_ITEMS.forEach(
505
362
  ({ label, name, childrenPropertyName, type }) => {
@@ -508,18 +365,13 @@ export default class AmfReference extends LightningElement {
508
365
  case "summary": {
509
366
  const summary = model[type];
510
367
  const meta = this.addToMetadata(
511
- parentReferencePath,
512
368
  referenceId,
513
369
  type,
514
- summary,
515
- label
370
+ summary
516
371
  );
517
372
  children.push({
518
373
  label,
519
- name: this.getReferencePathWithMeta(
520
- parentReferencePath,
521
- meta
522
- )
374
+ name: this.getReferencePathWithMeta(meta)
523
375
  });
524
376
  break;
525
377
  }
@@ -533,17 +385,15 @@ export default class AmfReference extends LightningElement {
533
385
  indexedName
534
386
  );
535
387
  const childTopics = this.assignEndpointNavItems(
536
- parentReferencePath,
537
388
  referenceId,
538
389
  model[childrenPropertyName]
539
390
  );
540
391
  children.push({
541
392
  label,
542
393
  name: this.getReferencePathWithMeta(
543
- parentReferencePath,
544
394
  this.metadata[amfTopicId]?.meta
545
395
  ),
546
- isExpanded: expandChildren,
396
+ isExpanded: false,
547
397
  children: childTopics
548
398
  });
549
399
  }
@@ -575,23 +425,19 @@ export default class AmfReference extends LightningElement {
575
425
  children.push({
576
426
  label,
577
427
  name: this.getReferencePathWithMeta(
578
- parentReferencePath,
579
428
  this.metadata[amfTopicId]?.meta
580
429
  ),
581
- isExpanded: expandChildren,
430
+ isExpanded: false,
582
431
  children: model[childrenPropertyName].map(
583
432
  (topic) => {
584
433
  const meta = this.addToMetadata(
585
- parentReferencePath,
586
434
  referenceId,
587
435
  type,
588
- topic,
589
- topic.label
436
+ topic
590
437
  );
591
438
  return {
592
439
  label: topic.label,
593
440
  name: this.getReferencePathWithMeta(
594
- parentReferencePath,
595
441
  meta
596
442
  )
597
443
  };
@@ -603,41 +449,46 @@ export default class AmfReference extends LightningElement {
603
449
  }
604
450
  );
605
451
 
606
- this.navigation[amfIdx] = {
607
- ...this.navigation[amfIdx],
608
- children,
609
- isChildrenLoading: false
452
+ // store nav items for each spec in order
453
+ this.navAmfOrder[amfIdx] = {
454
+ label: model.title,
455
+ name: this.getReferencePathWithMeta(`${referenceId}-root`),
456
+ isExpanded: amfIdx === 0, // only expand the first spec
457
+ children
610
458
  };
611
- this.navigation = [...this.navigation];
459
+
460
+ // update navigation with each specs nav items as they become available
461
+ // navigation has to be an array because dx-sidebar expects an array.
462
+ const navigation = [];
463
+ for (const navAmf of this.navAmfOrder) {
464
+ if (navAmf) {
465
+ navigation.push(navAmf);
466
+ }
467
+ }
468
+ this.navigation = navigation;
612
469
  }
613
470
 
614
471
  protected addToMetadata(
615
- parentReferencePath: string,
616
472
  referenceId: string,
617
473
  type: string,
618
- topic: { id: string; domId: string },
619
- navTitle: string
620
- ): string | undefined {
474
+ topic: { id: string; domId: string }
475
+ ): string {
621
476
  const { urlIdentifer, prefix } = URL_CONFIG[type];
622
477
 
623
478
  // encodeURI to avoid special characters in the URL meta.
624
479
  const identifier =
625
480
  topic[urlIdentifer] && this.encodeIdentifier(topic[urlIdentifer]);
626
- let meta;
627
- // Assuming that there will be an identifier always
628
- if (identifier) {
629
- meta = prefix ? `${prefix}${identifier}` : `${identifier}`;
630
- this.metadata[meta] = {
631
- parentReferencePath,
632
- meta,
633
- referenceId,
634
- amfId: topic.id,
635
- elementId: topic.domId,
636
- identifier,
637
- type,
638
- navTitle
639
- };
640
- }
481
+ const meta = prefix
482
+ ? `${referenceId}:${prefix}${identifier}`
483
+ : `${referenceId}:${identifier}`;
484
+ this.metadata[meta] = {
485
+ meta: meta,
486
+ referenceId: referenceId,
487
+ amfId: topic.id,
488
+ elementId: topic.domId,
489
+ identifier,
490
+ type
491
+ };
641
492
  return meta;
642
493
  }
643
494
 
@@ -696,25 +547,54 @@ export default class AmfReference extends LightningElement {
696
547
  }
697
548
 
698
549
  /**
699
- * Parses URL query params without decoding of params
550
+ * Parses url query params without decoding of params
700
551
  */
701
- private parseParams(params: string): qs.ParsedQuery<string> {
702
- if (!params) {
552
+ private parseParams(path: string): qs.ParsedQuery<string> {
553
+ if (!path) {
703
554
  return {};
704
555
  }
705
- return qs.parse(params, {
556
+ return qs.parse(path, {
706
557
  decode: false
707
558
  });
708
559
  }
709
560
 
561
+ /**
562
+ * Gets the portion from the URL query param 'meta'.
563
+ */
564
+ protected getCurrentRefMeta(
565
+ previousRefMetaInSession?: string
566
+ ): RouteMeta | null {
567
+ const path = window.location.search;
568
+ const urlParams = this.parseParams(path);
569
+ let meta = urlParams.meta as string;
570
+ let routeMeta = null;
571
+ if (previousRefMetaInSession) {
572
+ const refParts = previousRefMetaInSession.split(":");
573
+ const newRefId = refParts.length > 0 ? refParts[0] : null;
574
+ const [, type, topicId] = previousRefMetaInSession.split(":");
575
+ meta = newRefId ? [newRefId, type, topicId].join(":") : null;
576
+ } else if (!meta) {
577
+ // If no `meta` explicitly exists, check the URL hash to see whether this is one we
578
+ // want to redirect (see GUS W-10718771 for one reference where we want hash-based
579
+ // redirects)
580
+ const { hash } = window.location;
581
+ const strippedHash = hash.startsWith("#") ? hash.slice(1) : hash;
582
+ meta = urlHashToMetaRedirectMap[strippedHash];
583
+ }
584
+ if (meta) {
585
+ routeMeta = new RouteMeta(meta);
586
+ }
587
+ return routeMeta;
588
+ }
589
+
710
590
  /**
711
591
  * Normalizes topic identifier by replacing spaces with '+'
712
592
  * and running encodeURI() on it
713
- * @param identifier raw identifier for a topic as parsed from the spec file
593
+ * @param identifer raw identifer for a topic as parsed from the spec file
714
594
  * @returns normalized and encoded identifier
715
595
  */
716
- protected encodeIdentifier(identifier: string): string {
717
- let result = identifier.trim();
596
+ protected encodeIdentifier(identifer: string): string {
597
+ let result = identifer.trim();
718
598
  result = result.replace(new RegExp(/\s+/, "g"), "+");
719
599
  return encodeURI(result);
720
600
  }
@@ -726,130 +606,86 @@ export default class AmfReference extends LightningElement {
726
606
  return `${referenceId}:${id}`;
727
607
  }
728
608
 
729
- protected updateUrlWithSelected(
730
- parentReferencePath: string,
731
- meta?: string
732
- ): void {
609
+ protected updateSelectedItemFromUrlQuery(): void {
610
+ const currentMeta: RouteMeta | null = this.getCurrentRefMeta();
611
+ const metadata = currentMeta && this.getMetadataByUrlQuery(currentMeta);
612
+ if (metadata) {
613
+ const {
614
+ referenceId,
615
+ amfId,
616
+ type,
617
+ elementId
618
+ }: AmfMetadataTopic = metadata;
619
+ this.loadContent(
620
+ referenceId,
621
+ amfId,
622
+ type,
623
+ elementId,
624
+ currentMeta.meta
625
+ );
626
+ }
627
+ }
628
+ protected onApiNavigationChanged(): void {
629
+ // The API Navigation event will always intend to navigate within the current reference
630
+ const metadata = this.metadata[
631
+ this.getReferencePathWithMeta(this.selectedTopic.meta)
632
+ ];
633
+ const {
634
+ referenceId,
635
+ amfId,
636
+ type,
637
+ elementId
638
+ }: AmfMetadataTopic = metadata;
639
+ this.loadContent(referenceId, amfId, type, elementId, metadata.meta);
640
+ this.updateUrlWithSelected();
641
+ }
642
+
643
+ protected updateUrlWithSelected(meta?: string): void {
733
644
  if (meta) {
734
645
  window.history.pushState(
735
646
  {},
736
647
  "",
737
- `${parentReferencePath}?meta=${meta}`
648
+ `${window.location.pathname}?meta=${meta}`
738
649
  );
739
650
  }
740
651
  }
741
652
 
742
653
  /**
743
- * Does a replace on the URL meta, so it does not create a history entry.
654
+ * Does a replace on the url meta, so it does not create a history entry.
744
655
  */
745
- protected replaceUrlWithSelected(
746
- parentReferencePath: string,
747
- meta?: string
748
- ): void {
656
+ protected replaceUrlWithSelected(meta?: string): void {
749
657
  if (meta) {
750
658
  window.history.replaceState(
751
659
  {},
752
660
  "",
753
- `${parentReferencePath}?meta=${meta}`
661
+ `${window.location.pathname}?meta=${meta}`
754
662
  );
755
663
  }
756
664
  }
757
665
 
758
- /**
759
- * This method gets called when the user navigates back and forth using browser arrows
760
- * Updates content depending on the type of reference - spec based or markdown
761
- */
762
- protected updateSelectedItemFromUrlQuery(): void {
763
- const specBasedReference = this.isSpecBasedReference(
764
- this._currentReferenceId
765
- );
766
- if (specBasedReference) {
767
- const currentMeta: RouteMeta | null = this.getReferenceMetaInfo(
768
- window.location.href
769
- );
770
- const metadata =
771
- currentMeta && this.getMetadataByUrlQuery(currentMeta);
772
- if (metadata) {
773
- const {
774
- parentReferencePath,
775
- referenceId,
776
- amfId,
777
- type,
778
- elementId
779
- }: AmfMetadataTopic = metadata;
780
- this.loadSpecReferenceContent(
781
- parentReferencePath,
782
- referenceId,
783
- amfId,
784
- type,
785
- elementId,
786
- currentMeta.meta
787
- );
788
- }
789
- } else {
790
- this.loadMarkdownBasedReference();
791
- }
792
- }
793
-
794
- /**
795
- * The API Navigation event will always intend to navigate within the current reference
796
- * @param event
797
- */
798
- protected onApiNavigationChanged(): void {
799
- const specBasedReference = this.isSpecBasedReference(
800
- this._currentReferenceId
801
- );
802
- if (specBasedReference) {
803
- const { meta } = this.selectedTopic;
804
- const metadata = this.metadata[meta];
805
- if (metadata) {
806
- const {
807
- parentReferencePath,
808
- referenceId,
809
- amfId,
810
- type,
811
- elementId
812
- }: AmfMetadataTopic = metadata;
813
- this.loadSpecReferenceContent(
814
- parentReferencePath,
815
- referenceId,
816
- amfId,
817
- type,
818
- elementId,
819
- metadata.meta
820
- );
821
- }
822
- } else {
823
- this.loadMarkdownBasedReference();
824
- }
825
- }
826
-
827
666
  /**
828
667
  * Updates the currently selected amf and topic
829
668
  */
830
- protected loadSpecReferenceContent(
831
- parentReferencePath: string,
669
+ protected loadContent(
832
670
  referenceId: string,
833
671
  amfId: string,
834
672
  type: string,
835
- elementId: string,
836
- meta: string
673
+ elementId = "",
674
+ meta = ""
837
675
  ): void {
838
676
  this.selectedTopic = {
839
677
  referenceId,
840
- parentReferencePath,
841
678
  amfId,
842
679
  elementId,
843
680
  type,
844
681
  meta
845
682
  };
846
- this.selectedSidebarValue = this.getReferencePathWithMeta(
847
- parentReferencePath,
848
- meta
849
- );
683
+ this.selectedSidebarValue = this.getReferencePathWithMeta(meta);
850
684
 
851
685
  this.handleSelectedItem();
852
686
 
687
+ // Ensures that the URL always has the meta, that way we don't get two history entries for summary
688
+ this.replaceUrlWithSelected(meta);
853
689
  this.updateDocPhase();
854
690
  }
855
691
 
@@ -860,9 +696,10 @@ export default class AmfReference extends LightningElement {
860
696
  /* If parent level doc phase is enabled, Individual reference level doc phase should not be considered */
861
697
 
862
698
  if (!this.isParentLevelDocPhaseEnabled) {
863
- const selectedReference = this._amfConfigList.find(
699
+ const referenceId = this.selectedTopic?.referenceId;
700
+ const selectedReference = this._amfConfig.find(
864
701
  (referenceItem: AmfConfig) => {
865
- return referenceItem.id === this._currentReferenceId;
702
+ return referenceItem.id === referenceId;
866
703
  }
867
704
  );
868
705
  if (selectedReference) {
@@ -874,389 +711,88 @@ export default class AmfReference extends LightningElement {
874
711
  }
875
712
 
876
713
  /**
877
- * @returns meta query param from given Url
878
- */
879
- getMetaFromUrl(referenceUrl: string): string {
880
- const indexOfQueryParam = referenceUrl.indexOf("?");
881
- const urlPath = referenceUrl.substring(
882
- indexOfQueryParam >= 0 ? indexOfQueryParam : referenceUrl.length
883
- );
884
- return this.parseParams(urlPath).meta as string;
885
- }
886
-
887
- /**
888
- *
889
- * @returns meta for given markdown based referenceUrl
890
- * Consider last topic url in ../references/reference-name/example.html
891
- */
892
- getMarkdownReferenceMeta(referenceUrl: string): string {
893
- let meta = "";
894
- if (referenceUrl) {
895
- const slashSeparatorItems = referenceUrl.split("/");
896
- const lastItem =
897
- slashSeparatorItems[slashSeparatorItems.length - 1];
898
- if (lastItem.endsWith(".html")) {
899
- meta = lastItem;
900
- }
901
- }
902
- return meta;
903
- }
904
-
905
- /**
906
- *
907
- * @returns RouteMeta object for given referenceUrl
908
- * referenceId - gets referenceId from url
909
- * For spec based references gets meta parm from url and then topicId & type from meta
910
- * For markdown based references gets topicId as last html path in the name, meta & type will be empty
911
- */
912
- getReferenceMetaInfo(referenceUrl: string): RouteMeta | undefined {
913
- let metaReferenceInfo;
914
- if (referenceUrl) {
915
- const referenceId = this.getReferenceIdFromUrl(referenceUrl);
916
- let meta = "";
917
- let topicId = "";
918
- let type = "";
919
- if (this.isSpecBasedReference(referenceId)) {
920
- meta = this.getMetaFromUrl(referenceUrl);
921
- if (meta) {
922
- if (meta.includes(":")) {
923
- const metaInfo = meta.split(":");
924
- type = metaInfo[0];
925
- topicId = metaInfo[1] || type;
926
- } else {
927
- topicId = meta;
928
- }
929
- }
930
- } else {
931
- topicId = this.getMarkdownReferenceMeta(referenceUrl);
932
- }
933
- metaReferenceInfo = {
934
- referenceId,
935
- meta,
936
- topicId,
937
- type
938
- };
939
- }
940
- return metaReferenceInfo;
941
- }
942
-
943
- /**
944
- * Finds and returns referenceUrl and topicTitle if given topic url matches
945
- */
946
- getReferenceDetailsInGivenTopics(
947
- topics: ParsedMarkdownTopic[],
948
- topicMeta: string
949
- ): { referenceUrl: string; topicTitle: string } {
950
- let referenceUrl = "";
951
- let topicTitle = "";
952
- for (let i = 0; i < topics.length; i++) {
953
- const topic = topics[i];
954
- const meta = this.getMarkdownReferenceMeta(topic.link.href);
955
- const childTopics = topic.children;
956
- if (meta === topicMeta) {
957
- referenceUrl = topic.link.href;
958
- topicTitle = topic.label;
959
- } else if (childTopics && childTopics.length) {
960
- const referenceDetails = this.getReferenceDetailsInGivenTopics(
961
- childTopics,
962
- topicMeta
963
- );
964
- referenceUrl = referenceDetails.referenceUrl;
965
- topicTitle = referenceDetails.topicTitle;
966
- }
967
- if (referenceUrl && topicTitle) {
968
- break;
969
- }
970
- }
971
- return {
972
- referenceUrl,
973
- topicTitle
974
- };
975
- }
976
-
977
- /**
978
- * Gives referenceUrl and topicTitle for given markdown topic url
979
- */
980
- getRefDetailsForGivenTopicMeta(
981
- referenceId: string,
982
- topicMeta: string
983
- ): { referenceUrl: string; topicTitle: string } | undefined {
984
- const amfConfig = this.getAmfConfigWithId(referenceId);
985
- let referenceDetails;
986
- if (amfConfig) {
987
- const topics = amfConfig.topic?.children || [];
988
- referenceDetails = this.getReferenceDetailsInGivenTopics(
989
- topics,
990
- topicMeta
991
- );
992
- }
993
- return referenceDetails;
994
- }
995
-
996
- /**
997
- * Updates the DOM on the first load
714
+ * Updates the DOM on first load
998
715
  */
999
716
  updateView(): void {
1000
- const previousRefUrlInSession = window.sessionStorage.getItem(
1001
- this.docsReferenceUrlSessionKey
1002
- );
1003
- window.sessionStorage.removeItem(this.docsReferenceUrlSessionKey);
1004
- let previousRefInfo = this.getReferenceMetaInfo(
1005
- previousRefUrlInSession
1006
- );
1007
-
1008
- // For spec based reference, We should consider urlData to show same topic when user reloads after navigating to specific topic
1009
- if (!previousRefInfo) {
1010
- const currentUrl = window.location.href;
1011
- const urlReferenceId = this.getReferenceIdFromUrl(currentUrl);
1012
- if (urlReferenceId && this.isSpecBasedReference(urlReferenceId)) {
1013
- if (
1014
- !this.isProjectRootPath() &&
1015
- !this.isParentReferencePath(currentUrl)
1016
- ) {
1017
- previousRefInfo = this.getReferenceMetaInfo(currentUrl);
1018
- }
1019
- }
1020
- }
1021
-
1022
717
  let referenceId: string;
1023
718
  let topicId = "";
1024
-
1025
- if (
1026
- previousRefInfo &&
1027
- this._amfConfigMap.has(previousRefInfo.referenceId)
1028
- ) {
1029
- referenceId = previousRefInfo.referenceId;
1030
- topicId = previousRefInfo.topicId;
1031
- } else {
1032
- referenceId = this._currentReferenceId;
1033
- }
1034
-
1035
- const specBasedReference = this.isSpecBasedReference(referenceId);
1036
- if (specBasedReference) {
1037
- // Wait till the AMF is loaded.
1038
- this.amfFetchPromiseMap[referenceId].then(() => {
1039
- let selectedItemMetaData = this.getMetadataByIdentifier(
1040
- referenceId,
1041
- topicId
1042
- );
1043
- if (!selectedItemMetaData) {
1044
- // Doesn't exist, let's use the summary.
1045
- selectedItemMetaData = this.getMetadataByType(
1046
- referenceId,
1047
- "summary"
1048
- );
1049
- }
1050
-
1051
- if (selectedItemMetaData) {
1052
- this.loadSpecReferenceContent(
1053
- selectedItemMetaData.parentReferencePath,
1054
- selectedItemMetaData.referenceId,
1055
- selectedItemMetaData.amfId,
1056
- selectedItemMetaData.type,
1057
- "",
1058
- selectedItemMetaData.meta
1059
- );
1060
- this.updateUrlWithSelected(
1061
- selectedItemMetaData.parentReferencePath,
1062
- selectedItemMetaData.meta
1063
- );
1064
- this.updateNavTitleMetaTag(selectedItemMetaData.navTitle);
1065
- }
1066
- });
1067
- } else {
1068
- let invalidTopicReferenceUrl = "";
1069
- if (topicId) {
1070
- const referenceDetails = this.getRefDetailsForGivenTopicMeta(
1071
- referenceId,
1072
- topicId
1073
- );
1074
- const selectedItemUrl = referenceDetails?.referenceUrl;
1075
- if (!selectedItemUrl) {
1076
- invalidTopicReferenceUrl = previousRefUrlInSession;
1077
- }
1078
- }
1079
- if (!invalidTopicReferenceUrl) {
1080
- const referenceUrl = window.location.href;
1081
- const referenceMeta =
1082
- this.getMarkdownReferenceMeta(referenceUrl);
1083
- const selectedItemRefId =
1084
- this.getReferenceIdFromUrl(referenceUrl);
1085
- const referenceDetails = this.getRefDetailsForGivenTopicMeta(
1086
- selectedItemRefId,
1087
- referenceMeta
1088
- );
1089
- this.updateNavTitleMetaTag(referenceDetails.topicTitle);
719
+ const previousRefMetaInSession = window.sessionStorage.getItem(
720
+ this.docsReferenceMetaSessionKey
721
+ );
722
+ window.sessionStorage.removeItem(this.docsReferenceMetaSessionKey);
723
+ const currentMeta = this.getCurrentRefMeta(previousRefMetaInSession);
724
+ if (currentMeta) {
725
+ referenceId = currentMeta.referenceId;
726
+ topicId = currentMeta.topicId;
727
+ if (!this.amfFetchPromiseMap[referenceId]) {
728
+ // This could happen if they specify a bad query value.
729
+ // In this case, we'll do the logic below to use the default amf
730
+ referenceId = null;
1090
731
  }
1091
- this.loadMarkdownBasedReference(invalidTopicReferenceUrl);
1092
732
  }
1093
- }
1094
733
 
1095
- /**
1096
- * Navigates to reference of the given URL
1097
- * @param url
1098
- */
1099
- private loadNewReferenceItem(url: string): void {
1100
- const referenceId = this.getReferenceIdFromUrl(url);
1101
- const referenceItem = this.getAmfConfigWithId(referenceId);
1102
- if (referenceItem) {
1103
- window.location.href = referenceItem.href;
1104
- }
1105
- }
1106
-
1107
- /**
1108
- * @param referenceUrl to which user wants to navigate
1109
- * Redirect to first sub item if it's root level item, otherwise content will be loaded
1110
- * Push the history as a first child item
1111
- * set selected sidebar value as a pathname
1112
- */
1113
-
1114
- private loadMarkdownBasedReference(referenceUrl?: string): void {
1115
- let referenceId = "";
1116
- const currentUrl = window.location.href;
1117
- if (this.isProjectRootPath()) {
1118
- /**
1119
- * CASE1: This case is to consider when the user navigates to references by clicking a project card
1120
- * Ex: /docs/example-project/references should navigate to the first topic in the first reference
1121
- */
1122
- referenceId = this._currentReferenceId;
1123
- } else if (this.isParentReferencePath(referenceUrl)) {
1124
- /**
1125
- * CASE2: This case is to navigate to respective reference when the user clicked on root item
1126
- * Ex: .../references/markdown-ref should navigate to first topic.
1127
- */
1128
- referenceId = this.getReferenceIdFromUrl(referenceUrl);
1129
- } else if (this.isParentReferencePath(currentUrl)) {
1130
- /**
1131
- * CASE3: This case is to navigate to respective reference when the user entered url with reference id
1132
- * Ex: .../references/markdown-ref should navigate to first topic.
1133
- */
1134
- referenceId = this.getReferenceIdFromUrl(currentUrl);
1135
- } else if (referenceUrl) {
1136
- /**
1137
- * CASE4: This case is to navigate to first item when we don't have topic in the selected version
1138
- * Ex: .../references/markdown-ref/not-existed-topic-url should navigate to first topic.
1139
- */
1140
- const referenceMeta = this.getMarkdownReferenceMeta(referenceUrl);
1141
- const selectedItemRefId = this.getReferenceIdFromUrl(referenceUrl);
1142
- const referenceDetails = this.getRefDetailsForGivenTopicMeta(
1143
- selectedItemRefId,
1144
- referenceMeta
1145
- );
1146
- const selectedItemUrl = referenceDetails?.referenceUrl;
1147
- if (!selectedItemUrl) {
1148
- referenceId = this.getReferenceIdFromUrl(referenceUrl);
734
+ if (!referenceId) {
735
+ referenceId = this._amfConfig[0].id;
736
+ if (!this.amfFetchPromiseMap[referenceId]) {
737
+ // This should never happen.
738
+ referenceId = Object.keys(this.amfFetchPromiseMap)[0];
1149
739
  }
1150
740
  }
1151
741
 
1152
- if (referenceId) {
1153
- const amfConfig = this.getAmfConfigWithId(referenceId);
1154
- let redirectReferenceUrl = "";
1155
- if (amfConfig) {
1156
- const childrenItems = amfConfig.topic.children;
1157
- if (childrenItems.length > 0) {
1158
- redirectReferenceUrl = childrenItems[0].link.href;
1159
- }
742
+ // Wait till the AMF is loaded.
743
+ this.amfFetchPromiseMap[referenceId].then(() => {
744
+ let topic = this.getMetadataByIdentifier(referenceId, topicId);
745
+ if (!topic) {
746
+ // Doesn't exist, let's use the summary.
747
+ topic = this.getMetadataByType(referenceId, "summary");
1160
748
  }
1161
- if (redirectReferenceUrl) {
1162
- if (this.isParentReferencePath(referenceUrl)) {
1163
- // This is for CASE2 mentioned above, Where we need to navigate user to respective href
1164
- window.location.href = redirectReferenceUrl;
1165
- } else {
1166
- // This is for CASE 1,3 and 4 mentioned above, Where we need to update the browser history
1167
- window.history.replaceState({}, "", redirectReferenceUrl);
1168
- }
1169
- }
1170
- }
1171
749
 
1172
- this.versions = this.getVersions();
1173
-
1174
- this.updateDocPhase();
1175
- this.selectedSidebarValue = window.location.pathname;
750
+ if (topic) {
751
+ this.loadContent(
752
+ topic.referenceId,
753
+ topic.amfId,
754
+ topic.type,
755
+ "",
756
+ topic.meta
757
+ );
758
+ }
759
+ });
1176
760
  }
1177
761
 
1178
762
  /**
1179
- * Currently, used to handle the version change and store the current reference Url.
763
+ * Currently, used to handle the version change and storing the current meta query param to the session storage.
1180
764
  */
1181
765
  handleVersionChange(): void {
1182
- const currentUrl = window.location.href;
1183
- window.sessionStorage.setItem(
1184
- this.docsReferenceUrlSessionKey,
1185
- currentUrl
1186
- );
1187
- }
1188
-
1189
- private updateNavTitleMetaTag(navTitle = ""): void {
1190
- // this is required to update the nav title meta tag.
1191
- // eslint-disable-next-line @lwc/lwc/no-document-query
1192
- const metaNavTitle = document.querySelector('meta[name="nav-title"]');
1193
- if (metaNavTitle && navTitle) {
1194
- metaNavTitle.setAttribute("content", navTitle);
766
+ const path = window.location.search;
767
+ const urlParams = this.parseParams(path);
768
+ const meta = urlParams.meta as string;
769
+ if (meta) {
770
+ window.sessionStorage.setItem(
771
+ this.docsReferenceMetaSessionKey,
772
+ meta
773
+ );
1195
774
  }
1196
775
  }
1197
776
 
1198
777
  onNavSelect(event: CustomEvent): void {
1199
778
  const name = event.detail.name;
1200
- if (name) {
1201
- const urlReferenceId = this.getReferenceIdFromUrl(name);
1202
- const specBasedReference =
1203
- this.isSpecBasedReference(urlReferenceId);
1204
- if (specBasedReference) {
1205
- const metaVal = this.getMetaFromUrl(name);
1206
- const currentSelectedMeta = this.selectedTopic
1207
- ? this.selectedTopic.meta
1208
- : "";
1209
-
1210
- if (metaVal && metaVal === currentSelectedMeta) {
1211
- // selecting the same nav item, skip update
1212
- return;
1213
- }
779
+ const indexOfQueryParam = name.indexOf("?");
780
+ const urlPath = name.substring(
781
+ indexOfQueryParam >= 0 ? indexOfQueryParam : name.length
782
+ );
783
+ const metaVal = this.parseParams(urlPath).meta as string;
784
+ const currentSelectedMeta = this.selectedTopic.meta;
1214
785
 
1215
- const metadata = this.metadata[metaVal];
1216
- if (metadata) {
1217
- const {
1218
- parentReferencePath,
1219
- referenceId,
1220
- amfId,
1221
- type,
1222
- elementId
1223
- } = metadata;
1224
- this.loadSpecReferenceContent(
1225
- parentReferencePath,
1226
- referenceId,
1227
- amfId,
1228
- type,
1229
- elementId,
1230
- metaVal
1231
- );
1232
- this.updateUrlWithSelected(parentReferencePath, metaVal);
1233
- this.updateNavTitleMetaTag(metadata.navTitle);
1234
- } else {
1235
- if (this.isParentReferencePath(name)) {
1236
- this.loadNewReferenceItem(name);
1237
- }
1238
- }
1239
- } else {
1240
- this.loadMarkdownBasedReference(name);
1241
- }
786
+ if (metaVal === currentSelectedMeta) {
787
+ // selecting the same nav item, skip update
788
+ return;
1242
789
  }
1243
- }
1244
790
 
1245
- onExpandCollapse(event: CustomEvent): void {
1246
- const { name, isSelectAction, isExpanded } = event.detail;
1247
- if (!isSelectAction && isExpanded) {
1248
- const referenceId = this.getReferenceIdFromUrl(name);
1249
- const currentUrl = window.location.href;
1250
- const currentReferenceId = this.getReferenceIdFromUrl(currentUrl);
1251
- //No need to do anything if user is expanding currently selected reference
1252
- if (referenceId !== currentReferenceId) {
1253
- const isSpecBasedReference =
1254
- this.isSpecBasedReference(referenceId);
1255
- if (isSpecBasedReference) {
1256
- // Perform functionality same as item selection
1257
- this.onNavSelect(event);
1258
- }
1259
- }
791
+ const metadata = this.metadata[metaVal];
792
+ if (metadata) {
793
+ const { referenceId, amfId, type, elementId } = metadata;
794
+ this.loadContent(referenceId, amfId, type, elementId, metaVal);
795
+ this.updateUrlWithSelected(metaVal);
1260
796
  }
1261
797
  }
1262
798