8
0
Просмотр исходного кода

Cleaned up a bit the code, added callback for numbered list, added creating new batch in the AutoformatEngine.

Maksymilian Barnaś 9 лет назад
Родитель
Сommit
b381266418

+ 36 - 15
packages/ckeditor5-autoformat/src/autoformat.js

@@ -28,17 +28,42 @@ export default class Autoformat extends Feature {
 	init() {
 		const editor = this.editor;
 
-		if ( editor.commands.has( 'blockquote' ) ) {
-			new AutoformatEngine( editor, /^>\s$/, 'blockquote' );
-		}
-
 		if ( editor.commands.has( 'bulletedList' ) ) {
-			new AutoformatEngine( editor, /^[\*\-]\s$/, 'bulletedList' );
+			new AutoformatEngine( editor, /^[\*\-]\s$/, ( context ) => {
+				const { range, batch, element } = context;
+				const ancestors = element.getAncestors();
+				const command = editor.commands.get( 'bulletedList' );
+
+				const isInList = command.value || ancestors.some( ( element ) => {
+					return element.name === 'listItem';
+				} );
+
+				if ( isInList ) {
+					return;
+				}
+
+				batch.remove( range );
+				editor.execute( 'bulletedList', { batch } );
+			} );
 		}
 
-		// TODO Should I start from custom number?
 		if ( editor.commands.has( 'numberedList' ) ) {
-			new AutoformatEngine( editor, /^\d+[\.|)]?\s$/, 'numberedList' ); // "1 A", "1. A", "123 A"
+			new AutoformatEngine( editor, /^\d+[\.|)]?\s$/, ( context ) => {
+				const { range, batch, element } = context;
+				const ancestors = element.getAncestors();
+				const command = editor.commands.get( 'numberedList' );
+
+				const isInList = command.value || ancestors.some( ( element ) => {
+					return element.name === 'listItem';
+				} );
+
+				if ( isInList ) {
+					return;
+				}
+
+				batch.remove( range );
+				editor.execute( 'numberedList', { batch } );
+			} );
 		}
 
 		if ( editor.commands.has( 'heading' ) ) {
@@ -49,23 +74,19 @@ export default class Autoformat extends Feature {
 			//
 			// After ctrl+z: <p>## ^</p> (so undo two steps)
 			new AutoformatEngine( editor, /^(#{1,3})\s$/, ( context ) => {
-				const { batch, match, range } = context;
+				const { range, batch, match } = context;
 
 				// TODO The heading command may be reconfigured in the future to support a different number
 				// of headings. That option must be exposed somehow, because we need to know here whether the replacement
 				// can be done or not.
-
 				const headingLevel = match[ 1 ].length;
-				batch.remove( range );
 
-				// This part needs slightly changed HeadingCommand.
-				// TODO Commit change to ckeditor5-heading, don't forget to update tests.
-				// TODO Also commit changes to ckeditor5-engine/model/liveposition.js.
+				batch.remove( range );
 				editor.execute( 'heading', {
-					batch: batch,
+					batch,
 					formatId: `heading${ headingLevel }`
 				} );
-			} ); // "# A", "## A"...
+			} );
 		}
 	}
 }

+ 12 - 8
packages/ckeditor5-autoformat/src/autoformatengine.js

@@ -16,25 +16,27 @@ export default class AutoformatEngine {
 	 * @param {Regex} pattern Regular expression to exec on just inserted text.
 	 * @param {Function|String} callbackOrCommand Callback to execute or command to run when text is matched.
 	 */
-	constructor ( editor, pattern, callbackOrCommand ) {
+	constructor( editor, pattern, callbackOrCommand ) {
 		let callback;
 
-		if ( typeof callbackOrCommand === 'function' ) {
+		if ( typeof callbackOrCommand == 'function' ) {
 			callback = callbackOrCommand;
 		} else {
+			// We assume that the actual command name was provided.
 			const command = callbackOrCommand;
 
 			callback = ( context ) => {
 				const { batch, range } = context;
 
+				// Remove matched pattern by default
 				batch.remove( range );
-				editor.execute( command, {
-					batch
-				} );
+
+				// Create new batch for removal and command execution.
+				editor.execute( command, batch );
 			};
 		}
 
-		editor.document.on( 'change', ( event, type, changes, batch ) => {
+		editor.document.on( 'change', ( event, type, changes ) => {
 			if ( type != 'insert' ) {
 				return;
 			}
@@ -44,7 +46,6 @@ export default class AutoformatEngine {
 					direction: 'backward',
 					startPosition: Position.createAfter( value )
 				} );
-
 				const currentValue = walker.next().value;
 				const text = currentValue.item.data;
 
@@ -62,10 +63,13 @@ export default class AutoformatEngine {
 				let lastPath = _getLastPathPart( currentValue.nextPosition.path );
 				let liveStartPosition = LivePosition.createFromParentAndOffset( currentValue.item.parent, lastPath + match.index );
 
-				editor.document.enqueueChanges( () => {
+				editor.document.enqueueChanges( function() {
 					const range = Range.createFromPositionAndShift( liveStartPosition, match[ 0 ].length );
 					const element = currentValue.item;
 
+					// Create new batch to separate typing batch from the Autoformat changes.
+					const batch = editor.document.batch();
+
 					callback( { batch, match, range, element } );
 				} );
 			}