about summary refs log tree commit diff stats
path: root/src/css
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-29 23:37:52 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-29 23:37:52 +0100
commita1c62fc955166e0d379bb55985981a8f680ac357 (patch)
tree3f6d4b0c409376a4d40805ce176476feeb0f12a6 /src/css
parent69646c6e3ba8b67934553bb0baed39ddb72a3d2f (diff)
downloadchawan-a1c62fc955166e0d379bb55985981a8f680ac357.tar.gz
css: fix some bugs and improve cascading a bit
Diffstat (limited to 'src/css')
-rw-r--r--src/css/cascade.nim33
-rw-r--r--src/css/cssparser.nim2
-rw-r--r--src/css/match.nim2
-rw-r--r--src/css/selectorparser.nim15
-rw-r--r--src/css/sheet.nim2
-rw-r--r--src/css/stylednode.nim18
-rw-r--r--src/css/values.nim24
7 files changed, 78 insertions, 18 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 633bf0f5..0b85addd 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -232,10 +232,6 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
 
   var author: seq[CSSStylesheet]
 
-  if document.head != nil:
-    for sheet in document.head.sheets:
-      author.add(sheet.applyMediaQuery())
-
   var lenstack = newSeqOfCap[int](256)
   var styledStack: seq[CascadeLevel]
   styledStack.add((nil, document.html, PSEUDO_NONE, cachedTree))
@@ -368,13 +364,28 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
           styledStack.add((styledParent, nil, ps, nil))
 
       let elem = Element(styledChild.node)
-      # Add a nil before the last element (in-stack), so we can remove the
-      # stylesheets
-      let sheets = elem.sheets()
-      if sheets.len > 0:
-        for sheet in sheets:
-          author.add(sheet.applyMediaQuery())
-        lenstack.add(sheets.len)
+      if cachedChild != nil and result != styledChild:
+        styledChild.sheets = cachedChild.sheets
+      else:
+        if unlikely(result == styledChild):
+          #TODO this is ugly. we should cache head sheets separately.
+          let head = document.head
+          if head != nil:
+            if head.invalid or cachedChild == nil:
+              let sheets = head.sheets()
+              for sheet in sheets:
+                styledChild.sheets.add(sheet.applyMediaQuery())
+        else:
+          let sheets = elem.sheets()
+          if sheets.len > 0:
+            for sheet in sheets:
+              styledChild.sheets.add(sheet.applyMediaQuery())
+      if styledChild.sheets.len > 0:
+        for sheet in styledChild.sheets:
+          author.add(sheet)
+        lenstack.add(styledChild.sheets.len)
+        # Add a nil before the last element (in-stack), so we know when to
+        # remove inline author sheets.
         styledStack.add((nil, nil, PSEUDO_NONE, nil))
 
       stack_append styledChild, PSEUDO_AFTER
diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim
index 29f88151..864119ea 100644
--- a/src/css/cssparser.nim
+++ b/src/css/cssparser.nim
@@ -555,7 +555,7 @@ proc consumeQualifiedRule(state: var CSSParseState): Option[CSSQualifiedRule] =
   var r = CSSQualifiedRule()
   while state.has():
     let t = state.consume()
-    if t of CSSSimpleBlock:
+    if t of CSSSimpleBlock and CSSSimpleBlock(t).token == CSS_LBRACE_TOKEN:
       r.oblock = CSSSimpleBlock(t)
       return some(r)
     elif t == CSS_LBRACE_TOKEN:
diff --git a/src/css/match.nim b/src/css/match.nim
index 950061a1..2d69943b 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -98,6 +98,8 @@ func pseudoSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem:
     return not selem.selectorsMatch(sel.pseudo.fsels, felem)
   of PSEUDO_IS, PSEUDO_WHERE:
     return selem.selectorsMatch(sel.pseudo.fsels, felem)
+  of PSEUDO_LANG:
+    return sel.pseudo.s == "en" #TODO languages?
 
 func combinatorSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T): bool =
   let selem = elem
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index 48bc8367..1e0d1a66 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -24,7 +24,7 @@ type
   PseudoClass* = enum
     PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER,
     PSEUDO_ROOT, PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD, PSEUDO_CHECKED,
-    PSEUDO_FOCUS, PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE
+    PSEUDO_FOCUS, PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE, PSEUDO_LANG
 
   CombinatorType* = enum
     DESCENDANT_COMBINATOR, CHILD_COMBINATOR, NEXT_SIBLING_COMBINATOR,
@@ -64,6 +64,8 @@ type
       ofsels*: Option[SelectorList]
     of PSEUDO_IS, PSEUDO_WHERE, PSEUDO_NOT:
       fsels*: SelectorList
+    of PSEUDO_LANG:
+      s*: string
     else: discard
 
   # Kind of an oversimplification, but the distinction between complex and
@@ -397,6 +399,17 @@ proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction)
   of "nth-last-child":
     state.parseNthChild(cssfunction, PseudoData(t: PSEUDO_NTH_LAST_CHILD))
     return
+  of "lang":
+    if cssfunction.value.len == 0: return
+    var i = 0
+    template tok: CSSComponentValue = cssfunction.value[i]
+    while i < cssfunction.value.len:
+      if tok != CSS_WHITESPACE_TOKEN: break
+      inc i
+    if i >= cssfunction.value.len: return
+    if tok != CSS_IDENT_TOKEN: return
+    state.addSelector(Selector(t: PSEUDO_SELECTOR, pseudo: PseudoData(t: PSEUDO_LANG, s: CSSToken(tok).value)))
+    return
   else: return
   state.query = QUERY_TYPE
   var data = PseudoData(t: ftype)
