Update wmts-hidpi, add nicer-api-docs

This commit is contained in:
Andreas Hocevar
2014-05-06 13:02:46 -05:00
parent b3ac1afd00
commit 1e25fc5585
2239 changed files with 3726515 additions and 37010 deletions

View File

@@ -0,0 +1,60 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern base class.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Base pattern class for DOM matching.
*
* @constructor
*/
goog.dom.pattern.AbstractPattern = function() {
};
/**
* The first node matched by this pattern.
* @type {Node}
*/
goog.dom.pattern.AbstractPattern.prototype.matchedNode = null;
/**
* Reset any internal state this pattern keeps.
*/
goog.dom.pattern.AbstractPattern.prototype.reset = function() {
// The base implementation does nothing.
};
/**
* Test whether this pattern matches the given token.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} {@code MATCH} if the pattern matches.
*/
goog.dom.pattern.AbstractPattern.prototype.matchToken = function(token, type) {
return goog.dom.pattern.MatchType.NO_MATCH;
};

View File

@@ -0,0 +1,75 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match any children of a tag.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.AllChildren');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches any nodes at or below the current tree depth.
*
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.AllChildren = function() {
};
goog.inherits(goog.dom.pattern.AllChildren, goog.dom.pattern.AbstractPattern);
/**
* Tracks the matcher's depth to detect the end of the tag.
*
* @type {number}
* @private
*/
goog.dom.pattern.AllChildren.prototype.depth_ = 0;
/**
* Test whether the given token is on the same level.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the
* same level or deeper and {@code BACKTRACK_MATCH} if not.
* @override
*/
goog.dom.pattern.AllChildren.prototype.matchToken = function(token, type) {
this.depth_ += type;
if (this.depth_ >= 0) {
return goog.dom.pattern.MatchType.MATCHING;
} else {
this.depth_ = 0;
return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
}
};
/**
* Reset any internal state this pattern keeps.
* @override
*/
goog.dom.pattern.AllChildren.prototype.reset = function() {
this.depth_ = 0;
};

View File

@@ -0,0 +1,82 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Useful callback functions for the DOM matcher.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.callback');
goog.require('goog.dom');
goog.require('goog.dom.TagWalkType');
goog.require('goog.iter');
/**
* Callback function for use in {@link goog.dom.pattern.Matcher.addPattern}
* that removes the matched node from the tree. Should be used in conjunciton
* with a {@link goog.dom.pattern.StartTag} pattern.
*
* @param {Node} node The node matched by the pattern.
* @param {goog.dom.TagIterator} position The position where the match
* finished.
* @return {boolean} Returns true to indicate tree changes were made.
*/
goog.dom.pattern.callback.removeNode = function(node, position) {
// Find out which position would be next.
position.setPosition(node, goog.dom.TagWalkType.END_TAG);
goog.iter.nextOrValue(position, null);
// Remove the node.
goog.dom.removeNode(node);
// Correct for the depth change.
position.depth -= 1;
// Indicate that we made position/tree changes.
return true;
};
/**
* Callback function for use in {@link goog.dom.pattern.Matcher.addPattern}
* that removes the matched node from the tree and replaces it with its
* children. Should be used in conjunction with a
* {@link goog.dom.pattern.StartTag} pattern.
*
* @param {Element} node The node matched by the pattern.
* @param {goog.dom.TagIterator} position The position where the match
* finished.
* @return {boolean} Returns true to indicate tree changes were made.
*/
goog.dom.pattern.callback.flattenElement = function(node, position) {
// Find out which position would be next.
position.setPosition(node, node.firstChild ?
goog.dom.TagWalkType.START_TAG :
goog.dom.TagWalkType.END_TAG);
goog.iter.nextOrValue(position, null);
// Flatten the node.
goog.dom.flattenElement(node);
// Correct for the depth change.
position.depth -= 1;
// Indicate that we made position/tree changes.
return true;
};

View File

