Browse Source

Other: Mapping callbacks for inline widgets should be feature-specific.

Szymon Cofalik 7 năm trước cách đây
mục cha
commit
cb4e256477

+ 0 - 5
packages/ckeditor5-engine/src/controller/editingcontroller.js

@@ -16,7 +16,6 @@ import { clearAttributes, convertCollapsedSelection, convertRangeSelection, inse
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import { convertSelectionChange } from '../conversion/upcasthelpers';
-import { mapModelPositionOnInlineElement, mapViewPositionInsideInlineElement } from '../conversion/mapper-helpers';
 
 /**
  * Controller for the editing pipeline. The editing pipeline controls {@link ~EditingController#model model} rendering,
@@ -122,10 +121,6 @@ export default class EditingController {
 
 			return viewRoot;
 		} );
-
-		// Attach view-to-model & model-to-view position mapper for inline elements (inline widget).
-		this.mapper.on( 'viewToModelPosition', mapViewPositionInsideInlineElement( this.model ) );
-		this.mapper.on( 'modelToViewPosition', mapModelPositionOnInlineElement( this.model, this.view ) );
 	}
 
 	/**

+ 0 - 114
packages/ckeditor5-engine/src/conversion/mapper-helpers.js

@@ -1,114 +0,0 @@
-/**
- * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/**
- * @module engine/conversion/mapper-helpers
- */
-
-/**
- * Maps view position to model position if view positions is wrongly set inside inline element - ie. inline widget.
- *
- *		editor.editing.mapper.on( 'viewToModel', mapViewPositionInsideInlineElement( model ) );
- *
- * It will try to map view offset of selection to an expected model position in order to create consistent selection.
- *
- * If DOM selection starts before inline element then view position offset will be 0 and be considered at it start and thus model position
- * will be placed "after" element to select it:
- *
- * 1. When selection starts before inline widget (offset=0):
- *
- *		//                           +- view position
- *		//                           |
- *		<p>f[oo <span class="widget">]widget</span></p>
- *
- *		// will map to:
- *
- *		//                                             +- model position
- *		//                                             |
- *		<paragraph>f[oo <inline-widget></inline-widget>]</paragraph>
- *
- * 2. When selection start before inline widget (offset=0):
- *
- *		//                            +- view position
- *		//                            |
- *		<p><span class="widget">widget[</span> ba]r</p>
- *
- *		// will map to:
- *
- *		//         +- model position
- *		//         |
- *		<paragraph>[<inline-widget></inline-widget> ba]r</paragraph>
- *
- * @param {module:engine/model/model~Model} model
- * @return {Function}
- */
-export function mapViewPositionInsideInlineElement( model ) {
-	const schema = model.schema;
-
-	return ( evt, data ) => {
-		const { mapper, viewPosition } = data;
-
-		const viewParent = viewPosition.parent;
-
-		const modelParent = mapper.toModelElement( viewParent );
-
-		if ( modelParent && schema.isInline( modelParent ) ) {
-			const isAtStart = viewPosition.offset === 0;
-
-			data.modelPosition = model.createPositionAt( modelParent, isAtStart ? 'after' : 'before' );
-		}
-	};
-}
-
-/**
- * Maps model position to view position if the position set after/before inline element (ie. inline widget).
- *
- *		editor.editing.mapper.on( 'modelToView', mapModelPositionOnInlineElement( model, view ) );
- *
- * This method ensures that selection set on an inline element is set outside surrounding text nodes as by default the position would be set
- * at the end or beginning of a text node that is previous/next to the inline element:
- *
- * Without this mapper helper the selection would set inside text nodes:
- *
- *		//             +-------------------------------+--- model positions
- *		//             \                               |
- *		<paragraph>foo [<inline-widget></inline-widget>]</paragraph>
- *
- *		// will map to:
- *		//     +---------------------+- view positions (inside text nodes)
- *		//     |                     |
- *		<p>foo {<span class="widget">}widget</span></p>
- *
- * With this mapper helper the selection will set outside text nodes:
- *
- *		//     +---------------------+--- view positions (outside text nodes)
- *		//     |                     |
- *		<p>foo [<span class="widget">]widget</span></p>
- *
- * @param {module:engine/model/model~Model} model
- * @param {module:engine/model/model~Model} view
- * @return {Function}
- */
-export function mapModelPositionOnInlineElement( model, view ) {
-	return ( evt, data ) => {
-		if ( data.isPhantom ) {
-			return;
-		}
-		const modelPosition = data.modelPosition;
-
-		const isBeforeNode = modelPosition.stickiness === 'toNext';
-		const node = isBeforeNode ? modelPosition.nodeAfter : modelPosition.nodeBefore;
-
-		if ( node && model.schema.isInline( node ) ) {
-			const viewElement = data.mapper.toViewElement( node );
-
-			if ( !viewElement ) {
-				return;
-			}
-
-			data.viewPosition = isBeforeNode ? view.createPositionBefore( viewElement ) : view.createPositionAfter( viewElement );
-		}
-	};
-}

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

@@ -1,157 +0,0 @@
-/**
- * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-import Model from '../../src/model/model';
-
-import { setData as modelSetData } from '../../src/dev-utils/model';
-import View from '../../src/view/view';
-import createViewRoot from '../view/_utils/createroot';
-import { setData as viewSetData } from '../../src/dev-utils/view';
-import Mapper from '../../src/conversion/mapper';
-import ViewPosition from '../../src/view/position';
-import { mapModelPositionOnInlineElement, mapViewPositionInsideInlineElement } from '../../src/conversion/mapper-helpers';
-
-describe( 'mapper-helpers', () => {
-	let model, view, viewDocument, mapper, modelRoot, viewRoot, viewInlineWidget, viewP, modelParagraph, inlineWidget;
-
-	beforeEach( () => {
-		model = new Model();
-		modelRoot = model.document.createRoot();
-		model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
-		model.schema.register( 'inline-widget', { isInline: true, isObject: true, allowWhere: '$text' } );
-
-		modelSetData( model, '<paragraph>foo[<inline-widget></inline-widget>]bar</paragraph>' );
-
-		view = new View();
-		viewDocument = view.document;
-		viewRoot = createViewRoot( viewDocument, 'div', 'main' );
-
-		viewSetData( view, '<p>foo<placeholder>widget description</placeholder>bar</p>' );
-
-		viewP = viewRoot.getChild( 0 );
-		viewInlineWidget = viewP.getChild( 1 );
-		modelParagraph = modelRoot.getChild( 0 );
-		inlineWidget = modelParagraph.getChild( 1 );
-
-		mapper = new Mapper();
-		mapper.bindElements( modelRoot, viewRoot );
-		mapper.bindElements( modelParagraph, viewRoot.getChild( 0 ) );
-		mapper.bindElements( inlineWidget, viewInlineWidget );
-	} );
-
-	describe( 'mapViewPositionInsideInlineElement()', () => {
-		beforeEach( () => {
-			mapper.on( 'viewToModelPosition', mapViewPositionInsideInlineElement( model ) );
-		} );
-
-		it( 'should return position after inline-widget when view position is at start of inline-widget', () => {
-			const viewPosition = new ViewPosition( viewInlineWidget, 0 );
-
-			const modelPosition = mapper.toModelPosition( viewPosition );
-
-			expect( modelPosition.parent ).to.equal( modelParagraph );
-			// The offset in <paragraph> should be after the inline-widget:
-			// PARAGRAPH
-			//   |- foo            before: [ 0 ]         after: [ 3 ]
-			//   |- INLINE-WIDGET  before: [ 3 ]         after: [ 4 ]
-			//   |- bar            before: [ 4 ]         after: [ 7 ]
-			expect( modelPosition.offset ).to.equal( 4 );
-		} );
-
-		it( 'should return position before inline-widget when view position is not at start of inline-widget', () => {
-			const viewPosition = new ViewPosition( viewInlineWidget, 2 ); // in real-case scenarios is 1 even if placeholder has text.
-
-			const modelPosition = mapper.toModelPosition( viewPosition );
-
-			expect( modelPosition.parent ).to.equal( modelParagraph );
-			// The offset in <paragraph> should be before the inline-widget:
-			// PARAGRAPH
-			//   |- foo            before: [ 0 ]         after: [ 3 ]
-			//   |- INLINE-WIDGET  before: [ 3 ]         after: [ 4 ]
-			//   |- bar            before: [ 4 ]         after: [ 7 ]
-			expect( modelPosition.offset ).to.equal( 3 );
-		} );
-
-		it( 'should do nothing if position maps to text node', () => {
-			const viewPosition = new ViewPosition( viewP.getChild( 0 ), 1 );
-
-			const data = { viewPosition, mapper };
-
-			const mapperHelper = mapViewPositionInsideInlineElement( model );
-			mapperHelper( {}, data );
-
-			expect( data.modelPosition ).to.be.undefined;
-		} );
-
-		it( 'should do nothing if position maps to a non-inline element', () => {
-			const viewPosition = new ViewPosition( viewP, 0 );
-
-			const data = { viewPosition, mapper };
-
-			const mapperHelper = mapViewPositionInsideInlineElement( model );
-			mapperHelper( {}, data );
-
-			expect( data.modelPosition ).to.be.undefined;
-		} );
-	} );
-
-	describe( 'mapModelPositionOnInlineElement()', () => {
-		beforeEach( () => {
-			mapper.on( 'modelToViewPosition', mapModelPositionOnInlineElement( model, view ) );
-		} );
-
-		it( 'should return position after inline-widget when view position is at start of inline-widget', () => {
-			const modelPosition = model.createPositionFromPath( modelRoot, [ 0, 4 ], 'toPrevious' );
-
-			const viewPosition = mapper.toViewPosition( modelPosition );
-
-			expect( viewPosition.parent ).to.equal( viewP );
-			expect( viewPosition.offset ).to.equal( 2 );
-			expect( viewPosition.nodeBefore ).to.equal( viewInlineWidget );
-		} );
-
-		it( 'should return position before inline-widget when view position is not at start of inline-widget', () => {
-			const modelPosition = model.createPositionFromPath( modelRoot, [ 0, 3 ], 'toNext' );
-
-			const viewPosition = mapper.toViewPosition( modelPosition );
-
-			expect( viewPosition.parent ).to.equal( viewP );
-			expect( viewPosition.offset ).to.equal( 1 );
-			expect( viewPosition.nodeAfter ).to.equal( viewInlineWidget );
-		} );
-
-		it( 'should do nothing if position is phantom', () => {
-			const modelPosition = model.createPositionFromPath( modelRoot, [ 0, 4 ], 'toPrevious' );
-
-			const data = { isPhantom: true };
-
-			mapper.toViewPosition( modelPosition, data );
-
-			expect( data.modelPosition ).to.be.undefined;
-		} );
-
-		it( 'should do nothing if position\'s parent is not mapped', () => {
-			mapper.unbindViewElement( viewInlineWidget );
-
-			const modelPosition = model.createPositionFromPath( modelRoot, [ 0, 4 ], 'toPrevious' );
-
-			const data = {};
-
-			mapper.toViewPosition( modelPosition, data );
-
-			expect( data.modelPosition ).to.be.undefined;
-		} );
-
-		it( 'should do nothing if position maps to a non-inline element', () => {
-			const modelPosition = model.createPositionFromPath( modelRoot, [ 0 ], 'toPrevious' );
-
-			const data = {};
-
-			mapper.toViewPosition( modelPosition, data );
-
-			expect( data.modelPosition ).to.be.undefined;
-		} );
-	} );
-} );