css_parser 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/css_parser/regexps.rb +2 -0
- data/lib/css_parser/rule_set.rb +100 -93
- data/lib/css_parser/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecd734b97658689e087ca19039ea51377c23d9e1c4be6099b084006150255fce
|
4
|
+
data.tar.gz: d5a326fac6e3b57fe75fa3bc664ae8511a0e0dcf34f80dd5736ee8cc9709f5ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ca0d59324036c9071c5f957235f10022d3db4841d4e4782e147f30e2cde1a1cd46873ede55db01b260676fc7289c0e7c4ad7e0e6ac7dbd0b38a1de8aa13333a1
|
7
|
+
data.tar.gz: da5fb20229ecfac93b0436a0ed6954c109908429628cd635751c58fd9b3d029227da06a60bb80f5f4bd2fac55851ac258e7ff59d09fea59e93157f38d21c0fac
|
data/lib/css_parser/regexps.rb
CHANGED
@@ -22,6 +22,7 @@ module CssParser
|
|
22
22
|
|
23
23
|
RE_URI = /(url\(\s*(\s*#{RE_STRING}\s*)\s*\))|(url\(\s*([!#$%&*\-~]|#{RE_NON_ASCII}|#{RE_ESCAPE})*\s*)\)/ixm.freeze
|
24
24
|
URI_RX = /url\(("([^"]*)"|'([^']*)'|([^)]*))\)/im.freeze
|
25
|
+
URI_RX_OR_NONE = Regexp.union(URI_RX, /none/i)
|
25
26
|
RE_GRADIENT = /[-a-z]*gradient\([-a-z0-9 .,#%()]*\)/im.freeze
|
26
27
|
|
27
28
|
# Initial parsing
|
@@ -43,6 +44,7 @@ module CssParser
|
|
43
44
|
'upper-latin', 'hebrew', 'armenian', 'georgian', 'cjk-ideographic', 'hiragana',
|
44
45
|
'hira-gana-iroha', 'katakana-iroha', 'katakana', 'none'
|
45
46
|
)
|
47
|
+
RE_IMAGE = Regexp.union(CssParser::URI_RX, CssParser::RE_GRADIENT, /none/i)
|
46
48
|
|
47
49
|
STRIP_CSS_COMMENTS_RX = %r{/\*.*?\*/}m.freeze
|
48
50
|
STRIP_HTML_COMMENTS_RX = /<!--|-->/m.freeze
|
data/lib/css_parser/rule_set.rb
CHANGED
@@ -44,9 +44,7 @@ module CssParser
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def to_s
|
47
|
-
|
48
|
-
|
49
|
-
"#{value} !important"
|
47
|
+
important ? "#{value} !important" : value
|
50
48
|
end
|
51
49
|
|
52
50
|
def ==(other)
|
@@ -88,15 +86,11 @@ module CssParser
|
|
88
86
|
|
89
87
|
if value.is_a?(Value)
|
90
88
|
declarations[property] = value
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
delete(property)
|
96
|
-
return
|
89
|
+
elsif value.to_s.strip.empty?
|
90
|
+
delete property
|
91
|
+
else
|
92
|
+
declarations[property] = Value.new(value)
|
97
93
|
end
|
98
|
-
|
99
|
-
declarations[property] = Value.new(value)
|
100
94
|
end
|
101
95
|
alias add_declaration! []=
|
102
96
|
|
@@ -153,14 +147,18 @@ module CssParser
|
|
153
147
|
|
154
148
|
# We should preserve subsequent declarations of the same properties
|
155
149
|
# and prior important ones if replacement one is not important
|
156
|
-
replacements = replacement_declarations.each.with_object({}) do |(key,
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
150
|
+
replacements = replacement_declarations.each.with_object({}) do |(key, replacement), result|
|
151
|
+
existing = declarations[key]
|
152
|
+
|
153
|
+
# No existing -> set
|
154
|
+
unless existing
|
155
|
+
result[key] = replacement
|
156
|
+
next
|
157
|
+
end
|
158
|
+
|
159
|
+
# Replacement more important than existing -> replace
|
160
|
+
if replacement.important && !existing.important
|
161
|
+
result[key] = replacement
|
164
162
|
replaced_index = replacement_keys.index(key)
|
165
163
|
replacement_keys.delete_at(replaced_index)
|
166
164
|
replacement_values.delete_at(replaced_index)
|
@@ -168,13 +166,12 @@ module CssParser
|
|
168
166
|
next
|
169
167
|
end
|
170
168
|
|
171
|
-
# Existing
|
172
|
-
|
173
|
-
next if !value.important && declarations[key].important
|
169
|
+
# Existing is more important than replacement -> keep
|
170
|
+
next if !replacement.important && existing.important
|
174
171
|
|
175
|
-
#
|
172
|
+
# Existing and replacement importance are the same,
|
176
173
|
# value which is declared later wins
|
177
|
-
result[key] =
|
174
|
+
result[key] = replacement if property_index > replacement_keys.index(key)
|
178
175
|
end
|
179
176
|
|
180
177
|
return if replacements.empty?
|
@@ -245,9 +242,9 @@ module CssParser
|
|
245
242
|
|
246
243
|
# Get the value of a property
|
247
244
|
def get_value(property)
|
248
|
-
return '' unless declarations
|
245
|
+
return '' unless (value = declarations[property])
|
249
246
|
|
250
|
-
"#{
|
247
|
+
"#{value};"
|
251
248
|
end
|
252
249
|
alias [] get_value
|
253
250
|
|
@@ -301,19 +298,23 @@ module CssParser
|
|
301
298
|
#
|
302
299
|
# See http://www.w3.org/TR/CSS21/colors.html#propdef-background
|
303
300
|
def expand_background_shorthand! # :nodoc:
|
304
|
-
return unless declarations
|
305
|
-
|
306
|
-
value =
|
307
|
-
|
308
|
-
replacement =
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
301
|
+
return unless (declaration = declarations['background'])
|
302
|
+
|
303
|
+
value = declaration.value.dup
|
304
|
+
|
305
|
+
replacement =
|
306
|
+
if value.match(CssParser::RE_INHERIT)
|
307
|
+
BACKGROUND_PROPERTIES.map { |key| [key, 'inherit'] }.to_h
|
308
|
+
else
|
309
|
+
{
|
310
|
+
'background-image' => value.slice!(CssParser::RE_IMAGE),
|
311
|
+
'background-attachment' => value.slice!(CssParser::RE_SCROLL_FIXED),
|
312
|
+
'background-repeat' => value.slice!(CssParser::RE_REPEAT),
|
313
|
+
'background-color' => value.slice!(CssParser::RE_COLOUR),
|
314
|
+
'background-size' => extract_background_size_from(value),
|
315
|
+
'background-position' => value.slice!(CssParser::RE_BACKGROUND_POSITION)
|
316
|
+
}
|
317
|
+
end
|
317
318
|
|
318
319
|
declarations.replace_declaration!('background', replacement, preserve_importance: true)
|
319
320
|
end
|
@@ -328,9 +329,9 @@ module CssParser
|
|
328
329
|
# Additional splitting happens in expand_dimensions_shorthand!
|
329
330
|
def expand_border_shorthand! # :nodoc:
|
330
331
|
BORDER_PROPERTIES.each do |k|
|
331
|
-
next unless declarations
|
332
|
+
next unless (declaration = declarations[k])
|
332
333
|
|
333
|
-
value =
|
334
|
+
value = declaration.value.dup
|
334
335
|
|
335
336
|
replacement = {
|
336
337
|
"#{k}-width" => value.slice!(CssParser::RE_BORDER_UNITS),
|
@@ -346,9 +347,9 @@ module CssParser
|
|
346
347
|
# into their constituent parts. Handles margin, padding, border-color, border-style and border-width.
|
347
348
|
def expand_dimensions_shorthand! # :nodoc:
|
348
349
|
DIMENSIONS.each do |property, (top, right, bottom, left)|
|
349
|
-
next unless declarations
|
350
|
+
next unless (declaration = declarations[property])
|
350
351
|
|
351
|
-
value =
|
352
|
+
value = declaration.value.dup
|
352
353
|
|
353
354
|
# RGB and HSL values in borders are the only units that can have spaces (within params).
|
354
355
|
# We cheat a bit here by stripping spaces after commas in RGB and HSL values so that we
|
@@ -369,38 +370,39 @@ module CssParser
|
|
369
370
|
values << matches[1] # left = right
|
370
371
|
when 4
|
371
372
|
values = matches.to_a
|
373
|
+
else
|
374
|
+
raise ArgumentError, "Cannot parse #{value}"
|
372
375
|
end
|
373
376
|
|
374
377
|
t, r, b, l = values
|
378
|
+
replacement = {top => t, right => r, bottom => b, left => l}
|
375
379
|
|
376
|
-
declarations.replace_declaration!(
|
377
|
-
property,
|
378
|
-
{top => t, right => r, bottom => b, left => l},
|
379
|
-
preserve_importance: true
|
380
|
-
)
|
380
|
+
declarations.replace_declaration!(property, replacement, preserve_importance: true)
|
381
381
|
end
|
382
382
|
end
|
383
383
|
|
384
384
|
# Convert shorthand font declarations (e.g. <tt>font: 300 italic 11px/14px verdana, helvetica, sans-serif;</tt>)
|
385
385
|
# into their constituent parts.
|
386
386
|
def expand_font_shorthand! # :nodoc:
|
387
|
-
return unless declarations
|
388
|
-
|
389
|
-
font_props = {}
|
387
|
+
return unless (declaration = declarations['font'])
|
390
388
|
|
391
389
|
# reset properties to 'normal' per http://www.w3.org/TR/CSS21/fonts.html#font-shorthand
|
392
|
-
|
393
|
-
|
394
|
-
|
390
|
+
font_props = {
|
391
|
+
'font-style' => 'normal',
|
392
|
+
'font-variant' => 'normal',
|
393
|
+
'font-weight' => 'normal',
|
394
|
+
'font-size' => 'normal',
|
395
|
+
'line-height' => 'normal'
|
396
|
+
}
|
395
397
|
|
396
|
-
value =
|
398
|
+
value = declaration.value.dup
|
397
399
|
value.gsub!(%r{/\s+}, '/') # handle spaces between font size and height shorthand (e.g. 14px/ 16px)
|
398
400
|
|
399
401
|
in_fonts = false
|
400
402
|
|
401
|
-
matches = value.scan(/
|
402
|
-
matches.each do |
|
403
|
-
m
|
403
|
+
matches = value.scan(/"(?:.*[^"])"|'(?:.*[^'])'|(?:\w[^ ,]+)/)
|
404
|
+
matches.each do |m|
|
405
|
+
m.strip!
|
404
406
|
m.gsub!(/;$/, '')
|
405
407
|
|
406
408
|
if in_fonts
|
@@ -411,7 +413,7 @@ module CssParser
|
|
411
413
|
end
|
412
414
|
elsif m =~ /normal|inherit/i
|
413
415
|
['font-style', 'font-weight', 'font-variant'].each do |font_prop|
|
414
|
-
font_props[font_prop]
|
416
|
+
font_props[font_prop] ||= m
|
415
417
|
end
|
416
418
|
elsif m =~ /italic|oblique/i
|
417
419
|
font_props['font-style'] = m
|
@@ -420,8 +422,8 @@ module CssParser
|
|
420
422
|
elsif m =~ /[1-9]00$|bold|bolder|lighter/i
|
421
423
|
font_props['font-weight'] = m
|
422
424
|
elsif m =~ CssParser::FONT_UNITS_RX
|
423
|
-
if m
|
424
|
-
font_props['font-size'], font_props['line-height'] = m.split('/')
|
425
|
+
if m.include?('/')
|
426
|
+
font_props['font-size'], font_props['line-height'] = m.split('/', 2)
|
425
427
|
else
|
426
428
|
font_props['font-size'] = m
|
427
429
|
end
|
@@ -437,16 +439,20 @@ module CssParser
|
|
437
439
|
#
|
438
440
|
# See http://www.w3.org/TR/CSS21/generate.html#lists
|
439
441
|
def expand_list_style_shorthand! # :nodoc:
|
440
|
-
return unless declarations
|
441
|
-
|
442
|
-
value =
|
443
|
-
|
444
|
-
replacement =
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
442
|
+
return unless (declaration = declarations['list-style'])
|
443
|
+
|
444
|
+
value = declaration.value.dup
|
445
|
+
|
446
|
+
replacement =
|
447
|
+
if value =~ CssParser::RE_INHERIT
|
448
|
+
LIST_STYLE_PROPERTIES.map { |key| [key, 'inherit'] }.to_h
|
449
|
+
else
|
450
|
+
{
|
451
|
+
'list-style-type' => value.slice!(CssParser::RE_LIST_STYLE_TYPE),
|
452
|
+
'list-style-position' => value.slice!(CssParser::RE_INSIDE_OUTSIDE),
|
453
|
+
'list-style-image' => value.slice!(CssParser::URI_RX_OR_NONE)
|
454
|
+
}
|
455
|
+
end
|
450
456
|
|
451
457
|
declarations.replace_declaration!('list-style', replacement, preserve_importance: true)
|
452
458
|
end
|
@@ -466,10 +472,11 @@ module CssParser
|
|
466
472
|
values = []
|
467
473
|
properties_to_delete = []
|
468
474
|
properties.each do |property|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
475
|
+
next unless (declaration = declarations[property])
|
476
|
+
next if declaration.important
|
477
|
+
|
478
|
+
values << declaration.value
|
479
|
+
properties_to_delete << property
|
473
480
|
end
|
474
481
|
|
475
482
|
return if values.length <= 1
|
@@ -490,12 +497,9 @@ module CssParser
|
|
490
497
|
# background-position by preceding it with a backslash. In this case we also need to
|
491
498
|
# have a background-position property, so we set it if it's missing.
|
492
499
|
# http://www.w3schools.com/cssref/css3_pr_background.asp
|
493
|
-
if
|
494
|
-
|
495
|
-
|
496
|
-
end
|
497
|
-
|
498
|
-
declarations['background-size'].value = "/ #{declarations['background-size'].value}"
|
500
|
+
if (declaration = declarations['background-size']) && !declaration.important
|
501
|
+
declarations['background-position'] ||= '0% 0%'
|
502
|
+
declaration.value = "/ #{declaration.value}"
|
499
503
|
end
|
500
504
|
|
501
505
|
create_shorthand_properties! BACKGROUND_PROPERTIES, 'background'
|
@@ -509,12 +513,15 @@ module CssParser
|
|
509
513
|
values = []
|
510
514
|
|
511
515
|
BORDER_STYLE_PROPERTIES.each do |property|
|
512
|
-
next unless
|
516
|
+
next unless (declaration = declarations[property])
|
517
|
+
next if declaration.important
|
518
|
+
|
513
519
|
# can't merge if any value contains a space (i.e. has multiple values)
|
514
520
|
# we temporarily remove any spaces after commas for the check (inside rgba, etc...)
|
515
|
-
return nil if
|
521
|
+
return nil if declaration.value.gsub(/,\s/, ',').strip =~ /\s/
|
522
|
+
|
523
|
+
values << declaration.value
|
516
524
|
|
517
|
-
values << declarations[property].value
|
518
525
|
declarations.delete(property)
|
519
526
|
end
|
520
527
|
|
@@ -529,10 +536,10 @@ module CssParser
|
|
529
536
|
return if declarations.size < NUMBER_OF_DIMENSIONS
|
530
537
|
|
531
538
|
DIMENSIONS.each do |property, dimensions|
|
532
|
-
values =
|
533
|
-
next unless declarations
|
539
|
+
values = [:top, :right, :bottom, :left].each_with_index.with_object({}) do |(side, index), result|
|
540
|
+
next unless (declaration = declarations[dimensions[index]])
|
534
541
|
|
535
|
-
result[side] =
|
542
|
+
result[side] = declaration.value
|
536
543
|
end
|
537
544
|
|
538
545
|
# All four dimensions must be present
|
@@ -586,15 +593,15 @@ module CssParser
|
|
586
593
|
|
587
594
|
def compute_dimensions_shorthand(values)
|
588
595
|
# All four sides are equal, returning single value
|
589
|
-
return
|
596
|
+
return [:top] if values.values.uniq.count == 1
|
590
597
|
|
591
598
|
# `/* top | right | bottom | left */`
|
592
|
-
return
|
599
|
+
return [:top, :right, :bottom, :left] if values[:left] != values[:right]
|
593
600
|
|
594
601
|
# Vertical are the same & horizontal are the same, `/* vertical | horizontal */`
|
595
|
-
return
|
602
|
+
return [:top, :left] if values[:top] == values[:bottom]
|
596
603
|
|
597
|
-
|
604
|
+
[:top, :left, :bottom]
|
598
605
|
end
|
599
606
|
|
600
607
|
def parse_declarations!(block) # :nodoc:
|
@@ -604,10 +611,10 @@ module CssParser
|
|
604
611
|
|
605
612
|
continuation = nil
|
606
613
|
block.split(/[;$]+/m).each do |decs|
|
607
|
-
decs = continuation ? continuation + decs : decs
|
614
|
+
decs = (continuation ? continuation + decs : decs)
|
608
615
|
if decs =~ /\([^)]*\Z/ # if it has an unmatched parenthesis
|
609
616
|
continuation = "#{decs};"
|
610
|
-
elsif (matches = decs.match(/\s*(.[^:]*)\s*:\s*(.+?)(
|
617
|
+
elsif (matches = decs.match(/\s*(.[^:]*)\s*:\s*(.+?)(?:;?\s*\Z)/i))
|
611
618
|
# skip end_of_declaration
|
612
619
|
property = matches[1]
|
613
620
|
value = matches[2]
|
data/lib/css_parser/version.rb
CHANGED
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.
|
4
|
+
version: 1.9.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: 2021-
|
11
|
+
date: 2021-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|