img-kit 1.3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 06110885384e166f0c19be2cd296d9259c88487c
4
+ data.tar.gz: a5c794145d084b19878bf91625c23ed3cd0ab7af
5
+ SHA512:
6
+ metadata.gz: 1fd97dddc1a97022742b2cb9f2638f8035d0f3bb712358faa9a57afbe17774ba74d7158527c42c60b5e1a14ffa83804d8fce3f15b6dec7b8cc00cf38a712b70b
7
+ data.tar.gz: c08b9f4b965e74d72a71809d53c428729ddc9666399220e79d7f1ae632ebc3c28e55a93009035b0670a65e8ede5ed35342c7a70263fe9b5bbdae2865c06c89d2
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,6 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ test.sh
5
+ .rvmrc
6
+ vendor
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "rake"
7
+ gem "rspec", "~> 2"
8
+ gem "rspec-core", "~> 2"
9
+ gem "mocha"
10
+ gem "rack"
11
+ gem "ruby-debug19", :platforms => :mri_19
12
+ gem "ruby-debug", :platforms => :mri_18
13
+ end
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ img-kit (1.3.9.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ archive-tar-minitar (0.5.2)
10
+ columnize (0.3.4)
11
+ diff-lcs (1.1.2)
12
+ linecache (0.46)
13
+ rbx-require-relative (> 0.0.4)
14
+ linecache19 (0.5.12)
15
+ ruby_core_source (>= 0.1.4)
16
+ mocha (0.9.12)
17
+ rack (1.3.0)
18
+ rake (0.9.2.2)
19
+ rbx-require-relative (0.0.5)
20
+ rspec (2.6.0)
21
+ rspec-core (~> 2.6.0)
22
+ rspec-expectations (~> 2.6.0)
23
+ rspec-mocks (~> 2.6.0)
24
+ rspec-core (2.6.4)
25
+ rspec-expectations (2.6.0)
26
+ diff-lcs (~> 1.1.2)
27
+ rspec-mocks (2.6.0)
28
+ ruby-debug (0.10.4)
29
+ columnize (>= 0.1)
30
+ ruby-debug-base (~> 0.10.4.0)
31
+ ruby-debug-base (0.10.4)
32
+ linecache (>= 0.3)
33
+ ruby-debug-base19 (0.11.25)
34
+ columnize (>= 0.3.1)
35
+ linecache19 (>= 0.5.11)
36
+ ruby_core_source (>= 0.1.4)
37
+ ruby-debug19 (0.11.6)
38
+ columnize (>= 0.3.1)
39
+ linecache19 (>= 0.5.11)
40
+ ruby-debug-base19 (>= 0.11.19)
41
+ ruby_core_source (0.1.5)
42
+ archive-tar-minitar (>= 0.5.2)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ img-kit!
49
+ mocha
50
+ rack
51
+ rake
52
+ rspec (~> 2)
53
+ rspec-core (~> 2)
54
+ ruby-debug
55
+ ruby-debug19
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ This is a derivative work.
2
+
3
+ Original Copyright (c) 2009 jdpace
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,12 @@
1
+ ******************************************************************
2
+
3
+ Now install wkhtmltoimage binaries:
4
+ Global: sudo `which imgkit` --install-wkhtmltoimage
5
+ rvmsudo imgkit --install-wkhtmltoimage
6
+ (installs to default /usr/local/bin/wkhtmltoimage)
7
+
8
+ inside RVM folder: export TO=`which imgkit | sed 's:/imgkit:/wkhtmltoimage:'` && imgkit --install-wkhtmltoimage
9
+ (you'll have to configure the location of the binary if you do this!)
10
+
11
+ (run imgkit --help to see more options)
12
+ ******************************************************************
@@ -0,0 +1,15 @@
1
+ # IMGKit
2
+
3
+ Cloned from [csquared](http://github.com/csquared/IMGKit) to fix these bugs:
4
+
5
+ 1. Don't **spawn** new `wkhtmltoimage` and continue execution: wait for them to terminate!
6
+
7
+ 2. Recognize that `TempFile` is a file.
8
+
9
+ The problem with 1. was that, while `wkhtmltoimage` was still running, the
10
+ (only partially) rendered image was being uploaded to S3, causing broken images.
11
+
12
+ The problem with 2. was that, since `wkhtmltoimage` [does not work with HTML in STDIN](http://code.google.com/p/wkhtmltopdf/issues/detail?id=534),
13
+ the HTML must be stored in a temporary file, and the original IMGKit thinks that
14
+ [Tempfile instances are not files](https://github.com/csquared/IMGKit/blob/master/lib/imgkit/source.rb#L14).
15
+
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+ Bundler.require
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Default: run specs.'
7
+ task :default => :spec
8
+
9
+ desc "Run specs"
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
12
+ # Put spec opts in a file named .rspec in root
13
+ end
14
+
15
+ task :specs => :spec
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'optparse'
4
+ require 'rbconfig'
5
+ require 'open-uri'
6
+ require 'imgkit/configuration'
7
+ require 'imgkit/version'
8
+
9
+ GOOGLE_CODE_URL = ENV['GOOGLE_CODE_URL'] || "http://code.google.com/p/wkhtmltopdf/downloads/list?can=1"
10
+
11
+ def detect_architecture
12
+ case arch = Config::CONFIG['arch']
13
+ when /x86_64-linux/i
14
+ 'amd64'
15
+ when /linux/i
16
+ 'i386'
17
+ when /darwin/i
18
+ 'OSX'
19
+ else
20
+ cant_find_binaries(arch)
21
+ end
22
+ end
23
+
24
+ def cant_find_binaries(arch)
25
+ puts "Sorry, I couldn't find the binary for your architecture (#{arch}) \n at #{GOOGLE_CODE_URL}"
26
+ puts "Please go to that page, unzip the appropriate binary, and install"
27
+ exit(1)
28
+ end
29
+
30
+ def cleanup(install_to)
31
+ `rm -rf wkhtmltoimage*` rescue nil
32
+ `rm #{install_to}` rescue nil
33
+ end
34
+
35
+ def download_wkhtmltoimage(arch)
36
+ if ENV['BZIP']
37
+ download = "wkhtmltoimage-0.10.0_beta4-static-#{arch}.tar.bz2"
38
+ url = "http://wkhtmltopdf.googlecode.com/files/wkhtmltoimage-0.10.0_beta4-static-#{arch}.tar.bz2"
39
+ else
40
+ page = open(GOOGLE_CODE_URL).read
41
+ download = page.match(/href=".*name=(.*wkhtmltoimage-.*#{arch}.*?)&/) or cant_find_binaries(arch)
42
+ download = download[1]
43
+ url = "http://wkhtmltopdf.googlecode.com/files/#{download}"
44
+ end
45
+ puts "Downloading #{download} from #{url}"
46
+
47
+ `curl #{url} > #{download}`
48
+ download
49
+ end
50
+
51
+ def install(download, arch, install_to)
52
+ puts "Installing #{download} to #{install_to}"
53
+ if download =~ /.tar.bz2$/
54
+ `tar xjvf #{download}`
55
+ `mv wkhtmltoimage #{install_to}`
56
+ elsif download =~ /.tar.lzma$/
57
+ raise "couldn't extract archive: lzcat not found" unless system("which lzcat > /dev/null 2>/dev/null")
58
+ puts "Warning: lzcat is broken on Ubuntu. Re-run with --use-bzip to install alternate version"
59
+ `lzcat #{download} | tar x`
60
+ `mv wkhtmltoimage-#{arch} #{install_to}`
61
+ else
62
+ `mv #{download} #{install_to}`
63
+ end
64
+ `chmod +x #{install_to}`
65
+ end
66
+
67
+ @command = Proc.new { puts "Nothing to do: use --help"}
68
+
69
+ OptionParser.new do |parser|
70
+ parser.banner = "IMGKit\n\nOptions are:"
71
+
72
+ parser.on("--use-bzip", "Force bzip download for Ubuntu because lzcat is broken") do
73
+ ENV['BZIP'] = 'true'
74
+ end
75
+
76
+ parser.on("--install-wkhtmltoimage", "Install wkhtmltoimage binaries (TO=/usr/local/bin ARCHITECTURE=i386)") do
77
+ @command = Proc.new do
78
+ architecture = ENV['ARCHITECTURE'] || detect_architecture
79
+ install_to = ENV['TO'] ? ENV['TO']+'/wkhtmltoimage' : IMGKit.configuration.wkhtmltoimage
80
+
81
+ Dir.chdir '/tmp'
82
+
83
+ cleanup(install_to)
84
+ download = download_wkhtmltoimage(architecture)
85
+ install(download, architecture, install_to)
86
+ end
87
+ end
88
+
89
+ parser.on("--version", "Show Version.") do
90
+ @command = Proc.new do
91
+ puts IMGKit::VERSION
92
+ end
93
+ end
94
+
95
+ parser.on("-h", "--help", "Show this.") { puts parser; exit }
96
+ end.parse!
97
+
98
+ @command.call
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "imgkit/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "img-kit"
7
+ s.version = IMGKit::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["csquared"]
10
+ s.email = %q{christopher.continanza@gmail.com}
11
+ s.homepage = "http://github.com/topspin/imgkit"
12
+ s.summary = %q{HTML+CSS -> JPG}
13
+ s.description = %q{Uses wkhtmltoimage to create Images using HTML}
14
+ s.post_install_message = File.read('POST_INSTALL')
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'open3'
3
+ require 'imgkit/source'
4
+ require 'imgkit/imgkit'
5
+ require 'imgkit/configuration'
6
+ require 'imgkit/version'
@@ -0,0 +1,35 @@
1
+ class IMGKit
2
+ class Configuration
3
+ attr_accessor :meta_tag_prefix, :wkhtmltoimage, :default_options, :default_format
4
+
5
+ def initialize
6
+ @meta_tag_prefix = 'imgkit-'
7
+ @default_options = {:height => 1000}
8
+ @default_format = :jpg
9
+ @wkhtmltoimage ||= (defined?(Bundler::GemfileError) ? `bundle exec which wkhtmltoimage` : `which wkhtmltoimage`).chomp
10
+ @wkhtmltoimage = '/usr/local/bin/wkhtmltoimage' if @wkhtmltoimage.strip.empty? # Fallback
11
+ end
12
+ end
13
+
14
+ class << self
15
+ attr_accessor :configuration
16
+ end
17
+
18
+ # Configure IMGKit someplace sensible,
19
+ # like config/initializers/imgkit.rb
20
+ #
21
+ # @example
22
+ # IMGKit.configure do |config|
23
+ # config.wkhtmltoimage = '/usr/bin/wkhtmltoimage'
24
+ # end
25
+
26
+ def self.configuration
27
+ @configuration ||= Configuration.new
28
+ end
29
+
30
+
31
+ def self.configure
32
+ self.configuration
33
+ yield(configuration)
34
+ end
35
+ end
@@ -0,0 +1,199 @@
1
+ class IMGKit
2
+ KNOWN_FORMATS = [:jpg, :jpeg, :png, :tiff, :tif]
3
+
4
+ class NoExecutableError < StandardError
5
+ def initialize
6
+ msg = "No wkhtmltoimage executable found at #{IMGKit.configuration.wkhtmltoimage}\n"
7
+ msg << ">> Install wkhtmltoimage by hand or try running `imgkit --install-wkhtmltoimage`"
8
+ super(msg)
9
+ end
10
+ end
11
+
12
+ class ImproperSourceError < StandardError
13
+ def initialize(msg)
14
+ super("Improper Source: #{msg}")
15
+ end
16
+ end
17
+
18
+ class CommandFailedError < RuntimeError
19
+ attr_reader :command, :stderr
20
+ def initialize(command, stderr)
21
+ @command = command
22
+ @stderr = stderr
23
+ super("Command failed: #{command}: #{stderr}")
24
+ end
25
+ end
26
+
27
+ class UnknownFormatError < StandardError
28
+ def initialize(format)
29
+ super("Unknown Format: #{format}")
30
+ end
31
+ end
32
+
33
+ attr_accessor :source, :stylesheets
34
+ attr_reader :options
35
+
36
+ def initialize(url_file_or_html, options = {})
37
+ @source = Source.new(url_file_or_html)
38
+
39
+ @stylesheets = []
40
+
41
+ @options = IMGKit.configuration.default_options.merge(options)
42
+ @options.merge! find_options_in_meta(url_file_or_html) unless source.url?
43
+
44
+ raise NoExecutableError.new unless File.exists?(IMGKit.configuration.wkhtmltoimage)
45
+ end
46
+
47
+ def command
48
+ args = [executable]
49
+ args += normalize_options(@options).to_a.flatten.compact
50
+
51
+ if @source.html?
52
+ html_file = Tempfile.open ['file', '.html']
53
+ html_file.write @source.to_s
54
+ html_file.close
55
+ args << html_file.path
56
+ else
57
+ args << @source.to_s
58
+ end
59
+
60
+ args << '-' # Read IMG from stdout
61
+ args
62
+ end
63
+
64
+ def executable
65
+ default = IMGKit.configuration.wkhtmltoimage
66
+ return default if default !~ /^\// # its not a path, so nothing we can do
67
+ if File.exist?(default)
68
+ default
69
+ else
70
+ default.split('/').last
71
+ end
72
+ end
73
+
74
+ if Open3.respond_to? :capture3
75
+ def capture3(*opts)
76
+ Open3.capture3 *opts
77
+ end
78
+ else
79
+ # Lifted from ruby 1.9.2-p290 sources for ruby 1.8 compatibility
80
+ # and modified to work on 1.8
81
+ def capture3(*cmd, &block)
82
+ if Hash === cmd.last
83
+ opts = cmd.pop.dup
84
+ else
85
+ opts = {}
86
+ end
87
+
88
+ stdin_data = opts.delete(:stdin_data) || ''
89
+ binmode = opts.delete(:binmode)
90
+
91
+ Open3.popen3(*cmd) {|i, o, e|
92
+ if binmode
93
+ i.binmode
94
+ o.binmode
95
+ e.binmode
96
+ end
97
+ out_reader = Thread.new { o.read }
98
+ err_reader = Thread.new { e.read }
99
+ i.write stdin_data
100
+ i.close
101
+ [out_reader.value, err_reader.value]
102
+ }
103
+ end
104
+ end
105
+
106
+ def to_img(format = nil)
107
+ append_stylesheets
108
+ set_format(format)
109
+
110
+ result = `#{command.join ' '}`
111
+ result.force_encoding("ASCII-8BIT") if result.respond_to? :force_encoding
112
+
113
+ raise CommandFailedError.new(command.join(' '), '') if result.size == 0
114
+ result
115
+ end
116
+
117
+ def to_file(path)
118
+ format = File.extname(path).gsub(/^\./,'').to_sym
119
+ set_format(format)
120
+ File.open(path,'w:ASCII-8BIT') {|file| file << self.to_img}
121
+ end
122
+
123
+ def method_missing(name, *args, &block)
124
+ if(m = name.to_s.match(/^to_(\w+)/))
125
+ self.send(:to_img, m[1].to_sym)
126
+ else
127
+ super
128
+ end
129
+ end
130
+
131
+ protected
132
+
133
+ def find_options_in_meta(body)
134
+ imgkit_meta_tags(body).inject({}) do |found, tag|
135
+ name = tag.attributes["name"].sub(/^#{IMGKit.configuration.meta_tag_prefix}/, '').to_sym
136
+ found.merge(name => tag.attributes["content"])
137
+ end
138
+ end
139
+
140
+ def imgkit_meta_tags(body)
141
+ require 'rexml/document'
142
+ xml_body = REXML::Document.new(body)
143
+ found = []
144
+ xml_body.elements.each("html/head/meta") do |tag|
145
+ found << tag if tag.attributes['name'].to_s =~ /^#{IMGKit.configuration.meta_tag_prefix}/
146
+ end
147
+ found
148
+ rescue # rexml random crash on invalid xml
149
+ []
150
+ end
151
+
152
+ def style_tag_for(stylesheet)
153
+ "<style>#{stylesheet.respond_to?(:read) ? stylesheet.read : File.read(stylesheet)}</style>"
154
+ end
155
+
156
+ def append_stylesheets
157
+ raise ImproperSourceError.new('Stylesheets may only be added to an HTML source') if stylesheets.any? && !@source.html?
158
+
159
+ stylesheets.each do |stylesheet|
160
+ if @source.to_s.match(/<\/head>/)
161
+ @source.to_s.gsub!(/(<\/head>)/, style_tag_for(stylesheet)+'\1')
162
+ else
163
+ @source.to_s.insert(0, style_tag_for(stylesheet))
164
+ end
165
+ end
166
+ end
167
+
168
+ def normalize_options(options)
169
+ normalized_options = {}
170
+
171
+ options.each do |key, value|
172
+ next if !value
173
+ normalized_key = "--#{normalize_arg key}"
174
+ normalized_options[normalized_key] = normalize_value(value)
175
+ end
176
+ normalized_options
177
+ end
178
+
179
+ def normalize_arg(arg)
180
+ arg.to_s.downcase.gsub(/[^a-z0-9]/,'-')
181
+ end
182
+
183
+ def normalize_value(value)
184
+ case value
185
+ when TrueClass
186
+ nil
187
+ when Array
188
+ value
189
+ else
190
+ value.to_s
191
+ end
192
+ end
193
+
194
+ def set_format(format)
195
+ format = IMGKit.configuration.default_format unless format
196
+ @options.merge!(:format => format.to_s) unless @options[:format]
197
+ raise UnknownFormatError.new(format) unless KNOWN_FORMATS.include?(@options[:format].to_sym)
198
+ end
199
+ end
@@ -0,0 +1,27 @@
1
+ class IMGKit
2
+
3
+ class Source
4
+
5
+ def initialize(url_file_or_html)
6
+ @source = url_file_or_html
7
+ end
8
+
9
+ def url?
10
+ @source.is_a?(String) && @source.match(/\Ahttp/)
11
+ end
12
+
13
+ def file?
14
+ @source.kind_of?(File) || @source.kind_of?(Tempfile)
15
+ end
16
+
17
+ def html?
18
+ !(url? || file?)
19
+ end
20
+
21
+ def to_s
22
+ file? ? @source.path : @source
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,3 @@
1
+ class IMGKit
2
+ VERSION = "1.3.9.1"
3
+ end
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ echo 'I have a problem' > /dev/stderr
3
+ exit 1
@@ -0,0 +1 @@
1
+ body { font-size: 20px; }
@@ -0,0 +1,5 @@
1
+ <html>
2
+ <body>
3
+ <h1>Oh Hai!</h1>
4
+ </body>
5
+ </html>
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+
3
+ describe IMGKit do
4
+ context "initialization" do
5
+ it "should accept HTML as the source" do
6
+ imgkit = IMGKit.new('<h1>Oh Hai</h1>')
7
+ imgkit.source.should be_html
8
+ imgkit.source.to_s.should == '<h1>Oh Hai</h1>'
9
+ end
10
+
11
+ it "should accept a URL as the source" do
12
+ imgkit = IMGKit.new('http://google.com')
13
+ imgkit.source.should be_url
14
+ imgkit.source.to_s.should == 'http://google.com'
15
+ end
16
+
17
+ it "should accept a File as the source" do
18
+ file_path = File.join(SPEC_ROOT,'fixtures','example.html')
19
+ imgkit = IMGKit.new(File.new(file_path))
20
+ imgkit.source.should be_file
21
+ imgkit.source.to_s.should == file_path
22
+ end
23
+
24
+ it "should provide no default options" do
25
+ end
26
+
27
+ it "should set a default height" do
28
+ imgkit = IMGKit.new('<h1>Oh Hai</h1>')
29
+ imgkit.options.length.should be 1
30
+ imgkit.options[:height].should be 1000
31
+ end
32
+
33
+
34
+ =begin
35
+ it "should default to 'UTF-8' encoding" do
36
+ imgkit = IMGKit.new('Captación')
37
+ end
38
+ =end
39
+
40
+ it "should not have any stylesheet by default" do
41
+ imgkit = IMGKit.new('<h1>Oh Hai</h1>')
42
+ imgkit.stylesheets.should be_empty
43
+ end
44
+ end
45
+
46
+ context "command" do
47
+ it "should contstruct the correct command" do
48
+ imgkit = IMGKit.new('html')
49
+ imgkit.command[0].should include('wkhtmltoimage')
50
+ imgkit.command.should include('-')
51
+ end
52
+
53
+ it "should parse the options into a cmd line friedly format" do
54
+ imgkit = IMGKit.new('html', :quality => 75)
55
+ imgkit.command.should include('--quality')
56
+ end
57
+
58
+ it "will not include default options it is told to omit" do
59
+ imgkit = IMGKit.new('html')
60
+ imgkit = IMGKit.new('html', :disable_smart_shrinking => false)
61
+ imgkit.command.should_not include('--disable-smart-shrinking')
62
+ end
63
+ it "should encapsulate string arguments in quotes" do
64
+ imgkit = IMGKit.new('html', :header_center => "foo [page]")
65
+ imgkit.command[imgkit.command.index('--header-center') + 1].should == 'foo [page]'
66
+ end
67
+
68
+ it "should properly handle multi-part arguments" do
69
+ imgkit = IMGKit.new('html', :custom_header => ['User-Agent', 'some user agent'])
70
+ imgkit.command[imgkit.command.index('--custom-header') + 1].should == 'User-Agent'
71
+ imgkit.command[imgkit.command.index('--custom-header') + 2].should == 'some user agent'
72
+ end
73
+
74
+ it "read the source from a temporary file if it is html" do
75
+ imgkit = IMGKit.new('html')
76
+ imgkit.command[-2].should_not == '-'
77
+ end
78
+
79
+ it "specify the URL to the source if it is a url" do
80
+ imgkit = IMGKit.new('http://google.com')
81
+ imgkit.command[-2..-1].should == ['http://google.com', '-']
82
+ end
83
+
84
+ it "should specify the path to the source if it is a file" do
85
+ file_path = File.join(SPEC_ROOT,'fixtures','example.html')
86
+ imgkit = IMGKit.new(File.new(file_path))
87
+ imgkit.command[-2..-1].should == [file_path, '-']
88
+ end
89
+
90
+ it "should detect special imgkit meta tags" do
91
+ body = %{
92
+ <html>
93
+ <head>
94
+ <meta name="imgkit-page_size" content="Legal"/>
95
+ <meta name="imgkit-orientation" content="Landscape"/>
96
+ <meta name="imgkit-crop-h" content="900"/>
97
+ </head>
98
+ </html>
99
+ }
100
+ imgkit = IMGKit.new(body)
101
+ imgkit.command[imgkit.command.index('--page-size') + 1].should == 'Legal'
102
+ imgkit.command[imgkit.command.index('--orientation') + 1].should == 'Landscape'
103
+ imgkit.command[imgkit.command.index('--crop-h') + 1].should == '900'
104
+ end
105
+ end
106
+
107
+ context "#to_img(format = nil)" do
108
+ def filetype_of(img)
109
+ result = nil
110
+ tmpfile = Tempfile.new('imgkit')
111
+ File.open(tmpfile.path, 'w') { |f| f << img }
112
+ result = `file #{tmpfile.path}`
113
+ tmpfile.unlink()
114
+ result
115
+ end
116
+
117
+ it "should generate a IMG of the HTML" do
118
+ imgkit = IMGKit.new('html')
119
+ img = imgkit.to_img
120
+ filetype_of(img).should include('JPEG')
121
+ end
122
+
123
+ it "should generate an Image with a numerical parameter" do
124
+ imgkit = IMGKit.new('html', :quality => 50)
125
+ img = imgkit.to_img
126
+ filetype_of(img).should include('JPEG')
127
+ end
128
+
129
+ it "should generate an Image with a symbol parameter" do
130
+ imgkit = IMGKit.new('html', :username => 'chris')
131
+ img = imgkit.to_img
132
+ filetype_of(img).should include('JPEG')
133
+ end
134
+
135
+ it "should have the stylesheet added to the head if it has one" do
136
+ imgkit = IMGKit.new("<html><head></head><body>Hai!</body></html>")
137
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
138
+ imgkit.stylesheets << css
139
+ imgkit.to_img
140
+ imgkit.source.to_s.should include("<style>#{File.read(css)}</style>")
141
+ end
142
+
143
+ it "should accept stylesheet as an object which responds to #read" do
144
+ imgkit = IMGKit.new("<html><head></head><body>Hai!</body></html>")
145
+ css = StringIO.new( File.read(File.join(SPEC_ROOT,'fixtures','example.css')) )
146
+ imgkit.stylesheets << css
147
+ imgkit.to_img
148
+ imgkit.source.to_s.should include("<style>#{css.string}</style>")
149
+ end
150
+
151
+ it "should prepend style tags if the HTML doesn't have a head tag" do
152
+ imgkit = IMGKit.new("<html><body>Hai!</body></html>")
153
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
154
+ imgkit.stylesheets << css
155
+ imgkit.to_img
156
+ imgkit.source.to_s.should include("<style>#{File.read(css)}</style><html>")
157
+ end
158
+
159
+ it "should throw an error if the source is not html and stylesheets have been added" do
160
+ imgkit = IMGKit.new('http://google.com')
161
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
162
+ imgkit.stylesheets << css
163
+ lambda { imgkit.to_img }.should raise_error(IMGKit::ImproperSourceError)
164
+ end
165
+
166
+ def set_wkhtmltoimage_binary(binary)
167
+ spec_dir = File.dirname(__FILE__)
168
+ IMGKit.configuration.should_receive(:wkhtmltoimage).at_least(1).times.and_return(File.join(spec_dir, binary))
169
+ end
170
+
171
+ it "should throw an error if the wkhtmltoimage command fails" do
172
+ set_wkhtmltoimage_binary 'error_binary'
173
+ imgkit = IMGKit.new('http://www.example.com')
174
+ lambda { imgkit.to_img }.should raise_error(IMGKit::CommandFailedError)
175
+ end
176
+
177
+ it "should be able to handle lots of error output" do
178
+ set_wkhtmltoimage_binary 'warning_binary'
179
+ imgkit = IMGKit.new("<html><body>Hai!</body></html>")
180
+ imgkit.to_img.should == "result\n"
181
+ end
182
+
183
+ context "when there is no format" do
184
+ it "should fallback to jpg" do
185
+ IMGKit.new("Hello, world").to_img.should be_a(:jpg)
186
+ end
187
+
188
+ context "when a default_format has been configured" do
189
+ before do
190
+ IMGKit.configure do |config|
191
+ config.default_format = :png
192
+ end
193
+ end
194
+
195
+ after do
196
+ IMGKit.configure do |config|
197
+ config.default_format = :jpg
198
+ end
199
+ end
200
+
201
+ it "should use the configured format" do
202
+ IMGKit.new("Oh hai!").to_img.should be_a(:png)
203
+ end
204
+ end
205
+ end
206
+
207
+ context "when format = :jpg" do
208
+ it "should create a jpg" do
209
+ IMGKit.new("Hello, world").to_img(:jpg).should be_a(:jpg)
210
+ end
211
+ end
212
+
213
+ context "when format is a known format" do
214
+ it "should create an image with that format" do
215
+ IMGKit::KNOWN_FORMATS.each do |format|
216
+ IMGKit.new("Hello, world").to_img(format).should be_a(format)
217
+ end
218
+ end
219
+ end
220
+
221
+ context "when format is unknown" do
222
+ it "should raise an UnknownFormatError" do
223
+ lambda { IMGKit.new("Hello, world").to_img(:blah) }.should raise_error(IMGKit::UnknownFormatError)
224
+ end
225
+ end
226
+ end
227
+
228
+ context "#to_<known_format>" do
229
+ IMGKit::KNOWN_FORMATS.each do |format|
230
+ describe "#to_#{format}" do
231
+ it "should create a #{format}" do
232
+ IMGKit.new("Hello").send("to_#{format}").should be_a(format)
233
+ end
234
+ end
235
+ end
236
+ end
237
+
238
+ context "#to_<unkown_format>" do
239
+ it "should raise and UnknownFormatError" do
240
+ lambda { IMGKit.new("Hello, world").to_blah }.should raise_error(IMGKit::UnknownFormatError)
241
+ end
242
+ end
243
+
244
+ context "#to_file" do
245
+ before do
246
+ @file_path = File.join(SPEC_ROOT,'fixtures','test.jpg')
247
+ File.delete(@file_path) if File.exist?(@file_path)
248
+ end
249
+
250
+ after do
251
+ File.delete(@file_path) if File.exist?(@file_path)
252
+ end
253
+
254
+ it "should create a file with the result of :to_img as content" do
255
+ imgkit = IMGKit.new('html', :quality => 50)
256
+ imgkit.expects(:to_img).returns('CONTENT')
257
+ file = imgkit.to_file(@file_path)
258
+ file.should be_instance_of(File)
259
+ File.read(file.path).should == 'CONTENT'
260
+ end
261
+
262
+ IMGKit::KNOWN_FORMATS.each do |format|
263
+ it "should use the extension #{format} as the format" do
264
+ @file_path = File.join(SPEC_ROOT,'fixtures',"test.#{format}")
265
+ imgkit = IMGKit.new('html', :quality => 50)
266
+ file = imgkit.to_file(@file_path)
267
+ file.should be_instance_of(File)
268
+ File.open(file.path, "r:ASCII-8BIT") { |f| f.read.should be_a(format) }
269
+ end
270
+ end
271
+
272
+ it "should raise UnknownFormatError when format is unknown" do
273
+ kit = IMGKit.new("html")
274
+ lambda {
275
+ kit.to_file("file.bad_format")
276
+ }.should raise_error(IMGKit::UnknownFormatError)
277
+ end
278
+
279
+ it "should not create the file if format is unknown" do
280
+ kit = IMGKit.new("html")
281
+ kit.to_file("file.bad_format") rescue nil
282
+ File.exist?("file.bad_format").should be_false
283
+ end
284
+ end
285
+
286
+ context "security" do
287
+ before do
288
+ @test_path = File.join(SPEC_ROOT,'fixtures','security-oops')
289
+ File.delete(@test_path) if File.exist?(@test_path)
290
+ end
291
+
292
+ after do
293
+ File.delete(@test_path) if File.exist?(@test_path)
294
+ end
295
+
296
+ it "should not allow shell injection in options" do
297
+ imgkit = IMGKit.new('html', :password => "blah\"; touch #{@test_path} #")
298
+ lambda { imgkit.to_img }.should raise_error(IMGKit::CommandFailedError)
299
+ end
300
+ end
301
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe IMGKit::Source do
4
+
5
+ describe "#url?" do
6
+ it "should return true if passed a url like string" do
7
+ source = IMGKit::Source.new('http://google.com')
8
+ source.should be_url
9
+ end
10
+
11
+ it "should return false if passed a file" do
12
+ source = IMGKit::Source.new(File.new(__FILE__))
13
+ source.should_not be_url
14
+ end
15
+
16
+ it "should return false if passed HTML" do
17
+ source = IMGKit::Source.new('<blink>Oh Hai!</blink>')
18
+ source.should_not be_url
19
+ end
20
+
21
+ it "should return false if passed HTML with a line starting with 'http'" do
22
+ source = IMGKit::Source.new("<blink>Oh Hai!</blink>\nhttp://google.com")
23
+ source.should_not be_url
24
+ end
25
+ end
26
+
27
+ describe "#file?" do
28
+ it "should return true if passed a file" do
29
+ source = IMGKit::Source.new(File.new(__FILE__))
30
+ source.should be_file
31
+ end
32
+
33
+ it "should return true if passed a temporary file" do
34
+ source = IMGKit::Source.new(Tempfile.new 'temp_file')
35
+ source.should be_file
36
+ end
37
+
38
+ it "should return false if passed a url like string" do
39
+ source = IMGKit::Source.new('http://google.com')
40
+ source.should_not be_file
41
+ end
42
+
43
+ it "should return false if passed HTML" do
44
+ source = IMGKit::Source.new('<blink>Oh Hai!</blink>')
45
+ source.should_not be_file
46
+ end
47
+ end
48
+
49
+ describe "#html?" do
50
+ it "should return true if passed HTML" do
51
+ source = IMGKit::Source.new('<blink>Oh Hai!</blink>')
52
+ source.should be_html
53
+ end
54
+
55
+ it "should return false if passed a file" do
56
+ source = IMGKit::Source.new(File.new(__FILE__))
57
+ source.should_not be_html
58
+ end
59
+
60
+ it "should return false if passed a url like string" do
61
+ source = IMGKit::Source.new('http://google.com')
62
+ source.should_not be_html
63
+ end
64
+ end
65
+
66
+ describe "#to_s" do
67
+ it "should return the HTML if passed HTML" do
68
+ source = IMGKit::Source.new('<blink>Oh Hai!</blink>')
69
+ source.to_s.should == '<blink>Oh Hai!</blink>'
70
+ end
71
+
72
+ it "should return a path if passed a file" do
73
+ source = IMGKit::Source.new(File.new(__FILE__))
74
+ source.to_s.should == __FILE__
75
+ end
76
+
77
+ it "should return the url if passed a url like string" do
78
+ source = IMGKit::Source.new('http://google.com')
79
+ source.to_s.should == 'http://google.com'
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,48 @@
1
+ SPEC_ROOT = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(SPEC_ROOT)
3
+ $LOAD_PATH.unshift(File.join(SPEC_ROOT, '..', 'lib'))
4
+ require 'imgkit'
5
+ require 'rspec'
6
+ require 'rspec/autorun'
7
+ require 'mocha'
8
+ require 'rack'
9
+ require 'tempfile'
10
+
11
+ RSpec.configure do |config|
12
+ config.before do
13
+ IMGKit.any_instance.stubs(:wkhtmltoimage).returns(
14
+ File.join(SPEC_ROOT,'..','bin','wkhtmltoimage-proxy')
15
+ )
16
+ end
17
+ end
18
+
19
+ module MagicNumber
20
+ extend self
21
+ JPG = "\xFF\xD8\xFF\xE0"
22
+ JPEG = JPG
23
+ PNG = "\x89\x50\x4e\x47"
24
+ TIFF = "\x49\x49\x2a\x00"
25
+ TIF = TIFF
26
+ GIF = "\x47\x49\x46\x38"
27
+
28
+
29
+ if "".respond_to?(:force_encoding)
30
+ constants.each { |c| const_get(c).force_encoding("ASCII-8BIT") }
31
+ end
32
+
33
+ def read(string)
34
+ string[0,4]
35
+ end
36
+ end
37
+
38
+ RSpec::Matchers.define :be_a do |expected|
39
+ match do |actual|
40
+ @expected = MagicNumber.const_get(expected.to_s.upcase)
41
+ MagicNumber.read(actual) == @expected
42
+ end
43
+
44
+ failure_message_for_should do |actual|
45
+ actual = MagicNumber.read(actual)
46
+ "expctected #{actual.inspect},#{actual.encoding} to equal #{@expected.inspect},#{@expected.encoding}"
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ for i in {1..1000}; do
4
+ echo "Some kind of a long error message so that the operating system buffer gets filled" > /dev/stderr
5
+ done
6
+
7
+ echo "result"
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: img-kit
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.9.1
5
+ platform: ruby
6
+ authors:
7
+ - csquared
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-20 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Uses wkhtmltoimage to create Images using HTML
14
+ email: christopher.continanza@gmail.com
15
+ executables:
16
+ - imgkit
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .document
21
+ - .gitignore
22
+ - .rspec
23
+ - .rvmrc
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - LICENSE
27
+ - POST_INSTALL
28
+ - README.md
29
+ - Rakefile
30
+ - bin/imgkit
31
+ - imgkit.gemspec
32
+ - lib/imgkit.rb
33
+ - lib/imgkit/configuration.rb
34
+ - lib/imgkit/imgkit.rb
35
+ - lib/imgkit/source.rb
36
+ - lib/imgkit/version.rb
37
+ - spec/error_binary
38
+ - spec/fixtures/example.css
39
+ - spec/fixtures/example.html
40
+ - spec/imgkit_spec.rb
41
+ - spec/source_spec.rb
42
+ - spec/spec_helper.rb
43
+ - spec/warning_binary
44
+ homepage: http://github.com/topspin/imgkit
45
+ licenses: []
46
+ metadata: {}
47
+ post_install_message: |
48
+ ******************************************************************
49
+
50
+ Now install wkhtmltoimage binaries:
51
+ Global: sudo `which imgkit` --install-wkhtmltoimage
52
+ rvmsudo imgkit --install-wkhtmltoimage
53
+ (installs to default /usr/local/bin/wkhtmltoimage)
54
+
55
+ inside RVM folder: export TO=`which imgkit | sed 's:/imgkit:/wkhtmltoimage:'` && imgkit --install-wkhtmltoimage
56
+ (you'll have to configure the location of the binary if you do this!)
57
+
58
+ (run imgkit --help to see more options)
59
+ ******************************************************************
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.1.0
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: HTML+CSS -> JPG
79
+ test_files:
80
+ - spec/error_binary
81
+ - spec/fixtures/example.css
82
+ - spec/fixtures/example.html
83
+ - spec/imgkit_spec.rb
84
+ - spec/source_spec.rb
85
+ - spec/spec_helper.rb
86
+ - spec/warning_binary
87
+ has_rdoc: