Class: ContentUrls::CssParser

Inherits:
Object
  • Object
show all
Defined in:
lib/content_urls/parsers/css_parser.rb

Overview

CssParser finds and rewrites URLs in CSS content.

Implementation note:

This methods in this class identify URLs by using regular expressions based on the W3C CSS 2.1 Specification (www.w3.org/TR/CSS21/syndata.html).

Class Method Summary collapse

Class Method Details

.rewrite_each_url(content, &block) ⇒ Object

Rewrites each URL in the CSS content by calling the supplied block with each URL.

Examples:

Rewrite URLs in CSS code

css = 'body { background: url(/images/rainbows.jpg) }'
css = ContentUrls::CssParser.rewrite_each_url(css) {|url| url.sub(/rainbows.jpg/, 'unicorns.jpg')}
puts "Rewritten: #{css}"
# => "Rewritten: body { background: url(/images/unicorns.jpg) }"

Parameters:

  • content (String)

    the CSS content.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/content_urls/parsers/css_parser.rb', line 40

def self.rewrite_each_url(content, &block)
  urls = {}
  parser = ::CssParser::Parser.new
  parser.load_string!(content)
  parser.each_selector do |selector|
    parser[selector].each do |element|
      remaining = element
      while !remaining.empty?
        if match = @@regex_uri.match(remaining)
          urls[match[:url]] = match[:uri]
          remaining = match.post_match
        else
          remaining = ''
        end
      end
    end
  end
  rewritten_content = [{:content => content, :is_rewritten => false}]
  urls.each do |property_value, url|
    rewritten_url = yield url
    if rewritten_url != url
      rewritten_property_value = property_value.dup
      rewritten_property_value[url] = rewritten_url
      i = 0
      while i < rewritten_content.count
        if !rewritten_content[i][:is_rewritten]
          if match = /#{Regexp.escape(property_value)}/.match(rewritten_content[i][:content])
            if match.pre_match.length > 0
              rewritten_content.insert(i, {:content => match.pre_match, :is_rewritten => false})
              i += 1
            end
            rewritten_content[i] = {:content => rewritten_property_value, :is_rewritten => true}
            if match.post_match.length > 0
              rewritten_content.insert(i+1, {:content => match.post_match, :is_rewritten => false})
            end
          end
        end
        i += 1
      end
    end
  end
  rewritten_content.map { |c| c[:content]}.join
end

.urls(content) ⇒ Array

Returns the URLs found in the CSS content.

Examples:

Parse CSS code for URLs

css = 'body { background: url(/images/rainbows.jpg) }'
ContentUrls::CssParser.urls(css).each do |url|
  puts "Found URL: #{url}"
end
# => "Found URL: /images/rainbows.jpg"

Parameters:

  • content (String)

    the CSS content.

Returns:

  • (Array)

    the unique URLs found in the content.



23
24
25
26
27
28
# File 'lib/content_urls/parsers/css_parser.rb', line 23

def self.urls(content)
  urls = []
  rewrite_each_url(content) { |url| urls << url; url }
  urls.uniq!
  urls
end