achilles 1.1.0 → 1.1.1

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: d393e3c7e9d04d6a472ba4e41c727fffca5fa3088f5d064a08a0f9cd4b2bfcf2
4
- data.tar.gz: 911efcf9ddc72755b3b26b9a8ae3d0a5538d4d33ba2f8476d6c4ae4c8aa54e8e
3
+ metadata.gz: d860cd0be6faa8af39117c4dc6feadb2445f48ccfd687963a3a8eeddbe1c3b95
4
+ data.tar.gz: '09cdfabdfa0895b1a3c7a92726baf49cb234a9a716b8a1e3a65c7eb6e578904e'
5
5
  SHA512:
6
- metadata.gz: a480a6ca6a9b154cdf723aa53560a1caa2a82f41f569a3e2d79dafbd80e50d1dea7a9c9b18d29f69c8eb9d693af79b358929929b9842a014645eaf939105dea5
7
- data.tar.gz: 52f50f6c02b169e7d592363571da480961aa6ac52a856aaca72dc3f26f4e5c557e9b5c918e24f18bdfec6d5d37685936e49678e093ea182d4dc8730bad6d898c
6
+ metadata.gz: 7899f56529ad2a867a289b546241023e235a1d848d3a22ceb1a396fb92a515c9edeb3b50decdec7d37e952f9c5fc524326c8d1fc3456e78f5e1c7db5be53c10d
7
+ data.tar.gz: 7d43d1c196f608be65a27d42840cdd0a3f3bac7bb86870dec876b89bdbfdf63408465dabd265986322638300ab0d8287c3a747e2b2830ccc3c824bf74217318e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to Achilles will be documented in this file.
4
4
 
5
+ ## 1.1.1
6
+
7
+ ### Fixed
8
+
9
+ - Fixed Turbo browser history restoration so components restored from cached DOM
10
+ are registered and set up again when their registry entries were already
11
+ removed.
12
+ - Fixed component subtree deregistration so child components are removed with
13
+ their parent and cannot block later re-registration.
14
+ - Added browser system coverage for back, forward, restored nested components,
15
+ restored form-field listeners, Turbo-replaced form restoration, and duplicate
16
+ listener prevention.
17
+
5
18
  ## 1.1.0
6
19
 
7
20
  ### Added
data/README.md CHANGED
@@ -8,6 +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
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).
14
+
11
15
  ## Why Achilles?
12
16
 
13
17
  Rails and Turbo make server-rendered interfaces productive, but many apps still
