diff --git a/packages/ckeditor5-clipboard/src/clipboardpipeline.ts b/packages/ckeditor5-clipboard/src/clipboardpipeline.ts index 0192c323e7e..18d1e18ed9b 100644 --- a/packages/ckeditor5-clipboard/src/clipboardpipeline.ts +++ b/packages/ckeditor5-clipboard/src/clipboardpipeline.ts @@ -224,15 +224,17 @@ export default class ClipboardPipeline extends Plugin { if ( data.content ) { content = data.content; } else { - let contentData = ''; - - if ( dataTransfer.getData( 'text/html' ) ) { - contentData = normalizeClipboardHtml( dataTransfer.getData( 'text/html' ) ); - } else if ( dataTransfer.getData( 'text/plain' ) ) { - contentData = plainTextToHtml( dataTransfer.getData( 'text/plain' ) ); + const htmlOrView = this.fire( 'inputHtmlNormalization', { + html: dataTransfer.getData( 'text/html' ), + dataTransfer, + method: data.method + } ) || ''; + + if ( typeof htmlOrView === 'string' ) { + content = this.editor.data.htmlProcessor.toView( htmlOrView ); + } else { + content = htmlOrView; } - - content = this.editor.data.htmlProcessor.toView( contentData ); } const eventInfo = new EventInfo( this, 'inputTransformation' ); @@ -287,6 +289,18 @@ export default class ClipboardPipeline extends Plugin { this.listenTo( this, 'contentInsertion', ( evt, data ) => { data.resultRange = clipboardMarkersUtils._pasteFragmentWithMarkers( data.content ); }, { priority: 'low' } ); + + this.listenTo( this, 'inputHtmlNormalization', ( evt, { dataTransfer } ) => { + if ( evt.return ) { + return; + } + + if ( dataTransfer.getData( 'text/html' ) ) { + evt.return = normalizeClipboardHtml( dataTransfer.getData( 'text/html' ) ); + } else if ( dataTransfer.getData( 'text/plain' ) ) { + evt.return = plainTextToHtml( dataTransfer.getData( 'text/plain' ) ); + } + }, { priority: 'low' } ); } /** @@ -391,6 +405,41 @@ export interface ClipboardInputTransformationData { method: 'paste' | 'drop'; } +/** + * Fired when the HTML content from the clipboard is being normalized, just before it is processed by the input pipeline and + * converted to a view document fragment. + * + * It is a part of the {@glink framework/deep-dive/clipboard#input-pipeline clipboard input pipeline}. + * + * **Note**: Your should not stop this event if you want to change the input data. You should modify the `return` property instead. + */ +export type ClipboardInputHTMLNormalizationEvent = { + name: 'inputHtmlNormalization'; + args: [ data: ClipboardInputHTMLNormalizationData ]; + return: string | ViewDocumentFragment; +}; + +/** + * The data of 'inputHtmlNormalization' event. + */ +export interface ClipboardInputHTMLNormalizationData { + + /** + * The data transfer instance. + */ + dataTransfer: DataTransfer; + + /** + * The HTML content from the clipboard. + */ + html: string; + + /** + * Whether the event was triggered by a paste or a drop operation. + */ + method: 'paste' | 'drop'; +} + /** * Fired with the `content`, `dataTransfer`, `method`, and `targetRanges` properties: * diff --git a/packages/ckeditor5-clipboard/src/index.ts b/packages/ckeditor5-clipboard/src/index.ts index caf5c93e1c5..bec51ca0ae7 100644 --- a/packages/ckeditor5-clipboard/src/index.ts +++ b/packages/ckeditor5-clipboard/src/index.ts @@ -12,6 +12,7 @@ export { default as ClipboardPipeline, type ClipboardContentInsertionEvent, type ClipboardContentInsertionData, + type ClipboardInputHTMLNormalizationEvent, type ClipboardInputTransformationEvent, type ClipboardInputTransformationData, type ClipboardOutputTransformationEvent, diff --git a/packages/ckeditor5-clipboard/tests/clipboardpipeline.js b/packages/ckeditor5-clipboard/tests/clipboardpipeline.js index 9d9153872eb..e43f9abdc16 100644 --- a/packages/ckeditor5-clipboard/tests/clipboardpipeline.js +++ b/packages/ckeditor5-clipboard/tests/clipboardpipeline.js @@ -462,6 +462,110 @@ describe( 'ClipboardPipeline feature', () => { expect( spy.callCount ).to.equal( 1 ); } ); + describe( 'html normalization', () => { + it( 'should allow chaining html normalization', () => { + const dataTransferMock = createDataTransfer( { 'text/html': '

foo

', 'text/plain': 'foo' } ); + const preventDefaultSpy = sinon.spy(); + + clipboardPlugin.on( 'inputHtmlNormalization', ( evt, data ) => { + evt.return = data.html.replace( 'foo', 'bar' ); + }, { priority: 'high' } ); + + clipboardPlugin.on( 'inputTransformation', ( evt, data ) => { + expect( stringifyView( data.content ) ).to.equal( '

bar

' ); + } ); + + viewDocument.fire( 'paste', { + stopPropagation: () => {}, + dataTransfer: dataTransferMock, + preventDefault: preventDefaultSpy + } ); + } ); + + it( 'should allow chaining html normalization (pick content from data transfer)', () => { + const dataTransferMock = createDataTransfer( { 'text/html': '

foo

', 'text/plain': 'foo' } ); + const preventDefaultSpy = sinon.spy(); + + clipboardPlugin.on( 'inputHtmlNormalization', ( evt, { dataTransfer } ) => { + evt.return = dataTransfer.getData( 'text/html' ).replace( 'foo', 'bar' ); + }, { priority: 'high' } ); + + clipboardPlugin.on( 'inputTransformation', ( evt, data ) => { + expect( stringifyView( data.content ) ).to.equal( '

bar

' ); + } ); + + viewDocument.fire( 'paste', { + stopPropagation: () => {}, + dataTransfer: dataTransferMock, + preventDefault: preventDefaultSpy + } ); + } ); + + it( 'should allow stopping html normalization chain', () => { + const dataTransferMock = createDataTransfer( { 'text/html': '

foo

', 'text/plain': 'foo' } ); + const preventDefaultSpy = sinon.spy(); + + clipboardPlugin.on( 'inputHtmlNormalization', ( evt, { html } ) => { + evt.return = html.replace( 'foo', 'bar' ); + evt.stop(); + }, { priority: 'high' } ); + + clipboardPlugin.on( 'inputHtmlNormalization', evt => { + // This handler should not be called + evt.return = '

baz

'; + }, { priority: 'normal' } ); + + clipboardPlugin.on( 'inputTransformation', ( _, data ) => { + expect( stringifyView( data.content ) ).to.equal( '

bar

' ); + } ); + + viewDocument.fire( 'paste', { + stopPropagation: () => {}, + dataTransfer: dataTransferMock, + preventDefault: preventDefaultSpy + } ); + } ); + + it( 'should call default normalizer if no custom handlers provided HTML content', () => { + const dataTransferMock = createDataTransfer( { 'text/html': '

foo

', 'text/plain': 'foo' } ); + const preventDefaultSpy = sinon.spy(); + + clipboardPlugin.on( 'inputHtmlNormalization', () => { + // This handler does not provide any content + }, { priority: 'high' } ); + + clipboardPlugin.on( 'inputTransformation', ( _, data ) => { + expect( stringifyView( data.content ) ).to.equal( '

foo

' ); + } ); + + viewDocument.fire( 'paste', { + stopPropagation: () => {}, + dataTransfer: dataTransferMock, + preventDefault: preventDefaultSpy + } ); + } ); + + it( 'should be possible to return view document fragment from html normalization', () => { + const dataTransferMock = createDataTransfer( { 'text/html': '

foo

', 'text/plain': 'foo' } ); + const preventDefaultSpy = sinon.spy(); + + clipboardPlugin.on( 'inputHtmlNormalization', ( evt, { html } ) => { + evt.return = parseView( html ); + }, { priority: 'high' } ); + + clipboardPlugin.on( 'inputTransformation', ( _, data ) => { + expect( data.content ).not.be.instanceOf( String ); + expect( stringifyView( data.content ) ).to.equal( '

foo

' ); + } ); + + viewDocument.fire( 'paste', { + stopPropagation: () => {}, + dataTransfer: dataTransferMock, + preventDefault: preventDefaultSpy + } ); + } ); + } ); + function createDataTransfer( data ) { return { getData( type ) { diff --git a/packages/ckeditor5-paste-from-office/src/index.ts b/packages/ckeditor5-paste-from-office/src/index.ts index c096e3afb92..f069a91dbfb 100644 --- a/packages/ckeditor5-paste-from-office/src/index.ts +++ b/packages/ckeditor5-paste-from-office/src/index.ts @@ -8,7 +8,7 @@ */ export { default as PasteFromOffice } from './pastefromoffice.js'; -export type { Normalizer, NormalizerData } from './normalizer.js'; +export type { Normalizer } from './normalizer.js'; export { default as MSWordNormalizer } from './normalizers/mswordnormalizer.js'; export { parseHtml } from './filters/parse.js'; diff --git a/packages/ckeditor5-paste-from-office/src/normalizer.ts b/packages/ckeditor5-paste-from-office/src/normalizer.ts index 9de0c4bf9ad..2c69587e934 100644 --- a/packages/ckeditor5-paste-from-office/src/normalizer.ts +++ b/packages/ckeditor5-paste-from-office/src/normalizer.ts @@ -7,8 +7,7 @@ * @module paste-from-office/normalizer */ -import type { ClipboardInputTransformationData } from 'ckeditor5/src/clipboard.js'; -import type { ParseHtmlResult } from './filters/parse.js'; +import type { DataTransfer, ViewDocumentFragment } from 'ckeditor5/src/engine.js'; /** * Interface defining a content transformation pasted from an external editor. @@ -27,10 +26,5 @@ export interface Normalizer { /** * Executes the normalization of a given data. */ - execute( data: NormalizerData ): void; -} - -export interface NormalizerData extends ClipboardInputTransformationData { - _isTransformedWithPasteFromOffice?: boolean; - _parsedData: ParseHtmlResult; + execute( data: DataTransfer ): ViewDocumentFragment; } diff --git a/packages/ckeditor5-paste-from-office/src/normalizers/googledocsnormalizer.ts b/packages/ckeditor5-paste-from-office/src/normalizers/googledocsnormalizer.ts index 12968fbab1a..1ecb6a4abc1 100644 --- a/packages/ckeditor5-paste-from-office/src/normalizers/googledocsnormalizer.ts +++ b/packages/ckeditor5-paste-from-office/src/normalizers/googledocsnormalizer.ts @@ -7,12 +7,18 @@ * @module paste-from-office/normalizers/googledocsnormalizer */ -import { UpcastWriter, type ViewDocument } from 'ckeditor5/src/engine.js'; +import { + UpcastWriter, + type ViewDocument, + type DataTransfer, + type ViewDocumentFragment +} from 'ckeditor5/src/engine.js'; import removeBoldWrapper from '../filters/removeboldwrapper.js'; import transformBlockBrsToParagraphs from '../filters/br.js'; import { unwrapParagraphInListItem } from '../filters/list.js'; -import type { Normalizer, NormalizerData } from '../normalizer.js'; +import type { Normalizer } from '../normalizer.js'; +import { parseHtml } from '../filters/parse.js'; const googleDocsMatch = /id=("|')docs-internal-guid-[-0-9a-f]+("|')/i; @@ -41,14 +47,17 @@ export default class GoogleDocsNormalizer implements Normalizer { /** * @inheritDoc */ - public execute( data: NormalizerData ): void { + public execute( dataTransfer: DataTransfer ): ViewDocumentFragment { const writer = new UpcastWriter( this.document ); - const { body: documentFragment } = data._parsedData; + const { body: documentFragment } = parseHtml( + dataTransfer.getData( 'text/html' ), + this.document.stylesProcessor + ); removeBoldWrapper( documentFragment, writer ); unwrapParagraphInListItem( documentFragment, writer ); transformBlockBrsToParagraphs( documentFragment, writer ); - data.content = documentFragment; + return documentFragment; } } diff --git a/packages/ckeditor5-paste-from-office/src/normalizers/googlesheetsnormalizer.ts b/packages/ckeditor5-paste-from-office/src/normalizers/googlesheetsnormalizer.ts index a5910eea033..e906db83d4d 100644 --- a/packages/ckeditor5-paste-from-office/src/normalizers/googlesheetsnormalizer.ts +++ b/packages/ckeditor5-paste-from-office/src/normalizers/googlesheetsnormalizer.ts @@ -7,13 +7,19 @@ * @module paste-from-office/normalizers/googlesheetsnormalizer */ -import { UpcastWriter, type ViewDocument } from 'ckeditor5/src/engine.js'; +import { + UpcastWriter, + type ViewDocument, + type DataTransfer, + type ViewDocumentFragment +} from 'ckeditor5/src/engine.js'; import removeXmlns from '../filters/removexmlns.js'; import removeGoogleSheetsTag from '../filters/removegooglesheetstag.js'; import removeInvalidTableWidth from '../filters/removeinvalidtablewidth.js'; import removeStyleBlock from '../filters/removestyleblock.js'; -import type { Normalizer, NormalizerData } from '../normalizer.js'; +import type { Normalizer } from '../normalizer.js'; +import { parseHtml } from '../filters/parse.js'; const googleSheetsMatch = //i; const msWordMatch2 = /xmlns:o="urn:schemas-microsoft-com/i; @@ -45,15 +51,18 @@ export default class MSWordNormalizer implements Normalizer { /** * @inheritDoc */ - public execute( data: NormalizerData ): void { + public execute( dataTransfer: DataTransfer ): ViewDocumentFragment { const writer = new UpcastWriter( this.document ); - const { body: documentFragment, stylesString } = data._parsedData; + const { body: documentFragment, stylesString } = parseHtml( + dataTransfer.getData( 'text/html' ), + this.document.stylesProcessor + ); transformBookmarks( documentFragment, writer ); transformListItemLikeElementsIntoLists( documentFragment, stylesString, this.hasMultiLevelListPlugin ); - replaceImagesSourceWithBase64( documentFragment, data.dataTransfer.getData( 'text/rtf' ) ); + replaceImagesSourceWithBase64( documentFragment, dataTransfer.getData( 'text/rtf' ) ); removeMSAttributes( documentFragment ); - data.content = documentFragment; + return documentFragment; } } diff --git a/packages/ckeditor5-paste-from-office/src/pastefromoffice.ts b/packages/ckeditor5-paste-from-office/src/pastefromoffice.ts index 01229356f30..58bd5b68b83 100644 --- a/packages/ckeditor5-paste-from-office/src/pastefromoffice.ts +++ b/packages/ckeditor5-paste-from-office/src/pastefromoffice.ts @@ -8,15 +8,15 @@ */ import { Plugin } from 'ckeditor5/src/core.js'; +import { ViewDocumentFragment } from 'ckeditor5/src/engine.js'; -import { ClipboardPipeline } from 'ckeditor5/src/clipboard.js'; +import { type ClipboardInputHTMLNormalizationEvent, ClipboardPipeline } from 'ckeditor5/src/clipboard.js'; import MSWordNormalizer from './normalizers/mswordnormalizer.js'; import GoogleDocsNormalizer from './normalizers/googledocsnormalizer.js'; import GoogleSheetsNormalizer from './normalizers/googlesheetsnormalizer.js'; -import { parseHtml } from './filters/parse.js'; -import type { Normalizer, NormalizerData } from './normalizer.js'; +import type { Normalizer } from './normalizer.js'; /** * The Paste from Office plugin. @@ -67,33 +67,35 @@ export default class PasteFromOffice extends Plugin { normalizers.push( new GoogleDocsNormalizer( viewDocument ) ); normalizers.push( new GoogleSheetsNormalizer( viewDocument ) ); - clipboardPipeline.on( - 'inputTransformation', - ( evt, data: NormalizerData ) => { - if ( data._isTransformedWithPasteFromOffice ) { - return; - } + clipboardPipeline.on( 'inputHtmlNormalization', ( evt, data ) => { + if ( evt.return instanceof ViewDocumentFragment && evt.return.isTransformedWithPasteFromOffice ) { + return; + } - const codeBlock = editor.model.document.selection.getFirstPosition()!.parent; + const codeBlock = editor.model.document.selection.getFirstPosition()!.parent; - if ( codeBlock.is( 'element', 'codeBlock' ) ) { - return; - } + if ( codeBlock.is( 'element', 'codeBlock' ) ) { + return; + } - const htmlString = data.dataTransfer.getData( 'text/html' ); - const activeNormalizer = normalizers.find( normalizer => normalizer.isActive( htmlString ) ); + const activeNormalizer = normalizers.find( normalizer => normalizer.isActive( data.html ) ); - if ( activeNormalizer ) { - if ( !data._parsedData ) { - data._parsedData = parseHtml( htmlString, viewDocument.stylesProcessor ); - } + if ( activeNormalizer ) { + const result = activeNormalizer.execute( data.dataTransfer ); - activeNormalizer.execute( data ); - - data._isTransformedWithPasteFromOffice = true; - } - }, - { priority: 'high' } - ); + evt.return = result; + evt.return.isTransformedWithPasteFromOffice = true; + } + } ); } } + +type ClipboardInputHTMLPofNormalizationEvent = + Omit + & { + return: + | string + | ViewDocumentFragment & { + isTransformedWithPasteFromOffice?: boolean; + }; + }; diff --git a/packages/ckeditor5-paste-from-office/tests/_utils/utils.js b/packages/ckeditor5-paste-from-office/tests/_utils/utils.js index e5e20e29b50..6cba99c7630 100644 --- a/packages/ckeditor5-paste-from-office/tests/_utils/utils.js +++ b/packages/ckeditor5-paste-from-office/tests/_utils/utils.js @@ -7,18 +7,11 @@ import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor.js'; import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor.js'; -import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document.js'; -import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor.js'; -import normalizeClipboardData from '@ckeditor/ckeditor5-clipboard/src/utils/normalizeclipboarddata.js'; import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml.js'; import { setData, stringify as stringifyModel } from '@ckeditor/ckeditor5-engine/src/dev-utils/model.js'; import { stringify as stringifyView } from '@ckeditor/ckeditor5-engine/src/dev-utils/view.js'; -import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap.js'; - -const htmlDataProcessor = new HtmlDataProcessor( new ViewDocument( new StylesProcessor() ) ); - /** * Mocks dataTransfer object which can be used for simulating paste. * @@ -174,16 +167,15 @@ function generateNormalizationTests( title, fixtures, editorConfig, skip, only ) testRunner( name, () => { // Simulate data from Clipboard event const clipboardPlugin = editor.plugins.get( 'ClipboardPipeline' ); - const content = htmlDataProcessor.toView( normalizeClipboardData( fixtures.input[ name ] ) ); const dataTransfer = createDataTransfer( { 'text/html': fixtures.input[ name ], 'text/rtf': fixtures.inputRtf && fixtures.inputRtf[ name ] } ); - // data.content might be completely overwritten with a new object, so we need obtain final result for comparison. - const data = { content, dataTransfer }; - clipboardPlugin.fire( 'inputTransformation', data ); - const transformedContent = data.content; + const transformedContent = clipboardPlugin.fire( 'inputHtmlNormalization', { + html: dataTransfer.getData( 'text/html' ), + dataTransfer + } ); expectNormalized( transformedContent, diff --git a/packages/ckeditor5-paste-from-office/tests/pastefromoffice.js b/packages/ckeditor5-paste-from-office/tests/pastefromoffice.js index 30bedd6719d..40d087e5e4f 100644 --- a/packages/ckeditor5-paste-from-office/tests/pastefromoffice.js +++ b/packages/ckeditor5-paste-from-office/tests/pastefromoffice.js @@ -18,6 +18,8 @@ import CodeBlockEditing from '@ckeditor/ckeditor5-code-block/src/codeblockeditin import { setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model.js'; import { priorities } from '@ckeditor/ckeditor5-utils'; import { DomConverter } from '@ckeditor/ckeditor5-engine'; +import MSWordNormalizer from '../src/normalizers/mswordnormalizer.js'; +import GoogleDocsNormalizer from '../src/normalizers/googledocsnormalizer.js'; /* global document, DOMParser */ @@ -124,17 +126,16 @@ describe( 'PasteFromOffice', () => { } ); function checkCorrectData( inputString ) { - const data = setUpData( inputString ); - const getDataSpy = sinon.spy( data.dataTransfer, 'getData' ); + const dataTransfer = createHTMLDataTransfer( inputString ); + const getDataSpy = sinon.spy( dataTransfer, 'getData' ); - clipboard.fire( 'inputTransformation', data ); + const result = clipboard.fire( 'inputHtmlNormalization', { + dataTransfer, + html: dataTransfer.getData( 'text/html' ) + } ); - expect( data._isTransformedWithPasteFromOffice ).to.be.true; - expect( data._parsedData ).to.have.property( 'body' ); - expect( data._parsedData ).to.have.property( 'bodyString' ); - expect( data._parsedData ).to.have.property( 'styles' ); - expect( data._parsedData ).to.have.property( 'stylesString' ); - expect( data._parsedData.body ).to.be.instanceOf( ViewDocumentFragment ); + expect( result.isTransformedWithPasteFromOffice ).to.be.true; + expect( result ).to.be.instanceOf( ViewDocumentFragment ); sinon.assert.called( getDataSpy ); } @@ -164,25 +165,29 @@ describe( 'PasteFromOffice', () => { it( 'should process data for codeBlock', () => { setModelData( editor.model, '[]' ); - const data = setUpData( '

' ); - const getDataSpy = sinon.spy( data.dataTransfer, 'getData' ); + const inputString = '

'; + const dataTransfer = createHTMLDataTransfer( inputString ); - clipboard.fire( 'inputTransformation', data ); + const result = clipboard.fire( 'inputHtmlNormalization', { + dataTransfer, + html: dataTransfer.getData( 'text/html' ) + } ); - expect( data._isTransformedWithPasteFromOffice ).to.be.undefined; - expect( data._parsedData ).to.be.undefined; - - sinon.assert.notCalled( getDataSpy ); + expect( result.isTransformedWithPasteFromOffice ).to.be.undefined; + expect( result ).to.be.equal( inputString ); } ); function checkNotProcessedData( inputString ) { - const data = setUpData( inputString ); - const getDataSpy = sinon.spy( data.dataTransfer, 'getData' ); + const dataTransfer = createHTMLDataTransfer( inputString ); + const getDataSpy = sinon.spy( dataTransfer, 'getData' ); - clipboard.fire( 'inputTransformation', data ); + const result = clipboard.fire( 'inputHtmlNormalization', { + dataTransfer, + html: dataTransfer.getData( 'text/html' ) + } ); - expect( data._isTransformedWithPasteFromOffice ).to.be.undefined; - expect( data._parsedData ).to.be.undefined; + expect( result.isTransformedWithPasteFromOffice ).to.be.undefined; + expect( result ).to.be.equal( inputString ); sinon.assert.called( getDataSpy ); } @@ -190,42 +195,44 @@ describe( 'PasteFromOffice', () => { describe( 'data which already have the flag', () => { it( 'should not process again ms word data containing a flag', () => { - checkAlreadyProcessedData( '' + - '

Hello world

' ); + checkAlreadyProcessedData( + MSWordNormalizer, + '' + + '

Hello world

' + ); } ); it( 'should not process again google docs data containing a flag', () => { - checkAlreadyProcessedData( '

Hello world

' ); + checkAlreadyProcessedData( + GoogleDocsNormalizer, + '

Hello world

' ); } ); - function checkAlreadyProcessedData( inputString ) { - const data = setUpData( inputString, true ); - const getDataSpy = sinon.spy( data.dataTransfer, 'getData' ); + function checkAlreadyProcessedData( Normalizer, inputString ) { + clipboard.on( 'inputHtmlNormalization', evt => { + evt.return = new ViewDocumentFragment( null ); + evt.return.isTransformedWithPasteFromOffice = true; + }, { priority: 'high' } ); + + const executeSpy = sinon.spy( Normalizer.prototype, 'execute' ); + const dataTransfer = createHTMLDataTransfer( inputString, true ); - clipboard.fire( 'inputTransformation', data ); + const result = clipboard.fire( 'inputHtmlNormalization', { + dataTransfer, + html: dataTransfer.getData( 'text/html' ) + } ); - expect( data._isTransformedWithPasteFromOffice ).to.be.true; - expect( data._parsedData ).to.be.undefined; + expect( result.isTransformedWithPasteFromOffice ).to.be.true; + expect( result ).to.be.instanceOf( ViewDocumentFragment ); - sinon.assert.notCalled( getDataSpy ); + executeSpy.restore(); + expect( executeSpy ).not.to.be.called; } } ); } ); - // @param {String} inputString html to be processed by paste from office - // @param {Boolean} [isTransformedWithPasteFromOffice=false] if set, marks output data with isTransformedWithPasteFromOffice flag - // @returns {Object} data object simulating content obtained from the clipboard - function setUpData( inputString, isTransformedWithPasteFromOffice = false ) { - const data = { - content: htmlDataProcessor.toView( inputString ), - dataTransfer: createDataTransfer( { 'text/html': inputString } ) - }; - - if ( isTransformedWithPasteFromOffice ) { - data._isTransformedWithPasteFromOffice = true; - } - - return data; + function createHTMLDataTransfer( inputString ) { + return createDataTransfer( { 'text/html': inputString } ); } } );