css_parser 1.7.1 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/css_parser/parser.rb +111 -101
- data/lib/css_parser/regexps.rb +59 -36
- data/lib/css_parser/rule_set.rb +377 -242
- data/lib/css_parser/version.rb +3 -1
- data/lib/css_parser.rb +25 -35
- metadata +119 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47d696725a77d514c0a1ca529dc18e39d41bdd4106a786f21219f14c2ccf43f5
|
4
|
+
data.tar.gz: eb6a39b541cfa6bd8c4d66fc4e0adb06310922794b47e582989aba6dd8f5729b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db5d0a6cf245796841621194c360c31f5f349596fa00a755152bd109a50707ff5dc301a47601fb09400fa00479e2319a9321f3657c9eb0d5a11b4db7c5d8b048
|
7
|
+
data.tar.gz: 7dd50eff88bc656f81928098d736fb7c657ebe6ced0328523cee6e3e778f5b2e7d285311436be6ffd210f8b122467f99dfad739828d43530db41e60a74694b25
|
data/lib/css_parser/parser.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module CssParser
|
3
4
|
# Exception class used for any errors encountered while downloading remote files.
|
4
5
|
class RemoteFileError < IOError; end
|
@@ -15,13 +16,12 @@ module CssParser
|
|
15
16
|
# [<tt>import</tt>] Follow <tt>@import</tt> rules. Boolean, default is <tt>true</tt>.
|
16
17
|
# [<tt>io_exceptions</tt>] Throw an exception if a link can not be found. Boolean, default is <tt>true</tt>.
|
17
18
|
class Parser
|
18
|
-
USER_AGENT
|
19
|
-
|
20
|
-
|
21
|
-
STRIP_HTML_COMMENTS_RX = /\<\!\-\-|\-\-\>/m
|
19
|
+
USER_AGENT = "Ruby CSS Parser/#{CssParser::VERSION} (https://github.com/premailer/css_parser)"
|
20
|
+
STRIP_CSS_COMMENTS_RX = %r{/\*.*?\*/}m.freeze
|
21
|
+
STRIP_HTML_COMMENTS_RX = /<!--|-->/m.freeze
|
22
22
|
|
23
23
|
# Initial parsing
|
24
|
-
RE_AT_IMPORT_RULE =
|
24
|
+
RE_AT_IMPORT_RULE = /@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s)]*)["']?\)?([\w\s,^\]()]*)\)?[;\n]?/.freeze
|
25
25
|
|
26
26
|
MAX_REDIRECTS = 3
|
27
27
|
|
@@ -35,10 +35,14 @@ module CssParser
|
|
35
35
|
class << self; attr_reader :folded_declaration_cache; end
|
36
36
|
|
37
37
|
def initialize(options = {})
|
38
|
-
@options = {
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
@options = {
|
39
|
+
absolute_paths: false,
|
40
|
+
import: true,
|
41
|
+
io_exceptions: true,
|
42
|
+
rule_set_exceptions: true,
|
43
|
+
capture_offsets: false,
|
44
|
+
user_agent: USER_AGENT
|
45
|
+
}.merge(options)
|
42
46
|
|
43
47
|
# array of RuleSets
|
44
48
|
@rules = []
|
@@ -70,21 +74,20 @@ module CssParser
|
|
70
74
|
# Returns an array of declarations.
|
71
75
|
def find_by_selector(selector, media_types = :all)
|
72
76
|
out = []
|
73
|
-
each_selector(media_types) do |sel, dec,
|
77
|
+
each_selector(media_types) do |sel, dec, _spec|
|
74
78
|
out << dec if sel.strip == selector.strip
|
75
79
|
end
|
76
80
|
out
|
77
81
|
end
|
78
|
-
|
82
|
+
alias [] find_by_selector
|
79
83
|
|
80
84
|
# Finds the rule sets that match the given selectors
|
81
85
|
def find_rule_sets(selectors, media_types = :all)
|
82
86
|
rule_sets = []
|
83
87
|
|
84
88
|
selectors.each do |selector|
|
85
|
-
selector.gsub
|
86
|
-
|
87
|
-
each_rule_set(media_types) do |rule_set, media_type|
|
89
|
+
selector = selector.gsub(/\s+/, ' ').strip
|
90
|
+
each_rule_set(media_types) do |rule_set, _media_type|
|
88
91
|
if !rule_sets.member?(rule_set) && rule_set.selectors.member?(selector)
|
89
92
|
rule_sets << rule_set
|
90
93
|
end
|
@@ -115,9 +118,9 @@ module CssParser
|
|
115
118
|
# parser = CssParser::Parser.new
|
116
119
|
# parser.add_block!(css)
|
117
120
|
def add_block!(block, options = {})
|
118
|
-
options = {:
|
119
|
-
options[:media_types] = [options[:media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
|
120
|
-
options[:only_media_types] = [options[:only_media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
|
121
|
+
options = {base_uri: nil, base_dir: nil, charset: nil, media_types: :all, only_media_types: :all}.merge(options)
|
122
|
+
options[:media_types] = [options[:media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt) }
|
123
|
+
options[:only_media_types] = [options[:only_media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt) }
|
121
124
|
|
122
125
|
block = cleanup_block(block, options)
|
123
126
|
|
@@ -129,19 +132,19 @@ module CssParser
|
|
129
132
|
if @options[:import]
|
130
133
|
block.scan(RE_AT_IMPORT_RULE).each do |import_rule|
|
131
134
|
media_types = []
|
132
|
-
if media_string = import_rule[-1]
|
133
|
-
media_string.split(
|
135
|
+
if (media_string = import_rule[-1])
|
136
|
+
media_string.split(/,/).each do |t|
|
134
137
|
media_types << CssParser.sanitize_media_query(t) unless t.empty?
|
135
138
|
end
|
136
139
|
else
|
137
140
|
media_types = [:all]
|
138
141
|
end
|
139
142
|
|
140
|
-
next unless options[:only_media_types].include?(:all) or media_types.
|
143
|
+
next unless options[:only_media_types].include?(:all) or media_types.empty? or !(media_types & options[:only_media_types]).empty?
|
141
144
|
|
142
145
|
import_path = import_rule[0].to_s.gsub(/['"]*/, '').strip
|
143
146
|
|
144
|
-
import_options = {
|
147
|
+
import_options = {media_types: media_types}
|
145
148
|
import_options[:capture_offsets] = true if options[:capture_offsets]
|
146
149
|
|
147
150
|
if options[:base_uri]
|
@@ -167,6 +170,8 @@ module CssParser
|
|
167
170
|
def add_rule!(selectors, declarations, media_types = :all)
|
168
171
|
rule_set = RuleSet.new(selectors, declarations)
|
169
172
|
add_rule_set!(rule_set, media_types)
|
173
|
+
rescue ArgumentError => e
|
174
|
+
raise e if @options[:rule_set_exceptions]
|
170
175
|
end
|
171
176
|
|
172
177
|
# Add a CSS rule by setting the +selectors+, +declarations+, +filename+, +offset+ and +media_types+.
|
@@ -183,21 +188,21 @@ module CssParser
|
|
183
188
|
#
|
184
189
|
# +media_types+ can be a symbol or an array of symbols.
|
185
190
|
def add_rule_set!(ruleset, media_types = :all)
|
186
|
-
raise ArgumentError unless ruleset.
|
191
|
+
raise ArgumentError unless ruleset.is_a?(CssParser::RuleSet)
|
187
192
|
|
188
|
-
media_types = [media_types] unless Array
|
189
|
-
media_types = media_types.flat_map { |mt| CssParser.sanitize_media_query(mt)}
|
193
|
+
media_types = [media_types] unless media_types.is_a?(Array)
|
194
|
+
media_types = media_types.flat_map { |mt| CssParser.sanitize_media_query(mt) }
|
190
195
|
|
191
|
-
@rules << {:
|
196
|
+
@rules << {media_types: media_types, rules: ruleset}
|
192
197
|
end
|
193
198
|
|
194
199
|
# Remove a CssParser RuleSet object.
|
195
200
|
#
|
196
201
|
# +media_types+ can be a symbol or an array of symbols.
|
197
202
|
def remove_rule_set!(ruleset, media_types = :all)
|
198
|
-
raise ArgumentError unless ruleset.
|
203
|
+
raise ArgumentError unless ruleset.is_a?(CssParser::RuleSet)
|
199
204
|
|
200
|
-
media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
|
205
|
+
media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt) }
|
201
206
|
|
202
207
|
@rules.reject! do |rule|
|
203
208
|
rule[:media_types] == media_types && rule[:rules].to_s == ruleset.to_s
|
@@ -209,7 +214,7 @@ module CssParser
|
|
209
214
|
# +media_types+ can be a symbol or an array of symbols.
|
210
215
|
def each_rule_set(media_types = :all) # :yields: rule_set, media_types
|
211
216
|
media_types = [:all] if media_types.nil?
|
212
|
-
media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
|
217
|
+
media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt) }
|
213
218
|
|
214
219
|
@rules.each do |block|
|
215
220
|
if media_types.include?(:all) or block[:media_types].any? { |mt| media_types.include?(mt) }
|
@@ -222,7 +227,7 @@ module CssParser
|
|
222
227
|
def to_h(which_media = :all)
|
223
228
|
out = {}
|
224
229
|
styles_by_media_types = {}
|
225
|
-
each_selector(which_media) do |selectors, declarations,
|
230
|
+
each_selector(which_media) do |selectors, declarations, _specificity, media_types|
|
226
231
|
media_types.each do |media_type|
|
227
232
|
styles_by_media_types[media_type] ||= []
|
228
233
|
styles_by_media_types[media_type] << [selectors, declarations]
|
@@ -244,7 +249,7 @@ module CssParser
|
|
244
249
|
# +media_types+ can be a symbol or an array of symbols.
|
245
250
|
# See RuleSet#each_selector for +options+.
|
246
251
|
def each_selector(all_media_types = :all, options = {}) # :yields: selectors, declarations, specificity, media_types
|
247
|
-
return to_enum(
|
252
|
+
return to_enum(__method__, all_media_types, options) unless block_given?
|
248
253
|
|
249
254
|
each_rule_set(all_media_types) do |rule_set, media_types|
|
250
255
|
rule_set.each_selector(options) do |selectors, declarations, specificity|
|
@@ -255,9 +260,10 @@ module CssParser
|
|
255
260
|
|
256
261
|
# Output all CSS rules as a single stylesheet.
|
257
262
|
def to_s(which_media = :all)
|
258
|
-
out =
|
263
|
+
out = []
|
259
264
|
styles_by_media_types = {}
|
260
|
-
|
265
|
+
|
266
|
+
each_selector(which_media) do |selectors, declarations, _specificity, media_types|
|
261
267
|
media_types.each do |media_type|
|
262
268
|
styles_by_media_types[media_type] ||= []
|
263
269
|
styles_by_media_types[media_type] << [selectors, declarations]
|
@@ -266,20 +272,21 @@ module CssParser
|
|
266
272
|
|
267
273
|
styles_by_media_types.each_pair do |media_type, media_styles|
|
268
274
|
media_block = (media_type != :all)
|
269
|
-
out << "@media #{media_type} {
|
275
|
+
out << "@media #{media_type} {" if media_block
|
270
276
|
|
271
277
|
media_styles.each do |media_style|
|
272
278
|
if media_block
|
273
|
-
out
|
279
|
+
out.push(" #{media_style[0]} {\n #{media_style[1]}\n }")
|
274
280
|
else
|
275
|
-
out
|
281
|
+
out.push("#{media_style[0]} {\n#{media_style[1]}\n}")
|
276
282
|
end
|
277
283
|
end
|
278
284
|
|
279
|
-
out <<
|
285
|
+
out << '}' if media_block
|
280
286
|
end
|
281
287
|
|
282
|
-
out
|
288
|
+
out << ''
|
289
|
+
out.join("\n")
|
283
290
|
end
|
284
291
|
|
285
292
|
# A hash of { :media_query => rule_sets }
|
@@ -287,7 +294,7 @@ module CssParser
|
|
287
294
|
rules_by_media = {}
|
288
295
|
@rules.each do |block|
|
289
296
|
block[:media_types].each do |mt|
|
290
|
-
unless rules_by_media.
|
297
|
+
unless rules_by_media.key?(mt)
|
291
298
|
rules_by_media[mt] = []
|
292
299
|
end
|
293
300
|
rules_by_media[mt] << block[:rules]
|
@@ -299,15 +306,13 @@ module CssParser
|
|
299
306
|
|
300
307
|
# Merge declarations with the same selector.
|
301
308
|
def compact! # :nodoc:
|
302
|
-
|
303
|
-
|
304
|
-
compacted
|
309
|
+
[]
|
305
310
|
end
|
306
311
|
|
307
312
|
def parse_block_into_rule_sets!(block, options = {}) # :nodoc:
|
308
313
|
current_media_queries = [:all]
|
309
314
|
if options[:media_types]
|
310
|
-
current_media_queries = options[:media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
|
315
|
+
current_media_queries = options[:media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt) }
|
311
316
|
end
|
312
317
|
|
313
318
|
in_declarations = 0
|
@@ -326,7 +331,7 @@ module CssParser
|
|
326
331
|
rule_start = nil
|
327
332
|
offset = nil
|
328
333
|
|
329
|
-
block.scan(/\s
|
334
|
+
block.scan(/\s+|\\{2,}|\\?[{}\s"]|[()]|.[^\s"{}()\\]*/) do |token|
|
330
335
|
# save the regex offset so that we know where in the file we are
|
331
336
|
offset = Regexp.last_match.offset(0) if options[:capture_offsets]
|
332
337
|
|
@@ -349,7 +354,7 @@ module CssParser
|
|
349
354
|
current_declarations << token
|
350
355
|
|
351
356
|
if !in_string && token.include?('}')
|
352
|
-
current_declarations.gsub!(/\}
|
357
|
+
current_declarations.gsub!(/\}\s*$/, '')
|
353
358
|
|
354
359
|
in_declarations -= 1
|
355
360
|
current_declarations.strip!
|
@@ -374,7 +379,7 @@ module CssParser
|
|
374
379
|
current_media_queries = []
|
375
380
|
elsif in_at_media_rule
|
376
381
|
if token.include?('{')
|
377
|
-
block_depth
|
382
|
+
block_depth += 1
|
378
383
|
in_at_media_rule = false
|
379
384
|
in_media_block = true
|
380
385
|
current_media_queries << CssParser.sanitize_media_query(current_media_query)
|
@@ -388,43 +393,48 @@ module CssParser
|
|
388
393
|
current_media_query = String.new
|
389
394
|
else
|
390
395
|
token.strip!
|
391
|
-
|
396
|
+
# special-case the ( and ) tokens to remove inner-whitespace
|
397
|
+
# (eg we'd prefer '(width: 500px)' to '( width: 500px )' )
|
398
|
+
case token
|
399
|
+
when '('
|
400
|
+
current_media_query << token
|
401
|
+
when ')'
|
402
|
+
current_media_query.sub!(/ ?$/, token)
|
403
|
+
else
|
404
|
+
current_media_query << token << ' '
|
405
|
+
end
|
392
406
|
end
|
393
407
|
elsif in_charset or token =~ /@charset/i
|
394
408
|
# iterate until we are out of the charset declaration
|
395
409
|
in_charset = !token.include?(';')
|
396
|
-
|
397
|
-
|
398
|
-
block_depth = block_depth - 1
|
399
|
-
|
400
|
-
# reset the current media query scope
|
401
|
-
if in_media_block
|
402
|
-
current_media_queries = [:all]
|
403
|
-
in_media_block = false
|
404
|
-
end
|
405
|
-
else
|
406
|
-
if !in_string && token.include?('{')
|
407
|
-
current_selectors.strip!
|
408
|
-
in_declarations += 1
|
409
|
-
else
|
410
|
-
# if we are in a selector, add the token to the current selectors
|
411
|
-
current_selectors << token
|
410
|
+
elsif !in_string && token.include?('}')
|
411
|
+
block_depth -= 1
|
412
412
|
|
413
|
-
|
414
|
-
|
415
|
-
|
413
|
+
# reset the current media query scope
|
414
|
+
if in_media_block
|
415
|
+
current_media_queries = [:all]
|
416
|
+
in_media_block = false
|
416
417
|
end
|
418
|
+
elsif !in_string && token.include?('{')
|
419
|
+
current_selectors.strip!
|
420
|
+
in_declarations += 1
|
421
|
+
else
|
422
|
+
# if we are in a selector, add the token to the current selectors
|
423
|
+
current_selectors << token
|
424
|
+
|
425
|
+
# mark this as the beginning of the selector unless we have already marked it
|
426
|
+
rule_start = offset.first if options[:capture_offsets] && rule_start.nil? && token =~ /^[^\s]+$/
|
417
427
|
end
|
418
428
|
end
|
419
429
|
|
420
430
|
# check for unclosed braces
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
add_rule!(current_selectors, current_declarations, current_media_queries)
|
426
|
-
end
|
431
|
+
return unless in_declarations > 0
|
432
|
+
|
433
|
+
unless options[:capture_offsets]
|
434
|
+
return add_rule!(current_selectors, current_declarations, current_media_queries)
|
427
435
|
end
|
436
|
+
|
437
|
+
add_rule_with_offsets!(current_selectors, current_declarations, options[:filename], (rule_start..offset.last), current_media_queries)
|
428
438
|
end
|
429
439
|
|
430
440
|
# Load a remote CSS file.
|
@@ -437,7 +447,7 @@ module CssParser
|
|
437
447
|
def load_uri!(uri, options = {}, deprecated = nil)
|
438
448
|
uri = Addressable::URI.parse(uri) unless uri.respond_to? :scheme
|
439
449
|
|
440
|
-
opts = {:
|
450
|
+
opts = {base_uri: nil, media_types: :all}
|
441
451
|
|
442
452
|
if options.is_a? Hash
|
443
453
|
opts.merge!(options)
|
@@ -457,14 +467,13 @@ module CssParser
|
|
457
467
|
opts[:filename] = uri.to_s if opts[:capture_offsets]
|
458
468
|
|
459
469
|
src, = read_remote_file(uri) # skip charset
|
460
|
-
|
461
|
-
|
462
|
-
end
|
470
|
+
|
471
|
+
add_block!(src, opts) if src
|
463
472
|
end
|
464
473
|
|
465
474
|
# Load a local CSS file.
|
466
475
|
def load_file!(file_name, options = {}, deprecated = nil)
|
467
|
-
opts = {:
|
476
|
+
opts = {base_dir: nil, media_types: :all}
|
468
477
|
|
469
478
|
if options.is_a? Hash
|
470
479
|
opts.merge!(options)
|
@@ -487,7 +496,7 @@ module CssParser
|
|
487
496
|
|
488
497
|
# Load a local CSS string.
|
489
498
|
def load_string!(src, options = {}, deprecated = nil)
|
490
|
-
opts = {:
|
499
|
+
opts = {base_dir: nil, media_types: :all}
|
491
500
|
|
492
501
|
if options.is_a? Hash
|
493
502
|
opts.merge!(options)
|
@@ -499,9 +508,8 @@ module CssParser
|
|
499
508
|
add_block!(src, opts)
|
500
509
|
end
|
501
510
|
|
502
|
-
|
503
|
-
|
504
511
|
protected
|
512
|
+
|
505
513
|
# Check that a path hasn't been loaded already
|
506
514
|
#
|
507
515
|
# Raises a CircularReferenceError exception if io_exceptions are on,
|
@@ -510,10 +518,11 @@ module CssParser
|
|
510
518
|
path = path.to_s
|
511
519
|
if @loaded_uris.include?(path)
|
512
520
|
raise CircularReferenceError, "can't load #{path} more than once" if @options[:io_exceptions]
|
513
|
-
|
521
|
+
|
522
|
+
false
|
514
523
|
else
|
515
524
|
@loaded_uris << path
|
516
|
-
|
525
|
+
true
|
517
526
|
end
|
518
527
|
end
|
519
528
|
|
@@ -541,7 +550,7 @@ module CssParser
|
|
541
550
|
utf8_block = ignore_pattern(utf8_block, STRIP_HTML_COMMENTS_RX, options)
|
542
551
|
|
543
552
|
# Strip lines containing just whitespace
|
544
|
-
utf8_block.gsub!(/^\s+$/,
|
553
|
+
utf8_block.gsub!(/^\s+$/, '') unless options[:capture_offsets]
|
545
554
|
|
546
555
|
utf8_block
|
547
556
|
end
|
@@ -577,11 +586,8 @@ module CssParser
|
|
577
586
|
if uri.scheme == 'file'
|
578
587
|
# local file
|
579
588
|
path = uri.path
|
580
|
-
path.gsub!(
|
581
|
-
|
582
|
-
src = fh.read
|
583
|
-
charset = fh.respond_to?(:charset) ? fh.charset : 'utf-8'
|
584
|
-
fh.close
|
589
|
+
path.gsub!(%r{^/}, '') if Gem.win_platform?
|
590
|
+
src = File.read(path, mode: 'rb')
|
585
591
|
else
|
586
592
|
# remote file
|
587
593
|
if uri.scheme == 'https'
|
@@ -593,27 +599,28 @@ module CssParser
|
|
593
599
|
http = Net::HTTP.new(uri.host, uri.port)
|
594
600
|
end
|
595
601
|
|
596
|
-
res = http.get(uri.request_uri, {'User-Agent' =>
|
602
|
+
res = http.get(uri.request_uri, {'User-Agent' => @options[:user_agent], 'Accept-Encoding' => 'gzip'})
|
597
603
|
src = res.body
|
598
604
|
charset = res.respond_to?(:charset) ? res.encoding : 'utf-8'
|
599
605
|
|
600
606
|
if res.code.to_i >= 400
|
601
607
|
@redirect_count = nil
|
602
|
-
raise RemoteFileError
|
608
|
+
raise RemoteFileError, uri.to_s if @options[:io_exceptions]
|
609
|
+
|
603
610
|
return '', nil
|
604
611
|
elsif res.code.to_i >= 300 and res.code.to_i < 400
|
605
|
-
|
612
|
+
unless res['Location'].nil?
|
606
613
|
return read_remote_file Addressable::URI.parse(Addressable::URI.escape(res['Location']))
|
607
614
|
end
|
608
615
|
end
|
609
616
|
|
610
617
|
case res['content-encoding']
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
618
|
+
when 'gzip'
|
619
|
+
io = Zlib::GzipReader.new(StringIO.new(res.body))
|
620
|
+
src = io.read
|
621
|
+
when 'deflate'
|
622
|
+
io = Zlib::Inflate.new
|
623
|
+
src = io.inflate(res.body)
|
617
624
|
end
|
618
625
|
end
|
619
626
|
|
@@ -627,15 +634,17 @@ module CssParser
|
|
627
634
|
end
|
628
635
|
rescue
|
629
636
|
@redirect_count = nil
|
630
|
-
raise RemoteFileError
|
637
|
+
raise RemoteFileError, uri.to_s if @options[:io_exceptions]
|
638
|
+
|
631
639
|
return nil, nil
|
632
640
|
end
|
633
641
|
|
634
642
|
@redirect_count = nil
|
635
|
-
|
643
|
+
[src, charset]
|
636
644
|
end
|
637
645
|
|
638
646
|
private
|
647
|
+
|
639
648
|
# Save a folded declaration block to the internal cache.
|
640
649
|
def save_folded_declaration(block_hash, folded_declaration) # :nodoc:
|
641
650
|
@folded_declaration_cache[block_hash] = folded_declaration
|
@@ -643,7 +652,7 @@ module CssParser
|
|
643
652
|
|
644
653
|
# Retrieve a folded declaration block from the internal cache.
|
645
654
|
def get_folded_declaration(block_hash) # :nodoc:
|
646
|
-
|
655
|
+
@folded_declaration_cache[block_hash] ||= nil
|
647
656
|
end
|
648
657
|
|
649
658
|
def reset! # :nodoc:
|
@@ -657,14 +666,15 @@ module CssParser
|
|
657
666
|
# passed hash
|
658
667
|
def css_node_to_h(hash, key, val)
|
659
668
|
hash[key.strip] = '' and return hash if val.nil?
|
669
|
+
|
660
670
|
lines = val.split(';')
|
661
671
|
nodes = {}
|
662
672
|
lines.each do |line|
|
663
673
|
parts = line.split(':', 2)
|
664
|
-
if
|
674
|
+
if parts[1] =~ /:/
|
665
675
|
nodes[parts[0]] = css_node_to_h(hash, parts[0], parts[1])
|
666
676
|
else
|
667
|
-
nodes[parts[0].to_s.strip] =parts[1].to_s.strip
|
677
|
+
nodes[parts[0].to_s.strip] = parts[1].to_s.strip
|
668
678
|
end
|
669
679
|
end
|
670
680
|
hash[key.strip] = nodes
|