lib/css_parser/parser.rb in css_parser-1.2.2 vs lib/css_parser/parser.rb in css_parser-1.2.3
- old
+ new
@@ -19,17 +19,15 @@
STRIP_CSS_COMMENTS_RX = /\/\*.*?\*\//m
STRIP_HTML_COMMENTS_RX = /\<\!\-\-|\-\-\>/m
# Initial parsing
- RE_AT_IMPORT_RULE = /\@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s\)]*)["']?\)?([\w\s\,^\])]*)\)?[;\n]?/
+ RE_AT_IMPORT_RULE = /\@import\s*(?:url\s*)?(?:\()?(?:\s*)["']?([^'"\s\)]*)["']?\)?([\w\s\,^\]\(\))]*)\)?[;\n]?/
# Array of CSS files that have been loaded.
attr_reader :loaded_uris
-
- #attr_reader :rules
-
+
#--
# Class variable? see http://www.oreillynet.com/ruby/blog/2007/01/nubygems_dont_use_class_variab_1.html
#++
@folded_declaration_cache = {}
class << self; attr_reader :folded_declaration_cache; end
@@ -96,28 +94,30 @@
#
# parser = CssParser::Parser.new
# parser.add_block!(css)
def add_block!(block, options = {})
options = {:base_uri => nil, :base_dir => nil, :charset => nil, :media_types => :all, :only_media_types => :all}.merge(options)
- options[:media_types] = [options[:media_types]].flatten
- options[:only_media_types] = [options[:only_media_types]].flatten
+ options[:media_types] = [options[:media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
+ options[:only_media_types] = [options[:only_media_types]].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
block = cleanup_block(block)
if options[:base_uri] and @options[:absolute_paths]
block = CssParser.convert_uris(block, options[:base_uri])
end
-
+
# Load @imported CSS
- block.scan(RE_AT_IMPORT_RULE).each do |import_rule|
+ block.scan(RE_AT_IMPORT_RULE).each do |import_rule|
media_types = []
if media_string = import_rule[-1]
- media_string.split(/\s|\,/).each do |t|
- media_types << t.to_sym unless t.empty?
+ media_string.split(/[,]/).each do |t|
+ media_types << CssParser.sanitize_media_query(t) unless t.empty?
end
+ else
+ media_types = [:all]
end
-
+
next unless options[:only_media_types].include?(:all) or media_types.length < 1 or (media_types & options[:only_media_types]).length > 0
import_path = import_rule[0].to_s.gsub(/['"]*/, '').strip
if options[:base_uri]
@@ -146,21 +146,21 @@
#
# +media_types+ can be a symbol or an array of symbols.
def add_rule_set!(ruleset, media_types = :all)
raise ArgumentError unless ruleset.kind_of?(CssParser::RuleSet)
- media_types = [media_types] if media_types.kind_of?(Symbol)
+ media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
@rules << {:media_types => media_types, :rules => ruleset}
end
# Iterate through RuleSet objects.
#
# +media_types+ can be a symbol or an array of symbols.
def each_rule_set(media_types = :all) # :yields: rule_set
media_types = [:all] if media_types.nil?
- media_types = [media_types] if media_types.kind_of?(Symbol)
+ media_types = [media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
@rules.each do |block|
if media_types.include?(:all) or block[:media_types].any? { |mt| media_types.include?(mt) }
yield block[:rules]
end
@@ -171,11 +171,10 @@
#
# +media_types+ can be a symbol or an array of symbols.
# See RuleSet#each_selector for +options+.
def each_selector(media_types = :all, options = {}) # :yields: selectors, declarations, specificity
each_rule_set(media_types) do |rule_set|
- #puts rule_set
rule_set.each_selector(options) do |selectors, declarations, specificity|
yield selectors, declarations, specificity
end
end
end
@@ -186,45 +185,59 @@
each_selector(media_types) do |selectors, declarations, specificity|
out << "#{selectors} {\n#{declarations}\n}\n"
end
out
end
+
+ # A hash of { :media_query => rule_sets }
+ def rules_by_media_query
+ rules_by_media = {}
+ @rules.each do |block|
+ block[:media_types].each do |mt|
+ unless rules_by_media.has_key?(mt)
+ rules_by_media[mt] = []
+ end
+ rules_by_media[mt] << block[:rules]
+ end
+ end
+
+ rules_by_media
+ end
# Merge declarations with the same selector.
def compact! # :nodoc:
compacted = []
compacted
end
def parse_block_into_rule_sets!(block, options = {}) # :nodoc:
- options = {:media_types => :all}.merge(options)
- media_types = options[:media_types]
+ current_media_queries = [:all]
+ if options[:media_types]
+ current_media_queries = options[:media_types].flatten.collect { |mt| CssParser.sanitize_media_query(mt)}
+ end
in_declarations = 0
-
block_depth = 0
- # @charset is ignored for now
- in_charset = false
+ in_charset = false # @charset is ignored for now
in_string = false
in_at_media_rule = false
+ in_media_block = false
current_selectors = ''
+ current_media_query = ''
current_declarations = ''
block.scan(/([\\]?[{}\s"]|(.[^\s"{}\\]*))/).each do |matches|
- #block.scan(/((.[^{}"\n\r\f\s]*)[\s]|(.[^{}"\n\r\f]*)\{|(.[^{}"\n\r\f]*)\}|(.[^{}"\n\r\f]*)\"|(.*)[\s]+)/).each do |matches|
token = matches[0]
- #puts "TOKEN: #{token}" unless token =~ /^[\s]*$/
if token =~ /\A"/ # found un-escaped double quote
in_string = !in_string
end
if in_declarations > 0
-
# too deep, malformed declaration block
if in_declarations > 1
in_declarations -= 1 if token =~ /\}/
next
end
@@ -240,12 +253,11 @@
current_declarations.gsub!(/\}[\s]*$/, '')
in_declarations -= 1
unless current_declarations.strip.empty?
- #puts "SAVING #{current_selectors} -> #{current_declarations}"
- add_rule!(current_selectors, current_declarations, media_types)
+ add_rule!(current_selectors, current_declarations, current_media_queries)
end
current_selectors = ''
current_declarations = ''
end
@@ -255,20 +267,34 @@
media_types = []
elsif in_at_media_rule
if token =~ /\{/
block_depth = block_depth + 1
in_at_media_rule = false
+ in_media_block = true
+ current_media_queries << CssParser.sanitize_media_query(current_media_query)
+ current_media_query = ''
+ elsif token =~ /[,]/
+ # new media query begins
+ token.gsub!(/[,]/, ' ')
+ current_media_query += token.strip + ' '
+ current_media_queries << CssParser.sanitize_media_query(current_media_query)
+ current_media_query = ''
else
- token.gsub!(/[,\s]*/, '')
- media_types << token.strip.downcase.to_sym unless token.empty?
+ current_media_query += token.strip + ' '
end
elsif in_charset or token =~ /@charset/i
# iterate until we are out of the charset declaration
in_charset = (token =~ /;/ ? false : true)
else
if token =~ /\}/ and not in_string
block_depth = block_depth - 1
+
+ # reset the current media query scope
+ if in_media_block
+ current_media_queries = []
+ in_media_block = false
+ end
else
if token =~ /\{/ and not in_string
current_selectors.gsub!(/^[\s]*/, '')
current_selectors.gsub!(/[\s]*$/, '')
in_declarations += 1
@@ -279,11 +305,11 @@
end
end
# check for unclosed braces
if in_declarations > 0
- add_rule!(current_selectors, current_declarations, media_types)
- end
+ add_rule!(current_selectors, current_declarations, current_media_queries)
+ end
end
# Load a remote CSS file.
#
# You can also pass in file://test.css