css_parser 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3d5b5c79aede3d12a3344be3870321727fe767f6
4
- data.tar.gz: 521049bab4d31bc8ae2540baee5915c055d34644
2
+ SHA256:
3
+ metadata.gz: 66714382244cadbf112104868d94ff8b131ac4cf007deacac52d726bee1a9f9a
4
+ data.tar.gz: 8ac559b1fb982da00dfbef4188b3773d2a78637f4db26393aba7cf62287b7883
5
5
  SHA512:
6
- metadata.gz: a833504d1b764b03ad05e1ded20dd7af5093905d40b0c4730c69317c434c26757380e485416db00921dbaadb7e21b342a801545d70f4643fa6e827554d9ab1af
7
- data.tar.gz: 9ffb58947816d2b1daef923373da67c3f75944e52e7389b5fcc3547efbe9fd3b404c101a3973d013ce37cdb226ab429e6cfc1e6f41dfbf8ef5530f02ef03f7fa
6
+ metadata.gz: ba75d2e879d80cb7c854889990fd190f5c1fb664ed96b3a47ad78614a257d2ed7acfc3ba453ea34e87612636512305089c1a73d081c8a1c729a854217b17613e
7
+ data.tar.gz: ff49b36b1007ae8ce0ecbfd6a2e92536d16c46062898c0a3bae402bacdb731785d6e4b80b0d08e557fcf372f2b0da2d75629c471c8ed2ce59addd13629eda9b9
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'addressable/uri'
2
3
  require 'uri'
3
4
  require 'net/https'
@@ -122,10 +123,10 @@ module CssParser
122
123
  def self.calculate_specificity(selector)
123
124
  a = 0
124
125
  b = selector.scan(/\#/).length
125
- c = selector.scan(NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX).length
126
- d = selector.scan(ELEMENTS_AND_PSEUDO_ELEMENTS_RX).length
126
+ c = selector.scan(NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX_NC).length
127
+ d = selector.scan(ELEMENTS_AND_PSEUDO_ELEMENTS_RX_NC).length
127
128
 
128
- (a.to_s + b.to_s + c.to_s + d.to_s).to_i
129
+ "#{a}#{b}#{c}#{d}".to_i
129
130
  rescue
130
131
  return 0
131
132
  end
@@ -160,7 +161,8 @@ module CssParser
160
161
  end
161
162
 
162
163
  def self.sanitize_media_query(raw)
163
- mq = raw.to_s.gsub(/[\s]+/, ' ').strip
164
+ mq = raw.to_s.gsub(/[\s]+/, ' ')
165
+ mq.strip!
164
166
  mq = 'all' if mq.empty?
165
167
  mq.to_sym
166
168
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CssParser
2
3
  # Exception class used for any errors encountered while downloading remote files.
3
4
  class RemoteFileError < IOError; end
@@ -184,7 +185,8 @@ module CssParser
184
185
  def add_rule_set!(ruleset, media_types = :all)
185
186
  raise ArgumentError unless ruleset.kind_of?(CssParser::RuleSet)
186
187
 
187
- media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
188
+ media_types = [media_types] unless Array === media_types
189
+ media_types = media_types.flat_map { |mt| CssParser.sanitize_media_query(mt)}
188
190
 
189
191
  @rules << {:media_types => media_types, :rules => ruleset}
190
192
  end
@@ -242,6 +244,8 @@ module CssParser
242
244
  # +media_types+ can be a symbol or an array of symbols.
243
245
  # See RuleSet#each_selector for +options+.
244
246
  def each_selector(all_media_types = :all, options = {}) # :yields: selectors, declarations, specificity, media_types
247
+ return to_enum(:each_selector) unless block_given?
248
+
245
249
  each_rule_set(all_media_types) do |rule_set, media_types|
246
250
  rule_set.each_selector(options) do |selectors, declarations, specificity|
247
251
  yield selectors, declarations, specificity, media_types
@@ -251,7 +255,7 @@ module CssParser
251
255
 
252
256
  # Output all CSS rules as a single stylesheet.
253
257
  def to_s(which_media = :all)
254
- out = ''
258
+ out = String.new
255
259
  styles_by_media_types = {}
256
260
  each_selector(which_media) do |selectors, declarations, specificity, media_types|
257
261
  media_types.each do |media_type|
@@ -262,17 +266,17 @@ module CssParser
262
266
 
263
267
  styles_by_media_types.each_pair do |media_type, media_styles|
264
268
  media_block = (media_type != :all)
265
- out += "@media #{media_type} {\n" if media_block
269
+ out << "@media #{media_type} {\n" if media_block
266
270
 
267
271
  media_styles.each do |media_style|
268
272
  if media_block
269
- out += " #{media_style[0]} {\n #{media_style[1]}\n }\n"
273
+ out << " #{media_style[0]} {\n #{media_style[1]}\n }\n"
270
274
  else
271
- out += "#{media_style[0]} {\n#{media_style[1]}\n}\n"
275
+ out << "#{media_style[0]} {\n#{media_style[1]}\n}\n"
272
276
  end
273
277
  end
274
278
 
275
- out += "}\n" if media_block
279
+ out << "}\n" if media_block
276
280
  end
277
281
 
278
282
  out
@@ -314,44 +318,43 @@ module CssParser
314
318
  in_at_media_rule = false
315
319
  in_media_block = false
316
320
 
317
- current_selectors = ''
318
- current_media_query = ''
319
- current_declarations = ''
321
+ current_selectors = String.new
322
+ current_media_query = String.new
323
+ current_declarations = String.new
320
324
 
321
325
  # once we are in a rule, we will use this to store where we started if we are capturing offsets
322
326
  rule_start = nil
323
327
  offset = nil
324
328
 
325
- block.scan(/(([\\]{2,})|([\\]?[{}\s"])|(.[^\s"{}\\]*))/) do |matches|
326
- token = matches[0]
327
-
329
+ block.scan(/\s+|[\\]{2,}|[\\]?[{}\s"]|.[^\s"{}\\]*/) do |token|
328
330
  # save the regex offset so that we know where in the file we are
329
331
  offset = Regexp.last_match.offset(0) if options[:capture_offsets]
330
332
 
331
- if token =~ /\A"/ # found un-escaped double quote
333
+ if token.start_with?('"') # found un-escaped double quote
332
334
  in_string = !in_string
333
335
  end
334
336
 
335
337
  if in_declarations > 0
336
338
  # too deep, malformed declaration block
337
339
  if in_declarations > 1
338
- in_declarations -= 1 if token =~ /\}/
340
+ in_declarations -= 1 if token.include?('}')
339
341
  next
