hotwire-livereload 1.1.0 → 1.2.0
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/README.md +27 -2
- data/app/assets/javascripts/hotwire-livereload-turbo-stream.js +104 -0
- data/app/assets/javascripts/hotwire-livereload.js +8 -4
- data/app/channels/hotwire/livereload/reload_channel.rb +2 -0
- data/app/helpers/hotwire/livereload/livereload_tags_helper.rb +6 -2
- data/app/javascript/hotwire-livereload-turbo-stream.js +15 -0
- data/app/javascript/hotwire-livereload.js +1 -13
- data/app/javascript/lib/hotwire-livereload-received.js +13 -0
- data/app/views/hotwire/livereload/_head_action_cable.html.erb +3 -0
- data/app/views/hotwire/livereload/_head_turbo_stream.html.erb +4 -0
- data/app/views/hotwire/livereload/_turbo_stream.html.erb +4 -0
- data/lib/hotwire/livereload/engine.rb +19 -5
- data/lib/hotwire/livereload/version.rb +1 -1
- data/lib/install/install.rb +3 -4
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdb5e0a8c1342dc5af1e3a27db5ddf0bda5cc2a9ce76c14c5394ab8663738fe2
|
4
|
+
data.tar.gz: 7fb9d5acc0fdaf8e27fa2b7f59efb0d721e5fe3b49c979f7e8f4984963d8f0cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a52ac26354b673196a82b73092c9db51ad6dd77a0da1024d74c4193afb6e21abd981e7fc6b66f1b37d314ff2ce98b2e653e209a1047b5e3c0488ebd316b99ea
|
7
|
+
data.tar.gz: 002a116713b349590ed9f6c288b1290ab7760e7d128e878d8373abac46dba9bfc638fdadb3dc0d7b3d8e60cec2021315dc2a1e6a29012242c6f26cd7e9404722
|
data/README.md
CHANGED
@@ -4,11 +4,15 @@ Automatically reload Hotwire Turbo when app files are modified.
|
|
4
4
|
|
5
5
|
https://user-images.githubusercontent.com/839922/148676469-0acfa036-832e-4b40-aa05-1fdd945baa1f.mp4
|
6
6
|
|
7
|
-
##
|
7
|
+
## Dependencies
|
8
|
+
|
9
|
+
* [Redis](https://redis.io/)
|
10
|
+
|
11
|
+
## Getting started
|
8
12
|
|
9
13
|
Add `hotwire-livereload` to your Gemfile:
|
10
14
|
```
|
11
|
-
bundle add hotwire-livereload
|
15
|
+
bundle add hotwire-livereload
|
12
16
|
```
|
13
17
|
|
14
18
|
Run installer:
|
@@ -63,6 +67,27 @@ Rails.application.configure do
|
|
63
67
|
end
|
64
68
|
```
|
65
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
|
+
|
66
91
|
## Disable livereload
|
67
92
|
|
68
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
|
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,7 +1,11 @@
|
|
1
1
|
module Hotwire::Livereload::LivereloadTagsHelper
|
2
2
|
def hotwire_livereload_tags
|
3
|
-
|
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
|
-
|
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
|
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)
|
@@ -9,6 +9,7 @@ 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
|
12
13
|
config.hotwire_livereload.disable_default_listeners = false
|
13
14
|
config.autoload_once_paths = %W(
|
14
15
|
#{root}/app/channels
|
@@ -17,7 +18,7 @@ module Hotwire
|
|
17
18
|
|
18
19
|
initializer "hotwire_livereload.assets" do
|
19
20
|
if Rails.application.config.respond_to?(:assets)
|
20
|
-
Rails.application.config.assets.precompile += %w( hotwire-livereload.js )
|
21
|
+
Rails.application.config.assets.precompile += %w( hotwire-livereload.js hotwire-livereload-turbo-stream.js)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -60,10 +61,12 @@ module Hotwire
|
|
60
61
|
path.match(%r{#{force_reload_paths}})
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
67
70
|
end
|
68
71
|
end
|
69
72
|
@listener.start
|
@@ -76,5 +79,16 @@ module Hotwire
|
|
76
79
|
end
|
77
80
|
end
|
78
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
|
79
93
|
end
|
80
94
|
end
|
data/lib/install/install.rb
CHANGED
@@ -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
|
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", %
|
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: 1.
|
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: 2022-
|
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.
|
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.
|