@salesforcedevs/docs-components 0.0.0 → 0.0.1-superscript

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.
Files changed (83) hide show
  1. package/lwc.config.json +12 -2
  2. package/package.json +29 -27
  3. package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
  4. package/src/modules/doc/amfReference/amfReference.css +11 -3
  5. package/src/modules/doc/amfReference/amfReference.html +35 -26
  6. package/src/modules/doc/amfReference/amfReference.ts +239 -95
  7. package/src/modules/doc/amfReference/types.ts +3 -11
  8. package/src/modules/doc/amfTopic/amfTopic.css +20 -0
  9. package/src/modules/doc/amfTopic/amfTopic.ts +59 -18
  10. package/src/modules/doc/amfTopic/types.ts +15 -13
  11. package/src/modules/doc/amfTopic/utils.ts +12 -6
  12. package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +17 -10
  13. package/src/modules/doc/breadcrumbs/breadcrumbs.html +6 -9
  14. package/src/modules/doc/breadcrumbs/breadcrumbs.ts +30 -34
  15. package/src/modules/doc/componentPlayground/componentPlayground.css +30 -0
  16. package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
  17. package/src/modules/doc/componentPlayground/componentPlayground.ts +97 -0
  18. package/src/modules/doc/content/content.css +70 -76
  19. package/src/modules/doc/content/content.html +1 -0
  20. package/src/modules/doc/content/content.ts +24 -46
  21. package/src/modules/doc/contentCallout/contentCallout.css +11 -7
  22. package/src/modules/doc/contentCallout/contentCallout.html +11 -4
  23. package/src/modules/doc/contentCallout/contentCallout.ts +8 -1
  24. package/src/modules/doc/contentLayout/contentLayout.css +1 -98
  25. package/src/modules/doc/contentLayout/contentLayout.html +46 -31
  26. package/src/modules/doc/contentLayout/contentLayout.ts +337 -89
  27. package/src/modules/doc/contentMedia/contentMedia.css +1 -1
  28. package/src/modules/doc/doDont/doDont.css +47 -0
  29. package/src/modules/doc/doDont/doDont.html +27 -0
  30. package/src/modules/doc/doDont/doDont.ts +17 -0
  31. package/src/modules/doc/header/header.css +65 -36
  32. package/src/modules/doc/header/header.html +44 -138
  33. package/src/modules/doc/header/header.ts +62 -74
  34. package/src/modules/doc/heading/heading.css +16 -37
  35. package/src/modules/doc/heading/heading.html +4 -4
  36. package/src/modules/doc/heading/heading.ts +12 -10
  37. package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
  38. package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
  39. package/src/modules/doc/headingContent/headingContent.css +1 -1
  40. package/src/modules/doc/headingContent/headingContent.html +2 -2
  41. package/src/modules/doc/headingContent/headingContent.ts +2 -2
  42. package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +9 -0
  43. package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +64 -0
  44. package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +269 -0
  45. package/src/modules/doc/overview/overview.css +40 -0
  46. package/src/modules/doc/overview/overview.html +34 -0
  47. package/src/modules/doc/overview/overview.ts +12 -0
  48. package/src/modules/doc/phase/phase.css +11 -3
  49. package/src/modules/doc/phase/phase.html +12 -2
  50. package/src/modules/doc/phase/phase.ts +44 -8
  51. package/src/modules/doc/redocReference/redocReference.css +7 -0
  52. package/src/modules/doc/redocReference/redocReference.html +13 -0
  53. package/src/modules/doc/redocReference/redocReference.ts +425 -0
  54. package/src/modules/doc/specificationContent/specificationContent.css +36 -0
  55. package/src/modules/doc/specificationContent/specificationContent.html +177 -0
  56. package/src/modules/doc/specificationContent/specificationContent.ts +166 -0
  57. package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
  58. package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
  59. package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
  60. package/src/modules/doc/superscriptSubscript/superscriptSubscript.html +8 -0
  61. package/src/modules/doc/superscriptSubscript/superscriptSubscript.ts +16 -0
  62. package/src/modules/doc/toc/toc.html +1 -3
  63. package/src/modules/doc/toc/toc.ts +1 -1
  64. package/src/modules/doc/toolbar/toolbar.ts +6 -6
  65. package/src/modules/doc/versionPicker/versionPicker.css +64 -0
  66. package/src/modules/doc/versionPicker/versionPicker.html +40 -0
  67. package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
  68. package/src/modules/doc/xmlContent/types.ts +9 -3
  69. package/src/modules/doc/xmlContent/utils.ts +3 -1
  70. package/src/modules/doc/xmlContent/xmlContent.css +16 -4
  71. package/src/modules/doc/xmlContent/xmlContent.html +36 -21
  72. package/src/modules/doc/xmlContent/xmlContent.ts +295 -120
  73. package/src/modules/docHelpers/amfStyle/amfStyle.css +6 -8
  74. package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +162 -0
  75. package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
  76. package/src/modules/docHelpers/status/status.css +1 -1
  77. package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
  78. package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
  79. package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
  80. package/src/modules/docUtils/utils/utils.ts +32 -0
  81. package/LICENSE +0 -12
  82. package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
  83. package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +0 -39
