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.
@@ -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(filePattern) {
5
+ static async reload(changedFilePath) {
6
6
  const document = await reloadHtmlDocument()
7
- return new StimulusReloader(document, filePattern).reload()
7
+ return new StimulusReloader(document, changedFilePath).reload()
8
8
  }
9
9
 
10
- constructor(document, filePattern = /./) {
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.filePattern = filePattern
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.filePattern.test(path)
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.filePattern.test(`${controller.identifier}_controller`))
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
@@ -1,2 +1,3 @@
1
1
  Hotwire::Spark::Engine.routes.draw do
2
+ get "/source_files", to: "source_files#show"
2
3
  end
@@ -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
@@ -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
- file_watcher.monitor Hotwire::Spark.public_send(paths_name) do |file_path|
39
- broadcast_reload_action(action, file_path)
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
- ActionController::Base.helpers
42
+ @request.controller_instance.helpers
42
43
  end
43
44
 
44
45
  def inject_options(html)
45
- if Hotwire::Spark.logging
46
- html.sub("</head>", "#{logging_option}</head>")
47
- else
48
- html
49
- end
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
@@ -1,5 +1,5 @@
1
1
  module Hotwire
2
2
  module Spark
3
- VERSION = "0.1.9"
3
+ VERSION = "0.1.11"
4
4
  end
5
5
  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
- mattr_accessor :css_paths, default: []
12
- mattr_accessor :html_paths, default: []
13
- mattr_accessor :stimulus_paths, default: []
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.9
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-22 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: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 8.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: 8.0.0
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/html_reloader.js
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