pdfkit 0.5.4 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pdfkit might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -3
- data/README.md +31 -9
- data/lib/pdfkit/configuration.rb +13 -2
- data/lib/pdfkit/middleware.rb +19 -7
- data/lib/pdfkit/pdfkit.rb +59 -8
- data/lib/pdfkit/version.rb +1 -1
- data/pdfkit.gemspec +3 -4
- data/spec/fixtures/example_with_hex_symbol.css +3 -0
- data/spec/middleware_spec.rb +108 -7
- data/spec/pdfkit_spec.rb +93 -1
- metadata +97 -141
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 764756275a1f0ec235f57ed6a3cb5f5e5e6055b6
|
4
|
+
data.tar.gz: 2047827224d1f92c618e98cd84b851e336eec86f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa15b3d4424bba3c20424d3fb4427237d6373d162fce9ebc7b634bfdd24a012472de8f65b7e0ac09416117baba4269a4627e489dbafc436610514282c9e49f82
|
7
|
+
data.tar.gz: e83aaee209a65b4826c25daceae3023464e41b7a1361c130c213c4dd86e3c66730ea8878b49a87efc93d0c9d0166913a310db57c4d095bca0bb3fd238afaf247
|
data/.gitignore
CHANGED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pdfkit
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
2014-02-18
|
2
|
+
==================
|
3
|
+
* Bump to 0.6.0
|
4
|
+
* Added ability to run wkhtmltopdf without `--quiet`
|
5
|
+
* Now handles repeatable options as both config parameters and meta tag
|
6
|
+
options
|
7
|
+
* Fix status code 2 being treated as failure
|
8
|
+
* Escape `\X` in styesheets
|
9
|
+
* Allow controllers to set PDFKit-save-pdf
|
10
|
+
* Fix Middleware not respecting subdomains in path
|
11
|
+
|
1
12
|
2013-06-12
|
2
13
|
==================
|
3
14
|
* Bump to 0.5.4
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pdfkit (0.
|
4
|
+
pdfkit (0.6.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -24,7 +24,6 @@ GEM
|
|
24
24
|
rspec-expectations (2.6.0)
|
25
25
|
diff-lcs (~> 1.1.2)
|
26
26
|
rspec-mocks (2.6.0)
|
27
|
-
wkhtmltopdf-binary (0.9.5.3)
|
28
27
|
|
29
28
|
PLATFORMS
|
30
29
|
ruby
|
@@ -37,4 +36,3 @@ DEPENDENCIES
|
|
37
36
|
rake (~> 0.9.2)
|
38
37
|
rdoc (~> 4.0.1)
|
39
38
|
rspec (~> 2.2.0)
|
40
|
-
wkhtmltopdf-binary (~> 0.9.5)
|
data/README.md
CHANGED
@@ -14,7 +14,7 @@ gem install pdfkit
|
|
14
14
|
|
15
15
|
<https://github.com/pdfkit/pdfkit/wiki/Installing-WKHTMLTOPDF>
|
16
16
|
|
17
|
-
2. Try using the wkhtmltopdf-binary gem (mac + linux i386)
|
17
|
+
2. Try using the `wkhtmltopdf-binary` gem (mac + linux i386)
|
18
18
|
```
|
19
19
|
gem install wkhtmltopdf-binary
|
20
20
|
```
|
@@ -40,18 +40,29 @@ kit = PDFKit.new(File.new('/path/to/html'))
|
|
40
40
|
|
41
41
|
# Add any kind of option through meta tags
|
42
42
|
PDFKit.new('<html><head><meta name="pdfkit-page_size" content="Letter"')
|
43
|
+
PDFKit.new('<html><head><meta name="pdfkit-cookie cookie_name1" content="cookie_value1"')
|
44
|
+
PDFKit.new('<html><head><meta name="pdfkit-cookie cookie_name2" content="cookie_value2"')
|
45
|
+
```
|
46
|
+
### Using cookies in scraping
|
47
|
+
If you want to pass a cookie to cookie to pdfkit to scrape a website, you can
|
48
|
+
pass it in a hash:
|
49
|
+
```ruby
|
50
|
+
kit = PDFKit.new(url, cookie: {cookie_name: :cookie_value})
|
51
|
+
kit = PDFKit.new(url, [:cookie, :cookie_name1] => :cookie_val1, [:cookie, :cookie_name2] => :cookie_val2)
|
43
52
|
```
|
44
53
|
## Configuration
|
45
|
-
If you're on Windows or you installed wkhtmltopdf by hand to a location other than
|
54
|
+
If you're on Windows or you installed wkhtmltopdf by hand to a location other than `/usr/local/bin` you will need to tell PDFKit where the binary is. You can configure PDFKit like so:
|
46
55
|
```ruby
|
47
56
|
# config/initializers/pdfkit.rb
|
48
57
|
PDFKit.configure do |config|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
#
|
58
|
+
config.wkhtmltopdf = '/path/to/wkhtmltopdf'
|
59
|
+
config.default_options = {
|
60
|
+
:page_size => 'Legal',
|
61
|
+
:print_media_type => true
|
62
|
+
}
|
63
|
+
# Use only if your external hostname is unavailable on the server.
|
64
|
+
config.root_url = "http://localhost"
|
65
|
+
config.verbose = false
|
55
66
|
end
|
56
67
|
```
|
57
68
|
## Middleware
|
@@ -91,6 +102,17 @@ config.middleware.use PDFKit::Middleware, {}, :except => [%r[^/prawn], %r[^/secr
|
|
91
102
|
# conditions can be strings (either one or an array)
|
92
103
|
config.middleware.use PDFKit::Middleware, {}, :except => ['/secret']
|
93
104
|
```
|
105
|
+
**Saving the generated .pdf to disk**
|
106
|
+
|
107
|
+
Setting the `PDFKit-save-pdf` header will cause PDFKit to write the generated .pdf to the file indicated by the value of the header.
|
108
|
+
|
109
|
+
For example:
|
110
|
+
```ruby
|
111
|
+
headers['PDFKit-save-pdf'] = 'path/to/saved.pdf'
|
112
|
+
```
|
113
|
+
|
114
|
+
Will cause the .pdf to be saved to `path/to/saved.pdf` in addition to being sent back to the client. If the path is not writable/non-existant the write will fail silently. The `PDFKit-save-pdf` header is never sent back to the client.
|
115
|
+
|
94
116
|
## Troubleshooting
|
95
117
|
|
96
118
|
* **Single thread issue:** In development environments it is common to run a
|
@@ -129,7 +151,7 @@ config.middleware.use PDFKit::Middleware, {}, :except => ['/secret']
|
|
129
151
|
## Note on Patches/Pull Requests
|
130
152
|
|
131
153
|
* Fork the project.
|
132
|
-
* Setup your development environment with: gem install bundler
|
154
|
+
* Setup your development environment with: `gem install bundler`; `bundle install`
|
133
155
|
* Make your feature addition or bug fix.
|
134
156
|
* Add tests for it. This is important so I don't break it in a
|
135
157
|
future version unintentionally.
|
data/lib/pdfkit/configuration.rb
CHANGED
@@ -1,24 +1,34 @@
|
|
1
1
|
class PDFKit
|
2
2
|
class Configuration
|
3
3
|
attr_accessor :meta_tag_prefix, :default_options, :root_url
|
4
|
-
attr_writer :wkhtmltopdf
|
4
|
+
attr_writer :wkhtmltopdf, :verbose
|
5
5
|
|
6
6
|
def initialize
|
7
|
+
@verbose = false
|
7
8
|
@meta_tag_prefix = 'pdfkit-'
|
8
9
|
@default_options = {
|
9
10
|
:disable_smart_shrinking => false,
|
11
|
+
:quiet => true,
|
10
12
|
:page_size => 'Letter',
|
11
13
|
:margin_top => '0.75in',
|
12
14
|
:margin_right => '0.75in',
|
13
15
|
:margin_bottom => '0.75in',
|
14
16
|
:margin_left => '0.75in',
|
15
|
-
:encoding =>
|
17
|
+
:encoding => 'UTF-8'
|
16
18
|
}
|
17
19
|
end
|
18
20
|
|
19
21
|
def wkhtmltopdf
|
20
22
|
@wkhtmltopdf ||= (defined?(Bundler::GemfileError) ? `bundle exec which wkhtmltopdf` : `which wkhtmltopdf`).chomp
|
21
23
|
end
|
24
|
+
|
25
|
+
def quiet?
|
26
|
+
!@verbose
|
27
|
+
end
|
28
|
+
|
29
|
+
def verbose?
|
30
|
+
@verbose
|
31
|
+
end
|
22
32
|
end
|
23
33
|
|
24
34
|
class << self
|
@@ -31,6 +41,7 @@ class PDFKit
|
|
31
41
|
# @example
|
32
42
|
# PDFKit.configure do |config|
|
33
43
|
# config.wkhtmltopdf = '/usr/bin/wkhtmltopdf'
|
44
|
+
# config.verbose = true
|
34
45
|
# end
|
35
46
|
|
36
47
|
def self.configuration
|
data/lib/pdfkit/middleware.rb
CHANGED
@@ -11,6 +11,7 @@ class PDFKit
|
|
11
11
|
def call(env)
|
12
12
|
@request = Rack::Request.new(env)
|
13
13
|
@render_pdf = false
|
14
|
+
@caching = @conditions.delete(:caching) { false }
|
14
15
|
|
15
16
|
set_request_to_render_as_pdf(env) if render_as_pdf?
|
16
17
|
status, headers, response = @app.call(env)
|
@@ -21,12 +22,19 @@ class PDFKit
|
|
21
22
|
body = PDFKit.new(translate_paths(body, env), @options).to_pdf
|
22
23
|
response = [body]
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
if headers['PDFKit-save-pdf']
|
26
|
+
File.open(headers['PDFKit-save-pdf'], 'wb') { |file| file.write(body) } rescue nil
|
27
|
+
headers.delete('PDFKit-save-pdf')
|
28
|
+
end
|
29
|
+
|
30
|
+
unless @caching
|
31
|
+
# Do not cache PDFs
|
32
|
+
headers.delete('ETag')
|
33
|
+
headers.delete('Cache-Control')
|
34
|
+
end
|
27
35
|
|
28
|
-
headers[
|
29
|
-
headers[
|
36
|
+
headers['Content-Length'] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s
|
37
|
+
headers['Content-Type'] = 'application/pdf'
|
30
38
|
end
|
31
39
|
|
32
40
|
[status, headers, response]
|
@@ -39,7 +47,7 @@ class PDFKit
|
|
39
47
|
# Host with protocol
|
40
48
|
root = PDFKit.configuration.root_url || "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/"
|
41
49
|
|
42
|
-
body.gsub(/(href|src)=(['"])\/([^\"']*|[^"']*)['"]/, '\1=\2' + root + '\3\2')
|
50
|
+
body.gsub(/(href|src)=(['"])\/([^\/]([^\"']*|[^"']*))['"]/, '\1=\2' + root + '\3\2')
|
43
51
|
end
|
44
52
|
|
45
53
|
def rendering_pdf?
|
@@ -76,10 +84,14 @@ class PDFKit
|
|
76
84
|
|
77
85
|
def set_request_to_render_as_pdf(env)
|
78
86
|
@render_pdf = true
|
87
|
+
|
79
88
|
path = @request.path.sub(%r{\.pdf$}, '')
|
89
|
+
path = path.sub(@request.script_name, '')
|
90
|
+
|
80
91
|
%w[PATH_INFO REQUEST_URI].each { |e| env[e] = path }
|
92
|
+
|
81
93
|
env['HTTP_ACCEPT'] = concat(env['HTTP_ACCEPT'], Rack::Mime.mime_type('.html'))
|
82
|
-
env[
|
94
|
+
env['Rack-Middleware-PDFKit'] = 'true'
|
83
95
|
end
|
84
96
|
|
85
97
|
def concat(accepts, type)
|
data/lib/pdfkit/pdfkit.rb
CHANGED
@@ -25,6 +25,7 @@ class PDFKit
|
|
25
25
|
@stylesheets = []
|
26
26
|
|
27
27
|
@options = PDFKit.configuration.default_options.merge(options)
|
28
|
+
@options.delete(:quiet) if PDFKit.configuration.verbose?
|
28
29
|
@options.merge! find_options_in_meta(url_file_or_html) unless source.url?
|
29
30
|
@options = normalize_options(@options)
|
30
31
|
|
@@ -34,7 +35,6 @@ class PDFKit
|
|
34
35
|
def command(path = nil)
|
35
36
|
args = [executable]
|
36
37
|
args += @options.to_a.flatten.compact
|
37
|
-
args << '--quiet'
|
38
38
|
|
39
39
|
if @source.html?
|
40
40
|
args << '-' # Get HTML from stdin
|
@@ -70,7 +70,7 @@ class PDFKit
|
|
70
70
|
result = File.read(path) if path
|
71
71
|
|
72
72
|
# $? is thread safe per http://stackoverflow.com/questions/2164887/thread-safe-external-process-in-ruby-plus-checking-exitstatus
|
73
|
-
raise "command failed: #{invoke}" if result.to_s.strip.empty? or
|
73
|
+
raise "command failed (exitstatus=#{$?.exitstatus}): #{invoke}" if result.to_s.strip.empty? or !successful?($?)
|
74
74
|
return result
|
75
75
|
end
|
76
76
|
|
@@ -81,6 +81,10 @@ class PDFKit
|
|
81
81
|
|
82
82
|
protected
|
83
83
|
|
84
|
+
# Pulled from:
|
85
|
+
# https://github.com/wkhtmltopdf/wkhtmltopdf/blob/ebf9b6cfc4c58a31349fb94c568b254fac37b3d3/README_WKHTMLTOIMAGE#L27
|
86
|
+
REPEATABLE_OPTIONS = %w[--allow --cookie --custom-header --post --post-file --run-script]
|
87
|
+
|
84
88
|
def find_options_in_meta(content)
|
85
89
|
# Read file if content is a File
|
86
90
|
content = content.read if content.is_a?(File)
|
@@ -88,11 +92,19 @@ class PDFKit
|
|
88
92
|
found = {}
|
89
93
|
content.scan(/<meta [^>]*>/) do |meta|
|
90
94
|
if meta.match(/name=["']#{PDFKit.configuration.meta_tag_prefix}/)
|
91
|
-
name = meta.scan(/name=["']#{PDFKit.configuration.meta_tag_prefix}([^"']*)/)[0][0]
|
92
|
-
found[name
|
95
|
+
name = meta.scan(/name=["']#{PDFKit.configuration.meta_tag_prefix}([^"']*)/)[0][0].split
|
96
|
+
found[name] = meta.scan(/content=["'](.*[^\\])["']/)[0][0]
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
100
|
+
tuple_keys = found.keys.select { |k| k.is_a? Array }
|
101
|
+
tuple_keys.each do |key|
|
102
|
+
value = found.delete key
|
103
|
+
new_key = key.shift
|
104
|
+
found[new_key] ||= {}
|
105
|
+
found[new_key][key] = value
|
106
|
+
end
|
107
|
+
|
96
108
|
found
|
97
109
|
end
|
98
110
|
|
@@ -105,7 +117,7 @@ class PDFKit
|
|
105
117
|
|
106
118
|
stylesheets.each do |stylesheet|
|
107
119
|
if @source.to_s.match(/<\/head>/)
|
108
|
-
@source = Source.new(@source.to_s.gsub(/(<\/head>)
|
120
|
+
@source = Source.new(@source.to_s.gsub(/(<\/head>)/) {|s| style_tag_for(stylesheet) + s })
|
109
121
|
else
|
110
122
|
@source.to_s.insert(0, style_tag_for(stylesheet))
|
111
123
|
end
|
@@ -117,9 +129,20 @@ class PDFKit
|
|
117
129
|
|
118
130
|
options.each do |key, value|
|
119
131
|
next if !value
|
132
|
+
|
133
|
+
# The actual option for wkhtmltopdf
|
120
134
|
normalized_key = "--#{normalize_arg key}"
|
121
|
-
|
135
|
+
|
136
|
+
# If the option is repeatable, attempt to normalize all values
|
137
|
+
if REPEATABLE_OPTIONS.include? normalized_key
|
138
|
+
normalize_repeatable_value(value) do |normalized_key_piece, normalized_value|
|
139
|
+
normalized_options[[normalized_key, normalized_key_piece]] = normalized_value
|
140
|
+
end
|
141
|
+
else # Otherwise, just normalize it like usual
|
142
|
+
normalized_options[normalized_key] = normalize_value(value)
|
143
|
+
end
|
122
144
|
end
|
145
|
+
|
123
146
|
normalized_options
|
124
147
|
end
|
125
148
|
|
@@ -129,10 +152,10 @@ class PDFKit
|
|
129
152
|
|
130
153
|
def normalize_value(value)
|
131
154
|
case value
|
132
|
-
when TrueClass #ie, ==true, see http://www.ruby-doc.org/core-1.9.3/TrueClass.html
|
155
|
+
when TrueClass, 'true' #ie, ==true, see http://www.ruby-doc.org/core-1.9.3/TrueClass.html
|
133
156
|
nil
|
134
157
|
when Hash
|
135
|
-
value.to_a.flatten.collect{|x| x.
|
158
|
+
value.to_a.flatten.collect{|x| normalize_value(x)}.compact
|
136
159
|
when Array
|
137
160
|
value.flatten.collect{|x| x.to_s}
|
138
161
|
else
|
@@ -140,4 +163,32 @@ class PDFKit
|
|
140
163
|
end
|
141
164
|
end
|
142
165
|
|
166
|
+
def normalize_repeatable_value(value)
|
167
|
+
case value
|
168
|
+
when Hash, Array
|
169
|
+
value.each do |(key, value)|
|
170
|
+
yield [normalize_value(key), normalize_value(value)]
|
171
|
+
end
|
172
|
+
else
|
173
|
+
[normalize_value(value), '']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def successful?(status)
|
178
|
+
return true if status.success?
|
179
|
+
|
180
|
+
# Some of the codes: https://code.google.com/p/wkhtmltopdf/issues/detail?id=1088
|
181
|
+
# returned when assets are missing (404): https://code.google.com/p/wkhtmltopdf/issues/detail?id=548
|
182
|
+
return true if status.exitstatus == 2 && error_handling?
|
183
|
+
|
184
|
+
false
|
185
|
+
end
|
186
|
+
|
187
|
+
def error_handling?
|
188
|
+
@options.key?('--ignore-load-errors') ||
|
189
|
+
# wkhtmltopdf v0.10.0 beta4 replaces ignore-load-errors with load-error-handling
|
190
|
+
# https://code.google.com/p/wkhtmltopdf/issues/detail?id=55
|
191
|
+
%w(skip ignore).include?(@options['--load-error-handling'])
|
192
|
+
end
|
193
|
+
|
143
194
|
end
|
data/lib/pdfkit/version.rb
CHANGED
data/pdfkit.gemspec
CHANGED
@@ -20,11 +20,10 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
22
|
# Developmnet Dependencies
|
23
|
+
s.add_development_dependency(%q<activesupport>, [">= 3.0.8"])
|
24
|
+
s.add_development_dependency(%q<mocha>, [">= 0.9.10"])
|
25
|
+
s.add_development_dependency(%q<rack-test>, [">= 0.5.6"])
|
23
26
|
s.add_development_dependency(%q<rake>, ["~>0.9.2"])
|
24
27
|
s.add_development_dependency(%q<rdoc>, ["~> 4.0.1"])
|
25
28
|
s.add_development_dependency(%q<rspec>, ["~> 2.2.0"])
|
26
|
-
s.add_development_dependency(%q<mocha>, [">= 0.9.10"])
|
27
|
-
s.add_development_dependency(%q<rack-test>, [">= 0.5.6"])
|
28
|
-
s.add_development_dependency(%q<activesupport>, [">= 3.0.8"])
|
29
|
-
s.add_development_dependency(%q<wkhtmltopdf-binary>, ["~> 0.9.5"])
|
30
29
|
end
|
data/spec/middleware_spec.rb
CHANGED
@@ -2,11 +2,11 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
def app; Rack::Lint.new(@app); end
|
4
4
|
|
5
|
-
def mock_app(options = {}, conditions = {})
|
5
|
+
def mock_app(options = {}, conditions = {}, custom_headers = {})
|
6
6
|
main_app = lambda { |env|
|
7
7
|
@env = env
|
8
|
-
|
9
|
-
[200,
|
8
|
+
full_headers = headers.merge custom_headers
|
9
|
+
[200, full_headers, @body || ['Hello world!']]
|
10
10
|
}
|
11
11
|
|
12
12
|
builder = Rack::Builder.new
|
@@ -16,8 +16,39 @@ def mock_app(options = {}, conditions = {})
|
|
16
16
|
end
|
17
17
|
|
18
18
|
describe PDFKit::Middleware do
|
19
|
+
let(:headers) { {'Content-Type' => "text/html"} }
|
19
20
|
|
20
21
|
describe "#call" do
|
22
|
+
describe "caching" do
|
23
|
+
let(:headers) { {'Content-Type' => "text/html", 'ETag' => 'foo', 'Cache-Control' => 'max-age=2592000, public'} }
|
24
|
+
|
25
|
+
context "by default" do
|
26
|
+
before { mock_app }
|
27
|
+
|
28
|
+
it "deletes ETag" do
|
29
|
+
get 'http://www.example.org/public/test.pdf'
|
30
|
+
last_response.headers["ETag"].should be_nil
|
31
|
+
end
|
32
|
+
it "deletes Cache-Control" do
|
33
|
+
get 'http://www.example.org/public/test.pdf'
|
34
|
+
last_response.headers["Cache-Control"].should be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when on" do
|
39
|
+
before { mock_app({}, :caching => true) }
|
40
|
+
|
41
|
+
it "preserves ETag" do
|
42
|
+
get 'http://www.example.org/public/test.pdf'
|
43
|
+
last_response.headers["ETag"].should_not be_nil
|
44
|
+
end
|
45
|
+
it "preserves Cache-Control" do
|
46
|
+
get 'http://www.example.org/public/test.pdf'
|
47
|
+
last_response.headers["Cache-Control"].should_not be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
21
52
|
describe "conditions" do
|
22
53
|
describe ":only" do
|
23
54
|
|
@@ -194,21 +225,85 @@ describe PDFKit::Middleware do
|
|
194
225
|
end # string
|
195
226
|
|
196
227
|
end
|
228
|
+
|
229
|
+
describe "saving generated pdf to disk" do
|
230
|
+
before do
|
231
|
+
#make sure tests don't find an old test_save.pdf
|
232
|
+
File.delete('spec/test_save.pdf') if File.exists?('spec/test_save.pdf')
|
233
|
+
File.exists?('spec/test_save.pdf').should be_false
|
234
|
+
end
|
235
|
+
|
236
|
+
context "when header PDFKit-save-pdf is present" do
|
237
|
+
it "should saved the .pdf to disk" do
|
238
|
+
headers = { 'PDFKit-save-pdf' => 'spec/test_save.pdf' }
|
239
|
+
mock_app({}, {only: '/public'}, headers)
|
240
|
+
get 'http://www.example.org/public/test_save.pdf'
|
241
|
+
File.exists?('spec/test_save.pdf').should be_true
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should not raise when target directory does not exist" do
|
245
|
+
headers = { 'PDFKit-save-pdf' => '/this/dir/does/not/exist/spec/test_save.pdf' }
|
246
|
+
mock_app({}, {only: '/public'}, headers)
|
247
|
+
expect {
|
248
|
+
get 'http://www.example.com/public/test_save.pdf'
|
249
|
+
}.not_to raise_error(Exception)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "when header PDFKit-save-pdf is not present" do
|
254
|
+
it "should not saved the .pdf to disk" do
|
255
|
+
mock_app({}, {only: '/public'}, {} )
|
256
|
+
get 'http://www.example.org/public/test_save.pdf'
|
257
|
+
File.exists?('spec/test_save.pdf').should be_false
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
197
261
|
end
|
198
262
|
|
199
|
-
|
200
|
-
|
263
|
+
describe "remove .pdf from PATH_INFO and REQUEST_URI" do
|
264
|
+
before { mock_app }
|
201
265
|
|
202
266
|
context "matching" do
|
267
|
+
|
203
268
|
specify do
|
204
269
|
get 'http://www.example.org/public/file.pdf'
|
205
270
|
@env["PATH_INFO"].should == "/public/file"
|
206
271
|
@env["REQUEST_URI"].should == "/public/file"
|
272
|
+
@env["SCRIPT_NAME"].should be_empty
|
207
273
|
end
|
208
274
|
specify do
|
209
275
|
get 'http://www.example.org/public/file.txt'
|
210
276
|
@env["PATH_INFO"].should == "/public/file.txt"
|
211
277
|
@env["REQUEST_URI"].should be_nil
|
278
|
+
@env["SCRIPT_NAME"].should be_empty
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "subdomain matching" do
|
283
|
+
before do
|
284
|
+
main_app = lambda { |env|
|
285
|
+
@env = env
|
286
|
+
@env['SCRIPT_NAME'] = '/example.org'
|
287
|
+
headers = {'Content-Type' => "text/html"}
|
288
|
+
[200, headers, @body || ['Hello world!']]
|
289
|
+
}
|
290
|
+
|
291
|
+
builder = Rack::Builder.new
|
292
|
+
builder.use PDFKit::Middleware
|
293
|
+
builder.run main_app
|
294
|
+
@app = builder.to_app
|
295
|
+
end
|
296
|
+
specify do
|
297
|
+
get 'http://example.org/sub/public/file.pdf'
|
298
|
+
@env["PATH_INFO"].should == "/sub/public/file"
|
299
|
+
@env["REQUEST_URI"].should == "/sub/public/file"
|
300
|
+
@env["SCRIPT_NAME"].should == "/example.org"
|
301
|
+
end
|
302
|
+
specify do
|
303
|
+
get 'http://example.org/sub/public/file.txt'
|
304
|
+
@env["PATH_INFO"].should == "/sub/public/file.txt"
|
305
|
+
@env["REQUEST_URI"].should be_nil
|
306
|
+
@env["SCRIPT_NAME"].should == "/example.org"
|
212
307
|
end
|
213
308
|
end
|
214
309
|
|
@@ -233,13 +328,19 @@ describe PDFKit::Middleware do
|
|
233
328
|
body.should == "<link href=\"http://example.com/stylesheets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />"
|
234
329
|
end
|
235
330
|
|
331
|
+
it "should correctly parse relative url with double quotes" do
|
332
|
+
@body = %{<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>}
|
333
|
+
body = @pdf.send :translate_paths, @body, @env
|
334
|
+
body.should == "<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>"
|
335
|
+
end
|
336
|
+
|
236
337
|
it "should return the body even if there are no valid substitutions found" do
|
237
338
|
@body = "NO MATCH"
|
238
339
|
body = @pdf.send :translate_paths, @body, @env
|
239
340
|
body.should == "NO MATCH"
|
240
341
|
end
|
241
342
|
end
|
242
|
-
|
343
|
+
|
243
344
|
describe "#translate_paths with root_url configuration" do
|
244
345
|
before do
|
245
346
|
@pdf = PDFKit::Middleware.new({})
|
@@ -254,7 +355,7 @@ describe PDFKit::Middleware do
|
|
254
355
|
body = @pdf.send :translate_paths, @body, @env
|
255
356
|
body.should == "<html><head><link href='http://example.net/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src=\"http://example.net/test.png\" /></body></html>"
|
256
357
|
end
|
257
|
-
|
358
|
+
|
258
359
|
after do
|
259
360
|
PDFKit.configure do |config|
|
260
361
|
config.root_url = nil
|
data/spec/pdfkit_spec.rb
CHANGED
@@ -61,6 +61,26 @@ describe PDFKit do
|
|
61
61
|
command.should include "--replace foo bar"
|
62
62
|
end
|
63
63
|
|
64
|
+
it "should setup one cookie only" do
|
65
|
+
pdfkit = PDFKit.new('html', cookie: {cookie_name: :cookie_value})
|
66
|
+
command = pdfkit.command
|
67
|
+
command.should include "--cookie cookie_name cookie_value"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should setup multiple cookies when passed a hash" do
|
71
|
+
pdfkit = PDFKit.new('html', :cookie => {:cookie_name1 => :cookie_val1, :cookie_name2 => :cookie_val2})
|
72
|
+
command = pdfkit.command
|
73
|
+
command.should include "--cookie cookie_name1 cookie_val1"
|
74
|
+
command.should include "--cookie cookie_name2 cookie_val2"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should setup multiple cookies when passed an array of tuples" do
|
78
|
+
pdfkit = PDFKit.new('html', :cookie => [[:cookie_name1, :cookie_val1], [:cookie_name2, :cookie_val2]])
|
79
|
+
command = pdfkit.command
|
80
|
+
command.should include "--cookie cookie_name1 cookie_val1"
|
81
|
+
command.should include "--cookie cookie_name2 cookie_val2"
|
82
|
+
end
|
83
|
+
|
64
84
|
it "will not include default options it is told to omit" do
|
65
85
|
PDFKit.configure do |config|
|
66
86
|
config.default_options[:disable_smart_shrinking] = true
|
@@ -119,6 +139,34 @@ describe PDFKit do
|
|
119
139
|
command.should include "--orientation Landscape"
|
120
140
|
end
|
121
141
|
|
142
|
+
it "should detect cookies meta tag" do
|
143
|
+
body = %{
|
144
|
+
<html>
|
145
|
+
<head>
|
146
|
+
<meta name="pdfkit-cookie rails_session" content='rails_session_value' />
|
147
|
+
<meta name="pdfkit-cookie cookie_variable" content='cookie_variable_value' />
|
148
|
+
</head>
|
149
|
+
</html>
|
150
|
+
}
|
151
|
+
pdfkit = PDFKit.new(body)
|
152
|
+
command = pdfkit.command
|
153
|
+
command.should include "--cookie rails_session rails_session_value --cookie cookie_variable cookie_variable_value"
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should detect disable_smart_shrinking meta tag" do
|
157
|
+
body = %{
|
158
|
+
<html>
|
159
|
+
<head>
|
160
|
+
<meta name="pdfkit-disable_smart_shrinking" content="true"/>
|
161
|
+
</head>
|
162
|
+
</html>
|
163
|
+
}
|
164
|
+
pdfkit = PDFKit.new(body)
|
165
|
+
command = pdfkit.command
|
166
|
+
command.should include "--disable-smart-shrinking"
|
167
|
+
command.should_not include "--disable-smart-shrinking true"
|
168
|
+
end
|
169
|
+
|
122
170
|
it "should detect special pdfkit meta tags despite bad markup" do
|
123
171
|
body = %{
|
124
172
|
<html>
|
@@ -151,6 +199,29 @@ describe PDFKit do
|
|
151
199
|
command.should include "--orientation Landscape"
|
152
200
|
end
|
153
201
|
|
202
|
+
it "should not use quiet" do
|
203
|
+
pdfkit = PDFKit.new('html', quiet: false)
|
204
|
+
pdfkit.command.should_not include '--quiet'
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should use quiet option by defautl" do
|
208
|
+
pdfkit = PDFKit.new('html')
|
209
|
+
pdfkit.command.should include '--quiet'
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should not use quiet option in verbose mode" do
|
213
|
+
PDFKit.configure do |config|
|
214
|
+
config.verbose = true
|
215
|
+
end
|
216
|
+
|
217
|
+
pdfkit = PDFKit.new('html')
|
218
|
+
pdfkit.command.should_not include '--quiet'
|
219
|
+
|
220
|
+
PDFKit.configure do |config|
|
221
|
+
config.verbose = false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
154
225
|
end
|
155
226
|
|
156
227
|
context "#to_pdf" do
|
@@ -203,9 +274,30 @@ describe PDFKit do
|
|
203
274
|
pdfkit.source.to_s.should include("<style>#{File.read(css)}</style></head>")
|
204
275
|
end
|
205
276
|
|
277
|
+
it "should escape \\X in stylesheets" do
|
278
|
+
pdfkit = PDFKit.new("<html><head></head><body>Hai!</body></html>")
|
279
|
+
css = File.join(SPEC_ROOT,'fixtures','example_with_hex_symbol.css')
|
280
|
+
pdfkit.stylesheets << css
|
281
|
+
pdfkit.to_pdf
|
282
|
+
pdfkit.source.to_s.should include("<style>#{File.read(css)}</style></head>")
|
283
|
+
end
|
284
|
+
|
285
|
+
#NOTICE: This test is failed if use wkhtmltopdf-binary (0.9.9.1)
|
206
286
|
it "should throw an error if it is unable to connect" do
|
207
287
|
pdfkit = PDFKit.new("http://google.com/this-should-not-be-found/404.html")
|
208
|
-
lambda { pdfkit.to_pdf }.should raise_error
|
288
|
+
lambda { pdfkit.to_pdf }.should raise_error /exitstatus=2/
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should not throw an error if it is unable to connect", pending: 'this test works for wkhtmltopdf-binary (0.9.9.1)' do
|
292
|
+
pdfkit = PDFKit.new("http://localhost/this-should-not-be-found/404.html")
|
293
|
+
pdf = pdfkit.to_pdf
|
294
|
+
pdf[0...4].should == "%PDF" # PDF Signature at the beginning
|
295
|
+
end
|
296
|
+
|
297
|
+
it "should generate PDF if there are missing assets" do
|
298
|
+
pdfkit = PDFKit.new("<html><body><img alt='' src='http://example.com/surely-it-doesnt-exist.gif' /></body></html>", ignore_load_errors: true)
|
299
|
+
pdf = pdfkit.to_pdf
|
300
|
+
pdf[0...4].should == "%PDF" # PDF Signature at the beginning
|
209
301
|
end
|
210
302
|
end
|
211
303
|
|
metadata
CHANGED
@@ -1,148 +1,112 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pdfkit
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 5
|
9
|
-
- 4
|
10
|
-
version: 0.5.4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.1
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Jared Pace
|
14
8
|
- Relevance
|
15
9
|
autorequire:
|
16
10
|
bindir: bin
|
17
11
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2014-02-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 3.0.8
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 3.0.8
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: mocha
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.9.10
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.9.10
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rack-test
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 0.5.6
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.5.6
|
56
|
+
- !ruby/object:Gem::Dependency
|
22
57
|
name: rake
|
23
|
-
|
24
|
-
|
25
|
-
requirements:
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
26
60
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 63
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
- 9
|
32
|
-
- 2
|
61
|
+
- !ruby/object:Gem::Version
|
33
62
|
version: 0.9.2
|
34
|
-
prerelease: false
|
35
63
|
type: :development
|
36
|
-
|
37
|
-
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2
|
70
|
+
- !ruby/object:Gem::Dependency
|
38
71
|
name: rdoc
|
39
|
-
|
40
|
-
|
41
|
-
requirements:
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
42
74
|
- - ~>
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
hash: 61
|
45
|
-
segments:
|
46
|
-
- 4
|
47
|
-
- 0
|
48
|
-
- 1
|
75
|
+
- !ruby/object:Gem::Version
|
49
76
|
version: 4.0.1
|
50
|
-
prerelease: false
|
51
77
|
type: :development
|
52
|
-
|
53
|
-
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ~>
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 4.0.1
|
84
|
+
- !ruby/object:Gem::Dependency
|
54
85
|
name: rspec
|
55
|
-
|
56
|
-
|
57
|
-
requirements:
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
58
88
|
- - ~>
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
hash: 7
|
61
|
-
segments:
|
62
|
-
- 2
|
63
|
-
- 2
|
64
|
-
- 0
|
89
|
+
- !ruby/object:Gem::Version
|
65
90
|
version: 2.2.0
|
66
|
-
prerelease: false
|
67
91
|
type: :development
|
68
|
-
requirement: *id003
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: mocha
|
71
|
-
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
|
-
none: false
|
73
|
-
requirements:
|
74
|
-
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
hash: 47
|
77
|
-
segments:
|
78
|
-
- 0
|
79
|
-
- 9
|
80
|
-
- 10
|
81
|
-
version: 0.9.10
|
82
92
|
prerelease: false
|
83
|
-
|
84
|
-
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: rack-test
|
87
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
88
|
-
none: false
|
89
|
-
requirements:
|
90
|
-
- - ">="
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
hash: 7
|
93
|
-
segments:
|
94
|
-
- 0
|
95
|
-
- 5
|
96
|
-
- 6
|
97
|
-
version: 0.5.6
|
98
|
-
prerelease: false
|
99
|
-
type: :development
|
100
|
-
requirement: *id005
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
|
-
name: activesupport
|
103
|
-
version_requirements: &id006 !ruby/object:Gem::Requirement
|
104
|
-
none: false
|
105
|
-
requirements:
|
106
|
-
- - ">="
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
hash: 23
|
109
|
-
segments:
|
110
|
-
- 3
|
111
|
-
- 0
|
112
|
-
- 8
|
113
|
-
version: 3.0.8
|
114
|
-
prerelease: false
|
115
|
-
type: :development
|
116
|
-
requirement: *id006
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
name: wkhtmltopdf-binary
|
119
|
-
version_requirements: &id007 !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
|
-
requirements:
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
122
95
|
- - ~>
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
|
125
|
-
segments:
|
126
|
-
- 0
|
127
|
-
- 9
|
128
|
-
- 5
|
129
|
-
version: 0.9.5
|
130
|
-
prerelease: false
|
131
|
-
type: :development
|
132
|
-
requirement: *id007
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 2.2.0
|
133
98
|
description: Uses wkhtmltopdf to create PDFs using HTML
|
134
|
-
email:
|
99
|
+
email:
|
135
100
|
- jared@codewordstudios.com
|
136
101
|
executables: []
|
137
|
-
|
138
102
|
extensions: []
|
139
|
-
|
140
103
|
extra_rdoc_files: []
|
141
|
-
|
142
|
-
files:
|
104
|
+
files:
|
143
105
|
- .document
|
144
106
|
- .gitignore
|
145
107
|
- .rspec
|
108
|
+
- .ruby-gemset
|
109
|
+
- .ruby-version
|
146
110
|
- .travis.yml
|
147
111
|
- CHANGELOG.md
|
148
112
|
- Gemfile
|
@@ -160,46 +124,38 @@ files:
|
|
160
124
|
- pdfkit.gemspec
|
161
125
|
- spec/fixtures/example.css
|
162
126
|
- spec/fixtures/example.html
|
127
|
+
- spec/fixtures/example_with_hex_symbol.css
|
163
128
|
- spec/middleware_spec.rb
|
164
129
|
- spec/pdfkit_spec.rb
|
165
130
|
- spec/source_spec.rb
|
166
131
|
- spec/spec_helper.rb
|
167
132
|
homepage: https://github.com/pdfkit/pdfkit
|
168
133
|
licenses: []
|
169
|
-
|
134
|
+
metadata: {}
|
170
135
|
post_install_message:
|
171
136
|
rdoc_options: []
|
172
|
-
|
173
|
-
require_paths:
|
137
|
+
require_paths:
|
174
138
|
- lib
|
175
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
none: false
|
186
|
-
requirements:
|
187
|
-
- - ">="
|
188
|
-
- !ruby/object:Gem::Version
|
189
|
-
hash: 3
|
190
|
-
segments:
|
191
|
-
- 0
|
192
|
-
version: "0"
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
193
149
|
requirements: []
|
194
|
-
|
195
150
|
rubyforge_project: pdfkit
|
196
|
-
rubygems_version:
|
151
|
+
rubygems_version: 2.0.3
|
197
152
|
signing_key:
|
198
|
-
specification_version:
|
153
|
+
specification_version: 4
|
199
154
|
summary: HTML+CSS -> PDF
|
200
|
-
test_files:
|
155
|
+
test_files:
|
201
156
|
- spec/fixtures/example.css
|
202
157
|
- spec/fixtures/example.html
|
158
|
+
- spec/fixtures/example_with_hex_symbol.css
|
203
159
|
- spec/middleware_spec.rb
|
204
160
|
- spec/pdfkit_spec.rb
|
205
161
|
- spec/source_spec.rb
|