turbo-rails 2.0.0.pre.beta.1 → 2.0.0.pre.beta.2
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/app/assets/javascripts/turbo.js +119 -60
- data/app/assets/javascripts/turbo.min.js +6 -6
- data/app/assets/javascripts/turbo.min.js.map +1 -1
- data/app/javascript/turbo/index.js +2 -0
- data/app/jobs/turbo/streams/broadcast_job.rb +1 -1
- data/app/models/concerns/turbo/broadcastable.rb +5 -3
- data/lib/turbo/version.rb +1 -1
- data/lib/turbo-rails.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d87101284e042e02ec6ba74cdf085367415619ee0c0f1c8b4013ad18022c00c7
|
4
|
+
data.tar.gz: 1d514a6ece035de00be6c8af254662476343db15827ca02b27fbcd7caab14d5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b81a8c738ec5f9ff1c3584a4598e116eb5e54557295717e8eaa6ae582d66408c0554477a1bbf7a623bc8d409e45db1e984892c7a784aea2047163c719fb97a7
|
7
|
+
data.tar.gz: 1f86ba10f8bd0b76a722eac75490bc309e292e5dd04c7a488b153792ae9f00c9aef4cedf6dc28534569366c7089667abeaa8ac7ad9458ed50a82be58fec13f42
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
Turbo 8.0.0-beta.
|
2
|
+
Turbo 8.0.0-beta.2
|
3
3
|
Copyright © 2023 37signals LLC
|
4
4
|
*/
|
5
5
|
(function(prototype) {
|
@@ -485,12 +485,31 @@ async function around(callback, reader) {
|
|
485
485
|
return [ before, after ];
|
486
486
|
}
|
487
487
|
|
488
|
-
|
488
|
+
class LimitedSet extends Set {
|
489
|
+
constructor(maxSize) {
|
490
|
+
super();
|
491
|
+
this.maxSize = maxSize;
|
492
|
+
}
|
493
|
+
add(value) {
|
494
|
+
if (this.size >= this.maxSize) {
|
495
|
+
const iterator = this.values();
|
496
|
+
const oldestValue = iterator.next().value;
|
497
|
+
this.delete(oldestValue);
|
498
|
+
}
|
499
|
+
super.add(value);
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
const recentRequests = new LimitedSet(20);
|
504
|
+
|
505
|
+
const nativeFetch = window.fetch;
|
506
|
+
|
507
|
+
function fetchWithTurboHeaders(url, options = {}) {
|
489
508
|
const modifiedHeaders = new Headers(options.headers || {});
|
490
509
|
const requestUID = uuid();
|
491
|
-
|
510
|
+
recentRequests.add(requestUID);
|
492
511
|
modifiedHeaders.append("X-Turbo-Request-Id", requestUID);
|
493
|
-
return
|
512
|
+
return nativeFetch(url, {
|
494
513
|
...options,
|
495
514
|
headers: modifiedHeaders
|
496
515
|
});
|
@@ -609,7 +628,7 @@ class FetchRequest {
|
|
609
628
|
await this.#allowRequestToBeIntercepted(fetchOptions);
|
610
629
|
try {
|
611
630
|
this.delegate.requestStarted(this);
|
612
|
-
const response = await
|
631
|
+
const response = await fetchWithTurboHeaders(this.url.href, fetchOptions);
|
613
632
|
return await this.receive(response);
|
614
633
|
} catch (error) {
|
615
634
|
if (error.name !== "AbortError") {
|
@@ -848,6 +867,7 @@ class FormSubmission {
|
|
848
867
|
this.state = FormSubmissionState.waiting;
|
849
868
|
this.submitter?.setAttribute("disabled", "");
|
850
869
|
this.setSubmitsWith();
|
870
|
+
markAsBusy(this.formElement);
|
851
871
|
dispatch("turbo:submit-start", {
|
852
872
|
target: this.formElement,
|
853
873
|
detail: {
|
@@ -895,6 +915,7 @@ class FormSubmission {
|
|
895
915
|
this.state = FormSubmissionState.stopped;
|
896
916
|
this.submitter?.removeAttribute("disabled");
|
897
917
|
this.resetSubmitterText();
|
918
|
+
clearBusyState(this.formElement);
|
898
919
|
dispatch("turbo:submit-end", {
|
899
920
|
target: this.formElement,
|
900
921
|
detail: {
|
@@ -1176,6 +1197,12 @@ class View {
|
|
1176
1197
|
this.element.removeAttribute("data-turbo-preview");
|
1177
1198
|
}
|
1178
1199
|
}
|
1200
|
+
markVisitDirection(direction) {
|
1201
|
+
this.element.setAttribute("data-turbo-visit-direction", direction);
|
1202
|
+
}
|
1203
|
+
unmarkVisitDirection() {
|
1204
|
+
this.element.removeAttribute("data-turbo-visit-direction");
|
1205
|
+
}
|
1179
1206
|
async renderSnapshot(renderer) {
|
1180
1207
|
await renderer.render();
|
1181
1208
|
}
|
@@ -1480,14 +1507,14 @@ class FrameRenderer extends Renderer {
|
|
1480
1507
|
return true;
|
1481
1508
|
}
|
1482
1509
|
async render() {
|
1483
|
-
await
|
1510
|
+
await nextRepaint();
|
1484
1511
|
this.preservingPermanentElements((() => {
|
1485
1512
|
this.loadFrameElement();
|
1486
1513
|
}));
|
1487
1514
|
this.scrollFrameIntoView();
|
1488
|
-
await
|
1515
|
+
await nextRepaint();
|
1489
1516
|
this.focusFirstAutofocusableElement();
|
1490
|
-
await
|
1517
|
+
await nextRepaint();
|
1491
1518
|
this.activateScriptElements();
|
1492
1519
|
}
|
1493
1520
|
loadFrameElement() {
|
@@ -1846,6 +1873,12 @@ const SystemStatusCode = {
|
|
1846
1873
|
contentTypeMismatch: -2
|
1847
1874
|
};
|
1848
1875
|
|
1876
|
+
const Direction = {
|
1877
|
+
advance: "forward",
|
1878
|
+
restore: "back",
|
1879
|
+
replace: "none"
|
1880
|
+
};
|
1881
|
+
|
1849
1882
|
class Visit {
|
1850
1883
|
identifier=uuid();
|
1851
1884
|
timingMetrics={};
|
@@ -1861,7 +1894,7 @@ class Visit {
|
|
1861
1894
|
this.delegate = delegate;
|
1862
1895
|
this.location = location;
|
1863
1896
|
this.restorationIdentifier = restorationIdentifier || uuid();
|
1864
|
-
const {action: action, historyChanged: historyChanged, referrer: referrer, snapshot: snapshot, snapshotHTML: snapshotHTML, response: response, visitCachedSnapshot: visitCachedSnapshot, willRender: willRender, updateHistory: updateHistory, shouldCacheSnapshot: shouldCacheSnapshot, acceptsStreamResponse: acceptsStreamResponse} = {
|
1897
|
+
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} = {
|
1865
1898
|
...defaultOptions,
|
1866
1899
|
...options
|
1867
1900
|
};
|
@@ -1878,6 +1911,7 @@ class Visit {
|
|
1878
1911
|
this.scrolled = !willRender;
|
1879
1912
|
this.shouldCacheSnapshot = shouldCacheSnapshot;
|
1880
1913
|
this.acceptsStreamResponse = acceptsStreamResponse;
|
1914
|
+
this.direction = direction || Direction[action];
|
1881
1915
|
}
|
1882
1916
|
get adapter() {
|
1883
1917
|
return this.delegate.adapter;
|
@@ -2098,7 +2132,7 @@ class Visit {
|
|
2098
2132
|
this.finishRequest();
|
2099
2133
|
}
|
2100
2134
|
performScroll() {
|
2101
|
-
if (!this.scrolled && !this.view.forceReloaded && !this.view.
|
2135
|
+
if (!this.scrolled && !this.view.forceReloaded && !this.view.shouldPreserveScrollPosition(this)) {
|
2102
2136
|
if (this.action == "restore") {
|
2103
2137
|
this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();
|
2104
2138
|
} else {
|
@@ -2162,9 +2196,7 @@ class Visit {
|
|
2162
2196
|
}
|
2163
2197
|
async render(callback) {
|
2164
2198
|
this.cancelRender();
|
2165
|
-
await
|
2166
|
-
this.frame = requestAnimationFrame((() => resolve()));
|
2167
|
-
}));
|
2199
|
+
this.frame = await nextRepaint();
|
2168
2200
|
await callback();
|
2169
2201
|
delete this.frame;
|
2170
2202
|
}
|
@@ -2386,6 +2418,7 @@ class History {
|
|
2386
2418
|
restorationData={};
|
2387
2419
|
started=false;
|
2388
2420
|
pageLoaded=false;
|
2421
|
+
currentIndex=0;
|
2389
2422
|
constructor(delegate) {
|
2390
2423
|
this.delegate = delegate;
|
2391
2424
|
}
|
@@ -2393,6 +2426,7 @@ class History {
|
|
2393
2426
|
if (!this.started) {
|
2394
2427
|
addEventListener("popstate", this.onPopState, false);
|
2395
2428
|
addEventListener("load", this.onPageLoad, false);
|
2429
|
+
this.currentIndex = history.state?.turbo?.restorationIndex || 0;
|
2396
2430
|
this.started = true;
|
2397
2431
|
this.replace(new URL(window.location.href));
|
2398
2432
|
}
|
@@ -2411,9 +2445,11 @@ class History {
|
|
2411
2445
|
this.update(history.replaceState, location, restorationIdentifier);
|
2412
2446
|
}
|
2413
2447
|
update(method, location, restorationIdentifier = uuid()) {
|
2448
|
+
if (method === history.pushState) ++this.currentIndex;
|
2414
2449
|
const state = {
|
2415
2450
|
turbo: {
|
2416
|
-
restorationIdentifier: restorationIdentifier
|
2451
|
+
restorationIdentifier: restorationIdentifier,
|
2452
|
+
restorationIndex: this.currentIndex
|
2417
2453
|
}
|
2418
2454
|
};
|
2419
2455
|
method.call(history, state, "", location.href);
|
@@ -2448,9 +2484,11 @@ class History {
|
|
2448
2484
|
const {turbo: turbo} = event.state || {};
|
2449
2485
|
if (turbo) {
|
2450
2486
|
this.location = new URL(window.location.href);
|
2451
|
-
const {restorationIdentifier: restorationIdentifier} = turbo;
|
2487
|
+
const {restorationIdentifier: restorationIdentifier, restorationIndex: restorationIndex} = turbo;
|
2452
2488
|
this.restorationIdentifier = restorationIdentifier;
|
2453
|
-
this.
|
2489
|
+
const direction = restorationIndex > this.currentIndex ? "forward" : "back";
|
2490
|
+
this.delegate.historyPoppedToLocationWithRestorationIdentifierAndDirection(this.location, restorationIdentifier, direction);
|
2491
|
+
this.currentIndex = restorationIndex;
|
2454
2492
|
}
|
2455
2493
|
}
|
2456
2494
|
};
|
@@ -2725,7 +2763,7 @@ async function withAutofocusFromFragment(fragment, callback) {
|
|
2725
2763
|
elementWithAutofocus.id = willAutofocusId;
|
2726
2764
|
}
|
2727
2765
|
callback();
|
2728
|
-
await
|
2766
|
+
await nextRepaint();
|
2729
2767
|
const hasNoActiveElement = document.activeElement == null || document.activeElement == document.body;
|
2730
2768
|
if (hasNoActiveElement && willAutofocusId) {
|
2731
2769
|
const elementToAutofocus = document.getElementById(willAutofocusId);
|
@@ -3663,7 +3701,10 @@ class PageView extends View {
|
|
3663
3701
|
return this.snapshotCache.get(location);
|
3664
3702
|
}
|
3665
3703
|
isPageRefresh(visit) {
|
3666
|
-
return !visit || this.lastRenderedLocation.
|
3704
|
+
return !visit || this.lastRenderedLocation.pathname === visit.location.pathname && visit.action === "replace";
|
3705
|
+
}
|
3706
|
+
shouldPreserveScrollPosition(visit) {
|
3707
|
+
return this.isPageRefresh(visit) && this.snapshot.shouldPreserveScrollPosition;
|
3667
3708
|
}
|
3668
3709
|
get snapshot() {
|
3669
3710
|
return PageSnapshot.fromElement(this.element);
|
@@ -3672,24 +3713,25 @@ class PageView extends View {
|
|
3672
3713
|
|
3673
3714
|
class Preloader {
|
3674
3715
|
selector="a[data-turbo-preload]";
|
3675
|
-
constructor(delegate) {
|
3716
|
+
constructor(delegate, snapshotCache) {
|
3676
3717
|
this.delegate = delegate;
|
3677
|
-
|
3678
|
-
get snapshotCache() {
|
3679
|
-
return this.delegate.navigator.view.snapshotCache;
|
3718
|
+
this.snapshotCache = snapshotCache;
|
3680
3719
|
}
|
3681
3720
|
start() {
|
3682
3721
|
if (document.readyState === "loading") {
|
3683
|
-
|
3684
|
-
this.preloadOnLoadLinksForView(document.body);
|
3685
|
-
}));
|
3722
|
+
document.addEventListener("DOMContentLoaded", this.#preloadAll);
|
3686
3723
|
} else {
|
3687
3724
|
this.preloadOnLoadLinksForView(document.body);
|
3688
3725
|
}
|
3689
3726
|
}
|
3727
|
+
stop() {
|
3728
|
+
document.removeEventListener("DOMContentLoaded", this.#preloadAll);
|
3729
|
+
}
|
3690
3730
|
preloadOnLoadLinksForView(element) {
|
3691
3731
|
for (const link of element.querySelectorAll(this.selector)) {
|
3692
|
-
this.
|
3732
|
+
if (this.delegate.shouldPreloadLink(link)) {
|
3733
|
+
this.preloadURL(link);
|
3734
|
+
}
|
3693
3735
|
}
|
3694
3736
|
}
|
3695
3737
|
async preloadURL(link) {
|
@@ -3697,33 +3739,27 @@ class Preloader {
|
|
3697
3739
|
if (this.snapshotCache.has(location)) {
|
3698
3740
|
return;
|
3699
3741
|
}
|
3700
|
-
|
3701
|
-
|
3702
|
-
headers: {
|
3703
|
-
"Sec-Purpose": "prefetch",
|
3704
|
-
Accept: "text/html"
|
3705
|
-
}
|
3706
|
-
});
|
3707
|
-
const responseText = await response.text();
|
3708
|
-
const snapshot = PageSnapshot.fromHTMLString(responseText);
|
3709
|
-
this.snapshotCache.put(location, snapshot);
|
3710
|
-
} catch (_) {}
|
3742
|
+
const fetchRequest = new FetchRequest(this, FetchMethod.get, location, new URLSearchParams, link);
|
3743
|
+
await fetchRequest.perform();
|
3711
3744
|
}
|
3712
|
-
|
3713
|
-
|
3714
|
-
class LimitedSet extends Set {
|
3715
|
-
constructor(maxSize) {
|
3716
|
-
super();
|
3717
|
-
this.maxSize = maxSize;
|
3745
|
+
prepareRequest(fetchRequest) {
|
3746
|
+
fetchRequest.headers["Sec-Purpose"] = "prefetch";
|
3718
3747
|
}
|
3719
|
-
|
3720
|
-
|
3721
|
-
const
|
3722
|
-
const
|
3723
|
-
this.
|
3724
|
-
}
|
3725
|
-
super.add(value);
|
3748
|
+
async requestSucceededWithResponse(fetchRequest, fetchResponse) {
|
3749
|
+
try {
|
3750
|
+
const responseHTML = await fetchResponse.responseHTML;
|
3751
|
+
const snapshot = PageSnapshot.fromHTMLString(responseHTML);
|
3752
|
+
this.snapshotCache.put(fetchRequest.url, snapshot);
|
3753
|
+
} catch (_) {}
|
3726
3754
|
}
|
3755
|
+
requestStarted(fetchRequest) {}
|
3756
|
+
requestErrored(fetchRequest) {}
|
3757
|
+
requestFinished(fetchRequest) {}
|
3758
|
+
requestPreventedHandlingResponse(fetchRequest, fetchResponse) {}
|
3759
|
+
requestFailedWithResponse(fetchRequest, fetchResponse) {}
|
3760
|
+
#preloadAll=() => {
|
3761
|
+
this.preloadOnLoadLinksForView(document.body);
|
3762
|
+
};
|
3727
3763
|
}
|
3728
3764
|
|
3729
3765
|
class Cache {
|
@@ -3750,7 +3786,6 @@ class Cache {
|
|
3750
3786
|
class Session {
|
3751
3787
|
navigator=new Navigator(this);
|
3752
3788
|
history=new History(this);
|
3753
|
-
preloader=new Preloader(this);
|
3754
3789
|
view=new PageView(this, document.documentElement);
|
3755
3790
|
adapter=new BrowserAdapter(this);
|
3756
3791
|
pageObserver=new PageObserver(this);
|
@@ -3763,12 +3798,15 @@ class Session {
|
|
3763
3798
|
frameRedirector=new FrameRedirector(this, document.documentElement);
|
3764
3799
|
streamMessageRenderer=new StreamMessageRenderer;
|
3765
3800
|
cache=new Cache(this);
|
3766
|
-
recentRequests=new LimitedSet(20);
|
3767
3801
|
drive=true;
|
3768
3802
|
enabled=true;
|
3769
3803
|
progressBarDelay=500;
|
3770
3804
|
started=false;
|
3771
3805
|
formMode="on";
|
3806
|
+
constructor(recentRequests) {
|
3807
|
+
this.recentRequests = recentRequests;
|
3808
|
+
this.preloader = new Preloader(this, this.view.snapshotCache);
|
3809
|
+
}
|
3772
3810
|
start() {
|
3773
3811
|
if (!this.started) {
|
3774
3812
|
this.pageObserver.start();
|
@@ -3799,6 +3837,7 @@ class Session {
|
|
3799
3837
|
this.streamObserver.stop();
|
3800
3838
|
this.frameRedirector.stop();
|
3801
3839
|
this.history.stop();
|
3840
|
+
this.preloader.stop();
|
3802
3841
|
this.started = false;
|
3803
3842
|
}
|
3804
3843
|
}
|
@@ -3847,11 +3886,24 @@ class Session {
|
|
3847
3886
|
get restorationIdentifier() {
|
3848
3887
|
return this.history.restorationIdentifier;
|
3849
3888
|
}
|
3850
|
-
|
3889
|
+
shouldPreloadLink(element) {
|
3890
|
+
const isUnsafe = element.hasAttribute("data-turbo-method");
|
3891
|
+
const isStream = element.hasAttribute("data-turbo-stream");
|
3892
|
+
const frameTarget = element.getAttribute("data-turbo-frame");
|
3893
|
+
const frame = frameTarget == "_top" ? null : document.getElementById(frameTarget) || findClosestRecursively(element, "turbo-frame:not([disabled])");
|
3894
|
+
if (isUnsafe || isStream || frame instanceof FrameElement) {
|
3895
|
+
return false;
|
3896
|
+
} else {
|
3897
|
+
const location = new URL(element.href);
|
3898
|
+
return this.elementIsNavigatable(element) && locationIsVisitable(location, this.snapshot.rootLocation);
|
3899
|
+
}
|
3900
|
+
}
|
3901
|
+
historyPoppedToLocationWithRestorationIdentifierAndDirection(location, restorationIdentifier, direction) {
|
3851
3902
|
if (this.enabled) {
|
3852
3903
|
this.navigator.startVisit(location, restorationIdentifier, {
|
3853
3904
|
action: "restore",
|
3854
|
-
historyChanged: true
|
3905
|
+
historyChanged: true,
|
3906
|
+
direction: direction
|
3855
3907
|
});
|
3856
3908
|
} else {
|
3857
3909
|
this.adapter.pageInvalidated({
|
@@ -3889,6 +3941,7 @@ class Session {
|
|
3889
3941
|
visitStarted(visit) {
|
3890
3942
|
if (!visit.acceptsStreamResponse) {
|
3891
3943
|
markAsBusy(document.documentElement);
|
3944
|
+
this.view.markVisitDirection(visit.direction);
|
3892
3945
|
}
|
3893
3946
|
extendURLWithDeprecatedProperties(visit.location);
|
3894
3947
|
if (!visit.silent) {
|
@@ -3896,6 +3949,7 @@ class Session {
|
|
3896
3949
|
}
|
3897
3950
|
}
|
3898
3951
|
visitCompleted(visit) {
|
3952
|
+
this.view.unmarkVisitDirection();
|
3899
3953
|
clearBusyState(document.documentElement);
|
3900
3954
|
this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
|
3901
3955
|
}
|
@@ -4086,7 +4140,7 @@ const deprecatedLocationPropertyDescriptors = {
|
|
4086
4140
|
}
|
4087
4141
|
};
|
4088
4142
|
|
4089
|
-
const session = new Session;
|
4143
|
+
const session = new Session(recentRequests);
|
4090
4144
|
|
4091
4145
|
const {cache: cache, navigator: navigator$1} = session;
|
4092
4146
|
|
@@ -4139,7 +4193,7 @@ var Turbo = Object.freeze({
|
|
4139
4193
|
PageRenderer: PageRenderer,
|
4140
4194
|
PageSnapshot: PageSnapshot,
|
4141
4195
|
FrameRenderer: FrameRenderer,
|
4142
|
-
fetch:
|
4196
|
+
fetch: fetchWithTurboHeaders,
|
4143
4197
|
start: start,
|
4144
4198
|
registerAdapter: registerAdapter,
|
4145
4199
|
visit: visit,
|
@@ -4806,11 +4860,14 @@ if (customElements.get("turbo-stream-source") === undefined) {
|
|
4806
4860
|
}
|
4807
4861
|
})();
|
4808
4862
|
|
4809
|
-
window.Turbo =
|
4863
|
+
window.Turbo = {
|
4864
|
+
...Turbo,
|
4865
|
+
StreamActions: StreamActions
|
4866
|
+
};
|
4810
4867
|
|
4811
4868
|
start();
|
4812
4869
|
|
4813
|
-
var
|
4870
|
+
var Turbo$1 = Object.freeze({
|
4814
4871
|
__proto__: null,
|
4815
4872
|
FetchEnctype: FetchEnctype,
|
4816
4873
|
FetchMethod: FetchMethod,
|
@@ -4828,7 +4885,7 @@ var turbo_es2017Esm = Object.freeze({
|
|
4828
4885
|
clearCache: clearCache,
|
4829
4886
|
connectStreamSource: connectStreamSource,
|
4830
4887
|
disconnectStreamSource: disconnectStreamSource,
|
4831
|
-
fetch:
|
4888
|
+
fetch: fetchWithTurboHeaders,
|
4832
4889
|
fetchEnctypeFromString: fetchEnctypeFromString,
|
4833
4890
|
fetchMethodFromString: fetchMethodFromString,
|
4834
4891
|
isSafe: isSafe,
|
@@ -4979,6 +5036,8 @@ function isBodyInit(body) {
|
|
4979
5036
|
return body instanceof FormData || body instanceof URLSearchParams;
|
4980
5037
|
}
|
4981
5038
|
|
5039
|
+
window.Turbo = Turbo$1;
|
5040
|
+
|
4982
5041
|
addEventListener("turbo:before-fetch-request", encodeMethodIntoRequestBody);
|
4983
5042
|
|
4984
5043
|
var adapters = {
|
@@ -5514,4 +5573,4 @@ var index = Object.freeze({
|
|
5514
5573
|
getConfig: getConfig
|
5515
5574
|
});
|
5516
5575
|
|
5517
|
-
export {
|
5576
|
+
export { Turbo$1 as Turbo, cable };
|