hotwire-spark 0.1.9 → 0.1.11
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 +34 -10
- data/app/assets/javascripts/hotwire_spark.js +75 -27
- data/app/assets/javascripts/hotwire_spark.min.js +1 -1
- data/app/assets/javascripts/hotwire_spark.min.js.map +1 -1
- data/app/javascript/hotwire/spark/channels/monitoring_channel.js +10 -9
- data/app/javascript/hotwire/spark/index.js +10 -2
- data/app/javascript/hotwire/spark/reloaders/{html_reloader.js → morph_html_reloader.js} +8 -8
- data/app/javascript/hotwire/spark/reloaders/replace_html_reloader.js +31 -0
- data/app/javascript/hotwire/spark/reloaders/stimulus_reloader.js +23 -7
- data/config/routes.rb +1 -0
- data/lib/hotwire/spark/change.rb +37 -0
- data/lib/hotwire/spark/default_options.rb +36 -0
- data/lib/hotwire/spark/engine.rb +2 -5
- data/lib/hotwire/spark/file_watcher.rb +5 -1
- data/lib/hotwire/spark/installer.rb +9 -14
- data/lib/hotwire/spark/middleware.rb +12 -7
- data/lib/hotwire/spark/version.rb +1 -1
- data/lib/hotwire-spark.rb +6 -3
- metadata +8 -5
@@ -0,0 +1,31 @@
|
|
1
|
+
import { log } from "../logger.js"
|
2
|
+
|
3
|
+
export class ReplaceHtmlReloader {
|
4
|
+
static async reload() {
|
5
|
+
return new ReplaceHtmlReloader().reload()
|
6
|
+
}
|
7
|
+
|
8
|
+
async reload() {
|
9
|
+
await this.#reloadHtml()
|
10
|
+
}
|
11
|
+
|
12
|
+
async #reloadHtml() {
|
13
|
+
log("Reload html with Turbo...")
|
14
|
+
|
15
|
+
this.#keepScrollPosition()
|
16
|
+
await this.#visitCurrentPage()
|
17
|
+
}
|
18
|
+
|
19
|
+
#keepScrollPosition() {
|
20
|
+
document.addEventListener("turbo:before-render", () => {
|
21
|
+
Turbo.navigator.currentVisit.scrolled = true
|
22
|
+
}, { once: true })
|
23
|
+
}
|
24
|
+
|
25
|
+
#visitCurrentPage() {
|
26
|
+
return new Promise(resolve => {
|
27
|
+
document.addEventListener("turbo:load", () => resolve(document), { once: true })
|
28
|
+
window.Turbo.visit(window.location)
|
29
|
+
})
|
30
|
+
}
|
31
|
+
}
|
@@ -2,14 +2,23 @@ import { log } from "../logger.js"
|
|
2
2
|
import { cacheBustedUrl, reloadHtmlDocument } from "../helpers.js"
|
3
3
|
|
4
4
|
export class StimulusReloader {
|
5
|
-
static async reload(
|
5
|
+
static async reload(changedFilePath) {
|
6
6
|
const document = await reloadHtmlDocument()
|
7
|
-
return new StimulusReloader(document,
|
7
|
+
return new StimulusReloader(document, changedFilePath).reload()
|
8
8
|
}
|
9
9
|
|
10
|
-
|
10
|
+
static async reloadAll() {
|
11
|
+
Stimulus.controllers.forEach(controller => {
|
12
|
+
Stimulus.unload(controller.identifier)
|
13
|
+
Stimulus.register(controller.identifier, controller.constructor)
|
14
|
+
})
|
15
|
+
|
16
|
+
return Promise.resolve()
|
17
|
+
}
|
18
|
+
|
19
|
+
constructor(document, changedFilePath) {
|
11
20
|
this.document = document
|
12
|
-
this.
|
21
|
+
this.changedFilePath = changedFilePath
|
13
22
|
this.application = window.Stimulus
|
14
23
|
}
|
15
24
|
|
@@ -40,7 +49,12 @@ export class StimulusReloader {
|
|
40
49
|
}
|
41
50
|
|
42
51
|
#shouldReloadController(path) {
|
43
|
-
return this
|
52
|
+
return this.#extractControllerName(path) === this.#changedControllerIdentifier
|
53
|
+
}
|
54
|
+
|
55
|
+
get #changedControllerIdentifier() {
|
56
|
+
this.changedControllerIdentifier = this.changedControllerIdentifier || this.#extractControllerName(this.changedFilePath)
|
57
|
+
return this.changedControllerIdentifier
|
44
58
|
}
|
45
59
|
|
46
60
|
get #stimulusPathsByModule() {
|
@@ -72,7 +86,7 @@ export class StimulusReloader {
|
|
72
86
|
if (this.#didChangeTriggerAReload) {
|
73
87
|
return []
|
74
88
|
} else {
|
75
|
-
return this.application.controllers.filter(controller => this
|
89
|
+
return this.application.controllers.filter(controller => this.#changedControllerIdentifier === controller.identifier)
|
76
90
|
}
|
77
91
|
}
|
78
92
|
|
@@ -86,10 +100,12 @@ export class StimulusReloader {
|
|
86
100
|
|
87
101
|
#extractControllerName(path) {
|
88
102
|
return path
|
89
|
-
.replace(
|
103
|
+
.replace(/^\/+/, "")
|
104
|
+
.replace(/^controllers\//, "")
|
90
105
|
.replace("_controller", "")
|
91
106
|
.replace(/\//g, "--")
|
92
107
|
.replace(/_/g, "-")
|
108
|
+
.replace(/\.js$/, "")
|
93
109
|
}
|
94
110
|
|
95
111
|
#registerController(name, module) {
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
class Hotwire::Spark::Change
|
2
|
+
attr_reader :paths, :extensions, :changed_path, :action
|
3
|
+
|
4
|
+
def initialize(paths, extensions, changed_path, action)
|
5
|
+
@paths = paths
|
6
|
+
@extensions = extensions
|
7
|
+
@changed_path = changed_path
|
8
|
+
@action = action
|
9
|
+
end
|
10
|
+
|
11
|
+
def broadcast
|
12
|
+
broadcast_reload_action if should_broadcast?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def broadcast_reload_action
|
17
|
+
Hotwire::Spark.cable_server.broadcast "hotwire_spark", reload_message
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload_message
|
21
|
+
{ action: action, path: canonical_changed_path }
|
22
|
+
end
|
23
|
+
|
24
|
+
def canonical_changed_path
|
25
|
+
canonical_changed_path = changed_path
|
26
|
+
paths.each { |path| canonical_changed_path = canonical_changed_path.to_s.gsub(/^#{path}/, "") }
|
27
|
+
canonical_changed_path
|
28
|
+
end
|
29
|
+
|
30
|
+
def should_broadcast?
|
31
|
+
changed_path.to_s =~ extension_regexp
|
32
|
+
end
|
33
|
+
|
34
|
+
def extension_regexp
|
35
|
+
/#{extensions.map { |ext| "\\." + ext }.join("|")}$/
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Hotwire::Spark::DefaultOptions
|
2
|
+
def initialize
|
3
|
+
@config = base_options
|
4
|
+
|
5
|
+
build
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_h
|
9
|
+
@config
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def base_options
|
14
|
+
{
|
15
|
+
enabled: Rails.env.development?,
|
16
|
+
css_paths: File.directory?("app/assets/builds") ? %w[ app/assets/builds ] : %w[ app/assets/stylesheets ],
|
17
|
+
css_extensions: %w[ css ],
|
18
|
+
html_paths: %w[ app/controllers app/helpers app/models app/views ],
|
19
|
+
html_extensions: %w[ rb erb ],
|
20
|
+
stimulus_paths: %w[ app/javascript/controllers ],
|
21
|
+
stimulus_extensions: %w[ js ],
|
22
|
+
html_reload_method: :morph
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def build
|
27
|
+
configure_jsbundling if defined?(Jsbundling)
|
28
|
+
end
|
29
|
+
|
30
|
+
def configure_jsbundling
|
31
|
+
@config[:stimulus_paths] = []
|
32
|
+
@config[:html_paths] << "app/assets/builds"
|
33
|
+
@config[:html_extensions] << "js"
|
34
|
+
@config[:html_reload_method] = :replace
|
35
|
+
end
|
36
|
+
end
|
data/lib/hotwire/spark/engine.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "action_cable/server/base"
|
2
|
+
require "hotwire/spark/default_options"
|
2
3
|
|
3
4
|
module Hotwire::Spark
|
4
5
|
class Engine < ::Rails::Engine
|
@@ -6,11 +7,7 @@ module Hotwire::Spark
|
|
6
7
|
|
7
8
|
config.hotwire = ActiveSupport::OrderedOptions.new unless config.respond_to?(:hotwire)
|
8
9
|
config.hotwire.spark = ActiveSupport::OrderedOptions.new
|
9
|
-
config.hotwire.spark.merge!
|
10
|
-
enabled: Rails.env.development?,
|
11
|
-
css_paths: File.directory?("app/assets/builds") ? %w[ app/assets/builds ] : %w[ app/assets/stylesheets ],
|
12
|
-
html_paths: %w[ app/controllers app/helpers app/models app/views ],
|
13
|
-
stimulus_paths: %w[ app/javascript/controllers ]
|
10
|
+
config.hotwire.spark.merge! Hotwire::Spark::DefaultOptions.new.to_h
|
14
11
|
|
15
12
|
initializer "hotwire_spark.config" do |application|
|
16
13
|
config.hotwire.spark.each do |key, value|
|
@@ -36,9 +36,13 @@ class Hotwire::Spark::FileWatcher
|
|
36
36
|
changed_files.each do |file|
|
37
37
|
@callbacks_by_path.each do |path, callbacks|
|
38
38
|
if file.to_s.start_with?(path.to_s)
|
39
|
-
callbacks.each { |callback| callback.call(file) }
|
39
|
+
callbacks.each { |callback| callback.call(as_relative_path(file)) }
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
+
|
45
|
+
def as_relative_path(path)
|
46
|
+
Pathname.new(path).relative_path_from(Rails.application.root)
|
47
|
+
end
|
44
48
|
end
|
@@ -29,25 +29,20 @@ class Hotwire::Spark::Installer
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def register_monitored_paths
|
32
|
-
monitor :css_paths, action: :reload_css
|
33
|
-
monitor :html_paths, action: :reload_html
|
34
|
-
monitor :stimulus_paths, action: :reload_stimulus
|
32
|
+
monitor :css_paths, action: :reload_css, extensions: Hotwire::Spark.css_extensions
|
33
|
+
monitor :html_paths, action: :reload_html, extensions: Hotwire::Spark.html_extensions
|
34
|
+
monitor :stimulus_paths, action: :reload_stimulus, extensions: Hotwire::Spark.stimulus_extensions
|
35
35
|
end
|
36
36
|
|
37
|
-
def monitor(paths_name, action:)
|
38
|
-
|
39
|
-
|
37
|
+
def monitor(paths_name, action:, extensions:)
|
38
|
+
paths = Hotwire::Spark.public_send(paths_name)
|
39
|
+
if paths.present?
|
40
|
+
file_watcher.monitor paths do |file_path|
|
41
|
+
Hotwire::Spark::Change.new(paths, extensions, file_path, action).broadcast
|
42
|
+
end
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
def broadcast_reload_action(action, file_path)
|
44
|
-
Hotwire::Spark.cable_server.broadcast "hotwire_spark", reload_message_for(action, file_path)
|
45
|
-
end
|
46
|
-
|
47
|
-
def reload_message_for(action, file_path)
|
48
|
-
{ action: action, path: file_path }
|
49
|
-
end
|
50
|
-
|
51
46
|
def file_watcher
|
52
47
|
@file_watches ||= Hotwire::Spark::FileWatcher.new
|
53
48
|
end
|
@@ -7,6 +7,7 @@ class Hotwire::Spark::Middleware
|
|
7
7
|
status, headers, response = @app.call(env)
|
8
8
|
|
9
9
|
if html_response?(headers)
|
10
|
+
@request = ActionDispatch::Request.new(env)
|
10
11
|
html = html_from(response)
|
11
12
|
html = inject_javascript(html)
|
12
13
|
html = inject_options(html)
|
@@ -38,18 +39,22 @@ class Hotwire::Spark::Middleware
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def view_helpers
|
41
|
-
|
42
|
+
@request.controller_instance.helpers
|
42
43
|
end
|
43
44
|
|
44
45
|
def inject_options(html)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
html.sub("</head>", "#{options}</head>")
|
47
|
+
end
|
48
|
+
|
49
|
+
def options
|
50
|
+
[ logging_option, html_reload_method_option ].compact.join("\n")
|
50
51
|
end
|
51
52
|
|
52
53
|
def logging_option
|
53
|
-
view_helpers.tag.meta(name: "hotwire-spark:logging", content: "true")
|
54
|
+
view_helpers.tag.meta(name: "hotwire-spark:logging", content: "true") if Hotwire::Spark.logging
|
55
|
+
end
|
56
|
+
|
57
|
+
def html_reload_method_option
|
58
|
+
view_helpers.tag.meta(name: "hotwire-spark:html-reload-method", content: Hotwire::Spark.html_reload_method)
|
54
59
|
end
|
55
60
|
end
|
data/lib/hotwire-spark.rb
CHANGED
@@ -8,10 +8,13 @@ loader.ignore("#{__dir__}/hotwire/spark/version.rb")
|
|
8
8
|
loader.setup
|
9
9
|
|
10
10
|
module Hotwire::Spark
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
%i[ css html stimulus ].each do |type|
|
12
|
+
mattr_accessor "#{type}_paths".to_sym, default: []
|
13
|
+
mattr_accessor "#{type}_extensions".to_sym, default: []
|
14
|
+
end
|
15
|
+
|
14
16
|
mattr_accessor :logging, default: false
|
17
|
+
mattr_accessor :html_reload_method, default: :morph
|
15
18
|
|
16
19
|
mattr_accessor :enabled, default: Rails.env.development?
|
17
20
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotwire-spark
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jorge Manrubia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-12-
|
11
|
+
date: 2024-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ 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: zeitwerk
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,11 +131,14 @@ files:
|
|
131
131
|
- app/javascript/hotwire/spark/index.js
|
132
132
|
- app/javascript/hotwire/spark/logger.js
|
133
133
|
- app/javascript/hotwire/spark/reloaders/css_reloader.js
|
134
|
-
- app/javascript/hotwire/spark/reloaders/
|
134
|
+
- app/javascript/hotwire/spark/reloaders/morph_html_reloader.js
|
135
|
+
- app/javascript/hotwire/spark/reloaders/replace_html_reloader.js
|
135
136
|
- app/javascript/hotwire/spark/reloaders/stimulus_reloader.js
|
136
137
|
- config/routes.rb
|
137
138
|
- lib/hotwire-spark.rb
|
138
139
|
- lib/hotwire/spark/action_cable/server.rb
|
140
|
+
- lib/hotwire/spark/change.rb
|
141
|
+
- lib/hotwire/spark/default_options.rb
|
139
142
|
- lib/hotwire/spark/engine.rb
|
140
143
|
- lib/hotwire/spark/file_watcher.rb
|
141
144
|
- lib/hotwire/spark/installer.rb
|