1
1
import { htmlEscape } from 'escape-goat' ;
2
2
import { POST } from '../../modules/fetch.js' ;
3
3
import { imageInfo } from '../../utils/image.js' ;
4
+ import { getPastedContent , replaceTextareaSelection } from '../../utils/dom.js' ;
5
+ import { isUrl } from '../../utils/url.js' ;
4
6
5
7
async function uploadFile ( file , uploadUrl ) {
6
8
const formData = new FormData ( ) ;
@@ -10,17 +12,6 @@ async function uploadFile(file, uploadUrl) {
10
12
return await res . json ( ) ;
11
13
}
12
14
13
- function clipboardPastedImages ( e ) {
14
- if ( ! e . clipboardData ) return [ ] ;
15
-
16
- const files = [ ] ;
17
- for ( const item of e . clipboardData . items || [ ] ) {
18
- if ( ! item . type || ! item . type . startsWith ( 'image/' ) ) continue ;
19
- files . push ( item . getAsFile ( ) ) ;
20
- }
21
- return files ;
22
- }
23
-
24
15
function triggerEditorContentChanged ( target ) {
25
16
target . dispatchEvent ( new CustomEvent ( 'ce-editor-content-changed' , { bubbles : true } ) ) ;
26
17
}
@@ -91,20 +82,16 @@ class CodeMirrorEditor {
91
82
}
92
83
}
93
84
94
- const uploadClipboardImage = async ( editor , dropzone , e ) => {
85
+ async function handleClipboardImages ( editor , dropzone , images , e ) {
95
86
const uploadUrl = dropzone . getAttribute ( 'data-upload-url' ) ;
96
87
const filesContainer = dropzone . querySelector ( '.files' ) ;
97
88
98
- if ( ! uploadUrl || ! filesContainer ) return ;
89
+ if ( ! dropzone || ! uploadUrl || ! filesContainer || ! images . length ) return ;
99
90
100
- const pastedImages = clipboardPastedImages ( e ) ;
101
- if ( ! pastedImages || pastedImages . length === 0 ) {
102
- return ;
103
- }
104
91
e . preventDefault ( ) ;
105
92
e . stopPropagation ( ) ;
106
93
107
- for ( const img of pastedImages ) {
94
+ for ( const img of images ) {
108
95
const name = img . name . slice ( 0 , img . name . lastIndexOf ( '.' ) ) ;
109
96
110
97
const placeholder = `` ;
@@ -131,18 +118,37 @@ const uploadClipboardImage = async (editor, dropzone, e) => {
131
118
input . value = uuid ;
132
119
filesContainer . append ( input ) ;
133
120
}
134
- } ;
121
+ }
122
+
123
+ function handleClipboardText ( textarea , text , e ) {
124
+ // when pasting links over selected text, turn it into [text](link)
125
+ const { value, selectionStart, selectionEnd} = textarea ;
126
+ const selectedText = value . substring ( selectionStart , selectionEnd ) ;
127
+ const trimmedText = text . trim ( ) ;
128
+ if ( selectedText && isUrl ( trimmedText ) ) {
129
+ e . stopPropagation ( ) ;
130
+ e . preventDefault ( ) ;
131
+ replaceTextareaSelection ( textarea , `[${ selectedText } ](${ trimmedText } )` ) ;
132
+ }
133
+ }
135
134
136
135
export function initEasyMDEImagePaste ( easyMDE , dropzone ) {
137
- if ( ! dropzone ) return ;
138
- easyMDE . codemirror . on ( 'paste' , async ( _ , e ) => {
139
- return uploadClipboardImage ( new CodeMirrorEditor ( easyMDE . codemirror ) , dropzone , e ) ;
136
+ easyMDE . codemirror . on ( 'paste' , ( _ , e ) => {
137
+ const { images} = getPastedContent ( e ) ;
138
+ if ( images . length ) {
139
+ handleClipboardImages ( new CodeMirrorEditor ( easyMDE . codemirror ) , dropzone , images , e ) ;
140
+ }
140
141
} ) ;
141
142
}
142
143
143
144
export function initTextareaImagePaste ( textarea , dropzone ) {
144
- if ( ! dropzone ) return ;
145
- textarea . addEventListener ( 'paste' , async ( e ) => {
146
- return uploadClipboardImage ( new TextareaEditor ( textarea ) , dropzone , e ) ;
145
+ textarea . addEventListener ( 'paste' , ( e ) => {
146
+ const { images, text} = getPastedContent ( e ) ;
147
+ if ( text ) {
148
+ handleClipboardText ( textarea , text , e ) ;
149
+ }
150
+ if ( images . length ) {
151
+ handleClipboardImages ( new TextareaEditor ( textarea ) , dropzone , images , e ) ;
152
+ }
147
153
} ) ;
148
154
}
0 commit comments