@hotwired/turbo 8.0.6 → 8.0.11

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Turbo 8.0.6
2
+ Turbo 8.0.11
3
3
  Copyright © 2024 37signals LLC
4
4
  */
5
5
  /**
@@ -313,7 +313,7 @@ function activateScriptElement(element) {
313
313
  return element
314
314
  } else {
315
315
  const createdScriptElement = document.createElement("script");
316
- const cspNonce = getMetaContent("csp-nonce");
316
+ const cspNonce = getCspNonce();
317
317
  if (cspNonce) {
318
318
  createdScriptElement.nonce = cspNonce;
319
319
  }
@@ -486,6 +486,15 @@ function getMetaContent(name) {
486
486
  return element && element.content
487
487
  }
488
488
 
489
+ function getCspNonce() {
490
+ const element = getMetaElement("csp-nonce");
491
+
492
+ if (element) {
493
+ const { nonce, content } = element;
494
+ return nonce == "" ? content : nonce
495
+ }
496
+ }
497
+
489
498
  function setMetaContent(name, content) {
490
499
  let element = getMetaElement(name);
491
500
 
@@ -1843,12 +1852,16 @@ function createPlaceholderForPermanentElement(permanentElement) {
1843
1852
  class Renderer {
1844
1853
  #activeElement = null
1845
1854
 
1846
- constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
1855
+ static renderElement(currentElement, newElement) {
1856
+ // Abstract method
1857
+ }
1858
+
1859
+ constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) {
1847
1860
  this.currentSnapshot = currentSnapshot;
1848
1861
  this.newSnapshot = newSnapshot;
1849
1862
  this.isPreview = isPreview;
1850
1863
  this.willRender = willRender;
1851
- this.renderElement = renderElement;
1864
+ this.renderElement = this.constructor.renderElement;
1852
1865
  this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
1853
1866
  }
1854
1867
 
@@ -2919,6 +2932,10 @@ class MorphingFrameRenderer extends FrameRenderer {
2919
2932
 
2920
2933
  morphChildren(currentElement, newElement);
2921
2934
  }
2935
+
2936
+ async preservingPermanentElements(callback) {
2937
+ return await callback()
2938
+ }
2922
2939
  }
2923
2940
 
2924
2941
  class ProgressBar {
@@ -3027,8 +3044,9 @@ class ProgressBar {
3027
3044
  const element = document.createElement("style");
3028
3045
  element.type = "text/css";
3029
3046
  element.textContent = ProgressBar.defaultCSS;
3030
- if (this.cspNonce) {
3031
- element.nonce = this.cspNonce;
3047
+ const cspNonce = getCspNonce();
3048
+ if (cspNonce) {
3049
+ element.nonce = cspNonce;
3032
3050
  }
3033
3051
  return element
3034
3052
  }
@@ -3038,10 +3056,6 @@ class ProgressBar {
3038
3056
  element.className = "turbo-progress-bar";
3039
3057
  return element
3040
3058
  }
3041
-
3042
- get cspNonce() {
3043
- return getMetaContent("csp-nonce")
3044
- }
3045
3059
  }
3046
3060
 
3047
3061
  class HeadSnapshot extends Snapshot {
@@ -5032,7 +5046,7 @@ class PageView extends View {
5032
5046
  const shouldMorphPage = this.isPageRefresh(visit) && this.snapshot.shouldMorphPage;
5033
5047
  const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;
5034
5048
 
5035
- const renderer = new rendererClass(this.snapshot, snapshot, rendererClass.renderElement, isPreview, willRender);
5049
+ const renderer = new rendererClass(this.snapshot, snapshot, isPreview, willRender);
5036
5050
 
5037
5051
  if (!renderer.shouldRender) {
5038
5052
  this.forceReloaded = true;
@@ -5045,7 +5059,7 @@ class PageView extends View {
5045
5059
 
5046
5060
  renderError(snapshot, visit) {
5047
5061
  visit?.changeHistory();
5048
- const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
5062
+ const renderer = new ErrorRenderer(this.snapshot, snapshot, false);
5049
5063
  return this.render(renderer)
5050
5064
  }
5051
5065
 
@@ -5816,6 +5830,7 @@ class FrameController {
5816
5830
  #connected = false
5817
5831
  #hasBeenLoaded = false
5818
5832
  #ignoredAttributes = new Set()
5833
+ #shouldMorphFrame = false
5819
5834
  action = null
5820
5835
 
5821
5836
  constructor(element) {
@@ -5873,13 +5888,10 @@ class FrameController {
5873
5888
  }
5874
5889
 
5875
5890
  sourceURLReloaded() {
5876
- if (this.element.shouldReloadWithMorph) {
5877
- this.element.addEventListener("turbo:before-frame-render", ({ detail }) => {
5878
- detail.render = MorphingFrameRenderer.renderElement;
5879
- }, { once: true });
5880
- }
5891
+ const { refresh, src } = this.element;
5892
+
5893
+ this.#shouldMorphFrame = src && refresh === "morph";
5881
5894
 
5882
- const { src } = this.element;
5883
5895
  this.element.removeAttribute("complete");
5884
5896
  this.element.src = null;
5885
5897
  this.element.src = src;
@@ -5922,6 +5934,7 @@ class FrameController {
5922
5934
  }
5923
5935
  }
5924
5936
  } finally {
5937
+ this.#shouldMorphFrame = false;
5925
5938
  this.fetchResponseLoaded = () => Promise.resolve();
5926
5939
  }
5927
5940
  }
@@ -6087,11 +6100,11 @@ class FrameController {
6087
6100
 
6088
6101
  async #loadFrameResponse(fetchResponse, document) {
6089
6102
  const newFrameElement = await this.extractForeignFrameElement(document.body);
6103
+ const rendererClass = this.#shouldMorphFrame ? MorphingFrameRenderer : FrameRenderer;
6090
6104
 
6091
6105
  if (newFrameElement) {
6092
6106
  const snapshot = new Snapshot(newFrameElement);
6093
- const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
6094
-
6107
+ const renderer = new rendererClass(this, this.view.snapshot, snapshot, false, false);
6095
6108
  if (this.view.renderPromise) await this.view.renderPromise;
6096
6109
  this.changeHistory();
6097
6110
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Turbo 8.0.6
2
+ Turbo 8.0.11
3
3
  Copyright © 2024 37signals LLC
4
4
  */
