about summary refs log tree commit diff stats
path: root/src/css
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-01-15 20:48:29 +0100
committerbptato <nincsnevem662@gmail.com>2024-02-07 22:21:48 +0100
commit168bd542d989c76ce3ff09a29b8d77af448c3c12 (patch)
treee71ccd2bbce8da91caae46edf5df57f157a45d15 /src/css
parent0beb8385d88c20efbd00b7f9e6ac57bf19a109c7 (diff)
downloadchawan-168bd542d989c76ce3ff09a29b8d77af448c3c12.tar.gz
Update chame
* Update chame to the latest version
* Get rid of nodeType usage
* Add atoms
* Re-implement DOM attributes
* document.write
Diffstat (limited to 'src/css')
-rw-r--r--src/css/cascade.nim8
-rw-r--r--src/css/match.nim9
-rw-r--r--src/css/selectorparser.nim58
-rw-r--r--src/css/sheet.nim60
4 files changed, 74 insertions, 61 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index f9422a19..4df558c0 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -91,7 +91,7 @@ proc calcRule(tosorts: var ToSorts, styledNode: StyledNode, rule: CSSRuleDef) =
 func calcRules(styledNode: StyledNode, sheet: CSSStylesheet): DeclarationList =
   var tosorts: ToSorts
   let elem = Element(styledNode.node)
