Repository navigation
Conversation
petyosi
left a comment
There was a problem hiding this comment.
Thanks for this. Routing source/diff insertions through CodeMirror is the right direction, and the tests separate the old and new behaviour well (20 of the 27 unit tests fail on main). A few things need to change before this can go in.
1. setMarkdown is dropped after a source → diff switch (src/plugins/core/index.ts, the viewMode$ subscription)
Source ↔ diff switches no longer publish setMarkdown$, so markdown$ keeps the last rich-text value. setMarkdown$ then compares new values against that stale value (newMarkdown.trim() !== oldMarkdown.trim()) and drops calls that should change the document.
Repro: load A, edit to B in source mode, switch to diff, call setMarkdown('A') (e.g. a "reset" button). The editor keeps showing B. On main it shows A.
The single-mode case is already broken on main, but this PR makes it reachable through ordinary mode switches. In source/diff mode, compare against markdownSourceEditorValue$ and publish the new document to it directly. Re-publishing an unchanged markdown$ won't emit, so the existing link can't carry it.
2. Pending selection/history is lost under StrictMode (getSourceEditorConfig in diff-source/index.tsx)
getSourceEditorConfig clears pendingSourceEditorState$ as it reads it. StrictMode's throwaway first mount takes the pending state, and the real mount gets only { doc }: cursor at 0 and nothing to undo. Content is kept, but the "selection and history carry over" guarantee doesn't hold in development. Please make the read side-effect free (the doc-equality check already covers stale state) and clear the pending state on viewMode$ changes instead.
3. Inserting right after source → diff ignores the source cursor
When sourceEditorView$ still holds the outgoing view, the pending state is built from scratch with the cursor at 0. Put the source cursor at the end of Original rich text, switch to diff, call insertMarkdown('X'), and you get XOriginal rich text. Building the pending state from editor.view.state when an outgoing view exists keeps both the selection and the history.
Smaller things
EditorState.readOnly.of(...)in the pending state has no effect, because programmaticreplaceSelectionignores it. Either drop it or add an explicitreadOnly$guard in the handler.- The pending-state construction is duplicated between the insert handler and
getSourceEditorConfig. A shared helper would keep them from drifting. - Please note the behaviour change in the description: source ↔ diff no longer round-trips through Lexical, so the parse-error banner and
onErrornow fire only when returning to rich-text.
Fixes #636.
Problem
insertMarkdown()always updates the hidden Lexical editor. In source and diff mode that editor can still contain the last rich-text document, so an insertion replaces newer source edits with stale content.Changes
The public API and the existing rich-text selection requirement are unchanged.
Verification
Latest head:
53887ad239839a53c9128d66098310023032c1de, incorporating current main and the Firefox clipboard fixture correction.The expanded regressions cover external
setMarkdown, source-to-diff transitions, StrictMode remounts, pending insertions, selection/history preservation, and read-only behavior. Native browser verification is now complete through upstream CI.