5
5
  (function (global, factory) {
@@ -319,7 +319,7 @@ Copyright © 2024 37signals LLC
319
319
  return element
320
320
  } else {
321
321
  const createdScriptElement = document.createElement("script");
322
- const cspNonce = getMetaContent("csp-nonce");
322
+ const cspNonce = getCspNonce();
323
323
  if (cspNonce) {
324
324
  createdScriptElement.nonce = cspNonce;
325
325
  }
@@ -492,6 +492,15 @@ Copyright © 2024 37signals LLC
492
492
  return element && element.content
493
493
  }
494
494
 
495
+ function getCspNonce() {
496
+ const element = getMetaElement("csp-nonce");
497
+
498
+ if (element) {
499
+ const { nonce, content } = element;
500
+ return nonce == "" ? content : nonce
501
+ }
502
+ }
503
+
495
504
  function setMetaContent(name, content) {
496
505
  let element = getMetaElement(name);
497
506
 
@@ -1849,12 +1858,16 @@ Copyright © 2024 37signals LLC
1849
1858
  class Renderer {
1850
1859
  #activeElement = null
1851
1860
 
1852
- constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
1861
+ static renderElement(currentElement, newElement) {
1862
+ // Abstract method
1863
+ }
1864
+
1865
+ constructor(currentSnapshot, newSnapshot, isPreview, willRender = true) {
1853
1866
  this.currentSnapshot = currentSnapshot;
1854
1867
  this.newSnapshot = newSnapshot;
1855
1868
  this.isPreview = isPreview;
1856
1869
  this.willRender = willRender;
1857
- this.renderElement = renderElement;
1870
+ this.renderElement = this.constructor.renderElement;
1858
1871
  this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
1859
1872
  }
1860
1873
 
@@ -2925,6 +2938,10 @@ Copyright © 2024 37signals LLC
2925
2938
 
2926
2939
  morphChildren(currentElement, newElement);
2927
2940
  }
2941
+
2942
+ async preservingPermanentElements(callback) {
2943
+ return await callback()
2944
+ }
2928
2945
  }
2929
2946
 
2930
2947
  class ProgressBar {
@@ -3033,8 +3050,9 @@ Copyright © 2024 37signals LLC
3033
3050
  const element = document.createElement("style");
3034
3051
  element.type = "text/css";
3035
3052
  element.textContent = ProgressBar.defaultCSS;
3036
- if (this.cspNonce) {
3037
- element.nonce = this.cspNonce;
3053
+ const cspNonce = getCspNonce();
3054
+ if (cspNonce) {
3055
+ element.nonce = cspNonce;
3038
3056
  }
3039
3057
  return element
3040
3058
  }
@@ -3044,10 +3062,6 @@ Copyright © 2024 37signals LLC
3044
3062
  element.className = "turbo-progress-bar";
3045
3063
  return element
3046
3064
  }
3047
-
3048
- get cspNonce() {
3049
- return getMetaContent("csp-nonce")
3050
- }
3051
3065
  }