@@ -0,0 +1,72 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Callback object that counts matches.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.callback.Counter');
/**
* Callback class for counting matches.
* @constructor
*/
goog.dom.pattern.callback.Counter = function() {
};
/**
* The count of objects matched so far.
*
* @type {number}
*/
goog.dom.pattern.callback.Counter.prototype.count = 0;
/**
* The callback function. Suitable as a callback for
* {@link goog.dom.pattern.Matcher}.
* @type {Function}
* @private
*/
goog.dom.pattern.callback.Counter.prototype.callback_ = null;
/**
* Get a bound callback function that is suitable as a callback for
* {@link goog.dom.pattern.Matcher}.
*
* @return {Function} A callback function.
*/
goog.dom.pattern.callback.Counter.prototype.getCallback = function() {
if (!this.callback_) {
this.callback_ = goog.bind(function() {
this.count++;
return false;
}, this);
}
return this.callback_;
};
/**
* Reset the counter.
*/
goog.dom.pattern.callback.Counter.prototype.reset = function() {
this.count = 0;
};

View File

@@ -0,0 +1,77 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Callback object that tests if a pattern matches at least once.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.callback.Test');
goog.require('goog.iter.StopIteration');
/**
* Callback class for testing for at least one match.
* @constructor
*/
goog.dom.pattern.callback.Test = function() {
};
/**
* Whether or not the pattern matched.
*
* @type {boolean}
*/
goog.dom.pattern.callback.Test.prototype.matched = false;
/**
* The callback function. Suitable as a callback for
* {@link goog.dom.pattern.Matcher}.
* @type {Function}
* @private
*/
goog.dom.pattern.callback.Test.prototype.callback_ = null;
/**
* Get a bound callback function that is suitable as a callback for
* {@link goog.dom.pattern.Matcher}.
*
* @return {Function} A callback function.
*/
goog.dom.pattern.callback.Test.prototype.getCallback = function() {
if (!this.callback_) {
this.callback_ = goog.bind(function(node, position) {
// Mark our match.
this.matched = true;
// Stop searching.
throw goog.iter.StopIteration;
}, this);
}
return this.callback_;
};
/**
* Reset the counter.
*/
goog.dom.pattern.callback.Test.prototype.reset = function() {
this.matched = false;
};

View File

@@ -0,0 +1,154 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match any children of a tag, and
* specifically collect those that match a child pattern.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.ChildMatches');
goog.require('goog.dom.pattern.AllChildren');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches any nodes at or below the current tree depth.
*
* @param {goog.dom.pattern.AbstractPattern} childPattern Pattern to collect
* child matches of.
* @param {number=} opt_minimumMatches Enforce a minimum nuber of matches.
* Defaults to 0.
* @constructor
* @extends {goog.dom.pattern.AllChildren}
*/
goog.dom.pattern.ChildMatches = function(childPattern, opt_minimumMatches) {
this.childPattern_ = childPattern;
this.matches = [];
this.minimumMatches_ = opt_minimumMatches || 0;
goog.dom.pattern.AllChildren.call(this);
};
goog.inherits(goog.dom.pattern.ChildMatches, goog.dom.pattern.AllChildren);
/**
* Array of matched child nodes.
*
* @type {Array.<Node>}
*/
goog.dom.pattern.ChildMatches.prototype.matches;
/**
* Minimum number of matches.
*
* @type {number}
* @private
*/
goog.dom.pattern.ChildMatches.prototype.minimumMatches_ = 0;
/**
* The child pattern to collect matches from.
*
* @type {goog.dom.pattern.AbstractPattern}
* @private
*/
goog.dom.pattern.ChildMatches.prototype.childPattern_;
/**
* Whether the pattern has recently matched or failed to match and will need to
* be reset when starting a new round of matches.
*
* @type {boolean}
* @private
*/
goog.dom.pattern.ChildMatches.prototype.needsReset_ = false;
/**
* Test whether the given token is on the same level.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} {@code MATCHING} if the token is on the
* same level or deeper and {@code BACKTRACK_MATCH} if not.
* @override
*/
goog.dom.pattern.ChildMatches.prototype.matchToken = function(token, type) {
// Defer resets so we maintain our matches array until the last possible time.
if (this.needsReset_) {
this.reset();
}
// Call the super-method to ensure we stay in the child tree.
var status =
goog.dom.pattern.AllChildren.prototype.matchToken.apply(this, arguments);
switch (status) {
case goog.dom.pattern.MatchType.MATCHING:
var backtrack = false;
switch (this.childPattern_.matchToken(token, type)) {
case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
backtrack = true;
case goog.dom.pattern.MatchType.MATCH:
// Collect the match.
this.matches.push(this.childPattern_.matchedNode);
break;
default:
// Keep trying if we haven't hit a terminal state.
break;
}
if (backtrack) {
// The only interesting result is a MATCH, since BACKTRACK_MATCH means
// we are hitting an infinite loop on something like a Repeat(0).
if (this.childPattern_.matchToken(token, type) ==
goog.dom.pattern.MatchType.MATCH) {
this.matches.push(this.childPattern_.matchedNode);
}
}
return goog.dom.pattern.MatchType.MATCHING;
case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
// TODO(robbyw): this should return something like BACKTRACK_NO_MATCH
// when we don't meet our minimum.
this.needsReset_ = true;
return (this.matches.length >= this.minimumMatches_) ?
goog.dom.pattern.MatchType.BACKTRACK_MATCH :
goog.dom.pattern.MatchType.NO_MATCH;
default:
this.needsReset_ = true;
return status;
}
};
/**
* Reset any internal state this pattern keeps.
* @override
*/
goog.dom.pattern.ChildMatches.prototype.reset = function() {
this.needsReset_ = false;
this.matches.length = 0;
this.childPattern_.reset();
goog.dom.pattern.AllChildren.prototype.reset.call(this);
};

