This commit is contained in:
Vanessa 2022-09-15 22:48:03 +08:00
parent a3548499be
commit 0285730c59
7 changed files with 123 additions and 45 deletions

View file

@ -213,7 +213,7 @@
}
}
span[data-type="inline-math"] {
span[data-type~="inline-math"] {
user-select: text;
display: inline;
// https://github.com/siyuan-note/siyuan/issues/3081 test $\begin{bmatrix} a & b \\c & d \\ e & f\end{bmatrix}$ test

View file

@ -0,0 +1,75 @@
import {ToolbarItem} from "./ToolbarItem";
import * as dayjs from "dayjs";
import {updateTransaction} from "../wysiwyg/transaction";
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
import {focusByRange, focusByWbr} from "../util/selection";
import {mathRender} from "../markdown/mathRender";
export class InlineMath extends ToolbarItem {
public element: HTMLElement;
constructor(protyle: IProtyle, menuItem: IMenuItem) {
super(protyle, menuItem);
this.element.addEventListener("click", async (event: MouseEvent & { changedTouches: MouseEvent[] }) => {
protyle.toolbar.element.classList.add("fn__none");
event.stopPropagation();
const range = protyle.toolbar.range;
const nodeElement = hasClosestBlock(range.startContainer);
if (!nodeElement) {
return;
}
const inlineMathElement = hasClosestByAttribute(range.startContainer, "data-type", "inline-math");
if (inlineMathElement) {
mathRender(inlineMathElement);
return;
}
if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) {
range.setStartBefore(range.startContainer.parentElement);
}
if (!["DIV", "TD", "TH"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) {
range.setEndAfter(range.endContainer.parentElement);
}
const wbrElement = document.createElement("wbr");
range.insertNode(wbrElement);
const html = nodeElement.outerHTML;
const newElement = document.createElement("span");
newElement.className = "render-node";
newElement.setAttribute("contenteditable", "false");
newElement.setAttribute("data-type", "inline-math");
newElement.setAttribute("data-subtype", "math");
newElement.setAttribute("data-content", range.toString());
range.extractContents();
range.insertNode(newElement);
mathRender(newElement);
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
wbrElement.remove();
});
}
}
export const removeLink = (linkElement: HTMLElement, range: Range) => {
const types = linkElement.getAttribute("data-type").split(" ");
if (types.length === 1) {
const linkParentElement = linkElement.parentElement;
linkElement.outerHTML = linkElement.innerHTML + "<wbr>";
focusByWbr(linkParentElement, range);
} else {
types.find((itemType, index) => {
if ("a" === itemType) {
types.splice(index, 1);
return true;
}
});
linkElement.setAttribute("data-type", types.join(" "));
linkElement.removeAttribute("data-href");
range.selectNodeContents(linkElement);
range.collapse(false);
focusByRange(range);
}
};

View file

@ -12,7 +12,7 @@ export class ToolbarItem {
this.element.setAttribute("data-type", menuItem.name);
this.element.setAttribute("aria-label", tip + hotkey);
this.element.innerHTML = `<svg><use xlink:href="#${menuItem.icon}"></use></svg>`;
if (["text", "a", "block-ref"].includes(menuItem.name)) {
if (["text", "a", "block-ref", "inline-math"].includes(menuItem.name)) {
return;
}
this.element.addEventListener(getEventName(), (event) => {

View file

@ -41,6 +41,7 @@ import {renderAssetsPreview} from "../../asset/renderAssets";
import {electronUndo} from "../undo";
import {previewTemplate} from "./util";
import {showMessage} from "../../dialog/message";
import {InlineMath} from "./InlineMath";
export class Toolbar {
public element: HTMLElement;
@ -125,7 +126,7 @@ export class Toolbar {
});
const types = this.getCurrentType();
types.forEach(item => {
if (["a", "block-ref", "text", "file-annotation-ref"].includes(item)) {
if (["a", "block-ref", "text", "file-annotation-ref", "inline-math"].includes(item)) {
return;
}
this.element.querySelector(`[data-type="${item}"]`).classList.add("protyle-toolbar__item--current");
@ -163,15 +164,15 @@ export class Toolbar {
types = types.concat((endElement.getAttribute("data-type") || "").split(" "));
}
// if (range.startOffset === range.startContainer.textContent.length) {
// const nextSibling = hasNextSibling(range.startContainer) as Element;
// if (nextSibling && nextSibling.nodeType !== 3) {
// types = types.concat((nextSibling.getAttribute("data-type") || "").split(" "));
// }
// const nextSibling = hasNextSibling(range.startContainer) as Element;
// if (nextSibling && nextSibling.nodeType !== 3) {
// types = types.concat((nextSibling.getAttribute("data-type") || "").split(" "));
// }
// } else if (range.endOffset === 0) {
// const previousSibling = hasPreviousSibling(range.startContainer) as Element;
// if (previousSibling && previousSibling.nodeType !== 3) {
// types = types.concat((previousSibling.getAttribute("data-type") || "").split(" "));
// }
// if (previousSibling && previousSibling.nodeType !== 3) {
// types = types.concat((previousSibling.getAttribute("data-type") || "").split(" "));
// }
// }
range.cloneContents().childNodes.forEach((item: HTMLElement) => {
if (item.nodeType !== 3) {
@ -195,12 +196,14 @@ export class Toolbar {
case "sup":
case "sub":
case "kbd":
case "inline-math":
menuItemObj = new ToolbarItem(protyle, menuItem);
break;
case "block-ref":
menuItemObj = new BlockRef(protyle, menuItem);
break;
case "inline-math":
menuItemObj = new InlineMath(protyle, menuItem);
break;
case "|":
menuItemObj = new Divider();
break;
@ -488,12 +491,12 @@ export class Toolbar {
// return;
// }
let startElement = this.range.startContainer as Element;
if (this.range.startContainer.nodeType === 3) {
startElement = this.range.startContainer.parentElement;
if (startElement.getAttribute("data-type") === "virtual-block-ref" && !["DIV", "TD", "TH"].includes(startElement.parentElement.tagName)) {
startElement = startElement.parentElement;
}
}
// if (this.range.startContainer.nodeType === 3) {
// startElement = this.range.startContainer.parentElement;
// if (startElement.getAttribute("data-type") === "virtual-block-ref" && !["DIV", "TD", "TH"].includes(startElement.parentElement.tagName)) {
// startElement = startElement.parentElement;
// }
// }
// table 选中处理
const tableElement = hasClosestByAttribute(startElement, "data-type", "NodeTable");
@ -523,19 +526,19 @@ export class Toolbar {
}
}
if (this.range.toString() === "" && action === "range" && getSelectionOffset(startElement, protyle.wysiwyg.element).end === startElement.textContent.length &&
this.range.startContainer.nodeType === 3 && !this.range.startContainer.parentElement.getAttribute("contenteditable") &&
types.length > 0) {
// 跳出行内元素
const textNode = document.createTextNode(Constants.ZWSP);
this.range.startContainer.parentElement.after(textNode);
this.range.selectNodeContents(textNode);
this.range.collapse(false);
if (types.includes(type)) {
// 如果不是同一种行内元素,需进行后续的渲染操作
return;
}
}
// if (this.range.toString() === "" && action === "range" && getSelectionOffset(startElement, protyle.wysiwyg.element).end === startElement.textContent.length &&
// this.range.startContainer.nodeType === 3 && !this.range.startContainer.parentElement.getAttribute("contenteditable") &&
// types.length > 0) {
// // 跳出行内元素
// const textNode = document.createTextNode(Constants.ZWSP);
// this.range.startContainer.parentElement.after(textNode);
// this.range.selectNodeContents(textNode);
// this.range.collapse(false);
// if (types.includes(type)) {
// // 如果不是同一种行内元素,需进行后续的渲染操作
// return;
// }
// }
// if (types.length > 0 && types.includes("link") && action === "range") {
// // 链接快捷键不应取消,应该显示链接信息
// linkMenu(protyle, this.range.startContainer.parentElement);
@ -653,15 +656,15 @@ export class Toolbar {
// this.range.selectNodeContents(refNode);
// hintRef(refText, protyle, true);
// break;
case "inline-math":
newElement = document.createElement("span");
newElement.className = "render-node";
newElement.setAttribute("contenteditable", "false");
newElement.setAttribute("data-type", "inline-math");
newElement.setAttribute("data-subtype", "math");
newElement.setAttribute("data-content", startText + selectContents.textContent + endText);
mathRender(newElement);
break;
// case "inline-math":
// newElement = document.createElement("span");
// newElement.className = "render-node";
// newElement.setAttribute("contenteditable", "false");
// newElement.setAttribute("data-type", "inline-math");
// newElement.setAttribute("data-subtype", "math");
// newElement.setAttribute("data-content", startText + selectContents.textContent + endText);
// mathRender(newElement);
// break;
}
// if (newElement) {
// this.range.insertNode(newElement);

View file

@ -152,7 +152,7 @@ const listEnter = (protyle: IProtyle, blockElement: HTMLElement, range: Range) =
selectNode.firstChild.remove();
}
// https://github.com/siyuan-note/siyuan/issues/3850
if (editableElement?.lastElementChild?.getAttribute("data-type") === "inline-math" &&
if (editableElement?.lastElementChild?.getAttribute("data-type").indexOf("inline-math") > -1 &&
!hasNextSibling(editableElement?.lastElementChild)) {
editableElement.insertAdjacentText("beforeend", "\n");
}
@ -390,7 +390,7 @@ export const enter = (blockElement: HTMLElement, range: Range, protyle: IProtyle
selectNode.firstChild.remove();
}
// https://github.com/siyuan-note/siyuan/issues/3850
if (editableElement?.lastElementChild?.getAttribute("data-type") === "inline-math" &&
if (editableElement?.lastElementChild?.getAttribute("data-type").indexOf("inline-math") > -1 &&
!hasNextSibling(editableElement?.lastElementChild)) {
editableElement.insertAdjacentText("beforeend", "\n");
}

View file

@ -535,11 +535,11 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
// https://github.com/siyuan-note/siyuan/issues/5185
if (range.startOffset === 0 && range.startContainer.nodeType === 3) {
const previousSibling = hasPreviousSibling(range.startContainer) as HTMLElement;
if (previousSibling && previousSibling.nodeType !== 3 && previousSibling.getAttribute("data-type") === "inline-math") {
if (previousSibling && previousSibling.nodeType !== 3 && previousSibling.getAttribute("data-type").indexOf("inline-math") > -1) {
protyle.toolbar.showRender(protyle, previousSibling);
return;
} else if (!previousSibling && range.startContainer.parentElement.previousSibling.isSameNode(range.startContainer.parentElement.previousElementSibling) &&
range.startContainer.parentElement.previousElementSibling.getAttribute("data-type") === "inline-math") {
range.startContainer.parentElement.previousElementSibling.getAttribute("data-type").indexOf("inline-math") > -1) {
protyle.toolbar.showRender(protyle, range.startContainer.parentElement.previousElementSibling);
return;
}
@ -1185,7 +1185,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
}
if (matchHotKey(menuItem.hotkey, event)) {
protyle.toolbar.range = getEditorRange(protyle.wysiwyg.element);
if (["text", "a", "block-ref"].includes(menuItem.name)) {
if (["text", "a", "block-ref", "inline-math"].includes(menuItem.name)) {
protyle.toolbar.element.querySelector(`[data-type="${menuItem.name}"]`).dispatchEvent(new CustomEvent("block-ref" === menuItem.name ? getEventName() : "click"));
} else {
protyle.toolbar.setInlineMark(protyle, menuItem.name, "range");

View file

@ -442,7 +442,7 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran
// 非空块
range.setEndAfter(editableElement.lastChild);
// 数学公式会车后再删除 https://github.com/siyuan-note/siyuan/issues/3850
if (previousLastEditElement?.lastElementChild?.getAttribute("data-type") === "inline-math") {
if (previousLastEditElement?.lastElementChild?.getAttribute("data-type").indexOf("inline-math") > -1) {
const lastSibling = hasNextSibling(previousLastEditElement?.lastElementChild);
if (lastSibling && lastSibling.textContent === "\n") {
lastSibling.remove();