@salesforcedevs/docs-components 1.28.5-node22-1 → 1.28.5-redoc-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/docs-components",
3
- "version": "1.28.5-node22-1",
3
+ "version": "1.28.5-redoc-alpha",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -42,7 +42,18 @@
42
42
  latest-version={latestVersion}
43
43
  ></doc-version-picker>
44
44
  </div>
45
- <template lwc:if={showSpecBasedReference}>
45
+ <template lwc:if={showRedocReference}>
46
+ <doc-redoc-reference
47
+ reference-config={redocReferenceConfig}
48
+ doc-phase-info={docPhaseInfo}
49
+ project-title={projectTitle}
50
+ spec-title={redocSpecTitle}
51
+ origin={origin}
52
+ >
53
+ <div class="redoc-container"></div>
54
+ </doc-redoc-reference>
55
+ </template>
56
+ <template lwc:elseif={showSpecBasedReference}>
46
57
  <div class="container">
47
58
  <div class="api-documentation">
48
59
  <doc-amf-topic
@@ -24,6 +24,7 @@ import {
24
24
  NAVIGATION_ITEMS,
25
25
  URL_CONFIG,
26
26
  REFERENCE_TYPES,
27
+ RENDER_WITH,
27
28
  oldReferenceIdNewReferenceIdMap
28
29
  } from "./constants";
29
30
  import { restoreScroll } from "dx/scrollManager";