View File

@@ -0,0 +1,53 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match the end of a tag.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.EndTag');
goog.require('goog.dom.TagWalkType');
goog.require('goog.dom.pattern.Tag');
/**
* Pattern object that matches a closing tag.
*
* @param {string|RegExp} tag Name of the tag. Also will accept a regular
* expression to match against the tag name.
* @param {Object=} opt_attrs Optional map of attribute names to desired values.
* This pattern will only match when all attributes are present and match
* the string or regular expression value provided here.
* @param {Object=} opt_styles Optional map of CSS style names to desired
* values. This pattern will only match when all styles are present and
* match the string or regular expression value provided here.
* @param {Function=} opt_test Optional function that takes the element as a
* parameter and returns true if this pattern should match it.
* @constructor
* @extends {goog.dom.pattern.Tag}
*/
goog.dom.pattern.EndTag = function(tag, opt_attrs, opt_styles, opt_test) {
goog.dom.pattern.Tag.call(
this,
tag,
goog.dom.TagWalkType.END_TAG,
opt_attrs,
opt_styles,
opt_test);
};
goog.inherits(goog.dom.pattern.EndTag, goog.dom.pattern.Tag);

View File

@@ -0,0 +1,93 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a tag and all of its children.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.FullTag');
goog.require('goog.dom.pattern.MatchType');
goog.require('goog.dom.pattern.StartTag');
goog.require('goog.dom.pattern.Tag');
/**
* Pattern object that matches a full tag including all its children.
*
* @param {string|RegExp} tag Name of the tag. Also will accept a regular
* expression to match against the tag name.
* @param {Object=} opt_attrs Optional map of attribute names to desired values.
* This pattern will only match when all attributes are present and match
* the string or regular expression value provided here.
* @param {Object=} opt_styles Optional map of CSS style names to desired
* values. This pattern will only match when all styles are present and
* match the string or regular expression value provided here.
* @param {Function=} opt_test Optional function that takes the element as a
* parameter and returns true if this pattern should match it.
* @constructor
* @extends {goog.dom.pattern.StartTag}
*/
goog.dom.pattern.FullTag = function(tag, opt_attrs, opt_styles, opt_test) {
goog.dom.pattern.StartTag.call(
this,
tag,
opt_attrs,
opt_styles,
opt_test);
};
goog.inherits(goog.dom.pattern.FullTag, goog.dom.pattern.StartTag);
/**
* Tracks the matcher's depth to detect the end of the tag.
*
* @type {number}
* @private
*/
goog.dom.pattern.FullTag.prototype.depth_ = 0;
/**
* Test whether the given token is a start tag token which matches the tag name,
* style, and attributes provided in the constructor.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> at the end of our
* tag, <code>MATCHING</code> if we are within the tag, and
* <code>NO_MATCH</code> if the starting tag does not match.
* @override
*/
goog.dom.pattern.FullTag.prototype.matchToken = function(token, type) {
if (!this.depth_) {
// If we have not yet started, make sure we match as a StartTag.
if (goog.dom.pattern.Tag.prototype.matchToken.call(this, token, type)) {
this.depth_ = type;
return goog.dom.pattern.MatchType.MATCHING;
} else {
return goog.dom.pattern.MatchType.NO_MATCH;
}
} else {
this.depth_ += type;
return this.depth_ ?
goog.dom.pattern.MatchType.MATCHING :
goog.dom.pattern.MatchType.MATCH;
}
};

