achilles 1.1.1 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d860cd0be6faa8af39117c4dc6feadb2445f48ccfd687963a3a8eeddbe1c3b95
4
- data.tar.gz: '09cdfabdfa0895b1a3c7a92726baf49cb234a9a716b8a1e3a65c7eb6e578904e'
3
+ metadata.gz: b4d4c63799a2a26d7d7a819ec2e17559de59d80be593e5b28d2cc6445864ccda
4
+ data.tar.gz: 8fe623f377d068436dc08beed221ad293ed85159a46930aa5868e24aece5a1ca
5
5
  SHA512:
6
- metadata.gz: 7899f56529ad2a867a289b546241023e235a1d848d3a22ceb1a396fb92a515c9edeb3b50decdec7d37e952f9c5fc524326c8d1fc3456e78f5e1c7db5be53c10d
7
- data.tar.gz: 7d43d1c196f608be65a27d42840cdd0a3f3bac7bb86870dec876b89bdbfdf63408465dabd265986322638300ab0d8287c3a747e2b2830ccc3c824bf74217318e
6
+ metadata.gz: 5a1b4835b8cc60697ac3eb8d44e23c8799f76fa0d82f9a481b6a1a8cbdfe77373b91e1443dfcb62b6d733430bae427cd5bf624b3390f8a4f59ce5c632e223292
7
+ data.tar.gz: f6eed0197de6d71b6c74f4dfedf63920207f798fd4260a1d22076d7459587624fa2aa3d6fa88dc51d90fbe3be2735b687265122eb1222a67cfe25d9a94960f66
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to Achilles will be documented in this file.
4
4
 
5
+ ## 1.1.2
6
+
7
+ ### Fixed
8
+
9
+ - Fixed Turbo Frame rendering so registered components in the outgoing frame are
10
+ torn down and deregistered immediately before Turbo invokes the frame renderer.
11
+
5
12
  ## 1.1.1
6
13
 
7
14
  ### Fixed
data/README.md CHANGED
@@ -8,9 +8,10 @@ Achilles scans the page for elements with `data-component-class`, instantiates
8
8
  the matching JavaScript class, and calls `setup` and `teardown` as Turbo renders
9
9
  new pages or new component markup is inserted.
10
10
 
11
- Current applications should use Achilles `1.1.1`. If you are upgrading an
11
+ Current applications should use Achilles `1.1.2`. If you are upgrading an
12
12
  existing app, start with the [1.1.0 upgrade guide](docs/upgrading-to-1.1.0.md)
13
- and then read the [1.1.1 release note](docs/releases/v1.1.1.md).
13
+ and then read the [1.1.1](docs/releases/v1.1.1.md) and
14
+ [1.1.2](docs/releases/v1.1.2.md) release notes.
14
15
 
15
16
  ## Why Achilles?
16
17
 
@@ -185,6 +186,9 @@ The dummy Rails app includes a working counter component. See
185
186
 
186
187
  - `setup()` runs after `turbo:load` and after new matching DOM nodes are inserted.
187
188
  - `teardown()` runs before Turbo renders a new page.
189
+ - Before Turbo renders replacement content in a frame, Achilles tears down and
190
+ deregisters registered components in the outgoing frame from children to
191
+ parents.
188
192
  - `setup()` and `teardown()` are called once per registered component instance.
189
193
  - Parent components are set up before their children.
190
194
  - Child components are torn down before their parents.
@@ -276,8 +280,8 @@ If no timezone is present, Achilles falls back to `Etc/UTC`.
276
280
 
277
281
  Applications upgrading to `1.1.0` should read the
278
282
  [1.1.0 upgrade guide](docs/upgrading-to-1.1.0.md). The complete upgrade index
279
- lives in [docs/upgrading.md](docs/upgrading.md), and the GitHub release draft is
280
- available at [docs/releases/v1.1.1.md](docs/releases/v1.1.1.md).
283
+ lives in [docs/upgrading.md](docs/upgrading.md), and the current release note is
284
+ available at [docs/releases/v1.1.2.md](docs/releases/v1.1.2.md).
281
285
 
282
286
  ## Upgrading From 0.1.3
283
287
 
@@ -4,6 +4,7 @@ class Turbo {
4
4
  _teardownCallback;
5
5
  _setupHandler;
6
6
  _teardownHandler;
7
+ _frameRenderHandler;
7
8
  _started = false;
8
9
 
9
10
  constructor(application, setupCallback, teardownCallback) {
@@ -27,8 +28,24 @@ class Turbo {
27
28
  this._teardownCallback();
28
29
  };
29
30
 
31
+ this._frameRenderHandler = (event) => {
32
+ const frame = event.target;
33
+ const originalRender = event.detail?.render;
34
+
35
+ if (!frame || typeof originalRender !== "function") {
36
+ return;
37
+ }
38
+
39
+ const componentRegistry = this._application.componentRegistry;
40
+ event.detail.render = function(...args) {
41
+ componentRegistry.teardownAndDeregisterWithin(frame);
42
+ return Reflect.apply(originalRender, this, args);
43
+ };
44
+ };
45
+
30
46
  document.addEventListener("turbo:load", this._setupHandler);
31
47
  document.addEventListener("turbo:before-render", this._teardownHandler);
48
+ document.addEventListener("turbo:before-frame-render", this._frameRenderHandler);
32
49
  this._started = true;
33
50
  }
34
51
 
@@ -39,8 +56,10 @@ class Turbo {
39
56
 
40
57
  document.removeEventListener("turbo:load", this._setupHandler);
41
58
  document.removeEventListener("turbo:before-render", this._teardownHandler);
59
+ document.removeEventListener("turbo:before-frame-render", this._frameRenderHandler);
42
60
  this._setupHandler = null;
43
61
  this._teardownHandler = null;
62
+ this._frameRenderHandler = null;
44
63
  this._started = false;
45
64
  }
46
65
  }
