Przeglądaj źródła

Typing bug fixes and cleaning.

Piotr Jasiun 9 lat temu
rodzic
commit
356d5c0c22
1 zmienionych plików z 71 dodań i 117 usunięć
  1. 71 117
      packages/ckeditor5-typing/src/typing.js

+ 71 - 117
packages/ckeditor5-typing/src/typing.js

@@ -11,7 +11,6 @@ import ModelPosition from '../engine/model/position.js';
 import ModelRange from '../engine/model/range.js';
 import ViewPosition from '../engine/view/position.js';
 import ViewText from '../engine/view/text.js';
-import ViewContainerElement from '../engine/view/containerelement.js';
 import diff from '../utils/diff.js';
 import diffToChanges from '../utils/difftochanges.js';
 import { getCode } from '../utils/keyboard.js';
@@ -155,140 +154,91 @@ class MutationHandler {
 	 * @param {Array.<engine.view.Document~MutatatedText|engine.view.Document~MutatatedChildren>} mutations
 	 */
 	handle( mutations ) {
-		// The below code indicates how multi-mutations consumers can be implemented.
-		// In the future we may need those to handle more advanced case, like spellchecking across text with attributes.
-		//
-		// // Clone the array, because consumers will modify it.
-		// mutations = mutations.slice( 0 );
-
-		// for ( let consumer of MutationHandler.consumers.multi ) {
-		// 	consumer( mutations, this );
-
-		// 	if ( !mutations.length ) {
-		// 		return;
-		// 	}
-		// }
-
-		mutations.forEach( mutation => {
-			for ( let consumer of MutationHandler.consumers.single ) {
-				if ( consumer.check( mutation ) ) {
-					consumer.consume( mutation, this );
-
-					return;
-				}
+		for ( let mutation of mutations ) {
+			// Fortunately it will never be both.
+			this._handleTextMutation( mutation );
+			this._handleTextNodeInsertion( mutation );
+		}
+
+		this.buffer.input( Math.max( this.insertedCharacterCount, 0 ) );
+
+		if ( this.selectionPosition ) {
+			this.editing.model.selection.collapse( this.selectionPosition );
+		}
+	}
+
+	_handleTextMutation( mutation ) {
+		if ( mutation.type != 'text' ) {
+			return;
+		}
+
+		const changes = diffToChanges( diff( mutation.oldText, mutation.newText ), mutation.newText );
+
+		for ( let change of changes ) {
+			const viewPos = new ViewPosition( mutation.node, change.index );
+			const modelPos = this.editing.mapper.toModelPosition( viewPos );
+
+			if ( change.type == 'INSERT' ) {
+				const insertedText = change.values.join( '' );
+
+				this._insert( modelPos, insertedText );
+
+				this.selectionPosition = ModelPosition.createAt( modelPos.parent, modelPos.offset + insertedText.length );
+			} else /* if ( change.type == 'DELETE' ) */ {
+				this._remove( new ModelRange( modelPos, modelPos.getShiftedBy( change.howMany ) ), change.howMany );
+
+				this.selectionPosition = modelPos;
 			}
-		} );
+		}
+	}
+
+	_handleTextNodeInsertion( mutation ) {
+		if ( mutation.type != 'children' ) {
+			return;
+		}
+
+		// One new node.
+		if ( mutation.newChildren.length - mutation.oldChildren.length != 1 ) {
+			return false;
+		}
+		// Which is text.
+		const changes = diffToChanges( diff( mutation.oldChildren, mutation.newChildren ), mutation.newChildren );
+		const change = changes[ 0 ];
+
+		if ( change.type != 'INSERT' ) {
+			return false;
+		}
+
+		if ( !( change.values[ 0 ] instanceof ViewText ) ) {
+			return false;
+		}
+
+		const viewPos = new ViewPosition( mutation.node, change.index );
+		const modelPos = this.editing.mapper.toModelPosition( viewPos );
+		const insertedText = mutation.newChildren[ 0 ].data;
 
-		this._commit();
+		this._insert( modelPos, insertedText );
+
+		this.selectionPosition = ModelPosition.createAt( modelPos.parent, 'END' );
 	}
 
-	insert( { position, text, selectionPosition } ) {
+	_insert( position, text ) {
 		this.buffer.batch.weakInsert( position, text );
 
 		this.insertedCharacterCount += text.length;
-		this.selectionPosition = selectionPosition;
 	}
 
-	remove( { range, selectionPosition } ) {
+	_remove( range, length ) {
 		this.buffer.batch.remove( range );
 
-		this.selectionPosition = selectionPosition;
-	}
-
-	/**
-	 * Commits all changes. While specific consumers will modify the document,
-	 * also the change buffer and selection needs to be updated. This should be done
-	 * once, at the end.
-	 *
-	 * @private
-	 */
-	_commit() {
-		this.buffer.input( this.insertedCharacterCount );
-
-		if ( this.selectionPosition ) {
-			this.editing.model.selection.collapse( this.selectionPosition );
-		}
+		this.insertedCharacterCount -= length;
 	}
 }
 
-/**
- * @static
- * @member {Object} typing.typing.MutationHandler.consumers
- */
-MutationHandler.consumers = {
-	/**
-	 * @member {Array} typing.typing.MutationHandler.consumers.single
-	 */
-	single: [
-		// Simple text nodes change.
-		{
-			check( mutation ) {
-				return ( mutation.type == 'text' );
-			},
-
-			consume( mutation, handler ) {
-				const changes = diffToChanges( diff( mutation.oldText, mutation.newText ), mutation.newText );
-
-				console.log( 'Text node change handler', JSON.stringify( changes ) ); // jshint ignore:line
-				console.log( mutation ); // jshint ignore:line
-
-				changes.forEach( change => {
-					const viewPos = new ViewPosition( mutation.node, change.index );
-					const modelPos = handler.editing.mapper.toModelPosition( viewPos );
-
-					if ( change.type == 'INSERT' ) {
-						const insertedText = change.values.join( '' );
-
-						handler.insert( {
-							position: modelPos,
-							text: insertedText,
-							selectionPosition: ModelPosition.createAt( modelPos.parent, modelPos.offset + insertedText.length )
-						} );
-					} else /* if ( change.type == 'DELETE' ) */ {
-						handler.remove( {
-							range: new ModelRange( modelPos, modelPos.getShiftedBy( change.howMany ) ),
-							selectionPosition: modelPos
-						} );
-					}
-				} );
-			}
-		},
-
-		// Insertion into empty container.
-		{
-			check( mutation ) {
-				return (
-					mutation.oldChildren.length === 0 &&
-					mutation.newChildren.length === 1 &&
-					( mutation.newChildren[ 0 ] instanceof ViewText ) &&
-					( mutation.node instanceof ViewContainerElement )
-				);
-			},
-
-			consume( mutation, handler ) {
-				console.log( 'Insertion into empty container handler', mutation ); // jshint ignore:line
-
-				const viewPos = new ViewPosition( mutation.node, 0 );
-				const modelPos = handler.editing.mapper.toModelPosition( viewPos );
-				const insertedText = mutation.newChildren[ 0 ].data;
-
-				handler.insert( {
-					position: modelPos,
-					text: insertedText,
-					selectionPosition: ModelPosition.createAt( modelPos.parent, 'END' )
-				} );
-			}
-		}
-	]
-};
-
 // This is absolutely lame, but it's enough for now.
 
 const safeKeystrokes = [
-	getCode( 'ctrl' ),
-	getCode( 'cmd' ),
 	getCode( 'shift' ),
-	getCode( 'alt' ),
 	getCode( 'arrowUp' ),
 	getCode( 'arrowRight' ),
 	getCode( 'arrowDown' ),
@@ -296,5 +246,9 @@ const safeKeystrokes = [
 ];
 
 function isSafeKeystroke( keyData ) {
+	if ( keyData.ctrlKey || keyData.altKey ) {
+		return true;
+	}
+
 	return safeKeystrokes.indexOf( keyData.keyCode ) > -1;
 }