turbo-rails 2.0.0.pre.beta.4 → 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: 1ebbd80b386f589e8154d0bb0c5a49cbd38dd43e09ad33a33c6981d0d6518d19
4
- data.tar.gz: 94b8d1dcbe102085ddef02c04e3c546d0e96298b7fafce1853875446cb40847a
3
+ metadata.gz: 629282c25f127e2c0942f0a9635086e30595dbebda133ce77184da1d153514d5
4
+ data.tar.gz: 7cb06dba5377f8bbca58b6066b0f13bbb01f1ed705cb11179d326583b9e1e8cf
5
5
  SHA512:
6
- metadata.gz: 4851e50f1411ac0544fd2d9f330f82c9453af40e98b92a5a31a117f20e6a2e28ade5298868a1c6786568eb686546db89c213e3c3ad17dffd52c984cbc84a7eb0
7
- data.tar.gz: feb01812e76d08c659e0c9ffff7ef9dea553ae126603b94b63fa88821ec80acd1d4a6dc8c3921270657f236b66adc25d68507c0de0743e3e7d6f7a3df3644a07
6
+ metadata.gz: ba7ff71a246d6c088408dafbf6778a734776bf54f8006a6b8d6c375f60e8f6b61b9db35b38ddeb7bb757a4d902fe2bf1c88408c0437f7eafef14854741e39aee
7
+ data.tar.gz: d0ce9c29add7525e7afdf8fcc691b937df92a51a39588d86d45ad88e5236dec28630d52722032024b67d534ca251dde1182666442bab98e9822a60e841548973
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Turbo 8.0.0-beta.4
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
  }