@@ -130,6 +130,39 @@ class ComponentsRegistry {
130
130
  this.deregisterComponent(id);
131
131
  }
132
132
 
133
+ teardownAndDeregisterWithin(rootElement) {
134
+ if(!rootElement || typeof rootElement.contains !== 'function')
135
+ return;
136
+
137
+ Object.values(this._registeredComponents)
138
+ .filter((component) => {
139
+ if(component.id === AppConstants.PageComponentId)
140
+ return false;
141
+
142
+ let element = this.elementForId(component.id);
143
+ return element && rootElement.contains(element);
144
+ })
145
+ .sort((firstComponent, secondComponent) => {
146
+ return this.elementDepth(secondComponent.id) - this.elementDepth(firstComponent.id);
147
+ })
148
+ .forEach((component) => {
149
+ if(this.getRegisteredComponent(component.id))
150
+ this.teardownAndDeregister(component.id);
151
+ });
152
+ }
153
+
154
+ elementDepth(id) {
155
+ let depth = 0;
156
+ let element = this.elementForId(id);
157
+
158
+ while(element?.parentElement) {
159
+ depth += 1;
160
+ element = element.parentElement;
161
+ }
162
+
163
+ return depth;
164
+ }
165
+
133
166
  elementNotFound(id) {
134
167
  console.error('Cannot find element while setup, so teardown & deregister. id: ' + id);
135
168
  this.teardownAndDeregister(id);
@@ -0,0 +1,58 @@
1
+ # Achilles 1.1.2
2
+
3
+ Achilles `1.1.2` is a patch release for Rails + Turbo applications using Turbo
4
+ Frames. It fixes late component cleanup when Turbo replaces frame content.
5
+
6
+ ## Who Should Upgrade
7
+
8
+ Upgrade from `1.1.0` or `1.1.1` if your application registers
9
+ Achilles-managed components inside a Turbo Frame or on the frame root itself.
10
+
11
+ There are no new application setup requirements in this patch release. Apps
12
+ upgrading from versions before `1.1.0` should still read the
13
+ [1.1.0 upgrade guide](../upgrading-to-1.1.0.md).
14
+
15
+ ## Fixed
16
+
17
+ - Registered components in an outgoing Turbo Frame are now torn down and
18
+ deregistered immediately before Turbo invokes the frame renderer.
19
+ - Cleanup runs from children to parents and includes the frame root when it is
20
+ registered as a component.
21
+ - The original Turbo renderer keeps its receiver, arguments, return value, and
22
+ error behavior.
23
+ - Incoming components continue to register through the existing DOM observer,
24
+ while ordinary non-Turbo removal behavior remains unchanged.
25
+ - Starting and stopping an Achilles application manages the frame-render
26
+ listener without creating duplicates.
27
+
28
+ ## Compatibility
29
+
30
+ This backward-compatible `1.1.x` patch intentionally moves frame-contained
31
+ teardown earlier, while the outgoing component elements are still present,
32
+ instead of relying on missing-element recovery after replacement.
33
+
34
+ Achilles continues to require Turbo Rails `2.0.11` or newer. This release does
35
+ not add dependencies or require an application migration.
36
+
37
+ ## Verification
38
+
39
+ This release was verified with:
40
+
41
+ ```bash
42
+ bin/rails test
43
+ node --test test/javascript/*_test.mjs
44
+ for file in $(rg --files app/javascript/achilles test/dummy/app/javascript test/javascript | rg "\.(js|mjs)$"); do node --input-type=module --check < "$file" || exit 1; done
45
+ bin/rails test:system
46
+ RAILS_ENV=test bin/rails app:assets:precompile
47
+ gem build achilles.gemspec
48
+ ```
49
+
50
+ The system suite covers a native Turbo Frame replacement with a registered
51
+ frame root, nested outgoing components, incoming component registration and
52
+ interaction, and browser-console error checks.
53
+
54
+ ## Links
55
+
56
+ - [Changelog](../../CHANGELOG.md)
57
+ - [Upgrade index](../upgrading.md)
58
+ - [1.1.0 upgrade guide](../upgrading-to-1.1.0.md)
data/docs/upgrading.md CHANGED
@@ -12,6 +12,7 @@ setup, component markup, lifecycle behavior, or public APIs.
12
12
 
13
13
  ## Release Notes
14
14
 
15
+ - [Achilles 1.1.2](releases/v1.1.2.md)
15
16
  - [Achilles 1.1.1](releases/v1.1.1.md)
16
17
  - [Achilles 1.1.0](releases/v1.1.0.md)
17
18
 
@@ -1,3 +1,3 @@
1
1
  module Achilles
2
- VERSION = "1.1.1"
2
+ VERSION = "1.1.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: achilles
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jey Geethan
@@ -92,6 +92,7 @@ files:
92
92
  - docs/release-checklist.md
93
93
  - docs/releases/v1.1.0.md
94
94
  - docs/releases/v1.1.1.md
95
+ - docs/releases/v1.1.2.md
95
96
  - docs/upgrading-to-1.1.0.md
96
97
  - docs/upgrading.md
97
98
  - docs/v1-roadmap.md