8
0
Piotr Jasiun 9 rokov pred
rodič
commit
7be8657f00

+ 150 - 0
packages/ckeditor5-engine/src/treeview/writer.js

@@ -0,0 +1,150 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * @class treeView.Writer
+ */
+ export default class Writer {
+	constructor() {
+		this._priorities = new WeakMap();
+	}
+
+	isContainer( node ) {
+		return !this._priorities.has( node );
+	}
+
+	isAttribute( node ) {
+		return this._priorities.has( node );
+	}
+
+	getPriority( node ) {
+		return this._priorities.get( node );
+	}
+
+	insertIntoContainer( position, node ) {
+		const container = getParentContainer( position );
+
+		const insertionPosition = this.breakAttributes( position, container );
+
+		container.insertChildren( insertionPosition, nodes );
+
+		const length = utils.isIterable( nodes ) ? utils.getIterableCount( nodes ) : 1;
+		const endPosition = insertionPosition.getShiftedBy( length );
+
+		this.mergeAttributes( endPosition );
+		this.mergeAttributes( insertionPosition );
+	}
+
+	getParentContainer( position ) {
+		let container = position.parent;
+
+		while ( !this.isContainer( container ) ) {
+			container = container.parent;
+		}
+
+		return container;
+	}
+
+	// return position
+	breakAttributes( position, limit ) {
+		if ( !limit ) {
+			limit = this.getParentContainer( position );
+		}
+
+		let offset = position.offset;
+		let node = position.parent;
+
+		if ( this.isContainer( node ) ) {
+			return position;
+		}
+
+		const parentIsText = node instanceof Text;
+		const length = parentIsText ? node.data.length : node.getChildCount();
+
+		if ( offset == length ) {
+			const parentPosition = new Position( node.parent, node.getIndex() + 1 );
+
+			return this.breakAttributes( parentPosition, limit );
+		} else if ( offset == 0 ) {
+			const parentPosition = new Position( node.parent, node.getIndex() );
+
+			return this.breakAttributes( parentPosition, limit );
+		} else {
+			// Break.
+			const offsetAfter = node.getIndex() + 1;
+
+			if ( parentIsText ) {
+				// Break text.
+				const textToMove = node.data.slice( offset );
+				node.data = node.data.slice( 0, offset );
+				node.parent.insertChildren( offsetAfter, new Text( textToMove ) );
+
+				return new Position( node.parent, offsetAfter );
+			} else {
+				// Break element.
+				const nodeClone = node.cloneNode();
+				// Clone priority.
+				this._priorities.set( nodeClone, this._priorities.get( node ) );
+
+				node.parent.insertChildren( offsetAfter, nodeClone );
+
+				const nodesToMove = sourceElement.removeChildren( sourceOffset, this.howMany );
+
+				nodeClone.appendChildren( nodesToMove );
+
+				return new Position( node.parent, offsetAfter );
+			}
+		}
+	}
+
+	// Should also merge text nodes
+	mergeAttributes( position ) {
+		let offset = position.offset;
+		let parentNode = position.parent;
+
+		if ( parentNode instanceof Text ) {
+			return position;
+		}
+
+		let nodeBefore = parentNode.getChild( offset - 1 );
+		let nodeAfter = parentNode.getChild( offset );
+
+		if ( nodeBefore instanceof Text && nodeAfter instanceof Text ) {
+			const nodeBeforeLength = nodeBefore.data.length;
+
+			nodeBefore.data += nodeAfter.data;
+			parentNode.removeChildren( offset );
+
+			return new Position( nodeBefore, nodeBeforeLength );
+		} else if ( nodeBefore.same( nodeAfter ) ) {
+			const nodeBeforePriority = this._priorities.get( nodeBefore );
+			const nodeAfterPriority = this._priorities.get( nodeAfter );
+
+			if ( nodeBeforePriority === undefined || nodeBeforePriority !== nodeAfterPriority ) {
+				return position;
+			}
+
+			nodeBefore.appendChildren( nodeAfter.getChildren() );
+
+			nodeAfter.remove();
+		}
+
+		return position;
+	}
+
+	removeFromContainer( range ) {
+	}
+
+	removeEmptyAttributes( position ) {
+	}
+
+	wrap( range, element, priority ) {
+	}
+
+	unwrap( range, element ) {
+	}
+}