Skip to content

Commit 6a4628f

Browse files
authored
feat(Clipboard): get markup from html that has only text (#78)
1 parent d11e9e0 commit 6a4628f

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/extensions/behavior/Clipboard/clipboard.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {isTextSelection, isNodeSelection, isWholeSelection} from '../../../utils
1919
import {BaseNode, pType} from '../../base/BaseSchema';
2020

2121
import {isInsideCode} from './code';
22-
import {DataTransferType, isIosSafariShare} from './utils';
22+
import {DataTransferType, extractTextContentFromHtml, isIosSafariShare} from './utils';
2323

2424
export type ClipboardPluginOptions = {
2525
yfmParser: Parser;
@@ -99,12 +99,31 @@ export const clipboard = ({
9999
!e.clipboardData.types.includes(DataTransferType.Yfm) &&
100100
(data = e.clipboardData.getData(DataTransferType.Html))
101101
) {
102-
return false; // default html pasting
102+
const textFromHtml = extractTextContentFromHtml(data);
103+
if (textFromHtml) {
104+
const res = tryCatch(() => textParser.parse(textFromHtml));
105+
if (res.success) {
106+
const docNode = res.result;
107+
const slice = getSliceFromMarkupFragment(docNode.content);
108+
view.dispatch(
109+
trackTransactionMetrics(
110+
view.state.tr.replaceSelection(slice),
111+
'paste',
112+
{clipboardDataFormat: DataTransferType.Html},
113+
),
114+
);
115+
isPasteHandled = true;
116+
} else {
117+
logger.error(res.error);
118+
console.error(res.error);
119+
}
120+
} else return false; // default html pasting
103121
}
104122

105123
if (
106-
(data = e.clipboardData.getData(DataTransferType.Yfm)) ||
107-
(data = e.clipboardData.getData(DataTransferType.Text))
124+
!isPasteHandled &&
125+
((data = e.clipboardData.getData(DataTransferType.Yfm)) ||
126+
(data = e.clipboardData.getData(DataTransferType.Text)))
108127
) {
109128
let parser: Parser;
110129
let dataFormat: string;

src/extensions/behavior/Clipboard/utils.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,25 @@ export function isFilesFromHtml({types}: DataTransfer): boolean {
3333
export function isImageFile(file: File): boolean {
3434
return file.type.startsWith('image/');
3535
}
36+
37+
export function extractTextContentFromHtml(html: string) {
38+
const element = document.createElement('div');
39+
element.innerHTML = html;
40+
element.replaceChildren(...Array.from(element.children).filter((v) => v.nodeName !== 'META'));
41+
42+
// Look if all nodes are div or span. That they don't have any classname and have only text child.
43+
if (
44+
Array.from(element.children).every(({nodeName, classList, childNodes}) => {
45+
return (
46+
(nodeName === 'DIV' || nodeName === 'SPAN') &&
47+
!classList.length &&
48+
childNodes.length === 1 &&
49+
(childNodes[0].nodeName === '#text' || childNodes[0].nodeName === 'BR')
50+
);
51+
})
52+
) {
53+
return Array.from(element.children).reduce((a, v) => a + v.textContent + '\n', '');
54+
}
55+
56+
return null;
57+
}

0 commit comments

Comments
 (0)