fix(editor): restore CodeMirror default spacing

Remove the zero-padding line override that replaced CodeMirror's built-in horizontal spacing and caused the editor content regression reported in #6093.

Disable completion icons through CodeMirror configuration, preserve placeholder and dark-theme contrast, and remove redundant editor style overrides.

Fixes #6093
This commit is contained in:
boojack
2026-07-14 21:35:55 +08:00
parent 8d9849e13f
commit df1967df91
6 changed files with 17 additions and 24 deletions
@@ -1,8 +1,6 @@
/*
* Styling for the CodeMirror source editor, in plain CSS with the app's theme
* variables — the same model Obsidian / GitHub use for an app-integrated CM6
* editor (class-based tokens + CSS, not a CSS-in-JS theme). Co-located with the
* component and scoped to its wrapper so nothing leaks to other CM instances.
* Scoped CodeMirror styling using the app's theme variables. The styles are
* co-located with the component so they do not leak to other editor instances.
*
* Token classes (.cm-md-*) come from the tagHighlighter in theme.ts; heading
* line classes (.cm-md-h*) from headingDecorations.ts; #tag/@mention
@@ -22,11 +20,12 @@
outline: none;
}
& .cm-content {
caret-color: var(--foreground);
font-family: inherit;
padding: 0;
}
& .cm-line {
padding: 0;
padding-inline: 0;
}
& .cm-scroller {
font-family: inherit;
@@ -35,16 +34,13 @@
}
& .cm-placeholder {
color: var(--muted-foreground);
opacity: 0.7;
}
/* drawSelection() caret + selection (no base color theme is loaded). */
& .cm-cursor,
& .cm-dropCursor {
border-left-color: var(--foreground);
}
& .cm-selectionBackground,
& .cm-focused .cm-selectionBackground {
& .cm-content::selection,
& .cm-content ::selection {
background: var(--accent);
}
@@ -117,19 +113,14 @@
}
& .cm-tooltip-autocomplete > ul {
font-family: inherit;
color: var(--popover-foreground);
}
& .cm-tooltip-autocomplete > ul > li {
padding: 0.25rem 0.5rem;
color: var(--popover-foreground);
}
& .cm-tooltip-autocomplete > ul > li[aria-selected] {
background: var(--accent);
color: var(--accent-foreground);
}
& .cm-completionIcon {
display: none;
}
& .cm-completionMatchedText {
text-decoration: none;
font-weight: 600;
@@ -2,7 +2,7 @@ import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirro
import { markdown } from "@codemirror/lang-markdown";
import { indentUnit } from "@codemirror/language";
import { Compartment, type Extension } from "@codemirror/state";
import { placeholder as cmPlaceholder, drawSelection, dropCursor, EditorView, type KeyBinding, keymap } from "@codemirror/view";
import { placeholder as cmPlaceholder, dropCursor, EditorView, type KeyBinding, keymap } from "@codemirror/view";
import { GFM } from "@lezer/markdown";
import { headingDecorations } from "./headingDecorations";
import { liftListItem, sinkListItem } from "./listIndent";
@@ -74,7 +74,6 @@ export function buildEditorExtensions({
// Core editing behavior. These are the pieces from CM6 setup that this memo
// editor uses, without enabling multi-cursor selection.
history(),
drawSelection(),
dropCursor(),
// Indent with spaces (markdown), matching the 2-space bullet nesting.
indentUnit.of(" "),
@@ -21,5 +21,8 @@ export function makeTagCompletionSource(getTags: () => string[]) {
}
export function tagAutocomplete(getTags: () => string[]): Extension {
return autocompletion({ override: [makeTagCompletionSource(getTags)] });
return autocompletion({
override: [makeTagCompletionSource(getTags)],
icons: false,
});
}
@@ -3,7 +3,7 @@ import { tags as t, tagHighlighter } from "@lezer/highlight";
/**
* Map markdown syntax tokens to stable class names. ALL visual styling lives in
* plain CSS (the `.memo-editor-content` block in `src/index.css`) so the editor
* plain CSS (the `.memo-editor-content` block in `Editor/editor.css`) so the editor
* is themed like the rest of the app — Tailwind/theme tokens in a stylesheet —
* rather than a CodeMirror CSS-in-JS theme object. Headings (`.cm-md-h*`) and
* `#tag`/`@mention` (`.cm-memo-*`) classes come from the decoration plugins;
+2 -2
View File
@@ -11,8 +11,8 @@
--popover-foreground: oklch(0.92 0.006 255);
/* Primary - readable blue for selected items, links, and focused controls */
--primary: oklch(0.62 0.11 250);
--primary-foreground: oklch(0.98 0.004 255);
--primary: oklch(0.66 0.11 250);
--primary-foreground: oklch(0.24 0.008 255);
/* Secondary - elevated surface for secondary buttons */
--secondary: oklch(0.33 0.011 255);
+3 -3
View File
@@ -13,7 +13,7 @@ describe("MemoEditor CodeMirror extensions", () => {
document.body.replaceChildren();
});
it("uses CodeMirror's selection and placeholder extensions without enabling multi-cursor selection", () => {
it("uses the native selection and CodeMirror placeholder without enabling multi-cursor selection", () => {
const parent = document.body.appendChild(document.createElement("div"));
const state = EditorState.create({
doc: "",
@@ -30,8 +30,8 @@ describe("MemoEditor CodeMirror extensions", () => {
views.push(view);
expect(view.state.facet(EditorState.allowMultipleSelections)).toBe(false);
expect(view.dom.querySelector(".cm-selectionLayer")).not.toBeNull();
expect(view.dom.querySelector(".cm-cursorLayer")).not.toBeNull();
expect(view.dom.querySelector(".cm-selectionLayer")).toBeNull();
expect(view.dom.querySelector(".cm-cursorLayer")).toBeNull();
expect(view.contentDOM).toHaveAttribute("aria-placeholder", "Any thoughts...");
expect(view.dom.querySelector(".cm-placeholder")).toHaveTextContent("Any thoughts...");
});