@salesforcedevs/docs-components 1.27.21 → 1.27.22-banner10

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.
package/lwc.config.json CHANGED
@@ -6,6 +6,7 @@
6
6
  ],
7
7
  "expose": [
8
8
  "doc/amfReference",
9
+ "doc/banner",
9
10
  "doc/breadcrumbs",
10
11
  "doc/componentPlayground",
11
12
  "doc/content",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.27.21",
3
+ "version": "1.27.22-banner10",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -25,5 +25,5 @@
25
25
  "@types/lodash.orderby": "4.6.9",
26
26
  "@types/lodash.uniqby": "4.7.9"
27
27
  },
28
- "gitHead": "bb47c49e52267b9068ff826a16f39364f49e3086"
28
+ "gitHead": "c74a086b4b41bf4d36f01c89feb97d0360dcf97f"
29
29
  }
@@ -0,0 +1,211 @@
1
+ @import "dxHelpers/reset";
2
+ @import "dxHelpers/text";
3
+
4
+ :host {
5
+ display: block;
6
+
7
+ --doc-banner-bg: var(--neutral-90, #e5e5e5);
8
+ --doc-banner-height: 44px;
9
+ --doc-banner-padding-x-left: 40px;
10
+ --doc-banner-padding-x-right: var(--dx-g-spacing-lg);
11
+ --doc-banner-icon-size: 18.4615px;
12
+ --doc-banner-icon-frame-width: calc(
13
+ var(--doc-banner-padding-x-left) + var(--doc-banner-icon-size) +
14
+ var(--dx-g-spacing-sm)
15
+ );
16
+ --doc-banner-close-color: #747474;
17
+ --doc-banner-primary-bg: #0176d3;
18
+ --doc-banner-primary-bg-hover: #0160b3;
19
+ }
20
+
21
+ .doc-notification-bar {
22
+ display: flex;
23
+ align-items: flex-start;
24
+ justify-content: space-between;
25
+ width: 100%;
26
+ margin: 0;
27
+ min-height: var(--doc-banner-height);
28
+ padding: 0 var(--doc-banner-padding-x-right) 0
29
+ var(--doc-banner-padding-x-left);
30
+ background: var(--doc-banner-bg);
31
+ box-sizing: border-box;
32
+ }
33
+
34
+ .doc-notification-bar .icon-wrap,
35
+ .doc-notification-bar .main,
36
+ .doc-notification-bar .content,
37
+ .doc-notification-bar .actions,
38
+ .doc-notification-bar .close-wrap {
39
+ display: flex;
40
+ align-items: center;
41
+ }
42
+
43
+ .doc-notification-bar .icon-wrap,
44
+ .doc-notification-bar .close-wrap {
45
+ flex-shrink: 0;
46
+ }
47
+
48
+ .doc-notification-bar .main {
49
+ flex: 1 1 0;
50
+ min-width: 0;
51
+ align-self: flex-start;
52
+ padding: 6px 0;
53
+ gap: var(--dx-g-spacing-md);
54
+ }
55
+
56
+ .doc-notification-bar .icon-wrap {
57
+ width: calc(var(--doc-banner-icon-size) + var(--dx-g-spacing-sm));
58
+ min-height: 32px;
59
+ align-self: flex-start;
60
+ justify-content: flex-start;
61
+ align-items: flex-start;
62
+ }
63
+
64
+ .doc-notification-bar .icon-wrap dx-icon {
65
+ --dx-c-icon-size: var(--doc-banner-icon-size);
66
+
67
+ width: var(--doc-banner-icon-size);
68
+ height: var(--doc-banner-icon-size);
69
+ padding: 12px 8px 0 0;
70
+ box-sizing: content-box;
71
+ }
72
+
73
+ .doc-notification-bar .content {
74
+ flex: 0 1 auto;
75
+ min-width: 0;
76
+ max-width: 100%;
77
+ min-height: 32px;
78
+ align-items: flex-start;
79
+ gap: var(--dx-g-spacing-sm);
80
+ }
81
+
82
+ .doc-notification-bar .message {
83
+ margin: 0;
84
+ padding: 6px 0;
85
+ font-size: 14px;
86
+ font-weight: 400;
87
+ line-height: 20px;
88
+ color: var(--dx-g-neutral-30, #444);
89
+ }
90
+
91
+ .doc-notification-bar .message a {
92
+ color: var(--dx-g-cloud-blue-vibrant-50);
93
+ text-decoration: underline;
94
+ }
95
+
96
+ .doc-notification-bar .message a:hover {
97
+ opacity: 0.9;
98
+ }
99
+
100
+ .doc-notification-bar .actions {
101
+ flex-shrink: 0;
102
+ min-height: 32px;
103
+ gap: var(--dx-g-spacing-smd);
104
+ flex-wrap: wrap;
105
+ }
106
+
107
+ .doc-notification-bar .primary-btn {
108
+ --dx-c-button-primary-color: var(--doc-banner-primary-bg);
109
+ --dx-c-button-primary-color-hover: var(--doc-banner-primary-bg-hover);
110
+ --dx-c-button-vertical-spacing: 0;
111
+ --dx-c-button-horizontal-spacing: var(--dx-g-spacing-md);
112
+
113
+ min-width: min(144px, 100%);
114
+ height: 32px;
115
+ border-radius: var(--dx-g-spacing-xs);
116
+ }
117
+
118
+ .doc-notification-bar .primary-btn::part(container) {
119
+ min-width: min(144px, 100%);
120
+ width: 100%;
121
+ height: 32px;
122
+ padding: 0 var(--dx-g-spacing-md);
123
+ border-radius: var(--dx-g-spacing-xs);
124
+ }
125
+
126
+ .doc-notification-bar .secondary-btn {
127
+ font-weight: var(--dx-g-font-normal);
128
+ }
129
+
130
+ .doc-notification-bar .close-wrap {
131
+ align-self: flex-start;
132
+ justify-content: center;
133
+ align-items: center;
134
+ width: 52px;
135
+ height: 44px;
136
+ padding: 12px 8px 18px;
137
+ margin-left: auto;
138
+ box-sizing: border-box;
139
+ }
140
+
141
+ .doc-notification-bar .close-wrap .close-btn {
142
+ width: 100%;
143
+ height: 100%;
144
+
145
+ --dx-c-button-custom-color: var(--doc-banner-close-color);
146
+ --dx-c-button-custom-color-hover: var(--doc-banner-close-color);
147
+ --dx-c-button-custom-background: transparent;
148
+ --dx-c-button-custom-background-hover: rgb(0 0 0 / 5%);
149
+ --dx-c-button-custom-border: none;
150
+ --dx-c-button-custom-border-hover: none;
151
+ }
152
+
153
+ @media (max-width: 1279px) {
154
+ :host {
155
+ --doc-banner-padding-x-left: 32px;
156
+ --doc-banner-padding-x-right: var(--dx-g-spacing-md);
157
+ }
158
+
159
+ .doc-notification-bar {
160
+ position: relative;
161
+ max-width: 100%;
162
+ min-height: 78px;
163
+ flex-wrap: wrap;
164
+ align-content: space-between;
165
+ padding: 0 var(--doc-banner-padding-x-right) 0 0;
166
+ }
167
+
168
+ .doc-notification-bar .icon-wrap {
169
+ position: absolute;
170
+ left: 0;
171
+ top: 0;
172
+ bottom: 0;
173
+ width: var(--doc-banner-icon-frame-width);
174
+ min-height: 0;
175
+ padding: 0 0 0 var(--doc-banner-padding-x-left);
176
+ order: 0;
177
+ }
178
+
179
+ .doc-notification-bar .main {
180
+ order: 1;
181
+ flex-wrap: wrap;
182
+ margin-left: var(--doc-banner-icon-frame-width);
183
+ gap: var(--dx-g-spacing-2xs);
184
+ }
185
+
186
+ .doc-notification-bar .content {
187
+ order: 0;
188
+ }
189
+
190
+ .doc-notification-bar .close-wrap {
191
+ order: 2;
192
+ min-height: 44px;
193
+ }
194
+
195
+ .doc-notification-bar .actions {
196
+ order: 1;
197
+ flex: 0 0 100%;
198
+ width: 100%;
199
+ }
200
+ }
201
+
202
+ @media (max-width: 768px) {
203
+ :host {
204
+ --doc-banner-padding-x-left: 24px;
205
+ --doc-banner-padding-x-right: var(--dx-g-spacing-sm);
206
+ }
207
+
208
+ .doc-notification-bar {
209
+ min-height: 44px;
210
+ }
211
+ }
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <template lwc:if={showBanner}>
3
+ <div class="doc-notification-bar" part="container">
4
+ <div class="icon-wrap" part="icon-wrap">
5
+ <dx-icon symbol="info" part="icon" color="#747474"></dx-icon>
6
+ </div>
7
+ <div class="main" part="main">
8
+ <div class="content" part="content">
9
+ <p class="message dx-text-body-4" part="message">
10
+ <template lwc:if={messageText}>{messageText}</template>
11
+ <template lwc:if={hasMessageLink}>
12
+ <a
13
+ href={messageLinkUrl}
14
+ target="_blank"
15
+ rel="noopener noreferrer"
16
+ part="message-link"
17
+ >
18
+ {messageLinkText}
19
+ </a>
20
+ </template>
21
+ </p>
22
+ </div>
23
+ <div class="actions" part="actions">
24
+ <template lwc:if={hasPrimaryButton}>
25
+ <dx-button
26
+ class="primary-btn"
27
+ href={buttonHref}
28
+ variant="primary"
29
+ size="small"
30
+ part="button"
31
+ >
32
+ {buttonLabel}
33
+ </dx-button>
34
+ </template>
35
+ <template lwc:if={hasSecondaryAction}>
36
+ <dx-button
37
+ class="secondary-btn"
38
+ variant="inline"
39
+ onclick={handleSecondaryClick}
40
+ part="secondary"
41
+ >
42
+ {secondaryLabel}
43
+ </dx-button>
44
+ </template>
45
+ </div>
46
+ </div>
47
+ <template lwc:if={showCloseButton}>
48
+ <div class="close-wrap" part="close-wrap">
49
+ <dx-button
50
+ class="close-btn"
51
+ variant="icon-only"
52
+ icon-symbol="close"
53
+ icon-color="#747474"
54
+ aria-label="Close"
55
+ onclick={handleCloseClick}
56
+ part="close"
57
+ ></dx-button>
58
+ </div>
59
+ </template>
60
+ </div>
61
+ </template>
62
+ </template>
@@ -0,0 +1,92 @@
1
+ import { LightningElement, api, track } from "lwc";
2
+ import { normalizeBoolean } from "dxUtils/normalizers";
3
+
4
+ const LOCALE_BANNER_STORAGE_PREFIX = "dsc-doc-locale-banner-dismissed-";
5
+
6
+ export default class Banner extends LightningElement {
7
+ @api messageText = "";
8
+
9
+ @api messageLinkUrl = "";
10
+
11
+ @api messageLinkText = "here";
12
+
13
+ @api buttonLabel = "";
14
+
15
+ @api buttonHref = "";
16
+
17
+ @api secondaryLabel = "";
18
+
19
+ @api dismissStorageKey = "";
20
+
21
+ _showCloseButton = false;
22
+
23
+ @api
24
+ get showCloseButton(): boolean {
25
+ return this._showCloseButton;
26
+ }
27
+ set showCloseButton(value: string | boolean) {
28
+ this._showCloseButton = normalizeBoolean(value);
29
+ }
30
+
31
+ @track private _dismissed = false;
32
+
33
+ connectedCallback() {
34
+ if (
35
+ this.dismissStorageKey &&
36
+ typeof window !== "undefined" &&
37
+ window.sessionStorage
38
+ ) {
39
+ this._dismissed =
40
+ window.sessionStorage.getItem(
41
+ `${LOCALE_BANNER_STORAGE_PREFIX}${this.dismissStorageKey}`
42
+ ) === "true";
43
+ }
44
+ }
45
+
46
+ get showBanner(): boolean {
47
+ if (!this.dismissStorageKey) {
48
+ return true;
49
+ }
50
+ return !this._dismissed;
51
+ }
52
+
53
+ get hasMessageLink(): boolean {
54
+ return !!this.messageLinkUrl;
55
+ }
56
+
57
+ get hasPrimaryButton(): boolean {
58
+ return !!(this.buttonLabel && this.buttonHref);
59
+ }
60
+
61
+ get hasSecondaryAction(): boolean {
62
+ return !!this.secondaryLabel;
63
+ }
64
+
65
+ persistDismissAndHide() {
66
+ if (
67
+ this.dismissStorageKey &&
68
+ typeof window !== "undefined" &&
69
+ window.sessionStorage
70
+ ) {
71
+ window.sessionStorage.setItem(
72
+ `${LOCALE_BANNER_STORAGE_PREFIX}${this.dismissStorageKey}`,
73
+ "true"
74
+ );
75
+ }
76
+ this._dismissed = true;
77
+ }
78
+
79
+ handleSecondaryClick() {
80
+ this.persistDismissAndHide();
81
+ this.dispatchEvent(
82
+ new CustomEvent("dismiss", { bubbles: true, composed: true })
83
+ );
84
+ }
85
+
86
+ handleCloseClick() {
87
+ this.persistDismissAndHide();
88
+ this.dispatchEvent(
89
+ new CustomEvent("dismiss", { bubbles: true, composed: true })
90
+ );
91
+ }
92
+ }
@@ -17,6 +17,9 @@
17
17
  <slot name="sidebar-header" slot="version-picker"></slot>
18
18
  </dx-sidebar-old>
19
19
  <div class="content-body-doc-phase-container">
20
+ <div class="locale-notification-wrapper">
21
+ <slot name="locale-banner"></slot>
22
+ </div>
20
23
  <div class="doc-phase-wrapper">
21
24
  <slot name="doc-phase"></slot>
22
25
  </div>
@@ -268,6 +268,9 @@ export default class ContentLayout extends LightningElement {
268
268
  ".sticky-doc-header"
269
269
  ) as HTMLElement;
270
270
 
271
+ const localeBannerWrapper = this.template.querySelector(
272
+ ".locale-notification-wrapper"
273
+ ) as HTMLElement;
271
274
  const docPhaseWrapper = this.template.querySelector(
272
275
  ".doc-phase-wrapper"
273
276
  ) as HTMLElement;
@@ -275,6 +278,12 @@ export default class ContentLayout extends LightningElement {
275
278
  ".version-wrapper"
276
279
  ) as HTMLElement;
277
280
 
281
+ const localeBannerSlot = localeBannerWrapper?.querySelector(
282
+ "[name=locale-banner]"
283
+ ) as HTMLSlotElement | null;
284
+ const localeBannerEl = localeBannerSlot?.assignedElements?.()[0] as
285
+ | HTMLElement
286
+ | undefined;
278
287
  const docPhaseEl = (
279
288
  docPhaseWrapper.querySelector("[name=doc-phase]")! as any
280
289
  ).assignedElements()[0] as HTMLSlotElement;
@@ -297,6 +306,12 @@ export default class ContentLayout extends LightningElement {
297
306
  const docHeaderHeight = docHeaderEl.getBoundingClientRect().height;
298
307
  const totalHeaderHeight = globalNavHeight + docHeaderHeight;
299
308
 
309
+ const localeBannerHeight = localeBannerEl?.offsetHeight ?? 0;
310
+ const docPhaseElHeight =
311
+ (docPhaseEl?.getBoundingClientRect?.()?.height ?? 0) +
312
+ (verBannerEl?.getBoundingClientRect?.()?.height ?? 0);
313
+ const totalBannerHeight = localeBannerHeight + docPhaseElHeight;
314
+
300
315
  // Selecting the doc section heading and RNB here.
301
316
  const docHeadingEls = Array.from(
302
317
  document.querySelectorAll("doc-heading")
@@ -313,15 +328,10 @@ export default class ContentLayout extends LightningElement {
313
328
  `${globalNavHeight}px`
314
329
  );
315
330
 
316
- const docPhaseElHeight =
317
- docPhaseEl || verBannerEl
318
- ? (docPhaseEl || verBannerEl).getBoundingClientRect().height
319
- : 0;
320
-
321
331
  // Adjusting the doc section heading on scroll.
322
332
  docHeadingEls.forEach((docHeadingEl) => {
323
333
  (docHeadingEl as any).style.scrollMarginTop = `${
324
- totalHeaderHeight + docPhaseElHeight + 40
334
+ totalHeaderHeight + totalBannerHeight + 40
325
335
  }px`;
326
336
  });
327
337
 
@@ -331,10 +341,10 @@ export default class ContentLayout extends LightningElement {
331
341
  const viewportHeight = window.innerHeight;
332
342
  const maxHeight =
333
343
  viewportHeight -
334
- (docPhaseElHeight + totalHeaderHeight + 24); //added some margin of dx-toc
344
+ (totalBannerHeight + totalHeaderHeight + 24); //added some margin of dx-toc
335
345
 
336
346
  rightNavBarEl.style.top = `${
337
- totalHeaderHeight + docPhaseElHeight
347
+ totalHeaderHeight + totalBannerHeight
338
348
  }px`;
339
349
 
340
350
  const toc = rightNavBarEl.querySelector("dx-toc");
@@ -512,13 +522,22 @@ export default class ContentLayout extends LightningElement {
512
522
  globalNavEl?.offsetHeight +
513
523
  contextNavEl?.offsetHeight;
514
524
 
525
+ const localeBannerWrapper = this.template.querySelector(
526
+ ".locale-notification-wrapper"
527
+ ) as HTMLElement;
528
+ const localeBannerSlot = localeBannerWrapper?.querySelector(
529
+ "[name=locale-banner]"
530
+ ) as HTMLSlotElement | null;
531
+ const localeBannerEl = localeBannerSlot?.assignedElements?.()[0] as
532
+ | HTMLElement
533
+ | undefined;
515
534
  const docPhaseEl = (
516
535
  this.template.querySelector("[name=doc-phase]")! as any
517
536
  ).assignedElements()[0] as HTMLSlotElement;
518
537
 
519
- const offset = docPhaseEl
520
- ? headerHeight + docPhaseEl.offsetHeight
521
- : headerHeight;
538
+ const localeBannerHeight = localeBannerEl?.offsetHeight ?? 0;
539
+ const docPhaseHeight = docPhaseEl?.offsetHeight ?? 0;
540
+ const offset = headerHeight + localeBannerHeight + docPhaseHeight;
522
541
 
523
542
  for (const headingElement of headingElements as any) {
524
543
  if (headingElement.getAttribute("id") === hash) {
@@ -291,11 +291,7 @@ export default class RedocReference extends LightningElement {
291
291
  this.insertDocPhase(apiContentDiv, docPhaseInfo);
292
292
  }
293
293
 
294
- if (typeof Sprig !== "undefined") {
295
- this.insertSprigSurvey(apiContentDiv);
296
- }
297
-
298
- this.insertFooter(apiContentDiv);
294
+ this.appendFooterItems(apiContentDiv);
299
295
 
300
296
  // Wait for footer to be rendered before updating styles
301
297
  requestAnimationFrame(() => {
@@ -358,6 +354,16 @@ export default class RedocReference extends LightningElement {
358
354
  wrapper.appendChild(feedbackElement);
359
355
  }
360
356
 
357
+ private appendFooterItems(parent: HTMLElement): void {
358
+ const container = document.createElement("div");
359
+ container.className = "appended-footer-container";
360
+ if (typeof Sprig !== "undefined") {
361
+ this.insertSprigSurvey(container);
362
+ }
363
+ this.insertFooter(container);
364
+ parent.appendChild(container);
365
+ }
366
+
361
367
  // Adjusts third column bottom position to prevent footer overlap
362
368
  private updateRedocThirdColumnStyle(redocContainer: HTMLElement): void {
363
369
  const footer = redocContainer.querySelector(
@@ -15,6 +15,18 @@
15
15
  reading-time={computedReadingTime}
16
16
  origin={origin}
17
17
  >
18
+ <doc-banner
19
+ slot="locale-banner"
20
+ lwc:if={showLocaleBannerInSlot}
21
+ message-text="This text was translated using Salesforce's machine translation system. More details can be found "
22
+ message-link-url="https://help.salesforce.com/s/articleView?id=sf.machine_translation.htm"
23
+ message-link-text="here"
24
+ button-label="Switch to English"
25
+ button-href={localeBannerEnUsHref}
26
+ secondary-label="Not Now"
27
+ show-close-button="true"
28
+ dismiss-storage-key={deliverable}
29
+ ></doc-banner>
18
30
  <doc-phase
19
31
  slot="version-banner"
20
32
  lwc:if={showVersionBanner}
@@ -17,6 +17,7 @@ import { LightningElementWithState } from "dxBaseElements/lightningElementWithSt
17
17
  import { oldVersionDocInfo } from "docUtils/utils";
18
18
  import { Breadcrumb, DocPhaseInfo, Language } from "typings/custom";
19
19
  import { track as trackGTM } from "dxUtils/analytics";
20
+ import { normalizeBoolean } from "dxUtils/normalizers";
20
21
  import DOMPurify from "dompurify";
21
22
 
22
23
  // TODO: Imitating from actual implementation as doc-content use it like this. We should refactor it later.
@@ -48,6 +49,11 @@ export default class DocXmlContent extends LightningElementWithState<{
48
49
  /** Optional origin URL for the footer MFE (e.g. wp-json endpoint). Passed through to dx-footer-mfe. */
49
50
  @api origin: string | null = null;
50
51
 
52
+ /** Optional base URL for the canonical link (e.g. https://developer.salesforce.com). When set, used instead of window.location for the canonical href. */
53
+ @api baseUrl: string | null = null;
54
+
55
+ @api localeBannerEnabled = false;
56
+
51
57
  @api
52
58
  get allLanguages(): Array<Language> {
53
59
  return this._allLanguages;
@@ -74,6 +80,7 @@ export default class DocXmlContent extends LightningElementWithState<{
74
80
  private docTitle = "";
75
81
  private _pathName = "";
76
82
  private listenerAttached = false;
83
+ private _xmlLocaleBannerDispatched = false;
77
84
  private sidebarFooterContent: SiderbarFooter = { ...defaultSidebarFooter };
78
85
  private latestVersion = false;
79
86
  private previewVersion = false;
@@ -215,6 +222,15 @@ export default class DocXmlContent extends LightningElementWithState<{
215
222
  this.setState({ internalLinkClicked: false });
216
223
  }
217
224
 
225
+ if (
226
+ this.displayContent &&
227
+ !normalizeBoolean(this.localeBannerEnabled) &&
228
+ this.shouldShowLocaleBanner &&
229
+ !this._xmlLocaleBannerDispatched
230
+ ) {
231
+ this.injectLocaleBannerIntoThemeHost();
232
+ }
233
+
218
234
  if (
219
235
  (this.prevState.isFetchingContent &&
220
236
  !this.state.isFetchingContent) ||
@@ -251,6 +267,85 @@ export default class DocXmlContent extends LightningElementWithState<{
251
267
  return this.pageReference.deliverable;
252
268
  }
253
269
 
270
+ private get showLocaleBannerInSlot(): boolean {
271
+ return (
272
+ normalizeBoolean(this.localeBannerEnabled) &&
273
+ this.shouldShowLocaleBanner
274
+ );
275
+ }
276
+
277
+ private get shouldShowLocaleBanner(): boolean {
278
+ if (!this.pageReference?.deliverable) {
279
+ return false;
280
+ }
281
+ if (!this.language || this.language.id === "en-us") {
282
+ return false;
283
+ }
284
+ const hasEnUs = this.availableLanguages?.some(
285
+ (lang: DocLanguage) => lang.id === "en-us"
286
+ );
287
+ return !!hasEnUs;
288
+ }
289
+
290
+ private get localeBannerEnUsHref(): string {
291
+ if (!this.pageReference) {
292
+ return "";
293
+ }
294
+ const enUsLanguage = this.availableLanguages?.find(
295
+ (lang: DocLanguage) => lang.id === "en-us"
296
+ );
297
+ if (!enUsLanguage) {
298
+ return "";
299
+ }
300
+ return this.pageReferenceToString({
301
+ ...this.pageReference,
302
+ docId: enUsLanguage.url
303
+ });
304
+ }
305
+
306
+ private injectLocaleBannerIntoThemeHost(retryCount = 0): void {
307
+ if (typeof document === "undefined") {
308
+ return;
309
+ }
310
+ const host = document.getElementById("doc-xml-locale-banner-host");
311
+ if (!host) {
312
+ const maxRetries = 5;
313
+ const delays = [100, 300, 500, 800, 1200];
314
+ if (retryCount < maxRetries) {
315
+ const delay = delays[retryCount] ?? 1200;
316
+ setTimeout(
317
+ () => this.injectLocaleBannerIntoThemeHost(retryCount + 1),
318
+ delay
319
+ );
320
+ }
321
+ return;
322
+ }
323
+ if (host.hasChildNodes()) {
324
+ return;
325
+ }
326
+ const banner = document.createElement("doc-banner");
327
+ banner.setAttribute(
328
+ "message-text",
329
+ "This text was translated using Salesforce's machine translation system. More details can be found "
330
+ );
331
+ banner.setAttribute(
332
+ "message-link-url",
333
+ "https://help.salesforce.com/s/articleView?id=sf.machine_translation.htm"
334
+ );
335
+ banner.setAttribute("message-link-text", "here");
336
+ banner.setAttribute("button-label", "Switch to English");
337
+ banner.setAttribute("button-href", this.localeBannerEnUsHref);
338
+ banner.setAttribute("secondary-label", "Not Now");
339
+ banner.setAttribute("show-close-button", "true");
340
+ banner.setAttribute(
341
+ "dismiss-storage-key",
342
+ this.deliverable || "default"
343
+ );
344
+ host.setAttribute("aria-hidden", "false");
345
+ host.appendChild(banner);
346
+ this._xmlLocaleBannerDispatched = true;
347
+ }
348
+
254
349
  private get useOldSidebar(): boolean {
255
350
  // Coveo is enabled and the version is greater than 51 (within the latest 3 versions)
256
351
  // TODO: we need a better fix for version number check
@@ -766,21 +861,19 @@ export default class DocXmlContent extends LightningElementWithState<{
766
861
  }
767
862
 
768
863
  if (this.pageReference) {
769
- const metadescription = document.querySelector(
864
+ const canonicalLink = document.querySelector(
770
865
  'link[rel="canonical"]'
771
866
  );
772
- if (metadescription) {
867
+ if (canonicalLink) {
773
868
  const copyPageReference = { ...this.pageReference };
774
869
  copyPageReference.docId = copyPageReference.docId
775
870
  ? this.dropVersionFromDocId(copyPageReference.docId)
776
871
  : copyPageReference.docId;
777
- metadescription.setAttribute(
778
- "href",
779
- window.location.protocol +
780
- "//" +
781
- window.location.host +
782
- this.pageReferenceToString(copyPageReference)
783
- );
872
+ const path = this.pageReferenceToString(copyPageReference);
873
+ const origin = this.baseUrl
874
+ ? this.baseUrl.replace(/\/$/, "")
875
+ : `${window.location.protocol}//${window.location.host}`;
876
+ canonicalLink.setAttribute("href", `${origin}${path}`);
784
877
  }
785
878
  }
786
879
 
@@ -125,7 +125,7 @@ dx-toc {
125
125
  max-width: 1000px;
126
126
  flex: 1;
127
127
  width: 0;
128
- word-break: break-word;
128
+ overflow-wrap: break-word;
129
129
  }
130
130
 
131
131
  .is-sticky {