Repository navigation
fix(preview): zoom content by font size, and sync the preview to the editor only when the reader leads - #1072
Merged
Merged
Conversation
…editor only when the reader leads Content zoom was CSS zoom around both panes, so in split view the editor was zoomed twice and Monaco's minimap drag ran ahead of the pointer. It now scales the preview's font sizes and measure, as the editor's font already was, and a zoom step keeps the line at the top. Typing near the top of the editor made it bounce: the preview re-render's scroll anchoring nudge was synced back to the editor, whose cursor reveal pulled it back. Preview scrolls now reach the editor only while the reader's last input in the panes was outside the editor. Closes #1071.
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1071, reported by @Zman199 on Windows 10 at 135% zoom: in split view the minimap slider ran ahead of the pointer when dragged, and typing made the editor bounce up and down or keep scrolling.
Mechanism
Content zoom was CSS
zoomon.markdown-container, which in split view wraps the editor pane as well, while the editor also multiplied its font size by the zoom. So the split-view editor was zoomed twice (a line 36.4px on screen at 140%, against 26px in the editor alone), and Monaco's minimap drag adds the pointer'spageYdelta, which is in zoomed pixels, to a slider position in unzoomed ones: 100px of mouse moved the slider 140px.The bounce is a loop. With sticky scroll on, Monaco keeps five lines above a cursor it reveals, so a keystroke near the top of the editor scrolls it up and the preview follows. The preview then re-renders, and Chromium's scroll anchoring nudges it a few pixels.
handleScrollcannot tell that nudge from the reader scrolling, so sync moves the editor back down into the five lines, and the next keystroke starts it again. At 140% it happened at 6 of 10 scroll positions; at 100% at none.Change
zoom: the preview's body and code font sizes and its measure are multiplied by the zoom, as the editor's font already was. Nothing on screen carries a CSS zoom any more, so editor, preview and pointer share one pixel space. Text scales and spacing does not, which is how VS Code'smarkdown.preview.fontSizebehaves; footnotes andkbd, the two pieces of body text with a fixed px size, are nowem. Images and diagrams keep their size, and the editor toolbar no longer grows in split view.previewLayout, so the outline's gutter check sees the width the text actually takes.scrollTopthat stays put, where CSS zoom scaled the offset too. The fold wrappers are re-measured first (measureNow), since placing the line before they caught up moved it a paragraph per step.For reference, VS Code's preview ignores its own scroll events for 50ms after the editor moves it and has no guard for re-renders; its editor has no reveal margin to pull back, so the loop does not form there. Joplin restores a stored scroll percentage after every content change and marks its own scrolls with an expiring counter.
Exports are unaffected by zoom, as before. With a non-default preview font size, exported footnotes and
kbdnow keep their proportion to the body text instead of staying at 12px and 11px.Tests
scripts/preview.test.ts: at 150% an 880px measure is 1320px of a 1400px pane and the outline counts as covering the text. Red without thepreviewLayoutchange.scripts/layout.test.ts:measureNowpublishes fold heights without waiting for a frame.The input rule and the zoom-step restore live in
MarkdownViewer.svelte, which the suites do not mount; both were checked in the app.Verification
All pass (951 + 770). In a dev build on Windows 11 (WebView2 157, display at 200%), driven over the DevTools protocol at 140%:
Not verified: macOS and Linux; a trackpad or touch scroll of the preview on real hardware; and the flag-clearing path itself, which I could not provoke.