340
342
  end
341
343
 
342
- if token =~ /\{/ and not in_string
344
+ if !in_string && token.include?('{')
343
345
  in_declarations += 1
344
346
  next
345
347
  end
346
348
 
347
- current_declarations += token
349
+ current_declarations << token
348
350
 
349
- if token =~ /\}/ and not in_string
351
+ if !in_string && token.include?('}')
350
352
  current_declarations.gsub!(/\}[\s]*$/, '')
351
353
 
352
354
  in_declarations -= 1
355
+ current_declarations.strip!
353
356
 
354
- unless current_declarations.strip.empty?
357
+ unless current_declarations.empty?
355
358
  if options[:capture_offsets]
356
359
  add_rule_with_offsets!(current_selectors, current_declarations, options[:filename], (rule_start..offset.last), current_media_queries)
357
360
  else
@@ -359,8 +362,8 @@ module CssParser
359
362
  end
360
363
  end
361
364
 
362
- current_selectors = ''
363
- current_declarations = ''
365
+ current_selectors = String.new
366
+ current_declarations = String.new
364
367
 
365
368
  # restart our search for selectors and declarations
366
369
  rule_start = nil if options[:capture_offsets]
@@ -370,26 +373,28 @@ module CssParser
370
373
  in_at_media_rule = true
371
374
  current_media_queries = []
372
375
  elsif in_at_media_rule