View File

@@ -0,0 +1,150 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern matcher. Allows for simple searching of DOM
* using patterns descended from {@link goog.dom.pattern.AbstractPattern}.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.Matcher');
goog.require('goog.dom.TagIterator');
goog.require('goog.dom.pattern.MatchType');
goog.require('goog.iter');
// TODO(robbyw): Allow for backtracks of size > 1.
/**
* Given a set of patterns and a root node, this class tests the patterns in
* parallel.
*
* It is not (yet) a smart matcher - it doesn't do any advanced backtracking.
* Given the pattern <code>DIV, SPAN</code> the matcher will not match
* <code>DIV, DIV, SPAN</code> because it starts matching at the first
* <code>DIV</code>, fails to match <code>SPAN</code> at the second, and never
* backtracks to try again.
*
* It is also possible to have a set of complex patterns that when matched in
* parallel will miss some possible matches. Running multiple times will catch
* all matches eventually.
*
* @constructor
*/
goog.dom.pattern.Matcher = function() {
this.patterns_ = [];
this.callbacks_ = [];
};
/**
* Array of patterns to attempt to match in parallel.
*
* @type {Array.<goog.dom.pattern.AbstractPattern>}
* @private
*/
goog.dom.pattern.Matcher.prototype.patterns_;
/**
* Array of callbacks to call when a pattern is matched. The indexing is the
* same as the {@link #patterns_} array.
*
* @type {Array.<Function>}
* @private
*/
goog.dom.pattern.Matcher.prototype.callbacks_;
/**
* Adds a pattern to be matched. The callback can return an object whose keys
* are processing instructions.
*
* @param {goog.dom.pattern.AbstractPattern} pattern The pattern to add.
* @param {Function} callback Function to call when a match is found. Uses
* the above semantics.
*/
goog.dom.pattern.Matcher.prototype.addPattern = function(pattern, callback) {
this.patterns_.push(pattern);
this.callbacks_.push(callback);
};
/**
* Resets all the patterns.
*
* @private
*/
goog.dom.pattern.Matcher.prototype.reset_ = function() {
for (var i = 0, len = this.patterns_.length; i < len; i++) {
this.patterns_[i].reset();
}
};
/**
* Test the given node against all patterns.
*
* @param {goog.dom.TagIterator} position A position in a node walk that is
* located at the token to process.
* @return {boolean} Whether a pattern modified the position or tree
* and its callback resulted in DOM structure or position modification.
* @private
*/
goog.dom.pattern.Matcher.prototype.matchToken_ = function(position) {
for (var i = 0, len = this.patterns_.length; i < len; i++) {
var pattern = this.patterns_[i];
switch (pattern.matchToken(position.node, position.tagType)) {
case goog.dom.pattern.MatchType.MATCH:
case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
var callback = this.callbacks_[i];
// Callbacks are allowed to modify the current position, but must
// return true if the do.
if (callback(pattern.matchedNode, position, pattern)) {
return true;
}
default:
// Do nothing.
break;
}
}
return false;
};
/**
* Match the set of patterns against a match tree.
*
* @param {Node} node The root node of the tree to match.
*/
goog.dom.pattern.Matcher.prototype.match = function(node) {
var position = new goog.dom.TagIterator(node);
this.reset_();
goog.iter.forEach(position, function() {
while (this.matchToken_(position)) {
// Since we've moved, our old pattern statuses don't make sense any more.
// Reset them.
this.reset_();
}
}, this);
};

View File

@@ -0,0 +1,58 @@
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a node of the given type.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.NodeType');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches any node of the given type.
* @param {goog.dom.NodeType} nodeType The node type to match.
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.NodeType = function(nodeType) {
/**
* The node type to match.
* @type {goog.dom.NodeType}
* @private
*/
this.nodeType_ = nodeType;
};
goog.inherits(goog.dom.pattern.NodeType, goog.dom.pattern.AbstractPattern);
/**
* Test whether the given token is a text token which matches the string or
* regular expression provided in the constructor.
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
* matches, <code>NO_MATCH</code> otherwise.
* @override
*/
goog.dom.pattern.NodeType.prototype.matchToken = function(token, type) {
return token.nodeType == this.nodeType_ ?
goog.dom.pattern.MatchType.MATCH :
goog.dom.pattern.MatchType.NO_MATCH;
};

View File

@@ -0,0 +1,93 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM patterns. Allows for description of complex DOM patterns
* using regular expression like constructs.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern');
goog.provide('goog.dom.pattern.MatchType');
/**
* Regular expression for breaking text nodes.
* @type {RegExp}
*/
goog.dom.pattern.BREAKING_TEXTNODE_RE = /^\s*$/;
/**
* Utility function to match a string against either a string or a regular
* expression.
*
* @param {string|RegExp} obj Either a string or a regular expression.
* @param {string} str The string to match.
* @return {boolean} Whether the strings are equal, or if the string matches
* the regular expression.
*/
goog.dom.pattern.matchStringOrRegex = function(obj, str) {
if (goog.isString(obj)) {
// Match a string
return str == obj;
} else {
// Match a regular expression
return !!(str && str.match(obj));
}
};
/**
* Utility function to match a DOM attribute against either a string or a
* regular expression. Conforms to the interface spec for
* {@link goog.object#every}.
*
* @param {string|RegExp} elem Either a string or a regular expression.
* @param {string} index The attribute name to match.
* @param {Object} orig The original map of matches to test.
* @return {boolean} Whether the strings are equal, or if the attribute matches
* the regular expression.
* @this {Element} Called using goog.object every on an Element.
*/
goog.dom.pattern.matchStringOrRegexMap = function(elem, index, orig) {
return goog.dom.pattern.matchStringOrRegex(elem,
index in this ? this[index] :
(this.getAttribute ? this.getAttribute(index) : null));
};
/**
* When matched to a token, a pattern may return any of the following statuses:
* <ol>
* <li><code>NO_MATCH</code> - The pattern does not match. This is the only
* value that evaluates to <code>false</code> in a boolean context.
* <li><code>MATCHING</code> - The token is part of an incomplete match.
* <li><code>MATCH</code> - The token completes a match.
* <li><code>BACKTRACK_MATCH</code> - The token does not match, but indicates
* the end of a repetitive match. For instance, in regular expressions,
* the pattern <code>/a+/</code> would match <code>'aaaaaaaab'</code>.
* Every <code>'a'</code> token would give a status of
* <code>MATCHING</code> while the <code>'b'</code> token would give a
* status of <code>BACKTRACK_MATCH</code>.
* </ol>
* @enum {number}
*/
goog.dom.pattern.MatchType = {
NO_MATCH: 0,
MATCHING: 1,
MATCH: 2,
BACKTRACK_MATCH: 3
};

View File

