1
- import type { Mark } from 'prosemirror-model' ;
2
- import type { EditorState } from 'prosemirror-state' ;
1
+ import dd from 'ts-dedent' ;
2
+
3
+ import { getLoggerFromState } from '#core' ;
4
+ import type { Mark } from '#pm/model' ;
5
+ import { type EditorState , Plugin } from '#pm/state' ;
6
+
7
+ import { DataTransferType , isFilesOnly , isIosSafariShare } from './utils' ;
3
8
4
9
const isCodeMark = ( mark : Mark ) => mark . type . spec . code ;
5
10
@@ -23,3 +28,63 @@ export function isInsideInlineCode(state: EditorState): boolean {
23
28
}
24
29
return fromHasCodeMark ;
25
30
}
31
+
32
+ /**
33
+ * This plugin handles paste into any type of code: code block or code mark.
34
+ * If selection is inside code, it always prevents execution of all next paste handlers.
35
+ * It takes a value from following clipboard data types: uri-list, files or text data.
36
+ */
37
+ export const handlePasteIntoCodePlugin = ( ) => {
38
+ return new Plugin ( {
39
+ props : {
40
+ handleDOMEvents : {
41
+ paste ( view , event ) {
42
+ if ( ! event . clipboardData ) return false ;
43
+ const { clipboardData} = event ;
44
+
45
+ const codeType = isInsideCode ( view . state ) ;
46
+ if ( ! codeType ) return false ;
47
+
48
+ let text : string ;
49
+ let dataFormat : string ;
50
+
51
+ if ( isIosSafariShare ( clipboardData ) ) {
52
+ dataFormat = DataTransferType . UriList ;
53
+ text = clipboardData . getData ( DataTransferType . UriList ) ;
54
+ } else if ( isFilesOnly ( clipboardData ) ) {
55
+ dataFormat = DataTransferType . Files ;
56
+ text = Array . from ( clipboardData . files )
57
+ . map ( ( file ) => file . name )
58
+ . join ( ' ' ) ;
59
+ } else {
60
+ dataFormat = DataTransferType . Text ;
61
+ text = dd ( clipboardData . getData ( DataTransferType . Text ) ) ;
62
+ }
63
+
64
+ if ( codeType === 'inline' ) {
65
+ text = text . replaceAll ( '\n' , '↵' ) ;
66
+ }
67
+
68
+ const { state, dispatch} = view ;
69
+
70
+ getLoggerFromState ( state ) . event ( {
71
+ codeType,
72
+ dataFormat,
73
+ domEvent : 'paste' ,
74
+ event : 'paste-into-code' ,
75
+ dataTypes : clipboardData . types ,
76
+ } ) ;
77
+
78
+ event . preventDefault ( ) ;
79
+ dispatch (
80
+ state . tr
81
+ . replaceSelectionWith ( state . schema . text ( text ) , true )
82
+ . scrollIntoView ( ) ,
83
+ ) ;
84
+
85
+ return true ;
86
+ } ,
87
+ } ,
88
+ } ,
89
+ } ) ;
90
+ } ;
0 commit comments