diff --git a/app/src/protyle/util/selection.ts b/app/src/protyle/util/selection.ts index 6d4dd5631..7d7fb09f1 100644 --- a/app/src/protyle/util/selection.ts +++ b/app/src/protyle/util/selection.ts @@ -135,7 +135,7 @@ export const getRangeByPoint = (x: number, y: number) => { return range; }; -export const getEditorRange = (element: Element) => { +export const getEditorRange = (element: Element): Range => { let range: Range; if (getSelection().rangeCount > 0) { range = getSelection().getRangeAt(0); @@ -153,7 +153,10 @@ export const getEditorRange = (element: Element) => { } if (element.classList.contains("li") || element.classList.contains("list")) { - return getEditorRange(element.querySelector("[data-node-id]")); + const childElement = element.querySelector("[data-node-id]") + if (childElement) { + return getEditorRange(childElement); + } } // 代码块过长,在代码块的下一个块前删除,代码块会滚动到顶部,因粗需要 preventScroll @@ -171,9 +174,9 @@ export const getEditorRange = (element: Element) => { if (!targetElement) { const type = element.getAttribute("data-type"); if (type === "NodeThematicBreak") { - targetElement= element.firstElementChild; + targetElement = element.firstElementChild; } else if (type === "NodeBlockQueryEmbed") { - targetElement = element.lastElementChild.previousElementSibling?.firstChild; + targetElement = element.lastElementChild.previousElementSibling?.firstChild; } else if (["NodeMathBlock", "NodeHTMLBlock"].includes(type)) { targetElement = element.lastElementChild.previousElementSibling?.lastElementChild?.firstChild; } else if (type === "NodeVideo") { @@ -575,8 +578,8 @@ export const focusBlock = (element: Element, parentElement?: HTMLElement, toStar genRenderFrame(element); range.setStart(element.firstElementChild.lastElementChild.firstChild, 0); setRange = true; - } else if (type === "NodeHTMLBlock") { - range.selectNodeContents(element.lastElementChild.previousElementSibling.lastElementChild.firstChild, 0); + } else if (type === "NodeHTMLBlock") { + range.setStart(element.lastElementChild.previousElementSibling.lastElementChild.firstChild, 0); range.collapse(true); setRange = true; } else if (type === "NodeIFrame" || type === "NodeWidget") { diff --git a/app/src/protyle/wysiwyg/getBlock.ts b/app/src/protyle/wysiwyg/getBlock.ts index d2c4facd3..559792e46 100644 --- a/app/src/protyle/wysiwyg/getBlock.ts +++ b/app/src/protyle/wysiwyg/getBlock.ts @@ -164,11 +164,18 @@ export const hasNextSibling = (element: Node) => { }; export const isEndOfBlock = (range: Range) => { - if (range.endContainer.textContent.length !== range.endOffset) { - return false; + if (range.endContainer.nodeType === 3 && + range.endContainer.textContent.length !== range.endOffset && + range.endContainer.textContent !== Constants.ZWSP && + range.endContainer.textContent !== "\n") { + return false; } let nextSibling = range.endContainer; + if (range.endContainer.nodeType !== 3 && range.endContainer.childNodes[range.endOffset]) { + nextSibling = range.endContainer.childNodes[range.endOffset]; + } + while (nextSibling) { if (hasNextSibling(nextSibling)) { return false; diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 016f571c5..e08363cd4 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -853,11 +853,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } // 需使用 innerText,否则 br 无法传唤为 /n https://github.com/siyuan-note/siyuan/issues/12066 // 段末反向删除 https://github.com/siyuan-note/insider/issues/274 - if (position.end === editElement.innerText.length || - // 软换行后删除 https://github.com/siyuan-note/siyuan/issues/11118 - (position.end === editElement.innerText.length - 1 && editElement.innerText.endsWith("\n")) || - // 图片后无内容删除 https://github.com/siyuan-note/siyuan/issues/11868 - (position.end === editElement.innerText.length - 1 && editElement.innerText.endsWith(Constants.ZWSP))) { + if (isEndOfBlock(range)) { const nextElement = getNextBlock(getTopAloneElement(nodeElement)); if (nextElement) { const nextRange = focusBlock(nextElement); @@ -934,8 +930,8 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { event.preventDefault(); return; } - // 图片后为空格,在空格后删除 https://github.com/siyuan-note/siyuan/issues/13949 if (range.startOffset === 1 && range.startContainer.textContent.length === 1) { + // 图片后为空格,在空格后删除 https://github.com/siyuan-note/siyuan/issues/13949 const rangePreviousElement = hasPreviousSibling(range.startContainer) as HTMLElement; const rangeNextElement = hasNextSibling(range.startContainer) as HTMLElement; if (rangePreviousElement && rangePreviousElement.nodeType === 1 && rangePreviousElement.classList.contains("img") && @@ -949,6 +945,17 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { event.preventDefault(); return; } + // 图片前有一个字符,在字符后删除 + if (position.start === 1 && !rangePreviousElement && rangeNextElement && rangeNextElement.nodeType === 1 && rangeNextElement.classList.contains("img")) { + const wbrElement = document.createElement("wbr"); + range.insertNode(wbrElement); + const oldHTML = nodeElement.outerHTML; + wbrElement.previousSibling.textContent = Constants.ZWSP; + updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML); + focusByWbr(nodeElement, range); + event.preventDefault(); + return; + } } // 代码块中空行 ⌘+Del 异常 https://ld246.com/article/1663166544901 if (nodeElement.classList.contains("code-block") && isOnlyMeta(event) &&