diff --git a/app/src/assets/scss/protyle/_protyle.scss b/app/src/assets/scss/protyle/_protyle.scss index f58da8518..26b9a8240 100644 --- a/app/src/assets/scss/protyle/_protyle.scss +++ b/app/src/assets/scss/protyle/_protyle.scss @@ -409,6 +409,12 @@ } } +.protyle-cursor { + position: absolute; + right: 0; + top: 0; +} + table[contenteditable="false"] + .protyle-action__table > .table__resize { display: none; } diff --git a/app/src/protyle/render/mathRender.ts b/app/src/protyle/render/mathRender.ts index 0678e8800..11635cccb 100644 --- a/app/src/protyle/render/mathRender.ts +++ b/app/src/protyle/render/mathRender.ts @@ -4,6 +4,7 @@ import {Constants} from "../../constants"; import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock"; import {hasClosestBlock} from "../util/hasClosest"; import {looseJsonParse} from "../../util/functions"; +import {genRenderFrame} from "./util"; export const mathRender = (element: Element, cdn = Constants.PROTYLE_CDN, maxWidth = false) => { let mathElements: Element[] = []; @@ -24,43 +25,40 @@ export const mathRender = (element: Element, cdn = Constants.PROTYLE_CDN, maxWid return; } mathElement.setAttribute("data-render", "true"); - let renderElement = mathElement; - if (mathElement.tagName === "DIV") { - renderElement = mathElement.firstElementChild as HTMLElement; - } let macros = {}; try { macros = looseJsonParse(window.siyuan.config.editor.katexMacros || "{}"); } catch (e) { console.warn("KaTex macros is not JSON", e); } + const isBlock = mathElement.tagName === "DIV"; try { - renderElement.innerHTML = window.katex.renderToString(Lute.UnEscapeHTMLStr(mathElement.getAttribute("data-content")), { - displayMode: mathElement.tagName === "DIV", + const mathHTML = window.katex.renderToString(Lute.UnEscapeHTMLStr(mathElement.getAttribute("data-content")), { + displayMode: isBlock, output: "html", macros, trust: true, // REF: https://katex.org/docs/supported#html strict: (errorCode) => errorCode === "unicodeTextInMathMode" ? "ignore" : "warn", }); - renderElement.classList.remove("ft__error"); const blockElement = hasClosestBlock(mathElement); - if (mathElement.tagName === "DIV") { - renderElement.firstElementChild.setAttribute("contenteditable", "false"); - if (renderElement.childElementCount < 2) { - // 不能使用 contenteditable="false",否则光标无法移动到该块 - renderElement.insertAdjacentHTML("beforeend", `${Constants.ZWSP}`); - } + if (isBlock) { + genRenderFrame(mathElement); + mathElement.firstElementChild.firstElementChild.classList.remove("ft__error"); + mathElement.firstElementChild.firstElementChild.setAttribute("contenteditable", "false"); + mathElement.firstElementChild.firstElementChild.innerHTML = mathHTML; // https://github.com/siyuan-note/siyuan/issues/3541 - const baseElements = renderElement.querySelectorAll(".base"); + const baseElements = mathElement.querySelectorAll(".base"); if (baseElements.length > 0) { baseElements[baseElements.length - 1].insertAdjacentHTML("afterend", ""); } // https://github.com/siyuan-note/siyuan/issues/4334 - const newlineElement = renderElement.querySelector(".katex-html > .newline"); + const newlineElement = mathElement.querySelector(".katex-html > .newline"); if (newlineElement) { newlineElement.parentElement.style.display = "block"; } } else { + mathElement.classList.remove("ft__error"); + mathElement.innerHTML = mathHTML; if (blockElement && mathElement.getBoundingClientRect().width > blockElement.clientWidth) { mathElement.style.maxWidth = "100%"; mathElement.style.overflowX = "auto"; @@ -110,7 +108,7 @@ export const mathRender = (element: Element, cdn = Constants.PROTYLE_CDN, maxWid // export pdf if (maxWidth) { setTimeout(() => { - if (mathElement.tagName === "DIV") { + if (isBlock) { const katexElement = mathElement.querySelector(".katex-display"); if (katexElement.clientWidth < katexElement.scrollWidth) { katexElement.firstElementChild.setAttribute("style", `font-size:${katexElement.clientWidth * 100 / katexElement.scrollWidth}%`); @@ -123,8 +121,15 @@ export const mathRender = (element: Element, cdn = Constants.PROTYLE_CDN, maxWid }); } } catch (e) { - renderElement.innerHTML = e.message; - renderElement.classList.add("ft__error"); + if (isBlock) { + genRenderFrame(mathElement); + mathElement.firstElementChild.firstElementChild.setAttribute("contenteditable", "false"); + mathElement.firstElementChild.firstElementChild.innerHTML = e.message; + mathElement.firstElementChild.firstElementChild.classList.add("ft__error"); + } else { + mathElement.innerHTML = e.message; + mathElement.classList.add("ft__error"); + } } }); }); diff --git a/app/src/protyle/render/util.ts b/app/src/protyle/render/util.ts index 7bf606174..3ef9ee470 100644 --- a/app/src/protyle/render/util.ts +++ b/app/src/protyle/render/util.ts @@ -17,15 +17,20 @@ export const genIconHTML = (element?: false | HTMLElement) => { `; }; -export const genRenderFrame = (renderElement:Element) => { - if (renderElement.querySelector(".protyle-icons")) { +export const genRenderFrame = (renderElement: Element) => { + if (renderElement.querySelector(".protyle-cursor")) { return; } - renderElement.insertAdjacentHTML("afterbegin",`
+ const type = renderElement.getAttribute("data-type"); + if (type === "NodeBlockQueryEmbed") { + renderElement.insertAdjacentHTML("afterbegin", `
-
${Constants.ZWSP}
`) +
${Constants.ZWSP}
`); + } else if (type==="NodeMathBlock") { + renderElement.firstElementChild.innerHTML = `${Constants.ZWSP}`; + } } export const processClonePHElement = (item: Element) => { diff --git a/app/src/protyle/util/selection.ts b/app/src/protyle/util/selection.ts index 00ca1b736..6d4dd5631 100644 --- a/app/src/protyle/util/selection.ts +++ b/app/src/protyle/util/selection.ts @@ -151,8 +151,17 @@ export const getEditorRange = (element: Element) => { return range; } } + + if (element.classList.contains("li") || element.classList.contains("list")) { + return getEditorRange(element.querySelector("[data-node-id]")); + } + // 代码块过长,在代码块的下一个块前删除,代码块会滚动到顶部,因粗需要 preventScroll (element as HTMLElement).focus({preventScroll: true}); + if (!range) { + range = document.createRange(); + } + let targetElement; if (element.classList.contains("table")) { // 当光标不在表格区域中时表格无法被复制 https://ld246.com/article/1650510736504 @@ -160,13 +169,23 @@ export const getEditorRange = (element: Element) => { } else { targetElement = getContenteditableElement(element); if (!targetElement) { - targetElement = element; + const type = element.getAttribute("data-type"); + if (type === "NodeThematicBreak") { + targetElement= element.firstElementChild; + } else if (type === "NodeBlockQueryEmbed") { + targetElement = element.lastElementChild.previousElementSibling?.firstChild; + } else if (["NodeMathBlock", "NodeHTMLBlock"].includes(type)) { + targetElement = element.lastElementChild.previousElementSibling?.lastElementChild?.firstChild; + } else if (type === "NodeVideo") { + targetElement = element.firstElementChild.firstChild; + } else if (type === "NodeAudio") { + targetElement = element.firstElementChild.lastChild; + } } else if (targetElement.tagName === "TABLE") { // 文档中开头为表格,获取错误 https://ld246.com/article/1663408335459?r=88250 targetElement = targetElement.querySelector("th") || element.querySelector("td"); } } - range = targetElement.ownerDocument.createRange(); range.setStart(targetElement || element, 0); range.collapse(true); return range; @@ -552,21 +571,19 @@ export const focusBlock = (element: Element, parentElement?: HTMLElement, toStar range.setStart(element.lastElementChild.previousElementSibling.firstChild, 0); range.collapse(true); setRange = true; - } else if (["NodeMathBlock", "NodeHTMLBlock"].includes(type)) { - if (element.lastElementChild.previousElementSibling?.lastElementChild?.firstChild) { - // https://ld246.com/article/1655714737572 - range.selectNodeContents(element.lastElementChild.previousElementSibling.lastElementChild.firstChild); - range.collapse(true); - } else if (element.lastElementChild.previousElementSibling) { - range.selectNodeContents(element.lastElementChild.previousElementSibling); - range.collapse(true); - } + } else if (type === "NodeMathBlock") { + genRenderFrame(element); + range.setStart(element.firstElementChild.lastElementChild.firstChild, 0); + setRange = true; + } else if (type === "NodeHTMLBlock") { + range.selectNodeContents(element.lastElementChild.previousElementSibling.lastElementChild.firstChild, 0); + range.collapse(true); setRange = true; } else if (type === "NodeIFrame" || type === "NodeWidget") { range.setStart(element, 0); setRange = true; } else if (type === "NodeVideo") { - range.setStart(element.firstElementChild, 0); + range.setStart(element.firstElementChild.firstChild, 0); setRange = true; } else if (type === "NodeAudio") { range.setStart(element.firstElementChild.lastChild, 0);