Skip to content

Commit aeea473

Browse files
committed
@hotwired/turbo-rails v8.0.18
1 parent 00e6cba commit aeea473

File tree

5 files changed

+77
-39
lines changed

5 files changed

+77
-39
lines changed

app/assets/javascripts/turbo.js

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
Turbo 8.0.13
2+
Turbo 8.0.17
33
Copyright © 2025 37signals LLC
44
*/
55
(function(prototype) {
@@ -409,7 +409,11 @@ function doesNotTargetIFrame(name) {
409409
}
410410

411411
function findLinkFromClickTarget(target) {
412-
return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
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;
413417
}
414418

415419
function getLocationForLink(link) {
@@ -488,8 +492,8 @@ function getExtension(url) {
488492
}
489493

490494
function isPrefixedBy(baseURL, url) {
491-
const prefix = getPrefix(url);
492-
return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
495+
const prefix = addTrailingSlash(url.origin + url.pathname);
496+
return addTrailingSlash(baseURL.href) === prefix || baseURL.href.startsWith(prefix);
493497
}
494498

495499
function locationIsVisitable(location, rootLocation) {
@@ -517,10 +521,6 @@ function getLastPathComponent(url) {
517521
return getPathComponents(url).slice(-1)[0];
518522
}
519523

520-
function getPrefix(url) {
521-
return addTrailingSlash(url.origin + url.pathname);
522-
}
523-
524524
function addTrailingSlash(value) {
525525
return value.endsWith("/") ? value : value + "/";
526526
}
@@ -588,14 +588,12 @@ class LimitedSet extends Set {
588588

589589
const recentRequests = new LimitedSet(20);
590590

591-
const nativeFetch = window.fetch;
592-
593591
function fetchWithTurboHeaders(url, options = {}) {
594592
const modifiedHeaders = new Headers(options.headers || {});
595593
const requestUID = uuid();
596594
recentRequests.add(requestUID);
597595
modifiedHeaders.append("X-Turbo-Request-Id", requestUID);
598-
return nativeFetch(url, {
596+
return window.fetch(url, {
599597
...options,
600598
headers: modifiedHeaders
601599
});
@@ -1243,8 +1241,8 @@ class View {
12431241
scrollToAnchor(anchor) {
12441242
const element = this.snapshot.getElementForAnchor(anchor);
12451243
if (element) {
1246-
this.scrollToElement(element);
12471244
this.focusElement(element);
1245+
this.scrollToElement(element);
12481246
} else {
12491247
this.scrollToPosition({
12501248
x: 0,
@@ -2281,12 +2279,21 @@ function morphElements(currentElement, newElement, {callbacks: callbacks, ...opt
22812279
});
22822280
}
22832281

2284-
function morphChildren(currentElement, newElement) {
2282+
function morphChildren(currentElement, newElement, options = {}) {
22852283
morphElements(currentElement, newElement.childNodes, {
2284+
...options,
22862285
morphStyle: "innerHTML"
22872286
});
22882287
}
22892288

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+
22902297
class DefaultIdiomorphCallbacks {
22912298
#beforeNodeMorphed;
22922299
constructor({beforeNodeMorphed: beforeNodeMorphed} = {}) {
@@ -2344,7 +2351,17 @@ class MorphingFrameRenderer extends FrameRenderer {
23442351
newElement: newElement
23452352
}
23462353
});
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+
});
23482365
}
23492366
async preservingPermanentElements(callback) {
23502367
return await callback();
@@ -2596,7 +2613,8 @@ class PageSnapshot extends Snapshot {
25962613
return this.getSetting("visit-control") != "reload";
25972614
}
25982615
get prefersViewTransitions() {
2599-
return this.headSnapshot.getMetaValue("view-transition") === "same-origin";
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;
26002618
}
26012619
get shouldMorphPage() {
26022620
return this.getSetting("refresh-method") === "morph";
@@ -3011,6 +3029,7 @@ class BrowserAdapter {
30113029
}
30123030
visitStarted(visit) {
30133031
this.location = visit.location;
3032+
this.redirectedToLocation = null;
30143033
visit.loadCachedSnapshot();
30153034
visit.issueRequest();
30163035
visit.goToSamePageAnchor();
@@ -3025,6 +3044,9 @@ class BrowserAdapter {
30253044
}
30263045
visitRequestCompleted(visit) {
30273046
visit.loadResponse();
3047+
if (visit.response.redirected) {
3048+
this.redirectedToLocation = visit.redirectedToLocation;
3049+
}
30283050
}
30293051
visitRequestFailedWithStatusCode(visit, statusCode) {
30303052
switch (statusCode) {
@@ -3095,7 +3117,7 @@ class BrowserAdapter {
30953117
dispatch("turbo:reload", {
30963118
detail: reason
30973119
});
3098-
window.location.href = this.location?.toString() || window.location.href;
3120+
window.location.href = (this.redirectedToLocation || this.location)?.toString() || window.location.href;
30993121
}
31003122
get navigator() {
31013123
return this.session.navigator;
@@ -3338,6 +3360,7 @@ class LinkPrefetchObserver {
33383360
if (this.delegate.canPrefetchRequestToLocation(link, location)) {
33393361
this.#prefetchedLink = link;
33403362
const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams, target);
3363+
fetchRequest.fetchOptions.priority = "low";
33413364
prefetchCache.setLater(location.toString(), fetchRequest, this.#cacheTtl);
33423365
}
33433366
}
@@ -3988,12 +4011,15 @@ class MorphingPageRenderer extends PageRenderer {
39884011
static renderElement(currentElement, newElement) {
39894012
morphElements(currentElement, newElement, {
39904013
callbacks: {
3991-
beforeNodeMorphed: element => !canRefreshFrame(element)
4014+
beforeNodeMorphed: (node, newNode) => {
4015+
if (shouldRefreshFrameWithMorphing(node, newNode) && !closestFrameReloadableWithMorphing(node)) {
4016+
node.reload();
4017+
return false;
4018+
}
4019+
return true;
4020+
}
39924021
}
39934022
});
3994-
for (const frame of currentElement.querySelectorAll("turbo-frame")) {
3995-
if (canRefreshFrame(frame)) frame.reload();
3996-
}
39974023
dispatch("turbo:morph", {
39984024
detail: {
39994025
currentElement: currentElement,
@@ -4012,10 +4038,6 @@ class MorphingPageRenderer extends PageRenderer {
40124038
}
40134039
}
40144040

4015-
function canRefreshFrame(frame) {
4016-
return frame instanceof FrameElement && frame.src && frame.refresh === "morph" && !frame.closest("[data-turbo-permanent]");
4017-
}
4018-
40194041
class SnapshotCache {
40204042
keys=[];
40214043
snapshots={};
@@ -4616,6 +4638,14 @@ function setFormMode(mode) {
46164638
config.forms.mode = mode;
46174639
}
46184640

4641+
function morphBodyElements(currentBody, newBody) {
4642+
MorphingPageRenderer.renderElement(currentBody, newBody);
4643+
}
4644+
4645+
function morphTurboFrameElements(currentFrame, newFrame) {
4646+
MorphingFrameRenderer.renderElement(currentFrame, newFrame);
4647+
}
4648+
46194649
var Turbo = Object.freeze({
46204650
__proto__: null,
46214651
navigator: navigator$1,
@@ -4635,7 +4665,11 @@ var Turbo = Object.freeze({
46354665
clearCache: clearCache,
46364666
setProgressBarDelay: setProgressBarDelay,
46374667
setConfirmMethod: setConfirmMethod,
4638-
setFormMode: setFormMode
4668+
setFormMode: setFormMode,
4669+
morphBodyElements: morphBodyElements,
4670+
morphTurboFrameElements: morphTurboFrameElements,
4671+
morphChildren: morphChildren,
4672+
morphElements: morphElements
46394673
});
46404674

46414675
class TurboFrameMissingError extends Error {}
@@ -5330,6 +5364,10 @@ var Turbo$1 = Object.freeze({
53305364
fetchEnctypeFromString: fetchEnctypeFromString,
53315365
fetchMethodFromString: fetchMethodFromString,
53325366
isSafe: isSafe,
5367+
morphBodyElements: morphBodyElements,
5368+
morphChildren: morphChildren,
5369+
morphElements: morphElements,
5370+
morphTurboFrameElements: morphTurboFrameElements,
53335371
navigator: navigator$1,
53345372
registerAdapter: registerAdapter,
53355373
renderStreamMessage: renderStreamMessage,

app/assets/javascripts/turbo.min.js

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/assets/javascripts/turbo.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hotwired/turbo-rails",
3-
"version": "8.0.16",
3+
"version": "8.0.18",
44
"description": "The speed of a single-page web application without having to write any JavaScript",
55
"module": "app/javascript/turbo/index.js",
66
"main": "app/assets/javascripts/turbo.js",
@@ -16,10 +16,10 @@
1616
"scripts": {
1717
"build": "rollup -c",
1818
"prerelease": "yarn build && git --no-pager diff && echo && npm pack --dry-run && echo && read -n 1 -p \"Look OK? Press any key to publish and commit v$npm_package_version\" && echo",
19-
"release": "npm publish && git commit -am \"$npm_package_name v$npm_package_version\" && git push"
19+
"release": "yarn publish && git commit -am \"$npm_package_name v$npm_package_version\" && git push"
2020
},
2121
"dependencies": {
22-
"@hotwired/turbo": "^8.0.13",
22+
"@hotwired/turbo": "^8.0.18",
2323
"@rails/actioncable": ">=7.0"
2424
},
2525
"devDependencies": {

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
chalk "^2.4.2"
2525
js-tokens "^4.0.0"
2626

27-
"@hotwired/turbo@^8.0.13":
28-
version "8.0.13"
29-
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.13.tgz#ab35fda9d358432c8a872a833844b38cccb8c25b"
30-
integrity sha512-M7qXUqcGab6G5PKOiwhgbByTtrPgKPFCTMNQ52QhzUEXEqmp0/ApEguUesh/FPiUjrmFec+3lq98KsWnYY2C7g==
27+
"@hotwired/turbo@^8.0.18":
28+
version "8.0.18"
29+
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.18.tgz#10ae3de450b955862f89e30c50d96d676813744e"
30+
integrity sha512-dG0N7khQsP8sujclodQE3DYkI4Lq7uKA04fhT0DCC/DwMgn4T4WM3aji6EC6+iCfABQeJncY0SraXqVeOq0vvQ==
3131

3232
"@jridgewell/gen-mapping@^0.3.0":
3333
version "0.3.3"

0 commit comments

Comments
 (0)