Sfoglia il codice sorgente

Other (clipboard): Changed paste as plain text implementation to work better with links.

Previous implementation caused "LinkEditing typing over the link should not preserve selection attributes when the changes are not caused by typing (pasting check)" test case to fail. See https://travis-ci.org/github/ckeditor/ckeditor5/builds/719551313.
Marek Lewandowski 5 anni fa
parent
commit
cb08c3e3a1

+ 19 - 13
packages/ckeditor5-clipboard/src/clipboard.js

@@ -97,7 +97,6 @@ export default class Clipboard extends Plugin {
 			if ( !data.content.isEmpty ) {
 				const dataController = this.editor.data;
 				const model = this.editor.model;
-				const initialAttributes = new Map( modelDocument.selection.getAttributes() );
 
 				// Convert the pasted content to a model document fragment.
 				// Conversion is contextual, but in this case we need an "all allowed" context and for that
@@ -108,19 +107,26 @@ export default class Clipboard extends Plugin {
 					return;
 				}
 
-				// Plain text can be determined based on event flag (#7799) or auto detection (#1006).
-				const isPlainText = data.asPlainText || isPlainTextFragment( modelFragment );
-
-				model.change( writer => {
-					const insertedRange = model.insertContent( modelFragment );
-
-					// The insertedRange needs to be verified, as the return value might easily be discarded like in #7887.
-					if ( isPlainText && insertedRange ) {
-						for ( const item of insertedRange.getItems() ) {
-							writer.setAttributes( initialAttributes, item );
+				// Plain text can be determined based on event flag (#7799) or auto detection (#1006). If detected
+				// preserve selection attributes on pasted items.
+				if ( data.asPlainText || isPlainTextFragment( modelFragment ) ) {
+					// Consider only formatting attributes.
+					const textAttributes = new Map( Array.from( modelDocument.selection.getAttributes() ).filter(
+						keyValuePair => editor.model.schema.getAttributeProperties( keyValuePair[ 0 ] ).isFormatting
+					) );
+
+					model.change( writer => {
+						const range = writer.createRangeIn( modelFragment );
+
+						for ( const item of range.getItems() ) {
+							if ( item.is( '$text' ) || item.is( '$textProxy' ) ) {
+								writer.setAttributes( textAttributes, item );
+							}
 						}
-					}
-				} );
+					} );
+				}
+
+				model.insertContent( modelFragment );
 
 				evt.stop();
 			}

+ 22 - 0
packages/ckeditor5-clipboard/tests/clipboard.js

@@ -351,6 +351,9 @@ describe( 'Clipboard feature', () => {
 				model = editor.model;
 
 				model.schema.extend( '$text', { allowAttributes: 'bold' } );
+				model.schema.extend( '$text', { allowAttributes: 'test' } );
+
+				editor.model.schema.setAttributeProperties( 'bold', { isFormatting: true } );
 
 				model.schema.register( 'softBreak', {
 					allowWhere: '$text',
@@ -522,6 +525,25 @@ describe( 'Clipboard feature', () => {
 
 				expect( getModelData( model ) ).to.equal( '<paragraph><$text bold="true">Bolded []text.</$text></paragraph>' );
 			} );
+
+			it( 'ignores non-formatting text attributes', () => {
+				setModelData( model, '<paragraph><$text test="true">Bolded []text.</$text></paragraph>' );
+
+				const dataTransferMock = createDataTransfer( {
+					'text/html': 'foo',
+					'text/plain': 'foo'
+				} );
+
+				viewDocument.fire( 'clipboardInput', {
+					dataTransfer: dataTransferMock,
+					asPlainText: false,
+					stopPropagation() {},
+					preventDefault() {}
+				} );
+
+				expect( getModelData( model ) ).to.equal(
+					'<paragraph><$text test="true">Bolded </$text>foo[]<$text test="true">text.</$text></paragraph>' );
+			} );
 		} );
 
 		function createDataTransfer( data ) {