Bladeren bron

Added: `conversion.Mapper#findMappedViewAncestor`.

Szymon Cofalik 6 jaren geleden
bovenliggende
commit
60aa13544f

+ 18 - 8
packages/ckeditor5-engine/src/conversion/mapper.js

@@ -91,14 +91,8 @@ export default class Mapper {
 				return;
 			}
 
-			let viewBlock = data.viewPosition.parent;
-			let modelParent = this._viewToModelMapping.get( viewBlock );
-
-			while ( !modelParent ) {
-				viewBlock = viewBlock.parent;
-				modelParent = this._viewToModelMapping.get( viewBlock );
-			}
-
+			const viewBlock = this.findMappedViewAncestor( data.viewPosition );
+			const modelParent = this._viewToModelMapping.get( viewBlock );
 			const modelOffset = this._toModelOffset( data.viewPosition.parent, data.viewPosition.offset, viewBlock );
 
 			data.modelPosition = ModelPosition._createAt( modelParent, modelOffset );
@@ -339,6 +333,22 @@ export default class Mapper {
 	}
 
 	/**
+	 * For given `viewPosition`, finds and returns the closest ancestor that is mapped to an element in model.
+	 *
+	 * @param {module:engine/model/view/position~Position} viewPosition Position for which mapped ancestor should be found.
+	 * @returns {module:engine/model/view/element~Element}
+	 */
+	findMappedViewAncestor( viewPosition ) {
+		let parent = viewPosition.parent;
+
+		while ( !this._viewToModelMapping.has( parent ) ) {
+			parent = parent.parent;
+		}
+
+		return parent;
+	}
+
+	/**
 	 * Calculates model offset based on the view position and the block element.
 	 *
 	 * Example:

+ 23 - 0
packages/ckeditor5-engine/tests/conversion/mapper.js

@@ -721,4 +721,27 @@ describe( 'Mapper', () => {
 			expect( mapper.getModelLength( viewDiv ) ).to.equal( 6 );
 		} );
 	} );
+
+	it( 'findMappedViewAncestor should return for given view position the closest ancestor which is mapped to a model element', () => {
+		const mapper = new Mapper();
+
+		const modelP = new ModelElement( 'p' );
+		const modelDiv = new ModelElement( 'div' );
+
+		const viewText = new ViewText( 'foo' );
+		const viewSpan = new ViewElement( 'span', null, viewText );
+		const viewP = new ViewElement( 'p', null, viewSpan );
+		const viewDiv = new ViewElement( 'div', null, viewP );
+
+		mapper.bindElements( modelP, viewP );
+		mapper.bindElements( modelDiv, viewDiv );
+
+		// <div><p><span>f{}oo</span></p></div>.
+
+		const viewPosition = new ViewPosition( viewText, 1 );
+
+		const viewMappedAncestor = mapper.findMappedViewAncestor( viewPosition );
+
+		expect( viewMappedAncestor ).to.equal( viewP );
+	} );
 } );