mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-20 16:40:13 +01:00
Merge b2bbaef088 into db4fb41024
This commit is contained in:
commit
4f6055e264
3 changed files with 148 additions and 62 deletions
|
|
@ -104,12 +104,19 @@ export const hasClosestByClassName = (element: Node, className: string, top = fa
|
||||||
|
|
||||||
export const hasClosestBlock = (element: Node) => {
|
export const hasClosestBlock = (element: Node) => {
|
||||||
const nodeElement = hasClosestByAttribute(element, "data-node-id", null);
|
const nodeElement = hasClosestByAttribute(element, "data-node-id", null);
|
||||||
if (nodeElement && nodeElement.tagName !== "BUTTON" && nodeElement.getAttribute("data-type")?.startsWith("Node")) {
|
if (isBlockElement(nodeElement)) {
|
||||||
return nodeElement;
|
return nodeElement;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isBlockElement = (element: Element | false | undefined) => {
|
||||||
|
if (!element) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return element.hasAttribute("data-node-id") && element.tagName !== "BUTTON" && (element.getAttribute("data-type")?.startsWith("Node") ?? false);
|
||||||
|
};
|
||||||
|
|
||||||
export const isInEmbedBlock = (element: Element) => {
|
export const isInEmbedBlock = (element: Element) => {
|
||||||
const embedElement = hasTopClosestByAttribute(element, "data-type", "NodeBlockQueryEmbed");
|
const embedElement = hasTopClosestByAttribute(element, "data-type", "NodeBlockQueryEmbed");
|
||||||
if (embedElement) {
|
if (embedElement) {
|
||||||
|
|
|
||||||
|
|
@ -1070,31 +1070,40 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 软换行
|
// 软换行
|
||||||
if (matchHotKey("⇧↩", event) && selectText === "" && softEnter(range, nodeElement, protyle)) {
|
if (selectText === "" && matchHotKey("⇧↩", event) && softEnter(range, nodeElement, protyle)) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 代码块语言选择 https://github.com/siyuan-note/siyuan/issues/14126
|
// 代码块语言选择 https://github.com/siyuan-note/siyuan/issues/14126
|
||||||
if (matchHotKey("⌥↩", event) && selectText === "") {
|
// 列表插入末尾子项 https://github.com/siyuan-note/siyuan/issues/11164
|
||||||
|
if (selectText === "" && matchHotKey("⌥↩", event) && !isIncludesHotKey("⌥↩")) {
|
||||||
const selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
|
const selectElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"));
|
||||||
if (selectElements.length === 0) {
|
if (selectElements.length === 0) {
|
||||||
selectElements.push(nodeElement);
|
selectElements.push(nodeElement);
|
||||||
}
|
}
|
||||||
if (selectElements.length > 0 && !isIncludesHotKey("⌥↩")) {
|
|
||||||
const otherElement = selectElements.find(item => {
|
const codeBlockElements = selectElements.filter(item => {
|
||||||
return !item.classList.contains("code-block");
|
return item.classList.contains("code-block");
|
||||||
});
|
});
|
||||||
if (!otherElement) {
|
if (codeBlockElements.length > 0) {
|
||||||
const languageElements: HTMLElement[] = [];
|
const languageElements: HTMLElement[] = [];
|
||||||
selectElements.forEach(item => {
|
codeBlockElements.forEach(item => {
|
||||||
languageElements.push(item.querySelector(".protyle-action__language"));
|
languageElements.push(item.querySelector(".protyle-action__language"));
|
||||||
});
|
});
|
||||||
protyle.toolbar.showCodeLanguage(protyle, languageElements);
|
protyle.toolbar.showCodeLanguage(protyle, languageElements);
|
||||||
} else {
|
event.stopPropagation();
|
||||||
addSubList(protyle, nodeElement, range);
|
event.preventDefault();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const liBlockElement = hasClosestByClassName(nodeElement, "li");
|
||||||
|
if (liBlockElement) {
|
||||||
|
selectElements.forEach(item => {
|
||||||
|
item.classList.remove("protyle-wysiwyg--select");
|
||||||
|
});
|
||||||
|
addSubList(protyle, nodeElement, range);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,24 @@ import {genEmptyBlock} from "../../block/util";
|
||||||
import * as dayjs from "dayjs";
|
import * as dayjs from "dayjs";
|
||||||
import {Constants} from "../../constants";
|
import {Constants} from "../../constants";
|
||||||
import {moveToPrevious, removeBlock} from "./remove";
|
import {moveToPrevious, removeBlock} from "./remove";
|
||||||
import {hasClosestByClassName} from "../util/hasClosest";
|
import {hasClosestByClassName, isBlockElement} from "../util/hasClosest";
|
||||||
import {setFold} from "../../menus/protyle";
|
import {setFold} from "../../menus/protyle";
|
||||||
import {getParentBlock} from "./getBlock";
|
import {getParentBlock} from "./getBlock";
|
||||||
|
|
||||||
|
const getLastChildBlock = (element: Element): Element | null => {
|
||||||
|
if (!element || !element.lastElementChild) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let current = element.lastElementChild.previousElementSibling;
|
||||||
|
while (current) {
|
||||||
|
if (isBlockElement(current)) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
current = current.previousElementSibling;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export const updateListOrder = (listElement: Element, sIndex?: number) => {
|
export const updateListOrder = (listElement: Element, sIndex?: number) => {
|
||||||
if (listElement.getAttribute("data-subtype") !== "o") {
|
if (listElement.getAttribute("data-subtype") !== "o") {
|
||||||
return;
|
return;
|
||||||
|
|
@ -35,38 +49,86 @@ export const updateListOrder = (listElement: Element, sIndex?: number) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const genListItemElement = (listItemElement: Element, offset = 0, wbr = false) => {
|
export const genListItemElement = (listItemElement: Element, offset = 0, wbr = false, startIndex?: number) => {
|
||||||
const element = document.createElement("template");
|
const element = document.createElement("template");
|
||||||
const type = listItemElement.getAttribute("data-subtype");
|
const type = listItemElement.getAttribute("data-subtype") || "u";
|
||||||
if (type === "o") {
|
if (type === "o") {
|
||||||
const index = parseInt(listItemElement.getAttribute("data-marker")) + offset;
|
const index = startIndex !== undefined ? startIndex : parseInt(listItemElement.getAttribute("data-marker")) + offset + 1;
|
||||||
element.innerHTML = `<div data-marker="${index + 1}." data-subtype="${type}" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div contenteditable="false" class="protyle-action protyle-action--order" draggable="true">${index + 1}.</div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
element.innerHTML = `<div data-marker="${index}." data-subtype="o" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div contenteditable="false" class="protyle-action protyle-action--order" draggable="true">${index}.</div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
||||||
} else if (type === "t") {
|
} else if (type === "t") {
|
||||||
element.innerHTML = `<div data-marker="*" data-subtype="${type}" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
element.innerHTML = `<div data-marker="*" data-subtype="t" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div class="protyle-action protyle-action--task" draggable="true"><svg><use xlink:href="#iconUncheck"></use></svg></div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
||||||
} else {
|
} else {
|
||||||
element.innerHTML = `<div data-marker="*" data-subtype="${type}" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div class="protyle-action" draggable="true"><svg><use xlink:href="#iconDot"></use></svg></div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
element.innerHTML = `<div data-marker="*" data-subtype="u" data-node-id="${Lute.NewNodeID()}" data-type="NodeListItem" class="li"><div class="protyle-action" draggable="true"><svg><use xlink:href="#iconDot"></use></svg></div>${genEmptyBlock(false, wbr)}<div class="protyle-attr" contenteditable="false"></div></div>`;
|
||||||
}
|
}
|
||||||
return element.content.firstElementChild as HTMLElement;
|
return element.content.firstElementChild as HTMLElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range) => {
|
export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range) => {
|
||||||
const parentItemElement = hasClosestByClassName(nodeElement, "li");
|
const liElement = hasClosestByClassName(nodeElement, "li");
|
||||||
if (!parentItemElement) {
|
if (!liElement) {
|
||||||
|
// 上层必须有列表项块才插入子列表
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const lastSubItem = parentItemElement.querySelector(".list")?.lastElementChild.previousElementSibling;
|
if (nodeElement.classList.contains("list") || nodeElement.classList.contains("li")) {
|
||||||
if (!lastSubItem) {
|
// 不存在 nodeElement 为列表块或列表项块的情况,如果以后需要的话再实现
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let listElement: Element | null | false = null;
|
||||||
|
// 向上遍历到列表项块,得到列表项块的直接子块
|
||||||
|
let blockElement = nodeElement;
|
||||||
|
while (blockElement.parentElement !== liElement) {
|
||||||
|
blockElement = blockElement.parentElement;
|
||||||
|
}
|
||||||
|
// 考虑到列表项块内可能存在多个字列表块,在 nodeElement 的后面查找最近的同级列表块,如果不存在则在列表项块的最后一个子块后面插入新的列表块
|
||||||
|
let nextSibling = blockElement?.nextElementSibling;
|
||||||
|
while (nextSibling) {
|
||||||
|
if (nextSibling.classList.contains("list")) {
|
||||||
|
listElement = nextSibling;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nextSibling = nextSibling.nextElementSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无列表块:在列表项块的最后一个子块后面插入新的列表块
|
||||||
|
if (!listElement) {
|
||||||
|
const lastChildBlock = getLastChildBlock(liElement);
|
||||||
|
if (!lastChildBlock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const subType = liElement.getAttribute("data-subtype") || "u";
|
||||||
|
const id = Lute.NewNodeID();
|
||||||
|
const newListItemElement = genListItemElement(liElement, 0, true, 1);
|
||||||
|
const newListHTML = `<div data-subtype="${subType}" data-node-id="${id}" data-type="NodeList" class="list" updated="${dayjs().format("YYYYMMDDHHmmss")}">${newListItemElement.outerHTML}<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`;
|
||||||
|
lastChildBlock.insertAdjacentHTML("afterend", newListHTML);
|
||||||
|
transaction(protyle, [{
|
||||||
|
action: "insert",
|
||||||
|
id,
|
||||||
|
data: newListHTML,
|
||||||
|
previousID: lastChildBlock.getAttribute("data-node-id"),
|
||||||
|
}], [{
|
||||||
|
action: "delete",
|
||||||
|
id,
|
||||||
|
}]);
|
||||||
|
focusByWbr(lastChildBlock.nextElementSibling, range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有列表块:在列表块的最后一个列表项块后插入新的列表项块
|
||||||
|
const lastSubItem = getLastChildBlock(listElement);
|
||||||
|
if (lastSubItem) {
|
||||||
const newListElement = genListItemElement(lastSubItem, 0, true);
|
const newListElement = genListItemElement(lastSubItem, 0, true);
|
||||||
const id = newListElement.getAttribute("data-node-id");
|
const id = newListElement.getAttribute("data-node-id");
|
||||||
lastSubItem.after(newListElement);
|
lastSubItem.after(newListElement);
|
||||||
|
|
||||||
if (lastSubItem.parentElement.getAttribute("fold") === "1") {
|
if (lastSubItem.parentElement.getAttribute("fold") === "1") {
|
||||||
setFold(protyle, lastSubItem.parentElement, true);
|
setFold(protyle, lastSubItem.parentElement, true);
|
||||||
}
|
}
|
||||||
if (parentItemElement.getAttribute("fold") === "1") {
|
if (liElement.getAttribute("fold") === "1") {
|
||||||
setFold(protyle, parentItemElement, true);
|
setFold(protyle, liElement, true);
|
||||||
|
}
|
||||||
|
const parentListElement = hasClosestByClassName(liElement, "list");
|
||||||
|
if (parentListElement && parentListElement.getAttribute("fold") === "1") {
|
||||||
|
setFold(protyle, parentListElement, true);
|
||||||
}
|
}
|
||||||
transaction(protyle, [{
|
transaction(protyle, [{
|
||||||
action: "insert",
|
action: "insert",
|
||||||
|
|
@ -78,6 +140,8 @@ export const addSubList = (protyle: IProtyle, nodeElement: Element, range: Range
|
||||||
id,
|
id,
|
||||||
}]);
|
}]);
|
||||||
focusByWbr(newListElement, range);
|
focusByWbr(newListElement, range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const listIndent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {
|
export const listIndent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {
|
||||||
|
|
@ -99,15 +163,17 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
range.collapse(false);
|
range.collapse(false);
|
||||||
range.insertNode(document.createElement("wbr"));
|
range.insertNode(document.createElement("wbr"));
|
||||||
const html = previousElement.parentElement.outerHTML;
|
const html = previousElement.parentElement.outerHTML;
|
||||||
if (previousElement.lastElementChild.previousElementSibling.getAttribute("data-type") === "NodeList") {
|
const previousLastBlock = getLastChildBlock(previousElement);
|
||||||
|
if (previousLastBlock && previousLastBlock.getAttribute("data-type") === "NodeList") {
|
||||||
// 上一个列表的最后一项为子列表
|
// 上一个列表的最后一项为子列表
|
||||||
const previousLastListHTML = previousElement.lastElementChild.previousElementSibling.outerHTML;
|
const previousLastListHTML = previousLastBlock.outerHTML;
|
||||||
|
|
||||||
const doOperations: IOperation[] = [];
|
const doOperations: IOperation[] = [];
|
||||||
const undoOperations: IOperation[] = [];
|
const undoOperations: IOperation[] = [];
|
||||||
|
|
||||||
const subtype = previousElement.lastElementChild.previousElementSibling.getAttribute("data-subtype");
|
const subtype = previousLastBlock.getAttribute("data-subtype");
|
||||||
let previousID = previousElement.lastElementChild.previousElementSibling.lastElementChild.previousElementSibling.getAttribute("data-node-id");
|
const previousLastListLastBlock = getLastChildBlock(previousLastBlock);
|
||||||
|
let previousID = previousLastListLastBlock ? previousLastListLastBlock.getAttribute("data-node-id") : undefined;
|
||||||
liItemElements.forEach((item, index) => {
|
liItemElements.forEach((item, index) => {
|
||||||
doOperations.push({
|
doOperations.push({
|
||||||
action: "move",
|
action: "move",
|
||||||
|
|
@ -125,23 +191,23 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
if (subtype === "o") {
|
if (subtype === "o") {
|
||||||
actionElement.classList.add("protyle-action--order");
|
actionElement.classList.add("protyle-action--order");
|
||||||
actionElement.classList.remove("protyle-action--task");
|
actionElement.classList.remove("protyle-action--task");
|
||||||
previousElement.lastElementChild.previousElementSibling.lastElementChild.before(item);
|
previousLastBlock.lastElementChild.before(item);
|
||||||
} else if (subtype === "t") {
|
} else if (subtype === "t") {
|
||||||
item.setAttribute("data-marker", "*");
|
item.setAttribute("data-marker", "*");
|
||||||
actionElement.innerHTML = `<svg><use xlink:href="#icon${item.classList.contains("protyle-task--done") ? "Check" : "Uncheck"}"></use></svg>`;
|
actionElement.innerHTML = `<svg><use xlink:href="#icon${item.classList.contains("protyle-task--done") ? "Check" : "Uncheck"}"></use></svg>`;
|
||||||
actionElement.classList.remove("protyle-action--order");
|
actionElement.classList.remove("protyle-action--order");
|
||||||
actionElement.classList.add("protyle-action--task");
|
actionElement.classList.add("protyle-action--task");
|
||||||
previousElement.lastElementChild.previousElementSibling.lastElementChild.before(item);
|
previousLastBlock.lastElementChild.before(item);
|
||||||
} else {
|
} else {
|
||||||
item.setAttribute("data-marker", "*");
|
item.setAttribute("data-marker", "*");
|
||||||
actionElement.innerHTML = '<svg><use xlink:href="#iconDot"></use></svg>';
|
actionElement.innerHTML = '<svg><use xlink:href="#iconDot"></use></svg>';
|
||||||
actionElement.classList.remove("protyle-action--order", "protyle-action--task");
|
actionElement.classList.remove("protyle-action--order", "protyle-action--task");
|
||||||
previousElement.lastElementChild.previousElementSibling.lastElementChild.before(item);
|
previousLastBlock.lastElementChild.before(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (subtype === "o") {
|
if (subtype === "o") {
|
||||||
updateListOrder(previousElement.lastElementChild.previousElementSibling);
|
updateListOrder(previousLastBlock);
|
||||||
updateListOrder(previousElement.parentElement);
|
updateListOrder(previousElement.parentElement);
|
||||||
} else if (previousElement.getAttribute("data-subtype") === "o") {
|
} else if (previousElement.getAttribute("data-subtype") === "o") {
|
||||||
updateListOrder(previousElement.parentElement);
|
updateListOrder(previousElement.parentElement);
|
||||||
|
|
@ -150,13 +216,13 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
if (previousElement.parentElement.classList.contains("protyle-wysiwyg")) {
|
if (previousElement.parentElement.classList.contains("protyle-wysiwyg")) {
|
||||||
doOperations.push({
|
doOperations.push({
|
||||||
action: "update",
|
action: "update",
|
||||||
data: previousElement.lastElementChild.previousElementSibling.outerHTML,
|
data: previousLastBlock.outerHTML,
|
||||||
id: previousElement.lastElementChild.previousElementSibling.getAttribute("data-node-id")
|
id: previousLastBlock.getAttribute("data-node-id")
|
||||||
});
|
});
|
||||||
undoOperations.push({
|
undoOperations.push({
|
||||||
action: "update",
|
action: "update",
|
||||||
data: previousLastListHTML,
|
data: previousLastListHTML,
|
||||||
id: previousElement.lastElementChild.previousElementSibling.getAttribute("data-node-id")
|
id: previousLastBlock.getAttribute("data-node-id")
|
||||||
});
|
});
|
||||||
transaction(protyle, doOperations, undoOperations);
|
transaction(protyle, doOperations, undoOperations);
|
||||||
}
|
}
|
||||||
|
|
@ -170,11 +236,12 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
newListElement.setAttribute("class", "list");
|
newListElement.setAttribute("class", "list");
|
||||||
newListElement.setAttribute("data-subtype", subType);
|
newListElement.setAttribute("data-subtype", subType);
|
||||||
newListElement.innerHTML = '<div class="protyle-attr" contenteditable="false"></div>';
|
newListElement.innerHTML = '<div class="protyle-attr" contenteditable="false"></div>';
|
||||||
|
const previousLastBlockForNewList = getLastChildBlock(previousElement);
|
||||||
const doOperations: IOperation[] = [{
|
const doOperations: IOperation[] = [{
|
||||||
action: "insert",
|
action: "insert",
|
||||||
data: newListElement.outerHTML,
|
data: newListElement.outerHTML,
|
||||||
id: newListId,
|
id: newListId,
|
||||||
previousID: previousElement.lastElementChild.previousElementSibling.getAttribute("data-node-id")
|
previousID: previousLastBlockForNewList ? previousLastBlockForNewList.getAttribute("data-node-id") : undefined
|
||||||
}];
|
}];
|
||||||
previousElement.lastElementChild.before(newListElement);
|
previousElement.lastElementChild.before(newListElement);
|
||||||
const undoOperations: IOperation[] = [];
|
const undoOperations: IOperation[] = [];
|
||||||
|
|
@ -374,7 +441,7 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
let topPreviousID = liId;
|
let topPreviousID = liId;
|
||||||
let previousElement: Element = liElement;
|
let previousElement: Element = liElement;
|
||||||
let nextElement = liItemElements[liItemElements.length - 1].nextElementSibling;
|
let nextElement = liItemElements[liItemElements.length - 1].nextElementSibling;
|
||||||
let lastBlockElement = liItemElements[liItemElements.length - 1].lastElementChild.previousElementSibling;
|
let lastBlockElement = getLastChildBlock(liItemElements[liItemElements.length - 1]);
|
||||||
liItemElements.forEach(item => {
|
liItemElements.forEach(item => {
|
||||||
Array.from(item.children).forEach((blockElement, index) => {
|
Array.from(item.children).forEach((blockElement, index) => {
|
||||||
const id = blockElement.getAttribute("data-node-id");
|
const id = blockElement.getAttribute("data-node-id");
|
||||||
|
|
@ -402,7 +469,7 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
if (!window.siyuan.config.editor.listLogicalOutdent && !nextElement.classList.contains("protyle-attr")) {
|
if (!window.siyuan.config.editor.listLogicalOutdent && !nextElement.classList.contains("protyle-attr")) {
|
||||||
// 传统缩进
|
// 传统缩进
|
||||||
let newId;
|
let newId;
|
||||||
if (lastBlockElement.getAttribute("data-subtype") !== nextElement.getAttribute("data-subtype")) {
|
if (!lastBlockElement || lastBlockElement.getAttribute("data-subtype") !== nextElement.getAttribute("data-subtype")) {
|
||||||
newId = Lute.NewNodeID();
|
newId = Lute.NewNodeID();
|
||||||
lastBlockElement = document.createElement("div");
|
lastBlockElement = document.createElement("div");
|
||||||
lastBlockElement.classList.add("list");
|
lastBlockElement.classList.add("list");
|
||||||
|
|
@ -421,10 +488,11 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
}
|
}
|
||||||
let topOldPreviousID;
|
let topOldPreviousID;
|
||||||
while (nextElement && !nextElement.classList.contains("protyle-attr")) {
|
while (nextElement && !nextElement.classList.contains("protyle-attr")) {
|
||||||
|
const lastBlockLastBlock = lastBlockElement ? getLastChildBlock(lastBlockElement) : null;
|
||||||
topDoOperations.push({
|
topDoOperations.push({
|
||||||
action: "move",
|
action: "move",
|
||||||
id: nextElement.getAttribute("data-node-id"),
|
id: nextElement.getAttribute("data-node-id"),
|
||||||
previousID: topOldPreviousID || lastBlockElement.lastElementChild.previousElementSibling?.getAttribute("data-node-id"),
|
previousID: topOldPreviousID || (lastBlockLastBlock ? lastBlockLastBlock.getAttribute("data-node-id") : undefined),
|
||||||
parentID: lastBlockElement.getAttribute("data-node-id")
|
parentID: lastBlockElement.getAttribute("data-node-id")
|
||||||
});
|
});
|
||||||
topUndoOperations.push({
|
topUndoOperations.push({
|
||||||
|
|
@ -546,7 +614,7 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
}
|
}
|
||||||
const html = parentLiItemElement.parentElement.outerHTML;
|
const html = parentLiItemElement.parentElement.outerHTML;
|
||||||
let nextElement = liItemElements[liItemElements.length - 1].nextElementSibling;
|
let nextElement = liItemElements[liItemElements.length - 1].nextElementSibling;
|
||||||
let lastBlockElement = liItemElements[liItemElements.length - 1].lastElementChild.previousElementSibling;
|
let lastBlockElement = getLastChildBlock(liItemElements[liItemElements.length - 1]);
|
||||||
liItemElements.reverse().forEach(item => {
|
liItemElements.reverse().forEach(item => {
|
||||||
const itemId = item.getAttribute("data-node-id");
|
const itemId = item.getAttribute("data-node-id");
|
||||||
doOperations.push({
|
doOperations.push({
|
||||||
|
|
@ -612,7 +680,7 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
if (!window.siyuan.config.editor.listLogicalOutdent && !nextElement.classList.contains("protyle-attr")) {
|
if (!window.siyuan.config.editor.listLogicalOutdent && !nextElement.classList.contains("protyle-attr")) {
|
||||||
// 传统缩进
|
// 传统缩进
|
||||||
let newId;
|
let newId;
|
||||||
if (!lastBlockElement.classList.contains("list")) {
|
if (!lastBlockElement || !lastBlockElement.classList.contains("list")) {
|
||||||
newId = Lute.NewNodeID();
|
newId = Lute.NewNodeID();
|
||||||
lastBlockElement = document.createElement("div");
|
lastBlockElement = document.createElement("div");
|
||||||
lastBlockElement.classList.add("list");
|
lastBlockElement.classList.add("list");
|
||||||
|
|
@ -621,11 +689,12 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
lastBlockElement.setAttribute("data-type", "NodeList");
|
lastBlockElement.setAttribute("data-type", "NodeList");
|
||||||
lastBlockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
lastBlockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||||
lastBlockElement.innerHTML = `<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div>`;
|
lastBlockElement.innerHTML = `<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div>`;
|
||||||
|
const firstItemLastBlock = getLastChildBlock(liItemElements[0]);
|
||||||
doOperations.push({
|
doOperations.push({
|
||||||
action: "insert",
|
action: "insert",
|
||||||
id: newId,
|
id: newId,
|
||||||
data: lastBlockElement.outerHTML,
|
data: lastBlockElement.outerHTML,
|
||||||
previousID: liItemElements[0].lastElementChild.previousElementSibling.getAttribute("data-node-id"),
|
previousID: firstItemLastBlock ? firstItemLastBlock.getAttribute("data-node-id") : undefined,
|
||||||
});
|
});
|
||||||
liItemElements[0].lastElementChild.before(lastBlockElement);
|
liItemElements[0].lastElementChild.before(lastBlockElement);
|
||||||
}
|
}
|
||||||
|
|
@ -647,10 +716,11 @@ export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
data: nextElement.outerHTML
|
data: nextElement.outerHTML
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const lastBlockLastBlock = getLastChildBlock(lastBlockElement);
|
||||||
doOperations.push({
|
doOperations.push({
|
||||||
action: "move",
|
action: "move",
|
||||||
id: nextId,
|
id: nextId,
|
||||||
previousID: subPreviousID || lastBlockElement.lastElementChild.previousElementSibling?.getAttribute("data-node-id"),
|
previousID: subPreviousID || (lastBlockLastBlock ? lastBlockLastBlock.getAttribute("data-node-id") : undefined),
|
||||||
parentID: lastBlockElement.getAttribute("data-node-id")
|
parentID: lastBlockElement.getAttribute("data-node-id")
|
||||||
});
|
});
|
||||||
undoOperations.push({
|
undoOperations.push({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue