@salesforcedevs/docs-components 0.56.2-seo-test16 → 0.57.0-alpha-1
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 +1 -1
- package/src/modules/doc/amfReference/amfReference.html +5 -13
- package/src/modules/doc/amfReference/amfReference.ts +303 -793
- package/src/modules/doc/amfReference/route-meta.ts +22 -0
- package/src/modules/doc/amfReference/types.ts +3 -43
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.css +2 -1
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.html +1 -1
- package/src/modules/doc/breadcrumbItem/breadcrumbItem.ts +17 -1
- package/src/modules/doc/breadcrumbs/breadcrumbs.css +9 -1
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +12 -2
- package/src/modules/doc/breadcrumbs/breadcrumbs.ts +46 -6
- package/src/modules/doc/contentLayout/contentLayout.css +1 -5
- package/src/modules/doc/contentLayout/contentLayout.html +2 -9
- package/src/modules/doc/contentLayout/contentLayout.ts +29 -74
- package/src/modules/doc/xmlContent/types.ts +3 -0
- package/src/modules/doc/xmlContent/utils.ts +14 -11
- package/src/modules/doc/xmlContent/xmlContent.css +5 -0
- package/src/modules/doc/xmlContent/xmlContent.html +5 -0
- package/src/modules/doc/xmlContent/xmlContent.ts +64 -15
- package/src/modules/doc/amfReference/constants.ts +0 -76
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the URL reference meta on Reference page.
|
|
3
|
+
* Contains information on selected Reference ID, Topic ID, and Topic Type
|
|
4
|
+
* separated by ":"
|
|
5
|
+
*/
|
|
6
|
+
export class RouteMeta {
|
|
7
|
+
meta: string;
|
|
8
|
+
referenceId = "";
|
|
9
|
+
topicId = "";
|
|
10
|
+
type = "";
|
|
11
|
+
|
|
12
|
+
constructor(meta: string) {
|
|
13
|
+
this.meta = meta;
|
|
14
|
+
|
|
15
|
+
if (meta && meta.includes(":")) {
|
|
16
|
+
const [referenceId, type, topicId] = meta.split(":");
|
|
17
|
+
this.referenceId = referenceId;
|
|
18
|
+
this.topicId = topicId || type;
|
|
19
|
+
this.type = type;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -2,7 +2,6 @@ import { Json } from "typings/custom";
|
|
|
2
2
|
|
|
3
3
|
export interface AmfTopicType {
|
|
4
4
|
referenceId: string;
|
|
5
|
-
parentReferencePath: string;
|
|
6
5
|
amfId: string;
|
|
7
6
|
elementId: string;
|
|
8
7
|
type: string;
|
|
@@ -11,7 +10,6 @@ export interface AmfTopicType {
|
|
|
11
10
|
export interface AmfMetadataTopic extends AmfTopicType {
|
|
12
11
|
meta: string;
|
|
13
12
|
identifier: string;
|
|
14
|
-
navTitle?: string;
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
export interface AmfMetaTopicType extends AmfTopicType {
|
|
@@ -55,37 +53,11 @@ export type DocPhaseEntry = {
|
|
|
55
53
|
body: string;
|
|
56
54
|
};
|
|
57
55
|
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Represents parsed topic for the sidebar.
|
|
62
|
-
*/
|
|
63
|
-
export interface ParsedMarkdownTopic {
|
|
64
|
-
label: string;
|
|
65
|
-
name: string;
|
|
66
|
-
children: ParsedMarkdownTopic[];
|
|
67
|
-
link?: {
|
|
68
|
-
href: string;
|
|
69
|
-
target?: string;
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface AmfConfig {
|
|
56
|
+
export interface AmfConfig extends AmfModelRecord {
|
|
74
57
|
id: string;
|
|
58
|
+
amf: string;
|
|
75
59
|
version?: string;
|
|
76
60
|
docPhase?: DocPhaseEntry;
|
|
77
|
-
title: string;
|
|
78
|
-
href: string;
|
|
79
|
-
referenceType: ReferenceType;
|
|
80
|
-
|
|
81
|
-
// determines if a reference config is the current active and selected one.
|
|
82
|
-
isSelected: boolean;
|
|
83
|
-
|
|
84
|
-
// required for spec based references
|
|
85
|
-
amf?: string;
|
|
86
|
-
|
|
87
|
-
// required for markdown based references
|
|
88
|
-
topic?: ParsedMarkdownTopic;
|
|
89
61
|
}
|
|
90
62
|
|
|
91
63
|
export interface ParsedTopicModel {
|
|
@@ -112,22 +84,10 @@ export interface ReferenceVersion {
|
|
|
112
84
|
label: string;
|
|
113
85
|
deprecated?: boolean;
|
|
114
86
|
selected?: boolean;
|
|
115
|
-
link: {
|
|
116
|
-
href: string;
|
|
117
|
-
};
|
|
118
87
|
}
|
|
119
88
|
|
|
120
89
|
export interface ReferenceSetConfig {
|
|
121
|
-
refId?: string;
|
|
122
90
|
versionToRefMap?: Map<string, Array<AmfConfig>>;
|
|
123
91
|
refList: Array<AmfConfig>;
|
|
124
|
-
versions
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export interface RouteMeta {
|
|
128
|
-
meta: string;
|
|
129
|
-
referenceId: string;
|
|
130
|
-
topicId: string;
|
|
131
|
-
//type is only for spec based references
|
|
132
|
-
type?: string;
|
|
92
|
+
versions?: Array<ReferenceVersion>;
|
|
133
93
|
}
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
:host {
|
|
5
5
|
display: flex;
|
|
6
6
|
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
7
8
|
width: fit-content;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
:host(.breadcrumb_long) {
|
|
11
12
|
/* ensure 30 character min-width */
|
|
12
|
-
min-width:
|
|
13
|
+
min-width: 200px;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
:host(.breadcrumb_back-arrow) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { track } from "dxUtils/analytics";
|
|
1
2
|
import { LightningElement, api } from "lwc";
|
|
2
|
-
import { BreadcrumbItemVariant } from "typings/custom";
|
|
3
|
+
import { AnalyticsPayload, BreadcrumbItemVariant } from "typings/custom";
|
|
3
4
|
|
|
4
5
|
const BREADCRUMB_LONG = "breadcrumb_long";
|
|
5
6
|
const BREADCRUMB_BACK_ARROW = "breadcrumb_back-arrow";
|
|
@@ -7,6 +8,8 @@ const BREADCRUMB_BACK_ARROW = "breadcrumb_back-arrow";
|
|
|
7
8
|
const LONG_LABEL_NUMBER = 30;
|
|
8
9
|
export default class BreadcrumbItem extends LightningElement {
|
|
9
10
|
@api href?: string;
|
|
11
|
+
@api analyticsEvent!: string;
|
|
12
|
+
@api analyticsBasePayload!: AnalyticsPayload;
|
|
10
13
|
|
|
11
14
|
@api
|
|
12
15
|
get label() {
|
|
@@ -46,4 +49,17 @@ export default class BreadcrumbItem extends LightningElement {
|
|
|
46
49
|
private get isBackArrowVariant(): boolean {
|
|
47
50
|
return this._variant === "back-arrow";
|
|
48
51
|
}
|
|
52
|
+
|
|
53
|
+
private onLinkClick(event: Event): void {
|
|
54
|
+
if (!this.analyticsEvent) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
track(event.target!, this.analyticsEvent, {
|
|
59
|
+
...this.analyticsBasePayload,
|
|
60
|
+
clickText: this.label,
|
|
61
|
+
itemTitle: this.label,
|
|
62
|
+
pageLocation: window.location.pathname
|
|
63
|
+
});
|
|
64
|
+
}
|
|
49
65
|
}
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
:host {
|
|
5
5
|
--dx-c-breadcrumbs-title-color: var(--dx-g-blue-vibrant-20);
|
|
6
6
|
--dx-c-breadcrumbs-breadcrumb-color: var(--dx-g-blue-vibrant-20);
|
|
7
|
+
|
|
8
|
+
font-family: var(--dx-g-font-sans);
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
nav {
|
|
10
12
|
display: flex;
|
|
11
13
|
align-items: center;
|
|
12
|
-
height: 100%;
|
|
13
14
|
position: relative;
|
|
14
15
|
gap: var(--dx-g-spacing-sm);
|
|
15
16
|
}
|
|
@@ -17,3 +18,10 @@ nav {
|
|
|
17
18
|
.breadcrumb-item_slash {
|
|
18
19
|
min-width: fit-content;
|
|
19
20
|
}
|
|
21
|
+
|
|
22
|
+
dx-dropdown {
|
|
23
|
+
--dx-c-dropdown-option-font-size: var(--dx-g-text-sm);
|
|
24
|
+
--dx-c-dropdown-option-label-color: var(
|
|
25
|
+
--dx-c-breadcrumbs-breadcrumb-color
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
<template if:false={renderSmallVariant}>
|
|
4
4
|
<template if:true={renderFirstCrumb}>
|
|
5
5
|
<doc-breadcrumb-item
|
|
6
|
+
analytics-event={analyticsEventName}
|
|
7
|
+
analytics-base-payload={analyticsBasePayload}
|
|
6
8
|
href={firstCrumb.href}
|
|
7
9
|
label={firstCrumb.label}
|
|
8
10
|
></doc-breadcrumb-item>
|
|
@@ -11,10 +13,14 @@
|
|
|
11
13
|
<template if:true={renderDropdown}>
|
|
12
14
|
<dx-dropdown
|
|
13
15
|
if:true={renderDropdown}
|
|
16
|
+
analytics-event={analyticsEventName}
|
|
17
|
+
analytics-base-payload={analyticsBasePayload}
|
|
14
18
|
options={dropdownOptions}
|
|
15
19
|
open-on-hover
|
|
16
20
|
placement="bottom"
|
|
17
|
-
|
|
21
|
+
suppress-gtm-nav-headings
|
|
22
|
+
variant="indented"
|
|
23
|
+
width="fit-content"
|
|
18
24
|
>
|
|
19
25
|
<dx-button
|
|
20
26
|
aria-label="Open Breadcrumbs Dropdown"
|
|
@@ -27,8 +33,10 @@
|
|
|
27
33
|
</template>
|
|
28
34
|
<template for:each={breadcrumbItems} for:item="breadcrumb">
|
|
29
35
|
<doc-breadcrumb-item
|
|
36
|
+
analytics-event={analyticsEventName}
|
|
37
|
+
analytics-base-payload={analyticsBasePayload}
|
|
30
38
|
href={breadcrumb.href}
|
|
31
|
-
key={breadcrumb.
|
|
39
|
+
key={breadcrumb.id}
|
|
32
40
|
label={breadcrumb.label}
|
|
33
41
|
></doc-breadcrumb-item>
|
|
34
42
|
<span class="breadcrumb-item_slash" key={breadcrumb.label}>
|
|
@@ -39,6 +47,8 @@
|
|
|
39
47
|
</template>
|
|
40
48
|
<template if:true={renderSmallVariant}>
|
|
41
49
|
<doc-breadcrumb-item
|
|
50
|
+
analytics-event={analyticsEventName}
|
|
51
|
+
analytics-base-payload={analyticsBasePayload}
|
|
42
52
|
href={lastLinkCrump.href}
|
|
43
53
|
label={lastLinkCrump.label}
|
|
44
54
|
variant="back-arrow"
|
|
@@ -8,13 +8,22 @@ type BreadcrumbConfig = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
const GAP = 8;
|
|
11
|
+
|
|
12
|
+
// Unit in pixels based on Salesforce Sans font-family.
|
|
11
13
|
const CONSTANTS = {
|
|
12
|
-
pixelPerCharacter: 7.
|
|
13
|
-
pixelPerCrumbSpace: GAP * 2 +
|
|
14
|
-
minWidthPerCrumb:
|
|
14
|
+
pixelPerCharacter: 7.7,
|
|
15
|
+
pixelPerCrumbSpace: GAP * 2 + 8.6,
|
|
16
|
+
minWidthPerCrumb: 200,
|
|
15
17
|
dropdownWidth: 32
|
|
16
18
|
};
|
|
17
19
|
|
|
20
|
+
export const ANALYTICS_EVENT_NAME = "custEv_breadcrumbClick";
|
|
21
|
+
export const ANALYTICS_BASE_PAYLOAD = {
|
|
22
|
+
elementType: "breadcrumb",
|
|
23
|
+
locationOnPage: "breadcrumb",
|
|
24
|
+
ctaClick: true
|
|
25
|
+
};
|
|
26
|
+
|
|
18
27
|
export default class Breadcrumbs extends LightningElement {
|
|
19
28
|
@api ariaLabel: string = "Documentation Breadcrumbs";
|
|
20
29
|
|
|
@@ -22,15 +31,26 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
22
31
|
get breadcrumbs(): Breadcrumb[] {
|
|
23
32
|
return this._breadcrumbs;
|
|
24
33
|
}
|
|
34
|
+
|
|
25
35
|
set breadcrumbs(value) {
|
|
26
|
-
this.
|
|
36
|
+
this.normalizeAndAssignBreadcrumbs(value);
|
|
27
37
|
this.calculateBreadcrumbsConfigs();
|
|
28
38
|
if (this.observer) {
|
|
29
39
|
this.updateDropdownOptionAmount();
|
|
30
40
|
}
|
|
31
41
|
}
|
|
32
42
|
|
|
43
|
+
@api
|
|
44
|
+
get pixelPerCharacter(): number {
|
|
45
|
+
return this._pixelPerCharacter;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
set pixelPerCharacter(value: number | string) {
|
|
49
|
+
this._pixelPerCharacter = +value;
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
private _breadcrumbs: Breadcrumb[] = [];
|
|
53
|
+
private _pixelPerCharacter = CONSTANTS.pixelPerCharacter;
|
|
34
54
|
private navWidth = 0;
|
|
35
55
|
private observer: ResizeObserver | null = null;
|
|
36
56
|
private breadcrumbConfigs: BreadcrumbConfig[] = [];
|
|
@@ -65,7 +85,7 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
65
85
|
private get dropdownOptions(): OptionWithLink[] {
|
|
66
86
|
return this.breadcrumbs!.slice(1, this.dropdownOptionAmount! + 1).map(
|
|
67
87
|
(link) => ({
|
|
68
|
-
id: link.
|
|
88
|
+
id: link.id!,
|
|
69
89
|
label: link.label,
|
|
70
90
|
link: { href: link.href! }
|
|
71
91
|
})
|
|
@@ -84,6 +104,14 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
84
104
|
return this.breadcrumbs[this.breadcrumbs.length - 1];
|
|
85
105
|
}
|
|
86
106
|
|
|
107
|
+
private get analyticsEventName() {
|
|
108
|
+
return ANALYTICS_EVENT_NAME;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private get analyticsBasePayload() {
|
|
112
|
+
return ANALYTICS_BASE_PAYLOAD;
|
|
113
|
+
}
|
|
114
|
+
|
|
87
115
|
renderedCallback(): void {
|
|
88
116
|
if (!this.observer) {
|
|
89
117
|
this.observer = new ResizeObserver((entries) => {
|
|
@@ -103,6 +131,17 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
103
131
|
this.observer?.disconnect();
|
|
104
132
|
}
|
|
105
133
|
|
|
134
|
+
private normalizeAndAssignBreadcrumbs(breadcrumbs?: Breadcrumb[] | string) {
|
|
135
|
+
if (!breadcrumbs) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this._breadcrumbs = toJson(breadcrumbs).map((crumb: Breadcrumb) => ({
|
|
140
|
+
...crumb,
|
|
141
|
+
id: crumb.id || crumb.href
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
|
|
106
145
|
private updateDropdownOptionAmount(): void {
|
|
107
146
|
this.dropdownOptionAmount = this.breadcrumbConfigs.find(
|
|
108
147
|
({ minWidth }) => minWidth <= this.navWidth
|
|
@@ -135,7 +174,8 @@ export default class Breadcrumbs extends LightningElement {
|
|
|
135
174
|
(previousValue, element) =>
|
|
136
175
|
previousValue +
|
|
137
176
|
Math.min(
|
|
138
|
-
element.label.length *
|
|
177
|
+
element.label.length *
|
|
178
|
+
(this.pixelPerCharacter || CONSTANTS.pixelPerCharacter),
|
|
139
179
|
CONSTANTS.minWidthPerCrumb
|
|
140
180
|
),
|
|
141
181
|
(breadcrumbs.length - 1) * CONSTANTS.pixelPerCrumbSpace + offset
|
|
@@ -56,7 +56,7 @@ dx-toc {
|
|
|
56
56
|
max-width: 275px;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
doc-breadcrumbs {
|
|
60
60
|
display: block;
|
|
61
61
|
margin-bottom: var(--dx-g-spacing-2xl);
|
|
62
62
|
}
|
|
@@ -68,10 +68,6 @@ dx-breadcrumbs {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
@media screen and (max-width: 800px) {
|
|
71
|
-
dx-breadcrumbs {
|
|
72
|
-
display: none;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
71
|
.content-body {
|
|
76
72
|
margin-top: var(--dx-c-content-vertical-spacing);
|
|
77
73
|
}
|
|
@@ -28,17 +28,10 @@
|
|
|
28
28
|
<slot name="doc-phase"></slot>
|
|
29
29
|
<div class="content-body-container">
|
|
30
30
|
<div class="content-body">
|
|
31
|
-
<
|
|
31
|
+
<doc-breadcrumbs
|
|
32
32
|
if:true={breadcrumbs}
|
|
33
33
|
breadcrumbs={breadcrumbs}
|
|
34
|
-
|
|
35
|
-
hide-current-location
|
|
36
|
-
></dx-breadcrumbs>
|
|
37
|
-
<dx-breadcrumbs
|
|
38
|
-
if:false={breadcrumbs}
|
|
39
|
-
pathname={pathname}
|
|
40
|
-
hide-current-location
|
|
41
|
-
></dx-breadcrumbs>
|
|
34
|
+
></doc-breadcrumbs>
|
|
42
35
|
<slot onslotchange={onSlotChange}></slot>
|
|
43
36
|
</div>
|
|
44
37
|
<div class="right-nav-bar is-sticky">
|
|
@@ -20,7 +20,6 @@ const HIGHLIGHTABLE_SELECTOR = [
|
|
|
20
20
|
"th",
|
|
21
21
|
"td"
|
|
22
22
|
].join(",");
|
|
23
|
-
const OBSERVER_ATTACH_WAIT_TIME = 500;
|
|
24
23
|
|
|
25
24
|
export default class ContentLayout extends LightningElement {
|
|
26
25
|
@api sidebarValue: string;
|
|
@@ -96,8 +95,6 @@ export default class ContentLayout extends LightningElement {
|
|
|
96
95
|
target: window
|
|
97
96
|
});
|
|
98
97
|
private tocValue?: string = undefined;
|
|
99
|
-
private observerTimerId = null;
|
|
100
|
-
private didScrollToSelectedHash = false;
|
|
101
98
|
|
|
102
99
|
get showToc(): boolean {
|
|
103
100
|
return this.tocOptions && this.tocOptions.length > 0;
|
|
@@ -122,18 +119,6 @@ export default class ContentLayout extends LightningElement {
|
|
|
122
119
|
}
|
|
123
120
|
}
|
|
124
121
|
|
|
125
|
-
renderedCallback(): void {
|
|
126
|
-
/**
|
|
127
|
-
* Note: We are adding timeout because chrome is optimizing and not triggering recent renderedCallback though elements reference is changed
|
|
128
|
-
* Also we are considering recent renderedCallback
|
|
129
|
-
*/
|
|
130
|
-
this.clearRenderObserverTimer();
|
|
131
|
-
this.observerTimerId = setTimeout(
|
|
132
|
-
this.attachInteractionObserver,
|
|
133
|
-
OBSERVER_ATTACH_WAIT_TIME
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
122
|
disconnectedCallback(): void {
|
|
138
123
|
this.disconnectObserver();
|
|
139
124
|
window.removeEventListener(
|
|
@@ -141,25 +126,19 @@ export default class ContentLayout extends LightningElement {
|
|
|
141
126
|
this.updateHighlighted
|
|
142
127
|
);
|
|
143
128
|
this.searchSyncer.dispose();
|
|
144
|
-
this.clearRenderObserverTimer();
|
|
145
129
|
}
|
|
146
130
|
|
|
147
|
-
clearRenderObserverTimer = () => {
|
|
148
|
-
if (this.observerTimerId) {
|
|
149
|
-
clearTimeout(this.observerTimerId);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
131
|
updateHighlighted = (event: Event): void =>
|
|
154
132
|
highlightTerms(
|
|
155
133
|
this.querySelectorAll(HIGHLIGHTABLE_SELECTOR),
|
|
156
134
|
(event as CustomEvent<string>).detail
|
|
157
135
|
);
|
|
158
136
|
|
|
159
|
-
|
|
137
|
+
onSlotChange(event: Event): void {
|
|
160
138
|
if (!this.enableSlotChange) {
|
|
161
139
|
return;
|
|
162
140
|
}
|
|
141
|
+
|
|
163
142
|
this.disconnectObserver();
|
|
164
143
|
this.observer = new IntersectionObserver((entries) => {
|
|
165
144
|
entries.forEach(
|
|
@@ -171,54 +150,30 @@ export default class ContentLayout extends LightningElement {
|
|
|
171
150
|
this.calculateActualSection();
|
|
172
151
|
});
|
|
173
152
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
153
|
+
const anchoredTags = (event.target as HTMLSlotElement)
|
|
154
|
+
.assignedElements()
|
|
155
|
+
.filter(({ tagName }) => tagName === TOC_HEADER_TAG)
|
|
156
|
+
.map((tag) => {
|
|
157
|
+
tag.id = tag.hash;
|
|
158
|
+
return tag;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this._tocOptions = anchoredTags.map((tag) => ({
|
|
162
|
+
anchor: `#${tag.hash}`,
|
|
163
|
+
id: tag.id,
|
|
164
|
+
label: tag.title
|
|
165
|
+
}));
|
|
166
|
+
|
|
167
|
+
this.scrollToHash(anchoredTags);
|
|
168
|
+
|
|
169
|
+
anchoredTags.forEach((section) => {
|
|
170
|
+
const id = section.getAttribute("id");
|
|
179
171
|
this.anchoredElements[id] = {
|
|
180
172
|
id,
|
|
181
173
|
intersect: false
|
|
182
174
|
};
|
|
183
|
-
this.observer.observe(
|
|
184
|
-
}
|
|
185
|
-
if (!this.didScrollToSelectedHash) {
|
|
186
|
-
this.didScrollToSelectedHash = true;
|
|
187
|
-
this.scrollToHash(headingElements);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
onSlotChange(event: Event): void {
|
|
192
|
-
const slotElements = (
|
|
193
|
-
event.target as HTMLSlotElement
|
|
194
|
-
).assignedElements();
|
|
195
|
-
|
|
196
|
-
if (slotElements.length) {
|
|
197
|
-
const slotContentElement = slotElements[0];
|
|
198
|
-
const headingElements =
|
|
199
|
-
slotContentElement.ownerDocument?.getElementsByTagName(
|
|
200
|
-
TOC_HEADER_TAG
|
|
201
|
-
);
|
|
202
|
-
for (const headingElement of headingElements) {
|
|
203
|
-
// Sometimes elements hash is not being set when slot content is wrapped with div
|
|
204
|
-
headingElement.hash =
|
|
205
|
-
headingElement.attributes.hash?.nodeValue;
|
|
206
|
-
}
|
|
207
|
-
const tocOptions = [];
|
|
208
|
-
for (const headingElement of headingElements) {
|
|
209
|
-
headingElement.id = headingElement.hash;
|
|
210
|
-
|
|
211
|
-
// Update tocOptions from anchorTags
|
|
212
|
-
const tocItem = {
|
|
213
|
-
anchor: `#${headingElement.hash}`,
|
|
214
|
-
id: headingElement.id,
|
|
215
|
-
label: headingElement.title
|
|
216
|
-
};
|
|
217
|
-
tocOptions.push(tocItem);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
this._tocOptions = tocOptions;
|
|
221
|
-
}
|
|
175
|
+
this.observer.observe(section);
|
|
176
|
+
});
|
|
222
177
|
}
|
|
223
178
|
|
|
224
179
|
private disconnectObserver(): void {
|
|
@@ -228,16 +183,16 @@ export default class ContentLayout extends LightningElement {
|
|
|
228
183
|
}
|
|
229
184
|
}
|
|
230
185
|
|
|
231
|
-
|
|
232
|
-
private scrollToHash(headingElements: NodeListOf<Element>): void {
|
|
186
|
+
private scrollToHash(anchoredTags: Array<Element>): void {
|
|
233
187
|
let { hash } = window.location;
|
|
188
|
+
|
|
234
189
|
if (hash) {
|
|
235
190
|
hash = hash.substr(1);
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
191
|
+
const toScrollElement = anchoredTags.find(
|
|
192
|
+
(element) => element.getAttribute("id") === hash
|
|
193
|
+
);
|
|
194
|
+
if (toScrollElement) {
|
|
195
|
+
toScrollElement.scrollIntoView({ behavior: "auto" });
|
|
241
196
|
}
|
|
242
197
|
}
|
|
243
198
|
}
|
|
@@ -24,6 +24,7 @@ export type TreeNode = {
|
|
|
24
24
|
name: string;
|
|
25
25
|
children?: Array<TreeNode>;
|
|
26
26
|
isExpanded?: boolean;
|
|
27
|
+
parent?: TreeNode;
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
type DropdownOption = {
|
|
@@ -109,3 +110,5 @@ export type ContentApiOptions = {
|
|
|
109
110
|
version: string;
|
|
110
111
|
language: string;
|
|
111
112
|
};
|
|
113
|
+
|
|
114
|
+
export type TocMap = { [key: string]: TreeNode };
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
DocumentData,
|
|
9
9
|
DocLanguage,
|
|
10
10
|
DocVersion,
|
|
11
|
-
TreeNode
|
|
11
|
+
TreeNode,
|
|
12
|
+
TocMap
|
|
12
13
|
} from "./types";
|
|
13
14
|
import { Language } from "typings/custom";
|
|
14
15
|
import { getLanguageDisplayTextById } from "dxUtils/language";
|
|
@@ -100,26 +101,26 @@ export class FetchContent {
|
|
|
100
101
|
|
|
101
102
|
private normalizeNavItem(
|
|
102
103
|
navItem: ApiNavItem,
|
|
103
|
-
tocMap:
|
|
104
|
+
tocMap: TocMap,
|
|
105
|
+
parentNavItem?: TreeNode
|
|
104
106
|
): TreeNode {
|
|
105
107
|
const name = this.calculateNavItemName(navItem, tocMap);
|
|
106
108
|
const node: TreeNode = {
|
|
107
109
|
label: navItem.text,
|
|
108
|
-
name
|
|
110
|
+
name,
|
|
111
|
+
parent: parentNavItem
|
|
109
112
|
};
|
|
113
|
+
|
|
110
114
|
if (name) {
|
|
111
115
|
tocMap[name] = node;
|
|
112
116
|
}
|
|
113
117
|
node.children = navItem.children?.map((child) =>
|
|
114
|
-
this.normalizeNavItem(child, tocMap)
|
|
118
|
+
this.normalizeNavItem(child, tocMap, node)
|
|
115
119
|
);
|
|
116
120
|
return node;
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
private calculateNavItemName(
|
|
120
|
-
navItem: ApiNavItem,
|
|
121
|
-
tocMap: { [key: string]: TreeNode }
|
|
122
|
-
): string {
|
|
123
|
+
private calculateNavItemName(navItem: ApiNavItem, tocMap: TocMap): string {
|
|
123
124
|
let href = navItem.a_attr?.href || "";
|
|
124
125
|
if (href.includes("#")) {
|
|
125
126
|
const [pathUrl] = href.split("#");
|
|
@@ -144,11 +145,13 @@ export class FetchContent {
|
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
private normalizeLanguage(language: ApiDocLanguage): DocLanguage {
|
|
147
|
-
|
|
148
148
|
return (
|
|
149
149
|
language && {
|
|
150
|
-
label:
|
|
151
|
-
|
|
150
|
+
label:
|
|
151
|
+
getLanguageDisplayTextById(
|
|
152
|
+
this.languages,
|
|
153
|
+
language.locale
|
|
154
|
+
) || language.label,
|
|
152
155
|
id: language.locale,
|
|
153
156
|
code: language.code,
|
|
154
157
|
url: language.url
|
|
@@ -25,6 +25,11 @@
|
|
|
25
25
|
</dx-button>
|
|
26
26
|
</dx-dropdown>
|
|
27
27
|
</div>
|
|
28
|
+
<doc-breadcrumbs
|
|
29
|
+
if:true={breadcrumbs}
|
|
30
|
+
breadcrumbs={breadcrumbs}
|
|
31
|
+
pixel-per-character={breadcrumbPixelPerCharacter}
|
|
32
|
+
></doc-breadcrumbs>
|
|
28
33
|
<doc-content
|
|
29
34
|
docs-data={docContent}
|
|
30
35
|
page-reference={pageReference}
|