Skip to content

Commit ca2c419

Browse files
fix: Backspace bug when current block is empty and previous block's last child is empty (#2610)
Co-authored-by: Nick the Sick <computers@nickthesick.com>
1 parent 07df972 commit ca2c419

6 files changed

Lines changed: 6774 additions & 7840 deletions

File tree

package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"eslint-plugin-import": "^2.32.0",
1212
"glob": "^10.5.0",
1313
"nx": "22.5.4",
14-
"prettier": "^3.6.2",
14+
"prettier": "3.6.2",
1515
"prettier-plugin-tailwindcss": "^0.6.14",
1616
"serve": "14.2.4",
1717
"typescript": "^5.9.3",
@@ -33,7 +33,21 @@
3333
"msw",
3434
"nx",
3535
"unrs-resolver"
36-
]
36+
],
37+
"overrides": {
38+
"@tiptap/extension-link": "3.15.3",
39+
"msw": "2.11.5",
40+
"ai": "6.0.5",
41+
"@ai-sdk/anthropic": "3.0.2",
42+
"@ai-sdk/openai": "3.0.2",
43+
"@ai-sdk/groq": "3.0.2",
44+
"@ai-sdk/google": "3.0.2",
45+
"@ai-sdk/mistral": "3.0.2",
46+
"@ai-sdk/openai-compatible": "2.0.2",
47+
"@ai-sdk/provider-utils": "4.0.2",
48+
"@ai-sdk/react": "3.0.5",
49+
"@ai-sdk/gateway": "3.0.4"
50+
}
3751
},
3852
"packageManager": "pnpm@10.23.0+sha512.21c4e5698002ade97e4efe8b8b4a89a8de3c85a37919f957e7a0f30f38fbc5bbdd05980ffe29179b2fb6e6e691242e098d945d1601772cad0fef5fb6411e2a4b",
3953
"private": true,

packages/core/src/extensions/tiptap-extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,26 @@ export const KeyboardShortcutsExtension = Extension.create<{
226226
state.doc,
227227
blockInfo.bnBlock.beforePos,
228228
);
229-
if (!prevBlockInfo || !prevBlockInfo.isBlockContainer) {
229+
if (!prevBlockInfo) {
230+
return false;
231+
}
232+
const bottomNestedPrevBlockInfo = getBottomNestedBlockInfo(
233+
state.doc,
234+
prevBlockInfo,
235+
);
236+
if (!bottomNestedPrevBlockInfo.isBlockContainer) {
237+
return false;
238+
}
239+
if (
240+
!bottomNestedPrevBlockInfo ||
241+
!bottomNestedPrevBlockInfo.isBlockContainer
242+
) {
230243
return false;
231244
}
232245

233246
let chainedCommands = chain();
234247

235-
// Moves the children of the current block to the previous one.
248+
// Moves the children the current block.
236249
if (blockInfo.childContainer) {
237250
chainedCommands.insertContentAt(
238251
blockInfo.bnBlock.afterPos,
@@ -241,8 +254,8 @@ export const KeyboardShortcutsExtension = Extension.create<{
241254
}
242255

243256
if (
244-
prevBlockInfo.blockContent.node.type.spec.content ===
245-
"tableRow+"
257+
bottomNestedPrevBlockInfo.blockContent.node.type.spec
258+
.content === "tableRow+"
246259
) {
247260
const tableBlockEndPos = blockInfo.bnBlock.beforePos - 1;
248261
const tableBlockContentEndPos = tableBlockEndPos - 1;
@@ -254,17 +267,18 @@ export const KeyboardShortcutsExtension = Extension.create<{
254267
lastCellParagraphEndPos,
255268
);
256269
} else if (
257-
prevBlockInfo.blockContent.node.type.spec.content === ""
270+
bottomNestedPrevBlockInfo.blockContent.node.type.spec
271+
.content === ""
258272
) {
259273
chainedCommands = chainedCommands.setNodeSelection(
260-
prevBlockInfo.blockContent.beforePos,
274+
bottomNestedPrevBlockInfo.blockContent.beforePos,
261275
);
262276
} else {
263-
const blockContentStartPos =
264-
prevBlockInfo.blockContent.afterPos - 1;
277+
const blockContentEndPos =
278+
bottomNestedPrevBlockInfo.blockContent.afterPos - 1;
265279

266280
chainedCommands =
267-
chainedCommands.setTextSelection(blockContentStartPos);
281+
chainedCommands.setTextSelection(blockContentEndPos);
268282
}
269283

270284
return chainedCommands

packages/core/src/schema/blocks/createSpec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,19 @@ export function addNodeAndExtensionsToSpec<
211211
editor as any,
212212
);
213213

214+
// Cast needed because render returns `dom: HTMLElement | DocumentFragment`
215+
// but tiptap's NodeView expects `dom: HTMLElement`
216+
const typedNodeView = nodeView as unknown as NodeView;
217+
214218
if (blockImplementation.meta?.selectable === false) {
215-
applyNonSelectableBlockFix(nodeView, this.editor);
219+
applyNonSelectableBlockFix(typedNodeView, this.editor);
216220
}
217221

218222
// See explanation for why `update` is not implemented for NodeViews
219223
// https://github.com/TypeCellOS/BlockNote/pull/1904#discussion_r2313461464
220224
// TODO: in a future version, we might want to implement updates so that
221225
// vanilla blocks don't always re-render entirely (https://github.com/TypeCellOS/BlockNote/issues/220)
222-
return nodeView;
226+
return typedNodeView;
223227
};
224228
},
225229
});

playground/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
"@blocknote/xl-multi-column": "workspace:^",
2828
"@blocknote/xl-odt-exporter": "workspace:^",
2929
"@blocknote/xl-pdf-exporter": "workspace:^",
30+
"@emotion/react": "11.14.0",
31+
"@emotion/styled": "11.14.1",
3032
"@liveblocks/core": "3.7.1-tiptap3",
3133
"@liveblocks/react": "3.7.1-tiptap3",
3234
"@liveblocks/react-blocknote": "3.7.1-tiptap3",

playground/src/examples.gen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@
321321
"pathFromRoot": "examples/01-basic",
322322
"slug": "basic"
323323
},
324-
"readme": "This example makes the editor read-only while showing the same content as the [Default Schema Showcase](/examples/01-basic/04-default-blocks/) example.\n\n**Relevant Docs:**\n\n- [Editor Setup](/docs/getting-started/editor-setup)\n- [Document Structure](/docs/foundations/document-structure)\n- [Default Schema](/docs/foundations/schemas)"
324+
"readme": "This example makes the editor read-only while showing the same content as the [Default Schema Showcase](/examples/basic/default-blocks) example.\n\n**Relevant Docs:**\n\n- [Editor Setup](/docs/getting-started/editor-setup)\n- [Document Structure](/docs/foundations/document-structure)\n- [Default Schema](/docs/foundations/schemas)"
325325
},
326326
{
327327
"projectSlug": "testing",

0 commit comments

Comments
 (0)