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' ;
38
49const isCodeMark = ( mark : Mark ) => mark . type . spec . code ;
510
@@ -23,3 +28,63 @@ export function isInsideInlineCode(state: EditorState): boolean {
2328 }
2429 return fromHasCodeMark ;
2530}
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