Module: CssParser

### Home Classes Methods

### In Files

- lib/css_parser.rb
- lib/css_parser/parser.rb
- lib/css_parser/regexps.rb
- lib/css_parser/rule_set.rb
- lib/css_parser/version.rb

### Namespace

- CLASS CssParser::CircularReferenceError
- CLASS CssParser::Parser
- CLASS CssParser::RemoteFileError
- CLASS CssParser::RuleSet

### Methods

- ::calculate_specificity
- ::convert_uris
- ::merge
- ::regex_possible_values
- ::sanitize_media_query

### Class/Module Index

Quicksearch

- CssParser
- CssParser::CircularReferenceError
- CssParser::Parser
- CssParser::RemoteFileError
- CssParser::RuleSet

No matching classes.

# CssParser

### Constants

VERSION

### Public Class Methods

calculate_specificity(selector) click to toggle source

Calculates the specificity of a CSS selector per www.w3.org/TR/CSS21/cascade.html#specificity

Returns an integer.

#### Example

    CssParser.calculate_specificity('#content div p:first-line a:link')
    => 114

    # File lib/css_parser.rb, line 122
    def self.calculate_specificity(selector)
      a = 0
      b = selector.scan(/\#/).length
      c = selector.scan(NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX).length
      d = selector.scan(ELEMENTS_AND_PSEUDO_ELEMENTS_RX).length

      (a.to_s + b.to_s + c.to_s + d.to_s).to_i
    rescue
      return 0
    end

convert_uris(css, base_uri) click to toggle source

Make `url()` links absolute.

Takes a block of CSS and returns it with all relative URIs converted to absolute URIs.

"For CSS style sheets, the base URI is that of the style sheet, not that of the source document." per www.w3.org/TR/CSS21/syndata.html#uri

Returns a string.

#### Example

    CssParser.convert_uris("body { background: url('../style/yellow.png?abc=123') };",
                 "http://example.org/style/basic.css").inspect
    => "body { background: url('http://example.org/style/yellow.png?abc=123') };"

    # File lib/css_parser.rb, line 146
    def self.convert_uris(css, base_uri)
      base_uri = Addressable::URI.parse(base_uri) unless base_uri.kind_of?(Addressable::URI)

      css.gsub(URI_RX) do
        uri = $1.to_s
        uri.gsub!(/["']+/, '')
        # Don't process URLs that are already absolute
        unless uri =~ /^[a-z]+\:\/\//
          begin
            uri = base_uri + uri
          rescue; end
        end
        "url('#{uri.to_s}')"
      end
    end

merge(*rule_sets) click to toggle source

Merge multiple CSS RuleSets by cascading according to the CSS 2.1 cascading rules (www.w3.org/TR/REC-CSS2/cascade.html#cascading-order).

Takes one or more RuleSet objects.

Returns a RuleSet.

#### Cascading

If a RuleSet object has its `specificity` defined, that specificity is used in the cascade calculations.

If no specificity is explicitly set and the RuleSet has one selector, the specificity is calculated using that selector.

If no selectors the specificity is treated as 0.

If multiple selectors are present then the greatest specificity is used.

#### Example #1

    rs1 = RuleSet.new(nil, 'color: black;')
    rs2 = RuleSet.new(nil, 'margin: 0px;')

    merged = CssParser.merge(rs1, rs2)

    puts merged
    => "{ margin: 0px; color: black; }"

#### Example #2

    rs1 = RuleSet.new(nil, 'background-color: black;')
    rs2 = RuleSet.new(nil, 'background-image: none;')

    merged = CssParser.merge(rs1, rs2)

    puts merged
    => "{ background: none black; }"

    # File lib/css_parser.rb, line 54
    def self.merge(*rule_sets)
      @folded_declaration_cache = {}

      # in case called like CssParser.merge([rule_set, rule_set])
      rule_sets.flatten! if rule_sets[0].kind_of?(Array)

      unless rule_sets.all? {|rs| rs.kind_of?(CssParser::RuleSet)}
        raise ArgumentError, "all parameters must be CssParser::RuleSets."
      end

      return rule_sets[0] if rule_sets.length == 1

      # Internal storage of CSS properties that we will keep
      properties = {}

      rule_sets.each do |rule_set|
        rule_set.expand_shorthand!

        specificity = rule_set.specificity
        unless specificity
          if rule_set.selectors.length == 0
            specificity = 0
          else
            specificity = rule_set.selectors.map { |s| calculate_specificity(s) }.compact.max || 0
          end
        end

        rule_set.each_declaration do |property, value, is_important|
          # Add the property to the list to be folded per http://www.w3.org/TR/CSS21/cascade.html#cascading-order
          if not properties.has_key?(property)
            properties[property] = {:value => value, :specificity => specificity, :is_important => is_important}
          elsif is_important
            if not properties[property][:is_important] or properties[property][:specificity] <= specificity
              properties[property] = {:value => value, :specificity => specificity, :is_important => is_important}
            end
          elsif properties[property][:specificity] < specificity or properties[property][:specificity] == specificity
            unless properties[property][:is_important]
              properties[property] = {:value => value, :specificity => specificity, :is_important => is_important}
            end
          end
       end
      end

      merged = RuleSet.new(nil, nil)

      properties.each do |property, details|
        if details[:is_important]
          merged[property.strip] = details[:value].strip.gsub(/\;\Z/, '') + '!important'
        else
          merged[property.strip] = details[:value].strip
        end
      end

      merged.create_shorthand!
      merged
    end

regex_possible_values(*values) click to toggle source

    # File lib/css_parser/regexps.rb, line 2
    def self.regex_possible_values *values
      Regexp.new("([\s]*^)?(#{values.join('|')})([\s]*$)?", 'i')
    end

sanitize_media_query(raw) click to toggle source

    # File lib/css_parser.rb, line 162
    def self.sanitize_media_query(raw)
      mq = raw.to_s.gsub(/[\s]+/, ' ').strip
      mq = 'all' if mq.empty?
      mq.to_sym
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.