Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ckeditor/ckeditor5-clipboard

Package Overview
Dependencies
Maintainers
1
Versions
709
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ckeditor/ckeditor5-clipboard - npm Package Compare versions

Comparing version 26.0.0 to 27.0.0

src/clipboardpipeline.js

32

package.json
{
"name": "@ckeditor/ckeditor5-clipboard",
"version": "26.0.0",
"version": "27.0.0",
"description": "Clipboard integration for CKEditor 5.",

@@ -15,12 +15,26 @@ "keywords": [

"dependencies": {
"@ckeditor/ckeditor5-core": "^26.0.0",
"@ckeditor/ckeditor5-engine": "^26.0.0",
"@ckeditor/ckeditor5-utils": "^26.0.0"
"@ckeditor/ckeditor5-core": "^27.0.0",
"@ckeditor/ckeditor5-engine": "^27.0.0",
"@ckeditor/ckeditor5-utils": "^27.0.0",
"@ckeditor/ckeditor5-widget": "^27.0.0",
"lodash-es": "^4.17.11"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^26.0.0",
"@ckeditor/ckeditor5-block-quote": "^26.0.0",
"@ckeditor/ckeditor5-editor-classic": "^26.0.0",
"@ckeditor/ckeditor5-link": "^26.0.0",
"@ckeditor/ckeditor5-paragraph": "^26.0.0"
"@ckeditor/ckeditor5-alignment": "^27.0.0",
"@ckeditor/ckeditor5-basic-styles": "^27.0.0",
"@ckeditor/ckeditor5-block-quote": "^27.0.0",
"@ckeditor/ckeditor5-cloud-services": "^27.0.0",
"@ckeditor/ckeditor5-code-block": "^27.0.0",
"@ckeditor/ckeditor5-easy-image": "^27.0.0",
"@ckeditor/ckeditor5-editor-classic": "^27.0.0",
"@ckeditor/ckeditor5-enter": "^27.0.0",
"@ckeditor/ckeditor5-horizontal-line": "^27.0.0",
"@ckeditor/ckeditor5-image": "^27.0.0",
"@ckeditor/ckeditor5-link": "^27.0.0",
"@ckeditor/ckeditor5-page-break": "^27.0.0",
"@ckeditor/ckeditor5-paragraph": "^27.0.0",
"@ckeditor/ckeditor5-paste-from-office": "^27.0.0",
"@ckeditor/ckeditor5-remove-format": "^27.0.0",
"@ckeditor/ckeditor5-table": "^27.0.0",
"@ckeditor/ckeditor5-typing": "^27.0.0"
},

@@ -27,0 +41,0 @@ "engines": {

@@ -11,19 +11,17 @@ /**

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ClipboardPipeline from './clipboardpipeline';
import DragDrop from './dragdrop';
import PastePlainText from './pasteplaintext';
import ClipboardObserver from './clipboardobserver';
import plainTextToHtml from './utils/plaintexttohtml';
import normalizeClipboardHtml from './utils/normalizeclipboarddata';
import viewToPlainText from './utils/viewtoplaintext.js';
import EventInfo from '@ckeditor/ckeditor5-utils/src/eventinfo';
/**
* The clipboard feature. It is responsible for intercepting the `paste` and `drop` events and
* passing the pasted content through the clipboard pipeline in order to insert it into the editor's content.
* It also handles the `cut` and `copy` events to fill the native clipboard with serialized editor's data.
* The clipboard feature.
*
* Read more about the clipboard integration in {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive} guide.
*
* This is a "glue" plugin which loads the following plugins:
* * {@link module:clipboard/clipboardpipeline~ClipboardPipeline}
* * {@link module:clipboard/dragdrop~DragDrop}
* * {@link module:clipboard/pasteplaintext~PastePlainText}
*
* @extends module:core/plugin~Plugin

@@ -43,213 +41,4 @@ */

static get requires() {
return [ PastePlainText ];
return [ ClipboardPipeline, DragDrop, PastePlainText ];
}
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const modelDocument = editor.model.document;
const view = editor.editing.view;
const viewDocument = view.document;
view.addObserver( ClipboardObserver );
// The clipboard paste pipeline.
// Pasting and dropping is disabled when editor is read-only.
// See: https://github.com/ckeditor/ckeditor5-clipboard/issues/26.
this.listenTo( viewDocument, 'clipboardInput', evt => {
if ( editor.isReadOnly ) {
evt.stop();
}
}, { priority: 'highest' } );
this.listenTo( viewDocument, 'clipboardInput', ( evt, data ) => {
const dataTransfer = data.dataTransfer;
let content = '';
if ( dataTransfer.getData( 'text/html' ) ) {
content = normalizeClipboardHtml( dataTransfer.getData( 'text/html' ) );
} else if ( dataTransfer.getData( 'text/plain' ) ) {
content = plainTextToHtml( dataTransfer.getData( 'text/plain' ) );
}
content = this.editor.data.htmlProcessor.toView( content );
const eventInfo = new EventInfo( this, 'inputTransformation' );
this.fire( eventInfo, {
content,
dataTransfer,
asPlainText: data.asPlainText
} );
// If CKEditor handled the input, do not bubble the original event any further.
// This helps external integrations recognize that fact and act accordingly.
// https://github.com/ckeditor/ckeditor5-upload/issues/92
if ( eventInfo.stop.called ) {
evt.stop();
}
view.scrollToTheSelection();
}, { priority: 'low' } );
this.listenTo( this, 'inputTransformation', ( evt, data ) => {
if ( !data.content.isEmpty ) {
const dataController = this.editor.data;
const model = this.editor.model;
// Convert the pasted content to a model document fragment.
// The conversion is contextual, but in this case we need an "all allowed" context
// and for that we use the $clipboardHolder item.
const modelFragment = dataController.toModel( data.content, '$clipboardHolder' );
if ( modelFragment.childCount == 0 ) {
return;
}
model.change( writer => {
const selection = model.document.selection;
// 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, model.schema ) ) {
// Formatting attributes should be preserved.
const textAttributes = Array.from( selection.getAttributes() )
.filter( ( [ key ] ) => model.schema.getAttributeProperties( key ).isFormatting );
if ( !selection.isCollapsed ) {
model.deleteContent( selection, { doNotAutoparagraph: true } );
}
// Also preserve other attributes if they survived the content deletion (because they were not fully selected).
// For example linkHref is not a formatting attribute but it should be preserved if pasted text was in the middle
// of a link.
textAttributes.push( ...selection.getAttributes() );
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();
}
}, { priority: 'low' } );
// The clipboard copy/cut pipeline.
function onCopyCut( evt, data ) {
const dataTransfer = data.dataTransfer;
data.preventDefault();
const content = editor.data.toView( editor.model.getSelectedContent( modelDocument.selection ) );
viewDocument.fire( 'clipboardOutput', { dataTransfer, content, method: evt.name } );
}
this.listenTo( viewDocument, 'copy', onCopyCut, { priority: 'low' } );
this.listenTo( viewDocument, 'cut', ( evt, data ) => {
// Cutting is disabled when editor is read-only.
// See: https://github.com/ckeditor/ckeditor5-clipboard/issues/26.
if ( editor.isReadOnly ) {
data.preventDefault();
} else {
onCopyCut( evt, data );
}
}, { priority: 'low' } );
this.listenTo( viewDocument, 'clipboardOutput', ( evt, data ) => {
if ( !data.content.isEmpty ) {
data.dataTransfer.setData( 'text/html', this.editor.data.htmlProcessor.toData( data.content ) );
data.dataTransfer.setData( 'text/plain', viewToPlainText( data.content ) );
}
if ( data.method == 'cut' ) {
editor.model.deleteContent( modelDocument.selection );
}
}, { priority: 'low' } );
}
}
/**
* Fired with a `content` and `dataTransfer` objects. The `content` which comes from the clipboard (was pasted or dropped)
* should be processed in order to be inserted into the editor. The `dataTransfer` object is available
* in case the transformation functions need access to raw clipboard data.
*
* It is a part of the {@glink framework/guides/deep-dive/clipboard#input-pipeline "clipboard input pipeline"}.
*
* @see module:clipboard/clipboardobserver~ClipboardObserver
* @see module:clipboard/clipboard~Clipboard
* @event module:clipboard/clipboard~Clipboard#event:inputTransformation
* @param {Object} data Event data.
* @param {module:engine/view/documentfragment~DocumentFragment} data.content Event data. Content to be inserted into the editor.
* It can be modified by the event listeners. Read more about the clipboard pipelines in
* {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive}.
* @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer Data transfer instance.
* @param {Boolean} data.asPlainText If set to `true`, the content is pasted as plain text.
*/
/**
* Fired on {@link module:engine/view/document~Document#event:copy} and {@link module:engine/view/document~Document#event:cut}
* with a copy of selected content. The content can be processed before it ends up in the clipboard.
*
* It is a part of the {@glink framework/guides/deep-dive/clipboard#output-pipeline "clipboard output pipeline"}.
*
* @see module:clipboard/clipboardobserver~ClipboardObserver
* @see module:clipboard/clipboard~Clipboard
* @event module:engine/view/document~Document#event:clipboardOutput
* @param {module:clipboard/clipboard~ClipboardOutputEventData} data Event data.
*/
/**
* The value of the {@link module:engine/view/document~Document#event:clipboardOutput} event.
*
* @class module:clipboard/clipboard~ClipboardOutputEventData
*/
/**
* Data transfer instance.
*
* @readonly
* @member {module:clipboard/datatransfer~DataTransfer} module:clipboard/clipboard~ClipboardOutputEventData#dataTransfer
*/
/**
* Content to be put into the clipboard. It can be modified by the event listeners.
* Read more about the clipboard pipelines in {@glink framework/guides/deep-dive/clipboard "Clipboard" deep dive}.
*
* @member {module:engine/view/documentfragment~DocumentFragment} module:clipboard/clipboard~ClipboardOutputEventData#content
*/
/**
* Whether the event was triggered by a copy or cut operation.
*
* @member {'copy'|'cut'} module:clipboard/clipboard~ClipboardOutputEventData#method
*/
// Returns true if specified `documentFragment` represents a plain text.
//
// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment
// @param {module:engine/model/schema~Schema} schema
// @returns {Boolean}
function isPlainTextFragment( documentFragment, schema ) {
if ( documentFragment.childCount > 1 ) {
return false;
}
const child = documentFragment.getChild( 0 );
if ( schema.isObject( child ) ) {
return false;
}
return [ ...child.getAttributeKeys() ].length == 0;
}

@@ -19,12 +19,17 @@ /**

*
* * {@link module:engine/view/document~Document#event:clipboardInput}
* * {@link module:engine/view/document~Document#event:dragover}
* * {@link module:engine/view/document~Document#event:drop}
* * {@link module:engine/view/document~Document#event:paste}
* * {@link module:engine/view/document~Document#event:copy}
* * {@link module:engine/view/document~Document#event:cut}
* * {@link module:engine/view/document~Document#event:clipboardInput},
* * {@link module:engine/view/document~Document#event:paste},
* * {@link module:engine/view/document~Document#event:copy},
* * {@link module:engine/view/document~Document#event:cut},
* * {@link module:engine/view/document~Document#event:drop},
* * {@link module:engine/view/document~Document#event:dragover},
* * {@link module:engine/view/document~Document#event:dragging},
* * {@link module:engine/view/document~Document#event:dragstart},
* * {@link module:engine/view/document~Document#event:dragend},
* * {@link module:engine/view/document~Document#event:dragenter},
* * {@link module:engine/view/document~Document#event:dragleave}.
*
* Note that this observer is not available by default (it is not added by the engine).
* To make it available, it needs to be added to {@link module:engine/view/document~Document} by
* the {@link module:engine/view/view~View#addObserver `View#addObserver()`} method. You can also load the
* **Note**: This observer is not available by default (ckeditor5-engine does not add it on its own).
* To make it available, it needs to be added to {@link module:engine/view/document~Document} by using
* the {@link module:engine/view/view~View#addObserver `View#addObserver()`} method. Alternatively, you can load the
* {@link module:clipboard/clipboard~Clipboard} plugin which adds this observer automatically (because it uses it).

@@ -40,25 +45,29 @@ *

this.domEventType = [ 'paste', 'copy', 'cut', 'drop', 'dragover' ];
this.domEventType = [ 'paste', 'copy', 'cut', 'drop', 'dragover', 'dragstart', 'dragend', 'dragenter', 'dragleave' ];
this.listenTo( viewDocument, 'paste', handleInput, { priority: 'low' } );
this.listenTo( viewDocument, 'drop', handleInput, { priority: 'low' } );
this.listenTo( viewDocument, 'paste', handleInput( 'clipboardInput' ), { priority: 'low' } );
this.listenTo( viewDocument, 'drop', handleInput( 'clipboardInput' ), { priority: 'low' } );
this.listenTo( viewDocument, 'dragover', handleInput( 'dragging' ), { priority: 'low' } );
function handleInput( evt, data ) {
data.preventDefault();
function handleInput( type ) {
return ( evt, data ) => {
data.preventDefault();
const targetRanges = data.dropRange ? [ data.dropRange ] : Array.from( viewDocument.selection.getRanges() );
const targetRanges = data.dropRange ? [ data.dropRange ] : null;
const eventInfo = new EventInfo( viewDocument, type );
const eventInfo = new EventInfo( viewDocument, 'clipboardInput' );
viewDocument.fire( eventInfo, {
dataTransfer: data.dataTransfer,
method: evt.name,
targetRanges,
target: data.target
} );
viewDocument.fire( eventInfo, {
dataTransfer: data.dataTransfer,
targetRanges
} );
// If CKEditor handled the input, do not bubble the original event any further.
// This helps external integrations recognize that fact and act accordingly.
// https://github.com/ckeditor/ckeditor5-upload/issues/92
if ( eventInfo.stop.called ) {
data.stopPropagation();
}
// If CKEditor handled the input, do not bubble the original event any further.
// This helps external integrations recognize that fact and act accordingly.
// https://github.com/ckeditor/ckeditor5-upload/issues/92
if ( eventInfo.stop.called ) {
data.stopPropagation();
}
};
}

@@ -72,3 +81,3 @@ }

if ( domEvent.type == 'drop' ) {
if ( domEvent.type == 'drop' || domEvent.type == 'dragover' ) {
evtData.dropRange = getDropViewRange( this.view, domEvent );

@@ -100,5 +109,5 @@ }

return view.domConverter.domRangeToView( domRange );
} else {
return view.document.selection.getFirstRange();
}
return null;
}

@@ -111,8 +120,9 @@

*
* Fired with a `dataTransfer` which comes from the clipboard and whose content should be processed
* This event carries a `dataTransfer` object which comes from the clipboard and which content should be processed
* and inserted into the editor.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -124,5 +134,7 @@ * @see module:clipboard/clipboardobserver~ClipboardObserver

* @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer The data transfer instance.
* @param {'paste'|'drop'} method Whether the event was triggered by a paste or drop operation.
* @param {module:engine/view/element~Element} target The tree view element representing the target.
* @param {Array.<module:engine/view/range~Range>} data.targetRanges Ranges which are the target of the operation
* (usually – into which the content should be inserted).
* If clipboard input was triggered by a paste operation, then these are the selection ranges. If by a drop operation,
* If the clipboard input was triggered by a paste operation, then this property is not set. If by a drop operation,
* then it is the drop position (which can be different than the selection at the moment of drop).

@@ -132,9 +144,10 @@ */

/**
* Fired when the user drags the content over one of the editables.
* Fired when the user drags the content over one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -147,9 +160,10 @@ * @see module:engine/view/document~Document#event:clipboardInput

/**
* Fired when the user dropped the content into one of the editables.
* Fired when the user dropped the content into one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -163,9 +177,10 @@ * @see module:engine/view/document~Document#event:clipboardInput

/**
* Fired when the user pasted the content into one of the editables.
* Fired when the user pasted the content into one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -178,9 +193,10 @@ * @see module:engine/view/document~Document#event:clipboardInput

/**
* Fired when the user copied the content from one of the editables.
* Fired when the user copied the content from one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -193,9 +209,10 @@ * @see module:clipboard/clipboardobserver~ClipboardObserver

/**
* Fired when the user cut the content from one of the editables.
* Fired when the user cut the content from one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* Note that this event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by the {@link module:engine/view/view~View#addObserver} method.
* This is done by the {@link module:clipboard/clipboard~Clipboard} feature. If it is not loaded, it must be done manually.
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*

@@ -223,1 +240,85 @@ * @see module:clipboard/clipboardobserver~ClipboardObserver

*/
/**
* Fired as a continuation of the {@link #event:dragover} event.
*
* It is a part of the {@glink framework/guides/deep-dive/clipboard#input-pipeline "clipboard input pipeline"}.
*
* This event carries a `dataTransfer` object which comes from the clipboard and which content should be processed
* and inserted into the editor.
*
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*
* @see module:clipboard/clipboardobserver~ClipboardObserver
* @see module:clipboard/clipboard~Clipboard
* @event module:engine/view/document~Document#event:dragging
* @param {Object} data Event data.
* @param {module:clipboard/datatransfer~DataTransfer} data.dataTransfer The data transfer instance.
* @param {module:engine/view/element~Element} target The tree view element representing the target.
* @param {Array.<module:engine/view/range~Range>} data.targetRanges Ranges which are the target of the operation
* (usually – into which the content should be inserted).
* It is the drop position (which can be different than the selection at the moment of drop).
*/
/**
* Fired when the user starts dragging the content in one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*
* @see module:engine/view/document~Document#event:clipboardInput
* @event module:engine/view/document~Document#event:dragstart
* @param {module:clipboard/clipboardobserver~ClipboardEventData} data The event data.
*/
/**
* Fired when the user ended dragging the content.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*
* @see module:engine/view/document~Document#event:clipboardInput
* @event module:engine/view/document~Document#event:dragend
* @param {module:clipboard/clipboardobserver~ClipboardEventData} data The event data.
*/
/**
* Fired when the user drags the content into one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*
* @see module:engine/view/document~Document#event:clipboardInput
* @event module:engine/view/document~Document#event:dragenter
* @param {module:clipboard/clipboardobserver~ClipboardEventData} data The event data.
*/
/**
* Fired when the user drags the content out of one of the editing roots of the editor.
*
* Introduced by {@link module:clipboard/clipboardobserver~ClipboardObserver}.
*
* **Note**: This event is not available by default. To make it available, {@link module:clipboard/clipboardobserver~ClipboardObserver}
* needs to be added to the {@link module:engine/view/document~Document} by using the {@link module:engine/view/view~View#addObserver}
* method. This is usually done by the {@link module:clipboard/clipboard~Clipboard} plugin, but if for some reason it is not loaded,
* the observer must be added manually.
*
* @see module:engine/view/document~Document#event:clipboardInput
* @event module:engine/view/document~Document#event:dragleave
* @param {module:clipboard/clipboardobserver~ClipboardEventData} data The event data.
*/

@@ -62,2 +62,37 @@ /**

}
/**
* The effect that is allowed for a drag operation.
*
* @param {String} value
*/
set effectAllowed( value ) {
this._native.effectAllowed = value;
}
get effectAllowed() {
return this._native.effectAllowed;
}
/**
* The actual drop effect.
*
* @param {String} value
*/
set dropEffect( value ) {
this._native.dropEffect = value;
}
get dropEffect() {
return this._native.dropEffect;
}
/**
* Whether dragging operation was canceled.
*
* @returns {Boolean}
*/
get isCanceled() {
return this._native.dropEffect == 'none' || !!this._native.mozUserCancelled;
}
}

@@ -64,0 +99,0 @@

@@ -11,3 +11,4 @@ /**

export { default as Clipboard } from './clipboard';
export { default as ClipboardPipeline } from './clipboardpipeline';
export { default as DragDrop } from './dragdrop';
export { default as PastePlainText } from './pasteplaintext';

@@ -7,3 +7,3 @@ /**

/**
* @module clipboard/clipboard
* @module clipboard/pasteplaintext
*/

@@ -14,2 +14,3 @@

import ClipboardObserver from './clipboardobserver';
import ClipboardPipeline from './clipboardpipeline';

@@ -34,5 +35,16 @@ /**

*/
static get requires() {
return [ ClipboardPipeline ];
}
/**
* @inheritDoc
*/
init() {
const view = this.editor.editing.view;
const editor = this.editor;
const model = editor.model;
const view = editor.editing.view;
const viewDocument = view.document;
const selection = model.document.selection;
let shiftPressed = false;

@@ -46,8 +58,52 @@

this.listenTo( viewDocument, 'clipboardInput', ( evt, data ) => {
if ( shiftPressed ) {
data.asPlainText = true;
editor.plugins.get( ClipboardPipeline ).on( 'contentInsertion', ( evt, data ) => {
// Plain text can be determined based on event flag (#7799) or auto-detection (#1006). If detected,
// preserve selection attributes on pasted items.
if ( !shiftPressed && !isPlainTextFragment( data.content, model.schema ) ) {
return;
}
}, { priority: 'high' } );
model.change( writer => {
// Formatting attributes should be preserved.
const textAttributes = Array.from( selection.getAttributes() )
.filter( ( [ key ] ) => model.schema.getAttributeProperties( key ).isFormatting );
if ( !selection.isCollapsed ) {
model.deleteContent( selection, { doNotAutoparagraph: true } );
}
// Also preserve other attributes if they survived the content deletion (because they were not fully selected).
// For example linkHref is not a formatting attribute but it should be preserved if pasted text was in the middle
// of a link.
textAttributes.push( ...selection.getAttributes() );
const range = writer.createRangeIn( data.content );
for ( const item of range.getItems() ) {
if ( item.is( '$textProxy' ) ) {
writer.setAttributes( textAttributes, item );
}
}
} );
} );
}
}
// Returns true if specified `documentFragment` represents a plain text.
//
// @param {module:engine/view/documentfragment~DocumentFragment} documentFragment
// @param {module:engine/model/schema~Schema} schema
// @returns {Boolean}
function isPlainTextFragment( documentFragment, schema ) {
if ( documentFragment.childCount > 1 ) {
return false;
}
const child = documentFragment.getChild( 0 );
if ( schema.isObject( child ) ) {
return false;
}
return [ ...child.getAttributeKeys() ].length == 0;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc