@alignable/bifrost 0.0.10 → 0.0.12

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.
Files changed (112) hide show
  1. package/dist/index.d.ts +1 -22
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/lib/PageShell.d.ts.map +1 -1
  4. package/dist/lib/getElementAttributes.d.ts +2 -0
  5. package/dist/lib/getElementAttributes.d.ts.map +1 -0
  6. package/dist/lib/getElementAttributes.js +7 -0
  7. package/dist/lib/turbolinks/browser_adapter.d.ts.map +1 -1
  8. package/dist/lib/turbolinks/browser_adapter.js +1 -4
  9. package/dist/lib/turbolinks/controller.d.ts +18 -44
  10. package/dist/lib/turbolinks/controller.d.ts.map +1 -1
  11. package/dist/lib/turbolinks/controller.js +42 -113
  12. package/dist/lib/turbolinks/head_details.d.ts +1 -0
  13. package/dist/lib/turbolinks/head_details.d.ts.map +1 -1
  14. package/dist/lib/turbolinks/head_details.js +5 -0
  15. package/dist/lib/turbolinks/index.d.ts +3 -3
  16. package/dist/lib/turbolinks/index.d.ts.map +1 -1
  17. package/dist/lib/turbolinks/index.js +18 -18
  18. package/dist/lib/turbolinks/lruCache.d.ts.map +1 -0
  19. package/dist/lib/turbolinks/mergeHead.d.ts +2 -0
  20. package/dist/lib/turbolinks/mergeHead.d.ts.map +1 -0
  21. package/dist/lib/{mergeHead.js → turbolinks/mergeHead.js} +27 -33
  22. package/dist/lib/turbolinks/util.d.ts +4 -0
  23. package/dist/lib/turbolinks/util.d.ts.map +1 -1
  24. package/dist/lib/turbolinks/util.js +40 -0
  25. package/dist/lib/turbolinks/visit.d.ts +5 -23
  26. package/dist/lib/turbolinks/visit.d.ts.map +1 -1
  27. package/dist/lib/turbolinks/visit.js +54 -118
  28. package/dist/proxy/pages/onRenderClient.d.ts.map +1 -1
  29. package/dist/proxy/pages/onRenderClient.js +40 -29
  30. package/dist/proxy/pages/onRenderHtml.d.ts.map +1 -1
  31. package/dist/proxy/pages/onRenderHtml.js +19 -5
  32. package/dist/proxy/pages/restorationVisit/+config.d.ts +2 -0
  33. package/dist/proxy/pages/restorationVisit/+config.d.ts.map +1 -1
  34. package/dist/proxy/pages/restorationVisit/+config.js +3 -0
  35. package/dist/proxy/pages/restorationVisit/onRenderClient.d.ts +3 -0
  36. package/dist/proxy/pages/restorationVisit/onRenderClient.d.ts.map +1 -0
  37. package/dist/proxy/pages/restorationVisit/onRenderClient.js +41 -0
  38. package/dist/renderer/onBeforeRoute.d.ts +1 -6
  39. package/dist/renderer/onBeforeRoute.d.ts.map +1 -1
  40. package/dist/renderer/onBeforeRoute.js +19 -11
  41. package/dist/renderer/onRenderClient.d.ts.map +1 -1
  42. package/dist/renderer/onRenderClient.js +29 -23
  43. package/dist/renderer/onRenderHtml.d.ts.map +1 -1
  44. package/dist/renderer/onRenderHtml.js +12 -16
  45. package/dist/renderer/utils/buildHead.d.ts +4 -0
  46. package/dist/renderer/utils/buildHead.d.ts.map +1 -0
  47. package/dist/renderer/utils/buildHead.js +10 -0
  48. package/dist/types/internal.d.ts +28 -17
  49. package/dist/types/internal.d.ts.map +1 -1
  50. package/package.json +13 -5
  51. package/dist/lib/dispatchTurbolinks.d.ts +0 -28
  52. package/dist/lib/dispatchTurbolinks.d.ts.map +0 -1
  53. package/dist/lib/dispatchTurbolinks.js +0 -5
  54. package/dist/lib/domUtils.d.ts +0 -3
  55. package/dist/lib/domUtils.d.ts.map +0 -1
  56. package/dist/lib/domUtils.js +0 -34
  57. package/dist/lib/getGlobalObject.d.ts +0 -5
  58. package/dist/lib/getGlobalObject.d.ts.map +0 -1
  59. package/dist/lib/getGlobalObject.js +0 -7
  60. package/dist/lib/linkInterceptor.d.ts +0 -2
  61. package/dist/lib/linkInterceptor.d.ts.map +0 -1
  62. package/dist/lib/linkInterceptor.js +0 -74
  63. package/dist/lib/lruCache.d.ts.map +0 -1
  64. package/dist/lib/mergeHead.d.ts +0 -2
  65. package/dist/lib/mergeHead.d.ts.map +0 -1
  66. package/dist/lib/navigateAnywhere.d.ts +0 -3
  67. package/dist/lib/navigateAnywhere.d.ts.map +0 -1
  68. package/dist/lib/navigateAnywhere.js +0 -15
  69. package/dist/lib/snapshots.d.ts +0 -9
  70. package/dist/lib/snapshots.d.ts.map +0 -1
  71. package/dist/lib/snapshots.js +0 -50
  72. package/dist/lib/turbolinks/history.d.ts +0 -22
  73. package/dist/lib/turbolinks/history.d.ts.map +0 -1
  74. package/dist/lib/turbolinks/history.js +0 -60
  75. package/dist/lib/turbolinks/namespace.d.ts +0 -12
  76. package/dist/lib/turbolinks/namespace.d.ts.map +0 -1
  77. package/dist/lib/turbolinks/namespace.js +0 -20
  78. package/dist/lib/turbolinks/passthrough_renderer.d.ts +0 -32
  79. package/dist/lib/turbolinks/passthrough_renderer.d.ts.map +0 -1
  80. package/dist/lib/turbolinks/passthrough_renderer.js +0 -128
  81. package/dist/lib/turbolinks/renderer.d.ts +0 -14
  82. package/dist/lib/turbolinks/renderer.d.ts.map +0 -1
  83. package/dist/lib/turbolinks/renderer.js +0 -28
  84. package/dist/lib/turbolinks/scroll_manager.d.ts +0 -16
  85. package/dist/lib/turbolinks/scroll_manager.d.ts.map +0 -1
  86. package/dist/lib/turbolinks/scroll_manager.js +0 -32
  87. package/dist/lib/turbolinks/snapshot.d.ts +0 -25
  88. package/dist/lib/turbolinks/snapshot.d.ts.map +0 -1
  89. package/dist/lib/turbolinks/snapshot.js +0 -77
  90. package/dist/lib/turbolinks/snapshot_cache.d.ts +0 -18
  91. package/dist/lib/turbolinks/snapshot_cache.d.ts.map +0 -1
  92. package/dist/lib/turbolinks/snapshot_cache.js +0 -42
  93. package/dist/lib/turbolinks/snapshot_renderer copy.d.ts +0 -45
  94. package/dist/lib/turbolinks/snapshot_renderer copy.d.ts.map +0 -1
  95. package/dist/lib/turbolinks/snapshot_renderer copy.js +0 -179
  96. package/dist/lib/turbolinks/snapshot_renderer.d.ts +0 -43
  97. package/dist/lib/turbolinks/snapshot_renderer.d.ts.map +0 -1
  98. package/dist/lib/turbolinks/snapshot_renderer.js +0 -139
  99. package/dist/lib/turbolinks/view.d.ts +0 -21
  100. package/dist/lib/turbolinks/view.d.ts.map +0 -1
  101. package/dist/lib/turbolinks/view.js +0 -42
  102. package/dist/lib/turbolinks.d.ts +0 -5
  103. package/dist/lib/turbolinks.d.ts.map +0 -1
  104. package/dist/lib/turbolinks.js +0 -14
  105. package/dist/proxy/pages/onPageTransitionStart.d.ts +0 -3
  106. package/dist/proxy/pages/onPageTransitionStart.d.ts.map +0 -1
  107. package/dist/proxy/pages/onPageTransitionStart.js +0 -9
  108. package/dist/renderer/utils/formatMetaObject.d.ts +0 -4
  109. package/dist/renderer/utils/formatMetaObject.d.ts.map +0 -1
  110. package/dist/renderer/utils/formatMetaObject.js +0 -3
  111. /package/dist/lib/{lruCache.d.ts → turbolinks/lruCache.d.ts} +0 -0
  112. /package/dist/lib/{lruCache.js → turbolinks/lruCache.js} +0 -0
