hotwire-livereload 0.3.0 → 1.2.0

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: a4397b862ba6f621e8442f674fbf5ffa478422e8d01b293f299afbd8213154ac
4
- data.tar.gz: e9e4a35a16d3f09c9f88467e2e0267ee98220d6be0ddda7bd28fc9b3cb8bff95
3
+ metadata.gz: cdb5e0a8c1342dc5af1e3a27db5ddf0bda5cc2a9ce76c14c5394ab8663738fe2
4
+ data.tar.gz: 7fb9d5acc0fdaf8e27fa2b7f59efb0d721e5fe3b49c979f7e8f4984963d8f0cd
5
5
  SHA512:
6
- metadata.gz: 71e11b2197803862c7afb86717f6ccc753ddd60923e7f330b715af28f2263fe49e8baa839bf6d7110ff5bf6dfddeba49c84c7182ea5edc54400c9597e7cbd0ec
7
- data.tar.gz: a847e23ec3f9eb51ba0f7a7cc3d9ee112980b5eae0ae250e5d82505c19cebd97f6849c01a058d227946d9c075c043cca5909120aa09cc3f95fafa4e121233fe9
6
+ metadata.gz: 2a52ac26354b673196a82b73092c9db51ad6dd77a0da1024d74c4193afb6e21abd981e7fc6b66f1b37d314ff2ce98b2e653e209a1047b5e3c0488ebd316b99ea
7
+ data.tar.gz: 002a116713b349590ed9f6c288b1290ab7760e7d128e878d8373abac46dba9bfc638fdadb3dc0d7b3d8e60cec2021315dc2a1e6a29012242c6f26cd7e9404722
data/README.md CHANGED
@@ -1,16 +1,18 @@
1
1
  # Hotwire::Livereload
2
2
 
3
- Automatically reload Hotwire Turbo when "view" files are modified.
3
+ Automatically reload Hotwire Turbo when app files are modified.
4
4
 
5
- https://user-images.githubusercontent.com/839922/131983979-afd0bcc7-86e8-4c53-9758-3bf762dbb16a.mp4
5
+ https://user-images.githubusercontent.com/839922/148676469-0acfa036-832e-4b40-aa05-1fdd945baa1f.mp4
6
6
 
7
- ## Installation
7
+ ## Dependencies
8
8
 
