diff options
author | bptato <nincsnevem662@gmail.com> | 2022-12-29 23:37:52 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2022-12-29 23:37:52 +0100 |
commit | a1c62fc955166e0d379bb55985981a8f680ac357 (patch) | |
tree | 3f6d4b0c409376a4d40805ce176476feeb0f12a6 /src/css | |
parent | 69646c6e3ba8b67934553bb0baed39ddb72a3d2f (diff) | |
download | chawan-a1c62fc955166e0d379bb55985981a8f680ac357.tar.gz |
css: fix some bugs and improve cascading a bit
Diffstat (limited to 'src/css')
-rw-r--r-- | src/css/cascade.nim | 33 | ||||
-rw-r--r-- | src/css/cssparser.nim | 2 | ||||
-rw-r--r-- | src/css/match.nim | 2 | ||||
-rw-r--r-- | src/css/selectorparser.nim | 15 | ||||
-rw-r--r-- | src/css/sheet.nim | 2 | ||||
-rw-r--r-- | src/css/stylednode.nim | 18 | ||||
-rw-r--r-- | src/css/values.nim | 24 |
7 files changed, 78 insertions, 18 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim index 633bf0f5..0b85addd 100644 --- a/src/css/cascade.nim +++ b/src/css/cascade.nim @@ -232,10 +232,6 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN var author: seq[CSSStylesheet] - if document.head != nil: - for sheet in document.head.sheets: - author.add(sheet.applyMediaQuery()) - var lenstack = newSeqOfCap[int](256) var styledStack: seq[CascadeLevel] styledStack.add((nil, document.html, PSEUDO_NONE, cachedTree)) @@ -368,13 +364,28 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN styledStack.add((styledParent, nil, ps, nil)) let elem = Element(styledChild.node) - # Add a nil before the last element (in-stack), so we can remove the - # stylesheets - let sheets = elem.sheets() - if sheets.len > 0: - for sheet in sheets: - author.add(sheet.applyMediaQuery()) - lenstack.add(sheets.len) + if cachedChild != nil and result != styledChild: + styledChild.sheets = cachedChild.sheets + else: + if unlikely(result == styledChild): + #TODO this is ugly. we should cache head sheets separately. + let head = document.head + if head != nil: + if head.invalid or cachedChild == nil: + let sheets = head.sheets() + for sheet in sheets: + styledChild.sheets.add(sheet.applyMediaQuery()) + else: + let sheets = elem.sheets() + if sheets.len > 0: + for sheet in sheets: + styledChild.sheets.add(sheet.applyMediaQuery()) + if styledChild.sheets.len > 0: + for sheet in styledChild.sheets: + author.add(sheet) + lenstack.add(styledChild.sheets.len) + # Add a nil before the last element (in-stack), so we know when to + # remove inline author sheets. styledStack.add((nil, nil, PSEUDO_NONE, nil)) stack_append styledChild, PSEUDO_AFTER diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim index 29f88151..864119ea 100644 --- a/src/css/cssparser.nim +++ b/src/css/cssparser.nim @@ -555,7 +555,7 @@ proc consumeQualifiedRule(state: var CSSParseState): Option[CSSQualifiedRule] = var r = CSSQualifiedRule() while state.has(): let t = state.consume() - if t of CSSSimpleBlock: + if t of CSSSimpleBlock and CSSSimpleBlock(t).token == CSS_LBRACE_TOKEN: r.oblock = CSSSimpleBlock(t) return some(r) elif t == CSS_LBRACE_TOKEN: diff --git a/src/css/match.nim b/src/css/match.nim index 950061a1..2d69943b 100644 --- a/src/css/match.nim +++ b/src/css/match.nim @@ -98,6 +98,8 @@ func pseudoSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: return not selem.selectorsMatch(sel.pseudo.fsels, felem) of PSEUDO_IS, PSEUDO_WHERE: return selem.selectorsMatch(sel.pseudo.fsels, felem) + of PSEUDO_LANG: + return sel.pseudo.s == "en" #TODO languages? func combinatorSelectorMatches[T: Element|StyledNode](elem: T, sel: Selector, felem: T): bool = let selem = elem diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim index 48bc8367..1e0d1a66 100644 --- a/src/css/selectorparser.nim +++ b/src/css/selectorparser.nim @@ -24,7 +24,7 @@ type PseudoClass* = enum PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER, PSEUDO_ROOT, PSEUDO_NTH_CHILD, PSEUDO_NTH_LAST_CHILD, PSEUDO_CHECKED, - PSEUDO_FOCUS, PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE + PSEUDO_FOCUS, PSEUDO_IS, PSEUDO_NOT, PSEUDO_WHERE, PSEUDO_LANG CombinatorType* = enum DESCENDANT_COMBINATOR, CHILD_COMBINATOR, NEXT_SIBLING_COMBINATOR, @@ -64,6 +64,8 @@ type ofsels*: Option[SelectorList] of PSEUDO_IS, PSEUDO_WHERE, PSEUDO_NOT: fsels*: SelectorList + of PSEUDO_LANG: + s*: string else: discard # Kind of an oversimplification, but the distinction between complex and @@ -397,6 +399,17 @@ proc parseSelectorFunction(state: var SelectorParser, cssfunction: CSSFunction) of "nth-last-child": state.parseNthChild(cssfunction, PseudoData(t: PSEUDO_NTH_LAST_CHILD)) return + of "lang": + if cssfunction.value.len == 0: return + var i = 0 + template tok: CSSComponentValue = cssfunction.value[i] + while i < cssfunction.value.len: + if tok != CSS_WHITESPACE_TOKEN: break + inc i + if i >= cssfunction.value.len: return + if tok != CSS_IDENT_TOKEN: return + state.addSelector(Selector(t: PSEUDO_SELECTOR, pseudo: PseudoData(t: PSEUDO_LANG, s: CSSToken(tok).value))) + return else: return state.query = QUERY_TYPE var data = PseudoData(t: ftype) diff --git a/src/css/sheet.nim b/src/css/sheet.nim index 1b70e52a..846f6b31 100644 --- a/src/css/sheet.nim +++ b/src/css/sheet.nim @@ -171,7 +171,7 @@ proc getDeclarations(rule: CSSQualifiedRule): seq[CSSDeclaration] {.inline.} = proc addRule(stylesheet: var CSSStylesheet, rule: CSSQualifiedRule) = let sels = parseSelectors(rule.prelude) - if sels.len > 1 or sels[^1].len > 0: + if sels.len > 0 and sels[^1].len > 0: let r = CSSRuleDef(sels: sels, decls: rule.getDeclarations()) stylesheet.add(r) diff --git a/src/css/stylednode.nim b/src/css/stylednode.nim index 2760e179..30358b29 100644 --- a/src/css/stylednode.nim +++ b/src/css/stylednode.nim @@ -1,4 +1,5 @@ import css/selectorparser +import css/sheet import css/values import html/dom import html/tags @@ -59,6 +60,7 @@ type computed*: CSSComputedValues children*: seq[StyledNode] depends*: DependencyInfo + sheets*: seq[CSSStylesheet] of STYLED_REPLACEMENT: # replaced elements: quotes, or (TODO) markers, images content*: CSSContent @@ -76,6 +78,20 @@ iterator elementList_rev*(node: StyledNode): StyledNode {.inline.} = for i in countdown(node.children.high, 0): yield node.children[i] +func findElement*(root: StyledNode, elem: Element): StyledNode = + var stack: seq[StyledNode] + for child in root.elementList_rev: + if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE: + stack.add(child) + let en = Node(elem) + while stack.len > 0: + let node = stack.pop() + if node.node == en: + return node + for child in node.elementList_rev: + if child.t == STYLED_ELEMENT and child.pseudo == PSEUDO_NONE: + stack.add(child) + func isDomElement*(styledNode: StyledNode): bool {.inline.} = styledNode.t == STYLED_ELEMENT and styledNode.pseudo == PSEUDO_NONE @@ -120,7 +136,7 @@ proc addDependency*(styledNode, dep: StyledNode, t: DependencyType) = if dep notin styledNode.depends.nodes[t]: styledNode.depends.nodes[t].add(dep) -func newStyledElement*(parent: StyledNode, element: Element, computed: CSSComputedValues, reg: sink DependencyInfo): StyledNode = +func newStyledElement*(parent: StyledNode, element: Element, computed: CSSComputedValues, reg: DependencyInfo): StyledNode = result = StyledNode(t: STYLED_ELEMENT, computed: computed, node: element, parent: parent) result.depends = reg result.parent = parent diff --git a/src/css/values.nim b/src/css/values.nim index f80aa0ee..249db7db 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -15,7 +15,7 @@ export selectorparser.PseudoElem type CSSShorthandType = enum SHORTHAND_NONE, SHORTHAND_ALL, SHORTHAND_MARGIN, SHORTHAND_PADDING, - SHORTHAND_BACKGROUND + SHORTHAND_BACKGROUND, SHORTHAND_LIST_STYLE CSSUnit* = enum UNIT_CM, UNIT_MM, UNIT_IN, UNIT_PX, UNIT_PT, UNIT_PC, @@ -209,7 +209,8 @@ const ShorthandNames = { "all": SHORTHAND_ALL, "margin": SHORTHAND_MARGIN, "padding": SHORTHAND_PADDING, - "background": SHORTHAND_BACKGROUND + "background": SHORTHAND_BACKGROUND, + "list-style": SHORTHAND_LIST_STYLE }.toTable() const PropertyNames = { @@ -1108,11 +1109,28 @@ proc getComputedValues(d: CSSDeclaration): seq[(CSSComputedValue, CSSGlobalValue try: bgcolorval.color = cssColor(tok) result.add((bgcolorval, global)) - break except CSSValueError: discard else: result.add((bgcolorval, global)) + of SHORTHAND_LIST_STYLE: + let global = cssGlobal(d) + let positionptype = PROPERTY_LIST_STYLE_POSITION + let positionval = CSSComputedValue(t: positionptype, v: valueType(positionptype)) + let typeptype = PROPERTY_LIST_STYLE_TYPE + let typeval = CSSComputedValue(t: typeptype, v: valueType(typeptype)) + if global == VALUE_NOGLOBAL: + for tok in d.value: + try: + positionval.liststyleposition = cssListStylePosition(tok) + result.add((positionval, global)) + except CSSValueError: + try: + typeval.liststyletype = cssListStyleType(tok) + result.add((typeval, global)) + except CSSValueError: + #TODO list-style-image + discard func equals*(a, b: CSSComputedValue): bool = if a == b: |