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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +55 -0
- data/LICENSE +22 -0
- data/POST_INSTALL +12 -0
- data/README.md +15 -0
- data/Rakefile +15 -0
- data/bin/imgkit +98 -0
- data/imgkit.gemspec +20 -0
- data/lib/imgkit.rb +6 -0
- data/lib/imgkit/configuration.rb +35 -0
- data/lib/imgkit/imgkit.rb +199 -0
- data/lib/imgkit/source.rb +27 -0
- data/lib/imgkit/version.rb +3 -0
- data/spec/error_binary +3 -0
- data/spec/fixtures/example.css +1 -0
- data/spec/fixtures/example.html +5 -0
- data/spec/imgkit_spec.rb +301 -0
- data/spec/source_spec.rb +83 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/warning_binary +7 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -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
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -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.
|
data/POST_INSTALL
ADDED
@@ -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
|
+
******************************************************************
|
data/README.md
ADDED
@@ -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
|
+
|
data/Rakefile
ADDED
@@ -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
|
data/bin/imgkit
ADDED
@@ -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
|
data/imgkit.gemspec
ADDED
@@ -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
|
data/lib/imgkit.rb
ADDED
@@ -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
|
data/spec/error_binary
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
body { font-size: 20px; }
|
data/spec/imgkit_spec.rb
ADDED
@@ -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
|
data/spec/source_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
data/spec/warning_binary
ADDED
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:
|