@@ -0,0 +1,190 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a tag and all of its children.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.Repeat');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches a repetition of another pattern.
* @param {goog.dom.pattern.AbstractPattern} pattern The pattern to
* repetitively match.
* @param {number=} opt_minimum The minimum number of times to match. Defaults
* to 0.
* @param {number=} opt_maximum The maximum number of times to match. Defaults
* to unlimited.
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.Repeat = function(pattern,
opt_minimum,
opt_maximum) {
this.pattern_ = pattern;
this.minimum_ = opt_minimum || 0;
this.maximum_ = opt_maximum || null;
this.matches = [];
};
goog.inherits(goog.dom.pattern.Repeat, goog.dom.pattern.AbstractPattern);
/**
* Pattern to repetitively match.
*
* @type {goog.dom.pattern.AbstractPattern}
* @private
*/
goog.dom.pattern.Repeat.prototype.pattern_;
/**
* Minimum number of times to match the pattern.
*
* @private
*/
goog.dom.pattern.Repeat.prototype.minimum_ = 0;
/**
* Optional maximum number of times to match the pattern. A {@code null} value
* will be treated as infinity.
*
* @type {?number}
* @private
*/
goog.dom.pattern.Repeat.prototype.maximum_ = 0;
/**
* Number of times the pattern has matched.
*
* @type {number}
*/
goog.dom.pattern.Repeat.prototype.count = 0;
/**
* Whether the pattern has recently matched or failed to match and will need to
* be reset when starting a new round of matches.
*
* @type {boolean}
* @private
*/
goog.dom.pattern.Repeat.prototype.needsReset_ = false;
/**
* The matched nodes.
*
* @type {Array.<Node>}
*/
goog.dom.pattern.Repeat.prototype.matches;
/**
* Test whether the given token continues a repeated series of matches of the
* pattern given in the constructor.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
* matches, <code>BACKTRACK_MATCH</code> if the pattern does not match
* but already had accumulated matches, <code>MATCHING</code> if the pattern
* starts a match, and <code>NO_MATCH</code> if the pattern does not match.
* @suppress {missingProperties} See the broken line below.
* @override
*/
goog.dom.pattern.Repeat.prototype.matchToken = function(token, type) {
// Reset if we're starting a new match
if (this.needsReset_) {
this.reset();
}
// If the option is set, ignore any whitespace only text nodes
if (token.nodeType == goog.dom.NodeType.TEXT &&
token.nodeValue.match(/^\s+$/)) {
return goog.dom.pattern.MatchType.MATCHING;
}
switch (this.pattern_.matchToken(token, type)) {
case goog.dom.pattern.MatchType.MATCH:
// Record the first token we match.
if (this.count == 0) {
this.matchedNode = token;
}
// Mark the match
this.count++;
// Add to the list
this.matches.push(this.pattern_.matchedNode);
// Check if this match hits our maximum
if (this.maximum_ !== null && this.count == this.maximum_) {
this.needsReset_ = true;
return goog.dom.pattern.MatchType.MATCH;
} else {
return goog.dom.pattern.MatchType.MATCHING;
}
case goog.dom.pattern.MatchType.MATCHING:
// This can happen when our child pattern is a sequence or a repetition.
return goog.dom.pattern.MatchType.MATCHING;
case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
// This happens if our child pattern is repetitive too.
// TODO(robbyw): Backtrack further if necessary.
this.count++;
// NOTE(nicksantos): This line of code is broken. this.patterns_ doesn't
// exist, and this.currentPosition_ doesn't exit. When this is fixed,
// remove the missingProperties suppression above.
if (this.currentPosition_ == this.patterns_.length) {
this.needsReset_ = true;
return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
} else {
// Retry the same token on the next iteration of the child pattern.
return this.matchToken(token, type);
}
default:
this.needsReset_ = true;
if (this.count >= this.minimum_) {
return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
} else {
return goog.dom.pattern.MatchType.NO_MATCH;
}
}
};
/**
* Reset any internal state this pattern keeps.
* @override
*/
goog.dom.pattern.Repeat.prototype.reset = function() {
this.pattern_.reset();
this.count = 0;
this.needsReset_ = false;
this.matches.length = 0;
};

View File