@@ -1,14 +1,23 @@
1
- import { dispatchTurbolinks } from "./dispatchTurbolinks.js";
2
- import { activateNewBodyScriptElements, createScriptElement } from "./domUtils.js";
1
+ import { createScriptElement } from "./util";
3
2
  const allHeadScriptsEverRun = {};
4
3
  let firstLoad = true;
5
- // takes in innerHTML of head
6
- export function mergeHead(head) {
7
- const parsed = document.createRange().createContextualFragment(head); // Create a 'tiny' document and parse the html string
8
- const newHead = categorizeHead(parsed);
4
+ let lastTrackedScriptSignature;
5
+ export async function mergeHead(head, trackScripts, reload) {
6
+ const newHead = categorizeHead(head);
9
7
  const oldHead = categorizeHead(document.head);
10
- if (!trackedScriptsIdentical(oldHead.scripts, newHead.scripts)) {
11
- window.location.reload();
8
+ if (head
9
+ .querySelector('meta[name="turbolinks-visit-control"]')
10
+ ?.getAttribute("content") === "reload") {
11
+ reload();
12
+ }
13
+ if (trackScripts) {
14
+ lastTrackedScriptSignature =
15
+ lastTrackedScriptSignature ||
16
+ trackedElementSignature([...oldHead.scripts, ...oldHead.stylesheets]);
17
+ if (lastTrackedScriptSignature !==
18
+ trackedElementSignature([...newHead.scripts, ...newHead.stylesheets])) {
19
+ reload();
20
+ }
12
21
  }
13
22
  if (firstLoad) {
14
23
  // TODO: messy code
@@ -22,17 +31,15 @@ export function mergeHead(head) {
22
31
  copyNewHeadStylesheetElements(newHead.stylesheets, oldHead.stylesheets);
23
32
  removeCurrentHeadProvisionalElements(oldHead.provisional);
24
33
  copyNewHeadProvisionalElements(newHead.provisional);
25
- copyNewHeadScriptElements(newHead.scripts);
34
+ return new Promise((resolve) => {
35
+ copyNewHeadScriptElements(newHead.scripts, resolve);
36
+ });
26
37
  }
27
- function trackedScriptsIdentical(prev, next) {
28
- return (prev
38
+ function trackedElementSignature(scripts) {
39
+ return scripts
29
40
  .filter(elementIsTracked)
30
41
  .map((s) => s.outerHTML)
31
- .join() ===
32
- next
33
- .filter(elementIsTracked)
34
- .map((s) => s.outerHTML)
35
- .join());
42
+ .join();
36
43
  }
37
44
  function copyNewHeadStylesheetElements(next, prev) {
38
45
  const existing = prev.map((s) => s.outerHTML);
@@ -42,17 +49,10 @@ function copyNewHeadStylesheetElements(next, prev) {
42
49
  }
43
50
  }
44
51
  }
45
- function copyNewHeadScriptElements(next) {
52
+ function copyNewHeadScriptElements(next, onScriptsLoaded) {
46
53
  let blockingLoaded = [];
47
54
  function dispatch() {
48
- const scripts = document.body
49
- .querySelector("#proxied-body")
50
- .querySelectorAll("script");
51
- // TODO: maybe this goes in onTransitionEnd? Need to test.
52
- activateNewBodyScriptElements(Array.from(scripts));
53
- focusFirstAutofocusableElement();
54
- dispatchTurbolinks("turbolinks:render", {});
55
- dispatchTurbolinks("turbolinks:load", { url: window.location.href });
55
+ onScriptsLoaded();
56
56
  }
57
57
  for (const element of next) {
58
58
  const runBefore = element.outerHTML in allHeadScriptsEverRun;
@@ -75,8 +75,8 @@ function copyNewHeadScriptElements(next) {
75
75
  }
76
76
  }
77
77
  if (blockingLoaded.length === 0) {
78
- //TODO: raf waits for react to run... not 100% sure of the reliability
79
- requestAnimationFrame(() => requestAnimationFrame(dispatch));
78
+ // raf waits for react to finish
79
+ requestAnimationFrame(dispatch);
80
80
  }
81
81
  }
82
82
  function removeCurrentHeadProvisionalElements(prev) {
@@ -89,12 +89,6 @@ function copyNewHeadProvisionalElements(next) {
89
89
  document.head.appendChild(element);
90
90
  }
91
91
  }
92
- function focusFirstAutofocusableElement() {
93
- const element = document.body.querySelector("[autofocus]");
94
- if (element && "focus" in element && typeof element.focus === "function") {
95
- element.focus();
96
- }
97
- }
98
92
  function elementIsTracked(element) {
99
93
  return element.getAttribute("data-turbolinks-track") == "reload";
100
94
  }
@@ -11,4 +11,8 @@ export declare function dispatch(eventName: string, { target, cancelable, data }
11
11
  };
12
12
  export declare function unindent(strings: TemplateStringsArray, ...values: any[]): string;
13
13
  export declare function uuid(): string;
14
+ export declare function createScriptElement(element: Element, cb?: () => void): Element;
15
+ export declare function copyElementAttributes(destinationElement: Element, sourceElement: Element): void;
16
+ export declare function activateNewBodyScriptElements(newScriptElements: HTMLScriptElement[]): void;
17
+ export declare function focusFirstAutofocusableElement(): void;
14
18
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAElD;AAED,eAAO,MAAM,OAAO,YAwBQ,OAAO,YAAY,MAAM,mBAGjD,CAAC;AAEL,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,QAExC;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAE,OAAO,CAAC,eAAe,CAAM;UAEK,GAAG;EAkBpE;AASD,wBAAgB,QAAQ,CACtB,OAAO,EAAE,oBAAoB,EAC7B,GAAG,MAAM,EAAE,GAAG,EAAE,GACf,MAAM,CAKR;AAaD,wBAAgB,IAAI,WAcnB"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAElD;AAED,eAAO,MAAM,OAAO,YAwBQ,OAAO,YAAY,MAAM,mBAGjD,CAAC;AAEL,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,QAExC;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAE,OAAO,CAAC,eAAe,CAAM;UAEK,GAAG;EAkBpE;AASD,wBAAgB,QAAQ,CACtB,OAAO,EAAE,oBAAoB,EAC7B,GAAG,MAAM,EAAE,GAAG,EAAE,GACf,MAAM,CAKR;AAaD,wBAAgB,IAAI,WAcnB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,MAAM,IAAI,WAepE;AAED,wBAAgB,qBAAqB,CACnC,kBAAkB,EAAE,OAAO,EAC3B,aAAa,EAAE,OAAO,QAKvB;AAQD,wBAAgB,6BAA6B,CAC3C,iBAAiB,EAAE,iBAAiB,EAAE,QAMvC;AAED,wBAAgB,8BAA8B,SAK7C"}
@@ -83,3 +83,43 @@ export function uuid() {
83
83
  })
84
84
  .join("");
85
85
  }
86
+ export function createScriptElement(element, cb) {
87
+ if (element.getAttribute("data-turbolinks-eval") == "false") {
88
+ return element;
89
+ }
90
+ else {
91
+ const createdScriptElement = document.createElement("script");
92
+ createdScriptElement.textContent = element.textContent;
93
+ // async false makes scripts run in-order. it wont block js execution (thankfully)
94
+ // https://github.com/turbolinks/turbolinks/issues/282#issuecomment-355731712
95
+ createdScriptElement.async = false;
96
+ copyElementAttributes(createdScriptElement, element);
97
+ if (cb) {
98
+ createdScriptElement.addEventListener("load", cb);
99
+ }
100
+ return createdScriptElement;
101
+ }
102
+ }
103
+ export function copyElementAttributes(destinationElement, sourceElement) {
104
+ for (const { name, value } of array(sourceElement.attributes)) {
105
+ destinationElement.setAttribute(name, value);
106
+ }
107
+ }
108
+ function replaceElementWithElement(fromElement, toElement) {
109
+ const parentElement = fromElement.parentElement;
110
+ if (parentElement) {
111
+ return parentElement.replaceChild(toElement, fromElement);
112
+ }
113
+ }
114
+ export function activateNewBodyScriptElements(newScriptElements) {
115
+ for (const inertScriptElement of newScriptElements) {
116
+ const activatedScriptElement = createScriptElement(inertScriptElement);
117
+ replaceElementWithElement(inertScriptElement, activatedScriptElement);
118
+ }
119
+ }
120
+ export function focusFirstAutofocusableElement() {
121
+ const element = document.body.querySelector("[autofocus]");
122
+ if (element && "focus" in element && typeof element.focus === "function") {
123
+ element.focus();
124
+ }
125
+ }
@@ -1,9 +1,6 @@
1
1
  import { Adapter } from "./adapter";
2
- import { Controller, RestorationData } from "./controller";
3
- import { HttpRequest } from "./http_request";
2
+ import { Controller } from "./controller.js";
4
3
  import { Location } from "./location";
5
- import { RenderCallback } from "./renderer";
6
- import { Snapshot } from "./snapshot";
7
4
  import { Action } from "./types";
8
5
  export declare enum TimingMetric {
9
6
  visitStart = "visitStart",
@@ -28,19 +25,15 @@ export declare class Visit {
28
25
  readonly identifier: string;
29
26
  readonly restorationIdentifier: string;
30
27
  readonly timingMetrics: TimingMetrics;
31
- followedRedirect: boolean;
32
28
  frame?: number;
33
- historyChanged: boolean;
34
29
  location: Location;
35
30
  progress: number;
36
31
  referrer?: Location;
37
32
  redirectedToLocation?: Location;
38
- request?: HttpRequest;
39
- response?: string;
40
- restorationData?: RestorationData;
41
- scrolled: boolean;
42
33
  snapshotCached: boolean;
43
34
  state: VisitState;
35
+ requestInFlight: boolean;
36
+ renderFn?: () => Promise<void>;
44
37
  constructor(controller: Controller, location: Location, action: Action, restorationIdentifier?: string);
45
38
  start(): void;
46
39
  cancel(): void;
@@ -48,26 +41,15 @@ export declare class Visit {
48
41
  fail(): void;
49
42
  changeHistory(): void;
50
43
  issueRequest(): void;
51
- getCachedSnapshot(): Snapshot | undefined;
44
+ getCachedSnapshot(): import("./controller.js").Snapshot | undefined;
52
45
  hasCachedSnapshot(): boolean;
53
46
  loadCachedSnapshot(): void;
54
47
  loadResponse(): void;
55
- followRedirect(): void;
56
- requestStarted(): void;
57
- requestProgressed(progress: number): void;
58
- requestCompletedWithResponse(response: string, redirectedToLocation?: Location): void;
59
- requestFailedWithStatusCode(statusCode: number, response?: string): void;
60
- requestFinished(): void;
61
- performScroll: () => void;
62
- scrollToRestoredPosition(): true | undefined;
63
- scrollToAnchor(): true | undefined;
64
- scrollToTop(): void;
65
48
  recordTimingMetric(metric: TimingMetric): void;
66
49
  getTimingMetrics(): TimingMetrics;
67
- getHistoryMethodForAction(action: Action): (locatable: import("./location").Locatable, restorationIdentifier: string) => void;
68
50
  shouldIssueRequest(): boolean;
69
51
  cacheSnapshot(): void;
70
- render(callback: RenderCallback): void;
52
+ render(callback: () => Promise<void>): void;
71
53
  cancelRender(): void;
72
54
  }
73
55
  //# sourceMappingURL=visit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"visit.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/visit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,oBAAY,YAAY;IACtB,UAAU,eAAe;IACzB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,QAAQ,aAAa;CACtB;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;KAAG,MAAM,IAAI,YAAY,GAAG,GAAG;CAAE,CAAC,CAAC;AAEvE,oBAAY,UAAU;IACpB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB;AAED,qBAAa,KAAK;IAChB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,SAAU;IAC7B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAM;IAE3C,gBAAgB,UAAS;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,UAAS;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,SAAK;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oBAAoB,CAAC,EAAE,QAAQ,CAAC;IAChC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,UAAS;IACjB,cAAc,UAAS;IACvB,KAAK,aAA0B;gBAG7B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,qBAAqB,GAAE,MAAe;IASxC,KAAK;IAQL,MAAM;IAUN,QAAQ;IASR,IAAI;IAOJ,aAAa;IAWb,YAAY;IAQZ,iBAAiB;IAcjB,iBAAiB;IAIjB,kBAAkB;IAelB,YAAY;IAqBZ,cAAc;IAad,cAAc;IAKd,iBAAiB,CAAC,QAAQ,EAAE,MAAM;IAOlC,4BAA4B,CAC1B,QAAQ,EAAE,MAAM,EAChB,oBAAoB,CAAC,EAAE,QAAQ;IAOjC,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAKjE,eAAe;IAOf,aAAa,aASX;IAEF,wBAAwB;IAUxB,cAAc;IAOd,WAAW;IAMX,kBAAkB,CAAC,MAAM,EAAE,YAAY;IAIvC,gBAAgB,IAAI,aAAa;IAMjC,yBAAyB,CAAC,MAAM,EAAE,MAAM;IAUxC,kBAAkB;IAIlB,aAAa;IAOb,MAAM,CAAC,QAAQ,EAAE,cAAc;IAQ/B,YAAY;CAMb"}
1
+ {"version":3,"file":"visit.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/visit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,oBAAY,YAAY;IACtB,UAAU,eAAe;IACzB,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IACzB,QAAQ,aAAa;CACtB;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC;KAAG,MAAM,IAAI,YAAY,GAAG,GAAG;CAAE,CAAC,CAAC;AAEvE,oBAAY,UAAU;IACpB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,SAAS,cAAc;CACxB;AAED,qBAAa,KAAK;IAChB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,SAAU;IAC7B,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAM;IAE3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,SAAK;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,oBAAoB,CAAC,EAAE,QAAQ,CAAC;IAChC,cAAc,UAAS;IACvB,KAAK,aAA0B;IAE/B,eAAe,UAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;gBAG7B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,EACd,qBAAqB,GAAE,MAAe;IASxC,KAAK;IAQL,MAAM;IAQN,QAAQ;IASR,IAAI;IAOJ,aAAa;IAKb,YAAY;IAgBZ,iBAAiB;IAWjB,iBAAiB;IAIjB,kBAAkB;IAKlB,YAAY;IA+CZ,kBAAkB,CAAC,MAAM,EAAE,YAAY;IAIvC,gBAAgB,IAAI,aAAa;IAMjC,kBAAkB;IAIlB,aAAa;IAOb,MAAM,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAQpC,YAAY;CAMb"}
@@ -1,5 +1,4 @@
1
- import { HttpRequest } from "./http_request";
2
- import { Snapshot } from "./snapshot";
1
+ import { navigate } from "vite-plugin-ssr/client/router";
3
2
  import { uuid } from "./util";
4
3
  export var TimingMetric;
5
4
  (function (TimingMetric) {
@@ -20,24 +19,10 @@ export class Visit {
20
19
  constructor(controller, location, action, restorationIdentifier = uuid()) {
21
20
  this.identifier = uuid();
22
21
  this.timingMetrics = {};
23
- this.followedRedirect = false;
24
- this.historyChanged = false;
25
22
  this.progress = 0;
26
- this.scrolled = false;
27
23
  this.snapshotCached = false;
28
24
  this.state = VisitState.initialized;
29
- // Scrolling
30
- this.performScroll = () => {
31
- if (!this.scrolled) {
32
- if (this.action == "restore") {
33
- this.scrollToRestoredPosition() || this.scrollToTop();
34
- }
35
- else {
36
- this.scrollToAnchor() || this.scrollToTop();
37
- }
38
- this.scrolled = true;
39
- }
40
- };
25
+ this.requestInFlight = false;
41
26
  this.controller = controller;
42
27
  this.location = location;
43
28
  this.action = action;
@@ -53,9 +38,7 @@ export class Visit {
53
38
  }
54
39
  cancel() {
55
40
  if (this.state == VisitState.started) {
56
- if (this.request) {
57
- this.request.cancel();
58
- }
41
+ this.requestInFlight = false;
59
42
  this.cancelRender();
60
43
  this.state = VisitState.canceled;
61
44
  }
@@ -75,27 +58,25 @@ export class Visit {
75
58
  }
76
59
  }
77
60
  changeHistory() {
78
- if (!this.historyChanged) {
79
- const actionForHistory = this.location.isEqualTo(this.referrer)
80
- ? "replace"
81
- : this.action;
82
- const method = this.getHistoryMethodForAction(actionForHistory);
83
- method.call(this.controller, this.location, this.restorationIdentifier);
84
- this.historyChanged = true;
85
- }
61
+ // no-op since issueRequest calls navigate which handles all of this already
62
+ return;
86
63
  }
87
64
  issueRequest() {
88
- if (this.shouldIssueRequest() && !this.request) {
89
- this.progress = 0;
90
- this.request = new HttpRequest(this, this.location, this.referrer);
91
- this.request.send();
65
+ if (!this.requestInFlight) {
66
+ if (this.shouldIssueRequest()) {
67
+ const url = new URL(this.location.toString(), this.location.getOrigin());
68
+ navigate(url.pathname + url.hash + url.search, {
69
+ overwriteLastHistoryEntry: this.action === "replace",
70
+ }).catch(console.error);
71
+ this.progress = 0;
72
+ this.requestInFlight = true;
73
+ }
92
74
  }
93
75
  }
94
76
  getCachedSnapshot() {
95
77
  const snapshot = this.controller.getCachedSnapshotForLocation(this.location);
96
- if (snapshot &&
97
- (!this.location.anchor || snapshot.hasAnchor(this.location.anchor))) {
98
- if (this.action == "restore" || snapshot.isPreviewable()) {
78
+ if (snapshot) {
79
+ if (this.action == "restore") {
99
80
  return snapshot;
100
81
  }
101
82
  }
@@ -104,86 +85,51 @@ export class Visit {
104
85
  return this.getCachedSnapshot() != null;
105
86
  }
106
87
  loadCachedSnapshot() {
107
- const snapshot = this.getCachedSnapshot();
108
- if (snapshot) {
109
- const isPreview = this.shouldIssueRequest();
110
- this.render(() => {
111
- this.cacheSnapshot();
112
- this.controller.render({ snapshot, isPreview }, this.performScroll);
113
- this.adapter.visitRendered(this);
114
- if (!isPreview) {
115
- this.complete();
116
- }
117
- });
118
- }
88
+ // no-op since issueRequest calls navigate which handles all of this already
89
+ return;
119
90
  }
120
91
  loadResponse() {
121
- const { request, response } = this;
122
- if (request && response) {
123
- this.render(() => {
124
- this.cacheSnapshot();
125
- if (request.failed) {
126
- this.controller.render({ error: this.response }, this.performScroll);
127
- this.adapter.visitRendered(this);
128
- this.fail();
129
- }
130
- else {
131
- this.controller.render({ snapshot: Snapshot.fromHTMLString(response) }, this.performScroll);
132
- this.adapter.visitRendered(this);
133
- this.complete();
134
- }
135
- });
136
- }
137
- }
138
- followRedirect() {
139
- if (this.redirectedToLocation && !this.followedRedirect) {
140
- this.location = this.redirectedToLocation;
141
- this.controller.replaceHistoryWithLocationAndRestorationIdentifier(this.redirectedToLocation, this.restorationIdentifier);
142
- this.followedRedirect = true;
143
- }
92
+ this.render(async () => {
93
+ if (!this.renderFn)
94
+ throw new Error("Render details not set before rendering");
95
+ this.cacheSnapshot();
96
+ await this.renderFn();
97
+ this.complete();
98
+ });
144
99
  }
145
100
  // HTTP request delegate
101
+ /*
146
102
  requestStarted() {
147
- this.recordTimingMetric(TimingMetric.requestStart);
148
- this.adapter.visitRequestStarted(this);
149
- }
150
- requestProgressed(progress) {
151
- this.progress = progress;
152
- if (this.adapter.visitRequestProgressed) {
153
- this.adapter.visitRequestProgressed(this);
154
- }
155
- }
156
- requestCompletedWithResponse(response, redirectedToLocation) {
157
- this.response = response;
158
- this.redirectedToLocation = redirectedToLocation;
159
- this.adapter.visitRequestCompleted(this);
160
- }
161
- requestFailedWithStatusCode(statusCode, response) {
162
- this.response = response;
163
- this.adapter.visitRequestFailedWithStatusCode(this, statusCode);
164
- }
103
+ this.recordTimingMetric(TimingMetric.requestStart);
104
+ this.adapter.visitRequestStarted(this);
105
+ }
106
+
107
+ requestProgressed(progress: number) {
108
+ this.progress = progress;
109
+ if (this.adapter.visitRequestProgressed) {
110
+ this.adapter.visitRequestProgressed(this);
111
+ }
112
+ }
113
+
114
+ requestCompletedWithResponse(
115
+ response: string,
116
+ redirectedToLocation?: Location
117
+ ) {
118
+ this.response = response;
119
+ this.redirectedToLocation = redirectedToLocation;
120
+ this.adapter.visitRequestCompleted(this);
121
+ }
122
+
123
+ requestFailedWithStatusCode(statusCode: number, response?: string) {
124
+ this.response = response;
125
+ this.adapter.visitRequestFailedWithStatusCode(this, statusCode);
126
+ }
127
+
165
128
  requestFinished() {
166
- this.recordTimingMetric(TimingMetric.requestEnd);
167
- this.adapter.visitRequestFinished(this);
168
- }
169
- scrollToRestoredPosition() {
170
- const position = this.restorationData
171
- ? this.restorationData.scrollPosition
172
- : undefined;
173
- if (position) {
174
- this.controller.scrollToPosition(position);
175
- return true;
176
- }
177
- }
178
- scrollToAnchor() {
179
- if (this.location.anchor != null) {
180
- this.controller.scrollToAnchor(this.location.anchor);
181
- return true;
182
- }
183
- }
184
- scrollToTop() {
185
- this.controller.scrollToPosition({ x: 0, y: 0 });
129
+ this.recordTimingMetric(TimingMetric.requestEnd);
130
+ this.adapter.visitRequestFinished(this);
186
131
  }
132
+ */
187
133
  // Instrumentation
188
134
  recordTimingMetric(metric) {
189
135
  this.timingMetrics[metric] = new Date().getTime();
@@ -192,16 +138,6 @@ export class Visit {
192
138
  return { ...this.timingMetrics };
193
139
  }
194
140
  // Private
195
- getHistoryMethodForAction(action) {
196
- switch (action) {
197
- case "replace":
198
- return this.controller
199
- .replaceHistoryWithLocationAndRestorationIdentifier;
200
- case "advance":
201
- case "restore":
202
- return this.controller.pushHistoryWithLocationAndRestorationIdentifier;
203
- }
204
- }
205
141
  shouldIssueRequest() {
206
142
  return this.action == "restore" ? !this.hasCachedSnapshot() : true;
207
143
  }
@@ -1 +1 @@
1
- {"version":3,"file":"onRenderClient.d.ts","sourceRoot":"","sources":["../../../proxy/pages/onRenderClient.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAajE,wBAA8B,cAAc,CAC1C,WAAW,EAAE,sBAAsB,iBAgDpC"}
1
+ {"version":3,"file":"onRenderClient.d.ts","sourceRoot":"","sources":["../../../proxy/pages/onRenderClient.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AASjE,wBAA8B,cAAc,CAC1C,WAAW,EAAE,sBAAsB,iBA4DpC"}
@@ -1,45 +1,56 @@
1
1
  import React from "react";
2
2
  import { renderReact } from "../../lib/renderReact.js";
3
3
  import { PageShell } from "../../lib/PageShell.js";
4
- import { turbolinksClickListener } from "../../lib/linkInterceptor.js";
5
- import { dispatchTurbolinks } from "../../lib/dispatchTurbolinks.js";
6
- import { mergeHead } from "../../lib/mergeHead.js";
7
- import { cacheProxiedBody, writeRestorationIdentifier, } from "../../lib/snapshots.js";
8
- import { navigateAnywhere } from "../../lib/navigateAnywhere.js";
9
- import { setupTurbolinks } from "../../lib/turbolinks.js";
10
- setupTurbolinks();
4
+ import { Turbolinks } from "../../lib/turbolinks/index.js";
5
+ import { copyElementAttributes, } from "../../lib/turbolinks/util.js";
6
+ import { getElementAttributes } from "../../lib/getElementAttributes.js";
7
+ Turbolinks.start();
11
8
  export default async function onRenderClient(pageContext) {
12
- if (navigateAnywhere(pageContext.redirectTo))
9
+ if (pageContext.redirectTo) {
10
+ Turbolinks.visit(pageContext.redirectTo);
13
11
  return;
14
- let body;
12
+ }
15
13
  const { layoutProps, layout } = pageContext;
16
- const Layout = pageContext.config.layoutMap[layout];
14
+ const { layoutMap } = pageContext.config;
15
+ if (!layoutMap) {
16
+ throw new Error("layoutMap needs to be defined in config");
17
+ }
18
+ const Layout = layoutMap[layout];
19
+ function render(body) {
20
+ renderReact(React.createElement(PageShell, { key: pageContext.urlOriginal, pageContext: pageContext },
21
+ React.createElement(Layout, { ...layoutProps },
22
+ React.createElement("div", { id: "proxied-body", dangerouslySetInnerHTML: { __html: body } }))), pageContext.isHydration);
23
+ }
24
+ let bodyEl;
17
25
  if (pageContext.isHydration) {
18
26
  // During hydration of initial ssr, body is in dom, not page props (to avoid double-send)
19
- body = document.getElementById("proxied-body").innerHTML;
27
+ bodyEl = document.getElementById("proxied-body");
28
+ render(bodyEl.innerHTML);
20
29
  }
21
30
  else {
22
31
  const { proxySendClient: proxy } = pageContext;
23
32
  if (!proxy) {
24
- console.error("proxy/+onRenderClient did not receive proxySendClient nor is there a cached snapshot");
33
+ console.error("proxy/+onRenderClient did not receive proxySendClient");
25
34
  return;
26
35
  }
27
- cacheProxiedBody();
28
- dispatchTurbolinks("turbolinks:before-render", { newBody: proxy.body });
29
- body = proxy.body;
30
- document.body
31
- .getAttributeNames()
32
- .forEach((n) => document.body.removeAttribute(n));
33
- for (const [name, value] of Object.entries(proxy.bodyAttrs)) {
34
- document.body.setAttribute(name, value);
35
- }
36
- mergeHead(proxy.head);
36
+ const parsed = document.createElement("html");
37
+ parsed.innerHTML = proxy;
38
+ bodyEl = parsed.querySelector("body");
39
+ const headEl = parsed.querySelector("head");
40
+ Turbolinks._vpsOnRenderClient(headEl, true, () => {
41
+ // merge body attributes
42
+ document.body
43
+ .getAttributeNames()
44
+ .forEach((n) => document.body.removeAttribute(n));
45
+ copyElementAttributes(document.body, bodyEl);
46
+ // render body with react
47
+ render(bodyEl.innerHTML);
48
+ });
37
49
  }
38
- writeRestorationIdentifier(pageContext);
39
- // addEventListener de-dupes so we are safe to just blindly call this every time
40
- // non-proxy pages remove the listener
41
- document.addEventListener("click", turbolinksClickListener);
42
- renderReact(React.createElement(PageShell, { key: pageContext.urlOriginal, pageContext: pageContext },
43
- React.createElement(Layout, { ...layoutProps },
44
- React.createElement("div", { id: "proxied-body", dangerouslySetInnerHTML: { __html: body } }))), pageContext.isHydration);
50
+ // cache page context will save it and return it to us during restoration visits
51
+ Turbolinks._vpsCachePageContext({
52
+ layoutProps,
53
+ layout,
54
+ bodyAttrs: getElementAttributes(bodyEl),
55
+ });
45
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"onRenderHtml.d.ts","sourceRoot":"","sources":["../../../proxy/pages/onRenderHtml.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,wBAA8B,YAAY,CACxC,WAAW,EAAE,sBAAsB;;;;;;GAsDpC"}
1
+ {"version":3,"file":"onRenderHtml.d.ts","sourceRoot":"","sources":["../../../proxy/pages/onRenderHtml.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAKjE,wBAA8B,YAAY,CACxC,WAAW,EAAE,sBAAsB;;;;;;GAkEpC"}
@@ -2,25 +2,39 @@ import React from "react";
2
2
  import ReactDOMServer from "react-dom/server";
3
3
  import { dangerouslySkipEscape, escapeInject } from "vite-plugin-ssr/server";
4
4
  import { PageShell } from "../../lib/PageShell.js";
5
+ import jsdom from "jsdom";
6
+ import { getElementAttributes } from "../../lib/getElementAttributes.js";
5
7
  export default async function onRenderHtml(pageContext) {
6
8
  if (pageContext.proxy) {
7
- const { proxy: { head, body, bodyAttrs }, layoutProps, layout, } = pageContext;
8
- const Layout = pageContext.config.layoutMap[layout];
9
+ const { proxy, layoutProps, layout } = pageContext;
10
+ const dom = new jsdom.JSDOM(proxy);
11
+ const doc = dom.window.document;
12
+ const bodyEl = doc.querySelector("body");
13
+ const head = doc.querySelector("head");
14
+ if (!bodyEl || !head) {
15
+ throw new Error("Proxy failed");
16
+ }
17
+ const { layoutMap } = pageContext.config;
18
+ if (!layoutMap) {
19
+ throw new Error("layoutMap needs to be defined in config");
20
+ }
21
+ const Layout = layoutMap[layout];
9
22
  if (!Layout)
10
23
  throw new Error(`${layout} layout not found`);
11
24
  const pageHtml = ReactDOMServer.renderToString(React.createElement(PageShell, { pageContext: pageContext },
12
25
  React.createElement(Layout, { ...layoutProps },
13
- React.createElement("div", { id: "proxied-body", dangerouslySetInnerHTML: { __html: body } }))));
26
+ React.createElement("div", { id: "proxied-body", dangerouslySetInnerHTML: { __html: bodyEl.innerHTML } }))));
14
27
  const documentHtml = escapeInject `
15
28
  <!DOCTYPE html>
16
29
  <html>
17
30
  <head>
18
- ${dangerouslySkipEscape(head)}
31
+ ${dangerouslySkipEscape(head.innerHTML)}
19
32
  ${
20
33
  // We need to fire turbolinks:load exactly on DCL, so it must be a blocking head script to catch DCL event.
21
34
  // Vite loads scripts with type="module" so the rest of our code will show up too late.
22
35
  // TODO: figure out how to bundle this better. at least read from a .js file
23
36
  dangerouslySkipEscape(`<script>
37
+ window.Turbolinks = {controller:{restorationIdentifier: ''}};
24
38
  addEventListener("DOMContentLoaded", () => {
25
39
  const event = new Event("turbolinks:load", { bubbles: true, cancelable: true });
26
40
  event.data = {url: window.location.href};
@@ -28,7 +42,7 @@ export default async function onRenderHtml(pageContext) {
28
42
  })
29
43
  </script>`)}
30
44
  </head>
31
- <body ${dangerouslySkipEscape(Object.entries(bodyAttrs)
45
+ <body ${dangerouslySkipEscape(Object.entries(getElementAttributes(bodyEl))
32
46
  .map(([name, value]) => `${name}="${value}"`)
33
47
  .join(" "))}>
34
48
  <div id="page-view">${dangerouslySkipEscape(pageHtml)}</div>
@@ -1,6 +1,8 @@
1
1
  declare const _default: {
2
2
  route: string;
3
3
  Page: string;
4
+ onRenderClient: "import:@alignable/bifrost/proxy/pages/restorationVisit/onRenderClient";
5
+ passToClient: string[];
4
6
  meta: {
5
7
  onBeforeRender: {
6
8
  env: "server-and-client";
@@ -1 +1 @@
1
- {"version":3,"file":"+config.d.ts","sourceRoot":"","sources":["../../../../proxy/pages/restorationVisit/+config.ts"],"names":[],"mappings":";;;;;;;;;AAEA,wBAWgC"}
1
+ {"version":3,"file":"+config.d.ts","sourceRoot":"","sources":["../../../../proxy/pages/restorationVisit/+config.ts"],"names":[],"mappings":";;;;;;;;;;;AAEA,wBAcgC"}
@@ -1,6 +1,9 @@
1
1
  export default {
2
2
  route: "import:@alignable/bifrost/proxy/pages/restorationVisit/route",
3
3
  Page: "import:@alignable/bifrost/proxy/pages/Page",
4
+ onRenderClient: "import:@alignable/bifrost/proxy/pages/restorationVisit/onRenderClient",
5
+ // See onBeforeRoute for how head and body are inserted from Turbolinks snapshot
6
+ passToClient: ["headEl", "bodyEl", "layout", "layoutProps"],
4
7
  meta: {
5
8
  onBeforeRender: {
6
9
  // We tell vite-plugin-ssr to load and execute onBeforeRender()
@@ -0,0 +1,3 @@
1
+ import { PageContextProxyRestorationVisit } from "../../../types/internal.js";
2
+ export default function onRenderClient(pageContext: PageContextProxyRestorationVisit): Promise<void>;
3
+ //# sourceMappingURL=onRenderClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onRenderClient.d.ts","sourceRoot":"","sources":["../../../../proxy/pages/restorationVisit/onRenderClient.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAO9E,wBAA8B,cAAc,CAC1C,WAAW,EAAE,gCAAgC,iBA2C9C"}