2026-04-15 15:12:47 +00:00
|
|
|
import pathlib
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
REPO_ROOT = pathlib.Path(__file__).parent.parent.resolve()
|
|
|
|
|
BOOT_JS = (REPO_ROOT / "static" / "boot.js").read_text(encoding="utf-8")
|
|
|
|
|
UI_JS = (REPO_ROOT / "static" / "ui.js").read_text(encoding="utf-8")
|
|
|
|
|
SESSIONS_JS = (REPO_ROOT / "static" / "sessions.js").read_text(encoding="utf-8")
|
|
|
|
|
|
|
|
|
|
|
2026-04-15 15:21:56 +00:00
|
|
|
def _ime_guarded_enter_pattern(event_var_pattern, require_no_shift=False):
|
v0.50.264 polish followups: i18n parity + assistant-output readability
Closes #1442 (server-side _LOGIN_LOCALE missing ja/pt/ko)
Closes #1443 (promote _isImeEnter helper to 6 other Safari Enter guards)
Closes #1446 (glued-bold-heading lift for LLM thinking-block output)
Closes #1447 (markdown heading visual hierarchy in chat messages)
All four issues were filed by the Opus pre-release advisor on the v0.50.264 batch
or by Cygnus via Discord (relayed by @AvidFuturist, May 1 2026). They share a
common shape — narrow, well-scoped, independent of each other, all adding
regression tests.
== #1442: _LOGIN_LOCALE parity (api/routes.py + static/i18n.js) ==
Added entries for ja/pt/ko to the server-side _LOGIN_LOCALE dict that renders
the localized login page BEFORE the JS i18n bundle loads. With v0.50.264
shipping Japanese as the 8th built-in locale, ja/pt/ko users were seeing the
English login page even with their language preference set.
While auditing static/i18n.js for English leakage, also fixed:
- ko: 10 user-facing login/sign-out/password keys still in English
- es: 3 sign-out/auth-disabled keys still in English
Tests: tests/test_login_locale_parity.py (20 tests) — pins both invariants:
(a) every locale in i18n.js LOCALES has a matching _LOGIN_LOCALE entry
(b) every locale's login-flow keys (13 of them) are translated, not English
== #1443: window._isImeEnter promotion ==
PR #1441 fixed the Safari IME-composition Enter race in the chat composer
(`#msg`) by widening the guard from `e.isComposing` to a `_isImeEnter(e)`
helper that combines three signals (isComposing || keyCode===229 ||
_imeComposing flag). Six other Enter-input handlers were left on the original
narrow guard and would still drop IME composition Enters on Safari for
Japanese/Chinese/Korean users.
Promoted the helper to `window._isImeEnter` (defined in static/boot.js) and
replaced the `e.isComposing` guards at all six sites:
- static/sessions.js: session rename, project create, project rename
- static/ui.js: app dialog (confirm/prompt), message edit, workspace rename
The state-free part of the helper (`isComposing || keyCode===229`) handles
Safari's race for any focused input without needing per-input composition
listeners — only `#msg` keeps the local `_imeComposing` flag.
Tests:
- tests/test_issue1443_ime_helper_promotion.py (9 tests) — pins each site
+ verifies no raw `e.isComposing` Enter-guards remain in sessions.js/ui.js
- tests/test_ime_composition.py — alternation regex extended to accept
the windowed helper form (loosen-test-on-shape-change pattern from
v0.50.264 reflection notes)
== #1446: glued-bold-heading lift (static/ui.js renderMd + Python mirror) ==
LLMs in thinking/reasoning mode emit "section headers" glued to the end of the
previous paragraph with no whitespace:
Para 1 text.**Heading to Para 2**
Para 2 text.**Heading to Para 3**
The renderer correctly produces inline `<strong>` per CommonMark, but it looks
like trailing emphasis on the body text rather than a section break. Cygnus
reported this as "Markdown feedback 2 of 3."
Added a single regex pre-pass in renderMd():
s.replace(/([.!?])\*\*([^*\n]{1,80})\*\*\n\n/g, '$1\n\n**$2**\n\n')
Constraints chosen to avoid false positives:
- Trigger only on `[.!?]` IMMEDIATELY before `**` (no space) — almost always
an LLM-glued heading, not intentional emphasis
- Inner text ≤80 chars, no `*` or newline (single-line only)
- Trailing `\n\n` required — preserves "this is **important** to know."
mid-paragraph emphasis untouched
- Position: after rawPreStash restore, before fence_stash restore — fenced
code blocks stay protected (their content is `\x00P` / `\x00F` tokens
when the lift runs)
Mirrored in tests/test_sprint16.py render_md() so both stay in sync.
Tests: tests/test_issue1446_glued_heading_lift.py (17 tests, 5 of which drive
the actual ui.js renderMd via node) — covers all 3 trigger forms (.!?), all 4
preserve-emphasis cases the issue spec'd, fenced/inline code protection,
chained glued headings, source-level position pin, regex shape pin.
== #1447: markdown heading visual hierarchy (static/style.css) ==
Pre-fix sizes in `.msg-body`:
h1 18px, h2 16px, h3 14px (= body), h4 13px, h5 12px, h6 11px
So h3 was indistinguishable from body and h4/h5/h6 were SMALLER than body.
Cygnus's report: "Markdown feedback 3 of 3 — Headings seem to be missing
across the board in Hermes. They're there, but all plaintext."
New sizes:
h1 24px (border-bottom) h2 20px (border-bottom) h3 17px h4 15px
h5 14px (uppercase, tracked) h6 13px (uppercase, tracked, muted)
All headings now `font-weight:700` + `color:var(--strong)` for stronger ink.
h5/h6 use uppercase + letter-spacing for "label-style" affordance instead
of being smaller-than-body.
Synced .preview-md (file preview pane) to match exactly so a markdown file
preview and a chat message render identically. Added missing h4/h5/h6 rules
to .preview-md (it only had h1-h3 before).
Updated data-font-size="small"/"large" h1-h6 overrides to scale
proportionally with the new defaults. Hierarchy preserved at all three
font-size settings.
Tests: tests/test_issue1447_heading_hierarchy.py (9 tests) — pins the size
hierarchy, the bottom borders on h1/h2, the uppercase affordance on h5/h6,
the .preview-md sync, and the small/large override scaling.
== Verification ==
pytest tests/ -q → 3748 passed (+56 new)
bash ~/WebUI/scripts/run-browser-tests.sh → 20 + 11 PASS
bash ~/WebUI/scripts/webui_qa_agent.sh 8789 → 23/23 PASS
Visual confirmation in browser at port 8789:
- Heading hierarchy clearly visible at all 6 levels
- Glued-bold lift produces separate paragraphs as designed
- window._isImeEnter accessible from any module after boot.js
- Login page renders ja/pt/ko strings correctly (curl -s /login)
2026-05-02 04:04:23 +00:00
|
|
|
"""Accept the IME guard in any of three shapes that have been used in the codebase:
|
|
|
|
|
|
|
|
|
|
1. Original `e.isComposing` (pre-#1441)
|
|
|
|
|
2. Module-local `_isImeEnter(e)` (PR #1441 — chat composer in boot.js)
|
|
|
|
|
3. Window-exposed `window._isImeEnter(e)` (issue #1443 — promoted to ui.js,
|
|
|
|
|
sessions.js so all 6 Enter-input sites use the same Safari-aware guard).
|
test: pr1441 IME helper guards + pr1439 ja locale parity
- Loosen test_ime_composition._ime_guarded_enter_pattern to accept the
new _isImeEnter(e) helper (PR #1441 widened guard for Safari + 229 keyCode
+ manual _imeComposing flag). Original e.isComposing-only pattern still
matches via alternation.
- Add test_pr1441_ime_safari_guard.py (6 tests): pin the 3-guard helper,
compositionstart sets manual flag, compositionend defers reset to next
tick (Safari race), null-guard $('msg') for non-chat pages, send-Enter
uses helper, dropdown-Enter uses helper.
- Add test_japanese_locale.py (8 tests): mirror Chinese/Korean templates,
block exists, representative translations, full key parity with English,
no extra keys, duplicates mirror en exactly, placeholders preserved,
arrow-function values mirrored, _label uses Japanese script.
2026-05-02 02:44:59 +00:00
|
|
|
"""
|
2026-04-15 15:21:56 +00:00
|
|
|
no_shift = rf"\s*&&\s*!\s*{event_var_pattern}\.shiftKey" if require_no_shift else ""
|
v0.50.264 polish followups: i18n parity + assistant-output readability
Closes #1442 (server-side _LOGIN_LOCALE missing ja/pt/ko)
Closes #1443 (promote _isImeEnter helper to 6 other Safari Enter guards)
Closes #1446 (glued-bold-heading lift for LLM thinking-block output)
Closes #1447 (markdown heading visual hierarchy in chat messages)
All four issues were filed by the Opus pre-release advisor on the v0.50.264 batch
or by Cygnus via Discord (relayed by @AvidFuturist, May 1 2026). They share a
common shape — narrow, well-scoped, independent of each other, all adding
regression tests.
== #1442: _LOGIN_LOCALE parity (api/routes.py + static/i18n.js) ==
Added entries for ja/pt/ko to the server-side _LOGIN_LOCALE dict that renders
the localized login page BEFORE the JS i18n bundle loads. With v0.50.264
shipping Japanese as the 8th built-in locale, ja/pt/ko users were seeing the
English login page even with their language preference set.
While auditing static/i18n.js for English leakage, also fixed:
- ko: 10 user-facing login/sign-out/password keys still in English
- es: 3 sign-out/auth-disabled keys still in English
Tests: tests/test_login_locale_parity.py (20 tests) — pins both invariants:
(a) every locale in i18n.js LOCALES has a matching _LOGIN_LOCALE entry
(b) every locale's login-flow keys (13 of them) are translated, not English
== #1443: window._isImeEnter promotion ==
PR #1441 fixed the Safari IME-composition Enter race in the chat composer
(`#msg`) by widening the guard from `e.isComposing` to a `_isImeEnter(e)`
helper that combines three signals (isComposing || keyCode===229 ||
_imeComposing flag). Six other Enter-input handlers were left on the original
narrow guard and would still drop IME composition Enters on Safari for
Japanese/Chinese/Korean users.
Promoted the helper to `window._isImeEnter` (defined in static/boot.js) and
replaced the `e.isComposing` guards at all six sites:
- static/sessions.js: session rename, project create, project rename
- static/ui.js: app dialog (confirm/prompt), message edit, workspace rename
The state-free part of the helper (`isComposing || keyCode===229`) handles
Safari's race for any focused input without needing per-input composition
listeners — only `#msg` keeps the local `_imeComposing` flag.
Tests:
- tests/test_issue1443_ime_helper_promotion.py (9 tests) — pins each site
+ verifies no raw `e.isComposing` Enter-guards remain in sessions.js/ui.js
- tests/test_ime_composition.py — alternation regex extended to accept
the windowed helper form (loosen-test-on-shape-change pattern from
v0.50.264 reflection notes)
== #1446: glued-bold-heading lift (static/ui.js renderMd + Python mirror) ==
LLMs in thinking/reasoning mode emit "section headers" glued to the end of the
previous paragraph with no whitespace:
Para 1 text.**Heading to Para 2**
Para 2 text.**Heading to Para 3**
The renderer correctly produces inline `<strong>` per CommonMark, but it looks
like trailing emphasis on the body text rather than a section break. Cygnus
reported this as "Markdown feedback 2 of 3."
Added a single regex pre-pass in renderMd():
s.replace(/([.!?])\*\*([^*\n]{1,80})\*\*\n\n/g, '$1\n\n**$2**\n\n')
Constraints chosen to avoid false positives:
- Trigger only on `[.!?]` IMMEDIATELY before `**` (no space) — almost always
an LLM-glued heading, not intentional emphasis
- Inner text ≤80 chars, no `*` or newline (single-line only)
- Trailing `\n\n` required — preserves "this is **important** to know."
mid-paragraph emphasis untouched
- Position: after rawPreStash restore, before fence_stash restore — fenced
code blocks stay protected (their content is `\x00P` / `\x00F` tokens
when the lift runs)
Mirrored in tests/test_sprint16.py render_md() so both stay in sync.
Tests: tests/test_issue1446_glued_heading_lift.py (17 tests, 5 of which drive
the actual ui.js renderMd via node) — covers all 3 trigger forms (.!?), all 4
preserve-emphasis cases the issue spec'd, fenced/inline code protection,
chained glued headings, source-level position pin, regex shape pin.
== #1447: markdown heading visual hierarchy (static/style.css) ==
Pre-fix sizes in `.msg-body`:
h1 18px, h2 16px, h3 14px (= body), h4 13px, h5 12px, h6 11px
So h3 was indistinguishable from body and h4/h5/h6 were SMALLER than body.
Cygnus's report: "Markdown feedback 3 of 3 — Headings seem to be missing
across the board in Hermes. They're there, but all plaintext."
New sizes:
h1 24px (border-bottom) h2 20px (border-bottom) h3 17px h4 15px
h5 14px (uppercase, tracked) h6 13px (uppercase, tracked, muted)
All headings now `font-weight:700` + `color:var(--strong)` for stronger ink.
h5/h6 use uppercase + letter-spacing for "label-style" affordance instead
of being smaller-than-body.
Synced .preview-md (file preview pane) to match exactly so a markdown file
preview and a chat message render identically. Added missing h4/h5/h6 rules
to .preview-md (it only had h1-h3 before).
Updated data-font-size="small"/"large" h1-h6 overrides to scale
proportionally with the new defaults. Hierarchy preserved at all three
font-size settings.
Tests: tests/test_issue1447_heading_hierarchy.py (9 tests) — pins the size
hierarchy, the bottom borders on h1/h2, the uppercase affordance on h5/h6,
the .preview-md sync, and the small/large override scaling.
== Verification ==
pytest tests/ -q → 3748 passed (+56 new)
bash ~/WebUI/scripts/run-browser-tests.sh → 20 + 11 PASS
bash ~/WebUI/scripts/webui_qa_agent.sh 8789 → 23/23 PASS
Visual confirmation in browser at port 8789:
- Heading hierarchy clearly visible at all 6 levels
- Glued-bold lift produces separate paragraphs as designed
- window._isImeEnter accessible from any module after boot.js
- Login page renders ja/pt/ko strings correctly (curl -s /login)
2026-05-02 04:04:23 +00:00
|
|
|
# Either: if(e.isComposing) ... | if(_isImeEnter(e)) ... | if(window._isImeEnter&&window._isImeEnter(e)) ...
|
test: pr1441 IME helper guards + pr1439 ja locale parity
- Loosen test_ime_composition._ime_guarded_enter_pattern to accept the
new _isImeEnter(e) helper (PR #1441 widened guard for Safari + 229 keyCode
+ manual _imeComposing flag). Original e.isComposing-only pattern still
matches via alternation.
- Add test_pr1441_ime_safari_guard.py (6 tests): pin the 3-guard helper,
compositionstart sets manual flag, compositionend defers reset to next
tick (Safari race), null-guard $('msg') for non-chat pages, send-Enter
uses helper, dropdown-Enter uses helper.
- Add test_japanese_locale.py (8 tests): mirror Chinese/Korean templates,
block exists, representative translations, full key parity with English,
no extra keys, duplicates mirror en exactly, placeholders preserved,
arrow-function values mirrored, _label uses Japanese script.
2026-05-02 02:44:59 +00:00
|
|
|
guard = (
|
|
|
|
|
rf"if\s*\(\s*"
|
|
|
|
|
rf"(?:{event_var_pattern}\.isComposing"
|
v0.50.264 polish followups: i18n parity + assistant-output readability
Closes #1442 (server-side _LOGIN_LOCALE missing ja/pt/ko)
Closes #1443 (promote _isImeEnter helper to 6 other Safari Enter guards)
Closes #1446 (glued-bold-heading lift for LLM thinking-block output)
Closes #1447 (markdown heading visual hierarchy in chat messages)
All four issues were filed by the Opus pre-release advisor on the v0.50.264 batch
or by Cygnus via Discord (relayed by @AvidFuturist, May 1 2026). They share a
common shape — narrow, well-scoped, independent of each other, all adding
regression tests.
== #1442: _LOGIN_LOCALE parity (api/routes.py + static/i18n.js) ==
Added entries for ja/pt/ko to the server-side _LOGIN_LOCALE dict that renders
the localized login page BEFORE the JS i18n bundle loads. With v0.50.264
shipping Japanese as the 8th built-in locale, ja/pt/ko users were seeing the
English login page even with their language preference set.
While auditing static/i18n.js for English leakage, also fixed:
- ko: 10 user-facing login/sign-out/password keys still in English
- es: 3 sign-out/auth-disabled keys still in English
Tests: tests/test_login_locale_parity.py (20 tests) — pins both invariants:
(a) every locale in i18n.js LOCALES has a matching _LOGIN_LOCALE entry
(b) every locale's login-flow keys (13 of them) are translated, not English
== #1443: window._isImeEnter promotion ==
PR #1441 fixed the Safari IME-composition Enter race in the chat composer
(`#msg`) by widening the guard from `e.isComposing` to a `_isImeEnter(e)`
helper that combines three signals (isComposing || keyCode===229 ||
_imeComposing flag). Six other Enter-input handlers were left on the original
narrow guard and would still drop IME composition Enters on Safari for
Japanese/Chinese/Korean users.
Promoted the helper to `window._isImeEnter` (defined in static/boot.js) and
replaced the `e.isComposing` guards at all six sites:
- static/sessions.js: session rename, project create, project rename
- static/ui.js: app dialog (confirm/prompt), message edit, workspace rename
The state-free part of the helper (`isComposing || keyCode===229`) handles
Safari's race for any focused input without needing per-input composition
listeners — only `#msg` keeps the local `_imeComposing` flag.
Tests:
- tests/test_issue1443_ime_helper_promotion.py (9 tests) — pins each site
+ verifies no raw `e.isComposing` Enter-guards remain in sessions.js/ui.js
- tests/test_ime_composition.py — alternation regex extended to accept
the windowed helper form (loosen-test-on-shape-change pattern from
v0.50.264 reflection notes)
== #1446: glued-bold-heading lift (static/ui.js renderMd + Python mirror) ==
LLMs in thinking/reasoning mode emit "section headers" glued to the end of the
previous paragraph with no whitespace:
Para 1 text.**Heading to Para 2**
Para 2 text.**Heading to Para 3**
The renderer correctly produces inline `<strong>` per CommonMark, but it looks
like trailing emphasis on the body text rather than a section break. Cygnus
reported this as "Markdown feedback 2 of 3."
Added a single regex pre-pass in renderMd():
s.replace(/([.!?])\*\*([^*\n]{1,80})\*\*\n\n/g, '$1\n\n**$2**\n\n')
Constraints chosen to avoid false positives:
- Trigger only on `[.!?]` IMMEDIATELY before `**` (no space) — almost always
an LLM-glued heading, not intentional emphasis
- Inner text ≤80 chars, no `*` or newline (single-line only)
- Trailing `\n\n` required — preserves "this is **important** to know."
mid-paragraph emphasis untouched
- Position: after rawPreStash restore, before fence_stash restore — fenced
code blocks stay protected (their content is `\x00P` / `\x00F` tokens
when the lift runs)
Mirrored in tests/test_sprint16.py render_md() so both stay in sync.
Tests: tests/test_issue1446_glued_heading_lift.py (17 tests, 5 of which drive
the actual ui.js renderMd via node) — covers all 3 trigger forms (.!?), all 4
preserve-emphasis cases the issue spec'd, fenced/inline code protection,
chained glued headings, source-level position pin, regex shape pin.
== #1447: markdown heading visual hierarchy (static/style.css) ==
Pre-fix sizes in `.msg-body`:
h1 18px, h2 16px, h3 14px (= body), h4 13px, h5 12px, h6 11px
So h3 was indistinguishable from body and h4/h5/h6 were SMALLER than body.
Cygnus's report: "Markdown feedback 3 of 3 — Headings seem to be missing
across the board in Hermes. They're there, but all plaintext."
New sizes:
h1 24px (border-bottom) h2 20px (border-bottom) h3 17px h4 15px
h5 14px (uppercase, tracked) h6 13px (uppercase, tracked, muted)
All headings now `font-weight:700` + `color:var(--strong)` for stronger ink.
h5/h6 use uppercase + letter-spacing for "label-style" affordance instead
of being smaller-than-body.
Synced .preview-md (file preview pane) to match exactly so a markdown file
preview and a chat message render identically. Added missing h4/h5/h6 rules
to .preview-md (it only had h1-h3 before).
Updated data-font-size="small"/"large" h1-h6 overrides to scale
proportionally with the new defaults. Hierarchy preserved at all three
font-size settings.
Tests: tests/test_issue1447_heading_hierarchy.py (9 tests) — pins the size
hierarchy, the bottom borders on h1/h2, the uppercase affordance on h5/h6,
the .preview-md sync, and the small/large override scaling.
== Verification ==
pytest tests/ -q → 3748 passed (+56 new)
bash ~/WebUI/scripts/run-browser-tests.sh → 20 + 11 PASS
bash ~/WebUI/scripts/webui_qa_agent.sh 8789 → 23/23 PASS
Visual confirmation in browser at port 8789:
- Heading hierarchy clearly visible at all 6 levels
- Glued-bold lift produces separate paragraphs as designed
- window._isImeEnter accessible from any module after boot.js
- Login page renders ja/pt/ko strings correctly (curl -s /login)
2026-05-02 04:04:23 +00:00
|
|
|
rf"|_isImeEnter\(\s*{event_var_pattern}\s*\)"
|
|
|
|
|
rf"|window\._isImeEnter\s*&&\s*window\._isImeEnter\s*\(\s*{event_var_pattern}\s*\))"
|
test: pr1441 IME helper guards + pr1439 ja locale parity
- Loosen test_ime_composition._ime_guarded_enter_pattern to accept the
new _isImeEnter(e) helper (PR #1441 widened guard for Safari + 229 keyCode
+ manual _imeComposing flag). Original e.isComposing-only pattern still
matches via alternation.
- Add test_pr1441_ime_safari_guard.py (6 tests): pin the 3-guard helper,
compositionstart sets manual flag, compositionend defers reset to next
tick (Safari race), null-guard $('msg') for non-chat pages, send-Enter
uses helper, dropdown-Enter uses helper.
- Add test_japanese_locale.py (8 tests): mirror Chinese/Korean templates,
block exists, representative translations, full key parity with English,
no extra keys, duplicates mirror en exactly, placeholders preserved,
arrow-function values mirrored, _label uses Japanese script.
2026-05-02 02:44:59 +00:00
|
|
|
rf"\s*\)\s*"
|
|
|
|
|
)
|
2026-04-15 15:21:56 +00:00
|
|
|
return (
|
|
|
|
|
rf"if\s*\(\s*{event_var_pattern}\.key\s*===\s*'Enter'{no_shift}\s*\)\s*\{{\s*"
|
test: pr1441 IME helper guards + pr1439 ja locale parity
- Loosen test_ime_composition._ime_guarded_enter_pattern to accept the
new _isImeEnter(e) helper (PR #1441 widened guard for Safari + 229 keyCode
+ manual _imeComposing flag). Original e.isComposing-only pattern still
matches via alternation.
- Add test_pr1441_ime_safari_guard.py (6 tests): pin the 3-guard helper,
compositionstart sets manual flag, compositionend defers reset to next
tick (Safari race), null-guard $('msg') for non-chat pages, send-Enter
uses helper, dropdown-Enter uses helper.
- Add test_japanese_locale.py (8 tests): mirror Chinese/Korean templates,
block exists, representative translations, full key parity with English,
no extra keys, duplicates mirror en exactly, placeholders preserved,
arrow-function values mirrored, _label uses Japanese script.
2026-05-02 02:44:59 +00:00
|
|
|
+ guard +
|
2026-04-15 15:21:56 +00:00
|
|
|
rf"(?:\{{\s*return\s*;?\s*\}}|return\s*;?)"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2026-04-15 15:12:47 +00:00
|
|
|
def test_boot_chat_enter_send_respects_ime_composition():
|
|
|
|
|
assert re.search(
|
2026-04-15 15:21:56 +00:00
|
|
|
_ime_guarded_enter_pattern("e"),
|
2026-04-15 15:12:47 +00:00
|
|
|
BOOT_JS,
|
2026-04-15 15:21:56 +00:00
|
|
|
re.DOTALL,
|
2026-04-15 15:12:47 +00:00
|
|
|
), "Chat composer Enter handler must ignore IME composition Enter in static/boot.js"
|
|
|
|
|
assert re.search(
|
2026-04-15 15:21:56 +00:00
|
|
|
_ime_guarded_enter_pattern("e", require_no_shift=True),
|
2026-04-15 15:12:47 +00:00
|
|
|
BOOT_JS,
|
2026-04-15 15:21:56 +00:00
|
|
|
re.DOTALL,
|
2026-04-15 15:12:47 +00:00
|
|
|
), "Command dropdown Enter handler must ignore IME composition Enter in static/boot.js"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_ui_enter_submit_paths_respect_ime_composition():
|
|
|
|
|
assert re.search(
|
2026-04-15 15:21:56 +00:00
|
|
|
rf"document\.addEventListener\('keydown',e=>\{{[\s\S]*?{_ime_guarded_enter_pattern('e')}",
|
2026-04-15 15:12:47 +00:00
|
|
|
UI_JS,
|
2026-04-15 15:21:56 +00:00
|
|
|
re.DOTALL,
|
2026-04-15 15:12:47 +00:00
|
|
|
), \
|
|
|
|
|
"App dialog Enter handler must ignore IME composition Enter in static/ui.js"
|
2026-04-15 15:21:56 +00:00
|
|
|
assert re.search(
|
|
|
|
|
_ime_guarded_enter_pattern("e", require_no_shift=True),
|
|
|
|
|
UI_JS,
|
|
|
|
|
re.DOTALL,
|
|
|
|
|
), \
|
2026-04-15 15:12:47 +00:00
|
|
|
"Message edit Enter-to-save handler must ignore IME composition Enter in static/ui.js"
|
|
|
|
|
assert re.search(
|
2026-04-15 15:21:56 +00:00
|
|
|
rf"inp\.onkeydown=\(e2\)=>\{{\s*{_ime_guarded_enter_pattern('e2')}",
|
2026-04-15 15:12:47 +00:00
|
|
|
UI_JS,
|
2026-04-15 15:21:56 +00:00
|
|
|
re.DOTALL,
|
2026-04-15 15:12:47 +00:00
|
|
|
), \
|
|
|
|
|
"Workspace rename Enter handler must ignore IME composition Enter in static/ui.js"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_sessions_enter_submit_paths_respect_ime_composition():
|
|
|
|
|
matches = re.findall(
|
2026-04-15 15:21:56 +00:00
|
|
|
_ime_guarded_enter_pattern(r"e2?"),
|
2026-04-15 15:12:47 +00:00
|
|
|
SESSIONS_JS,
|
2026-04-15 15:21:56 +00:00
|
|
|
re.DOTALL,
|
2026-04-15 15:12:47 +00:00
|
|
|
)
|
|
|
|
|
assert len(matches) >= 3, \
|
|
|
|
|
"Session and project rename/create Enter handlers must ignore IME composition Enter in static/sessions.js"
|