class UnderOs::Page::StylesMatcher

Public Class Methods

new(css_rule) click to toggle source
Calls superclass method
# File lib/under_os/page/matcher.rb, line 3
def self.new(css_rule)
  @cache           ||= {}
  @cache[css_rule] ||= super
end
new(css_rule) click to toggle source
# File lib/under_os/page/matcher.rb, line 8
def initialize(css_rule)
  css_rules = css_rule.strip.split(/\s*,\s*/)

  if css_rules.size == 1
    rules    = css_rules[0].scan(/([\S]+)/).map(&:first)
    @rule    = parse(rules.pop)
    @parent  = rules.size == 0 ? false : self.class.new(rules.join(' '))
  else
    @multiple_matchers = css_rules.map{ |rule| self.class.new(rule) }
  end
end

Public Instance Methods

match(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 20
def match(view)
  score_for(view) != 0
end
score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 24
def score_for(view)
  return summary_score_for(view) if @multiple_matchers

  id_score    = id_score_for(view)
  tag_score   = tag_score_for(view)
  class_score = class_score_for(view)
  attrs_score = attrs_score_for(view)
  total_score = id_score + tag_score + class_score + attrs_score

  total_score = 0 if id_score    == 0 && @rule[:id]
  total_score = 0 if tag_score   == 0 && @rule[:tag]
  total_score = 0 if class_score == 0 && @rule[:classes].size != 0
  total_score = 0 if attrs_score == 0 && @rule[:attrs].size != 0

  if @parent && total_score != 0
    parent_score = parent_score_for(view)
    total_score  = parent_score == 0 ? 0 : total_score + parent_score
  end

  total_score
end

Private Instance Methods

attrs_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 66
def attrs_score_for(view)
  score = 0; return 0 if @rule[:attrs].size == 0

  @rule[:attrs].each do |key, value, operand|
    attr = view.respond_to?(key) && view.__send__(key)
    attr = attr.to_s if attr.is_a?(Symbol) || attr.is_a?(Numeric)

    if attr && attr.is_a?(String)
      matches = case operand
      when '='  then attr == value
      when '*=' then attr.include?(value)
      when '^=' then attr.starts_with?(value)
      when '$=' then attr.ends_with?(value)
      when '~=' then attr.split(' ').include?(value)
      when '|=' then attr.split('-').include?(value)
      end

      score += 1 if matches
    end
  end

  score
end
class_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 60
def class_score_for(view)
  return 0 if @rule[:classes].size == 0
  match = @rule[:classes] & view.classNames
  match.size == @rule[:classes].size ? match.size : 0
end
id_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 52
def id_score_for(view)
  @rule[:id] == view.id ? 1 : 0
end
parent_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 90
def parent_score_for(view)
  parent = view; score = 0

  while parent = parent.parent
    score = @parent.score_for(parent)
    break if score > 0
  end

  score
end
parse(string) click to toggle source
# File lib/under_os/page/matcher.rb, line 101
def parse(string)
  {}.tap do |rule|
    if m = string.match(/^([a-z\*]+)/)
      rule[:tag] = m[1].upcase
    else
      rule[:tag] = false # so it wouldn't match nil
    end

    if m = string.match(/#([a-z_\-0-9]+)/)
      rule[:id] = m[1]
    else
      rule[:id] = false # so it wouldn't match nil
    end

    if m = string.scan(/(\.)([a-z_\-0-9]+)/)
      rule[:classes] = m.map{|c| c[1]}
    else
      rule[:classes] = []
    end

    if m = string.scan(/\[\s*([a-z]+)\s*([*^$~|]{0,1}=)\s*('|")?(.+?)(\3)?\s*\]/)
      rule[:attrs] = m.map{|c| [c[0], c[3], c[1]] }
    else
      rule[:attrs] = []
    end
  end
end
summary_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 48
def summary_score_for(view)
  @multiple_matchers.map{ |matcher| matcher.score_for(view) }.max
end
tag_score_for(view) click to toggle source
# File lib/under_os/page/matcher.rb, line 56
def tag_score_for(view)
  @rule[:tag] == '*' || @rule[:tag] == view.tagName ? 1 : 0
end