373
- if token =~ /\{/
376
+ if token.include?('{')
374
377
  block_depth = block_depth + 1
375
378
  in_at_media_rule = false
376
379
  in_media_block = true
377
380
  current_media_queries << CssParser.sanitize_media_query(current_media_query)
378
- current_media_query = ''
379
- elsif token =~ /[,]/
381
+ current_media_query = String.new
382
+ elsif token.include?(',')
380
383
  # new media query begins
381
- token.gsub!(/[,]/, ' ')
382
- current_media_query += token.strip + ' '
384
+ token.tr!(',', ' ')
385
+ token.strip!
386
+ current_media_query << token << ' '
383
387
  current_media_queries << CssParser.sanitize_media_query(current_media_query)
384
- current_media_query = ''
388
+ current_media_query = String.new
385
389
  else
386
- current_media_query += token.strip + ' '
390
+ token.strip!
391
+ current_media_query << token << ' '
387
392
  end
388
393
  elsif in_charset or token =~ /@charset/i
389
394
  # iterate until we are out of the charset declaration
390
- in_charset = (token =~ /;/ ? false : true)
395
+ in_charset = !token.include?(';')
391
396
  else
392
- if token =~ /\}/ and not in_string
397
+ if !in_string && token.include?('}')
393
398
  block_depth = block_depth - 1
394
399
 
395
400
  # reset the current media query scope
@@ -398,12 +403,12 @@ module CssParser
398
403
  in_media_block = false
399
404
  end
400
405
  else
