Module: Habaki::SelectorMatcher

Included in:
Rules, Stylesheet, Stylesheets
Defined in:
lib/habaki/rules.rb

Overview

selector matcher helper

Instance Method Summary collapse

Instance Method Details

#each_match(element, *args) {|rule, selector, specificity| ... } ⇒ void

This method returns an undefined value.

traverse rules matching with Visitor::Element

Parameters:

Yield Parameters:



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/habaki/rules.rb', line 65

def each_match(element, *args, &block)
  @hash_tree ||= {}
  index_selectors!(*args) unless @hash_tree[args]

  lookup_rules(args, element.tag_name, element.class_name, element.id_name) do |rule|
    rule.each_selector do |selector|
      specificity = Specificity.new
      if selector.element_match?(element, specificity)
        block.call rule, selector, specificity
      end
    end
  end
end

#each_matching_rule(element, *args) {|rule| ... } ⇒ void

This method returns an undefined value.

traverse rules matching with Visitor::Element

Parameters:

Yield Parameters:



83
84
85
86
87
# File 'lib/habaki/rules.rb', line 83

def each_matching_rule(element, *args, &block)
  find_matching_rules(element, *args).each do |rule|
    block.call rule
  end
end

#find_matching_declarations(element, *args) ⇒ Declarations

get cascaded declarations results for Visitor::Element

Parameters:

Returns:



104
105
106
107
108
109
110
111
112
# File 'lib/habaki/rules.rb', line 104

def find_matching_declarations(element, *args)
  declarations = Declarations.new
  each_matching_rule(element, *args) do |rule|
    rule.each_declaration do |decl|
      declarations.replace_important(decl)
    end
  end
  declarations
end

#find_matching_rules(element, *args) ⇒ Array<Rule>

rules matching with Visitor::Element ordered by specificity score (highest last)

Parameters:

Returns:



92
93
94
95
96
97
98
99
# File 'lib/habaki/rules.rb', line 92

def find_matching_rules(element, *args)
  results = []
  each_match(element, *args) do |rule, selector, specificity|
    results << [specificity.score, rule]
  end
  results.sort! { |a, b| a.first <=> b.first }
  results.map(&:last)
end

#index_selectors!(*args) ⇒ Object

small hash index on tag, class and id



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/habaki/rules.rb', line 5

def index_selectors!(*args)
  @hash_tree[args] = {}

  each_rule(*args) do |rule|
    rule.each_selector do |selector|
      sub_sels = selector.sub_selectors.last
      tag_name = nil
      class_name = nil
      id_name = nil
      sub_sels.each do |sub_sel|
        case sub_sel.match
        when :tag
          tag_name = sub_sel.tag.local
        when :class
          class_name = sub_sel.value
        when :id
          id_name = sub_sel.value
        end
      end

      class_or_id = nil
      class_or_id = ".#{class_name}" if class_name
      class_or_id = "##{id_name}" if id_name

      @hash_tree[args][tag_name||"*"] ||= {}
      @hash_tree[args][tag_name||"*"][class_or_id] ||= Set.new
      @hash_tree[args][tag_name||"*"][class_or_id] << rule
    end
  end
end

#lookup_rules(args, tag_name, class_name, id_name, &block) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/habaki/rules.rb', line 36

def lookup_rules(args, tag_name, class_name, id_name, &block)
  @hash_tree[args].dig(tag_name, nil)&.each do |rule|
    block.call rule
  end

  classes_names = [nil]
  classes_names = class_name.split(" ") if class_name

  classes_names.each do |p_class_name|
    class_or_id = nil
    class_or_id = ".#{p_class_name}" if p_class_name
    class_or_id = "##{id_name}" if id_name

    @hash_tree[args].dig("*", class_or_id)&.each do |rule|
      block.call rule
    end

    @hash_tree[args].dig(tag_name, class_or_id)&.each do |rule|
      block.call rule
    end
  end
end