mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 09:00:12 +01:00
This commit is contained in:
parent
3919eccb90
commit
8c5a32188d
4 changed files with 95 additions and 6 deletions
|
|
@ -8,7 +8,7 @@ import {
|
||||||
isNotEditBlock
|
isNotEditBlock
|
||||||
} from "./getBlock";
|
} from "./getBlock";
|
||||||
import {transaction, updateTransaction} from "./transaction";
|
import {transaction, updateTransaction} from "./transaction";
|
||||||
import {genListItemElement, listOutdent, updateListOrder} from "./list";
|
import {breakList, genListItemElement, listOutdent, updateListOrder} from "./list";
|
||||||
import {hasClosestByMatchTag} from "../util/hasClosest";
|
import {hasClosestByMatchTag} from "../util/hasClosest";
|
||||||
import {highlightRender} from "../markdown/highlightRender";
|
import {highlightRender} from "../markdown/highlightRender";
|
||||||
import {setPosition} from "../../util/setPosition";
|
import {setPosition} from "../../util/setPosition";
|
||||||
|
|
@ -21,12 +21,17 @@ const listEnter = (protyle: IProtyle, blockElement: HTMLElement, range: Range) =
|
||||||
const editableElement = getContenteditableElement(blockElement);
|
const editableElement = getContenteditableElement(blockElement);
|
||||||
if (// \n 是因为 https://github.com/siyuan-note/siyuan/issues/3846
|
if (// \n 是因为 https://github.com/siyuan-note/siyuan/issues/3846
|
||||||
["", "\n"].includes(editableElement.textContent) &&
|
["", "\n"].includes(editableElement.textContent) &&
|
||||||
listItemElement.nextElementSibling?.classList.contains("protyle-attr") &&
|
|
||||||
blockElement.previousElementSibling.classList.contains("protyle-action") &&
|
blockElement.previousElementSibling.classList.contains("protyle-action") &&
|
||||||
!blockElement.querySelector("img") // https://ld246.com/article/1651820644238
|
!blockElement.querySelector("img") // https://ld246.com/article/1651820644238
|
||||||
) {
|
) {
|
||||||
|
if (listItemElement.nextElementSibling?.classList.contains("protyle-attr")) {
|
||||||
listOutdent(protyle, [blockElement.parentElement], range);
|
listOutdent(protyle, [blockElement.parentElement], range);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (!listItemElement.parentElement.classList.contains("protyle-wysiwyg")) {
|
||||||
|
// 打断列表
|
||||||
|
breakList(protyle, blockElement, range);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const position = getSelectionOffset(editableElement, protyle.wysiwyg.element, range);
|
const position = getSelectionOffset(editableElement, protyle.wysiwyg.element, range);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import {focusByWbr} from "../util/selection";
|
import {focusByWbr} from "../util/selection";
|
||||||
import {transaction, updateTransaction} from "./transaction";
|
import {transaction, updateTransaction} from "./transaction";
|
||||||
import {genEmptyBlock} from "../../block/util";
|
import {genEmptyBlock} from "../../block/util";
|
||||||
|
import * as dayjs from "dayjs";
|
||||||
|
import {Constants} from "../../constants";
|
||||||
|
|
||||||
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") {
|
||||||
|
|
@ -173,6 +175,88 @@ export const listIndent = (protyle: IProtyle, liItemElements: Element[], range:
|
||||||
focusByWbr(previousElement, 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) => {
|
export const listOutdent = (protyle: IProtyle, liItemElements: Element[], range: Range) => {
|
||||||
const liElement = liItemElements[0].parentElement;
|
const liElement = liItemElements[0].parentElement;
|
||||||
const liId = liElement.getAttribute("data-node-id");
|
const liId = liElement.getAttribute("data-node-id");
|
||||||
|
|
|
||||||
2
app/src/types/index.d.ts
vendored
2
app/src/types/index.d.ts
vendored
|
|
@ -126,7 +126,7 @@ interface ISiyuan {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOperation {
|
interface IOperation {
|
||||||
action: TOperation,
|
action: TOperation, // move, delete 不需要传 data
|
||||||
id: string,
|
id: string,
|
||||||
data?: string,
|
data?: string,
|
||||||
parentID?: string
|
parentID?: string
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue