diff options
author | bptato <nincsnevem662@gmail.com> | 2024-01-15 20:48:29 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-02-07 22:21:48 +0100 |
commit | 168bd542d989c76ce3ff09a29b8d77af448c3c12 (patch) | |
tree | e71ccd2bbce8da91caae46edf5df57f157a45d15 /src/css | |
parent | 0beb8385d88c20efbd00b7f9e6ac57bf19a109c7 (diff) | |
download | chawan-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.nim | 8 | ||||
-rw-r--r-- | src/css/match.nim | 9 | ||||
-rw-r--r-- | src/css/selectorparser.nim | 58 | ||||
-rw-r--r-- | src/css/sheet.nim | 60 |
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) |