Class: Inliner::Inline
- Inherits:
-
Object
- Object
- Inliner::Inline
- Defined in:
- lib/inliner.rb
Instance Method Summary collapse
- #asset_contents(uri) ⇒ Object
- #asset_uri(node) ⇒ Object
- #create_data_uri(path, contents) ⇒ Object
- #get_urls(urls) ⇒ Object
-
#initialize(url) ⇒ Inline
constructor
A new instance of Inline.
- #inline ⇒ Object
- #inline_asset(node) ⇒ Object
- #inline_css_assets(contents) ⇒ Object
- #inline_node(contents, node) ⇒ Object
- #to_html ⇒ Object
- #validate_url(url) ⇒ Object
Constructor Details
#initialize(url) ⇒ Inline
Returns a new instance of Inline.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/inliner.rb', line 11 def initialize(url) unless validate_url(url) raise ArgumentError, "#{url} is not a valid URL!" end @assets = {} @url = URI.parse(url) EM.run do http = EM::HttpRequest.new(@url, :connect_timeout => 5, :inactivity_timeout => 10).get :redirects => 1 http.callback { @doc = Nokogiri::HTML(http.response) EM.stop } end end |
Instance Method Details
#asset_contents(uri) ⇒ Object
130 131 132 |
# File 'lib/inliner.rb', line 130 def asset_contents(uri) @assets[uri] || Net::HTTP.get(URI.parse(uri)) end |
#asset_uri(node) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/inliner.rb', line 115 def asset_uri(node) path = case node.name when 'script' node['src'] when 'img' node['src'] when 'link' node['href'] end return false unless path uri = @url + path uri.to_s end |
#create_data_uri(path, contents) ⇒ Object
70 71 72 73 |
# File 'lib/inliner.rb', line 70 def create_data_uri(path, contents) mime = Rack::Mime.mime_type(File.extname(path)) "data:#{Rack::Mime.mime_type(File.extname(path))};base64,#{[contents].pack('m').gsub(/\n/, "")}" end |
#get_urls(urls) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/inliner.rb', line 79 def get_urls(urls) assets = {} EventMachine.run do multi = EventMachine::MultiRequest.new urls.uniq.each_with_index do |url, idx| begin http = EventMachine::HttpRequest.new(url, :connect_timeout => 1) req = http.get :redirects => 1 rescue URI::InvalidURIError(e) p e.backtrace end multi.add url, req end multi.callback do multi.responses[:callback].each do |idx, r| #p idx assets[idx] = r.response end EventMachine.stop end end assets end |
#inline ⇒ Object
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/inliner.rb', line 104 def inline assets = @doc.css('img') + @doc.css('link[rel="stylesheet"][href]') + @doc.css('script[src]') urls = assets.map {|node| asset_uri(node)} @assets = get_urls urls assets.each do |node| inline_asset node end to_html end |
#inline_asset(node) ⇒ Object
31 32 33 34 35 36 |
# File 'lib/inliner.rb', line 31 def inline_asset(node) contents = asset_contents(asset_uri(node)) return if !contents node.before inline_node(contents, node) node.remove end |
#inline_css_assets(contents) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/inliner.rb', line 54 def inline_css_assets(contents) css_urls = Hash[contents.scan(/url\([\'"]?(.+?)[\'"]?\)/).map { |u| uri = @url + u[0] [u[0], uri.to_s] }] unless css_urls.empty? get_urls(css_urls.values) css_urls.each do |path, full| data_uri = create_data_uri(path, asset_contents(full)) contents = contents.gsub(path, data_uri) end end contents end |
#inline_node(contents, node) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/inliner.rb', line 38 def inline_node(contents, node) case node.name when 'img' inline = node.clone inline['src'] = create_data_uri(asset_uri(node), contents) inline['alt'] = node['alt'] if node['alt'] when 'link' inline = Nokogiri::XML::Node.new 'style', @doc inline.content = inline_css_assets(contents) else inline = Nokogiri::XML::Node.new node.name, @doc inline.content = contents end inline end |
#to_html ⇒ Object
75 76 77 |
# File 'lib/inliner.rb', line 75 def to_html return @doc.to_s end |
#validate_url(url) ⇒ Object
27 28 29 |
# File 'lib/inliner.rb', line 27 def validate_url(url) !(url =~ URI::regexp).nil? end |