@@ -0,0 +1,141 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a sequence of other patterns.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.Sequence');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches a sequence of other patterns.
*
* @param {Array.<goog.dom.pattern.AbstractPattern>} patterns Ordered array of
* patterns to match.
* @param {boolean=} opt_ignoreWhitespace Optional flag to ignore text nodes
* consisting entirely of whitespace. The default is to not ignore them.
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.Sequence = function(patterns, opt_ignoreWhitespace) {
this.patterns = patterns;
this.ignoreWhitespace_ = !!opt_ignoreWhitespace;
};
goog.inherits(goog.dom.pattern.Sequence, goog.dom.pattern.AbstractPattern);
/**
* Ordered array of patterns to match.
*
* @type {Array.<goog.dom.pattern.AbstractPattern>}
*/
goog.dom.pattern.Sequence.prototype.patterns;
/**
* Position in the patterns array we have reached by successful matches.
*
* @type {number}
* @private
*/
goog.dom.pattern.Sequence.prototype.currentPosition_ = 0;
/**
* Whether or not to ignore whitespace only Text nodes.
*
* @type {boolean}
* @private
*/
goog.dom.pattern.Sequence.prototype.ignoreWhitespace_ = false;
/**
* Test whether the given token starts, continues, or finishes the sequence
* of patterns given in the constructor.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
* matches, <code>MATCHING</code> if the pattern starts a match, and
* <code>NO_MATCH</code> if the pattern does not match.
* @override
*/
goog.dom.pattern.Sequence.prototype.matchToken = function(token, type) {
// If the option is set, ignore any whitespace only text nodes
if (this.ignoreWhitespace_ && token.nodeType == goog.dom.NodeType.TEXT &&
goog.dom.pattern.BREAKING_TEXTNODE_RE.test(token.nodeValue)) {
return goog.dom.pattern.MatchType.MATCHING;
}
switch (this.patterns[this.currentPosition_].matchToken(token, type)) {
case goog.dom.pattern.MatchType.MATCH:
// Record the first token we match.
if (this.currentPosition_ == 0) {
this.matchedNode = token;
}
// Move forward one position.
this.currentPosition_++;
// Check if this is the last position.
if (this.currentPosition_ == this.patterns.length) {
this.reset();
return goog.dom.pattern.MatchType.MATCH;
} else {
return goog.dom.pattern.MatchType.MATCHING;
}
case goog.dom.pattern.MatchType.MATCHING:
// This can happen when our child pattern is a sequence or a repetition.
return goog.dom.pattern.MatchType.MATCHING;
case goog.dom.pattern.MatchType.BACKTRACK_MATCH:
// This means a repetitive match succeeded 1 token ago.
// TODO(robbyw): Backtrack further if necessary.
this.currentPosition_++;
if (this.currentPosition_ == this.patterns.length) {
this.reset();
return goog.dom.pattern.MatchType.BACKTRACK_MATCH;
} else {
// Retry the same token on the next pattern.
return this.matchToken(token, type);
}
default:
this.reset();
return goog.dom.pattern.MatchType.NO_MATCH;
}
};
/**
* Reset any internal state this pattern keeps.
* @override
*/
goog.dom.pattern.Sequence.prototype.reset = function() {
if (this.patterns[this.currentPosition_]) {
this.patterns[this.currentPosition_].reset();
}
this.currentPosition_ = 0;
};

View File

@@ -0,0 +1,53 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match the start of a tag.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.StartTag');
goog.require('goog.dom.TagWalkType');
goog.require('goog.dom.pattern.Tag');
/**
* Pattern object that matches an opening tag.
*
* @param {string|RegExp} tag Name of the tag. Also will accept a regular
* expression to match against the tag name.
* @param {Object=} opt_attrs Optional map of attribute names to desired values.
* This pattern will only match when all attributes are present and match
* the string or regular expression value provided here.
* @param {Object=} opt_styles Optional map of CSS style names to desired
* values. This pattern will only match when all styles are present and
* match the string or regular expression value provided here.
* @param {Function=} opt_test Optional function that takes the element as a
* parameter and returns true if this pattern should match it.
* @constructor
* @extends {goog.dom.pattern.Tag}
*/
goog.dom.pattern.StartTag = function(tag, opt_attrs, opt_styles, opt_test) {
goog.dom.pattern.Tag.call(
this,
tag,
goog.dom.TagWalkType.START_TAG,
opt_attrs,
opt_styles,
opt_test);
};
goog.inherits(goog.dom.pattern.StartTag, goog.dom.pattern.Tag);

View File

@@ -0,0 +1,150 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a tag.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.Tag');
goog.require('goog.dom.pattern');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
goog.require('goog.object');
/**
* Pattern object that matches an tag.
*
* @param {string|RegExp} tag Name of the tag. Also will accept a regular
* expression to match against the tag name.
* @param {goog.dom.TagWalkType} type Type of token to match.
* @param {Object=} opt_attrs Optional map of attribute names to desired values.
* This pattern will only match when all attributes are present and match
* the string or regular expression value provided here.
* @param {Object=} opt_styles Optional map of CSS style names to desired
* values. This pattern will only match when all styles are present and
* match the string or regular expression value provided here.
* @param {Function=} opt_test Optional function that takes the element as a
* parameter and returns true if this pattern should match it.
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.Tag = function(tag, type, opt_attrs, opt_styles, opt_test) {
if (goog.isString(tag)) {
this.tag_ = tag.toUpperCase();
} else {
this.tag_ = tag;
}
this.type_ = type;
this.attrs_ = opt_attrs || null;
this.styles_ = opt_styles || null;
this.test_ = opt_test || null;
};
goog.inherits(goog.dom.pattern.Tag, goog.dom.pattern.AbstractPattern);
/**
* The tag to match.
*
* @type {string|RegExp}
* @private
*/
goog.dom.pattern.Tag.prototype.tag_;
/**
* The type of token to match.
*
* @type {goog.dom.TagWalkType}
* @private
*/
goog.dom.pattern.Tag.prototype.type_;
/**
* The attributes to test for.
*
* @type {Object}
* @private
*/
goog.dom.pattern.Tag.prototype.attrs_ = null;
/**
* The styles to test for.
*
* @type {Object}
* @private
*/
goog.dom.pattern.Tag.prototype.styles_ = null;
/**
* Function that takes the element as a parameter and returns true if this
* pattern should match it.
*
* @type {Function}
* @private
*/
goog.dom.pattern.Tag.prototype.test_ = null;
/**
* Test whether the given token is a tag token which matches the tag name,
* style, and attributes provided in the constructor.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
* matches, <code>NO_MATCH</code> otherwise.
* @override
*/
goog.dom.pattern.Tag.prototype.matchToken = function(token, type) {
// Check the direction and tag name.
if (type == this.type_ &&
goog.dom.pattern.matchStringOrRegex(this.tag_, token.nodeName)) {
// Check the attributes.
if (this.attrs_ &&
!goog.object.every(
this.attrs_,
goog.dom.pattern.matchStringOrRegexMap,
token)) {
return goog.dom.pattern.MatchType.NO_MATCH;
}
// Check the styles.
if (this.styles_ &&
!goog.object.every(
this.styles_,
goog.dom.pattern.matchStringOrRegexMap,
token.style)) {
return goog.dom.pattern.MatchType.NO_MATCH;
}
if (this.test_ && !this.test_(token)) {
return goog.dom.pattern.MatchType.NO_MATCH;
}
// If we reach this point, we have a match and should save it.
this.matchedNode = token;
return goog.dom.pattern.MatchType.MATCH;
}
return goog.dom.pattern.MatchType.NO_MATCH;
};

View File

@@ -0,0 +1,70 @@
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview DOM pattern to match a text node.
*
* @author robbyw@google.com (Robby Walker)
*/
goog.provide('goog.dom.pattern.Text');
goog.require('goog.dom.NodeType');
goog.require('goog.dom.pattern');
goog.require('goog.dom.pattern.AbstractPattern');
goog.require('goog.dom.pattern.MatchType');
/**
* Pattern object that matches text by exact matching or regular expressions.
*
* @param {string|RegExp} match String or regular expression to match against.
* @constructor
* @extends {goog.dom.pattern.AbstractPattern}
*/
goog.dom.pattern.Text = function(match) {
this.match_ = match;
};
goog.inherits(goog.dom.pattern.Text, goog.dom.pattern.AbstractPattern);
/**
* The text or regular expression to match.
*
* @type {string|RegExp}
* @private
*/
goog.dom.pattern.Text.prototype.match_;
/**
* Test whether the given token is a text token which matches the string or
* regular expression provided in the constructor.
*
* @param {Node} token Token to match against.
* @param {goog.dom.TagWalkType} type The type of token.
* @return {goog.dom.pattern.MatchType} <code>MATCH</code> if the pattern
* matches, <code>NO_MATCH</code> otherwise.
* @override
*/
goog.dom.pattern.Text.prototype.matchToken = function(token, type) {
if (token.nodeType == goog.dom.NodeType.TEXT &&
goog.dom.pattern.matchStringOrRegex(this.match_, token.nodeValue)) {
this.matchedNode = token;
return goog.dom.pattern.MatchType.MATCH;
}
return goog.dom.pattern.MatchType.NO_MATCH;
};