You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by sh...@apache.org on 2025/05/20 07:10:56 UTC
(answer) 12/12: fix: When copying text and images, can the images only appear at the end of the article
This is an automated email from the ASF dual-hosted git repository.
shuai pushed a commit to branch test
in repository https://gitbox.apache.org/repos/asf/answer.git
commit 9331690b0d4da9900ef51faf138533e5f26d8c22
Author: shuai <li...@sifou.com>
AuthorDate: Tue May 20 15:06:24 2025 +0800
fix: When copying text and images, can the images only appear at the end of the article
---
ui/src/components/Editor/ToolBars/image.tsx | 74 +++++++++++++++++++++--------
ui/src/components/Editor/utils/index.ts | 10 ++++
2 files changed, 64 insertions(+), 20 deletions(-)
diff --git a/ui/src/components/Editor/ToolBars/image.tsx b/ui/src/components/Editor/ToolBars/image.tsx
index 322da08d..766301f2 100644
--- a/ui/src/components/Editor/ToolBars/image.tsx
+++ b/ui/src/components/Editor/ToolBars/image.tsx
@@ -228,30 +228,64 @@ const Image = ({ editorInstance }) => {
return;
}
event.preventDefault();
-
- let innerText = '';
- const allPTag = new DOMParser()
- .parseFromString(
- htmlStr.replace(
- /<img([\s\S]*?) src\s*=\s*(['"])([\s\S]*?)\2([^>]*)>/gi,
- `<p>\n\n</p>`,
- ),
- 'text/html',
- )
- .querySelectorAll('body p');
-
- allPTag.forEach((p, index) => {
- const text = p.textContent || '';
- if (text !== '') {
- if (index === allPTag.length - 1) {
- innerText += `${p.textContent}`;
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(htmlStr, 'text/html');
+ const { body } = doc;
+
+ let markdownText = '';
+
+ function traverse(node) {
+ if (node.nodeType === Node.TEXT_NODE) {
+ // text node
+ markdownText += node.textContent;
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
+ // element node
+ const tagName = node.tagName.toLowerCase();
+
+ if (tagName === 'img') {
+ // img node
+ const src = node.getAttribute('src');
+ const alt = node.getAttribute('alt') || t('image.text');
+ markdownText += ``;
+ } else if (tagName === 'br') {
+ // br node
+ markdownText += '\n';
} else {
- innerText += `${p.textContent}${text.endsWith('\n') ? '' : '\n\n'}`;
+ for (let i = 0; i < node.childNodes.length; i += 1) {
+ traverse(node.childNodes[i]);
+ }
+ }
+
+ const blockLevelElements = [
+ 'p',
+ 'div',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'ul',
+ 'ol',
+ 'li',
+ 'blockquote',
+ 'pre',
+ 'table',
+ 'thead',
+ 'tbody',
+ 'tr',
+ 'th',
+ 'td',
+ ];
+ if (blockLevelElements.includes(tagName)) {
+ markdownText += '\n\n';
}
}
- });
+ }
+
+ traverse(body);
- editor.replaceSelection(innerText);
+ editor.replaceSelection(markdownText);
};
const handleClick = () => {
if (!link.value) {
diff --git a/ui/src/components/Editor/utils/index.ts b/ui/src/components/Editor/utils/index.ts
index 3977367c..61e95fbb 100644
--- a/ui/src/components/Editor/utils/index.ts
+++ b/ui/src/components/Editor/utils/index.ts
@@ -172,6 +172,16 @@ export const useEditor = ({
placeholder(placeholderText),
EditorView.lineWrapping,
editableCompartment.of(EditorView.editable.of(true)),
+ EditorView.domEventHandlers({
+ paste(event) {
+ const clipboard = event.clipboardData as DataTransfer;
+ const htmlStr = clipboard.getData('text/html');
+ const imgRegex =
+ /<img([\s\S]*?) src\s*=\s*(['"])([\s\S]*?)\2([^>]*)>/;
+
+ return Boolean(htmlStr.match(imgRegex));
+ },
+ }),
],
});