diff options
author | bptato <nincsnevem662@gmail.com> | 2025-01-14 18:59:17 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-01-14 21:48:20 +0100 |
commit | 99b72030569ae2f688002bd71d1fb58ad6daec90 (patch) | |
tree | 07846b88ac6016cca4f0ae3638c91f48ad40e7a7 /src/css/cssvalues.nim | |
parent | b88ff4a313e04632c41d7ef90370599484a6f0bc (diff) | |
download | chawan-99b72030569ae2f688002bd71d1fb58ad6daec90.tar.gz |
css: refactor selector parsing & cascading, some work on variables
Untangled some nested arrays to reduce the number of intermediary seqs in cascade, and collapsed the two rule def sorts into just one (per pseudo element). This should make cascading somewhat faster. Also, we now parse variables, but they aren't resolved yet. Probably a seq won't cut it for var lookup...
Diffstat (limited to 'src/css/cssvalues.nim')
-rw-r--r-- | src/css/cssvalues.nim | 105 |
1 files changed, 80 insertions, 25 deletions
diff --git a/src/css/cssvalues.nim b/src/css/cssvalues.nim index fa24b39b..a2c661d6 100644 --- a/src/css/cssvalues.nim +++ b/src/css/cssvalues.nim @@ -7,14 +7,13 @@ import std/tables import css/cssparser import css/lunit import css/selectorparser +import html/catom import types/bitmap import types/color import types/opt import types/winattrs import utils/twtstr -export selectorparser.PseudoElem - type CSSPropertyType* = enum # primitive/enum properties: stored as byte @@ -410,13 +409,26 @@ type coUser coAuthor + CSSEntryType* = enum + ceBit, ceObject, ceWord, ceVar + CSSComputedEntry* = object t*: CSSPropertyType global*: CSSGlobalType - #TODO case on t? - bit*: uint8 - word*: CSSValueWord - obj*: CSSValue + case et*: CSSEntryType + of ceBit: + bit*: uint8 + of ceWord: + word*: CSSValueWord + of ceObject: + obj*: CSSValue + of ceVar: + cvar*: CAtom + + CSSVariable* = ref object + name*: CAtom + cvals*: seq[CSSComponentValue] + resolved: seq[tuple[v: CSSValueType; entry: CSSComputedEntry]] static: doAssert sizeof(CSSValueBit) == 1 @@ -1247,34 +1259,66 @@ func cssNumber(cval: CSSComponentValue; positive: bool): Opt[float32] = proc makeEntry*(t: CSSPropertyType; obj: CSSValue; global = cgtNone): CSSComputedEntry = - return CSSComputedEntry(t: t, obj: obj, global: global) + return CSSComputedEntry(et: ceObject, t: t, obj: obj, global: global) proc makeEntry*(t: CSSPropertyType; word: CSSValueWord; global = cgtNone): CSSComputedEntry = - return CSSComputedEntry(t: t, word: word, global: global) + return CSSComputedEntry(et: ceWord, t: t, word: word, global: global) proc makeEntry*(t: CSSPropertyType; bit: CSSValueBit; global = cgtNone): CSSComputedEntry = - return CSSComputedEntry(t: t, bit: bit.dummy, global: global) + return CSSComputedEntry(et: ceBit, t: t, bit: bit.dummy, global: global) proc makeEntry*(t: CSSPropertyType; global: CSSGlobalType): CSSComputedEntry = - return CSSComputedEntry(t: t, global: global) + return CSSComputedEntry(et: ceObject, t: t, global: global) + +proc parseVar(fun: CSSFunction; entry: var CSSComputedEntry; + attrs: WindowAttributes; factory: CAtomFactory): Opt[void] = + let i = fun.value.skipBlanks(0) + if i >= fun.value.len or fun.value.skipBlanks(i + 1) < fun.value.len: + return err() + let cval = fun.value[i] + if not (cval of CSSToken): + return err() + let tok = CSSToken(fun.value[i]) + if tok.t != cttIdent: + return err() + entry = CSSComputedEntry( + et: ceVar, + cvar: factory.toAtom(tok.value.substr(2)) + ) + return ok() proc parseValue(cvals: openArray[CSSComponentValue]; - entry: var CSSComputedEntry; attrs: WindowAttributes): Opt[void] = + entry: var CSSComputedEntry; attrs: WindowAttributes; + factory: CAtomFactory): Opt[void] = var i = cvals.skipBlanks(0) if i >= cvals.len: return err() let cval = cvals[i] - let t = entry.t inc i + if cval of CSSFunction: + let fun = CSSFunction(cval) + if fun.name.equalsIgnoreCase("var"): + if cvals.skipBlanks(i) < cvals.len: + return err() + return fun.parseVar(entry, attrs, factory) + let t = entry.t let v = valueType(t) template set_new(prop, val: untyped) = - entry.obj = CSSValue(v: v, prop: val) + entry = CSSComputedEntry( + t: entry.t, + et: ceObject, + obj: CSSValue(v: v, prop: val) + ) template set_word(prop, val: untyped) = - entry.word = CSSValueWord(prop: val) + entry = CSSComputedEntry( + t: entry.t, + et: ceWord, + word: CSSValueWord(prop: val) + ) template set_bit(prop, val: untyped) = - entry.bit = cast[uint8](val) + entry = CSSComputedEntry(t: entry.t, et: ceBit, bit: cast[uint8](val)) case v of cvtDisplay: set_bit display, ?parseIdent[CSSDisplay](cval) of cvtWhiteSpace: set_bit whiteSpace, ?parseIdent[CSSWhiteSpace](cval) @@ -1426,7 +1470,8 @@ const PropertyPaddingSpec = [ ] proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string; - cvals: openArray[CSSComponentValue]; attrs: WindowAttributes): Err[void] = + cvals: openArray[CSSComponentValue]; attrs: WindowAttributes; + factory: CAtomFactory): Err[void] = var i = cvals.skipBlanks(0) if i >= cvals.len: return err() @@ -1439,8 +1484,12 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string; if global != cgtNone: res.add(makeEntry(t, global)) else: - var entry = CSSComputedEntry(t: t) - ?cvals.parseValue(entry, attrs) + let et = case t.reprType + of cprtBit: ceBit + of cprtObject: ceObject + of cprtWord: ceWord + var entry = CSSComputedEntry(t: t, et: et) + ?cvals.parseValue(entry, attrs, factory) res.add(entry) of cstAll: if global == cgtNone: @@ -1561,9 +1610,9 @@ proc parseComputedValues*(res: var seq[CSSComputedEntry]; name: string; return ok() proc parseComputedValues*(name: string; value: seq[CSSComponentValue]; - attrs: WindowAttributes): seq[CSSComputedEntry] = + attrs: WindowAttributes; factory: CAtomFactory): seq[CSSComputedEntry] = var res: seq[CSSComputedEntry] = @[] - if res.parseComputedValues(name, value, attrs).isSome: + if res.parseComputedValues(name, value, attrs, factory).isSome: return res return @[] @@ -1591,8 +1640,13 @@ type InitMap* = array[CSSPropertyType, set[InitType]] + CSSVariableMap* = ref object + parent*: CSSVariableMap + vars*: seq[CSSVariable] + proc applyValue*(vals: CSSValues; entry: CSSComputedEntry; - parent, previousOrigin: CSSValues; inited: InitMap; initType: InitType) = + varMap: CSSVariableMap; parent, previousOrigin: CSSValues; inited: InitMap; + initType: InitType) = case entry.global of cgtInherit: if parent != nil: @@ -1609,10 +1663,11 @@ proc applyValue*(vals: CSSValues; entry: CSSComputedEntry; else: vals.initialOrInheritFrom(parent, entry.t) of cgtNone: - case entry.t.reprType - of cprtBit: vals.bits[entry.t].dummy = entry.bit - of cprtWord: vals.words[entry.t] = entry.word - of cprtObject: vals.objs[entry.t] = entry.obj + case entry.et + of ceBit: vals.bits[entry.t].dummy = entry.bit + of ceWord: vals.words[entry.t] = entry.word + of ceObject: vals.objs[entry.t] = entry.obj + of ceVar: discard #eprint "TODO" func inheritProperties*(parent: CSSValues): CSSValues = result = CSSValues() |