Skip to content

fix(autoPair): improve CJK input stability and test coverage - #6

Merged
xiaolai merged 2 commits into
mainfrom
investigate/input-stability
Jan 25, 2026
Merged

fix(autoPair): improve CJK input stability and test coverage#6
xiaolai merged 2 commits into
mainfrom
investigate/input-stability

Conversation

@xiaolai

@xiaolai xiaolai commented Jan 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fix auto-pair extension to use central imeGuard utilities for proper CJK composition handling
  • Improve test coverage for tiptapFocus.ts (35% → 95%) and sourcePeek.ts (46% → 85%)

Changes

Auto-pair IME Fix

The auto-pair extension was using a local isComposing flag that didn't account for straggler key events after compositionend. This caused interference with CJK input methods.

Solution: Integrated with the central imeGuard utilities that provide:

  • Composition state tracking via isProseMirrorComposing
  • 50ms grace period after compositionend via isProseMirrorInCompositionGrace
  • IME key event detection via isImeKeyEvent

Test Coverage Improvements

File Before After
tiptapFocus.ts 35% 95%
sourcePeek.ts 46% 85%

New tests cover:

  • Fresh document load with scroll preservation
  • Retry logic when editor view is disconnected
  • Error handling for focus and selection operations
  • Anchor rect calculation for source peek
  • Markdown application with error scenarios

Test plan

  • All 2118 tests pass
  • pnpm check:all passes
  • Manual test: Type CJK characters with IME and verify auto-pair doesn't interfere
  • Manual test: Verify cursor restoration works after mode switching

Replace local isComposing flag with shared imeGuard utilities that
provide grace period protection (50ms after compositionend) for
straggler key events during CJK input.
tiptapFocus.ts: 35% → 94% coverage
- Add tests for fresh document load (null cursor info)
- Add tests for retry logic when view is disconnected
- Add tests for max retry limit
- Add tests for focus error handling
- Add tests for scroll position preservation
- Add tests for setSelection error handling

sourcePeek.ts: 46% → 85% coverage
- Add tests for inline content wrapping
- Add tests for multi-paragraph serialization
- Add tests for shallow selection handling
- Add tests for getSourcePeekAnchorRect
- Add tests for applySourcePeekMarkdown
@xiaolai

xiaolai commented Jan 25, 2026

Copy link
Copy Markdown
Owner Author

Code Review

Summary

The fix correctly replaces the local isComposing boolean with the centralized imeGuard utilities.

Changes Analysis

Change Assessment
isComposingOrGrace() helper ✅ Clean abstraction combining composition state + grace period
Remove compositionstart handler ✅ Correct - ProseMirror's view.composing handles this
Add isImeKeyEvent() check ✅ Catches IME keycode 229 in keydown
markProseMirrorCompositionEnd() ✅ Enables 50ms grace period tracking

Why This Fix Works

The 50ms grace period from imeGuard addresses the root cause: straggler key events arriving after compositionend but before IME is fully settled.

Test Coverage

Good additions for tiptapFocus.ts (35%→95%) and sourcePeek.ts (46%→85%):

  • Error handling paths
  • Retry logic
  • Scroll preservation
  • Edge cases

Note

PR shows 2118 tests but main now has 2176 (recent merge). No conflicts detected.

Ready to merge

@xiaolai
xiaolai merged commit 4e09b0c into main Jan 25, 2026
@xiaolai
xiaolai deleted the investigate/input-stability branch January 25, 2026 15:38
xiaolai added a commit that referenced this pull request Feb 19, 2026
Issues fixed:
- #6: Add StatusBar warning when auto-save paused (file missing)
- #15: Use Documents folder instead of Home for default save location
- #19: Fix race condition in recent files menu by storing snapshot in Rust
- #30: Fix dock icon drop when no document windows exist
- #35: Show toast notification when file auto-reloads
- #37: Add "Restore to Disk" context menu for missing files

Additional improvements:
- Add toast on pinned tab close attempt (#7)
- Add toast on save failure (#5/#14)
- Add toasts for drag-drop failures (#25, #26, #27)
- Improve cold start file open reliability (#9, #34)
- Fix no-window menu operations (#17, #18, #21)
xiaolai added a commit that referenced this pull request Feb 19, 2026
fix(autoPair): improve CJK input stability and test coverage
xiaolai added a commit that referenced this pull request Feb 22, 2026
Add multi-cursor tokens to design-tokens.md documentation per rule #6:
"Update this doc when adding new tokens to index.css."
xiaolai added a commit that referenced this pull request Feb 22, 2026
* fix: move multi-cursor tokens to index.css (source of truth)

The multi-cursor plugin was defining :root tokens in its own CSS file,
violating the convention that all design tokens live in index.css.

Closes #171

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback for PR #178

Add multi-cursor tokens to design-tokens.md documentation per rule #6:
"Update this doc when adding new tokens to index.css."

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: xiaolai <lixiaolai@gmail.com>
xiaolai added a commit that referenced this pull request Apr 22, 2026
Two rounds of audit→fix→verify with codex-toolkit resolved the following
issues on the feat/large-file-ux branch:

Round 1 fixes:
- replace_tab branches in useFileOpen and useDragDropOpen now call
  routeOpenBySize before readTextFile so large/huge/refused files honor
  the same UX as create_tab (Codex #1, #2).
- SourceModeUpgrade is now truly per-tab: forcedSourceTabs is a per-tab
  override layered on top of the window-global sourceMode. Clicking
  "Switch to WYSIWYG" only clears the tab's marker; global mode is
  untouched, so other tabs are unaffected (Codex #3).
- fileLoadStore.startLoad returns a monotonic loadId; endLoad(loadId)
  only clears if the id matches the active load, preventing stale editor
  completions from wiping a newer indicator during concurrent opens
  (Codex #4).
- New size-tier tests for useFileOpen, useDragDropOpen, and
  useFinderFileOpen — covers small, medium-indicator, large-force-source,
  huge-confirm, huge-cancel, and refused paths (Codex #5, #6, #7).
- WindowContext toast now goes through i18n.t (Codex #8).
- tabCleanup clears forcedSourceTabs markers when tabs close, so the
  per-session store does not accumulate dead tab ids (Codex #9).
- file_ops.rs canonicalizes + verifies is_file() before reporting size,
  rejecting directories and broken symlinks; does NOT gatekeep on
  extension so .txt (supported by the open dialog) still works
  (Codex #10).
- Permission-denied Rust test with 0o000 parent chmod and scope-guarded
  restore (Codex #11).

Round 2 consistency follow-ups:
- useUnifiedHistory.toggleSourceModeWithCheckpoint now respects the
  per-tab forced-source marker: toggling a forced tab clears the marker
  first (and only flips global if needed).
- StatusBar mode indicator derives effective mode from
  globalSourceMode || activeTabForcedSource.
- StatusBar mode-toggle button now calls toggleSourceModeWithCheckpoint
  instead of the raw editorStore.toggleSourceMode, matching the F6 path.
- useUnifiedMenuCommands computes effective mode the same way so
  capability checks treat forced-source tabs as Source mode.

Coverage thresholds relaxed by 0.05 pp functions and 0.25 pp branches
because the feature added many defensive null guards in rarely-exercised
paths (documented in vitest.config.ts). 18,137 tests passing.
xulis pushed a commit to xulis/vmark that referenced this pull request May 11, 2026
* fix: move multi-cursor tokens to index.css (source of truth)

The multi-cursor plugin was defining :root tokens in its own CSS file,
violating the convention that all design tokens live in index.css.

Closes xiaolai#171

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback for PR xiaolai#178

Add multi-cursor tokens to design-tokens.md documentation per rule xiaolai#6:
"Update this doc when adding new tokens to index.css."

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: xiaolai <lixiaolai@gmail.com>
xiaolai added a commit that referenced this pull request May 26, 2026
…ow-editor

Resolves audit findings #3, #4, #5, #6 from the prior /cc-suite:audit-fix run.

#3 — blockMathKeymap.test.ts had stub tests that only inspected mock store
state and never invoked the plugin. Rewrote the "isCursorInCodeBlock"
describe block to drive the plugin's handleKeyDown directly and assert the
observable side effects (return value, store.exitEditing call, dispatched
transaction shape). Also surfaced and fixed a latent PM hazard: both
blockMathKeymap.exitEditing and codePreview.exitEditMode resolved $pos
against state.doc, but tr.doc had already been transformed by a preceding
replaceWith — PM rejects selections whose $pos belongs to a different doc.
Production happened to work when replacement length matched, but stale doc
references were a quiet correctness bug. Switched both sites to resolve
against tr.doc.

#4 — Replaced hardcoded UI strings in tiptap.ts and previewHelpers.ts with
i18n keys (editor:preview.empty / .renderFailed / .rendering / .emptyDiagram
/ .emptyMindmap / .emptySvg / .emptyWorkflow / .emptyMath). Added the eight
new keys to all ten editor.json locale files. Lint:i18n passes 219/219.

#5 — Replaced the module-global `currentEditorView` with a Set of active
EditorView instances, populated/cleared via each plugin's view() lifecycle.
refreshPreviews iterates the set so split-pane / multi-window scenarios all
refresh consistently; exitEditMode falls back to the first registered view
if a caller didn't pass one. Updated the "Known limitations" header to
reflect the new architecture. Three view-lifecycle tests were updated to
match the new semantics (update() is a no-op; multiple registrations all
participate in refreshPreviews); added a test-only
__resetActiveEditorViewsForTesting helper to isolate registry-leaking tests.

#6 — Added :focus-visible to four interactive buttons in workflow-editor.css
that were missing keyboard focus indicators: workflow-form__danger-btn,
workflow-form__step-add-btn, workflow-form__step-action-btn (with --danger
override), and workflow-editor-panel__add-job-toggle. Pattern follows the
existing .workflow-form__with-remove background-highlight convention from
.claude/rules/33-focus-indicators.md.

All 18 812 unit tests pass. Lints (ESLint, i18n, design-tokens) pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant