wicked_pdf 1.1.0 → 2.1.0
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 +5 -5
- data/.github/issue_template.md +15 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +160 -30
- data/.travis.yml +56 -34
- data/CHANGELOG.md +115 -40
- data/README.md +93 -19
- data/Rakefile +14 -4
- data/gemfiles/4.0.gemfile +1 -0
- data/gemfiles/4.1.gemfile +1 -0
- data/gemfiles/4.2.gemfile +3 -0
- data/gemfiles/5.0.gemfile +2 -0
- data/gemfiles/5.1.gemfile +8 -0
- data/gemfiles/5.2.gemfile +10 -0
- data/gemfiles/6.0.gemfile +11 -0
- data/gemfiles/rails_edge.gemfile +5 -2
- data/generators/wicked_pdf/templates/wicked_pdf.rb +6 -0
- data/lib/generators/wicked_pdf_generator.rb +5 -9
- data/lib/wicked_pdf.rb +62 -48
- data/lib/wicked_pdf/middleware.rb +1 -1
- data/lib/wicked_pdf/pdf_helper.rb +29 -21
- data/lib/wicked_pdf/progress.rb +33 -0
- data/lib/wicked_pdf/railtie.rb +9 -38
- data/lib/wicked_pdf/version.rb +1 -1
- data/lib/wicked_pdf/wicked_pdf_helper.rb +2 -1
- data/lib/wicked_pdf/wicked_pdf_helper/assets.rb +73 -7
- data/test/fixtures/database.yml +4 -0
- data/test/fixtures/manifest.js +3 -0
- data/test/functional/pdf_helper_test.rb +71 -0
- data/test/test_helper.rb +11 -8
- data/test/unit/wicked_pdf_test.rb +22 -3
- data/test/unit/wkhtmltopdf_location_test.rb +50 -0
- data/wicked_pdf.gemspec +20 -12
- metadata +53 -28
- data/gemfiles/2.3.gemfile +0 -10
- data/gemfiles/3.0.gemfile +0 -12
- data/gemfiles/3.1.gemfile +0 -13
- data/gemfiles/3.2.gemfile +0 -12
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# Wicked PDF [](http://badge.fury.io/rb/wicked_pdf) [](http://travis-ci.org/mileszs/wicked_pdf) [](https://codeclimate.com/github/mileszs/wicked_pdf) [](https://www.codetriage.com/mileszs/wicked_pdf)
|
2
2
|
|
3
3
|
## A PDF generation plugin for Ruby on Rails
|
4
4
|
|
5
5
|
Wicked PDF uses the shell utility [wkhtmltopdf](http://wkhtmltopdf.org) to serve a PDF file to a user from HTML. In other words, rather than dealing with a PDF generation DSL of some sort, you simply write an HTML view as you would normally, then let Wicked PDF take care of the hard stuff.
|
6
6
|
|
7
|
-
_Wicked PDF has been verified to work on Ruby versions
|
7
|
+
_Wicked PDF has been verified to work on Ruby versions 2.2 through 2.6; Rails 4 through 6.1_
|
8
8
|
|
9
9
|
### Installation
|
10
10
|
|
@@ -26,8 +26,8 @@ to `config/initializers/mime_types.rb` in older versions of Rails.
|
|
26
26
|
|
27
27
|
Because `wicked_pdf` is a wrapper for [wkhtmltopdf](http://wkhtmltopdf.org/), you'll need to install that, too.
|
28
28
|
|
29
|
-
The simplest way to install all of the binaries
|
30
|
-
To install that, add
|
29
|
+
The simplest way to install all of the binaries on most Linux or OSX systems is through the gem [wkhtmltopdf-binary](https://github.com/zakird/wkhtmltopdf_binary_gem). Builds for other systems are available [here](https://wkhtmltopdf.org/downloads.html)
|
30
|
+
To install that gem, add this:
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
gem 'wkhtmltopdf-binary'
|
@@ -35,7 +35,9 @@ gem 'wkhtmltopdf-binary'
|
|
35
35
|
|
36
36
|
To your Gemfile and run `bundle install`.
|
37
37
|
|
38
|
-
This
|
38
|
+
This gem currently installs version 0.12.x of `wkhtmltopdf`. Some of the options listed below are specific 0.9 or below, and others are for 0.12 and up.
|
39
|
+
|
40
|
+
You can see what flags are supported for the current version in [wkhtmltopdf's auto-generated manual](https://wkhtmltopdf.org/usage/wkhtmltopdf.txt)
|
39
41
|
|
40
42
|
If your wkhtmltopdf executable is not on your webserver's path, you can configure it in an initializer:
|
41
43
|
|
@@ -83,7 +85,6 @@ The wkhtmltopdf binary is run outside of your Rails application; therefore, your
|
|
83
85
|
</body>
|
84
86
|
</html>
|
85
87
|
```
|
86
|
-
|
87
88
|
Using wicked_pdf_helpers with asset pipeline raises `Asset names passed to helpers should not include the "/assets/" prefix.` error. To work around this, you can use `wicked_pdf_asset_base64` with the normal Rails helpers, but be aware that this will base64 encode your content and inline it in the page. This is very quick for small assets, but large ones can take a long time.
|
88
89
|
|
89
90
|
```html
|
@@ -106,6 +107,21 @@ Using wicked_pdf_helpers with asset pipeline raises `Asset names passed to helpe
|
|
106
107
|
</html>
|
107
108
|
```
|
108
109
|
|
110
|
+
#### Webpacker usage
|
111
|
+
|
112
|
+
wicked_pdf supports webpack assets.
|
113
|
+
|
114
|
+
Use `wicked_pdf_stylesheet_pack_tag` for stylesheets
|
115
|
+
Use `wicked_pdf_javascript_pack_tag` for javascripts
|
116
|
+
|
117
|
+
Use `wicked_pdf_asset_pack_path` to access an asset directly, for example: `image_tag wicked_pdf_asset_pack_path("media/images/foobar.png")`
|
118
|
+
|
119
|
+
#### Asset pipeline usage
|
120
|
+
|
121
|
+
It is best to precompile assets used in PDF views. This will help avoid issues when it comes to deploying, as Rails serves asset files differently between development and production (`config.assets.compile = false`), which can make it look like your PDFs work in development, but fail to load assets in production.
|
122
|
+
|
123
|
+
config.assets.precompile += ['blueprint/screen.css', 'pdf.css', 'jquery.ui.datepicker.js', 'pdf.js', ...etc...]
|
124
|
+
|
109
125
|
#### CDN reference
|
110
126
|
|
111
127
|
In this case, you can use that standard Rails helpers and point to the current CDN for whichever framework you are using. For jQuery, it would look somethng like this, given the current versions at the time of this writing.
|
@@ -116,13 +132,11 @@ In this case, you can use that standard Rails helpers and point to the current C
|
|
116
132
|
<%= javascript_include_tag "http://code.jquery.com/jquery-1.10.0.min.js" %>
|
117
133
|
<%= javascript_include_tag "http://code.jquery.com/ui/1.10.3/jquery-ui.min.js" %>
|
118
134
|
```
|
119
|
-
#### Asset pipeline usage
|
120
135
|
|
121
|
-
|
136
|
+
### Advanced Usage with all available options
|
122
137
|
|
123
|
-
|
138
|
+
_NOTE: Certain options are only supported in specific versions of wkhtmltopdf._
|
124
139
|
|
125
|
-
### Advanced Usage with all available options
|
126
140
|
```ruby
|
127
141
|
class ThingsController < ApplicationController
|
128
142
|
def show
|
@@ -132,8 +146,10 @@ class ThingsController < ApplicationController
|
|
132
146
|
render pdf: 'file_name',
|
133
147
|
disposition: 'attachment', # default 'inline'
|
134
148
|
template: 'things/show',
|
135
|
-
|
136
|
-
|
149
|
+
locals: {foo: @bar},
|
150
|
+
file: "#{Rails.root}/files/foo.erb",
|
151
|
+
inline: '<!doctype html><html><head></head><body>INLINE HTML</body></html>',
|
152
|
+
layout: 'pdf', # for a pdf.pdf.erb file
|
137
153
|
wkhtmltopdf: '/usr/local/bin/wkhtmltopdf', # path to binary
|
138
154
|
show_as_html: params.key?('debug'), # allow debugging based on url param
|
139
155
|
orientation: 'Landscape', # default Portrait
|
@@ -142,6 +158,7 @@ class ThingsController < ApplicationController
|
|
142
158
|
page_width: NUMBER,
|
143
159
|
save_to_file: Rails.root.join('pdfs', "#{filename}.pdf"),
|
144
160
|
save_only: false, # depends on :save_to_file being set first
|
161
|
+
default_protocol: 'http',
|
145
162
|
proxy: 'TEXT',
|
146
163
|
basic_auth: false # when true username & password are automatically sent from session
|
147
164
|
username: 'TEXT',
|
@@ -169,12 +186,21 @@ class ThingsController < ApplicationController
|
|
169
186
|
disable_internal_links: true,
|
170
187
|
disable_external_links: true,
|
171
188
|
print_media_type: true,
|
189
|
+
|
190
|
+
# define as true the key 'disable_local_file_access' or 'enable_local_file_access', not both
|
191
|
+
disable_local_file_access: true,
|
192
|
+
enable_local_file_access: false,
|
193
|
+
|
172
194
|
disable_smart_shrinking: true,
|
173
195
|
use_xserver: true,
|
174
|
-
background: false, #
|
196
|
+
background: false, # background needs to be true to enable background colors to render
|
175
197
|
no_background: true,
|
198
|
+
no_stop_slow_scripts: false,
|
176
199
|
viewport_size: 'TEXT', # available only with use_xserver or patched QT
|
177
200
|
extra: '', # directly inserted into the command to wkhtmltopdf
|
201
|
+
raise_on_all_errors: nil, # raise error for any stderr output. Such as missing media, image assets
|
202
|
+
log_level: 'info', # Available values: none, error, warn, or info - only available with wkhtmltopdf 0.12.5+
|
203
|
+
quiet: false, # `false` is same as `log_level: 'info'`, `true` is same as `log_level: 'none'`
|
178
204
|
outline: { outline: true,
|
179
205
|
outline_depth: LEVEL },
|
180
206
|
margin: { top: SIZE, # default 10 (mm)
|
@@ -230,7 +256,8 @@ class ThingsController < ApplicationController
|
|
230
256
|
disable_links: true,
|
231
257
|
disable_toc_links: true,
|
232
258
|
disable_back_links:true,
|
233
|
-
xsl_style_sheet: 'file.xsl'} # optional XSLT stylesheet to use for styling table of contents
|
259
|
+
xsl_style_sheet: 'file.xsl'}, # optional XSLT stylesheet to use for styling table of contents
|
260
|
+
progress: proc { |output| puts output } # proc called when console output changes
|
234
261
|
end
|
235
262
|
end
|
236
263
|
end
|
@@ -267,9 +294,20 @@ pdf = WickedPdf.new.pdf_from_url('https://github.com/mileszs/wicked_pdf')
|
|
267
294
|
|
268
295
|
# create a pdf from string using templates, layouts and content option for header or footer
|
269
296
|
pdf = WickedPdf.new.pdf_from_string(
|
270
|
-
render_to_string('templates/pdf', layout: 'pdfs/layout_pdf'),
|
297
|
+
render_to_string('templates/pdf', layout: 'pdfs/layout_pdf.html'),
|
271
298
|
footer: {
|
272
|
-
content: render_to_string(
|
299
|
+
content: render_to_string(
|
300
|
+
'templates/footer',
|
301
|
+
layout: 'pdfs/layout_pdf.html'
|
302
|
+
)
|
303
|
+
}
|
304
|
+
)
|
305
|
+
|
306
|
+
# It is possible to use footer/header templates without a layout, in that case you need to provide a valid HTML document
|
307
|
+
pdf = WickedPdf.new.pdf_from_string(
|
308
|
+
render_to_string('templates/full_pdf_template'),
|
309
|
+
header: {
|
310
|
+
content: render_to_string('templates/full_header_template')
|
273
311
|
}
|
274
312
|
)
|
275
313
|
|
@@ -281,12 +319,33 @@ save_path = Rails.root.join('pdfs','filename.pdf')
|
|
281
319
|
File.open(save_path, 'wb') do |file|
|
282
320
|
file << pdf
|
283
321
|
end
|
322
|
+
|
323
|
+
# you can also track progress on your PDF generation, such as when using it from within a Resque job
|
324
|
+
class PdfJob
|
325
|
+
def perform
|
326
|
+
blk = proc { |output|
|
327
|
+
match = output.match(/\[.+\] Page (?<current_page>\d+) of (?<total_pages>\d+)/)
|
328
|
+
if match
|
329
|
+
current_page = match[:current_page].to_i
|
330
|
+
total_pages = match[:total_pages].to_i
|
331
|
+
message = "Generated #{current_page} of #{total_pages} pages"
|
332
|
+
at current_page, total_pages, message
|
333
|
+
end
|
334
|
+
}
|
335
|
+
WickedPdf.new.pdf_from_string(html, progress: blk)
|
336
|
+
end
|
337
|
+
end
|
284
338
|
```
|
285
339
|
If you need to display utf encoded characters, add this to your pdf views or layouts:
|
286
340
|
```html
|
287
341
|
<meta charset="utf-8" />
|
288
342
|
```
|
289
|
-
|
343
|
+
If you need to return a PDF in a controller with Rails in API mode:
|
344
|
+
```ruby
|
345
|
+
pdf_html = ActionController::Base.new.render_to_string(template: 'controller_name/action_name', layout: 'pdf')
|
346
|
+
pdf = WickedPdf.new.pdf_from_string(pdf_html)
|
347
|
+
send_data pdf, filename: 'file.pdf'
|
348
|
+
```
|
290
349
|
### Page Breaks
|
291
350
|
|
292
351
|
You can control page breaks with CSS.
|
@@ -340,7 +399,7 @@ If you would like to have WickedPdf automatically generate PDF views for all (or
|
|
340
399
|
require 'wicked_pdf'
|
341
400
|
config.middleware.use WickedPdf::Middleware
|
342
401
|
```
|
343
|
-
If you want to turn on or off the middleware for certain
|
402
|
+
If you want to turn on or off the middleware for certain URLs, use the `:only` or `:except` conditions like so:
|
344
403
|
```ruby
|
345
404
|
# conditions can be plain strings or regular expressions, and you can supply only one or an array
|
346
405
|
config.middleware.use WickedPdf::Middleware, {}, only: '/invoice'
|
@@ -348,6 +407,19 @@ config.middleware.use WickedPdf::Middleware, {}, except: [ %r[^/admin], '/secret
|
|
348
407
|
```
|
349
408
|
If you use the standard `render pdf: 'some_pdf'` in your app, you will want to exclude those actions from the middleware.
|
350
409
|
|
410
|
+
|
411
|
+
### Include in an email as an attachment
|
412
|
+
|
413
|
+
To include a rendered pdf file in an email you can do the following:
|
414
|
+
|
415
|
+
```ruby
|
416
|
+
attachments['attachment.pdf'] = WickedPdf.new.pdf_from_string(
|
417
|
+
render_to_string('link_to_view.pdf.erb', layout: 'pdf')
|
418
|
+
)
|
419
|
+
```
|
420
|
+
|
421
|
+
This will render the pdf to a string and include it in the email. This is very slow so make sure you schedule your email delivery in a job.
|
422
|
+
|
351
423
|
### Further Reading
|
352
424
|
|
353
425
|
Mike Ackerman's post [How To Create PDFs in Rails](https://www.viget.com/articles/how-to-create-pdfs-in-rails)
|
@@ -375,7 +447,9 @@ However, the wicked_pdf_* helpers will use file:/// paths for assets when using
|
|
375
447
|
|
376
448
|
#### Gotchas
|
377
449
|
|
378
|
-
If one image from your HTML cannot be found (relative or wrong path for
|
450
|
+
If one image from your HTML cannot be found (relative or wrong path for example), others images with right paths **may not** be displayed in the output PDF as well (it seems to be an issue with wkhtmltopdf).
|
451
|
+
|
452
|
+
wkhtmltopdf may render at different resolutions on different platforms. For example, Linux prints at 75 dpi (native for WebKit) while on Windows it's at the desktop's DPI (which is normally 96 dpi). [Use `:zoom => 0.78125`](https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2184) (75/96) to match Linux rendering to Windows.
|
379
453
|
|
380
454
|
### Inspiration
|
381
455
|
|
data/Rakefile
CHANGED
@@ -34,18 +34,28 @@ desc 'Generate dummy application for test cases'
|
|
34
34
|
task :dummy_generate do
|
35
35
|
Rake::Task[:dummy_remove].invoke
|
36
36
|
puts 'Creating dummy application to run tests'
|
37
|
-
|
38
|
-
|
37
|
+
if Rails::VERSION::MAJOR > 2
|
38
|
+
system('rails new test/dummy --database=sqlite3')
|
39
|
+
else
|
40
|
+
system('rails test/dummy')
|
41
|
+
end
|
39
42
|
system('touch test/dummy/db/schema.rb')
|
43
|
+
FileUtils.cp 'test/fixtures/database.yml', 'test/dummy/config/'
|
40
44
|
FileUtils.rm_r Dir.glob('test/dummy/test/*')
|
45
|
+
|
46
|
+
# rails 6 needs this to be present before start:
|
47
|
+
FileUtils.mkdir_p('test/dummy/app/assets/config')
|
48
|
+
FileUtils.mkdir_p('test/dummy/app/assets/javascripts')
|
49
|
+
FileUtils.cp 'test/fixtures/manifest.js', 'test/dummy/app/assets/config/'
|
50
|
+
FileUtils.cp 'test/fixtures/wicked.js', 'test/dummy/app/assets/javascripts/'
|
41
51
|
end
|
42
52
|
|
43
53
|
desc 'Remove dummy application'
|
44
54
|
task :dummy_remove do
|
45
|
-
FileUtils.rm_r Dir.glob('test/dummy
|
55
|
+
FileUtils.rm_r Dir.glob('test/dummy/')
|
46
56
|
end
|
47
57
|
|
48
|
-
desc 'Generate documentation for the wicked_pdf
|
58
|
+
desc 'Generate documentation for the wicked_pdf gem.'
|
49
59
|
RDoc::Task.new(:rdoc) do |rdoc|
|
50
60
|
rdoc.rdoc_dir = 'rdoc'
|
51
61
|
rdoc.title = 'WickedPdf'
|
data/gemfiles/4.0.gemfile
CHANGED
data/gemfiles/4.1.gemfile
CHANGED
data/gemfiles/4.2.gemfile
CHANGED
data/gemfiles/5.0.gemfile
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rdoc'
|
4
|
+
gem 'rails', '~> 5.2'
|
5
|
+
gem 'sqlite3', '~> 1.3.6'
|
6
|
+
gem 'sprockets', '~>3.0' # v4 strips newlines from assets causing tests to fail
|
7
|
+
gem 'bootsnap' # required to run `rake test` in Rails 5.2
|
8
|
+
gem 'mocha', '= 1.3' # newer versions blow up
|
9
|
+
|
10
|
+
gemspec path: '../'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'bundler', '~>2'
|
4
|
+
gem 'rdoc'
|
5
|
+
gem 'rails', '~>6.0.1'
|
6
|
+
gem 'sqlite3', '~> 1.4'
|
7
|
+
gem 'sprockets', '~>3.0'
|
8
|
+
gem 'bootsnap' # required to run `rake test` in Rails 6.0
|
9
|
+
gem 'mocha', '= 1.3' # newer versions blow up
|
10
|
+
|
11
|
+
gemspec path: '../'
|
data/gemfiles/rails_edge.gemfile
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gem 'rdoc'
|
4
|
-
gem 'rails', git:
|
4
|
+
gem 'rails', git: 'https://github.com/rails/rails.git'
|
5
|
+
gem 'sqlite3', '~> 1.4'
|
6
|
+
gem 'bootsnap' # required to run `rake test` in Rails 6.0
|
7
|
+
gem 'mocha', '= 1.3' # newer versions blow up
|
5
8
|
|
6
9
|
gemspec path: '../'
|
@@ -18,4 +18,10 @@ WickedPdf.config = {
|
|
18
18
|
# Layout file to be used for all PDFs
|
19
19
|
# (but can be overridden in `render :pdf` calls)
|
20
20
|
# layout: 'pdf.html',
|
21
|
+
|
22
|
+
# Using wkhtmltopdf without an X server can be achieved by enabling the
|
23
|
+
# 'use_xvfb' flag. This will wrap all wkhtmltopdf commands around the
|
24
|
+
# 'xvfb-run' command, in order to simulate an X server.
|
25
|
+
#
|
26
|
+
# use_xvfb: true,
|
21
27
|
}
|
@@ -1,11 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def copy_initializer
|
7
|
-
copy_file 'wicked_pdf.rb', 'config/initializers/wicked_pdf.rb'
|
8
|
-
end
|
1
|
+
# Rails generator invoked with 'rails generate wicked_pdf'
|
2
|
+
class WickedPdfGenerator < Rails::Generators::Base
|
3
|
+
source_root(File.expand_path(File.dirname(__FILE__) + '/../../generators/wicked_pdf/templates'))
|
4
|
+
def copy_initializer
|
5
|
+
copy_file 'wicked_pdf.rb', 'config/initializers/wicked_pdf.rb'
|
9
6
|
end
|
10
|
-
|
11
7
|
end
|
data/lib/wicked_pdf.rb
CHANGED
@@ -1,32 +1,19 @@
|
|
1
1
|
# wkhtml2pdf Ruby interface
|
2
|
-
# http://
|
2
|
+
# http://wkhtmltopdf.org/
|
3
3
|
|
4
4
|
require 'logger'
|
5
5
|
require 'digest/md5'
|
6
6
|
require 'rbconfig'
|
7
|
+
require 'open3'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
else
|
11
|
-
require 'open3'
|
12
|
-
end
|
13
|
-
|
14
|
-
begin
|
15
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
16
|
-
rescue LoadError
|
17
|
-
require 'active_support/core_ext/class/attribute_accessors'
|
18
|
-
end
|
19
|
-
|
20
|
-
begin
|
21
|
-
require 'active_support/core_ext/object/blank'
|
22
|
-
rescue LoadError
|
23
|
-
require 'active_support/core_ext/blank'
|
24
|
-
end
|
9
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
10
|
+
require 'active_support/core_ext/object/blank'
|
25
11
|
|
26
12
|
require 'wicked_pdf/version'
|
27
13
|
require 'wicked_pdf/railtie'
|
28
14
|
require 'wicked_pdf/tempfile'
|
29
15
|
require 'wicked_pdf/middleware'
|
16
|
+
require 'wicked_pdf/progress'
|
30
17
|
|
31
18
|
class WickedPdf
|
32
19
|
DEFAULT_BINARY_VERSION = Gem::Version.new('0.9.9')
|
@@ -36,6 +23,8 @@ class WickedPdf
|
|
36
23
|
cattr_accessor :config
|
37
24
|
attr_accessor :binary_version
|
38
25
|
|
26
|
+
include Progress
|
27
|
+
|
39
28
|
def initialize(wkhtmltopdf_binary_path = nil)
|
40
29
|
@exe_path = wkhtmltopdf_binary_path || find_wkhtmltopdf_binary_path
|
41
30
|
raise "Location of #{EXE_NAME} unknown" if @exe_path.empty?
|
@@ -68,15 +57,19 @@ class WickedPdf
|
|
68
57
|
options.merge!(WickedPdf.config) { |_key, option, _config| option }
|
69
58
|
generated_pdf_file = WickedPdfTempfile.new('wicked_pdf_generated_file.pdf', options[:temp_path])
|
70
59
|
command = [@exe_path]
|
71
|
-
command
|
60
|
+
command.unshift(find_xvfb_run_binary_path) if options[:use_xvfb]
|
72
61
|
command += parse_options(options)
|
73
62
|
command << url
|
74
63
|
command << generated_pdf_file.path.to_s
|
75
64
|
|
76
65
|
print_command(command.inspect) if in_development_mode?
|
77
66
|
|
78
|
-
|
79
|
-
|
67
|
+
if track_progress?(options)
|
68
|
+
invoke_with_progress(command, options)
|
69
|
+
else
|
70
|
+
err = Open3.popen3(*command) do |_stdin, _stdout, stderr|
|
71
|
+
stderr.read
|
72
|
+
end
|
80
73
|
end
|
81
74
|
if options[:return_file]
|
82
75
|
return_file = options.delete(:return_file)
|
@@ -85,9 +78,10 @@ class WickedPdf
|
|
85
78
|
generated_pdf_file.rewind
|
86
79
|
generated_pdf_file.binmode
|
87
80
|
pdf = generated_pdf_file.read
|
81
|
+
raise "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?
|
88
82
|
raise "PDF could not be generated!\n Command Error: #{err}" if pdf && pdf.rstrip.empty?
|
89
83
|
pdf
|
90
|
-
rescue => e
|
84
|
+
rescue StandardError => e
|
91
85
|
raise "Failed to execute:\n#{command}\nError: #{e}"
|
92
86
|
ensure
|
93
87
|
generated_pdf_file.close! if generated_pdf_file && !return_file
|
@@ -96,7 +90,7 @@ class WickedPdf
|
|
96
90
|
private
|
97
91
|
|
98
92
|
def in_development_mode?
|
99
|
-
return Rails.env == 'development' if defined?(Rails)
|
93
|
+
return Rails.env == 'development' if defined?(Rails.env)
|
100
94
|
RAILS_ENV == 'development' if defined?(RAILS_ENV)
|
101
95
|
end
|
102
96
|
|
@@ -105,19 +99,19 @@ class WickedPdf
|
|
105
99
|
end
|
106
100
|
|
107
101
|
def print_command(cmd)
|
108
|
-
|
102
|
+
Rails.logger.debug '[wicked_pdf]: ' + cmd
|
109
103
|
end
|
110
104
|
|
111
105
|
def retrieve_binary_version
|
112
106
|
_stdin, stdout, _stderr = Open3.popen3(@exe_path + ' -V')
|
113
107
|
@binary_version = parse_version(stdout.gets(nil))
|
114
|
-
rescue
|
108
|
+
rescue StandardError
|
115
109
|
DEFAULT_BINARY_VERSION
|
116
110
|
end
|
117
111
|
|
118
112
|
def parse_version(version_info)
|
119
113
|
match_data = /wkhtmltopdf\s*(\d*\.\d*\.\d*\w*)/.match(version_info)
|
120
|
-
if match_data && (
|
114
|
+
if match_data && (match_data.length == 2)
|
121
115
|
Gem::Version.new(match_data[1])
|
122
116
|
else
|
123
117
|
DEFAULT_BINARY_VERSION
|
@@ -195,24 +189,26 @@ class WickedPdf
|
|
195
189
|
|
196
190
|
def parse_header_footer(options)
|
197
191
|
r = []
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
192
|
+
unless options.blank?
|
193
|
+
[:header, :footer].collect do |hf|
|
194
|
+
next if options[hf].blank?
|
195
|
+
opt_hf = options[hf]
|
196
|
+
r += make_options(opt_hf, [:center, :font_name, :left, :right], hf.to_s)
|
197
|
+
r += make_options(opt_hf, [:font_size, :spacing], hf.to_s, :numeric)
|
198
|
+
r += make_options(opt_hf, [:line], hf.to_s, :boolean)
|
199
|
+
if options[hf] && options[hf][:content]
|
200
|
+
@hf_tempfiles = [] unless defined?(@hf_tempfiles)
|
201
|
+
@hf_tempfiles.push(tf = WickedPdfTempfile.new("wicked_#{hf}_pdf.html"))
|
202
|
+
tf.write options[hf][:content]
|
203
|
+
tf.flush
|
204
|
+
options[hf][:html] = {}
|
205
|
+
options[hf][:html][:url] = "file:///#{tf.path}"
|
206
|
+
end
|
207
|
+
unless opt_hf[:html].blank?
|
208
|
+
r += make_option("#{hf}-html", opt_hf[:html][:url]) unless opt_hf[:html][:url].blank?
|
209
|
+
end
|
214
210
|
end
|
215
|
-
end
|
211
|
+
end
|
216
212
|
r
|
217
213
|
end
|
218
214
|
|
@@ -284,10 +280,12 @@ class WickedPdf
|
|
284
280
|
:dpi,
|
285
281
|
:page_size,
|
286
282
|
:page_width,
|
287
|
-
:title
|
283
|
+
:title,
|
284
|
+
:log_level])
|
288
285
|
r += make_options(options, [:lowquality,
|
289
286
|
:grayscale,
|
290
|
-
:no_pdf_compression
|
287
|
+
:no_pdf_compression,
|
288
|
+
:quiet], '', :boolean)
|
291
289
|
r += make_options(options, [:image_dpi,
|
292
290
|
:image_quality,
|
293
291
|
:page_height], '', :numeric)
|
@@ -319,24 +317,40 @@ class WickedPdf
|
|
319
317
|
:disable_internal_links,
|
320
318
|
:disable_external_links,
|
321
319
|
:print_media_type,
|
320
|
+
:disable_local_file_access,
|
321
|
+
:enable_local_file_access,
|
322
322
|
:disable_smart_shrinking,
|
323
323
|
:use_xserver,
|
324
324
|
:no_background,
|
325
|
+
:images,
|
326
|
+
:no_images,
|
325
327
|
:no_stop_slow_scripts], '', :boolean)
|
326
328
|
end
|
327
329
|
r
|
328
330
|
end
|
329
331
|
|
332
|
+
def possible_binary_locations
|
333
|
+
possible_locations = (ENV['PATH'].split(':') + %w[/usr/bin /usr/local/bin]).uniq
|
334
|
+
possible_locations += %w[~/bin] if ENV.key?('HOME')
|
335
|
+
end
|
336
|
+
|
330
337
|
def find_wkhtmltopdf_binary_path
|
331
|
-
possible_locations =
|
338
|
+
possible_locations = possible_binary_locations
|
332
339
|
exe_path ||= WickedPdf.config[:exe_path] unless WickedPdf.config.empty?
|
333
340
|
exe_path ||= begin
|
334
|
-
detected_path = (defined?(Bundler) ?
|
341
|
+
detected_path = (defined?(Bundler) ? Bundler.which('wkhtmltopdf') : `which wkhtmltopdf`).chomp
|
335
342
|
detected_path.present? && detected_path
|
336
|
-
rescue
|
343
|
+
rescue StandardError
|
337
344
|
nil
|
338
345
|
end
|
339
346
|
exe_path ||= possible_locations.map { |l| File.expand_path("#{l}/#{EXE_NAME}") }.find { |location| File.exist?(location) }
|
340
347
|
exe_path || ''
|
341
348
|
end
|
349
|
+
|
350
|
+
def find_xvfb_run_binary_path
|
351
|
+
possible_locations = possible_binary_locations
|
352
|
+
path = possible_locations.map { |l| File.expand_path("#{l}/xvfb-run") }.find { |location| File.exist?(location) }
|
353
|
+
raise StandardError.new('Could not find binary xvfb-run on the system.') unless path
|
354
|
+
path
|
355
|
+
end
|
342
356
|
end
|