Procházet zdrojové kódy

Added changes to attributes manipulation in core.treeView.Element to support styles.

Szymon Kupś před 9 roky
rodič
revize
b85f314a1c

+ 65 - 8
packages/ckeditor5-engine/src/treeview/element.js

@@ -89,13 +89,7 @@ export default class Element extends Node {
 		this._styles = new Map();
 
 		if ( this._attrs.has( 'style' ) ) {
-			const styleString = this._attrs.get( 'style' );
-			const regex = /\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g;
-			let matchStyle;
-
-			while ( ( matchStyle = regex.exec( styleString ) ) !== null ) {
-				this._styles.set( matchStyle[ 1 ], matchStyle[ 2 ].trim() );
-			}
+			parseInlineStyles( this._styles, this._attrs.get( 'style' ) );
 			this._attrs.delete( 'style' );
 		}
 	}
@@ -179,6 +173,7 @@ export default class Element extends Node {
 
 	/**
 	 * Returns an iterator that contains the keys for attributes.
+	 * Order of inserting attributes is not preserved.
 	 *
 	 * @returns {Iterator.<String>} Keys for attributes.
 	 */
@@ -187,6 +182,10 @@ export default class Element extends Node {
 			yield 'class';
 		}
 
+		if ( this._styles.size > 0 ) {
+			yield 'style';
+		}
+
 		yield* this._attrs.keys();
 	}
 
@@ -205,6 +204,20 @@ export default class Element extends Node {
 			return undefined;
 		}
 
+		if ( key == 'style' ) {
+			if ( this._styles.size > 0 ) {
+				let styleString = '';
+
+				for ( let [ property, value ] of this._styles ) {
+					styleString += `${ property }:${ value };`;
+				}
+
+				return styleString;
+			}
+
+			return undefined;
+		}
+
 		return this._attrs.get( key );
 	}
 
@@ -219,6 +232,10 @@ export default class Element extends Node {
 			return this._classes.size  > 0;
 		}
 
+		if ( key == 'style' ) {
+			return this._styles.size > 0;
+		}
+
 		return this._attrs.has( key );
 	}
 
@@ -235,7 +252,9 @@ export default class Element extends Node {
 		if ( key == 'class' ) {
 			const classArray = value.split( /\s+/ );
 			this._classes.clear();
-			this.addClass( ...classArray );
+			classArray.forEach( name => this._classes.add( name ) );
+		} else if ( key == 'style' ) {
+			parseInlineStyles( this._styles, value );
 		} else {
 			this._attrs.set( key, value );
 		}
@@ -279,6 +298,29 @@ export default class Element extends Node {
 	removeAttribute( key ) {
 		this._fireChange( 'ATTRIBUTES', this );
 
+		// Remove class attribute.
+		if ( key == 'class' ) {
+			if ( this._classes.size > 0 ) {
+				this._classes.clear();
+
+				return true;
+			}
+
+			return false;
+		}
+
+		// Remove style attribute.
+		if ( key == 'style' ) {
+			if ( this._styles.size > 0 ) {
+				this._styles.clear();
+
+				return true;
+			}
+
+			return false;
+		}
+
+		// Remove other attributes.
 		return this._attrs.delete( key );
 	}
 
@@ -445,3 +487,18 @@ export default class Element extends Node {
 		property.forEach( name => this._styles.delete( name ) );
 	}
 }
+
+// Parses inline styles and puts property - value pairs into styles map.
+// Styles map is cleared before insertion.
+//
+// @param {Map.<String, String>} stylesMap Map to insert parsed properties and values.
+// @param {String} stylesString Styles to parse.
+function parseInlineStyles( stylesMap, stylesString ) {
+	const regex = /\s*([^:;\s]+)\s*:\s*([^;]+)\s*(?=;|$)/g;
+	let matchStyle;
+	stylesMap.clear();
+
+	while ( ( matchStyle = regex.exec( stylesString ) ) !== null ) {
+		stylesMap.set( matchStyle[ 1 ], matchStyle[ 2 ].trim() );
+	}
+}

+ 49 - 0
packages/ckeditor5-engine/tests/treeview/element.js

@@ -337,6 +337,17 @@ describe( 'Element', () => {
 				expect( el._classes.has( 'baz' )  ).to.be.false;
 				expect( el._classes.has( 'qux' )  ).to.be.true;
 			} );
+
+			it( 'should replace all styles', () => {
+				el.setStyle( 'color', 'red' );
+				el.setStyle( 'top', '10px' );
+				el.setAttribute( 'style', 'border:none' );
+
+				expect( el.hasStyle( 'color' ) ).to.be.false;
+				expect( el.hasStyle( 'top' ) ).to.be.false;
+				expect( el.hasStyle( 'border' ) ).to.be.true;
+				expect( el.getStyle( 'border' ) ).to.equal( 'none' );
+			} );
 		} );
 
 		describe( 'getAttribute', () => {
@@ -356,6 +367,13 @@ describe( 'Element', () => {
 			it( 'should return undefined if no class attribute', () => {
 				expect( el.getAttribute( 'class' ) ).to.be.undefined;
 			} );
+
+			it( 'should return style attribute', () => {
+				el.setStyle( 'color', 'red' );
+				el.setStyle( 'top', '10px' );
+
+				expect( el.getAttribute( 'style' ) ).to.equal( 'color:red;top:10px;' );
+			} );
 		} );
 
 		describe( 'hasAttribute', () => {
@@ -371,6 +389,12 @@ describe( 'Element', () => {
 				el.addClass( 'foo' );
 				expect( el.hasAttribute( 'class' ) ).to.be.true;
 			} );
+
+			it( 'should return true if element has style attribute', () => {
+				expect( el.hasAttribute( 'style' ) ).to.be.false;
+				el.setStyle( 'border', '1px solid red' );
+				expect( el.hasAttribute( 'style' ) ).to.be.true;
+			} );
 		} );
 
 		describe( 'getAttributeKeys', () => {
@@ -400,6 +424,18 @@ describe( 'Element', () => {
 					i++;
 				}
 			} );
+
+			it( 'should return style key', () => {
+				el.setStyle( 'color', 'black' );
+				el.setAttribute( 'bar', true );
+				const expected = [ 'style', 'bar' ];
+				let i = 0;
+
+				for ( let key of el.getAttributeKeys() ) {
+					expect( key ).to.equal( expected[ i ] );
+					i++;
+				}
+			} );
 		} );
 
 		describe( 'removeAttribute', () => {
@@ -414,6 +450,19 @@ describe( 'Element', () => {
 
 				expect( utils.count( el.getAttributeKeys() ) ).to.equal( 0 );
 			} );
+
+			it( 'should remove classe attribute', () => {
+				el.addClass( 'foo', 'bar' );
+				el.removeAttribute( 'class' );
+
+				expect( el.hasAttribute( 'class' ) ).to.be.false;
+				expect( el.hasClass( 'foo' ) ).to.be.false;
+				expect( el.hasClass( 'bar' ) ).to.be.false;
+			} );
+
+			// it( 'should fire event', () => {
+			//
+			// } );
 		} );
 	} );