@@ -79,6 +83,9 @@ achilles.componentsClassMapper.addComponentClass("CounterComponent", CounterComp
79
83
  achilles.start();
80
84
  ```
81
85
 
86
+ Call `start()` after registering component classes. Achilles parses the current
87
+ page and attaches Turbo lifecycle hooks when the application starts.
88
+
82
89
  Create components by extending `ComponentBase`:
83
90
 
84
91
  ```js
@@ -108,9 +115,10 @@ Mark the component root in your view:
108
115
  <button id="counter" data-component-class="CounterComponent">0</button>
109
116
  ```
110
117
 
111
- Every component root must have a unique `id`. Achilles uses that id to register
112
- the component, find its root element, and avoid running setup twice for the same
113
- DOM node.
118
+ Every component root must have a non-empty unique `id`. Achilles uses that id to
119
+ register the component, find its root element, and avoid running setup twice for
120
+ the same DOM node. Components without ids are skipped and reported in the browser
121
+ console.
114
122
 
115
123
  ## Dynamic Components
116
124
 
@@ -148,6 +156,26 @@ Register the component class once:
148
156
  achilles.componentsClassMapper.addComponentClass("NotificationComponent", NotificationComponent);
149
157
  ```
150
158
 
159
+ ## Nested Components
160
+
161
+ Achilles keeps a component tree rooted at a single synthetic `Page` component.
162
+ A component's parent is its nearest ancestor element with `data-component-class`.
163
+ If there is no component ancestor, its parent is `Page`.
164
+
165
+ ```erb
166
+ <div id="dashboard" data-component-class="DashboardComponent">
167
+ <div id="filters" data-component-class="FiltersComponent"></div>
168
+ </div>
169
+ ```
170
+
171
+ This creates the following component tree:
172
+
173
+ ```text
174
+ Page
175
+ dashboard
176
+ filters
177
+ ```
178
+
151
179
  ## Example App
152
180
 
153
181
  The dummy Rails app includes a working counter component. See
@@ -158,8 +186,17 @@ The dummy Rails app includes a working counter component. See
158
186
  - `setup()` runs after `turbo:load` and after new matching DOM nodes are inserted.
159
187
  - `teardown()` runs before Turbo renders a new page.
160
188
  - `setup()` and `teardown()` are called once per registered component instance.
189
+ - Parent components are set up before their children.
190
+ - Child components are torn down before their parents.
161
191
  - Components that attach listeners, timers, observers, subscriptions, or widgets
162
192
  should clean them up in `teardown()`.
193
+ - Lifecycle errors are logged and swallowed by default so one broken component
194
+ does not stop the page. Enable strict mode in tests or development when errors
195
+ should be re-raised:
196
+
197
+ ```js
198
+ achilles.strictLifecycleErrors = true;
199
+ ```
163
200
 
164
201
  ## API Reference
165
202
 
@@ -178,6 +215,7 @@ Useful properties:
178
215
 
179
216
  - `componentsClassMapper`: register component classes by name.
180
217
  - `componentRegistry`: inspect or manage registered component instances.
218
+ - `strictLifecycleErrors`: re-raise lifecycle errors after logging them.
181
219
  - `timezone`: access the configured app timezone.
182
220
 
183
221
  Call `start()` after registering component classes. Call `stop()` when an
@@ -219,7 +257,9 @@ Useful methods:
219
257
  ```
220
258
 
221
259
  The `data-component-class` value must match a class registered with
222
- `componentsClassMapper`.
260
+ `componentsClassMapper`. The element must also have a non-empty unique `id`.
261
+ Nested components are parented by DOM ancestry, with top-level components
262
+ parented by the synthetic `Page` component.
223
263
 
224
264
  ## Timezone
225
265
 
@@ -232,6 +272,13 @@ value through `achilles.timezone.timezoneString`.
232
272
 
233
273
  If no timezone is present, Achilles falls back to `Etc/UTC`.
234
274
 
275
+ ## Upgrading
276
+
277
+ Applications upgrading to `1.1.0` should read the
278
+ [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).
281
+
235
282
  ## Upgrading From 0.1.3
236
283
 
237
284
  Achilles `1.0.0` changes `rootElement()` to return a DOM element. It no longer
@@ -255,9 +302,8 @@ Or wrap explicitly if the application still uses jQuery:
255
302
  $(this.rootElement()).addClass("is-open");
256
303
  ```
257
304
 
258
- Applications upgrading Achilles should start with the
259
- [upgrade guide](docs/upgrading.md). Applications upgrading from `0.1.3` should
260
- also read the [v1 migration guide](docs/migrating-from-0.1.3-to-v1.md).
305
+ Applications upgrading from `0.1.3` should also read the
306
+ [v1 migration guide](docs/migrating-from-0.1.3-to-v1.md).
261
307
 
262
308
  ## Contributing
263
309
 
@@ -117,8 +117,8 @@ class Application {
117
117
  }
118
118
 
119
119
  deregisterAllComponentsExceptPage() {
120
- let pageComponent = this.componentRegistry.getRegisteredComponent(AppConstants.PageComponentId)
121
- pageComponent.subComponents.forEach((subComponentId) => {
120
+ let pageComponent = this.componentRegistry.getRegisteredComponent(AppConstants.PageComponentId);
121
+ [...pageComponent.subComponents].forEach((subComponentId) => {
122
122
  this.componentRegistry.deregisterComponent(subComponentId);
123
123
  })
124
124
  }
@@ -22,7 +22,7 @@ class ComponentParser {
22
22
  console.error(elem);
23
23
  return;
24
24
  }
25
- if(elem.dataset.componentRegistered === 'true') {
25
+ if(elem.dataset.componentRegistered === 'true' && this._componentRegistry.getRegisteredComponent(elem.id)) {
26
26
  return;
27
27
  }
28
28
  try {
@@ -53,6 +53,10 @@ class ComponentsRegistry {
53
53
  if(!component)
54
54
  return;
55
55
 
56
+ [...component.subComponents].forEach((subComponentId) => {
57
+ this.deregisterComponent(subComponentId);
58
+ });
59
+
56
60
  let parentComponent = this.getRegisteredComponent(component.parentComponentId);
57
61
 
58
62
  if(parentComponent != null){
@@ -1,18 +1,29 @@
1
1
  # Release Checklist
2
2
 
3
- Use this checklist for `1.0.0.rc1` and future releases.
3
+ Use this checklist for every Achilles release. Replace `VERSION` with the
4
+ version being prepared, for example `1.1.0`.
4
5
 
5
- ## Before Building
6
+ ## Before Finalizing The Version
6
7
 
8
+ - Confirm the release type: patch, minor, major, or prerelease.
7
9
  - Confirm `lib/achilles/version.rb` has the intended version.
8
10
  - Confirm `CHANGELOG.md` has an entry for the intended version.
11
+ - Confirm application-facing changes have an upgrade note in `docs/upgrading.md`.
12
+ - Confirm release notes exist in `docs/releases/` when the release needs a
13
+ GitHub release body.
14
+ - Confirm package file expectations are covered by `test/gemspec_files_test.rb`
15
+ when adding source or documentation files.
16
+
17
+ ## Before Building
18
+
9
19
  - Confirm CI is green on GitHub.
10
20
  - Run the local verification commands:
11
21
 
12
22
  ```bash
13
23
  bin/rails test
24
+ node --test test/javascript/*_test.mjs
25
+ 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
14
26
  bin/rails test:system
15
- for file in $(find app/javascript/achilles test/dummy/app/javascript -name '*.js' -print); do node --input-type=module --check < "$file" || exit 1; done
16
27
  RAILS_ENV=test bin/rails app:assets:precompile
17
28
  ```
18
29
 
@@ -25,13 +36,13 @@ gem build achilles.gemspec
25
36
  Confirm the generated gem name matches the intended version:
26
37
 
27
38
  ```bash
28
- ls achilles-*.gem
39
+ ls achilles-VERSION.gem
29
40
  ```
30
41
 
31
42
  ## Test In A Real Application
32
43
 
33
- In one application that currently uses Achilles `0.1.3`, point the Gemfile to
34
- the local checkout or install the built prerelease gem.
44
+ Before a broad rollout, test the built gem in at least one real Rails + Turbo
45
+ application that already uses Achilles.
35
46
 
36
47
  Check:
37
48
 
@@ -45,30 +56,37 @@ Check:
45
56
  - components that attach window, document, timer, observer, or third-party
46
57
  widget state
47
58
 
48
- For v1, `rootElement()` returns a DOM element. If a component expects a jQuery
49
- object, update it to use DOM APIs or wrap explicitly with
50
- `$(this.rootElement())`.
59
+ For releases with breaking or compatibility-sensitive behavior, test one app
60
+ first, then roll out to the rest of the maintained apps gradually.
51
61
 
52
62
  ## Publish A Prerelease
53
63
 
54
- Only publish `1.0.0.rc1` after local checks and GitHub CI pass.
64
+ Publish a prerelease only when the release needs real-app validation before a
65
+ final tag.
55
66
 
56
67
  ```bash
57
- gem push achilles-1.0.0.rc1.gem
58
- git tag v1.0.0.rc1
59
- git push origin v1.0.0.rc1
68
+ git tag vVERSION
69
+ git push origin vVERSION
70
+ gem push achilles-VERSION.gem
60
71
  ```
61
72
 
62
- ## Publish Final v1.0.0
73
+ Mark the GitHub release as a prerelease and include the matching release notes.
63
74
 
64
- Publish final `1.0.0` only after at least one real application has successfully
65
- tested the release candidate.
75
+ ## Publish A Final Release
76
+
77
+ Publish a final release after local checks, GitHub CI, packaging verification,
78
+ and real-app testing are complete.
79
+
80
+ ```bash
81
+ git tag vVERSION
82
+ git push origin vVERSION
83
+ gem push achilles-VERSION.gem
84
+ ```
66
85
 
67
- Before final release:
86
+ After pushing:
68
87
 
69
- - update `lib/achilles/version.rb` to `1.0.0`
70
- - update `CHANGELOG.md` from `1.0.0.rc1` to `1.0.0`
71
- - run all local checks
72
- - confirm GitHub CI is green
73
- - build and push `achilles-1.0.0.gem`
74
- - tag `v1.0.0`
88
+ - Create or update the GitHub release for `vVERSION`.
89
+ - Paste the release note from `docs/releases/vVERSION.md` when one exists, for
90
+ example `docs/releases/v1.1.0.md`.
91
+ - Link the release back to the upgrade guide for application-facing changes.
92
+ - Confirm the pushed gem is visible on RubyGems.
@@ -0,0 +1,74 @@
1
+ # Achilles 1.1.0
2
+
3
+ Achilles `1.1.0` tightens the application lifecycle for Rails + Turbo apps and
4
+ adds stronger nested-component behavior. This release is intended for existing
5
+ Achilles users who want explicit startup, safer teardown ordering, and better
6
+ runtime behavior around Turbo navigation and dynamic markup.
7
+
8
+ ## Upgrade First
9
+
10
+ This release includes application-facing changes. Before upgrading an existing
11
+ app, read the full guide:
12
+
13
+ - [Upgrading to 1.1.0](../upgrading-to-1.1.0.md)
14
+
15
+ The most important change is explicit application startup:
16
+
17
+ ```js
18
+ const achilles = new Application();
19
+ achilles.componentsClassMapper.addComponentClass("MenuComponent", MenuComponent);
20
+ achilles.start();
21
+ ```
22
+
23
+ Call `start()` after registering component classes. Achilles no longer starts
24
+ from the `Application` constructor.
25
+
26
+ ## Highlights
27
+
28
+ - Added explicit `Application#start` and `Application#stop` lifecycle methods.
29
+ - Added `Application#strictLifecycleErrors` for tests and development.
30
+ - Component parentage now follows DOM ancestry under the synthetic `Page` root.
31
+ - Component teardown now runs from children to parents.
32
+ - Elements with `data-component-class` must have a non-empty `id`; invalid roots
33
+ are skipped with a browser-console error.
34
+ - Achilles now requires `turbo-rails`, so Turbo importmap assets are available
35
+ to host applications.
36
+ - Added browser system coverage for nested components inside Turbo form
37
+ replacement and Turbo Drive navigation.
38
+
39
+ ## Breaking Or Compatibility-Sensitive Changes
40
+
41
+ Applications should check these items before updating:
42
+
43
+ - Search for `new Application` and make sure each Achilles instance calls
44
+ `start()` after all component classes are registered.
45
+ - Search for `data-component-class` and make sure every component root has a
46
+ non-empty unique `id`.
47
+ - Review parent components whose `teardown()` removes DOM nodes, shared event
48
+ targets, widgets, or state that child components also use during cleanup.
49
+ - If you have tests that should fail on lifecycle errors, enable strict mode:
50
+
51
+ ```js
52
+ achilles.strictLifecycleErrors = true;
53
+ ```
54
+
55
+ ## Verification
56
+
57
+ This release line was verified with:
58
+
59
+ ```bash
60
+ bin/rails test
61
+ node --test test/javascript/*_test.mjs
62
+ bin/rails test:system
63
+ RAILS_ENV=test bin/rails app:assets:precompile
64
+ gem build achilles.gemspec
65
+ ```
66
+
67
+ One real application has also been updated successfully. Continue testing in
68
+ your own Rails + Turbo apps before rolling the update through every project.
69
+
70
+ ## Links
71
+
72
+ - [Changelog](../../CHANGELOG.md)
73
+ - [Upgrade index](../upgrading.md)
74
+ - [1.1.0 upgrade guide](../upgrading-to-1.1.0.md)
@@ -0,0 +1,46 @@
1
+ # Achilles 1.1.1
2
+
3
+ Achilles `1.1.1` is a patch release for Rails + Turbo applications using
4
+ browser history restoration. It fixes restored component markup that appeared on
5
+ screen after browser back or forward navigation but no longer had active
6
+ Achilles event listeners.
7
+
8
+ ## Who Should Upgrade
9
+
10
+ Upgrade from `1.1.0` if your application uses Turbo Drive navigation and users
11
+ can return to Achilles-managed pages with the browser back or forward buttons.
12
+
13
+ There are no new application setup requirements in this patch release. Apps
14
+ upgrading from versions before `1.1.0` should still read the
15
+ [1.1.0 upgrade guide](../upgrading-to-1.1.0.md).
16
+
17
+ ## Fixed
18
+
19
+ - Restored Turbo-cached DOM with stale `data-component-registered="true"` flags
20
+ is now parsed correctly when Achilles no longer has a matching registry entry.
21
+ - Deregistering a parent component now deregisters its child component subtree,
22
+ preventing orphaned child registry entries from blocking future setup.
23
+ - Page-level deregistration now iterates over a stable copy of child component
24
+ ids while the registry is being mutated.
25
+
26
+ ## Verification
27
+
28
+ This release was verified with:
29
+
30
+ ```bash
31
+ bin/rails test
32
+ node --test test/javascript/*_test.mjs
33
+ bin/rails test:system
34
+ RAILS_ENV=test bin/rails app:assets:precompile
35
+ gem build achilles.gemspec
36
+ ```
37
+
38
+ The system suite includes browser back, browser forward, restored nested
39
+ components, restored form-field listeners, restored Turbo-replaced forms, and
40
+ duplicate listener prevention.
41
+
42
+ ## Links
43
+
44
+ - [Changelog](../../CHANGELOG.md)
45
+ - [Upgrade index](../upgrading.md)
46
+ - [1.1.0 upgrade guide](../upgrading-to-1.1.0.md)
data/docs/upgrading.md CHANGED
@@ -10,6 +10,11 @@ setup, component markup, lifecycle behavior, or public APIs.
10
10
  - [Upgrading to 1.1.0](upgrading-to-1.1.0.md)
11
11
  - [Migrating from 0.1.3 to v1](migrating-from-0.1.3-to-v1.md)
12
12
 
13
+ ## Release Notes
14
+
15
+ - [Achilles 1.1.1](releases/v1.1.1.md)
16
+ - [Achilles 1.1.0](releases/v1.1.0.md)
17
+
13
18
  ## Upgrade Policy
14
19
 
15
20
  Before upgrading an existing application:
@@ -1,3 +1,3 @@
1
1
  module Achilles
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
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.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jey Geethan
@@ -90,6 +90,8 @@ files:
90
90
  - docs/core-js-gaps.md
91
91
  - docs/migrating-from-0.1.3-to-v1.md
92
92
  - docs/release-checklist.md
93
+ - docs/releases/v1.1.0.md
94
+ - docs/releases/v1.1.1.md
93
95
  - docs/upgrading-to-1.1.0.md
94
96
  - docs/upgrading.md
95
97
  - docs/v1-roadmap.md