class PredicateFactoryPredicateFactory generates boolean-valued functions that implement tests of specific CSS selectors.
Each generated function has the signature:
predicate(node,node_metadata,dom_metadata)
and returns true iff the given node matches
the associated CSS selection rule.
(This is an internal class, primarily used by
the class Stew. These methods are subject to
change without notice.)
class PredicateFactoryand_predicate generates a function that returns true iff all of the given predicates evaluate to true.
  and_predicate:(predicates)->
    return (node,node_metadata,dom_metadata)->
      for predicate in predicates
        if not predicate(node,node_metadata,dom_metadata)
          return false
      return trueor_predicate generates a function that returns true iff any of the given predicates evaluate to true.
  or_predicate:(predicates)->
    return (node,node_metadata,dom_metadata)->
      for predicate in predicates
        if predicate(node,node_metadata,dom_metadata)
          return true
      return falseby_attribute_predicate creates a predicate
that returns true if the given attrname
matches the given attrvalue.
When attrvalue is null, then the predicate will
return true if the tested node has an attribute
named attrname.
When attrvalue is a String then the predicate will
return true if the value of the attrname attribute
equals the attrvalue string.
When attrvalue is a RegExp then the predicate will
return true if the value of the attrname attribute
matches the attrvalue expression.
When valuedelim is non-null, the specified value will
be used as a delimiter by which to split the value of
the attrname attribute, and the corresponding elements
will be tested rather than the entire string.
For example, the call:
by_attribute_predicate('class','foo',/\s+/)
will return a function that tests if a given DOM node
has been assigned class foo.  E.g, true for these:
<span class="foo"></span>
<span class="bar foo"></span>
and false for these:
<span></span>
<span class="food"></span>
              by_attribute_predicate:(attrname,attrvalue=null,valuedelim=null)->
    if typeof(attrname) is 'string'
      np = (str)->str is attrname
    else
      np = (str)->attrname.test(str)
    if attrvalue is null
      vp = null
    else if typeof(attrvalue) is 'string'
      attrvalue = attrvalue.replace(/\\\"/g,'"')
      vp = (str)->str is attrvalue
    else if attrvalue?.test?
      vp = (str)->attrvalue.test(str)
    return (node)->
      for name,value of node?.attribs
        if np(name)
          if vp is null
            return true
          else
            if valuedelim?
              if value?
                for token in value.split(valuedelim)
                  if vp(token)
                    return true
            else
              if vp(value)
                return true
      return falseby_class_predicate creates a predicate
that returns true if the given DOM node has
the specified klass value.
  by_class_predicate:(klass)=>
    return @by_attribute_predicate('class',klass,/\s+/)by_id_predicate creates a predicate
that returns true if the given DOM node has
the specified id value.
  by_id_predicate:(id)=>
    return @by_attribute_predicate('id',id)by_attr_exists_predicate creates a
predicate that returns true if the given DOM
node has an attribute with the specified attrname,
regardless of the value for the atttribute.
  by_attr_exists_predicate:(attrname)=>
    return @by_attribute_predicate(attrname,null)by_attr_value_predicate is an alias to by_attribute_predicate.
  by_attr_value_predicate:(attrname,attrvalue,valuedelim)=>
    return @by_attribute_predicate(attrname,attrvalue,valuedelim)_escape_for_regexp is an internal utility function that escapes reserved characters to create a string that can be embedded in a regular expression.
  _escape_for_regexp:(str)->return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1")by_attr_value_pipe_equals creates a predicate that
implements the [name|=value] CSS selector (matching tags
with a name attribute with a value matching value
(exactly) or a value that starts with value followed
by a - character..
(Used for selectors such as [lang|=en], for example,
which will match the values en, en-US and en-CA.)
When attrvalue is a regular expression:
If attrvalue doesn't already start with
^ (matching the beginning of a line),
then ^ will be added.
If attrvalue doesn't already end with
($|-) (matching the end of a line, or -)
then ($|-) will be added.
Hence the regular expression /f[aeio]o?/
would be converted to /^f[aeio]o?($|-)/ but
the regular expression /^en($|-)/ would be
left alone.
  by_attr_value_pipe_equals:(attrname,attrvalue)=>
    if typeof attrvalue is 'string'
      regexp_source = @_escape_for_regexp(attrvalue)
      attrvalue = new RegExp("^#{regexp_source}($|-)")
    else
      regexp_source = attrvalue.source
      modifier = ''
      modifier += 'i' if attrvalue.ignoreCase
      modifier += 'g' if attrvalue.global
      modifier += 'm' if attrvalue.multiline
      unless /^\^/.test attrvalue.source
        regexp_source = "^#{regexp_source}"
      unless /\(\$\|-\)$/.test regexp_source
        regexp_source = "#{regexp_source}($|-)"
      attrvalue = new RegExp(regexp_source,modifier)
    return @by_attribute_predicate(attrname,attrvalue)by_tag_predicate creates a
predicate that returns true if the given DOM
node is a tag with the specified name.
If name is a RegExp then the predicate will
return true if tag's name matches the
specified expression.
If name is a String then the predicate will
return true if the tag's name equals the
specified string.
  by_tag_predicate:(name)->
    if typeof name is 'string'
      return (node)->(name is node.name)
    else
      return (node)->(name.test(node.name))first_child_predicate returns a predicate that evaluates to true
iff the given node is the first child tag node among all of
its siblings.
  #{ TODO FIXME should :first-child also consider elements like <script>?
  first_child_predicate:()->return @_first_child_impl
  _first_child_impl:(node,node_metadata,dom_metadata)->
    if node.type is 'tag' and node_metadata.siblings?
      for elt in node_metadata.siblings
        if elt.type is 'tag'
          return node._stew_node_id is elt._stew_node_id
    return falseany_tag_predicate returns a predicate that evaluates
to true iff the given node is a tag.
  any_tag_predicate:()->return @_any_tag_impl(...and _any_tag_impl is the implementation of that predicate.)
  _any_tag_impl:(node)->(node?.type is 'tag')descendant_predicate
returns a predicate that for the given array
P containing n, evaluates to true for
a given node if:
P[n-1](node) is true, and
P[n-2](parent) is true for some element
parent that is an ancestor of node
P[n-3](parent2) is true for some element
 parent2 that is an ancestor of parent
...etc.
In other words, the returned predicate will evalue to true
for the current node if each of the given predicates
evaluates to true for some ancestor of the node, in sequence.
(I.e., the node that matches predicates[n] must be an ancestor
of the node that mathces predicates[n+1].)
  descendant_predicate:(predicates)->
    if predicates.length is 1
      return predicates[0]
    else
      return (node,node_metadata,dom_metadata)->
        if predicates[predicates.length-1](node,node_metadata,dom_metadata)
          cloned_path = [].concat(node_metadata.path)
          cloned_predicates = [].concat(predicates)
          cloned_predicates.pop() # drop last predicate, we just tested it
          while cloned_path.length > 0
            node = cloned_path.pop()
            node_metadata = dom_metadata[node._stew_node_id]
            if cloned_predicates[cloned_predicates.length-1](node,node_metadata,dom_metadata)
              cloned_predicates.pop()
              if cloned_predicates.length is 0
                return true
                break
        return falsedirect_descendant_predicate returns a predicate
that evaluates to true iff child_selector evalutes
to true for the given node and parent_selector evalutes
to true for the given node's parent.
  direct_descendant_predicate:(parent_selector,child_selector)->
    return (node,node_metadata,dom_metadata)->
      if child_selector(node,node_metadata,dom_metadata)
        parent = node_metadata.parent
        parent_metadata = dom_metadata[parent._stew_node_id]
        return parent_selector(parent,parent_metadata,dom_metadata)
      return falseadjacent_sibling_predicate returns a predicate
that evaluates to true iff second evaluates
to true for the given node and first evaluates
to true for the tag sibling immediately preceding
the given node.
  adjacent_sibling_predicate:(first,second)->
    return (node,node_metadata,dom_metadata)->
      if second(node,node_metadata,dom_metadata)
        prev_tag_index = node_metadata.sib_index - 1
        while prev_tag_index > 0
          if node_metadata.siblings[prev_tag_index].type is 'tag'
            prev_tag = node_metadata.siblings[prev_tag_index]
            return first(prev_tag,dom_metadata[prev_tag._stew_node_id],dom_metadata)
          else
            prev_tag_index -= 1
      return falsepreceding_sibling_predicate returns a predicate
that evaluates to true iff second evaluates
to true for the given node and first evaluates
to true for some tag sibling preceding
the given node.
  preceding_sibling_predicate:(first,second)->
    return (node,node_metadata,dom_metadata)->
      if second(node,node_metadata,dom_metadata)
        for prev,index in node_metadata.siblings
          if index is node_metadata.sib_index
            return false
          else if prev.type is 'tag'
            if first(prev,dom_metadata[prev._stew_node_id],dom_metadata)
              return true
      return falseThe PredicateFactory class is exported under the name PredicateFactory.
exports = exports ? this
exports.PredicateFactory = PredicateFactory