about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/css/cascade.nim2
-rw-r--r--src/css/match.nim108
2 files changed, 47 insertions, 63 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 7da77664..d0cba1de 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -80,7 +80,7 @@ type
 proc calcRule(tosorts: var ToSorts; element: Element;
     depends: var DependencyInfo; rule: CSSRuleDef) =
   for sel in rule.sels:
-    if element.selectorsMatch(sel, depends):
+    if element.matches(sel, depends):
       let spec = getSpecificity(sel)
       tosorts[sel.pseudo].add((spec, rule))
 
diff --git a/src/css/match.nim b/src/css/match.nim
index 382d6312..41df6ded 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -9,7 +9,7 @@ import html/dom
 import utils/twtstr
 
 #TODO rfNone should match insensitively for certain properties
-func attrSelectorMatches(element: Element; sel: Selector): bool =
+func matchesAttr(element: Element; sel: Selector): bool =
   case sel.rel.t
   of rtExists: return element.attrb(sel.attr)
   of rtEquals:
@@ -58,19 +58,19 @@ func attrSelectorMatches(element: Element; sel: Selector): bool =
       return val.contains(selval)
     of rfS: return val.contains(sel.value)
 
-func selectorsMatch*(element: Element; cxsel: ComplexSelector;
+func matches*(element: Element; cxsel: ComplexSelector;
   depends: var DependencyInfo): bool
 
-func selectorsMatch(element: Element; slist: SelectorList;
+func matches(element: Element; slist: SelectorList;
     depends: var DependencyInfo): bool =
   for cxsel in slist:
-    if element.selectorsMatch(cxsel, depends):
+    if element.matches(cxsel, depends):
       return true
   return false
 
-func pseudoSelectorMatches(element: Element; sel: Selector;
+func matches(element: Element; pseudo: PseudoData;
     depends: var DependencyInfo): bool =
-  case sel.pseudo.t
+  case pseudo.t
   of pcFirstChild: return element.parentNode.firstElementChild == element
   of pcLastChild: return element.parentNode.lastElementChild == element
   of pcFirstNode: return element.isFirstVisualNode()
@@ -89,9 +89,9 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
     return element.hover
   of pcRoot: return element == element.document.documentElement
   of pcNthChild:
-    let A = sel.pseudo.anb.A # step
-    let B = sel.pseudo.anb.B # start
-    if sel.pseudo.ofsels.len == 0:
+    let A = pseudo.anb.A # step
+    let B = pseudo.anb.B # start
+    if pseudo.ofsels.len == 0:
       let i = element.elIndex + 1
       if A == 0:
         return i == B
@@ -99,7 +99,7 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
       if A < 0:
         return j <= 0 and j mod A == 0
       return j >= 0 and j mod A == 0
-    if element.selectorsMatch(sel.pseudo.ofsels, depends):
+    if element.matches(pseudo.ofsels, depends):
       var i = 1
       for child in element.parentNode.elementList:
         if child == element:
@@ -109,13 +109,13 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
           if A < 0:
             return j <= 0 and j mod A == 0
           return j >= 0 and j mod A == 0
-        if child.selectorsMatch(sel.pseudo.ofsels, depends):
+        if child.matches(pseudo.ofsels, depends):
           inc i
     return false
   of pcNthLastChild:
-    let A = sel.pseudo.anb.A # step
-    let B = sel.pseudo.anb.B # start
-    if sel.pseudo.ofsels.len == 0:
+    let A = pseudo.anb.A # step
+    let B = pseudo.anb.B # start
+    if pseudo.ofsels.len == 0:
       let last = element.parentNode.lastElementChild
       let i = last.elIndex + 1 - element.elIndex
       if A == 0:
@@ -124,7 +124,7 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
       if A < 0:
         return j <= 0 and j mod A == 0
       return j >= 0 and j mod A == 0
-    if element.selectorsMatch(sel.pseudo.ofsels, depends):
+    if element.matches(pseudo.ofsels, depends):
       var i = 1
       for child in element.parentNode.elementList_rev:
         if child == element:
@@ -134,8 +134,7 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
           if A < 0:
             return j <= 0 and j mod A == 0
           return j >= 0 and j mod A == 0
-        if sel.pseudo.ofsels.len == 0 or
-            child.selectorsMatch(sel.pseudo.ofsels, depends):
+        if child.matches(pseudo.ofsels, depends):
           inc i
     return false
   of pcChecked:
@@ -149,18 +148,18 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
     depends.add(element, dtFocus)
     return element.document.focus == element
   of pcNot:
-    return not element.selectorsMatch(sel.pseudo.fsels, depends)
+    return not element.matches(pseudo.fsels, depends)
   of pcIs, pcWhere:
-    return element.selectorsMatch(sel.pseudo.fsels, depends)
+    return element.matches(pseudo.fsels, depends)
   of pcLang:
-    return sel.pseudo.s == "en" #TODO languages?
+    return pseudo.s == "en" #TODO languages?
   of pcLink:
     return element.tagType in {TAG_A, TAG_AREA} and element.attrb(satHref)
   of pcVisited:
     return false
 
-func selectorMatches(element: Element; sel: Selector;
-    depends: var DependencyInfo): bool =
+func matches(element: Element; sel: Selector; depends: var DependencyInfo):
+    bool =
   case sel.t
   of stType:
     return element.localName == sel.tag
@@ -173,88 +172,73 @@ func selectorMatches(element: Element; sel: Selector;
   of stId:
     return sel.id == element.document.factory.toLowerAscii(element.id)
   of stAttr:
-    return element.attrSelectorMatches(sel)
+    return element.matchesAttr(sel)
   of stPseudoClass:
-    return pseudoSelectorMatches(element, sel, depends)
+    return element.matches(sel.pseudo, depends)
   of stPseudoElement:
     return true
   of stUniversal:
     return true
 
-func selectorsMatch(element: Element; sels: CompoundSelector;
+func matches(element: Element; sels: CompoundSelector;
     depends: var DependencyInfo): bool =
   for sel in sels:
-    if not selectorMatches(element, sel, depends):
+    if not element.matches(sel, depends):
       return false
   return true
 
-func complexSelectorMatches(element: Element; cxsel: ComplexSelector;
+# Note: this modifies "depends".
+func matches*(element: Element; cxsel: ComplexSelector;
     depends: var DependencyInfo): bool =
   var e = element
   for i in countdown(cxsel.high, 0):
-    let sels = cxsel[i]
-    if e == nil:
-      return false
     var match = false
-    case sels.ct
+    case cxsel[i].ct
     of ctNone:
-      match = e.selectorsMatch(sels, depends)
+      match = e.matches(cxsel[i], depends)
     of ctDescendant:
       e = e.parentElement
       while e != nil:
-        if e.selectorsMatch(sels, depends):
+        if e.matches(cxsel[i], depends):
           match = true
           break
         e = e.parentElement
     of ctChild:
       e = e.parentElement
       if e != nil:
-        match = e.selectorsMatch(sels, depends)
+        match = e.matches(cxsel[i], depends)
     of ctNextSibling:
-      if e.parentElement == nil: return false
-      var found = false
-      for child in e.parentElement.elementList_rev:
-        if e == child:
-          found = true
-          continue
-        if found:
-          e = child
-          match = e.selectorsMatch(sels, depends)
-          break
+      let prev = e.previousElementSibling
+      if prev != nil:
+        e = prev
+        match = e.matches(cxsel[i], depends)
     of ctSubsequentSibling:
-      var found = false
-      if e.parentElement == nil: return false
-      for child in e.parentElement.elementList_rev:
-        if child == element:
-          found = true
-          continue
-        if not found: continue
-        if child.selectorsMatch(sels, depends):
-          e = child
-          match = true
-          break
+      let parent = e.parentNode
+      for j in countdown(e.index - 1, 0):
+        let child = parent.childList[j]
+        if child of Element:
+          let child = Element(child)
+          if child.matches(cxsel[i], depends):
+            e = child
+            match = true
+            break
     if not match:
       return false
   return true
 
-# Note: this modifies "depends".
-func selectorsMatch*(element: Element; cxsel: ComplexSelector;
-    depends: var DependencyInfo): bool =
-  return element.complexSelectorMatches(cxsel, depends)
-
 # Forward declaration hack
 querySelectorAllImpl = proc(node: Node; q: string): seq[Element] =
   result = @[]
   let selectors = parseSelectors(q, node.document.factory)
   for element in node.elements:
     var dummy: DependencyInfo
-    if element.selectorsMatch(selectors, dummy):
+    if element.matches(selectors, dummy):
       result.add(element)
 
 querySelectorImpl = proc(node: Node; q: string): Element =
   let selectors = parseSelectors(q, node.document.factory)
   for element in node.elements:
     var dummy: DependencyInfo
-    if element.selectorsMatch(selectors, dummy):
+    if element.matches(selectors, dummy):
       return element
   return nil