@salesforcedevs/docs-components 1.34.0-alpha2 → 1.34.0-banner-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.
package/package.json
CHANGED
|
@@ -9,7 +9,8 @@ import SprigSurvey from "doc/sprigSurvey";
|
|
|
9
9
|
import { throttle } from "throttle-debounce";
|
|
10
10
|
import { pollUntil } from "dxUtils/async";
|
|
11
11
|
import { toJson } from "dxUtils/normalizers";
|
|
12
|
-
import
|
|
12
|
+
import { oldVersionDocInfo } from "docUtils/utils";
|
|
13
|
+
import type { DocPhaseInfo, OptionWithLink } from "typings/custom";
|
|
13
14
|
|
|
14
15
|
declare global {
|
|
15
16
|
interface Window {
|
|
@@ -185,6 +186,14 @@ export default class RedocReference extends LightningElement {
|
|
|
185
186
|
return this.versions.length > 0;
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
/** "Newer version available" banner info when on a non-latest version, else null. */
|
|
190
|
+
private get oldVersionInfo(): DocPhaseInfo | null {
|
|
191
|
+
if (this.versions.length > 1 && !this.latestVersion) {
|
|
192
|
+
return oldVersionDocInfo(this.versions[0].link.href);
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
188
197
|
/** A single version has nothing to choose, so it renders read-only. */
|
|
189
198
|
get isVersionReadOnly(): boolean {
|
|
190
199
|
return this.versions.length === 1;
|
|
@@ -586,10 +595,7 @@ export default class RedocReference extends LightningElement {
|
|
|
586
595
|
const apiContentDiv = await this.waitForApiContent(redocContainer);
|
|
587
596
|
apiContentDiv.setAttribute("lwc:dom", "manual");
|
|
588
597
|
|
|
589
|
-
|
|
590
|
-
if (docPhaseInfo) {
|
|
591
|
-
this.insertDocPhase(apiContentDiv, docPhaseInfo);
|
|
592
|
-
}
|
|
598
|
+
this.insertStatusItems(apiContentDiv);
|
|
593
599
|
|
|
594
600
|
this.appendFooterItems(apiContentDiv);
|
|
595
601
|
|
|
@@ -780,15 +786,40 @@ export default class RedocReference extends LightningElement {
|
|
|
780
786
|
return container.querySelector<HTMLElement>(".api-content")!;
|
|
781
787
|
}
|
|
782
788
|
|
|
783
|
-
//
|
|
784
|
-
|
|
789
|
+
// Inserts the doc phase and, on a non-latest version, a dismissible
|
|
790
|
+
// "newer version" banner into a shared doc-phase-wrapper at container start
|
|
791
|
+
private insertStatusItems(container: HTMLElement): void {
|
|
792
|
+
const docPhaseInfo = this.getDocPhaseInfo();
|
|
793
|
+
const oldVersionInfo = this.oldVersionInfo;
|
|
794
|
+
if (!docPhaseInfo && !oldVersionInfo) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
|
|
785
798
|
const wrapper = document.createElement("div");
|
|
786
799
|
wrapper.className = "doc-phase-wrapper";
|
|
787
800
|
container.insertBefore(wrapper, container.firstChild);
|
|
788
801
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
802
|
+
if (docPhaseInfo) {
|
|
803
|
+
const docPhaseElement = createElement("doc-phase", {
|
|
804
|
+
is: DocPhase
|
|
805
|
+
});
|
|
806
|
+
Object.assign(docPhaseElement, { docPhaseInfo });
|
|
807
|
+
wrapper.appendChild(docPhaseElement);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
if (oldVersionInfo) {
|
|
811
|
+
const versionBanner = createElement("doc-phase", { is: DocPhase });
|
|
812
|
+
Object.assign(versionBanner, {
|
|
813
|
+
docPhaseInfo: oldVersionInfo,
|
|
814
|
+
dismissible: true,
|
|
815
|
+
iconName: "warning"
|
|
816
|
+
});
|
|
817
|
+
versionBanner.addEventListener("dismissphase", () => {
|
|
818
|
+
versionBanner.remove();
|
|
819
|
+
this.updateSidebarPosition();
|
|
820
|
+
});
|
|
821
|
+
wrapper.appendChild(versionBanner);
|
|
822
|
+
}
|
|
792
823
|
}
|
|
793
824
|
|
|
794
825
|
// Appends footer component to container
|
|
@@ -24,6 +24,14 @@
|
|
|
24
24
|
lwc:if={docPhaseInfo}
|
|
25
25
|
doc-phase-info={docPhaseInfo}
|
|
26
26
|
></doc-phase>
|
|
27
|
+
<doc-phase
|
|
28
|
+
slot="version-banner"
|
|
29
|
+
lwc:if={showVersionBanner}
|
|
30
|
+
doc-phase-info={oldVersionInfo}
|
|
31
|
+
icon-name="warning"
|
|
32
|
+
dismissible="true"
|
|
33
|
+
ondismissphase={handleDismissVersionBanner}
|
|
34
|
+
></doc-phase>
|
|
27
35
|
<slot></slot>
|
|
28
36
|
</doc-content-layout>
|
|
29
37
|
</template>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { LightningElement, api } from "lwc";
|
|
1
|
+
import { LightningElement, api, track } from "lwc";
|
|
2
2
|
import { toJson } from "dxUtils/normalizers";
|
|
3
|
-
import type {
|
|
3
|
+
import type { VersionedNode } from "dxUtils/topicVersion";
|
|
4
|
+
import {
|
|
5
|
+
findTopicVersionForCurrentPage,
|
|
6
|
+
latestHrefForCurrentPage
|
|
7
|
+
} from "dxUtils/topicVersion";
|
|
8
|
+
import { oldVersionDocInfo } from "docUtils/utils";
|
|
9
|
+
import type { DocPhaseInfo, OptionWithLink, TreeNode } from "typings/custom";
|
|
4
10
|
|
|
5
11
|
/**
|
|
6
12
|
* Per-topic type emitted by the docs content-type parser
|
|
@@ -67,6 +73,9 @@ export default class UnifiedContentLayout extends LightningElement {
|
|
|
67
73
|
|
|
68
74
|
private _docPhaseInfo: string | null = null;
|
|
69
75
|
private _sidebarContent: unknown = null;
|
|
76
|
+
private _oldVersionInfo: DocPhaseInfo | null = null;
|
|
77
|
+
|
|
78
|
+
@track showVersionBanner = false;
|
|
70
79
|
|
|
71
80
|
@api
|
|
72
81
|
get docPhaseInfo(): string | null {
|
|
@@ -83,9 +92,40 @@ export default class UnifiedContentLayout extends LightningElement {
|
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
set sidebarContent(value: string) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
95
|
+
const topics = decorateTopicsWithForwardArrow(toJson(value)?.topics);
|
|
96
|
+
this._sidebarContent = topics;
|
|
97
|
+
this.updateTopicVersionBanner(topics as VersionedNode[] | undefined);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get oldVersionInfo(): DocPhaseInfo | null {
|
|
101
|
+
return this._oldVersionInfo;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
handleDismissVersionBanner(): void {
|
|
105
|
+
this.showVersionBanner = false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Same banner references use when the reader is on an older version.
|
|
110
|
+
* Topic versions are not a separate page property: the sidebar tree
|
|
111
|
+
* carries each version's switching URL, and the current pathname says
|
|
112
|
+
* which one is open.
|
|
113
|
+
*/
|
|
114
|
+
private updateTopicVersionBanner(
|
|
115
|
+
topics: VersionedNode[] | undefined
|
|
116
|
+
): void {
|
|
117
|
+
const match = findTopicVersionForCurrentPage(topics);
|
|
118
|
+
const latest = match?.node.versions?.[0];
|
|
119
|
+
const latestHref = latestHrefForCurrentPage(match?.node.versions);
|
|
120
|
+
|
|
121
|
+
if (match && latest && match.version.id !== latest.id && latestHref) {
|
|
122
|
+
this._oldVersionInfo = oldVersionDocInfo(latestHref);
|
|
123
|
+
this.showVersionBanner = true;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
this._oldVersionInfo = null;
|
|
128
|
+
this.showVersionBanner = false;
|
|
89
129
|
}
|
|
90
130
|
|
|
91
131
|
private get enableFooter(): boolean {
|
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
import { CoveoAnalyticsClient } from "coveo.analytics/dist/browser.mjs"; // This fix is required for Node 20 upgrade, so that Coveo analytics is loaded properly by LWR.
|
|
2
2
|
|
|
3
|
+
// Resolve against the current origin (version links are usually relative) and
|
|
4
|
+
// keep only http/https. Blocks executable schemes like javascript:/data: that
|
|
5
|
+
// would run when the innerHTML-rendered link is clicked
|
|
6
|
+
// encodeURI then keeps the value from breaking out of the href attribute.
|
|
7
|
+
const toSafeHref = (link: string): string => {
|
|
8
|
+
try {
|
|
9
|
+
const { protocol } = new URL(link, window.location.origin);
|
|
10
|
+
if (protocol === "http:" || protocol === "https:") {
|
|
11
|
+
return encodeURI(link);
|
|
12
|
+
}
|
|
13
|
+
} catch {
|
|
14
|
+
// Fall through to the rejection below.
|
|
15
|
+
}
|
|
16
|
+
console.warn(`Blocked unsafe version link: ${link}`);
|
|
17
|
+
return "#";
|
|
18
|
+
};
|
|
19
|
+
|
|
3
20
|
export const oldVersionDocInfo = (latestVersionLink: string) => {
|
|
21
|
+
const safeLink = toSafeHref(latestVersionLink);
|
|
4
22
|
return {
|
|
5
23
|
title: "Newer Version Available",
|
|
6
|
-
body: `This content describes an older version of this product.
|
|
7
|
-
<a style="font-weight: bold;" href="${
|
|
24
|
+
body: `This content describes an older version of this product.
|
|
25
|
+
<a style="font-weight: bold;" href="${safeLink}">View Latest</a>`
|
|
8
26
|
};
|
|
9
27
|
};
|
|
10
28
|
|