Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #69 from ckeditor/t/68
Browse files Browse the repository at this point in the history
Fix: Images pasted with additional HTML content will not be handled by the upload plugin. Closes #68.
  • Loading branch information
Reinmar authored Nov 10, 2017
2 parents 6c8ef08 + b1392f7 commit 8d0644a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/imageuploadengine.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export default class ImageUploadEngine extends Plugin {

// Execute imageUpload command when image is dropped or pasted.
editor.editing.view.on( 'clipboardInput', ( evt, data ) => {
// Skip if non empty HTML data is included.
// https://github.com/ckeditor/ckeditor5-upload/issues/68
if ( isHtmlIncluded( data.dataTransfer ) ) {
return;
}

let targetModelSelection = new ModelSelection(
data.targetRanges.map( viewRange => editor.editing.mapper.toModelRange( viewRange ) )
);
Expand Down Expand Up @@ -194,3 +200,11 @@ export default class ImageUploadEngine extends Plugin {
}
}
}

// Returns true if non-empty `text/html` is included in data transfer.
//
// @param {module:clipboard/datatransfer~DataTransfer} dataTransfer
// @returns {Boolean}
export function isHtmlIncluded( dataTransfer ) {
return dataTransfer.types.indexOf( 'text/html' ) > -1 && dataTransfer.getData( 'text/html' ) !== '';
}
26 changes: 22 additions & 4 deletions tests/imageuploadengine.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe( 'ImageUploadEngine', () => {
it( 'should execute imageUpload command when image is pasted', () => {
const spy = sinon.spy( editor, 'execute' );
const fileMock = createNativeFileMock();
const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
const dataTransfer = new DataTransfer( { files: [ fileMock ], types: [ 'Files' ] } );
setModelData( doc, '<paragraph>[]foo</paragraph>' );

const targetRange = Range.createFromParentsAndOffsets( doc.getRoot(), 1, doc.getRoot(), 1 );
Expand All @@ -94,7 +94,7 @@ describe( 'ImageUploadEngine', () => {
it( 'should execute imageUpload command with an optimized position when image is pasted', () => {
const spy = sinon.spy( editor, 'execute' );
const fileMock = createNativeFileMock();
const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
const dataTransfer = new DataTransfer( { files: [ fileMock ], types: [ 'Files' ] } );
setModelData( doc, '<paragraph>[]foo</paragraph>' );

const paragraph = doc.getRoot().getChild( 0 );
Expand All @@ -115,7 +115,7 @@ describe( 'ImageUploadEngine', () => {
it( 'should execute imageUpload command when multiple files image are pasted', () => {
const spy = sinon.spy( editor, 'execute' );
const files = [ createNativeFileMock(), createNativeFileMock() ];
const dataTransfer = new DataTransfer( { files } );
const dataTransfer = new DataTransfer( { files, types: [ 'Files' ] } );
setModelData( doc, '<paragraph>[]foo</paragraph>' );

const targetRange = Range.createFromParentsAndOffsets( doc.getRoot(), 1, doc.getRoot(), 1 );
Expand Down Expand Up @@ -143,7 +143,7 @@ describe( 'ImageUploadEngine', () => {
type: 'media/mp3',
size: 1024
};
const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
const dataTransfer = new DataTransfer( { files: [ fileMock ], types: [ 'Files' ] } );

setModelData( doc, '<paragraph>foo[]</paragraph>' );

Expand All @@ -155,6 +155,24 @@ describe( 'ImageUploadEngine', () => {
sinon.assert.notCalled( spy );
} );

it( 'should not execute imageUpload command when there is non-empty HTML content pasted', () => {
const spy = sinon.spy( editor, 'execute' );
const fileMock = createNativeFileMock();
const dataTransfer = new DataTransfer( {
files: [ fileMock ],
types: [ 'Files', 'text/html' ],
getData: type => type === 'text/html' ? '<p>SomeData</p>' : ''
} );
setModelData( doc, '<paragraph>[]foo</paragraph>' );

const targetRange = Range.createFromParentsAndOffsets( doc.getRoot(), 1, doc.getRoot(), 1 );
const targetViewRange = editor.editing.mapper.toViewRange( targetRange );

viewDocument.fire( 'clipboardInput', { dataTransfer, targetRanges: [ targetViewRange ] } );

sinon.assert.notCalled( spy );
} );

it( 'should not convert image\'s uploadId attribute if is consumed already', () => {
editor.editing.modelToView.on( 'addAttribute:uploadId:image', ( evt, data, consumable ) => {
consumable.consume( data.item, eventNameToConsumableType( evt.name ) );
Expand Down

0 comments on commit 8d0644a

Please sign in to comment.