Skip to content

Commit

Permalink
editor: fix backspace deleting formatting in list item (#6712)
Browse files Browse the repository at this point in the history
* fix hitting backspace inside the second (or next) p in list item deleted the formatting of the entire list item

Signed-off-by: 01zulfi <[email protected]>
  • Loading branch information
01zulfi committed Nov 18, 2024
1 parent 34d0123 commit f90935e
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 2 deletions.
28 changes: 26 additions & 2 deletions packages/editor/patches/@tiptap+extension-list-keymap+2.6.6.patch
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/node_modules/@tiptap/extension-list-keymap/dist/index.cjs b/node_modules/@tiptap/extension-list-keymap/dist/index.cjs
index 0f8ae36..2f715b5 100644
index 0f8ae36..adeee92 100644
--- a/node_modules/@tiptap/extension-list-keymap/dist/index.cjs
+++ b/node_modules/@tiptap/extension-list-keymap/dist/index.cjs
@@ -82,7 +82,9 @@ const handleBackspace = (editor, name, parentListTypes) => {
Expand All @@ -13,8 +13,20 @@ index 0f8ae36..2f715b5 100644
const $listPos = editor.state.doc.resolve($anchor.before() - 1);
const listDescendants = [];
$listPos.node().descendants((node, pos) => {
@@ -111,6 +113,11 @@ const handleBackspace = (editor, name, parentListTypes) => {
if (!listItemPos) {
return false;
}
+ // if the current position is not at the start of the list item
+ // then join backward i.e. join within the list item
+ if (listItemPos.$pos.parentOffset !== 0) {
+ return editor.commands.joinBackward();
+ }
const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
const prevNode = $prev.node(listItemPos.depth);
const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
diff --git a/node_modules/@tiptap/extension-list-keymap/dist/index.js b/node_modules/@tiptap/extension-list-keymap/dist/index.js
index f7ab1e4..8645c44 100644
index f7ab1e4..6ea03d5 100644
--- a/node_modules/@tiptap/extension-list-keymap/dist/index.js
+++ b/node_modules/@tiptap/extension-list-keymap/dist/index.js
@@ -78,7 +78,9 @@ const handleBackspace = (editor, name, parentListTypes) => {
Expand All @@ -28,3 +40,15 @@ index f7ab1e4..8645c44 100644
const $listPos = editor.state.doc.resolve($anchor.before() - 1);
const listDescendants = [];
$listPos.node().descendants((node, pos) => {
@@ -107,6 +109,11 @@ const handleBackspace = (editor, name, parentListTypes) => {
if (!listItemPos) {
return false;
}
+ // if the current position is not at the start of the list item
+ // then join backward i.e. join within the list item
+ if (listItemPos.$pos.parentOffset !== 0) {
+ return editor.commands.joinBackward();
+ }
const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
const prevNode = $prev.node(listItemPos.depth);
const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`hitting backspace at the start of first list item 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><p>item1</p><ul><li><p>item2</p></li></ul></div></div>"`;

exports[`hitting backspace at the start of the second (or next) list item 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><ul><li><p>item1item2</p></li></ul></div></div>"`;

exports[`hitting backspace at the start of the second (or next) paragraph inside the list item 1`] = `"<div><div contenteditable="true" translate="no" class="tiptap ProseMirror" tabindex="0"><ul><li><p>item 1item 2</p></li></ul></div></div>"`;
138 changes: 138 additions & 0 deletions packages/editor/src/extensions/list-item/tests/list-item.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import ListKeymap from "@tiptap/extension-list-keymap";
import { expect, test } from "vitest";
import { createEditor, h, li, p, ul } from "../../../../test-utils/index.js";
import BulletList from "../../bullet-list/index.js";
import CheckListItem from "../../check-list-item/index.js";
import CheckList from "../../check-list/index.js";
import OrderedList from "../../ordered-list/index.js";
import { OutlineListItem } from "../../outline-list-item/index.js";
import { OutlineList } from "../../outline-list/index.js";
import { TaskItemNode } from "../../task-item/index.js";
import { TaskListNode } from "../../task-list/index.js";
import { ListItem } from "../index.js";

test("hitting backspace at the start of first list item", async () => {
const el = ul([li([p(["item1"])]), li([p(["item2"])])]);
const editorElement = h("div");
const editor = createEditor({
element: editorElement,
initialContent: el.outerHTML,
extensions: {
listItem: ListItem,
listKeymap: ListKeymap.configure({
listTypes: [
{
itemName: ListItem.name,
wrapperNames: [BulletList.name, OrderedList.name]
},
{
itemName: TaskItemNode.name,
wrapperNames: [TaskListNode.name]
},
{
itemName: OutlineListItem.name,
wrapperNames: [OutlineList.name]
},
{
itemName: CheckListItem.name,
wrapperNames: [CheckList.name]
}
]
})
}
});
const event = new KeyboardEvent("keydown", { key: "Backspace" });
editor.editor.view.dom.dispatchEvent(event);
expect(editorElement.outerHTML).toMatchSnapshot();
});

test("hitting backspace at the start of the second (or next) list item", async () => {
const el = ul([li([p(["item1"])]), li([p(["item2"])])]);
const editorElement = h("div");
const editor = createEditor({
element: editorElement,
initialContent: el.outerHTML,
extensions: {
listItem: ListItem,
listKeymap: ListKeymap.configure({
listTypes: [
{
itemName: ListItem.name,
wrapperNames: [BulletList.name, OrderedList.name]
},
{
itemName: TaskItemNode.name,
wrapperNames: [TaskListNode.name]
},
{
itemName: OutlineListItem.name,
wrapperNames: [OutlineList.name]
},
{
itemName: CheckListItem.name,
wrapperNames: [CheckList.name]
}
]
})
}
});
editor.editor.commands.setTextSelection(12);
const event = new KeyboardEvent("keydown", { key: "Backspace" });
editor.editor.view.dom.dispatchEvent(event);
expect(editorElement.outerHTML).toMatchSnapshot();
});

test("hitting backspace at the start of the second (or next) paragraph inside the list item", async () => {
const el = ul([li([p(["item 1"]), p(["item 2"])])]).outerHTML;
const editorElement = h("div");
const editor = createEditor({
element: editorElement,
initialContent: el,
extensions: {
listItem: ListItem,
listKeymap: ListKeymap.configure({
listTypes: [
{
itemName: ListItem.name,
wrapperNames: [BulletList.name, OrderedList.name]
},
{
itemName: TaskItemNode.name,
wrapperNames: [TaskListNode.name]
},
{
itemName: OutlineListItem.name,
wrapperNames: [OutlineList.name]
},
{
itemName: CheckListItem.name,
wrapperNames: [CheckList.name]
}
]
})
}
});
editor.editor.commands.setTextSelection(11);
const event = new KeyboardEvent("keydown", { key: "Backspace" });
editor.editor.view.dom.dispatchEvent(event);
expect(editorElement.outerHTML).toMatchSnapshot();
});
1 change: 1 addition & 0 deletions packages/editor/test-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function elem<K extends keyof HTMLElementTagNameMap>(tag: K) {

export const ul = elem("ul");
export const li = elem("li");
export const p = elem("p");

export function text(text: string) {
return document.createTextNode(text);
Expand Down

0 comments on commit f90935e

Please sign in to comment.