3052
3066
 
3053
3067
  class HeadSnapshot extends Snapshot {
@@ -5038,7 +5052,7 @@ Copyright © 2024 37signals LLC
5038
5052
  const shouldMorphPage = this.isPageRefresh(visit) && this.snapshot.shouldMorphPage;
5039
5053
  const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;
5040
5054
 
5041
- const renderer = new rendererClass(this.snapshot, snapshot, rendererClass.renderElement, isPreview, willRender);
5055
+ const renderer = new rendererClass(this.snapshot, snapshot, isPreview, willRender);
5042
5056
 
5043
5057
  if (!renderer.shouldRender) {
5044
5058
  this.forceReloaded = true;
@@ -5051,7 +5065,7 @@ Copyright © 2024 37signals LLC
5051
5065
 
5052
5066
  renderError(snapshot, visit) {
5053
5067
  visit?.changeHistory();
5054
- const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
5068
+ const renderer = new ErrorRenderer(this.snapshot, snapshot, false);
5055
5069
  return this.render(renderer)
5056
5070
  }
5057
5071
 
@@ -5822,6 +5836,7 @@ Copyright © 2024 37signals LLC
5822
5836
  #connected = false
5823
5837
  #hasBeenLoaded = false
5824
5838
  #ignoredAttributes = new Set()
5839
+ #shouldMorphFrame = false
5825
5840
  action = null
5826
5841
 
5827
5842
  constructor(element) {
@@ -5879,13 +5894,10 @@ Copyright © 2024 37signals LLC
5879
5894
  }
5880
5895
 
5881
5896
  sourceURLReloaded() {
5882
- if (this.element.shouldReloadWithMorph) {
5883
- this.element.addEventListener("turbo:before-frame-render", ({ detail }) => {
5884
- detail.render = MorphingFrameRenderer.renderElement;
5885
- }, { once: true });
5886
- }
5897
+ const { refresh, src } = this.element;
5898
+
5899
+ this.#shouldMorphFrame = src && refresh === "morph";
5887
5900
 
5888
- const { src } = this.element;
5889
5901
  this.element.removeAttribute("complete");
5890
5902
  this.element.src = null;
5891
5903
  this.element.src = src;
@@ -5928,6 +5940,7 @@ Copyright © 2024 37signals LLC
5928
5940
  }
5929
5941
  }
5930
5942
  } finally {
5943
+ this.#shouldMorphFrame = false;
5931
5944
  this.fetchResponseLoaded = () => Promise.resolve();
5932
5945
  }
5933
5946
  }
@@ -6093,11 +6106,11 @@ Copyright © 2024 37signals LLC
6093
6106
 
6094
6107
  async #loadFrameResponse(fetchResponse, document) {
6095
6108
  const newFrameElement = await this.extractForeignFrameElement(document.body);
6109
+ const rendererClass = this.#shouldMorphFrame ? MorphingFrameRenderer : FrameRenderer;
6096
6110
 
6097
6111
  if (newFrameElement) {
6098
6112
  const snapshot = new Snapshot(newFrameElement);
6099
- const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
6100
-
6113
+ const renderer = new rendererClass(this, this.view.snapshot, snapshot, false, false);
6101
6114
  if (this.view.renderPromise) await this.view.renderPromise;
6102
6115
  this.changeHistory();
6103
6116
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotwired/turbo",
3
- "version": "8.0.6",
3
+ "version": "8.0.11",
4
4
  "description": "The speed of a single-page web application without having to write any JavaScript",
5
5
  "module": "dist/turbo.es2017-esm.js",
6
6
  "main": "dist/turbo.es2017-umd.js",