瀏覽代碼

The feature should handle clipboard input and make sure the existing code block is not split.

Aleksander Nowodzinski 6 年之前
父節點
當前提交
bc4c3b63dc

+ 22 - 3
packages/ckeditor5-code-block/src/codeblockediting.js

@@ -39,6 +39,7 @@ export default class CodeBlockEditing extends Plugin {
 	init() {
 		const editor = this.editor;
 		const schema = editor.model.schema;
+		const model = editor.model;
 
 		// Command.
 		editor.commands.add( 'codeBlock', new CodeBlockCommand( editor ) );
@@ -61,12 +62,30 @@ export default class CodeBlockEditing extends Plugin {
 		} );
 
 		// Conversion.
-		editor.editing.downcastDispatcher.on( 'insert:codeBlock', modelViewCodeBlockInsertion( editor.model ) );
+		editor.editing.downcastDispatcher.on( 'insert:codeBlock', modelViewCodeBlockInsertion( model ) );
 
-		editor.data.downcastDispatcher.on( 'insert:codeBlock', modelViewCodeBlockInsertion( editor.model ) );
-		editor.data.downcastDispatcher.on( 'insert:softBreak', modelViewSoftBreakInsertion( editor.model ), { priority: 'high' } );
+		editor.data.downcastDispatcher.on( 'insert:codeBlock', modelViewCodeBlockInsertion( model ) );
+		editor.data.downcastDispatcher.on( 'insert:softBreak', modelViewSoftBreakInsertion( model ), { priority: 'high' } );
 
 		editor.data.upcastDispatcher.on( 'element:pre', dataViewModelCodeBlockInsertion( editor.data ) );
+
+		// Intercept the clipboard input when the selection is anchored in the code block and force the clipboard
+		// data to be pasted as a single plain text. Otherwise, the code lines will split the code block and
+		// "spill out" as separate paragraphs.
+		this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
+			const modelSelection = model.document.selection;
+
+			if ( !modelSelection.anchor.parent.is( 'codeBlock' ) ) {
+				return;
+			}
+
+			const text = data.dataTransfer.getData( 'text/plain' );
+
+			model.change( writer => {
+				model.insertContent( writer.createText( text ), modelSelection );
+				evt.stop();
+			} );
+		} );
 	}
 
 	/**

+ 34 - 0
packages/ckeditor5-code-block/tests/codeblockediting.js

@@ -304,4 +304,38 @@ describe( 'CodeBlockEditing', () => {
 			expect( getModelData( model ) ).to.equal( '<codeBlock>[]Hello World!</codeBlock>' );
 		} );
 	} );
+
+	describe( 'clipboard integration', () => {
+		it( 'should not intercept input when selection anchored outside any code block', () => {
+			setModelData( model, '<paragraph>f[]oo</paragraph>' );
+
+			const dataTransferMock = {
+				getData: sinon.stub().withArgs( 'text/plain' ).returns( 'bar' )
+			};
+
+			editor.editing.view.document.fire( 'clipboardInput', {
+				dataTransfer: dataTransferMock,
+				stop: sinon.spy()
+			} );
+
+			expect( getModelData( model ) ).to.equal( '<paragraph>f[]oo</paragraph>' );
+			sinon.assert.notCalled( dataTransferMock.getData );
+		} );
+
+		it( 'should intercept input when selection anchored in the code block', () => {
+			setModelData( model, '<codeBlock>f[o]o</codeBlock>' );
+
+			const dataTransferMock = {
+				getData: sinon.stub().withArgs( 'text/plain' ).returns( 'bar\nbaz\n' )
+			};
+
+			editor.editing.view.document.fire( 'clipboardInput', {
+				dataTransfer: dataTransferMock,
+				stop: sinon.spy()
+			} );
+
+			expect( getModelData( model ) ).to.equal( '<codeBlock>fbar\nbaz\n[]o</codeBlock>' );
+			sinon.assert.calledOnce( dataTransferMock.getData );
+		} );
+	} );
 } );