401
- if token =~ /\{/ and not in_string
406
+ if !in_string && token.include?('{')
402
407
  current_selectors.strip!
403
408
  in_declarations += 1
404
409
  else
405
410
  # if we are in a selector, add the token to the current selectors
406
- current_selectors += token
411
+ current_selectors << token
407
412
 
408
413
  # mark this as the beginning of the selector unless we have already marked it
409
414
  rule_start = offset.first if options[:capture_offsets] && rule_start.nil? && token =~ /^[^\s]+$/
@@ -54,12 +54,12 @@ module CssParser
54
54
 
55
55
 
56
56
  # Patterns for specificity calculations
57
- NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX= /
58
- (\.[\w]+) # classes
57
+ NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX_NC= /
58
+ (?:\.[\w]+) # classes
59
59
  |
60
- \[(\w+) # attributes
60
+ \[(?:\w+) # attributes
61
61
  |
62
- (\:( # pseudo classes
62
+ (?:\:(?: # pseudo classes
63
63
  link|visited|active
64
64
  |hover|focus
65
65
  |lang
@@ -72,10 +72,10 @@ module CssParser
72
72
  |empty|contains
73
73
  ))
74
74
  /ix
75
- ELEMENTS_AND_PSEUDO_ELEMENTS_RX = /
76
- ((^|[\s\+\>\~]+)[\w]+ # elements
75
+ ELEMENTS_AND_PSEUDO_ELEMENTS_RX_NC = /
76
+ (?:(?:^|[\s\+\>\~]+)[\w]+ # elements
77
77
  |
78
- \:{1,2}( # pseudo-elements
78
+ \:{1,2}(?: # pseudo-elements
79
79
  after|before
80
80
  |first-letter|first-line
81
81
  |selection
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module CssParser
2
3
  class RuleSet
3
4
  # Patterns for specificity calculations
@@ -6,6 +7,19 @@ module CssParser
6
7
 
7
8
  BACKGROUND_PROPERTIES = ['background-color', 'background-image', 'background-repeat', 'background-position', 'background-size', 'background-attachment']
8
9
  LIST_STYLE_PROPERTIES = ['list-style-type', 'list-style-position', 'list-style-image']
10
+ FONT_STYLE_PROPERTIES = ['font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family']
11
+ BORDER_STYLE_PROPERTIES = ['border-width', 'border-style', 'border-color']
12
+ BORDER_PROPERTIES = ['border', 'border-left', 'border-right', 'border-top', 'border-bottom']
13
+
14
+ NUMBER_OF_DIMENSIONS = 4
15
+
16
+ DIMENSIONS = [
17
+ ['margin', %w(margin-top margin-right margin-bottom margin-left)],
18
+ ['padding', %w(padding-top padding-right padding-bottom padding-left)],
19
+ ['border-color', %w(border-top-color border-right-color border-bottom-color border-left-color)],
20
+ ['border-style', %w(border-top-style border-right-style border-bottom-style border-left-style)],
21
+ ['border-width', %w(border-top-width border-right-width border-bottom-width border-left-width)],
22
+ ]
9
23
 
10
24
  # Array of selector strings.
11
25
  attr_reader :selectors
@@ -27,7 +41,7 @@ module CssParser
27
41
  return '' unless property and not property.empty?
28
42
 
29
43
  property = property.downcase.strip
30
- properties = @declarations.inject('') do |val, (key, data)|
44
+ properties = @declarations.inject(String.new) do |val, (key, data)|
31
45
  #puts "COMPARING #{key} #{key.inspect} against #{property} #{property.inspect}"
32
46
  importance = data[:is_important] ? ' !important' : ''
33
47
  val << "#{data[:value]}#{importance}; " if key.downcase.strip == property
@@ -58,7 +72,8 @@ module CssParser
58
72
 
59
73
  value.gsub!(/;\Z/, '')
60
74
  is_important = !value.gsub!(CssParser::IMPORTANT_IN_PROPERTY_RX, '').nil?
61
- property = property.downcase.strip
75
+ property = property.downcase
76
+ property.strip!
62
77
  #puts "SAVING #{property} #{value} #{is_important.inspect}"
63
78
  @declarations[property] = {
64
79
  :value => value, :is_important => is_important, :order => @order += 1
@@ -105,13 +120,14 @@ module CssParser
105
120
  # TODO: Clean-up regexp doesn't seem to work
106
121
  #++
107
122
  def declarations_to_s(options = {})
108
- options = {:force_important => false}.merge(options)
109
- str = ''
110
- each_declaration do |prop, val, is_important|
111
- importance = (options[:force_important] || is_important) ? ' !important' : ''
112
- str += "#{prop}: #{val}#{importance}; "
113
- end
114
- str.gsub(/^[\s^(\{)]+|[\n\r\f\t]*|[\s]+$/mx, '').strip
123
+ str = String.new
124
+ each_declaration do |prop, val, is_important|
125
+ importance = (options[:force_important] || is_important) ? ' !important' : ''
126
+ str << "#{prop}: #{val}#{importance}; "
127
+ end
128
+ str.gsub!(/^[\s^(\{)]+|[\n\r\f\t]*|[\s]+$/mx, '')
129
+ str.strip!
130
+ str
115
131
  end
116
132
 
117
133
  # Return the CSS rule set as a string.
@@ -164,7 +180,7 @@ module CssParser
164
180
  # Split shorthand border declarations (e.g. <tt>border: 1px red;</tt>)
165
181
  # Additional splitting happens in expand_dimensions_shorthand!
166
182
  def expand_border_shorthand! # :nodoc:
167
- ['border', 'border-left', 'border-right', 'border-top', 'border-bottom'].each do |k|
183
+ BORDER_PROPERTIES.each do |k|
168
184
  next unless @declarations.has_key?(k)
169
185
 
170
186
  value = @declarations[k][:value]
@@ -180,14 +196,8 @@ module CssParser
180
196
  # Split shorthand dimensional declarations (e.g. <tt>margin: 0px auto;</tt>)
181
197
  # into their constituent parts. Handles margin, padding, border-color, border-style and border-width.
182
198
  def expand_dimensions_shorthand! # :nodoc:
183
- {'margin' => 'margin-%s',
184
- 'padding' => 'padding-%s',
185
- 'border-color' => 'border-%s-color',
186
- 'border-style' => 'border-%s-style',
187
- 'border-width' => 'border-%s-width'}.each do |property, expanded|
188
-
199
+ DIMENSIONS.each do |property, (top, right, bottom, left)|
189
200
  next unless @declarations.has_key?(property)
190
-
191
201
  value = @declarations[property][:value]
192
202
 
193
203
  # RGB and HSL values in borders are the only units that can have spaces (within params).
@@ -199,29 +209,24 @@ module CssParser
199
209
 
200
210
  matches = value.strip.split(/\s+/)
201
211
 
202
- t, r, b, l = nil
203
-
204
212
  case matches.length
205
- when 1
206
- t, r, b, l = matches[0], matches[0], matches[0], matches[0]
207
- when 2
208
- t, b = matches[0], matches[0]
209
- r, l = matches[1], matches[1]
210
- when 3
211
- t = matches[0]
212
- r, l = matches[1], matches[1]
213
- b = matches[2]
214
- when 4
215
- t = matches[0]
216
- r = matches[1]
217
- b = matches[2]
218
- l = matches[3]
213
+ when 1
214
+ values = matches.to_a * 4
215
+ when 2
216
+ values = matches.to_a * 2
217
+ when 3
218
+ values = matches.to_a
219
+ values << matches[1] # left = right
220
+ when 4
221
+ values = matches.to_a
219
222
  end
220
223
 
221
- split_declaration(property, expanded % 'top', t)
222
- split_declaration(property, expanded % 'right', r)
223
- split_declaration(property, expanded % 'bottom', b)
224
- split_declaration(property, expanded % 'left', l)
224
+ t, r, b, l = values
225
+
226
+ split_declaration(property, top, t)
227
+ split_declaration(property, right, r)
228
+ split_declaration(property, bottom, b)
229
+ split_declaration(property, left, l)
225
230
 
226
231
  @declarations.delete(property)
227
232
  end
@@ -362,7 +367,7 @@ module CssParser
362
367
  def create_border_shorthand! # :nodoc:
363
368
  values = []
364
369
 
365
- ['border-width', 'border-style', 'border-color'].each do |property|
370
+ BORDER_STYLE_PROPERTIES.each do |property|
366
371
  if @declarations.has_key?(property) and not @declarations[property][:is_important]
367
372
  # can't merge if any value contains a space (i.e. has multiple values)
368
373
  # we temporarily remove any spaces after commas for the check (inside rgba, etc...)
@@ -371,9 +376,7 @@ module CssParser
371
376
  end
372
377
  end
373
378
 
374
- @declarations.delete('border-width')
375
- @declarations.delete('border-style')
376
- @declarations.delete('border-color')
379
+ BORDER_STYLE_PROPERTIES.each { |prop| @declarations.delete(prop)}
377
380
 
378
381
  unless values.empty?
379
382
  @declarations['border'] = {:value => values.join(' ')}
@@ -383,23 +386,20 @@ module CssParser
383
386
  # Looks for long format CSS dimensional properties (margin, padding, border-color, border-style and border-width)
384
387
  # and converts them into shorthand CSS properties.
385
388
  def create_dimensions_shorthand! # :nodoc:
386
- directions = ['top', 'right', 'bottom', 'left']
387
-
388
- {'margin' => 'margin-%s',
389
- 'padding' => 'padding-%s',
390
- 'border-color' => 'border-%s-color',
391
- 'border-style' => 'border-%s-style',
392
- 'border-width' => 'border-%s-width'}.each do |property, expanded|
389
+ return if @declarations.size < NUMBER_OF_DIMENSIONS
393
390
 
394
- top, right, bottom, left = ['top', 'right', 'bottom', 'left'].map { |side| expanded % side }
395
- foldable = @declarations.select do |dim, val|
396
- dim == top or dim == right or dim == bottom or dim == left
397
- end
391
+ DIMENSIONS.each do |property, dimensions|
392
+ (top, right, bottom, left) = dimensions
398
393
  # All four dimensions must be present
399
- if foldable.length == 4
394
+ if dimensions.count { |d| @declarations[d] } == NUMBER_OF_DIMENSIONS
400
395
  values = {}
401
396
 
402
- directions.each { |d| values[d.to_sym] = @declarations[expanded % d][:value].downcase.strip }
397
+ [
398
+ [:top, top],
399
+ [:right, right],
400
+ [:bottom, bottom],
401
+ [:left, left],
402
+ ].each { |d, key| values[d] = @declarations[key][:value].downcase.strip }
403
403
 
404
404
  if values[:left] == values[:right]
405
405
  if values[:top] == values[:bottom]
@@ -419,7 +419,7 @@ module CssParser
419
419
  @declarations[property] = {:value => new_value.strip} unless new_value.empty?
420
420
 
421
421
  # Delete the longhand values
422
- directions.each { |d| @declarations.delete(expanded % d) }
422
+ [top, right, bottom, left].each { |d| @declarations.delete(d) }
423
423
  end
424
424
  end
425
425
  end
@@ -429,33 +429,28 @@ module CssParser
429
429
  # tries to convert them into a shorthand CSS <tt>font</tt> property. All
430
430
  # font properties must be present in order to create a shorthand declaration.
431
431
  def create_font_shorthand! # :nodoc:
432
- ['font-style', 'font-variant', 'font-weight', 'font-size',
433
- 'line-height', 'font-family'].each do |prop|
432
+ FONT_STYLE_PROPERTIES.each do |prop|
434
433
  return unless @declarations.has_key?(prop)
435
434
  end
436
435
 
437
- new_value = ''
436
+ new_value = String.new
438
437
  ['font-style', 'font-variant', 'font-weight'].each do |property|
439
438
  unless @declarations[property][:value] == 'normal'
440
- new_value += @declarations[property][:value] + ' '
439
+ new_value << @declarations[property][:value] << ' '
441
440
  end
442
441
  end
443
442
 
444
- new_value += @declarations['font-size'][:value]
443
+ new_value << @declarations['font-size'][:value]
445
444
 
446
445
  unless @declarations['line-height'][:value] == 'normal'
447
- new_value += '/' + @declarations['line-height'][:value]
446
+ new_value << '/' << @declarations['line-height'][:value]
448
447
  end
449
448
 
450
- new_value += ' ' + @declarations['font-family'][:value]
449
+ new_value << ' ' << @declarations['font-family'][:value]
451
450
 
452
451
  @declarations['font'] = {:value => new_value.gsub(/[\s]+/, ' ').strip}
453
452
 
454
- ['font-style', 'font-variant', 'font-weight', 'font-size',
455
- 'line-height', 'font-family'].each do |prop|
456
- @declarations.delete(prop)
457
- end
458
-
453
+ FONT_STYLE_PROPERTIES.each { |prop| @declarations.delete(prop) }
459
454
  end
460
455
 
461
456
  # Looks for long format CSS list-style properties (e.g. <tt>list-style-type</tt>) and
@@ -482,7 +477,9 @@ module CssParser
482
477
  @declarations[dest] = {}
483
478
  end
484
479
  end
485
- @declarations[dest] = @declarations[src].merge({:value => v.to_s.strip})
480
+
481
+ @declarations[dest] = @declarations[src].dup
482
+ @declarations[dest][:value] = v.to_s.strip
486
483
  end
487
484
 
488
485
  def parse_declarations!(block) # :nodoc:
@@ -490,19 +487,18 @@ module CssParser
490
487
 
491
488
  return unless block
492
489
 
493
- block.gsub!(/(^[\s]*)|([\s]*$)/, '')
494
-
495
- continuation = ''
490
+ continuation = nil
496
491
  block.split(/[\;$]+/m).each do |decs|
497
- decs = continuation + decs
492
+ decs = continuation ? continuation + decs : decs
498
493
  if decs =~ /\([^)]*\Z/ # if it has an unmatched parenthesis
499
494
  continuation = decs + ';'
500
495
 
501
- elsif matches = decs.match(/(.[^:]*)\s*:\s*(.+)(;?\s*\Z)/i)
502
- property, value, = matches.captures # skip end_of_declaration
503
-
496
+ elsif matches = decs.match(/\s*(.[^:]*)\s*:\s*(.+?)(;?\s*\Z)/i)
497
+ # skip end_of_declaration
498
+ property = matches[1]
499
+ value = matches[2]
504
500
  add_declaration!(property, value)
505
- continuation = ''
501
+ continuation = nil
506
502
  end
507
503
  end
508
504
  end
@@ -511,7 +507,11 @@ module CssParser
511
507
  # TODO: way too simplistic
512
508
  #++
513
509
  def parse_selectors!(selectors) # :nodoc:
514
- @selectors = selectors.split(',').map { |s| s.gsub(/\s+/, ' ').strip }
510
+ @selectors = selectors.split(',').map do |s|
511
+ s.gsub!(/\s+/, ' ')
512
+ s.strip!
513
+ s
514
+ end
515
515
  end
516
516
  end
517
517
 
@@ -1,3 +1,3 @@
1
1
  module CssParser
2
- VERSION = "1.6.0".freeze
2
+ VERSION = "1.7.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: css_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dunae
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-08 00:00:00.000000000 Z
11
+ date: 2019-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -56,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  version: '0'
57
57
  requirements: []
58
58
  rubyforge_project:
59
- rubygems_version: 2.5.1
59
+ rubygems_version: 2.7.6
60
60
  signing_key:
61
61
  specification_version: 4
62
62
  summary: Ruby CSS parser.