mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-02-17 12:38:07 +01:00
98 lines
4.3 KiB
TypeScript
98 lines
4.3 KiB
TypeScript
|
|
import {focusByWbr, getEditorRange} from "../protyle/util/selection";
|
||
|
|
import {hasClosestBlock} from "../protyle/util/hasClosest";
|
||
|
|
import {getTopAloneElement} from "../protyle/wysiwyg/getBlock";
|
||
|
|
import {genListItemElement, updateListOrder} from "../protyle/wysiwyg/list";
|
||
|
|
import {transaction, updateTransaction} from "../protyle/wysiwyg/transaction";
|
||
|
|
import {scrollCenter} from "../util/highlightById";
|
||
|
|
import {Constants} from "../constants";
|
||
|
|
|
||
|
|
export const genSBElement = (layout: string, id?: string, attrHTML?: string) => {
|
||
|
|
const sbElement = document.createElement("div");
|
||
|
|
sbElement.setAttribute("data-node-id", id || Lute.NewNodeID());
|
||
|
|
sbElement.setAttribute("data-type", "NodeSuperBlock");
|
||
|
|
sbElement.setAttribute("class", "sb");
|
||
|
|
sbElement.setAttribute("data-sb-layout", layout);
|
||
|
|
sbElement.innerHTML = attrHTML || `<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div>`;
|
||
|
|
return sbElement;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const insertEmptyBlock = (protyle: IProtyle, position: InsertPosition, id?: string) => {
|
||
|
|
const range = getEditorRange(protyle.wysiwyg.element);
|
||
|
|
let blockElement: Element;
|
||
|
|
if (id) {
|
||
|
|
blockElement = protyle.wysiwyg.element.querySelector(`[data-node-id="${id}"]`);
|
||
|
|
} else {
|
||
|
|
const selectElements = protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select");
|
||
|
|
if (selectElements.length > 0) {
|
||
|
|
if (position === "beforebegin") {
|
||
|
|
blockElement = selectElements[0];
|
||
|
|
} else {
|
||
|
|
blockElement = selectElements[selectElements.length - 1];
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
blockElement = hasClosestBlock(range.startContainer) as HTMLElement;
|
||
|
|
blockElement = getTopAloneElement(blockElement);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!blockElement) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
let previousID;
|
||
|
|
if (position === "beforebegin") {
|
||
|
|
if (blockElement.previousElementSibling) {
|
||
|
|
previousID = blockElement.previousElementSibling.getAttribute("data-node-id");
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
previousID = blockElement.getAttribute("data-node-id");
|
||
|
|
}
|
||
|
|
let newElement = genEmptyElement(false, true);
|
||
|
|
let orderIndex = 1;
|
||
|
|
if (blockElement.getAttribute("data-type") === "NodeListItem") {
|
||
|
|
newElement = genListItemElement(blockElement, 0, true) as HTMLDivElement;
|
||
|
|
orderIndex = parseInt(blockElement.parentElement.firstElementChild.getAttribute("data-marker"));
|
||
|
|
}
|
||
|
|
const parentOldHTML = blockElement.parentElement.outerHTML;
|
||
|
|
const newId = newElement.getAttribute("data-node-id");
|
||
|
|
blockElement.insertAdjacentElement(position, newElement);
|
||
|
|
if (blockElement.getAttribute("data-type") === "NodeListItem" && blockElement.getAttribute("data-subtype") === "o") {
|
||
|
|
updateListOrder(newElement.parentElement, orderIndex);
|
||
|
|
updateTransaction(protyle, newElement.parentElement.getAttribute("data-node-id"), newElement.parentElement.outerHTML, parentOldHTML);
|
||
|
|
} else {
|
||
|
|
transaction(protyle, [{
|
||
|
|
action: "insert",
|
||
|
|
data: newElement.outerHTML,
|
||
|
|
id: newId,
|
||
|
|
previousID,
|
||
|
|
parentID: blockElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID
|
||
|
|
}], [{
|
||
|
|
action: "delete",
|
||
|
|
id: newId,
|
||
|
|
}]);
|
||
|
|
}
|
||
|
|
focusByWbr(protyle.wysiwyg.element, range);
|
||
|
|
scrollCenter(protyle);
|
||
|
|
};
|
||
|
|
|
||
|
|
export const genEmptyBlock = (zwsp = true, wbr = true, string?: string) => {
|
||
|
|
let html = "";
|
||
|
|
if (zwsp) {
|
||
|
|
html = Constants.ZWSP;
|
||
|
|
}
|
||
|
|
if (wbr) {
|
||
|
|
html += "<wbr>";
|
||
|
|
}
|
||
|
|
if (string) {
|
||
|
|
html += string;
|
||
|
|
}
|
||
|
|
return `<div data-node-id="${Lute.NewNodeID()}" data-type="NodeParagraph" class="p"><div contenteditable="true" spellcheck="false">${html}</div><div contenteditable="false" class="protyle-attr">${Constants.ZWSP}</div></div>`;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const genEmptyElement = (zwsp = true, wbr = true, id?: string) => {
|
||
|
|
const element = document.createElement("div");
|
||
|
|
element.setAttribute("data-node-id", id || Lute.NewNodeID());
|
||
|
|
element.setAttribute("data-type", "NodeParagraph");
|
||
|
|
element.classList.add("p");
|
||
|
|
element.innerHTML = `<div contenteditable="true" spellcheck="false">${zwsp ? Constants.ZWSP : ""}${wbr ? "<wbr>" : ""}</div><div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div>`;
|
||
|
|
return element;
|
||
|
|
};
|