turbo-rails 0.7.9 → 0.7.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55602f24631c11bc8034e778f706fe6866caca4ff1907b7217c7d4150cf26acd
4
- data.tar.gz: bfe2afe2a79b5659a66e44bf43d959ee17cc091e18c925207c56a3a7beb71443
3
+ metadata.gz: 580519d63f8208480ca58ba6a406d3b8d012365af8e96768a447ad1848576d0d
4
+ data.tar.gz: e12f497a997e28c2850a8bb2d2731717a97d82d3e46fea0d3b35829190b3fd4e
5
5
  SHA512:
6
- metadata.gz: 2049be5687158e196102d4a89f1ca1f1e4a5c6f90987b8bc6884f5e8689ef7725853f9d562bc066e4267c06bd7b82c885494d9c35184aca752036377bcdb7fbf
7
- data.tar.gz: 384956d8e415c8461021b9ef5d4fbec379f81f3b5e6964c08a9b502c8141060187e9838bf1e6aabe973fff1419968ea234534752373c698446da272b28e57ed8
6
+ metadata.gz: b8c233bab026cd81eaeebe394e92cd19d217e08f2dce28e0cfbc3f6490c8536e833bdb70db2f3056da82f3a61253d97da13881dc82de48dfe23e106eb48cb7dc
7
+ data.tar.gz: 67df314bd48116ff91f246f212ca3775361a9a18cce54842e5f19d00f465eadee3f500269288d49c200ed6414b83873d53ff32eb46d0cb8a99dd12c658716923
data/README.md CHANGED
@@ -50,7 +50,7 @@ The JavaScript for Turbo can either be run through the asset pipeline, which is
50
50
 
51
51
  Running `turbo:install` will install through NPM if Webpacker is installed in the application. Otherwise the asset pipeline version is used. To use the asset pipeline version, you must have `importmap-rails` installed first and listed higher in the Gemfile.
52
52
 
53
- If you're using Webpack and need to use the cable consumer, you can import [`cable`](https://github.com/hotwired/turbo-rails/blob/main/app/javascript/turbo/cable.js) (`import { cable } from "@hotwired/turbo-rails"`), but ensure that your application actually *uses* the members it `import`s when using this style (see [turbo-rails#48](https://github.com/hotwired/turbo-rails/issues/48)).
53
+ If you're using node and need to use the cable consumer, you can import [`cable`](https://github.com/hotwired/turbo-rails/blob/main/app/javascript/turbo/cable.js) (`import { cable } from "@hotwired/turbo-rails"`), but ensure that your application actually *uses* the members it `import`s when using this style (see [turbo-rails#48](https://github.com/hotwired/turbo-rails/issues/48)).
54
54
 
55
55
  The `Turbo` instance is automatically assigned to `window.Turbo` upon import:
56
56
 
@@ -71,10 +71,7 @@ Turbo can coexist with Rails UJS, but you need to take a series of upgrade steps
71
71
 
72
72
  ## Development
73
73
 
74
- * To run the Rails tests: `bundle exec rake`.
75
- * To install dependencies: `bundle install`
76
- * To prepare the test database: `cd test/dummy; RAILS_ENV=test ./bin/rails db:migrate`
77
- * To compile the JavaScript for the asset pipeline: `yarn build`
74
+ Run the tests with `./bin/test`.
78
75
 
79
76
 
80
77
  ## License
