@hotwired/turbo-rails 8.0.20 → 8.0.21
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/app/assets/javascripts/turbo.js +209 -253
- package/package.json +2 -2
|
@@ -1,68 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
Turbo 8.0.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Turbo 8.0.21
|
|
3
|
+
Copyright © 2026 37signals LLC
|
|
4
4
|
*/
|
|
5
|
-
(function(prototype) {
|
|
6
|
-
if (typeof prototype.requestSubmit == "function") return;
|
|
7
|
-
prototype.requestSubmit = function(submitter) {
|
|
8
|
-
if (submitter) {
|
|
9
|
-
validateSubmitter(submitter, this);
|
|
10
|
-
submitter.click();
|
|
11
|
-
} else {
|
|
12
|
-
submitter = document.createElement("input");
|
|
13
|
-
submitter.type = "submit";
|
|
14
|
-
submitter.hidden = true;
|
|
15
|
-
this.appendChild(submitter);
|
|
16
|
-
submitter.click();
|
|
17
|
-
this.removeChild(submitter);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
function validateSubmitter(submitter, form) {
|
|
21
|
-
submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
|
|
22
|
-
submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button");
|
|
23
|
-
submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
|
|
24
|
-
}
|
|
25
|
-
function raise(errorConstructor, message, name) {
|
|
26
|
-
throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name);
|
|
27
|
-
}
|
|
28
|
-
})(HTMLFormElement.prototype);
|
|
29
|
-
|
|
30
|
-
const submittersByForm = new WeakMap;
|
|
31
|
-
|
|
32
|
-
function findSubmitterFromClickTarget(target) {
|
|
33
|
-
const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
34
|
-
const candidate = element ? element.closest("input, button") : null;
|
|
35
|
-
return candidate?.type == "submit" ? candidate : null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function clickCaptured(event) {
|
|
39
|
-
const submitter = findSubmitterFromClickTarget(event.target);
|
|
40
|
-
if (submitter && submitter.form) {
|
|
41
|
-
submittersByForm.set(submitter.form, submitter);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
(function() {
|
|
46
|
-
if ("submitter" in Event.prototype) return;
|
|
47
|
-
let prototype = window.Event.prototype;
|
|
48
|
-
if ("SubmitEvent" in window) {
|
|
49
|
-
const prototypeOfSubmitEvent = window.SubmitEvent.prototype;
|
|
50
|
-
if (/Apple Computer/.test(navigator.vendor) && !("submitter" in prototypeOfSubmitEvent)) {
|
|
51
|
-
prototype = prototypeOfSubmitEvent;
|
|
52
|
-
} else {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
addEventListener("click", clickCaptured, true);
|
|
57
|
-
Object.defineProperty(prototype, "submitter", {
|
|
58
|
-
get() {
|
|
59
|
-
if (this.type == "submit" && this.target instanceof HTMLFormElement) {
|
|
60
|
-
return submittersByForm.get(this.target);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
})();
|
|
65
|
-
|
|
66
5
|
const FrameLoadingStyle = {
|
|
67
6
|
eager: "eager",
|
|
68
7
|
lazy: "lazy"
|
|
@@ -240,10 +179,6 @@ function nextEventLoopTick() {
|
|
|
240
179
|
return new Promise((resolve => setTimeout((() => resolve()), 0)));
|
|
241
180
|
}
|
|
242
181
|
|
|
243
|
-
function nextMicrotask() {
|
|
244
|
-
return Promise.resolve();
|
|
245
|
-
}
|
|
246
|
-
|
|
247
182
|
function parseHTMLDocument(html = "") {
|
|
248
183
|
return (new DOMParser).parseFromString(html, "text/html");
|
|
249
184
|
}
|
|
@@ -273,7 +208,7 @@ function uuid() {
|
|
|
273
208
|
} else if (i == 19) {
|
|
274
209
|
return (Math.floor(Math.random() * 4) + 8).toString(16);
|
|
275
210
|
} else {
|
|
276
|
-
return Math.floor(Math.random() *
|
|
211
|
+
return Math.floor(Math.random() * 16).toString(16);
|
|
277
212
|
}
|
|
278
213
|
})).join("");
|
|
279
214
|
}
|
|
@@ -411,15 +346,13 @@ function doesNotTargetIFrame(name) {
|
|
|
411
346
|
function findLinkFromClickTarget(target) {
|
|
412
347
|
const link = findClosestRecursively(target, "a[href], a[xlink\\:href]");
|
|
413
348
|
if (!link) return null;
|
|
349
|
+
if (link.href.startsWith("#")) return null;
|
|
414
350
|
if (link.hasAttribute("download")) return null;
|
|
415
|
-
|
|
351
|
+
const linkTarget = link.getAttribute("target");
|
|
352
|
+
if (linkTarget && linkTarget !== "_self") return null;
|
|
416
353
|
return link;
|
|
417
354
|
}
|
|
418
355
|
|
|
419
|
-
function getLocationForLink(link) {
|
|
420
|
-
return expandURL(link.getAttribute("href") || "");
|
|
421
|
-
}
|
|
422
|
-
|
|
423
356
|
function debounce(fn, delay) {
|
|
424
357
|
let timeoutId = null;
|
|
425
358
|
return (...args) => {
|
|
@@ -500,6 +433,10 @@ function locationIsVisitable(location, rootLocation) {
|
|
|
500
433
|
return isPrefixedBy(location, rootLocation) && !config.drive.unvisitableExtensions.has(getExtension(location));
|
|
501
434
|
}
|
|
502
435
|
|
|
436
|
+
function getLocationForLink(link) {
|
|
437
|
+
return expandURL(link.getAttribute("href") || "");
|
|
438
|
+
}
|
|
439
|
+
|
|
503
440
|
function getRequestURL(url) {
|
|
504
441
|
const anchor = getAnchor(url);
|
|
505
442
|
return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href;
|
|
@@ -871,34 +808,94 @@ function importStreamElements(fragment) {
|
|
|
871
808
|
return fragment;
|
|
872
809
|
}
|
|
873
810
|
|
|
811
|
+
const identity = key => key;
|
|
812
|
+
|
|
813
|
+
class LRUCache {
|
|
814
|
+
keys=[];
|
|
815
|
+
entries={};
|
|
816
|
+
#toCacheKey;
|
|
817
|
+
constructor(size, toCacheKey = identity) {
|
|
818
|
+
this.size = size;
|
|
819
|
+
this.#toCacheKey = toCacheKey;
|
|
820
|
+
}
|
|
821
|
+
has(key) {
|
|
822
|
+
return this.#toCacheKey(key) in this.entries;
|
|
823
|
+
}
|
|
824
|
+
get(key) {
|
|
825
|
+
if (this.has(key)) {
|
|
826
|
+
const entry = this.read(key);
|
|
827
|
+
this.touch(key);
|
|
828
|
+
return entry;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
put(key, entry) {
|
|
832
|
+
this.write(key, entry);
|
|
833
|
+
this.touch(key);
|
|
834
|
+
return entry;
|
|
835
|
+
}
|
|
836
|
+
clear() {
|
|
837
|
+
for (const key of Object.keys(this.entries)) {
|
|
838
|
+
this.evict(key);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
read(key) {
|
|
842
|
+
return this.entries[this.#toCacheKey(key)];
|
|
843
|
+
}
|
|
844
|
+
write(key, entry) {
|
|
845
|
+
this.entries[this.#toCacheKey(key)] = entry;
|
|
846
|
+
}
|
|
847
|
+
touch(key) {
|
|
848
|
+
key = this.#toCacheKey(key);
|
|
849
|
+
const index = this.keys.indexOf(key);
|
|
850
|
+
if (index > -1) this.keys.splice(index, 1);
|
|
851
|
+
this.keys.unshift(key);
|
|
852
|
+
this.trim();
|
|
853
|
+
}
|
|
854
|
+
trim() {
|
|
855
|
+
for (const key of this.keys.splice(this.size)) {
|
|
856
|
+
this.evict(key);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
evict(key) {
|
|
860
|
+
delete this.entries[key];
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
874
864
|
const PREFETCH_DELAY = 100;
|
|
875
865
|
|
|
876
|
-
class PrefetchCache {
|
|
866
|
+
class PrefetchCache extends LRUCache {
|
|
877
867
|
#prefetchTimeout=null;
|
|
878
|
-
#
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
}
|
|
868
|
+
#maxAges={};
|
|
869
|
+
constructor(size = 1, prefetchDelay = PREFETCH_DELAY) {
|
|
870
|
+
super(size, toCacheKey);
|
|
871
|
+
this.prefetchDelay = prefetchDelay;
|
|
883
872
|
}
|
|
884
|
-
|
|
885
|
-
this.clear();
|
|
873
|
+
putLater(url, request, ttl) {
|
|
886
874
|
this.#prefetchTimeout = setTimeout((() => {
|
|
887
875
|
request.perform();
|
|
888
|
-
this.
|
|
876
|
+
this.put(url, request, ttl);
|
|
889
877
|
this.#prefetchTimeout = null;
|
|
890
|
-
}),
|
|
878
|
+
}), this.prefetchDelay);
|
|
891
879
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
request: request,
|
|
896
|
-
expire: new Date((new Date).getTime() + ttl)
|
|
897
|
-
};
|
|
880
|
+
put(url, request, ttl = cacheTtl) {
|
|
881
|
+
super.put(url, request);
|
|
882
|
+
this.#maxAges[toCacheKey(url)] = new Date((new Date).getTime() + ttl);
|
|
898
883
|
}
|
|
899
884
|
clear() {
|
|
885
|
+
super.clear();
|
|
900
886
|
if (this.#prefetchTimeout) clearTimeout(this.#prefetchTimeout);
|
|
901
|
-
|
|
887
|
+
}
|
|
888
|
+
evict(key) {
|
|
889
|
+
super.evict(key);
|
|
890
|
+
delete this.#maxAges[key];
|
|
891
|
+
}
|
|
892
|
+
has(key) {
|
|
893
|
+
if (super.has(key)) {
|
|
894
|
+
const maxAge = this.#maxAges[toCacheKey(key)];
|
|
895
|
+
return maxAge && maxAge > Date.now();
|
|
896
|
+
} else {
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
902
899
|
}
|
|
903
900
|
}
|
|
904
901
|
|
|
@@ -2629,11 +2626,17 @@ class PageSnapshot extends Snapshot {
|
|
|
2629
2626
|
for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
|
|
2630
2627
|
clonedPasswordInput.value = "";
|
|
2631
2628
|
}
|
|
2629
|
+
for (const clonedNoscriptElement of clonedElement.querySelectorAll("noscript")) {
|
|
2630
|
+
clonedNoscriptElement.remove();
|
|
2631
|
+
}
|
|
2632
2632
|
return new PageSnapshot(this.documentElement, clonedElement, this.headSnapshot);
|
|
2633
2633
|
}
|
|
2634
2634
|
get lang() {
|
|
2635
2635
|
return this.documentElement.getAttribute("lang");
|
|
2636
2636
|
}
|
|
2637
|
+
get dir() {
|
|
2638
|
+
return this.documentElement.getAttribute("dir");
|
|
2639
|
+
}
|
|
2637
2640
|
get headElement() {
|
|
2638
2641
|
return this.headSnapshot.element;
|
|
2639
2642
|
}
|
|
@@ -2657,11 +2660,11 @@ class PageSnapshot extends Snapshot {
|
|
|
2657
2660
|
const viewTransitionEnabled = this.getSetting("view-transition") === "true" || this.headSnapshot.getMetaValue("view-transition") === "same-origin";
|
|
2658
2661
|
return viewTransitionEnabled && !window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2659
2662
|
}
|
|
2660
|
-
get
|
|
2661
|
-
return this.getSetting("refresh-method")
|
|
2663
|
+
get refreshMethod() {
|
|
2664
|
+
return this.getSetting("refresh-method");
|
|
2662
2665
|
}
|
|
2663
|
-
get
|
|
2664
|
-
return this.getSetting("refresh-scroll")
|
|
2666
|
+
get refreshScroll() {
|
|
2667
|
+
return this.getSetting("refresh-scroll");
|
|
2665
2668
|
}
|
|
2666
2669
|
getSetting(name) {
|
|
2667
2670
|
return this.headSnapshot.getMetaValue(`turbo-${name}`);
|
|
@@ -2694,7 +2697,8 @@ const defaultOptions = {
|
|
|
2694
2697
|
willRender: true,
|
|
2695
2698
|
updateHistory: true,
|
|
2696
2699
|
shouldCacheSnapshot: true,
|
|
2697
|
-
acceptsStreamResponse: false
|
|
2700
|
+
acceptsStreamResponse: false,
|
|
2701
|
+
refresh: {}
|
|
2698
2702
|
};
|
|
2699
2703
|
|
|
2700
2704
|
const TimingMetric = {
|
|
@@ -2739,7 +2743,7 @@ class Visit {
|
|
|
2739
2743
|
this.delegate = delegate;
|
|
2740
2744
|
this.location = location;
|
|
2741
2745
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
|
2742
|
-
const {action: action, historyChanged: historyChanged, referrer: referrer, snapshot: snapshot, snapshotHTML: snapshotHTML, response: response, visitCachedSnapshot: visitCachedSnapshot, willRender: willRender, updateHistory: updateHistory, shouldCacheSnapshot: shouldCacheSnapshot, acceptsStreamResponse: acceptsStreamResponse, direction: direction} = {
|
|
2746
|
+
const {action: action, historyChanged: historyChanged, referrer: referrer, snapshot: snapshot, snapshotHTML: snapshotHTML, response: response, visitCachedSnapshot: visitCachedSnapshot, willRender: willRender, updateHistory: updateHistory, shouldCacheSnapshot: shouldCacheSnapshot, acceptsStreamResponse: acceptsStreamResponse, direction: direction, refresh: refresh} = {
|
|
2743
2747
|
...defaultOptions,
|
|
2744
2748
|
...options
|
|
2745
2749
|
};
|
|
@@ -2749,7 +2753,6 @@ class Visit {
|
|
|
2749
2753
|
this.snapshot = snapshot;
|
|
2750
2754
|
this.snapshotHTML = snapshotHTML;
|
|
2751
2755
|
this.response = response;
|
|
2752
|
-
this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
|
|
2753
2756
|
this.isPageRefresh = this.view.isPageRefresh(this);
|
|
2754
2757
|
this.visitCachedSnapshot = visitCachedSnapshot;
|
|
2755
2758
|
this.willRender = willRender;
|
|
@@ -2758,6 +2761,7 @@ class Visit {
|
|
|
2758
2761
|
this.shouldCacheSnapshot = shouldCacheSnapshot;
|
|
2759
2762
|
this.acceptsStreamResponse = acceptsStreamResponse;
|
|
2760
2763
|
this.direction = direction || Direction[action];
|
|
2764
|
+
this.refresh = refresh;
|
|
2761
2765
|
}
|
|
2762
2766
|
get adapter() {
|
|
2763
2767
|
return this.delegate.adapter;
|
|
@@ -2771,9 +2775,6 @@ class Visit {
|
|
|
2771
2775
|
get restorationData() {
|
|
2772
2776
|
return this.history.getRestorationDataForIdentifier(this.restorationIdentifier);
|
|
2773
2777
|
}
|
|
2774
|
-
get silent() {
|
|
2775
|
-
return this.isSamePage;
|
|
2776
|
-
}
|
|
2777
2778
|
start() {
|
|
2778
2779
|
if (this.state == VisitState.initialized) {
|
|
2779
2780
|
this.recordTimingMetric(TimingMetric.visitStart);
|
|
@@ -2892,7 +2893,7 @@ class Visit {
|
|
|
2892
2893
|
const isPreview = this.shouldIssueRequest();
|
|
2893
2894
|
this.render((async () => {
|
|
2894
2895
|
this.cacheSnapshot();
|
|
2895
|
-
if (this.
|
|
2896
|
+
if (this.isPageRefresh) {
|
|
2896
2897
|
this.adapter.visitRendered(this);
|
|
2897
2898
|
} else {
|
|
2898
2899
|
if (this.view.renderPromise) await this.view.renderPromise;
|
|
@@ -2916,16 +2917,6 @@ class Visit {
|
|
|
2916
2917
|
this.followedRedirect = true;
|
|
2917
2918
|
}
|
|
2918
2919
|
}
|
|
2919
|
-
goToSamePageAnchor() {
|
|
2920
|
-
if (this.isSamePage) {
|
|
2921
|
-
this.render((async () => {
|
|
2922
|
-
this.cacheSnapshot();
|
|
2923
|
-
this.performScroll();
|
|
2924
|
-
this.changeHistory();
|
|
2925
|
-
this.adapter.visitRendered(this);
|
|
2926
|
-
}));
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
2929
2920
|
prepareRequest(request) {
|
|
2930
2921
|
if (this.acceptsStreamResponse) {
|
|
2931
2922
|
request.acceptResponseType(StreamMessage.contentType);
|
|
@@ -2984,9 +2975,6 @@ class Visit {
|
|
|
2984
2975
|
} else {
|
|
2985
2976
|
this.scrollToAnchor() || this.view.scrollToTop();
|
|
2986
2977
|
}
|
|
2987
|
-
if (this.isSamePage) {
|
|
2988
|
-
this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location);
|
|
2989
|
-
}
|
|
2990
2978
|
this.scrolled = true;
|
|
2991
2979
|
}
|
|
2992
2980
|
}
|
|
@@ -3016,9 +3004,7 @@ class Visit {
|
|
|
3016
3004
|
return typeof this.response == "object";
|
|
3017
3005
|
}
|
|
3018
3006
|
shouldIssueRequest() {
|
|
3019
|
-
if (this.
|
|
3020
|
-
return false;
|
|
3021
|
-
} else if (this.action == "restore") {
|
|
3007
|
+
if (this.action == "restore") {
|
|
3022
3008
|
return !this.hasCachedSnapshot();
|
|
3023
3009
|
} else {
|
|
3024
3010
|
return this.willRender;
|
|
@@ -3073,7 +3059,6 @@ class BrowserAdapter {
|
|
|
3073
3059
|
this.redirectedToLocation = null;
|
|
3074
3060
|
visit.loadCachedSnapshot();
|
|
3075
3061
|
visit.issueRequest();
|
|
3076
|
-
visit.goToSamePageAnchor();
|
|
3077
3062
|
}
|
|
3078
3063
|
visitRequestStarted(visit) {
|
|
3079
3064
|
this.progressBar.setValue(0);
|
|
@@ -3167,7 +3152,6 @@ class BrowserAdapter {
|
|
|
3167
3152
|
|
|
3168
3153
|
class CacheObserver {
|
|
3169
3154
|
selector="[data-turbo-temporary]";
|
|
3170
|
-
deprecatedSelector="[data-turbo-cache=false]";
|
|
3171
3155
|
started=false;
|
|
3172
3156
|
start() {
|
|
3173
3157
|
if (!this.started) {
|
|
@@ -3187,14 +3171,7 @@ class CacheObserver {
|
|
|
3187
3171
|
}
|
|
3188
3172
|
};
|
|
3189
3173
|
get temporaryElements() {
|
|
3190
|
-
return [ ...document.querySelectorAll(this.selector)
|
|
3191
|
-
}
|
|
3192
|
-
get temporaryElementsWithDeprecation() {
|
|
3193
|
-
const elements = document.querySelectorAll(this.deprecatedSelector);
|
|
3194
|
-
if (elements.length) {
|
|
3195
|
-
console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`);
|
|
3196
|
-
}
|
|
3197
|
-
return [ ...elements ];
|
|
3174
|
+
return [ ...document.querySelectorAll(this.selector) ];
|
|
3198
3175
|
}
|
|
3199
3176
|
}
|
|
3200
3177
|
|
|
@@ -3262,7 +3239,6 @@ class History {
|
|
|
3262
3239
|
restorationIdentifier=uuid();
|
|
3263
3240
|
restorationData={};
|
|
3264
3241
|
started=false;
|
|
3265
|
-
pageLoaded=false;
|
|
3266
3242
|
currentIndex=0;
|
|
3267
3243
|
constructor(delegate) {
|
|
3268
3244
|
this.delegate = delegate;
|
|
@@ -3270,7 +3246,6 @@ class History {
|
|
|
3270
3246
|
start() {
|
|
3271
3247
|
if (!this.started) {
|
|
3272
3248
|
addEventListener("popstate", this.onPopState, false);
|
|
3273
|
-
addEventListener("load", this.onPageLoad, false);
|
|
3274
3249
|
this.currentIndex = history.state?.turbo?.restorationIndex || 0;
|
|
3275
3250
|
this.started = true;
|
|
3276
3251
|
this.replace(new URL(window.location.href));
|
|
@@ -3279,7 +3254,6 @@ class History {
|
|
|
3279
3254
|
stop() {
|
|
3280
3255
|
if (this.started) {
|
|
3281
3256
|
removeEventListener("popstate", this.onPopState, false);
|
|
3282
|
-
removeEventListener("load", this.onPageLoad, false);
|
|
3283
3257
|
this.started = false;
|
|
3284
3258
|
}
|
|
3285
3259
|
}
|
|
@@ -3325,28 +3299,19 @@ class History {
|
|
|
3325
3299
|
}
|
|
3326
3300
|
}
|
|
3327
3301
|
onPopState=event => {
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3302
|
+
const {turbo: turbo} = event.state || {};
|
|
3303
|
+
this.location = new URL(window.location.href);
|
|
3304
|
+
if (turbo) {
|
|
3305
|
+
const {restorationIdentifier: restorationIdentifier, restorationIndex: restorationIndex} = turbo;
|
|
3306
|
+
this.restorationIdentifier = restorationIdentifier;
|
|
3307
|
+
const direction = restorationIndex > this.currentIndex ? "forward" : "back";
|
|
3308
|
+
this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction);
|
|
3309
|
+
this.currentIndex = restorationIndex;
|
|
3310
|
+
} else {
|
|
3311
|
+
this.currentIndex++;
|
|
3312
|
+
this.delegate.historyPoppedWithEmptyState(this.location);
|
|
3338
3313
|
}
|
|
3339
3314
|
};
|
|
3340
|
-
onPageLoad=async _event => {
|
|
3341
|
-
await nextMicrotask();
|
|
3342
|
-
this.pageLoaded = true;
|
|
3343
|
-
};
|
|
3344
|
-
shouldHandlePopState() {
|
|
3345
|
-
return this.pageIsLoaded();
|
|
3346
|
-
}
|
|
3347
|
-
pageIsLoaded() {
|
|
3348
|
-
return this.pageLoaded || document.readyState == "complete";
|
|
3349
|
-
}
|
|
3350
3315
|
}
|
|
3351
3316
|
|
|
3352
3317
|
class LinkPrefetchObserver {
|
|
@@ -3402,7 +3367,7 @@ class LinkPrefetchObserver {
|
|
|
3402
3367
|
this.#prefetchedLink = link;
|
|
3403
3368
|
const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams, target);
|
|
3404
3369
|
fetchRequest.fetchOptions.priority = "low";
|
|
3405
|
-
prefetchCache.
|
|
3370
|
+
prefetchCache.putLater(location, fetchRequest, this.#cacheTtl);
|
|
3406
3371
|
}
|
|
3407
3372
|
}
|
|
3408
3373
|
};
|
|
@@ -3415,7 +3380,7 @@ class LinkPrefetchObserver {
|
|
|
3415
3380
|
};
|
|
3416
3381
|
#tryToUsePrefetchedRequest=event => {
|
|
3417
3382
|
if (event.target.tagName !== "FORM" && event.detail.fetchOptions.method === "GET") {
|
|
3418
|
-
const cached = prefetchCache.get(event.detail.url
|
|
3383
|
+
const cached = prefetchCache.get(event.detail.url);
|
|
3419
3384
|
if (cached) {
|
|
3420
3385
|
event.detail.fetchRequest = cached;
|
|
3421
3386
|
}
|
|
@@ -3564,7 +3529,7 @@ class Navigator {
|
|
|
3564
3529
|
} else {
|
|
3565
3530
|
await this.view.renderPage(snapshot, false, true, this.currentVisit);
|
|
3566
3531
|
}
|
|
3567
|
-
if (
|
|
3532
|
+
if (snapshot.refreshScroll !== "preserve") {
|
|
3568
3533
|
this.view.scrollToTop();
|
|
3569
3534
|
}
|
|
3570
3535
|
this.view.clearSnapshotCache();
|
|
@@ -3592,13 +3557,7 @@ class Navigator {
|
|
|
3592
3557
|
delete this.currentVisit;
|
|
3593
3558
|
}
|
|
3594
3559
|
locationWithActionIsSamePage(location, action) {
|
|
3595
|
-
|
|
3596
|
-
const currentAnchor = getAnchor(this.view.lastRenderedLocation);
|
|
3597
|
-
const isRestorationToTop = action === "restore" && typeof anchor === "undefined";
|
|
3598
|
-
return action !== "replace" && getRequestURL(location) === getRequestURL(this.view.lastRenderedLocation) && (isRestorationToTop || anchor != null && anchor !== currentAnchor);
|
|
3599
|
-
}
|
|
3600
|
-
visitScrolledToSamePageLocation(oldURL, newURL) {
|
|
3601
|
-
this.delegate.visitScrolledToSamePageLocation(oldURL, newURL);
|
|
3560
|
+
return false;
|
|
3602
3561
|
}
|
|
3603
3562
|
get location() {
|
|
3604
3563
|
return this.history.location;
|
|
@@ -3929,12 +3888,17 @@ class PageRenderer extends Renderer {
|
|
|
3929
3888
|
}
|
|
3930
3889
|
#setLanguage() {
|
|
3931
3890
|
const {documentElement: documentElement} = this.currentSnapshot;
|
|
3932
|
-
const {lang: lang} = this.newSnapshot;
|
|
3891
|
+
const {dir: dir, lang: lang} = this.newSnapshot;
|
|
3933
3892
|
if (lang) {
|
|
3934
3893
|
documentElement.setAttribute("lang", lang);
|
|
3935
3894
|
} else {
|
|
3936
3895
|
documentElement.removeAttribute("lang");
|
|
3937
3896
|
}
|
|
3897
|
+
if (dir) {
|
|
3898
|
+
documentElement.setAttribute("dir", dir);
|
|
3899
|
+
} else {
|
|
3900
|
+
documentElement.removeAttribute("dir");
|
|
3901
|
+
}
|
|
3938
3902
|
}
|
|
3939
3903
|
async mergeHead() {
|
|
3940
3904
|
const mergedHeadElements = this.mergeProvisionalElements();
|
|
@@ -4014,8 +3978,14 @@ class PageRenderer extends Renderer {
|
|
|
4014
3978
|
}
|
|
4015
3979
|
activateNewBody() {
|
|
4016
3980
|
document.adoptNode(this.newElement);
|
|
3981
|
+
this.removeNoscriptElements();
|
|
4017
3982
|
this.activateNewBodyScriptElements();
|
|
4018
3983
|
}
|
|
3984
|
+
removeNoscriptElements() {
|
|
3985
|
+
for (const noscriptElement of this.newElement.querySelectorAll("noscript")) {
|
|
3986
|
+
noscriptElement.remove();
|
|
3987
|
+
}
|
|
3988
|
+
}
|
|
4019
3989
|
activateNewBodyScriptElements() {
|
|
4020
3990
|
for (const inertScriptElement of this.newBodyScriptElements) {
|
|
4021
3991
|
const activatedScriptElement = activateScriptElement(inertScriptElement);
|
|
@@ -4079,47 +4049,12 @@ class MorphingPageRenderer extends PageRenderer {
|
|
|
4079
4049
|
}
|
|
4080
4050
|
}
|
|
4081
4051
|
|
|
4082
|
-
class SnapshotCache {
|
|
4083
|
-
keys=[];
|
|
4084
|
-
snapshots={};
|
|
4052
|
+
class SnapshotCache extends LRUCache {
|
|
4085
4053
|
constructor(size) {
|
|
4086
|
-
|
|
4087
|
-
}
|
|
4088
|
-
has(location) {
|
|
4089
|
-
return toCacheKey(location) in this.snapshots;
|
|
4090
|
-
}
|
|
4091
|
-
get(location) {
|
|
4092
|
-
if (this.has(location)) {
|
|
4093
|
-
const snapshot = this.read(location);
|
|
4094
|
-
this.touch(location);
|
|
4095
|
-
return snapshot;
|
|
4096
|
-
}
|
|
4097
|
-
}
|
|
4098
|
-
put(location, snapshot) {
|
|
4099
|
-
this.write(location, snapshot);
|
|
4100
|
-
this.touch(location);
|
|
4101
|
-
return snapshot;
|
|
4054
|
+
super(size, toCacheKey);
|
|
4102
4055
|
}
|
|
4103
|
-
|
|
4104
|
-
this.
|
|
4105
|
-
}
|
|
4106
|
-
read(location) {
|
|
4107
|
-
return this.snapshots[toCacheKey(location)];
|
|
4108
|
-
}
|
|
4109
|
-
write(location, snapshot) {
|
|
4110
|
-
this.snapshots[toCacheKey(location)] = snapshot;
|
|
4111
|
-
}
|
|
4112
|
-
touch(location) {
|
|
4113
|
-
const key = toCacheKey(location);
|
|
4114
|
-
const index = this.keys.indexOf(key);
|
|
4115
|
-
if (index > -1) this.keys.splice(index, 1);
|
|
4116
|
-
this.keys.unshift(key);
|
|
4117
|
-
this.trim();
|
|
4118
|
-
}
|
|
4119
|
-
trim() {
|
|
4120
|
-
for (const key of this.keys.splice(this.size)) {
|
|
4121
|
-
delete this.snapshots[key];
|
|
4122
|
-
}
|
|
4056
|
+
get snapshots() {
|
|
4057
|
+
return this.entries;
|
|
4123
4058
|
}
|
|
4124
4059
|
}
|
|
4125
4060
|
|
|
@@ -4131,7 +4066,7 @@ class PageView extends View {
|
|
|
4131
4066
|
return this.snapshot.prefersViewTransitions && newSnapshot.prefersViewTransitions;
|
|
4132
4067
|
}
|
|
4133
4068
|
renderPage(snapshot, isPreview = false, willRender = true, visit) {
|
|
4134
|
-
const shouldMorphPage = this.isPageRefresh(visit) && this.snapshot.
|
|
4069
|
+
const shouldMorphPage = this.isPageRefresh(visit) && (visit?.refresh?.method || this.snapshot.refreshMethod) === "morph";
|
|
4135
4070
|
const rendererClass = shouldMorphPage ? MorphingPageRenderer : PageRenderer;
|
|
4136
4071
|
const renderer = new rendererClass(this.snapshot, snapshot, isPreview, willRender);
|
|
4137
4072
|
if (!renderer.shouldRender) {
|
|
@@ -4166,7 +4101,7 @@ class PageView extends View {
|
|
|
4166
4101
|
return !visit || this.lastRenderedLocation.pathname === visit.location.pathname && visit.action === "replace";
|
|
4167
4102
|
}
|
|
4168
4103
|
shouldPreserveScrollPosition(visit) {
|
|
4169
|
-
return this.isPageRefresh(visit) && this.snapshot.
|
|
4104
|
+
return this.isPageRefresh(visit) && (visit?.refresh?.scroll || this.snapshot.refreshScroll) === "preserve";
|
|
4170
4105
|
}
|
|
4171
4106
|
get snapshot() {
|
|
4172
4107
|
return PageSnapshot.fromElement(this.element);
|
|
@@ -4319,13 +4254,21 @@ class Session {
|
|
|
4319
4254
|
this.navigator.proposeVisit(expandURL(location), options);
|
|
4320
4255
|
}
|
|
4321
4256
|
}
|
|
4322
|
-
refresh(url,
|
|
4257
|
+
refresh(url, options = {}) {
|
|
4258
|
+
options = typeof options === "string" ? {
|
|
4259
|
+
requestId: options
|
|
4260
|
+
} : options;
|
|
4261
|
+
const {method: method, requestId: requestId, scroll: scroll} = options;
|
|
4323
4262
|
const isRecentRequest = requestId && this.recentRequests.has(requestId);
|
|
4324
4263
|
const isCurrentUrl = url === document.baseURI;
|
|
4325
4264
|
if (!isRecentRequest && !this.navigator.currentVisit && isCurrentUrl) {
|
|
4326
4265
|
this.visit(url, {
|
|
4327
4266
|
action: "replace",
|
|
4328
|
-
shouldCacheSnapshot: false
|
|
4267
|
+
shouldCacheSnapshot: false,
|
|
4268
|
+
refresh: {
|
|
4269
|
+
method: method,
|
|
4270
|
+
scroll: scroll
|
|
4271
|
+
}
|
|
4329
4272
|
});
|
|
4330
4273
|
}
|
|
4331
4274
|
}
|
|
@@ -4401,6 +4344,11 @@ class Session {
|
|
|
4401
4344
|
});
|
|
4402
4345
|
}
|
|
4403
4346
|
}
|
|
4347
|
+
historyPoppedWithEmptyState(location) {
|
|
4348
|
+
this.history.replace(location);
|
|
4349
|
+
this.view.lastRenderedLocation = location;
|
|
4350
|
+
this.view.cacheSnapshot();
|
|
4351
|
+
}
|
|
4404
4352
|
scrollPositionChanged(position) {
|
|
4405
4353
|
this.history.updateRestorationData({
|
|
4406
4354
|
scrollPosition: position
|
|
@@ -4425,7 +4373,7 @@ class Session {
|
|
|
4425
4373
|
});
|
|
4426
4374
|
}
|
|
4427
4375
|
allowsVisitingLocationWithAction(location, action) {
|
|
4428
|
-
return this.
|
|
4376
|
+
return this.applicationAllowsVisitingLocation(location);
|
|
4429
4377
|
}
|
|
4430
4378
|
visitProposedToLocation(location, options) {
|
|
4431
4379
|
extendURLWithDeprecatedProperties(location);
|
|
@@ -4437,21 +4385,13 @@ class Session {
|
|
|
4437
4385
|
this.view.markVisitDirection(visit.direction);
|
|
4438
4386
|
}
|
|
4439
4387
|
extendURLWithDeprecatedProperties(visit.location);
|
|
4440
|
-
|
|
4441
|
-
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
|
|
4442
|
-
}
|
|
4388
|
+
this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
|
|
4443
4389
|
}
|
|
4444
4390
|
visitCompleted(visit) {
|
|
4445
4391
|
this.view.unmarkVisitDirection();
|
|
4446
4392
|
clearBusyState(document.documentElement);
|
|
4447
4393
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
|
4448
4394
|
}
|
|
4449
|
-
locationWithActionIsSamePage(location, action) {
|
|
4450
|
-
return this.navigator.locationWithActionIsSamePage(location, action);
|
|
4451
|
-
}
|
|
4452
|
-
visitScrolledToSamePageLocation(oldURL, newURL) {
|
|
4453
|
-
this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL);
|
|
4454
|
-
}
|
|
4455
4395
|
willSubmitForm(form, submitter) {
|
|
4456
4396
|
const action = getAction$1(form, submitter);
|
|
4457
4397
|
return this.submissionIsNavigatable(form, submitter) && locationIsVisitable(expandURL(action), this.snapshot.rootLocation);
|
|
@@ -4473,9 +4413,7 @@ class Session {
|
|
|
4473
4413
|
this.renderStreamMessage(message);
|
|
4474
4414
|
}
|
|
4475
4415
|
viewWillCacheSnapshot() {
|
|
4476
|
-
|
|
4477
|
-
this.notifyApplicationBeforeCachingSnapshot();
|
|
4478
|
-
}
|
|
4416
|
+
this.notifyApplicationBeforeCachingSnapshot();
|
|
4479
4417
|
}
|
|
4480
4418
|
allowsImmediateRender({element: element}, options) {
|
|
4481
4419
|
const event = this.notifyApplicationBeforeRender(element, options);
|
|
@@ -4562,12 +4500,6 @@ class Session {
|
|
|
4562
4500
|
}
|
|
4563
4501
|
});
|
|
4564
4502
|
}
|
|
4565
|
-
notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
|
|
4566
|
-
dispatchEvent(new HashChangeEvent("hashchange", {
|
|
4567
|
-
oldURL: oldURL.toString(),
|
|
4568
|
-
newURL: newURL.toString()
|
|
4569
|
-
}));
|
|
4570
|
-
}
|
|
4571
4503
|
notifyApplicationAfterFrameLoad(frame) {
|
|
4572
4504
|
return dispatch("turbo:frame-load", {
|
|
4573
4505
|
target: frame
|
|
@@ -4633,7 +4565,7 @@ const deprecatedLocationPropertyDescriptors = {
|
|
|
4633
4565
|
|
|
4634
4566
|
const session = new Session(recentRequests);
|
|
4635
4567
|
|
|
4636
|
-
const {cache: cache, navigator: navigator
|
|
4568
|
+
const {cache: cache, navigator: navigator} = session;
|
|
4637
4569
|
|
|
4638
4570
|
function start() {
|
|
4639
4571
|
session.start();
|
|
@@ -4659,11 +4591,6 @@ function renderStreamMessage(message) {
|
|
|
4659
4591
|
session.renderStreamMessage(message);
|
|
4660
4592
|
}
|
|
4661
4593
|
|
|
4662
|
-
function clearCache() {
|
|
4663
|
-
console.warn("Please replace `Turbo.clearCache()` with `Turbo.cache.clear()`. The top-level function is deprecated and will be removed in a future version of Turbo.`");
|
|
4664
|
-
session.clearCache();
|
|
4665
|
-
}
|
|
4666
|
-
|
|
4667
4594
|
function setProgressBarDelay(delay) {
|
|
4668
4595
|
console.warn("Please replace `Turbo.setProgressBarDelay(delay)` with `Turbo.config.drive.progressBarDelay = delay`. The top-level function is deprecated and will be removed in a future version of Turbo.`");
|
|
4669
4596
|
config.drive.progressBarDelay = delay;
|
|
@@ -4689,7 +4616,7 @@ function morphTurboFrameElements(currentFrame, newFrame) {
|
|
|
4689
4616
|
|
|
4690
4617
|
var Turbo = Object.freeze({
|
|
4691
4618
|
__proto__: null,
|
|
4692
|
-
navigator: navigator
|
|
4619
|
+
navigator: navigator,
|
|
4693
4620
|
session: session,
|
|
4694
4621
|
cache: cache,
|
|
4695
4622
|
PageRenderer: PageRenderer,
|
|
@@ -4703,7 +4630,6 @@ var Turbo = Object.freeze({
|
|
|
4703
4630
|
connectStreamSource: connectStreamSource,
|
|
4704
4631
|
disconnectStreamSource: disconnectStreamSource,
|
|
4705
4632
|
renderStreamMessage: renderStreamMessage,
|
|
4706
|
-
clearCache: clearCache,
|
|
4707
4633
|
setProgressBarDelay: setProgressBarDelay,
|
|
4708
4634
|
setConfirmMethod: setConfirmMethod,
|
|
4709
4635
|
setFormMode: setFormMode,
|
|
@@ -4753,15 +4679,23 @@ class FrameController {
|
|
|
4753
4679
|
this.formLinkClickObserver.stop();
|
|
4754
4680
|
this.linkInterceptor.stop();
|
|
4755
4681
|
this.formSubmitObserver.stop();
|
|
4682
|
+
if (!this.element.hasAttribute("recurse")) {
|
|
4683
|
+
this.#currentFetchRequest?.cancel();
|
|
4684
|
+
}
|
|
4756
4685
|
}
|
|
4757
4686
|
}
|
|
4758
4687
|
disabledChanged() {
|
|
4759
|
-
if (this.
|
|
4688
|
+
if (this.disabled) {
|
|
4689
|
+
this.#currentFetchRequest?.cancel();
|
|
4690
|
+
} else if (this.loadingStyle == FrameLoadingStyle.eager) {
|
|
4760
4691
|
this.#loadSourceURL();
|
|
4761
4692
|
}
|
|
4762
4693
|
}
|
|
4763
4694
|
sourceURLChanged() {
|
|
4764
4695
|
if (this.#isIgnoringChangesTo("src")) return;
|
|
4696
|
+
if (!this.sourceURL) {
|
|
4697
|
+
this.#currentFetchRequest?.cancel();
|
|
4698
|
+
}
|
|
4765
4699
|
if (this.element.isConnected) {
|
|
4766
4700
|
this.complete = false;
|
|
4767
4701
|
}
|
|
@@ -4839,11 +4773,12 @@ class FrameController {
|
|
|
4839
4773
|
}
|
|
4840
4774
|
this.formSubmission = new FormSubmission(this, element, submitter);
|
|
4841
4775
|
const {fetchRequest: fetchRequest} = this.formSubmission;
|
|
4842
|
-
this
|
|
4776
|
+
const frame = this.#findFrameElement(element, submitter);
|
|
4777
|
+
this.prepareRequest(fetchRequest, frame);
|
|
4843
4778
|
this.formSubmission.start();
|
|
4844
4779
|
}
|
|
4845
|
-
prepareRequest(request) {
|
|
4846
|
-
request.headers["Turbo-Frame"] =
|
|
4780
|
+
prepareRequest(request, frame = this) {
|
|
4781
|
+
request.headers["Turbo-Frame"] = frame.id;
|
|
4847
4782
|
if (this.currentNavigationElement?.hasAttribute("data-turbo-stream")) {
|
|
4848
4783
|
request.acceptResponseType(StreamMessage.contentType);
|
|
4849
4784
|
}
|
|
@@ -5037,7 +4972,8 @@ class FrameController {
|
|
|
5037
4972
|
}
|
|
5038
4973
|
#findFrameElement(element, submitter) {
|
|
5039
4974
|
const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
|
|
5040
|
-
|
|
4975
|
+
const target = this.#getFrameElementById(id);
|
|
4976
|
+
return target instanceof FrameElement ? target : this.element;
|
|
5041
4977
|
}
|
|
5042
4978
|
async extractForeignFrameElement(container) {
|
|
5043
4979
|
let element;
|
|
@@ -5071,9 +5007,11 @@ class FrameController {
|
|
|
5071
5007
|
return false;
|
|
5072
5008
|
}
|
|
5073
5009
|
if (id) {
|
|
5074
|
-
const frameElement = getFrameElementById(id);
|
|
5010
|
+
const frameElement = this.#getFrameElementById(id);
|
|
5075
5011
|
if (frameElement) {
|
|
5076
5012
|
return !frameElement.disabled;
|
|
5013
|
+
} else if (id == "_parent") {
|
|
5014
|
+
return false;
|
|
5077
5015
|
}
|
|
5078
5016
|
}
|
|
5079
5017
|
if (!session.elementIsNavigatable(element)) {
|
|
@@ -5087,8 +5025,11 @@ class FrameController {
|
|
|
5087
5025
|
get id() {
|
|
5088
5026
|
return this.element.id;
|
|
5089
5027
|
}
|
|
5028
|
+
get disabled() {
|
|
5029
|
+
return this.element.disabled;
|
|
5030
|
+
}
|
|
5090
5031
|
get enabled() {
|
|
5091
|
-
return !this.
|
|
5032
|
+
return !this.disabled;
|
|
5092
5033
|
}
|
|
5093
5034
|
get sourceURL() {
|
|
5094
5035
|
if (this.element.src) {
|
|
@@ -5137,13 +5078,12 @@ class FrameController {
|
|
|
5137
5078
|
callback();
|
|
5138
5079
|
delete this.currentNavigationElement;
|
|
5139
5080
|
}
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
return element;
|
|
5081
|
+
#getFrameElementById(id) {
|
|
5082
|
+
if (id != null) {
|
|
5083
|
+
const element = id === "_parent" ? this.element.parentElement.closest("turbo-frame") : document.getElementById(id);
|
|
5084
|
+
if (element instanceof FrameElement) {
|
|
5085
|
+
return element;
|
|
5086
|
+
}
|
|
5147
5087
|
}
|
|
5148
5088
|
}
|
|
5149
5089
|
}
|
|
@@ -5167,6 +5107,7 @@ function activateElement(element, currentURL) {
|
|
|
5167
5107
|
|
|
5168
5108
|
const StreamActions = {
|
|
5169
5109
|
after() {
|
|
5110
|
+
this.removeDuplicateTargetSiblings();
|
|
5170
5111
|
this.targetElements.forEach((e => e.parentElement?.insertBefore(this.templateContent, e.nextSibling)));
|
|
5171
5112
|
},
|
|
5172
5113
|
append() {
|
|
@@ -5174,6 +5115,7 @@ const StreamActions = {
|
|
|
5174
5115
|
this.targetElements.forEach((e => e.append(this.templateContent)));
|
|
5175
5116
|
},
|
|
5176
5117
|
before() {
|
|
5118
|
+
this.removeDuplicateTargetSiblings();
|
|
5177
5119
|
this.targetElements.forEach((e => e.parentElement?.insertBefore(this.templateContent, e)));
|
|
5178
5120
|
},
|
|
5179
5121
|
prepend() {
|
|
@@ -5205,7 +5147,14 @@ const StreamActions = {
|
|
|
5205
5147
|
}));
|
|
5206
5148
|
},
|
|
5207
5149
|
refresh() {
|
|
5208
|
-
|
|
5150
|
+
const method = this.getAttribute("method");
|
|
5151
|
+
const requestId = this.requestId;
|
|
5152
|
+
const scroll = this.getAttribute("scroll");
|
|
5153
|
+
session.refresh(this.baseURI, {
|
|
5154
|
+
method: method,
|
|
5155
|
+
requestId: requestId,
|
|
5156
|
+
scroll: scroll
|
|
5157
|
+
});
|
|
5209
5158
|
}
|
|
5210
5159
|
};
|
|
5211
5160
|
|
|
@@ -5244,6 +5193,14 @@ class StreamElement extends HTMLElement {
|
|
|
5244
5193
|
const newChildrenIds = [ ...this.templateContent?.children || [] ].filter((c => !!c.getAttribute("id"))).map((c => c.getAttribute("id")));
|
|
5245
5194
|
return existingChildren.filter((c => newChildrenIds.includes(c.getAttribute("id"))));
|
|
5246
5195
|
}
|
|
5196
|
+
removeDuplicateTargetSiblings() {
|
|
5197
|
+
this.duplicateSiblings.forEach((c => c.remove()));
|
|
5198
|
+
}
|
|
5199
|
+
get duplicateSiblings() {
|
|
5200
|
+
const existingChildren = this.targetElements.flatMap((e => [ ...e.parentElement.children ])).filter((c => !!c.id));
|
|
5201
|
+
const newChildrenIds = [ ...this.templateContent?.children || [] ].filter((c => !!c.id)).map((c => c.id));
|
|
5202
|
+
return existingChildren.filter((c => newChildrenIds.includes(c.id)));
|
|
5203
|
+
}
|
|
5247
5204
|
get performAction() {
|
|
5248
5205
|
if (this.action) {
|
|
5249
5206
|
const actionFunction = StreamActions[this.action];
|
|
@@ -5354,10 +5311,10 @@ if (customElements.get("turbo-stream-source") === undefined) {
|
|
|
5354
5311
|
}
|
|
5355
5312
|
|
|
5356
5313
|
(() => {
|
|
5357
|
-
|
|
5358
|
-
if (!
|
|
5359
|
-
if (
|
|
5360
|
-
element =
|
|
5314
|
+
const scriptElement = document.currentScript;
|
|
5315
|
+
if (!scriptElement) return;
|
|
5316
|
+
if (scriptElement.hasAttribute("data-turbo-suppress-warning")) return;
|
|
5317
|
+
let element = scriptElement.parentElement;
|
|
5361
5318
|
while (element) {
|
|
5362
5319
|
if (element == document.body) {
|
|
5363
5320
|
return console.warn(unindent`
|
|
@@ -5369,7 +5326,7 @@ if (customElements.get("turbo-stream-source") === undefined) {
|
|
|
5369
5326
|
|
|
5370
5327
|
——
|
|
5371
5328
|
Suppress this warning by adding a "data-turbo-suppress-warning" attribute to: %s
|
|
5372
|
-
`,
|
|
5329
|
+
`, scriptElement.outerHTML);
|
|
5373
5330
|
}
|
|
5374
5331
|
element = element.parentElement;
|
|
5375
5332
|
}
|
|
@@ -5397,7 +5354,6 @@ var Turbo$1 = Object.freeze({
|
|
|
5397
5354
|
StreamElement: StreamElement,
|
|
5398
5355
|
StreamSourceElement: StreamSourceElement,
|
|
5399
5356
|
cache: cache,
|
|
5400
|
-
clearCache: clearCache,
|
|
5401
5357
|
config: config,
|
|
5402
5358
|
connectStreamSource: connectStreamSource,
|
|
5403
5359
|
disconnectStreamSource: disconnectStreamSource,
|
|
@@ -5409,7 +5365,7 @@ var Turbo$1 = Object.freeze({
|
|
|
5409
5365
|
morphChildren: morphChildren,
|
|
5410
5366
|
morphElements: morphElements,
|
|
5411
5367
|
morphTurboFrameElements: morphTurboFrameElements,
|
|
5412
|
-
navigator: navigator
|
|
5368
|
+
navigator: navigator,
|
|
5413
5369
|
registerAdapter: registerAdapter,
|
|
5414
5370
|
renderStreamMessage: renderStreamMessage,
|
|
5415
5371
|
session: session,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotwired/turbo-rails",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.21",
|
|
4
4
|
"description": "The speed of a single-page web application without having to write any JavaScript",
|
|
5
5
|
"module": "app/javascript/turbo/index.js",
|
|
6
6
|
"main": "app/assets/javascripts/turbo.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"release": "yarn publish && git commit -am \"$npm_package_name v$npm_package_version\" && git push"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@hotwired/turbo": "^8.0.
|
|
22
|
+
"@hotwired/turbo": "^8.0.21",
|
|
23
23
|
"@rails/actioncable": ">=7.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|