diff --git a/src/imageupload/imageuploadediting.js b/src/imageupload/imageuploadediting.js index 73949e0e..20fa317f 100644 --- a/src/imageupload/imageuploadediting.js +++ b/src/imageupload/imageuploadediting.js @@ -10,10 +10,11 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository'; import Notification from '@ckeditor/ckeditor5-ui/src/notification/notification'; +import UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter'; import { upcastAttributeToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters'; import ImageUploadCommand from '../../src/imageupload/imageuploadcommand'; -import { isImageType, isLocalImage, wrapImageToFetch } from '../../src/imageupload/utils'; +import { isImageType, isLocalImage, fetchLocalImage } from '../../src/imageupload/utils'; /** * The editing part of the image upload feature. It registers the `'imageUpload'` command. @@ -98,11 +99,9 @@ export default class ImageUploadEditing extends Plugin { // inserted into the content. Then, those images are uploaded once they appear in the model // (see Document#change listener below). this.listenTo( editor.plugins.get( 'Clipboard' ), 'inputTransformation', ( evt, data ) => { - const view = editor.editing.view; - - const fetchableImages = Array.from( view.createRangeIn( data.content ) ) + const fetchableImages = Array.from( editor.editing.view.createRangeIn( data.content ) ) .filter( value => isLocalImage( value.item ) && !value.item.getAttribute( 'uploadProcessed' ) ) - .map( ( value, index ) => wrapImageToFetch( value.item, index ) ); + .map( value => fetchLocalImage( value.item ) ); if ( !fetchableImages.length ) { return; @@ -111,25 +110,21 @@ export default class ImageUploadEditing extends Plugin { evt.stop(); Promise.all( fetchableImages ).then( items => { + const writer = new UpcastWriter(); + for ( const item of items ) { if ( !item.file ) { // Failed to fetch image or create a file instance, remove image element. - view.change( writer => { - writer.remove( item.image ); - } ); + writer.remove( item.image ); } else { + // Set attribute marking the image as processed. + writer.setAttribute( 'uploadProcessed', true, item.image ); + const loader = fileRepository.createLoader( item.file ); if ( loader ) { - view.change( writer => { - writer.setAttribute( 'src', '', item.image ); - writer.setAttribute( 'uploadId', loader.id, item.image ); - } ); - } else { - view.change( writer => { - // Set attribute so the image will not be processed 2nd time. - writer.setAttribute( 'uploadProcessed', true, item.image ); - } ); + writer.setAttribute( 'src', '', item.image ); + writer.setAttribute( 'uploadId', loader.id, item.image ); } } } diff --git a/src/imageupload/utils.js b/src/imageupload/utils.js index fe5d0332..fc61910c 100644 --- a/src/imageupload/utils.js +++ b/src/imageupload/utils.js @@ -25,12 +25,11 @@ export function isImageType( file ) { * Creates a promise which fetches the image local source (base64 or blob) and returns as a `File` object. * * @param {module:engine/view/element~Element} image Image which source to fetch. - * @param {Number} index Image index used as image name suffix. * @returns {Promise} A promise which resolves when image source is fetched and converted to `File` instance. * It resolves with object holding initial image element (as `image`) and its file source (as `file`). If * the `file` attribute is null, it means fetching failed. */ -export function wrapImageToFetch( image, index ) { +export function fetchLocalImage( image ) { return new Promise( resolve => { // Fetch works asynchronously and so does not block browser UI when processing data. fetch( image.getAttribute( 'src' ) ) @@ -38,7 +37,7 @@ export function wrapImageToFetch( image, index ) { .then( blob => { const mimeType = getImageMimeType( blob, image.getAttribute( 'src' ) ); const ext = mimeType.replace( 'image/', '' ); - const filename = `${ Number( new Date() ) }-image${ index }.${ ext }`; + const filename = `image.${ ext }`; const file = createFileFromBlob( blob, filename, mimeType ); resolve( { image, file } ); @@ -57,14 +56,12 @@ export function wrapImageToFetch( image, index ) { * @returns {Boolean} */ export function isLocalImage( node ) { - return node.is( 'element', 'img' ) && node.getAttribute( 'src' ) && - ( node.getAttribute( 'src' ).match( /data:image\/\w+;base64,/g ) || - if ( !node.is( 'element', 'img' ) || node.getAttribute( 'src' ) ) { - return false; - } - - return ( node.getAttribute( 'src' ).match( /data:image\/\w+;base64,/g ) || - node.getAttribute( 'src' ).match( /blob:/g ) ); + if ( !node.is( 'element', 'img' ) || !node.getAttribute( 'src' ) ) { + return false; + } + + return node.getAttribute( 'src' ).match( /^data:image\/\w+;base64,/g ) || + node.getAttribute( 'src' ).match( /^blob:/g ); } // Extracts image type based on its blob representation or its source.