diff --git a/src/css/sheet.nim b/src/css/sheet.nim
index 1b70e52a..846f6b31 100644
--- a/src/css/sheet.nim
+++ b/src/css/sheet.nim
@@ -171,7 +171,7 @@ proc getDeclarations(rule: CSSQualifiedRule): seq[CSSDeclaration] {.inline.} =
 
 proc addRule(stylesheet: var CSSStylesheet, rule: CSSQualifiedRule) =
   let sels = parseSelectors(rule.prelude)
-  if sels.len > 1 or sels[^1].len > 0:
+  if sels.len > 0 and sels[^1].len > 0:
     let r = CSSRuleDef(sels: sels, decls: rule.getDeclarations())
     stylesheet.add(r)
 
diff --git a/src/css/stylednode.nim b/src/css/stylednode.nim
index 2760e179..30358b29 100644
--- a/src/css/stylednode.nim
+++ b/src/css/stylednode.nim
@@ -1,4 +1,5 @@
 import css/selectorparser
+import css/sheet
 import css/values
 import html/dom
 import html/tags
@@ -59,6 +60,7 @@ type
       computed*: CSSComputedValues
       children*: seq[StyledNode]
       depends*: DependencyInfo
+      sheets*: seq[CSSStylesheet]
     of STYLED_REPLACEMENT: # replaced elements: quotes, or (TODO) markers, images
       content*: CSSContent
 
@@ -76,6 +78,20 @@ iterator elementList_rev*(node: StyledNode): StyledNode {.inline.} =
   for i in countdown(node.children.high, 0):
     yield node.children[i]
 
+func findElement*(root: StyledNode, elem: Element): StyledNode =
+  var stack: seq[StyledNode]
+  for child in root.elementList_rev:
+    if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE:
+      stack.add(child)
+  let en = Node(elem)
+  while stack.len > 0:
+    let node = stack.pop()
+    if node.node == en:
+      return node
+    for child in node.elementList_rev:
+      if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE:
+        stack.add(child)
+
 func isDomElement*(styledNode: StyledNode): bool {.inline.} =
   styledNode.t == STYLED_ELEMENT and styledNode.pseudo == PSEUDO_NONE
 
@@ -120,7 +136,7 @@ proc addDependency*(styledNode, dep: StyledNode, t: DependencyType) =
   if dep notin styledNode.depends.nodes[t]:
     styledNode.depends.nodes[t].add(dep)
 
-func newStyledElement*(parent: StyledNode, element: Element, computed: CSSComputedValues, reg: sink DependencyInfo): StyledNode =
+func newStyledElement*(parent: StyledNode, element: Element, computed: CSSComputedValues, reg: DependencyInfo): StyledNode =
   result = StyledNode(t: STYLED_ELEMENT, computed: computed, node: element, parent: parent)
   result.depends = reg
   result.parent = parent
diff --git a/src/css/values.nim b/src/css/values.nim
index f80aa0ee..249db7db 100644
--- a/src/css/values.nim
+++ b/src/css/values.nim
@@ -15,7 +15,7 @@ export selectorparser.PseudoElem
 type
   CSSShorthandType = enum
     SHORTHAND_NONE, SHORTHAND_ALL, SHORTHAND_MARGIN, SHORTHAND_PADDING,
-    SHORTHAND_BACKGROUND
+    SHORTHAND_BACKGROUND, SHORTHAND_LIST_STYLE
 
   CSSUnit* = enum
     UNIT_CM, UNIT_MM, UNIT_IN, UNIT_PX, UNIT_PT, UNIT_PC,
@@ -209,7 +209,8 @@ const ShorthandNames = {
   "all": SHORTHAND_ALL,
   "margin": SHORTHAND_MARGIN,
   "padding": SHORTHAND_PADDING,
-  "background": SHORTHAND_BACKGROUND
+  "background": SHORTHAND_BACKGROUND,
+  "list-style": SHORTHAND_LIST_STYLE
 }.toTable()
 
 const PropertyNames = {
@@ -1108,11 +1109,28 @@ proc getComputedValues(d: CSSDeclaration): seq[(CSSComputedValue, CSSGlobalValue
           try:
             bgcolorval.color = cssColor(tok)
             result.add((bgcolorval, global))
-            break
           except CSSValueError:
             discard
     else:
       result.add((bgcolorval, global))
+  of SHORTHAND_LIST_STYLE:
+    let global = cssGlobal(d)
+    let positionptype = PROPERTY_LIST_STYLE_POSITION
+    let positionval = CSSComputedValue(t: positionptype, v: valueType(positionptype))
+    let typeptype = PROPERTY_LIST_STYLE_TYPE
+    let typeval = CSSComputedValue(t: typeptype, v: valueType(typeptype))
+    if global == VALUE_NOGLOBAL:
+      for tok in d.value:
+        try:
+          positionval.liststyleposition = cssListStylePosition(tok)
+          result.add((positionval, global))
+        except CSSValueError:
+          try:
+            typeval.liststyletype = cssListStyleType(tok)
+            result.add((typeval, global))
+          except CSSValueError:
+            #TODO list-style-image
+            discard
 
 func equals*(a, b: CSSComputedValue): bool =
   if a == b: