about summary refs log tree commit diff stats
path: root/src/css
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-02-08 01:32:40 +0100
committerbptato <nincsnevem662@gmail.com>2024-02-08 01:44:32 +0100
commitf666dbafec85ba6ed64db8123ceae28b80c4cb3b (patch)
treec8a26185197f2391551ae9f2570042d7e8e0fa10 /src/css
parent6faf5cff21f8c1d382ffa605b7aa56be30ff54db (diff)
downloadchawan-f666dbafec85ba6ed64db8123ceae28b80c4cb3b.tar.gz
dom: atomize id, name, DOMTokenList
Diffstat (limited to 'src/css')
-rw-r--r--src/css/selectorparser.nim40
-rw-r--r--src/css/sheet.nim117
2 files changed, 90 insertions, 67 deletions
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index 9e79a36d..eacb48d9 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -51,13 +51,17 @@ type
       when defined(debug):
         tags: string
     of ID_SELECTOR:
-      id*: string
+      id*: CAtom
+      when defined(debug):
+        ids: string
+    of CLASS_SELECTOR:
+      class*: CAtom
+      when defined(debug):
+        classs: string
     of ATTR_SELECTOR:
       attr*: string
       value*: string
       rel*: SelectorRelation
-    of CLASS_SELECTOR:
-      class*: string
     of UNIVERSAL_SELECTOR: #TODO namespaces?
       discard
     of PSEUDO_SELECTOR:
@@ -112,9 +116,12 @@ func `$`*(sel: Selector): string =
     when defined(debug):
       return sel.tags
     else:
-      return "tagt " & $int(sel.tag)
+      return "ATOM" & $int(sel.tag)
   of ID_SELECTOR:
-    return '#' & sel.id
+    when defined(debug):
+      return "#" & sel.ids
+    else:
+      return "#ATOM" & $int(sel.id)
   of ATTR_SELECTOR:
     let rel = case sel.rel.t
     of RELATION_EXISTS: ""
@@ -130,7 +137,10 @@ func `$`*(sel: Selector): string =
     of FLAG_S: " s"
     return '[' & sel.attr & rel & sel.value & flag & ']'
   of CLASS_SELECTOR:
-    return '.' & sel.class
+    when defined(debug):
+      return "." & sel.classs
+    else:
+      return ".ATOM" & $int(sel.id)
   of UNIVERSAL_SELECTOR:
     return "*"
   of PSEUDO_SELECTOR:
@@ -397,7 +407,10 @@ proc parseClassSelector(state: var SelectorParser): Selector =
   if not state.has(): fail
   let tok = get_tok state.consume()
   if tok.tokenType != CSS_IDENT_TOKEN: fail
-  return Selector(t: CLASS_SELECTOR, class: tok.value)
+  let class = state.factory.toAtom(tok.value)
+  result = Selector(t: CLASS_SELECTOR, class: class)
+  when defined(debug):
+    result.classs = tok.value
 
 proc parseCompoundSelector(state: var SelectorParser): CompoundSelector =
   result = CompoundSelector()
@@ -408,14 +421,21 @@ proc parseCompoundSelector(state: var SelectorParser): CompoundSelector =
       case tok.tokenType
       of CSS_IDENT_TOKEN:
         inc state.at
-        let tag = state.factory.toAtom(tok.value.toLowerAscii())
-        result.add(Selector(t: TYPE_SELECTOR, tag: tag))
+        let s = tok.value.toLowerAscii()
+        let tag = state.factory.toAtom(s)
+        let sel = Selector(t: TYPE_SELECTOR, tag: tag)
+        when defined(debug):
+          sel.tags = s
+        result.add(sel)
       of CSS_COLON_TOKEN:
         inc state.at
         result.add(state.parsePseudoSelector())
       of CSS_HASH_TOKEN:
         inc state.at
-        result.add(Selector(t: ID_SELECTOR, id: tok.value))
+        let id = state.factory.toAtom(tok.value)
+        result.add(Selector(t: ID_SELECTOR, id: id))
+        when defined(debug):
+          result[^1].ids = tok.value
       of CSS_COMMA_TOKEN: break
       of CSS_DELIM_TOKEN:
         case tok.cvalue
