about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/css/cascade.nim67
-rw-r--r--src/html/dom.nim4
-rw-r--r--src/html/parser.nim10
-rw-r--r--src/io/buffer.nim13
5 files changed, 49 insertions, 46 deletions
diff --git a/.gitignore b/.gitignore
index cf1c849f..dd5ebe3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 a
 cha
 test/
+profile_results.txt
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index fe3a08fd..761280f5 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -117,7 +117,7 @@ proc checkRendered(element: Element, prev: CSSSpecifiedValues, ppseudo: array[PS
             element.rendered = false
             return
 
-proc applyRules(element: Element, ua, user: DeclarationList, author: seq[DeclarationList], pseudo: PseudoElem) =
+proc applyDeclarations(element: Element, ua, user: DeclarationList, author: seq[DeclarationList], pseudo: PseudoElem) =
   var ares: ApplyResult
 
   ares.applyNormal(ua[pseudo])
@@ -144,62 +144,65 @@ proc applyRules(element: Element, ua, user: DeclarationList, author: seq[Declara
   for rule in ares.important:
     element.applyProperty(rule, pseudo)
 
-# TODO this is kinda broken
 func applyMediaQuery(ss: CSSStylesheet): CSSStylesheet =
   result = ss
   for mq in ss.mq_list:
     if mq.query.applies():
       result.add(mq.children.applyMediaQuery())
 
-proc applyRules(document: Document, ua, user: CSSStylesheet) =
-  var stack: seq[Element]
+proc resetRules(elem: Element) =
+  elem.css = if elem.parentElement != nil:
+    elem.parentElement.css.inheritProperties()
+  else:
+    rootProperties()
+
+  for pseudo in PSEUDO_BEFORE..PSEUDO_AFTER:
+    elem.pseudo[pseudo] = nil
+
+proc applyRules(elem: Element, ua, user: CSSStylesheet, author: seq[CSSStylesheet]) {.inline.} =
+  let uadecls = calcRules(elem, ua)
+  let userdecls = calcRules(elem, user)
+  var authordecls: seq[DeclarationList]
+  for rule in author:
+    authordecls.add(calcRules(elem, rule))
 
-  var embedded_rules: seq[CSSStylesheet]
+  for pseudo in PseudoElem:
+    elem.applyDeclarations(uadecls, userdecls, authordecls, pseudo)
 
-  stack.add(document.head)
+proc applyRules(document: Document, ua, user: CSSStylesheet) =
+  var author: seq[CSSStylesheet]
 
   for sheet in document.head.sheets:
-    embedded_rules.add(sheet)
+    author.add(sheet)
 
-  stack.setLen(0)
+  var stack: seq[Element]
 
   stack.add(document.root)
-
-  var lastlen = 0
+  var lenstack = newSeqOfCap[int](15)
 
   while stack.len > 0:
     let elem = stack.pop()
 
-    # Add a nil after the last element, so we can remove the stylesheets
+    # Remove stylesheets on nil
     if elem == nil:
-      embedded_rules.setLen(embedded_rules.len - lastlen)
+      let len = lenstack.pop()
+      author.setLen(author.len - len)
       continue
 
-    embedded_rules.add(elem.sheets)
-    lastlen = elem.sheets.len
-
     if not elem.cssapplied:
       let prev = elem.css
       let ppseudo = elem.pseudo
-      if elem.parentElement != nil:
-        elem.css = elem.parentElement.css.inheritProperties()
-      else:
-        elem.css = rootProperties()
-      for pseudo in PSEUDO_BEFORE..PSEUDO_AFTER:
-        elem.pseudo[pseudo] = nil
-
-      let uarules = calcRules(elem, ua)
-      let userrules = calcRules(elem, user)
-      var authorrules: seq[DeclarationList]
-      for rule in embedded_rules:
-        authorrules.add(calcRules(elem, rule))
-
-      for pseudo in PseudoElem:
-        elem.applyRules(uarules, userrules, authorrules, pseudo)
-
+      elem.resetRules()
+      elem.applyRules(ua, user, author)
       elem.checkRendered(prev, ppseudo)
 
-    stack.add(nil)
+    # Add 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)
+      stack.add(nil)
+
     for i in countdown(elem.children.high, 0):
       stack.add(elem.children[i])
 
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 27e2eef8..22020c58 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -1,6 +1,5 @@
 import tables
 import options
-import streams
 import strutils
 
 import css/values
@@ -117,13 +116,10 @@ type
     ordinalvalue*: int
 
   HTMLStyleElement* = ref object of HTMLElement
-    sheet*: CSSStylesheet
 
   HTMLLinkElement* = ref object of HTMLElement
     href*: string
     rel*: string
-    sheet*: CSSStylesheet
-    s*: Stream
 
 # For debugging
 template `$`*(node: Node): string =
diff --git a/src/html/parser.nim b/src/html/parser.nim
index 6f5ad937..d28be97b 100644
--- a/src/html/parser.nim
+++ b/src/html/parser.nim
@@ -307,12 +307,6 @@ proc processDocumentStartElement(state: var HTMLParseState, element: Element, ta
     case element.tagType
     of VoidTagTypes:
       processDocumentEndNode(state)
-      if element.tagType == TAG_LINK:
-        if HTMLLinkElement(element).s != nil:
-          let content = HTMLLinkElement(element).s.readAll()
-          HTMLLinkElement(element).sheet = parseStylesheet(content)
-          HTMLLinkElement(element).s.close()
-          HTMLLinkElement(element).parentElement.sheets.add(HTMLLinkElement(element).sheet)
     of TAG_LI:
       HTMLLIElement(element).applyOrdinal() #needs to know parent
     else: discard
@@ -336,8 +330,8 @@ proc processDocumentEndElement(state: var HTMLParseState, tag: DOMParsedTag) =
       var str = ""
       for child in style.textNodes:
         str &= child.data
-      style.sheet = newStringStream(str).parseStylesheet()
-      style.parentElement.sheets.add(style.sheet)
+      let sheet = newStringStream(str).parseStylesheet()
+      style.parentElement.sheets.add(sheet)
     else: discard
     processDocumentEndNode(state)
 
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 06f3ba51..4020c2f2 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -710,7 +710,11 @@ proc updateHover(buffer: Buffer) =
   buffer.prevnode = thisnode
 
 proc loadResources(buffer: Buffer, document: Document) =
-  for elem in document.head.children:
+  var stack: seq[Element]
+  stack.add(document.root)
+  while stack.len > 0:
+    let elem = stack.pop()
+
     if elem.tagType == TAG_LINK:
       let elem = HTMLLinkElement(elem)
       if elem.rel == "stylesheet":
@@ -718,7 +722,12 @@ proc loadResources(buffer: Buffer, document: Document) =
         if url.issome:
           let res = buffer.loader.getPage(url.get)
           if res.s != nil and res.contenttype == "text/css":
-            elem.s = res.s
+            let sheet = parseStylesheet(res.s.readAll())
+            elem.parentElement.sheets.add(sheet)
+
+    for i in countdown(elem.children.high, 0):
+      let child = elem.children[i]
+      stack.add(child)
 
 proc load*(buffer: Buffer) =
   case buffer.contenttype