@salesforcedevs/docs-components 0.56.2 → 0.57.1-flex-ref1
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 +2 -2
- package/src/modules/doc/amfReference/amfReference.html +13 -5
- package/src/modules/doc/amfReference/amfReference.ts +799 -303
- package/src/modules/doc/amfReference/constants.ts +76 -0
- package/src/modules/doc/amfReference/types.ts +43 -3
- 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 +7 -1
- package/src/modules/doc/breadcrumbs/breadcrumbs.html +11 -1
- package/src/modules/doc/breadcrumbs/breadcrumbs.ts +15 -0
- package/src/modules/doc/contentLayout/contentLayout.ts +74 -29
- package/LICENSE +0 -12
- package/src/modules/doc/amfReference/route-meta.ts +0 -22
|
@@ -3,7 +3,7 @@ import { noCase } from "no-case";
|
|
|
3
3
|
import { sentenceCase } from "sentence-case";
|
|
4
4
|
import qs from "query-string";
|
|
5
5
|
import { AmfModelParser } from "./utils";
|
|
6
|
-
import {
|
|
6
|
+
import { normalizeBoolean } from "dxUtils/normalizers";
|
|
7
7
|
import type {
|
|
8
8
|
AmfConfig,
|
|
9
9
|
AmfMetadataTopic,
|
|
@@ -14,94 +14,46 @@ import type {
|
|
|
14
14
|
TopicModel,
|
|
15
15
|
ReferenceVersion,
|
|
16
16
|
ReferenceSetConfig,
|
|
17
|
-
AmfMetaTopicType
|
|
17
|
+
AmfMetaTopicType,
|
|
18
|
+
RouteMeta,
|
|
19
|
+
ParsedMarkdownTopic
|
|
18
20
|
} from "./types";
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
label: "Endpoints",
|
|
29
|
-
name: "endpoints",
|
|
30
|
-
childrenPropertyName: "endpoints",
|
|
31
|
-
type: "endpoint"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
label: "Documentation",
|
|
35
|
-
name: "documentation",
|
|
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"
|
|
86
|
-
};
|
|
22
|
+
import {
|
|
23
|
+
NAVIGATION_ITEMS,
|
|
24
|
+
URL_CONFIG,
|
|
25
|
+
REFERENCE_TYPES,
|
|
26
|
+
oldReferenceIdNewReferenceIdMap
|
|
27
|
+
} from "./constants";
|
|
87
28
|
|
|
88
29
|
export default class AmfReference extends LightningElement {
|
|
89
|
-
@api breadcrumbs?: string = null;
|
|
90
|
-
@api sidebarHeader
|
|
30
|
+
@api breadcrumbs?: string | null | undefined = null;
|
|
31
|
+
@api sidebarHeader!: string;
|
|
91
32
|
@api coveoOrganizationId!: string;
|
|
92
33
|
@api coveoPublicAccessToken!: string;
|
|
93
34
|
@api coveoAdvancedQueryConfig!: string;
|
|
94
35
|
@api coveoSearchHub!: string;
|
|
95
36
|
@api useOldSidebar?: boolean = false;
|
|
37
|
+
@api tocTitle?: string;
|
|
38
|
+
@api tocOptions?: string;
|
|
39
|
+
@track navigation = [];
|
|
40
|
+
@track versions: Array<ReferenceVersion> = [];
|
|
96
41
|
|
|
97
42
|
// Update this to update what component gets rendered in the content block
|
|
98
43
|
@track
|
|
99
|
-
protected topicModel
|
|
44
|
+
protected topicModel!: TopicModel;
|
|
100
45
|
|
|
101
46
|
get isVersionEnabled(): boolean {
|
|
102
47
|
return !!this._referenceSetConfig?.versions?.length;
|
|
103
48
|
}
|
|
104
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Gives if the currently selected reference is spec based or not
|
|
52
|
+
*/
|
|
53
|
+
get showSpecBasedReference(): boolean {
|
|
54
|
+
return this.isSpecBasedReference(this._currentReferenceId);
|
|
55
|
+
}
|
|
56
|
+
|
|
105
57
|
@api
|
|
106
58
|
get referenceSetConfig(): ReferenceSetConfig {
|
|
107
59
|
return this._referenceSetConfig;
|
|
@@ -122,22 +74,42 @@ export default class AmfReference extends LightningElement {
|
|
|
122
74
|
this._referenceSetConfig = refConfig;
|
|
123
75
|
} catch (e) {
|
|
124
76
|
this._referenceSetConfig = {
|
|
125
|
-
refList: []
|
|
77
|
+
refList: [],
|
|
78
|
+
versions: []
|
|
126
79
|
};
|
|
127
80
|
}
|
|
128
81
|
|
|
82
|
+
this._amfConfigList = this._referenceSetConfig.refList || [];
|
|
83
|
+
|
|
84
|
+
this._amfConfigList.forEach((amfConfig) => {
|
|
85
|
+
this._amfConfigMap.set(amfConfig.id, amfConfig);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (this._amfConfigList.length > 0) {
|
|
89
|
+
this._currentReferenceId =
|
|
90
|
+
this._referenceSetConfig.refId || this._amfConfigList[0].id;
|
|
91
|
+
}
|
|
92
|
+
|
|
129
93
|
if (this.isVersionEnabled) {
|
|
130
94
|
const selectedVersion = this.getSelectedVersion();
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* If current selected is markdown based reference,
|
|
98
|
+
* We will assign versions once the selected item url is updated
|
|
99
|
+
*/
|
|
100
|
+
if (this.isSpecBasedReference(this._currentReferenceId)) {
|
|
101
|
+
this.versions = this.getVersions();
|
|
102
|
+
}
|
|
135
103
|
this.selectedVersion = selectedVersion;
|
|
136
|
-
} else {
|
|
137
|
-
this._amfConfig = this._referenceSetConfig.refList;
|
|
138
104
|
}
|
|
139
105
|
|
|
140
|
-
|
|
106
|
+
// This is to check if the url is hash based and redirect if needed
|
|
107
|
+
const redirectUrl = this.getHashBasedRedirectUrl();
|
|
108
|
+
if (redirectUrl) {
|
|
109
|
+
window.location.href = redirectUrl;
|
|
110
|
+
} else {
|
|
111
|
+
this.updateAmfConfigInView();
|
|
112
|
+
}
|
|
141
113
|
}
|
|
142
114
|
|
|
143
115
|
@api
|
|
@@ -152,53 +124,51 @@ export default class AmfReference extends LightningElement {
|
|
|
152
124
|
}
|
|
153
125
|
}
|
|
154
126
|
|
|
127
|
+
@api
|
|
128
|
+
get expandChildren() {
|
|
129
|
+
return this._expandChildren;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
set expandChildren(value) {
|
|
133
|
+
this._expandChildren = normalizeBoolean(value);
|
|
134
|
+
}
|
|
135
|
+
|
|
155
136
|
// model
|
|
156
|
-
protected
|
|
157
|
-
protected
|
|
137
|
+
protected _amfConfigList: AmfConfig[] = [];
|
|
138
|
+
protected _amfConfigMap: Map<string, AmfConfig> = new Map();
|
|
139
|
+
protected _referenceSetConfig!: ReferenceSetConfig;
|
|
158
140
|
protected _currentReferenceId = "";
|
|
159
141
|
|
|
142
|
+
protected parentReferenceUrls = [];
|
|
160
143
|
protected amfMap: Record<string, AmfModelRecord> = {};
|
|
161
144
|
protected amfFetchPromiseMap = {};
|
|
162
145
|
protected metadata: { [key: string]: AmfMetadataTopic } = {};
|
|
163
|
-
protected selectedTopic
|
|
164
|
-
protected navigation = [];
|
|
146
|
+
protected selectedTopic?: AmfMetaTopicType = undefined;
|
|
165
147
|
protected selectedSidebarValue = undefined;
|
|
166
|
-
protected versions: Array<ReferenceVersion> = [];
|
|
167
|
-
protected selectedVersion: ReferenceVersion = null;
|
|
168
148
|
|
|
169
|
-
|
|
170
|
-
private navAmfOrder = [];
|
|
149
|
+
protected selectedVersion: ReferenceVersion | null = null;
|
|
171
150
|
|
|
172
|
-
private
|
|
151
|
+
private hasRendered = false;
|
|
173
152
|
|
|
174
153
|
private isParentLevelDocPhaseEnabled = false;
|
|
175
|
-
private selectedReferenceDocPhase?: string = null;
|
|
154
|
+
private selectedReferenceDocPhase?: string | null = null;
|
|
155
|
+
private _expandChildren?: boolean = false;
|
|
176
156
|
|
|
177
157
|
/**
|
|
178
|
-
* Key for storing the currently selected reference
|
|
179
|
-
* previously selected reference
|
|
158
|
+
* Key for storing the currently selected reference url. This will be used to save the
|
|
159
|
+
* previously selected reference url and restoring it when changing between reference versions.
|
|
180
160
|
*/
|
|
181
|
-
private readonly
|
|
161
|
+
private readonly docsReferenceUrlSessionKey: string = "docsReferenceUrl";
|
|
182
162
|
|
|
183
163
|
_boundOnApiNavigationChanged;
|
|
184
164
|
_boundUpdateSelectedItemFromUrlQuery;
|
|
185
165
|
|
|
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
166
|
constructor() {
|
|
195
167
|
super();
|
|
196
|
-
this._boundOnApiNavigationChanged =
|
|
197
|
-
this
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
this
|
|
201
|
-
);
|
|
168
|
+
this._boundOnApiNavigationChanged =
|
|
169
|
+
this.onApiNavigationChanged.bind(this);
|
|
170
|
+
this._boundUpdateSelectedItemFromUrlQuery =
|
|
171
|
+
this.updateSelectedItemFromUrlQuery.bind(this);
|
|
202
172
|
}
|
|
203
173
|
|
|
204
174
|
connectedCallback(): void {
|
|
@@ -226,7 +196,7 @@ export default class AmfReference extends LightningElement {
|
|
|
226
196
|
renderedCallback(): void {
|
|
227
197
|
if (!this.hasRendered) {
|
|
228
198
|
this.hasRendered = true;
|
|
229
|
-
if (this.
|
|
199
|
+
if (this._amfConfigList && this._amfConfigList.length) {
|
|
230
200
|
// If amfConfig has a value and length, it is assumed that fetch
|
|
231
201
|
// has already been called and promises stored.
|
|
232
202
|
this.updateView();
|
|
@@ -234,6 +204,109 @@ export default class AmfReference extends LightningElement {
|
|
|
234
204
|
}
|
|
235
205
|
}
|
|
236
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Check if the URL hash to see whether this is one we want to redirect
|
|
209
|
+
* See GUS W-10718771 for references where we want hash-based redirects
|
|
210
|
+
* Return if we needs to redirect url to updated url
|
|
211
|
+
*/
|
|
212
|
+
private getHashBasedRedirectUrl(): string | undefined {
|
|
213
|
+
const { hash } = window.location;
|
|
214
|
+
let hashBasedRedirectUrl = "";
|
|
215
|
+
if (hash) {
|
|
216
|
+
const strippedHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
217
|
+
const strippedHashItems = strippedHash
|
|
218
|
+
? strippedHash.split(":")
|
|
219
|
+
: [];
|
|
220
|
+
if (strippedHashItems.length) {
|
|
221
|
+
const referenceId = strippedHashItems[0];
|
|
222
|
+
const meta = strippedHashItems[1];
|
|
223
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
224
|
+
const updatedReferenceId =
|
|
225
|
+
oldReferenceIdNewReferenceIdMap[referenceId];
|
|
226
|
+
const newReferenceId = updatedReferenceId || referenceId;
|
|
227
|
+
const referenceItemConfig =
|
|
228
|
+
this.getAmfConfigWithId(newReferenceId);
|
|
229
|
+
if (referenceItemConfig) {
|
|
230
|
+
hashBasedRedirectUrl = `${referenceItemConfig.href}?meta=${encodedMeta}`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return hashBasedRedirectUrl;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param referenceId
|
|
239
|
+
* @returns AMFConfig with given reference Id
|
|
240
|
+
*/
|
|
241
|
+
private getAmfConfigWithId(referenceId: string): AmfConfig | undefined {
|
|
242
|
+
return this._amfConfigMap.get(referenceId);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @param referenceId
|
|
247
|
+
* @returns if the reference is spec based one or not with given referenceId.
|
|
248
|
+
*/
|
|
249
|
+
private isSpecBasedReference(referenceId: string): boolean {
|
|
250
|
+
const selectedReference = this.getAmfConfigWithId(referenceId);
|
|
251
|
+
return selectedReference
|
|
252
|
+
? selectedReference.referenceType !== REFERENCE_TYPES.markdown
|
|
253
|
+
: false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/*
|
|
257
|
+
* Refactor below method when sidebar allows sending extraData along with the name for each item.
|
|
258
|
+
* See if we can refactor the below method using regex.
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* @param url
|
|
263
|
+
* @returns reference Id from url path / selected sidebar item.
|
|
264
|
+
*/
|
|
265
|
+
private getReferenceIdFromUrl(url: string): string {
|
|
266
|
+
let referenceId = "";
|
|
267
|
+
const urlItems = url.split("/references/");
|
|
268
|
+
if (urlItems.length > 1) {
|
|
269
|
+
const rightSidePart = urlItems[1];
|
|
270
|
+
|
|
271
|
+
//This covers urls like "/project-name/references/reference-id/..."
|
|
272
|
+
const slashSeparatorItems = rightSidePart.split("/");
|
|
273
|
+
|
|
274
|
+
//This covers urls like "/project-name/references/reference-id?meta=Summary"
|
|
275
|
+
const querySeparatorItems = slashSeparatorItems[0].split("?");
|
|
276
|
+
|
|
277
|
+
referenceId = querySeparatorItems[0];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return referenceId;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @returns versions to be shown in the dropdown
|
|
285
|
+
* For markdown based specs, Adds selected markdown topic url to same references
|
|
286
|
+
*/
|
|
287
|
+
private getVersions(): Array<ReferenceVersion> {
|
|
288
|
+
const allVersions = this._referenceSetConfig.versions;
|
|
289
|
+
if (!this.isSpecBasedReference(this._currentReferenceId)) {
|
|
290
|
+
const currentRefMeta = this.getMarkdownReferenceMeta(
|
|
291
|
+
window.location.href
|
|
292
|
+
);
|
|
293
|
+
if (currentRefMeta) {
|
|
294
|
+
for (let i = 0; i < allVersions.length; i++) {
|
|
295
|
+
const versionItem = allVersions[i];
|
|
296
|
+
const referenceLink = versionItem.link.href;
|
|
297
|
+
const referenceId =
|
|
298
|
+
this.getReferenceIdFromUrl(referenceLink);
|
|
299
|
+
if (this._currentReferenceId === referenceId) {
|
|
300
|
+
// This is to navigate to respective topic in the changed version
|
|
301
|
+
versionItem.link.href = `${referenceLink}/${currentRefMeta}`;
|
|
302
|
+
allVersions[i] = versionItem;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return allVersions;
|
|
308
|
+
}
|
|
309
|
+
|
|
237
310
|
/**
|
|
238
311
|
* Returns the selected version or the first available version.
|
|
239
312
|
*/
|
|
@@ -247,9 +320,9 @@ export default class AmfReference extends LightningElement {
|
|
|
247
320
|
}
|
|
248
321
|
|
|
249
322
|
private updateAmfConfigInView(): void {
|
|
250
|
-
if (this.
|
|
323
|
+
if (this._amfConfigList && this._amfConfigList.length) {
|
|
251
324
|
// fetch AMF Json as soon as config is set
|
|
252
|
-
this.
|
|
325
|
+
this.populateReferenceItems();
|
|
253
326
|
// update() must be called after renderedCallback.
|
|
254
327
|
if (this.hasRendered) {
|
|
255
328
|
this.updateView();
|
|
@@ -269,17 +342,69 @@ export default class AmfReference extends LightningElement {
|
|
|
269
342
|
}
|
|
270
343
|
|
|
271
344
|
/**
|
|
272
|
-
*
|
|
273
|
-
* Stores each fetch promise for handling after renderCallback.
|
|
345
|
+
* Returns whether current location is project root path like ../example-project/references
|
|
274
346
|
*/
|
|
275
|
-
private
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
347
|
+
private isProjectRootPath(): boolean {
|
|
348
|
+
return this.getReferenceIdFromUrl(window.location.href) === "";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Returns whether given url is parent reference path like ../example-project/references/reference-id
|
|
353
|
+
*/
|
|
354
|
+
private isParentReferencePath(urlPath: string): boolean {
|
|
355
|
+
if (!urlPath) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
const parentReferenceIndex = this.parentReferenceUrls.findIndex(
|
|
359
|
+
(referenceUrl: string) => {
|
|
360
|
+
return urlPath.endsWith(referenceUrl);
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
return parentReferenceIndex !== -1;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Populates reference Items from amfConfigList and assigns it to navigation for sidebar
|
|
368
|
+
*/
|
|
369
|
+
private populateReferenceItems(): void {
|
|
370
|
+
const navAmfOrder = [];
|
|
371
|
+
for (const [index, amfConfig] of this._amfConfigList.entries()) {
|
|
372
|
+
let navItemChildren = [];
|
|
373
|
+
let isChildrenLoading = false;
|
|
374
|
+
if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
|
|
375
|
+
if (amfConfig.isSelected) {
|
|
376
|
+
const amfPromise = this.fetchAmf(amfConfig).then(
|
|
377
|
+
(amfJson) => {
|
|
378
|
+
this.updateModel(amfConfig.id, amfJson);
|
|
379
|
+
this.assignNavigationItemsFromAmf(amfConfig, index);
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
this.amfFetchPromiseMap[amfConfig.id] = amfPromise;
|
|
383
|
+
}
|
|
384
|
+
isChildrenLoading = true;
|
|
385
|
+
} else {
|
|
386
|
+
navItemChildren = amfConfig.topic.children;
|
|
387
|
+
}
|
|
388
|
+
// store nav items for each spec in order
|
|
389
|
+
navAmfOrder[index] = {
|
|
390
|
+
label: amfConfig.title,
|
|
391
|
+
name: amfConfig.href,
|
|
392
|
+
isExpanded:
|
|
393
|
+
amfConfig.isSelected ||
|
|
394
|
+
this.isExpandChildrenEnabled(amfConfig.id),
|
|
395
|
+
children: navItemChildren,
|
|
396
|
+
isChildrenLoading
|
|
397
|
+
};
|
|
398
|
+
this.parentReferenceUrls.push(amfConfig.href);
|
|
282
399
|
}
|
|
400
|
+
this.navigation = navAmfOrder;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Returns a boolean indicating whether the children should be expanded or not.
|
|
405
|
+
*/
|
|
406
|
+
private isExpandChildrenEnabled(referenceId: string): boolean {
|
|
407
|
+
return this.expandChildren && this._currentReferenceId === referenceId;
|
|
283
408
|
}
|
|
284
409
|
|
|
285
410
|
/**
|
|
@@ -311,7 +436,7 @@ export default class AmfReference extends LightningElement {
|
|
|
311
436
|
|
|
312
437
|
/**
|
|
313
438
|
* Transforms a list of model data for endpoints into corresponding
|
|
314
|
-
* navigation list items that
|
|
439
|
+
* navigation list items that are compatible with dx-sidebar.
|
|
315
440
|
* Compatible with transforming AMF data parsed from both RAML and OAS spec.
|
|
316
441
|
* Transforms a flat list of endpoints into a nested list based on indentation level
|
|
317
442
|
* for RAML spec.
|
|
@@ -319,6 +444,7 @@ export default class AmfReference extends LightningElement {
|
|
|
319
444
|
* @returns {array<Object>} List of navigation items
|
|
320
445
|
*/
|
|
321
446
|
private assignEndpointNavItems(
|
|
447
|
+
parentReferencePath: string,
|
|
322
448
|
referenceId: string,
|
|
323
449
|
items: ParsedTopicModel[]
|
|
324
450
|
): NavItem[] {
|
|
@@ -326,22 +452,39 @@ export default class AmfReference extends LightningElement {
|
|
|
326
452
|
|
|
327
453
|
items.forEach((item) => {
|
|
328
454
|
item.methods?.forEach((method) => {
|
|
329
|
-
const
|
|
455
|
+
const title =
|
|
456
|
+
this.getTitleForLabel(method.label) || method.method;
|
|
457
|
+
const meta = this.addToMetadata(
|
|
458
|
+
parentReferencePath,
|
|
459
|
+
referenceId,
|
|
460
|
+
"method",
|
|
461
|
+
method,
|
|
462
|
+
title
|
|
463
|
+
);
|
|
330
464
|
methodList.push(
|
|
331
465
|
Object.assign(method, {
|
|
332
|
-
name: this.getReferencePathWithMeta(
|
|
333
|
-
|
|
334
|
-
|
|
466
|
+
name: this.getReferencePathWithMeta(
|
|
467
|
+
parentReferencePath,
|
|
468
|
+
meta
|
|
469
|
+
),
|
|
470
|
+
label: title
|
|
335
471
|
})
|
|
336
472
|
);
|
|
337
473
|
});
|
|
338
474
|
});
|
|
339
|
-
|
|
340
475
|
return methodList;
|
|
341
476
|
}
|
|
342
477
|
|
|
343
|
-
|
|
344
|
-
|
|
478
|
+
/**
|
|
479
|
+
* Gives URL path for reference items, Which can be used to push to the history
|
|
480
|
+
*/
|
|
481
|
+
private getReferencePathWithMeta(
|
|
482
|
+
parentReferencePath: string,
|
|
483
|
+
meta: string
|
|
484
|
+
): string {
|
|
485
|
+
// update the encoded url meta param
|
|
486
|
+
const encodedMeta = meta ? this.getUrlEncoded(meta) : "";
|
|
487
|
+
return encodedMeta ? `${parentReferencePath}?meta=${encodedMeta}` : "";
|
|
345
488
|
}
|
|
346
489
|
|
|
347
490
|
/**
|
|
@@ -351,12 +494,15 @@ export default class AmfReference extends LightningElement {
|
|
|
351
494
|
* The 'endpoint' nav item may have nested children.
|
|
352
495
|
*/
|
|
353
496
|
private assignNavigationItemsFromAmf(
|
|
354
|
-
|
|
497
|
+
amfConfig: AmfConfig,
|
|
355
498
|
amfIdx: number
|
|
356
499
|
): void {
|
|
500
|
+
const referenceId = amfConfig.id;
|
|
501
|
+
const parentReferencePath = amfConfig.href;
|
|
357
502
|
const model = this.amfMap[referenceId].parser.parsedModel;
|
|
358
503
|
|
|
359
504
|
const children = [];
|
|
505
|
+
const expandChildren = this.isExpandChildrenEnabled(referenceId);
|
|
360
506
|
|
|
361
507
|
NAVIGATION_ITEMS.forEach(
|
|
362
508
|
({ label, name, childrenPropertyName, type }) => {
|
|
@@ -365,13 +511,18 @@ export default class AmfReference extends LightningElement {
|
|
|
365
511
|
case "summary": {
|
|
366
512
|
const summary = model[type];
|
|
367
513
|
const meta = this.addToMetadata(
|
|
514
|
+
parentReferencePath,
|
|
368
515
|
referenceId,
|
|
369
516
|
type,
|
|
370
|
-
summary
|
|
517
|
+
summary,
|
|
518
|
+
label
|
|
371
519
|
);
|
|
372
520
|
children.push({
|
|
373
521
|
label,
|
|
374
|
-
name: this.getReferencePathWithMeta(
|
|
522
|
+
name: this.getReferencePathWithMeta(
|
|
523
|
+
parentReferencePath,
|
|
524
|
+
meta
|
|
525
|
+
)
|
|
375
526
|
});
|
|
376
527
|
break;
|
|
377
528
|
}
|
|
@@ -385,15 +536,17 @@ export default class AmfReference extends LightningElement {
|
|
|
385
536
|
indexedName
|
|
386
537
|
);
|
|
387
538
|
const childTopics = this.assignEndpointNavItems(
|
|
539
|
+
parentReferencePath,
|
|
388
540
|
referenceId,
|
|
389
541
|
model[childrenPropertyName]
|
|
390
542
|
);
|
|
391
543
|
children.push({
|
|
392
544
|
label,
|
|
393
545
|
name: this.getReferencePathWithMeta(
|
|
546
|
+
parentReferencePath,
|
|
394
547
|
this.metadata[amfTopicId]?.meta
|
|
395
548
|
),
|
|
396
|
-
isExpanded:
|
|
549
|
+
isExpanded: expandChildren,
|
|
397
550
|
children: childTopics
|
|
398
551
|
});
|
|
399
552
|
}
|
|
@@ -425,19 +578,23 @@ export default class AmfReference extends LightningElement {
|
|
|
425
578
|
children.push({
|
|
426
579
|
label,
|
|
427
580
|
name: this.getReferencePathWithMeta(
|
|
581
|
+
parentReferencePath,
|
|
428
582
|
this.metadata[amfTopicId]?.meta
|
|
429
583
|
),
|
|
430
|
-
isExpanded:
|
|
584
|
+
isExpanded: expandChildren,
|
|
431
585
|
children: model[childrenPropertyName].map(
|
|
432
586
|
(topic) => {
|
|
433
587
|
const meta = this.addToMetadata(
|
|
588
|
+
parentReferencePath,
|
|
434
589
|
referenceId,
|
|
435
590
|
type,
|
|
436
|
-
topic
|
|
591
|
+
topic,
|
|
592
|
+
topic.label
|
|
437
593
|
);
|
|
438
594
|
return {
|
|
439
595
|
label: topic.label,
|
|
440
596
|
name: this.getReferencePathWithMeta(
|
|
597
|
+
parentReferencePath,
|
|
441
598
|
meta
|
|
442
599
|
)
|
|
443
600
|
};
|
|
@@ -449,46 +606,41 @@ export default class AmfReference extends LightningElement {
|
|
|
449
606
|
}
|
|
450
607
|
);
|
|
451
608
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
isExpanded: amfIdx === 0, // only expand the first spec
|
|
457
|
-
children
|
|
609
|
+
this.navigation[amfIdx] = {
|
|
610
|
+
...this.navigation[amfIdx],
|
|
611
|
+
children,
|
|
612
|
+
isChildrenLoading: false
|
|
458
613
|
};
|
|
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;
|
|
614
|
+
this.navigation = [...this.navigation];
|
|
469
615
|
}
|
|
470
616
|
|
|
471
617
|
protected addToMetadata(
|
|
618
|
+
parentReferencePath: string,
|
|
472
619
|
referenceId: string,
|
|
473
620
|
type: string,
|
|
474
|
-
topic: { id: string; domId: string }
|
|
475
|
-
|
|
621
|
+
topic: { id: string; domId: string },
|
|
622
|
+
navTitle: string
|
|
623
|
+
): string | undefined {
|
|
476
624
|
const { urlIdentifer, prefix } = URL_CONFIG[type];
|
|
477
625
|
|
|
478
626
|
// encodeURI to avoid special characters in the URL meta.
|
|
479
627
|
const identifier =
|
|
480
628
|
topic[urlIdentifer] && this.encodeIdentifier(topic[urlIdentifer]);
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
meta
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
629
|
+
let meta;
|
|
630
|
+
// Assuming that there will be an identifier always
|
|
631
|
+
if (identifier) {
|
|
632
|
+
meta = prefix ? `${prefix}${identifier}` : `${identifier}`;
|
|
633
|
+
this.metadata[meta] = {
|
|
634
|
+
parentReferencePath,
|
|
635
|
+
meta,
|
|
636
|
+
referenceId,
|
|
637
|
+
amfId: topic.id,
|
|
638
|
+
elementId: topic.domId,
|
|
639
|
+
identifier,
|
|
640
|
+
type,
|
|
641
|
+
navTitle
|
|
642
|
+
};
|
|
643
|
+
}
|
|
492
644
|
return meta;
|
|
493
645
|
}
|
|
494
646
|
|
|
@@ -547,54 +699,25 @@ export default class AmfReference extends LightningElement {
|
|
|
547
699
|
}
|
|
548
700
|
|
|
549
701
|
/**
|
|
550
|
-
* Parses
|
|
702
|
+
* Parses URL query params without decoding of params
|
|
551
703
|
*/
|
|
552
|
-
private parseParams(
|
|
553
|
-
if (!
|
|
704
|
+
private parseParams(params: string): qs.ParsedQuery<string> {
|
|
705
|
+
if (!params) {
|
|
554
706
|
return {};
|
|
555
707
|
}
|
|
556
|
-
return qs.parse(
|
|
708
|
+
return qs.parse(params, {
|
|
557
709
|
decode: false
|
|
558
710
|
});
|
|
559
711
|
}
|
|
560
712
|
|
|
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
713
|
/**
|
|
591
714
|
* Normalizes topic identifier by replacing spaces with '+'
|
|
592
715
|
* and running encodeURI() on it
|
|
593
|
-
* @param
|
|
716
|
+
* @param identifier raw identifier for a topic as parsed from the spec file
|
|
594
717
|
* @returns normalized and encoded identifier
|
|
595
718
|
*/
|
|
596
|
-
protected encodeIdentifier(
|
|
597
|
-
let result =
|
|
719
|
+
protected encodeIdentifier(identifier: string): string {
|
|
720
|
+
let result = identifier.trim();
|
|
598
721
|
result = result.replace(new RegExp(/\s+/, "g"), "+");
|
|
599
722
|
return encodeURI(result);
|
|
600
723
|
}
|
|
@@ -606,86 +729,134 @@ export default class AmfReference extends LightningElement {
|
|
|
606
729
|
return `${referenceId}:${id}`;
|
|
607
730
|
}
|
|
608
731
|
|
|
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 {
|
|
732
|
+
protected updateUrlWithSelected(
|
|
733
|
+
parentReferencePath: string,
|
|
734
|
+
meta?: string
|
|
735
|
+
): void {
|
|
644
736
|
if (meta) {
|
|
737
|
+
// update the encoded url meta param
|
|
738
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
645
739
|
window.history.pushState(
|
|
646
740
|
{},
|
|
647
741
|
"",
|
|
648
|
-
`${
|
|
742
|
+
`${parentReferencePath}?meta=${encodedMeta}`
|
|
649
743
|
);
|
|
650
744
|
}
|
|
651
745
|
}
|
|
652
746
|
|
|
653
747
|
/**
|
|
654
|
-
* Does a replace on the
|
|
748
|
+
* Does a replace on the URL meta, so it does not create a history entry.
|
|
655
749
|
*/
|
|
656
|
-
protected replaceUrlWithSelected(
|
|
750
|
+
protected replaceUrlWithSelected(
|
|
751
|
+
parentReferencePath: string,
|
|
752
|
+
meta?: string
|
|
753
|
+
): void {
|
|
657
754
|
if (meta) {
|
|
755
|
+
// update the encoded url meta param
|
|
756
|
+
const encodedMeta = this.getUrlEncoded(meta);
|
|
658
757
|
window.history.replaceState(
|
|
659
758
|
{},
|
|
660
759
|
"",
|
|
661
|
-
`${
|
|
760
|
+
`${parentReferencePath}?meta=${encodedMeta}`
|
|
662
761
|
);
|
|
663
762
|
}
|
|
664
763
|
}
|
|
665
764
|
|
|
765
|
+
/**
|
|
766
|
+
* This method gets called when the user navigates back and forth using browser arrows
|
|
767
|
+
* Updates content depending on the type of reference - spec based or markdown
|
|
768
|
+
*/
|
|
769
|
+
protected updateSelectedItemFromUrlQuery(): void {
|
|
770
|
+
const specBasedReference = this.isSpecBasedReference(
|
|
771
|
+
this._currentReferenceId
|
|
772
|
+
);
|
|
773
|
+
if (specBasedReference) {
|
|
774
|
+
const currentMeta: RouteMeta | null = this.getReferenceMetaInfo(
|
|
775
|
+
window.location.href
|
|
776
|
+
);
|
|
777
|
+
const metadata =
|
|
778
|
+
currentMeta && this.getMetadataByUrlQuery(currentMeta);
|
|
779
|
+
if (metadata) {
|
|
780
|
+
const {
|
|
781
|
+
parentReferencePath,
|
|
782
|
+
referenceId,
|
|
783
|
+
amfId,
|
|
784
|
+
type,
|
|
785
|
+
elementId
|
|
786
|
+
}: AmfMetadataTopic = metadata;
|
|
787
|
+
this.loadSpecReferenceContent(
|
|
788
|
+
parentReferencePath,
|
|
789
|
+
referenceId,
|
|
790
|
+
amfId,
|
|
791
|
+
type,
|
|
792
|
+
elementId,
|
|
793
|
+
currentMeta.meta
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
} else {
|
|
797
|
+
this.loadMarkdownBasedReference();
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* The API Navigation event will always intend to navigate within the current reference
|
|
803
|
+
* @param event
|
|
804
|
+
*/
|
|
805
|
+
protected onApiNavigationChanged(): void {
|
|
806
|
+
const specBasedReference = this.isSpecBasedReference(
|
|
807
|
+
this._currentReferenceId
|
|
808
|
+
);
|
|
809
|
+
if (specBasedReference) {
|
|
810
|
+
const { meta } = this.selectedTopic;
|
|
811
|
+
const metadata = this.metadata[meta];
|
|
812
|
+
if (metadata) {
|
|
813
|
+
const {
|
|
814
|
+
parentReferencePath,
|
|
815
|
+
referenceId,
|
|
816
|
+
amfId,
|
|
817
|
+
type,
|
|
818
|
+
elementId
|
|
819
|
+
}: AmfMetadataTopic = metadata;
|
|
820
|
+
this.loadSpecReferenceContent(
|
|
821
|
+
parentReferencePath,
|
|
822
|
+
referenceId,
|
|
823
|
+
amfId,
|
|
824
|
+
type,
|
|
825
|
+
elementId,
|
|
826
|
+
metadata.meta
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
} else {
|
|
830
|
+
this.loadMarkdownBasedReference();
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
666
834
|
/**
|
|
667
835
|
* Updates the currently selected amf and topic
|
|
668
836
|
*/
|
|
669
|
-
protected
|
|
837
|
+
protected loadSpecReferenceContent(
|
|
838
|
+
parentReferencePath: string,
|
|
670
839
|
referenceId: string,
|
|
671
840
|
amfId: string,
|
|
672
841
|
type: string,
|
|
673
|
-
elementId
|
|
674
|
-
meta
|
|
842
|
+
elementId: string,
|
|
843
|
+
meta: string
|
|
675
844
|
): void {
|
|
676
845
|
this.selectedTopic = {
|
|
677
846
|
referenceId,
|
|
847
|
+
parentReferencePath,
|
|
678
848
|
amfId,
|
|
679
849
|
elementId,
|
|
680
850
|
type,
|
|
681
851
|
meta
|
|
682
852
|
};
|
|
683
|
-
this.selectedSidebarValue = this.getReferencePathWithMeta(
|
|
853
|
+
this.selectedSidebarValue = this.getReferencePathWithMeta(
|
|
854
|
+
parentReferencePath,
|
|
855
|
+
meta
|
|
856
|
+
);
|
|
684
857
|
|
|
685
858
|
this.handleSelectedItem();
|
|
686
859
|
|
|
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
860
|
this.updateDocPhase();
|
|
690
861
|
}
|
|
691
862
|
|
|
@@ -696,10 +867,9 @@ export default class AmfReference extends LightningElement {
|
|
|
696
867
|
/* If parent level doc phase is enabled, Individual reference level doc phase should not be considered */
|
|
697
868
|
|
|
698
869
|
if (!this.isParentLevelDocPhaseEnabled) {
|
|
699
|
-
const
|
|
700
|
-
const selectedReference = this._amfConfig.find(
|
|
870
|
+
const selectedReference = this._amfConfigList.find(
|
|
701
871
|
(referenceItem: AmfConfig) => {
|
|
702
|
-
return referenceItem.id ===
|
|
872
|
+
return referenceItem.id === this._currentReferenceId;
|
|
703
873
|
}
|
|
704
874
|
);
|
|
705
875
|
if (selectedReference) {
|
|
@@ -711,88 +881,414 @@ export default class AmfReference extends LightningElement {
|
|
|
711
881
|
}
|
|
712
882
|
|
|
713
883
|
/**
|
|
714
|
-
*
|
|
884
|
+
* Returns the decoded meta query param from given Url as it is being used internally.
|
|
715
885
|
*/
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
this.docsReferenceMetaSessionKey
|
|
886
|
+
getMetaFromUrl(referenceUrl: string): string {
|
|
887
|
+
const indexOfQueryParam = referenceUrl.indexOf("?");
|
|
888
|
+
const urlPath = referenceUrl.substring(
|
|
889
|
+
indexOfQueryParam >= 0 ? indexOfQueryParam : referenceUrl.length
|
|
721
890
|
);
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
891
|
+
const meta = this.parseParams(urlPath).meta as string;
|
|
892
|
+
// Always get the meta query param encoded and decode it and store it for internal use
|
|
893
|
+
// This has 2 advantages,
|
|
894
|
+
// 1. Supports backward compatible meta query param, so there is no need for redirects.
|
|
895
|
+
// 2. Supports Prerender and Coveo for their crawling.
|
|
896
|
+
const encodedMeta = meta && this.getUrlEncoded(meta);
|
|
897
|
+
const decodedMeta = encodedMeta && decodeURIComponent(encodedMeta);
|
|
898
|
+
return decodedMeta || "";
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
*
|
|
903
|
+
* @returns meta for given markdown based referenceUrl
|
|
904
|
+
* Consider last topic url in ../references/reference-name/example.html
|
|
905
|
+
*/
|
|
906
|
+
getMarkdownReferenceMeta(referenceUrl: string): string {
|
|
907
|
+
let meta = "";
|
|
908
|
+
if (referenceUrl) {
|
|
909
|
+
const slashSeparatorItems = referenceUrl.split("/");
|
|
910
|
+
const lastItem =
|
|
911
|
+
slashSeparatorItems[slashSeparatorItems.length - 1];
|
|
912
|
+
if (lastItem.endsWith(".html")) {
|
|
913
|
+
meta = lastItem;
|
|
731
914
|
}
|
|
732
915
|
}
|
|
916
|
+
return meta;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Gets the encoded url.
|
|
921
|
+
* This method will return the encoded url for 2 cases,
|
|
922
|
+
* 1. If the url is encoded already
|
|
923
|
+
* 2. If the url is decoded
|
|
924
|
+
*/
|
|
925
|
+
getUrlEncoded(url: string) {
|
|
926
|
+
// if url matches, then return the encoded url.
|
|
927
|
+
if (decodeURIComponent(url) === url) {
|
|
928
|
+
return encodeURIComponent(url);
|
|
929
|
+
}
|
|
930
|
+
// return the encoded url.
|
|
931
|
+
return this.getUrlEncoded(decodeURIComponent(url));
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
*
|
|
936
|
+
* @returns RouteMeta object for given referenceUrl
|
|
937
|
+
* referenceId - gets referenceId from url
|
|
938
|
+
* For spec based references gets meta parm from url and then topicId & type from meta
|
|
939
|
+
* For markdown based references gets topicId as last html path in the name, meta & type will be empty
|
|
940
|
+
*/
|
|
941
|
+
getReferenceMetaInfo(referenceUrl: string): RouteMeta | undefined {
|
|
942
|
+
let metaReferenceInfo;
|
|
943
|
+
if (referenceUrl) {
|
|
944
|
+
const referenceId = this.getReferenceIdFromUrl(referenceUrl);
|
|
945
|
+
let meta = "";
|
|
946
|
+
let topicId = "";
|
|
947
|
+
let type = "";
|
|
948
|
+
if (this.isSpecBasedReference(referenceId)) {
|
|
949
|
+
meta = this.getMetaFromUrl(referenceUrl);
|
|
950
|
+
if (meta) {
|
|
951
|
+
if (meta.includes(":")) {
|
|
952
|
+
const metaInfo = meta.split(":");
|
|
953
|
+
type = metaInfo[0];
|
|
954
|
+
topicId = metaInfo[1] || type;
|
|
955
|
+
} else {
|
|
956
|
+
topicId = meta;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
} else {
|
|
960
|
+
topicId = this.getMarkdownReferenceMeta(referenceUrl);
|
|
961
|
+
}
|
|
962
|
+
metaReferenceInfo = {
|
|
963
|
+
referenceId,
|
|
964
|
+
meta,
|
|
965
|
+
topicId,
|
|
966
|
+
type
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
return metaReferenceInfo;
|
|
970
|
+
}
|
|
733
971
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
972
|
+
/**
|
|
973
|
+
* Finds and returns referenceUrl and topicTitle if given topic url matches
|
|
974
|
+
*/
|
|
975
|
+
getReferenceDetailsInGivenTopics(
|
|
976
|
+
topics: ParsedMarkdownTopic[],
|
|
977
|
+
topicMeta: string
|
|
978
|
+
): { referenceUrl: string; topicTitle: string } {
|
|
979
|
+
let referenceUrl = "";
|
|
980
|
+
let topicTitle = "";
|
|
981
|
+
for (let i = 0; i < topics.length; i++) {
|
|
982
|
+
const topic = topics[i];
|
|
983
|
+
const meta = this.getMarkdownReferenceMeta(topic.link.href);
|
|
984
|
+
const childTopics = topic.children;
|
|
985
|
+
if (meta === topicMeta) {
|
|
986
|
+
referenceUrl = topic.link.href;
|
|
987
|
+
topicTitle = topic.label;
|
|
988
|
+
} else if (childTopics && childTopics.length) {
|
|
989
|
+
const referenceDetails = this.getReferenceDetailsInGivenTopics(
|
|
990
|
+
childTopics,
|
|
991
|
+
topicMeta
|
|
992
|
+
);
|
|
993
|
+
referenceUrl = referenceDetails.referenceUrl;
|
|
994
|
+
topicTitle = referenceDetails.topicTitle;
|
|
995
|
+
}
|
|
996
|
+
if (referenceUrl && topicTitle) {
|
|
997
|
+
break;
|
|
739
998
|
}
|
|
740
999
|
}
|
|
1000
|
+
return {
|
|
1001
|
+
referenceUrl,
|
|
1002
|
+
topicTitle
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Gives referenceUrl and topicTitle for given markdown topic url
|
|
1008
|
+
*/
|
|
1009
|
+
getRefDetailsForGivenTopicMeta(
|
|
1010
|
+
referenceId: string,
|
|
1011
|
+
topicMeta: string
|
|
1012
|
+
): { referenceUrl: string; topicTitle: string } | undefined {
|
|
1013
|
+
const amfConfig = this.getAmfConfigWithId(referenceId);
|
|
1014
|
+
let referenceDetails;
|
|
1015
|
+
if (amfConfig) {
|
|
1016
|
+
const topics = amfConfig.topic?.children || [];
|
|
1017
|
+
referenceDetails = this.getReferenceDetailsInGivenTopics(
|
|
1018
|
+
topics,
|
|
1019
|
+
topicMeta
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
return referenceDetails;
|
|
1023
|
+
}
|
|
741
1024
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
1025
|
+
/**
|
|
1026
|
+
* Updates the DOM on the first load
|
|
1027
|
+
*/
|
|
1028
|
+
updateView(): void {
|
|
1029
|
+
const previousRefUrlInSession = window.sessionStorage.getItem(
|
|
1030
|
+
this.docsReferenceUrlSessionKey
|
|
1031
|
+
);
|
|
1032
|
+
window.sessionStorage.removeItem(this.docsReferenceUrlSessionKey);
|
|
1033
|
+
let previousRefInfo = this.getReferenceMetaInfo(
|
|
1034
|
+
previousRefUrlInSession
|
|
1035
|
+
);
|
|
1036
|
+
|
|
1037
|
+
// For spec based reference, We should consider urlData to show same topic when user reloads after navigating to specific topic
|
|
1038
|
+
if (!previousRefInfo) {
|
|
1039
|
+
const currentUrl = window.location.href;
|
|
1040
|
+
const urlReferenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1041
|
+
if (urlReferenceId && this.isSpecBasedReference(urlReferenceId)) {
|
|
1042
|
+
if (
|
|
1043
|
+
!this.isProjectRootPath() &&
|
|
1044
|
+
!this.isParentReferencePath(currentUrl)
|
|
1045
|
+
) {
|
|
1046
|
+
previousRefInfo = this.getReferenceMetaInfo(currentUrl);
|
|
1047
|
+
}
|
|
748
1048
|
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
let referenceId: string;
|
|
1052
|
+
let topicId = "";
|
|
1053
|
+
|
|
1054
|
+
if (
|
|
1055
|
+
previousRefInfo &&
|
|
1056
|
+
this._amfConfigMap.has(previousRefInfo.referenceId)
|
|
1057
|
+
) {
|
|
1058
|
+
referenceId = previousRefInfo.referenceId;
|
|
1059
|
+
topicId = previousRefInfo.topicId;
|
|
1060
|
+
} else {
|
|
1061
|
+
referenceId = this._currentReferenceId;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
const specBasedReference = this.isSpecBasedReference(referenceId);
|
|
1065
|
+
if (specBasedReference) {
|
|
1066
|
+
// Wait till the AMF is loaded.
|
|
1067
|
+
this.amfFetchPromiseMap[referenceId].then(() => {
|
|
1068
|
+
let selectedItemMetaData = this.getMetadataByIdentifier(
|
|
1069
|
+
referenceId,
|
|
1070
|
+
topicId
|
|
1071
|
+
);
|
|
1072
|
+
if (!selectedItemMetaData) {
|
|
1073
|
+
// Doesn't exist, let's use the summary.
|
|
1074
|
+
selectedItemMetaData = this.getMetadataByType(
|
|
1075
|
+
referenceId,
|
|
1076
|
+
"summary"
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
749
1079
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1080
|
+
if (selectedItemMetaData) {
|
|
1081
|
+
this.loadSpecReferenceContent(
|
|
1082
|
+
selectedItemMetaData.parentReferencePath,
|
|
1083
|
+
selectedItemMetaData.referenceId,
|
|
1084
|
+
selectedItemMetaData.amfId,
|
|
1085
|
+
selectedItemMetaData.type,
|
|
1086
|
+
"",
|
|
1087
|
+
selectedItemMetaData.meta
|
|
1088
|
+
);
|
|
1089
|
+
this.updateUrlWithSelected(
|
|
1090
|
+
selectedItemMetaData.parentReferencePath,
|
|
1091
|
+
selectedItemMetaData.meta
|
|
1092
|
+
);
|
|
1093
|
+
this.updateNavTitleMetaTag(selectedItemMetaData.navTitle);
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1096
|
+
} else {
|
|
1097
|
+
let invalidTopicReferenceUrl = "";
|
|
1098
|
+
if (topicId) {
|
|
1099
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1100
|
+
referenceId,
|
|
1101
|
+
topicId
|
|
757
1102
|
);
|
|
1103
|
+
const selectedItemUrl = referenceDetails?.referenceUrl;
|
|
1104
|
+
if (!selectedItemUrl) {
|
|
1105
|
+
invalidTopicReferenceUrl = previousRefUrlInSession;
|
|
1106
|
+
}
|
|
758
1107
|
}
|
|
759
|
-
|
|
1108
|
+
this.loadMarkdownBasedReference(invalidTopicReferenceUrl);
|
|
1109
|
+
}
|
|
760
1110
|
}
|
|
761
1111
|
|
|
762
1112
|
/**
|
|
763
|
-
*
|
|
1113
|
+
* Navigates to reference of the given URL
|
|
1114
|
+
* @param url
|
|
764
1115
|
*/
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
const
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
1116
|
+
private loadNewReferenceItem(url: string): void {
|
|
1117
|
+
const referenceId = this.getReferenceIdFromUrl(url);
|
|
1118
|
+
const referenceItem = this.getAmfConfigWithId(referenceId);
|
|
1119
|
+
if (referenceItem) {
|
|
1120
|
+
window.location.href = referenceItem.href;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
/**
|
|
1125
|
+
* @param referenceUrl to which user wants to navigate
|
|
1126
|
+
* Redirect to first sub item if it's root level item, otherwise content will be loaded
|
|
1127
|
+
* Push the history as a first child item
|
|
1128
|
+
* set selected sidebar value as a pathname
|
|
1129
|
+
*/
|
|
1130
|
+
|
|
1131
|
+
private loadMarkdownBasedReference(referenceUrl?: string): void {
|
|
1132
|
+
let referenceId = "";
|
|
1133
|
+
const currentUrl = window.location.href;
|
|
1134
|
+
if (this.isProjectRootPath()) {
|
|
1135
|
+
/**
|
|
1136
|
+
* CASE1: This case is to consider when the user navigates to references by clicking a project card
|
|
1137
|
+
* Ex: /docs/example-project/references should navigate to the first topic in the first reference
|
|
1138
|
+
*/
|
|
1139
|
+
referenceId = this._currentReferenceId;
|
|
1140
|
+
} else if (this.isParentReferencePath(referenceUrl)) {
|
|
1141
|
+
/**
|
|
1142
|
+
* CASE2: This case is to navigate to respective reference when the user clicked on root item
|
|
1143
|
+
* Ex: .../references/markdown-ref should navigate to first topic.
|
|
1144
|
+
*/
|
|
1145
|
+
referenceId = this.getReferenceIdFromUrl(referenceUrl);
|
|
1146
|
+
} else if (this.isParentReferencePath(currentUrl)) {
|
|
1147
|
+
/**
|
|
1148
|
+
* CASE3: This case is to navigate to respective reference when the user entered url with reference id
|
|
1149
|
+
* Ex: .../references/markdown-ref should navigate to first topic.
|
|
1150
|
+
*/
|
|
1151
|
+
referenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1152
|
+
} else if (referenceUrl) {
|
|
1153
|
+
/**
|
|
1154
|
+
* CASE4: This case is to navigate to first item when we don't have topic in the selected version
|
|
1155
|
+
* Ex: .../references/markdown-ref/not-existed-topic-url should navigate to first topic.
|
|
1156
|
+
*/
|
|
1157
|
+
const referenceMeta = this.getMarkdownReferenceMeta(referenceUrl);
|
|
1158
|
+
const selectedItemRefId = this.getReferenceIdFromUrl(referenceUrl);
|
|
1159
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1160
|
+
selectedItemRefId,
|
|
1161
|
+
referenceMeta
|
|
773
1162
|
);
|
|
1163
|
+
const selectedItemUrl = referenceDetails?.referenceUrl;
|
|
1164
|
+
if (!selectedItemUrl) {
|
|
1165
|
+
referenceId = this.getReferenceIdFromUrl(referenceUrl);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
let isRedirecting = false;
|
|
1170
|
+
if (referenceId) {
|
|
1171
|
+
const amfConfig = this.getAmfConfigWithId(referenceId);
|
|
1172
|
+
let redirectReferenceUrl = "";
|
|
1173
|
+
if (amfConfig) {
|
|
1174
|
+
const childrenItems = amfConfig.topic.children;
|
|
1175
|
+
if (childrenItems.length > 0) {
|
|
1176
|
+
redirectReferenceUrl = childrenItems[0].link.href;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
if (redirectReferenceUrl) {
|
|
1180
|
+
if (this.isParentReferencePath(referenceUrl)) {
|
|
1181
|
+
// This is for CASE2 mentioned above, Where we need to navigate user to respective href
|
|
1182
|
+
isRedirecting = true;
|
|
1183
|
+
window.location.href = redirectReferenceUrl;
|
|
1184
|
+
} else {
|
|
1185
|
+
// This is for CASE 1,3 and 4 mentioned above, Where we need to update the browser history
|
|
1186
|
+
window.history.replaceState({}, "", redirectReferenceUrl);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
if (!isRedirecting) {
|
|
1191
|
+
const currentReferenceUrl = window.location.href;
|
|
1192
|
+
const referenceMeta =
|
|
1193
|
+
this.getMarkdownReferenceMeta(currentReferenceUrl);
|
|
1194
|
+
const selectedItemRefId =
|
|
1195
|
+
this.getReferenceIdFromUrl(currentReferenceUrl);
|
|
1196
|
+
const referenceDetails = this.getRefDetailsForGivenTopicMeta(
|
|
1197
|
+
selectedItemRefId,
|
|
1198
|
+
referenceMeta
|
|
1199
|
+
);
|
|
1200
|
+
if (referenceDetails) {
|
|
1201
|
+
this.updateNavTitleMetaTag(referenceDetails.topicTitle);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
this.versions = this.getVersions();
|
|
1205
|
+
this.updateDocPhase();
|
|
1206
|
+
this.selectedSidebarValue = window.location.pathname;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
* Currently, used to handle the version change and store the current reference Url.
|
|
1212
|
+
*/
|
|
1213
|
+
handleVersionChange(): void {
|
|
1214
|
+
const currentUrl = window.location.href;
|
|
1215
|
+
window.sessionStorage.setItem(
|
|
1216
|
+
this.docsReferenceUrlSessionKey,
|
|
1217
|
+
currentUrl
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
private updateNavTitleMetaTag(navTitle = ""): void {
|
|
1222
|
+
// this is required to update the nav title meta tag.
|
|
1223
|
+
// eslint-disable-next-line @lwc/lwc/no-document-query
|
|
1224
|
+
const metaNavTitle = document.querySelector('meta[name="nav-title"]');
|
|
1225
|
+
if (metaNavTitle && navTitle) {
|
|
1226
|
+
metaNavTitle.setAttribute("content", navTitle);
|
|
774
1227
|
}
|
|
775
1228
|
}
|
|
776
1229
|
|
|
777
1230
|
onNavSelect(event: CustomEvent): void {
|
|
778
1231
|
const name = event.detail.name;
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
1232
|
+
if (name) {
|
|
1233
|
+
const urlReferenceId = this.getReferenceIdFromUrl(name);
|
|
1234
|
+
const specBasedReference =
|
|
1235
|
+
this.isSpecBasedReference(urlReferenceId);
|
|
1236
|
+
if (specBasedReference) {
|
|
1237
|
+
const metaVal = this.getMetaFromUrl(name);
|
|
1238
|
+
const currentSelectedMeta = this.selectedTopic
|
|
1239
|
+
? this.selectedTopic.meta
|
|
1240
|
+
: "";
|
|
1241
|
+
|
|
1242
|
+
if (metaVal && metaVal === currentSelectedMeta) {
|
|
1243
|
+
// selecting the same nav item, skip update
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
785
1246
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1247
|
+
const metadata = this.metadata[metaVal];
|
|
1248
|
+
if (metadata) {
|
|
1249
|
+
const {
|
|
1250
|
+
parentReferencePath,
|
|
1251
|
+
referenceId,
|
|
1252
|
+
amfId,
|
|
1253
|
+
type,
|
|
1254
|
+
elementId
|
|
1255
|
+
} = metadata;
|
|
1256
|
+
this.loadSpecReferenceContent(
|
|
1257
|
+
parentReferencePath,
|
|
1258
|
+
referenceId,
|
|
1259
|
+
amfId,
|
|
1260
|
+
type,
|
|
1261
|
+
elementId,
|
|
1262
|
+
metaVal
|
|
1263
|
+
);
|
|
1264
|
+
this.updateUrlWithSelected(parentReferencePath, metaVal);
|
|
1265
|
+
this.updateNavTitleMetaTag(metadata.navTitle);
|
|
1266
|
+
} else {
|
|
1267
|
+
if (this.isParentReferencePath(name)) {
|
|
1268
|
+
this.loadNewReferenceItem(name);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
} else {
|
|
1272
|
+
this.loadMarkdownBasedReference(name);
|
|
1273
|
+
}
|
|
789
1274
|
}
|
|
1275
|
+
}
|
|
790
1276
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
this.
|
|
795
|
-
|
|
1277
|
+
onExpandCollapse(event: CustomEvent): void {
|
|
1278
|
+
const { name, isSelectAction, isExpanded } = event.detail;
|
|
1279
|
+
if (!isSelectAction && isExpanded) {
|
|
1280
|
+
const referenceId = this.getReferenceIdFromUrl(name);
|
|
1281
|
+
const currentUrl = window.location.href;
|
|
1282
|
+
const currentReferenceId = this.getReferenceIdFromUrl(currentUrl);
|
|
1283
|
+
//No need to do anything if user is expanding currently selected reference
|
|
1284
|
+
if (referenceId !== currentReferenceId) {
|
|
1285
|
+
const isSpecBasedReference =
|
|
1286
|
+
this.isSpecBasedReference(referenceId);
|
|
1287
|
+
if (isSpecBasedReference) {
|
|
1288
|
+
// Perform functionality same as item selection
|
|
1289
|
+
this.onNavSelect(event);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
796
1292
|
}
|
|
797
1293
|
}
|
|
798
1294
|
|