class CSSNative::Rule

Constants

COMBINATORS
PSEUDO_CLASSES

pseudo-classes name of value is pseudo-class, array values are acceptad options

Equality is compared by <option> === <value>, allowing 
classes to test for instances or regex matching

If array is empty, there's no limitations (in the code, foraml CSS may differ) If array is nil, it takes no options

PSEUDO_ELEMENTS

pseudo-elements definition semantics same as pseudo-classes

Public Class Methods

new(parent, name = "", previous: nil) click to toggle source
# File lib/css-native/rule.rb, line 5
def initialize(parent, name = "", previous: nil)
  @previous = previous
  @parent = parent
  @selector = name.to_s
  @stylesheet = Stylesheet.new(self)
end

Public Instance Methods

all(&block) click to toggle source
# File lib/css-native/rule.rb, line 54
def all(&block)
  selector_error("*") if previous_selector?
  append_selector("*", :all)
  chain(&block)
end
combinator(c) click to toggle source

Combinators

# File lib/css-native/rule.rb, line 78
def combinator(c)
  m = c.to_sym
  selector_error(COMBINATORS[m].strip) if previous_combinator?
  append_selector(COMBINATORS[m], :combinator)
  self
end
join(rule = nil, &block) click to toggle source

Grouping selectors

# File lib/css-native/rule.rb, line 61
def join(rule = nil, &block)
  raise JoinError unless rule.kind_of?(Rule) || rule.nil?
  selector_error(",") if previous_combinator?

  if rule.kind_of? Rule
    selector = rule.instance_variable_get(:@selector)
    previous = rule.instance_variable_get(:@previous)

    append_selector("," + selector, previous)
    previous_combinator? ? self : chain(&block)
  else
    append_selector(",", :join)
    self
  end
end
method_missing(m, *args, &block) click to toggle source
Calls superclass method
# File lib/css-native/rule.rb, line 113
def method_missing(m, *args, &block)
  if COMBINATORS.key?(m)
    combinator(m)
  elsif PSEUDO_CLASSES.key?(m)
    pseudo_class(m, *args, &block)
  elsif PSEUDO_ELEMENTS.key?(m)
    pseudo_element(m, *args, &block)
  else
    super(m, *args, &block)
  end
end
pseudo_class(name, *args, &block) click to toggle source
# File lib/css-native/rule.rb, line 85
def pseudo_class(name, *args, &block)
  pc = name.to_s.gsub("_", "-")
  m = name.to_s.gsub("-", "_").to_sym
  raise PseudoClassError.new(method: pc) unless PSEUDO_CLASSES.key?(m)

  unless args.all? {|arg| valid_arg?(PSEUDO_CLASSES[m], arg.to_s)}
    raise PseudoClassError.new(argument: arg, method: pc) 
  end
  
  selector = ":#{pc}" + (args.empty? ? "" : "(#{args.join(" ")})")
  append_selector(selector, :pseudo_class)
  chain(&block)
end
pseudo_element(name, *args, &block) click to toggle source
# File lib/css-native/rule.rb, line 99
def pseudo_element(name, *args, &block)
  pe = name.to_s.gsub("_", "-")
  m = name.to_s.gsub("-", "_").to_sym
  raise PseudoElementError.new(method: pe) unless PSEUDO_ELEMENTS.key?(m)
 
  unless args.all? {|arg| valid_arg?(PSEUDO_ELEMENTS[m], arg.to_s)}
    raise PseudoElementError.new(argument: arg, method: pe)
  end

  selector = "::#{pe}" + (args.empty? ? "" : "(#{args.join(" ")})")
  append_selector(selector, :pseudo_element)
  chain(&block)
end
respond_to_missing?(m, include_all = false) click to toggle source
Calls superclass method
# File lib/css-native/rule.rb, line 125
def respond_to_missing?(m, include_all = false)
  COMBINATORS.key?(m) ||
  PSEUDO_CLASSES.key?(m) ||
  PSEUDO_ELEMENTS.key?(m) ||
  super(m, include_all)
