css_parser 1.6.0 → 1.7.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 +5 -5
- data/lib/css_parser.rb +6 -4
- data/lib/css_parser/parser.rb +36 -31
- data/lib/css_parser/regexps.rb +7 -7
- data/lib/css_parser/rule_set.rb +77 -77
- data/lib/css_parser/version.rb +1 -1
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 66714382244cadbf112104868d94ff8b131ac4cf007deacac52d726bee1a9f9a
         | 
| 4 | 
            +
              data.tar.gz: 8ac559b1fb982da00dfbef4188b3773d2a78637f4db26393aba7cf62287b7883
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ba75d2e879d80cb7c854889990fd190f5c1fb664ed96b3a47ad78614a257d2ed7acfc3ba453ea34e87612636512305089c1a73d081c8a1c729a854217b17613e
         | 
| 7 | 
            +
              data.tar.gz: ff49b36b1007ae8ce0ecbfd6a2e92536d16c46062898c0a3bae402bacdb731785d6e4b80b0d08e557fcf372f2b0da2d75629c471c8ed2ce59addd13629eda9b9
         | 
    
        data/lib/css_parser.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            require 'addressable/uri'
         | 
| 2 3 | 
             
            require 'uri'
         | 
| 3 4 | 
             
            require 'net/https'
         | 
| @@ -122,10 +123,10 @@ module CssParser | |
| 122 123 | 
             
              def self.calculate_specificity(selector)
         | 
| 123 124 | 
             
                a = 0
         | 
