@salesforcedevs/docs-components 0.56.2 → 0.56.3-example
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 +10 -2
- package/package.json +19 -13
- package/src/modules/doc/{amfReference/utils.ts → amfModelParser/amfModelParser.ts} +10 -5
- package/src/modules/doc/amfReference/amfReference.css +23 -3
- package/src/modules/doc/amfReference/amfReference.html +42 -21
- package/src/modules/doc/amfReference/amfReference.ts +1022 -341
- package/src/modules/doc/amfReference/constants.ts +76 -0
- package/src/modules/doc/amfReference/types.ts +45 -13
- package/src/modules/doc/amfTopic/amfTopic.css +20 -0
- package/src/modules/doc/amfTopic/amfTopic.ts +35 -18
- package/src/modules/doc/amfTopic/types.ts +15 -13
- package/src/modules/doc/amfTopic/utils.ts +12 -6
- 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 +22 -0
- package/src/modules/doc/breadcrumbs/breadcrumbs.css +9 -1
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +44 -34
- package/src/modules/doc/breadcrumbs/breadcrumbs.ts +62 -23
- package/src/modules/doc/componentPlayground/componentPlayground.css +22 -0
- package/src/modules/doc/componentPlayground/componentPlayground.html +20 -0
- package/src/modules/doc/componentPlayground/componentPlayground.ts +42 -0
- package/src/modules/doc/content/content.css +70 -76
- package/src/modules/doc/content/content.html +1 -0
- package/src/modules/doc/content/content.ts +26 -47
- package/src/modules/doc/contentCallout/contentCallout.css +15 -7
- package/src/modules/doc/contentCallout/contentCallout.html +13 -4
- package/src/modules/doc/contentCallout/contentCallout.ts +14 -2
- package/src/modules/doc/contentLayout/contentLayout.css +1 -100
- package/src/modules/doc/contentLayout/contentLayout.html +30 -17
- package/src/modules/doc/contentLayout/contentLayout.ts +354 -65
- package/src/modules/doc/doDont/doDont.css +47 -0
- package/src/modules/doc/doDont/doDont.html +27 -0
- package/src/modules/doc/doDont/doDont.ts +17 -0
- package/src/modules/doc/header/header.css +65 -36
- package/src/modules/doc/header/header.html +41 -139
- package/src/modules/doc/header/header.ts +54 -76
- package/src/modules/doc/heading/heading.css +16 -37
- package/src/modules/doc/heading/heading.html +4 -4
- package/src/modules/doc/heading/heading.ts +12 -10
- package/src/modules/doc/headingAnchor/headingAnchor.css +2 -2
- package/src/modules/doc/headingAnchor/headingAnchor.ts +2 -2
- package/src/modules/doc/headingContent/headingContent.css +6 -8
- package/src/modules/doc/headingContent/headingContent.html +9 -15
- package/src/modules/doc/headingContent/headingContent.ts +2 -14
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.css +1 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.html +68 -0
- package/src/modules/doc/lwcContentLayout/lwcContentLayout.ts +256 -0
- package/src/modules/doc/overview/overview.css +40 -0
- package/src/modules/doc/overview/overview.html +34 -0
- package/src/modules/doc/overview/overview.ts +12 -0
- package/src/modules/doc/phase/phase.css +18 -3
- package/src/modules/doc/phase/phase.html +15 -3
- package/src/modules/doc/phase/phase.ts +44 -8
- package/src/modules/doc/specificationContent/specificationContent.css +36 -0
- package/src/modules/doc/specificationContent/specificationContent.html +167 -0
- package/src/modules/doc/specificationContent/specificationContent.ts +127 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.html +20 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.scoped.css +16 -0
- package/src/modules/doc/sprigSurvey/sprigSurvey.ts +16 -0
- package/src/modules/doc/toc/toc.ts +1 -1
- package/src/modules/doc/versionPicker/versionPicker.css +64 -0
- package/src/modules/doc/versionPicker/versionPicker.html +38 -0
- package/src/modules/doc/versionPicker/versionPicker.ts +65 -0
- package/src/modules/doc/xmlContent/types.ts +12 -3
- package/src/modules/doc/xmlContent/utils.ts +17 -12
- package/src/modules/doc/xmlContent/xmlContent.css +32 -3
- package/src/modules/doc/xmlContent/xmlContent.html +41 -15
- package/src/modules/doc/xmlContent/xmlContent.ts +295 -95
- package/src/modules/docHelpers/amfStyle/amfStyle.css +10 -45
- package/src/modules/docHelpers/contentLayoutStyle/contentLayoutStyle.css +131 -0
- package/src/modules/docHelpers/imgStyle/imgStyle.css +59 -0
- package/src/modules/docHelpers/status/status.css +1 -1
- package/src/modules/docUtils/{SearchSyncer/SearchSyncer.ts → searchSyncer/searchSyncer.ts} +1 -0
- package/src/modules/docUtils/utils/__mocks__/coveo.analytics.ts +16 -0
- package/src/modules/docUtils/utils/coveo.analytics.d.ts +10 -0
- package/src/modules/docUtils/utils/utils.ts +32 -0
- package/LICENSE +0 -12
- package/src/modules/doc/amfReference/route-meta.ts +0 -22
- package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +0 -93
- 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 "
|
|
6
|
-
import {
|
|
5
|
+
import { AmfModelParser } from "doc/amfModelParser";
|
|
6
|
+
import { normalizeBoolean, toJson } from "dxUtils/normalizers";
|
|
7
|
+
import type { OptionWithLink } from "typings/custom";
|
|
7
8
|
import type {
|
|
8
9
|
AmfConfig,
|
|
9
10
|
AmfMetadataTopic,
|
|
@@ -14,94 +15,62 @@ import type {
|
|
|
14
15
|
TopicModel,
|
|
15
16
|
ReferenceVersion,
|
|
16
17
|
ReferenceSetConfig,
|
|
17
|
-
AmfMetaTopicType
|
|
18
|
+
AmfMetaTopicType,
|
|
19
|
+
RouteMeta,
|
|
20
|
+
ParsedMarkdownTopic
|
|
18
21
|
} from "./types";
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
childrenPropertyName: "docs",
|
|
37
|
-
type: "documentation"
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
label: "Types",
|
|
41
|
-
name: "types",
|
|
42
|
-
childrenPropertyName: "types",
|
|
43
|
-
type: "type"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
label: "Security",
|
|
47
|
-
name: "security",
|
|
48
|
-
childrenPropertyName: "security",
|
|
49
|
-
type: "security"
|
|
50
|
-
}
|
|
51
|
-
];
|
|
52
|
-
|
|
53
|
-
const URL_CONFIG = {
|
|
54
|
-
summary: {
|
|
55
|
-
urlIdentifer: "label"
|
|
56
|
-
},
|
|
57
|
-
endpoint: {
|
|
58
|
-
urlIdentifer: "path"
|
|
59
|
-
},
|
|
60
|
-
method: {
|
|
61
|
-
urlIdentifer: "label"
|
|
62
|
-
},
|
|
63
|
-
documentation: {
|
|
64
|
-
urlIdentifer: "label"
|
|
65
|
-
},
|
|
66
|
-
type: {
|
|
67
|
-
urlIdentifer: "label",
|
|
68
|
-
prefix: "type:"
|
|
69
|
-
},
|
|
70
|
-
security: {
|
|
71
|
-
urlIdentifer: "label",
|
|
72
|
-
prefix: "security:"
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const urlHashToMetaRedirectMap = {
|
|
77
|
-
"commerce-api-assignments:Summary": "assignments:Summary",
|
|
78
|
-
"commerce-api-campaigns:Summary": "campaigns:Summary",
|
|
79
|
-
"commerce-api-catalogs:Summary": "catalogs:Summary",
|
|
80
|
-
"cdn-zones:Summary": "cdn-api-process-apis:Summary",
|
|
81
|
-
"inventory-impex:Summary": "impex:Summary",
|
|
82
|
-
"inventory-reservations:Summary": "inventory-reservation-service:Summary",
|
|
83
|
-
"shopper-login-and-api-access-service:Summary": "shopper-login:Summary",
|
|
84
|
-
"shopper-login-and-api-access-service-admin:Summary": "slas-admin:Summary",
|
|
85
|
-
"einstein-recommendations:Summary": "einstein-api-quick-start-guide:Summary"
|
|
23
|
+
import {
|
|
24
|
+
NAVIGATION_ITEMS,
|
|
25
|
+
URL_CONFIG,
|
|
26
|
+
REFERENCE_TYPES,
|
|
27
|
+
oldReferenceIdNewReferenceIdMap
|
|
28
|
+
} from "./constants";
|
|
29
|
+
import { restoreScroll } from "dx/scrollManager";
|
|
30
|
+
import { DocPhaseInfo } from "typings/custom";
|
|
31
|
+
import { logCoveoPageView, oldVersionDocInfo } from "docUtils/utils";
|
|
32
|
+
|
|
33
|
+
type NavigationItem = {
|
|
34
|
+
label: string;
|
|
35
|
+
name: string;
|
|
36
|
+
isExpanded: boolean;
|
|
37
|
+
children: ParsedMarkdownTopic[];
|
|
38
|
+
isChildrenLoading: boolean;
|
|
86
39
|
};
|
|
87
40
|
|
|
88
41
|
export default class AmfReference extends LightningElement {
|
|
89
|
-
@api breadcrumbs
|
|
90
|
-
@api sidebarHeader
|
|
42
|
+
@api breadcrumbs: string | null = null;
|
|
43
|
+
@api sidebarHeader!: string;
|
|
91
44
|
@api coveoOrganizationId!: string;
|
|
92
45
|
@api coveoPublicAccessToken!: string;
|
|
93
|
-
@api
|
|
46
|
+
@api coveoAnalyticsToken!: string;
|
|
94
47
|
@api coveoSearchHub!: string;
|
|
95
|
-
@api useOldSidebar
|
|
48
|
+
@api useOldSidebar: boolean = false;
|
|
49
|
+
@api tocTitle?: string;
|
|
50
|
+
@api tocOptions?: string;
|
|
51
|
+
@api languages!: OptionWithLink[];
|
|
52
|
+
@api language!: string;
|
|
53
|
+
@api hideFooter = false;
|
|
54
|
+
@track navigation = [] as NavigationItem[];
|
|
55
|
+
@track versions: Array<ReferenceVersion> = [];
|
|
56
|
+
@track showVersionBanner = false;
|
|
57
|
+
@track _coveoAdvancedQueryConfig!: { [key: string]: any };
|
|
96
58
|
|
|
97
59
|
// Update this to update what component gets rendered in the content block
|
|
98
60
|
@track
|
|
99
|
-
protected topicModel
|
|
61
|
+
protected topicModel!: TopicModel;
|
|
100
62
|
|
|
101
63
|
get isVersionEnabled(): boolean {
|
|
102
64
|
return !!this._referenceSetConfig?.versions?.length;
|
|
103
65
|
}
|
|
104
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Gives if the currently selected reference is spec based or not
|
|
69
|
+
*/
|
|
70
|
+
get showSpecBasedReference(): boolean {
|
|
71
|
+
return this.isSpecBasedReference(this._currentReferenceId);
|
|
72
|
+
}
|
|
73
|
+
|
|
105
74
|
@api
|
|
106
75
|
get referenceSetConfig(): ReferenceSetConfig {
|
|
107
76
|
return this._referenceSetConfig;
|
|
@@ -122,27 +91,57 @@ export default class AmfReference extends LightningElement {
|
|
|
122
91
|
this._referenceSetConfig = refConfig;
|
|
123
92
|
} catch (e) {
|
|
124
93
|
this._referenceSetConfig = {
|
|
125
|
-
refList: []
|
|
94
|
+
refList: [],
|
|
95
|
+
versions: []
|
|
126
96
|
};
|
|
127
97
|
}
|
|
128
98
|
|
|
99
|
+
this._amfConfigList = this._referenceSetConfig.refList || [];
|
|
100
|
+
|
|
101
|
+
this._amfConfigList.forEach((amfConfig) => {
|
|
102
|
+
this._amfConfigMap.set(amfConfig.id, amfConfig);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (this._amfConfigList.length > 0) {
|
|
106
|
+
this._currentReferenceId =
|
|
107
|
+
this._referenceSetConfig.refId || this._amfConfigList[0].id;
|
|
108
|
+
}
|
|
109
|
+
|
|
129
110
|
if (this.isVersionEnabled) {
|
|
130
111
|
const selectedVersion = this.getSelectedVersion();
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* If current selected is markdown based reference,
|
|
115
|
+
* We will assign versions once the selected item url is updated
|
|
116
|
+
*/
|
|
117
|
+
if (this.isSpecBasedReference(this._currentReferenceId)) {
|
|
118
|
+
this.versions = this.getVersions();
|
|
119
|
+
}
|
|
135
120
|
this.selectedVersion = selectedVersion;
|
|
121
|
+
if (this.isSpecBasedReference(this._currentReferenceId)) {
|
|
122
|
+
this.isVersionFetched = true;
|
|
123
|
+
if (this.oldVersionInfo) {
|
|
124
|
+
this.showVersionBanner = true;
|
|
125
|
+
} else {
|
|
126
|
+
this.latestVersion = true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
136
129
|
} else {
|
|
137
|
-
this.
|
|
130
|
+
this.isVersionFetched = true;
|
|
138
131
|
}
|
|
139
132
|
|
|
140
|
-
|
|
133
|
+
// This is to check if the url is hash based and redirect if needed
|
|
134
|
+
const redirectUrl = this.getHashBasedRedirectUrl();
|
|
135
|
+
if (redirectUrl) {
|
|
136
|
+
window.location.href = redirectUrl;
|
|
137
|
+
} else {
|
|
138
|
+
this.updateAmfConfigInView();
|
|
139
|
+
}
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
@api
|
|
144
|
-
get docPhaseInfo() {
|
|
145
|
-
return this.selectedReferenceDocPhase;
|
|
143
|
+
get docPhaseInfo(): string | null {
|
|
144
|
+
return this.selectedReferenceDocPhase || null;
|
|
146
145
|
}
|
|
147
146
|
|
|
148
147
|
set docPhaseInfo(value: string) {
|
|
@@ -152,53 +151,83 @@ export default class AmfReference extends LightningElement {
|
|
|
152
151
|
}
|
|
153
152
|
}
|
|
154
153
|
|
|
154
|
+
@api
|
|
155
|
+
get expandChildren() {
|
|
156
|
+
return this._expandChildren;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
set expandChildren(value) {
|
|
160
|
+
this._expandChildren = normalizeBoolean(value);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/*
|
|
164
|
+
* The get coveoAdvancedQueryConfig() method returns this._coveoAdvancedQueryConfig,
|
|
165
|
+
* but before returning it, it checks if there are multiple versions (this.versions.length > 1)
|
|
166
|
+
* and if a version is selected (this.selectedVersion). If both conditions are met,
|
|
167
|
+
* it updates the version property of this._coveoAdvancedQueryConfig with the selected version.
|
|
168
|
+
*/
|
|
169
|
+
@api
|
|
170
|
+
get coveoAdvancedQueryConfig(): { [key: string]: any } {
|
|
171
|
+
const coveoConfig = this._coveoAdvancedQueryConfig;
|
|
172
|
+
if (this.versions.length > 1 && this.selectedVersion) {
|
|
173
|
+
const currentGAVersionRef = this.versions[0];
|
|
174
|
+
if (this.selectedVersion.id !== currentGAVersionRef.id) {
|
|
175
|
+
// Currently Coveo only supports query without "v"
|
|
176
|
+
const version = this.selectedVersion.id.replace("v", "");
|
|
177
|
+
coveoConfig.version = version;
|
|
178
|
+
this._coveoAdvancedQueryConfig = coveoConfig;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return this._coveoAdvancedQueryConfig;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
set coveoAdvancedQueryConfig(config) {
|
|
185
|
+
this._coveoAdvancedQueryConfig = toJson(config);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private get enableFooter(): boolean {
|
|
189
|
+
return !this.hideFooter;
|
|
190
|
+
}
|
|
191
|
+
|
|
155
192
|
// model
|
|
156
|
-
protected
|
|
157
|
-
protected
|
|
193
|
+
protected _amfConfigList: AmfConfig[] = [];
|
|
194
|
+
protected _amfConfigMap: Map<string, AmfConfig> = new Map();
|
|
195
|
+
protected _referenceSetConfig!: ReferenceSetConfig;
|
|
158
196
|
protected _currentReferenceId = "";
|
|
159
197
|
|
|
198
|
+
protected parentReferenceUrls = [] as string[];
|
|
160
199
|
protected amfMap: Record<string, AmfModelRecord> = {};
|
|
161
|
-
protected amfFetchPromiseMap = {};
|
|
200
|
+
protected amfFetchPromiseMap = {} as any;
|
|
162
201
|
protected metadata: { [key: string]: AmfMetadataTopic } = {};
|
|
163
|
-
protected selectedTopic
|
|
164
|
-
protected
|
|
165
|
-
protected selectedSidebarValue = undefined;
|
|
166
|
-
protected versions: Array<ReferenceVersion> = [];
|
|
167
|
-
protected selectedVersion: ReferenceVersion = null;
|
|
202
|
+
protected selectedTopic?: AmfMetaTopicType = undefined;
|
|
203
|
+
protected selectedSidebarValue: string | undefined = undefined;
|
|
168
204
|
|
|
169
|
-
|
|
170
|
-
private navAmfOrder = [];
|
|
205
|
+
protected selectedVersion: ReferenceVersion | null = null;
|
|
171
206
|
|
|
172
|
-
private
|
|
207
|
+
private hasRendered = false;
|
|
173
208
|
|
|
174
209
|
private isParentLevelDocPhaseEnabled = false;
|
|
175
|
-
private selectedReferenceDocPhase?: string = null;
|
|
210
|
+
private selectedReferenceDocPhase?: string | null = null;
|
|
211
|
+
private _expandChildren?: boolean = false;
|
|
212
|
+
private isVersionFetched = false;
|
|
213
|
+
private latestVersion = false;
|
|
176
214
|
|
|
177
215
|
/**
|
|
178
|
-
* Key for storing the currently selected reference
|
|
179
|
-
* previously selected reference
|
|
216
|
+
* Key for storing the currently selected reference url. This will be used to save the
|
|
217
|
+
* previously selected reference url and restoring it when changing between reference versions.
|
|
180
218
|
*/
|
|
181
|
-
private readonly
|
|
219
|
+
private readonly docsReferenceUrlSessionKey: string = "docsReferenceUrl";
|
|
182
220
|
|
|
183
221
|
_boundOnApiNavigationChanged;
|
|
184
222
|
_boundUpdateSelectedItemFromUrlQuery;
|
|
185
223
|
|
|
186
|
-
get amfConfigMapped(): AmfConfig[] {
|
|
187
|
-
return this._amfConfig.map((config) => {
|
|
188
|
-
return config.id in this.amfMap
|
|
189
|
-
? Object.assign(config, this.amfMap[config.id])
|
|
190
|
-
: config;
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
|
|
194
224
|
constructor() {
|
|
195
225
|
super();
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
this._boundUpdateSelectedItemFromUrlQuery =
|
|
200
|
-
this
|
|
201
|
-
);
|
|
226
|
+
|
|
227
|
+
this._boundOnApiNavigationChanged =
|
|
228
|
+
this.onApiNavigationChanged.bind(this);
|
|
229
|
+
this._boundUpdateSelectedItemFromUrlQuery =
|
|
230
|
+
this.updateSelectedItemFromUrlQuery.bind(this);
|
|
202
231
|
}
|
|
203
232
|
|
|
204
233
|
connectedCallback(): void {
|
|
@@ -226,7 +255,7 @@ export default class AmfReference extends LightningElement {
|
|
|
226
255
|
renderedCallback(): void {
|
|
227
256
|
if (!this.hasRendered) {
|
|
228
257
|
this.hasRendered = true;
|
|
229
|
-
if (this.
|
|
258
|
+
if (this._amfConfigList && this._amfConfigList.length) {
|
|
230
259
|
// If amfConfig has a value and length, it is assumed that fetch
|
|
231
260
|
// has already been called and promises stored.
|
|
232
261
|
this.updateView();
|
|
@@ -234,22 +263,136 @@ export default class AmfReference extends LightningElement {
|
|
|
234
263
|
}
|
|
235
264
|
}
|
|
236
265
|
|
|
266
|
+
/**
|
|
267
|
+
* Check if the URL hash to see whether this is one we want to redirect
|
|
268
|
+
* See GUS W-10718771 for references where we want hash-based redirects
|
|
269
|
+
* Return if we needs to redirect url to updated url
|
|
270
|
+
*/
|
|
271
|
+
private getHashBasedRedirectUrl(): string | undefined {
|
|
272
|
+
const { hash } = window.location;
|
|
273
|
+
let hashBasedRedirectUrl = "";
|
|
274
|
+
if (hash) {
|
|
275
|
+
const strippedHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
276
|
+
const strippedHashItems = strippedHash
|
|
277
|
+
? strippedHash.split(":")
|
|
278
|
+
: [];
|
|
279
|
+
if (strippedHashItems.length) {
|
|
280
|
+
const referenceId = strippedHashItems[0];
|
|
281
|
+
const meta = strippedHashItems[1];
|
|
282
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
283
|
+
const updatedReferenceId =
|
|
284
|
+
oldReferenceIdNewReferenceIdMap[referenceId];
|
|
285
|
+
const newReferenceId = updatedReferenceId || referenceId;
|
|
286
|
+
const referenceItemConfig =
|
|
287
|
+
this.getAmfConfigWithId(newReferenceId);
|
|
288
|
+
if (referenceItemConfig) {
|
|
289
|
+
hashBasedRedirectUrl = `${referenceItemConfig.href}?meta=${encodedMeta}`;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return hashBasedRedirectUrl;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* @param referenceId
|
|
298
|
+
* @returns AMFConfig with given reference Id
|
|
299
|
+
*/
|
|
300
|
+
private getAmfConfigWithId(referenceId: string): AmfConfig | undefined {
|
|
301
|
+
return this._amfConfigMap.get(referenceId);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* @param referenceId
|
|
306
|
+
* @returns if the reference is spec based one or not with given referenceId.
|
|
307
|
+
*/
|
|
308
|
+
private isSpecBasedReference(referenceId: string): boolean {
|
|
309
|
+
const selectedReference = this.getAmfConfigWithId(referenceId);
|
|
310
|
+
return selectedReference
|
|
311
|
+
? selectedReference.referenceType !== REFERENCE_TYPES.markdown
|
|
312
|
+
: false;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/*
|
|
316
|
+
* Refactor below method when sidebar allows sending extraData along with the name for each item.
|
|
317
|
+
* See if we can refactor the below method using regex.
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @param url
|
|
322
|
+
* @returns reference Id from url path / selected sidebar item.
|
|
323
|
+
*/
|
|
324
|
+
private getReferenceIdFromUrl(url: string): string {
|
|
325
|
+
let referenceId = "";
|
|
326
|
+
const urlItems = url.split("/references/");
|
|
327
|
+
if (urlItems.length > 1) {
|
|
328
|
+
const rightSidePart = urlItems[1];
|
|
329
|
+
|
|
330
|
+
//This covers urls like "/project-name/references/reference-id/..."
|
|
331
|
+
const slashSeparatorItems = rightSidePart.split("/");
|
|
332
|
+
|
|
333
|
+
//This covers urls like "/project-name/references/reference-id?meta=Summary"
|
|
334
|
+
const querySeparatorItems = slashSeparatorItems[0].split("?");
|
|
335
|
+
|
|
336
|
+
referenceId = querySeparatorItems[0];
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return referenceId;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private get oldVersionInfo(): DocPhaseInfo | null {
|
|
343
|
+
let info = null;
|
|
344
|
+
if (this.versions.length > 1 && this.selectedVersion) {
|
|
345
|
+
const currentGAVersionRef = this.versions[0];
|
|
346
|
+
if (this.selectedVersion.id !== currentGAVersionRef.id) {
|
|
347
|
+
info = oldVersionDocInfo(currentGAVersionRef.link.href);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return info;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* @returns versions to be shown in the dropdown
|
|
355
|
+
* For markdown based specs, Adds selected markdown topic url to same references
|
|
356
|
+
*/
|
|
357
|
+
private getVersions(): Array<ReferenceVersion> {
|
|
358
|
+
const allVersions = this._referenceSetConfig.versions;
|
|
359
|
+
if (!this.isSpecBasedReference(this._currentReferenceId)) {
|
|
360
|
+
const currentRefMeta = this.getMarkdownReferenceMeta(
|
|
361
|
+
window.location.href
|
|
362
|
+
);
|
|
363
|
+
if (currentRefMeta) {
|
|
364
|
+
for (let i = 0; i < allVersions.length; i++) {
|
|
365
|
+
const versionItem = allVersions[i];
|
|
366
|
+
const referenceLink = versionItem.link.href;
|
|
367
|
+
const referenceId =
|
|
368
|
+
this.getReferenceIdFromUrl(referenceLink);
|
|
369
|
+
if (this._currentReferenceId === referenceId) {
|
|
370
|
+
// This is to navigate to respective topic in the changed version
|
|
371
|
+
versionItem.link.href = `${referenceLink}/${currentRefMeta}`;
|
|
372
|
+
allVersions[i] = versionItem;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return allVersions;
|
|
378
|
+
}
|
|
379
|
+
|
|
237
380
|
/**
|
|
238
381
|
* Returns the selected version or the first available version.
|
|
239
382
|
*/
|
|
240
|
-
private getSelectedVersion(): ReferenceVersion {
|
|
383
|
+
private getSelectedVersion(): ReferenceVersion | null {
|
|
241
384
|
const versions = this._referenceSetConfig?.versions || [];
|
|
242
385
|
const selectedVersion = versions.find(
|
|
243
386
|
(v: ReferenceVersion) => v.selected
|
|
244
387
|
);
|
|
245
388
|
// return a selected version if there is one, else return the first one.
|
|
246
|
-
return selectedVersion || (versions.length && versions[0]);
|
|
389
|
+
return selectedVersion || (versions.length && versions[0]) || null;
|
|
247
390
|
}
|
|
248
391
|
|
|
249
392
|
private updateAmfConfigInView(): void {
|
|
250
|
-
if (this.
|
|
393
|
+
if (this._amfConfigList && this._amfConfigList.length) {
|
|
251
394
|
// fetch AMF Json as soon as config is set
|
|
252
|
-
this.
|
|
395
|
+
this.populateReferenceItems();
|
|
253
396
|
// update() must be called after renderedCallback.
|
|
254
397
|
if (this.hasRendered) {
|
|
255
398
|
this.updateView();
|
|
@@ -257,9 +400,11 @@ export default class AmfReference extends LightningElement {
|
|
|
257
400
|
}
|
|
258
401
|
}
|
|
259
402
|
|
|
260
|
-
private async fetchAmf(
|
|
403
|
+
private async fetchAmf(
|
|
404
|
+
amfConfig: AmfConfig
|
|
405
|
+
): Promise<AmfModel | AmfModel[]> {
|
|
261
406
|
const { amf } = amfConfig;
|
|
262
|
-
const response = await fetch(amf
|
|
407
|
+
const response = await fetch(amf!, {
|
|
263
408
|
headers: {
|
|
264
409
|
"Cache-Control": `max-age=86400`
|
|
265
410
|
}
|
|
@@ -269,17 +414,95 @@ export default class AmfReference extends LightningElement {
|
|
|
269
414
|
}
|
|
270
415
|
|
|
271
416
|
/**
|
|
272
|
-
*
|
|
273
|
-
* Stores each fetch promise for handling after renderCallback.
|
|
417
|
+
* Returns whether current location is project root path like ../example-project/references
|
|
274
418
|
*/
|
|
275
|
-
private
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
419
|
+
private isProjectRootPath(): boolean {
|
|
420
|
+
return this.getReferenceIdFromUrl(window.location.href) === "";
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Returns whether given url is parent reference path like ../example-project/references/reference-id
|
|
425
|
+
*/
|
|
426
|
+
private isParentReferencePath(urlPath?: string | null): boolean {
|
|
427
|
+
if (!urlPath) {
|
|
428
|
+
return false;
|
|
282
429
|
}
|
|
430
|
+
const parentReferenceIndex = this.parentReferenceUrls.findIndex(
|
|
431
|
+
(referenceUrl: string) => {
|
|
432
|
+
return urlPath.endsWith(referenceUrl);
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
return parentReferenceIndex !== -1;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Expands the children of Markdown-based References.
|
|
440
|
+
*/
|
|
441
|
+
private expandChildrenForMarkdownReferences(
|
|
442
|
+
children: ParsedMarkdownTopic[]
|
|
443
|
+
): void {
|
|
444
|
+
if (!children) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
for (const childNode of children) {
|
|
448
|
+
childNode.isExpanded = true;
|
|
449
|
+
this.expandChildrenForMarkdownReferences(childNode.children);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Populates reference Items from amfConfigList and assigns it to navigation for sidebar
|
|
455
|
+
*/
|
|
456
|
+
private populateReferenceItems(): void {
|
|
457
|
+
const navAmfOrder = [] as NavigationItem[];
|
|
458
|
+
for (const [index, amfConfig] of this._amfConfigList.entries()) {
|
|
459
|
+
let navItemChildren = [] as ParsedMarkdownTopic[];
|
|
460
|
+
let isChildrenLoading = false;
|
|
461
|
+
if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
|
|
462
|
+
if (amfConfig.isSelected) {
|
|
463
|
+
const amfPromise = this.fetchAmf(amfConfig).then(
|
|
464
|
+
(amfJson) => {
|
|
465
|
+
this.updateModel(amfConfig.id, amfJson);
|
|
466
|
+
this.assignNavigationItemsFromAmf(amfConfig, index);
|
|
467
|
+
}
|
|
468
|
+
);
|
|
469
|
+
this.amfFetchPromiseMap[amfConfig.id] = amfPromise;
|
|
470
|
+
}
|
|
471
|
+
isChildrenLoading = true;
|
|
472
|
+
} else {
|
|
473
|
+
const isExpandChildrenEnabled = this.isExpandChildrenEnabled(
|
|
474
|
+
amfConfig.id
|
|
475
|
+
);
|
|
476
|
+
// check whether we should expand all the child nodes, this is required for Coveo to crawl.
|
|
477
|
+
if (isExpandChildrenEnabled) {
|
|
478
|
+
this.expandChildrenForMarkdownReferences(
|
|
479
|
+
amfConfig.topic!.children
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
navItemChildren = amfConfig.topic!.children;
|
|
483
|
+
}
|
|
484
|
+
// store nav items for each spec in order
|
|
485
|
+
navAmfOrder[index] = {
|
|
486
|
+
label: amfConfig.title,
|
|
487
|
+
name: amfConfig.href,
|
|
488
|
+
isExpanded:
|
|
489
|
+
amfConfig.isSelected ||
|
|
490
|
+
this.isExpandChildrenEnabled(amfConfig.id),
|
|
491
|
+
children: navItemChildren,
|
|
492
|
+
isChildrenLoading
|
|
493
|
+
};
|
|
494
|
+
this.parentReferenceUrls.push(amfConfig.href);
|
|
495
|
+
}
|
|
496
|
+
this.navigation = navAmfOrder;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Returns a boolean indicating whether the children should be expanded or not.
|
|
501
|
+
*/
|
|
502
|
+
private isExpandChildrenEnabled(referenceId: string): boolean {
|
|
503
|
+
return (
|
|
504
|
+
!!this.expandChildren && this._currentReferenceId === referenceId
|
|
505
|
+
);
|
|
283
506
|
}
|
|
284
507
|
|
|
285
508
|
/**
|
|
@@ -311,7 +534,7 @@ export default class AmfReference extends LightningElement {
|
|
|
311
534
|
|
|
312
535
|
/**
|
|
313
536
|
* Transforms a list of model data for endpoints into corresponding
|
|
314
|
-
* navigation list items that
|
|
537
|
+
* navigation list items that are compatible with dx-sidebar.
|
|
315
538
|
* Compatible with transforming AMF data parsed from both RAML and OAS spec.
|
|
316
539
|
* Transforms a flat list of endpoints into a nested list based on indentation level
|
|
317
540
|
* for RAML spec.
|
|
@@ -319,29 +542,47 @@ export default class AmfReference extends LightningElement {
|
|
|
319
542
|
* @returns {array<Object>} List of navigation items
|
|
320
543
|
*/
|
|
321
544
|
private assignEndpointNavItems(
|
|
545
|
+
parentReferencePath: string,
|
|
322
546
|
referenceId: string,
|
|
323
547
|
items: ParsedTopicModel[]
|
|
324
548
|
): NavItem[] {
|
|
325
|
-
const methodList = [];
|
|
549
|
+
const methodList = [] as NavItem[];
|
|
326
550
|
|
|
327
551
|
items.forEach((item) => {
|
|
328
552
|
item.methods?.forEach((method) => {
|
|
329
|
-
const
|
|
553
|
+
const title =
|
|
554
|
+
this.getTitleForLabel(method.label!) || method.method;
|
|
555
|
+
const meta = this.addToMetadata(
|
|
556
|
+
parentReferencePath,
|
|
557
|
+
referenceId,
|
|
558
|
+
"method",
|
|
559
|
+
method,
|
|
560
|
+
title
|
|
561
|
+
);
|
|
330
562
|
methodList.push(
|
|
331
563
|
Object.assign(method, {
|
|
332
|
-
name: this.getReferencePathWithMeta(
|
|
333
|
-
|
|
334
|
-
|
|
564
|
+
name: this.getReferencePathWithMeta(
|
|
565
|
+
parentReferencePath,
|
|
566
|
+
meta
|
|
567
|
+
),
|
|
568
|
+
label: title
|
|
335
569
|
})
|
|
336
570
|
);
|
|
337
571
|
});
|
|
338
572
|
});
|
|
339
|
-
|
|
340
573
|
return methodList;
|
|
341
574
|
}
|
|
342
575
|
|
|
343
|
-
|
|
344
|
-
|
|
576
|
+
/**
|
|
577
|
+
* Gives URL path for reference items, Which can be used to push to the history
|
|
578
|
+
*/
|
|
579
|
+
private getReferencePathWithMeta(
|
|
580
|
+
parentReferencePath: string,
|
|
581
|
+
meta: string
|
|
582
|
+
): string {
|
|
583
|
+
// update the encoded url meta param
|
|
584
|
+
const encodedMeta = meta ? this.getUrlEncoded(meta) : "";
|
|
585
|
+
return encodedMeta ? `${parentReferencePath}?meta=${encodedMeta}` : "";
|
|
345
586
|
}
|
|
346
587
|
|
|
347
588
|
/**
|
|
@@ -351,12 +592,15 @@ export default class AmfReference extends LightningElement {
|
|
|
351
592
|
* The 'endpoint' nav item may have nested children.
|
|
352
593
|
*/
|
|
353
594
|
private assignNavigationItemsFromAmf(
|
|
354
|
-
|
|
595
|
+
amfConfig: AmfConfig,
|
|
355
596
|
amfIdx: number
|
|
356
597
|
): void {
|
|
598
|
+
const referenceId = amfConfig.id;
|
|
599
|
+
const parentReferencePath = amfConfig.href;
|
|
357
600
|
const model = this.amfMap[referenceId].parser.parsedModel;
|
|
358
601
|
|
|
359
|
-
const children = [];
|
|
602
|
+
const children: any[] = [];
|
|
603
|
+
const expandChildren = this.isExpandChildrenEnabled(referenceId);
|
|
360
604
|
|
|
361
605
|
NAVIGATION_ITEMS.forEach(
|
|
362
606
|
({ label, name, childrenPropertyName, type }) => {
|
|
@@ -365,58 +609,67 @@ export default class AmfReference extends LightningElement {
|
|
|
365
609
|
case "summary": {
|
|
366
610
|
const summary = model[type];
|
|
367
611
|
const meta = this.addToMetadata(
|
|
612
|
+
parentReferencePath,
|
|
368
613
|
referenceId,
|
|
369
614
|
type,
|
|
370
|
-
summary
|
|
615
|
+
summary,
|
|
616
|
+
label
|
|
371
617
|
);
|
|
372
618
|
children.push({
|
|
373
619
|
label,
|
|
374
|
-
name: this.getReferencePathWithMeta(
|
|
620
|
+
name: this.getReferencePathWithMeta(
|
|
621
|
+
parentReferencePath,
|
|
622
|
+
meta
|
|
623
|
+
)
|
|
375
624
|
});
|
|
376
625
|
break;
|
|
377
626
|
}
|
|
378
627
|
case "endpoint":
|
|
379
628
|
if (
|
|
380
|
-
model[childrenPropertyName] &&
|
|
381
|
-
model[childrenPropertyName].length
|
|
629
|
+
model[childrenPropertyName!] &&
|
|
630
|
+
model[childrenPropertyName!].length
|
|
382
631
|
) {
|
|
383
632
|
const amfTopicId = this.getFormattedIdentifier(
|
|
384
633
|
referenceId,
|
|
385
634
|
indexedName
|
|
386
635
|
);
|
|
387
636
|
const childTopics = this.assignEndpointNavItems(
|
|
637
|
+
parentReferencePath,
|
|
388
638
|
referenceId,
|
|
389
|
-
model[childrenPropertyName]
|
|
639
|
+
model[childrenPropertyName!]
|
|
390
640
|
);
|
|
391
641
|
children.push({
|
|
392
642
|
label,
|
|
393
643
|
name: this.getReferencePathWithMeta(
|
|
644
|
+
parentReferencePath,
|
|
394
645
|
this.metadata[amfTopicId]?.meta
|
|
395
646
|
),
|
|
396
|
-
isExpanded:
|
|
647
|
+
isExpanded: expandChildren,
|
|
397
648
|
children: childTopics
|
|
398
649
|
});
|
|
399
650
|
}
|
|
400
651
|
break;
|
|
401
652
|
case "security":
|
|
402
653
|
case "type":
|
|
403
|
-
if (model[childrenPropertyName]?.length) {
|
|
654
|
+
if (model[childrenPropertyName!]?.length) {
|
|
404
655
|
// Sorting the types alphabetically
|
|
405
|
-
model[childrenPropertyName].sort(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
656
|
+
model[childrenPropertyName!].sort(
|
|
657
|
+
(typeA: any, typeB: any) => {
|
|
658
|
+
const typeALbl = typeA.label.toLowerCase();
|
|
659
|
+
const typeBLbl = typeB.label.toLowerCase();
|
|
660
|
+
return typeALbl < typeBLbl
|
|
661
|
+
? -1
|
|
662
|
+
: typeALbl > typeBLbl
|
|
663
|
+
? 1
|
|
664
|
+
: 0;
|
|
665
|
+
}
|
|
666
|
+
);
|
|
414
667
|
}
|
|
415
668
|
// eslint-disable-next-line no-fallthrough
|
|
416
669
|
default:
|
|
417
670
|
if (
|
|
418
|
-
model[childrenPropertyName] &&
|
|
419
|
-
model[childrenPropertyName].length
|
|
671
|
+
model[childrenPropertyName!] &&
|
|
672
|
+
model[childrenPropertyName!].length
|
|
420
673
|
) {
|
|
421
674
|
const amfTopicId = this.getFormattedIdentifier(
|
|
422
675
|
referenceId,
|
|
@@ -425,19 +678,23 @@ export default class AmfReference extends LightningElement {
|
|
|
425
678
|
children.push({
|
|
426
679
|
label,
|
|
427
680
|
name: this.getReferencePathWithMeta(
|
|
681
|
+
parentReferencePath,
|
|
428
682
|
this.metadata[amfTopicId]?.meta
|
|
429
683
|
),
|
|
430
|
-
isExpanded:
|
|
431
|
-
children: model[childrenPropertyName].map(
|
|
432
|
-
(topic) => {
|
|
684
|
+
isExpanded: expandChildren,
|
|
685
|
+
children: model[childrenPropertyName!].map(
|
|
686
|
+
(topic: any) => {
|
|
433
687
|
const meta = this.addToMetadata(
|
|
688
|
+
parentReferencePath,
|
|
434
689
|
referenceId,
|
|
435
690
|
type,
|
|
436
|
-
topic
|
|
691
|
+
topic,
|
|
692
|
+
topic.label
|
|
437
693
|
);
|
|
438
694
|
return {
|
|
439
695
|
label: topic.label,
|
|
440
696
|
name: this.getReferencePathWithMeta(
|
|
697
|
+
parentReferencePath,
|
|
441
698
|
meta
|
|
442
699
|
)
|
|
443
700
|
};
|
|
@@ -449,47 +706,48 @@ export default class AmfReference extends LightningElement {
|
|
|
449
706
|
}
|
|
450
707
|
);
|
|
451
708
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
isExpanded: amfIdx === 0, // only expand the first spec
|
|
457
|
-
children
|
|
709
|
+
this.navigation[amfIdx] = {
|
|
710
|
+
...this.navigation[amfIdx],
|
|
711
|
+
children,
|
|
712
|
+
isChildrenLoading: false
|
|
458
713
|
};
|
|
459
|
-
|
|
460
|
-
// update navigation with each specs nav items as they become available
|
|
461
|
-
// navigation has to be an array because dx-sidebar expects an array.
|
|
462
|
-
const navigation = [];
|
|
463
|
-
for (const navAmf of this.navAmfOrder) {
|
|
464
|
-
if (navAmf) {
|
|
465
|
-
navigation.push(navAmf);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
this.navigation = navigation;
|
|
714
|
+
this.navigation = [...this.navigation];
|
|
469
715
|
}
|
|
470
716
|
|
|
471
717
|
protected addToMetadata(
|
|
718
|
+
parentReferencePath: string,
|
|
472
719
|
referenceId: string,
|
|
473
720
|
type: string,
|
|
474
|
-
topic: { id: string; domId: string }
|
|
721
|
+
topic: { id: string; domId: string },
|
|
722
|
+
navTitle: string
|
|
475
723
|
): string {
|
|
476
|
-
const
|
|
724
|
+
const config = URL_CONFIG[type as keyof typeof URL_CONFIG];
|
|
725
|
+
const urlIdentifer = config.urlIdentifer;
|
|
726
|
+
let prefix = null;
|
|
727
|
+
if ("prefix" in config) {
|
|
728
|
+
prefix = config.prefix;
|
|
729
|
+
}
|
|
477
730
|
|
|
478
731
|
// encodeURI to avoid special characters in the URL meta.
|
|
479
732
|
const identifier =
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
meta:
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
733
|
+
urlIdentifer in topic &&
|
|
734
|
+
this.encodeIdentifier(topic[urlIdentifer as keyof typeof topic]);
|
|
735
|
+
let meta;
|
|
736
|
+
// Assuming that there will be an identifier always
|
|
737
|
+
if (identifier) {
|
|
738
|
+
meta = prefix ? `${prefix}${identifier}` : `${identifier}`;
|
|
739
|
+
this.metadata[meta] = {
|
|
740
|
+
parentReferencePath,
|
|
741
|
+
meta,
|
|
742
|
+
referenceId,
|
|
743
|
+
amfId: topic.id,
|
|
744
|
+
elementId: topic.domId,
|
|
745
|
+
identifier,
|
|
746
|
+
type,
|
|
747
|
+
navTitle
|
|
748
|
+
};
|
|
749
|
+
}
|
|
750
|
+
return meta!;
|
|
493
751
|
}
|
|
494
752
|
|
|
495
753
|
/**
|
|
@@ -500,7 +758,7 @@ export default class AmfReference extends LightningElement {
|
|
|
500
758
|
(metadata: AmfMetadataTopic) => {
|
|
501
759
|
return routeMeta.meta === metadata.meta;
|
|
502
760
|
}
|
|
503
|
-
)
|
|
761
|
+
)!;
|
|
504
762
|
}
|
|
505
763
|
|
|
506
764
|
/**
|
|
@@ -514,7 +772,7 @@ export default class AmfReference extends LightningElement {
|
|
|
514
772
|
return Object.values(this.metadata).find(
|
|
515
773
|
(metadata: AmfMetadataTopic) =>
|
|
516
774
|
referenceId === metadata.referenceId && amfId === metadata.amfId
|
|
517
|
-
)
|
|
775
|
+
)!;
|
|
518
776
|
}
|
|
519
777
|
|
|
520
778
|
/**
|
|
@@ -529,7 +787,7 @@ export default class AmfReference extends LightningElement {
|
|
|
529
787
|
(metadata: AmfMetadataTopic) =>
|
|
530
788
|
referenceId === metadata.referenceId &&
|
|
531
789
|
identifier === metadata.identifier
|
|
532
|
-
)
|
|
790
|
+
)!;
|
|
533
791
|
}
|
|
534
792
|
|
|
535
793
|
/**
|
|
@@ -543,58 +801,29 @@ export default class AmfReference extends LightningElement {
|
|
|
543
801
|
return Object.values(this.metadata).find(
|
|
544
802
|
(metadata: AmfMetadataTopic) =>
|
|
545
803
|
referenceId === metadata.referenceId && type === metadata.type
|
|
546
|
-
)
|
|
804
|
+
)!;
|
|
547
805
|
}
|
|
548
806
|
|
|
549
807
|
/**
|
|
550
|
-
* Parses
|
|
808
|
+
* Parses URL query params without decoding of params
|
|
551
809
|
*/
|
|
552
|
-
private parseParams(
|
|
553
|
-
if (!
|
|
810
|
+
private parseParams(params: string): qs.ParsedQuery<string> {
|
|
811
|
+
if (!params) {
|
|
554
812
|
return {};
|
|
555
813
|
}
|
|
556
|
-
return qs.parse(
|
|
814
|
+
return qs.parse(params, {
|
|
557
815
|
decode: false
|
|
558
816
|
});
|
|
559
817
|
}
|
|
560
818
|
|
|
561
|
-
/**
|
|
562
|
-
* Gets the portion from the URL query param 'meta'.
|
|
563
|
-
*/
|
|
564
|
-
protected getCurrentRefMeta(
|
|
565
|
-
previousRefMetaInSession?: string
|
|
566
|
-
): RouteMeta | null {
|
|
567
|
-
const path = window.location.search;
|
|
568
|
-
const urlParams = this.parseParams(path);
|
|
569
|
-
let meta = urlParams.meta as string;
|
|
570
|
-
let routeMeta = null;
|
|
571
|
-
if (previousRefMetaInSession) {
|
|
572
|
-
const refParts = previousRefMetaInSession.split(":");
|
|
573
|
-
const newRefId = refParts.length > 0 ? refParts[0] : null;
|
|
574
|
-
const [, type, topicId] = previousRefMetaInSession.split(":");
|
|
575
|
-
meta = newRefId ? [newRefId, type, topicId].join(":") : null;
|
|
576
|
-
} else if (!meta) {
|
|
577
|
-
// If no `meta` explicitly exists, check the URL hash to see whether this is one we
|
|
578
|
-
// want to redirect (see GUS W-10718771 for one reference where we want hash-based
|
|
579
|
-
// redirects)
|
|
580
|
-
const { hash } = window.location;
|
|
581
|
-
const strippedHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
582
|
-
meta = urlHashToMetaRedirectMap[strippedHash];
|
|
583
|
-
}
|
|
584
|
-
if (meta) {
|
|
585
|
-
routeMeta = new RouteMeta(meta);
|
|
586
|
-
}
|
|
587
|
-
return routeMeta;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
819
|
/**
|
|
591
820
|
* Normalizes topic identifier by replacing spaces with '+'
|
|
592
821
|
* and running encodeURI() on it
|
|
593
|
-
* @param
|
|
822
|
+
* @param identifier raw identifier for a topic as parsed from the spec file
|
|
594
823
|
* @returns normalized and encoded identifier
|
|
595
824
|
*/
|
|
596
|
-
protected encodeIdentifier(
|
|
597
|
-
let result =
|
|
825
|
+
protected encodeIdentifier(identifier: string): string {
|
|
826
|
+
let result = identifier.trim();
|
|
598
827
|
result = result.replace(new RegExp(/\s+/, "g"), "+");
|
|
599
828
|
return encodeURI(result);
|
|
600
829
|
}
|
|
@@ -606,86 +835,137 @@ export default class AmfReference extends LightningElement {
|
|
|
606
835
|
return `${referenceId}:${id}`;
|
|
607
836
|
}
|
|
608
837
|
|
|
609
|
-
protected
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
const {
|
|
614
|
-
referenceId,
|
|
615
|
-
amfId,
|
|
616
|
-
type,
|
|
617
|
-
elementId
|
|
618
|
-
}: AmfMetadataTopic = metadata;
|
|
619
|
-
this.loadContent(
|
|
620
|
-
referenceId,
|
|
621
|
-
amfId,
|
|
622
|
-
type,
|
|
623
|
-
elementId,
|
|
624
|
-
currentMeta.meta
|
|
625
|
-
);
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
protected onApiNavigationChanged(): void {
|
|
629
|
-
// The API Navigation event will always intend to navigate within the current reference
|
|
630
|
-
const metadata = this.metadata[
|
|
631
|
-
this.getReferencePathWithMeta(this.selectedTopic.meta)
|
|
632
|
-
];
|
|
633
|
-
const {
|
|
634
|
-
referenceId,
|
|
635
|
-
amfId,
|
|
636
|
-
type,
|
|
637
|
-
elementId
|
|
638
|
-
}: AmfMetadataTopic = metadata;
|
|
639
|
-
this.loadContent(referenceId, amfId, type, elementId, metadata.meta);
|
|
640
|
-
this.updateUrlWithSelected();
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
protected updateUrlWithSelected(meta?: string): void {
|
|
838
|
+
protected updateUrlWithSelected(
|
|
839
|
+
parentReferencePath: string,
|
|
840
|
+
meta?: string
|
|
841
|
+
): void {
|
|
644
842
|
if (meta) {
|
|
843
|
+
// update the encoded url meta param
|
|
844
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
845
|
+
|
|
645
846
|
window.history.pushState(
|
|
646
847
|
{},
|
|
647
848
|
"",
|
|
648
|
-
`${
|
|
849
|
+
`${parentReferencePath}?meta=${encodedMeta}`
|
|
649
850
|
);
|
|
650
851
|
}
|
|
651
852
|
}
|
|
652
853
|
|
|
653
854
|
/**
|
|
654
|
-
* Does a replace on the
|
|
855
|
+
* Does a replace on the URL meta, so it does not create a history entry.
|
|
655
856
|
*/
|
|
656
|
-
protected replaceUrlWithSelected(
|
|
857
|
+
protected replaceUrlWithSelected(
|
|
858
|
+
parentReferencePath: string,
|
|
859
|
+
meta?: string
|
|
860
|
+
): void {
|
|
657
861
|
if (meta) {
|
|
862
|
+
// update the encoded url meta param
|
|
863
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
864
|
+
|
|
658
865
|
window.history.replaceState(
|
|
659
|
-
|
|
866
|
+
window.history.state,
|
|
660
867
|
"",
|
|
661
|
-
`${
|
|
868
|
+
`${parentReferencePath}?meta=${encodedMeta}`
|
|
662
869
|
);
|
|
663
870
|
}
|
|
664
871
|
}
|
|
665
872
|
|
|
873
|
+
/**
|
|
874
|
+
* This method gets called when the user navigates back and forth using browser arrows
|
|
875
|
+
* Updates content depending on the type of reference - spec based or markdown
|
|
876
|
+
*/
|
|
877
|
+
protected updateSelectedItemFromUrlQuery(): void {
|
|
878
|
+
const specBasedReference = this.isSpecBasedReference(
|
|
879
|
+
this._currentReferenceId
|
|
880
|
+
);
|
|
881
|
+
if (specBasedReference) {
|
|
882
|
+
const currentMeta: RouteMeta | undefined =
|
|
883
|
+
this.getReferenceMetaInfo(window.location.href);
|
|
884
|
+
const metadata =
|
|
885
|
+
currentMeta && this.getMetadataByUrlQuery(currentMeta);
|
|
886
|
+
if (metadata) {
|
|
887
|
+
const {
|
|
888
|
+
parentReferencePath,
|
|
889
|
+
referenceId,
|
|
890
|
+
amfId,
|
|
891
|
+
type,
|
|
892
|
+
elementId
|
|
893
|
+
}: AmfMetadataTopic = metadata;
|
|
894
|
+
this.loadSpecReferenceContent(
|
|
895
|
+
parentReferencePath,
|
|
896
|
+
referenceId,
|
|
897
|
+
amfId,
|
|
898
|
+
type,
|
|
899
|
+
elementId,
|
|
900
|
+
currentMeta.meta
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
} else {
|
|
904
|
+
this.loadMarkdownBasedReference();
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
restoreScroll(); // don't try this at home kids
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* The API Navigation event will always intend to navigate within the current reference
|
|
912
|
+
* @param event
|
|
913
|
+
*/
|
|
914
|
+
protected onApiNavigationChanged(): void {
|
|
915
|
+
const specBasedReference = this.isSpecBasedReference(
|
|
916
|
+
this._currentReferenceId
|
|
917
|
+
);
|
|
918
|
+
if (specBasedReference) {
|
|
919
|
+
const { meta } = this.selectedTopic!;
|
|
920
|
+
const metadata = this.metadata[meta];
|
|
921
|
+
if (metadata) {
|
|
922
|
+
const {
|
|
923
|
+
parentReferencePath,
|
|
924
|
+
referenceId,
|
|
925
|
+
amfId,
|
|
926
|
+
type,
|
|
927
|
+
elementId
|
|
928
|
+
}: AmfMetadataTopic = metadata;
|
|
929
|
+
this.loadSpecReferenceContent(
|
|
930
|
+
parentReferencePath,
|
|
931
|
+
referenceId,
|
|
932
|
+
amfId,
|
|
933
|
+
type,
|
|
934
|
+
elementId,
|
|
935
|
+
metadata.meta
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
} else {
|
|
939
|
+
this.loadMarkdownBasedReference();
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
666
943
|
/**
|
|
667
944
|
* Updates the currently selected amf and topic
|
|
668
945
|
*/
|
|
669
|
-
protected
|
|
946
|
+
protected loadSpecReferenceContent(
|
|
947
|
+
parentReferencePath: string,
|
|
670
948
|
referenceId: string,
|
|
671
949
|
amfId: string,
|
|
672
950
|
type: string,
|
|
673
|
-
elementId
|
|
674
|
-
meta
|
|
951
|
+
elementId: string,
|
|
952
|
+
meta: string
|
|
675
953
|
): void {
|
|
676
954
|
this.selectedTopic = {
|
|
677
955
|
referenceId,
|
|
956
|
+
parentReferencePath,
|
|
678
957
|
amfId,
|
|
679
958
|
elementId,
|
|
680
959
|
type,
|
|
681
960
|
meta
|
|
682
961
|
};
|
|
683
|
-
this.selectedSidebarValue = this.getReferencePathWithMeta(
|
|
962
|
+
this.selectedSidebarValue = this.getReferencePathWithMeta(
|
|
963
|
+
parentReferencePath,
|
|
964
|
+
meta
|
|
965
|
+
);
|
|
684
966
|
|
|
685
967
|
this.handleSelectedItem();
|
|
686
968
|
|
|
687
|
-
// Ensures that the URL always has the meta, that way we don't get two history entries for summary
|
|
688
|
-
this.replaceUrlWithSelected(meta);
|
|
689
969
|
this.updateDocPhase();
|
|
690
970
|
}
|
|
691
971
|
|
|
@@ -696,10 +976,9 @@ export default class AmfReference extends LightningElement {
|
|
|
696
976
|
/* If parent level doc phase is enabled, Individual reference level doc phase should not be considered */
|
|
697
977
|
|
|
698
978
|
if (!this.isParentLevelDocPhaseEnabled) {
|
|
699
|
-
const
|
|
700
|
-
const selectedReference = this._amfConfig.find(
|
|
979
|
+
const selectedReference = this._amfConfigList.find(
|
|
701
980
|
(referenceItem: AmfConfig) => {
|
|
702
|
-
return referenceItem.id ===
|
|
981
|
+
return referenceItem.id === this._currentReferenceId;
|
|
703
982
|
}
|
|
704
983
|
);
|
|
705
984
|
if (selectedReference) {
|
|
@@ -711,103 +990,505 @@ export default class AmfReference extends LightningElement {
|
|
|
711
990
|
}
|
|
712
991
|
|
|
713
992
|
/**
|
|
714
|
-
*
|
|
993
|
+
* Returns the decoded meta query param from given Url as it is being used internally.
|
|
994
|
+
*/
|
|
995
|
+
getMetaFromUrl(referenceUrl: string): string {
|
|
996
|
+
const indexOfQueryParam = referenceUrl.indexOf("?");
|
|
997
|
+
const urlPath = referenceUrl.substring(
|
|
998
|
+
indexOfQueryParam >= 0 ? indexOfQueryParam : referenceUrl.length
|
|
999
|
+
);
|
|
1000
|
+
const meta = this.parseParams(urlPath).meta as string;
|
|
1001
|
+
// Always get the meta query param encoded and decode it and store it for internal use
|
|
1002
|
+
// This has 2 advantages,
|
|
1003
|
+
// 1. Supports backward compatible meta query param, so there is no need for redirects.
|
|
1004
|
+
// 2. Supports Prerender and Coveo for their crawling.
|
|
1005
|
+
const encodedMeta = meta && this.getUrlEncoded(meta);
|
|
1006
|
+
const decodedMeta = encodedMeta && decodeURIComponent(encodedMeta);
|
|
1007
|
+
return decodedMeta || "";
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/**
|
|
1011
|
+
*
|
|
1012
|
+
* @returns meta for given markdown based referenceUrl
|
|
1013
|
+
* Consider last topic url in ../references/reference-name/example.html
|
|
1014
|
+
*/
|
|
1015
|
+
getMarkdownReferenceMeta(referenceUrl: string): string {
|
|
1016
|
+
let meta = "";
|
|
1017
|
+
if (referenceUrl) {
|
|
1018
|
+
const slashSeparatorItems = referenceUrl.split("/");
|
|
1019
|
+
const lastItem =
|
|
1020
|
+
slashSeparatorItems[slashSeparatorItems.length - 1];
|
|
1021
|
+
if (lastItem.endsWith(".html")) {
|
|
1022
|
+
meta = lastItem;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return meta;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/**
|
|
1029
|
+
* Gets the encoded url.
|
|
1030
|
+
* This method will return the encoded url for 2 cases,
|
|
1031
|
+
* 1. If the url is encoded already
|
|
1032
|
+
* 2. If the url is decoded
|
|
1033
|
+
*/
|
|
1034
|
+
getUrlEncoded(url: string): string {
|
|
1035
|
+
// if url matches, then return the encoded url.
|
|
1036
|
+
if (decodeURIComponent(url) === url) {
|
|
1037
|
+
return encodeURIComponent(url);
|
|
1038
|
+
}
|
|
1039
|
+
// return the encoded url.
|
|
1040
|
+
return this.getUrlEncoded(decodeURIComponent(url));
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
*
|
|
1045
|
+
* @returns RouteMeta object for given referenceUrl
|
|
1046
|
+
* referenceId - gets referenceId from url
|
|
1047
|
+
* For spec based references gets meta parm from url and then topicId & type from meta
|
|
1048
|
+
* For markdown based references gets topicId as last html path in the name, meta & type will be empty
|
|
1049
|
+
*/
|
|
1050
|
+
getReferenceMetaInfo(referenceUrl: string | null): RouteMeta | undefined {
|
|
1051
|
+
let metaReferenceInfo;
|
|
1052
|
+
if (referenceUrl) {
|
|
1053
|
+
const referenceId = this.getReferenceIdFromUrl(referenceUrl);
|
|
1054
|
+
let meta = "";
|
|
1055
|
+
let topicId = "";
|
|
1056
|
+
let type = "";
|
|
1057
|
+
if (this.isSpecBasedReference(referenceId)) {
|
|
1058
|
+
meta = this.getMetaFromUrl(referenceUrl);
|
|
1059
|
+
if (meta) {
|
|
1060
|
+
if (meta.includes(":")) {
|
|
1061
|
+
const metaInfo = meta.split(":");
|
|
1062
|
+
type = metaInfo[0];
|
|
1063
|
+
topicId = metaInfo[1] || type;
|
|
1064
|
+
} else {
|
|
1065
|
+
topicId = meta;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
} else {
|
|
1069
|
+
topicId = this.getMarkdownReferenceMeta(referenceUrl);
|
|
1070
|
+
}
|
|
1071
|
+
metaReferenceInfo = {
|
|
1072
|
+
referenceId,
|
|
1073
|
+
meta,
|
|
1074
|
+
topicId,
|
|
1075
|
+
type
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
return metaReferenceInfo;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/**
|
|
1082
|
+
* Finds and returns referenceUrl and topicTitle if given topic url matches
|
|
1083
|
+
*/
|
|
1084
|
+
getReferenceDetailsInGivenTopics(
|
|
1085
|
+
topics: ParsedMarkdownTopic[],
|
|
1086
|
+
topicMeta: string
|
|
1087
|
+
): { referenceUrl: string; topicTitle: string } {
|
|
1088
|
+
let referenceUrl = "";
|
|
1089
|
+
let topicTitle = "";
|
|
1090
|
+
for (let i = 0; i < topics.length; i++) {
|
|
1091
|
+
const topic = topics[i];
|
|
1092
|
+
const meta = this.getMarkdownReferenceMeta(topic.link!.href);
|
|
1093
|
+
const childTopics = topic.children;
|
|
1094
|
+
if (meta === topicMeta) {
|
|
1095
|
+
referenceUrl = topic.link!.href;
|
|
1096
|
+
topicTitle = topic.label;
|
|
1097
|
+
} else if (childTopics && childTopics.length) {
|
|
1098
|
+
const referenceDetails = this.getReferenceDetailsInGivenTopics(
|
|
1099
|
+
childTopics,
|
|
1100
|
+
topicMeta
|
|
1101
|
+
);
|
|
1102
|
+
referenceUrl = referenceDetails.referenceUrl;
|
|
1103
|
+
topicTitle = referenceDetails.topicTitle;
|
|
1104
|
+
}
|
|
1105
|
+
if (referenceUrl && topicTitle) {
|
|
1106
|
+
break;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
return {
|
|
1110
|
+
referenceUrl,
|
|
1111
|
+
topicTitle
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Gives referenceUrl and topicTitle for given markdown topic url
|
|
1117
|
+
*/
|
|
1118
|
+
getRefDetailsForGivenTopicMeta(
|
|
1119
|
+
referenceId: string,
|
|
1120
|
+
topicMeta: string
|
|
1121
|
+
): { referenceUrl: string; topicTitle: string } | undefined {
|
|
1122
|
+
const amfConfig = this.getAmfConfigWithId(referenceId);
|
|
1123
|
+
let referenceDetails;
|
|
1124
|
+
if (amfConfig) {
|
|
1125
|
+
const topics = amfConfig.topic?.children || [];
|
|
1126
|
+
referenceDetails = this.getReferenceDetailsInGivenTopics(
|
|
1127
|
+
topics,
|
|
1128
|
+
topicMeta
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
return referenceDetails;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/**
|
|
1135
|
+
* Updates the DOM on the first load
|
|
715
1136
|
*/
|
|
716
1137
|
updateView(): void {
|
|
1138
|
+
const previousRefUrlInSession = window.sessionStorage.getItem(
|
|
1139
|
+
this.docsReferenceUrlSessionKey
|
|
1140
|
+
);
|
|
1141
|
+
window.sessionStorage.removeItem(this.docsReferenceUrlSessionKey);
|
|
1142
|
+
let previousRefInfo = this.getReferenceMetaInfo(
|
|
1143
|
+
previousRefUrlInSession
|
|
1144
|
+
);
|
|
1145
|
+
|
|
1146
|
+
// For spec based reference, We should consider urlData to show same topic when user reloads after navigating to specific topic
|
|
1147
|
+
if (!previousRefInfo) {
|
|
1148
|
+
const currentUrl = window.location.href;
|
|
1149
|
+
const urlReferenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1150
|
+
if (urlReferenceId && this.isSpecBasedReference(urlReferenceId)) {
|
|
1151
|
+
if (
|
|
1152
|
+
!this.isProjectRootPath() &&
|
|
1153
|
+
!this.isParentReferencePath(currentUrl)
|
|
1154
|
+
) {
|
|
1155
|
+
previousRefInfo = this.getReferenceMetaInfo(currentUrl);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
717
1160
|
let referenceId: string;
|
|
718
1161
|
let topicId = "";
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
1162
|
+
|
|
1163
|
+
if (
|
|
1164
|
+
previousRefInfo &&
|
|
1165
|
+
this._amfConfigMap.has(previousRefInfo.referenceId)
|
|
1166
|
+
) {
|
|
1167
|
+
referenceId = previousRefInfo.referenceId;
|
|
1168
|
+
topicId = previousRefInfo.topicId;
|
|
1169
|
+
} else {
|
|
1170
|
+
referenceId = this._currentReferenceId;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
const specBasedReference = this.isSpecBasedReference(referenceId);
|
|
1174
|
+
if (specBasedReference) {
|
|
1175
|
+
// Wait till the AMF is loaded.
|
|
1176
|
+
this.amfFetchPromiseMap[referenceId].then(() => {
|
|
1177
|
+
let selectedItemMetaData = this.getMetadataByIdentifier(
|
|
1178
|
+
referenceId,
|
|
1179
|
+
topicId
|
|
1180
|
+
);
|
|
1181
|
+
if (!selectedItemMetaData) {
|
|
1182
|
+
// Doesn't exist, let's use the summary.
|
|
1183
|
+
selectedItemMetaData = this.getMetadataByType(
|
|
1184
|
+
referenceId,
|
|
1185
|
+
"summary"
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
if (selectedItemMetaData) {
|
|
1190
|
+
this.loadSpecReferenceContent(
|
|
1191
|
+
selectedItemMetaData.parentReferencePath,
|
|
1192
|
+
selectedItemMetaData.referenceId,
|
|
1193
|
+
selectedItemMetaData.amfId,
|
|
1194
|
+
selectedItemMetaData.type,
|
|
1195
|
+
"",
|
|
1196
|
+
selectedItemMetaData.meta
|
|
1197
|
+
);
|
|
1198
|
+
|
|
1199
|
+
this.updateUrlWithSelected(
|
|
1200
|
+
selectedItemMetaData.parentReferencePath,
|
|
1201
|
+
selectedItemMetaData.meta
|
|
1202
|
+
);
|
|
1203
|
+
this.updateTags(selectedItemMetaData.navTitle);
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
} else {
|
|
1207
|
+
let invalidTopicReferenceUrl: string | null = "";
|
|
1208
|
+
if (topicId) {
|
|
1209
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1210
|
+
referenceId,
|
|
1211
|
+
topicId
|
|
1212
|
+
);
|
|
1213
|
+
const selectedItemUrl = referenceDetails?.referenceUrl;
|
|
1214
|
+
if (!selectedItemUrl) {
|
|
1215
|
+
invalidTopicReferenceUrl = previousRefUrlInSession;
|
|
1216
|
+
}
|
|
731
1217
|
}
|
|
1218
|
+
this.loadMarkdownBasedReference(invalidTopicReferenceUrl);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Navigates to reference of the given URL
|
|
1224
|
+
* @param url
|
|
1225
|
+
*/
|
|
1226
|
+
private loadNewReferenceItem(url: string): void {
|
|
1227
|
+
const referenceId = this.getReferenceIdFromUrl(url);
|
|
1228
|
+
const referenceItem = this.getAmfConfigWithId(referenceId);
|
|
1229
|
+
if (referenceItem) {
|
|
1230
|
+
window.location.href = referenceItem.href;
|
|
732
1231
|
}
|
|
1232
|
+
}
|
|
733
1233
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
1234
|
+
/**
|
|
1235
|
+
* @param referenceUrl to which user wants to navigate
|
|
1236
|
+
* Redirect to first sub item if it's root level item, otherwise content will be loaded
|
|
1237
|
+
* Push the history as a first child item
|
|
1238
|
+
* set selected sidebar value as a pathname
|
|
1239
|
+
*/
|
|
1240
|
+
|
|
1241
|
+
private loadMarkdownBasedReference(referenceUrl?: string | null): void {
|
|
1242
|
+
// MILES TODO: figure out if we ever need to log a coveo page view in here
|
|
1243
|
+
// this would be the case if at some point we 'load' a new 'markdown based reference'
|
|
1244
|
+
// without actually triggering a page load
|
|
1245
|
+
let referenceId = "";
|
|
1246
|
+
const currentUrl = window.location.href;
|
|
1247
|
+
if (this.isProjectRootPath()) {
|
|
1248
|
+
/**
|
|
1249
|
+
* CASE1: This case is to consider when the user navigates to references by clicking a project card
|
|
1250
|
+
* Ex: /docs/example-project/references should navigate to the first topic in the first reference
|
|
1251
|
+
*/
|
|
1252
|
+
referenceId = this._currentReferenceId;
|
|
1253
|
+
} else if (this.isParentReferencePath(referenceUrl)) {
|
|
1254
|
+
/**
|
|
1255
|
+
* CASE2: This case is to navigate to respective reference when the user clicked on root item
|
|
1256
|
+
* Ex: .../references/markdown-ref should navigate to first topic.
|
|
1257
|
+
*/
|
|
1258
|
+
referenceId = this.getReferenceIdFromUrl(referenceUrl!);
|
|
1259
|
+
} else if (this.isParentReferencePath(currentUrl)) {
|
|
1260
|
+
/**
|
|
1261
|
+
* CASE3: This case is to navigate to respective reference when the user entered url with reference id
|
|
1262
|
+
* Ex: .../references/markdown-ref should navigate to first topic.
|
|
1263
|
+
*/
|
|
1264
|
+
referenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1265
|
+
} else if (referenceUrl) {
|
|
1266
|
+
/**
|
|
1267
|
+
* CASE4: This case is to navigate to first item when we don't have topic in the selected version
|
|
1268
|
+
* Ex: .../references/markdown-ref/not-existed-topic-url should navigate to first topic.
|
|
1269
|
+
*/
|
|
1270
|
+
const referenceMeta = this.getMarkdownReferenceMeta(referenceUrl);
|
|
1271
|
+
const selectedItemRefId = this.getReferenceIdFromUrl(referenceUrl);
|
|
1272
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1273
|
+
selectedItemRefId,
|
|
1274
|
+
referenceMeta
|
|
1275
|
+
);
|
|
1276
|
+
const selectedItemUrl = referenceDetails?.referenceUrl;
|
|
1277
|
+
if (!selectedItemUrl) {
|
|
1278
|
+
referenceId = this.getReferenceIdFromUrl(referenceUrl);
|
|
739
1279
|
}
|
|
740
1280
|
}
|
|
741
1281
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
1282
|
+
let isRedirecting = false;
|
|
1283
|
+
if (referenceId) {
|
|
1284
|
+
const amfConfig = this.getAmfConfigWithId(referenceId);
|
|
1285
|
+
let redirectReferenceUrl = "";
|
|
1286
|
+
if (amfConfig) {
|
|
1287
|
+
const childrenItems = amfConfig.topic!.children;
|
|
1288
|
+
if (childrenItems.length > 0) {
|
|
1289
|
+
redirectReferenceUrl = childrenItems[0].link!.href;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
if (redirectReferenceUrl) {
|
|
1293
|
+
if (this.isParentReferencePath(referenceUrl)) {
|
|
1294
|
+
// This is for CASE2 mentioned above, Where we need to navigate user to respective href
|
|
1295
|
+
isRedirecting = true;
|
|
1296
|
+
window.location.href = redirectReferenceUrl;
|
|
1297
|
+
} else {
|
|
1298
|
+
// This is for CASE 1,3 and 4 mentioned above, Where we need to update the browser history
|
|
1299
|
+
window.history.replaceState(
|
|
1300
|
+
window.history.state,
|
|
1301
|
+
"",
|
|
1302
|
+
redirectReferenceUrl
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
if (!isRedirecting) {
|
|
1308
|
+
const currentReferenceUrl = window.location.href;
|
|
1309
|
+
const referenceMeta =
|
|
1310
|
+
this.getMarkdownReferenceMeta(currentReferenceUrl);
|
|
1311
|
+
const selectedItemRefId =
|
|
1312
|
+
this.getReferenceIdFromUrl(currentReferenceUrl);
|
|
1313
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1314
|
+
selectedItemRefId,
|
|
1315
|
+
referenceMeta
|
|
1316
|
+
);
|
|
1317
|
+
if (referenceDetails) {
|
|
1318
|
+
this.updateTags(referenceDetails.topicTitle);
|
|
748
1319
|
}
|
|
749
1320
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
"",
|
|
756
|
-
topic.meta
|
|
757
|
-
);
|
|
1321
|
+
this.versions = this.getVersions();
|
|
1322
|
+
if (this.oldVersionInfo) {
|
|
1323
|
+
this.showVersionBanner = true;
|
|
1324
|
+
} else {
|
|
1325
|
+
this.latestVersion = true;
|
|
758
1326
|
}
|
|
759
|
-
|
|
1327
|
+
|
|
1328
|
+
this.isVersionFetched = true;
|
|
1329
|
+
this.updateDocPhase();
|
|
1330
|
+
this.selectedSidebarValue = window.location.pathname;
|
|
1331
|
+
}
|
|
760
1332
|
}
|
|
761
1333
|
|
|
762
1334
|
/**
|
|
763
|
-
* Currently, used to handle the version change and
|
|
1335
|
+
* Currently, used to handle the version change and store the current reference Url.
|
|
764
1336
|
*/
|
|
765
1337
|
handleVersionChange(): void {
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
1338
|
+
const currentUrl = window.location.href;
|
|
1339
|
+
window.sessionStorage.setItem(
|
|
1340
|
+
this.docsReferenceUrlSessionKey,
|
|
1341
|
+
currentUrl
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
handleDismissVersionBanner() {
|
|
1346
|
+
this.showVersionBanner = false;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
private updateTags(navTitle = ""): void {
|
|
1350
|
+
if (!navTitle) {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// this is required to update the nav title meta tag.
|
|
1355
|
+
// eslint-disable-next-line @lwc/lwc/no-document-query
|
|
1356
|
+
const metaNavTitle = document.querySelector('meta[name="nav-title"]');
|
|
1357
|
+
// eslint-disable-next-line @lwc/lwc/no-document-query
|
|
1358
|
+
const titleTag = document.querySelector("title");
|
|
1359
|
+
const TITLE_SEPARATOR = " | ";
|
|
1360
|
+
|
|
1361
|
+
if (metaNavTitle) {
|
|
1362
|
+
metaNavTitle.setAttribute("content", navTitle);
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Right now, the title tag only changes when you pick a Ref spec,
|
|
1367
|
+
* not every time you choose a subsection of the Ref spec.
|
|
1368
|
+
* This update aims to refresh the title tag with each selection.
|
|
1369
|
+
* If a Ref spec is chosen, we add the value of the <selected topic> to the title.
|
|
1370
|
+
* If a subsection is selected, we update the first part of the current
|
|
1371
|
+
* title with the new <selected topic>.
|
|
1372
|
+
* Example: Following is a sample project structure.
|
|
1373
|
+
* - Project Name
|
|
1374
|
+
* - Ref Spec1
|
|
1375
|
+
* - Summary
|
|
1376
|
+
* - Endpoints
|
|
1377
|
+
* - E1
|
|
1378
|
+
* - E2
|
|
1379
|
+
* - Ref Spec2
|
|
1380
|
+
* - Summary
|
|
1381
|
+
* - Endpoints
|
|
1382
|
+
* - E1 (Selected)
|
|
1383
|
+
* - E2
|
|
1384
|
+
* Previous Title: Ref Spec2 | Project Name | Salesforce Developer
|
|
1385
|
+
* New Title: E1 | Ref Spec2 | Project Name | Salesforce Developer
|
|
1386
|
+
*
|
|
1387
|
+
*/
|
|
1388
|
+
if (titleTag) {
|
|
1389
|
+
let titleTagValue = titleTag.textContent;
|
|
1390
|
+
const titleTagSectionValues: string[] =
|
|
1391
|
+
titleTagValue?.split(TITLE_SEPARATOR);
|
|
1392
|
+
if (titleTagSectionValues) {
|
|
1393
|
+
if (titleTagSectionValues.length <= 3) {
|
|
1394
|
+
titleTagValue = navTitle + TITLE_SEPARATOR + titleTagValue;
|
|
1395
|
+
} else {
|
|
1396
|
+
titleTagSectionValues[0] = navTitle;
|
|
1397
|
+
titleTagValue = titleTagSectionValues.join(TITLE_SEPARATOR);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
titleTag.textContent = titleTagValue;
|
|
774
1401
|
}
|
|
775
1402
|
}
|
|
776
1403
|
|
|
777
1404
|
onNavSelect(event: CustomEvent): void {
|
|
778
1405
|
const name = event.detail.name;
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1406
|
+
if (name) {
|
|
1407
|
+
const urlReferenceId = this.getReferenceIdFromUrl(name);
|
|
1408
|
+
const specBasedReference =
|
|
1409
|
+
this.isSpecBasedReference(urlReferenceId);
|
|
1410
|
+
if (specBasedReference) {
|
|
1411
|
+
const metaVal = this.getMetaFromUrl(name);
|
|
1412
|
+
const currentSelectedMeta = this.selectedTopic
|
|
1413
|
+
? this.selectedTopic.meta
|
|
1414
|
+
: "";
|
|
1415
|
+
|
|
1416
|
+
if (metaVal && metaVal === currentSelectedMeta) {
|
|
1417
|
+
// selecting the same nav item, skip update
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
785
1420
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1421
|
+
const metadata = this.metadata[metaVal];
|
|
1422
|
+
if (metadata) {
|
|
1423
|
+
const {
|
|
1424
|
+
parentReferencePath,
|
|
1425
|
+
referenceId,
|
|
1426
|
+
amfId,
|
|
1427
|
+
type,
|
|
1428
|
+
elementId
|
|
1429
|
+
} = metadata;
|
|
1430
|
+
this.loadSpecReferenceContent(
|
|
1431
|
+
parentReferencePath,
|
|
1432
|
+
referenceId,
|
|
1433
|
+
amfId,
|
|
1434
|
+
type,
|
|
1435
|
+
elementId,
|
|
1436
|
+
metaVal
|
|
1437
|
+
);
|
|
1438
|
+
|
|
1439
|
+
logCoveoPageView(
|
|
1440
|
+
this.coveoOrganizationId,
|
|
1441
|
+
this.coveoAnalyticsToken
|
|
1442
|
+
);
|
|
1443
|
+
this.updateUrlWithSelected(parentReferencePath, metaVal);
|
|
1444
|
+
this.updateTags(metadata.navTitle);
|
|
1445
|
+
} else {
|
|
1446
|
+
if (this.isParentReferencePath(name)) {
|
|
1447
|
+
this.loadNewReferenceItem(name);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
} else {
|
|
1451
|
+
this.loadMarkdownBasedReference(name);
|
|
1452
|
+
}
|
|
789
1453
|
}
|
|
1454
|
+
}
|
|
790
1455
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
this.
|
|
795
|
-
|
|
1456
|
+
onExpandCollapse(event: CustomEvent): void {
|
|
1457
|
+
const { name, isSelectAction, isExpanded } = event.detail;
|
|
1458
|
+
if (!isSelectAction && isExpanded) {
|
|
1459
|
+
const referenceId = this.getReferenceIdFromUrl(name);
|
|
1460
|
+
const currentUrl = window.location.href;
|
|
1461
|
+
const currentReferenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1462
|
+
//No need to do anything if user is expanding currently selected reference
|
|
1463
|
+
if (referenceId !== currentReferenceId) {
|
|
1464
|
+
const isSpecBasedReference =
|
|
1465
|
+
this.isSpecBasedReference(referenceId);
|
|
1466
|
+
if (isSpecBasedReference) {
|
|
1467
|
+
// Perform functionality same as item selection
|
|
1468
|
+
this.onNavSelect(event);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
796
1471
|
}
|
|
797
1472
|
}
|
|
798
1473
|
|
|
799
1474
|
handleSelectedItem(): void {
|
|
800
1475
|
// update topic view
|
|
801
|
-
const { referenceId, amfId, type } = this.selectedTopic
|
|
1476
|
+
const { referenceId, amfId, type } = this.selectedTopic!;
|
|
1477
|
+
|
|
1478
|
+
// Adding stringify inside try/catch
|
|
1479
|
+
let amfModelString = "";
|
|
1480
|
+
try {
|
|
1481
|
+
amfModelString = JSON.stringify(this.amfMap[referenceId].model);
|
|
1482
|
+
} catch (error) {
|
|
1483
|
+
console.error(`Error stringifying amf model: ${error}`);
|
|
1484
|
+
}
|
|
802
1485
|
|
|
803
1486
|
// This updates the component in the content section.
|
|
804
1487
|
this.topicModel = {
|
|
805
1488
|
type,
|
|
806
|
-
amf:
|
|
1489
|
+
amf: amfModelString,
|
|
807
1490
|
parser: this.amfMap[referenceId].parser,
|
|
808
1491
|
id: amfId
|
|
809
1492
|
};
|
|
810
|
-
|
|
811
|
-
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
812
1493
|
}
|
|
813
1494
|
}
|