Class: CssParser::RuleSet::Declarations

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/css_parser/rule_set.rb

Defined Under Namespace

Classes: Value

Instance Method Summary collapse

Constructor Details

#initialize(declarations = {}) ⇒ Declarations

Returns a new instance of Declarations.



71
72
73
74
# File 'lib/css_parser/rule_set.rb', line 71

def initialize(declarations = {})
  self.declarations = {}
  declarations.each { |property, value| add_declaration!(property, value) }
end

Instance Method Details

#==(other) ⇒ Object



214
215
216
217
218
# File 'lib/css_parser/rule_set.rb', line 214

def ==(other)
  return false unless other.is_a?(self.class)

  declarations == other.declarations && declarations.keys == other.declarations.keys
end

#[](property) ⇒ Object Also known as: get_value



112
113
114
# File 'lib/css_parser/rule_set.rb', line 112

def [](property)
  declarations[normalize_property(property)]
end

#[]=(property, value) ⇒ Object Also known as: add_declaration!

Add a CSS declaration If the property already exists its value will be over-written unless it was !important and the new value is not !important. If the value is empty - property will be deleted

Examples:

declarations['color'] = 'blue'

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

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

Parameters:

  • property (#to_s)

    that should be added

  • value (Value, #to_s)

    of the property



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/css_parser/rule_set.rb', line 95

def []=(property, value)
  property = normalize_property(property)
  currently_important = declarations[property]&.important

  if value.is_a?(Value) && (!currently_important || value.important)
    declarations[property] = value
  elsif value.to_s.strip.empty?
    delete property
  else
    value = Value.new(value)
    declarations[property] = value if !currently_important || value.important
  end
rescue ArgumentError => e
  raise e.exception, "#{property} #{e.message}"
end

#delete(property) ⇒ Object Also known as: remove_declaration!

Remove CSS declaration

Examples:

declarations.delete('color')

Parameters:

  • property (#to_s)

    property to be removed



130
131
132
# File 'lib/css_parser/rule_set.rb', line 130

def delete(property)
  declarations.delete(normalize_property(property))
end

#key?(property) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
# File 'lib/css_parser/rule_set.rb', line 117

def key?(property)
  declarations.key?(normalize_property(property))
end

#replace_declaration!(property, replacements, preserve_importance: false) ⇒ Object

Replace CSS property with multiple declarations

Examples:

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">}>

Parameters:

  • property (#to_s)

    property name to be replaces

  • replacements (Hash<String => [String, Value]>)

    hash with properties to replace with

Raises:

  • (ArgumentError)


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/css_parser/rule_set.rb', line 148

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

#sizeObject



121
122
123
# File 'lib/css_parser/rule_set.rb', line 121

def size
  declarations.size
end

#to_s(options = {}) ⇒ Object



203
204
205
206
207
208
209
210
211
212
# File 'lib/css_parser/rule_set.rb', line 203

def to_s(options = {})
  str = declarations.reduce(+'') 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