fix: bypass CodeMirror posAtCoords for accurate cursor at non-100% CSS zoom

CSS zoom on document.documentElement causes a coordinate space mismatch
between mouse event clientX/Y (viewport space) and Range.getClientRects()
(CSS space), breaking CodeMirror's click-to-position mapping. The previous
requestMeasure() fix only recalibrated cached geometry, not this mismatch.

New approach: zoomCursorFix extension patches posAtCoords/posAndSideAtCoords
on the EditorView instance to use document.caretRangeFromPoint() — the
browser's native, zoom-aware API — with coord-adjustment fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lucaronin
2026-03-09 10:43:46 +01:00
parent e3d616cd26
commit 0082c02eb4
4 changed files with 241 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ import { EditorView, lineNumbers, highlightActiveLine, keymap } from '@codemirro
import { EditorState } from '@codemirror/state'
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'
import { frontmatterHighlightPlugin, frontmatterHighlightTheme } from '../extensions/frontmatterHighlight'
import { zoomCursorFix } from '../extensions/zoomCursorFix'
const FONT_FAMILY = '"Berkeley Mono", "JetBrains Mono", "Fira Mono", ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
@@ -98,6 +99,7 @@ export function useCodeMirror(
buildBaseTheme(isDark),
frontmatterHighlightTheme(isDark),
frontmatterHighlightPlugin,
zoomCursorFix(),
EditorView.updateListener.of((update) => {
if (update.docChanged) {
callbacksRef.current.onDocChange(update.state.doc.toString())