From d31ddfd06cb05f7bc13d9cdca91898268292b74c Mon Sep 17 00:00:00 2001 From: Clarence Palmer Date: Thu, 26 Feb 2026 21:16:30 -0800 Subject: [PATCH 1/2] fix: allow backspace to move to next run --- .../src/core/commands/backspaceNextToRun.js | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/super-editor/src/core/commands/backspaceNextToRun.js b/packages/super-editor/src/core/commands/backspaceNextToRun.js index 24584049fc..3b3f16ad0a 100644 --- a/packages/super-editor/src/core/commands/backspaceNextToRun.js +++ b/packages/super-editor/src/core/commands/backspaceNextToRun.js @@ -1,7 +1,7 @@ import { Selection } from 'prosemirror-state'; -const findPreviousTextDeleteRange = (doc, cursorPos, minPos) => { - for (let pos = cursorPos - 1; pos >= minPos; pos -= 1) { +const findPreviousTextDeleteRange = (doc, cursorPos) => { + for (let pos = cursorPos - 1; pos > 0; pos -= 1) { const $probe = doc.resolve(pos); const nodeBefore = $probe.nodeBefore; if (!nodeBefore?.isText || !nodeBefore.text?.length) continue; @@ -32,17 +32,7 @@ export const backspaceNextToRun = if (prevNode?.type !== runType || prevNode.content.size === 0) return false; } - // Constrain the text scan to the adjacent run so we never delete - // text from a previous paragraph or an unrelated run. - let runContentStart; - if ($pos.nodeBefore) { - runContentStart = $pos.pos - $pos.nodeBefore.nodeSize + 1; - } else { - const prevNode = state.doc.resolve($pos.start() - 1).nodeBefore; - runContentStart = $pos.start() - 1 - prevNode.nodeSize + 1; - } - - const deleteRange = findPreviousTextDeleteRange(state.doc, $pos.pos, runContentStart); + const deleteRange = findPreviousTextDeleteRange(state.doc, $pos.pos); if (!deleteRange) return false; tr.delete(deleteRange.from, deleteRange.to).setSelection(Selection.near(tr.doc.resolve(deleteRange.from))); From ab5dcf11472056cb8333a4ea2506152af97994fa Mon Sep 17 00:00:00 2001 From: Clarence Palmer Date: Thu, 26 Feb 2026 21:36:37 -0800 Subject: [PATCH 2/2] revert: tests too --- .../core/commands/backspaceNextToRun.test.js | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/packages/super-editor/src/core/commands/backspaceNextToRun.test.js b/packages/super-editor/src/core/commands/backspaceNextToRun.test.js index 215b6e1568..80b59a8a10 100644 --- a/packages/super-editor/src/core/commands/backspaceNextToRun.test.js +++ b/packages/super-editor/src/core/commands/backspaceNextToRun.test.js @@ -109,27 +109,4 @@ describe('backspaceNextToRun', () => { }); expect(bookmarkCount).toBe(1); }); - - it('does not scan into previous paragraphs when adjacent run has only non-text inline content', () => { - const schema = makeSchema(); - const doc = schema.node('doc', null, [ - schema.node('paragraph', null, [schema.node('run', null, schema.text('A'))]), - schema.node('paragraph', null, [ - schema.node('run', null, [schema.node('bookmarkEnd')]), - schema.node('run', null, schema.text('B')), - ]), - ]); - - const boundary = posBetweenRuns(doc, ''); - expect(boundary).not.toBeNull(); - - const state = EditorState.create({ schema, doc, selection: TextSelection.create(doc, boundary ?? 1) }); - const dispatch = vi.fn(); - - const ok = backspaceNextToRun()({ state, tr: state.tr, dispatch }); - - expect(ok).toBe(false); - expect(dispatch).not.toHaveBeenCalled(); - expect(state.doc.textContent).toBe('AB'); - }); });