This commit is contained in:
Vanessa 2022-06-14 19:23:45 +08:00
parent 3919eccb90
commit 8c5a32188d
4 changed files with 95 additions and 6 deletions

View file

@ -374,7 +374,7 @@ export const focusByWbr = (element: Element, range: Range) => {
} else if (wbrPreviousSibling.nodeType !== 3 && (wbrPreviousSibling as HTMLElement).classList.contains("img")) {
// <img><wbr>, 删除图片后的唯一的一个字符
range.setStartAfter(wbrPreviousSibling);
} else {
} else {
// <span class="hljs-function"><span class="hljs-keyword">fun</span></span>
range.setStartBefore(wbrElement);
}

View file

@ -8,7 +8,7 @@ import {
isNotEditBlock
} from "./getBlock";
import {transaction, updateTransaction} from "./transaction";
import {genListItemElement, listOutdent, updateListOrder} from "./list";
import {breakList, genListItemElement, listOutdent, updateListOrder} from "./list";
import {hasClosestByMatchTag} from "../util/hasClosest";
import {highlightRender} from "../markdown/highlightRender";
import {setPosition} from "../../util/setPosition";
@ -21,12 +21,17 @@ const listEnter = (protyle: IProtyle, blockElement: HTMLElement, range: Range) =
const editableElement = getContenteditableElement(blockElement);
if (// \n 是因为 https://github.com/siyuan-note/siyuan/issues/3846
["", "\n"].includes(editableElement.textContent) &&
listItemElement.nextElementSibling?.classList.contains("protyle-attr") &&
blockElement.previousElementSibling.classList.contains("protyle-action") &&
!blockElement.querySelector("img") // https://ld246.com/article/1651820644238
) {
listOutdent(protyle, [blockElement.parentElement], range);
return true;
if (listItemElement.nextElementSibling?.classList.contains("protyle-attr")) {
listOutdent(protyle, [blockElement.parentElement], range);
return true;
} else if (!listItemElement.parentElement.classList.contains("protyle-wysiwyg")) {
// 打断列表
breakList(protyle, blockElement, range);
return true;
}
}
const position = getSelectionOffset(editableElement, protyle.wysiwyg.element, range);

View file

@ -1,6 +1,8 @@
import {focusByWbr} from "../util/selection";
import {transaction, updateTransaction} from "./transaction";
import {genEmptyBlock} from "../../block/util";
import * as dayjs from "dayjs";
import {Constants} from "../../constants";
export const updateListOrder = (listElement: Element, sIndex?: number) => {
if (listElement.getAttribute("data-subtype") !== "o") {
@ -173,6 +175,88 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
focusByWbr(previousElement, range);
};
export const breakList = (protyle: IProtyle, blockElement: Element, range: Range) => {
const listItemElement = blockElement.parentElement
const listItemId = listItemElement.getAttribute("data-node-id")
const doOperations: IOperation[] = [];
const undoOperations: IOperation[] = [];
range.insertNode(document.createElement("wbr"))
const newListId = Lute.NewNodeID()
let newListHTML = ''
let hasFind = 0
Array.from(listItemElement.parentElement.children).forEach(item => {
if (!hasFind && item.isSameNode(listItemElement)) {
hasFind = 1
} else if (hasFind && !item.classList.contains("protyle-attr")) {
undoOperations.push({
id: item.getAttribute("data-node-id"),
action: "move",
previousID: listItemId,
})
doOperations.push({
id: item.getAttribute("data-node-id"),
action: "delete",
})
if (item.getAttribute("data-subtype") === "o") {
undoOperations.push({
id: item.getAttribute("data-node-id"),
action: "update",
data: item.outerHTML,
})
item.setAttribute("data-marker", hasFind + ".")
item.firstElementChild.innerHTML = hasFind + "."
}
newListHTML += item.outerHTML
item.remove();
hasFind++;
}
})
undoOperations.reverse();
newListHTML = `<div data-subtype="${listItemElement.getAttribute("data-subtype")}" data-node-id="${newListId}" data-type="NodeList" class="list" updated="${dayjs().format("YYYYMMDDHHmmss")}">${newListHTML}<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`
listItemElement.parentElement.insertAdjacentHTML("afterend", newListHTML);
doOperations.push({
id: newListId,
action: "insert",
previousID: listItemElement.parentElement.getAttribute("data-node-id"),
data: newListHTML
})
undoOperations.push({
id: newListId,
action: "delete"
})
Array.from(listItemElement.children).reverse().forEach((item) => {
if (!item.classList.contains("protyle-action") && !item.classList.contains("protyle-attr")) {
doOperations.push({
id: item.getAttribute("data-node-id"),
action: "move",
previousID: listItemElement.parentElement.getAttribute("data-node-id")
})
undoOperations.push({
id: item.getAttribute("data-node-id"),
action: "move",
parentID: listItemId
})
listItemElement.parentElement.after(item);
}
})
undoOperations.splice(0, 0, {
id: listItemId,
action: "insert",
data: listItemElement.outerHTML,
previousID: listItemElement.previousElementSibling.getAttribute("data-node-id"),
parentID: listItemElement.parentElement.getAttribute("data-node-id")
})
listItemElement.remove()
doOperations.push({
id: listItemId,
action: "delete",
})
transaction(protyle, doOperations, undoOperations);
focusByWbr(protyle.wysiwyg.element, range);
}
export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {
const liElement = liItemElements[0].parentElement;
const liId = liElement.getAttribute("data-node-id");

View file

@ -126,7 +126,7 @@ interface ISiyuan {
}
interface IOperation {
action: TOperation,
action: TOperation, // move delete 不需要传 data
id: string,
data?: string,
parentID?: string