class CssParser::RuleSet::Declarations

Attributes

declarations[RW]

Public Class Methods

new(declarations = {}) click to toggle source
# File lib/css_parser/rule_set.rb, line 69
def initialize(declarations = {})
  self.declarations = {}
  declarations.each { |property, value| add_declaration!(property, value) }
end

Public Instance Methods

==(other) click to toggle source
# File lib/css_parser/rule_set.rb, line 209
def ==(other)
  return false unless other.is_a?(self.class)

  declarations == other.declarations && declarations.keys == other.declarations.keys
end
[](property) click to toggle source
# File lib/css_parser/rule_set.rb, line 107
def [](property)
  declarations[normalize_property(property)]
end
Also aliased as: get_value
[]=(property, value) click to toggle source

Add a CSS declaration @param [#to_s] property that should be added @param [Value, to_s] value of the property

@example

declarations['color'] = 'blue'

puts declarations['color']
=> #<CssParser::RuleSet::Declarations::Value:0x000000000305c730 @important=false, @order=1, @value="blue">

@example

declarations['margin'] = '0px auto !important'

puts declarations['margin']
=> #<CssParser::RuleSet::Declarations::Value:0x00000000030c1838 @important=true, @order=2, @value="0px auto">

If the property already exists its value will be over-written. If the value is empty - property will be deleted

# File lib/css_parser/rule_set.rb, line 92
def []=(property, value)
  property = normalize_property(property)

  if value.is_a?(Value)
    declarations[property] = value
  elsif value.to_s.strip.empty?
    delete property
  else
    declarations[property] = Value.new(value)
  end
rescue ArgumentError => e
  raise e.exception, "#{property} #{e.message}"
end
Also aliased as: add_declaration!
add_declaration!(property, value)
Alias for: []=
delete(property) click to toggle source

Remove CSS declaration @param [#to_s] property property to be removed

@example

declarations.delete('color')
# File lib/css_parser/rule_set.rb, line 125
def delete(property)
  declarations.delete(normalize_property(property))
end
Also aliased as: remove_declaration!
get_value(property)
Alias for: []
key?(property) click to toggle source
# File lib/css_parser/rule_set.rb, line 112
def key?(property)
  declarations.key?(normalize_property(property))
end
remove_declaration!(property)
Alias for: delete
replace_declaration!(property, replacements, preserve_importance: false) click to toggle source

Replace CSS property with multiple declarations @param [#to_s] property property name to be replaces @param [Hash<String => [String, Value]>] replacements hash with properties to replace with

@example

declarations = Declarations.new('line-height' => '0.25px', 'font' => 'small-caps', 'font-size' => '12em')
declarations.replace_declaration!('font', {'line-height' => '1px', 'font-variant' => 'small-caps', 'font-size' => '24px'})
declarations
=> #<CssParser::RuleSet::Declarations:0x00000000029c3018
@declarations=
{"line-height"=>#<CssParser::RuleSet::Declarations::Value:0x00000000038ac458 @important=false, @value="1px">,
 "font-variant"=>#<CssParser::RuleSet::Declarations::Value:0x00000000039b3ec8 @important=false, @value="small-caps">,
 "font-size"=>#<CssParser::RuleSet::Declarations::Value:0x00000000029c2c80 @important=false, @value="12em">}>
# File lib/css_parser/rule_set.rb, line 143
def replace_declaration!(property, replacements, preserve_importance: false)
  property = normalize_property(property)
  raise ArgumentError, "property #{property} does not exist" unless key?(property)

  replacement_declarations = self.class.new(replacements)

  if preserve_importance
    importance = get_value(property).important
    replacement_declarations.each_value { |value| value.important = importance }
  end

  replacement_keys = declarations.keys
  replacement_values = declarations.values
  property_index = replacement_keys.index(property)

  # We should preserve subsequent declarations of the same properties
  # and prior important ones if replacement one is not important
  replacements = replacement_declarations.each.with_object({}) do |(key, replacement), result|
    existing = declarations[key]

    # No existing -> set
    unless existing
      result[key] = replacement
      next
    end

    # Replacement more important than existing -> replace
    if replacement.important && !existing.important
      result[key] = replacement
      replaced_index = replacement_keys.index(key)
      replacement_keys.delete_at(replaced_index)
      replacement_values.delete_at(replaced_index)
      property_index -= 1 if replaced_index < property_index
      next
    end

    # Existing is more important than replacement -> keep
    next if !replacement.important && existing.important

    # Existing and replacement importance are the same,
    # value which is declared later wins
    result[key] = replacement if property_index > replacement_keys.index(key)
  end

  return if replacements.empty?

  replacement_keys.delete_at(property_index)
  replacement_keys.insert(property_index, *replacements.keys)

  replacement_values.delete_at(property_index)
  replacement_values.insert(property_index, *replacements.values)

  self.declarations = replacement_keys.zip(replacement_values).to_h
end
size() click to toggle source
# File lib/css_parser/rule_set.rb, line 116
def size
  declarations.size
end
to_s(options = {}) click to toggle source
# File lib/css_parser/rule_set.rb, line 198
def to_s(options = {})
  str = declarations.reduce(String.new) do |memo, (prop, value)|
    importance = options[:force_important] || value.important ? ' !important' : ''
    memo << "#{prop}: #{value.value}#{importance}; "
  end
  # TODO: Clean-up regexp doesn't seem to work
  str.gsub!(/^[\s^({)]+|[\n\r\f\t]*|\s+$/mx, '')
  str.strip!
  str
end

Private Instance Methods

normalize_property(property) click to toggle source
# File lib/css_parser/rule_set.rb, line 223
def normalize_property(property)
  property = property.to_s.downcase
  property.strip!
  property
end