Class: CSS::Cascade

Inherits:
Object
  • Object
show all
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, and ‘@media` chains are evaluated against the supplied context up-front so non-matching rules are dropped). `resolve(element)` is then cheap to call per node.

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: Match, RuleEntry

Constant Summary collapse

TRANSPARENT_AT_RULES =
%w[supports layer scope starting-style container].freeze

Instance Method Summary collapse

Constructor Details

#initialize(stylesheet, context: MediaQueries::Context.default) ⇒ Cascade

Returns a new instance of Cascade.



25
26
27
28
# File 'lib/css/cascade.rb', line 25

def initialize(stylesheet, context: MediaQueries::Context.default)
  @context = context
  @entries = compile(stylesheet)
end

Instance Method Details

#resolve(element, inline_style: nil) ⇒ Object

Returns Hash<String, Declaration> of winning declarations.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/css/cascade.rb', line 31

def resolve(element, inline_style: nil)
  order   = 0
  matches = []

  @entries.each do |entry|
    spec = best_matching_specificity(element, entry.selector_pairs)
    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