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: