Explorar o código

Introduced merge delta.

Piotr Jasiun %!s(int64=10) %!d(string=hai) anos
pai
achega
c9be613343

+ 62 - 0
packages/ckeditor5-utils/src/document/delta/mergedelta.js

@@ -0,0 +1,62 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+CKEDITOR.define( [
+	'document/delta/delta',
+	'document/delta/register',
+	'document/position',
+	'document/element',
+	'document/operation/removeoperation',
+	'document/operation/moveoperation',
+	'ckeditorerror'
+], ( Delta, register, Position, Element, RemoveOperation, MoveOperation, CKEditorError ) => {
+	/**
+	 * @class document.delta.MergeDelta
+	 */
+	class MergeDelta extends Delta {}
+
+	register( 'merge', ( doc, transaction, position ) => {
+		const delta = new MergeDelta();
+		const nodeBefore = position.nodeBefore;
+		const nodeAfter = position.nodeAfter;
+
+		if ( !( nodeBefore instanceof Element ) ) {
+			/**
+			 * Node before merge position must be an element.
+			 *
+			 * @error transaction-merge-no-element-before
+			 */
+			throw new CKEditorError(
+				'transaction-merge-no-element-before: Node before merge position must be an element.' );
+		}
+
+		if ( !( nodeAfter instanceof Element ) ) {
+			/**
+			 * Node after merge position must be an element.
+			 *
+			 * @error transaction-merge-no-element-after
+			 */
+			throw new CKEditorError(
+				'transaction-merge-no-element-after: Node after merge position must be an element.' );
+		}
+
+		const positionAfter = Position.createFromParentAndOffset( nodeAfter, 0 );
+		const positionBefore = Position.createFromParentAndOffset( nodeBefore, nodeBefore.getChildCount() );
+
+		const move = new MoveOperation( positionAfter, positionBefore, nodeAfter.getChildCount(), doc.version );
+		doc.applyOperation( move );
+		delta.addOperation( move );
+
+		const remove = new RemoveOperation( position, 1, doc.version );
+		doc.applyOperation( remove );
+		delta.addOperation( remove );
+
+		transaction.addDelta( delta );
+	} );
+
+	return MergeDelta;
+} );

+ 2 - 1
packages/ckeditor5-utils/src/document/transaction.js

@@ -10,7 +10,8 @@ CKEDITOR.define( [
 	'document/delta/insertdelta',
 	'document/delta/removedelta',
 	'document/delta/changedelta',
-	'document/delta/splitdelta'
+	'document/delta/splitdelta',
+	'document/delta/mergedelta'
 ], ( Transaction ) => {
 	return Transaction;
 } );

+ 71 - 0
packages/ckeditor5-utils/tests/document/deltas/mergedelta.js

@@ -0,0 +1,71 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* bender-tags: document, delta */
+
+/* bender-include: ../../_tools/tools.js */
+
+'use strict';
+
+const modules = bender.amd.require(
+	'document/document',
+	'document/position',
+	'document/element',
+	'document/attribute',
+	'ckeditorerror' );
+
+describe( 'Transaction', () => {
+	let Document, Position, Element, Attribute, CKEditorError;
+
+	let doc, root, p1, p2;
+
+	before( () => {
+		Document = modules[ 'document/document' ];
+		Position = modules[ 'document/position' ];
+		Element = modules[ 'document/element' ];
+		Attribute = modules[ 'document/attribute' ];
+		CKEditorError = modules.ckeditorerror;
+	} );
+
+	beforeEach( () => {
+		doc = new Document();
+		root = doc.createRoot( 'root' );
+
+		p1 = new Element( 'p', [ new Attribute( 'key1', 'value1' ) ], 'foo' );
+		p2 = new Element( 'p', [ new Attribute( 'key2', 'value2' ) ], 'bar' );
+
+		root.insertChildren( 0, [ p1, p2 ] );
+	} );
+
+	describe( 'merge', () => {
+		it( 'should merge foo and bar into foobar', () => {
+			doc.makeTransaction().merge( new Position( [ 1 ], root ) );
+
+			expect( root.getChildCount() ).to.equal( 1 );
+			expect( root.getChild( 0 ).name ).to.equal( 'p' );
+			expect( root.getChild( 0 ).getChildCount() ).to.equal( 6 );
+			expect( root.getChild( 0 )._getAttrCount() ).to.equal( 1 );
+			expect( root.getChild( 0 ).getAttr( 'key1' ) ).to.equal( 'value1' );
+			expect( root.getChild( 0 ).getChild( 0 ).character ).to.equal( 'f' );
+			expect( root.getChild( 0 ).getChild( 1 ).character ).to.equal( 'o' );
+			expect( root.getChild( 0 ).getChild( 2 ).character ).to.equal( 'o' );
+			expect( root.getChild( 0 ).getChild( 3 ).character ).to.equal( 'b' );
+			expect( root.getChild( 0 ).getChild( 4 ).character ).to.equal( 'a' );
+			expect( root.getChild( 0 ).getChild( 5 ).character ).to.equal( 'r' );
+		} );
+
+		it( 'should throw if there is no element after', () => {
+			expect( () => {
+				doc.makeTransaction().merge( new Position( [ 2 ], root ) );
+			} ).to.throw( CKEditorError, /^transaction-merge-no-element-after/ );
+		} );
+
+		it( 'should throw if there is no element before', () => {
+			expect( () => {
+				doc.makeTransaction().merge( new Position( [ 0, 2 ], root ) );
+			} ).to.throw( CKEditorError, /^transaction-merge-no-element-before/ );
+		} );
+	} );
+} );