8
0
Quellcode durchsuchen

Added: Introduced `view.AttributeElement#id`.

Szymon Cofalik vor 7 Jahren
Ursprung
Commit
717c06f847

+ 46 - 7
packages/ckeditor5-engine/src/view/attributeelement.js

@@ -34,9 +34,7 @@ export default class AttributeElement extends Element {
 		super( name, attrs, children );
 
 		/**
-		 * Element priority. Attributes have to have the same priority to be
-		 * {@link module:engine/view/element~Element#isSimilar similar}. Setting different priorities on similar
- 		 * nodes may prevent merging, e.g. two `<abbr>` nodes next each other shouldn't be merged.
+		 * Element priority. Decides in what order elements are wrapped by {@link module:engine/view/writer~Writer}.
 		 *
 		 * @protected
 		 * @member {Number}
@@ -44,6 +42,15 @@ export default class AttributeElement extends Element {
 		this._priority = DEFAULT_PRIORITY;
 
 		/**
+		 * Element identifier. If set, it is used by {@link module:engine/view/element~Element#isSimilar},
+		 * and then two elements are considered similar if, and only if they have the same `_id`.
+		 *
+		 * @protected
+		 * @member {String|Number}
+		 */
+		this._id = null;
+
+		/**
 		 * Returns block {@link module:engine/view/filler filler} offset or `null` if block filler is not needed.
 		 *
 		 * @method #getFillerOffset
@@ -53,16 +60,27 @@ export default class AttributeElement extends Element {
 	}
 
 	/**
-	 * Priority of this element.
+	 * Element priority. Decides in what order elements are wrapped by {@link module:engine/view/writer~Writer}.
 	 *
 	 * @readonly
-	 * @return {Number}
+	 * @returns {Number}
 	 */
 	get priority() {
 		return this._priority;
 	}
 
 	/**
+	 * Element identifier. If set, it is used by {@link module:engine/view/element~Element#isSimilar},
+	 * and then two elements are considered similar if, and only if they have the same `_id`.
+	 *
+	 * @readonly
+	 * @returns {String|Number}
+	 */
+	get id() {
+		return this._id;
+	}
+
+	/**
 	 * @inheritDoc
 	 */
 	is( type, name = null ) {
@@ -75,13 +93,31 @@ export default class AttributeElement extends Element {
 
 	/**
 	 * Checks if this element is similar to other element.
-	 * Both elements should have the same name, attributes and priority to be considered as similar.
-	 * Two similar elements can contain different set of children nodes.
+	 *
+	 * If none of elements has set {@link module:engine/view/attributeelement~AttributeElement#id}, then both elements
+	 * should have the same name, attributes and priority to be considered as similar. Two similar elements can contain
+	 * different set of children nodes.
+	 *
+	 * If at least one element has {@link module:engine/view/attributeelement~AttributeElement#id} set, then both
+	 * elements have to have the same {@link module:engine/view/attributeelement~AttributeElement#id} value to be
+	 * considered similar.
+	 *
+	 * Similarity is important for {@link module:engine/view/writer~Writer}. For example:
+	 *
+	 * * two following similar elements can be merged together into one, longer element,
+	 * * {@link module:engine/view/writer~Writer#unwrap} checks similarity of passed element and processed element to
+	 * decide whether processed element should be unwrapped,
+	 * * etc.
 	 *
 	 * @param {module:engine/view/element~Element} otherElement
 	 * @returns {Boolean}
 	 */
 	isSimilar( otherElement ) {
+		// If any element has an `id` set, just compare the ids.
+		if ( this.id !== null || otherElement.id !== null ) {
+			return this.id === otherElement.id;
+		}
+
 		return super.isSimilar( otherElement ) && this.priority == otherElement.priority;
 	}
 
@@ -99,6 +135,9 @@ export default class AttributeElement extends Element {
 		// Clone priority too.
 		cloned._priority = this._priority;
 
+		// And id too.
+		cloned._id = this._id;
+
 		return cloned;
 	}
 }

+ 26 - 0
packages/ckeditor5-engine/tests/view/attributeelement.js

@@ -80,6 +80,32 @@ describe( 'AttributeElement', () => {
 
 			expect( b1.isSimilar( b2 ) ).to.be.false;
 		} );
+
+		it( 'should return true if ids are the same even if other properties are different', () => {
+			const element1 = new AttributeElement( 'b' );
+			element1._id = 'xyz';
+
+			const element2 = new AttributeElement( 'b', { foo: 'bar' } );
+			element2._id = 'xyz';
+
+			const element3 = new AttributeElement( 'span' );
+			element3._id = 'xyz';
+
+			expect( element1.isSimilar( element2 ) ).to.be.true;
+			expect( element1.isSimilar( element3 ) ).to.be.true;
+		} );
+
+		it( 'should return false if ids are different even if other properties are same', () => {
+			const element1 = new AttributeElement( 'span', { foo: 'bar' } );
+			element1._priority = 3;
+			element1._id = 'foo';
+
+			const element2 = new AttributeElement( 'span', { foo: 'bar' } );
+			element2._priority = 3;
+			element2._id = 'bar';
+
+			expect( element1.isSimilar( element2 ) ).to.be.false;
+		} );
 	} );
 
 	describe( 'getFillerOffset', () => {