@@ -44,6 +45,12 @@ export default class AmfReference extends LightningElement {
44
45
  /** Optional Twitter "via" handle (e.g. SalesforceDevs) for social share; passed to doc-content-layout. */
45
46
  @api twitterVia: string | null = null;
46
47
  @api sidebarHeader!: string;
48
+ /**
49
+ * Project title shown by `<doc-header>` (as its `subtitle`). Forwarded to
50
+ * `<doc-redoc-reference>` so it can surface the same project title inside
51
+ * the Redoc-rendered UI.
52
+ */
53
+ @api projectTitle: string | null = null;
47
54
  @api tocTitle?: string;
48
55
  @api tocOptions?: string;
49
56
  @api tocAriaLevel?: string;
@@ -69,7 +76,48 @@ export default class AmfReference extends LightningElement {
69
76
  * Gives if the currently selected reference is spec based or not
70
77
  */
71
78
  get showSpecBasedReference(): boolean {
72
- return this.isSpecBasedReference(this._currentReferenceId);
79
+ return (
80
+ this.isSpecBasedReference(this._currentReferenceId) &&
81
+ !this.showRedocReference
82
+ );
83
+ }
84
+
85
+ /**
86
+ * Whether the currently selected reference is rendered with Redoc.
87
+ * Driven by the backend-supplied `renderWith` attribute on the AmfConfig.
88
+ */
89
+ get showRedocReference(): boolean {
90
+ return this.isRedocReference(this._currentReferenceId);
91
+ }
92
+
93
+ /**
94
+ * Serialized config consumed by `<doc-redoc-reference>`. Built from the
95
+ * currently selected redoc reference so Redoc has a single spec to render.
96
+ */
97
+ get redocReferenceConfig(): string {
98
+ const ref = this.getAmfConfigWithId(this._currentReferenceId);
99
+ if (!ref) {
100
+ return JSON.stringify({ refList: [] });
101
+ }
102
+ return JSON.stringify({
103
+ refList: [
104
+ {
105
+ source: ref.source || ref.amf || "",
106
+ href: ref.href,
107
+ isSelected: true,
108
+ docPhase: ref.docPhase ?? null
109
+ }
110
+ ]
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Title of the currently selected spec. Forwarded to `<doc-redoc-reference>`
116
+ * so it can label the spec inside the Redoc UI.
117
+ */
118
+ get redocSpecTitle(): string {
119
+ const ref = this.getAmfConfigWithId(this._currentReferenceId);
120
+ return ref?.title ?? "";
73
121
  }
74
122
 
75
123
  @api
@@ -296,6 +344,16 @@ export default class AmfReference extends LightningElement {
296
344
  : false;
297
345
  }
298
346
 
347
+ /**
348
+ * @param referenceId
349
+ * @returns whether the reference should be rendered with Redoc rather than
350
+ * the AMF-based topic renderer.
351
+ */
352
+ private isRedocReference(referenceId: string): boolean {
353
+ const selectedReference = this.getAmfConfigWithId(referenceId);
354
+ return selectedReference?.renderWith === RENDER_WITH.redoc;
355
+ }
356
+
299
357
  /*
300
358
  * Refactor below method when sidebar allows sending extraData along with the name for each item.
301
359
  * See if we can refactor the below method using regex.
@@ -442,7 +500,11 @@ export default class AmfReference extends LightningElement {
442
500
  for (const [index, amfConfig] of this._amfConfigList.entries()) {
443
501
  let navItemChildren = [] as ParsedMarkdownTopic[];
444
502
  let isChildrenLoading = false;
445
- if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
503
+ if (amfConfig.renderWith === RENDER_WITH.redoc) {
504
+ // Redoc-rendered specs have no AMF model and no sub-tree; they
505
+ // appear as leaf items in the sidebar and open the Redoc UI on
506
+ // selection.
507
+ } else if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
446
508
  if (amfConfig.isSelected) {
447
509
  const amfPromise = this.fetchAmf(amfConfig).then(
448
510
  (amfJson) => {
@@ -862,6 +924,12 @@ export default class AmfReference extends LightningElement {
862
924
  const specBasedReference = this.isSpecBasedReference(
863
925
  this._currentReferenceId
864
926
  );
927
+ if (this.isRedocReference(this._currentReferenceId)) {
928
+ // Redoc reads its own state from referenceConfig + window.location;
929
+ // no metadata to sync from URL on our side.
930
+ restoreScroll();
931
+ return;
932
+ }
865
933
  if (specBasedReference) {
866
934
  const currentMeta: RouteMeta | undefined =
867
935
  this.getReferenceMetaInfo(window.location.href);
@@ -896,6 +964,9 @@ export default class AmfReference extends LightningElement {
896
964
  * @param event
897
965
  */
898
966
  protected onApiNavigationChanged(): void {
967
+ if (this.isRedocReference(this._currentReferenceId)) {
968
+ return;
969
+ }
899
970
  const specBasedReference = this.isSpecBasedReference(
900
971
  this._currentReferenceId
901
972
  );
@@ -1165,6 +1236,12 @@ export default class AmfReference extends LightningElement {
1165
1236
  }
1166
1237
 
1167
1238
  const specBasedReference = this.isSpecBasedReference(referenceId);
1239
+ const redocReference = this.isRedocReference(referenceId);
1240
+ if (redocReference) {
1241
+ // Redoc-rendered references have no AMF model; the redoc component
1242
+ // handles its own URL/spec resolution from referenceConfig.
1243
+ return;
1244
+ }
1168
1245
  if (specBasedReference) {
1169
1246
  // Wait till the AMF is loaded.
1170
1247
  this.amfFetchPromiseMap[referenceId].then(() => {
@@ -61,6 +61,10 @@ export const REFERENCE_TYPES = {
61
61
  oa3: "rest-oa3"
62
62
  };
63
63
 
64
+ export const RENDER_WITH = {
65
+ redoc: "redoc"
66
+ };
67
+
64
68
  const oldReferenceIdNewReferenceIdMap: Record<string, string> = {
65
69
  "commerce-api-assignments": "assignments",
66
70
  "commerce-api-campaigns": "campaigns",
@@ -78,6 +78,19 @@ export interface AmfConfig {
78
78
 
79
79
  // required for markdown based references
80
80
  topic?: ParsedMarkdownTopic;
81
+
82
+ /**
83
+ * Optional renderer override sent by the backend.
84
+ * When "redoc", spec-based references are rendered with Redoc instead of
85
+ * the AMF-based topic view. Other values fall back to the default pipeline.
86
+ */
87
+ renderWith?: string;
88
+
89
+ /**
90
+ * Spec URL consumed by alternate renderers (e.g. Redoc). For redoc-rendered
91
+ * references this is the OpenAPI document URL.
92
+ */
93
+ source?: string;
81
94
  }
82
95
 
83
96
  export interface ParsedTopicModel {
@@ -5,3 +5,27 @@
5
5
  var(--dx-g-spacing-xl)
6
6
  );
7
7
  }
8
+
9
+ .redoc-project-header {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: var(--dx-g-spacing-2xs);
13
+ padding: var(--dx-g-spacing-s) var(--dx-g-spacing-m);
14
+ }
15
+
16
+ .redoc-project-back {
17
+ display: inline-flex;
18
+ align-items: center;
19
+ gap: var(--dx-g-spacing-xs);
20
+ color: var(--dx-g-blue-vibrant-50);
21
+ text-decoration: none;
22
+ width: fit-content;
23
+ }
24
+
25
+ .redoc-project-back:hover .redoc-project-title {
26
+ text-decoration: underline;
27
+ }
28
+
29
+ .redoc-spec-title {
30
+ margin: 0;
31
+ }
@@ -8,6 +8,22 @@
8
8
  ></dx-error>
9
9
  </template>
10
10
  <template lwc:else>
11
+ <div lwc:if={showRedocHeader} class="redoc-project-header">
12
+ <a
13
+ lwc:if={projectTitle}
14
+ class="redoc-project-back"
15
+ href="#"
16
+ onclick={onBackClick}
17
+ >
18
+ <dx-icon sprite="utility" symbol="back" size="small"></dx-icon>
19
+ <span class="redoc-project-title dx-text-body-4">
20
+ {projectTitle}
21
+ </span>
22
+ </a>
23
+ <h2 lwc:if={specTitle} class="redoc-spec-title dx-text-display-6">
24
+ {specTitle}
25
+ </h2>
26
+ </div>
11
27
  <slot></slot>
12
28
  </template>
13
29
  </template>
@@ -71,6 +71,28 @@ export default class RedocReference extends LightningElement {
71
71
  /** Optional origin URL for the footer MFE (e.g. wp-json endpoint). Passed through to dx-footer. */
72
72
  @api origin: string | null = null;
73
73
 
74
+ /**
75
+ * Project title (same value passed to `<doc-header>` as `subtitle`). Used
76
+ * inside the Redoc-rendered UI to label the parent project.
77
+ */
78
+ @api projectTitle: string | null = null;
79
+
80
+ /** Title of the currently selected spec, shown beneath the project title. */
81
+ @api specTitle: string | null = null;
82
+
83
+ get showRedocHeader(): boolean {
84
+ return !!(this.projectTitle || this.specTitle);
85
+ }
86
+
87
+ /**
88
+ * Navigates back to the previous history entry when the user clicks the
89
+ * project-title back link rendered above the Redoc UI.
90
+ */
91
+ private onBackClick(event: Event): void {
92
+ event.preventDefault();
93
+ window.history.back();
94
+ }
95
+
74
96
  /** When origin is provided, pass it to the footer; otherwise use dx-footer's default. */
75
97
  get effectiveFooterOrigin(): string {
76
98
  return (
@@ -108,7 +130,13 @@ export default class RedocReference extends LightningElement {
108
130
  }
109
131
 
110
132
  private getRedocContainer(): HTMLElement | null {
111
- return document.querySelector(".redoc-container");
133
+ // Prefer the slotted container in the consumer's light DOM so this
134
+ // component composes inside shadow trees; fall back to a global
135
+ // `.redoc-container` for legacy page-level integrations.
136
+ return (
137
+ this.querySelector<HTMLElement>(".redoc-container") ||
138
+ document.querySelector<HTMLElement>(".redoc-container")
139
+ );
112
140
  }
113
141
 
114
142
  private getSelectedReference(): ReferenceItem | null {
package/.npmrc DELETED
@@ -1 +0,0 @@
1
- //registry.npmjs.org/:_authToken=${SFDOCS_NPM_AUTH_TOKEN}