2024-05-01 12:06:38 +08:00
|
|
|
|
import {focusBlock, focusByRange, focusByWbr, getSelectionOffset, setLastNodeRange} from "../util/selection";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {
|
|
|
|
|
|
getContenteditableElement,
|
|
|
|
|
|
getLastBlock,
|
|
|
|
|
|
getNextBlock,
|
|
|
|
|
|
getPreviousBlock,
|
|
|
|
|
|
getTopAloneElement,
|
2024-05-01 12:06:38 +08:00
|
|
|
|
getTopEmptyElement,
|
|
|
|
|
|
hasNextSibling,
|
|
|
|
|
|
hasPreviousSibling
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} from "./getBlock";
|
2025-01-09 18:07:31 +08:00
|
|
|
|
import {transaction, turnsIntoOneTransaction, turnsIntoTransaction, updateTransaction} from "./transaction";
|
2022-06-15 23:05:14 +08:00
|
|
|
|
import {cancelSB, genEmptyElement} from "../../block/util";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {listOutdent, updateListOrder} from "./list";
|
2022-06-03 21:01:27 +08:00
|
|
|
|
import {setFold, zoomOut} from "../../menus/protyle";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {preventScroll} from "../scroll/preventScroll";
|
|
|
|
|
|
import {hideElements} from "../ui/hideElements";
|
2022-06-03 21:01:27 +08:00
|
|
|
|
import {Constants} from "../../constants";
|
2023-03-20 20:59:39 +08:00
|
|
|
|
import {scrollCenter} from "../../util/highlightById";
|
2023-09-28 11:57:45 +08:00
|
|
|
|
import {isMobile} from "../../util/functions";
|
2025-03-28 12:35:54 +08:00
|
|
|
|
import {mathRender} from "../render/mathRender";
|
2025-04-03 23:44:34 +08:00
|
|
|
|
import {hasClosestByClassName} from "../util/hasClosest";
|
|
|
|
|
|
import {getInstanceById} from "../../layout/util";
|
|
|
|
|
|
import {Tab} from "../../layout/Tab";
|
|
|
|
|
|
import {Backlink} from "../../layout/dock/Backlink";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2025-04-01 17:05:15 +08:00
|
|
|
|
export const removeBlock = async (protyle: IProtyle, blockElement: Element, range: Range, type: "Delete" | "Backspace" | "remove") => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 删除后,防止滚动条滚动后调用 get 请求,因为返回的请求已查找不到内容块了
|
|
|
|
|
|
preventScroll(protyle);
|
|
|
|
|
|
const selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
|
|
|
|
|
|
if (selectElements?.length > 0) {
|
|
|
|
|
|
const deletes: IOperation[] = [];
|
|
|
|
|
|
const inserts: IOperation[] = [];
|
2024-02-26 11:34:19 +08:00
|
|
|
|
let sideElement;
|
|
|
|
|
|
let sideIsNext = false;
|
|
|
|
|
|
if (type === "Backspace") {
|
|
|
|
|
|
sideElement = selectElements[0].previousElementSibling;
|
|
|
|
|
|
if (!sideElement) {
|
|
|
|
|
|
sideIsNext = true;
|
2024-02-27 08:31:12 +08:00
|
|
|
|
sideElement = selectElements[selectElements.length - 1].nextElementSibling;
|
2024-02-26 11:34:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
sideElement = selectElements[selectElements.length - 1].nextElementSibling;
|
|
|
|
|
|
sideIsNext = true;
|
|
|
|
|
|
if (!sideElement) {
|
|
|
|
|
|
sideIsNext = false;
|
|
|
|
|
|
sideElement = selectElements[0].previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let listElement: Element;
|
2022-06-16 12:11:21 +08:00
|
|
|
|
let topParentElement: Element;
|
2022-10-22 11:31:41 +08:00
|
|
|
|
hideElements(["select"], protyle);
|
2024-05-12 12:36:30 +08:00
|
|
|
|
let foldPreviousId: string;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
selectElements.find((item: HTMLElement) => {
|
|
|
|
|
|
const topElement = getTopAloneElement(item);
|
2022-06-16 12:11:21 +08:00
|
|
|
|
topParentElement = topElement.parentElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const id = topElement.getAttribute("data-node-id");
|
|
|
|
|
|
deletes.push({
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id,
|
|
|
|
|
|
});
|
2024-02-26 11:34:19 +08:00
|
|
|
|
if (type === "Backspace") {
|
|
|
|
|
|
sideElement = getPreviousBlock(topElement);
|
|
|
|
|
|
if (!sideElement) {
|
|
|
|
|
|
sideIsNext = true;
|
|
|
|
|
|
sideElement = getNextBlock(topElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2024-02-27 08:31:12 +08:00
|
|
|
|
sideElement = getNextBlock(topElement);
|
2024-02-26 11:34:19 +08:00
|
|
|
|
sideIsNext = true;
|
|
|
|
|
|
if (!sideElement) {
|
|
|
|
|
|
sideIsNext = false;
|
|
|
|
|
|
sideElement = getPreviousBlock(topElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-03 23:44:34 +08:00
|
|
|
|
if (!sideElement && !protyle.options.backlinkData) {
|
2024-02-26 11:34:19 +08:00
|
|
|
|
sideElement = topElement.parentElement || protyle.wysiwyg.element.firstElementChild;
|
|
|
|
|
|
sideIsNext = false;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (topElement.getAttribute("data-type") === "NodeHeading" && topElement.getAttribute("fold") === "1") {
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/2188
|
|
|
|
|
|
setFold(protyle, topElement, undefined, true);
|
2024-05-12 12:36:30 +08:00
|
|
|
|
let previousID = topElement.previousElementSibling ? topElement.previousElementSibling.getAttribute("data-node-id") : "";
|
2024-05-11 10:50:22 +08:00
|
|
|
|
if (typeof foldPreviousId !== "undefined") {
|
|
|
|
|
|
previousID = foldPreviousId;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
inserts.push({
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: topElement.outerHTML,
|
|
|
|
|
|
id,
|
2024-05-11 10:50:22 +08:00
|
|
|
|
previousID: previousID,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
parentID: topElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
});
|
2024-05-11 10:50:22 +08:00
|
|
|
|
// 折叠块和非折叠块同时删除时撤销异常 https://github.com/siyuan-note/siyuan/issues/11312
|
|
|
|
|
|
let foldPreviousElement = getPreviousBlock(topElement);
|
|
|
|
|
|
while (foldPreviousElement && foldPreviousElement.childElementCount === 3) {
|
|
|
|
|
|
foldPreviousElement = getPreviousBlock(foldPreviousElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (foldPreviousElement) {
|
|
|
|
|
|
foldPreviousId = foldPreviousElement.getAttribute("data-node-id");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
foldPreviousId = "";
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/4422
|
|
|
|
|
|
topElement.firstElementChild.removeAttribute("contenteditable");
|
|
|
|
|
|
// 在折叠标题后输入文字,然后全选删除再撤销会重建索引。因此不能删除折叠标题后新输入的输入折叠标题下的内容
|
|
|
|
|
|
const nextElement = topElement.nextElementSibling;
|
|
|
|
|
|
if (nextElement) {
|
|
|
|
|
|
const nextType = nextElement.getAttribute("data-type");
|
|
|
|
|
|
if (nextType !== "NodeHeading" ||
|
|
|
|
|
|
(nextType === "NodeHeading" && nextElement.getAttribute("data-subtype") > topElement.getAttribute("data-subtype"))) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2022-12-09 17:39:00 +08:00
|
|
|
|
let data = topElement.outerHTML; // 不能 spin ,否则 li 会变为 list
|
|
|
|
|
|
if (topElement.classList.contains("render-node") || topElement.querySelector("div.render-node")) {
|
|
|
|
|
|
data = protyle.lute.SpinBlockDOM(topElement.outerHTML); // 防止图表撤销问题
|
|
|
|
|
|
}
|
2024-05-11 10:50:22 +08:00
|
|
|
|
let previousID = topElement.previousElementSibling ? topElement.previousElementSibling.getAttribute("data-node-id") : "";
|
|
|
|
|
|
if (typeof foldPreviousId !== "undefined") {
|
|
|
|
|
|
previousID = foldPreviousId;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
inserts.push({
|
|
|
|
|
|
action: "insert",
|
2022-12-09 17:39:00 +08:00
|
|
|
|
data,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
id,
|
2024-05-11 10:50:22 +08:00
|
|
|
|
previousID,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
parentID: topElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
});
|
|
|
|
|
|
if (topElement.getAttribute("data-subtype") === "o" && topElement.classList.contains("li")) {
|
|
|
|
|
|
listElement = topElement.parentElement;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
listElement = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
topElement.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (sideElement) {
|
2022-06-03 21:01:27 +08:00
|
|
|
|
if (protyle.block.showAll && sideElement.classList.contains("protyle-wysiwyg") && protyle.wysiwyg.element.childElementCount === 0) {
|
|
|
|
|
|
setTimeout(() => {
|
2023-09-08 23:06:36 +08:00
|
|
|
|
zoomOut({protyle, id: protyle.block.parent2ID, focusId: protyle.block.parent2ID});
|
2022-06-03 21:01:27 +08:00
|
|
|
|
}, Constants.TIMEOUT_INPUT * 2 + 100);
|
|
|
|
|
|
} else {
|
2022-06-15 23:05:14 +08:00
|
|
|
|
if ((sideElement.classList.contains("protyle-wysiwyg") && protyle.wysiwyg.element.childElementCount === 0)) {
|
2022-06-23 19:01:05 +08:00
|
|
|
|
const newID = Lute.NewNodeID();
|
|
|
|
|
|
const emptyElement = genEmptyElement(false, true, newID);
|
2022-06-03 21:01:27 +08:00
|
|
|
|
sideElement.insertAdjacentElement("afterbegin", emptyElement);
|
|
|
|
|
|
deletes.push({
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: emptyElement.outerHTML,
|
2022-06-23 19:01:05 +08:00
|
|
|
|
id: newID,
|
2022-06-03 21:01:27 +08:00
|
|
|
|
parentID: sideElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
});
|
|
|
|
|
|
inserts.push({
|
|
|
|
|
|
action: "delete",
|
2022-06-23 19:01:05 +08:00
|
|
|
|
id: newID,
|
2022-06-03 21:01:27 +08:00
|
|
|
|
});
|
|
|
|
|
|
sideElement = undefined;
|
|
|
|
|
|
focusByWbr(emptyElement, range);
|
|
|
|
|
|
}
|
2023-10-05 20:30:20 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/5485
|
2024-02-26 11:34:19 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/10389
|
2024-04-05 22:21:29 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/10899
|
|
|
|
|
|
if (type !== "Backspace" && sideIsNext) {
|
2024-02-26 11:34:19 +08:00
|
|
|
|
focusBlock(sideElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
focusBlock(sideElement, undefined, false);
|
|
|
|
|
|
}
|
2023-03-20 20:59:39 +08:00
|
|
|
|
scrollCenter(protyle, sideElement);
|
2022-06-03 21:01:27 +08:00
|
|
|
|
if (listElement) {
|
|
|
|
|
|
inserts.push({
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
data: listElement.outerHTML
|
|
|
|
|
|
});
|
|
|
|
|
|
updateListOrder(listElement, 1);
|
|
|
|
|
|
deletes.push({
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
data: listElement.outerHTML
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-05-28 12:17:18 +08:00
|
|
|
|
if (deletes.length > 0) {
|
2022-06-15 23:05:14 +08:00
|
|
|
|
if (topParentElement && topParentElement.getAttribute("data-type") === "NodeSuperBlock" && topParentElement.childElementCount === 2) {
|
2025-04-02 13:08:20 +08:00
|
|
|
|
const sbData = await cancelSB(protyle, topParentElement, range);
|
2022-06-15 23:05:14 +08:00
|
|
|
|
transaction(protyle, deletes.concat(sbData.doOperations), sbData.undoOperations.concat(inserts.reverse()));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
transaction(protyle, deletes, inserts.reverse());
|
|
|
|
|
|
}
|
2022-05-28 12:17:18 +08:00
|
|
|
|
}
|
2022-06-15 23:05:14 +08:00
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
hideElements(["util"], protyle);
|
2025-04-08 10:58:10 +08:00
|
|
|
|
/// #if !MOBILE
|
2025-04-03 23:44:34 +08:00
|
|
|
|
if (!sideElement) {
|
2025-04-08 09:44:32 +08:00
|
|
|
|
const backlinkElement = hasClosestByClassName(protyle.element, "sy__backlink", true);
|
2025-04-03 23:44:34 +08:00
|
|
|
|
if (backlinkElement) {
|
2025-04-07 20:40:51 +08:00
|
|
|
|
const backLinkTab = getInstanceById(backlinkElement.getAttribute("data-id"), window.siyuan.layout.layout);
|
2025-04-03 23:44:34 +08:00
|
|
|
|
if (backLinkTab instanceof Tab && backLinkTab.model instanceof Backlink) {
|
2025-04-08 09:44:32 +08:00
|
|
|
|
const editors = backLinkTab.model.editors;
|
2025-04-03 23:44:34 +08:00
|
|
|
|
editors.find((item, index) => {
|
|
|
|
|
|
if (item.protyle.element.isSameNode(protyle.element)) {
|
|
|
|
|
|
item.destroy();
|
|
|
|
|
|
editors.splice(index, 1);
|
|
|
|
|
|
item.protyle.element.previousElementSibling.remove();
|
|
|
|
|
|
item.protyle.element.remove();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-08 10:58:10 +08:00
|
|
|
|
/// #endif
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-05-04 16:43:35 +08:00
|
|
|
|
const blockType = blockElement.getAttribute("data-type");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 空代码块直接删除
|
2024-05-02 13:36:47 +08:00
|
|
|
|
if (blockType === "NodeCodeBlock" && getContenteditableElement(blockElement).textContent.trim() === "") {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
blockElement.classList.add("protyle-wysiwyg--select");
|
2024-02-26 11:34:19 +08:00
|
|
|
|
removeBlock(protyle, blockElement, range, type);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-06-07 00:17:54 +08:00
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (!blockElement.previousElementSibling && blockElement.parentElement.getAttribute("data-type") === "NodeBlockquote") {
|
2025-03-29 09:35:19 +08:00
|
|
|
|
if (type !== "Delete") {
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const blockParentElement = blockElement.parentElement;
|
|
|
|
|
|
blockParentElement.insertAdjacentElement("beforebegin", blockElement);
|
|
|
|
|
|
if (blockParentElement.childElementCount === 1) {
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id: blockElement.getAttribute("data-node-id"),
|
|
|
|
|
|
previousID: blockElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockParentElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
}, {
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: blockParentElement.getAttribute("data-node-id")
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
id: blockParentElement.getAttribute("data-node-id"),
|
|
|
|
|
|
data: blockParentElement.outerHTML,
|
|
|
|
|
|
previousID: blockElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockParentElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
}, {
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id: blockElement.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockParentElement.getAttribute("data-node-id")
|
|
|
|
|
|
}]);
|
|
|
|
|
|
blockParentElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id: blockElement.getAttribute("data-node-id"),
|
|
|
|
|
|
previousID: blockElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockParentElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id: blockElement.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockParentElement.getAttribute("data-node-id")
|
|
|
|
|
|
}]);
|
|
|
|
|
|
}
|
2025-03-29 09:35:19 +08:00
|
|
|
|
if (type === "Delete") {
|
|
|
|
|
|
moveToPrevious(blockElement, range, true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
focusByWbr(blockElement, range);
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-04 16:54:59 +08:00
|
|
|
|
if (blockElement.parentElement.classList.contains("li") && blockElement.getAttribute("data-type") !== "NodeHeading" &&
|
|
|
|
|
|
blockElement.previousElementSibling.classList.contains("protyle-action")) {
|
2024-02-26 11:34:19 +08:00
|
|
|
|
removeLi(protyle, blockElement, range, type === "Delete");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-06-30 11:11:23 +08:00
|
|
|
|
const previousElement = getPreviousBlock(blockElement) as HTMLElement;
|
2024-06-07 00:17:54 +08:00
|
|
|
|
// 设置 bq 和代码块光标
|
|
|
|
|
|
// 需放在列表处理后 https://github.com/siyuan-note/siyuan/issues/11606
|
|
|
|
|
|
if (["NodeCodeBlock", "NodeTable", "NodeAttributeView"].includes(blockType)) {
|
2024-06-25 16:23:10 +08:00
|
|
|
|
if (previousElement) {
|
|
|
|
|
|
if (previousElement.classList.contains("p") && getContenteditableElement(previousElement).textContent === "") {
|
2024-06-25 16:26:14 +08:00
|
|
|
|
// 空块向后删除时移除改块 https://github.com/siyuan-note/siyuan/issues/11732
|
2024-07-06 09:57:00 +08:00
|
|
|
|
const ppElement = getPreviousBlock(previousElement);
|
2024-06-25 16:23:10 +08:00
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: previousElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: previousElement.outerHTML,
|
|
|
|
|
|
id: previousElement.getAttribute("data-node-id"),
|
2024-06-30 11:11:23 +08:00
|
|
|
|
parentID: previousElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID,
|
2024-07-25 20:22:57 +08:00
|
|
|
|
previousID: (ppElement && (!previousElement.previousElementSibling || !previousElement.previousElementSibling.classList.contains("protyle-action"))) ? ppElement.getAttribute("data-node-id") : undefined
|
2024-06-25 16:23:10 +08:00
|
|
|
|
}]);
|
|
|
|
|
|
previousElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
focusBlock(previousElement, undefined, false);
|
|
|
|
|
|
}
|
2024-06-07 00:17:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-05-02 13:36:47 +08:00
|
|
|
|
if (blockType === "NodeHeading") {
|
2024-03-13 00:19:06 +08:00
|
|
|
|
turnsIntoTransaction({
|
|
|
|
|
|
protyle: protyle,
|
|
|
|
|
|
selectsElement: [blockElement],
|
|
|
|
|
|
type: "Blocks2Ps",
|
|
|
|
|
|
range: moveToPrevious(blockElement, range, type === "Delete")
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-09-30 00:12:35 +08:00
|
|
|
|
if (blockElement.previousElementSibling && blockElement.previousElementSibling.classList.contains("protyle-breadcrumb__bar")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (!previousElement) {
|
|
|
|
|
|
if (protyle.wysiwyg.element.childElementCount > 1 && getContenteditableElement(blockElement).textContent === "") {
|
|
|
|
|
|
focusBlock(protyle.wysiwyg.element.firstElementChild.nextElementSibling);
|
|
|
|
|
|
// 列表项中包含超级块时需要到顶层
|
|
|
|
|
|
const topElement = getTopAloneElement(blockElement);
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: topElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: topElement.outerHTML,
|
|
|
|
|
|
id: topElement.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: protyle.block.parentID
|
|
|
|
|
|
}]);
|
|
|
|
|
|
topElement.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-16 12:11:21 +08:00
|
|
|
|
const parentElement = blockElement.parentElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const editableElement = getContenteditableElement(blockElement);
|
2023-09-15 20:24:58 +08:00
|
|
|
|
const previousLastElement = getLastBlock(previousElement) as HTMLElement;
|
2023-09-28 11:57:45 +08:00
|
|
|
|
if (range.toString() === "" && isMobile() && previousLastElement && previousLastElement.classList.contains("hr") && getSelectionOffset(editableElement).start === 0) {
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: previousLastElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: previousLastElement.outerHTML,
|
|
|
|
|
|
id: previousLastElement.getAttribute("data-node-id"),
|
|
|
|
|
|
previousID: previousLastElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: previousLastElement.parentElement.getAttribute("data-node-id")
|
|
|
|
|
|
}]);
|
|
|
|
|
|
previousLastElement.remove();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-19 13:39:31 +08:00
|
|
|
|
const isSelectNode = previousLastElement && (
|
|
|
|
|
|
previousLastElement.classList.contains("table") ||
|
|
|
|
|
|
previousLastElement.classList.contains("render-node") ||
|
|
|
|
|
|
previousLastElement.classList.contains("iframe") ||
|
|
|
|
|
|
previousLastElement.classList.contains("hr") ||
|
|
|
|
|
|
previousLastElement.classList.contains("av") ||
|
|
|
|
|
|
previousLastElement.classList.contains("code-block"));
|
2022-06-28 10:19:15 +08:00
|
|
|
|
const previousId = previousLastElement.getAttribute("data-node-id");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (isSelectNode) {
|
|
|
|
|
|
if (previousLastElement.classList.contains("code-block")) {
|
|
|
|
|
|
if (editableElement.textContent.trim() === "") {
|
|
|
|
|
|
const id = blockElement.getAttribute("data-node-id");
|
2022-06-15 23:05:14 +08:00
|
|
|
|
const doOperations: IOperation[] = [{
|
2022-05-26 15:18:53 +08:00
|
|
|
|
action: "delete",
|
|
|
|
|
|
id,
|
2022-06-16 12:11:21 +08:00
|
|
|
|
}];
|
2022-06-15 23:05:14 +08:00
|
|
|
|
const undoOperations: IOperation[] = [{
|
2022-05-26 15:18:53 +08:00
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: blockElement.outerHTML,
|
|
|
|
|
|
id: id,
|
2022-06-15 23:05:14 +08:00
|
|
|
|
previousID: blockElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: blockElement.parentElement.getAttribute("data-node-id")
|
2022-06-16 12:11:21 +08:00
|
|
|
|
}];
|
2022-05-26 15:18:53 +08:00
|
|
|
|
blockElement.remove();
|
2022-06-15 23:05:14 +08:00
|
|
|
|
// 取消超级块
|
|
|
|
|
|
if (parentElement.getAttribute("data-type") === "NodeSuperBlock" && parentElement.childElementCount === 2) {
|
2025-04-01 17:05:15 +08:00
|
|
|
|
const sbData = await cancelSB(protyle, parentElement);
|
2022-06-15 23:05:14 +08:00
|
|
|
|
transaction(protyle, doOperations.concat(sbData.doOperations), sbData.undoOperations.concat(undoOperations));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
|
|
|
|
|
}
|
2023-09-15 20:24:58 +08:00
|
|
|
|
focusBlock(protyle.wysiwyg.element.querySelector(`[data-node-id="${previousId}"]`), undefined, false);
|
2022-06-15 23:05:14 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
focusBlock(previousLastElement, undefined, false);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-01-18 19:46:21 +08:00
|
|
|
|
if (editableElement.textContent !== "" ||
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/10207
|
|
|
|
|
|
blockElement.classList.contains("av")) {
|
2022-08-19 14:39:19 +08:00
|
|
|
|
focusBlock(previousLastElement, undefined, false);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const removeElement = getTopEmptyElement(blockElement);
|
|
|
|
|
|
const removeId = removeElement.getAttribute("data-node-id");
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const undoOperations: IOperation[] = [{
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: previousLastElement.outerHTML,
|
2022-06-28 10:19:15 +08:00
|
|
|
|
id: previousId,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}, {
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
data: removeElement.outerHTML,
|
|
|
|
|
|
id: removeId,
|
|
|
|
|
|
// 不能使用 previousLastElement,否则在超级块下的元素前删除撤销错误
|
2022-06-15 23:05:14 +08:00
|
|
|
|
previousID: blockElement.previousElementSibling?.getAttribute("data-node-id"),
|
|
|
|
|
|
parentID: parentElement.getAttribute("data-node-id")
|
|
|
|
|
|
}];
|
|
|
|
|
|
const doOperations: IOperation[] = [{
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: removeId,
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}];
|
|
|
|
|
|
|
|
|
|
|
|
if (isSelectNode) {
|
|
|
|
|
|
// 需先移除 removeElement,否则 side 会选中 removeElement
|
|
|
|
|
|
removeElement.remove();
|
2022-08-19 14:39:19 +08:00
|
|
|
|
focusBlock(previousLastElement, undefined, false);
|
2024-11-26 10:49:21 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/13254
|
|
|
|
|
|
undoOperations.splice(0, 1);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
const previousLastEditElement = getContenteditableElement(previousLastElement);
|
2024-10-21 23:18:45 +08:00
|
|
|
|
if (editableElement && (editableElement.textContent !== "" || editableElement.querySelector(".emoji"))) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// 非空块
|
|
|
|
|
|
range.setEndAfter(editableElement.lastChild);
|
2023-01-13 16:16:11 +08:00
|
|
|
|
// 数学公式回车后再删除 https://github.com/siyuan-note/siyuan/issues/3850
|
2023-01-13 15:25:58 +08:00
|
|
|
|
if ((previousLastEditElement?.lastElementChild?.getAttribute("data-type") || "").indexOf("inline-math") > -1) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const lastSibling = hasNextSibling(previousLastEditElement?.lastElementChild);
|
|
|
|
|
|
if (lastSibling && lastSibling.textContent === "\n") {
|
|
|
|
|
|
lastSibling.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-12 13:09:56 +08:00
|
|
|
|
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/14807
|
|
|
|
|
|
if (previousLastEditElement) {
|
|
|
|
|
|
let previousLastChild = previousLastEditElement.lastChild;
|
2025-05-12 22:07:43 +08:00
|
|
|
|
if (previousLastChild && previousLastChild.nodeType === 3) {
|
2025-05-12 13:09:56 +08:00
|
|
|
|
if (!previousLastChild.textContent) {
|
|
|
|
|
|
previousLastChild = hasPreviousSibling(previousLastChild) as ChildNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (previousLastChild && previousLastChild.nodeType === 3 && previousLastChild.textContent.endsWith("\n")) {
|
|
|
|
|
|
previousLastChild.textContent = previousLastChild.textContent.slice(0, -1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const scroll = protyle.contentElement.scrollTop;
|
|
|
|
|
|
const leftNodes = range.extractContents();
|
|
|
|
|
|
range.selectNodeContents(previousLastEditElement);
|
|
|
|
|
|
range.collapse(false);
|
|
|
|
|
|
range.insertNode(leftNodes);
|
2025-03-21 14:09:08 +08:00
|
|
|
|
// 图片前删除到上一个文字块时,图片前有 zwsp
|
|
|
|
|
|
previousLastElement.outerHTML = protyle.lute.SpinBlockDOM(previousLastElement.outerHTML);
|
2025-03-28 12:35:54 +08:00
|
|
|
|
mathRender(getPreviousBlock(removeElement) as HTMLElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
removeElement.remove();
|
|
|
|
|
|
// extractContents 内容过多时需要进行滚动条重置,否则位置会错位
|
|
|
|
|
|
protyle.contentElement.scrollTop = scroll;
|
|
|
|
|
|
protyle.scroll.lastScrollTop = scroll - 1;
|
2022-06-15 23:05:14 +08:00
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: previousLastElement.outerHTML,
|
2022-06-28 10:19:15 +08:00
|
|
|
|
id: previousId,
|
2022-06-16 12:11:21 +08:00
|
|
|
|
});
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2022-06-15 23:05:14 +08:00
|
|
|
|
if (parentElement.getAttribute("data-type") === "NodeSuperBlock" && parentElement.childElementCount === 2) {
|
2025-04-01 17:05:15 +08:00
|
|
|
|
const sbData = await cancelSB(protyle, parentElement);
|
2022-06-15 23:05:14 +08:00
|
|
|
|
transaction(protyle, doOperations.concat(sbData.doOperations), sbData.undoOperations.concat(undoOperations));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
|
|
|
|
|
}
|
|
|
|
|
|
focusByWbr(protyle.wysiwyg.element, range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
2023-12-13 11:48:28 +08:00
|
|
|
|
|
|
|
|
|
|
export const moveToPrevious = (blockElement: Element, range: Range, isDelete: boolean) => {
|
|
|
|
|
|
if (isDelete) {
|
2023-12-13 11:49:17 +08:00
|
|
|
|
const previousBlockElement = getPreviousBlock(blockElement);
|
2023-12-13 11:48:28 +08:00
|
|
|
|
if (previousBlockElement) {
|
2023-12-13 11:49:17 +08:00
|
|
|
|
const previousEditElement = getContenteditableElement(getLastBlock(previousBlockElement));
|
2023-12-13 11:48:28 +08:00
|
|
|
|
if (previousEditElement) {
|
2024-03-13 00:19:06 +08:00
|
|
|
|
return setLastNodeRange(previousEditElement, range, false);
|
2023-12-13 11:48:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-12-13 11:49:17 +08:00
|
|
|
|
};
|
2024-02-26 16:22:36 +08:00
|
|
|
|
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/10393
|
2024-03-13 00:19:06 +08:00
|
|
|
|
export const removeImage = (imgSelectElement: Element, nodeElement: HTMLElement, range: Range, protyle: IProtyle) => {
|
2024-02-26 16:22:36 +08:00
|
|
|
|
const oldHTML = nodeElement.outerHTML;
|
|
|
|
|
|
const imgPreviousSibling = hasPreviousSibling(imgSelectElement);
|
|
|
|
|
|
if (imgPreviousSibling && imgPreviousSibling.textContent.endsWith(Constants.ZWSP)) {
|
|
|
|
|
|
imgPreviousSibling.textContent = imgPreviousSibling.textContent.substring(0, imgPreviousSibling.textContent.length - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
const imgNextSibling = hasNextSibling(imgSelectElement);
|
|
|
|
|
|
if (imgNextSibling && imgNextSibling.textContent.startsWith(Constants.ZWSP)) {
|
|
|
|
|
|
imgNextSibling.textContent = imgNextSibling.textContent.replace(Constants.ZWSP, "");
|
|
|
|
|
|
}
|
|
|
|
|
|
imgSelectElement.insertAdjacentHTML("afterend", "<wbr>");
|
|
|
|
|
|
imgSelectElement.remove();
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
|
|
|
|
|
focusByWbr(nodeElement, range);
|
2024-05-01 12:06:38 +08:00
|
|
|
|
// 不太清楚为什么删除图片后无法上下键定位,但重绘后就好了 https://ld246.com/article/1714314625702
|
2024-05-01 12:01:44 +08:00
|
|
|
|
const editElement = getContenteditableElement(nodeElement);
|
|
|
|
|
|
if (editElement.innerHTML.trim() === "") {
|
|
|
|
|
|
editElement.innerHTML = "";
|
|
|
|
|
|
}
|
2024-02-27 08:31:12 +08:00
|
|
|
|
};
|
2024-03-17 23:13:45 +08:00
|
|
|
|
|
|
|
|
|
|
const removeLi = (protyle: IProtyle, blockElement: Element, range: Range, isDelete = false) => {
|
|
|
|
|
|
if (!blockElement.parentElement.previousElementSibling && blockElement.parentElement.nextElementSibling && blockElement.parentElement.nextElementSibling.classList.contains("protyle-attr")) {
|
|
|
|
|
|
listOutdent(protyle, [blockElement.parentElement], range, isDelete, blockElement);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 第一个子列表合并到上一个块的末尾
|
|
|
|
|
|
if (!blockElement.parentElement.previousElementSibling && blockElement.parentElement.parentElement.parentElement.classList.contains("list")) {
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const listElement = blockElement.parentElement.parentElement;
|
|
|
|
|
|
const listHTML = listElement.outerHTML;
|
|
|
|
|
|
const previousLastElement = blockElement.parentElement.parentElement.previousElementSibling.lastElementChild;
|
|
|
|
|
|
const previousHTML = previousLastElement.parentElement.outerHTML;
|
|
|
|
|
|
blockElement.parentElement.firstElementChild.remove();
|
|
|
|
|
|
blockElement.parentElement.lastElementChild.remove();
|
|
|
|
|
|
previousLastElement.insertAdjacentHTML("beforebegin", blockElement.parentElement.innerHTML);
|
|
|
|
|
|
blockElement.parentElement.remove();
|
|
|
|
|
|
if (listElement.getAttribute("data-subtype") === "o") {
|
|
|
|
|
|
updateListOrder(listElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
data: listElement.outerHTML
|
|
|
|
|
|
}, {
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: previousLastElement.parentElement.outerHTML,
|
|
|
|
|
|
id: previousLastElement.parentElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: previousHTML,
|
|
|
|
|
|
id: previousLastElement.parentElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}, {
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: listHTML,
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
}]);
|
|
|
|
|
|
focusByWbr(previousLastElement.parentElement, range);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 顶级列表首行删除变为块
|
|
|
|
|
|
if (!blockElement.parentElement.previousElementSibling) {
|
|
|
|
|
|
if (blockElement.parentElement.parentElement.classList.contains("protyle-wysiwyg")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
moveToPrevious(blockElement, range, isDelete);
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const listElement = blockElement.parentElement.parentElement;
|
|
|
|
|
|
const listHTML = listElement.outerHTML;
|
|
|
|
|
|
blockElement.parentElement.firstElementChild.remove();
|
|
|
|
|
|
blockElement.parentElement.lastElementChild.remove();
|
|
|
|
|
|
const tempElement = document.createElement("div");
|
|
|
|
|
|
tempElement.innerHTML = blockElement.parentElement.innerHTML;
|
|
|
|
|
|
const doOperations: IOperation[] = [];
|
|
|
|
|
|
const undoOperations: IOperation[] = [];
|
|
|
|
|
|
Array.from(tempElement.children).forEach((item, index) => {
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
id: item.getAttribute("data-node-id"),
|
|
|
|
|
|
data: item.outerHTML,
|
|
|
|
|
|
previousID: index === 0 ? listElement.previousElementSibling?.getAttribute("data-node-id") : doOperations[index - 1].id,
|
|
|
|
|
|
parentID: listElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
|
|
|
|
|
});
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: item.getAttribute("data-node-id"),
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
listElement.insertAdjacentHTML("beforebegin", blockElement.parentElement.innerHTML);
|
|
|
|
|
|
blockElement.parentElement.remove();
|
|
|
|
|
|
if (listElement.getAttribute("data-subtype") === "o") {
|
|
|
|
|
|
updateListOrder(listElement, parseInt(listElement.firstElementChild.getAttribute("data-marker")) - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
doOperations.splice(0, 0, {
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
data: listElement.outerHTML
|
|
|
|
|
|
});
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "update",
|
|
|
|
|
|
data: listHTML,
|
|
|
|
|
|
id: listElement.getAttribute("data-node-id"),
|
|
|
|
|
|
});
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
2025-01-09 18:07:31 +08:00
|
|
|
|
if (listElement.parentElement.classList.contains("sb") &&
|
|
|
|
|
|
listElement.parentElement.getAttribute("data-sb-layout") === "col") {
|
2025-01-16 10:00:30 +08:00
|
|
|
|
const selectsElement: Element[] = [];
|
2025-01-09 18:07:31 +08:00
|
|
|
|
let previousElement: Element = listElement;
|
|
|
|
|
|
while (previousElement) {
|
|
|
|
|
|
selectsElement.push(previousElement);
|
|
|
|
|
|
if (undoOperations[0].id === previousElement.getAttribute("data-node-id")) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
previousElement = previousElement.previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
turnsIntoOneTransaction({
|
|
|
|
|
|
protyle,
|
|
|
|
|
|
selectsElement: selectsElement.reverse(),
|
|
|
|
|
|
type: "BlocksMergeSuperBlock",
|
|
|
|
|
|
level: "row"
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-03-17 23:13:45 +08:00
|
|
|
|
focusByWbr(protyle.wysiwyg.element, range);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 列表项合并到前一个列表项的最后一个块末尾
|
|
|
|
|
|
const listItemElement = blockElement.parentElement;
|
|
|
|
|
|
if (listItemElement.previousElementSibling && listItemElement.previousElementSibling.classList.contains("protyle-breadcrumb__bar")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const listItemId = listItemElement.getAttribute("data-node-id");
|
|
|
|
|
|
const listElement = listItemElement.parentElement;
|
|
|
|
|
|
moveToPrevious(blockElement, range, isDelete);
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = listElement.outerHTML;
|
|
|
|
|
|
const doOperations: IOperation[] = [];
|
|
|
|
|
|
const undoOperations: IOperation[] = [{
|
|
|
|
|
|
action: "insert",
|
|
|
|
|
|
id: listItemId,
|
|
|
|
|
|
data: "",
|
|
|
|
|
|
previousID: listItemElement.previousElementSibling.getAttribute("data-node-id")
|
|
|
|
|
|
}];
|
|
|
|
|
|
const previousLastElement = listItemElement.previousElementSibling.lastElementChild;
|
|
|
|
|
|
if (listItemElement.previousElementSibling.getAttribute("fold") === "1") {
|
|
|
|
|
|
if (getContenteditableElement(blockElement).textContent.trim() === "" &&
|
|
|
|
|
|
blockElement.nextElementSibling.classList.contains("protyle-attr")) {
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: listItemId
|
|
|
|
|
|
});
|
|
|
|
|
|
undoOperations[0].data = listItemElement.outerHTML;
|
|
|
|
|
|
setLastNodeRange(getContenteditableElement(listItemElement.previousElementSibling), range);
|
|
|
|
|
|
range.collapse(true);
|
|
|
|
|
|
listItemElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setLastNodeRange(getContenteditableElement(listItemElement.previousElementSibling), range);
|
|
|
|
|
|
range.collapse(true);
|
|
|
|
|
|
focusByRange(range);
|
|
|
|
|
|
blockElement.querySelector("wbr")?.remove();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
let previousID = previousLastElement.previousElementSibling.getAttribute("data-node-id");
|
|
|
|
|
|
Array.from(blockElement.parentElement.children).forEach((item, index) => {
|
|
|
|
|
|
if (item.classList.contains("protyle-action") || item.classList.contains("protyle-attr")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const id = item.getAttribute("data-node-id");
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id,
|
|
|
|
|
|
previousID,
|
|
|
|
|
|
});
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "move",
|
|
|
|
|
|
id,
|
|
|
|
|
|
previousID: index === 1 ? undefined : previousID,
|
|
|
|
|
|
parentID: listItemId
|
|
|
|
|
|
});
|
|
|
|
|
|
previousID = id;
|
|
|
|
|
|
previousLastElement.before(item);
|
|
|
|
|
|
});
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "delete",
|
|
|
|
|
|
id: listItemId
|
|
|
|
|
|
});
|
|
|
|
|
|
undoOperations[0].data = listItemElement.outerHTML;
|
|
|
|
|
|
listItemElement.remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (listElement.classList.contains("protyle-wysiwyg")) {
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (listElement.getAttribute("data-subtype") === "o") {
|
|
|
|
|
|
updateListOrder(listElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateTransaction(protyle, listElement.getAttribute("data-node-id"), listElement.outerHTML, html);
|
|
|
|
|
|
}
|
|
|
|
|
|
focusByWbr(previousLastElement.parentElement, range);
|
|
|
|
|
|
};
|