Skip to content

Commit

Permalink
Merge pull request #40 from codergeek121/morph-and-turbo-reload
Browse files Browse the repository at this point in the history
Allow Turbo to reload the page instead of morphing
  • Loading branch information
jorgemanrubia authored Dec 25, 2024
2 parents c1ccaa0 + 76b65b4 commit 8472e59
Show file tree
Hide file tree
Showing 19 changed files with 154 additions and 45 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ gem "rubocop-rails-omakase", require: false

gem "propshaft"
gem "importmap-rails"
gem "turbo-rails"
gem "stimulus-rails"
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ GEM
stringio (3.1.2)
thor (1.3.2)
timeout (0.4.3)
turbo-rails (2.0.11)
actionpack (>= 6.0.0)
railties (>= 6.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
Expand Down Expand Up @@ -283,6 +286,7 @@ DEPENDENCIES
rubocop-rails-omakase
sqlite3
stimulus-rails
turbo-rails

BUNDLED WITH
2.5.23
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ You can set configuration options on your `development.rb`. For example:
config.hotwire.spark.html_paths += %w[ lib ]
```

| Name | Description |
|------------------|------------------------------------------------------------------------------------------------------------------------------|
| `html_paths` | Paths where file changes trigger a content refresh. By default: `app/controllers`, `app/helpers`, `app/models`, `app/views`. |
| `css_paths` | Paths where file changes trigger a CSS refresh. By default: `app/assets/stylesheets` or `app/assets/builds` if exists. |
| `stimulus_paths` | Paths where file changes trigger a Stimulus controller refresh. By default: `app/javascript/controllers`. |
| `enabled` | Enable or disable live reloading. By default, it's only enabled in `development`. |
| `logging` | Show logs in the browser console when reloading happens. It's false by default. |
| Name | Description |
|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `html_paths` | Paths where file changes trigger a content refresh. By default: `app/controllers`, `app/helpers`, `app/models`, `app/views`. |
| `css_paths` | Paths where file changes trigger a CSS refresh. By default: `app/assets/stylesheets` or `app/assets/builds` if exists. |
| `stimulus_paths` | Paths where file changes trigger a Stimulus controller refresh. By default: `app/javascript/controllers`. |
| `enabled` | Enable or disable live reloading. By default, it's only enabled in `development`. |
| `logging` | Show logs in the browser console when reloading happens. It's false by default. |
| `html_reload_method` | Reload html by morphing (`"morph"`) or with a Turbo page reload (`"replace"`). By default `"morph"`. Use `"replace"` if your app is incompatible with morphing. |

## License

Expand Down
49 changes: 39 additions & 10 deletions app/assets/javascripts/hotwire_spark.js
Original file line number Diff line number Diff line change
Expand Up @@ -1387,7 +1387,7 @@ var HotwireSpark = (function () {
})();

function log() {
if (HotwireSpark.config.loggingEnabled) {
if (HotwireSpark$1.config.loggingEnabled) {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
Expand Down Expand Up @@ -1470,16 +1470,16 @@ var HotwireSpark = (function () {
}
}

class HtmlReloader {
class MorphHtmlReloader {
static async reload() {
return new HtmlReloader().reload();
return new MorphHtmlReloader().reload();
}
async reload() {
const reloadedDocument = await this.#reloadHtml();
const reloadedDocument = await this.#reloadWithMorph();
await this.#reloadStimulus(reloadedDocument);
}
async #reloadHtml() {
log("Reload html...");
async #reloadWithMorph() {
log("Reload html with morph...");
const reloadedDocument = await reloadHtmlDocument();
this.#updateBody(reloadedDocument.body);
return reloadedDocument;
Expand Down Expand Up @@ -1548,6 +1548,32 @@ var HotwireSpark = (function () {
}
}

class ReplaceHtmlReloader {
static async reload() {
return new ReplaceHtmlReloader().reload();
}
async reload() {
await this.#reloadWithTurbo();
}
#reloadWithTurbo() {
log("Reload html with Turbo...");
this.#maintainScrollPosition();
return new Promise(resolve => {
document.addEventListener("turbo:load", () => resolve(document), {
once: true
});
window.Turbo.visit(window.location);
});
}
#maintainScrollPosition() {
document.addEventListener("turbo:render", () => {
Turbo.navigator.currentVisit.scrolled = true;
}, {
once: true
});
}
}

consumer.subscriptions.create({
channel: "Hotwire::Spark::Channel"
}, {
Expand Down Expand Up @@ -1579,6 +1605,7 @@ var HotwireSpark = (function () {
}
},
reloadHtml() {
const HtmlReloader = HotwireSpark.config.htmlReloadMethod == "morph" ? MorphHtmlReloader : ReplaceHtmlReloader;
return HtmlReloader.reload();
},
reloadCss(fileName) {
Expand All @@ -1589,15 +1616,17 @@ var HotwireSpark = (function () {
}
});

const HotwireSpark = {
const HotwireSpark$1 = {
config: {
loggingEnabled: false
loggingEnabled: false,
htmlReloadMethod: "morph"
}
};
document.addEventListener("DOMContentLoaded", function () {
HotwireSpark.config.loggingEnabled = getConfigurationProperty("logging");
HotwireSpark$1.config.loggingEnabled = getConfigurationProperty("logging");
HotwireSpark$1.config.htmlReloadMethod = getConfigurationProperty("html-reload-method");
});

return HotwireSpark;
return HotwireSpark$1;

})();
2 changes: 1 addition & 1 deletion app/assets/javascripts/hotwire_spark.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/assets/javascripts/hotwire_spark.min.js.map

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion app/javascript/hotwire/spark/channels/monitoring_channel.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import consumer from "./consumer"
import { assetNameFromPath } from "../helpers.js";
import { HtmlReloader } from "../reloaders/html_reloader.js";
import { MorphHtmlReloader } from "../reloaders/morph_html_reloader.js";
import { CssReloader } from "../reloaders/css_reloader.js";
import { StimulusReloader } from "../reloaders/stimulus_reloader.js";
import { ReplaceHtmlReloader } from "../reloaders/replace_html_reloader.js";

consumer.subscriptions.create({ channel: "Hotwire::Spark::Channel" }, {
connected() {
Expand Down Expand Up @@ -33,6 +34,9 @@ consumer.subscriptions.create({ channel: "Hotwire::Spark::Channel" }, {
},

reloadHtml() {
const HtmlReloader = HotwireSpark.config.htmlReloadMethod == "morph"
? MorphHtmlReloader
: ReplaceHtmlReloader
return HtmlReloader.reload()
},

Expand Down
4 changes: 3 additions & 1 deletion app/javascript/hotwire/spark/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { getConfigurationProperty } from "./helpers.js";

const HotwireSpark = {
config: {
loggingEnabled: false
loggingEnabled: false,
htmlReloadMethod: "morph"
}
}

document.addEventListener("DOMContentLoaded", function() {
HotwireSpark.config.loggingEnabled = getConfigurationProperty("logging");
HotwireSpark.config.htmlReloadMethod = getConfigurationProperty("html-reload-method");
})

export default HotwireSpark
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Idiomorph } from "idiomorph/dist/idiomorph.esm.js"
import { log } from "../logger.js"
import { reloadHtmlDocument } from "../helpers.js"
import { log } from "../logger.js"
import { StimulusReloader } from "./stimulus_reloader.js"

export class HtmlReloader {
export class MorphHtmlReloader {
static async reload() {
return new HtmlReloader().reload()
return new MorphHtmlReloader().reload()
}

async reload() {
const reloadedDocument = await this.#reloadHtml()
const reloadedDocument = await this.#reloadWithMorph()
await this.#reloadStimulus(reloadedDocument)
}

async #reloadHtml() {
log("Reload html...")
async #reloadWithMorph() {
log("Reload html with morph...")

const reloadedDocument = await reloadHtmlDocument()
this.#updateBody(reloadedDocument.body)
Expand Down
28 changes: 28 additions & 0 deletions app/javascript/hotwire/spark/reloaders/replace_html_reloader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { log } from "../logger.js"

export class ReplaceHtmlReloader {
static async reload() {
return new ReplaceHtmlReloader().reload()
}

async reload() {
await this.#reloadWithTurbo()
}

#reloadWithTurbo() {
log("Reload html with Turbo...")

this.#maintainScrollPosition()

return new Promise(resolve => {
document.addEventListener("turbo:load", () => resolve(document), { once: true })
window.Turbo.visit(window.location)
})
}

#maintainScrollPosition() {
document.addEventListener("turbo:render", () => {
Turbo.navigator.currentVisit.scrolled = true
}, { once: true })
}
}
1 change: 1 addition & 0 deletions lib/hotwire-spark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module Hotwire::Spark
mattr_accessor :html_paths, default: []
mattr_accessor :stimulus_paths, default: []
mattr_accessor :logging, default: false
mattr_accessor :html_reload_method, default: "morph"

mattr_accessor :enabled, default: Rails.env.development?

Expand Down
16 changes: 10 additions & 6 deletions lib/hotwire/spark/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,18 @@ def view_helpers
end

def inject_options(html)
if Hotwire::Spark.logging
html.sub("</head>", "#{logging_option}</head>")
else
html
end
html.sub("</head>", "#{options}</head>")
end

def options
[ logging_option, html_reload_method_option ].compact.join("\n")
end

def logging_option
view_helpers.tag.meta(name: "hotwire-spark:logging", content: "true")
view_helpers.tag.meta(name: "hotwire-spark:logging", content: "true") if Hotwire::Spark.logging
end

def html_reload_method_option
view_helpers.tag.meta(name: "hotwire-spark:html-reload-method", content: Hotwire::Spark.html_reload_method)
end
end
1 change: 1 addition & 0 deletions test/dummy/app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
10 changes: 10 additions & 0 deletions test/dummy/app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@
<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag :app %>
<%= javascript_importmap_tags %>

<script>
let firstLoad = true
document.addEventListener("turbo:load", (event) => {
if (!firstLoad) {
document.body.setAttribute("data-turbo-navigated", "")
}
firstLoad = false
})
</script>
</head>

<body>
Expand Down
1 change: 1 addition & 0 deletions test/dummy/config/importmap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
pin "@hotwired/stimulus", to: "stimulus.min.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
pin_all_from "app/javascript/controllers", under: "controllers"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
12 changes: 0 additions & 12 deletions test/html_reload_test.rb

This file was deleted.

17 changes: 17 additions & 0 deletions test/morph_reload_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "application_system_test_case"

class MorphReloadTest < ApplicationSystemTestCase
setup do
Hotwire::Spark.html_reload_method = "morph"
end

test "reload HTML changes" do
visit root_path
assert_no_text "This was morphed"

edit_file "app/views/home/show.html.erb", replace: "_REPLACE_", with: "This was morphed!"

assert_text "This was morphed"
assert_no_css "[data-turbo-navigated]"
end
end
17 changes: 17 additions & 0 deletions test/replace_reload_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require "application_system_test_case"

class ReplaceReloadTest < ApplicationSystemTestCase
setup do
Hotwire::Spark.html_reload_method = "replace"
end

test "reload HTML changes" do
visit root_path
assert_no_text "This is pretty amazing"

edit_file "app/views/home/show.html.erb", replace: "cool", with: "amazing"

assert_text "This is pretty amazing"
assert_css "[data-turbo-navigated]"
end
end
1 change: 1 addition & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ActiveSupport::TestCase

setup do
reload_rails_reloader
Hotwire::Spark.html_reload_method = "morph"
end

private
Expand Down

0 comments on commit 8472e59

Please sign in to comment.