@salesforcedevs/docs-components 1.3.2 → 1.3.4-alpha

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 (74) hide show
  1. package/lwc.config.json +8 -1
  2. package/package.json +13 -13
  3. package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
  4. package/src/modules/doc/amfReference/amfReference.css +23 -3
  5. package/src/modules/doc/amfReference/amfReference.html +34 -21
  6. package/src/modules/doc/amfReference/amfReference.ts +225 -92
  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 +35 -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 +7 -9
  14. package/src/modules/doc/breadcrumbs/breadcrumbs.ts +30 -34
  15. package/src/modules/doc/componentPlayground/componentPlayground.css +22 -0
  16. package/src/modules/doc/componentPlayground/componentPlayground.html +15 -0
  17. package/src/modules/doc/componentPlayground/componentPlayground.ts +20 -0
  18. package/src/modules/doc/content/content.css +70 -76
  19. package/src/modules/doc/content/content.ts +18 -14
  20. package/src/modules/doc/contentCallout/contentCallout.css +12 -1
  21. package/src/modules/doc/contentCallout/contentCallout.html +11 -4
  22. package/src/modules/doc/contentCallout/contentCallout.ts +8 -1
  23. package/src/modules/doc/contentLayout/contentLayout.css +1 -98
  24. package/src/modules/doc/contentLayout/contentLayout.html +25 -11
  25. package/src/modules/doc/contentLayout/contentLayout.ts +296 -89
  26. package/src/modules/doc/doDont/doDont.css +47 -0
  27. package/src/modules/doc/doDont/doDont.html +27 -0
  28. package/src/modules/doc/doDont/doDont.ts +17 -0
  29. package/src/modules/doc/header/header.css +65 -36
  30. package/src/modules/doc/header/header.html +40 -146
  31. package/src/modules/doc/header/header.ts +32 -81
  32. package/src/modules/doc/heading/heading.css +16 -37
  33. package/src/modules/doc/heading/heading.html +4 -4
  34. package/src/modules/doc/heading/heading.ts +12 -10
  35. package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
  36. package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
  37. package/src/modules/doc/headingContent/headingContent.css +1 -1
  38. package/src/modules/doc/headingContent/headingContent.html +2 -2
  39. package/src/modules/doc/headingContent/headingContent.ts +2 -2
  40. package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +1 -0
  41. package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +64 -0
  42. package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +168 -0
  43. package/src/modules/doc/overview/overview.css +40 -0
  44. package/src/modules/doc/overview/overview.html +34 -0
  45. package/src/modules/doc/overview/overview.ts +12 -0
  46. package/src/modules/doc/phase/phase.css +18 -3
  47. package/src/modules/doc/phase/phase.html +12 -2
  48. package/src/modules/doc/phase/phase.ts +44 -8
  49. package/src/modules/doc/specificationContent/specificationContent.css +31 -0
  50. package/src/modules/doc/specificationContent/specificationContent.html +164 -0
  51. package/src/modules/doc/specificationContent/specificationContent.ts +114 -0
  52. package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
  53. package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
  54. package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
  55. package/src/modules/doc/toc/toc.html +1 -3
  56. package/src/modules/doc/toc/toc.ts +1 -1
  57. package/src/modules/doc/toolbar/toolbar.ts +6 -6
  58. package/src/modules/doc/versionPicker/versionPicker.css +64 -0
  59. package/src/modules/doc/versionPicker/versionPicker.html +38 -0
  60. package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
  61. package/src/modules/doc/xmlContent/types.ts +9 -3
  62. package/src/modules/doc/xmlContent/utils.ts +3 -1
  63. package/src/modules/doc/xmlContent/xmlContent.css +25 -3
  64. package/src/modules/doc/xmlContent/xmlContent.html +29 -17
  65. package/src/modules/doc/xmlContent/xmlContent.ts +197 -75
  66. package/src/modules/docHelpers/amfStyle/amfStyle.css +6 -6
  67. package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +131 -0
  68. package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
  69. package/src/modules/docHelpers/status/status.css +1 -1
  70. package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
  71. package/src/modules/docUtils/utils/utils.ts +32 -0
  72. package/LICENSE +0 -12
  73. package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
  74. package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +0 -39
