diff options
author | bptato <nincsnevem662@gmail.com> | 2024-02-08 01:32:40 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-08 01:44:32 +0100 |
commit | f666dbafec85ba6ed64db8123ceae28b80c4cb3b (patch) | |
tree | c8a26185197f2391551ae9f2570042d7e8e0fa10 /src/css | |
parent | 6faf5cff21f8c1d382ffa605b7aa56be30ff54db (diff) | |
download | chawan-f666dbafec85ba6ed64db8123ceae28b80c4cb3b.tar.gz |
dom: atomize id, name, DOMTokenList
Diffstat (limited to 'src/css')
-rw-r--r-- | src/css/selectorparser.nim | 40 | ||||
-rw-r--r-- | src/css/sheet.nim | 117 |
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: |