Przeglądaj źródła

Added documentation to treeView.Matcher methods.

Szymon Kupś 9 lat temu
rodzic
commit
4f3edadfb5

+ 167 - 37
packages/ckeditor5-engine/src/treeview/matcher.js

@@ -7,59 +7,155 @@
 
 /**
  * View matcher class.
- * Instance of this class can be used to find elements that match given pattern.
- * To match element with given name:
- *		matcher
+ * Instance of this class can be used to find {@link engine.treeView.Element elements} that match given pattern.
  *
  * @memberOf engine.treeView
  */
 export default class Matcher {
-	constructor( ...patterns ) {
+	/**
+	 * Creates new instance of Matcher.
+	 *
+	 * @param {String|RegExp|Object} [pattern] Match patterns. See {@link engine.treeView.Matcher#add add method} for
+	 * more information.
+	 */
+	constructor( ...pattern ) {
 		this._patterns = [];
 
-		this.add( ...patterns );
+		this.add( ...pattern );
 	}
 
 	/**
-	 * Adds pattern to matcher instance.
+	 * Adds pattern or patterns to matcher instance.
+	 *
+	 * Example patterns matching element's name:
+	 *
+	 *		// String.
+	 *		matcher.add( 'div' );
+	 *		matcher.add( { name: 'div' } );
+	 *
+	 *		// Regular expression.
+	 *		matcher.add( /^\w/ );
+	 *		matcher.add( { name: /^\w/ } );
+	 *
+	 * Example pattern matching element's attributes:
+	 *
+	 *		matcher.add( {
+	 *			attributes: {
+	 *				title: 'foobar',
+	 *				foo: /^\w+/
+	 *			}
+	 *		} );
+	 *
+	 * Example patterns matching element's classes:
+	 *
+	 *		// Single class.
+	 *		matcher.add( {
+	 *			class: 'foobar'
+	 *		} );
+	 *
+	 *		// Single class using regular expression.
+	 *		matcher.add( {
+	 *			class: /foo.../
+	 *		} );
+	 *
+	 *		// Multiple classes to match.
+	 *		matcher.add( {
+	 *			class: [ 'baz', 'bar', /foo.../ ]
+	 *		} ):
+	 *
+	 * Example pattern matching element's styles:
+	 *
+	 *		matcher.add( {
+	 *			style: {
+	 *				position: 'absolute',
+	 *				color: /^\w*blue$/
+	 *			}
+	 *		} );
 	 *
-	 * @param {...Object|String} patterns Object describing pattern details or string representing element's name.
-	 * @param {String} [patterns.name] Name of the element to match.
-	 * @param {Array} [patterns.attribute]
-	 * @param {String|Array.<String>} [patterns.class] Class name or array of class names to match.
-	 * @param {Object} [patterns.style]
+	 * Example function pattern:
+	 *
+	 *		matcher.add( ( element ) => {
+	 *			// Result of this function will be included in `match`
+	 *			// property of the object returned from matcher.match() call.
+	 *			if ( element.name === 'div' && element.getChildCount() > 0 ) {
+	 *				return { name: true };
+	 *			}
+	 *
+	 *			return null;
+	 *		} );
+	 *
+	 * Multiple patterns can be added in one call:
+	 *
+	 * 		matcher.add( 'div', { class: 'foobar' } );
+	 *
+	 * @param {Object|String|RegExp|function} pattern Object describing pattern details. If string or regular expression
+	 * is provided it will be used to match element's name. Pattern can be also provided in a form
+	 * of a function - then this function will be called with each {@link engine.treeView.Element element} as a parameter.
+	 * Function's return value will be stored under `match` key of the object returned from
+	 * {@link engine.treeView.Matcher#match match} or {@link engine.treeView.Matcher#matchAll matchAll} methods.
+	 * @param {String|RegExp} [pattern.name] Name or regular expression to match element's name.
+	 * @param {Object} [pattern.attribute] Object with key-value pairs representing attributes to match. Each object key
+	 * represents attribute name. Value under that key can be either a string or a regular expression and it will be
+	 * used to match attribute value.
+	 * @param {String|RegExp|Array} [pattern.class] Class name or array of class names to match. Each name can be
+	 * provided in a form of string or regular expression.
+	 * @param {Object} [pattern.style] Object with key-value pairs representing styles to match. Each object key
+	 * represents style name. Value under that key can be either a string or a regular expression and it will be used
+	 * to match style value.
 	 */
-	add( ...patterns ) {
-		for ( let pattern of patterns ) {
-			// String pattern is used as element's name.
-			if ( typeof pattern == 'string' ) {
-				pattern = { name: pattern };
+	add( ...pattern ) {
+		for ( let item of pattern ) {
+			// String or RegExp pattern is used as element's name.
+			if ( typeof item == 'string' || item instanceof RegExp ) {
+				item = { name: item };
 			}
 
 			// Single class name/RegExp can be provided.
-			if ( pattern.class && ( typeof pattern.class == 'string' || pattern.class instanceof RegExp ) ) {
-				pattern.class = [ pattern.class ];
+			if ( item.class && ( typeof item.class == 'string' || item.class instanceof RegExp ) ) {
+				item.class = [ item.class ];
 			}
 
-			this._patterns.push( pattern );
+			this._patterns.push( item );
 		}
 	}
 
 	/**
-	 * Matches elements for currently stored patterns. Returns information about first found element, otherwise returns
-	 * `null`.
+	 * Matches elements for currently stored patterns. Returns match information about first found
+	 * {@link engine.treeView.Element element}, otherwise returns `null`.
+	 *
+	 * Example of returned object:
+	 *
+	 *		{
+	 *			element: <instance of found element>,
+	 *			pattern: <pattern used to match found element>,
+	 *			match: {
+	 *				name: true,
+ 	 *				attributes: [ 'title', 'href' ],
+	 *				classes: [ 'foo' ],
+ 	 *				styles: [ 'color', 'position' ]
+	 *			}
+	 *		}
 	 *
-	 * @param {...Object} elements
-	 * @returns {*}
+	 * @see engine.treeView.Matcher#add
+	 * @see engine.treeView.Matcher#matchAll
+	 * @param {...core.treeView.Element} element View element to match against stored patterns.
+	 * @returns {Object|null} result
+	 * @returns {core.treeView.Element} result.element Matched view element.
+	 * @returns {Object|String|RegExp|function} result.pattern Pattern that was used to find matched element.
+	 * @returns {Object} result.match Object representing matched element parts.
+	 * @returns {Boolean} [result.match.name] True if name of the element was matched.
+	 * @returns {Array} [result.match.attribute] Array with matched attribute names.
+	 * @returns {Array} [result.match.class] Array with matched class names.
+	 * @returns {Array} [result.match.style] Array with matched style names.
 	 */
-	match( ...elements ) {
-		for ( let element of elements ) {
+	match( ...element ) {
+		for ( let singleElement of element ) {
 			for ( let pattern of this._patterns ) {
-				const match = isElementMatching( element, pattern );
+				const match = isElementMatching( singleElement, pattern );
 
 				if ( match ) {
 					return {
-						element: element,
+						element: singleElement,
 						pattern: pattern,
 						match: match
 					};
@@ -70,16 +166,26 @@ export default class Matcher {
 		return null;
 	}
 
-	matchAll( ...elements ) {
+	/**
+	 * Matches elements for currently stored patterns. Returns array of match information with all found
+	 * {@link engine.treeView.Element elements}. If no element is found - returns `null`.
+	 *
+	 * @see engine.treeView.Matcher#add
+	 * @see engine.treeView.Matcher#match
+	 * @param {...engine.treeView.Element} element View element to match against stored patterns.
+	 * @returns {Array.<Object>|null} Array with match information about found elements or `null`. For more information
+	 * see {@link engine.treeView.Matcher#match match method} description.
+	 */
+	matchAll( ...element ) {
 		const results = [];
 
-		for ( let element of elements ) {
+		for ( let singleElement of element ) {
 			for ( let pattern of this._patterns ) {
-				const match = isElementMatching( element, pattern );
+				const match = isElementMatching( singleElement, pattern );
 
 				if ( match ) {
 					results.push( {
-						element: element,
+						element: singleElement,
 						pattern: pattern,
 						match: match
 					} );
@@ -91,12 +197,16 @@ export default class Matcher {
 	}
 }
 
+// Returns match information if {@link engine.treeView.Element element} is matching provided pattern.
+// If element cannot be matched to provided pattern - returns `null`.
+//
+// @param {engine.treeView.Element} element
+// @param {Object|String|RegExp|function} pattern
+// @returns {Object|null} Returns object with match information or null if element is not matching.
 function isElementMatching( element, pattern ) {
 	// If pattern is provided as function - return result of that function;
 	if ( typeof pattern == 'function' ) {
-		const result = pattern( element );
-
-		return result ? result : null;
+		return pattern( element );
 	}
 
 	const match = {};
@@ -139,6 +249,11 @@ function isElementMatching( element, pattern ) {
 	return match;
 }
 
+// Checks if name can be matched by provided pattern.
+//
+// @param {String|RegExp} pattern
+// @param {String} name
+// @returns {Boolean} Returns `true` if name can be matched, `false` otherwise.
 function matchName( pattern, name ) {
 	// If pattern is provided as RegExp - test against this regexp.
 	if ( pattern instanceof RegExp ) {
@@ -148,6 +263,12 @@ function matchName( pattern, name ) {
 	return pattern === name;
 }
 
+// Checks if attributes of provided element can be matched against provided patterns.
+//
+// @param {Object} patterns Object with information about attributes to match. Each key of the object will be
+// used as attribute name. Value of each key can be a string or regular expression to match against attribute value.
+// @param {engine.treeView.Element} element Element which attributes will be tested.
+// @returns {Array|null} Returns array with matched attribute names or `null` if no attributes were matched.
 function matchAttributes( patterns, element ) {
 	const match = [];
 
@@ -176,12 +297,15 @@ function matchAttributes( patterns, element ) {
 	return match;
 }
 
+// Checks if classes of provided element can be matched against provided patterns.
+//
+// @param {Array.<String|RegExp>} patterns Array of strings or regular expressions to match against element's classes.
+// @param {engine.treeView.Element} element Element which classes will be tested.
+// @returns {Array|null} Returns array with matched class names or `null` if no classes were matched.
 function matchClasses( patterns, element ) {
 	const match = [];
 
-	for ( let name in patterns ) {
-		const pattern = patterns[ name ];
-
+	for ( let pattern of patterns ) {
 		if ( pattern instanceof RegExp ) {
 			const classes = element.getClassNames();
 
@@ -204,6 +328,12 @@ function matchClasses( patterns, element ) {
 	return match;
 }
 
+// Checks if styles of provided element can be matched against provided patterns.
+//
+// @param {Object} patterns Object with information about styles to match. Each key of the object will be
+// used as style name. Value of each key can be a string or regular expression to match against style value.
+// @param {engine.treeView.Element} element Element which styles will be tested.
+// @returns {Array|null} Returns array with matched style names or `null` if no styles were matched.
 function matchStyles( patterns, element ) {
 	const match = [];
 

+ 2 - 2
packages/ckeditor5-engine/tests/treeview/matcher.js

@@ -65,7 +65,7 @@ describe( 'Matcher', () => {
 		} );
 
 		it( 'should match element name with RegExp', () => {
-			const pattern = { name: /^text...a$/ };
+			const pattern = /^text...a$/;
 			const matcher = new Matcher( pattern );
 			const el1 = new Element( 'textarea' );
 			const el2 = new Element( 'div' );
@@ -74,7 +74,7 @@ describe( 'Matcher', () => {
 
 			expect( result ).to.be.an( 'object' );
 			expect( result ).to.have.property( 'element' ).that.equal( el1 );
-			expect( result ).to.have.property( 'pattern' ).that.has.property( 'name' ).that.equal( pattern.name );
+			expect( result ).to.have.property( 'pattern' ).that.has.property( 'name' ).that.equal( pattern );
 			expect( result ).to.have.property( 'match' ).that.has.property( 'name' ).that.is.true;
 			expect( matcher.match( el2 ) ).to.be.null;
 		} );