8
0
Pārlūkot izejas kodu

Added: view.writer#rename, fixed view.writer#move when it's moving nodes
around same parent.

Szymon Cofalik 9 gadi atpakaļ
vecāks
revīzija
1d7be5766b

+ 28 - 1
packages/ckeditor5-engine/src/view/writer.js

@@ -28,7 +28,8 @@ export default {
 	move,
 	wrap,
 	wrapPosition,
-	unwrap
+	unwrap,
+	rename
 };
 
 /**
@@ -355,6 +356,10 @@ export function remove( range ) {
  * {@link engine.view.Range#start start} and {@link engine.view.Range#end end} positions.
  */
 export function move( sourceRange, targetPosition ) {
+	if ( sourceRange.start.parent == targetPosition.parent ) {
+		targetPosition.offset -= sourceRange.end.offset - sourceRange.start.offset;
+	}
+
 	const nodes = remove( sourceRange );
 
 	return insert( targetPosition, nodes );
@@ -549,6 +554,28 @@ export function unwrap( range, attribute ) {
 	return new Range( start, end );
 }
 
+/**
+ * Renames element by creating a copy of renamed element but with changed name and then moving contents of the
+ * old element to the new one. Keep in mind that this will invalidate all {@link engine.view.Position positions} which
+ * has renamed element as {@link engine.view.Position#parent a parent}.
+ *
+ * New element has to be created because `Element#tagName` property in DOM is readonly.
+ *
+ * Since this function creates a new element and removes the given one, the new element is returned to keep reference.
+ *
+ * @param {engine.view.ContainerElement} viewElement Element to be renamed.
+ * @param {String} newName New name for element.
+ */
+export function rename( viewElement, newName ) {
+	const newElement = new ContainerElement( newName, viewElement.getAttributes() );
+
+	insert( Position.createAfter( viewElement ), newElement );
+	move( Range.createIn( viewElement ), Position.createAt( newElement ) );
+	remove( Range.createOn( viewElement ) );
+
+	return newElement;
+}
+
 // Returns first parent container of specified {@link engine.view.Position Position}.
 // Position's parent node is checked as first, then next parents are checked.
 // Note that {@link engine.view.DocumentFragment DocumentFragment} is treated like a container.

+ 10 - 0
packages/ckeditor5-engine/tests/view/writer/move.js

@@ -7,6 +7,7 @@
 
 import { move } from '/ckeditor5/engine/view/writer.js';
 import { stringify, parse } from '/tests/engine/_utils/view.js';
+import ViewPosition from '/ckeditor5/engine/view/position.js';
 
 describe( 'writer', () => {
 	/**
@@ -102,5 +103,14 @@ describe( 'writer', () => {
 		it( 'should move part of the text node in document fragment', () => {
 			test( 'fo{ob}ar', 'fo{}ar', 'foar', 'fo{ob}ar' );
 		} );
+
+		it( 'should correctly move text nodes inside same parent', () => {
+			let { view, selection } = parse( '<container:p>[<attribute:b>a</attribute:b>]b<attribute:b>c</attribute:b></container:p>' );
+
+			const newRange = move( selection.getFirstRange(), ViewPosition.createAt( view, 2 ) );
+
+			const expectedView = '<container:p>b[<attribute:b>a}c</attribute:b></container:p>';
+			expect( stringify( view, newRange, { showType: true } ) ).to.equal( expectedView );
+		} );
 	} );
 } );