fix: Block corruption when deleting block content using deleteLine command (#134)

* fix: cell corruption when deleting block contents

* customize deleteLine to fix cell corruption

* implemented tests for delete line

* moved deleteLine and selectedLineBlocks to delete-line.js
This commit is contained in:
Abhishek Maran 2024-02-07 17:33:59 +05:30 committed by GitHub
parent f9673b0954
commit 5eed314e32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 98 additions and 0 deletions

View File

@ -0,0 +1,46 @@
import { EditorSelection } from "@codemirror/state"
import { getActiveNoteBlock } from "./block"
function updateSel(sel, by) {
return EditorSelection.create(sel.ranges.map(by), sel.mainIndex);
}
function selectedLineBlocks(state) {
let blocks = [], upto = -1
for (let range of state.selection.ranges) {
let startLine = state.doc.lineAt(range.from), endLine = state.doc.lineAt(range.to)
if (!range.empty && range.to == endLine.from) endLine = state.doc.lineAt(range.to - 1)
if (upto >= startLine.number) {
let prev = blocks[blocks.length - 1]
prev.to = endLine.to
prev.ranges.push(range)
} else {
blocks.push({ from: startLine.from, to: endLine.to, ranges: [range] })
}
upto = endLine.number + 1
}
return blocks
}
export const deleteLine = (view) => {
if (view.state.readOnly)
return false
const { state } = view
const block = getActiveNoteBlock(view.state)
const selectedLines = selectedLineBlocks(state)
const changes = state.changes(selectedLines.map(({ from, to }) => {
if(from !== block.content.from || to !== block.content.to) {
if (from > 0) from--
else if (to < state.doc.length) to++
}
return { from, to }
}))
const selection = updateSel(state.selection, range => view.moveVertically(range, true)).map(changes)
view.dispatch({ changes, selection, scrollIntoView: true, userEvent: "delete.line" })
return true;
}

View File

@ -19,6 +19,7 @@ import {
import { pasteCommand, copyCommand, cutCommand } from "./copy-paste.js"
import { formatBlockContent } from "./block/format-code.js"
import { deleteLine } from "./block/delete-line.js"
export function keymapFromSpec(specs) {
@ -59,6 +60,7 @@ export function heynoteKeymap(editor) {
["Alt-Shift-f", formatBlockContent],
["Mod-Alt-ArrowDown", newCursorBelow],
["Mod-Alt-ArrowUp", newCursorAbove],
["Mod-Shift-k", deleteLine],
{key:"Mod-ArrowUp", run:gotoPreviousBlock, shift:selectPreviousBlock},
{key:"Mod-ArrowDown", run:gotoNextBlock, shift:selectNextBlock},
{key:"Ctrl-ArrowUp", run:gotoPreviousParagraph, shift:selectPreviousParagraph},

50
tests/delete-line.spec.js Normal file
View File

@ -0,0 +1,50 @@
import { expect, test } from "@playwright/test";
import { HeynotePage } from "./test-utils.js";
let heynotePage
test.beforeEach(async ({ page }) => {
heynotePage = new HeynotePage(page)
await heynotePage.goto()
expect((await heynotePage.getBlocks()).length).toBe(1)
await heynotePage.setContent(`
text
Block A
text content 1
text content 2
text content 3
text content 4
text
Block B
text
Block C`)
// check that blocks are created
expect((await heynotePage.getBlocks()).length).toBe(3)
// check that visual block layers are created
await expect(page.locator("css=.heynote-blocks-layer > div")).toHaveCount(3)
});
test("delete line on single line in Block A", async ({ page }) => {
for (let i = 0; i < 7; i++) {
await page.locator("body").press("ArrowUp")
}
for (let i = 0; i < 4; i++) {
await page.locator("body").press(`${heynotePage.isMac ? "Meta" : "Control"}+Shift+k`)
}
expect(await heynotePage.getBlockContent(0)).toBe("\ntext content 4");
});
test("delete line on selection in Block B", async ({ page }) => {
for (let i = 0; i < 1; i++) {
await page.locator("body").press("ArrowUp")
}
await page.locator("body").press(`${heynotePage.isMac ? "Meta" : "Control"}+A`)
await page.locator("body").press(`${heynotePage.isMac ? "Meta" : "Control"}+Shift+k`)
expect(await heynotePage.getBlockContent(1)).toBe('');
});