9
- The JavaScript for Hotwire::Livereload is installed via asset pipeline, which is included with this gem.
9
+ * [Redis](https://redis.io/)
10
+
11
+ ## Getting started
10
12
 
11
13
  Add `hotwire-livereload` to your Gemfile:
12
14
  ```
13
- bundle add hotwire-livereload --group development
15
+ bundle add hotwire-livereload
14
16
  ```
15
17
 
16
18
  Run installer:
@@ -18,9 +20,19 @@ Run installer:
18
20
  rails livereload:install
19
21
  ```
20
22
 
23
+ Folders listened by default:
24
+ - `app/views`
25
+ - `app/helpers`
26
+ - `app/javascript`
27
+ - `app/assets/stylesheets`
28
+ - `app/assets/javascripts`
29
+ - `app/assets/images`
30
+ - `app/components`
31
+ - `config/locales`
32
+
21
33
  ## Configuration
22
34
 
23
- You can watch for changes in additional folders by adding them to `listen_paths`. For example, you can watch for CSS changes:
35
+ You can watch for changes in additional folders by adding them to `listen_paths`:
24
36
  ```ruby
25
37
  # config/environments/development.rb
26
38
 
@@ -30,26 +42,52 @@ Rails.application.configure do
30
42
  end
31
43
  ```
32
44
 
33
- Folders listened by default:
34
- - `app/views`
35
- - `app/helpers`
36
- - `app/javascript`
37
- - `app/assets/stylesheets`
38
- - `app/assets/javascripts`
39
- - `app/assets/images`
40
- - `app/components`
41
- - `config/locales`
45
+ You can disable default listen paths and fully override them:
46
+ ```ruby
47
+ # config/environments/development.rb
48
+
49
+ Rails.application.configure do
50
+ # ...
51
+ config.hotwire_livereload.disable_default_listeners = true
52
+ config.hotwire_livereload.listen_paths = [
53
+ Rails.root.join("app/assets/stylesheets"),
54
+ Rails.root.join("app/javascript")
55
+ ]
56
+ end
57
+ ```
42
58
 
43
- You can setup force reloading (full page reload) for changes in some folders using `force_reload_paths` option. For example, you can trigger force reload on JS changes:
59
+ If you don't have `data-turbo-track="reload"` attribute on your JS and CSS bundles you might need to setup force reloading. This will trigger full browser reloading for JS and CSS files only:
44
60
  ```ruby
45
61
  # config/environments/development.rb
46
62
 
47
63
  Rails.application.configure do
48
64
  # ...
65
+ config.hotwire_livereload.force_reload_paths << Rails.root.join("app/assets/stylesheets")
49
66
  config.hotwire_livereload.force_reload_paths << Rails.root.join("app/javascript")
50
67
  end
51
68
  ```
52
69
 
70
+ Instead of a direct ActionCable websocket connection, you can reuse the existing TurboStream websocket connection and send updates using standard turbo-streams:
71
+ ```ruby
72
+ # config/environments/development.rb
73
+
74
+ Rails.application.configure do
75
+ # ...
76
+ config.hotwire_livereload.reload_method = :turbo_stream
77
+ end
78
+ ```
79
+
80
+ In that case you need to place `hotwire_livereload_tags` helper in your layout *after* the `<%= action_cable_meta_tag %>`.
81
+
82
+ ```diff
83
+ <head>
84
+ ...
85
+ <%= action_cable_meta_tag %>
86
+ + <%= hotwire_livereload_tags if Rails.env.development? %>
87
+ ...
88
+ </head>
89
+ ```
90
+
53
91
  ## Disable livereload
54
92
 
55
93
  To temporarily disable livereload use:
@@ -0,0 +1,104 @@
1
+ (() => {
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __reExport = (target, module, desc) => {
13
+ if (module && typeof module === "object" || typeof module === "function") {
14
+ for (let key of __getOwnPropNames(module))
15
+ if (!__hasOwnProp.call(target, key) && key !== "default")
16
+ __defProp(target, key, { get: () => module[key], enumerable: !(desc = __getOwnPropDesc(module, key)) || desc.enumerable });
17
+ }
18
+ return target;
19
+ };
20
+ var __toModule = (module) => {
21
+ return __reExport(__markAsModule(__defProp(module != null ? __create(__getProtoOf(module)) : {}, "default", module && module.__esModule && "default" in module ? { get: () => module.default, enumerable: true } : { value: module, enumerable: true })), module);
22
+ };
23
+
24
+ // node_modules/debounce/index.js
25
+ var require_debounce = __commonJS({
26
+ "node_modules/debounce/index.js"(exports, module) {
27
+ function debounce2(func, wait, immediate) {
28
+ var timeout, args, context, timestamp, result;
29
+ if (wait == null)
30
+ wait = 100;
31
+ function later() {
32
+ var last = Date.now() - timestamp;
33
+ if (last < wait && last >= 0) {
34
+ timeout = setTimeout(later, wait - last);
35
+ } else {
36
+ timeout = null;
37
+ if (!immediate) {
38
+ result = func.apply(context, args);
39
+ context = args = null;
40
+ }
41
+ }
42
+ }
43
+ ;
44
+ var debounced = function() {
45
+ context = this;
46
+ args = arguments;
47
+ timestamp = Date.now();
48
+ var callNow = immediate && !timeout;
49
+ if (!timeout)
50
+ timeout = setTimeout(later, wait);
51
+ if (callNow) {
52
+ result = func.apply(context, args);
53
+ context = args = null;
54
+ }
55
+ return result;
56
+ };
57
+ debounced.clear = function() {
58
+ if (timeout) {
59
+ clearTimeout(timeout);
60
+ timeout = null;
61
+ }
62
+ };
63
+ debounced.flush = function() {
64
+ if (timeout) {
65
+ result = func.apply(context, args);
66
+ context = args = null;
67
+ clearTimeout(timeout);
68
+ timeout = null;
69
+ }
70
+ };
71
+ return debounced;
72
+ }
73
+ debounce2.debounce = debounce2;
74
+ module.exports = debounce2;
75
+ }
76
+ });
77
+
78
+ // app/javascript/lib/hotwire-livereload-received.js
79
+ var import_debounce = __toModule(require_debounce());
80
+ var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => {
81
+ const onErrorPage = document.title === "Action Controller: Exception caught";
82
+ if (onErrorPage || force_reload) {
83
+ console.log("[Hotwire::Livereload] Files changed. Force reloading..");
84
+ document.location.reload();
85
+ } else {
86
+ console.log("[Hotwire::Livereload] Files changed. Reloading..");
87
+ Turbo.visit(window.location.href, { action: "replace" });
88
+ }
89
+ }, 300);
90
+
91
+ // app/javascript/hotwire-livereload-turbo-stream.js
92
+ (() => {
93
+ if (window.HotwireLivereload) {
94
+ return;
95
+ }
96
+ window.HotwireLivereload = function({ target }) {
97
+ const element = target.querySelector("template")?.content.getElementById("hotwire-livereload");
98
+ if (element) {
99
+ hotwire_livereload_received_default({ force_reload: element.dataset.forceReload });
100
+ }
101
+ };
102
+ document.addEventListener("turbo:before-stream-render", window.HotwireLivereload);
103
+ })();
104
+ })();
@@ -599,20 +599,24 @@
599
599
 
600
600
  // app/javascript/hotwire-livereload.js
601
601
  var import_actioncable = __toModule(require_action_cable());
602
+
603
+ // app/javascript/lib/hotwire-livereload-received.js
602
604
  var import_debounce = __toModule(require_debounce());
603
- var consumer = (0, import_actioncable.createConsumer)();
604
- var received = (0, import_debounce.default)(({ force_reload }) => {
605
+ var hotwire_livereload_received_default = (0, import_debounce.default)(({ force_reload }) => {
605
606
  const onErrorPage = document.title === "Action Controller: Exception caught";
606
607
  if (onErrorPage || force_reload) {
607
608
  console.log("[Hotwire::Livereload] Files changed. Force reloading..");
608
609
  document.location.reload();
609
610
  } else {
610
611
  console.log("[Hotwire::Livereload] Files changed. Reloading..");
611
- Turbo.visit(window.location.href);
612
+ Turbo.visit(window.location.href, { action: "replace" });
612
613
  }
613
614
  }, 300);
615
+
616
+ // app/javascript/hotwire-livereload.js
617
+ var consumer = (0, import_actioncable.createConsumer)();
614
618
  consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
615
- received,
619
+ received: hotwire_livereload_received_default,
616
620
  connected() {
617
621
  console.log("[Hotwire::Livereload] Websocket connected");
618
622
  },
@@ -1,3 +1,5 @@
1
+ return if Hotwire::Livereload::Engine.config.hotwire_livereload.reload_method == :turbo_stream
2
+
1
3
  class Hotwire::Livereload::ReloadChannel < ActionCable::Channel::Base
2
4
  def subscribed
3
5
  stream_from "hotwire-reload"
@@ -1,7 +1,11 @@
1
1
  module Hotwire::Livereload::LivereloadTagsHelper
2
2
  def hotwire_livereload_tags
3
- return unless Rails.env.development?
3
+ partial = if Hotwire::Livereload::Engine.config.hotwire_livereload.reload_method == :turbo_stream
4
+ 'hotwire/livereload/head_turbo_stream'
5
+ else
6
+ 'hotwire/livereload/head_action_cable'
7
+ end
4
8
 
5
- javascript_include_tag "hotwire-livereload", defer: true
9
+ render partial
6
10
  end
7
11
  end
@@ -0,0 +1,15 @@
1
+ import received from "./lib/hotwire-livereload-received"
2
+
3
+ (() => {
4
+ if(window.HotwireLivereload){ return; }
5
+
6
+ window.HotwireLivereload = function({ target }) {
7
+ const element = target.querySelector('template')?.content.getElementById('hotwire-livereload')
8
+ if (element) {
9
+ received({ force_reload: element.dataset.forceReload })
10
+ }
11
+ };
12
+
13
+ document.addEventListener('turbo:before-stream-render', window.HotwireLivereload);
14
+ })();
15
+
@@ -1,19 +1,7 @@
1
1
  import { createConsumer } from "@rails/actioncable"
2
- import debounce from "debounce"
2
+ import received from "./lib/hotwire-livereload-received"
3
3
 
4
4
  const consumer = createConsumer()
5
- const received = debounce(({force_reload}) => {
6
- const onErrorPage = document.title === "Action Controller: Exception caught"
7
-
8
- if (onErrorPage || force_reload) {
9
- console.log("[Hotwire::Livereload] Files changed. Force reloading..")
10
- document.location.reload()
11
- } else {
12
- console.log("[Hotwire::Livereload] Files changed. Reloading..")
13
- Turbo.visit(window.location.href)
14
- }
15
- }, 300)
16
-
17
5
  consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
18
6
  received,
19
7
 
@@ -0,0 +1,13 @@
1
+ import debounce from "debounce"
2
+
3
+ export default debounce(({force_reload}) => {
4
+ const onErrorPage = document.title === "Action Controller: Exception caught"
5
+
6
+ if (onErrorPage || force_reload) {
7
+ console.log("[Hotwire::Livereload] Files changed. Force reloading..")
8
+ document.location.reload()
9
+ } else {
10
+ console.log("[Hotwire::Livereload] Files changed. Reloading..")
11
+ Turbo.visit(window.location.href, { action: 'replace' })
12
+ }
13
+ }, 300)
@@ -0,0 +1,3 @@
1
+ <% if Rails.env.development? %>
2
+ <%= javascript_include_tag('hotwire-livereload', defer: true) %>
3
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <% if Rails.env.development? %>
2
+ <%= turbo_stream_from('hotwire-livereload') %>
3
+ <%= javascript_include_tag('hotwire-livereload-turbo-stream', defer: true) %>
4
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <%= tag.div(id: 'hotwire-livereload', data: {
2
+ changed: changed.to_json,
3
+ force_reload: force_reload || nil
4
+ }) %>
@@ -9,6 +9,8 @@ module Hotwire
9
9
  config.hotwire_livereload = ActiveSupport::OrderedOptions.new
10
10
  config.hotwire_livereload.listen_paths ||= []
11
11
  config.hotwire_livereload.force_reload_paths ||= []
12
+ config.hotwire_livereload.reload_method = :action_cable
13
+ config.hotwire_livereload.disable_default_listeners = false
12
14
  config.autoload_once_paths = %W(
13
15
  #{root}/app/channels
14
16
  #{root}/app/helpers
@@ -16,7 +18,7 @@ module Hotwire
16
18
 
17
19
  initializer "hotwire_livereload.assets" do
18
20
  if Rails.application.config.respond_to?(:assets)
19
- Rails.application.config.assets.precompile += %w( hotwire-livereload.js )
21
+ Rails.application.config.assets.precompile += %w( hotwire-livereload.js hotwire-livereload-turbo-stream.js)
20
22
  end
21
23
  end
22
24
 
@@ -27,19 +29,21 @@ module Hotwire
27
29
  end
28
30
 
29
31
  initializer "hotwire_livereload.set_configs" do |app|
30
- default_listen_paths = %w[
31
- app/views
32
- app/helpers
33
- app/javascript
34
- app/assets/stylesheets
35
- app/assets/javascripts
36
- app/assets/images
37
- app/components
38
- config/locales
39
- ].map { |p| Rails.root.join(p) }
40
-
41
32
  options = app.config.hotwire_livereload
42
- options.listen_paths += default_listen_paths.select { |p| Dir.exist?(p) }
33
+
34
+ unless options.disable_default_listeners
35
+ default_listen_paths = %w[
36
+ app/views
37
+ app/helpers
38
+ app/javascript
39
+ app/assets/stylesheets
40
+ app/assets/javascripts
41
+ app/assets/images
42
+ app/components
43
+ config/locales
44
+ ].map { |p| Rails.root.join(p) }
45
+ options.listen_paths += default_listen_paths.select { |p| Dir.exist?(p) }
46
+ end
43
47
  end
44
48
 
45
49
  config.after_initialize do |app|
@@ -57,10 +61,12 @@ module Hotwire
57
61
  path.match(%r{#{force_reload_paths}})
58
62
  end
59
63
 
60
- ActionCable.server.broadcast("hotwire-reload", {
61
- changed: changed,
62
- force_reload: force_reload
63
- })
64
+ options = {changed: changed, force_reload: force_reload}
65
+ if config.hotwire_livereload.reload_method == :turbo_stream
66
+ Hotwire::Livereload.turbo_stream(options)
67
+ else
68
+ Hotwire::Livereload.action_cable(options)
69
+ end
64
70
  end
65
71
  end
66
72
  @listener.start
@@ -73,5 +79,16 @@ module Hotwire
73
79
  end
74
80
  end
75
81
  end
82
+
83
+ def self.turbo_stream(locals)
84
+ Turbo::StreamsChannel.broadcast_replace_to('hotwire-livereload',
85
+ target: 'hotwire-livereload',
86
+ partial: 'hotwire/livereload/turbo_stream',
87
+ locals: locals)
88
+ end
89
+
90
+ def self.action_cable(opts)
91
+ ActionCable.server.broadcast("hotwire-reload", opts)
92
+ end
76
93
  end
77
94
  end
@@ -1,5 +1,5 @@
1
1
  module Hotwire
2
2
  module Livereload
3
- VERSION = "0.3.0"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
@@ -4,21 +4,20 @@ CABLE_CONFIG_PATH = Rails.root.join("config/cable.yml")
4
4
  if APP_LAYOUT_PATH.exist?
5
5
  say "Add Hotwire Livereload tag in application layout"
6
6
  content = <<-HTML
7
- \n <% if Rails.env.development? %>
8
- <%= javascript_include_tag "hotwire-livereload", defer: true %>
9
- <% end %>
7
+ \n <%= hotwire_livereload_tags if Rails.env.development? %>
10
8
  HTML
11
9
  insert_into_file APP_LAYOUT_PATH, content.chop, before: /\s*<\/head>/
12
10
  else
13
11
  say "Default application.html.erb is missing!", :red
14
12
  say %( Add <%= hotwire_livereload_tags %> within the <head> tag in your custom layout.)
13
+ say %( If using `config.hotwire_livereload.reload_method = :turbo_stream`, place *after* the `<%= action_cable_meta_tag %>`.)
15
14
  end
16
15
 
17
16
  if CABLE_CONFIG_PATH.exist?
18
17
  gemfile = File.read(Rails.root.join("Gemfile"))
19
18
  if gemfile.include?("redis")
20
19
  say "Uncomment redis in Gemfile"
21
- uncomment_lines "Gemfile", %(gem "redis")
20
+ uncomment_lines "Gemfile", %r{gem ['"]redis['"]}
22
21
  else
23
22
  say "Add redis to Gemfile"
24
23
  gem "redis"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire-livereload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Platonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-29 00:00:00.000000000 Z
11
+ date: 2022-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -47,10 +47,16 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - MIT-LICENSE
49
49
  - README.md
50
+ - app/assets/javascripts/hotwire-livereload-turbo-stream.js
50
51
  - app/assets/javascripts/hotwire-livereload.js
51
52
  - app/channels/hotwire/livereload/reload_channel.rb
52
53
  - app/helpers/hotwire/livereload/livereload_tags_helper.rb
54
+ - app/javascript/hotwire-livereload-turbo-stream.js
53
55
  - app/javascript/hotwire-livereload.js
56
+ - app/javascript/lib/hotwire-livereload-received.js
57
+ - app/views/hotwire/livereload/_head_action_cable.html.erb
58
+ - app/views/hotwire/livereload/_head_turbo_stream.html.erb
59
+ - app/views/hotwire/livereload/_turbo_stream.html.erb
54
60
  - lib/hotwire/livereload.rb
55
61
  - lib/hotwire/livereload/engine.rb
56
62
  - lib/hotwire/livereload/version.rb
@@ -75,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
81
  - !ruby/object:Gem::Version
76
82
  version: '0'
77
83
  requirements: []
78
- rubygems_version: 3.2.32
84
+ rubygems_version: 3.3.15
79
85
  signing_key:
80
86
  specification_version: 4
81
87
  summary: Automatically reload Hotwire Turbo when app files are modified.