diff options
-rw-r--r-- | src/css/cascade.nim | 7 | ||||
-rw-r--r-- | src/css/select.nim | 35 | ||||
-rw-r--r-- | src/html/dom.nim | 146 | ||||
-rw-r--r-- | src/io/buffer.nim | 3 |
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) = |