From bfe00e8d434e28c480adab5b05555609f17172e0 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Thu, 4 Dec 2025 23:07:16 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/16051 --- app/src/protyle/util/paste.ts | 65 +++++++++++++++-------------- app/src/protyle/wysiwyg/getBlock.ts | 22 +++++++++- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts index fcdcfc096..66a51ed73 100644 --- a/app/src/protyle/util/paste.ts +++ b/app/src/protyle/util/paste.ts @@ -13,7 +13,7 @@ import {scrollCenter} from "../../util/highlightById"; import {hideElements} from "../ui/hideElements"; import {avRender} from "../render/av/render"; import {cellScrollIntoView, getCellText} from "../render/av/cell"; -import {getContenteditableElement} from "../wysiwyg/getBlock"; +import {getCalloutInfo, getContenteditableElement} from "../wysiwyg/getBlock"; import {clearBlockElement} from "./clear"; export const getTextStar = (blockElement: HTMLElement, contentOnly = false) => { @@ -21,35 +21,35 @@ export const getTextStar = (blockElement: HTMLElement, contentOnly = false) => { let refText = ""; if (["NodeHeading", "NodeParagraph"].includes(dataType)) { refText = getContenteditableElement(blockElement).innerHTML; - } else { - if ("NodeHTMLBlock" === dataType) { - refText = "HTML"; - } else if ("NodeAttributeView" === dataType) { - refText = blockElement.querySelector(".av__title").textContent || window.siyuan.languages.database; - } else if ("NodeThematicBreak" === dataType) { - refText = window.siyuan.languages.line; - } else if ("NodeIFrame" === dataType) { - refText = "IFrame"; - } else if ("NodeWidget" === dataType) { - refText = window.siyuan.languages.widget; - } else if ("NodeVideo" === dataType) { - refText = window.siyuan.languages.video; - } else if ("NodeAudio" === dataType) { - refText = window.siyuan.languages.audio; - } else if (["NodeCodeBlock", "NodeTable"].includes(dataType)) { - refText = getPlainText(blockElement); - } else if (blockElement.classList.contains("render-node")) { - // 需在嵌入块后,代码块前 - refText += blockElement.dataset.subtype || Lute.UnEscapeHTMLStr(blockElement.getAttribute("data-content")); - } else if (["NodeBlockquote", "NodeCallout", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(dataType)) { - Array.from(blockElement.querySelectorAll("[data-node-id]")).find((item: HTMLElement) => { - if (!["NodeBlockquote", "NodeCallout", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(item.getAttribute("data-type"))) { - // 获取子块内容,使用容器块本身的 ID - refText = getTextStar(item, true); - return true; - } - }); - } + } else if ("NodeHTMLBlock" === dataType) { + refText = "HTML"; + } else if ("NodeAttributeView" === dataType) { + refText = blockElement.querySelector(".av__title").textContent || window.siyuan.languages.database; + } else if ("NodeThematicBreak" === dataType) { + refText = window.siyuan.languages.line; + } else if ("NodeIFrame" === dataType) { + refText = "IFrame"; + } else if ("NodeWidget" === dataType) { + refText = window.siyuan.languages.widget; + } else if ("NodeVideo" === dataType) { + refText = window.siyuan.languages.video; + } else if ("NodeAudio" === dataType) { + refText = window.siyuan.languages.audio; + } else if (["NodeCodeBlock", "NodeTable"].includes(dataType)) { + refText = getPlainText(blockElement); + } else if (blockElement.classList.contains("render-node")) { + // 需在嵌入块后,代码块前 + refText += blockElement.dataset.subtype || Lute.UnEscapeHTMLStr(blockElement.getAttribute("data-content")); + } else if (["NodeBlockquote", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(dataType)) { + Array.from(blockElement.querySelectorAll("[data-node-id]")).find((item: HTMLElement) => { + if (!["NodeBlockquote", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(item.getAttribute("data-type"))) { + // 获取子块内容,使用容器块本身的 ID + refText = getTextStar(item, true); + return true; + } + }); + } else if ("NodeCallout" === dataType) { + refText = getCalloutInfo(blockElement); } if (contentOnly) { return refText; @@ -91,7 +91,10 @@ export const getPlainText = (blockElement: HTMLElement, isNested = false) => { } }); text = text.slice(0, -1); - } else if (!isNested && ["NodeBlockquote", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(dataType)) { + } else if (!isNested && ["NodeBlockquote", "NodeCallout", "NodeList", "NodeSuperBlock", "NodeListItem"].includes(dataType)) { + if (dataType === "NodeCallout") { + text += `${getCalloutInfo(blockElement)}\n`; + } blockElement.querySelectorAll("[data-node-id]").forEach((item: HTMLElement) => { const nestedText = getPlainText(item, true); text += nestedText ? nestedText + "\n" : ""; diff --git a/app/src/protyle/wysiwyg/getBlock.ts b/app/src/protyle/wysiwyg/getBlock.ts index 196e127fe..1420dacc8 100644 --- a/app/src/protyle/wysiwyg/getBlock.ts +++ b/app/src/protyle/wysiwyg/getBlock.ts @@ -1,6 +1,11 @@ import {hasClosestBlock, hasClosestByAttribute, isInEmbedBlock} from "../util/hasClosest"; import {Constants} from "../../constants"; +export const getCalloutInfo = (element: Element) => { + const icon = element.querySelector(".callout-icon").textContent; + return (icon ? icon + " " : "") + element.querySelector(".callout-title").textContent; +}; + export const getPreviousBlock = (element: Element) => { let parentElement = element; while (parentElement) { @@ -117,15 +122,28 @@ export const getTopEmptyElement = (element: Element) => { }; export const getTopAloneElement = (topSourceElement: Element) => { - if ("NodeBlockquote" === topSourceElement.parentElement.getAttribute("data-type") && topSourceElement.parentElement.childElementCount === 2) { + if ("NodeBlockquote" === topSourceElement.parentElement.getAttribute("data-type") && + topSourceElement.parentElement.childElementCount === 2) { while (topSourceElement.parentElement && !topSourceElement.parentElement.classList.contains("protyle-wysiwyg")) { - if (topSourceElement.parentElement.getAttribute("data-type") === "NodeBlockquote" && topSourceElement.parentElement.childElementCount === 2) { + if (topSourceElement.parentElement.getAttribute("data-type") === "NodeBlockquote" && + topSourceElement.parentElement.childElementCount === 2) { topSourceElement = topSourceElement.parentElement; } else { topSourceElement = getTopAloneElement(topSourceElement); break; } } + } else if (topSourceElement.parentElement.classList.contains("callout-content") && + topSourceElement.parentElement.childElementCount === 1) { + while (topSourceElement.parentElement && !topSourceElement.parentElement.classList.contains("protyle-wysiwyg")) { + if (topSourceElement.parentElement.classList.contains("callout-content") && + topSourceElement.parentElement.childElementCount === 1) { + topSourceElement = topSourceElement.parentElement.parentElement; + } else { + topSourceElement = getTopAloneElement(topSourceElement); + break; + } + } } else if ("NodeSuperBlock" === topSourceElement.parentElement.getAttribute("data-type") && topSourceElement.parentElement.childElementCount === 2) { while (topSourceElement.parentElement && !topSourceElement.parentElement.classList.contains("protyle-wysiwyg")) { if (topSourceElement.parentElement.getAttribute("data-type") === "NodeSuperBlock" && topSourceElement.parentElement.childElementCount === 2) {