css_parser 1.1.1 → 1.1.2
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.
- data/lib/css_parser/parser.rb +63 -26
- data/lib/css_parser.rb +3 -1
- data/test/test_css_parser_loading.rb +18 -4
- data/test/test_css_parser_misc.rb +0 -1
- metadata +4 -4
data/lib/css_parser/parser.rb
CHANGED
@@ -23,11 +23,7 @@ module CssParser
|
|
23
23
|
# Initial parsing
|
24
24
|
RE_AT_IMPORT_RULE = /\@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s\)]*)["']?\)?([\w\s\,^\])]*)\)?[;\n]?/
|
25
25
|
|
26
|
-
|
27
|
-
# RE_AT_IMPORT_RULE = Regexp.new('@import[\s]*(' + RE_STRING.to_s + ')([\w\s\,]*)[;]?', Regexp::IGNORECASE) -- should handle url() even though it is not allowed
|
28
|
-
#++
|
29
|
-
|
30
|
-
# Array of CSS files that have been loaded.
|
26
|
+
# Array of CSS files that have been loaded.
|
31
27
|
attr_reader :loaded_uris
|
32
28
|
|
33
29
|
#attr_reader :rules
|
@@ -199,7 +195,7 @@ module CssParser
|
|
199
195
|
options = {:media_types => :all}.merge(options)
|
200
196
|
media_types = options[:media_types]
|
201
197
|
|
202
|
-
in_declarations =
|
198
|
+
in_declarations = 0
|
203
199
|
|
204
200
|
block_depth = 0
|
205
201
|
|
@@ -219,13 +215,25 @@ module CssParser
|
|
219
215
|
in_string = !in_string
|
220
216
|
end
|
221
217
|
|
222
|
-
if in_declarations
|
218
|
+
if in_declarations > 0
|
219
|
+
|
220
|
+
# too deep, malformed declaration block
|
221
|
+
if in_declarations > 1
|
222
|
+
in_declarations -= 1 if token =~ /\}/
|
223
|
+
next
|
224
|
+
end
|
225
|
+
|
226
|
+
if token =~ /\{/
|
227
|
+
in_declarations += 1
|
228
|
+
next
|
229
|
+
end
|
230
|
+
|
223
231
|
current_declarations += token
|
224
232
|
|
225
233
|
if token =~ /\}/ and not in_string
|
226
234
|
current_declarations.gsub!(/\}[\s]*$/, '')
|
227
235
|
|
228
|
-
in_declarations
|
236
|
+
in_declarations -= 1
|
229
237
|
|
230
238
|
unless current_declarations.strip.empty?
|
231
239
|
#puts "SAVING #{current_selectors} -> #{current_declarations}"
|
@@ -257,7 +265,7 @@ module CssParser
|
|
257
265
|
if token =~ /\{/ and not in_string
|
258
266
|
current_selectors.gsub!(/^[\s]*/, '')
|
259
267
|
current_selectors.gsub!(/[\s]*$/, '')
|
260
|
-
in_declarations
|
268
|
+
in_declarations += 1
|
261
269
|
else
|
262
270
|
current_selectors += token
|
263
271
|
end
|
@@ -267,13 +275,18 @@ module CssParser
|
|
267
275
|
end
|
268
276
|
|
269
277
|
# Load a remote CSS file.
|
278
|
+
#
|
279
|
+
# You can also pass in file://test.css
|
270
280
|
def load_uri!(uri, base_uri = nil, media_types = :all)
|
281
|
+
uri = URI.parse(uri) unless uri.respond_to? :scheme
|
282
|
+
if uri.scheme == 'file' or uri.scheme.nil?
|
283
|
+
uri.path = File.expand_path(uri.path)
|
284
|
+
uri.scheme = 'file'
|
285
|
+
end
|
271
286
|
base_uri = uri if base_uri.nil?
|
272
287
|
|
273
288
|
src, charset = read_remote_file(uri)
|
274
|
-
|
275
|
-
add_block!(src, {:media_types => media_types, :base_uri => base_uri})
|
276
|
-
end
|
289
|
+
add_block!(src, {:media_types => media_types, :base_uri => base_uri})
|
277
290
|
end
|
278
291
|
|
279
292
|
# Load a local CSS file.
|
@@ -321,27 +334,51 @@ module CssParser
|
|
321
334
|
|
322
335
|
@loaded_uris << uri.to_s
|
323
336
|
|
324
|
-
|
325
|
-
#fh = open(uri, 'rb')
|
326
|
-
fh = open(uri, 'rb', 'User-Agent' => USER_AGENT, 'Accept-Encoding' => 'gzip')
|
337
|
+
src = '', charset = nil
|
327
338
|
|
328
|
-
|
329
|
-
|
339
|
+
begin
|
340
|
+
uri = URI.parse(uri.to_s)
|
341
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
342
|
+
|
343
|
+
if uri.scheme == 'file'
|
344
|
+
# local file
|
345
|
+
fh = open(uri.path, 'rb')
|
346
|
+
src = fh.read
|
347
|
+
fh.close
|
330
348
|
else
|
331
|
-
|
332
|
-
|
349
|
+
# remote file
|
350
|
+
if uri.scheme == 'https'
|
351
|
+
http.use_ssl = true
|
352
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
353
|
+
end
|
333
354
|
|
334
|
-
|
355
|
+
res, src = http.get(uri.path, {'User-Agent' => USER_AGENT, 'Accept-Encoding' => 'gzip'})
|
356
|
+
charset = fh.respond_to?(:charset) ? fh.charset : 'utf-8'
|
335
357
|
|
336
|
-
|
337
|
-
|
358
|
+
if res.code.to_i >= 400
|
359
|
+
raise RemoteFileError if @options[:io_exceptions]
|
360
|
+
return '', nil
|
361
|
+
end
|
338
362
|
|
339
|
-
|
340
|
-
|
341
|
-
|
363
|
+
case res['content-encoding']
|
364
|
+
when 'gzip'
|
365
|
+
io = Zlib::GzipReader.new(StringIO.new(res.body))
|
366
|
+
src = io.read
|
367
|
+
when 'deflate'
|
368
|
+
io = Zlib::Inflate.new
|
369
|
+
src = io.inflate(res.body)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
if charset
|
374
|
+
ic = Iconv.new('UTF-8//IGNORE', charset)
|
375
|
+
src = ic.iconv(src)
|
376
|
+
end
|
377
|
+
rescue
|
342
378
|
raise RemoteFileError if @options[:io_exceptions]
|
343
|
-
return '', nil
|
344
379
|
end
|
380
|
+
|
381
|
+
return src, charset
|
345
382
|
end
|
346
383
|
|
347
384
|
private
|
data/lib/css_parser.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'net/https'
|
2
3
|
require 'open-uri'
|
3
4
|
require 'digest/md5'
|
4
5
|
require 'zlib'
|
6
|
+
require 'stringio'
|
5
7
|
require 'iconv'
|
6
8
|
|
7
9
|
module CssParser
|
8
|
-
VERSION = '1.1.
|
10
|
+
VERSION = '1.1.2'
|
9
11
|
|
10
12
|
# Merge multiple CSS RuleSets by cascading according to the CSS 2.1 cascading rules
|
11
13
|
# (http://www.w3.org/TR/REC-CSS2/cascade.html#cascading-order).
|
@@ -11,10 +11,10 @@ class CssParserLoadingTests < Test::Unit::TestCase
|
|
11
11
|
|
12
12
|
@uri_base = 'http://localhost:12000'
|
13
13
|
|
14
|
-
www_root = File.dirname(__FILE__) + '/fixtures/'
|
14
|
+
@www_root = File.dirname(__FILE__) + '/fixtures/'
|
15
15
|
|
16
16
|
@server_thread = Thread.new do
|
17
|
-
s = WEBrick::HTTPServer.new(:Port => 12000, :DocumentRoot => www_root, :Logger => Log.new(nil, BasicLog::FATAL), :AccessLog => [])
|
17
|
+
s = WEBrick::HTTPServer.new(:Port => 12000, :DocumentRoot => @www_root, :Logger => Log.new(nil, BasicLog::FATAL), :AccessLog => [])
|
18
18
|
@port = s.config[:Port]
|
19
19
|
begin
|
20
20
|
s.start
|
@@ -25,24 +25,38 @@ class CssParserLoadingTests < Test::Unit::TestCase
|
|
25
25
|
|
26
26
|
sleep 1 # ensure the server has time to load
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def teardown
|
30
30
|
@server_thread.kill
|
31
31
|
@server_thread.join(5)
|
32
32
|
@server_thread = nil
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def test_loading_a_local_file
|
36
36
|
file_name = File.dirname(__FILE__) + '/fixtures/simple.css'
|
37
37
|
@cp.load_file!(file_name)
|
38
38
|
assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
|
39
39
|
end
|
40
40
|
|
41
|
+
def test_loading_a_local_file_with_scheme
|
42
|
+
file_name = 'file://' + File.dirname(__FILE__) + '/fixtures/simple.css'
|
43
|
+
@cp.load_uri!(file_name)
|
44
|
+
assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
|
45
|
+
end
|
46
|
+
|
41
47
|
def test_loading_a_remote_file
|
42
48
|
@cp.load_uri!("#{@uri_base}/simple.css")
|
43
49
|
assert_equal 'margin: 0px;', @cp.find_by_selector('p').join(' ')
|
44
50
|
end
|
45
51
|
|
52
|
+
# http://github.com/alexdunae/css_parser/issues#issue/4
|
53
|
+
def test_loading_a_remote_file_over_ssl
|
54
|
+
# TODO: test SSL locally
|
55
|
+
@cp.load_uri!("https://www.expresspardons.com/inc/screen.css")
|
56
|
+
assert_match /margin\: 0\;/, @cp.find_by_selector('body').join(' ')
|
57
|
+
end
|
58
|
+
|
59
|
+
|
46
60
|
def test_following_at_import_rules_local
|
47
61
|
base_dir = File.dirname(__FILE__) + '/fixtures'
|
48
62
|
@cp.load_file!('import1.css', base_dir)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: css_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 1.1.
|
9
|
+
- 2
|
10
|
+
version: 1.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alex Dunae
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-28 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|