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

Merge pull request #179 from ckeditor/t/ckeditor5/1096

Internal: Use `Schema#isInline()` to determine text-like elements. See https://github.com/ckeditor/ckeditor5-engine/pull/1654.
Piotrek Koszuliński 7 лет назад
Родитель
Сommit
d303e3c0bb

+ 6 - 3
packages/ckeditor5-typing/src/utils/injecttypingmutationshandling.js

@@ -136,8 +136,10 @@ class MutationHandler {
 			modelFromDomChildren.pop();
 		}
 
+		const schema = this.editor.model.schema;
+
 		// Skip situations when common ancestor has any container elements.
-		if ( !isSafeForTextMutation( modelFromDomChildren ) || !isSafeForTextMutation( currentModelChildren ) ) {
+		if ( !isSafeForTextMutation( modelFromDomChildren, schema ) || !isSafeForTextMutation( currentModelChildren, schema ) ) {
 			return;
 		}
 
@@ -273,9 +275,10 @@ function getMutationsContainer( mutations ) {
 // Returns true if provided array contains content that won't be problematic during diffing and text mutation handling.
 //
 // @param {Array.<module:engine/model/node~Node>} children
+// @param {module:engine/model/schema~Schema} schema
 // @returns {Boolean}
-function isSafeForTextMutation( children ) {
-	return children.every( child => child.is( 'text' ) || child.is( 'softBreak' ) );
+function isSafeForTextMutation( children, schema ) {
+	return children.every( child => schema.isInline( child ) );
 }
 
 // Calculates first change index and number of characters that should be inserted and deleted starting from that index.

+ 1 - 1
packages/ckeditor5-typing/tests/deletecommand-integration.js

@@ -39,7 +39,7 @@ describe( 'DeleteCommand integration', () => {
 				// Mock paragraph feature.
 				model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );
 				model.schema.extend( 'paragraph', { allowIn: '$block' } );
-				model.schema.register( 'softBreak', { allowWhere: '$text' } );
+				model.schema.register( 'softBreak', { allowWhere: '$text', isInline: true } );
 
 				model.schema.register( 'img', {
 					allowWhere: '$text',

+ 77 - 0
packages/ckeditor5-typing/tests/input.js

@@ -17,6 +17,7 @@ import Writer from '@ckeditor/ckeditor5-engine/src/model/writer';
 
 import ViewText from '@ckeditor/ckeditor5-engine/src/view/text';
 import ViewElement from '@ckeditor/ckeditor5-engine/src/view/element';
+import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
 
 import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
 import { getCode } from '@ckeditor/ckeditor5-utils/src/keyboard';
@@ -570,6 +571,82 @@ describe( 'Input feature', () => {
 				'</p>'
 			);
 		} );
+
+		it( 'should handle correctly if last element is inline', () => {
+			editor.model.schema.register( 'placeholder', { allowWhere: '$text', isInline: true } );
+
+			editor.conversion.elementToElement( {
+				model: 'placeholder',
+				view: 'placeholder'
+			} );
+
+			editor.setData( '<p>foo<placeholder></placeholder></p>' );
+
+			editor.model.change( writer => {
+				writer.setSelection( editor.model.document.getRoot().getChild( 0 ), 'end' );
+			} );
+
+			expect( getViewData( view ) ).to.equal( '<p>foo<placeholder></placeholder>[]</p>' );
+
+			// We need to change the DOM content manually because typing algorithm actually does not check
+			// `newChildren` and `oldChildren` list but takes them from DOM and model.
+			const p = viewRoot.getChild( 0 );
+			const domP = editor.editing.view.domConverter.mapViewToDom( p );
+			domP.appendChild( document.createTextNode( '!' ) );
+
+			viewDocument.fire( 'mutations', [
+				{
+					type: 'children',
+					oldChildren: [ ...viewRoot.getChild( 0 ).getChildren() ],
+					newChildren: [
+						new ViewText( 'Foo' ),
+						new ViewContainerElement( 'placeholder' ),
+						new ViewText( 'f' )
+					],
+					node: viewRoot.getChild( 0 )
+				}
+			] );
+
+			expect( getViewData( view ) ).to.equal( '<p>foo<placeholder></placeholder>!{}</p>' );
+		} );
+
+		it( 'should handle correctly if some elements are inline', () => {
+			editor.model.schema.register( 'placeholder', { allowWhere: '$text', isInline: true } );
+
+			editor.conversion.elementToElement( {
+				model: 'placeholder',
+				view: 'placeholder'
+			} );
+
+			editor.setData( '<p>foo<placeholder></placeholder>bar<placeholder></placeholder>baz</p>' );
+
+			editor.model.change( writer => {
+				writer.setSelection( editor.model.document.getRoot().getChild( 0 ), 'end' );
+			} );
+
+			// We need to change the DOM content manually because typing algorithm actually does not check
+			// `newChildren` and `oldChildren` list but takes them from DOM and model.
+			const p = viewRoot.getChild( 0 );
+			const domP = editor.editing.view.domConverter.mapViewToDom( p );
+			domP.appendChild( document.createTextNode( '!' ) );
+
+			viewDocument.fire( 'mutations', [
+				{
+					type: 'children',
+					oldChildren: [ ...viewRoot.getChild( 0 ).getChildren() ],
+					newChildren: [
+						new ViewText( 'foo' ),
+						new ViewContainerElement( 'placeholder' ),
+						new ViewText( 'bar' ),
+						new ViewContainerElement( 'placeholder' ),
+						new ViewText( 'baz' )
+					],
+					node: viewRoot.getChild( 0 )
+				}
+			] );
+
+			expect( getViewData( view ) ).to.equal( '<p>foo<placeholder></placeholder>bar<placeholder></placeholder>baz!{}</p>' );
+		} );
 	} );
 
 	describe( 'keystroke handling', () => {