hotwire-livereload 1.4.0 → 2.0.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 +11 -27
- data/app/assets/javascripts/hotwire-livereload.js +466 -582
- data/app/javascript/hotwire-livereload.js +1 -2
- data/lib/hotwire/livereload/cable_server.rb +11 -0
- data/lib/hotwire/livereload/engine.rb +48 -84
- data/lib/hotwire/livereload/middleware.rb +56 -0
- data/lib/hotwire/livereload/version.rb +1 -1
- data/lib/hotwire/livereload.rb +62 -0
- data/lib/tasks/livereload_tasks.rake +0 -5
- metadata +8 -8
- data/app/helpers/hotwire/livereload/livereload_tags_helper.rb +0 -11
- data/lib/install/install.rb +0 -30
@@ -2,7 +2,7 @@ import { createConsumer } from "@rails/actioncable"
|
|
2
2
|
import received from "./lib/hotwire-livereload-received"
|
3
3
|
import scrollPosition from "./lib/hotwire-livereload-scroll-position"
|
4
4
|
|
5
|
-
const consumer = createConsumer()
|
5
|
+
const consumer = createConsumer("/hotwire-livereload")
|
6
6
|
consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
|
7
7
|
received,
|
8
8
|
|
@@ -19,4 +19,3 @@ document.addEventListener("turbo:load", () => {
|
|
19
19
|
scrollPosition.restore()
|
20
20
|
scrollPosition.remove()
|
21
21
|
})
|
22
|
-
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hotwire
|
2
|
+
module Livereload
|
3
|
+
class CableServer < ActionCable::Server::Base
|
4
|
+
def initialize
|
5
|
+
config = ::ActionCable::Server::Base.config.dup
|
6
|
+
config.connection_class = -> { ::ActionCable::Connection::Base }
|
7
|
+
super(config: config)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -1,69 +1,75 @@
|
|
1
|
-
require "rails"
|
2
|
-
require "action_cable/engine"
|
3
|
-
require "listen"
|
4
|
-
|
5
1
|
module Hotwire
|
6
2
|
module Livereload
|
7
3
|
class Engine < ::Rails::Engine
|
8
4
|
isolate_namespace Hotwire::Livereload
|
5
|
+
|
9
6
|
config.hotwire_livereload = ActiveSupport::OrderedOptions.new
|
10
7
|
config.hotwire_livereload.listen_paths ||= []
|
11
8
|
config.hotwire_livereload.skip_listen_paths ||= []
|
12
9
|
config.hotwire_livereload.force_reload_paths ||= []
|
13
10
|
config.hotwire_livereload.reload_method = :action_cable
|
14
11
|
config.hotwire_livereload.disable_default_listeners = false
|
15
|
-
config.autoload_once_paths = %W[
|
16
|
-
#{root}/app/channels
|
17
|
-
#{root}/app/helpers
|
18
|
-
]
|
12
|
+
config.autoload_once_paths = %W[#{root}/app/channels]
|
19
13
|
config.hotwire_livereload.listen_options ||= {}
|
20
14
|
config.hotwire_livereload.debounce_delay_ms = 0
|
21
15
|
|
22
|
-
initializer "hotwire_livereload.
|
23
|
-
if
|
24
|
-
|
16
|
+
initializer "hotwire_livereload.middleware" do
|
17
|
+
if Hotwire::Livereload.enabled?
|
18
|
+
config.app_middleware.insert_after ActionDispatch::Executor, Hotwire::Livereload::Middleware
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
28
|
-
initializer "hotwire_livereload.
|
29
|
-
|
30
|
-
|
22
|
+
initializer "hotwire_livereload.routes" do
|
23
|
+
if Hotwire::Livereload.enabled?
|
24
|
+
config.after_initialize do |app|
|
25
|
+
app.routes.prepend do
|
26
|
+
mount Hotwire::Livereload.cable_server => "/hotwire-livereload", :internal => true, :anchor => true
|
27
|
+
end
|
28
|
+
end
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
initializer "hotwire_livereload.
|
35
|
-
|
36
|
-
|
32
|
+
initializer "hotwire_livereload.assets" do
|
33
|
+
if Hotwire::Livereload.enabled? && Rails.application.config.respond_to?(:assets)
|
34
|
+
Rails.application.config.assets.precompile += %w[hotwire-livereload.js hotwire-livereload-turbo-stream.js]
|
35
|
+
end
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
38
|
+
initializer "hotwire_livereload.set_configs" do |app|
|
39
|
+
if Hotwire::Livereload.enabled?
|
40
|
+
options = app.config.hotwire_livereload
|
41
|
+
skip_listen_paths = options.skip_listen_paths.map(&:to_s).uniq
|
42
|
+
|
43
|
+
unless options.disable_default_listeners
|
44
|
+
default_listen_paths = %w[
|
45
|
+
app/views
|
46
|
+
app/helpers
|
47
|
+
app/javascript
|
48
|
+
app/assets/stylesheets
|
49
|
+
app/assets/javascripts
|
50
|
+
app/assets/images
|
51
|
+
app/components
|
52
|
+
config/locales
|
53
|
+
]
|
54
|
+
if defined?(Jsbundling)
|
55
|
+
default_listen_paths -= %w[app/javascript]
|
56
|
+
default_listen_paths += %w[app/assets/builds]
|
57
|
+
end
|
58
|
+
if defined?(Cssbundling)
|
59
|
+
default_listen_paths -= %w[app/assets/stylesheets]
|
60
|
+
default_listen_paths += %w[app/assets/builds]
|
61
|
+
end
|
62
|
+
options.listen_paths += default_listen_paths
|
63
|
+
.uniq
|
64
|
+
.map { |p| Rails.root.join(p) }
|
65
|
+
.select { |p| Dir.exist?(p) }
|
66
|
+
.reject { |p| skip_listen_paths.include?(p.to_s) }
|
56
67
|
end
|
57
|
-
options.listen_paths += default_listen_paths
|
58
|
-
.uniq
|
59
|
-
.map { |p| Rails.root.join(p) }
|
60
|
-
.select { |p| Dir.exist?(p) }
|
61
|
-
.reject { |p| skip_listen_paths.include?(p.to_s) }
|
62
68
|
end
|
63
69
|
end
|
64
70
|
|
65
71
|
config.after_initialize do |app|
|
66
|
-
if
|
72
|
+
if Hotwire::Livereload.enabled?
|
67
73
|
@trigger_reload = (Hotwire::Livereload.debounce(config.hotwire_livereload.debounce_delay_ms) do |options|
|
68
74
|
if config.hotwire_livereload.reload_method == :turbo_stream
|
69
75
|
Hotwire::Livereload.turbo_stream(options)
|
@@ -94,52 +100,10 @@ module Hotwire
|
|
94
100
|
end
|
95
101
|
|
96
102
|
at_exit do
|
97
|
-
if
|
103
|
+
if Hotwire::Livereload.enabled?
|
98
104
|
@listener&.stop
|
99
105
|
end
|
100
106
|
end
|
101
107
|
end
|
102
|
-
|
103
|
-
def self.turbo_stream(locals)
|
104
|
-
Turbo::StreamsChannel.broadcast_replace_to(
|
105
|
-
"hotwire-livereload",
|
106
|
-
target: "hotwire-livereload",
|
107
|
-
partial: "hotwire/livereload/turbo_stream",
|
108
|
-
locals: locals
|
109
|
-
)
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.action_cable(opts)
|
113
|
-
ActionCable.server.broadcast("hotwire-reload", opts)
|
114
|
-
end
|
115
|
-
|
116
|
-
def self.server_process?
|
117
|
-
puma_process = defined?(::Puma) && File.basename($0) == "puma"
|
118
|
-
rails_server = defined?(Rails::Server)
|
119
|
-
|
120
|
-
puma_process || rails_server
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.debounce(wait_ms, &block)
|
124
|
-
if wait_ms.zero?
|
125
|
-
return ->(*args) { yield(*args) }
|
126
|
-
end
|
127
|
-
|
128
|
-
mutex = Mutex.new
|
129
|
-
timer_thread = nil
|
130
|
-
seconds = wait_ms.to_f / 1000.0
|
131
|
-
|
132
|
-
lambda do |*args|
|
133
|
-
mutex.synchronize do
|
134
|
-
# Cancel previous timer
|
135
|
-
timer_thread&.kill
|
136
|
-
|
137
|
-
timer_thread = Thread.new do
|
138
|
-
sleep(seconds)
|
139
|
-
yield(*args)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
108
|
end
|
145
109
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Hotwire
|
2
|
+
module Livereload
|
3
|
+
class Middleware
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
request = ActionDispatch::Request.new(env)
|
10
|
+
status, headers, response = @app.call(env)
|
11
|
+
|
12
|
+
if html_response?(headers)
|
13
|
+
body = get_response_body(response)
|
14
|
+
if body&.include?("</head>")
|
15
|
+
body = inject_livereload_scripts(body, request)
|
16
|
+
headers["Content-Length"] = body.bytesize.to_s
|
17
|
+
response = [body]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
[status, headers, response]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def html_response?(headers)
|
27
|
+
headers["content-type"]&.include?("text/html")
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_response_body(response)
|
31
|
+
parts = []
|
32
|
+
response.each { |part| parts << part.to_s }
|
33
|
+
parts.join
|
34
|
+
end
|
35
|
+
|
36
|
+
def inject_livereload_scripts(body, request)
|
37
|
+
body.sub("</head>", "#{livereload_scripts(request)}</head>")
|
38
|
+
end
|
39
|
+
|
40
|
+
def view_helpers
|
41
|
+
ActionController::Base.helpers
|
42
|
+
end
|
43
|
+
|
44
|
+
def livereload_scripts(request)
|
45
|
+
if Hotwire::Livereload::Engine.config.hotwire_livereload.reload_method == :turbo_stream
|
46
|
+
view_helpers.safe_join [
|
47
|
+
view_helpers.turbo_stream_from("hotwire-livereload"),
|
48
|
+
view_helpers.javascript_include_tag("hotwire-livereload-turbo-stream", defer: true, nonce: request&.content_security_policy_nonce)
|
49
|
+
], "\n"
|
50
|
+
else
|
51
|
+
view_helpers.javascript_include_tag("hotwire-livereload", defer: true, nonce: request&.content_security_policy_nonce)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/hotwire/livereload.rb
CHANGED
@@ -1,7 +1,69 @@
|
|
1
|
+
# dependencies
|
2
|
+
require "rails"
|
3
|
+
require "action_cable/engine"
|
4
|
+
require "action_cable/server/base"
|
5
|
+
require "listen"
|
6
|
+
|
7
|
+
# modules
|
8
|
+
require "hotwire/livereload/cable_server"
|
9
|
+
require "hotwire/livereload/middleware"
|
10
|
+
require "hotwire/livereload/version"
|
1
11
|
require "hotwire/livereload/engine"
|
2
12
|
|
3
13
|
module Hotwire
|
4
14
|
module Livereload
|
5
15
|
DISABLE_FILE = "tmp/livereload-disabled.txt"
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def turbo_stream(locals)
|
19
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
20
|
+
"hotwire-livereload",
|
21
|
+
target: "hotwire-livereload",
|
22
|
+
partial: "hotwire/livereload/turbo_stream",
|
23
|
+
locals: locals
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cable_server
|
28
|
+
@cable_server ||= Hotwire::Livereload::CableServer.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def action_cable(opts)
|
32
|
+
cable_server.broadcast("hotwire-reload", opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def server_process?
|
36
|
+
puma_process = defined?(::Puma) && File.basename($0) == "puma"
|
37
|
+
rails_server = defined?(Rails::Server)
|
38
|
+
|
39
|
+
!!(puma_process || rails_server)
|
40
|
+
end
|
41
|
+
|
42
|
+
def enabled?
|
43
|
+
Rails.env.development? && server_process?
|
44
|
+
end
|
45
|
+
|
46
|
+
def debounce(wait_ms, &block)
|
47
|
+
if wait_ms.zero?
|
48
|
+
return ->(*args) { yield(*args) }
|
49
|
+
end
|
50
|
+
|
51
|
+
mutex = Mutex.new
|
52
|
+
timer_thread = nil
|
53
|
+
seconds = wait_ms.to_f / 1000.0
|
54
|
+
|
55
|
+
lambda do |*args|
|
56
|
+
mutex.synchronize do
|
57
|
+
# Cancel previous timer
|
58
|
+
timer_thread&.kill
|
59
|
+
|
60
|
+
timer_thread = Thread.new do
|
61
|
+
sleep(seconds)
|
62
|
+
yield(*args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
6
68
|
end
|
7
69
|
end
|
@@ -1,9 +1,4 @@
|
|
1
1
|
namespace :livereload do
|
2
|
-
desc "Install Hotwire::Livereload into the app"
|
3
|
-
task :install do
|
4
|
-
system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/install.rb", __dir__)}"
|
5
|
-
end
|
6
|
-
|
7
2
|
desc "Disable Hotwire::Livereload"
|
8
3
|
task :disable do
|
9
4
|
FileUtils.mkdir_p("tmp")
|
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:
|
4
|
+
version: 2.0.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: 2024-
|
11
|
+
date: 2024-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 7.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 7.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: actioncable
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 7.0.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 7.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: listen
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,7 +64,6 @@ files:
|
|
64
64
|
- app/assets/javascripts/hotwire-livereload-turbo-stream.js
|
65
65
|
- app/assets/javascripts/hotwire-livereload.js
|
66
66
|
- app/channels/hotwire/livereload/reload_channel.rb
|
67
|
-
- app/helpers/hotwire/livereload/livereload_tags_helper.rb
|
68
67
|
- app/javascript/hotwire-livereload-turbo-stream.js
|
69
68
|
- app/javascript/hotwire-livereload.js
|
70
69
|
- app/javascript/lib/hotwire-livereload-received.js
|
@@ -73,9 +72,10 @@ files:
|
|
73
72
|
- app/views/hotwire/livereload/_head_turbo_stream.html.erb
|
74
73
|
- app/views/hotwire/livereload/_turbo_stream.html.erb
|
75
74
|
- lib/hotwire/livereload.rb
|
75
|
+
- lib/hotwire/livereload/cable_server.rb
|
76
76
|
- lib/hotwire/livereload/engine.rb
|
77
|
+
- lib/hotwire/livereload/middleware.rb
|
77
78
|
- lib/hotwire/livereload/version.rb
|
78
|
-
- lib/install/install.rb
|
79
79
|
- lib/tasks/livereload_tasks.rake
|
80
80
|
homepage: https://github.com/kirillplatonov/hotwire-livereload
|
81
81
|
licenses:
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module Hotwire::Livereload::LivereloadTagsHelper
|
2
|
-
def hotwire_livereload_tags
|
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
|
8
|
-
|
9
|
-
render partial
|
10
|
-
end
|
11
|
-
end
|
data/lib/install/install.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
APP_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
|
2
|
-
CABLE_CONFIG_PATH = Rails.root.join("config/cable.yml")
|
3
|
-
|
4
|
-
if APP_LAYOUT_PATH.exist?
|
5
|
-
say "Add Hotwire Livereload tag in application layout"
|
6
|
-
content = <<~HTML
|
7
|
-
\n <%= hotwire_livereload_tags if Rails.env.development? %>
|
8
|
-
HTML
|
9
|
-
insert_into_file APP_LAYOUT_PATH, content.chop, before: /\s*<\/head>/
|
10
|
-
else
|
11
|
-
say "Default application.html.erb is missing!", :red
|
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 %>`.)
|
14
|
-
end
|
15
|
-
|
16
|
-
if CABLE_CONFIG_PATH.exist?
|
17
|
-
gemfile = File.read(Rails.root.join("Gemfile"))
|
18
|
-
if gemfile.include?("redis")
|
19
|
-
say "Uncomment redis in Gemfile"
|
20
|
-
uncomment_lines "Gemfile", %r{gem ['"]redis['"]}
|
21
|
-
else
|
22
|
-
say "Add redis to Gemfile"
|
23
|
-
gem "redis"
|
24
|
-
end
|
25
|
-
|
26
|
-
say "Switch development cable to use redis"
|
27
|
-
gsub_file CABLE_CONFIG_PATH.to_s, /development:\n\s+adapter: async/, "development:\n adapter: redis\n url: redis://localhost:6379/1"
|
28
|
-
else
|
29
|
-
say 'ActionCable config file (config/cable.yml) is missing. Uncomment "gem \'redis\'" in your Gemfile and create config/cable.yml to use Hotwire Livereload.'
|
30
|
-
end
|