i18n_proofreading 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 +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +3 -0
- data/lib/i18n_proofreading/version.rb +1 -1
- data/lib/i18n_proofreading/widget.js +33 -15
- data/lib/i18n_proofreading/widget.rb +4 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9a73bed80d485e35617f3ea214165c0ffcfc296721ac896f09d389cbf3a1b6e8
|
|
4
|
+
data.tar.gz: 4cc2e32bf3420c01ea3af58c33582ffaa37c9fd26cf6e7425db1b554c4652c84
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1c884b9b47f7e5712ab618fc663f5160ed7d7eabd571b295818efe445f11111f2bbb81e7110336594c7885d79c032479241623a33bb81d170309165ccb522f40
|
|
7
|
+
data.tar.gz: 7c939c1e63d708c6772dcd4e703816967942b1ca2400a05027cbd8fa200ec1c446de390daf2bca70cf5313eccaa4615dc132464ffbe395a3a8cfb19d84ba04f0
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.1.1] - 2026-10-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **A Turbo visit to a page without the tool now switches the widget off.**
|
|
10
|
+
Before, the widget kept the previous page's config when the new page carried
|
|
11
|
+
none, so the pill survived a sign-out or `enabled` turning false until a hard
|
|
12
|
+
reload, and a visit made while in suggest mode (Back, `Turbo.visit`) kept
|
|
13
|
+
every click on the new page frozen. A host that worked around this with a
|
|
14
|
+
`data-turbo-track="reload"` element can drop it.
|
|
15
|
+
- **The pill comes back after a Turbo render that has no `turbo:load`**, such
|
|
16
|
+
as a form answered with a 422 or a morph refresh. The widget's per-page setup
|
|
17
|
+
now runs on `turbo:render` as well as `turbo:load`; it is idempotent, so a
|
|
18
|
+
normal visit runs it twice at the cost of rebuilding one button.
|
|
19
|
+
- Costs: a page with a malformed config block now gets no widget instead of the
|
|
20
|
+
previous page's; a host that injects the tag in only some layouts sees the
|
|
21
|
+
pill only on those pages. No configuration, migration, or server-side change.
|
|
22
|
+
- Close a suggestion dialog that a custom render preserves after suggest mode
|
|
23
|
+
becomes unavailable or inactive, releasing its scroll and focus locks. Any
|
|
24
|
+
unsent draft in that dialog is discarded when leaving suggest mode.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Exercise real Turbo visits, cached history, 422 responses, and morph refreshes
|
|
29
|
+
in browser tests. Turbo is a development/test dependency only; the installed
|
|
30
|
+
gem still has no Turbo dependency or asset build step.
|
|
31
|
+
|
|
5
32
|
## [1.1.0] - 2026-10-18
|
|
6
33
|
|
|
7
34
|
- Add Rails edge CI and experimental Ruby 4.0+ Ractor request support. The host
|
data/README.md
CHANGED
|
@@ -314,6 +314,9 @@ configure Action View during initialization can boot reliably.
|
|
|
314
314
|
`script-src` including `strict-dynamic`. Runtime config ships as
|
|
315
315
|
`<script type="application/json">` (data, not code), so it needs no nonce and
|
|
316
316
|
survives Turbo visits.
|
|
317
|
+
- **The browser follows the server's gate across Turbo visits.** A page the
|
|
318
|
+
middleware injected nothing into (signed out, `enabled` false) turns the
|
|
319
|
+
widget off: no pill and no suggest mode, even when the previous page had them.
|
|
317
320
|
- **Rate-limited per IP** on the submission endpoint (30/min by default,
|
|
318
321
|
Rails 7.2+).
|
|
319
322
|
- **Host-owned review data.** A row may contain translated text, proposed text,
|
|
@@ -20,6 +20,12 @@
|
|
|
20
20
|
if (!config || window.__i18nProofreadingLoaded) return;
|
|
21
21
|
window.__i18nProofreadingLoaded = true;
|
|
22
22
|
|
|
23
|
+
// The state of a page without a config block: the middleware injected
|
|
24
|
+
// nothing, so the tool is not available there (signed out, `enabled` false,
|
|
25
|
+
// a layout without the tag). Handlers read `config.active`, so this keeps
|
|
26
|
+
// them inert instead of acting on the last page's config.
|
|
27
|
+
var UNAVAILABLE = { active: false, showPill: false };
|
|
28
|
+
|
|
23
29
|
var LEFT = "⟦"; // ⟦
|
|
24
30
|
var RIGHT = "⟧"; // ⟧
|
|
25
31
|
var TOKEN = new RegExp(LEFT + "([^" + RIGHT + "]+)" + RIGHT);
|
|
@@ -56,9 +62,13 @@
|
|
|
56
62
|
|
|
57
63
|
// Everything else lives in <body>, which Turbo replaces on every visit —
|
|
58
64
|
// taking the pill and the active-mode highlighting with it. Re-run the
|
|
59
|
-
// per-page setup
|
|
60
|
-
// reload. render() also runs now for the initial (or non-Turbo) load.
|
|
65
|
+
// per-page setup after every body swap so the widget keeps working without
|
|
66
|
+
// a hard reload. render() also runs now for the initial (or non-Turbo) load.
|
|
67
|
+
// turbo:render covers swaps with no turbo:load after them (a form answered
|
|
68
|
+
// with a 422 or 500, a morph refresh); turbo:load covers the rest. render()
|
|
69
|
+
// is idempotent, so a visit that fires both only rebuilds one button.
|
|
61
70
|
render();
|
|
71
|
+
document.addEventListener("turbo:render", render);
|
|
62
72
|
document.addEventListener("turbo:load", render);
|
|
63
73
|
document.addEventListener("turbo:frame-load", function () { strip(); });
|
|
64
74
|
|
|
@@ -88,18 +98,23 @@
|
|
|
88
98
|
|
|
89
99
|
function render() {
|
|
90
100
|
// Re-read on each visit: the injected config is data (not an executed
|
|
91
|
-
// script), so it reflects the page Turbo just rendered.
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
// script), so it reflects the page Turbo just rendered. No config means the
|
|
102
|
+
// tool is not available on this page, so the widget switches off rather
|
|
103
|
+
// than keep the previous page's pill or suggest mode across the visit.
|
|
104
|
+
config = readConfig() || UNAVAILABLE;
|
|
105
|
+
// A body swap can detach the dialog; a custom render can preserve it even
|
|
106
|
+
// after suggest mode is disabled. Both must release its scroll/focus lock.
|
|
107
|
+
if (overlay && (!config.active || !document.body.contains(overlay))) close();
|
|
108
|
+
// A cached snapshot or a morph can carry the previous page's pill; the
|
|
109
|
+
// current config alone decides whether one is shown.
|
|
110
|
+
removePill();
|
|
111
|
+
// <html> survives a Turbo visit, so the suggest-mode class must be cleared
|
|
112
|
+
// as well as set.
|
|
113
|
+
document.documentElement.classList.toggle("i18np-active", !!config.active);
|
|
114
|
+
if (config === UNAVAILABLE) return;
|
|
115
|
+
|
|
100
116
|
injectStyles();
|
|
101
117
|
if (config.showPill !== false) buildPill();
|
|
102
|
-
document.documentElement.classList.toggle("i18np-active", !!config.active);
|
|
103
118
|
if (config.active) strip();
|
|
104
119
|
}
|
|
105
120
|
|
|
@@ -199,10 +214,13 @@
|
|
|
199
214
|
|
|
200
215
|
// --- pill -----------------------------------------------------------------
|
|
201
216
|
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
|
|
217
|
+
function removePill() {
|
|
218
|
+
document.querySelectorAll(".i18np-pill").forEach(function (pill) {
|
|
219
|
+
pill.remove();
|
|
220
|
+
});
|
|
221
|
+
}
|
|
205
222
|
|
|
223
|
+
function buildPill() {
|
|
206
224
|
var pill = document.createElement("button");
|
|
207
225
|
pill.type = "button";
|
|
208
226
|
pill.className = "i18np-pill" + (config.active ? " i18np-pill-on" : "");
|
|
@@ -46,8 +46,10 @@ module I18nProofreading
|
|
|
46
46
|
# The config rides in a `type="application/json"` block: it is *data*, not
|
|
47
47
|
# code, so the browser never executes it and Turbo never tries to re-run it
|
|
48
48
|
# on a soft visit — which means it needs no CSP nonce and, crucially, the
|
|
49
|
-
# widget can re-read the *current* page's config
|
|
50
|
-
# instead of being stuck with whatever the last full load evaluated.
|
|
49
|
+
# widget can re-read the *current* page's config after every Turbo render
|
|
50
|
+
# instead of being stuck with whatever the last full load evaluated. A
|
|
51
|
+
# page without the block is a page the tool is off for, and the widget
|
|
52
|
+
# switches itself off there.
|
|
51
53
|
#
|
|
52
54
|
# The code is a same-origin `src` script served by the engine — NOT
|
|
53
55
|
# inlined. Under a nonce-based CSP, Turbo Drive body swaps re-run body
|