Class: CSS::Cascade
- Inherits:
-
Object
- Object
- CSS::Cascade
- Defined in:
- lib/css/cascade.rb
Overview
Resolves the cascade for a Stylesheet against a single element. Returns ‘Hash<String, Declaration>` keyed by property name with the winning declaration after applying:
- `@media` filtering (against a `MediaQueries::Context`)
- selector matching (`Selectors::Matcher`)
- cascade sort: `!important` > origin / inline > specificity > source order
The Stylesheet is compiled once on construction (selectors are pre-parsed, specificities pre-computed, ‘@media` chains are evaluated against the supplied context up-front, and rules are indexed by the rightmost compound’s strongest anchor — id > class > tag > universal). ‘resolve(element)` then visits only the rules whose anchor could match the element.
Cascade layers, ‘@scope` proximity, and Shadow DOM encapsulation are not modeled — `@layer`, `@supports`, `@container`, `@scope`, and `@starting-style` blocks are descended into unconditionally.
Defined Under Namespace
Classes: AnchorKey, Index, Match, RuleEntry
Constant Summary collapse
- TRANSPARENT_AT_RULES =
%w[supports layer scope starting-style container].freeze
Instance Method Summary collapse
-
#initialize(stylesheet, context: MediaQueries::Context.default) ⇒ Cascade
constructor
A new instance of Cascade.
-
#resolve(element, inline_style: nil, state: nil, cache: nil) ⇒ Object
Returns Hash<String, Declaration> of winning declarations.
Constructor Details
#initialize(stylesheet, context: MediaQueries::Context.default) ⇒ Cascade
Returns a new instance of Cascade.
27 28 29 30 31 |
# File 'lib/css/cascade.rb', line 27 def initialize(stylesheet, context: MediaQueries::Context.default) @context = context @entries = compile(stylesheet) @index = build_index(@entries) end |
Instance Method Details
#resolve(element, inline_style: nil, state: nil, cache: nil) ⇒ Object
Returns Hash<String, Declaration> of winning declarations.
‘state:` opts into stateful-pseudo matching — see `Selectors::Matcher#matches?` for the shape. Defaults to the stateless behavior (`:hover`, `:focus`, etc. never match).
‘cache:` lets callers share a per-element context cache across many resolves. The default `{}` is local to one call. Pass a persistent Hash when the DOM is stable across many resolves — Context (tag, id, classes) computation runs once per element instead of per resolve. The caller is responsible for clearing/replacing the cache on DOM mutation.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/css/cascade.rb', line 45 def resolve(element, inline_style: nil, state: nil, cache: nil) cache ||= {} candidates = collect_candidate_indexes(element, cache) order = 0 matches = [] candidates.each do |idx| entry = @entries[idx] spec = best_matching_specificity(element, entry.selector_pairs, cache, state) next if spec.nil? entry.declarations.each do |decl| order += 1 matches << Match.new(declaration: decl, specificity: spec, inline: false, order: order) end end if inline_style inline_declarations(inline_style).each do |decl| order += 1 matches << Match.new(declaration: decl, specificity: Selectors::Specificity::ZERO, inline: true, order: order) end end pick_winners(matches) end |