@alignable/bifrost 0.0.8 → 0.0.10
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 +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/getGlobalObject.d.ts +5 -0
- package/dist/lib/getGlobalObject.d.ts.map +1 -0
- package/dist/lib/getGlobalObject.js +7 -0
- package/dist/lib/turbolinks/adapter.d.ts +17 -0
- package/dist/lib/turbolinks/adapter.d.ts.map +1 -0
- package/dist/lib/turbolinks/adapter.js +1 -0
- package/dist/lib/turbolinks/browser_adapter.d.ts +28 -0
- package/dist/lib/turbolinks/browser_adapter.d.ts.map +1 -0
- package/dist/lib/turbolinks/browser_adapter.js +71 -0
- package/dist/lib/turbolinks/controller.d.ts +101 -0
- package/dist/lib/turbolinks/controller.d.ts.map +1 -0
- package/dist/lib/turbolinks/controller.js +290 -0
- package/dist/lib/turbolinks/head_details.d.ts +23 -0
- package/dist/lib/turbolinks/head_details.d.ts.map +1 -0
- package/dist/lib/turbolinks/head_details.js +92 -0
- package/dist/lib/turbolinks/history.d.ts +22 -0
- package/dist/lib/turbolinks/history.d.ts.map +1 -0
- package/dist/lib/turbolinks/history.js +60 -0
- package/dist/lib/turbolinks/index.d.ts +14 -0
- package/dist/lib/turbolinks/index.d.ts.map +1 -0
- package/dist/lib/turbolinks/index.js +55 -0
- package/dist/lib/turbolinks/location.d.ts +23 -0
- package/dist/lib/turbolinks/location.d.ts.map +1 -0
- package/dist/lib/turbolinks/location.js +75 -0
- package/dist/lib/turbolinks/namespace.d.ts +12 -0
- package/dist/lib/turbolinks/namespace.d.ts.map +1 -0
- package/dist/lib/turbolinks/namespace.js +20 -0
- package/dist/lib/turbolinks/passthrough_renderer.d.ts +32 -0
- package/dist/lib/turbolinks/passthrough_renderer.d.ts.map +1 -0
- package/dist/lib/turbolinks/passthrough_renderer.js +128 -0
- package/dist/lib/turbolinks/progress_bar.d.ts +24 -0
- package/dist/lib/turbolinks/progress_bar.d.ts.map +1 -0
- package/dist/lib/turbolinks/progress_bar.js +99 -0
- package/dist/lib/turbolinks/renderer.d.ts +14 -0
- package/dist/lib/turbolinks/renderer.d.ts.map +1 -0
- package/dist/lib/turbolinks/renderer.js +28 -0
- package/dist/lib/turbolinks/scroll_manager.d.ts +16 -0
- package/dist/lib/turbolinks/scroll_manager.d.ts.map +1 -0
- package/dist/lib/turbolinks/scroll_manager.js +32 -0
- package/dist/lib/turbolinks/snapshot.d.ts +25 -0
- package/dist/lib/turbolinks/snapshot.d.ts.map +1 -0
- package/dist/lib/turbolinks/snapshot.js +77 -0
- package/dist/lib/turbolinks/snapshot_cache.d.ts +18 -0
- package/dist/lib/turbolinks/snapshot_cache.d.ts.map +1 -0
- package/dist/lib/turbolinks/snapshot_cache.js +42 -0
- package/dist/lib/turbolinks/snapshot_renderer copy.d.ts +45 -0
- package/dist/lib/turbolinks/snapshot_renderer copy.d.ts.map +1 -0
- package/dist/lib/turbolinks/snapshot_renderer copy.js +179 -0
- package/dist/lib/turbolinks/snapshot_renderer.d.ts +43 -0
- package/dist/lib/turbolinks/snapshot_renderer.d.ts.map +1 -0
- package/dist/lib/turbolinks/snapshot_renderer.js +139 -0
- package/dist/lib/turbolinks/types.d.ts +7 -0
- package/dist/lib/turbolinks/types.d.ts.map +1 -0
- package/dist/lib/turbolinks/types.js +3 -0
- package/dist/lib/turbolinks/util.d.ts +14 -0
- package/dist/lib/turbolinks/util.d.ts.map +1 -0
- package/dist/lib/turbolinks/util.js +85 -0
- package/dist/lib/turbolinks/view.d.ts +21 -0
- package/dist/lib/turbolinks/view.d.ts.map +1 -0
- package/dist/lib/turbolinks/view.js +42 -0
- package/dist/lib/turbolinks/visit.d.ts +73 -0
- package/dist/lib/turbolinks/visit.d.ts.map +1 -0
- package/dist/lib/turbolinks/visit.js +227 -0
- package/dist/proxy/pages/+config.d.ts +4 -4
- package/dist/proxy/pages/+config.js +4 -4
- package/dist/proxy/pages/onPageTransitionStart.d.ts +3 -0
- package/dist/proxy/pages/onPageTransitionStart.d.ts.map +1 -0
- package/dist/proxy/pages/onPageTransitionStart.js +9 -0
- package/dist/proxy/pages/restorationVisit/+config.d.ts +2 -2
- package/dist/proxy/pages/restorationVisit/+config.js +2 -2
- package/dist/renderer/+config.d.ts +9 -3
- package/dist/renderer/+config.d.ts.map +1 -1
- package/dist/renderer/+config.js +6 -4
- package/dist/renderer/onRenderClient.d.ts.map +1 -1
- package/dist/renderer/onRenderClient.js +7 -1
- package/dist/renderer/onRenderHtml.d.ts.map +1 -1
- package/dist/renderer/onRenderHtml.js +9 -1
- package/dist/renderer/usePageContext.d.ts +1 -0
- package/dist/renderer/usePageContext.d.ts.map +1 -1
- package/dist/renderer/usePageContext.js +9 -1
- package/dist/renderer/utils/formatMetaObject.d.ts +4 -0
- package/dist/renderer/utils/formatMetaObject.d.ts.map +1 -0
- package/dist/renderer/utils/formatMetaObject.js +3 -0
- package/dist/renderer/utils/getGlobalObject.d.ts +5 -0
- package/dist/renderer/utils/getGlobalObject.d.ts.map +1 -0
- package/dist/renderer/utils/getGlobalObject.js +8 -0
- package/package.json +3 -3
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Renderer } from "./renderer";
|
|
2
|
+
import { array } from "./util";
|
|
3
|
+
export class SnapshotRenderer extends Renderer {
|
|
4
|
+
static render(delegate, callback, currentSnapshot, newSnapshot, isPreview) {
|
|
5
|
+
return new this(delegate, currentSnapshot, newSnapshot, isPreview).render(callback);
|
|
6
|
+
}
|
|
7
|
+
constructor(delegate, currentSnapshot, newSnapshot, isPreview) {
|
|
8
|
+
super();
|
|
9
|
+
this.delegate = delegate;
|
|
10
|
+
this.currentSnapshot = currentSnapshot;
|
|
11
|
+
this.currentHeadDetails = currentSnapshot.headDetails;
|
|
12
|
+
this.newSnapshot = newSnapshot;
|
|
13
|
+
this.newHeadDetails = newSnapshot.headDetails;
|
|
14
|
+
this.newBody = newSnapshot.bodyElement;
|
|
15
|
+
this.isPreview = isPreview;
|
|
16
|
+
}
|
|
17
|
+
render(callback) {
|
|
18
|
+
if (this.shouldRender()) {
|
|
19
|
+
this.mergeHead();
|
|
20
|
+
this.renderView(() => {
|
|
21
|
+
this.replaceBody();
|
|
22
|
+
if (!this.isPreview) {
|
|
23
|
+
this.focusFirstAutofocusableElement();
|
|
24
|
+
}
|
|
25
|
+
callback();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.invalidateView();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
mergeHead() {
|
|
33
|
+
this.copyNewHeadStylesheetElements();
|
|
34
|
+
this.copyNewHeadScriptElements();
|
|
35
|
+
this.removeCurrentHeadProvisionalElements();
|
|
36
|
+
this.copyNewHeadProvisionalElements();
|
|
37
|
+
}
|
|
38
|
+
replaceBody() {
|
|
39
|
+
const placeholders = this.relocateCurrentBodyPermanentElements();
|
|
40
|
+
this.activateNewBodyScriptElements();
|
|
41
|
+
this.assignNewBody();
|
|
42
|
+
this.replacePlaceholderElementsWithClonedPermanentElements(placeholders);
|
|
43
|
+
}
|
|
44
|
+
shouldRender() {
|
|
45
|
+
return this.newSnapshot.isVisitable() && this.trackedElementsAreIdentical();
|
|
46
|
+
}
|
|
47
|
+
trackedElementsAreIdentical() {
|
|
48
|
+
return (this.currentHeadDetails.getTrackedElementSignature() ==
|
|
49
|
+
this.newHeadDetails.getTrackedElementSignature());
|
|
50
|
+
}
|
|
51
|
+
copyNewHeadStylesheetElements() {
|
|
52
|
+
for (const element of this.getNewHeadStylesheetElements()) {
|
|
53
|
+
document.head.appendChild(element);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
copyNewHeadScriptElements() {
|
|
57
|
+
for (const element of this.getNewHeadScriptElements()) {
|
|
58
|
+
document.head.appendChild(this.createScriptElement(element));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
removeCurrentHeadProvisionalElements() {
|
|
62
|
+
for (const element of this.getCurrentHeadProvisionalElements()) {
|
|
63
|
+
document.head.removeChild(element);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
copyNewHeadProvisionalElements() {
|
|
67
|
+
for (const element of this.getNewHeadProvisionalElements()) {
|
|
68
|
+
document.head.appendChild(element);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
relocateCurrentBodyPermanentElements() {
|
|
72
|
+
return this.getCurrentBodyPermanentElements().reduce((placeholders, permanentElement) => {
|
|
73
|
+
const newElement = this.newSnapshot.getPermanentElementById(permanentElement.id);
|
|
74
|
+
if (newElement) {
|
|
75
|
+
const placeholder = createPlaceholderForPermanentElement(permanentElement);
|
|
76
|
+
replaceElementWithElement(permanentElement, placeholder.element);
|
|
77
|
+
replaceElementWithElement(newElement, permanentElement);
|
|
78
|
+
return [...placeholders, placeholder];
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return placeholders;
|
|
82
|
+
}
|
|
83
|
+
}, []);
|
|
84
|
+
}
|
|
85
|
+
replacePlaceholderElementsWithClonedPermanentElements(placeholders) {
|
|
86
|
+
for (const { element, permanentElement } of placeholders) {
|
|
87
|
+
const clonedElement = permanentElement.cloneNode(true);
|
|
88
|
+
replaceElementWithElement(element, clonedElement);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
activateNewBodyScriptElements() {
|
|
92
|
+
for (const inertScriptElement of this.getNewBodyScriptElements()) {
|
|
93
|
+
const activatedScriptElement = this.createScriptElement(inertScriptElement);
|
|
94
|
+
replaceElementWithElement(inertScriptElement, activatedScriptElement);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
assignNewBody() {
|
|
98
|
+
replaceElementWithElement(document.querySelector("#alignablewebnextjsframe").firstElementChild, this.newBody);
|
|
99
|
+
}
|
|
100
|
+
focusFirstAutofocusableElement() {
|
|
101
|
+
const element = this.newSnapshot.findFirstAutofocusableElement();
|
|
102
|
+
if (elementIsFocusable(element)) {
|
|
103
|
+
element.focus();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
getNewHeadStylesheetElements() {
|
|
107
|
+
return this.newHeadDetails.getStylesheetElementsNotInDetails(this.currentHeadDetails);
|
|
108
|
+
}
|
|
109
|
+
getNewHeadScriptElements() {
|
|
110
|
+
return this.newHeadDetails.getScriptElementsNotInDetails(this.currentHeadDetails);
|
|
111
|
+
}
|
|
112
|
+
getCurrentHeadProvisionalElements() {
|
|
113
|
+
return this.currentHeadDetails.getProvisionalElements();
|
|
114
|
+
}
|
|
115
|
+
getNewHeadProvisionalElements() {
|
|
116
|
+
return this.newHeadDetails.getProvisionalElements();
|
|
117
|
+
}
|
|
118
|
+
getCurrentBodyPermanentElements() {
|
|
119
|
+
return this.currentSnapshot.getPermanentElementsPresentInSnapshot(this.newSnapshot);
|
|
120
|
+
}
|
|
121
|
+
getNewBodyScriptElements() {
|
|
122
|
+
return array(this.newBody.querySelectorAll("script"));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function createPlaceholderForPermanentElement(permanentElement) {
|
|
126
|
+
const element = document.createElement("meta");
|
|
127
|
+
element.setAttribute("name", "turbolinks-permanent-placeholder");
|
|
128
|
+
element.setAttribute("content", permanentElement.id);
|
|
129
|
+
return { element, permanentElement };
|
|
130
|
+
}
|
|
131
|
+
function replaceElementWithElement(fromElement, toElement) {
|
|
132
|
+
const parentElement = fromElement.parentElement;
|
|
133
|
+
if (parentElement) {
|
|
134
|
+
return parentElement.replaceChild(toElement, fromElement);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function elementIsFocusable(element) {
|
|
138
|
+
return element && typeof element.focus == "function";
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEvD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,IAAI,MAAM,CAEtD;AAED,MAAM,MAAM,QAAQ,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function array<T>(values: ArrayLike<T>): T[];
|
|
2
|
+
export declare const closest: (element: Element, selector: string) => Element | null;
|
|
3
|
+
export declare function defer(callback: () => any): void;
|
|
4
|
+
export type DispatchOptions = {
|
|
5
|
+
target: EventTarget;
|
|
6
|
+
cancelable: boolean;
|
|
7
|
+
data: any;
|
|
8
|
+
};
|
|
9
|
+
export declare function dispatch(eventName: string, { target, cancelable, data }?: Partial<DispatchOptions>): Event & {
|
|
10
|
+
data: any;
|
|
11
|
+
};
|
|
12
|
+
export declare function unindent(strings: TemplateStringsArray, ...values: any[]): string;
|
|
13
|
+
export declare function uuid(): string;
|
|
14
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export function array(values) {
|
|
2
|
+
return Array.prototype.slice.call(values);
|
|
3
|
+
}
|
|
4
|
+
export const closest = (() => {
|
|
5
|
+
const html = document.documentElement;
|
|
6
|
+
const match = html.matches ||
|
|
7
|
+
html.webkitMatchesSelector ||
|
|
8
|
+
html.msMatchesSelector ||
|
|
9
|
+
html.mozMatchesSelector;
|
|
10
|
+
const closest = html.closest ||
|
|
11
|
+
function (selector) {
|
|
12
|
+
let element = this;
|
|
13
|
+
while (element) {
|
|
14
|
+
if (match.call(element, selector)) {
|
|
15
|
+
return element;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
element = element.parentElement;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return function (element, selector) {
|
|
23
|
+
return closest.call(element, selector);
|
|
24
|
+
};
|
|
25
|
+
})();
|
|
26
|
+
export function defer(callback) {
|
|
27
|
+
setTimeout(callback, 1);
|
|
28
|
+
}
|
|
29
|
+
export function dispatch(eventName, { target, cancelable, data } = {}) {
|
|
30
|
+
const event = document.createEvent("Events");
|
|
31
|
+
event.initEvent(eventName, true, cancelable == true);
|
|
32
|
+
event.data = data || {};
|
|
33
|
+
// Fix setting `defaultPrevented` when `preventDefault()` is called
|
|
34
|
+
// http://stackoverflow.com/questions/23349191/event-preventdefault-is-not-working-in-ie-11-for-custom-events
|
|
35
|
+
if (event.cancelable && !preventDefaultSupported) {
|
|
36
|
+
const { preventDefault } = event;
|
|
37
|
+
event.preventDefault = function () {
|
|
38
|
+
if (!this.defaultPrevented) {
|
|
39
|
+
Object.defineProperty(this, "defaultPrevented", { get: () => true });
|
|
40
|
+
}
|
|
41
|
+
preventDefault.call(this);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
(target || document).dispatchEvent(event);
|
|
45
|
+
return event;
|
|
46
|
+
}
|
|
47
|
+
const preventDefaultSupported = (() => {
|
|
48
|
+
const event = document.createEvent("Events");
|
|
49
|
+
event.initEvent("test", true, true);
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
return event.defaultPrevented;
|
|
52
|
+
})();
|
|
53
|
+
export function unindent(strings, ...values) {
|
|
54
|
+
const lines = trimLeft(interpolate(strings, values)).split("\n");
|
|
55
|
+
const match = lines[0].match(/^\s+/);
|
|
56
|
+
const indent = match ? match[0].length : 0;
|
|
57
|
+
return lines.map((line) => line.slice(indent)).join("\n");
|
|
58
|
+
}
|
|
59
|
+
function trimLeft(string) {
|
|
60
|
+
return string.replace(/^\n/, "");
|
|
61
|
+
}
|
|
62
|
+
function interpolate(strings, values) {
|
|
63
|
+
return strings.reduce((result, string, i) => {
|
|
64
|
+
const value = values[i] == undefined ? "" : values[i];
|
|
65
|
+
return result + string + value;
|
|
66
|
+
}, "");
|
|
67
|
+
}
|
|
68
|
+
export function uuid() {
|
|
69
|
+
return Array.apply(null, { length: 36 })
|
|
70
|
+
.map((_, i) => {
|
|
71
|
+
if (i == 8 || i == 13 || i == 18 || i == 23) {
|
|
72
|
+
return "-";
|
|
73
|
+
}
|
|
74
|
+
else if (i == 14) {
|
|
75
|
+
return "4";
|
|
76
|
+
}
|
|
77
|
+
else if (i == 19) {
|
|
78
|
+
return (Math.floor(Math.random() * 4) + 8).toString(16);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
return Math.floor(Math.random() * 15).toString(16);
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
.join("");
|
|
85
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Location } from "./location";
|
|
2
|
+
import { Snapshot } from "./snapshot";
|
|
3
|
+
import { RenderCallback, RenderDelegate } from "./snapshot_renderer";
|
|
4
|
+
export type RenderOptions = {
|
|
5
|
+
snapshot: Snapshot;
|
|
6
|
+
error: string;
|
|
7
|
+
isPreview: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare class View {
|
|
10
|
+
readonly delegate: RenderDelegate;
|
|
11
|
+
readonly htmlElement: HTMLHtmlElement;
|
|
12
|
+
constructor(delegate: RenderDelegate);
|
|
13
|
+
getRootLocation(): Location;
|
|
14
|
+
getElementForAnchor(anchor: string): Element | null;
|
|
15
|
+
getSnapshot(): Snapshot;
|
|
16
|
+
render({ snapshot, error, isPreview }: Partial<RenderOptions>, callback: RenderCallback): void;
|
|
17
|
+
markAsPreview(isPreview: boolean | undefined): void;
|
|
18
|
+
renderSnapshot(snapshot: Snapshot, isPreview: boolean | undefined, callback: RenderCallback): void;
|
|
19
|
+
renderError(error: string | undefined, callback: RenderCallback): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../../lib/turbolinks/view.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,cAAc,EACd,cAAc,EAEf,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,qBAAa,IAAI;IACf,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,WAAW,kBAA+C;gBAEvD,QAAQ,EAAE,cAAc;IAIpC,eAAe,IAAI,QAAQ;IAI3B,mBAAmB,CAAC,MAAM,EAAE,MAAM;IAIlC,WAAW,IAAI,QAAQ;IAIvB,MAAM,CACJ,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,aAAa,CAAC,EACtD,QAAQ,EAAE,cAAc;IAY1B,aAAa,CAAC,SAAS,EAAE,OAAO,GAAG,SAAS;IAQ5C,cAAc,CACZ,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,OAAO,GAAG,SAAS,EAC9B,QAAQ,EAAE,cAAc;IAW1B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,cAAc;CAGhE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ErrorRenderer } from "./error_renderer";
|
|
2
|
+
import { Snapshot } from "./snapshot";
|
|
3
|
+
import { SnapshotRenderer, } from "./snapshot_renderer";
|
|
4
|
+
export class View {
|
|
5
|
+
constructor(delegate) {
|
|
6
|
+
this.htmlElement = document.documentElement;
|
|
7
|
+
this.delegate = delegate;
|
|
8
|
+
}
|
|
9
|
+
getRootLocation() {
|
|
10
|
+
return this.getSnapshot().getRootLocation();
|
|
11
|
+
}
|
|
12
|
+
getElementForAnchor(anchor) {
|
|
13
|
+
return this.getSnapshot().getElementForAnchor(anchor);
|
|
14
|
+
}
|
|
15
|
+
getSnapshot() {
|
|
16
|
+
return Snapshot.fromHTMLElement(this.htmlElement);
|
|
17
|
+
}
|
|
18
|
+
render({ snapshot, error, isPreview }, callback) {
|
|
19
|
+
this.markAsPreview(isPreview);
|
|
20
|
+
if (snapshot) {
|
|
21
|
+
this.renderSnapshot(snapshot, isPreview, callback);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.renderError(error, callback);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Private
|
|
28
|
+
markAsPreview(isPreview) {
|
|
29
|
+
if (isPreview) {
|
|
30
|
+
this.htmlElement.setAttribute("data-turbolinks-preview", "");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.htmlElement.removeAttribute("data-turbolinks-preview");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
renderSnapshot(snapshot, isPreview, callback) {
|
|
37
|
+
SnapshotRenderer.render(this.delegate, callback, this.getSnapshot(), snapshot, isPreview || false);
|
|
38
|
+
}
|
|
39
|
+
renderError(error, callback) {
|
|
40
|
+
ErrorRenderer.render(this.delegate, callback, error || "");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Adapter } from "./adapter";
|
|
2
|
+
import { Controller, RestorationData } from "./controller";
|
|
3
|
+
import { HttpRequest } from "./http_request";
|
|
4
|
+
import { Location } from "./location";
|
|
5
|
+
import { RenderCallback } from "./renderer";
|
|
6
|
+
import { Snapshot } from "./snapshot";
|
|
7
|
+
import { Action } from "./types";
|
|
8
|
+
export declare enum TimingMetric {
|
|
9
|
+
visitStart = "visitStart",
|
|
10
|
+
requestStart = "requestStart",
|
|
11
|
+
requestEnd = "requestEnd",
|
|
12
|
+
visitEnd = "visitEnd"
|
|
13
|
+
}
|
|
14
|
+
export type TimingMetrics = Partial<{
|
|
15
|
+
[metric in TimingMetric]: any;
|
|
16
|
+
}>;
|
|
17
|
+
export declare enum VisitState {
|
|
18
|
+
initialized = "initialized",
|
|
19
|
+
started = "started",
|
|
20
|
+
canceled = "canceled",
|
|
21
|
+
failed = "failed",
|
|
22
|
+
completed = "completed"
|
|
23
|
+
}
|
|
24
|
+
export declare class Visit {
|
|
25
|
+
readonly controller: Controller;
|
|
26
|
+
readonly action: Action;
|
|
27
|
+
readonly adapter: Adapter;
|
|
28
|
+
readonly identifier: string;
|
|
29
|
+
readonly restorationIdentifier: string;
|
|
30
|
+
readonly timingMetrics: TimingMetrics;
|
|
31
|
+
followedRedirect: boolean;
|
|
32
|
+
frame?: number;
|
|
33
|
+
historyChanged: boolean;
|
|
34
|
+
location: Location;
|
|
35
|
+
progress: number;
|
|
36
|
+
referrer?: Location;
|
|
37
|
+
redirectedToLocation?: Location;
|
|
38
|
+
request?: HttpRequest;
|
|
39
|
+
response?: string;
|
|
40
|
+
restorationData?: RestorationData;
|
|
41
|
+
scrolled: boolean;
|
|
42
|
+
snapshotCached: boolean;
|
|
43
|
+
state: VisitState;
|
|
44
|
+
constructor(controller: Controller, location: Location, action: Action, restorationIdentifier?: string);
|
|
45
|
+
start(): void;
|
|
46
|
+
cancel(): void;
|
|
47
|
+
complete(): void;
|
|
48
|
+
fail(): void;
|
|
49
|
+
changeHistory(): void;
|
|
50
|
+
issueRequest(): void;
|
|
51
|
+
getCachedSnapshot(): Snapshot | undefined;
|
|
52
|
+
hasCachedSnapshot(): boolean;
|
|
53
|
+
loadCachedSnapshot(): void;
|
|
54
|
+
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
|
+
recordTimingMetric(metric: TimingMetric): void;
|
|
66
|
+
getTimingMetrics(): TimingMetrics;
|
|
67
|
+
getHistoryMethodForAction(action: Action): (locatable: import("./location").Locatable, restorationIdentifier: string) => void;
|
|
68
|
+
shouldIssueRequest(): boolean;
|
|
69
|
+
cacheSnapshot(): void;
|
|
70
|
+
render(callback: RenderCallback): void;
|
|
71
|
+
cancelRender(): void;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=visit.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { HttpRequest } from "./http_request";
|
|
2
|
+
import { Snapshot } from "./snapshot";
|
|
3
|
+
import { uuid } from "./util";
|
|
4
|
+
export var TimingMetric;
|
|
5
|
+
(function (TimingMetric) {
|
|
6
|
+
TimingMetric["visitStart"] = "visitStart";
|
|
7
|
+
TimingMetric["requestStart"] = "requestStart";
|
|
8
|
+
TimingMetric["requestEnd"] = "requestEnd";
|
|
9
|
+
TimingMetric["visitEnd"] = "visitEnd";
|
|
10
|
+
})(TimingMetric || (TimingMetric = {}));
|
|
11
|
+
export var VisitState;
|
|
12
|
+
(function (VisitState) {
|
|
13
|
+
VisitState["initialized"] = "initialized";
|
|
14
|
+
VisitState["started"] = "started";
|
|
15
|
+
VisitState["canceled"] = "canceled";
|
|
16
|
+
VisitState["failed"] = "failed";
|
|
17
|
+
VisitState["completed"] = "completed";
|
|
18
|
+
})(VisitState || (VisitState = {}));
|
|
19
|
+
export class Visit {
|
|
20
|
+
constructor(controller, location, action, restorationIdentifier = uuid()) {
|
|
21
|
+
this.identifier = uuid();
|
|
22
|
+
this.timingMetrics = {};
|
|
23
|
+
this.followedRedirect = false;
|
|
24
|
+
this.historyChanged = false;
|
|
25
|
+
this.progress = 0;
|
|
26
|
+
this.scrolled = false;
|
|
27
|
+
this.snapshotCached = false;
|
|
28
|
+
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
|
+
};
|
|
41
|
+
this.controller = controller;
|
|
42
|
+
this.location = location;
|
|
43
|
+
this.action = action;
|
|
44
|
+
this.adapter = controller.adapter;
|
|
45
|
+
this.restorationIdentifier = restorationIdentifier;
|
|
46
|
+
}
|
|
47
|
+
start() {
|
|
48
|
+
if (this.state == VisitState.initialized) {
|
|
49
|
+
this.recordTimingMetric(TimingMetric.visitStart);
|
|
50
|
+
this.state = VisitState.started;
|
|
51
|
+
this.adapter.visitStarted(this);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
cancel() {
|
|
55
|
+
if (this.state == VisitState.started) {
|
|
56
|
+
if (this.request) {
|
|
57
|
+
this.request.cancel();
|
|
58
|
+
}
|
|
59
|
+
this.cancelRender();
|
|
60
|
+
this.state = VisitState.canceled;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
complete() {
|
|
64
|
+
if (this.state == VisitState.started) {
|
|
65
|
+
this.recordTimingMetric(TimingMetric.visitEnd);
|
|
66
|
+
this.state = VisitState.completed;
|
|
67
|
+
this.adapter.visitCompleted(this);
|
|
68
|
+
this.controller.visitCompleted(this);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
fail() {
|
|
72
|
+
if (this.state == VisitState.started) {
|
|
73
|
+
this.state = VisitState.failed;
|
|
74
|
+
this.adapter.visitFailed(this);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
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
|
+
}
|
|
86
|
+
}
|
|
87
|
+
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();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
getCachedSnapshot() {
|
|
95
|
+
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()) {
|
|
99
|
+
return snapshot;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
hasCachedSnapshot() {
|
|
104
|
+
return this.getCachedSnapshot() != null;
|
|
105
|
+
}
|
|
106
|
+
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
|
+
}
|
|
119
|
+
}
|
|
120
|
+
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
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// HTTP request delegate
|
|
146
|
+
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
|
+
}
|
|
165
|
+
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 });
|
|
186
|
+
}
|
|
187
|
+
// Instrumentation
|
|
188
|
+
recordTimingMetric(metric) {
|
|
189
|
+
this.timingMetrics[metric] = new Date().getTime();
|
|
190
|
+
}
|
|
191
|
+
getTimingMetrics() {
|
|
192
|
+
return { ...this.timingMetrics };
|
|
193
|
+
}
|
|
194
|
+
// 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
|
+
shouldIssueRequest() {
|
|
206
|
+
return this.action == "restore" ? !this.hasCachedSnapshot() : true;
|
|
207
|
+
}
|
|
208
|
+
cacheSnapshot() {
|
|
209
|
+
if (!this.snapshotCached) {
|
|
210
|
+
this.controller.cacheSnapshot();
|
|
211
|
+
this.snapshotCached = true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
render(callback) {
|
|
215
|
+
this.cancelRender();
|
|
216
|
+
this.frame = requestAnimationFrame(() => {
|
|
217
|
+
delete this.frame;
|
|
218
|
+
callback.call(this);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
cancelRender() {
|
|
222
|
+
if (this.frame) {
|
|
223
|
+
cancelAnimationFrame(this.frame);
|
|
224
|
+
delete this.frame;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
2
|
route: string;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
onBeforeRender: "import:@alignable/bifrost/proxy/pages/onBeforeRender";
|
|
4
|
+
onRenderClient: "import:@alignable/bifrost/proxy/pages/onRenderClient";
|
|
5
|
+
onRenderHtml: "import:@alignable/bifrost/proxy/pages/onRenderHtml";
|
|
6
|
+
Page: string;
|
|
7
7
|
passToClient: string[];
|
|
8
8
|
clientRouting: true;
|
|
9
9
|
hydrationCanBeAborted: true;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
route: "/*",
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
onBeforeRender: "import:@alignable/bifrost/proxy/pages/onBeforeRender",
|
|
4
|
+
onRenderClient: "import:@alignable/bifrost/proxy/pages/onRenderClient",
|
|
5
|
+
onRenderHtml: "import:@alignable/bifrost/proxy/pages/onRenderHtml",
|
|
6
|
+
Page: "import:@alignable/bifrost/proxy/pages/Page",
|
|
7
7
|
passToClient: ["proxySendClient", "layout", "layoutProps", "redirectTo"],
|
|
8
8
|
clientRouting: true,
|
|
9
9
|
hydrationCanBeAborted: true,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onPageTransitionStart.d.ts","sourceRoot":"","sources":["../../../proxy/pages/onPageTransitionStart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yCAAyC,EAAE,MAAM,uBAAuB,CAAC;AAIlF,MAAM,CAAC,OAAO,UAAU,qBAAqB,CAC3C,WAAW,EAAE,yCAAyC,QAQvD"}
|