-  for rule in sheet.genRules(elem.tagType, elem.id, elem.classList.toks):
+  for rule in sheet.genRules(elem.localName, elem.id, elem.classList.toks):
     tosorts.calcRule(styledNode, rule)
   for i in PseudoElem:
     tosorts[i].sort((proc(x, y: (int, seq[CSSDeclaration])): int =
@@ -383,12 +383,12 @@ proc applyRulesFrameInvalid(frame: CascadeFrame, ua, user: CSSStylesheet,
   else:
     assert child != nil
     if styledParent != nil:
-      if child.nodeType == ELEMENT_NODE:
+      if child of Element:
         styledChild = styledParent.newStyledElement(Element(child))
         styledParent.children.add(styledChild)
         declmap = styledChild.calcRules(ua, user, author)
         applyStyle(styledParent, styledChild, declmap)
-      elif child.nodeType == TEXT_NODE:
+      elif child of Text:
         let text = Text(child)
         styledChild = styledParent.newStyledText(text)
         styledParent.children.add(styledChild)
@@ -475,7 +475,7 @@ proc appendChildren(styledStack: var seq[CascadeFrame], frame: CascadeFrame,
     styledStack.stackAppend(frame, styledChild, PSEUDO_NEWLINE, idx)
   else:
     for i in countdown(elem.childList.high, 0):
-      if elem.childList[i].nodeType in {ELEMENT_NODE, TEXT_NODE}:
+      if elem.childList[i] of Element or elem.childList[i] of Text:
         styledStack.stackAppend(frame, styledChild, elem.childList[i], idx)
     if elem.tagType == TAG_INPUT:
       styledStack.stackAppend(frame, styledChild, PSEUDO_INPUT_TEXT, idx)
diff --git a/src/css/match.nim b/src/css/match.nim
index bf78f6b5..0d1f507f 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -6,6 +6,7 @@ import std/tables
 import css/cssparser
 import css/selectorparser
 import css/stylednode
+import html/catom
 import html/dom
 import utils/twtstr
 
@@ -148,9 +149,7 @@ func selectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T = n
     let elem = Element(selem.node)
   case sel.t
   of TYPE_SELECTOR:
-    return elem.tagType == sel.tag
-  of UNKNOWN_TYPE_SELECTOR:
-    return elem.localName == sel.tagstr
+    return elem.localName == sel.tag
   of CLASS_SELECTOR:
     return sel.class in elem.classList
   of ID_SELECTOR:
@@ -232,14 +231,14 @@ func selectorsMatch*[T: Element|StyledNode](elem: T, cxsel: ComplexSelector, fel
   return elem.complexSelectorMatches(cxsel, felem)
 
 proc querySelectorAll(node: Node, q: string): seq[Element] =
-  let selectors = parseSelectors(newStringStream(q))
+  let selectors = parseSelectors(newStringStream(q), node.document.factory)
   for element in node.elements:
     if element.selectorsMatch(selectors):
       result.add(element)
 doqsa = (proc(node: Node, q: string): seq[Element] = querySelectorAll(node, q))
 
 proc querySelector(node: Node, q: string): Element =
-  let selectors = parseSelectors(newStringStream(q))
+  let selectors = parseSelectors(newStringStream(q), node.document.factory)
   for element in node.elements:
     if element.selectorsMatch(selectors):
       return element
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index 75f6182a..9e79a36d 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -3,14 +3,13 @@ import std/streams
 import std/strutils
 
 import css/cssparser
+import html/catom
 import utils/twtstr
 
-import chame/tags
-
 type
   SelectorType* = enum
-    TYPE_SELECTOR, UNKNOWN_TYPE_SELECTOR, ID_SELECTOR, ATTR_SELECTOR,
-    CLASS_SELECTOR, UNIVERSAL_SELECTOR, PSEUDO_SELECTOR, PSELEM_SELECTOR
+    TYPE_SELECTOR, ID_SELECTOR, ATTR_SELECTOR, CLASS_SELECTOR,
+    UNIVERSAL_SELECTOR, PSEUDO_SELECTOR, PSELEM_SELECTOR
 
   PseudoElem* = enum
     PSEUDO_NONE, PSEUDO_BEFORE, PSEUDO_AFTER,
@@ -32,6 +31,7 @@ type
     cvals: seq[CSSComponentValue]
     at: int
     failed: bool
+    factory: CAtomFactory
 
   RelationType* {.size: sizeof(int) div 2.} = enum
     RELATION_EXISTS, RELATION_EQUALS, RELATION_TOKEN, RELATION_BEGIN_DASH,
@@ -47,9 +47,9 @@ type
   Selector* = ref object # Simple selector
     case t*: SelectorType
     of TYPE_SELECTOR:
-      tag*: TagType
-    of UNKNOWN_TYPE_SELECTOR:
-      tagstr*: string
+      tag*: CAtom
+      when defined(debug):
+        tags: string
     of ID_SELECTOR:
       id*: string
     of ATTR_SELECTOR:
@@ -109,9 +109,10 @@ func `$`*(cxsel: ComplexSelector): string
 func `$`*(sel: Selector): string =
   case sel.t
   of TYPE_SELECTOR:
-    return tagName(sel.tag)
-  of UNKNOWN_TYPE_SELECTOR:
-    return sel.tagstr
+    when defined(debug):
+      return sel.tags
+    else:
+      return "tagt " & $int(sel.tag)
   of ID_SELECTOR:
     return '#' & sel.id
   of ATTR_SELECTOR:
@@ -205,7 +206,7 @@ func getSpecificity(sel: Selector): int =
       result += 1000
     of PSEUDO_WHERE: discard
     else: result += 1000
-  of TYPE_SELECTOR, UNKNOWN_TYPE_SELECTOR, PSELEM_SELECTOR:
+  of TYPE_SELECTOR, PSELEM_SELECTOR:
     result += 1
   of UNIVERSAL_SELECTOR:
     discard
@@ -242,15 +243,17 @@ template get_tok(cval: CSSComponentValue): CSSToken =
   if not (c of CSSToken): fail
   CSSToken(c)
 
-proc parseSelectorList(cvals: seq[CSSComponentValue]): SelectorList
+proc parseSelectorList(cvals: seq[CSSComponentValue], factory: CAtomFactory):
+  SelectorList
 
 # Functions that may contain other selectors, functions, etc.
-proc parseRecursiveSelectorFunction(state: var SelectorParser, class: PseudoClass, body: seq[CSSComponentValue]): Selector =
+proc parseRecursiveSelectorFunction(state: var SelectorParser,
+    class: PseudoClass, body: seq[CSSComponentValue]): Selector =
   var fun = Selector(
     t: PSEUDO_SELECTOR,
     pseudo: PseudoData(t: class),
   )
-  fun.pseudo.fsels = parseSelectorList(body)
+  fun.pseudo.fsels = parseSelectorList(body, state.factory)
   if fun.pseudo.fsels.len == 0: fail
   return fun
 
@@ -266,7 +269,8 @@ proc parseNthChild(state: var SelectorParser, cssfunction: CSSFunction, data: Ps
     return nthchild
   if not (get_tok cssfunction.value[i]).value.equalsIgnoreCase("of"): fail
   if i == cssfunction.value.len: fail
-  nthchild.pseudo.ofsels = parseSelectorList(cssfunction.value[i..^1])
+  nthchild.pseudo.ofsels = parseSelectorList(cssfunction.value[i..^1],
+    state.factory)
   if nthchild.pseudo.ofsels.len == 0: fail
   return nthchild
 
@@ -396,6 +400,7 @@ proc parseClassSelector(state: var SelectorParser): Selector =
   return Selector(t: CLASS_SELECTOR, class: tok.value)
 
 proc parseCompoundSelector(state: var SelectorParser): CompoundSelector =
+  result = CompoundSelector()
   while state.has():
     let cval = state.peek()
     if cval of CSSToken:
@@ -403,12 +408,8 @@ proc parseCompoundSelector(state: var SelectorParser): CompoundSelector =
       case tok.tokenType
       of CSS_IDENT_TOKEN:
         inc state.at
-        let s = tok.value.toLowerAscii()
-        let tag = tagType(s)
-        if tag == TAG_UNKNOWN:
-          result.add(Selector(t: UNKNOWN_TYPE_SELECTOR, tagstr: s))
-        else:
-          result.add(Selector(t: TYPE_SELECTOR, tag: tag))
+        let tag = state.factory.toAtom(tok.value.toLowerAscii())
+        result.add(Selector(t: TYPE_SELECTOR, tag: tag))
       of CSS_COLON_TOKEN:
         inc state.at
         result.add(state.parsePseudoSelector())
@@ -466,16 +467,19 @@ proc parseComplexSelector(state: var SelectorParser): ComplexSelector =
   if result.len == 0 or result[^1].ct != NO_COMBINATOR:
     fail
 
-proc parseSelectorList(cvals: seq[CSSComponentValue]): SelectorList =
-  var state = SelectorParser(cvals: cvals)
+proc parseSelectorList(cvals: seq[CSSComponentValue], factory: CAtomFactory):
+    SelectorList =
+  var state = SelectorParser(cvals: cvals, factory: factory)
   var res: SelectorList
   while state.has():
     res.add(state.parseComplexSelector())
   if not state.failed:
     return res
 
-func parseSelectors*(cvals: seq[CSSComponentValue]): seq[ComplexSelector] = {.cast(noSideEffect).}:
-  return parseSelectorList(cvals)
+proc parseSelectors*(cvals: seq[CSSComponentValue], factory: CAtomFactory):
+    seq[ComplexSelector] =
+  return parseSelectorList(cvals, factory)
 
-proc parseSelectors*(stream: Stream): seq[ComplexSelector] =
-  return parseSelectors(parseListOfComponentValues(stream))
+proc parseSelectors*(stream: Stream, factory: CAtomFactory):
+    seq[ComplexSelector] =
+  return parseSelectors(parseListOfComponentValues(stream), factory)
diff --git a/src/css/sheet.nim b/src/css/sheet.nim
index 2db7b47a..4990d991 100644
--- a/src/css/sheet.nim
+++ b/src/css/sheet.nim
@@ -2,11 +2,10 @@ import std/algorithm
 import std/streams
 import std/tables
 
-import css/mediaquery
 import css/cssparser
+import css/mediaquery
 import css/selectorparser
-
-import chame/tags
+import html/catom
 
 type
   CSSRuleBase* = ref object of RootObj
@@ -26,23 +25,27 @@ type
 
   CSSStylesheet* = ref object
     mqList*: seq[CSSMediaQueryDef]
-    tagTable: array[TagType, seq[CSSRuleDef]]
+    #TODO maybe just array[TagType] would be more efficient
+    tagTable: Table[CAtom, seq[CSSRuleDef]]
     idTable: Table[string, seq[CSSRuleDef]]
     classTable: Table[string, seq[CSSRuleDef]]
     generalList: seq[CSSRuleDef]
     len: int
+    factory: CAtomFactory
 
 type SelectorHashes = object
-  tag: TagType
+  tag: CAtom
   id: string
   class: string
 
-func newStylesheet*(cap: int): CSSStylesheet =
+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),
-    generalList: newSeqOfCap[CSSRuleDef](bucketsize)
+    generalList: newSeqOfCap[CSSRuleDef](bucketsize),
+    factory: factory
   )
 
 proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool
@@ -66,7 +69,7 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool =
   of ID_SELECTOR:
     hashes.id = sel.id
     return true
-  of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR, UNKNOWN_TYPE_SELECTOR:
+  of ATTR_SELECTOR, PSELEM_SELECTOR, UNIVERSAL_SELECTOR:
     return false
   of PSEUDO_SELECTOR:
     if sel.pseudo.t in {PSEUDO_IS, PSEUDO_WHERE}:
@@ -88,9 +91,9 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool =
       while i < sel.pseudo.fsels.len:
         var nhashes: SelectorHashes
         nhashes.getSelectorIds(sel.pseudo.fsels[i])
-        if hashes.tag == TAG_UNKNOWN:
+        if hashes.tag == CAtomNull:
           hashes.tag = nhashes.tag
-        elif not cancel_tag and nhashes.tag != TAG_UNKNOWN and nhashes.tag != hashes.tag:
+        elif not cancel_tag and nhashes.tag != CAtomNull and nhashes.tag != hashes.tag:
           cancel_tag = true
 
         if hashes.id == "":
@@ -106,23 +109,24 @@ proc getSelectorIds(hashes: var SelectorHashes, sel: Selector): bool =
         inc i
 
       if cancel_tag:
-        hashes.tag = TAG_UNKNOWN
+        hashes.tag = CAtomNull
       if cancel_id:
         hashes.id = ""
       if cancel_class:
         hashes.class = ""
 
-      if hashes.tag != TAG_UNKNOWN or hashes.id != "" or hashes.class != "":
+      if hashes.tag != CAtomNull or hashes.id != "" or hashes.class != "":
         return true
 
 proc ruleDefCmp(a, b: CSSRuleDef): int =
   cmp(a.idx, b.idx)
 
-iterator genRules*(sheet: CSSStylesheet, tag: TagType, id: string,
+iterator genRules*(sheet: CSSStylesheet, tag: CAtom, id: string,
     classes: seq[string]): CSSRuleDef =
   var rules: seq[CSSRuleDef]
-  for rule in sheet.tagTable[tag]:
-    rules.add(rule)
+  sheet.tagTable.withValue(tag, v):
+    for rule in v[]:
+      rules.add(rule)
   if id != "":
     sheet.idTable.withValue(id, v):
       for rule in v[]:
@@ -141,8 +145,11 @@ proc add(sheet: var CSSStylesheet, rule: CSSRuleDef) =
   var hashes: SelectorHashes
   for cxsel in rule.sels:
     hashes.getSelectorIds(cxsel)
-    if hashes.tag != TAG_UNKNOWN:
-      sheet.tagTable[hashes.tag].add(rule)
+    if hashes.tag != CAtomNull:
+      sheet.tagTable.withValue(hashes.tag, p):
+        p[].add(rule)
+      do:
+        sheet.tagTable[hashes.tag] = @[rule]
     elif hashes.id != "":
       sheet.idTable.withValue(hashes.id, p):
         p[].add(rule)
@@ -158,8 +165,11 @@ proc add(sheet: var CSSStylesheet, rule: CSSRuleDef) =
 
 proc add*(sheet: var CSSStylesheet, sheet2: CSSStylesheet) =
   sheet.generalList.add(sheet2.generalList)
-  for tag in TagType:
-    sheet.tagTable[tag].add(sheet2.tagTable[tag])
+  for key, value in sheet2.tagTable.pairs:
+    sheet.tagTable.withValue(key, p):
+      p[].add(value)
+    do:
+      sheet.tagTable[key] = value
   for key, value in sheet2.idTable.pairs:
     sheet.idTable.withValue(key, p):
       p[].add(value)
@@ -172,7 +182,7 @@ proc add*(sheet: var CSSStylesheet, sheet2: CSSStylesheet) =
       sheet.classTable[key] = value
 
 proc addRule(stylesheet: var CSSStylesheet, rule: CSSQualifiedRule) =
-  let sels = parseSelectors(rule.prelude)
+  let sels = parseSelectors(rule.prelude, stylesheet.factory)
   if sels.len > 0:
     let r = CSSRuleDef(
       sels: sels,
@@ -192,7 +202,7 @@ proc addAtRule(stylesheet: var CSSStylesheet, atrule: CSSAtRule) =
     let rules = atrule.oblock.value.parseListOfRules()
     if rules.len > 0:
       var media = CSSMediaQueryDef()
-      media.children = newStylesheet(rules.len)
+      media.children = newStylesheet(rules.len, stylesheet.factory)
       media.children.len = stylesheet.len
       media.query = query
       for rule in rules:
@@ -204,13 +214,13 @@ proc addAtRule(stylesheet: var CSSStylesheet, atrule: CSSAtRule) =
       stylesheet.len = media.children.len
   else: discard #TODO
 
-proc parseStylesheet*(s: Stream): CSSStylesheet =
+proc parseStylesheet*(s: Stream, factory: CAtomFactory): CSSStylesheet =
   let css = parseCSS(s)
-  result = newStylesheet(css.value.len)
+  result = newStylesheet(css.value.len, factory)
   for v in css.value:
     if v of CSSAtRule: result.addAtRule(CSSAtRule(v))
     else: result.addRule(CSSQualifiedRule(v))
   s.close()
 
-proc parseStylesheet*(s: string): CSSStylesheet =
-  return newStringStream(s).parseStylesheet()
+proc parseStylesheet*(s: string, factory: CAtomFactory): CSSStylesheet =
+  return newStringStream(s).parseStylesheet(factory)