From 86878ffcc49da0b62adfd814e4fb800a60fc26a2 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Wed, 2 Apr 2025 13:08:20 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/14496 --- app/src/block/util.ts | 10 ++++++++-- app/src/protyle/wysiwyg/remove.ts | 2 +- app/src/protyle/wysiwyg/transaction.ts | 10 +++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/block/util.ts b/app/src/block/util.ts index 174cde554..03becf26c 100644 --- a/app/src/block/util.ts +++ b/app/src/block/util.ts @@ -1,6 +1,6 @@ import {focusByWbr, getEditorRange} from "../protyle/util/selection"; import {hasClosestBlock} from "../protyle/util/hasClosest"; -import {getTopAloneElement} from "../protyle/wysiwyg/getBlock"; +import {getContenteditableElement, getTopAloneElement} from "../protyle/wysiwyg/getBlock"; import {genListItemElement, updateListOrder} from "../protyle/wysiwyg/list"; import {transaction, turnsIntoOneTransaction, updateTransaction} from "../protyle/wysiwyg/transaction"; import {scrollCenter} from "../util/highlightById"; @@ -11,7 +11,7 @@ import {fetchPost, fetchSyncPost} from "../util/fetch"; import {openFileById} from "../editor/util"; import {openMobileFileById} from "../mobile/editor"; -export const cancelSB = async (protyle: IProtyle, nodeElement: Element) => { +export const cancelSB = async (protyle: IProtyle, nodeElement: Element, range?: Range) => { const doOperations: IOperation[] = []; const undoOperations: IOperation[] = []; let previousId = nodeElement.previousElementSibling ? nodeElement.previousElementSibling.getAttribute("data-node-id") : undefined; @@ -45,12 +45,18 @@ export const cancelSB = async (protyle: IProtyle, nodeElement: Element) => { action: "delete", id, }); + if (range) { + getContenteditableElement(nodeElement).insertAdjacentHTML("afterbegin", "") + } nodeElement.lastElementChild.remove(); // 超级块中的 html 块需要反转义再赋值 https://github.com/siyuan-note/siyuan/issues/13155 nodeElement.querySelectorAll("protyle-html").forEach(item => { item.setAttribute("data-content", item.getAttribute("data-content").replace(/</g, "<").replace(/>/g, ">")); }); nodeElement.outerHTML = nodeElement.innerHTML; + if (range) { + focusByWbr(protyle.wysiwyg.element, range); + } return; } doOperations.push({ diff --git a/app/src/protyle/wysiwyg/remove.ts b/app/src/protyle/wysiwyg/remove.ts index 93825e050..fd020859a 100644 --- a/app/src/protyle/wysiwyg/remove.ts +++ b/app/src/protyle/wysiwyg/remove.ts @@ -181,7 +181,7 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang } if (deletes.length > 0) { if (topParentElement && topParentElement.getAttribute("data-type") === "NodeSuperBlock" && topParentElement.childElementCount === 2) { - const sbData = await cancelSB(protyle, topParentElement); + const sbData = await cancelSB(protyle, topParentElement, range); transaction(protyle, deletes.concat(sbData.doOperations), sbData.undoOperations.concat(inserts.reverse())); } else { transaction(protyle, deletes, inserts.reverse()); diff --git a/app/src/protyle/wysiwyg/transaction.ts b/app/src/protyle/wysiwyg/transaction.ts index 7d1fee9ee..5add861a4 100644 --- a/app/src/protyle/wysiwyg/transaction.ts +++ b/app/src/protyle/wysiwyg/transaction.ts @@ -746,11 +746,19 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo: } }); } else { + const parentElement = Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.parentID}"]`)); if (!protyle.options.backlinkData && operation.parentID === protyle.block.parentID) { protyle.wysiwyg.element.insertAdjacentHTML("afterbegin", operation.data); cursorElements.push(protyle.wysiwyg.element.firstElementChild); + } else if (parentElement.length === 0 && protyle.options.backlinkData && isUndo && getSelection().rangeCount > 0) { + // 反链面板删除超级块中的段落块后撤销 + const blockElement = hasClosestBlock(getSelection().getRangeAt(0).startContainer) + if (blockElement) { + blockElement.insertAdjacentHTML("beforebegin", operation.data); + cursorElements.push(blockElement.previousElementSibling); + } } else { - Array.from(protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.parentID}"]`)).forEach(item => { + parentElement.forEach(item => { if (!isInEmbedBlock(item)) { // 列表特殊处理 if (item.firstElementChild?.classList.contains("protyle-action")) {