Parcourir la source

Removing partial mention post-fixer now detects inserting inline elements and splitting parent.

Maciej Gołaszewski il y a 6 ans
Parent
commit
3e9ad92f5b

+ 33 - 19
packages/ckeditor5-mention/src/mentionediting.js

@@ -57,7 +57,7 @@ export default class MentionEditing extends Plugin {
 			view: createViewMentionElement
 		} );
 
-		doc.registerPostFixer( writer => removePartialMentionPostFixer( writer, doc ) );
+		doc.registerPostFixer( writer => removePartialMentionPostFixer( writer, doc, model.schema ) );
 		doc.registerPostFixer( writer => extendAttributeOnMentionPostFixer( writer, doc ) );
 		doc.registerPostFixer( writer => selectionMentionAttributePostFixer( writer, doc ) );
 
@@ -141,41 +141,55 @@ function selectionMentionAttributePostFixer( writer, doc ) {
 // @param {module:engine/model/writer~Writer} writer
 // @param {module:engine/model/document~Document} doc
 // @returns {Boolean} Returns true if selection was fixed.
-function removePartialMentionPostFixer( writer, doc ) {
+function removePartialMentionPostFixer( writer, doc, schema ) {
 	const changes = doc.differ.getChanges();
 
 	let wasChanged = false;
 
+	if ( !changes.length ) {
+		return;
+	}
+
 	for ( const change of changes ) {
 		// Check text node on current position;
+		const position = change.position;
+
 		if ( change.name == '$text' ) {
 			// Check textNode where the change occurred.
 			if ( change.type == 'insert' || change.type == 'remove' ) {
-				const textNode = change.position.textNode;
-
-				if ( !checkMentionAttributeOnNode( textNode ) ) {
-					writer.removeAttribute( 'mention', textNode );
-					wasChanged = true;
-				}
+				checkAndFix( position.textNode );
 			}
 
 			// Additional check: when removing text on mention boundaries.
 			if ( change.type == 'remove' ) {
-				const nodeBefore = change.position.nodeBefore;
-
-				if ( !checkMentionAttributeOnNode( nodeBefore ) ) {
-					writer.removeAttribute( 'mention', nodeBefore );
-					wasChanged = true;
-				}
+				checkAndFix( position.nodeBefore );
+				checkAndFix( position.nodeAfter );
+			}
+		}
 
-				const nodeAfter = change.position.nodeAfter;
+		// Check text nodes on inserted elements (might occur when splitting paragraph on enter key).
+		if ( change.name != '$text' && change.type == 'insert' && schema.checkChild( change.name, '$text' ) ) {
+			const insertedNode = position.nodeAfter;
 
-				if ( !checkMentionAttributeOnNode( nodeAfter ) ) {
-					writer.removeAttribute( 'mention', nodeAfter );
-					wasChanged = true;
-				}
+			for ( const child of insertedNode.getChildren() ) {
+				checkAndFix( child );
 			}
 		}
+
+		// Inserted inline elements might break mention.
+		if ( change.type == 'insert' && schema.isInline( change.name ) ) {
+			checkAndFix( position.nodeBefore );
+
+			const nodeAfterInserted = position.nodeAfter && position.nodeAfter.nextSibling;
+			checkAndFix( nodeAfterInserted );
+		}
+	}
+
+	function checkAndFix( textNode ) {
+		if ( !checkMentionAttributeOnNode( textNode ) ) {
+			writer.removeAttribute( 'mention', textNode );
+			wasChanged = true;
+		}
 	}
 
 	return wasChanged;

+ 30 - 0
packages/ckeditor5-mention/tests/mentionediting.js

@@ -285,6 +285,36 @@ describe( 'MentionEditing', () => {
 
 			expect( editor.getData() ).to.equal( '<p>foo <span class="mention" data-mention="John">@John</span>bar</p>' );
 		} );
+
+		it( 'should remove mention on inserting inline element inside a mention', () => {
+			model.schema.register( 'inline', {
+				allowWhere: '$text',
+				isInline: true
+			} );
+			editor.conversion.elementToElement( { model: 'inline', view: 'br' } );
+
+			editor.setData( '<p>foo <span class="mention" data-mention="John">@John</span> bar</p>' );
+
+			const paragraph = doc.getRoot().getChild( 0 );
+
+			model.change( writer => {
+				writer.insertElement( 'inline', paragraph, 7 );
+			} );
+
+			expect( editor.getData() ).to.equal( '<p>foo @Jo<br>hn bar</p>' );
+		} );
+
+		it( 'should remove mention when splitting paragraph with a mention', () => {
+			editor.setData( '<p>foo <span class="mention" data-mention="John">@John</span> bar</p>' );
+
+			const paragraph = doc.getRoot().getChild( 0 );
+
+			model.change( writer => {
+				writer.split( writer.createPositionAt( paragraph, 7 ) );
+			} );
+
+			expect( editor.getData() ).to.equal( '<p>foo @Jo</p><p>hn bar</p>' );
+		} );
 	} );
 
 	describe( 'extend attribute on mention post-fixer', () => {