turbo-rails 2.0.0.pre.beta.3 → 2.0.0.pre.rc.1
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 629282c25f127e2c0942f0a9635086e30595dbebda133ce77184da1d153514d5
|
4
|
+
data.tar.gz: 7cb06dba5377f8bbca58b6066b0f13bbb01f1ed705cb11179d326583b9e1e8cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba7ff71a246d6c088408dafbf6778a734776bf54f8006a6b8d6c375f60e8f6b61b9db35b38ddeb7bb757a4d902fe2bf1c88408c0437f7eafef14854741e39aee
|
7
|
+
data.tar.gz: d0ce9c29add7525e7afdf8fcc691b937df92a51a39588d86d45ad88e5236dec28630d52722032024b67d534ca251dde1182666442bab98e9822a60e841548973
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
Turbo 8.0.0-
|
2
|
+
Turbo 8.0.0-rc.1
|
3
3
|
Copyright © 2024 37signals LLC
|
4
4
|
*/
|
5
5
|
(function(prototype) {
|
@@ -1228,7 +1228,8 @@ class View {
|
|
1228
1228
|
return window;
|
1229
1229
|
}
|
1230
1230
|
async render(renderer) {
|
1231
|
-
const {isPreview: isPreview, shouldRender: shouldRender, newSnapshot: snapshot} = renderer;
|
1231
|
+
const {isPreview: isPreview, shouldRender: shouldRender, willRender: willRender, newSnapshot: snapshot} = renderer;
|
1232
|
+
const shouldInvalidate = willRender;
|
1232
1233
|
if (shouldRender) {
|
1233
1234
|
try {
|
1234
1235
|
this.renderPromise = new Promise((resolve => this.#resolveRenderPromise = resolve));
|
@@ -1237,7 +1238,8 @@ class View {
|
|
1237
1238
|
const renderInterception = new Promise((resolve => this.#resolveInterceptionPromise = resolve));
|
1238
1239
|
const options = {
|
1239
1240
|
resume: this.#resolveInterceptionPromise,
|
1240
|
-
render: this.renderer.renderElement
|
1241
|
+
render: this.renderer.renderElement,
|
1242
|
+
renderMethod: this.renderer.renderMethod
|
1241
1243
|
};
|
1242
1244
|
const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
|
1243
1245
|
if (!immediateRender) await renderInterception;
|
@@ -1250,7 +1252,7 @@ class View {
|
|
1250
1252
|
this.#resolveRenderPromise(undefined);
|
1251
1253
|
delete this.renderPromise;
|
1252
1254
|
}
|
1253
|
-
} else {
|
1255
|
+
} else if (shouldInvalidate) {
|
1254
1256
|
this.invalidate(renderer.reloadReason);
|
1255
1257
|
}
|
1256
1258
|
}
|
@@ -1623,8 +1625,6 @@ function readScrollBehavior(value, defaultValue) {
|
|
1623
1625
|
}
|
1624
1626
|
}
|
1625
1627
|
|
1626
|
-
const ProgressBarID = "turbo-progress-bar";
|
1627
|
-
|
1628
1628
|
class ProgressBar {
|
1629
1629
|
static animationDuration=300;
|
1630
1630
|
static get defaultCSS() {
|
@@ -1712,8 +1712,6 @@ class ProgressBar {
|
|
1712
1712
|
}
|
1713
1713
|
createStylesheetElement() {
|
1714
1714
|
const element = document.createElement("style");
|
1715
|
-
element.id = ProgressBarID;
|
1716
|
-
element.setAttribute("data-turbo-permanent", "");
|
1717
1715
|
element.type = "text/css";
|
1718
1716
|
element.textContent = ProgressBar.defaultCSS;
|
1719
1717
|
if (this.cspNonce) {
|
@@ -1969,6 +1967,7 @@ class Visit {
|
|
1969
1967
|
this.snapshotHTML = snapshotHTML;
|
1970
1968
|
this.response = response;
|
1971
1969
|
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
1970
|
+
this.isPageRefresh = this.view.isPageRefresh(this);
|
1972
1971
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
1973
1972
|
this.willRender = willRender;
|
1974
1973
|
this.updateHistory = updateHistory;
|
@@ -2110,7 +2109,7 @@ class Visit {
|
|
2110
2109
|
const isPreview = this.shouldIssueRequest();
|
2111
2110
|
this.render((async () => {
|
2112
2111
|
this.cacheSnapshot();
|
2113
|
-
if (this.isSamePage) {
|
2112
|
+
if (this.isSamePage || this.isPageRefresh) {
|
2114
2113
|
this.adapter.visitRendered(this);
|
2115
2114
|
} else {
|
2116
2115
|
if (this.view.renderPromise) await this.view.renderPromise;
|
@@ -2638,17 +2637,14 @@ class LinkPrefetchObserver {
|
|
2638
2637
|
};
|
2639
2638
|
prepareRequest(request) {
|
2640
2639
|
const link = request.target;
|
2641
|
-
request.headers["Sec-Purpose"] = "prefetch";
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
2646
|
-
if (turboFrame) {
|
2647
|
-
request.headers["Turbo-Frame"] = turboFrame.id;
|
2648
|
-
}
|
2640
|
+
request.headers["X-Sec-Purpose"] = "prefetch";
|
2641
|
+
const turboFrame = link.closest("turbo-frame");
|
2642
|
+
const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id;
|
2643
|
+
if (turboFrameTarget && turboFrameTarget !== "_top") {
|
2644
|
+
request.headers["Turbo-Frame"] = turboFrameTarget;
|
2649
2645
|
}
|
2650
2646
|
if (link.hasAttribute("data-turbo-stream")) {
|
2651
|
-
request.acceptResponseType(
|
2647
|
+
request.acceptResponseType(StreamMessage.contentType);
|
2652
2648
|
}
|
2653
2649
|
}
|
2654
2650
|
requestSucceededWithResponse() {}
|
@@ -2662,7 +2658,7 @@ class LinkPrefetchObserver {
|
|
2662
2658
|
}
|
2663
2659
|
#isPrefetchable(link) {
|
2664
2660
|
const href = link.getAttribute("href");
|
2665
|
-
if (!href || href === "#" || link.
|
2661
|
+
if (!href || href === "#" || link.getAttribute("data-turbo") === "false" || link.getAttribute("data-turbo-prefetch") === "false") {
|
2666
2662
|
return false;
|
2667
2663
|
}
|
2668
2664
|
if (link.origin !== document.location.origin) {
|
@@ -2674,17 +2670,15 @@ class LinkPrefetchObserver {
|
|
2674
2670
|
if (link.pathname + link.search === document.location.pathname + document.location.search) {
|
2675
2671
|
return false;
|
2676
2672
|
}
|
2677
|
-
|
2673
|
+
const turboMethod = link.getAttribute("data-turbo-method");
|
2674
|
+
if (turboMethod && turboMethod !== "get") {
|
2678
2675
|
return false;
|
2679
2676
|
}
|
2680
2677
|
if (targetsIframe(link)) {
|
2681
2678
|
return false;
|
2682
2679
|
}
|
2683
|
-
if (link.pathname + link.search === document.location.pathname + document.location.search) {
|
2684
|
-
return false;
|
2685
|
-
}
|
2686
2680
|
const turboPrefetchParent = findClosestRecursively(link, "[data-turbo-prefetch]");
|
2687
|
-
if (turboPrefetchParent && turboPrefetchParent.
|
2681
|
+
if (turboPrefetchParent && turboPrefetchParent.getAttribute("data-turbo-prefetch") === "false") {
|
2688
2682
|
return false;
|
2689
2683
|
}
|
2690
2684
|
return true;
|
@@ -3623,76 +3617,6 @@ var Idiomorph = function() {
|
|
3623
3617
|
};
|
3624
3618
|
}();
|
3625
3619
|
|
3626
|
-
class MorphRenderer extends Renderer {
|
3627
|
-
async render() {
|
3628
|
-
if (this.willRender) await this.#morphBody();
|
3629
|
-
}
|
3630
|
-
get renderMethod() {
|
3631
|
-
return "morph";
|
3632
|
-
}
|
3633
|
-
async #morphBody() {
|
3634
|
-
this.#morphElements(this.currentElement, this.newElement);
|
3635
|
-
this.#reloadRemoteFrames();
|
3636
|
-
dispatch("turbo:morph", {
|
3637
|
-
detail: {
|
3638
|
-
currentElement: this.currentElement,
|
3639
|
-
newElement: this.newElement
|
3640
|
-
}
|
3641
|
-
});
|
3642
|
-
}
|
3643
|
-
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
3644
|
-
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
3645
|
-
Idiomorph.morph(currentElement, newElement, {
|
3646
|
-
morphStyle: morphStyle,
|
3647
|
-
callbacks: {
|
3648
|
-
beforeNodeAdded: this.#shouldAddElement,
|
3649
|
-
beforeNodeMorphed: this.#shouldMorphElement,
|
3650
|
-
beforeNodeRemoved: this.#shouldRemoveElement
|
3651
|
-
}
|
3652
|
-
});
|
3653
|
-
}
|
3654
|
-
#shouldAddElement=node => !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id));
|
3655
|
-
#shouldMorphElement=(oldNode, newNode) => {
|
3656
|
-
if (oldNode instanceof HTMLElement) {
|
3657
|
-
return !oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode));
|
3658
|
-
} else {
|
3659
|
-
return true;
|
3660
|
-
}
|
3661
|
-
};
|
3662
|
-
#shouldRemoveElement=node => this.#shouldMorphElement(node);
|
3663
|
-
#reloadRemoteFrames() {
|
3664
|
-
this.#remoteFrames().forEach((frame => {
|
3665
|
-
if (this.#isFrameReloadedWithMorph(frame)) {
|
3666
|
-
this.#renderFrameWithMorph(frame);
|
3667
|
-
frame.reload();
|
3668
|
-
}
|
3669
|
-
}));
|
3670
|
-
}
|
3671
|
-
#renderFrameWithMorph(frame) {
|
3672
|
-
frame.addEventListener("turbo:before-frame-render", (event => {
|
3673
|
-
event.detail.render = this.#morphFrameUpdate;
|
3674
|
-
}), {
|
3675
|
-
once: true
|
3676
|
-
});
|
3677
|
-
}
|
3678
|
-
#morphFrameUpdate=(currentElement, newElement) => {
|
3679
|
-
dispatch("turbo:before-frame-morph", {
|
3680
|
-
target: currentElement,
|
3681
|
-
detail: {
|
3682
|
-
currentElement: currentElement,
|
3683
|
-
newElement: newElement
|
3684
|
-
}
|
3685
|
-
});
|
3686
|
-
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
3687
|
-
};
|
3688
|
-
#isFrameReloadedWithMorph(element) {
|
3689
|
-
return element.src && element.refresh === "morph";
|
3690
|
-
}
|
3691
|
-
#remoteFrames() {
|
3692
|
-
return Array.from(document.querySelectorAll("turbo-frame[src]")).filter((frame => !frame.closest("[data-turbo-permanent]")));
|
3693
|
-
}
|
3694
|
-
}
|
3695
|
-
|
3696
3620
|
class PageRenderer extends Renderer {
|
3697
3621
|
static renderElement(currentElement, newElement) {
|
3698
3622
|
if (document.body && newElement instanceof HTMLBodyElement) {
|
@@ -3756,7 +3680,7 @@ class PageRenderer extends Renderer {
|
|
3756
3680
|
await mergedHeadElements;
|
3757
3681
|
await newStylesheetElements;
|
3758
3682
|
if (this.willRender) {
|
3759
|
-
this.
|
3683
|
+
this.removeUnusedDynamicStylesheetElements();
|
3760
3684
|
}
|
3761
3685
|
}
|
3762
3686
|
async replaceBody() {
|
@@ -3781,8 +3705,8 @@ class PageRenderer extends Renderer {
|
|
3781
3705
|
document.head.appendChild(activateScriptElement(element));
|
3782
3706
|
}
|
3783
3707
|
}
|
3784
|
-
|
3785
|
-
for (const element of this.
|
3708
|
+
removeUnusedDynamicStylesheetElements() {
|
3709
|
+
for (const element of this.unusedDynamicStylesheetElements) {
|
3786
3710
|
document.head.removeChild(element);
|
3787
3711
|
}
|
3788
3712
|
}
|
@@ -3838,8 +3762,8 @@ class PageRenderer extends Renderer {
|
|
3838
3762
|
async assignNewBody() {
|
3839
3763
|
await this.renderElement(this.currentElement, this.newElement);
|
3840
3764
|
}
|
3841
|
-
get
|
3842
|
-
return this.oldHeadStylesheetElements.filter((element =>
|
3765
|
+
get unusedDynamicStylesheetElements() {
|
3766
|
+
return this.oldHeadStylesheetElements.filter((element => element.getAttribute("data-turbo-track") === "dynamic"));
|
3843
3767
|
}
|
3844
3768
|
get oldHeadStylesheetElements() {
|
3845
3769
|
return this.currentHeadSnapshot.getStylesheetElementsNotInSnapshot(this.newHeadSnapshot);
|
@@ -3861,6 +3785,109 @@ class PageRenderer extends Renderer {
|
|
3861
3785
|
}
|
3862
3786
|
}
|
3863
3787
|
|
3788
|
+
class MorphRenderer extends PageRenderer {
|
3789
|
+
async render() {
|
3790
|
+
if (this.willRender) await this.#morphBody();
|
3791
|
+
}
|
3792
|
+
get renderMethod() {
|
3793
|
+
return "morph";
|
3794
|
+
}
|
3795
|
+
async #morphBody() {
|
3796
|
+
this.#morphElements(this.currentElement, this.newElement);
|
3797
|
+
this.#reloadRemoteFrames();
|
3798
|
+
dispatch("turbo:morph", {
|
3799
|
+
detail: {
|
3800
|
+
currentElement: this.currentElement,
|
3801
|
+
newElement: this.newElement
|
3802
|
+
}
|
3803
|
+
});
|
3804
|
+
}
|
3805
|
+
#morphElements(currentElement, newElement, morphStyle = "outerHTML") {
|
3806
|
+
this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
|
3807
|
+
Idiomorph.morph(currentElement, newElement, {
|
3808
|
+
ignoreActiveValue: true,
|
3809
|
+
morphStyle: morphStyle,
|
3810
|
+
callbacks: {
|
3811
|
+
beforeNodeAdded: this.#shouldAddElement,
|
3812
|
+
beforeNodeMorphed: this.#shouldMorphElement,
|
3813
|
+
beforeAttributeUpdated: this.#shouldUpdateAttribute,
|
3814
|
+
beforeNodeRemoved: this.#shouldRemoveElement,
|
3815
|
+
afterNodeMorphed: this.#didMorphElement
|
3816
|
+
}
|
3817
|
+
});
|
3818
|
+
}
|
3819
|
+
#shouldAddElement=node => !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id));
|
3820
|
+
#shouldMorphElement=(oldNode, newNode) => {
|
3821
|
+
if (oldNode instanceof HTMLElement) {
|
3822
|
+
if (!oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode))) {
|
3823
|
+
const event = dispatch("turbo:before-morph-element", {
|
3824
|
+
cancelable: true,
|
3825
|
+
target: oldNode,
|
3826
|
+
detail: {
|
3827
|
+
newElement: newNode
|
3828
|
+
}
|
3829
|
+
});
|
3830
|
+
return !event.defaultPrevented;
|
3831
|
+
} else {
|
3832
|
+
return false;
|
3833
|
+
}
|
3834
|
+
}
|
3835
|
+
};
|
3836
|
+
#shouldUpdateAttribute=(attributeName, target, mutationType) => {
|
3837
|
+
const event = dispatch("turbo:before-morph-attribute", {
|
3838
|
+
cancelable: true,
|
3839
|
+
target: target,
|
3840
|
+
detail: {
|
3841
|
+
attributeName: attributeName,
|
3842
|
+
mutationType: mutationType
|
3843
|
+
}
|
3844
|
+
});
|
3845
|
+
return !event.defaultPrevented;
|
3846
|
+
};
|
3847
|
+
#didMorphElement=(oldNode, newNode) => {
|
3848
|
+
if (newNode instanceof HTMLElement) {
|
3849
|
+
dispatch("turbo:morph-element", {
|
3850
|
+
target: oldNode,
|
3851
|
+
detail: {
|
3852
|
+
newElement: newNode
|
3853
|
+
}
|
3854
|
+
});
|
3855
|
+
}
|
3856
|
+
};
|
3857
|
+
#shouldRemoveElement=node => this.#shouldMorphElement(node);
|
3858
|
+
#reloadRemoteFrames() {
|
3859
|
+
this.#remoteFrames().forEach((frame => {
|
3860
|
+
if (this.#isFrameReloadedWithMorph(frame)) {
|
3861
|
+
this.#renderFrameWithMorph(frame);
|
3862
|
+
frame.reload();
|
3863
|
+
}
|
3864
|
+
}));
|
3865
|
+
}
|
3866
|
+
#renderFrameWithMorph(frame) {
|
3867
|
+
frame.addEventListener("turbo:before-frame-render", (event => {
|
3868
|
+
event.detail.render = this.#morphFrameUpdate;
|
3869
|
+
}), {
|
3870
|
+
once: true
|
3871
|
+
});
|
3872
|
+
}
|
3873
|
+
#morphFrameUpdate=(currentElement, newElement) => {
|
3874
|
+
dispatch("turbo:before-frame-morph", {
|
3875
|
+
target: currentElement,
|
3876
|
+
detail: {
|
3877
|
+
currentElement: currentElement,
|
3878
|
+
newElement: newElement
|
3879
|
+
}
|
3880
|
+
});
|
3881
|
+
this.#morphElements(currentElement, newElement.children, "innerHTML");
|
3882
|
+
};
|
3883
|
+
#isFrameReloadedWithMorph(element) {
|
3884
|
+
return element.src && element.refresh === "morph";
|
3885
|
+
}
|
3886
|
+
#remoteFrames() {
|
3887
|
+
return Array.from(document.querySelectorAll("turbo-frame[src]")).filter((frame => !frame.closest("[data-turbo-permanent]")));
|
3888
|
+
}
|
3889
|
+
}
|
3890
|
+
|
3864
3891
|
class SnapshotCache {
|
3865
3892
|
keys=[];
|
3866
3893
|
snapshots={};
|
@@ -3987,7 +4014,7 @@ class Preloader {
|
|
3987
4014
|
await fetchRequest.perform();
|
3988
4015
|
}
|
3989
4016
|
prepareRequest(fetchRequest) {
|
3990
|
-
fetchRequest.headers["Sec-Purpose"] = "prefetch";
|
4017
|
+
fetchRequest.headers["X-Sec-Purpose"] = "prefetch";
|
3991
4018
|
}
|
3992
4019
|
async requestSucceededWithResponse(fetchRequest, fetchResponse) {
|
3993
4020
|
try {
|
@@ -4097,8 +4124,9 @@ class Session {
|
|
4097
4124
|
visit(location, options = {}) {
|
4098
4125
|
const frameElement = options.frame ? document.getElementById(options.frame) : null;
|
4099
4126
|
if (frameElement instanceof FrameElement) {
|
4127
|
+
const action = options.action || getVisitAction(frameElement);
|
4128
|
+
frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action);
|
4100
4129
|
frameElement.src = location.toString();
|
4101
|
-
frameElement.loaded;
|
4102
4130
|
} else {
|
4103
4131
|
this.navigator.proposeVisit(expandURL(location), options);
|
4104
4132
|
}
|
@@ -4568,7 +4596,7 @@ class FrameController {
|
|
4568
4596
|
}
|
4569
4597
|
}
|
4570
4598
|
elementAppearedInViewport(element) {
|
4571
|
-
this.proposeVisitIfNavigatedWithAction(element, element);
|
4599
|
+
this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element));
|
4572
4600
|
this.#loadSourceURL();
|
4573
4601
|
}
|
4574
4602
|
willSubmitFormLinkToLocation(link) {
|
@@ -4628,7 +4656,7 @@ class FrameController {
|
|
4628
4656
|
}
|
4629
4657
|
formSubmissionSucceededWithResponse(formSubmission, response) {
|
4630
4658
|
const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter);
|
4631
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.
|
4659
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame));
|
4632
4660
|
frame.delegate.loadResponse(response);
|
4633
4661
|
if (!formSubmission.isSafe) {
|
4634
4662
|
session.clearCache();
|
@@ -4705,13 +4733,13 @@ class FrameController {
|
|
4705
4733
|
}
|
4706
4734
|
#navigateFrame(element, url, submitter) {
|
4707
4735
|
const frame = this.#findFrameElement(element, submitter);
|
4708
|
-
frame.delegate.proposeVisitIfNavigatedWithAction(frame, element,
|
4736
|
+
frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter, element, frame));
|
4709
4737
|
this.#withCurrentNavigationElement(element, (() => {
|
4710
4738
|
frame.src = url;
|
4711
4739
|
}));
|
4712
4740
|
}
|
4713
|
-
proposeVisitIfNavigatedWithAction(frame,
|
4714
|
-
this.action =
|
4741
|
+
proposeVisitIfNavigatedWithAction(frame, action = null) {
|
4742
|
+
this.action = action;
|
4715
4743
|
if (this.action) {
|
4716
4744
|
const pageSnapshot = PageSnapshot.fromElement(frame).clone();
|
4717
4745
|
const {visitCachedSnapshot: visitCachedSnapshot} = frame.delegate;
|