lib/css_parser/parser.rb in css_parser-1.1.1 vs lib/css_parser/parser.rb in css_parser-1.1.2
- old
+ new
@@ -21,15 +21,11 @@
STRIP_HTML_COMMENTS_RX = /\<\!\-\-|\-\-\>/m
# Initial parsing
RE_AT_IMPORT_RULE = /\@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s\)]*)["']?\)?([\w\s\,^\])]*)\)?[;\n]?/
- #--
- # 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
- #++
-
- # Array of CSS files that have been loaded.
+ # Array of CSS files that have been loaded.
attr_reader :loaded_uris
#attr_reader :rules
#--
@@ -197,11 +193,11 @@
def parse_block_into_rule_sets!(block, options = {}) # :nodoc:
options = {:media_types => :all}.merge(options)
media_types = options[:media_types]
- in_declarations = false
+ in_declarations = 0
block_depth = 0
# @charset is ignored for now
in_charset = false
@@ -217,17 +213,29 @@
#puts "TOKEN: #{token}" unless token =~ /^[\s]*$/
if token =~ /\A"/ # found un-escaped double quote
in_string = !in_string
end
- if in_declarations
+ if in_declarations > 0
+
+ # too deep, malformed declaration block
+ if in_declarations > 1
+ in_declarations -= 1 if token =~ /\}/
+ next
+ end
+
+ if token =~ /\{/
+ in_declarations += 1
+ next
+ end
+
current_declarations += token
if token =~ /\}/ and not in_string
current_declarations.gsub!(/\}[\s]*$/, '')
- in_declarations = false
+ in_declarations -= 1
unless current_declarations.strip.empty?
#puts "SAVING #{current_selectors} -> #{current_declarations}"
add_rule!(current_selectors, current_declarations, media_types)
end
@@ -255,27 +263,32 @@
block_depth = block_depth - 1
else
if token =~ /\{/ and not in_string
current_selectors.gsub!(/^[\s]*/, '')
current_selectors.gsub!(/[\s]*$/, '')
- in_declarations = true
+ in_declarations += 1
else
current_selectors += token
end
end
end
end
end
# Load a remote CSS file.
+ #
+ # You can also pass in file://test.css
def load_uri!(uri, base_uri = nil, media_types = :all)
+ uri = URI.parse(uri) unless uri.respond_to? :scheme
+ if uri.scheme == 'file' or uri.scheme.nil?
+ uri.path = File.expand_path(uri.path)
+ uri.scheme = 'file'
+ end
base_uri = uri if base_uri.nil?
src, charset = read_remote_file(uri)
- unless src.empty?
- add_block!(src, {:media_types => media_types, :base_uri => base_uri})
- end
+ add_block!(src, {:media_types => media_types, :base_uri => base_uri})
end
# Load a local CSS file.
def load_file!(file_name, base_dir = nil, media_types = :all)
file_name = File.expand_path(file_name, base_dir)
@@ -319,30 +332,54 @@
return '', nil
end
@loaded_uris << uri.to_s
+ src = '', charset = nil
+
begin
- #fh = open(uri, 'rb')
- fh = open(uri, 'rb', 'User-Agent' => USER_AGENT, 'Accept-Encoding' => 'gzip')
+ uri = URI.parse(uri.to_s)
+ http = Net::HTTP.new(uri.host, uri.port)
- if fh.content_encoding.include?('gzip')
- remote_src = Zlib::GzipReader.new(fh).read
+ if uri.scheme == 'file'
+ # local file
+ fh = open(uri.path, 'rb')
+ src = fh.read
+ fh.close
else
- remote_src = fh.read
- end
+ # remote file
+ if uri.scheme == 'https'
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
- #puts "reading #{uri} (#{fh.charset})"
+ res, src = http.get(uri.path, {'User-Agent' => USER_AGENT, 'Accept-Encoding' => 'gzip'})
+ charset = fh.respond_to?(:charset) ? fh.charset : 'utf-8'
- ic = Iconv.new('UTF-8//IGNORE', fh.charset)
- src = ic.iconv(remote_src)
+ if res.code.to_i >= 400
+ raise RemoteFileError if @options[:io_exceptions]
+ return '', nil
+ end
- fh.close
- return src, fh.charset
- rescue Exception => e
+ case res['content-encoding']
+ when 'gzip'
+ io = Zlib::GzipReader.new(StringIO.new(res.body))
+ src = io.read
+ when 'deflate'
+ io = Zlib::Inflate.new
+ src = io.inflate(res.body)
+ end
+ end
+
+ if charset
+ ic = Iconv.new('UTF-8//IGNORE', charset)
+ src = ic.iconv(src)
+ end
+ rescue
raise RemoteFileError if @options[:io_exceptions]
- return '', nil
end
+
+ return src, charset
end
private
# Save a folded declaration block to the internal cache.
def save_folded_declaration(block_hash, folded_declaration) # :nodoc: