|
@@ -8,6 +8,7 @@
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
|
|
|
+import PastePlainText from './pasteplaintext';
|
|
|
|
|
|
|
|
import ClipboardObserver from './clipboardobserver';
|
|
import ClipboardObserver from './clipboardobserver';
|
|
|
|
|
|
|
@@ -35,6 +36,13 @@ export default class Clipboard extends Plugin {
|
|
|
return 'Clipboard';
|
|
return 'Clipboard';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @inheritDoc
|
|
|
|
|
+ */
|
|
|
|
|
+ static get requires() {
|
|
|
|
|
+ return [ PastePlainText ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* @inheritDoc
|
|
* @inheritDoc
|
|
|
*/
|
|
*/
|
|
@@ -77,7 +85,11 @@ export default class Clipboard extends Plugin {
|
|
|
content = this._htmlDataProcessor.toView( content );
|
|
content = this._htmlDataProcessor.toView( content );
|
|
|
|
|
|
|
|
const eventInfo = new EventInfo( this, 'inputTransformation' );
|
|
const eventInfo = new EventInfo( this, 'inputTransformation' );
|
|
|
- this.fire( eventInfo, { content, dataTransfer } );
|
|
|
|
|
|
|
+ this.fire( eventInfo, {
|
|
|
|
|
+ content,
|
|
|
|
|
+ dataTransfer,
|
|
|
|
|
+ asPlainText: data.asPlainText
|
|
|
|
|
+ } );
|
|
|
|
|
|
|
|
// If CKEditor handled the input, do not bubble the original event any further.
|
|
// If CKEditor handled the input, do not bubble the original event any further.
|
|
|
// This helps external integrations recognize that fact and act accordingly.
|
|
// This helps external integrations recognize that fact and act accordingly.
|
|
@@ -103,16 +115,27 @@ export default class Clipboard extends Plugin {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // While pasting plain text, apply selection attributes on the text.
|
|
|
|
|
- if ( isPlainText( modelFragment ) ) {
|
|
|
|
|
- const node = modelFragment.getChild( 0 );
|
|
|
|
|
|
|
+ // 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 => {
|
|
model.change( writer => {
|
|
|
- writer.setAttributes( modelDocument.selection.getAttributes(), node );
|
|
|
|
|
|
|
+ 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 );
|
|
model.insertContent( modelFragment );
|
|
|
|
|
+
|
|
|
evt.stop();
|
|
evt.stop();
|
|
|
}
|
|
}
|
|
|
}, { priority: 'low' } );
|
|
}, { priority: 'low' } );
|
|
@@ -168,6 +191,7 @@ export default class Clipboard extends Plugin {
|
|
|
* It can be modified by the event listeners. Read more about the clipboard pipelines in
|
|
* It can be modified by the event listeners. Read more about the clipboard pipelines in
|
|
|
* {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive}.
|
|
* {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive}.
|
|
|
* @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.
|
|
* @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.
|
|
|
|
|
+ * @param {Boolean} data.asPlainText If set to `true` content is pasted as plain text.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -212,7 +236,7 @@ export default class Clipboard extends Plugin {
|
|
|
//
|
|
//
|
|
|
// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment
|
|
// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment
|
|
|
// @returns {Boolean}
|
|
// @returns {Boolean}
|
|
|
-function isPlainText( documentFragment ) {
|
|
|
|
|
|
|
+function isPlainTextFragment( documentFragment ) {
|
|
|
if ( documentFragment.childCount > 1 ) {
|
|
if ( documentFragment.childCount > 1 ) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|