end
select(name, *args, type: :element, &block)
Alias for: with
to_s() click to toggle source
# File lib/css-native/rule.rb, line 132
def to_s
  "#{@selector} #{@stylesheet}"
end
with(name, *args, type: :element, &block) click to toggle source
# File lib/css-native/rule.rb, line 34
def with(name, *args, type: :element, &block)
  case type
  when :element
    if name == :all
      all(&block)
    else
      with_element(name, &block)
    end
  when :class
    with_class(name, &block)
  when :id
    with_id(name, &block)
  when :attribute
    with_attribute(name, *args, &block)
  else
    raise RuleError.new("undefined rule type '#{type}' for css selector")
  end
end
Also aliased as: select
with_attribute(name, op = :none, value = nil, case_sensitive: true, &block) click to toggle source
# File lib/css-native/rule.rb, line 29
def with_attribute(name, op = :none, value = nil, case_sensitive: true, &block)
  append_selector(format_attribute(name, op, value, case_sensitive: case_sensitive), :attribute)
  chain(&block)
end
with_class(name, &block) click to toggle source
# File lib/css-native/rule.rb, line 19
def with_class(name, &block)
  append_selector(format_class(name), :class)
  chain(&block)
end
with_element(name, &block) click to toggle source

basic selectors

# File lib/css-native/rule.rb, line 13
def with_element(name, &block)
  selector_error(name) if previous_selector?
  append_selector(format_element(name), :element)
  chain(&block)
end
with_id(name, &block) click to toggle source
# File lib/css-native/rule.rb, line 24
def with_id(name, &block)
  append_selector(format_id(name), :id)
  chain(&block)
end

Private Instance Methods

append_selector(item, symbol) click to toggle source
# File lib/css-native/rule.rb, line 161
def append_selector(item, symbol)
  @selector += item
  @previous = symbol
end
chain(&block) click to toggle source

If a block is given, executes that as a stylesheet. Otherwise, returns self to facilitate chaining

# File lib/css-native/rule.rb, line 152
def chain(&block)
  if block_given?
    @stylesheet.instance_exec(@stylesheet, &block)
    @parent.rules << to_s 
  else  
    self
  end
end
format_attribute(name, operation = :none, value = nil, case_sensitive: true) click to toggle source
# File lib/css-native/rule.rb, line 190
def format_attribute(name, operation = :none, value = nil, case_sensitive: true)
  # Other case not possible because of positional arguments
  raise AttributeError if operation != :none && value.nil?

  op = case operation.to_sym
       when :none        then ""
       when :equals      then "="
       when :include     then "~="
       when :matches     then "|="
       when :starts_with then "^="
       when :ends_with   then "$="
       when :contains    then "*="
       else
         raise AttributeComparisonError.new(operation: operation)
       end
  "[#{name}#{op}#{value.nil? ? "" : "\"#{value}\""}#{case_sensitive ? "" : " i"}]"
end
format_class(name) click to toggle source
# File lib/css-native/rule.rb, line 182
def format_class(name)
  ".#{name}"
end
format_element(name) click to toggle source
# File lib/css-native/rule.rb, line 178
def format_element(name)
  name.to_s
end
format_id(name) click to toggle source
# File lib/css-native/rule.rb, line 186
def format_id(name)
  "##{name}"
end
previous?(*args) click to toggle source
# File lib/css-native/rule.rb, line 138
def previous?(*args)
  args.include?(@previous)
end
previous_combinator?() click to toggle source
# File lib/css-native/rule.rb, line 142
def previous_combinator?
  previous?(:join, :combinator)
end
previous_selector?() click to toggle source
# File lib/css-native/rule.rb, line 146
def previous_selector?
  previous?(:element, :class, :id, :attribute, :all, :pseudo_class, :pseudo_element)
end
selector_error(name) click to toggle source
# File lib/css-native/rule.rb, line 166
def selector_error(name)
  raise SelectorError.new(element: name, previous: @previous)
end
valid_arg?(defs, arg) click to toggle source
# File lib/css-native/rule.rb, line 170
def valid_arg?(defs, arg)
  if defs.nil?
    arg.nil?
  else
    defs.empty? || defs.any? {|d| d === arg}
  end
end