fix: sync gutter element heights during editor font size zoom

CSS variable changes alone don't trigger CodeMirror's measure cycle, so
gutter element heights would diverge from content line heights. The fix
reconfigures the font theme compartment (throttled to once per rAF) to
force a proper state transition → measure → syncGutters path.

Also adds missing fontFamily on .cm-gutters and i18n for "Follow app theme".
This commit is contained in:
t8y2
2026-05-25 00:23:44 +08:00
parent dbd2b2bab5
commit ae49d87166
5 changed files with 39 additions and 2 deletions
@@ -733,7 +733,7 @@ watch(
: 'bg-muted-foreground/30 border-muted-foreground/40'
"
/>
{{ theme.label }}
{{ theme.value === "app" ? t("settings.followAppTheme") : theme.label }}
</div>
</SelectItem>
</SelectContent>
@@ -187,6 +187,37 @@ function syncEditorFontCssVars(fontSize = liveFontSize.value, fontFamily = setti
if (!editorRef.value) return;
editorRef.value.style.setProperty(EDITOR_FONT_SIZE_CSS_VAR, `${clampEditorFontSize(fontSize)}px`);
editorRef.value.style.setProperty(EDITOR_FONT_FAMILY_CSS_VAR, fontFamily);
const cm = editorRef.value.querySelector(".cm-editor") as HTMLElement | null;
if (cm) cm.style.lineHeight = "1.6";
}
let pendingFontReconfig: { size: number; family: string } | null = null;
let fontReconfigScheduled = false;
function reconfigureFontTheme(size: number, family: string) {
if (!fontThemeComp || !editorViewModule || !view.value) return;
view.value.dispatch({
effects: fontThemeComp.reconfigure(
editorFontTheme(editorViewModule.EditorView, size, family, {
fixedHeight: true,
scrollable: true,
}),
),
});
}
function scheduleFontThemeReconfig(size: number, family: string) {
pendingFontReconfig = { size, family };
if (fontReconfigScheduled) return;
fontReconfigScheduled = true;
requestAnimationFrame(() => {
fontReconfigScheduled = false;
const p = pendingFontReconfig;
if (p) {
pendingFontReconfig = null;
reconfigureFontTheme(p.size, p.family);
}
});
}
function applyLiveFontSize(size: number) {
@@ -194,7 +225,10 @@ function applyLiveFontSize(size: number) {
if (liveFontSize.value === next) return;
liveFontSize.value = next;
syncEditorFontCssVars(next);
view.value?.requestMeasure();
// Throttle compartment reconfiguration to at most once per animation
// frame so that CSS variable changes remain smooth on every wheel tick,
// while the CodeMirror measure → syncGutters path keeps gutters aligned.
scheduleFontThemeReconfig(next, settingsStore.editorSettings.fontFamily);
}
function commitFontSize(size: number) {
+1
View File
@@ -1286,6 +1286,7 @@ export default {
fontSize: "Font Size",
theme: "Theme",
selectTheme: "Select theme...",
followAppTheme: "Follow app theme",
appLayout: "Interface Layout",
appLayoutSeparated: "Modern separated",
appLayoutSeparatedDescription: "Clear panel separation with block-style tabs.",
+1
View File
@@ -1263,6 +1263,7 @@ export default {
fontSize: "字号",
theme: "主题",
selectTheme: "选择主题...",
followAppTheme: "跟随应用主题",
appLayout: "界面布局",
appLayoutSeparated: "现代分隔",
appLayoutSeparatedDescription: "面板分隔更清晰,标签页为块状样式。",
+1
View File
@@ -106,6 +106,7 @@ export function buildEditorFontThemeRules(
".cm-gutters": {
borderRight: "0 !important",
fontSize: `var(${EDITOR_FONT_SIZE_CSS_VAR}, ${defaults?.size ?? 13}px)`,
fontFamily: `var(${EDITOR_FONT_FAMILY_CSS_VAR}, ${defaults?.family ?? "monospace"})`,
position: "relative",
},
".cm-gutters:after": {