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

Commit 8d0644a

Browse files
authored
Merge pull request #69 from ckeditor/t/68
Fix: Images pasted with additional HTML content will not be handled by the upload plugin. Closes #68.
2 parents 6c8ef08 + b1392f7 commit 8d0644a

File tree

2 files changed

+36
-4
lines changed

2 files changed

+36
-4
lines changed

src/imageuploadengine.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ export default class ImageUploadEngine extends Plugin {
4646

4747
// Execute imageUpload command when image is dropped or pasted.
4848
editor.editing.view.on( 'clipboardInput', ( evt, data ) => {
49+
// Skip if non empty HTML data is included.
50+
// https://github.com/ckeditor/ckeditor5-upload/issues/68
51+
if ( isHtmlIncluded( data.dataTransfer ) ) {
52+
return;
53+
}
54+
4955
let targetModelSelection = new ModelSelection(
5056
data.targetRanges.map( viewRange => editor.editing.mapper.toModelRange( viewRange ) )
5157
);
@@ -194,3 +200,11 @@ export default class ImageUploadEngine extends Plugin {
194200
}
195201
}
196202
}
203+
204+
// Returns true if non-empty `text/html` is included in data transfer.
205+
//
206+
// @param {module:clipboard/datatransfer~DataTransfer} dataTransfer
207+
// @returns {Boolean}
208+
export function isHtmlIncluded( dataTransfer ) {
209+
return dataTransfer.types.indexOf( 'text/html' ) > -1 && dataTransfer.getData( 'text/html' ) !== '';
210+
}

tests/imageuploadengine.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe( 'ImageUploadEngine', () => {
7474
it( 'should execute imageUpload command when image is pasted', () => {
7575
const spy = sinon.spy( editor, 'execute' );
7676
const fileMock = createNativeFileMock();
77-
const dataTransfer = new DataTransfer( { files: [ fileMock ] } );
77+
const dataTransfer = new DataTransfer( { files: [ fileMock ], types: [ 'Files' ] } );
7878
setModelData( doc, '<paragraph>[]foo</paragraph>' );
7979

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

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

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

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

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

158+
it( 'should not execute imageUpload command when there is non-empty HTML content pasted', () => {
159+
const spy = sinon.spy( editor, 'execute' );
160+
const fileMock = createNativeFileMock();
161+
const dataTransfer = new DataTransfer( {
162+
files: [ fileMock ],
163+
types: [ 'Files', 'text/html' ],
164+
getData: type => type === 'text/html' ? '<p>SomeData</p>' : ''
165+
} );
166+
setModelData( doc, '<paragraph>[]foo</paragraph>' );
167+
168+
const targetRange = Range.createFromParentsAndOffsets( doc.getRoot(), 1, doc.getRoot(), 1 );
169+
const targetViewRange = editor.editing.mapper.toViewRange( targetRange );
170+
171+
viewDocument.fire( 'clipboardInput', { dataTransfer, targetRanges: [ targetViewRange ] } );
172+
173+
sinon.assert.notCalled( spy );
174+
} );
175+
158176
it( 'should not convert image\'s uploadId attribute if is consumed already', () => {
159177
editor.editing.modelToView.on( 'addAttribute:uploadId:image', ( evt, data, consumable ) => {
160178
consumable.consume( data.item, eventNameToConsumableType( evt.name ) );

0 commit comments

Comments
 (0)