turbo-rails 2.0.16 → 2.0.17
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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/turbo.js +63 -25
- data/app/assets/javascripts/turbo.min.js +6 -6
- data/app/assets/javascripts/turbo.min.js.map +1 -1
- data/app/models/concerns/turbo/broadcastable.rb +1 -1
- data/lib/turbo/version.rb +1 -1
- metadata +3 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5324994da4e834ec4efc08d381586e0deb95b1c49131601976f40711cf9cb7a5
|
4
|
+
data.tar.gz: d425c87cee99f1756786bc72b26a6a3151006f8409e35432ceb5795e0c054fdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 553197bfc4ebc3fa859d7678c7ea845625884e8859698a89c66ecf81e79559c4baa2c670f3a9401742cf2d01ad0965f4f729142c03cab579a5df971dfbc96f7b
|
7
|
+
data.tar.gz: ba86c285da8476f788d4dd6990dd7e632914dbdef83317799ae83839dc45d3465da477ced36f528d187208972d9f653cec533e1d42ed8eba6a130787823c07f9
|
data/README.md
CHANGED
@@ -206,7 +206,7 @@ Turbo can coexist with Rails UJS, but you need to take a series of upgrade steps
|
|
206
206
|
|
207
207
|
## Testing
|
208
208
|
|
209
|
-
The [`Turbo::TestAssertions`](./lib/turbo/test_assertions.rb) concern provides Turbo Stream test helpers that assert the presence or absence
|
209
|
+
The [`Turbo::TestAssertions`](./lib/turbo/test_assertions.rb) concern provides Turbo Stream test helpers that assert the presence or absence of `<turbo-stream>` elements in a rendered fragment of HTML. `Turbo::TestAssertions` are automatically included in [`ActiveSupport::TestCase`](https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html) and depend on the presence of [`rails-dom-testing`](https://github.com/rails/rails-dom-testing/) assertions.
|
210
210
|
|
211
211
|
The [`Turbo::TestAssertions::IntegrationTestAssertions`](./lib/turbo/test_assertions/integration_test_assertions.rb) are built on top of `Turbo::TestAssertions`, and add support for passing a `status:` keyword. They are automatically included in [`ActionDispatch::IntegrationTest`](https://edgeguides.rubyonrails.org/testing.html#integration-testing).
|
212
212
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
Turbo 8.0.
|
2
|
+
Turbo 8.0.17
|
3
3
|
Copyright © 2025 37signals LLC
|
4
4
|
*/
|
5
5
|
(function(prototype) {
|
@@ -409,7 +409,11 @@ function doesNotTargetIFrame(name) {
|
|
409
409
|
}
|
410
410
|
|
411
411
|
function findLinkFromClickTarget(target) {
|
412
|
-
|
412
|
+
const link = findClosestRecursively(target, "a[href], a[xlink\\:href]");
|
413
|
+
if (!link) return null;
|
414
|
+
if (link.hasAttribute("download")) return null;
|
415
|
+
if (link.hasAttribute("target") && link.target !== "_self") return null;
|
416
|
+
return link;
|
413
417
|
}
|
414
418
|
|
415
419
|
function getLocationForLink(link) {
|
@@ -488,8 +492,8 @@ function getExtension(url) {
|
|
488
492
|
}
|
489
493
|
|
490
494
|
function isPrefixedBy(baseURL, url) {
|
491
|
-
const prefix =
|
492
|
-
return baseURL.href ===
|
495
|
+
const prefix = addTrailingSlash(url.origin + url.pathname);
|
496
|
+
return addTrailingSlash(baseURL.href) === prefix || baseURL.href.startsWith(prefix);
|
493
497
|
}
|
494
498
|
|
495
499
|
function locationIsVisitable(location, rootLocation) {
|
@@ -517,10 +521,6 @@ function getLastPathComponent(url) {
|
|
517
521
|
return getPathComponents(url).slice(-1)[0];
|
518
522
|
}
|
519
523
|
|
520
|
-
function getPrefix(url) {
|
521
|
-
return addTrailingSlash(url.origin + url.pathname);
|
522
|
-
}
|
523
|
-
|
524
524
|
function addTrailingSlash(value) {
|
525
525
|
return value.endsWith("/") ? value : value + "/";
|
526
526
|
}
|
@@ -588,14 +588,12 @@ class LimitedSet extends Set {
|
|
588
588
|
|
589
589
|
const recentRequests = new LimitedSet(20);
|
590
590
|
|
591
|
-
const nativeFetch = window.fetch;
|
592
|
-
|
593
591
|
function fetchWithTurboHeaders(url, options = {}) {
|
594
592
|
const modifiedHeaders = new Headers(options.headers || {});
|
595
593
|
const requestUID = uuid();
|
596
594
|
recentRequests.add(requestUID);
|
597
595
|
modifiedHeaders.append("X-Turbo-Request-Id", requestUID);
|
598
|
-
return
|
596
|
+
return window.fetch(url, {
|
599
597
|
...options,
|
600
598
|
headers: modifiedHeaders
|
601
599
|
});
|
@@ -1243,8 +1241,8 @@ class View {
|
|
1243
1241
|
scrollToAnchor(anchor) {
|
1244
1242
|
const element = this.snapshot.getElementForAnchor(anchor);
|
1245
1243
|
if (element) {
|
1246
|
-
this.scrollToElement(element);
|
1247
1244
|
this.focusElement(element);
|
1245
|
+
this.scrollToElement(element);
|
1248
1246
|
} else {
|
1249
1247
|
this.scrollToPosition({
|
1250
1248
|
x: 0,
|
@@ -2281,12 +2279,21 @@ function morphElements(currentElement, newElement, {callbacks: callbacks, ...opt
|
|
2281
2279
|
});
|
2282
2280
|
}
|
2283
2281
|
|
2284
|
-
function morphChildren(currentElement, newElement) {
|
2282
|
+
function morphChildren(currentElement, newElement, options = {}) {
|
2285
2283
|
morphElements(currentElement, newElement.childNodes, {
|
2284
|
+
...options,
|
2286
2285
|
morphStyle: "innerHTML"
|
2287
2286
|
});
|
2288
2287
|
}
|
2289
2288
|
|
2289
|
+
function shouldRefreshFrameWithMorphing(currentFrame, newFrame) {
|
2290
|
+
return currentFrame instanceof FrameElement && newFrame instanceof Element && newFrame.nodeName === "TURBO-FRAME" && currentFrame.shouldReloadWithMorph && currentFrame.id === newFrame.id && (!newFrame.getAttribute("src") || urlsAreEqual(currentFrame.src, newFrame.getAttribute("src"))) && !currentFrame.closest("[data-turbo-permanent]");
|
2291
|
+
}
|
2292
|
+
|
2293
|
+
function closestFrameReloadableWithMorphing(node) {
|
2294
|
+
return node.parentElement.closest("turbo-frame[src][refresh=morph]");
|
2295
|
+
}
|
2296
|
+
|
2290
2297
|
class DefaultIdiomorphCallbacks {
|
2291
2298
|
#beforeNodeMorphed;
|
2292
2299
|
constructor({beforeNodeMorphed: beforeNodeMorphed} = {}) {
|
@@ -2344,7 +2351,17 @@ class MorphingFrameRenderer extends FrameRenderer {
|
|
2344
2351
|
newElement: newElement
|
2345
2352
|
}
|
2346
2353
|
});
|
2347
|
-
morphChildren(currentElement, newElement
|
2354
|
+
morphChildren(currentElement, newElement, {
|
2355
|
+
callbacks: {
|
2356
|
+
beforeNodeMorphed: (node, newNode) => {
|
2357
|
+
if (shouldRefreshFrameWithMorphing(node, newNode) && closestFrameReloadableWithMorphing(node) === currentElement) {
|
2358
|
+
node.reload();
|
2359
|
+
return false;
|
2360
|
+
}
|
2361
|
+
return true;
|
2362
|
+
}
|
2363
|
+
}
|
2364
|
+
});
|
2348
2365
|
}
|
2349
2366
|
async preservingPermanentElements(callback) {
|
2350
2367
|
return await callback();
|
@@ -2596,7 +2613,8 @@ class PageSnapshot extends Snapshot {
|
|
2596
2613
|
return this.getSetting("visit-control") != "reload";
|
2597
2614
|
}
|
2598
2615
|
get prefersViewTransitions() {
|
2599
|
-
|
2616
|
+
const viewTransitionEnabled = this.getSetting("view-transition") === "true" || this.headSnapshot.getMetaValue("view-transition") === "same-origin";
|
2617
|
+
return viewTransitionEnabled && !window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
2600
2618
|
}
|
2601
2619
|
get shouldMorphPage() {
|
2602
2620
|
return this.getSetting("refresh-method") === "morph";
|
@@ -3011,6 +3029,7 @@ class BrowserAdapter {
|
|
3011
3029
|
}
|
3012
3030
|
visitStarted(visit) {
|
3013
3031
|
this.location = visit.location;
|
3032
|
+
this.redirectedToLocation = null;
|
3014
3033
|
visit.loadCachedSnapshot();
|
3015
3034
|
visit.issueRequest();
|
3016
3035
|
visit.goToSamePageAnchor();
|
@@ -3025,6 +3044,9 @@ class BrowserAdapter {
|
|
3025
3044
|
}
|
3026
3045
|
visitRequestCompleted(visit) {
|
3027
3046
|
visit.loadResponse();
|
3047
|
+
if (visit.response.redirected) {
|
3048
|
+
this.redirectedToLocation = visit.redirectedToLocation;
|
3049
|
+
}
|
3028
3050
|
}
|
3029
3051
|
visitRequestFailedWithStatusCode(visit, statusCode) {
|
3030
3052
|
switch (statusCode) {
|
@@ -3095,7 +3117,7 @@ class BrowserAdapter {
|
|
3095
3117
|
dispatch("turbo:reload", {
|
3096
3118
|
detail: reason
|
3097
3119
|
});
|
3098
|
-
window.location.href = this.location?.toString() || window.location.href;
|
3120
|
+
window.location.href = (this.redirectedToLocation || this.location)?.toString() || window.location.href;
|
3099
3121
|
}
|
3100
3122
|
get navigator() {
|
3101
3123
|
return this.session.navigator;
|
@@ -3338,6 +3360,7 @@ class LinkPrefetchObserver {
|
|
3338
3360
|
if (this.delegate.canPrefetchRequestToLocation(link, location)) {
|
3339
3361
|
this.#prefetchedLink = link;
|
3340
3362
|
const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams, target);
|
3363
|
+
fetchRequest.fetchOptions.priority = "low";
|
3341
3364
|
prefetchCache.setLater(location.toString(), fetchRequest, this.#cacheTtl);
|
3342
3365
|
}
|
3343
3366
|
}
|
@@ -3988,12 +4011,15 @@ class MorphingPageRenderer extends PageRenderer {
|
|
3988
4011
|
static renderElement(currentElement, newElement) {
|
3989
4012
|
morphElements(currentElement, newElement, {
|
3990
4013
|
callbacks: {
|
3991
|
-
beforeNodeMorphed:
|
4014
|
+
beforeNodeMorphed: (node, newNode) => {
|
4015
|
+
if (shouldRefreshFrameWithMorphing(node, newNode) && !closestFrameReloadableWithMorphing(node)) {
|
4016
|
+
node.reload();
|
4017
|
+
return false;
|
4018
|
+
}
|
4019
|
+
return true;
|
4020
|
+
}
|
3992
4021
|
}
|
3993
4022
|
});
|
3994
|
-
for (const frame of currentElement.querySelectorAll("turbo-frame")) {
|
3995
|
-
if (canRefreshFrame(frame)) frame.reload();
|
3996
|
-
}
|
3997
4023
|
dispatch("turbo:morph", {
|
3998
4024
|
detail: {
|
3999
4025
|
currentElement: currentElement,
|
@@ -4012,10 +4038,6 @@ class MorphingPageRenderer extends PageRenderer {
|
|
4012
4038
|
}
|
4013
4039
|
}
|
4014
4040
|
|
4015
|
-
function canRefreshFrame(frame) {
|
4016
|
-
return frame instanceof FrameElement && frame.src && frame.refresh === "morph" && !frame.closest("[data-turbo-permanent]");
|
4017
|
-
}
|
4018
|
-
|
4019
4041
|
class SnapshotCache {
|
4020
4042
|
keys=[];
|
4021
4043
|
snapshots={};
|
@@ -4616,6 +4638,14 @@ function setFormMode(mode) {
|
|
4616
4638
|
config.forms.mode = mode;
|
4617
4639
|
}
|
4618
4640
|
|
4641
|
+
function morphBodyElements(currentBody, newBody) {
|
4642
|
+
MorphingPageRenderer.renderElement(currentBody, newBody);
|
4643
|
+
}
|
4644
|
+
|
4645
|
+
function morphTurboFrameElements(currentFrame, newFrame) {
|
4646
|
+
MorphingFrameRenderer.renderElement(currentFrame, newFrame);
|
4647
|
+
}
|
4648
|
+
|
4619
4649
|
var Turbo = Object.freeze({
|
4620
4650
|
__proto__: null,
|
4621
4651
|
navigator: navigator$1,
|
@@ -4635,7 +4665,11 @@ var Turbo = Object.freeze({
|
|
4635
4665
|
clearCache: clearCache,
|
4636
4666
|
setProgressBarDelay: setProgressBarDelay,
|
4637
4667
|
setConfirmMethod: setConfirmMethod,
|
4638
|
-
setFormMode: setFormMode
|
4668
|
+
setFormMode: setFormMode,
|
4669
|
+
morphBodyElements: morphBodyElements,
|
4670
|
+
morphTurboFrameElements: morphTurboFrameElements,
|
4671
|
+
morphChildren: morphChildren,
|
4672
|
+
morphElements: morphElements
|
4639
4673
|
});
|
4640
4674
|
|
4641
4675
|
class TurboFrameMissingError extends Error {}
|
@@ -5330,6 +5364,10 @@ var Turbo$1 = Object.freeze({
|
|
5330
5364
|
fetchEnctypeFromString: fetchEnctypeFromString,
|
5331
5365
|
fetchMethodFromString: fetchMethodFromString,
|
5332
5366
|
isSafe: isSafe,
|
5367
|
+
morphBodyElements: morphBodyElements,
|
5368
|
+
morphChildren: morphChildren,
|
5369
|
+
morphElements: morphElements,
|
5370
|
+
morphTurboFrameElements: morphTurboFrameElements,
|
5333
5371
|
navigator: navigator$1,
|
5334
5372
|
registerAdapter: registerAdapter,
|
5335
5373
|
renderStreamMessage: renderStreamMessage,
|