about summary refs log tree commit diff stats
path: root/src/css
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-08-23 18:58:45 +0200
committerbptato <nincsnevem662@gmail.com>2022-08-23 19:02:42 +0200
commit01a6051deb585696be18e6b90e9214fd8f5a64df (patch)
tree83b9882418751744fd1815706aecb990f9303070 /src/css
parent4eaa8830145aa78e37c0c21fd943a6de24adc9df (diff)
downloadchawan-01a6051deb585696be18e6b90e9214fd8f5a64df.tar.gz
Use more accurate selector terminology
Diffstat (limited to 'src/css')
-rw-r--r--src/css/match.nim6
-rw-r--r--src/css/selectorparser.nim51
-rw-r--r--src/css/sheet.nim13
3 files changed, 39 insertions, 31 deletions
diff --git a/src/css/match.nim b/src/css/match.nim
index 4393df42..31eba22e 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -21,9 +21,9 @@ func attrSelectorMatches(elem: Element, sel: Selector): bool =
   of '*': return elem.attr(sel.attr).contains(sel.value)
   else: return false
 
-func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: SelectorList, felem: T = nil): bool
+func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: ComplexSelector, felem: T = nil): bool
 
-func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: seq[SelectorList], felem: T = nil): bool =
+func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: SelectorList, felem: T = nil): bool =
   for slist in selectors:
     if elem.selectorsMatch(slist, felem):
       return true
@@ -184,7 +184,7 @@ func selectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T): b
 
 # WARNING for StyledNode, this has the side effect of modifying depends.
 #TODO make that an explicit flag or something, also get rid of the Element case
-func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: SelectorList, felem: T = nil): bool =
+func selectorsMatch*[T: Element|StyledNode](elem: T, selectors: ComplexSelector, felem: T = nil): bool =
   let felem = if felem != nil:
     felem
   else:
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index 483e5685..b7197d95 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -30,11 +30,11 @@ type
     SUBSEQ_SIBLING_COMBINATOR
 
   SelectorParser = object
-    selectors: seq[SelectorList]
+    selectors: seq[ComplexSelector]
     query: QueryMode
     combinator: Selector
 
-  Selector* = ref object of RootObj
+  Selector* = ref object of RootObj # compound selector
     case t*: SelectorType
     of TYPE_SELECTOR:
       tag*: TagType
@@ -54,24 +54,28 @@ type
       elem*: PseudoElem
     of COMBINATOR_SELECTOR:
       ct*: CombinatorType
-      csels*: seq[SelectorList]
+      csels*: SelectorList
 
   PseudoData* = object
     case t*: PseudoClass
     of PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD:
       anb*: CSSAnB
-      ofsels*: Option[seq[SelectorList]]
+      ofsels*: Option[SelectorList]
     of PSEUDO_IS, PSEUDO_WHERE, PSEUDO_NOT:
-      fsels*: seq[SelectorList]
+      fsels*: SelectorList
     else: discard
 
-  SelectorList* = seq[Selector]
+  # Kind of an oversimplification, but the distinction between complex and
+  # compound selectors isn't too significant.
+  ComplexSelector* = seq[Selector]
+
+  SelectorList* = seq[ComplexSelector]
 
 # For debugging
 proc tostr(ftype: enum): string =
   return ($ftype).split('_')[1..^1].join("-").tolower()
 
-proc `$`*(sellist: SelectorList): string
+proc `$`*(sellist: ComplexSelector): string
 
 proc `$`*(sel: Selector): string =
   case sel.t
@@ -119,11 +123,11 @@ proc `$`*(sel: Selector): string =
       if slist != sel.csels[^1]:
         result &= delim
 
-proc `$`*(sellist: SelectorList): string =
+proc `$`*(sellist: ComplexSelector): string =
   for sel in sellist:
     result &= $sel
 
-func getSpecificity*(sels: SelectorList): int
+func getSpecificity*(sels: ComplexSelector): int
 
 func getSpecificity(sel: Selector): int =
   case sel.t
@@ -159,16 +163,16 @@ func getSpecificity(sel: Selector): int =
     for child in sel.csels:
       result += getSpecificity(child)
 
-func getSpecificity*(sels: SelectorList): int =
+func getSpecificity*(sels: ComplexSelector): int =
   for sel in sels:
     result += getSpecificity(sel)
 
-func pseudo*(sels: SelectorList): PseudoElem =
+func pseudo*(sels: ComplexSelector): PseudoElem =
   if sels.len > 0 and sels[^1].t == PSELEM_SELECTOR:
     return sels[^1].elem
   return PSEUDO_NONE
 
-func optimizeSelectorList*(selectors: SelectorList): SelectorList =
+func optimizeComplexSelector*(selectors: ComplexSelector): ComplexSelector =
   #pass 1: check for invalid sequences
   var i = 1
   while i < selectors.len:
@@ -180,7 +184,7 @@ func optimizeSelectorList*(selectors: SelectorList): SelectorList =
   #pass 2: move selectors in combination
   if selectors.len > 1:
     var i = 0
-    var slow: SelectorList
+    var slow: ComplexSelector
     if selectors[0].t == UNIVERSAL_SELECTOR:
       inc i
 
