diff --git a/src/imageuploadcommand.js b/src/imageuploadcommand.js
index 988e6fe..72f4d08 100644
--- a/src/imageuploadcommand.js
+++ b/src/imageuploadcommand.js
@@ -44,20 +44,7 @@ export default class ImageUploadCommand extends Command {
}
doc.enqueueChanges( () => {
- let insertPosition;
- const selectedElement = selection.getSelectedElement();
-
- // If selected element is placed directly in root - put image after it.
- if ( selectedElement && selectedElement.parent.is( 'rootElement' ) ) {
- insertPosition = ModelPosition.createAfter( selectedElement );
- } else {
- // If selection is inside some block - put image before it.
- const firstBlock = doc.selection.getSelectedBlocks().next().value;
-
- if ( firstBlock ) {
- insertPosition = ModelPosition.createBefore( firstBlock );
- }
- }
+ const insertPosition = getInsertionPosition( doc );
// No position to insert.
if ( !insertPosition ) {
@@ -77,3 +64,33 @@ export default class ImageUploadCommand extends Command {
} );
}
}
+
+/**
+ * Returns correct image insertion position.
+ *
+ * @param {module:engine/model/document~Document} doc
+ * @returns {module:engine/model/position~Position|undefined}
+ */
+function getInsertionPosition( doc ) {
+ const selection = doc.selection;
+ const selectedElement = selection.getSelectedElement();
+
+ // If selected element is placed directly in root - return position after that element.
+ if ( selectedElement && selectedElement.parent.is( 'rootElement' ) ) {
+ return ModelPosition.createAfter( selectedElement );
+ }
+
+ const firstBlock = doc.selection.getSelectedBlocks().next().value;
+
+ if ( firstBlock ) {
+ const positionAfter = ModelPosition.createAfter( firstBlock );
+
+ // If selection is at the end of the block - return position after the block.
+ if ( selection.focus.isTouching( positionAfter ) ) {
+ return positionAfter;
+ }
+
+ // Otherwise return position before the block.
+ return ModelPosition.createBefore( firstBlock );
+ }
+}
diff --git a/tests/imageuploadcommand.js b/tests/imageuploadcommand.js
index cd5aaf1..02c5fda 100644
--- a/tests/imageuploadcommand.js
+++ b/tests/imageuploadcommand.js
@@ -39,11 +39,31 @@ describe( 'ImageUploadCommand', () => {
describe( '_doExecute', () => {
it( 'should insert image', () => {
+ const file = createNativeFileMock();
+ setModelData( document, '[]foo' );
+
+ command._doExecute( { file } );
+
+ const id = fileRepository.getLoader( file ).id;
+ expect( getModelData( document ) ).to.equal( `[]foo` );
+ } );
+
+ it( 'should insert image after block if selection is at its end', () => {
const file = createNativeFileMock();
setModelData( document, 'foo[]' );
command._doExecute( { file } );
+ const id = fileRepository.getLoader( file ).id;
+ expect( getModelData( document ) ).to.equal( `foo[]` );
+ } );
+
+ it( 'should insert image before block if selection is in the middle', () => {
+ const file = createNativeFileMock();
+ setModelData( document, 'f{}oo' );
+
+ command._doExecute( { file } );
+
const id = fileRepository.getLoader( file ).id;
expect( getModelData( document ) ).to.equal( `[]foo` );
} );
@@ -87,7 +107,7 @@ describe( 'ImageUploadCommand', () => {
const file = createNativeFileMock();
const spy = sinon.spy( batch, 'insert' );
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
command._doExecute( { batch, file } );
const id = fileRepository.getLoader( file ).id;
diff --git a/tests/imageuploadengine.js b/tests/imageuploadengine.js
index 751f87e..1693eda 100644
--- a/tests/imageuploadengine.js
+++ b/tests/imageuploadengine.js
@@ -61,7 +61,7 @@ describe( 'ImageUploadEngine', () => {
const spy = sinon.spy( editor, 'execute' );
const fileMock = createNativeFileMock();
const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
- setModelData( document, 'foo bar baz[]' );
+ setModelData( document, '[]foo bar baz' );
viewDocument.fire( 'clipboardInput', { dataTransfer } );
diff --git a/tests/imageuploadprogress.js b/tests/imageuploadprogress.js
index 9a700fc..22f85e3 100644
--- a/tests/imageuploadprogress.js
+++ b/tests/imageuploadprogress.js
@@ -53,7 +53,7 @@ describe( 'ImageUploadProgress', () => {
} );
it( 'should convert image\'s "reading" uploadStatus attribute', () => {
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
expect( getViewData( viewDocument ) ).to.equal(
@@ -64,7 +64,7 @@ describe( 'ImageUploadProgress', () => {
} );
it( 'should convert image\'s "uploading" uploadStatus attribute', ( done ) => {
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
document.once( 'changesDone', () => {
@@ -82,7 +82,7 @@ describe( 'ImageUploadProgress', () => {
} );
it( 'should update progressbar width on progress', ( done ) => {
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
document.once( 'changesDone', () => {
@@ -102,7 +102,7 @@ describe( 'ImageUploadProgress', () => {
} );
it( 'should convert image\'s "complete" uploadStatus attribute', ( done ) => {
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
document.once( 'changesDone', () => {
@@ -126,7 +126,7 @@ describe( 'ImageUploadProgress', () => {
const uploadProgress = editor.plugins.get( ImageUploadProgress );
uploadProgress.placeholder = base64Sample;
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
expect( getViewData( viewDocument ) ).to.equal(
@@ -141,7 +141,7 @@ describe( 'ImageUploadProgress', () => {
consumable.consume( data.item, eventNameToConsumableType( evt.name ) );
}, { priority: 'highest' } );
- setModelData( document, 'foo[]' );
+ setModelData( document, '[]foo' );
editor.execute( 'imageUpload', { file: createNativeFileMock() } );
expect( getViewData( viewDocument ) ).to.equal(