turbo-rails 0.7.8 → 0.7.12

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: b462e206a285eef400a2bab8a76a9eb74a9eba0d198acc1629b30095a87fa196
4
- data.tar.gz: 1201d9ad8acb6179db7418850fe4b4afd22089b006d7d88ae23f3c87b918cbd5
3
+ metadata.gz: 85771aa7f175db32f70c6b54ed5ae8ef2dd5e5538bf987b40d68eb6e4699e7b0
4
+ data.tar.gz: 946d4845a3f2478c5ca443507114d9a7fc5231a86ecf17a294dbe40c28b10174
5
5
  SHA512:
6
- metadata.gz: 347aa59be1a2cec371863c180680d01942d1d2f0ada0ec6bdf73f79a9492b5af33bdcb4e58b0de14f9c155cee558583e9821813ef10a9d0c11b30b6fb3cc7638
7
- data.tar.gz: 140dfbfe9c4091351fddce82c3e717563803d3979689ac546b5a41e1215fc668793c4895466be6d37967fb274d674c643075d37945267098c4551723901d1344
6
+ metadata.gz: 41651d40a449a1622e479b2c2950f82149749fce699b88a1a723a77fc3c23af543e491bb2aefafa4ad0cfe5e85db95b7ea8e059d15294db22537b74a39a18ceb
7
+ data.tar.gz: 78f1a8a26ddc16fa9263eac070b7311223decaa69409715f4931f03f410435374a883759e360410f8ae8729c6fd6fdeafbe9d3b9e57211aaa5af677aa9b884a7
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
 
@@ -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
  }
@@ -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.8"
2
+ VERSION = "0.7.12"
3
3
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.8
4
+ version: 0.7.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
8
8
  - Javan Mahkmali
9
9
  - David Heinemeier Hansson
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-30 00:00:00.000000000 Z
13
+ date: 2021-09-15 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -26,7 +26,7 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: 6.0.0
29
- description:
29
+ description:
30
30
  email: david@loudthinking.com
31
31
  executables: []
32
32
  extensions: []
@@ -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
@@ -68,7 +68,7 @@ homepage: https://github.com/hotwired/turbo-rails
68
68
  licenses:
69
69
  - MIT
70
70
  metadata: {}
71
- post_install_message:
71
+ post_install_message:
72
72
  rdoc_options: []
73
73
  require_paths:
74
74
  - lib
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  version: '0'
85
85
  requirements: []
86
86
  rubygems_version: 3.1.4
87
- signing_key:
87
+ signing_key:
88
88
  specification_version: 4
89
89
  summary: The speed of a single-page web application without having to write any JavaScript.
90
90
  test_files: []
@@ -1,23 +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
- insert_into_file \
13
- importmap_path.to_s,
14
- %( pin "@hotwired/turbo-rails", to: "turbo.js"\n\n),
15
- after: "Rails.application.config.importmap.draw do\n"
16
- else
17
- say <<~INSTRUCTIONS, :red
18
- You must add @hotwired/turbo-rails to your importmap to reference them via ESM.
19
- Example: pin "@hotwired/turbo-rails", to: "turbo.js"
20
- INSTRUCTIONS
21
- end
22
-
23
- 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"