@@ -31,6 +31,7 @@ function clickCaptured(event) {
31
31
 
32
32
  (function() {
33
33
  if ("SubmitEvent" in window) return;
34
+ if ("submitter" in Event.prototype) return;
34
35
  addEventListener("click", clickCaptured, true);
35
36
  Object.defineProperty(Event.prototype, "submitter", {
36
37
  get() {
@@ -226,11 +227,11 @@ class FetchResponse {
226
227
  return this.header("Content-Type");
227
228
  }
228
229
  get responseText() {
229
- return this.response.text();
230
+ return this.response.clone().text();
230
231
  }
231
232
  get responseHTML() {
232
233
  if (this.isHTML) {
233
- return this.response.text();
234
+ return this.response.clone().text();
234
235
  } else {
235
236
  return Promise.resolve(undefined);
236
237
  }
@@ -326,7 +327,7 @@ function fetchMethodFromString(method) {
326
327
  }
327
328
 
328
329
  class FetchRequest {
329
- constructor(delegate, method, location, body = new URLSearchParams) {
330
+ constructor(delegate, method, location, body = new URLSearchParams, target = null) {
330
331
  this.abortController = new AbortController;
331
332
  this.resolveRequestPromise = value => {};
332
333
  this.delegate = delegate;
@@ -338,6 +339,7 @@ class FetchRequest {
338
339
  this.body = body;
339
340
  this.url = location;
340
341
  }
342
+ this.target = target;
341
343
  }
342
344
  get location() {
343
345
  return this.url;
@@ -375,7 +377,8 @@ class FetchRequest {
375
377
  cancelable: true,
376
378
  detail: {
377
379
  fetchResponse: fetchResponse
378
- }
380
+ },
381
+ target: this.target
379
382
  });
380
383
  if (event.defaultPrevented) {
381
384
  this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
@@ -417,7 +420,8 @@ class FetchRequest {
417
420
  fetchOptions: fetchOptions,
418
421
  url: this.url.href,
419
422
  resume: this.resolveRequestPromise
420
- }
423
+ },
424
+ target: this.target
421
425
  });
422
426
  if (event.defaultPrevented) await requestInterception;
423
427
  }
@@ -538,7 +542,7 @@ class FormSubmission {
538
542
  this.formElement = formElement;
539
543
  this.submitter = submitter;
540
544
  this.formData = buildFormData(formElement, submitter);
541
- this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
545
+ this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
542
546
  this.mustRedirect = mustRedirect;
543
547
  }
544
548
  get method() {
@@ -1173,7 +1177,7 @@ ProgressBar.animationDuration = 300;
1173
1177
  class HeadSnapshot extends Snapshot {
1174
1178
  constructor() {
1175
1179
  super(...arguments);
1176
- this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).reduce(((result, element) => {
1180
+ this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).map((element => elementWithoutNonce(element))).reduce(((result, element) => {
1177
1181
  const {outerHTML: outerHTML} = element;
1178
1182
  const details = outerHTML in result ? result[outerHTML] : {
1179
1183
  type: elementType(element),
@@ -1255,6 +1259,13 @@ function elementIsMetaElementWithName(element, name) {
1255
1259
  return tagName == "meta" && element.getAttribute("name") == name;
1256
1260
  }
1257
1261
 
1262
+ function elementWithoutNonce(element) {
1263
+ if (element.hasAttribute("nonce")) {
1264
+ element.setAttribute("nonce", "");
1265
+ }
1266
+ return element;
1267
+ }
1268
+
1258
1269
  class PageSnapshot extends Snapshot {
1259
1270
  constructor(element, headSnapshot) {
1260
1271
  super(element);
@@ -1805,18 +1816,18 @@ class FrameRedirector {
1805
1816
  return this.shouldRedirect(element, submitter);
1806
1817
  }
1807
1818
  formSubmissionIntercepted(element, submitter) {
1808
- const frame = this.findFrameElement(element);
1819
+ const frame = this.findFrameElement(element, submitter);
1809
1820
  if (frame) {
1810
1821
  frame.removeAttribute("reloadable");
1811
1822
  frame.delegate.formSubmissionIntercepted(element, submitter);
1812
1823
  }
1813
1824
  }
1814
1825
  shouldRedirect(element, submitter) {
1815
- const frame = this.findFrameElement(element);
1826
+ const frame = this.findFrameElement(element, submitter);
1816
1827
  return frame ? frame != element.closest("turbo-frame") : false;
1817
1828
  }
1818
- findFrameElement(element) {
1819
- const id = element.getAttribute("data-turbo-frame");
1829
+ findFrameElement(element, submitter) {
1830
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
1820
1831
  if (id && id != "_top") {
1821
1832
  const frame = this.element.querySelector(`#${id}:not([disabled])`);
1822
1833
  if (frame instanceof FrameElement) {
@@ -2539,12 +2550,13 @@ class Session {
2539
2550
  });
2540
2551
  }
2541
2552
  convertLinkWithMethodClickToFormSubmission(link) {
2553
+ var _a;
2542
2554
  const linkMethod = link.getAttribute("data-turbo-method");
2543
2555
  if (linkMethod) {
2544
2556
  const form = document.createElement("form");
2545
2557
  form.method = linkMethod;
2546
2558
  form.action = link.getAttribute("href") || "undefined";
2547
- document.body.appendChild(form);
2559
+ (_a = link.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(form, link);
2548
2560
  return dispatch("submit", {
2549
2561
  cancelable: true,
2550
2562
  target: form
@@ -2896,7 +2908,7 @@ class FrameController {
2896
2908
  this.reloadable = false;
2897
2909
  this.formSubmission = new FormSubmission(this, element, submitter);
2898
2910
  if (this.formSubmission.fetchRequest.isIdempotent) {
2899
- this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
2911
+ this.navigateFrame(element, this.formSubmission.fetchRequest.url.href, submitter);
2900
2912
  } else {
2901
2913
  const {fetchRequest: fetchRequest} = this.formSubmission;
2902
2914
  this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
@@ -2932,7 +2944,7 @@ class FrameController {
2932
2944
  frame.setAttribute("busy", "");
2933
2945
  }
2934
2946
  formSubmissionSucceededWithResponse(formSubmission, response) {
2935
- const frame = this.findFrameElement(formSubmission.formElement);
2947
+ const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
2936
2948
  frame.delegate.loadResponse(response);
2937
2949
  }
2938
2950
  formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
@@ -2951,7 +2963,7 @@ class FrameController {
2951
2963
  viewRenderedSnapshot(snapshot, isPreview) {}
2952
2964
  viewInvalidated() {}
2953
2965
  async visit(url) {
2954
- const request = new FetchRequest(this, FetchMethod.get, expandURL(url));
2966
+ const request = new FetchRequest(this, FetchMethod.get, expandURL(url), undefined, this.element);
2955
2967
  return new Promise((resolve => {
2956
2968
  this.resolveVisitPromise = () => {
2957
2969
  this.resolveVisitPromise = () => {};
@@ -2960,13 +2972,14 @@ class FrameController {
2960
2972
  request.perform();
2961
2973
  }));
2962
2974
  }
2963
- navigateFrame(element, url) {
2964
- const frame = this.findFrameElement(element);
2975
+ navigateFrame(element, url, submitter) {
2976
+ const frame = this.findFrameElement(element, submitter);
2977
+ frame.setAttribute("reloadable", "");
2965
2978
  frame.src = url;
2966
2979
  }
2967
- findFrameElement(element) {
2980
+ findFrameElement(element, submitter) {
2968
2981
  var _a;
2969
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2982
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2970
2983
  return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
2971
2984
  }
2972
2985
  async extractForeignFrameElement(container) {
@@ -2987,7 +3000,7 @@ class FrameController {
2987
3000
  return new FrameElement;
2988
3001
  }
2989
3002
  shouldInterceptNavigation(element, submitter) {
2990
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
3003
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2991
3004
  if (!this.enabled || id == "_top") {
2992
3005
  return false;
2993
3006
  }
@@ -6,61 +6,61 @@ module Turbo::Streams::Broadcasts
6
6
  include Turbo::Streams::ActionHelper
7
7
 
8
8
  def broadcast_remove_to(*streamables, **opts)
9
- broadcast_action_to *streamables, action: :remove, **opts
9
+ broadcast_action_to(*streamables, action: :remove, **opts)
10
10
  end
11
11
 
12
12
  def broadcast_replace_to(*streamables, **opts)
13
- broadcast_action_to *streamables, action: :replace, **opts
13
+ broadcast_action_to(*streamables, action: :replace, **opts)
14
14
  end
15
15
 
16
16
  def broadcast_update_to(*streamables, **opts)
17
- broadcast_action_to *streamables, action: :update, **opts
17
+ broadcast_action_to(*streamables, action: :update, **opts)
18
18
  end
19
19
 
20
20
  def broadcast_before_to(*streamables, **opts)
21
- broadcast_action_to *streamables, action: :before, **opts
21
+ broadcast_action_to(*streamables, action: :before, **opts)
22
22
  end
23
23
 
24
24
  def broadcast_after_to(*streamables, **opts)
25
- broadcast_action_to *streamables, action: :after, **opts
25
+ broadcast_action_to(*streamables, action: :after, **opts)
26
26
  end
27
27
 
28
28
  def broadcast_append_to(*streamables, **opts)
29
- broadcast_action_to *streamables, action: :append, **opts
29
+ broadcast_action_to(*streamables, action: :append, **opts)
30
30
  end
31
31
 
32
32
  def broadcast_prepend_to(*streamables, **opts)
33
- broadcast_action_to *streamables, action: :prepend, **opts
33
+ broadcast_action_to(*streamables, action: :prepend, **opts)
34
34
  end
35
35
 
36
36
  def broadcast_action_to(*streamables, action:, target: nil, targets: nil, **rendering)
37
- broadcast_stream_to *streamables, content: turbo_stream_action_tag(action, target: target, targets: targets, template:
37
+ broadcast_stream_to(*streamables, content: turbo_stream_action_tag(action, target: target, targets: targets, template:
38
38
  rendering.delete(:content) || (rendering.any? ? render_format(:html, **rendering) : nil)
39
- )
39
+ ))
40
40
  end
41
41
 
42
42
  def broadcast_replace_later_to(*streamables, **opts)
43
- broadcast_action_later_to *streamables, action: :replace, **opts
43
+ broadcast_action_later_to(*streamables, action: :replace, **opts)
44
44
  end
45
45
 
46
46
  def broadcast_update_later_to(*streamables, **opts)
47
- broadcast_action_later_to *streamables, action: :update, **opts
47
+ broadcast_action_later_to(*streamables, action: :update, **opts)
48
48
  end
49
49
 
50
50
  def broadcast_before_later_to(*streamables, **opts)
51
- broadcast_action_later_to *streamables, action: :before, **opts
51
+ broadcast_action_later_to(*streamables, action: :before, **opts)
52
52
  end
53
53
 
54
54
  def broadcast_after_later_to(*streamables, **opts)
55
- broadcast_action_later_to *streamables, action: :after, **opts
55
+ broadcast_action_later_to(*streamables, action: :after, **opts)
56
56
  end
57
57
 
58
58
  def broadcast_append_later_to(*streamables, **opts)
59
- broadcast_action_later_to *streamables, action: :append, **opts
59
+ broadcast_action_later_to(*streamables, action: :append, **opts)
60
60
  end
61
61
 
62
62
  def broadcast_prepend_later_to(*streamables, **opts)
63
- broadcast_action_later_to *streamables, action: :prepend, **opts
63
+ broadcast_action_later_to(*streamables, action: :prepend, **opts)
64
64
  end
65
65
 
66
66
  def broadcast_action_later_to(*streamables, action:, target: nil, targets: nil, **rendering)
@@ -69,7 +69,7 @@ module Turbo::Streams::Broadcasts
69
69
  end
70
70
 
71
71
  def broadcast_render_to(*streamables, **rendering)
72
- broadcast_stream_to *streamables, content: render_format(:turbo_stream, **rendering)
72
+ broadcast_stream_to(*streamables, content: render_format(:turbo_stream, **rendering))
73
73
  end
74
74
 
75
75
  def broadcast_render_later_to(*streamables, **rendering)
@@ -14,7 +14,7 @@ module Turbo::Streams::ActionHelper
14
14
 
15
15
  if target = convert_to_turbo_stream_dom_id(target)
16
16
  %(<turbo-stream action="#{action}" target="#{target}">#{template}</turbo-stream>).html_safe
17
- elsif targets = convert_to_turbo_stream_dom_id(targets)
17
+ elsif targets = convert_to_turbo_stream_dom_id(targets, include_selector: true)
18
18
  %(<turbo-stream action="#{action}" targets="#{targets}">#{template}</turbo-stream>).html_safe
19
19
  else
20
20
  raise ArgumentError, "target or targets must be supplied"
@@ -22,7 +22,11 @@ module Turbo::Streams::ActionHelper
22
22
  end
23
23
 
24
24
  private
25
- def convert_to_turbo_stream_dom_id(target)
26
- target.respond_to?(:to_key) ? ActionView::RecordIdentifier.dom_id(target) : target
25
+ def convert_to_turbo_stream_dom_id(target, include_selector: false)
26
+ if target.respond_to?(:to_key)
27
+ [ ("#" if include_selector), ActionView::RecordIdentifier.dom_id(target) ].compact.join
28
+ else
29
+ target
30
+ end
27
31
  end
28
32
  end
@@ -76,7 +76,7 @@ module Turbo::Broadcastable
76
76
  # # Sends <turbo-stream action="remove" target="clearance_5"></turbo-stream> to the stream named "identity:2:clearances"
77
77
  # clearance.broadcast_remove_to examiner.identity, :clearances
78
78
  def broadcast_remove_to(*streamables, target: self)
79
- Turbo::StreamsChannel.broadcast_remove_to *streamables, target: target
79
+ Turbo::StreamsChannel.broadcast_remove_to(*streamables, target: target)
80
80
  end
81
81
 
82
82
  # Same as <tt>#broadcast_remove_to</tt>, but the designated stream is automatically set to the current model.
@@ -95,7 +95,7 @@ module Turbo::Broadcastable
95
95
  # # to the stream named "identity:2:clearances"
96
96
  # clearance.broadcast_replace_to examiner.identity, :clearances, partial: "clearances/other_partial", locals: { a: 1 }
97
97
  def broadcast_replace_to(*streamables, **rendering)
98
- Turbo::StreamsChannel.broadcast_replace_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
98
+ Turbo::StreamsChannel.broadcast_replace_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
99
99
  end
100
100
 
101
101
  # Same as <tt>#broadcast_replace_to</tt>, but the designated stream is automatically set to the current model.
@@ -114,7 +114,7 @@ module Turbo::Broadcastable
114
114
  # # to the stream named "identity:2:clearances"
115
115
  # clearance.broadcast_update_to examiner.identity, :clearances, partial: "clearances/other_partial", locals: { a: 1 }
116
116
  def broadcast_update_to(*streamables, **rendering)
117
- Turbo::StreamsChannel.broadcast_update_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
117
+ Turbo::StreamsChannel.broadcast_update_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
118
118
  end
119
119
 
120
120
  # Same as <tt>#broadcast_update_to</tt>, but the designated stream is automatically set to the current model.
@@ -135,7 +135,7 @@ module Turbo::Broadcastable
135
135
  # clearance.broadcast_before_to examiner.identity, :clearances, target: "clearance_5",
136
136
  # partial: "clearances/other_partial", locals: { a: 1 }
137
137
  def broadcast_before_to(*streamables, target:, **rendering)
138
- Turbo::StreamsChannel.broadcast_before_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
138
+ Turbo::StreamsChannel.broadcast_before_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
139
139
  end
140
140
 
141
141
  # Insert a rendering of this broadcastable model after the target identified by it's dom id passed as <tt>target</tt>
@@ -151,7 +151,7 @@ module Turbo::Broadcastable
151
151
  # clearance.broadcast_after_to examiner.identity, :clearances, target: "clearance_5",
152
152
  # partial: "clearances/other_partial", locals: { a: 1 }
153
153
  def broadcast_after_to(*streamables, target:, **rendering)
154
- Turbo::StreamsChannel.broadcast_after_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
154
+ Turbo::StreamsChannel.broadcast_after_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
155
155
  end
156
156
 
157
157
  # Append a rendering of this broadcastable model to the target identified by it's dom id passed as <tt>target</tt>
@@ -167,7 +167,7 @@ module Turbo::Broadcastable
167
167
  # clearance.broadcast_append_to examiner.identity, :clearances, target: "clearances",
168
168
  # partial: "clearances/other_partial", locals: { a: 1 }
169
169
  def broadcast_append_to(*streamables, target: broadcast_target_default, **rendering)
170
- Turbo::StreamsChannel.broadcast_append_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
170
+ Turbo::StreamsChannel.broadcast_append_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
171
171
  end
172
172
 
173
173
  # Same as <tt>#broadcast_append_to</tt>, but the designated stream is automatically set to the current model.
@@ -188,7 +188,7 @@ module Turbo::Broadcastable
188
188
  # clearance.broadcast_prepend_to examiner.identity, :clearances, target: "clearances",
189
189
  # partial: "clearances/other_partial", locals: { a: 1 }
190
190
  def broadcast_prepend_to(*streamables, target: broadcast_target_default, **rendering)
191
- Turbo::StreamsChannel.broadcast_prepend_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
191
+ Turbo::StreamsChannel.broadcast_prepend_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
192
192
  end
193
193
 
194
194
  # Same as <tt>#broadcast_prepend_to</tt>, but the designated stream is automatically set to the current model.
@@ -213,7 +213,7 @@ module Turbo::Broadcastable
213
213
 
214
214
  # Same as <tt>broadcast_replace_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
215
215
  def broadcast_replace_later_to(*streamables, **rendering)
216
- Turbo::StreamsChannel.broadcast_replace_later_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
216
+ Turbo::StreamsChannel.broadcast_replace_later_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
217
217
  end
218
218
 
219
219
  # Same as <tt>#broadcast_replace_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -223,7 +223,7 @@ module Turbo::Broadcastable
223
223
 
224
224
  # Same as <tt>broadcast_update_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
225
225
  def broadcast_update_later_to(*streamables, **rendering)
226
- Turbo::StreamsChannel.broadcast_update_later_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
226
+ Turbo::StreamsChannel.broadcast_update_later_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
227
227
  end
228
228
 
229
229
  # Same as <tt>#broadcast_update_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -233,7 +233,7 @@ module Turbo::Broadcastable
233
233
 
234
234
  # Same as <tt>broadcast_append_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
235
235
  def broadcast_append_later_to(*streamables, target: broadcast_target_default, **rendering)
236
- Turbo::StreamsChannel.broadcast_append_later_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
236
+ Turbo::StreamsChannel.broadcast_append_later_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
237
237
  end
238
238
 
239
239
  # Same as <tt>#broadcast_append_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -243,7 +243,7 @@ module Turbo::Broadcastable
243
243
 
244
244
  # Same as <tt>broadcast_prepend_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
245
245
  def broadcast_prepend_later_to(*streamables, target: broadcast_target_default, **rendering)
246
- Turbo::StreamsChannel.broadcast_prepend_later_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
246
+ Turbo::StreamsChannel.broadcast_prepend_later_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
247
247
  end
248
248
 
249
249
  # Same as <tt>#broadcast_prepend_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -283,7 +283,7 @@ module Turbo::Broadcastable
283
283
  # Same as <tt>broadcast_render_later</tt> but run with the added option of naming the stream using the passed
284
284
  # <tt>streamables</tt>.
285
285
  def broadcast_render_later_to(*streamables, **rendering)
286
- Turbo::StreamsChannel.broadcast_render_later_to *streamables, **broadcast_rendering_with_defaults(rendering)
286
+ Turbo::StreamsChannel.broadcast_render_later_to(*streamables, **broadcast_rendering_with_defaults(rendering))
287
287
  end
288
288
 
289
289
 
@@ -1,6 +1,6 @@
1
1
  if (cable_config_path = Rails.root.join("config/cable.yml")).exist?
2
2
  say "Enable redis in bundle"
3
- uncomment_lines "Gemfile", %(gem 'redis')
3
+ uncomment_lines "Gemfile", /gem ['"]redis['"]/
4
4
 
5
5
  say "Switch development cable to use redis"
6
6
  gsub_file cable_config_path.to_s, /development:\n\s+adapter: async/, "development:\n adapter: redis\n url: redis://localhost:6379/1"
@@ -0,0 +1,5 @@
1
+ say "Import Turbo"
2
+ append_to_file "app/javascript/application.js", %(import "@hotwired/turbo-rails"\n)
3
+
4
+ say "Pin Turbo"
5
+ append_to_file "config/importmap.rb", %(pin "@hotwired/turbo-rails", to: "turbo.js"\n)
@@ -0,0 +1,9 @@
1
+ if (js_entrypoint_path = Rails.root.join("app/javascript/application.js")).exist?
2
+ say "Import Turbo"
3
+ append_to_file "app/javascript/application.js", %(import "@hotwired/turbo-rails"\n)
4
+ else
5
+ say "You must import @hotwired/turbo-rails in your JavaScript entrypoint file", :red
6
+ end
7
+
8
+ say "Install Turbo"
9
+ run "yarn add @hotwired/turbo-rails"
@@ -1,24 +1,42 @@
1
- def run_turbo_install_template(path) system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}" end
1
+ def run_turbo_install_template(path)
2
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}"
3
+ end
4
+
5
+ def redis_installed?
6
+ system('which redis-server')
7
+ end
8
+
9
+ def switch_on_redis_if_available
10
+ if redis_installed?
11
+ Rake::Task["turbo:install:redis"].invoke
12
+ else
13
+ puts "Run turbo:install:redis to switch on Redis and use it in development for turbo streams"
14
+ end
15
+ end
2
16
 
3
17
  namespace :turbo do
4
18
  desc "Install Turbo into the app"
5
19
  task :install do
6
- if defined?(Webpacker::Engine)
7
- Rake::Task["turbo:install:webpacker"].invoke
20
+ if Rails.root.join("config/importmap.rb").exist?
21
+ Rake::Task["turbo:install:importmap"].invoke
22
+ elsif Rails.root.join("package.json").exist?
23
+ Rake::Task["turbo:install:node"].invoke
8
24
  else
9
- Rake::Task["turbo:install:asset_pipeline"].invoke
25
+ puts "You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem."
10
26
  end
11
27
  end
12
28
 
13
29
  namespace :install do
14
30
  desc "Install Turbo into the app with asset pipeline"
15
- task :asset_pipeline do
16
- run_turbo_install_template "turbo_with_asset_pipeline"
31
+ task :importmap do
32
+ run_turbo_install_template "turbo_with_importmap"
33
+ switch_on_redis_if_available
17
34
  end
18
35
 
19
36
  desc "Install Turbo into the app with webpacker"
20
- task :webpacker do
21
- run_turbo_install_template "turbo_with_webpacker"
37
+ task :node do
38
+ run_turbo_install_template "turbo_with_node"
39
+ switch_on_redis_if_available
22
40
  end
23
41
 
24
42
  desc "Switch on Redis and use it in development"
data/lib/turbo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Turbo
2
- VERSION = "0.7.9"
2
+ VERSION = "0.7.13"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.9
4
+ version: 0.7.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-31 00:00:00.000000000 Z
13
+ date: 2021-09-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -57,8 +57,8 @@ files:
57
57
  - app/models/turbo/streams/tag_builder.rb
58
58
  - config/routes.rb
59
59
  - lib/install/turbo_needs_redis.rb
60
- - lib/install/turbo_with_asset_pipeline.rb
61
- - lib/install/turbo_with_webpacker.rb
60
+ - lib/install/turbo_with_importmap.rb
61
+ - lib/install/turbo_with_node.rb
62
62
  - lib/tasks/turbo_tasks.rake
63
63
  - lib/turbo-rails.rb
64
64
  - lib/turbo/engine.rb
@@ -1,20 +0,0 @@
1
- if (app_js_path = Rails.root.join("app/javascript/application.js")).exist?
2
- say "Import turbo-rails in existing app/javascript/application.js"
3
- append_to_file app_js_path, %(import "@hotwired/turbo-rails"\n)
4
- else
5
- say <<~INSTRUCTIONS, :red
6
- You must import @hotwired/turbo-rails in your application.js.
7
- INSTRUCTIONS
8
- end
9
-
10
- if (importmap_path = Rails.root.join("config/importmap.rb")).exist?
11
- say "Pin @hotwired/turbo-rails in config/importmap.rb"
12
- append_to_file importmap_path.to_s, %(pin "@hotwired/turbo-rails", to: "turbo.js"\n)
13
- else
14
- say <<~INSTRUCTIONS, :red
15
- You must add @hotwired/turbo-rails to your importmap to reference them via ESM.
16
- Example: pin "@hotwired/turbo-rails", to: "turbo.js"
17
- INSTRUCTIONS
18
- end
19
-
20
- say "Run turbo:install:redis to switch on Redis and use it in development for turbo streams", :red
@@ -1,7 +0,0 @@
1
- say "Appending Turbo setup code to #{Webpacker.config.source_entry_path}/application.js"
2
- append_to_file "#{Webpacker.config.source_entry_path}/application.js", %(\nimport "@hotwired/turbo-rails"\n)
3
-
4
- say "Install Turbo"
5
- run "yarn add @hotwired/turbo-rails"
6
-
7
- say "Run turbo:install:redis to switch on Redis and use it in development for turbo streams"