@@ -207,13 +211,13 @@ proc getLastSel(state: SelectorParser): Selector =
   else:
     return state.selectors[^1][^1]
 
-proc addSelectorList(state: var SelectorParser) =
+proc addComplexSelector(state: var SelectorParser) =
   if state.combinator != nil:
     state.selectors[^1].add(state.combinator)
     state.combinator = nil
   state.selectors.add(newSeq[Selector]())
 
-func getSelectorLists(state: var SelectorParser): seq[SelectorList] =
+func getComplexSelectors(state: var SelectorParser): seq[ComplexSelector] =
   result = state.selectors
   if state.combinator != nil:
     result[^1].add(state.combinator)
@@ -223,8 +227,7 @@ proc parseSelectorCombinator(state: var SelectorParser, ct: CombinatorType, csst
                             CSS_COLON_TOKEN}:
     if state.combinator != nil and state.combinator.ct != ct:
       let nc = Selector(t: COMBINATOR_SELECTOR, ct: ct)
-      nc.csels.add(newSeq[Selector]())
-      nc.csels[^1].add(state.combinator)
+      nc.csels.add(@[state.combinator])
       state.combinator = nc
 
     if state.combinator == nil:
@@ -314,7 +317,7 @@ proc parseSelectorToken(state: var SelectorParser, csstoken: CSSToken) =
     state.addSelector(Selector(t: ID_SELECTOR, id: csstoken.value))
   of CSS_COMMA_TOKEN:
     if state.selectors[^1].len > 0:
-      state.addSelectorList()
+      state.addComplexSelector()
   of CSS_WHITESPACE_TOKEN:
     if state.selectors[^1].len > 0 or state.combinator != nil:
       state.query = QUERY_DESC_COMBINATOR
@@ -365,12 +368,12 @@ proc parseSelectorSimpleBlock(state: var SelectorParser, cssblock: CSSSimpleBloc
 
 proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction)
 
-proc parseSelectorFunctionBody(state: var SelectorParser, body: seq[CSSComponentValue]): seq[SelectorList] =
+proc parseSelectorFunctionBody(state: var SelectorParser, body: seq[CSSComponentValue]): seq[ComplexSelector] =
   let osels = state.selectors
   let ocomb = state.combinator
   state.combinator = nil
-  state.selectors = newSeq[SelectorList]()
-  state.addSelectorList()
+  state.selectors = newSeq[ComplexSelector]()
+  state.addComplexSelector()
   for cval in body:
     if cval of CSSToken:
       state.parseSelectorToken(CSSToken(cval))
@@ -378,7 +381,7 @@ proc parseSelectorFunctionBody(state: var SelectorParser, body: seq[CSSComponent
       state.parseSelectorSimpleBlock(CSSSimpleBlock(cval))
     elif cval of CSSFunction:
       state.parseSelectorFunction(CSSFunction(cval))
-  result = state.getSelectorLists()
+  result = state.getComplexSelectors()
   state.selectors = osels
   state.combinator = ocomb
 
@@ -423,9 +426,9 @@ proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction)
   state.addSelector(fun)
   fun.pseudo.fsels = state.parseSelectorFunctionBody(cssfunction.value)
 
-func parseSelectors*(cvals: seq[CSSComponentValue]): seq[SelectorList] = {.cast(noSideEffect).}:
+func parseSelectors*(cvals: seq[CSSComponentValue]): seq[ComplexSelector] = {.cast(noSideEffect).}:
   var state = SelectorParser()
-  state.addSelectorList()
+  state.addComplexSelector()
   for cval in cvals:
     if cval of CSSToken:
       state.parseSelectorToken(CSSToken(cval))
diff --git a/src/css/sheet.nim b/src/css/sheet.nim
index d7b25357..1b70e52a 100644
--- a/src/css/sheet.nim
+++ b/src/css/sheet.nim
@@ -10,7 +10,7 @@ type
   CSSRuleBase* = ref object of RootObj
 
   CSSRuleDef* = ref object of CSSRuleBase
-    sels*: seq[SelectorList]
+    sels*: SelectorList
     decls*: seq[CSSDeclaration]
 
   CSSConditionalDef* = ref object of CSSRuleBase
@@ -39,7 +39,7 @@ func newStylesheet*(cap: int): CSSStylesheet =
   result.class_table = newTable[string, seq[CSSRuleDef]](bucketsize)
   result.general_list = newSeqOfCap[CSSRuleDef](bucketsize)
 
-proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool {.inline.} =
+proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool =
   case sel.t
   of TYPE_SELECTOR:
     hashes.tag = sel.tag
@@ -50,8 +50,13 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool {.inline.}
   of ID_SELECTOR:
     hashes.id = sel.id
     return true
-  of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR, COMBINATOR_SELECTOR:
-    discard
+  of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR:
+    return false
+  of COMBINATOR_SELECTOR:
+    for sel in sel.csels[^1]:
+      if hashes.getSelectorIds(sel):
+        return true
+    return false
   of PSEUDO_SELECTOR:
     if sel.pseudo.t in {PSEUDO_IS, PSEUDO_WHERE}:
       # Basically just hash whatever the selectors have in common: