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:



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/habaki/rules.rb', line 77

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:



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

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:



116
117
118
119
120
121
122
123
124
# File 'lib/habaki/rules.rb', line 116

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:



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

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
58
59
60
61
62
63
64
65
66
67
68
69
# 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|
    if p_class_name
      class_or_id = ".#{p_class_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

  if id_name
    class_or_id = "##{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