@ -1,4 +1,5 @@
import $ from 'jquery' ;
const { csrfToken } = window . config ;
async function uploadFile ( file , uploadUrl ) {
@ -21,72 +22,104 @@ function clipboardPastedImages(e) {
if ( ! item . type || ! item . type . startsWith ( 'image/' ) ) continue ;
files . push ( item . getAsFile ( ) ) ;
}
if ( files . length ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
}
return files ;
}
class TextareaEditor {
constructor ( editor ) {
this . editor = editor ;
}
function insertAtCursor ( field , value ) {
if ( field . selectionStart || field . selectionStart === 0 ) {
const startPos = field . selectionStart ;
const endPos = field . selectionEnd ;
field . value = field . value . substring ( 0 , startPos ) + value + field . value . substring ( endPos , field . value . length ) ;
field . selectionStart = startPos + value . length ;
field . selectionEnd = startPos + value . length ;
} else {
field . value += value ;
insertPlaceholder ( value ) {
const editor = this . editor ;
const startPos = editor . selectionStart ;
const endPos = editor . selectionEnd ;
editor . value = editor . value . substring ( 0 , startPos ) + value + editor . value . substring ( endPos ) ;
editor . selectionStart = startPos ;
editor . selectionEnd = startPos + value . length ;
editor . focus ( ) ;
}
replacePlaceholder ( oldVal , newVal ) {
const editor = this . editor ;
const startPos = editor . selectionStart ;
const endPos = editor . selectionEnd ;
if ( editor . value . substring ( startPos , endPos ) === oldVal ) {
editor . value = editor . value . substring ( 0 , startPos ) + newVal + editor . value . substring ( endPos ) ;
editor . selectionEnd = startPos + newVal . length ;
} else {
editor . value = editor . value . replace ( oldVal , newVal ) ;
editor . selectionEnd -= oldVal . length ;
editor . selectionEnd += newVal . length ;
}
editor . selectionStart = editor . selectionEnd ;
editor . focus ( ) ;
}
}
function replaceAndKeepCursor ( field , oldval , newval ) {
if ( field . selectionStart || field . selectionStart === 0 ) {
const startPos = field . selectionStart ;
const endPos = field . selectionEnd ;
field . value = field . value . replace ( oldval , newval ) ;
field . selectionStart = startPos + newval . length - oldval . length ;
field . selectionEnd = endPos + newval . length - oldval . length ;
} else {
field . value = field . value . replace ( oldval , newval ) ;
class CodeMirrorEditor {
constructor ( editor ) {
this . editor = editor ;
}
insertPlaceholder ( value ) {
const editor = this . editor ;
const startPoint = editor . getCursor ( 'start' ) ;
const endPoint = editor . getCursor ( 'end' ) ;
editor . replaceSelection ( value ) ;
endPoint . ch = startPoint . ch + value . length ;
editor . setSelection ( startPoint , endPoint ) ;
editor . focus ( ) ;
}
replacePlaceholder ( oldVal , newVal ) {
const editor = this . editor ;
const endPoint = editor . getCursor ( 'end' ) ;
if ( editor . getSelection ( ) === oldVal ) {
editor . replaceSelection ( newVal ) ;
} else {
editor . setValue ( editor . getValue ( ) . replace ( oldVal , newVal ) ) ;
}
endPoint . ch -= oldVal . length ;
endPoint . ch += newVal . length ;
editor . setSelection ( endPoint , endPoint ) ;
editor . focus ( ) ;
}
}
export function initCompImagePaste ( $target ) {
$target . each ( function ( ) {
const dropzone = this . querySelector ( '.dropzone' ) ;
if ( ! dropzone ) {
export function initEasyMDEImagePaste ( easyMDE , $dropzone ) {
const uploadUrl = $dropzone . attr ( 'data-upload-url' ) ;
const $files = $dropzone . find ( '.files' ) ;
if ( ! uploadUrl || ! $files . length ) return ;
const uploadClipboardImage = async ( editor , e ) => {
const pastedImages = clipboardPastedImages ( e ) ;
if ( ! pastedImages || pastedImages . length === 0 ) {
return ;
}
const uploadUrl = dropzone . getAttribute ( 'data-upload-url' ) ;
const dropzoneFiles = dropzone . querySelector ( '.files' ) ;
for ( const textarea of this . querySelectorAll ( 'textarea' ) ) {
textarea . addEventListener ( 'paste' , async ( e ) => {
for ( const img of clipboardPastedImages ( e ) ) {
const name = img . name . slice ( 0 , img . name . lastIndexOf ( '.' ) ) ;
insertAtCursor ( textarea , ` ![ ${ name } ]() ` ) ;
const data = await uploadFile ( img , uploadUrl ) ;
replaceAndKeepCursor ( textarea , ` ![ ${ name } ]() ` , ` ![ ${ name } ](/attachments/ ${ data . uuid } ) ` ) ;
const input = $ ( ` <input id=" ${ data . uuid } " name="files" type="hidden"> ` ) . val ( data . uuid ) ;
dropzoneFiles . appendChild ( input [ 0 ] ) ;
}
} , false ) ;
}
} ) ;
}
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
export function initEasyMDEImagePaste ( easyMDE , dropzone , files ) {
const uploadUrl = dropzone . getAttribute ( 'data-upload-url' ) ;
easyMDE . codemirror . on ( 'paste' , async ( _ , e ) => {
for ( const img of clipboardPastedImages ( e ) ) {
for ( const img of pastedImages ) {
const name = img . name . slice ( 0 , img . name . lastIndexOf ( '.' ) ) ;
const placeholder = ` ![ ${ name } ](uploading ...) ` ;
editor . insertPlaceholder ( placeholder ) ;
const data = await uploadFile ( img , uploadUrl ) ;
const pos = easyMDE . codemirror . getCursor ( ) ;
easyMDE . codemirror . replaceRange ( ` ![ ${ name } ](/attachments/ ${ data . uuid } ) ` , pos ) ;
const input = $ ( ` <input id=" ${ data . uuid } " name="files" type="hidden"> ` ) . val ( data . uuid ) ;
files . append ( input ) ;
editor . replacePlaceholder ( placeholder , ` ![ ${ name } ](/attachments/ ${ data . uuid } ) ` ) ;
const $input = $ ( ` <input name="files" type="hidden"> ` ) . attr ( 'id' , data . uuid ) . val ( data . uuid ) ;
$files . append ( $input ) ;
}
} ;
easyMDE . codemirror . on ( 'paste' , async ( _ , e ) => {
return uploadClipboardImage ( new CodeMirrorEditor ( easyMDE . codemirror ) , e ) ;
} ) ;
$ ( easyMDE . element ) . on ( 'paste' , async ( e ) => {
return uploadClipboardImage ( new TextareaEditor ( easyMDE . element ) , e . originalEvent ) ;
} ) ;
}