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

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-alpha6",
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";
@@ -38,7 +37,7 @@ type NavigationItem = {
38
37
  isExpanded: boolean;
39
38
  children: ParsedMarkdownTopic[];
40
39
  isChildrenLoading: boolean;
41
- renderWith?: string;
40
+ showForwardArrow?: boolean;
42
41
  };
43
42
 
44
43
  export default class AmfReference extends LightningElement {
@@ -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,29 @@ export default class AmfReference extends LightningElement {
569
499
  this.isExpandChildrenEnabled(amfConfig.id),
570
500
  children: navItemChildren,
571
501
  isChildrenLoading,
572
- renderWith: amfConfig.renderWith
502
+ showForwardArrow: 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 whether the sidebar tile should render a forward arrow for
511
+ * this reference. Honors `redoc` set on the config, and also infers it
512
+ * for non-markdown references that have no AMF URL (i.e. those rendered
513
+ * by Redoc).
514
+ */
515
+ private resolveNavRenderWith(amfConfig: AmfConfig): boolean {
516
+ if (amfConfig.renderWith) {
517
+ return amfConfig.renderWith === "redoc";
518
+ }
519
+ return (
520
+ amfConfig.referenceType !== REFERENCE_TYPES.markdown &&
521
+ !amfConfig.amf
522
+ );
523
+ }
524
+
579
525
  /**
580
526
  * Returns a boolean indicating whether the children should be expanded or not.
581
527
  */
@@ -958,12 +904,6 @@ export default class AmfReference extends LightningElement {
958
904
  const specBasedReference = this.isSpecBasedReference(
959
905
  this._currentReferenceId
960
906
  );
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
907
  if (specBasedReference) {
968
908
  const currentMeta: RouteMeta | undefined =
969
909
  this.getReferenceMetaInfo(window.location.href);
@@ -998,9 +938,6 @@ export default class AmfReference extends LightningElement {
998
938
  * @param event
999
939
  */
1000
940
  protected onApiNavigationChanged(): void {
1001
- if (this.isRedocReference(this._currentReferenceId)) {
1002
- return;
1003
- }
1004
941
  const specBasedReference = this.isSpecBasedReference(
1005
942
  this._currentReferenceId
1006
943
  );
@@ -1270,12 +1207,6 @@ export default class AmfReference extends LightningElement {
1270
1207
  }
1271
1208
 
1272
1209
  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
1210
  if (specBasedReference) {
1280
1211
  // Wait till the AMF is loaded.
1281
1212
  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
@@ -86,16 +93,8 @@ export default class RedocReference extends LightningElement {
86
93
  */
87
94
  @api projectTitle: string | null = "All Reference";
88
95
 
89
- private _specTitle: string | null = null;
90
-
91
- /** Title of the currently selected spec, shown beneath the project title. */
92
- @api
93
96
  get specTitle(): string | null {
94
- return this._specTitle || this.getSelectedReference()?.title || null;
95
- }
96
-
97
- set specTitle(value: string | null) {
98
- this._specTitle = value || null;
97
+ return this.getSelectedReference()?.title ?? null;
99
98
  }
100
99
 
101
100
  /**
@@ -112,9 +111,46 @@ export default class RedocReference extends LightningElement {
112
111
  */
113
112
  private onBackClick = (event: Event): void => {
114
113
  event.preventDefault();
115
- window.history.back();
114
+ if (this.cameFromSameOriginPage()) {
115
+ window.history.back();
116
+ return;
117
+ }
118
+ const fallbackHref = this.getReferencesRootHref();
119
+ if (fallbackHref) {
120
+ window.location.href = fallbackHref;
121
+ }
116
122
  };
117
123
 
124
+ /**
125
+ * Returns true only when the page was reached via in-tab navigation from
126
+ * a same-origin page, so `history.back()` is safe to call. Checks both
127
+ * `initialHistoryLength` and `document.referrer` since neither signal is
128
+ * reliable on its own.
129
+ */
130
+ private cameFromSameOriginPage(): boolean {
131
+ if (this.initialHistoryLength <= 1 || !document.referrer) {
132
+ return false;
133
+ }
134
+ try {
135
+ return new URL(document.referrer).origin === window.location.origin;
136
+ } catch {
137
+ return false;
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Derives the project's `.../references` root from the current URL by
143
+ * trimming any trailing reference id (and deeper segments). Returns null
144
+ * when the URL doesn't contain a `/references` segment.
145
+ */
146
+ private getReferencesRootHref(): string | null {
147
+ const { pathname } = window.location;
148
+ const idx = pathname.lastIndexOf(REFERENCES_SEGMENT);
149
+ return idx === -1
150
+ ? null
151
+ : pathname.slice(0, idx + REFERENCES_SEGMENT.length);
152
+ }
153
+
118
154
  /** When origin is provided, pass it to the footer; otherwise use dx-footer's default. */
119
155
  get effectiveFooterOrigin(): string {
120
156
  return (
@@ -123,6 +159,10 @@ export default class RedocReference extends LightningElement {
123
159
  }
124
160
 
125
161
  connectedCallback(): void {
162
+ // Snapshot history length before Redoc pushes its own hash entries,
163
+ // so it reflects real in-tab navigation rather than Redoc's churn.
164
+ this.initialHistoryLength = window.history.length;
165
+
126
166
  window.addEventListener("scroll", this.handleScrollAndResize);
127
167
  window.addEventListener("resize", this.handleScrollAndResize);
128
168
  }