@salesforcedevs/docs-components 1.28.5-redoc-alpha4 → 1.28.5-redoc-alpha5

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-redoc-alpha4",
3
+ "version": "1.28.5-redoc-alpha5",
4
4
  "description": "Docs Lightning web components for DSC",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
@@ -42,18 +42,7 @@
42
42
  latest-version={latestVersion}
43
43
  ></doc-version-picker>
44
44
  </div>
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}>
45
+ <template lwc:if={showSpecBasedReference}>
57
46
  <div class="container">
58
47
  <div class="api-documentation">
59
48
  <doc-amf-topic
@@ -24,7 +24,6 @@ import {
24
24
  NAVIGATION_ITEMS,
25
25
  URL_CONFIG,
26
26
  REFERENCE_TYPES,
27
- RENDER_WITH,
28
27
  oldReferenceIdNewReferenceIdMap
29
28
  } from "./constants";
30
29
  import { restoreScroll } from "dx/scrollManager";
@@ -46,12 +45,6 @@ export default class AmfReference extends LightningElement {
46
45
  /** Optional Twitter "via" handle (e.g. SalesforceDevs) for social share; passed to doc-content-layout. */
47
46
  @api twitterVia: string | null = null;
48
47
  @api sidebarHeader!: string;
49
- /**
50
- * Project title shown by `<doc-header>` (as its `subtitle`). Forwarded to
51
- * `<doc-redoc-reference>` so it can surface the same project title inside
52
- * the Redoc-rendered UI.
53
- */
54
- @api projectTitle: string | null = null;
55
48
  @api tocTitle?: string;
56
49
  @api tocOptions?: string;
57
50
  @api tocAriaLevel?: string;
@@ -77,48 +70,7 @@ export default class AmfReference extends LightningElement {
77
70
  * Gives if the currently selected reference is spec based or not
78
71
  */
79
72
  get showSpecBasedReference(): boolean {
80
- return (
81
- this.isSpecBasedReference(this._currentReferenceId) &&
82
- !this.showRedocReference
83
- );
84
- }
85
-
86
- /**
87
- * Whether the currently selected reference is rendered with Redoc.
88
- * Driven by the backend-supplied `renderWith` attribute on the AmfConfig.
89
- */
90
- get showRedocReference(): boolean {
91
- return this.isRedocReference(this._currentReferenceId);
92
- }
93
-
94
- /**
95
- * Serialized config consumed by `<doc-redoc-reference>`. Built from the
96
- * currently selected redoc reference so Redoc has a single spec to render.
97
- */
98
- get redocReferenceConfig(): string {
99
- const ref = this.getAmfConfigWithId(this._currentReferenceId);
100
- if (!ref) {
101
- return JSON.stringify({ refList: [] });
102
- }
103
- return JSON.stringify({
104
- refList: [
105
- {
106
- source: ref.source || ref.amf || "",
107
- href: ref.href,
108
- isSelected: true,
109
- docPhase: ref.docPhase ?? null
110
- }
111
- ]
112
- });
113
- }
114
-
115
- /**
116
- * Title of the currently selected spec. Forwarded to `<doc-redoc-reference>`
117
- * so it can label the spec inside the Redoc UI.
118
- */
119
- get redocSpecTitle(): string {
120
- const ref = this.getAmfConfigWithId(this._currentReferenceId);
121
- return ref?.title ?? "";
73
+ return this.isSpecBasedReference(this._currentReferenceId);
122
74
  }
123
75
 
124
76
  @api
@@ -148,19 +100,6 @@ export default class AmfReference extends LightningElement {
148
100
 
149
101
  this._amfConfigList = this._referenceSetConfig.refList || [];
150
102
 
151
- // If the framework didn't tag the reference, infer redoc rendering
152
- // from the config shape: spec-based references with no AMF URL are
153
- // shipped as raw spec sources for Redoc to render directly.
154
- this._amfConfigList.forEach((amfConfig) => {
155
- if (
156
- !amfConfig.renderWith &&
157
- amfConfig.referenceType !== REFERENCE_TYPES.markdown &&
158
- !amfConfig.amf
159
- ) {
160
- amfConfig.renderWith = RENDER_WITH.redoc;
161
- }
162
- });
163
-
164
103
  this._amfConfigList.forEach((amfConfig) => {
165
104
  this._amfConfigMap.set(amfConfig.id, amfConfig);
166
105
  });
@@ -377,16 +316,6 @@ export default class AmfReference extends LightningElement {
377
316
  : false;
378
317
  }
379
318
 
380
- /**
381
- * @param referenceId
382
- * @returns whether the reference should be rendered with Redoc rather than
383
- * the AMF-based topic renderer.
384
- */
385
- private isRedocReference(referenceId: string): boolean {
386
- const selectedReference = this.getAmfConfigWithId(referenceId);
387
- return selectedReference?.renderWith === RENDER_WITH.redoc;
388
- }
389
-
390
319
  /*
391
320
  * Refactor below method when sidebar allows sending extraData along with the name for each item.
392
321
  * See if we can refactor the below method using regex.
@@ -533,8 +462,8 @@ export default class AmfReference extends LightningElement {
533
462
  for (const [index, amfConfig] of this._amfConfigList.entries()) {
534
463
  let navItemChildren = [] as ParsedMarkdownTopic[];
535
464
  let isChildrenLoading = false;
536
- if (amfConfig.renderWith !== RENDER_WITH.redoc) {
537
- if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
465
+ if (amfConfig.referenceType !== REFERENCE_TYPES.markdown) {
466
+ if (amfConfig.amf) {
538
467
  if (amfConfig.isSelected) {
539
468
  const amfPromise = this.fetchAmf(amfConfig).then(
540
469
  (amfJson) => {
@@ -548,17 +477,18 @@ export default class AmfReference extends LightningElement {
548
477
  this.amfFetchPromiseMap[amfConfig.id] = amfPromise;
549
478
  }
550
479
  isChildrenLoading = true;
551
- } else {
552
- const isExpandChildrenEnabled =
553
- this.isExpandChildrenEnabled(amfConfig.id);
554
- // check whether we should expand all the child nodes, this is required for Coveo to crawl.
555
- if (isExpandChildrenEnabled) {
556
- this.expandChildrenForMarkdownReferences(
557
- amfConfig.topic!.children
558
- );
559
- }
560
- navItemChildren = amfConfig.topic!.children;
561
480
  }
481
+ } else {
482
+ const isExpandChildrenEnabled = this.isExpandChildrenEnabled(
483
+ amfConfig.id
484
+ );
485
+ // check whether we should expand all the child nodes, this is required for Coveo to crawl.
486
+ if (isExpandChildrenEnabled) {
487
+ this.expandChildrenForMarkdownReferences(
488
+ amfConfig.topic!.children
489
+ );
490
+ }
491
+ navItemChildren = amfConfig.topic!.children;
562
492
  }
563
493
  // store nav items for each spec in order
564
494
  navAmfOrder[index] = {
@@ -569,13 +499,31 @@ export default class AmfReference extends LightningElement {
569
499
  this.isExpandChildrenEnabled(amfConfig.id),
570
500
  children: navItemChildren,
571
501
  isChildrenLoading,
572
- renderWith: amfConfig.renderWith
502
+ renderWith: this.resolveNavRenderWith(amfConfig)
573
503
  };
574
504
  this.parentReferenceUrls.push(amfConfig.href);
575
505
  }
576
506
  this.navigation = navAmfOrder;
577
507
  }
578
508
 
509
+ /**
510
+ * Determines the `renderWith` value forwarded to the sidebar. Honors any
511
+ * value set on the config; otherwise infers `"redoc"` for non-markdown
512
+ * references that have no AMF URL (i.e. those rendered by Redoc).
513
+ */
514
+ private resolveNavRenderWith(amfConfig: AmfConfig): string | undefined {
515
+ if (amfConfig.renderWith) {
516
+ return amfConfig.renderWith;
517
+ }
518
+ if (
519
+ amfConfig.referenceType !== REFERENCE_TYPES.markdown &&
520
+ !amfConfig.amf
521
+ ) {
522
+ return "redoc";
523
+ }
524
+ return undefined;
525
+ }
526
+
579
527
  /**
580
528
  * Returns a boolean indicating whether the children should be expanded or not.
581
529
  */
@@ -958,12 +906,6 @@ export default class AmfReference extends LightningElement {
958
906
  const specBasedReference = this.isSpecBasedReference(
959
907
  this._currentReferenceId
960
908
  );
961
- if (this.isRedocReference(this._currentReferenceId)) {
962
- // Redoc reads its own state from referenceConfig + window.location;
963
- // no metadata to sync from URL on our side.
964
- restoreScroll();
965
- return;
966
- }
967
909
  if (specBasedReference) {
968
910
  const currentMeta: RouteMeta | undefined =
969
911
  this.getReferenceMetaInfo(window.location.href);
@@ -998,9 +940,6 @@ export default class AmfReference extends LightningElement {
998
940
  * @param event
999
941
  */
1000
942
  protected onApiNavigationChanged(): void {
1001
- if (this.isRedocReference(this._currentReferenceId)) {
1002
- return;
1003
- }
1004
943
  const specBasedReference = this.isSpecBasedReference(
1005
944
  this._currentReferenceId
1006
945
  );
@@ -1270,12 +1209,6 @@ export default class AmfReference extends LightningElement {
1270
1209
  }
1271
1210
 
1272
1211
  const specBasedReference = this.isSpecBasedReference(referenceId);
1273
- const redocReference = this.isRedocReference(referenceId);
1274
- if (redocReference) {
1275
- // Redoc-rendered references have no AMF model; the redoc component
1276
- // handles its own URL/spec resolution from referenceConfig.
1277
- return;
1278
- }
1279
1212
  if (specBasedReference) {
1280
1213
  // Wait till the AMF is loaded.
1281
1214
  this.amfFetchPromiseMap[referenceId].then(() => {
@@ -61,10 +61,6 @@ export const REFERENCE_TYPES = {
61
61
  oa3: "rest-oa3"
62
62
  };
63
63
 
64
- export const RENDER_WITH = {
65
- redoc: "redoc"
66
- };
67
-
68
64
  const oldReferenceIdNewReferenceIdMap: Record<string, string> = {
69
65
  "commerce-api-assignments": "assignments",
70
66
  "commerce-api-campaigns": "campaigns",
@@ -83,11 +83,6 @@ export interface AmfConfig {
83
83
  * Required for rendering the arrow on LNB
84
84
  */
85
85
  renderWith?: string;
86
-
87
- /**
88
- * Spec URL consumed by alternate renderers (e.g. Redoc, Mulesoft).
89
- */
90
- source?: string;
91
86
  }
92
87
 
93
88
  export interface ParsedTopicModel {
@@ -37,6 +37,7 @@ type ReferenceConfig = {
37
37
  const SCROLL_THROTTLE_DELAY = 50;
38
38
  const ELEMENT_TIMEOUT = 10000;
39
39
  const ELEMENT_CHECK_INTERVAL = 100;
40
+ const REFERENCES_SEGMENT = "/references";
40
41
 
41
42
  export default class RedocReference extends LightningElement {
42
43
  private _referenceConfig: ReferenceConfig = { refList: [] };
@@ -47,6 +48,12 @@ export default class RedocReference extends LightningElement {
47
48
  private docPhaseWrapperElement: Element | null = null;
48
49
  private lastSidebarTop = 0;
49
50
 
51
+ /**
52
+ * History length captured at mount (pre-Redoc), used by `onBackClick` to
53
+ * distinguish in-tab navigation (> 1) from a fresh entry (=== 1).
54
+ */
55
+ private initialHistoryLength = 0;
56
+
50
57
  showError = false;
51
58
 
52
59
  @api
@@ -112,9 +119,46 @@ export default class RedocReference extends LightningElement {
112
119
  */
113
120
  private onBackClick = (event: Event): void => {
114
121
  event.preventDefault();
115
- window.history.back();
122
+ if (this.cameFromSameOriginPage()) {
123
+ window.history.back();
124
+ return;
125
+ }
126
+ const fallbackHref = this.getReferencesRootHref();
127
+ if (fallbackHref) {
128
+ window.location.href = fallbackHref;
129
+ }
116
130
  };
117
131
 
132
+ /**
133
+ * Returns true only when the page was reached via in-tab navigation from
134
+ * a same-origin page, so `history.back()` is safe to call. Checks both
135
+ * `initialHistoryLength` and `document.referrer` since neither signal is
136
+ * reliable on its own.
137
+ */
138
+ private cameFromSameOriginPage(): boolean {
139
+ if (this.initialHistoryLength <= 1 || !document.referrer) {
140
+ return false;
141
+ }
142
+ try {
143
+ return new URL(document.referrer).origin === window.location.origin;
144
+ } catch {
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Derives the project's `.../references` root from the current URL by
151
+ * trimming any trailing reference id (and deeper segments). Returns null
152
+ * when the URL doesn't contain a `/references` segment.
153
+ */
154
+ private getReferencesRootHref(): string | null {
155
+ const { pathname } = window.location;
156
+ const idx = pathname.lastIndexOf(REFERENCES_SEGMENT);
157
+ return idx === -1
158
+ ? null
159
+ : pathname.slice(0, idx + REFERENCES_SEGMENT.length);
160
+ }
161
+
118
162
  /** When origin is provided, pass it to the footer; otherwise use dx-footer's default. */
119
163
  get effectiveFooterOrigin(): string {
120
164
  return (
@@ -123,6 +167,10 @@ export default class RedocReference extends LightningElement {
123
167
  }
124
168
 
125
169
  connectedCallback(): void {
170
+ // Snapshot history length before Redoc pushes its own hash entries,
171
+ // so it reflects real in-tab navigation rather than Redoc's churn.
172
+ this.initialHistoryLength = window.history.length;
173
+
126
174
  window.addEventListener("scroll", this.handleScrollAndResize);
127
175
  window.addEventListener("resize", this.handleScrollAndResize);
128
176
  }