require 'hpricot'
require 'rest-client'
module Rack
class Gist
def initialize(app, options = {})
@app = app
@gist_path =
@options = {
:jquery => true
}.merge(options)
end
def call(env)
if path(env).match(%r{^/gist\.github\.com})
serve_gist(env)
else
status, headers, body = @app.call(env)
rewrite(status, headers, body)
end
end
private
def rewrite(status, headers, body)
if 'text/html' == headers['Content-Type']
body = [body].flatten
body.map! do |part|
Hpricot(part.to_s).tap do |doc|
extras = false
doc.search('script[@src*="gist.github.com"]').each do |tag|
extras = true
tag['src'].match(regex).tap do |match|
id, file = match[1, 2]
suffix, extra = file ? ["#file_#{file}", "rack-gist-file='#{file}'"] : ['', '']
tag.swap("
")
end
end
if extras
doc.search('head').append(css_html)
doc.search('body').tap do |node|
node.append(jquery_link) if @options[:jquery]
node.append(jquery_helper)
end
end
end.to_s
end
headers['Content-Length'] = body.map { |part| Rack::Utils.bytesize(part) }.inject(0) { |sum, size| sum + size }.to_s
end
[status, headers, body]
end
def serve_gist(env)
gist_id, file = path(env).match(%r{gist\.github\.com/(\d+)(?:/(.*))?\.js})[1,2]
cache = @options[:cache]
gist = (cache ? cache.fetch(cache_key(gist_id, file), :expires_in => 3600) { get_gist(gist_id, file) } : get_gist(gist_id, file)).to_s
[
200,
{
'Content-Type' => 'application/javascript',
'Content-Length' => Rack::Utils.bytesize(gist).to_s
},
[gist]
]
end
def get_gist(gist_id, file)
gist = RestClient.get(gist_url(gist_id, file))
gist = gist.split("\n").reject do |part|
part.empty?
end.last
selector = "#rack-gist-#{gist_id}"
selector << %Q{[rack-gist-file="#{file}"]} if file
gist.sub(/document\.write/, %Q{$('#{selector}').replaceWith})
end
def cache_key(gist_id, file)
key = "rack-gist:#{gist_id}"
key << ":#{file.gsub(/\s/, '')}" unless file.nil?
key
end
def gist_url(gist_id, file)
url = "http://gist.github.com/#{gist_id}.js"
url << "?file=#{file}" unless file.nil?
url
end
def path(env)
Rack::Utils.unescape(env['PATH_INFO'])
end
def regex
@regex ||= %r{gist\.github\.com/(\d+)\.js(?:\?file=(.*))?}
end
def css_html
"\n"
end
def jquery_link
"\n"
end
def jquery_helper
<<-EOJQ
EOJQ
end
end
end