@salesforcedevs/docs-components 0.54.0-alpha03 → 0.54.0-alpha04
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 +3 -2
- package/src/modules/README.md +41 -0
- package/src/modules/doc/amfReference/amfReference.ts +45 -106
- package/src/modules/doc/contentCallout/contentCallout.css +1 -1
- package/src/modules/docBaseElements/lightningElementWithState/lightningElementWithState.ts +3 -3
- package/src/modules/docHelpers/phaseContentLayout/phaseContentLayout.css +3 -1
- package/src/modules/docUtils/SearchSyncer/SearchSyncer.ts +7 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/docs-components",
|
|
3
|
-
"version": "0.54.0-
|
|
3
|
+
"version": "0.54.0-alpha04",
|
|
4
4
|
"description": "Docs Lightning web components for DSC",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.js",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"kagekiri": "^1.4.1",
|
|
18
18
|
"lodash.orderby": "^4.6.0",
|
|
19
19
|
"lodash.uniqby": "^4.7.0",
|
|
20
|
-
"query-string": "^7.1.1"
|
|
20
|
+
"query-string": "^7.1.1",
|
|
21
|
+
"sentence-case": "^3.0.4"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/classnames": "^2.2.10",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## AMF Reference
|
|
2
|
+
|
|
3
|
+
AMF refers to MuleSoft’s AML Modeling Framework for modeling documentation and it’s metadata. In this context, AMF is leveraged to parse and normalize API documentation from varying sources and formats, to one format which is the AMF file. We then leverage HTML Web Components created by MuleSoft to render this API documentation by passing it the generated AMF. These HTML Web Components may be referred to as API Console components, ARC (advanced rest components) components, or api documentation components (for the npm package).
|
|
4
|
+
|
|
5
|
+
Ref:
|
|
6
|
+
https://a.ml/docs/amf/
|
|
7
|
+
https://github.com/aml-org/amf
|
|
8
|
+
|
|
9
|
+
## AMF Reference Component
|
|
10
|
+
|
|
11
|
+
_Components:_ doc-amf-reference, apihub-amf-topic
|
|
12
|
+
|
|
13
|
+
The AMF Reference Component is a LWC component defined within the developer website’s theme. This component is rendered on the API Reference pages.
|
|
14
|
+
|
|
15
|
+
Ref: https://github.com/salesforcedevs/developer-website/tree/main/theme/src/modules/apihub
|
|
16
|
+
|
|
17
|
+
This component takes as input a list of JSON metadata containing the URL information of the reference spec data files. This JSON configuration is generated for each writer repository that contains reference content, and is generated by the SFDocs framework.
|
|
18
|
+
|
|
19
|
+
This component
|
|
20
|
+
|
|
21
|
+
- Takes as input the reference data files (as AMF JSON)
|
|
22
|
+
- Parses the AML data into a model
|
|
23
|
+
- Plugs the model into the ARC components to surface documentation content
|
|
24
|
+
- Handles navigation events to browse the content
|
|
25
|
+
|
|
26
|
+
### AMF Parser
|
|
27
|
+
|
|
28
|
+
Ref: https://github.com/salesforcedevs/developer-website/blob/main/theme/src/modules/apihub/amfReference/amf-parser.js
|
|
29
|
+
|
|
30
|
+
This class parses the AMF JSON data for one spec and extrapolates the data specific to rendering sections of that specs topic documentation.
|
|
31
|
+
|
|
32
|
+
The parsed data includes:
|
|
33
|
+
|
|
34
|
+
- Title
|
|
35
|
+
- Topics:
|
|
36
|
+
- Summary
|
|
37
|
+
- Endpoints
|
|
38
|
+
- Methods
|
|
39
|
+
- Types
|
|
40
|
+
- Docs
|
|
41
|
+
- Security
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { LightningElement, api, track } from "lwc";
|
|
2
|
+
import { noCase } from "no-case";
|
|
3
|
+
import { sentenceCase } from "sentence-case";
|
|
2
4
|
import qs from "query-string";
|
|
5
|
+
import { AmfModelParser } from "./utils";
|
|
6
|
+
import { RouteMeta } from "./route-meta";
|
|
3
7
|
import type {
|
|
4
8
|
AmfConfig,
|
|
5
9
|
AmfMetadataTopic,
|
|
@@ -12,8 +16,6 @@ import type {
|
|
|
12
16
|
ReferenceSetConfig,
|
|
13
17
|
AmfMetaTopicType
|
|
14
18
|
} from "./types";
|
|
15
|
-
import { AmfModelParser } from "./utils";
|
|
16
|
-
import { RouteMeta } from "./route-meta";
|
|
17
19
|
|
|
18
20
|
const NAVIGATION_ITEMS = [
|
|
19
21
|
{
|
|
@@ -191,10 +193,12 @@ export default class AmfReference extends LightningElement {
|
|
|
191
193
|
|
|
192
194
|
constructor() {
|
|
193
195
|
super();
|
|
194
|
-
this._boundOnApiNavigationChanged =
|
|
195
|
-
this
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
this._boundOnApiNavigationChanged = this.onApiNavigationChanged.bind(
|
|
197
|
+
this
|
|
198
|
+
);
|
|
199
|
+
this._boundUpdateSelectedItemFromUrlQuery = this.updateSelectedItemFromUrlQuery.bind(
|
|
200
|
+
this
|
|
201
|
+
);
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
connectedCallback(): void {
|
|
@@ -294,38 +298,15 @@ export default class AmfReference extends LightningElement {
|
|
|
294
298
|
}
|
|
295
299
|
|
|
296
300
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
301
|
-
* @param
|
|
302
|
-
* @returns
|
|
301
|
+
* Convert any case to a readable Title
|
|
302
|
+
* ex: snake_case => Snake case
|
|
303
|
+
* ex: camelCase => Camel case
|
|
304
|
+
* ex: PascalCase => Pascal case
|
|
305
|
+
* @param label
|
|
306
|
+
* @returns string
|
|
303
307
|
*/
|
|
304
|
-
private
|
|
305
|
-
|
|
306
|
-
model: ParsedTopicModel
|
|
307
|
-
): NavItem {
|
|
308
|
-
const { label, methods = [] } = model;
|
|
309
|
-
const meta = this.addToMetadata(referenceId, "endpoint", model);
|
|
310
|
-
|
|
311
|
-
const navItem: NavItem = {
|
|
312
|
-
name: this.getReferencePathWithMeta(meta),
|
|
313
|
-
label
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
if (methods.length) {
|
|
317
|
-
// assign the endpoint methods as its children
|
|
318
|
-
navItem.children = methods.map((method) => {
|
|
319
|
-
const _meta = this.addToMetadata(referenceId, "method", method);
|
|
320
|
-
return Object.assign(method, {
|
|
321
|
-
name: this.getReferencePathWithMeta(_meta),
|
|
322
|
-
label: method.label || method.method
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
navItem.isExpanded = false;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return navItem;
|
|
308
|
+
private getTitleForLabel(label: string): string {
|
|
309
|
+
return sentenceCase(noCase(label));
|
|
329
310
|
}
|
|
330
311
|
|
|
331
312
|
/**
|
|
@@ -341,71 +322,22 @@ export default class AmfReference extends LightningElement {
|
|
|
341
322
|
referenceId: string,
|
|
342
323
|
items: ParsedTopicModel[]
|
|
343
324
|
): NavItem[] {
|
|
344
|
-
const
|
|
345
|
-
let prevIndent = -1;
|
|
325
|
+
const methodList = [];
|
|
346
326
|
|
|
347
327
|
items.forEach((item) => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
// create new indent group
|
|
357
|
-
const indentGroup = {
|
|
358
|
-
indent,
|
|
359
|
-
children: [endpoint]
|
|
360
|
-
};
|
|
361
|
-
// push to stack
|
|
362
|
-
indentStack.push(indentGroup);
|
|
363
|
-
} else if (indent === prevIndent) {
|
|
364
|
-
// no change in indentation level
|
|
365
|
-
const lastIndentGroup = indentStack[indentStack.length - 1];
|
|
366
|
-
lastIndentGroup.children.push(endpoint);
|
|
367
|
-
} else {
|
|
368
|
-
// indent < prevIndent: back out to last matching indentation level
|
|
369
|
-
let indentGroup = indentStack.pop();
|
|
370
|
-
// hold on to the last indent group's children
|
|
371
|
-
let lastIndentGroupChildren = indentGroup.children;
|
|
372
|
-
|
|
373
|
-
while (indent < indentGroup.indent) {
|
|
374
|
-
// back out another indentation level
|
|
375
|
-
indentGroup = indentStack.pop();
|
|
376
|
-
// append children to next level's last child
|
|
377
|
-
const lastChild =
|
|
378
|
-
indentGroup.children[indentGroup.children.length - 1];
|
|
379
|
-
lastChild.children = (lastChild.children || []).concat(
|
|
380
|
-
lastIndentGroupChildren
|
|
381
|
-
);
|
|
382
|
-
lastIndentGroupChildren = indentGroup.children;
|
|
383
|
-
}
|
|
384
|
-
indentGroup.children.push(endpoint);
|
|
385
|
-
indentStack.push(indentGroup);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// update prevIndent
|
|
389
|
-
prevIndent = indent;
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// fold remaining indent levels up to the root
|
|
393
|
-
if (prevIndent > 0) {
|
|
394
|
-
let indentGroup = indentStack.pop();
|
|
395
|
-
let lastIndentGroupChildren = indentGroup.children;
|
|
396
|
-
while (indentGroup.indent > 0) {
|
|
397
|
-
indentGroup = indentStack.pop();
|
|
398
|
-
const lastChild =
|
|
399
|
-
indentGroup.children[indentGroup.children.length - 1];
|
|
400
|
-
lastChild.children = (lastChild.children || []).concat(
|
|
401
|
-
lastIndentGroupChildren
|
|
328
|
+
item.methods?.forEach((method) => {
|
|
329
|
+
const meta = this.addToMetadata(referenceId, "method", method);
|
|
330
|
+
methodList.push(
|
|
331
|
+
Object.assign(method, {
|
|
332
|
+
name: this.getReferencePathWithMeta(meta),
|
|
333
|
+
label:
|
|
334
|
+
this.getTitleForLabel(method.label) || method.method
|
|
335
|
+
})
|
|
402
336
|
);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
indentStack.push(indentGroup);
|
|
406
|
-
}
|
|
337
|
+
});
|
|
338
|
+
});
|
|
407
339
|
|
|
408
|
-
return
|
|
340
|
+
return methodList;
|
|
409
341
|
}
|
|
410
342
|
|
|
411
343
|
private getReferencePathWithMeta(meta: string): string {
|
|
@@ -678,8 +610,12 @@ export default class AmfReference extends LightningElement {
|
|
|
678
610
|
const currentMeta: RouteMeta | null = this.getCurrentRefMeta();
|
|
679
611
|
const metadata = currentMeta && this.getMetadataByUrlQuery(currentMeta);
|
|
680
612
|
if (metadata) {
|
|
681
|
-
const {
|
|
682
|
-
|
|
613
|
+
const {
|
|
614
|
+
referenceId,
|
|
615
|
+
amfId,
|
|
616
|
+
type,
|
|
617
|
+
elementId
|
|
618
|
+
}: AmfMetadataTopic = metadata;
|
|
683
619
|
this.loadContent(
|
|
684
620
|
referenceId,
|
|
685
621
|
amfId,
|
|
@@ -691,12 +627,15 @@ export default class AmfReference extends LightningElement {
|
|
|
691
627
|
}
|
|
692
628
|
protected onApiNavigationChanged(): void {
|
|
693
629
|
// The API Navigation event will always intend to navigate within the current reference
|
|
694
|
-
const metadata =
|
|
695
|
-
this.
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
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;
|
|
700
639
|
this.loadContent(referenceId, amfId, type, elementId, metadata.meta);
|
|
701
640
|
this.updateUrlWithSelected();
|
|
702
641
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import { LightningElement, track } from "lwc";
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -76,7 +75,9 @@ export abstract class LightningElementWithState<
|
|
|
76
75
|
};
|
|
77
76
|
this._didInitializeState = true;
|
|
78
77
|
} else {
|
|
79
|
-
throw new Error(
|
|
78
|
+
throw new Error(
|
|
79
|
+
"To mutate state after initialization, use `this.setState`."
|
|
80
|
+
);
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -90,4 +91,3 @@ export abstract class LightningElementWithState<
|
|
|
90
91
|
};
|
|
91
92
|
};
|
|
92
93
|
}
|
|
93
|
-
|
|
@@ -25,7 +25,9 @@ doc-phase::part(container) {
|
|
|
25
25
|
|
|
26
26
|
@media screen and (min-width: 1496px) {
|
|
27
27
|
doc-phase::part(container) {
|
|
28
|
-
margin-right: calc(
|
|
28
|
+
margin-right: calc(
|
|
29
|
+
var(--dx-g-page-padding-horizontal) - var(--dx-g-spacing-lg)
|
|
30
|
+
);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -4,7 +4,9 @@ export interface SearchSyncerConstructorArgs {
|
|
|
4
4
|
onUrlChange?: (nextSearchString: string) => unknown;
|
|
5
5
|
};
|
|
6
6
|
eventName: string;
|
|
7
|
-
historyMethod?:
|
|
7
|
+
historyMethod?:
|
|
8
|
+
| typeof window.history.pushState
|
|
9
|
+
| typeof window.history.replaceState;
|
|
8
10
|
searchParam: string;
|
|
9
11
|
shouldStopPropagation?: boolean;
|
|
10
12
|
target: EventTarget;
|
|
@@ -40,7 +42,10 @@ export class SearchSyncer {
|
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
public dispose = (): void => {
|
|
43
|
-
this.target.removeEventListener(
|
|
45
|
+
this.target.removeEventListener(
|
|
46
|
+
this.eventName,
|
|
47
|
+
this.handleSearchChange
|
|
48
|
+
);
|
|
44
49
|
this.target.removeEventListener("popstate", this.handlePopState);
|
|
45
50
|
this.target = undefined;
|
|
46
51
|
this.callbacks.onSearchChange = undefined;
|