| 124 125 | 
             
                b = selector.scan(/\#/).length
         | 
| 125 | 
            -
                c = selector.scan( | 
| 126 | 
            -
                d = selector.scan( | 
| 126 | 
            +
                c = selector.scan(NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX_NC).length
         | 
| 127 | 
            +
                d = selector.scan(ELEMENTS_AND_PSEUDO_ELEMENTS_RX_NC).length
         | 
| 127 128 |  | 
| 128 | 
            -
                 | 
| 129 | 
            +
                "#{a}#{b}#{c}#{d}".to_i
         | 
| 129 130 | 
             
              rescue
         | 
| 130 131 | 
             
                return 0
         | 
| 131 132 | 
             
              end
         | 
| @@ -160,7 +161,8 @@ module CssParser | |
| 160 161 | 
             
              end
         | 
| 161 162 |  | 
| 162 163 | 
             
              def self.sanitize_media_query(raw)
         | 
| 163 | 
            -
                mq = raw.to_s.gsub(/[\s]+/, ' ') | 
| 164 | 
            +
                mq = raw.to_s.gsub(/[\s]+/, ' ')
         | 
| 165 | 
            +
                mq.strip!
         | 
| 164 166 | 
             
                mq = 'all' if mq.empty?
         | 
| 165 167 | 
             
                mq.to_sym
         | 
| 166 168 | 
             
              end
         | 
    
        data/lib/css_parser/parser.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module CssParser
         | 
| 2 3 | 
             
              # Exception class used for any errors encountered while downloading remote files.
         | 
| 3 4 | 
             
              class RemoteFileError < IOError; end
         | 
| @@ -184,7 +185,8 @@ module CssParser | |
| 184 185 | 
             
                def add_rule_set!(ruleset, media_types = :all)
         | 
| 185 186 | 
             
                  raise ArgumentError unless ruleset.kind_of?(CssParser::RuleSet)
         | 
| 186 187 |  | 
| 187 | 
            -
                  media_types = [media_types] | 
| 188 | 
            +
                  media_types = [media_types] unless Array === media_types
         | 
| 189 | 
            +
                  media_types = media_types.flat_map { |mt| CssParser.sanitize_media_query(mt)}
         | 
| 188 190 |  | 
| 189 191 | 
             
                  @rules << {:media_types => media_types, :rules => ruleset}
         | 
| 190 192 | 
             
                end
         | 
| @@ -242,6 +244,8 @@ module CssParser | |
| 242 244 | 
             
                # +media_types+ can be a symbol or an array of symbols.
         | 
| 243 245 | 
             
                # See RuleSet#each_selector for +options+.
         | 
| 244 246 | 
             
                def each_selector(all_media_types = :all, options = {}) # :yields: selectors, declarations, specificity, media_types
         | 
| 247 | 
            +
                  return to_enum(:each_selector) unless block_given?
         | 
| 248 | 
            +
             | 
| 245 249 | 
             
                  each_rule_set(all_media_types) do |rule_set, media_types|
         | 
| 246 250 | 
             
                    rule_set.each_selector(options) do |selectors, declarations, specificity|
         | 
| 247 251 | 
             
                      yield selectors, declarations, specificity, media_types
         | 
| @@ -251,7 +255,7 @@ module CssParser | |
| 251 255 |  | 
| 252 256 | 
             
                # Output all CSS rules as a single stylesheet.
         | 
| 253 257 | 
             
                def to_s(which_media = :all)
         | 
| 254 | 
            -
                  out =  | 
| 258 | 
            +
                  out = String.new
         | 
| 255 259 | 
             
                  styles_by_media_types = {}
         | 
| 256 260 | 
             
                  each_selector(which_media) do |selectors, declarations, specificity, media_types|
         | 
| 257 261 | 
             
                    media_types.each do |media_type|
         | 
| @@ -262,17 +266,17 @@ module CssParser | |
| 262 266 |  | 
| 263 267 | 
             
                  styles_by_media_types.each_pair do |media_type, media_styles|
         | 
| 264 268 | 
             
                    media_block = (media_type != :all)
         | 
| 265 | 
            -
                    out  | 
| 269 | 
            +
                    out << "@media #{media_type} {\n" if media_block
         | 
| 266 270 |  | 
| 267 271 | 
             
                    media_styles.each do |media_style|
         | 
| 268 272 | 
             
                      if media_block
         | 
| 269 | 
            -
                        out  | 
| 273 | 
            +
                        out << "  #{media_style[0]} {\n    #{media_style[1]}\n  }\n"
         | 
| 270 274 | 
             
                      else
         | 
| 271 | 
            -
                        out  | 
| 275 | 
            +
                        out << "#{media_style[0]} {\n#{media_style[1]}\n}\n"
         | 
| 272 276 | 
             
                      end
         | 
| 273 277 | 
             
                    end
         | 
| 274 278 |  | 
| 275 | 
            -
                    out  | 
| 279 | 
            +
                    out << "}\n" if media_block
         | 
| 276 280 | 
             
                  end
         | 
| 277 281 |  | 
| 278 282 | 
             
                  out
         | 
| @@ -314,44 +318,43 @@ module CssParser | |
| 314 318 | 
             
                  in_at_media_rule = false
         | 
| 315 319 | 
             
                  in_media_block = false
         | 
| 316 320 |  | 
| 317 | 
            -
                  current_selectors =  | 
| 318 | 
            -
                  current_media_query =  | 
| 319 | 
            -
                  current_declarations =  | 
| 321 | 
            +
                  current_selectors = String.new
         | 
| 322 | 
            +
                  current_media_query = String.new
         | 
| 323 | 
            +
                  current_declarations = String.new
         | 
| 320 324 |  | 
| 321 325 | 
             
                  # once we are in a rule, we will use this to store where we started if we are capturing offsets
         | 
| 322 326 | 
             
                  rule_start = nil
         | 
| 323 327 | 
             
                  offset = nil
         | 
| 324 328 |  | 
| 325 | 
            -
                  block.scan( | 
| 326 | 
            -
                    token = matches[0]
         | 
| 327 | 
            -
             | 
| 329 | 
            +
                  block.scan(/\s+|[\\]{2,}|[\\]?[{}\s"]|.[^\s"{}\\]*/) do |token|
         | 
| 328 330 | 
             
                    # save the regex offset so that we know where in the file we are
         | 
| 329 331 | 
             
                    offset = Regexp.last_match.offset(0) if options[:capture_offsets]
         | 
| 330 332 |  | 
| 331 | 
            -
                    if token | 
| 333 | 
            +
                    if token.start_with?('"') # found un-escaped double quote
         | 
| 332 334 | 
             
                      in_string = !in_string
         | 
| 333 335 | 
             
                    end
         | 
| 334 336 |  | 
| 335 337 | 
             
                    if in_declarations > 0
         | 
| 336 338 | 
             
                      # too deep, malformed declaration block
         | 
| 337 339 | 
             
                      if in_declarations > 1
         | 
| 338 | 
            -
                        in_declarations -= 1 if token | 
| 340 | 
            +
                        in_declarations -= 1 if token.include?('}')
         | 
| 339 341 | 
             
                        next
         | 
| 340 342 | 
             
                      end
         | 
| 341 343 |  | 
| 342 | 
            -
                      if  | 
| 344 | 
            +
                      if !in_string && token.include?('{')
         | 
| 343 345 | 
             
                        in_declarations += 1
         | 
| 344 346 | 
             
                        next
         | 
| 345 347 | 
             
                      end
         | 
| 346 348 |  | 
| 347 | 
            -
                      current_declarations  | 
| 349 | 
            +
                      current_declarations << token
         | 
| 348 350 |  | 
| 349 | 
            -
                      if  | 
| 351 | 
            +
                      if !in_string && token.include?('}')
         | 
| 350 352 | 
             
                        current_declarations.gsub!(/\}[\s]*$/, '')
         | 
| 351 353 |  | 
| 352 354 | 
             
                        in_declarations -= 1
         | 
| 355 | 
            +
                        current_declarations.strip!
         | 
| 353 356 |  | 
| 354 | 
            -
                        unless current_declarations. | 
| 357 | 
            +
                        unless current_declarations.empty?
         | 
| 355 358 | 
             
                          if options[:capture_offsets]
         | 
| 356 359 | 
             
                            add_rule_with_offsets!(current_selectors, current_declarations, options[:filename], (rule_start..offset.last), current_media_queries)
         | 
| 357 360 | 
             
                          else
         | 
| @@ -359,8 +362,8 @@ module CssParser | |
| 359 362 | 
             
                          end
         | 
| 360 363 | 
             
                        end
         | 
| 361 364 |  | 
| 362 | 
            -
                        current_selectors =  | 
| 363 | 
            -
                        current_declarations =  | 
| 365 | 
            +
                        current_selectors = String.new
         | 
| 366 | 
            +
                        current_declarations = String.new
         | 
| 364 367 |  | 
| 365 368 | 
             
                        # restart our search for selectors and declarations
         | 
| 366 369 | 
             
                        rule_start = nil if options[:capture_offsets]
         | 
| @@ -370,26 +373,28 @@ module CssParser | |
| 370 373 | 
             
                      in_at_media_rule = true
         | 
| 371 374 | 
             
                      current_media_queries = []
         | 
| 372 375 | 
             
                    elsif in_at_media_rule
         | 
| 373 | 
            -
                      if token | 
| 376 | 
            +
                      if token.include?('{')
         | 
| 374 377 | 
             
                        block_depth = block_depth + 1
         | 
| 375 378 | 
             
                        in_at_media_rule = false
         | 
| 376 379 | 
             
                        in_media_block = true
         | 
| 377 380 | 
             
                        current_media_queries << CssParser.sanitize_media_query(current_media_query)
         | 
| 378 | 
            -
                        current_media_query =  | 
| 379 | 
            -
                      elsif token | 
| 381 | 
            +
                        current_media_query = String.new
         | 
| 382 | 
            +
                      elsif token.include?(',')
         | 
| 380 383 | 
             
                        # new media query begins
         | 
| 381 | 
            -
                        token. | 
| 382 | 
            -
                         | 
| 384 | 
            +
                        token.tr!(',', ' ')
         | 
| 385 | 
            +
                        token.strip!
         | 
| 386 | 
            +
                        current_media_query << token << ' '
         | 
| 383 387 | 
             
                        current_media_queries << CssParser.sanitize_media_query(current_media_query)
         | 
| 384 | 
            -
                        current_media_query =  | 
| 388 | 
            +
                        current_media_query = String.new
         | 
| 385 389 | 
             
                      else
         | 
| 386 | 
            -
                         | 
| 390 | 
            +
                        token.strip!
         | 
| 391 | 
            +
                        current_media_query << token << ' '
         | 
| 387 392 | 
             
                      end
         | 
| 388 393 | 
             
                    elsif in_charset or token =~ /@charset/i
         | 
| 389 394 | 
             
                      # iterate until we are out of the charset declaration
         | 
| 390 | 
            -
                      in_charset =  | 
| 395 | 
            +
                      in_charset = !token.include?(';')
         | 
| 391 396 | 
             
                    else
         | 
| 392 | 
            -
                      if  | 
| 397 | 
            +
                      if !in_string && token.include?('}')
         | 
| 393 398 | 
             
                        block_depth = block_depth - 1
         | 
| 394 399 |  | 
| 395 400 | 
             
                        # reset the current media query scope
         | 
| @@ -398,12 +403,12 @@ module CssParser | |
| 398 403 | 
             
                          in_media_block = false
         | 
| 399 404 | 
             
                        end
         | 
| 400 405 | 
             
                      else
         | 
| 401 | 
            -
                        if  | 
| 406 | 
            +
                        if !in_string && token.include?('{')
         | 
| 402 407 | 
             
                          current_selectors.strip!
         | 
| 403 408 | 
             
                          in_declarations += 1
         | 
| 404 409 | 
             
                        else
         | 
| 405 410 | 
             
                          # if we are in a selector, add the token to the current selectors
         | 
| 406 | 
            -
                          current_selectors  | 
| 411 | 
            +
                          current_selectors << token
         | 
| 407 412 |  | 
| 408 413 | 
             
                          # mark this as the beginning of the selector unless we have already marked it
         | 
| 409 414 | 
             
                          rule_start = offset.first if options[:capture_offsets] && rule_start.nil? && token =~ /^[^\s]+$/
         | 
    
        data/lib/css_parser/regexps.rb
    CHANGED
    
    | @@ -54,12 +54,12 @@ module CssParser | |
| 54 54 |  | 
| 55 55 |  | 
| 56 56 | 
             
              # Patterns for specificity calculations
         | 
| 57 | 
            -
               | 
| 58 | 
            -
                ( | 
| 57 | 
            +
              NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX_NC= /
         | 
| 58 | 
            +
                (?:\.[\w]+)                     # classes
         | 
| 59 59 | 
             
                |
         | 
| 60 | 
            -
                \[( | 
| 60 | 
            +
                \[(?:\w+)                       # attributes
         | 
| 61 61 | 
             
                |
         | 
| 62 | 
            -
                ( | 
| 62 | 
            +
                (?:\:(?:                          # pseudo classes
         | 
| 63 63 | 
             
                  link|visited|active
         | 
| 64 64 | 
             
                  |hover|focus
         | 
| 65 65 | 
             
                  |lang
         | 
| @@ -72,10 +72,10 @@ module CssParser | |
| 72 72 | 
             
                  |empty|contains
         | 
| 73 73 | 
             
                ))
         | 
| 74 74 | 
             
              /ix
         | 
| 75 | 
            -
               | 
| 76 | 
            -
                (( | 
| 75 | 
            +
              ELEMENTS_AND_PSEUDO_ELEMENTS_RX_NC = /
         | 
| 76 | 
            +
                (?:(?:^|[\s\+\>\~]+)[\w]+       # elements
         | 
| 77 77 | 
             
                |
         | 
| 78 | 
            -
                \:{1,2}(                    # pseudo-elements
         | 
| 78 | 
            +
                \:{1,2}(?:                    # pseudo-elements
         | 
| 79 79 | 
             
                  after|before
         | 
| 80 80 | 
             
                  |first-letter|first-line
         | 
| 81 81 | 
             
                  |selection
         | 
    
        data/lib/css_parser/rule_set.rb
    CHANGED
    
    | @@ -1,3 +1,4 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 1 2 | 
             
            module CssParser
         | 
| 2 3 | 
             
              class RuleSet
         | 
| 3 4 | 
             
                # Patterns for specificity calculations
         | 
| @@ -6,6 +7,19 @@ module CssParser | |
| 6 7 |  | 
| 7 8 | 
             
                BACKGROUND_PROPERTIES = ['background-color', 'background-image', 'background-repeat', 'background-position', 'background-size', 'background-attachment']
         | 
| 8 9 | 
             
                LIST_STYLE_PROPERTIES = ['list-style-type', 'list-style-position', 'list-style-image']
         | 
| 10 | 
            +
                FONT_STYLE_PROPERTIES = ['font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family']
         | 
| 11 | 
            +
                BORDER_STYLE_PROPERTIES = ['border-width', 'border-style', 'border-color']
         | 
| 12 | 
            +
                BORDER_PROPERTIES = ['border', 'border-left', 'border-right', 'border-top', 'border-bottom']
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                NUMBER_OF_DIMENSIONS = 4
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                DIMENSIONS = [
         | 
| 17 | 
            +
                  ['margin', %w(margin-top margin-right margin-bottom margin-left)],
         | 
| 18 | 
            +
                  ['padding', %w(padding-top padding-right padding-bottom padding-left)],
         | 
| 19 | 
            +
                  ['border-color', %w(border-top-color border-right-color border-bottom-color border-left-color)],
         | 
| 20 | 
            +
                  ['border-style', %w(border-top-style border-right-style border-bottom-style border-left-style)],
         | 
| 21 | 
            +
                  ['border-width', %w(border-top-width border-right-width border-bottom-width border-left-width)],
         | 
| 22 | 
            +
                ]
         | 
| 9 23 |  | 
| 10 24 | 
             
                # Array of selector strings.
         | 
| 11 25 | 
             
                attr_reader   :selectors
         | 
| @@ -27,7 +41,7 @@ module CssParser | |
| 27 41 | 
             
                  return '' unless property and not property.empty?
         | 
| 28 42 |  | 
| 29 43 | 
             
                  property = property.downcase.strip
         | 
| 30 | 
            -
                  properties = @declarations.inject( | 
| 44 | 
            +
                  properties = @declarations.inject(String.new) do |val, (key, data)|
         | 
| 31 45 | 
             
                    #puts "COMPARING #{key} #{key.inspect} against #{property} #{property.inspect}"
         | 
| 32 46 | 
             
                    importance = data[:is_important] ? ' !important' : ''
         | 
| 33 47 | 
             
                    val << "#{data[:value]}#{importance}; " if key.downcase.strip == property
         | 
| @@ -58,7 +72,8 @@ module CssParser | |
| 58 72 |  | 
| 59 73 | 
             
                  value.gsub!(/;\Z/, '')
         | 
| 60 74 | 
             
                  is_important = !value.gsub!(CssParser::IMPORTANT_IN_PROPERTY_RX, '').nil?
         | 
| 61 | 
            -
                  property = property.downcase | 
| 75 | 
            +
                  property = property.downcase
         | 
| 76 | 
            +
                  property.strip!
         | 
| 62 77 | 
             
                  #puts "SAVING #{property}  #{value} #{is_important.inspect}"
         | 
| 63 78 | 
             
                  @declarations[property] = {
         | 
| 64 79 | 
             
                    :value => value, :is_important => is_important, :order => @order += 1
         | 
| @@ -105,13 +120,14 @@ module CssParser | |
| 105 120 | 
             
                # TODO: Clean-up regexp doesn't seem to work
         | 
| 106 121 | 
             
                #++
         | 
| 107 122 | 
             
                def declarations_to_s(options = {})
         | 
| 108 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
             | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
             | 
| 123 | 
            +
                  str = String.new
         | 
| 124 | 
            +
                  each_declaration do |prop, val, is_important|
         | 
| 125 | 
            +
                    importance = (options[:force_important] || is_important) ? ' !important' : ''
         | 
| 126 | 
            +
                    str << "#{prop}: #{val}#{importance}; "
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                  str.gsub!(/^[\s^(\{)]+|[\n\r\f\t]*|[\s]+$/mx, '')
         | 
| 129 | 
            +
                  str.strip!
         | 
| 130 | 
            +
                  str
         | 
| 115 131 | 
             
                end
         | 
| 116 132 |  | 
| 117 133 | 
             
                # Return the CSS rule set as a string.
         | 
| @@ -164,7 +180,7 @@ module CssParser | |
| 164 180 | 
             
                # Split shorthand border declarations (e.g. <tt>border: 1px red;</tt>)
         | 
| 165 181 | 
             
                # Additional splitting happens in expand_dimensions_shorthand!
         | 
| 166 182 | 
             
                def expand_border_shorthand! # :nodoc:
         | 
| 167 | 
            -
                   | 
| 183 | 
            +
                  BORDER_PROPERTIES.each do |k|
         | 
| 168 184 | 
             
                    next unless @declarations.has_key?(k)
         | 
| 169 185 |  | 
| 170 186 | 
             
                    value = @declarations[k][:value]
         | 
| @@ -180,14 +196,8 @@ module CssParser | |
| 180 196 | 
             
                # Split shorthand dimensional declarations (e.g. <tt>margin: 0px auto;</tt>)
         | 
| 181 197 | 
             
                # into their constituent parts.  Handles margin, padding, border-color, border-style and border-width.
         | 
| 182 198 | 
             
                def expand_dimensions_shorthand! # :nodoc:
         | 
| 183 | 
            -
                   | 
| 184 | 
            -
                   'padding'      => 'padding-%s',
         | 
| 185 | 
            -
                   'border-color' => 'border-%s-color',
         | 
| 186 | 
            -
                   'border-style' => 'border-%s-style',
         | 
| 187 | 
            -
                   'border-width' => 'border-%s-width'}.each do |property, expanded|
         | 
| 188 | 
            -
             | 
| 199 | 
            +
                  DIMENSIONS.each do |property, (top, right, bottom, left)|
         | 
| 189 200 | 
             
                    next unless @declarations.has_key?(property)
         | 
| 190 | 
            -
             | 
| 191 201 | 
             
                    value = @declarations[property][:value]
         | 
| 192 202 |  | 
| 193 203 | 
             
                    # RGB and HSL values in borders are the only units that can have spaces (within params).
         | 
| @@ -199,29 +209,24 @@ module CssParser | |
| 199 209 |  | 
| 200 210 | 
             
                    matches = value.strip.split(/\s+/)
         | 
| 201 211 |  | 
| 202 | 
            -
                    t, r, b, l = nil
         | 
| 203 | 
            -
             | 
| 204 212 | 
             
                    case matches.length
         | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
                       | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 214 | 
            -
                      when 4
         | 
| 215 | 
            -
                        t =  matches[0]
         | 
| 216 | 
            -
                        r = matches[1]
         | 
| 217 | 
            -
                        b =  matches[2]
         | 
| 218 | 
            -
                        l = matches[3]
         | 
| 213 | 
            +
                    when 1
         | 
| 214 | 
            +
                      values = matches.to_a * 4
         | 
| 215 | 
            +
                    when 2
         | 
| 216 | 
            +
                      values = matches.to_a * 2
         | 
| 217 | 
            +
                    when 3
         | 
| 218 | 
            +
                      values = matches.to_a
         | 
| 219 | 
            +
                      values << matches[1] # left = right
         | 
| 220 | 
            +
                    when 4
         | 
| 221 | 
            +
                      values = matches.to_a
         | 
| 219 222 | 
             
                    end
         | 
| 220 223 |  | 
| 221 | 
            -
                     | 
| 222 | 
            -
             | 
| 223 | 
            -
                    split_declaration(property,  | 
| 224 | 
            -
                    split_declaration(property,  | 
| 224 | 
            +
                    t, r, b, l = values
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                    split_declaration(property, top, t)
         | 
| 227 | 
            +
                    split_declaration(property, right, r)
         | 
| 228 | 
            +
                    split_declaration(property, bottom, b)
         | 
| 229 | 
            +
                    split_declaration(property, left, l)
         | 
| 225 230 |  | 
| 226 231 | 
             
                    @declarations.delete(property)
         | 
| 227 232 | 
             
                  end
         | 
| @@ -362,7 +367,7 @@ module CssParser | |
| 362 367 | 
             
                def create_border_shorthand! # :nodoc:
         | 
| 363 368 | 
             
                  values = []
         | 
| 364 369 |  | 
| 365 | 
            -
                   | 
| 370 | 
            +
                  BORDER_STYLE_PROPERTIES.each do |property|
         | 
| 366 371 | 
             
                    if @declarations.has_key?(property) and not @declarations[property][:is_important]
         | 
| 367 372 | 
             
                      # can't merge if any value contains a space (i.e. has multiple values)
         | 
| 368 373 | 
             
                      # we temporarily remove any spaces after commas for the check (inside rgba, etc...)
         | 
| @@ -371,9 +376,7 @@ module CssParser | |
| 371 376 | 
             
                    end
         | 
| 372 377 | 
             
                  end
         | 
| 373 378 |  | 
| 374 | 
            -
                  @declarations.delete( | 
| 375 | 
            -
                  @declarations.delete('border-style')
         | 
| 376 | 
            -
                  @declarations.delete('border-color')
         | 
| 379 | 
            +
                  BORDER_STYLE_PROPERTIES.each { |prop| @declarations.delete(prop)}
         | 
| 377 380 |  | 
| 378 381 | 
             
                  unless values.empty?
         | 
| 379 382 | 
             
                    @declarations['border'] = {:value => values.join(' ')}
         | 
| @@ -383,23 +386,20 @@ module CssParser | |
| 383 386 | 
             
                # Looks for long format CSS dimensional properties (margin, padding, border-color, border-style and border-width)
         | 
| 384 387 | 
             
                # and converts them into shorthand CSS properties.
         | 
| 385 388 | 
             
                def create_dimensions_shorthand! # :nodoc:
         | 
| 386 | 
            -
                   | 
| 387 | 
            -
             | 
| 388 | 
            -
                  {'margin'       => 'margin-%s',
         | 
| 389 | 
            -
                   'padding'      => 'padding-%s',
         | 
| 390 | 
            -
                   'border-color' => 'border-%s-color',
         | 
| 391 | 
            -
                   'border-style' => 'border-%s-style',
         | 
| 392 | 
            -
                   'border-width' => 'border-%s-width'}.each do |property, expanded|
         | 
| 389 | 
            +
                  return if @declarations.size < NUMBER_OF_DIMENSIONS
         | 
| 393 390 |  | 
| 394 | 
            -
             | 
| 395 | 
            -
                     | 
| 396 | 
            -
                      dim == top or dim == right or dim == bottom or dim == left
         | 
| 397 | 
            -
                    end
         | 
| 391 | 
            +
                  DIMENSIONS.each do |property, dimensions|
         | 
| 392 | 
            +
                    (top, right, bottom, left) = dimensions
         | 
| 398 393 | 
             
                    # All four dimensions must be present
         | 
| 399 | 
            -
                    if  | 
| 394 | 
            +
                    if dimensions.count { |d| @declarations[d] } == NUMBER_OF_DIMENSIONS
         | 
| 400 395 | 
             
                      values = {}
         | 
| 401 396 |  | 
| 402 | 
            -
                       | 
| 397 | 
            +
                      [
         | 
| 398 | 
            +
                        [:top, top],
         | 
| 399 | 
            +
                        [:right, right],
         | 
| 400 | 
            +
                        [:bottom, bottom],
         | 
| 401 | 
            +
                        [:left, left],
         | 
| 402 | 
            +
                      ].each { |d, key| values[d] = @declarations[key][:value].downcase.strip }
         | 
| 403 403 |  | 
| 404 404 | 
             
                      if values[:left] == values[:right]
         | 
| 405 405 | 
             
                        if values[:top] == values[:bottom]
         | 
| @@ -419,7 +419,7 @@ module CssParser | |
| 419 419 | 
             
                      @declarations[property] = {:value => new_value.strip} unless new_value.empty?
         | 
| 420 420 |  | 
| 421 421 | 
             
                      # Delete the longhand values
         | 
| 422 | 
            -
                       | 
| 422 | 
            +
                      [top, right, bottom, left].each { |d| @declarations.delete(d) }
         | 
| 423 423 | 
             
                    end
         | 
| 424 424 | 
             
                  end
         | 
| 425 425 | 
             
                end
         | 
| @@ -429,33 +429,28 @@ module CssParser | |
| 429 429 | 
             
                # tries to convert them into a shorthand CSS <tt>font</tt> property.  All
         | 
| 430 430 | 
             
                # font properties must be present in order to create a shorthand declaration.
         | 
| 431 431 | 
             
                def create_font_shorthand! # :nodoc:
         | 
| 432 | 
            -
                   | 
| 433 | 
            -
                   'line-height', 'font-family'].each do |prop|
         | 
| 432 | 
            +
                  FONT_STYLE_PROPERTIES.each do |prop|
         | 
| 434 433 | 
             
                    return unless @declarations.has_key?(prop)
         | 
| 435 434 | 
             
                  end
         | 
| 436 435 |  | 
| 437 | 
            -
                  new_value =  | 
| 436 | 
            +
                  new_value = String.new
         | 
| 438 437 | 
             
                  ['font-style', 'font-variant', 'font-weight'].each do |property|
         | 
| 439 438 | 
             
                    unless @declarations[property][:value] == 'normal'
         | 
| 440 | 
            -
                      new_value  | 
| 439 | 
            +
                      new_value << @declarations[property][:value] << ' '
         | 
| 441 440 | 
             
                    end
         | 
| 442 441 | 
             
                  end
         | 
| 443 442 |  | 
| 444 | 
            -
                  new_value  | 
| 443 | 
            +
                  new_value << @declarations['font-size'][:value]
         | 
| 445 444 |  | 
| 446 445 | 
             
                  unless @declarations['line-height'][:value] == 'normal'
         | 
| 447 | 
            -
                    new_value  | 
| 446 | 
            +
                    new_value << '/' << @declarations['line-height'][:value]
         | 
| 448 447 | 
             
                  end
         | 
| 449 448 |  | 
| 450 | 
            -
                  new_value  | 
| 449 | 
            +
                  new_value << ' ' << @declarations['font-family'][:value]
         | 
| 451 450 |  | 
| 452 451 | 
             
                  @declarations['font'] = {:value => new_value.gsub(/[\s]+/, ' ').strip}
         | 
| 453 452 |  | 
| 454 | 
            -
                   | 
| 455 | 
            -
                   'line-height', 'font-family'].each do |prop|
         | 
| 456 | 
            -
                   @declarations.delete(prop)
         | 
| 457 | 
            -
                  end
         | 
| 458 | 
            -
             | 
| 453 | 
            +
                  FONT_STYLE_PROPERTIES.each { |prop| @declarations.delete(prop) }
         | 
| 459 454 | 
             
                end
         | 
| 460 455 |  | 
| 461 456 | 
             
                # Looks for long format CSS list-style properties (e.g. <tt>list-style-type</tt>) and
         | 
| @@ -482,7 +477,9 @@ module CssParser | |
| 482 477 | 
             
                      @declarations[dest] = {}
         | 
| 483 478 | 
             
                    end
         | 
| 484 479 | 
             
                  end
         | 
| 485 | 
            -
             | 
| 480 | 
            +
             | 
| 481 | 
            +
                  @declarations[dest] = @declarations[src].dup
         | 
| 482 | 
            +
                  @declarations[dest][:value] = v.to_s.strip
         | 
| 486 483 | 
             
                end
         | 
| 487 484 |  | 
| 488 485 | 
             
                def parse_declarations!(block) # :nodoc:
         | 
| @@ -490,19 +487,18 @@ module CssParser | |
| 490 487 |  | 
| 491 488 | 
             
                  return unless block
         | 
| 492 489 |  | 
| 493 | 
            -
                   | 
| 494 | 
            -
             | 
| 495 | 
            -
                  continuation = ''
         | 
| 490 | 
            +
                  continuation = nil
         | 
| 496 491 | 
             
                  block.split(/[\;$]+/m).each do |decs|
         | 
| 497 | 
            -
                    decs = continuation + decs
         | 
| 492 | 
            +
                    decs = continuation ? continuation + decs : decs
         | 
| 498 493 | 
             
                    if decs =~ /\([^)]*\Z/ # if it has an unmatched parenthesis
         | 
| 499 494 | 
             
                      continuation = decs + ';'
         | 
| 500 495 |  | 
| 501 | 
            -
                    elsif matches = decs.match( | 
| 502 | 
            -
                       | 
| 503 | 
            -
             | 
| 496 | 
            +
                    elsif matches = decs.match(/\s*(.[^:]*)\s*:\s*(.+?)(;?\s*\Z)/i)
         | 
| 497 | 
            +
                      # skip end_of_declaration
         | 
| 498 | 
            +
                      property = matches[1]
         | 
| 499 | 
            +
                      value = matches[2]
         | 
| 504 500 | 
             
                      add_declaration!(property, value)
         | 
| 505 | 
            -
                      continuation =  | 
| 501 | 
            +
                      continuation = nil
         | 
| 506 502 | 
             
                    end
         | 
| 507 503 | 
             
                  end
         | 
| 508 504 | 
             
                end
         | 
| @@ -511,7 +507,11 @@ module CssParser | |
| 511 507 | 
             
                # TODO: way too simplistic
         | 
| 512 508 | 
             
                #++
         | 
| 513 509 | 
             
                def parse_selectors!(selectors) # :nodoc:
         | 
| 514 | 
            -
                  @selectors = selectors.split(',').map  | 
| 510 | 
            +
                  @selectors = selectors.split(',').map do |s|
         | 
| 511 | 
            +
                    s.gsub!(/\s+/, ' ')
         | 
| 512 | 
            +
                    s.strip!
         | 
| 513 | 
            +
                    s
         | 
| 514 | 
            +
                  end
         | 
| 515 515 | 
             
                end
         | 
| 516 516 | 
             
              end
         | 
| 517 517 |  | 
    
        data/lib/css_parser/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: css_parser
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.7.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Alex Dunae
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2019-02-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: addressable
         | 
| @@ -56,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 56 56 | 
             
                  version: '0'
         | 
| 57 57 | 
             
            requirements: []
         | 
| 58 58 | 
             
            rubyforge_project: 
         | 
| 59 | 
            -
            rubygems_version: 2. | 
| 59 | 
            +
            rubygems_version: 2.7.6
         | 
| 60 60 | 
             
            signing_key: 
         | 
| 61 61 | 
             
            specification_version: 4
         | 
| 62 62 | 
             
            summary: Ruby CSS parser.
         |