@salesforcedevs/docs-components 0.56.1 → 0.56.2-seo-test1

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