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

Attribute on mention post-fixer will only check text nodes at change range boundaries.

Maciej Gołaszewski 6 лет назад
Родитель
Сommit
ff2602b68d

+ 10 - 27
packages/ckeditor5-mention/src/mentionediting.js

@@ -195,10 +195,15 @@ function extendAttributeOnMentionPostFixer( writer, doc ) {
 
 
 	for ( const change of changes ) {
 	for ( const change of changes ) {
 		if ( change.type === 'attribute' && change.attributeKey != 'mention' ) {
 		if ( change.type === 'attribute' && change.attributeKey != 'mention' ) {
-			// Check all mentions in changed range - attribute change may span over multiple text node.
-			for ( const textNode of getBrokenMentionsFromRange( change.range ) ) {
-				if ( textNode.getAttribute( change.attributeKey ) !== change.attributeNewValue ) {
-					writer.setAttribute( change.attributeKey, change.attributeNewValue, textNode );
+			// Check node at the left side of a range...
+			const nodeBefore = change.range.start.nodeBefore;
+			// ... and on right side of range.
+			const nodeAfter = change.range.end.nodeAfter;
+
+			for ( const node of [ nodeBefore, nodeAfter ] ) {
+				if ( isBrokenMentionNode( node ) && node.getAttribute( change.attributeKey ) != change.attributeNewValue ) {
+					writer.setAttribute( change.attributeKey, change.attributeNewValue, node );
+
 					wasChanged = true;
 					wasChanged = true;
 				}
 				}
 			}
 			}
@@ -214,7 +219,7 @@ function extendAttributeOnMentionPostFixer( writer, doc ) {
 // @param {module:engine/model/node~Node} node a node to check
 // @param {module:engine/model/node~Node} node a node to check
 // @returns {Boolean}
 // @returns {Boolean}
 function isBrokenMentionNode( node ) {
 function isBrokenMentionNode( node ) {
-	if ( !node || !( node.is( 'text' ) || node.is( 'textProxy' ) ) || !node.hasAttribute( 'mention' ) ) {
+	if ( !node || !node.is( 'text' ) || !node.hasAttribute( 'mention' ) ) {
 		return false;
 		return false;
 	}
 	}
 
 
@@ -226,28 +231,6 @@ function isBrokenMentionNode( node ) {
 	return text != expectedText;
 	return text != expectedText;
 }
 }
 
 
-// Yields all text nodes with broken mentions from a range - even if mention sticks out of the range boundary.
-//
-// @param {module:engine/range~Range} range
-function* getBrokenMentionsFromRange( range ) {
-	// Check node at the left side of a range.
-	if ( isBrokenMentionNode( range.start.nodeBefore ) ) {
-		yield range.start.nodeBefore;
-	}
-
-	// Yield text nodes with broken mention from the range.
-	for ( const textProxy of range.getItems() ) {
-		if ( isBrokenMentionNode( textProxy ) ) {
-			yield textProxy.textNode;
-		}
-	}
-
-	// Check node at the right side of a range.
-	if ( isBrokenMentionNode( range.end.nodeAfter ) ) {
-		yield range.end.nodeAfter;
-	}
-}
-
 // Fixes mention on text node it needs a fix.
 // Fixes mention on text node it needs a fix.
 //
 //
 // @param {module:engine/model/text~Text} textNode
 // @param {module:engine/model/text~Text} textNode

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

@@ -449,6 +449,52 @@ describe( 'MentionEditing', () => {
 				'</p>'
 				'</p>'
 			);
 			);
 		} );
 		} );
+
+		it( 'should work with multiple ranges in change set', () => {
+			model.schema.extend( '$text', { allowAttributes: [ 'foo' ] } );
+			editor.conversion.attributeToElement( {
+				model: {
+					key: 'foo',
+					values: [ 'a', 'b' ]
+				},
+				view: {
+					a: {
+						name: 'span',
+						classes: 'mark-a'
+					},
+					b: {
+						name: 'span',
+						classes: 'mark-b'
+					}
+				},
+				converterPriority: 'high'
+			} );
+
+			editor.setData(
+				'<p>' +
+					'<span class="mark-a">foo <span class="mention" data-mention="John">@John</span></span>' +
+					'<span class="mention" data-mention="John">@John</span> bar' +
+				'</p>'
+			);
+
+			model.change( writer => {
+				const paragraph = doc.getRoot().getChild( 0 );
+				const start = writer.createPositionAt( paragraph, 7 );
+				const range = writer.createRange( start, start.getShiftedBy( 5 ) );
+
+				writer.setAttribute( 'foo', 'b', range );
+			} );
+
+			expect( editor.getData() ).to.equal(
+				'<p>' +
+					'<span class="mark-a">foo </span>' +
+					'<span class="mark-b">' +
+						'<span class="mention" data-mention="John">@John</span>' +
+						'<span class="mention" data-mention="John">@John</span>' +
+					'</span> bar' +
+				'</p>'
+			);
+		} );
 	} );
 	} );
 
 
 	function createTestEditor( mentionConfig ) {
 	function createTestEditor( mentionConfig ) {