mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
1d30b973c4
* feat(editor): Mod+E toggles markdown edit mode in place (#1479) * fix(editor): scope the edit-mode exit chord and wire its tests into CI - Early-return the dedicated Mod+E exit listener when the event target is an INPUT/TEXTAREA outside .cm-editor, so native text fields (Ask AI box, annotation textareas) keep their own Mod+E instead of committing and exiting the edit session underneath them; match the key case-insensitively so Caps Lock cannot dead-key the exit. CodeMirror's content DOM is contenteditable, so the editor path is untouched. Also note in code that mounting atomic-editor's selectionToolbar() would claim Mod-e and dead-key the chord. - New DOM test pinning the ownership split (foreign textarea keeps the session open; the chord from inside CodeMirror still exits), revert-verified against the guard. - De-flake "never discards an unsaved source-backed buffer silently": the single setTimeout(0) after a contentEditable DOM mutation raced CodeMirror's MutationObserver, which happy-dom intermittently never re-delivers after CM's stop()/start() observer cycling — the buffer is now dirtied through the editor's own dispatch, with a bounded poll for the toolstrip's Save readout. 8/8 stable under CI's exact invocation preceded by another App suite (previously ~3/8 failures). - Add App.editModeShortcut.test.tsx to the DOM-gated file enumeration in .github/workflows/test.yml so the suite actually runs in CI. --------- Co-authored-by: Michael Ramos <mdramos8@gmail.com>
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { scrollableEditSurface } from "./editScroll";
|
|
|
|
const scrollElement = (scrollHeight: number, clientHeight: number): HTMLElement =>
|
|
({ scrollHeight, clientHeight }) as unknown as HTMLElement;
|
|
|
|
describe("scrollableEditSurface", () => {
|
|
// The desktop layout: CodeMirror grows to full content height inside the
|
|
// document viewport, so `.cm-scroller` has nothing to scroll. Restoring the
|
|
// offset into it would silently lose the reader's place (#1479).
|
|
test("falls back to the document viewport when the editor cannot scroll", () => {
|
|
const viewport = scrollElement(8_204, 1_055);
|
|
const scroller = scrollElement(8_106, 8_106);
|
|
|
|
expect(scrollableEditSurface(scroller, viewport, true)).toBe(viewport);
|
|
});
|
|
|
|
// A height-bounded shell (compact touch) bounds the editor instead, so the
|
|
// offset lives inside CodeMirror.
|
|
test("uses the editor scroller when the shell bounds the editor", () => {
|
|
const viewport = scrollElement(700, 700);
|
|
const scroller = scrollElement(2_000, 600);
|
|
|
|
expect(scrollableEditSurface(scroller, viewport, true)).toBe(scroller);
|
|
});
|
|
|
|
// Capturing on the way in happens while the viewer is still mounted: the
|
|
// editor's scroller is stale there, and the viewer's offset is the one to keep.
|
|
test("always reads the document viewport while not editing", () => {
|
|
const viewport = scrollElement(8_204, 1_055);
|
|
const scroller = scrollElement(2_000, 600);
|
|
|
|
expect(scrollableEditSurface(scroller, viewport, false)).toBe(viewport);
|
|
});
|
|
|
|
test("stays null when the viewport is unavailable", () => {
|
|
expect(scrollableEditSurface(null, null, true)).toBeNull();
|
|
});
|
|
});
|