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.
@@ -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.assets" do
23
- if Rails.application.config.respond_to?(:assets)
24
- Rails.application.config.assets.precompile += %w[hotwire-livereload.js hotwire-livereload-turbo-stream.js]
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.helpers" do
29
- ActiveSupport.on_load(:action_controller_base) do
30
- helper Hotwire::Livereload::LivereloadTagsHelper
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.set_configs" do |app|
35
- options = app.config.hotwire_livereload
36
- skip_listen_paths = options.skip_listen_paths.map(&:to_s).uniq
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
- unless options.disable_default_listeners
39
- default_listen_paths = %w[
40
- app/views
41
- app/helpers
42
- app/javascript
43
- app/assets/stylesheets
44
- app/assets/javascripts
45
- app/assets/images
46
- app/components
47
- config/locales
48
- ]
49
- if defined?(Jsbundling)
50
- default_listen_paths -= %w[app/javascript]
51
- default_listen_paths += %w[app/assets/builds]
52
- end
53
- if defined?(Cssbundling)
54
- default_listen_paths -= %w[app/assets/stylesheets]
55
- default_listen_paths += %w[app/assets/builds]
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 Rails.env.development? && Hotwire::Livereload.server_process?
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 Rails.env.development?
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
@@ -1,5 +1,5 @@
1
1
  module Hotwire
2
2
  module Livereload
3
- VERSION = "1.4.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -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: 1.4.0
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-04-30 00:00:00.000000000 Z
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: 6.0.0
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: 6.0.0
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: 6.0.0
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: 6.0.0
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
@@ -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