shutterbug 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -6,7 +6,13 @@
6
6
  A rack utility that will create and save images (pngs) from parts of your html's documents current dom. These images become available as public png resources in the rack application. Currently shutterbug supports HTML, SVG and Canvas elements.
7
7
 
8
8
 
9
- use Shutterbug::Rackapp
9
+ use Shutterbug::Rackapp do |config|
10
+ conf.resource_dir = "/Users/npaessel/tmp"
11
+ config.uri_prefix = "http://localhost:9292"
12
+ config.path_prefix = "/shutterbug"
13
+ end
14
+
15
+ Configuration options default to reasonable defaults.
10
16
 
11
17
 
12
18
  ## Installation
@@ -0,0 +1,22 @@
1
+ module Shutterbug
2
+ class BugFile
3
+ def initialize(filename)
4
+ @filename = filename
5
+ end
6
+
7
+ def open
8
+ @stream_file = File.open(@filename, 'r')
9
+ @stream_file.rewind
10
+ end
11
+
12
+ def each(&blk)
13
+ @stream_file.each(&blk)
14
+ ensure
15
+ @stream_file.close
16
+ end
17
+
18
+ def size
19
+ @stream_file.size
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,55 @@
1
+ module Shutterbug
2
+ class Configuration
3
+
4
+ attr_accessor :uri_prefix
5
+ attr_accessor :path_prefix
6
+ attr_accessor :resource_dir
7
+
8
+ def self.instance(opts={})
9
+ return @instance || @instance = self.new(opts)
10
+ end
11
+
12
+ def initialize(opts={})
13
+ self.uri_prefix = opts[:uri_prefix] || ""
14
+ self.path_prefix = opts[:path_prefix] || "/shutterbug"
15
+ self.resource_dir = opts[:resource_dir] || Dir.tmpdir
16
+ end
17
+
18
+ def js_path
19
+ "#{uri_prefix}#{path_prefix}/shutterbug.js"
20
+ end
21
+
22
+ def js_regex
23
+ /#{path_prefix}\/shutterbug.js/
24
+ end
25
+
26
+ def js_file
27
+ File.join(File.dirname(__FILE__),"shutterbug.js")
28
+ end
29
+
30
+ def convert_path
31
+ "#{uri_prefix}#{path_prefix}/make_snapshot"
32
+ end
33
+ def convert_regex
34
+ /#{path_prefix}\/make_snapshot/
35
+ end
36
+
37
+ def png_path(sha='')
38
+ "#{uri_prefix}#{path_prefix}/get_png/#{sha}"
39
+ end
40
+ def png_regex
41
+ /#{path_prefix}\/get_png\/([^\/]+)/
42
+ end
43
+
44
+ def html_path(sha='')
45
+ "#{uri_prefix}#{path_prefix}/get_html/#{sha}"
46
+ end
47
+ def html_regex
48
+ /#{path_prefix}\/get_html\/([^\/]+)/
49
+ end
50
+
51
+ def base_url(req)
52
+ req.POST()['base_url'] || req.referrer || "#{req.scheme}://#{req.host_with_port}"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module Shutterbug
2
+ class HtmlFile < BugFile; end
3
+ end
@@ -0,0 +1,11 @@
1
+ module Shutterbug
2
+ class JsFile < BugFile
3
+ def initialize(_config=Configuration.instance())
4
+ @config = _config
5
+ @javascript = File.read(@config.js_file).gsub(/CONVERT_PATH/,@config.convert_path)
6
+ end
7
+ def open
8
+ @stream_file = StringIO.new(@javascript)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,70 @@
1
+ module Shutterbug
2
+ class PhantomJob
3
+
4
+ attr_accessor :png_file
5
+ attr_accessor :html_file
6
+
7
+ def program
8
+ 'phantomjs'
9
+ end
10
+
11
+ def rasterize_js
12
+ File.join(File.dirname(__FILE__),'rasterize.js')
13
+ end
14
+
15
+ def initialize(base_url, html, css="", width=1000, height=700)
16
+ @base_url = base_url
17
+ @html = html
18
+ @css = css
19
+ @width = width
20
+ @height = height
21
+ end
22
+
23
+ def cache_key
24
+ return @key || @key = Digest::SHA1.hexdigest("#{@html}#{@css}#{@base_url}")[0..10]
25
+ end
26
+
27
+ def document
28
+ date = Time.now.strftime("%Y-%m-%d (%I:%M%p)")
29
+ """
30
+ <!DOCTYPE html>
31
+ <html>
32
+ <head>
33
+ <base href='#{@base_url}'>
34
+ <meta content='text/html;charset=utf-8' http-equiv='Content-Type'>
35
+ <title>content from #{@base_url} #{date}</title>
36
+ #{@css}
37
+ </head>
38
+ <body>
39
+ #{@html}
40
+ </body>
41
+ </html>
42
+ """
43
+ end
44
+
45
+ def base_path
46
+ Configuration.instance.resource_dir
47
+ end
48
+
49
+ def infilename
50
+ File.join(base_path,"phantom_#{cache_key}.html")
51
+ end
52
+
53
+ def outfilename
54
+ File.join(base_path,"phantom_#{cache_key}.png")
55
+ end
56
+
57
+ def rasterize_cl
58
+ %x[#{self.program} #{self.rasterize_js} #{self.infilename} #{self.outfilename} #{@width}*#{@height}]
59
+ end
60
+
61
+ def rasterize
62
+ infile = File.open(infilename, 'w') do |f|
63
+ f.write(document)
64
+ end
65
+ rasterize_cl()
66
+ self.png_file = PngFile.new(outfilename)
67
+ self.html_file = HtmlFile.new(infilename)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Shutterbug
2
+ class PngFile < BugFile; end
3
+ end
@@ -2,52 +2,36 @@
2
2
 
3
3
  module Shutterbug
4
4
  class Rackapp
5
- BASE_PATH = "/shutterbug"
6
5
 
7
- CONVERT_PATH = "#{BASE_PATH}/make_snapshot"
8
- CONVERT_REGEX = /#{CONVERT_PATH}/
9
-
10
- PNG_PATH = "#{BASE_PATH}/get_png"
11
- GET_PNG_REGEX = /#{PNG_PATH}\/([^\/]+)/
12
-
13
- HTML_PATH = "#{BASE_PATH}/get_html"
14
- GET_HTML_REGEX = /#{HTML_PATH}\/([^\/]+)/
15
-
16
- JS_PATH = "#{BASE_PATH}/shutterbug.js"
17
- JS_REGEX = /#{JS_PATH}$/
18
-
19
- def initialize app
6
+ def initialize(app, &block)
7
+ @config = Configuration.instance
8
+ yield @config if block_given?
20
9
  @app = app
21
- @shutterbug = Service.new()
10
+ @shutterbug = Service.new(@config)
22
11
  log "initialized"
23
12
  end
24
13
 
25
- def base_url(req)
26
- req.POST()['base_url'] || req.referrer || "#{req.scheme}://#{req.host_with_port}"
27
- end
28
-
29
14
  def do_convert(req)
30
15
  html = req.POST()['content'] || ""
31
16
  width = req.POST()['width'] || 1000
32
17
  height = req.POST()['height'] || 700
33
18
  css = req.POST()['css'] || ""
34
19
 
35
- signature = @shutterbug.convert(base_url(req), html, css, width, height)
36
- response_url = "#{PNG_PATH}/#{signature}"
37
- response_text = "<img src='#{response_url}' alt='#{signature}'>"
20
+ signature = @shutterbug.convert(@config.base_url(req), html, css, width, height)
21
+ response_text = "<img src='#{@config.png_path(signature)}' alt='#{signature}'>"
38
22
  return good_response(response_text,'text/plain')
39
23
  end
40
24
 
41
25
  def call env
42
26
  req = Rack::Request.new(env)
43
27
  case req.path
44
- when CONVERT_REGEX
28
+ when @config.convert_regex
45
29
  do_convert(req)
46
- when GET_PNG_REGEX
30
+ when @config.png_regex
47
31
  good_response(@shutterbug.get_png_file($1),'image/png')
48
- when GET_HTML_REGEX
32
+ when @config.html_regex
49
33
  good_response(@shutterbug.get_html_file($1),'text/html')
50
- when JS_PATH
34
+ when @config.js_regex
51
35
  good_response(@shutterbug.get_shutterbug_file, 'application/javascript')
52
36
  else
53
37
  skip(env)
@@ -1,87 +1,21 @@
1
1
  require 'stringio'
2
2
  module Shutterbug
3
3
  class Service
4
- class RackFile
5
- def initialize(file)
6
- @stream_file = file
7
- end
8
-
9
- def open
10
- @stream_file.open
11
- @stream_file.rewind
12
- end
13
-
14
- def each(&blk)
15
- @stream_file.each(&blk)
16
- ensure
17
- @stream_file.close
18
- end
19
-
20
- def size
21
- @stream_file.size
22
- end
23
- end
24
-
25
- class PngFile < RackFile; end
26
- class HtmlFile < RackFile; end
27
-
28
- class JSFile < RackFile
29
- def initialize(_filename)
30
- @javascript = File.read(_filename).gsub(/CONVERT_PATH/,Shutterbug::Rackapp::CONVERT_PATH)
31
- end
32
- def open
33
- @stream_file = StringIO.new(@javascript)
34
- end
35
- end
36
-
37
-
38
- PROGRAM = 'phantomjs'
39
- RASTERIZE_JS = File.join(File.dirname(__FILE__),'rasterize.js')
40
- SHUTTERBUG_JS = File.join(File.dirname(__FILE__),'shutterbug.js')
41
4
 
42
- def document(html, css, url_base)
43
- date = Time.now.strftime("%Y-%m-%d (%I:%M%p)")
44
- """
45
- <!DOCTYPE html>
46
- <html>
47
- <head>
48
- <base href='#{url_base}'>
49
- <meta content='text/html;charset=utf-8' http-equiv='Content-Type'>
50
- <title>png from #{url_base} #{date}</title>
51
- #{css}
52
- </head>
53
- <body>
54
- #{html}
55
- </body>
56
- </html>
57
- """
58
- end
59
-
60
- def initialize
5
+ def initialize(_config = Configuration.instance)
61
6
  @file_cache = {}
62
- @js_file = JSFile.new(SHUTTERBUG_JS)
7
+ @config = _config
8
+ @js_file = JsFile.new()
63
9
  end
64
10
 
65
11
  def convert(base_url, html, css="", width=1000, height=700)
66
- html_content = document(html, css, base_url)
67
- signature = Digest::SHA1.hexdigest(html_content)[0..10]
68
- return signature if @file_cache[signature]
69
-
70
- infile = Tempfile.new(['phantom_page','.html'])
71
- infile_name = infile.path
72
-
73
- outfile = Tempfile.new(['phantom_render','.png'])
74
- outfile_name = outfile.path
75
-
76
- begin
77
- infile.write(html_content)
78
- infile.rewind
79
- %x[#{PROGRAM} #{RASTERIZE_JS} #{infile_name} #{outfile_name} #{width}*#{height}]
80
- @file_cache[signature] = {'png' => PngFile.new(outfile), 'html' => HtmlFile.new(infile) }
81
- ensure
82
- infile.close
12
+ job = PhantomJob.new(base_url, html, css, width, height)
13
+ key = job.cache_key
14
+ unless (@file_cache[key])
15
+ job.rasterize
16
+ @file_cache[key] = {'html' => job.html_file, 'png' => job.png_file }
83
17
  end
84
- return signature
18
+ return key
85
19
  end
86
20
 
87
21
  def get_png_file(sha)
data/lib/shutterbug.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  module Shutterbug
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.6"
3
3
  autoload :Service, "shutterbug/service"
4
4
  autoload :Rackapp, "shutterbug/rackapp"
5
+ autoload :Configuration, "shutterbug/configuration"
6
+ autoload :BugFile, "shutterbug/bug_file"
7
+ autoload :HtmlFile, "shutterbug/html_file"
8
+ autoload :PngFile, "shutterbug/png_file"
9
+ autoload :JsFile, "shutterbug/js_file"
10
+ autoload :PhantomJob, "shutterbug/phantom_job"
5
11
  end
@@ -6,11 +6,13 @@ RSpec::Matchers.define :be_happy_response do |filetype|
6
6
  end
7
7
 
8
8
  describe Shutterbug::Rackapp do
9
- let(:sha) { "542112e" }
10
- let(:size) { 200 }
11
- let(:rackfile){ mock :fackfile, :size => size }
12
- let(:service) { mock :service }
13
- let(:app) { mock :app }
9
+ let(:sha) { "542112e" }
10
+ let(:size) { 200 }
11
+ let(:rackfile){ mock :fackfile, :size => size }
12
+ let(:service) { mock :service }
13
+ let(:app) { mock :app }
14
+ let(:config) { Shutterbug::Configuration.instance }
15
+
14
16
  let(:post_data) do
15
17
  {
16
18
  'content' => "<div class='foo'>foo!</div>",
@@ -20,6 +22,7 @@ describe Shutterbug::Rackapp do
20
22
  'base_url' => "http://localhost:8080/"
21
23
  }
22
24
  end
25
+
23
26
  subject { Shutterbug::Rackapp.new(app) }
24
27
 
25
28
  before(:each) do
@@ -46,7 +49,7 @@ describe Shutterbug::Rackapp do
46
49
  end
47
50
 
48
51
  describe "convert route" do
49
- let(:path) { Shutterbug::Rackapp::CONVERT_PATH }
52
+ let(:path) { config.convert_path }
50
53
  let(:image_response) { mock :image_response }
51
54
  it "should route #do_convert" do
52
55
  subject.should_receive(:do_convert, :with => req).and_return image_response
@@ -55,7 +58,7 @@ describe Shutterbug::Rackapp do
55
58
  end
56
59
 
57
60
  describe "get png route" do
58
- let(:path) { "#{Shutterbug::Rackapp::PNG_PATH}/#{sha}" }
61
+ let(:path) { config.png_path(sha) }
59
62
  it "should route #do_get_png" do
60
63
  service.should_receive(:get_png_file, :with => sha).and_return rackfile
61
64
  subject.call(mock).should be_happy_response('image/png')
@@ -63,7 +66,7 @@ describe Shutterbug::Rackapp do
63
66
  end
64
67
 
65
68
  describe "get html route" do
66
- let(:path) { "#{Shutterbug::Rackapp::HTML_PATH}/#{sha}" }
69
+ let(:path) { config.html_path(sha) }
67
70
  it "should route #do_get_html" do
68
71
  service.should_receive(:get_html_file, :with => sha).and_return rackfile
69
72
  subject.call(mock).should be_happy_response('text/html')
@@ -71,7 +74,7 @@ describe Shutterbug::Rackapp do
71
74
  end
72
75
 
73
76
  describe "get shutterbug javascipt route" do
74
- let(:path) { "#{Shutterbug::Rackapp::JS_PATH}" }
77
+ let(:path) { config.js_path }
75
78
  it "should route #do_get_shutterbug" do
76
79
  service.should_receive(:get_shutterbug_file).and_return rackfile
77
80
  subject.call(mock).should be_happy_response('application/javascript')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shutterbug
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-21 00:00:00.000000000 Z
12
+ date: 2013-06-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -112,6 +112,12 @@ files:
112
112
  - README.md
113
113
  - Rakefile
114
114
  - lib/shutterbug.rb
115
+ - lib/shutterbug/bug_file.rb
116
+ - lib/shutterbug/configuration.rb
117
+ - lib/shutterbug/html_file.rb
118
+ - lib/shutterbug/js_file.rb
119
+ - lib/shutterbug/phantom_job.rb
120
+ - lib/shutterbug/png_file.rb
115
121
  - lib/shutterbug/rackapp.rb
116
122
  - lib/shutterbug/rasterize.js
117
123
  - lib/shutterbug/service.rb
@@ -134,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
134
140
  version: '0'
135
141
  segments:
136
142
  - 0
137
- hash: 2066388252220893222
143
+ hash: -488192167171583670
138
144
  required_rubygems_version: !ruby/object:Gem::Requirement
139
145
  none: false
140
146
  requirements:
@@ -143,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
149
  version: '0'
144
150
  segments:
145
151
  - 0
146
- hash: 2066388252220893222
152
+ hash: -488192167171583670
147
153
  requirements: []
148
154
  rubyforge_project:
149
155
  rubygems_version: 1.8.23