@@ -1965,6 +1967,7 @@ class Visit {
1965
1967
  this.snapshotHTML = snapshotHTML;
1966
1968
  this.response = response;
1967
1969
  this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
1970
+ this.isPageRefresh = this.view.isPageRefresh(this);
1968
1971
  this.visitCachedSnapshot = visitCachedSnapshot;
1969
1972
  this.willRender = willRender;
1970
1973
  this.updateHistory = updateHistory;
@@ -2106,7 +2109,7 @@ class Visit {
2106
2109
  const isPreview = this.shouldIssueRequest();
2107
2110
  this.render((async () => {
2108
2111
  this.cacheSnapshot();
2109
- if (this.isSamePage) {
2112
+ if (this.isSamePage || this.isPageRefresh) {
2110
2113
  this.adapter.visitRendered(this);
2111
2114
  } else {
2112
2115
  if (this.view.renderPromise) await this.view.renderPromise;
@@ -2634,14 +2637,14 @@ class LinkPrefetchObserver {
2634
2637
  };
2635
2638
  prepareRequest(request) {
2636
2639
  const link = request.target;
2637
- request.headers["Sec-Purpose"] = "prefetch";
2640
+ request.headers["X-Sec-Purpose"] = "prefetch";
2638
2641
  const turboFrame = link.closest("turbo-frame");
2639
2642
  const turboFrameTarget = link.getAttribute("data-turbo-frame") || turboFrame?.getAttribute("target") || turboFrame?.id;
2640
2643
  if (turboFrameTarget && turboFrameTarget !== "_top") {
2641
2644
  request.headers["Turbo-Frame"] = turboFrameTarget;
2642
2645
  }
2643
2646
  if (link.hasAttribute("data-turbo-stream")) {
2644
- request.acceptResponseType("text/vnd.turbo-stream.html");
2647
+ request.acceptResponseType(StreamMessage.contentType);
2645
2648
  }
2646
2649
  }
2647
2650
  requestSucceededWithResponse() {}
@@ -2655,7 +2658,7 @@ class LinkPrefetchObserver {
2655
2658
  }
2656
2659
  #isPrefetchable(link) {
2657
2660
  const href = link.getAttribute("href");
2658
- if (!href || href === "#" || link.dataset.turbo === "false" || link.dataset.turboPrefetch === "false") {
2661
+ if (!href || href === "#" || link.getAttribute("data-turbo") === "false" || link.getAttribute("data-turbo-prefetch") === "false") {
2659
2662
  return false;
2660
2663
  }
2661
2664
  if (link.origin !== document.location.origin) {
@@ -2667,17 +2670,15 @@ class LinkPrefetchObserver {
2667
2670
  if (link.pathname + link.search === document.location.pathname + document.location.search) {
2668
2671
  return false;
2669
2672
  }
2670
- if (link.dataset.turboMethod && link.dataset.turboMethod !== "get") {
2673
+ const turboMethod = link.getAttribute("data-turbo-method");
2674
+ if (turboMethod && turboMethod !== "get") {
2671
2675
  return false;
2672
2676
  }
2673
2677
  if (targetsIframe(link)) {
2674
2678
  return false;
2675
2679
  }
2676
- if (link.pathname + link.search === document.location.pathname + document.location.search) {
2677
- return false;
2678
- }
2679
2680
  const turboPrefetchParent = findClosestRecursively(link, "[data-turbo-prefetch]");
2680
- if (turboPrefetchParent && turboPrefetchParent.dataset.turboPrefetch === "false") {
2681
+ if (turboPrefetchParent && turboPrefetchParent.getAttribute("data-turbo-prefetch") === "false") {
2681
2682
  return false;
2682
2683
  }
2683
2684
  return true;
@@ -3616,76 +3617,6 @@ var Idiomorph = function() {
3616
3617
  };
3617
3618
  }();
3618
3619
 
3619
- class MorphRenderer extends Renderer {
3620
- async render() {
3621
- if (this.willRender) await this.#morphBody();
3622
- }
3623
- get renderMethod() {
3624
- return "morph";
3625
- }
3626
- async #morphBody() {
3627
- this.#morphElements(this.currentElement, this.newElement);
3628
- this.#reloadRemoteFrames();
3629
- dispatch("turbo:morph", {
3630
- detail: {
3631
- currentElement: this.currentElement,
3632
- newElement: this.newElement
3633
- }
3634
- });
3635
- }
3636
- #morphElements(currentElement, newElement, morphStyle = "outerHTML") {
3637
- this.isMorphingTurboFrame = this.#isFrameReloadedWithMorph(currentElement);
3638
- Idiomorph.morph(currentElement, newElement, {
3639
- morphStyle: morphStyle,
3640
- callbacks: {
3641
- beforeNodeAdded: this.#shouldAddElement,
3642
- beforeNodeMorphed: this.#shouldMorphElement,
3643
- beforeNodeRemoved: this.#shouldRemoveElement
3644
- }
3645
- });
3646
- }
3647
- #shouldAddElement=node => !(node.id && node.hasAttribute("data-turbo-permanent") && document.getElementById(node.id));
3648
- #shouldMorphElement=(oldNode, newNode) => {
3649
- if (oldNode instanceof HTMLElement) {
3650
- return !oldNode.hasAttribute("data-turbo-permanent") && (this.isMorphingTurboFrame || !this.#isFrameReloadedWithMorph(oldNode));
3651
- } else {
3652
- return true;
3653
- }
3654
- };
3655
- #shouldRemoveElement=node => this.#shouldMorphElement(node);
3656
- #reloadRemoteFrames() {
3657
- this.#remoteFrames().forEach((frame => {
3658
- if (this.#isFrameReloadedWithMorph(frame)) {
3659
- this.#renderFrameWithMorph(frame);
3660
- frame.reload();
3661
- }
3662
- }));
3663
- }
3664
- #renderFrameWithMorph(frame) {
3665
- frame.addEventListener("turbo:before-frame-render", (event => {
3666
- event.detail.render = this.#morphFrameUpdate;
3667
- }), {
3668
- once: true
3669
- });
3670
- }
3671
- #morphFrameUpdate=(currentElement, newElement) => {
3672
- dispatch("turbo:before-frame-morph", {
3673
- target: currentElement,
3674
- detail: {
3675
- currentElement: currentElement,
3676
- newElement: newElement
3677
- }
3678
- });
3679
- this.#morphElements(currentElement, newElement.children, "innerHTML");
3680
- };
3681
- #isFrameReloadedWithMorph(element) {
3682
- return element.src && element.refresh === "morph";
3683
- }
3684
- #remoteFrames() {
3685
- return Array.from(document.querySelectorAll("turbo-frame[src]")).filter((frame => !frame.closest("[data-turbo-permanent]")));
3686
- }
3687
- }
3688
-
3689
3620
  class PageRenderer extends Renderer {
3690
3621
  static renderElement(currentElement, newElement) {
3691
3622
  if (document.body && newElement instanceof HTMLBodyElement) {
@@ -3854,6 +3785,109 @@ class PageRenderer extends Renderer {
3854
3785
  }
3855
3786
  }
3856
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
+
3857
3891
  class SnapshotCache {
3858
3892
  keys=[];
3859
3893
  snapshots={};
@@ -3980,7 +4014,7 @@ class Preloader {
3980
4014
  await fetchRequest.perform();
3981
4015
  }
3982
4016
  prepareRequest(fetchRequest) {
3983
- fetchRequest.headers["Sec-Purpose"] = "prefetch";
4017
+ fetchRequest.headers["X-Sec-Purpose"] = "prefetch";
3984
4018
  }
3985
4019
  async requestSucceededWithResponse(fetchRequest, fetchResponse) {
3986
4020
  try {
@@ -4090,8 +4124,9 @@ class Session {
4090
4124
  visit(location, options = {}) {
4091
4125
  const frameElement = options.frame ? document.getElementById(options.frame) : null;
4092
4126
  if (frameElement instanceof FrameElement) {
4127
+ const action = options.action || getVisitAction(frameElement);
4128
+ frameElement.delegate.proposeVisitIfNavigatedWithAction(frameElement, action);
4093
4129
  frameElement.src = location.toString();
4094
- frameElement.loaded;
4095
4130
  } else {
4096
4131
  this.navigator.proposeVisit(expandURL(location), options);
4097
4132
  }
@@ -4561,7 +4596,7 @@ class FrameController {
4561
4596
  }
4562
4597
  }
4563
4598
  elementAppearedInViewport(element) {
4564
- this.proposeVisitIfNavigatedWithAction(element, element);
4599
+ this.proposeVisitIfNavigatedWithAction(element, getVisitAction(element));
4565
4600
  this.#loadSourceURL();
4566
4601
  }
4567
4602
  willSubmitFormLinkToLocation(link) {
@@ -4621,7 +4656,7 @@ class FrameController {
4621
4656
  }
4622
4657
  formSubmissionSucceededWithResponse(formSubmission, response) {
4623
4658
  const frame = this.#findFrameElement(formSubmission.formElement, formSubmission.submitter);
4624
- frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
4659
+ frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(formSubmission.submitter, formSubmission.formElement, frame));
4625
4660
  frame.delegate.loadResponse(response);
4626
4661
  if (!formSubmission.isSafe) {
4627
4662
  session.clearCache();
@@ -4698,13 +4733,13 @@ class FrameController {
4698
4733
  }
4699
4734
  #navigateFrame(element, url, submitter) {
4700
4735
  const frame = this.#findFrameElement(element, submitter);
4701
- frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
4736
+ frame.delegate.proposeVisitIfNavigatedWithAction(frame, getVisitAction(submitter, element, frame));
4702
4737
  this.#withCurrentNavigationElement(element, (() => {
4703
4738
  frame.src = url;
4704
4739
  }));
4705
4740
  }
4706
- proposeVisitIfNavigatedWithAction(frame, element, submitter) {
4707
- this.action = getVisitAction(submitter, element, frame);
4741
+ proposeVisitIfNavigatedWithAction(frame, action = null) {
4742
+ this.action = action;
4708
4743
  if (this.action) {
4709
4744
  const pageSnapshot = PageSnapshot.fromElement(frame).clone();
4710
4745
  const {visitCachedSnapshot: visitCachedSnapshot} = frame.delegate;