|
|
@@ -14,8 +14,8 @@ import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange';
|
|
|
import Position from '@ckeditor/ckeditor5-engine/src/model/position';
|
|
|
import LivePosition from '@ckeditor/ckeditor5-engine/src/model/liveposition';
|
|
|
import TreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';
|
|
|
-import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
|
import Undo from '@ckeditor/ckeditor5-undo/src/undo';
|
|
|
+import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
|
|
|
|
const URL_REGEXP = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=]+$/;
|
|
|
|
|
|
@@ -39,6 +39,21 @@ export default class AutoMediaEmbed extends Plugin {
|
|
|
return 'AutoMediaEmbed';
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @inheritDoc
|
|
|
+ */
|
|
|
+ constructor( editor ) {
|
|
|
+ super( editor );
|
|
|
+
|
|
|
+ /**
|
|
|
+ * A timer id returned by `setTimeout` function.
|
|
|
+ *
|
|
|
+ * @private
|
|
|
+ * @member {Number} media-embed/automediaembed~AutoMediaEmbed#_timeoudId
|
|
|
+ */
|
|
|
+ this._timeoutId = null;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @inheritDoc
|
|
|
*/
|
|
|
@@ -46,33 +61,29 @@ export default class AutoMediaEmbed extends Plugin {
|
|
|
const editor = this.editor;
|
|
|
const modelDocument = editor.model.document;
|
|
|
|
|
|
- let leftLivePosition, rightLivePosition, timeoutId;
|
|
|
-
|
|
|
// We need to listen on `Clipboard#inputTransformation` because we need to save positions of selection.
|
|
|
// After pasting a content, between those position can be located a URL that should be transformed to media.
|
|
|
this.listenTo( editor.plugins.get( Clipboard ), 'inputTransformation', () => {
|
|
|
const firstRange = modelDocument.selection.getFirstRange();
|
|
|
|
|
|
- leftLivePosition = LivePosition.createFromPosition( firstRange.start );
|
|
|
+ const leftLivePosition = LivePosition.createFromPosition( firstRange.start );
|
|
|
leftLivePosition.stickiness = 'toPrevious';
|
|
|
|
|
|
- rightLivePosition = LivePosition.createFromPosition( firstRange.end );
|
|
|
+ const rightLivePosition = LivePosition.createFromPosition( firstRange.end );
|
|
|
rightLivePosition.stickiness = 'toNext';
|
|
|
|
|
|
modelDocument.once( 'change:data', () => {
|
|
|
- this._autoEmbedingEventHandler( leftLivePosition, rightLivePosition )
|
|
|
- .then( _timeoutId => {
|
|
|
- timeoutId = _timeoutId;
|
|
|
- leftLivePosition = null;
|
|
|
- rightLivePosition = null;
|
|
|
- } );
|
|
|
+ this._autoEmbedingEventHandler( leftLivePosition, rightLivePosition );
|
|
|
+
|
|
|
+ leftLivePosition.detach();
|
|
|
+ rightLivePosition.detach();
|
|
|
}, { priority: 'high' } );
|
|
|
} );
|
|
|
|
|
|
editor.commands.get( 'undo' ).on( 'execute', () => {
|
|
|
- if ( timeoutId ) {
|
|
|
- global.window.clearTimeout( timeoutId );
|
|
|
- timeoutId = null;
|
|
|
+ if ( this._timeoutId ) {
|
|
|
+ global.window.clearTimeout( this._timeoutId );
|
|
|
+ this._timeoutId = null;
|
|
|
}
|
|
|
}, { priority: 'high' } );
|
|
|
}
|
|
|
@@ -81,9 +92,8 @@ export default class AutoMediaEmbed extends Plugin {
|
|
|
* A handler that replaces the pasted URL with `<media>` element.
|
|
|
*
|
|
|
* @private
|
|
|
- * @param {module:engine/model/liveposition} leftPosition Left position of the selection.
|
|
|
- * @param {module:engine/model/liveposition} rightPosition Right position of the selection.
|
|
|
- * @returns {Promise}
|
|
|
+ * @param {module:engine/model/liveposition~LivePosition} leftPosition Left position of the selection.
|
|
|
+ * @param {module:engine/model/liveposition~LivePosition} rightPosition Right position of the selection.
|
|
|
*/
|
|
|
_autoEmbedingEventHandler( leftPosition, rightPosition ) {
|
|
|
const editor = this.editor;
|
|
|
@@ -101,33 +111,26 @@ export default class AutoMediaEmbed extends Plugin {
|
|
|
|
|
|
// If the url does not match to universal url regexp, let's skip that.
|
|
|
if ( !url.match( URL_REGEXP ) ) {
|
|
|
- return detach();
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
// If the url is valid from MediaEmbed plugin point of view, let's use it.
|
|
|
if ( !mediaRegistry.hasMedia( url ) ) {
|
|
|
- return detach();
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
// Positions won't be available in `setTimeout` function so let's clone it.
|
|
|
const positionToInsert = Position.createFromPosition( leftPosition );
|
|
|
|
|
|
// This action mustn't be executed if undo was called between pasting and ąuto-embeding.
|
|
|
- const timeoutId = global.window.setTimeout( () => {
|
|
|
+ this._timeoutId = global.window.setTimeout( () => {
|
|
|
editor.model.change( writer => {
|
|
|
+ this._timeoutId = null;
|
|
|
+
|
|
|
writer.remove( urlRange );
|
|
|
writer.setSelection( positionToInsert );
|
|
|
editor.commands.execute( 'mediaEmbed', url );
|
|
|
} );
|
|
|
}, 100 );
|
|
|
-
|
|
|
- return detach().then( () => timeoutId );
|
|
|
-
|
|
|
- function detach() {
|
|
|
- leftPosition.detach();
|
|
|
- rightPosition.detach();
|
|
|
-
|
|
|
- return Promise.resolve();
|
|
|
- }
|
|
|
}
|
|
|
}
|