diff --git a/CHANGES.md b/CHANGES.md index f61821b9536..1c4a63b6967 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,12 @@ Fixed Issues: * [#3524](https://github.com/ckeditor/ckeditor4/issues/3524): Fixed: [Easy Image](https://ckeditor.com/cke4/addon/easyimage) plugin throws an error when any image with not supported data type is pasted into editor. * [#3552](https://github.com/ckeditor/ckeditor4/issues/3352): Fixed: Incorrect value of [`CKEDITOR.plugins.widget.repository#selected`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html#property-selected) after selecting whole editor's content. * [#3586](https://github.com/ckeditor/ckeditor4/issues/3586): Fixed: Content pasted from Excel is not correctly recognised by [Paste from Word](https://ckeditor.com/cke4/addon/pastefromword) plugin. +* [#3585](https://github.com/ckeditor/ckeditor4/issues/3585): [Firefox] Fixed: Excel content is pasted as an image. +* [#3625](https://github.com/ckeditor/ckeditor4/issues/3625): [Firefox] Fixed: PowerPoint content is pasted as an image. + +API Changes: + +* [#3634](https://github.com/ckeditor/ckeditor4/issues/3634): Added the [`CKEDITOR.plugins.clipboard.dataTransfer#getTypes()`](https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_plugins_clipboard_dataTransfer.html#method-getTypes) method. ## CKEditor 4.13 diff --git a/plugins/clipboard/plugin.js b/plugins/clipboard/plugin.js index 86867f002bb..136904a0f7b 100644 --- a/plugins/clipboard/plugin.js +++ b/plugins/clipboard/plugin.js @@ -158,7 +158,7 @@ dataTransfer = dataObj.dataTransfer; // If data empty check for image content inside data transfer. https://dev.ckeditor.com/ticket/16705 - if ( !data && dataObj.method == 'paste' && dataTransfer && dataTransfer.getFilesCount() == 1 && latestId != dataTransfer.id ) { + if ( !data && dataObj.method == 'paste' && isFileData( dataTransfer ) ) { var file = dataTransfer.getFile( 0 ); if ( CKEDITOR.tools.indexOf( supportedImageTypes, file.type ) != -1 ) { @@ -190,6 +190,20 @@ }, null, null, 1 ); } + // Only dataTransfer objects containing only file should be considered + // to image pasting (#3585, #3625). + function isFileData( dataTransfer ) { + if ( !dataTransfer || latestId === dataTransfer.id ) { + return false; + } + + var types = dataTransfer.getTypes(), + isFileOnly = types.length === 1 && types[ 0 ] === 'Files', + containsFile = dataTransfer.getFilesCount() === 1; + + return isFileOnly && containsFile; + } + editor.on( 'paste', function( evt ) { // Init `dataTransfer` if `paste` event was fired without it, so it will be always available. if ( !evt.data.dataTransfer ) { @@ -2712,6 +2726,20 @@ return true; }, + /** + * Returns all MIME types inside the clipboard data. + * + * @since 4.13.1 + * @returns {String[]} + */ + getTypes: function() { + if ( !this.$ || !this.$.types ) { + return []; + } + + return [].slice.call( this.$.types ); + }, + /** * When the content of the clipboard is pasted in Chrome, the clipboard data object has an empty `files` property, * but it is possible to get the file as `items[0].getAsFile();` (https://dev.ckeditor.com/ticket/12961). diff --git a/tests/plugins/clipboard/datatransfer.js b/tests/plugins/clipboard/datatransfer.js index e3932d4684d..3b4190df196 100644 --- a/tests/plugins/clipboard/datatransfer.js +++ b/tests/plugins/clipboard/datatransfer.js @@ -1212,5 +1212,45 @@ bender.test( { var dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); assert.areSame( '
  • foo
  • ', dataTransfer.getData( 'text/html' ) ); + }, + + // (#3634) + 'test getTypes (custom types)': function() { + if ( !CKEDITOR.plugins.clipboard.isCustomDataTypesSupported || CKEDITOR.env.edge ) { + assert.ignore(); + } + + var expectedTypes = [ 'whatever/cke', 'custom/type' ], + nativeData, + dataTransfer; + + nativeData = bender.tools.mockNativeDataTransfer(); + nativeData.setData( 'whatever/cke', 'Test' ); + nativeData.setData( 'custom/type', 'lorem ipsum' ); + + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + arrayAssert.itemsAreSame( expectedTypes, dataTransfer.getTypes() ); + }, + + // (#3634) + 'test getTypes (non-custom types)': function() { + var expectedTypes = [ 'Text' ], + nativeData, + dataTransfer; + + nativeData = bender.tools.mockNativeDataTransfer(); + nativeData.setData( 'Text', 'Test' ); + + dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); + + arrayAssert.itemsAreSame( expectedTypes, dataTransfer.getTypes() ); + }, + + // (#3634) + 'test getTypes when there is no native data transfer': function() { + var dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer(); + + arrayAssert.itemsAreSame( [], dataTransfer.getTypes() ); } } ); diff --git a/tests/plugins/clipboard/manual/_assets/pasteimagehtml.pptx b/tests/plugins/clipboard/manual/_assets/pasteimagehtml.pptx new file mode 100644 index 00000000000..50f8e67cfcd Binary files /dev/null and b/tests/plugins/clipboard/manual/_assets/pasteimagehtml.pptx differ diff --git a/tests/plugins/clipboard/manual/_assets/pasteimagehtml.xlsx b/tests/plugins/clipboard/manual/_assets/pasteimagehtml.xlsx new file mode 100644 index 00000000000..b706650cb03 Binary files /dev/null and b/tests/plugins/clipboard/manual/_assets/pasteimagehtml.xlsx differ diff --git a/tests/plugins/clipboard/manual/pasteimagehtml.html b/tests/plugins/clipboard/manual/pasteimagehtml.html new file mode 100644 index 00000000000..bd7899c7ccb --- /dev/null +++ b/tests/plugins/clipboard/manual/pasteimagehtml.html @@ -0,0 +1,7 @@ +
    +

    Paste inside me

    +
    + + diff --git a/tests/plugins/clipboard/manual/pasteimagehtml.md b/tests/plugins/clipboard/manual/pasteimagehtml.md new file mode 100644 index 00000000000..43759d1ddfa --- /dev/null +++ b/tests/plugins/clipboard/manual/pasteimagehtml.md @@ -0,0 +1,22 @@ +@bender-ui: collapsed +@bender-tags: 3585, 3625, 4.13.1, bug, clipboard +@bender-ckeditor-plugins: wysiwygarea, toolbar, undo, basicstyles, image, clipboard, sourcearea + +## Scenario +1. Copy content from document. +2. Paste into the editor. + +### Expected + +Content is pasted as text/HTML. + +### Unexpected + +Content is pasted as image. + +Documents to check: + +* [PowerPoint one](_assets/pasteimagehtml.pptx), +* [Excel one](_assets/pasteimagehtml.xlsx). + +Note: formatting is not important in this test. Only the type of pasted content is important. diff --git a/tests/plugins/clipboard/pasteimage.js b/tests/plugins/clipboard/pasteimage.js index 29a12e39070..6d1e201be89 100644 --- a/tests/plugins/clipboard/pasteimage.js +++ b/tests/plugins/clipboard/pasteimage.js @@ -47,7 +47,7 @@ } )(); // Mock paste file from clipboard. - function mockPasteFile( editor, type ) { + function mockPasteFile( editor, type, additionalData ) { var nativeData = bender.tools.mockNativeDataTransfer(), dataTransfer = new CKEDITOR.plugins.clipboard.dataTransfer( nativeData ); @@ -55,6 +55,13 @@ name: 'mock.file', type: type } ); + nativeData.types.push( 'Files' ); + + if ( additionalData ) { + CKEDITOR.tools.array.forEach( additionalData, function( data ) { + nativeData.setData( data.type, data.data ); + } ); + } dataTransfer.cacheData(); @@ -137,7 +144,18 @@ '

    Paste image here: ^@

    ' ); }, - assertPaste: function( type, expected ) { + // (#3585, #3625) + 'test pasting image alongside other content': function() { + FileReader.setFileMockType( 'image/png' ); + FileReader.setReadResult( 'load' ); + + bender.tools.selection.setWithHtml( this.editor, '

    {}

    ' ); + this.assertPaste( 'image/png', '

    whateva^@

    ', [ + { type: 'text/html', data: 'whateva' } + ] ); + }, + + assertPaste: function( type, expected, additionalData ) { this.editor.once( 'paste', function() { resume( function() { assert.isInnerHtmlMatching( expected, bender.tools.selection.getWithHtml( this.editor ), { @@ -149,7 +167,7 @@ } ); }, this, null, 9999 ); - mockPasteFile( this.editor, type ); + mockPasteFile( this.editor, type, additionalData ); wait(); }