hjkl-css
Parser + AST for a CSS subset used to drive declarative UI styling.
Part of the hjkl monorepo — a vim-modal editor in Rust.
Toolkit-agnostic. Pair with hjkl-css-floem to map onto
floem views.
Supported subset
- Selectors: type (
label), class (.prompt), pseudo-class (:hover,:focus,:active,:disabled,:selected), and AND-combinations on a single simple selector (button.primary:hover). Selector lists (.a, .b) honoured. Combinators supported: descendant (), child (>), adjacent sibling (+), general sibling (~). - Properties (31 known):
color,background-color,width,height,flex-basis,padding,margin,gap,row-gap,column-gap,display,flex-direction,align-items,justify-content,flex-grow,flex-shrink,border,border-top,border-right,border-bottom,border-left,border-width,border-color,border-top-color,border-right-color,border-bottom-color,border-left-color,border-radius,outline,font-family,font-size,font-weight,font-style,text-align,line-height. Unknown properties are silently dropped per the lenient-parsing posture. - Values: hex colors (
#rgb,#rrggbb,#rrggbbaa),rgb()/rgba()functions, named colors (CSS Level 1), lengths inpx/%/ unitless (treated as px),autokeyword, unitless numbers, font-family lists, border shorthand (<width> <style> <color>). - Cascade: standard specificity (classes/pseudo = 10, type = 1);
!importantboost; CSS source-order tie-break (rule index, then in-rule declaration index).
Usage
use ;
let sheet = parse.expect;
let target = Node ;
let style = sheet.resolve;
assert_eq!;
resolve takes the target node, its ancestors (root → parent, exclusive of
target), its previous siblings (oldest → immediately preceding, exclusive of
target), and the active pseudo-class. Pass empty slices for top-level views with
no hierarchy.
ResolvedStyle::iter() yields properties in CSS source order, so adapters that
apply properties sequentially get spec-correct shorthand/longhand override
semantics.
Documentation
Contributing
See the monorepo CONTRIBUTING guide.
License
MIT — see LICENSE.