about summary refs log tree commit diff stats
path: root/src/css
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-07-29 20:26:48 +0200
committerbptato <nincsnevem662@gmail.com>2024-07-29 23:24:34 +0200
commit83d119903270acc85110c291fe0b7a4d967a9052 (patch)
treeaa9bdc680744fb2622486b84d6d5332af5d6498e /src/css
parent070e1e181f0efbd1aa4d760daa17fe2ad8e976e4 (diff)
downloadchawan-83d119903270acc85110c291fe0b7a4d967a9052.tar.gz
css: hash attribute names
Diffstat (limited to 'src/css')
-rw-r--r--src/css/cascade.nim25
-rw-r--r--src/css/sheet.nim75
2 files changed, 56 insertions, 44 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index a3039f15..8a8d8c44 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -1,6 +1,6 @@
 import std/algorithm
 import std/options
-import std/strutils
+import std/tables
 
 import chame/tags
 import css/cssparser
@@ -95,8 +95,27 @@ proc calcRule(tosorts: var ToSorts; styledNode: StyledNode; rule: CSSRuleDef) =
 
 func calcRules(styledNode: StyledNode; sheet: CSSStylesheet): RuleList =
   var tosorts: ToSorts
-  let elem = Element(styledNode.node)
-  for rule in sheet.genRules(elem.localName, elem.id, elem.classList.toks):
+  let element = Element(styledNode.node)
+  var rules: seq[CSSRuleDef] = @[]
+  sheet.tagTable.withValue(element.localName, v):
+    for rule in v[]:
+      rules.add(rule)
+  if element.id != CAtomNull:
+    sheet.idTable.withValue(element.id, v):
+      for rule in v[]:
+        rules.add(rule)
+  for class in element.classList.toks:
+    sheet.classTable.withValue(class, v):
+      for rule in v[]:
+        rules.add(rule)
+  for attr in element.attrs:
+    sheet.attrTable.withValue(attr.qualifiedName, v):
+      for rule in v[]:
+        rules.add(rule)
+  for rule in sheet.generalList:
+    rules.add(rule)
+  rules.sort(ruleDefCmp, order = Ascending)
+  for rule in rules:
     tosorts.calcRule(styledNode, rule)
   for i in PseudoElem:
     tosorts[i].sort((proc(x, y: (int, CSSRuleDef)): int =
diff --git a/src/css/sheet.nim b/src/css/sheet.nim
index eb11854e..579e7f9e 100644
--- a/src/css/sheet.nim
+++ b/src/css/sheet.nim
@@ -1,4 +1,3 @@
-import std/algorithm
 import std/tables
 
 import css/cssparser
@@ -26,10 +25,11 @@ type
 
   CSSStylesheet* = ref object
     mqList*: seq[CSSMediaQueryDef]
-    tagTable: Table[CAtom, seq[CSSRuleDef]]
-    idTable: Table[CAtom, seq[CSSRuleDef]]
-    classTable: Table[CAtom, seq[CSSRuleDef]]
-    generalList: seq[CSSRuleDef]
+    tagTable*: Table[CAtom, seq[CSSRuleDef]]
+    idTable*: Table[CAtom, seq[CSSRuleDef]]
+    classTable*: Table[CAtom, seq[CSSRuleDef]]
+    attrTable*: Table[CAtom, seq[CSSRuleDef]]
+    generalList*: seq[CSSRuleDef]
     len: int
     factory: CAtomFactory
 
@@ -37,6 +37,7 @@ type SelectorHashes = object
   tag: CAtom
   id: CAtom
   class: CAtom
+  attr: CAtom
 
 func newStylesheet*(cap: int; factory: CAtomFactory): CSSStylesheet =
   let bucketsize = cap div 2
@@ -44,6 +45,7 @@ func newStylesheet*(cap: int; factory: CAtomFactory): CSSStylesheet =
     tagTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
     idTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
     classTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
+    attrTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
     generalList: newSeqOfCap[CSSRuleDef](bucketsize),
     factory: factory
   )
@@ -69,43 +71,47 @@ proc getSelectorIds(hashes: var SelectorHashes; sel: Selector): bool =
   of stId:
     hashes.id = sel.id
     return true
-  of stAttr, stPseudoElement, stUniversal:
+  of stAttr:
+    hashes.attr = sel.attr
+  of stPseudoElement, stUniversal:
     return false
   of stPseudoClass:
     if sel.pseudo.t notin {pcIs, pcWhere}:
       return false
     # Basically just hash whatever the selectors have in common:
-    #1. get the hashable values of selector 1
-    #2. for every other selector x:
-    #3.   get hashable values of selector x
-    #4.   store hashable values of selector x that aren't stored yet
-    #5.   for every hashable value of selector 1 that doesn't match selector x
-    #6.     cancel hashable value
+    # 1. get the hashable values of selector 1
+    # 2. for every other selector x:
+    # 3.   get hashable values of selector x
+    # 4.   store hashable values of selector x that aren't stored yet
+    # 5.   for every hashable value of selector 1 that doesn't match selector x
+    # 6.     cancel hashable value
     var cancelTag = false
     var cancelId = false
     var cancelClass = false
+    var cancelAttr = false
     var i = 0
     if i < sel.pseudo.fsels.len:
       hashes.getSelectorIds(sel.pseudo.fsels[i])
       inc i
     while i < sel.pseudo.fsels.len:
-      var nhashes: SelectorHashes
+      var nhashes = SelectorHashes()
       nhashes.getSelectorIds(sel.pseudo.fsels[i])
       if hashes.tag == CAtomNull:
         hashes.tag = nhashes.tag
-      elif not cancelTag and nhashes.tag != CAtomNull and
-          nhashes.tag != hashes.tag:
+      elif nhashes.tag != CAtomNull and nhashes.tag != hashes.tag:
         cancelTag = true
       if hashes.id == CAtomNull:
         hashes.id = nhashes.id
-      elif not cancelId and nhashes.id != CAtomNull and
-          nhashes.id != hashes.id:
+      elif nhashes.id != CAtomNull and nhashes.id != hashes.id:
         cancelId = true
       if hashes.class == CAtomNull:
         hashes.class = nhashes.class
-      elif not cancelClass and nhashes.class != CAtomNull and
-          nhashes.class != hashes.class:
+      elif nhashes.class != CAtomNull and nhashes.class != hashes.class:
         cancelClass = true
+      if hashes.attr == CAtomNull:
+        hashes.attr = nhashes.attr
+      elif nhashes.attr != CAtomNull and nhashes.attr != hashes.attr:
+        cancelAttr = true
       inc i
     if cancelTag:
       hashes.tag = CAtomNull
@@ -113,34 +119,16 @@ proc getSelectorIds(hashes: var SelectorHashes; sel: Selector): bool =
       hashes.id = CAtomNull
     if cancelClass:
       hashes.class = CAtomNull
+    if cancelAttr:
+      hashes.attr = CAtomNull
     return hashes.tag != CAtomNull or hashes.id != CAtomNull or
       hashes.class != CAtomNull
 
-proc ruleDefCmp(a, b: CSSRuleDef): int =
+proc ruleDefCmp*(a, b: CSSRuleDef): int =
   cmp(a.idx, b.idx)
 
-iterator genRules*(sheet: CSSStylesheet; tag, id: CAtom; classes: seq[CAtom]):
-    CSSRuleDef =
-  var rules: seq[CSSRuleDef]
-  sheet.tagTable.withValue(tag, v):
-    for rule in v[]:
-      rules.add(rule)
-  if id != CAtomNull:
-    sheet.idTable.withValue(id, v):
-      for rule in v[]:
-        rules.add(rule)
-  for class in classes:
-    sheet.classTable.withValue(class, v):
-      for rule in v[]:
-        rules.add(rule)
-  for rule in sheet.generalList:
-    rules.add(rule)
-  rules.sort(ruleDefCmp, order = Ascending)
-  for rule in rules:
-    yield rule
-
 proc add(sheet: CSSStylesheet; rule: CSSRuleDef) =
-  var hashes: SelectorHashes
+  var hashes = SelectorHashes()
   for cxsel in rule.sels:
     hashes.getSelectorIds(cxsel)
     if hashes.tag != CAtomNull:
@@ -178,6 +166,11 @@ proc add*(sheet, sheet2: CSSStylesheet) =
       p[].add(value)
     do:
       sheet.classTable[key] = value
+  for key, value in sheet2.attrTable.pairs:
+    sheet.attrTable.withValue(key, p):
+      p[].add(value)
+    do:
+      sheet.attrTable[key] = value
 
 proc addRule(stylesheet: CSSStylesheet; rule: CSSQualifiedRule) =
   let sels = parseSelectors(rule.prelude, stylesheet.factory)