about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/css/cascade.nim7
-rw-r--r--src/css/select.nim35
-rw-r--r--src/html/dom.nim146
-rw-r--r--src/io/buffer.nim3
4 files changed, 100 insertions, 91 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 16e5664a..8b93e8d0 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -261,9 +261,10 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
       let elem = Element(styledChild.node)
       # Add a nil before the last element (in-stack), so we can remove the
       # stylesheets
-      if elem.sheets.len > 0:
-        author.add(elem.sheets)
-        lenstack.add(elem.sheets.len)
+      let sheets = elem.sheets()
+      if sheets.len > 0:
+        author.add(sheets)
+        lenstack.add(sheets.len)
         styledStack.add((nil, nil, PSEUDO_NONE, nil))
 
       stack_append styledChild, PSEUDO_AFTER
diff --git a/src/css/select.nim b/src/css/select.nim
index f8769418..b43604c4 100644
--- a/src/css/select.nim
+++ b/src/css/select.nim
@@ -30,7 +30,14 @@ func pseudoSelectorMatches(elem: Element, sel: Selector): bool =
   of PSEUDO_ONLY_CHILD: return elem.parentNode.firstElementChild == elem and elem.parentNode.lastElementChild == elem
   of PSEUDO_HOVER: return elem.hover
   of PSEUDO_ROOT: return elem == elem.document.html
-  of PSEUDO_NTH_CHILD: return int64(sel.pseudonum - 1) in elem.parentNode.children.low..elem.parentNode.children.high and elem.parentNode.children[int64(sel.pseudonum - 1)] == elem
+  of PSEUDO_NTH_CHILD:
+    let n = int64(sel.pseudonum - 1)
+    var i = 0
+    for child in elem.parentNode.children:
+      if i == n:
+        return child == elem
+      inc i
+    return false
   of PSEUDO_CHECKED:
     if elem.tagType == TAG_INPUT:
       return HTMLInputElement(elem).checked
@@ -74,18 +81,22 @@ func combinatorSelectorMatches(elem: Element, sel: Selector): bool =
         dec i
         e = e.parentElement
     of NEXT_SIBLING_COMBINATOR:
-      var e = elem.previousElementSibling
-      while e != nil and i >= 0:
-        if not e.selectorsMatch(sel.csels[i]):
-          return false
-        dec i
-        e = e.previousElementSibling
-    of SUBSEQ_SIBLING_COMBINATOR:
-      var e = elem.previousElementSibling
-      while e != nil and i >= 0:
-        if e.selectorsMatch(sel.csels[i]):
+      var found = false
+      for child in elem.parentElement.children_rev:
+        if found:
+          if not child.selectorsMatch(sel.csels[i]):
+            return false
           dec i
-        e = e.previousElementSibling
+        if child == elem:
+          found = true
+    of SUBSEQ_SIBLING_COMBINATOR:
+      var found = false
+      for child in elem.parentElement.children_rev:
+        if found:
+          if child.selectorsMatch(sel.csels[i]):
+            dec i
+        if child == elem:
+          found = true
     return i == -1
   return false
 
diff --git a/src/html/dom.nim b/src/html/dom.nim
index d5ee1015..2117e6f4 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -179,18 +179,45 @@ iterator children*(node: Node): Element {.inline.} =
     if child.nodeType == ELEMENT_NODE:
       yield Element(child)
 
-iterator elements*(node: Node, tag: TagType): Element {.inline.} =
-  var stack: seq[Element]
-  for child in node.children:
-    stack.add(child)
+iterator children_rev*(node: Node): Element {.inline.} =
+  for i in countdown(node.childNodes.high, 0):
+    let child = node.childNodes[i]
+    if child.nodeType == ELEMENT_NODE:
+      yield Element(child)
+
+# Returns the node's ancestors
+iterator ancestors*(node: Node): Element {.inline.} =
+  var element = node.parentElement
+  while element != nil:
+    yield element
+    element = element.parentElement
+
+# Returns the node itself and its ancestors
+iterator branch*(node: Node): Node {.inline.} =
+  var node = node
+  while node != nil:
+    yield node
+    node = node.parentNode
+
+# Returns the node's descendants
+iterator descendants*(node: Node): Node {.inline.} =
+  var stack: seq[Node]
+  stack.add(node.childNodes)
   while stack.len > 0:
-    let element = stack.pop()
-    if element.tagType == tag:
-      yield element
-    for i in countdown(element.childNodes.high, 0):
-      let child = element.childNodes[i]
-      if child.nodeType == ELEMENT_NODE:
-        stack.add(Element(child))
+    let node = stack.pop()
+    yield node
+    for i in countdown(node.childNodes.high, 0):
+      stack.add(node.childNodes[i])
+
+iterator elements*(node: Node): Element {.inline.} =
+  for child in node.descendants:
+    if child.nodeType == ELEMENT_NODE:
+      yield Element(child)
+
+iterator elements*(node: Node, tag: TagType): Element {.inline.} =
+  for desc in node.elements:
+    if desc.tagType == tag:
+      yield desc
 
 iterator inputs(form: HTMLFormElement): HTMLInputElement {.inline.} =
   for control in form.controls:
@@ -220,30 +247,6 @@ iterator textNodes*(node: Node): Text {.inline.} =
   for node in node.childNodes:
     if node.nodeType == TEXT_NODE:
       yield Text(node)
