Added
- Local typings for Obsidian's core-plugin view trees — obsidian-typings declares
Tree<T>,TreeItemandTreeCollapsibleItembut attachestreetoFileExplorerViewonly. Measured on 1.13.7, five views own an equivalent navigable tree:file-explorer,outline,tag,all-propertiesandbookmarks.changeFocusedItem()movesfocusedItemin all five, whilesetCollapsedis present only infile-explorer,outlineandtag. Resolution is by allowlist rather than by shape, becausebacklink(view.backlink.backlinkDom) andsearch(view.dom) carry aResultDom— a different interface that also haschangeFocusedItem, so duck-typing finds it.ResultDomis not inert: itschangeFocusedItemtakes'forwards'just asTree's does, and onsearchit moves focus.backlinkis unverified, its view having rendered no rows in two attempts. No user-visible behaviour changes; this is the groundwork for navigating those views, and follows theTableEditorroute of declaring locally, proving in the plugin, then upstreaming.- Plugin:
src/types/core-view-trees.d.ts(new),src/workspace/core-view-tree.ts(new)
- Plugin:
- Native File Explorer Vim navigation — when workspace navigation is enabled and the native File Explorer has focus, unmodified
h/j/k/lreuse its arrow-key behavior, including counted movement capped at 100. They are ordinaryGlobalMappingRegistryentries, so they remap and unmap like every other global binding:h/lunder a newexplorergate that keeps them from being swallowed outside the tree, andj/kas the existing scroll entries with an explorer branch, since the registry stores one entry per key. Interaction tracking preserves navigation when Obsidian targetsBODYand clears it on focus or pointer movement outside the explorer; pending chords such as<C-w>hare untouched. Rename controls, composition, modified keys, modals, editors, and other views retain their original keystrokes. (#191)- Plugin:
src/workspace/global-key-handler.ts,src/workspace/global-defaults.ts,src/workspace/global-mapping-registry.ts,src/workspace/file-explorer-context.ts(new)
- Plugin:
Fixed
- A focused sidebar pane no longer scrolls the main editor — with the tag or outline pane focused,
j/k/G/gg/H/L/<C-d>/<C-u>/<C-f>/<C-b>were intercepted and applied to the note behind them: five presses ofjscrolled the editor 196 px.workspaceNavViewTypesdoes not list those view types, so thestandardgate should have declined, butisPluginLeafActive()askedgetMostRecentLeaf(), which is documented as returning the root-split leaf "while a sidebar leaf might be active" and so reportedmarkdownin every case. The handler now tracks the leaf that actually gained focus throughactive-leaf-changeand prefers it, falling back togetMostRecentLeaf(). The search pane was already protected by the focused-input guard, and the File Explorer by its own navigation. (#191)- Plugin:
src/workspace/global-key-handler.ts
- Plugin:
- File Explorer
j/kno longer depend on that bug — they are thestandardscroll entries branching on explorer context, so once the gate correctly rejected sidebar leaves they stopped moving the tree.isPluginLeafActive()now declines to veto when the keystroke belongs to the File Explorer.- Plugin:
src/workspace/global-key-handler.ts
- Plugin:
- Multi-digit counts now reach global key bindings — every count typed outside the editor was truncated to its first digit, so
12gtwent to tab 1 and30jscrolled three lines instead of thirty. The first digit is captured in thegateApplies === nullbranch of the gate block, and that branch returns unconditionally for any key it does not consume. The continuation accumulator sat below the gate block, so it was unreachable for a second digit — an unmapped digit always resolves togateApplies === nulland returns there. Single-digit counts were unaffected, which is why this went unnoticed;3gtand its test have always passed. The accumulator now runs before the gate block, and carries a note that the ordering is load-bearing.- Plugin:
src/workspace/global-key-handler.ts
- Plugin:
Tests
keeps source-rendered frontmatter fully navigableis fixed, and it was test-side — the spec setpropertiesInDocumenttosource, but something reverted it during the reconnect that follows, so the walk ran withvisibleand stalled at the first body line. The product was correct throughout: the fork's gate readsgetVaultConfig(app, 'propertiesInDocument') === 'source'live and reportedfalsebecause that is what the config said. The tell was already in the spec — thevisibletest expects exactly the7,6,6,6,6,6thesourcetest was failing with, so the source walk had silently become the visible walk. Forced on Linux, where it had never failed, by injectingsetPropertiesMode('visible')before the walk: byte-identical to both CI observations.measureFrontmatterWalknow takes the expected mode and re-asserts it at walk time, and the forcing probe goes green with the injection still in place.- 3 further unit cases pin that File Explorer navigation is independent of
workspaceNavViewTypes(both gates), and that the explorer is still driven when it lives in a main-area tab, wheregetMostRecentLeaf()does reportfile-explorerand would otherwise veto it. Negative controls: removing the explorer exception failed both main-area and sidebar cases with[]instead of['ArrowDown']; making the explorer gate consultgetNavViewTypes()failed thehcase and bothh/ltranslations withprevented 0instead of1. - 16 unit cases in
test/unit/workspace/core-view-tree.test.tscover the allowlist, tree resolution, count handling and collapsibility reporting; 12 e2e cases intest/specs/core-view-trees.e2e.tsre-measure every declared row against a real Obsidian and assertbacklink/searchstay excluded. Negative controls: addingbacklinkto the navigable list failed both the pinned-list case and the exclusion case, claimingall-propertiescollapsible failed the pinned-list case, and addingbacklinkto the e2e's own list failed only that view while the real five stayed green. Two defects in the first draft of the e2e were caught this way and are worth recording — hoistingchangeFocusedIteminto a local detached it from its receiver and threw onthis.focusedItem, and comparing focus by label reported "did not move" forbookmarks, whose rows render no text. A third, found later: the original survey reportedsearchandbacklinkas inert because it readfocusedItem.selfEl, whichResultDomitems do not have — they exposeel.searchnavigates fine when called correctly, so the exclusion stands on the two interfaces being different, not on one being dead. - 5 unit cases and 3 e2e cases in
test/specs/global-nav.e2e.tscover the sidebar gate:tag/outline/search/backlinkmust not scroll the editor, a main-area nav view still must, and the File Explorer'sjstill moves the tree. Negative controls: removing the active-leaf preference scrolled the editor 77 px in thetagandoutlinee2e cases and failed 4 unit cases; removing the explorer exception left the File Explorerjdispatching no arrow. The unit mock also now collects everyactive-leaf-changesubscriber, because capturing only the last one bound theFileExplorerContextlistener instead of the handler's and hid the fix entirely. - 4 unit cases in
test/unit/global-key-handler.test.tscover two-digit, four-digit, and trailing-zero counts dispatched to abuiltinaction, plus12gtacross a multi-key chord — a separate path, since the count has to survive a partial match and a timeout restart. Each was negative-controlled by restoring the pre-fix file verbatim:12xdelivered1,9999xdelivered9,30xdelivered3, and12gtdelivered1. All four returned green once the fix was restored. - 25 File Explorer unit cases and 7 Obsidian E2E scenarios cover arrow translation, counts and the 100-movement cap, focus/pointer/contenteditable gates, physical-key observation,
<C-w>h, and the new registry behaviour:h/lare not swallowed outside the tree,j/kstill scroll there,<C-w>j/k/lstill reach their pane commands,hdisappears when workspace navigation is off, and a usergmap hoverrides the default. Every case was negative-controlled: registeringh/lat thestandardgate gaveprevented 1, dispatched 1instead of0, 0; an unconditional explorer branch gavescrolls 0instead of1; removing the<C-w>jentry gave[]instead of['editor:focus-bottom']; forcingwsNavtrue lefthregistered; blocking registry overwrite gavecommands []instead of['app:go-back']; orderingexplorerahead ofstructuralgaveprevented 0instead of1; removing thefocusinlistener dispatched one unwantedArrowDown; removing the synthetic-event guard reported<ArrowDown>as a physical key; removing the cap dispatched 9,999 instead of 100; and removing thecontentEditablegate gaveprevented 1, stopped 1instead of0, 0. (#191) - A truncated plugin-tarball download no longer kills a CI shard —
scripts/fetch-test-plugins.shpipedcurlintotar, so a response cut mid-stream was unrecoverable: codeload truncated aflash.nvimtarball,tardied withgzip: stdin: unexpected end of file, and the whole Windows shard failed before any test ran. A truncated body is not an HTTP error, socurl -fnever caught it. Each tarball now downloads to disk with--retry 3 --retry-all-errorsbefore extraction.- Plugin:
scripts/fetch-test-plugins.sh
- Plugin:
Documentation
AGENTS.md,CONTRIBUTING.md: the registry rule for global keys,src/workspace/file-explorer-context.ts,src/workspace/core-view-tree.ts, the locally declared core-plugin view trees, and the constraint thattest/specs/**cannot value-import asrc/**/*.tsmodule.docs/configuration/remapping.md,docs/configuration/settings.md: the File Explorer keys are remappable like any other global binding, and Workspace navigation gates them.test/flaky-inventory.md: three CI failures observed during this work.keeps source-rendered frontmatter fully navigablereproduced on Windows with diagnostics byte-identical to the inventoried macOS case, which ruled out the environment and led to the forced failure and fix recorded under Tests. It is now resolved as test-side, and is added to the main inventory table, which had been missing it. The other two —paints an embedded note the same way(macOS) andleaves the stock behaviour when the setting is disabled(Windows). Both are recorded asUnknownwith the observed values; a passing re-run is not a classification.AGENTS.md,CONTRIBUTING.md: File Explorer key handling.README.md,docs/features/workspace-navigation.md,docs/reference/keybindings.md: native File Explorer navigation, counts, focus gates, and editable-control exclusions.
Full Changelog: 1.1.1...1.2.0