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 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
@@ -20,4 +20,5 @@ pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
22
  .bundle
23
- spec/custom_wkhtmltopdf_path.rb
23
+ spec/custom_wkhtmltopdf_path.rb
24
+ spec/test_save.pdf
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
@@ -1,4 +1,9 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 1.9.2
4
3
  - 1.9.3
4
+ - 2.0.0
5
+
6
+ before_script:
7
+ - "export DISPLAY=:99.0"
8
+ - "sh -e /etc/init.d/xvfb start"
9
+ - "sudo apt-get install wkhtmltopdf"
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.5.4)
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 /usr/local/bin you will need to tell PDFKit where the binary is. You can configure PDFKit like so:
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
- # config.wkhtmltopdf = '/path/to/wkhtmltopdf'
50
- # config.default_options = {
51
- # :page_size => 'Legal',
52
- # :print_media_type => true
53
- # }
54
- # config.root_url = "http://localhost" # Use only if your external hostname is unavailable on the server.
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; bundle install
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.
@@ -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 => "UTF-8"
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
@@ -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
- # Do not cache PDFs
25
- headers.delete('ETag')
26
- headers.delete('Cache-Control')
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["Content-Length"] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s
29
- headers["Content-Type"] = "application/pdf"
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["Rack-Middleware-PDFKit"] = "true"
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 !$?.success?
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.to_sym] = meta.scan(/content=["']([^"']*)/)[0][0]
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>)/, style_tag_for(stylesheet)+'\1'))
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
- normalized_options[normalized_key] = normalize_value(value)
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.to_s}
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
@@ -1,3 +1,3 @@
1
1
  class PDFKit
2
- VERSION = "0.5.4"
2
+ VERSION = "0.6.1"
3
3
  end
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
@@ -0,0 +1,3 @@
1
+ .test:before {
2
+ content: '\2039';
3
+ }
@@ -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
- headers = {'Content-Type' => "text/html"}
9
- [200, headers, @body || ['Hello world!']]
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
- describe "remove .pdf from PATH_INFO and REQUEST_URI" do
200
- before { mock_app }
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
- hash: 3
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
- date: 2013-06-12 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
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
- version_requirements: &id001 !ruby/object:Gem::Requirement
24
- none: false
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
- requirement: *id001
37
- - !ruby/object:Gem::Dependency
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
- version_requirements: &id002 !ruby/object:Gem::Requirement
40
- none: false
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
- requirement: *id002
53
- - !ruby/object:Gem::Dependency
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
- version_requirements: &id003 !ruby/object:Gem::Requirement
56
- none: false
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
- type: :development
84
- requirement: *id004
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
- hash: 49
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
- none: false
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- hash: 3
181
- segments:
182
- - 0
183
- version: "0"
184
- required_rubygems_version: !ruby/object:Gem::Requirement
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: 1.8.25
151
+ rubygems_version: 2.0.3
197
152
  signing_key:
198
- specification_version: 3
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