diff --git a/src/css/sheet.nim b/src/css/sheet.nim
index 4990d991..14d9b717 100644
--- a/src/css/sheet.nim
+++ b/src/css/sheet.nim
@@ -25,25 +25,24 @@ type
 
   CSSStylesheet* = ref object
     mqList*: seq[CSSMediaQueryDef]
-    #TODO maybe just array[TagType] would be more efficient
     tagTable: Table[CAtom, seq[CSSRuleDef]]
-    idTable: Table[string, seq[CSSRuleDef]]
-    classTable: Table[string, seq[CSSRuleDef]]
+    idTable: Table[CAtom, seq[CSSRuleDef]]
+    classTable: Table[CAtom, seq[CSSRuleDef]]
     generalList: seq[CSSRuleDef]
     len: int
     factory: CAtomFactory
 
 type SelectorHashes = object
   tag: CAtom
-  id: string
-  class: string
+  id: CAtom
+  class: CAtom
 
 func newStylesheet*(cap: int, factory: CAtomFactory): CSSStylesheet =
   let bucketsize = cap div 2
   return CSSStylesheet(
     tagTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
-    idTable: initTable[string, seq[CSSRuleDef]](bucketsize),
-    classTable: initTable[string, seq[CSSRuleDef]](bucketsize),
+    idTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
+    classTable: initTable[CAtom, seq[CSSRuleDef]](bucketsize),
     generalList: newSeqOfCap[CSSRuleDef](bucketsize),
     factory: factory
   )
@@ -72,62 +71,66 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool =
   of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR:
     return false
   of PSEUDO_SELECTOR:
-    if sel.pseudo.t in {PSEUDO_IS, PSEUDO_WHERE}:
-      # 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
-      var cancel_tag = false
-      var cancel_id = false
-      var cancel_class = 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
-        nhashes.getSelectorIds(sel.pseudo.fsels[i])
-        if hashes.tag == CAtomNull:
-          hashes.tag = nhashes.tag
-        elif not cancel_tag and nhashes.tag != CAtomNull and nhashes.tag != hashes.tag:
-          cancel_tag = true
-
-        if hashes.id == "":
-          hashes.id = nhashes.id
-        elif not cancel_id and nhashes.id != "" and nhashes.id != hashes.id:
-          cancel_id = true
-
-        if hashes.class == "":
-          hashes.class = nhashes.class
-        elif not cancel_class and nhashes.class != "" and nhashes.class != hashes.class:
-          cancel_class = true
-
-        inc i
-
-      if cancel_tag:
-        hashes.tag = CAtomNull
-      if cancel_id:
-        hashes.id = ""
-      if cancel_class:
-        hashes.class = ""
-
-      if hashes.tag != CAtomNull or hashes.id != "" or hashes.class != "":
-        return true
+    if sel.pseudo.t notin {PSEUDO_IS, PSEUDO_WHERE}:
+      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
+    var cancelTag = false
+    var cancelId = false
+    var cancelClass = 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
+      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:
+        cancelTag = true
+
+      if hashes.id == CAtomNull:
+        hashes.id = nhashes.id
+      elif not cancelId and 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:
+        cancelClass = true
+
+      inc i
+
+    if cancelTag:
+      hashes.tag = CAtomNull
+    if cancelId:
+      hashes.id = CAtomNull
+    if cancelClass:
+      hashes.class = CAtomNull
+
+    return hashes.tag != CAtomNull or hashes.id != CAtomNull or
+      hashes.class != CAtomNull
 
 proc ruleDefCmp(a, b: CSSRuleDef): int =
   cmp(a.idx, b.idx)
 
-iterator genRules*(sheet: CSSStylesheet, tag: CAtom, id: string,
-    classes: seq[string]): CSSRuleDef =
+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 != "":
+  if id != CAtomNull:
     sheet.idTable.withValue(id, v):
       for rule in v[]:
         rules.add(rule)
@@ -150,12 +153,12 @@ proc add(sheet: var CSSStylesheet, rule: CSSRuleDef) =
         p[].add(rule)
       do:
         sheet.tagTable[hashes.tag] = @[rule]
-    elif hashes.id != "":
+    elif hashes.id != CAtomNull:
       sheet.idTable.withValue(hashes.id, p):
         p[].add(rule)
       do:
         sheet.idTable[hashes.id] = @[rule]
-    elif hashes.class != "":
+    elif hashes.class != CAtomNull:
       sheet.classTable.withValue(hashes.class, p):
         p[].add(rule)
       do: