Fixed
- Flash labels missing from top half of viewport with frontmatter scrolled off-screen — in Live Preview mode, when YAML frontmatter properties (~10-15 lines) were collapsed into a widget and scrolled off-screen, flash
f/F/t/Tlabels only appeared in the bottom half of the viewport. The number of missing lines matched the frontmatter line count. Root cause:getVisibleRange()insrc/easymotion/targets.tsusedview.lineBlockAtHeight()which relies on CM6's height map — when the collapsed frontmatter widget was off-screen, height estimation errors causedcoordsAtPos()to returnnullfor targets near the viewport top, andfilterVisibleTargets()dropped them. Fixed by usingview.visibleRanges(actually-rendered document ranges) instead oflineBlockAtHeight. Also affected EasyMotion target scanning. (#114)- Plugin:
src/easymotion/targets.ts(getVisibleRange— replacedlineBlockAtHeightwithview.visibleRanges) - Plugin:
test/unit/flash-targets.test.ts(updated CM6 stub to providevisibleRanges)
- Plugin:
v$dcursor off-by-one — visual-modev$dleft cursor at ch:5 instead of ch:4 after deleting to end of line. Root cause:clipCursorToContentin the delete operator ran whilevim.visualModewas stilltrue(allowingch = text.length), andexitVisualModeran after the operator returned without re-clamping. Fixed by re-clippingoperatorMoveTothroughclipCursorToContentafterexitVisualModeinapplyOperator.- Fork:
~/Repos/codemirror-vim/src/vim.js(applyOperator— re-clip cursor afterexitVisualMode) - Fork:
~/Repos/codemirror-vim/DIFFERENCES.md(added "Visual operator cursor re-clamping after exitVisualMode" section)
- Fork:
ssubstitute consumed by flash jump in Tier 1 tests — theskey did nothing innormal-editing.e2e.tsbecause the test vault hadflashJumpEnabled: true, which mappedsto flash jump mode instead of the built-in substitute (cl). Flash jump tests explicitly enable this setting in their ownbefore()hooks. Fixed by settingflashJumpEnabled: falseindata.jsonand adding a defensive disable in the test'sbefore()hook.- Plugin:
test-vault/.obsidian/plugins/vim-motions/data.json(flashJumpEnabled: false) - Plugin:
test/specs/vim-builtin/normal-editing.e2e.ts(defensive flash disable inbefore())
- Plugin:
vt.don multi-dot content consumed by flash labels —vt.don content with 2+ dot characters (e.g.,foo.bar.baz) deleted only 1 character because flash motions showed labels for the multiple.matches, consuming thedkey as a label character. Not a fork bug — flash working as designed (same as flash.nvim in Neovim). Fixed by settingenableFlash: falsein test vaultdata.jsonand disabling flash invisual-mode.e2e.tsbefore()hook. Flash-specific behavior is tested in dedicated test files.- Plugin:
test-vault/.obsidian/plugins/vim-motions/data.json(enableFlash: false) - Plugin:
test/specs/vim-builtin/visual-mode.e2e.ts(defensive flash disable inbefore())
- Plugin:
Added
vimHandleKeystest helper — new helper intest/helpers.tsthat dispatches all keys synchronously throughVim.handleKey()in a singleexecuteObsidiancallback, bypassing DOM event timing. Used for visual-mode compound operations that fail withvimRawKeysDOM dispatch.- Plugin:
test/helpers.ts(vimHandleKeysfunction)
- Plugin:
useHandleKeyflag onTestCaseDefinition— test cases can opt in tovimHandleKeysdispatch viauseHandleKey: true.testWithNeovimchecks this flag and routes tovimHandleKeysinstead ofdispatchVimKeys.- Plugin:
test/neovim/test-definitions.ts(useHandleKey?: booleanon interface, set on 6 visual-mode test cases) - Plugin:
test/neovim/test-wrapper.ts(importvimHandleKeys,useHandleKeyin config type, dispatch branching)
- Plugin:
- Deviation category classification — all deviations in
deviations.tsnow have acategoryfield (intentional,infra-limitation,upstream-bug,upstream-unsupported,recording-issue).findDeviation()export added.[INFRA-SKIP]console warnings emitted for infra-limitation deviations.- Plugin:
test/neovim/deviations.ts(interface + 25 entries classified +findDeviation()) - Plugin:
test/neovim/test-wrapper.ts(infra-skip logging in both live and golden paths)
- Plugin:
- Golden schema extended with
registersandvisualMode—GoldenCase.resultnow includes optionalregisters(unnamed register text + linewise flag) andvisualMode(charwise/linewise/blockwise). Recording captures these fields. Comparison is not yet enabled (register state leaks between tests in shared Obsidian session).- Plugin:
test/neovim/compare.ts(EditorStateextended,getObsidianState/getNeovimStatecapture registers and visual sub-mode) - Plugin:
test/neovim/golden.ts(GoldenCaseextended) - Plugin:
test/neovim/record-golden.ts(captures registers and visual mode) - Plugin:
test/neovim/client.ts(getRegisterType,getRawModemethods) - Plugin:
test/neovim/golden-data/*.json(24 files re-recorded with new fields)
- Plugin:
- Golden mode comparison —
testWithNeovim()golden path now comparesmodein addition tocontentandcursor. Mode mismatches that were previously invisible are now caught.- Plugin:
test/neovim/test-wrapper.ts(mode comparison in golden path)
- Plugin:
else { throw }guards on all 26SUITES.find()files — if a suite name is renamed intest-definitions.tsbut not in the spec file, the test runner produces an explicit failure instead of silently generating zero tests.- Plugin:
test/specs/vim-builtin/*.e2e.ts(26 files)
- Plugin:
Changed
- E2E test assertions strengthened — 35 tests that previously only checked
mode === 'normal'orassertPluginLoaded()now have content, cursor, or behavioral assertions. 16 workspace-layout ex-command tests renamed with[crash-guard]prefix. 1 tautological assertion fixed (toBeGreaterThanOrEqual(0)→toBe(0)).- Plugin:
test/specs/undo-tree.e2e.ts,test/specs/undo-tree-navigation.e2e.ts,test/specs/vim-builtin/ex-commands-expanded.e2e.ts,test/specs/vimrc.e2e.ts
- Plugin:
- Deviation count reduced — 6 visual-mode infra-limitation deviations resolved via
useHandleKey(V3j+J, vip+d, v+r, v+aw+d, vt.+d, v$+d). 1 deviation resolved via key-string fix (lua nmap change word—<Esc>literal →\x1bbyte). 1 reclassified frominfra-limitationtoupstream-bug(lua leader key mapping).
Tests
- 1 e2e test in
test/specs/flash-frontmatter-viewport.e2e.ts(issue #114): flash labels appear in top half of viewport when frontmatter properties are scrolled off-screen in Live Preview mode — verifies labels are not clustered in bottom half only
Documentation
CHANGELOG.mdKNOWN_LIMITATIONS.md: Added "E2E test infrastructure weaknesses" section with fixed/remaining items; markedssubstitute test failure as fixed; updated deviation-masked operations count and root causes; marked flash frontmatter viewport offset as fixedAGENTS.md: Updated deviation registry description with categories and[INFRA-SKIP]; updated test helpers withvimHandleKeys; updatedtargets.tsdescription withvisibleRangesCONTRIBUTING.md: AddedvimHandleKeysto helper list; addeduseHandleKeyflag documentation; updated deviations.ts description with categories; updatedtargets.tsdescription withvisibleRangesDIFFERENCES.md(fork): Added "Visual operator cursor re-clamping after exitVisualMode" section
Full Changelog: 0.103.0...0.104.0