@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.
- package/dist/index.d.ts +1 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/PageShell.d.ts.map +1 -1
- package/dist/lib/getElementAttributes.d.ts +2 -0
- package/dist/lib/getElementAttributes.d.ts.map +1 -0
- package/dist/lib/getElementAttributes.js +7 -0
- package/dist/lib/turbolinks/browser_adapter.d.ts.map +1 -1
- package/dist/lib/turbolinks/browser_adapter.js +1 -4
- package/dist/lib/turbolinks/controller.d.ts +18 -44
- package/dist/lib/turbolinks/controller.d.ts.map +1 -1
- package/dist/lib/turbolinks/controller.js +42 -113
- package/dist/lib/turbolinks/head_details.d.ts +1 -0
- package/dist/lib/turbolinks/head_details.d.ts.map +1 -1
- package/dist/lib/turbolinks/head_details.js +5 -0
- package/dist/lib/turbolinks/index.d.ts +3 -3
- package/dist/lib/turbolinks/index.d.ts.map +1 -1
- package/dist/lib/turbolinks/index.js +18 -18
- package/dist/lib/turbolinks/lruCache.d.ts.map +1 -0
- package/dist/lib/turbolinks/mergeHead.d.ts +2 -0
- package/dist/lib/turbolinks/mergeHead.d.ts.map +1 -0
- package/dist/lib/{mergeHead.js → turbolinks/mergeHead.js} +27 -33
- package/dist/lib/turbolinks/util.d.ts +4 -0
- package/dist/lib/turbolinks/util.d.ts.map +1 -1
- package/dist/lib/turbolinks/util.js +40 -0
- package/dist/lib/turbolinks/visit.d.ts +5 -23
- package/dist/lib/turbolinks/visit.d.ts.map +1 -1
- package/dist/lib/turbolinks/visit.js +54 -118
- package/dist/proxy/pages/onRenderClient.d.ts.map +1 -1
- package/dist/proxy/pages/onRenderClient.js +40 -29
- package/dist/proxy/pages/onRenderHtml.d.ts.map +1 -1
- package/dist/proxy/pages/onRenderHtml.js +19 -5
- package/dist/proxy/pages/restorationVisit/+config.d.ts +2 -0
- package/dist/proxy/pages/restorationVisit/+config.d.ts.map +1 -1
- package/dist/proxy/pages/restorationVisit/+config.js +3 -0
- package/dist/proxy/pages/restorationVisit/onRenderClient.d.ts +3 -0
- package/dist/proxy/pages/restorationVisit/onRenderClient.d.ts.map +1 -0
- package/dist/proxy/pages/restorationVisit/onRenderClient.js +41 -0
- package/dist/renderer/onBeforeRoute.d.ts +1 -6
- package/dist/renderer/onBeforeRoute.d.ts.map +1 -1
- package/dist/renderer/onBeforeRoute.js +19 -11
- package/dist/renderer/onRenderClient.d.ts.map +1 -1
- package/dist/renderer/onRenderClient.js +29 -23
- package/dist/renderer/onRenderHtml.d.ts.map +1 -1
- package/dist/renderer/onRenderHtml.js +12 -16
- package/dist/renderer/utils/buildHead.d.ts +4 -0
- package/dist/renderer/utils/buildHead.d.ts.map +1 -0
- package/dist/renderer/utils/buildHead.js +10 -0
- package/dist/types/internal.d.ts +28 -17
- package/dist/types/internal.d.ts.map +1 -1
- package/package.json +13 -5
- package/dist/lib/dispatchTurbolinks.d.ts +0 -28
- package/dist/lib/dispatchTurbolinks.d.ts.map +0 -1
- package/dist/lib/dispatchTurbolinks.js +0 -5
- package/dist/lib/domUtils.d.ts +0 -3
- package/dist/lib/domUtils.d.ts.map +0 -1
- package/dist/lib/domUtils.js +0 -34
- package/dist/lib/getGlobalObject.d.ts +0 -5
- package/dist/lib/getGlobalObject.d.ts.map +0 -1
- package/dist/lib/getGlobalObject.js +0 -7
- package/dist/lib/linkInterceptor.d.ts +0 -2
- package/dist/lib/linkInterceptor.d.ts.map +0 -1
- package/dist/lib/linkInterceptor.js +0 -74
- package/dist/lib/lruCache.d.ts.map +0 -1
- package/dist/lib/mergeHead.d.ts +0 -2
- package/dist/lib/mergeHead.d.ts.map +0 -1
- package/dist/lib/navigateAnywhere.d.ts +0 -3
- package/dist/lib/navigateAnywhere.d.ts.map +0 -1
- package/dist/lib/navigateAnywhere.js +0 -15
- package/dist/lib/snapshots.d.ts +0 -9
- package/dist/lib/snapshots.d.ts.map +0 -1
- package/dist/lib/snapshots.js +0 -50
- package/dist/lib/turbolinks/history.d.ts +0 -22
- package/dist/lib/turbolinks/history.d.ts.map +0 -1
- package/dist/lib/turbolinks/history.js +0 -60
- package/dist/lib/turbolinks/namespace.d.ts +0 -12
- package/dist/lib/turbolinks/namespace.d.ts.map +0 -1
- package/dist/lib/turbolinks/namespace.js +0 -20
- package/dist/lib/turbolinks/passthrough_renderer.d.ts +0 -32
- package/dist/lib/turbolinks/passthrough_renderer.d.ts.map +0 -1
- package/dist/lib/turbolinks/passthrough_renderer.js +0 -128
- package/dist/lib/turbolinks/renderer.d.ts +0 -14
- package/dist/lib/turbolinks/renderer.d.ts.map +0 -1
- package/dist/lib/turbolinks/renderer.js +0 -28
- package/dist/lib/turbolinks/scroll_manager.d.ts +0 -16
- package/dist/lib/turbolinks/scroll_manager.d.ts.map +0 -1
- package/dist/lib/turbolinks/scroll_manager.js +0 -32
- package/dist/lib/turbolinks/snapshot.d.ts +0 -25
- package/dist/lib/turbolinks/snapshot.d.ts.map +0 -1
- package/dist/lib/turbolinks/snapshot.js +0 -77
- package/dist/lib/turbolinks/snapshot_cache.d.ts +0 -18
- package/dist/lib/turbolinks/snapshot_cache.d.ts.map +0 -1
- package/dist/lib/turbolinks/snapshot_cache.js +0 -42
- package/dist/lib/turbolinks/snapshot_renderer copy.d.ts +0 -45
- package/dist/lib/turbolinks/snapshot_renderer copy.d.ts.map +0 -1
- package/dist/lib/turbolinks/snapshot_renderer copy.js +0 -179
- package/dist/lib/turbolinks/snapshot_renderer.d.ts +0 -43
- package/dist/lib/turbolinks/snapshot_renderer.d.ts.map +0 -1
- package/dist/lib/turbolinks/snapshot_renderer.js +0 -139
- package/dist/lib/turbolinks/view.d.ts +0 -21
- package/dist/lib/turbolinks/view.d.ts.map +0 -1
- package/dist/lib/turbolinks/view.js +0 -42
- package/dist/lib/turbolinks.d.ts +0 -5
- package/dist/lib/turbolinks.d.ts.map +0 -1
- package/dist/lib/turbolinks.js +0 -14
- package/dist/proxy/pages/onPageTransitionStart.d.ts +0 -3
- package/dist/proxy/pages/onPageTransitionStart.d.ts.map +0 -1
- package/dist/proxy/pages/onPageTransitionStart.js +0 -9
- package/dist/renderer/utils/formatMetaObject.d.ts +0 -4
- package/dist/renderer/utils/formatMetaObject.d.ts.map +0 -1
- package/dist/renderer/utils/formatMetaObject.js +0 -3
- /package/dist/lib/{lruCache.d.ts → turbolinks/lruCache.d.ts} +0 -0
- /package/dist/lib/{lruCache.js → turbolinks/lruCache.js} +0 -0
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { activateNewBodyScriptElements, createScriptElement } from "./domUtils.js";
|
|
1
|
+
import { createScriptElement } from "./util";
|
|
3
2
|
const allHeadScriptsEverRun = {};
|
|
4
3
|
let firstLoad = true;
|
|
5
|
-
|
|
6
|
-
export function mergeHead(head) {
|
|
7
|
-
const
|
|
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 (
|
|
11
|
-
|
|
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
|
-
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
copyNewHeadScriptElements(newHead.scripts, resolve);
|
|
36
|
+
});
|
|
26
37
|
}
|
|
27
|
-
function
|
|
28
|
-
return
|
|
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
|
-
|
|
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
|
-
//
|
|
79
|
-
requestAnimationFrame(
|
|
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
|
|
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:
|
|
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":"
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
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 (
|
|
89
|
-
this.
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
(
|
|
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
|
-
|
|
108
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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;
|
|
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 {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
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 (
|
|
9
|
+
if (pageContext.redirectTo) {
|
|
10
|
+
Turbolinks.visit(pageContext.redirectTo);
|
|
13
11
|
return;
|
|
14
|
-
|
|
12
|
+
}
|
|
15
13
|
const { layoutProps, layout } = pageContext;
|
|
16
|
-
const
|
|
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
|
-
|
|
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
|
|
33
|
+
console.error("proxy/+onRenderClient did not receive proxySendClient");
|
|
25
34
|
return;
|
|
26
35
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|
|
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
|
|
8
|
-
const
|
|
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:
|
|
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(
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"+config.d.ts","sourceRoot":"","sources":["../../../../proxy/pages/restorationVisit/+config.ts"],"names":[],"mappings":"
|
|
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 @@
|
|
|
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"}
|