@@ -2,8 +2,9 @@ import { LightningElement, api, track } from "lwc";
2
2
  import { noCase } from "no-case";
3
3
  import { sentenceCase } from "sentence-case";
4
4
  import qs from "query-string";
5
- import { AmfModelParser } from "./utils";
6
- import { normalizeBoolean } from "dxUtils/normalizers";
5
+ import { AmfModelParser } from "doc/amfModelParser";
6
+ import { normalizeBoolean, toJson } from "dxUtils/normalizers";
7
+ import type { OptionWithLink, Breadcrumb } from "typings/custom";
7
8
  import type {
8
9
  AmfConfig,
9
10
  AmfMetadataTopic,
@@ -25,19 +26,31 @@ import {
25
26
  REFERENCE_TYPES,
26
27
  oldReferenceIdNewReferenceIdMap
27
28
  } from "./constants";
29
+ import { restoreScroll } from "dx/scrollManager";
30
+ import { DocPhaseInfo } from "typings/custom";
31
+ import { oldVersionDocInfo } from "docUtils/utils";
32
+ import { track as trackEvent } from "dxUtils/analytics";
33
+
34
+ type NavigationItem = {
35
+ label: string;
36
+ name: string;
37
+ isExpanded: boolean;
38
+ children: ParsedMarkdownTopic[];
39
+ isChildrenLoading: boolean;
40
+ };
28
41
 
29
42
  export default class AmfReference extends LightningElement {
30
- @api breadcrumbs?: string | null | undefined = null;
43
+ @api breadcrumbs: string | null = null;
31
44
  @api sidebarHeader!: string;
32
- @api coveoOrganizationId!: string;
33
- @api coveoPublicAccessToken!: string;
34
- @api coveoAdvancedQueryConfig!: string;
35
- @api coveoSearchHub!: string;
36
- @api useOldSidebar?: boolean = false;
37
45
  @api tocTitle?: string;
38
46
  @api tocOptions?: string;
39
- @track navigation = [];
47
+ @api tocAriaLevel?: string;
48
+ @api languages!: OptionWithLink[];
49
+ @api language!: string;
50
+ @api hideFooter = false;
51
+ @track navigation = [] as NavigationItem[];
40
52
  @track versions: Array<ReferenceVersion> = [];
53
+ @track showVersionBanner = false;
41
54
 
42
55
  // Update this to update what component gets rendered in the content block
43
56
  @track
@@ -101,6 +114,16 @@ export default class AmfReference extends LightningElement {
101
114
  this.versions = this.getVersions();
102
115
  }
103
116
  this.selectedVersion = selectedVersion;
117
+ if (this.isSpecBasedReference(this._currentReferenceId)) {
118
+ this.isVersionFetched = true;
119
+ if (this.oldVersionInfo) {
120
+ this.showVersionBanner = true;
121
+ } else {
122
+ this.latestVersion = true;
123
+ }
124
+ }
125
+ } else {
126
+ this.isVersionFetched = true;
104
127
  }
105
128
 
106
129
  // This is to check if the url is hash based and redirect if needed
@@ -113,8 +136,8 @@ export default class AmfReference extends LightningElement {
113
136
  }
114
137
 
115
138
  @api
116
- get docPhaseInfo() {
117
- return this.selectedReferenceDocPhase;
139
+ get docPhaseInfo(): string | null {
140
+ return this.selectedReferenceDocPhase || null;
118
141
  }
119
142
 
120
143
  set docPhaseInfo(value: string) {
@@ -133,19 +156,30 @@ export default class AmfReference extends LightningElement {
133
156
  this._expandChildren = normalizeBoolean(value);
134
157
  }
135
158
 
159
+ private get enableFooter(): boolean {
160
+ return !this.hideFooter;
161
+ }
162
+
163
+ private get emptyStateMessage(): string {
164
+ return JSON.stringify([
165
+ "Select a relevant API specification",
166
+ "Please consider misspellings",
167
+ "Try different search keywords"
168
+ ]);
169
+ }
170
+
136
171
  // model
137
172
  protected _amfConfigList: AmfConfig[] = [];
138
173
  protected _amfConfigMap: Map<string, AmfConfig> = new Map();
139
174
  protected _referenceSetConfig!: ReferenceSetConfig;
140
175
  protected _currentReferenceId = "";
141
- protected _scrollInterval = 0;
142
176
 
143
- protected parentReferenceUrls = [];
177
+ protected parentReferenceUrls = [] as string[];
144
178
  protected amfMap: Record<string, AmfModelRecord> = {};
145
- protected amfFetchPromiseMap = {};
179
+ protected amfFetchPromiseMap = {} as any;
146
180
  protected metadata: { [key: string]: AmfMetadataTopic } = {};
147
181
  protected selectedTopic?: AmfMetaTopicType = undefined;
148
- protected selectedSidebarValue = undefined;
182
+ protected selectedSidebarValue: string | undefined = undefined;
149
183
 
150
184
  protected selectedVersion: ReferenceVersion | null = null;
151
185
 
@@ -154,6 +188,8 @@ export default class AmfReference extends LightningElement {
154
188
  private isParentLevelDocPhaseEnabled = false;
155
189
  private selectedReferenceDocPhase?: string | null = null;
156
190
  private _expandChildren?: boolean = false;
191
+ private isVersionFetched = false;
192
+ private latestVersion = false;
157
193
 
158
194
  /**
159
195
  * Key for storing the currently selected reference url. This will be used to save the
@@ -182,9 +218,6 @@ export default class AmfReference extends LightningElement {
182
218
  "popstate",
183
219
  this._boundUpdateSelectedItemFromUrlQuery
184
220
  );
185
- this._scrollInterval = window.setInterval(() => {
186
- this.saveScroll();
187
- }, 1000);
188
221
  }
189
222
 
190
223
  disconnectedCallback(): void {
@@ -196,20 +229,6 @@ export default class AmfReference extends LightningElement {
196
229
  "popstate",
197
230
  this._boundUpdateSelectedItemFromUrlQuery
198
231
  );
199
- window.clearInterval(this._scrollInterval);
200
- }
201
-
202
- saveScroll() {
203
- window.history.replaceState(
204
- { scrollValue: document.body.scrollTop },
205
- "",
206
- window.location.href
207
- );
208
- }
209
-
210
- restoreScroll() {
211
- document.body.scrollTop = document.documentElement.scrollTop =
212
- window.history.state?.scrollValue;
213
232
  }
214
233
 
215
234
  renderedCallback(): void {
@@ -299,6 +318,17 @@ export default class AmfReference extends LightningElement {
299
318
  return referenceId;
300
319
  }
301
320
 
321
+ private get oldVersionInfo(): DocPhaseInfo | null {
322
+ let info = null;
323
+ if (this.versions.length > 1 && this.selectedVersion) {
324
+ const currentGAVersionRef = this.versions[0];
325
+ if (this.selectedVersion.id !== currentGAVersionRef.id) {
326
+ info = oldVersionDocInfo(currentGAVersionRef.link.href);
327
+ }
328
+ }
329
+ return info;
330
+ }
331
+
302
332
  /**
303
333
  * @returns versions to be shown in the dropdown
304
334
  * For markdown based specs, Adds selected markdown topic url to same references
@@ -329,13 +359,13 @@ export default class AmfReference extends LightningElement {
329
359
  /**
330
360
  * Returns the selected version or the first available version.
331
361
  */
332
- private getSelectedVersion(): ReferenceVersion {
362
+ private getSelectedVersion(): ReferenceVersion | null {
333
363
  const versions = this._referenceSetConfig?.versions || [];
334
364
  const selectedVersion = versions.find(
335
365
  (v: ReferenceVersion) => v.selected
336
366
  );
337
367
  // return a selected version if there is one, else return the first one.
338
- return selectedVersion || (versions.length && versions[0]);
368
+ return selectedVersion || (versions.length && versions[0]) || null;
339
369
  }
340
370
 
341
371
  private updateAmfConfigInView(): void {
@@ -349,9 +379,11 @@ export default class AmfReference extends LightningElement {
349
379
  }
350
380
  }
351
381
 
352
- private async fetchAmf(amfConfig): Promise<AmfModel | AmfModel[]> {
382
+ private async fetchAmf(
383
+ amfConfig: AmfConfig
384
+ ): Promise<AmfModel | AmfModel[]> {
353
385
  const { amf } = amfConfig;
354
- const response = await fetch(amf, {
386
+ const response = await fetch(amf!, {
355
387
  headers: {
356
388
  "Cache-Control": `max-age=86400`
357
389
  }
@@ -370,7 +402,7 @@ export default class AmfReference extends LightningElement {
370
402
  /**
371
403
  * Returns whether given url is parent reference path like ../example-project/references/reference-id
372
404
  */
373
- private isParentReferencePath(urlPath: string): boolean {
405
+ private isParentReferencePath(urlPath?: string | null): boolean {
374
406
  if (!urlPath) {
375
407
  return false;
376
408
  }
@@ -401,9 +433,9 @@ export default class AmfReference extends LightningElement {
401
433
  * Populates reference Items from amfConfigList and assigns it to navigation for sidebar
402
434
  */
403
435
  private populateReferenceItems(): void {
404
- const navAmfOrder = [];
436
+ const navAmfOrder = [] as NavigationItem[];
405
437
  for (const [index, amfConfig] of this._amfConfigList.entries()) {
406
- let navItemChildren = [];
438
+ let navItemChildren = [] as ParsedMarkdownTopic[];
407
439
  let isChildrenLoading = false;
408
440
  if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
409
441
  if (amfConfig.isSelected) {
@@ -423,10 +455,10 @@ export default class AmfReference extends LightningElement {
423
455
  // check whether we should expand all the child nodes, this is required for Coveo to crawl.
424
456
  if (isExpandChildrenEnabled) {
425
457
  this.expandChildrenForMarkdownReferences(
426
- amfConfig.topic.children
458
+ amfConfig.topic!.children
427
459
  );
428
460
  }
429
- navItemChildren = amfConfig.topic.children;
461
+ navItemChildren = amfConfig.topic!.children;
430
462
  }
431
463
  // store nav items for each spec in order
432
464
  navAmfOrder[index] = {
@@ -447,7 +479,9 @@ export default class AmfReference extends LightningElement {
447
479
  * Returns a boolean indicating whether the children should be expanded or not.
448
480
  */
449
481
  private isExpandChildrenEnabled(referenceId: string): boolean {
450
- return this.expandChildren && this._currentReferenceId === referenceId;
482
+ return (
483
+ !!this.expandChildren && this._currentReferenceId === referenceId
484
+ );
451
485
  }
452
486
 
453
487
  /**
@@ -491,12 +525,12 @@ export default class AmfReference extends LightningElement {
491
525
  referenceId: string,
492
526
  items: ParsedTopicModel[]
493
527
  ): NavItem[] {
494
- const methodList = [];
528
+ const methodList = [] as NavItem[];
495
529
 
496
530
  items.forEach((item) => {
497
531
  item.methods?.forEach((method) => {
498
532
  const title =
499
- this.getTitleForLabel(method.label) || method.method;
533
+ this.getTitleForLabel(method.label!) || method.method;
500
534
  const meta = this.addToMetadata(
501
535
  parentReferencePath,
502
536
  referenceId,
@@ -544,7 +578,7 @@ export default class AmfReference extends LightningElement {
544
578
  const parentReferencePath = amfConfig.href;
545
579
  const model = this.amfMap[referenceId].parser.parsedModel;
546
580
 
547
- const children = [];
581
+ const children: any[] = [];
548
582
  const expandChildren = this.isExpandChildrenEnabled(referenceId);
549
583
 
550
584
  NAVIGATION_ITEMS.forEach(
@@ -571,8 +605,8 @@ export default class AmfReference extends LightningElement {
571
605
  }
572
606
  case "endpoint":
573
607
  if (
574
- model[childrenPropertyName] &&
575
- model[childrenPropertyName].length
608
+ model[childrenPropertyName!] &&
609
+ model[childrenPropertyName!].length
576
610
  ) {
577
611
  const amfTopicId = this.getFormattedIdentifier(
578
612
  referenceId,
@@ -581,7 +615,7 @@ export default class AmfReference extends LightningElement {
581
615
  const childTopics = this.assignEndpointNavItems(
582
616
  parentReferencePath,
583
617
  referenceId,
584
- model[childrenPropertyName]
618
+ model[childrenPropertyName!]
585
619
  );
586
620
  children.push({
587
621
  label,
@@ -596,23 +630,25 @@ export default class AmfReference extends LightningElement {
596
630
  break;
597
631
  case "security":
598
632
  case "type":
599
- if (model[childrenPropertyName]?.length) {
633
+ if (model[childrenPropertyName!]?.length) {
600
634
  // Sorting the types alphabetically
601
- model[childrenPropertyName].sort((typeA, typeB) => {
602
- const typeALbl = typeA.label.toLowerCase();
603
- const typeBLbl = typeB.label.toLowerCase();
604
- return typeALbl < typeBLbl
605
- ? -1
606
- : typeALbl > typeBLbl
607
- ? 1
608
- : 0;
609
- });
635
+ model[childrenPropertyName!].sort(
636
+ (typeA: any, typeB: any) => {
637
+ const typeALbl = typeA.label.toLowerCase();
638
+ const typeBLbl = typeB.label.toLowerCase();
639
+ return typeALbl < typeBLbl
640
+ ? -1
641
+ : typeALbl > typeBLbl
642
+ ? 1
643
+ : 0;
644
+ }
645
+ );
610
646
  }
611
647
  // eslint-disable-next-line no-fallthrough
612
648
  default:
613
649
  if (
614
- model[childrenPropertyName] &&
615
- model[childrenPropertyName].length
650
+ model[childrenPropertyName!] &&
651
+ model[childrenPropertyName!].length
616
652
  ) {
617
653
  const amfTopicId = this.getFormattedIdentifier(
618
654
  referenceId,
@@ -625,8 +661,8 @@ export default class AmfReference extends LightningElement {
625
661
  this.metadata[amfTopicId]?.meta
626
662
  ),
627
663
  isExpanded: expandChildren,
628
- children: model[childrenPropertyName].map(
629
- (topic) => {
664
+ children: model[childrenPropertyName!].map(
665
+ (topic: any) => {
630
666
  const meta = this.addToMetadata(
631
667
  parentReferencePath,
632
668
  referenceId,
@@ -663,12 +699,18 @@ export default class AmfReference extends LightningElement {
663
699
  type: string,
664
700
  topic: { id: string; domId: string },
665
701
  navTitle: string
666
- ): string | undefined {
667
- const { urlIdentifer, prefix } = URL_CONFIG[type];
702
+ ): string {
703
+ const config = URL_CONFIG[type as keyof typeof URL_CONFIG];
704
+ const urlIdentifer = config.urlIdentifer;
705
+ let prefix = null;
706
+ if ("prefix" in config) {
707
+ prefix = config.prefix;
708
+ }
668
709
 
669
710
  // encodeURI to avoid special characters in the URL meta.
670
711
  const identifier =
671
- topic[urlIdentifer] && this.encodeIdentifier(topic[urlIdentifer]);
712
+ urlIdentifer in topic &&
713
+ this.encodeIdentifier(topic[urlIdentifer as keyof typeof topic]);
672
714
  let meta;
673
715
  // Assuming that there will be an identifier always
674
716
  if (identifier) {
@@ -684,7 +726,7 @@ export default class AmfReference extends LightningElement {
684
726
  navTitle
685
727
  };
686
728
  }
687
- return meta;
729
+ return meta!;
688
730
  }
689
731
 
690
732
  /**
@@ -695,7 +737,7 @@ export default class AmfReference extends LightningElement {
695
737
  (metadata: AmfMetadataTopic) => {
696
738
  return routeMeta.meta === metadata.meta;
697
739
  }
698
- );
740
+ )!;
699
741
  }
700
742
 
701
743
  /**
@@ -709,7 +751,7 @@ export default class AmfReference extends LightningElement {
709
751
  return Object.values(this.metadata).find(
710
752
  (metadata: AmfMetadataTopic) =>
711
753
  referenceId === metadata.referenceId && amfId === metadata.amfId
712
- );
754
+ )!;
713
755
  }
714
756
 
715
757
  /**
@@ -724,7 +766,7 @@ export default class AmfReference extends LightningElement {
724
766
  (metadata: AmfMetadataTopic) =>
725
767
  referenceId === metadata.referenceId &&
726
768
  identifier === metadata.identifier
727
- );
769
+ )!;
728
770
  }
729
771
 
730
772
  /**
@@ -738,7 +780,7 @@ export default class AmfReference extends LightningElement {
738
780
  return Object.values(this.metadata).find(
739
781
  (metadata: AmfMetadataTopic) =>
740
782
  referenceId === metadata.referenceId && type === metadata.type
741
- );
783
+ )!;
742
784
  }
743
785
 
744
786
  /**
@@ -798,6 +840,7 @@ export default class AmfReference extends LightningElement {
798
840
  if (meta) {
799
841
  // update the encoded url meta param
800
842
  const encodedMeta = this.getUrlEncoded(meta);
843
+
801
844
  window.history.replaceState(
802
845
  window.history.state,
803
846
  "",
@@ -815,9 +858,8 @@ export default class AmfReference extends LightningElement {
815
858
  this._currentReferenceId
816
859
  );
817
860
  if (specBasedReference) {
818
- const currentMeta: RouteMeta | null = this.getReferenceMetaInfo(
819
- window.location.href
820
- );
861
+ const currentMeta: RouteMeta | undefined =
862
+ this.getReferenceMetaInfo(window.location.href);
821
863
  const metadata =
822
864
  currentMeta && this.getMetadataByUrlQuery(currentMeta);
823
865
  if (metadata) {
@@ -841,7 +883,7 @@ export default class AmfReference extends LightningElement {
841
883
  this.loadMarkdownBasedReference();
842
884
  }
843
885
 
844
- this.restoreScroll();
886
+ restoreScroll(); // don't try this at home kids
845
887
  }
846
888
 
847
889
  /**
@@ -849,13 +891,11 @@ export default class AmfReference extends LightningElement {
849
891
  * @param event
850
892
  */
851
893
  protected onApiNavigationChanged(): void {
852
- this.saveScroll();
853
-
854
894
  const specBasedReference = this.isSpecBasedReference(
855
895
  this._currentReferenceId
856
896
  );
857
897
  if (specBasedReference) {
858
- const { meta } = this.selectedTopic;
898
+ const { meta } = this.selectedTopic!;
859
899
  const metadata = this.metadata[meta];
860
900
  if (metadata) {
861
901
  const {
@@ -906,6 +946,16 @@ export default class AmfReference extends LightningElement {
906
946
  this.handleSelectedItem();
907
947
 
908
948
  this.updateDocPhase();
949
+
950
+ // Track page view when a new spec reference page is loaded
951
+ trackEvent(this.template.host, "doc_page_view", {
952
+ page_path: window.location.pathname + window.location.search,
953
+ reference_id: referenceId,
954
+ reference_type: "spec",
955
+ meta: meta,
956
+ topic_type: type,
957
+ article_name: this.getArticleName()
958
+ });
909
959
  }
910
960
 
911
961
  /**
@@ -970,7 +1020,7 @@ export default class AmfReference extends LightningElement {
970
1020
  * 1. If the url is encoded already
971
1021
  * 2. If the url is decoded
972
1022
  */
973
- getUrlEncoded(url: string) {
1023
+ getUrlEncoded(url: string): string {
974
1024
  // if url matches, then return the encoded url.
975
1025
  if (decodeURIComponent(url) === url) {
976
1026
  return encodeURIComponent(url);
@@ -986,7 +1036,7 @@ export default class AmfReference extends LightningElement {
986
1036
  * For spec based references gets meta parm from url and then topicId & type from meta
987
1037
  * For markdown based references gets topicId as last html path in the name, meta & type will be empty
988
1038
  */
989
- getReferenceMetaInfo(referenceUrl: string): RouteMeta | undefined {
1039
+ getReferenceMetaInfo(referenceUrl: string | null): RouteMeta | undefined {
990
1040
  let metaReferenceInfo;
991
1041
  if (referenceUrl) {
992
1042
  const referenceId = this.getReferenceIdFromUrl(referenceUrl);
@@ -1028,10 +1078,10 @@ export default class AmfReference extends LightningElement {
1028
1078
  let topicTitle = "";
1029
1079
  for (let i = 0; i < topics.length; i++) {
1030
1080
  const topic = topics[i];
1031
- const meta = this.getMarkdownReferenceMeta(topic.link.href);
1081
+ const meta = this.getMarkdownReferenceMeta(topic.link!.href);
1032
1082
  const childTopics = topic.children;
1033
1083
  if (meta === topicMeta) {
1034
- referenceUrl = topic.link.href;
1084
+ referenceUrl = topic.link!.href;
1035
1085
  topicTitle = topic.label;
1036
1086
  } else if (childTopics && childTopics.length) {
1037
1087
  const referenceDetails = this.getReferenceDetailsInGivenTopics(
@@ -1134,15 +1184,16 @@ export default class AmfReference extends LightningElement {
1134
1184
  "",
1135
1185
  selectedItemMetaData.meta
1136
1186
  );
1187
+
1137
1188
  this.updateUrlWithSelected(
1138
1189
  selectedItemMetaData.parentReferencePath,
1139
1190
  selectedItemMetaData.meta
1140
1191
  );
1141
- this.updateNavTitleMetaTag(selectedItemMetaData.navTitle);
1192
+ this.updateTags(selectedItemMetaData.navTitle);
1142
1193
  }
1143
1194
  });
1144
1195
  } else {
1145
- let invalidTopicReferenceUrl = "";
1196
+ let invalidTopicReferenceUrl: string | null = "";
1146
1197
  if (topicId) {
1147
1198
  const referenceDetails = this.getRefDetailsForGivenTopicMeta(
1148
1199
  referenceId,
@@ -1176,7 +1227,10 @@ export default class AmfReference extends LightningElement {
1176
1227
  * set selected sidebar value as a pathname
1177
1228
  */
1178
1229
 
1179
- private loadMarkdownBasedReference(referenceUrl?: string): void {
1230
+ private loadMarkdownBasedReference(referenceUrl?: string | null): void {
1231
+ // MILES TODO: figure out if we ever need to log a coveo page view in here
1232
+ // this would be the case if at some point we 'load' a new 'markdown based reference'
1233
+ // without actually triggering a page load
1180
1234
  let referenceId = "";
1181
1235
  const currentUrl = window.location.href;
1182
1236
  if (this.isProjectRootPath()) {
@@ -1190,7 +1244,7 @@ export default class AmfReference extends LightningElement {
1190
1244
  * CASE2: This case is to navigate to respective reference when the user clicked on root item
1191
1245
  * Ex: .../references/markdown-ref should navigate to first topic.
1192
1246
  */
1193
- referenceId = this.getReferenceIdFromUrl(referenceUrl);
1247
+ referenceId = this.getReferenceIdFromUrl(referenceUrl!);
1194
1248
  } else if (this.isParentReferencePath(currentUrl)) {
1195
1249
  /**
1196
1250
  * CASE3: This case is to navigate to respective reference when the user entered url with reference id
@@ -1219,9 +1273,9 @@ export default class AmfReference extends LightningElement {
1219
1273
  const amfConfig = this.getAmfConfigWithId(referenceId);
1220
1274
  let redirectReferenceUrl = "";
1221
1275
  if (amfConfig) {
1222
- const childrenItems = amfConfig.topic.children;
1276
+ const childrenItems = amfConfig.topic!.children;
1223
1277
  if (childrenItems.length > 0) {
1224
- redirectReferenceUrl = childrenItems[0].link.href;
1278
+ redirectReferenceUrl = childrenItems[0].link!.href;
1225
1279
  }
1226
1280
  }
1227
1281
  if (redirectReferenceUrl) {
@@ -1250,12 +1304,28 @@ export default class AmfReference extends LightningElement {
1250
1304
  referenceMeta
1251
1305
  );
1252
1306
  if (referenceDetails) {
1253
- this.updateNavTitleMetaTag(referenceDetails.topicTitle);
1307
+ this.updateTags(referenceDetails.topicTitle);
1254
1308
  }
1255
1309
 
1256
1310
  this.versions = this.getVersions();
1311
+ if (this.oldVersionInfo) {
1312
+ this.showVersionBanner = true;
1313
+ } else {
1314
+ this.latestVersion = true;
1315
+ }
1316
+
1317
+ this.isVersionFetched = true;
1257
1318
  this.updateDocPhase();
1258
1319
  this.selectedSidebarValue = window.location.pathname;
1320
+
1321
+ // Track page view when a new markdown reference page is loaded
1322
+ trackEvent(this.template.host, "doc_page_view", {
1323
+ page_path: window.location.pathname + window.location.search,
1324
+ reference_id: selectedItemRefId,
1325
+ reference_type: "markdown",
1326
+ topic_meta: referenceMeta,
1327
+ article_name: this.getArticleName()
1328
+ });
1259
1329
  }
1260
1330
  }
1261
1331
 
@@ -1270,18 +1340,66 @@ export default class AmfReference extends LightningElement {
1270
1340
  );
1271
1341
  }
1272
1342
 
1273
- private updateNavTitleMetaTag(navTitle = ""): void {
1343
+ handleDismissVersionBanner() {
1344
+ this.showVersionBanner = false;
1345
+ }
1346
+
1347
+ private updateTags(navTitle = ""): void {
1348
+ if (!navTitle) {
1349
+ return;
1350
+ }
1351
+
1274
1352
  // this is required to update the nav title meta tag.
1275
1353
  // eslint-disable-next-line @lwc/lwc/no-document-query
1276
1354
  const metaNavTitle = document.querySelector('meta[name="nav-title"]');
1277
- if (metaNavTitle && navTitle) {
1355
+ // eslint-disable-next-line @lwc/lwc/no-document-query
1356
+ const titleTag = document.querySelector("title");
1357
+ const TITLE_SEPARATOR = " | ";
1358
+
1359
+ if (metaNavTitle) {
1278
1360
  metaNavTitle.setAttribute("content", navTitle);
1279
1361
  }
1362
+
1363
+ /**
1364
+ * Right now, the title tag only changes when you pick a Ref spec,
1365
+ * not every time you choose a subsection of the Ref spec.
1366
+ * This update aims to refresh the title tag with each selection.
1367
+ * If a Ref spec is chosen, we add the value of the <selected topic> to the title.
1368
+ * If a subsection is selected, we update the first part of the current
1369
+ * title with the new <selected topic>.
1370
+ * Example: Following is a sample project structure.
1371
+ * - Project Name
1372
+ * - Ref Spec1
1373
+ * - Summary
1374
+ * - Endpoints
1375
+ * - E1
1376
+ * - E2
1377
+ * - Ref Spec2
1378
+ * - Summary
1379
+ * - Endpoints
1380
+ * - E1 (Selected)
1381
+ * - E2
1382
+ * Previous Title: Ref Spec2 | Project Name | Salesforce Developer
1383
+ * New Title: E1 | Ref Spec2 | Project Name | Salesforce Developer
1384
+ *
1385
+ */
1386
+ if (titleTag) {
1387
+ let titleTagValue = titleTag.textContent;
1388
+ const titleTagSectionValues: string[] =
1389
+ titleTagValue?.split(TITLE_SEPARATOR);
1390
+ if (titleTagSectionValues) {
1391
+ if (titleTagSectionValues.length <= 3) {
1392
+ titleTagValue = navTitle + TITLE_SEPARATOR + titleTagValue;
1393
+ } else {
1394
+ titleTagSectionValues[0] = navTitle;
1395
+ titleTagValue = titleTagSectionValues.join(TITLE_SEPARATOR);
1396
+ }
1397
+ }
1398
+ titleTag.textContent = titleTagValue;
1399
+ }
1280
1400
  }
1281
1401
 
1282
1402
  onNavSelect(event: CustomEvent): void {
1283
- this.saveScroll();
1284
-
1285
1403
  const name = event.detail.name;
1286
1404
  if (name) {
1287
1405
  const urlReferenceId = this.getReferenceIdFromUrl(name);
@@ -1315,8 +1433,9 @@ export default class AmfReference extends LightningElement {
1315
1433
  elementId,
1316
1434
  metaVal
1317
1435
  );
1436
+
1318
1437
  this.updateUrlWithSelected(parentReferencePath, metaVal);
1319
- this.updateNavTitleMetaTag(metadata.navTitle);
1438
+ this.updateTags(metadata.navTitle);
1320
1439
  } else {
1321
1440
  if (this.isParentReferencePath(name)) {
1322
1441
  this.loadNewReferenceItem(name);
@@ -1346,14 +1465,39 @@ export default class AmfReference extends LightningElement {
1346
1465
  }
1347
1466
  }
1348
1467
 
1468
+ private getArticleName(): string | undefined {
1469
+ if (!this.breadcrumbs) {
1470
+ return undefined;
1471
+ }
1472
+ try {
1473
+ const breadcrumbArray = toJson(this.breadcrumbs) as Breadcrumb[];
1474
+ if (Array.isArray(breadcrumbArray) && breadcrumbArray.length > 0) {
1475
+ // Join all breadcrumb labels with "/" to create article name
1476
+ // e.g., "Tooling API Objects/FieldDefinition"
1477
+ return breadcrumbArray.map((crumb) => crumb.label).join("/");
1478
+ }
1479
+ } catch (e) {
1480
+ // If parsing fails, return undefined
1481
+ }
1482
+ return undefined;
1483
+ }
1484
+
1349
1485
  handleSelectedItem(): void {
1350
1486
  // update topic view
1351
- const { referenceId, amfId, type } = this.selectedTopic;
1487
+ const { referenceId, amfId, type } = this.selectedTopic!;
1488
+
1489
+ // Adding stringify inside try/catch
1490
+ let amfModelString = "";
1491
+ try {
1492
+ amfModelString = JSON.stringify(this.amfMap[referenceId].model);
1493
+ } catch (error) {
1494
+ console.error(`Error stringifying amf model: ${error}`);
1495
+ }
1352
1496
 
1353
1497
  // This updates the component in the content section.
1354
1498
  this.topicModel = {
1355
1499
  type,
1356
- amf: this.amfMap[referenceId].model,
1500
+ amf: amfModelString,
1357
1501
  parser: this.amfMap[referenceId].parser,
1358
1502
  id: amfId
1359
1503
  };