-
-# Returns the node's ancestors
-iterator ancestors*(node: Node): Element {.inline.} =
-  var element = node.parentElement
-  while element != nil:
-    yield element
-    element = element.parentElement
-
-# Returns the node itself and its ancestors
-iterator branch*(node: Node): Node {.inline.} =
-  var node = node
-  while node != nil:
-    yield node
-    node = node.parentNode
-
-# Returns the node's descendants
-iterator descendants*(node: Node): Node {.inline.} =
-  var stack: seq[Node]
-  stack.add(node.childNodes)
-  while stack.len > 0:
-    let node = stack.pop()
-    yield node
-    for i in countdown(node.childNodes.high, 0):
-      stack.add(node.childNodes[i])
   
 iterator options*(select: HTMLSelectElement): HTMLOptionElement {.inline.} =
   for child in select.children:
@@ -309,26 +312,26 @@ func connected*(node: Node): bool =
 func inSameTree*(a, b: Node): bool =
   a.rootNode == b.rootNode
 
-func children*(node: Node): seq[Element] =
-  for child in node.children:
-    result.add(child)
-
 func filterDescendants*(element: Element, predicate: (proc(child: Element): bool)): seq[Element] =
   var stack: seq[Element]
-  stack.add(element.children)
+  for child in element.children_rev:
+    stack.add(child)
   while stack.len > 0:
     let child = stack.pop()
     if predicate(child):
       result.add(child)
-    stack.add(child.children)
+    for child in element.children_rev:
+      stack.add(child)
 
 func all_descendants*(element: Element): seq[Element] =
   var stack: seq[Element]
-  stack.add(element.children)
+  for child in element.children_rev:
+    stack.add(child)
   while stack.len > 0:
     let child = stack.pop()
     result.add(child)
-    stack.add(child.children)
+    for child in element.children_rev:
+      stack.add(child)
 
 # a == b or b in a's ancestors
 func contains*(a, b: Node): bool =
@@ -336,10 +339,6 @@ func contains*(a, b: Node): bool =
     if node == b: return true
   return false
 
-func branch*(node: Node): seq[Node] =
-  for node in node.branch:
-    result.add(node)
-
 func firstChild*(node: Node): Node =
   if node.childNodes.len == 0:
     return nil
@@ -351,29 +350,31 @@ func lastChild*(node: Node): Node =
   return node.childNodes[^1]
 
 func firstElementChild*(node: Node): Element =
-  if node.children.len == 0:
-    return nil
-  return node.children[0]
+  for child in node.children:
+    return child
+  return nil
 
 func lastElementChild*(node: Node): Element =
-  if node.children.len == 0:
-    return nil
-  return node.children[^1]
+  for child in node.children:
+    return child
+  return nil
 
 func previousElementSibling*(elem: Element): Element =
-  var e = elem.previousSibling
-  while e != nil:
-    if e.nodeType == ELEMENT_NODE:
-      return Element(e)
-    e = e.previousSibling
+  var i = elem.parentNode.childNodes.find(elem)
+  dec i
+  while i >= 0:
+    if elem.parentNode.childNodes[i].nodeType == ELEMENT_NODE:
+      return elem
+    dec i
   return nil
 
 func nextElementSibling*(elem: Element): Element =
-  var e = elem.nextSibling
-  while e != nil:
-    if e.nodeType == ELEMENT_NODE:
-      return Element(e)
-    e = e.nextSibling
+  var i = elem.parentNode.childNodes.find(elem)
+  inc i
+  while i < elem.parentNode.childNodes.len:
+    if elem.parentNode.childNodes[i].nodeType == ELEMENT_NODE:
+      return elem
+    inc i
   return nil
 
 func attr*(element: Element, s: string): string =
@@ -615,15 +616,15 @@ func newAttr*(parent: Element, key, value: string): Attr =
 func getElementById*(document: Document, id: string): Element =
   if id.len == 0:
     return nil
-  var stack = document.children
+  var stack: seq[Element]
+  for child in document.children_rev:
+    stack.add(child)
   while stack.len > 0:
     let element = stack.pop()
     if element.id == id:
       return element
-    for i in countdown(element.childNodes.high, 0):
-      let child = element.childNodes[i]
-      if child.nodeType == ELEMENT_NODE:
-        stack.add(Element(child))
+    for child in document.children_rev:
+      stack.add(child)
   return nil
 
 func getElementsByTag*(document: Document, tag: TagType): seq[Element] =
@@ -832,12 +833,9 @@ proc resetFormOwner(element: FormAssociatedElement) =
   element.form = nil
   if element.tagType in ListedElements and element.attrb("form") and element.connected:
     let form = element.attr("form")
-    for desc in element.rootNode.descendants:
-      if desc.nodeType == ELEMENT_NODE:
-        let desc = Element(desc)
-        if desc.id == form:
-          if desc.tagType == TAG_FORM:
-            element.setForm(HTMLFormElement(desc))
+    for desc in element.elements(TAG_FORM):
+      if desc.id == form:
+        element.setForm(HTMLFormElement(desc))
 
 proc insertionSteps(insertedNode: Node) =
   if insertedNode.nodeType == ELEMENT_NODE:
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index a9843eb4..e7a5d881 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -727,8 +727,7 @@ proc loadResources(buffer: Buffer, document: Document) =
               let sheet = parseStylesheet(res.s)
               elem.sheet = sheet
 
-    for i in countdown(elem.children.high, 0):
-      let child = elem.children[i]
+    for child in elem.children_rev:
       stack.add(child)
 
 proc load*(buffer: Buffer) =