diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/css/cascade.nim | 67 | ||||
-rw-r--r-- | src/html/dom.nim | 4 | ||||
-rw-r--r-- | src/html/parser.nim | 10 | ||||
-rw-r--r-- | src/io/buffer.nim | 13 |
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 |