@@ -1,32 +1,45 @@
1
1
  <template>
2
2
  <doc-content-layout
3
- if:true={loaded}
3
+ lwc:if={loaded}
4
+ lwc:ref="docContentLayout"
4
5
  coveo-organization-id={coveoOrganizationId}
5
6
  coveo-public-access-token={coveoPublicAccessToken}
6
- coveo-search-hub="Developer_Docs_SS"
7
+ coveo-analytics-token={coveoAnalyticsToken}
8
+ coveo-search-hub={coveoSearchHub}
7
9
  coveo-advanced-query-config={coveoAdvancedQueryConfig}
8
- sidebar-header="Pages"
10
+ sidebar-header={docTitle}
9
11
  sidebar-content={sidebarContent}
10
12
  sidebar-value={sidebarValue}
11
13
  onselect={handleSelect}
12
14
  use-old-sidebar={useOldSidebar}
15
+ onlangchange={handleLanguageChange}
16
+ languages={sidebarFooterContent.languages}
17
+ language={sidebarFooterContent.language}
18
+ bail-href={sidebarFooterContent.bailHref}
19
+ bail-label={sidebarFooterContent.bailLabel}
20
+ show-footer={enableFooter}
13
21
  >
14
- <div slot="sidebar-header" class="document-pickers">
15
- <dx-dropdown
22
+ <doc-phase
23
+ slot="version-banner"
24
+ lwc:if={showVersionBanner}
25
+ doc-phase-info={oldVersionInfo}
26
+ icon-name="warning"
27
+ dismissible="true"
28
+ ondismissphase={handleDismissVersionBanner}
29
+ ></doc-phase>
30
+ <div lwc:if={showVersionPicker} slot="sidebar-header">
31
+ <doc-version-picker
16
32
  data-type="version"
17
- suppress-gtm-nav-headings
18
- analytics-event={analyticsEvent}
19
- options={versionOptions}
20
- value={version.id}
21
- width="290px"
22
- >
23
- <dx-button variant="inline" disabled={disableVersion}>
24
- {version.releaseVersion}
25
- </dx-button>
26
- </dx-dropdown>
33
+ analytics-event="custEv_ctaLinkClick"
34
+ analytics-payload={ANALYTICS_PAYLOAD}
35
+ versions={versionOptions}
36
+ selected-version={version}
37
+ latest-version={latestVersion}
38
+ hide-badge={previewVersion}
39
+ ></doc-version-picker>
27
40
  </div>
28
41
  <doc-breadcrumbs
29
- if:true={showBreadcrumbs}
42
+ lwc:if={showBreadcrumbs}
30
43
  breadcrumbs={breadcrumbs}
31
44
  pixel-per-character={breadcrumbPixelPerCharacter}
32
45
  ></doc-breadcrumbs>
@@ -34,7 +47,6 @@
34
47
  docs-data={docContent}
35
48
  page-reference={pageReference}
36
49
  onnavclick={handleNavClick}
37
- style={docContentStyle}
38
50
  ></doc-content>
39
51
  </doc-content-layout>
40
52
  </template>
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @lwc/lwc/no-document-query */
1
2
  import { api, track } from "lwc";
2
3
  import { normalizeBoolean } from "dxUtils/normalizers";
3
4
  import { FetchContent } from "./utils";
@@ -7,30 +8,43 @@ import {
7
8
  DocVersion,
8
9
  TreeNode,
9
10
  Header,
11
+ SiderbarFooter,
10
12
  HistoryState,
11
13
  PageReference,
12
14
  TocMap
13
15
  } from "./types";
