diff --git a/packages/editor/src/extensions/behavior/Clipboard/clipboard.ts b/packages/editor/src/extensions/behavior/Clipboard/clipboard.ts index 359a72d1c..1082d450b 100644 --- a/packages/editor/src/extensions/behavior/Clipboard/clipboard.ts +++ b/packages/editor/src/extensions/behavior/Clipboard/clipboard.ts @@ -10,6 +10,7 @@ import {isNodeSelection, isTextSelection, isWholeSelection} from 'src/utils/sele import {BaseNode, pType} from '../../base/BaseSchema'; import {isInsideCode} from './code'; +import {detectMarkdown} from './markdown-detect'; import {getSelectionContent} from './selection-content'; import {trimTextSelection} from './trim-selection'; import {DataTransferType, extractTextContentFromHtml, isIosSafariShare, trimContent} from './utils'; @@ -98,6 +99,11 @@ export const clipboard = ({ return true; } + if (pasteDetectedMarkdown(view, e.clipboardData, textParser)) { + e.preventDefault(); + return true; + } + if ( !e.clipboardData.types.includes(DataTransferType.Yfm) && (data = e.clipboardData.getData(DataTransferType.Html)) @@ -216,6 +222,28 @@ export const clipboard = ({ }); }; +function pasteDetectedMarkdown( + view: EditorView, + clipboardData: DataTransfer, + textParser: Parser, +): boolean { + if (clipboardData.types.includes(DataTransferType.Yfm) || isInsideCode(view.state)) { + return false; + } + + const doc = detectMarkdown(clipboardData.getData(DataTransferType.Text), textParser); + if (!doc) return false; + + const slice = getSliceFromMarkupFragment(doc.content); + view.dispatch( + trackTransactionMetrics(view.state.tr.replaceSelection(slice), 'paste', { + clipboardDataFormat: DataTransferType.Text, + }), + ); + + return true; +} + function getSliceFromMarkupFragment(fragment: Fragment) { let start = 0; let end = 0; diff --git a/packages/editor/src/extensions/behavior/Clipboard/markdown-detect.test.ts b/packages/editor/src/extensions/behavior/Clipboard/markdown-detect.test.ts new file mode 100644 index 000000000..a60f94ffb --- /dev/null +++ b/packages/editor/src/extensions/behavior/Clipboard/markdown-detect.test.ts @@ -0,0 +1,93 @@ +import {EditorState} from 'prosemirror-state'; +import {builders} from 'prosemirror-test-builder'; +import {EditorView} from 'prosemirror-view'; + +import {dispatchPasteEvent} from '../../../../tests/dispatch-event'; +import {ExtensionsManager} from '../../../core'; +import {Logger2} from '../../../logger'; +import {BaseNode, BaseSchemaSpecs} from '../../base/specs'; +import {TableSpecs} from '../../markdown/Table/TableSpecs'; +import {CellAlign, TableAttrs, TableNode} from '../../markdown/Table/const'; +import {YfmTableSpecs} from '../../yfm/YfmTable/YfmTableSpecs'; + +import {detectMarkdown} from './markdown-detect'; +import {DataTransferType} from './utils'; + +import {Clipboard} from './index'; + +const MARKDOWN_TABLE = [ + '| Name | Role | Office | Tenure |', + '| --- | --- | --- | --- |', + '| Sergey | Frontend | Belgrade | 5 years |', + '| Anna | QA | Moscow | 3 years |', +].join('\n'); + +const HTML_TABLE = ` +
| Name | Role | Office | Tenure |
|---|---|---|---|
| Sergey | Frontend | Belgrade | 5 years |
| Anna | QA | Moscow | 3 years |