14
- import { SearchSyncer } from "docUtils/SearchSyncer";
15
- import { LightningElementWithState } from "docBaseElements/lightningElementWithState";
16
- import { Breadcrumb, Language } from "typings/custom";
16
+ import { SearchSyncer } from "docUtils/searchSyncer";
17
+ import { LightningElementWithState } from "dxBaseElements/lightningElementWithState";
18
+ import { logCoveoPageView, oldVersionDocInfo } from "docUtils/utils";
19
+ import { Breadcrumb, DocPhaseInfo, Language } from "typings/custom";
20
+ import { track as trackGTM } from "dxUtils/analytics";
17
21
 
18
22
  // TODO: Imitating from actual implementation as doc-content use it like this. We should refactor it later.
19
- const handleContentError = (error): void => console.log(error);
23
+ const handleContentError = (error: any): void => console.log(error);
20
24
 
21
25
  const PIXEL_PER_CHARACTER_MAP: { [key: string]: number } = {
22
26
  default: 7.7,
23
27
  "ja-jp": 12.5
24
28
  };
25
29
 
30
+ const defaultSidebarFooter: SiderbarFooter = {
31
+ bailHref: "",
32
+ bailLabel: "",
33
+ languages: [],
34
+ language: ""
35
+ };
26
36
  export default class DocXmlContent extends LightningElementWithState<{
27
37
  isFetchingDocument: boolean;
28
38
  isFetchingContent: boolean;
29
39
  lastHighlightedSearch: string;
40
+ internalLinkClicked: boolean;
30
41
  }> {
31
42
  @api apiDomain = "https://developer.salesforce.com";
32
43
  @api coveoOrganizationId!: string;
33
44
  @api coveoPublicAccessToken!: string;
45
+ @api coveoAnalyticsToken!: string;
46
+ @api coveoSearchHub!: string;
47
+ @api hideFooter = false;
34
48
 
35
49
  @api
36
50
  get allLanguages(): Array<Language> {
@@ -53,21 +67,27 @@ export default class DocXmlContent extends LightningElementWithState<{
53
67
  }
54
68
 
55
69
  private availableLanguages: Array<DocLanguage> = [];
56
- private availableVersions: Array<DocVersion> = [];
57
- private contentProvider: FetchContent;
70
+ @track private availableVersions: Array<DocVersion> = [];
71
+ private contentProvider?: FetchContent;
58
72
  private docContent = "";
59
- private language: DocLanguage = null;
73
+ private language?: DocLanguage | null = null;
60
74
  private loaded = false;
75
+ private _pageHeader?: Header;
61
76
  private pdfUrl = "";
62
77
  private tocMap: TocMap = {};
63
- private sidebarContent: Array<TreeNode> = null;
64
- private version: DocVersion = null;
78
+ private sidebarContent: Array<TreeNode> | null = null;
79
+ private version: DocVersion | null = null;
65
80
  private docTitle = "";
66
- private analyticsEvent = "custEv_ctaLinkClick";
67
81
  private _pathName = "";
68
- private _pageHeader?: Header;
69
82
  private listenerAttached = false;
70
83
  private _enableCoveo?: boolean = false;
84
+ private sidebarFooterContent: SiderbarFooter = { ...defaultSidebarFooter };
85
+ private latestVersion = false;
86
+ private previewVersion = false;
87
+
88
+ private get enableFooter(): boolean {
89
+ return !this.hideFooter;
90
+ }
71
91
 
72
92
  private searchSyncer = new SearchSyncer({
73
93
  callbacks: {
@@ -107,6 +127,37 @@ export default class DocXmlContent extends LightningElementWithState<{
107
127
  });
108
128
  private _allLanguages: Array<Language> = [];
109
129
 
130
+ private get oldVersionInfo(): DocPhaseInfo | null {
131
+ let info = null;
132
+ if (!this.disableVersion) {
133
+ const currentGAVersion = this.versionOptions.find(
134
+ (version) => !version.url.includes(version.id)
135
+ );
136
+ if (currentGAVersion?.link?.href && this.version?.id) {
137
+ const versionNo = currentGAVersion.id;
138
+ /**
139
+ * Need to show old version doc banner only if the version is less than the current ga version
140
+ * We should not show it to the preview version whose version is more than ga
141
+ **/
142
+ try {
143
+ if (parseFloat(this.version.id) < parseFloat(versionNo)) {
144
+ info = oldVersionDocInfo(currentGAVersion.link.href);
145
+ } else if (
146
+ parseFloat(this.version.id) > parseFloat(versionNo)
147
+ ) {
148
+ this.previewVersion = true;
149
+ }
150
+ } catch (exception) {
151
+ /* Ideally this use case should not happen, but just added to not to break the page*/
152
+ console.warn(exception);
153
+ }
154
+ }
155
+ }
156
+ return info;
157
+ }
158
+
159
+ @track showVersionBanner = false;
160
+
110
161
  @track private pageReference: PageReference = {};
111
162
  @track breadcrumbs: Array<Breadcrumb> = [];
112
163
 
@@ -142,8 +193,8 @@ export default class DocXmlContent extends LightningElementWithState<{
142
193
  renderedCallback(): void {
143
194
  this.setState({ internalLinkClicked: true });
144
195
  const urlSectionLink =
145
- this.pageReference?.hash?.split("#").length > 1
146
- ? this.pageReference.hash.split("#")[1]
196
+ this.pageReference?.hash?.split("#").length! > 1
197
+ ? this.pageReference.hash!.split("#")[1]
147
198
  : this.pageReference?.hash;
148
199
 
149
200
  const contentEl = this.template.querySelector("doc-content");
@@ -156,6 +207,7 @@ export default class DocXmlContent extends LightningElementWithState<{
156
207
 
157
208
  if (anchorEl) {
158
209
  anchorEl.scrollIntoView();
210
+
159
211
  this.setState({ internalLinkClicked: false });
160
212
  }
161
213
 
@@ -181,24 +233,17 @@ export default class DocXmlContent extends LightningElementWithState<{
181
233
  disconnectedCallback(): void {
182
234
  window.removeEventListener("popstate", this.handlePopState);
183
235
  this.searchSyncer.dispose();
184
- if (this.listenerAttached) {
185
- this.pageHeader.removeEventListener(
186
- "langchange",
187
- this.handleLanguageChange
188
- );
189
- this.listenerAttached = false;
190
- }
191
236
  }
192
237
 
193
- private get languageId(): string {
194
- return this.language.id.replace("-", "_");
238
+ private get languageId(): string | undefined {
239
+ return this.language?.id.replace("-", "_");
195
240
  }
196
241
 
197
- private get releaseVersionId(): string {
198
- return this.version.id;
242
+ private get releaseVersionId(): string | undefined {
243
+ return this.version?.id;
199
244
  }
200
245
 
201
- private get deliverable(): string {
246
+ private get deliverable(): string | undefined {
202
247
  return this.pageReference.deliverable;
203
248
  }
204
249
 
@@ -219,7 +264,11 @@ export default class DocXmlContent extends LightningElementWithState<{
219
264
  }
220
265
 
221
266
  private get coveoAdvancedQueryConfig(): CoveoAdvancedQueryXMLConfig {
222
- const config: { locale: string; topicid: string; version?: string } = {
267
+ const config: {
268
+ locale?: string;
269
+ topicid?: string;
270
+ version?: string;
271
+ } = {
223
272
  locale: this.languageId,
224
273
  topicid: this.deliverable
225
274
  };
@@ -233,7 +282,7 @@ export default class DocXmlContent extends LightningElementWithState<{
233
282
 
234
283
  private get pageHeader(): Header {
235
284
  if (!this._pageHeader) {
236
- this._pageHeader = document.querySelector("doc-header");
285
+ this._pageHeader = document.querySelector("doc-header")!;
237
286
  }
238
287
 
239
288
  return this._pageHeader;
@@ -276,13 +325,24 @@ export default class DocXmlContent extends LightningElementWithState<{
276
325
 
277
326
  private get breadcrumbPixelPerCharacter() {
278
327
  return (
279
- PIXEL_PER_CHARACTER_MAP[this.language.id] ||
328
+ PIXEL_PER_CHARACTER_MAP[this.language!.id] ||
280
329
  PIXEL_PER_CHARACTER_MAP.default
281
330
  );
282
331
  }
283
332
 
284
- private handlePopState = (): void =>
285
- this.updatePageReference(this.getReferenceFromUrl());
333
+ private get ANALYTICS_PAYLOAD() {
334
+ return {
335
+ element_title: "version picker",
336
+ content_category: "cta"
337
+ };
338
+ }
339
+
340
+ private handlePopState = (event: PopStateEvent): void =>
341
+ this.updatePageReference(this.getReferenceFromUrl(), event);
342
+
343
+ handleDismissVersionBanner() {
344
+ this.showVersionBanner = false;
345
+ }
286
346
 
287
347
  handleSelect(event: CustomEvent<{ name: string }>): void {
288
348
  event.stopPropagation();
@@ -314,7 +374,7 @@ export default class DocXmlContent extends LightningElementWithState<{
314
374
  this.updateUrl();
315
375
  }
316
376
 
317
- handleLanguageChange = (event: CustomEvent<string>): Promise<void> => {
377
+ handleLanguageChange = (event: any) => {
318
378
  if (this.language && this.language.id === event.detail) {
319
379
  return;
320
380
  }
@@ -322,12 +382,26 @@ export default class DocXmlContent extends LightningElementWithState<{
322
382
  this.language = this.availableLanguages.find(
323
383
  ({ id }) => id === event.detail
324
384
  );
325
- this.pageReference.docId = this.language.url;
385
+ this.pageReference.docId = this.language!.url;
386
+
387
+ trackGTM(event.target!, "custEv_ctaLinkClick", {
388
+ click_text: event.detail,
389
+ element_title: "language selector",
390
+ click_url: `${window.location.origin}${this.pageReferenceToString(
391
+ this.pageReference
392
+ )}`,
393
+ element_type: "link",
394
+ content_category: "cta"
395
+ });
396
+
326
397
  this.updateUrl();
327
398
  this.fetchDocument();
328
399
  };
329
400
 
330
- updatePageReference(newPageReference: PageReference): void {
401
+ updatePageReference(
402
+ newPageReference: PageReference,
403
+ event: PopStateEvent | undefined = undefined
404
+ ): void {
331
405
  this.pageReference.hash = newPageReference.hash;
332
406
  this.pageReference.search = newPageReference.search;
333
407
 
@@ -344,7 +418,10 @@ export default class DocXmlContent extends LightningElementWithState<{
344
418
  }
345
419
 
346
420
  this.fetchContent()
347
- .then(() => this.buildBreadcrumbs())
421
+ .then(() => {
422
+ this.buildBreadcrumbs();
423
+ document.body.scrollTop = event?.state?.scroll?.value || 0;
424
+ })
348
425
  .catch(handleContentError);
349
426
  }
350
427
 
@@ -379,8 +456,9 @@ export default class DocXmlContent extends LightningElementWithState<{
379
456
  this.setState({
380
457
  isFetchingDocument: true
381
458
  });
382
- const data = await this.contentProvider.fetchDocumentData(
383
- this.pageReference.docId
459
+
460
+ const data = await this.contentProvider!.fetchDocumentData(
461
+ this.pageReference.docId!
384
462
  );
385
463
 
386
464
  // This could be a 404 scenario.
@@ -400,7 +478,7 @@ export default class DocXmlContent extends LightningElementWithState<{
400
478
  this.availableVersions = data.availableVersions;
401
479
  this.pdfUrl = data.pdfUrl;
402
480
 
403
- this.updateHeader();
481
+ this.updateHeaderAndSidebarFooter();
404
482
 
405
483
  this.buildBreadcrumbs();
406
484
 
@@ -409,6 +487,12 @@ export default class DocXmlContent extends LightningElementWithState<{
409
487
  this.updateUrl(HistoryState.REPLACE_STATE);
410
488
  }
411
489
 
490
+ if (this.oldVersionInfo) {
491
+ this.showVersionBanner = true;
492
+ } else {
493
+ this.latestVersion = true;
494
+ }
495
+
412
496
  if (
413
497
  this.pageReference?.contentDocumentId?.replace(/\.htm$/, "") !==
414
498
  data.id
@@ -438,12 +522,12 @@ export default class DocXmlContent extends LightningElementWithState<{
438
522
  this.setState({
439
523
  isFetchingContent: true
440
524
  });
441
- const data = await this.contentProvider.fetchContent(
442
- this.pageReference.deliverable,
443
- this.pageReference.contentDocumentId,
525
+ const data = await this.contentProvider!.fetchContent(
526
+ this.pageReference.deliverable!,
527
+ this.pageReference.contentDocumentId!,
444
528
  {
445
- language: this.language.id,
446
- version: this.version.id
529
+ language: this.language!.id,
530
+ version: this.version!.id
447
531
  }
448
532
  );
449
533
 
@@ -452,11 +536,7 @@ export default class DocXmlContent extends LightningElementWithState<{
452
536
  this.addMetatags();
453
537
 
454
538
  if (!this.pageReference.hash) {
455
- document.querySelector("main")?.scrollIntoView({
456
- behavior: "smooth",
457
- block: "start",
458
- inline: "nearest"
459
- });
539
+ document.body.scrollIntoView();
460
540
  }
461
541
  }
462
542
  this.setState({
@@ -464,7 +544,7 @@ export default class DocXmlContent extends LightningElementWithState<{
464
544
  });
465
545
  }
466
546
 
467
- updateHeader(): void {
547
+ updateHeaderAndSidebarFooter(): void {
468
548
  if (!this.pageHeader) {
469
549
  return;
470
550
  }
@@ -474,20 +554,12 @@ export default class DocXmlContent extends LightningElementWithState<{
474
554
  }
475
555
 
476
556
  if (this.pdfUrl) {
477
- this.pageHeader.bailHref = this.pdfUrl;
478
- this.pageHeader.bailLabel = "PDF";
557
+ this.sidebarFooterContent.bailHref = this.pdfUrl;
558
+ this.sidebarFooterContent.bailLabel = "PDF";
479
559
  }
480
560
 
481
- if (!this.listenerAttached) {
482
- this.pageHeader.addEventListener(
483
- "langchange",
484
- this.handleLanguageChange
485
- );
486
- this.listenerAttached = true;
487
- }
488
-
489
- this.pageHeader.languages = this.availableLanguages;
490
- this.pageHeader.language = this.language?.id;
561
+ this.sidebarFooterContent.languages = this.availableLanguages;
562
+ this.sidebarFooterContent.language = this.language?.id;
491
563
 
492
564
  if (this.pageReference) {
493
565
  const { docId, deliverable, page } = this.pageReference;
@@ -496,6 +568,7 @@ export default class DocXmlContent extends LightningElementWithState<{
496
568
  }
497
569
 
498
570
  updateUrl(method = HistoryState.PUSH_STATE): void {
571
+ logCoveoPageView(this.coveoOrganizationId, this.coveoAnalyticsToken);
499
572
  window.history[method](
500
573
  {},
501
574
  "docs",
@@ -511,23 +584,24 @@ export default class DocXmlContent extends LightningElementWithState<{
511
584
  }
512
585
 
513
586
  private updateSearchInput(searchParam: string): void {
514
- this.template
515
- .querySelector("doc-content-layout")
516
- ?.setSidebarInputValue(searchParam);
587
+ (this.refs.docContentLayout as any)?.setSidebarInputValue(searchParam);
517
588
  }
518
589
 
519
590
  private pageReferenceToString(reference: PageReference): string {
520
591
  const { page, docId, deliverable, contentDocumentId, hash, search } =
521
592
  reference;
522
593
  return `/${page}/${docId}/${deliverable}/${contentDocumentId}${this.normalizeSearch(
523
- search
594
+ search!
524
595
  )}${this.normalizeHash(hash)}`;
525
596
  }
526
597
 
527
- private normalizeUrlPart(part: string, sentinel: string): string {
598
+ private normalizeUrlPart(
599
+ part: string | undefined,
600
+ sentinel: string
601
+ ): string {
528
602
  return (
529
603
  (part &&
530
- (part.startsWith(sentinel) ? part : `${sentinel}${part}`)) ||
604
+ (part.startsWith(sentinel!) ? part : `${sentinel}${part}`)) ||
531
605
  ""
532
606
  );
533
607
  }
@@ -536,16 +610,16 @@ export default class DocXmlContent extends LightningElementWithState<{
536
610
  return this.normalizeUrlPart(search, "?");
537
611
  }
538
612
 
539
- private normalizeHash(hash: string): string {
613
+ private normalizeHash(hash?: string): string {
540
614
  return this.normalizeUrlPart(hash, "#");
541
615
  }
542
616
 
543
617
  private getComposedTitle(
544
- topicTitle: string | undefined,
618
+ topicTitle: string | null | undefined,
545
619
  docTitle: string | undefined
546
620
  ): string {
547
621
  // map to avoid duplicates
548
- const titleMap = {};
622
+ const titleMap: { [key: string]: any } = {};
549
623
  if (topicTitle) {
550
624
  // sometimes the h1 tag text (which is docSubTitle) contains text with new line character. For e.g, "Bulk API 2.0 Older\n Documentation",
551
625
  // here it contains \n in the text context which needs to be removed
@@ -580,10 +654,6 @@ export default class DocXmlContent extends LightningElementWithState<{
580
654
  return this.breadcrumbs && this.breadcrumbs.length > 1;
581
655
  }
582
656
 
583
- get docContentStyle(): string {
584
- return this.showBreadcrumbs ? "" : "margin-top: 48px";
585
- }
586
-
587
657
  private buildBreadcrumbs(): void {
588
658
  const { contentDocumentId } = this.pageReference;
589
659
  if (!contentDocumentId) {
@@ -615,6 +685,20 @@ export default class DocXmlContent extends LightningElementWithState<{
615
685
  return [item];
616
686
  }
617
687
 
688
+ // This method take docId and drops the version from the docId.
689
+ // Example:
690
+ // Takes input string: docId = "atlas.en-us.238.0.b2b_b2c_comm_dev.meta"
691
+ // Output string: filteredDocId = "atlas.en-us.b2b_b2c_comm_dev.meta"
692
+ dropVersionFromDocId(docId: string): string {
693
+ if (!this.version?.id) {
694
+ return docId;
695
+ }
696
+
697
+ const curVersion = this.version.id + ".";
698
+ const filteredDocId = docId.replace(curVersion, "");
699
+ return filteredDocId;
700
+ }
701
+
618
702
  addMetatags(): void {
619
703
  const div = document.createElement("div");
620
704
  div.innerHTML = this.docContent;
@@ -624,7 +708,7 @@ export default class DocXmlContent extends LightningElementWithState<{
624
708
  const title = document.querySelector("title");
625
709
  const composedTitle = this.getComposedTitle(topicTitle, this.docTitle);
626
710
 
627
- if (title) {
711
+ if (title && title.textContent) {
628
712
  title.textContent = composedTitle;
629
713
  }
630
714
  const metatitle = document.querySelector('meta[name="title"]');
@@ -646,14 +730,52 @@ export default class DocXmlContent extends LightningElementWithState<{
646
730
  'link[rel="canonical"]'
647
731
  );
648
732
  if (metadescription) {
733
+ const copyPageReference = { ...this.pageReference };
734
+ copyPageReference.docId = copyPageReference.docId
735
+ ? this.dropVersionFromDocId(copyPageReference.docId)
736
+ : copyPageReference.docId;
649
737
  metadescription.setAttribute(
650
738
  "href",
651
739
  window.location.protocol +
652
740
  "//" +
653
741
  window.location.host +
654
- this.pageReferenceToString(this.pageReference)
742
+ this.pageReferenceToString(copyPageReference)
655
743
  );
656
744
  }
657
745
  }
746
+
747
+ this.addNoIndexMetaForOlderDocVersions();
748
+ }
749
+
750
+ /**
751
+ * Method adds noindex, follow meta tag to the older Couch DB doc pages.
752
+ * Fixes W-12547462.
753
+ */
754
+ private addNoIndexMetaForOlderDocVersions() {
755
+ // eslint-disable-next-line @lwc/lwc/no-document-query
756
+ const headTag = document.getElementsByTagName("head");
757
+ // this checks if the selected version is not the latest version,
758
+ // then it adds the noindex, follow meta tag to the older version pages.
759
+ const versionId = this.version!.id;
760
+ const docId = this.pageReference.docId;
761
+
762
+ // SEO fix:
763
+ // Doc id without version id is always considered latest and should be used for SEO.
764
+ // Condition is to find a docId which includes version id,
765
+ // these docs are always considered as old and should not be indexed including the preview docs.
766
+ if (
767
+ headTag.length &&
768
+ docId?.includes(versionId) &&
769
+ !document.querySelector('meta[name="robots"]')
770
+ ) {
771
+ const robotsMeta = document.createElement("meta");
772
+ robotsMeta.setAttribute("name", "robots");
773
+ robotsMeta.setAttribute("content", "noindex, follow");
774
+ headTag[0].appendChild(robotsMeta);
775
+ }
776
+ }
777
+
778
+ private get showVersionPicker(): boolean {
779
+ return !this.disableVersion;
658
780
  }
659
781
  }
@@ -166,12 +166,12 @@ api-security-documentation {
166
166
  --anypoint-button-emphasis-high-active-background-color: transparent;
167
167
 
168
168
  /* api example */
169
- --api-example-accent-color: rgb(250, 250, 250);
170
- --api-example-background-color: rgb(250, 250, 250);
169
+ --api-example-accent-color: rgb(250 250 250);
170
+ --api-example-background-color: rgb(250 250 250);
171
171
  --api-example-title-background-color: transparent;
172
172
 
173
173
  /* code snippets */
174
- --http-code-snippet-container-background-color: rgb(250, 250, 250);
174
+ --http-code-snippet-container-background-color: rgb(250 250 250);
175
175
  --http-code-snippet-container-padding: var(--dx-g-spacing-md);
176
176
 
177
177
  /* prism */
@@ -208,7 +208,7 @@ api-endpoint-documentation {
208
208
  );
209
209
 
210
210
  /* description */
211
- --api-endpoint-documentation-description-color: rgb(24, 24, 24);
211
+ --api-endpoint-documentation-description-color: rgb(24 24 24);
212
212
  }
213
213
 
214
214
  api-endpoint-documentation,
@@ -271,11 +271,11 @@ api-method-documentation {
271
271
  --api-method-documentation-http-method-label-font-weight: var(
272
272
  --dx-g-font-bold
273
273
  );
274
- --api-method-documentation-description-color: rgb(24, 24, 24);
274
+ --api-method-documentation-description-color: rgb(24 24 24);
275
275
  --api-method-documentation-operation-id-color: var(--dx-g-gray-50);
276
276
 
277
277
  /* body */
278
- --api-body-document-description-color: rgb(24, 24, 24);
278
+ --api-body-document-description-color: rgb(24 24 24);
279
279
  --api-body-document-media-type-selector-color: var(--dx-g-blue-vibrant-20);
280
280
  --api-body-document-media-type-selector-font-size: var(
281
281
  --amf-h8-mod-font-size