wicked_pdf 1.1.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/issue_template.md +15 -0
- data/.github/workflows/ci.yml +56 -0
- data/.rubocop.yml +62 -0
- data/.rubocop_todo.yml +81 -39
- data/CHANGELOG.md +194 -45
- data/README.md +136 -28
- data/Rakefile +12 -9
- data/gemfiles/5.0.gemfile +3 -1
- data/gemfiles/5.1.gemfile +8 -0
- data/gemfiles/5.2.gemfile +9 -0
- data/gemfiles/6.0.gemfile +10 -0
- data/gemfiles/6.1.gemfile +11 -0
- data/gemfiles/7.0.gemfile +11 -0
- data/generators/wicked_pdf/templates/wicked_pdf.rb +14 -5
- data/lib/generators/wicked_pdf_generator.rb +5 -9
- data/lib/wicked_pdf/binary.rb +65 -0
- data/lib/wicked_pdf/middleware.rb +1 -1
- data/lib/wicked_pdf/option_parser.rb +230 -0
- data/lib/wicked_pdf/pdf_helper.rb +35 -42
- data/lib/wicked_pdf/progress.rb +33 -0
- data/lib/wicked_pdf/railtie.rb +6 -44
- data/lib/wicked_pdf/tempfile.rb +33 -3
- data/lib/wicked_pdf/version.rb +1 -1
- data/lib/wicked_pdf/wicked_pdf_helper/assets.rb +200 -17
- data/lib/wicked_pdf/wicked_pdf_helper.rb +2 -1
- data/lib/wicked_pdf.rb +64 -275
- 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/functional/wicked_pdf_helper_assets_test.rb +61 -0
- data/test/test_helper.rb +13 -8
- data/test/unit/wicked_pdf_binary_test.rb +26 -0
- data/test/unit/wicked_pdf_option_parser_test.rb +133 -0
- data/test/unit/wicked_pdf_test.rb +25 -146
- data/test/unit/wkhtmltopdf_location_test.rb +48 -0
- data/wicked_pdf.gemspec +20 -13
- metadata +79 -36
- data/.travis.yml +0 -57
- 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/gemfiles/4.0.gemfile +0 -6
- data/gemfiles/4.1.gemfile +0 -6
- data/gemfiles/4.2.gemfile +0 -6
- data/gemfiles/rails_edge.gemfile +0 -6
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# Wicked PDF [![Build Status](https://
|
1
|
+
# Wicked PDF [![Gem Version](https://badge.fury.io/rb/wicked_pdf.svg)](http://badge.fury.io/rb/wicked_pdf) [![Build Status](https://github.com/mileszs/wicked_pdf/actions/workflows/ci.yml/badge.svg)](https://github.com/mileszs/wicked_pdf/actions/workflows/ci.yml) [![Code Climate](https://codeclimate.com/github/mileszs/wicked_pdf/badges/gpa.svg)](https://codeclimate.com/github/mileszs/wicked_pdf) [![Open Source Helpers](https://www.codetriage.com/mileszs/wicked_pdf/badges/users.svg)](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,13 +35,16 @@ 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
|
|
42
44
|
```ruby
|
43
|
-
WickedPdf.
|
44
|
-
exe_path
|
45
|
+
WickedPdf.configure do |c|
|
46
|
+
c.exe_path = '/usr/local/bin/wkhtmltopdf',
|
47
|
+
c.enable_local_file_access = true
|
45
48
|
}
|
46
49
|
```
|
47
50
|
|
@@ -83,7 +86,6 @@ The wkhtmltopdf binary is run outside of your Rails application; therefore, your
|
|
83
86
|
</body>
|
84
87
|
</html>
|
85
88
|
```
|
86
|
-
|
87
89
|
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
90
|
|
89
91
|
```html
|
@@ -106,23 +108,35 @@ Using wicked_pdf_helpers with asset pipeline raises `Asset names passed to helpe
|
|
106
108
|
</html>
|
107
109
|
```
|
108
110
|
|
111
|
+
#### Webpacker usage
|
112
|
+
|
113
|
+
wicked_pdf supports webpack assets.
|
114
|
+
|
115
|
+
- Use `wicked_pdf_stylesheet_pack_tag` for stylesheets
|
116
|
+
- Use `wicked_pdf_javascript_pack_tag` for javascripts
|
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.
|
112
128
|
```html
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
129
|
+
<!doctype html>
|
130
|
+
<html>
|
131
|
+
<head>
|
132
|
+
<%= javascript_include_tag "http://code.jquery.com/jquery-1.10.0.min.js" %>
|
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',
|
@@ -168,13 +185,25 @@ class ThingsController < ApplicationController
|
|
168
185
|
enable_plugins: true,
|
169
186
|
disable_internal_links: true,
|
170
187
|
disable_external_links: true,
|
188
|
+
keep_relative_links: true,
|
171
189
|
print_media_type: true,
|
190
|
+
|
191
|
+
# define as true the key 'disable_local_file_access' or 'enable_local_file_access', not both
|
192
|
+
disable_local_file_access: true,
|
193
|
+
enable_local_file_access: false, # must be true when using wkhtmltopdf > 0.12.6
|
194
|
+
allow: ["#{Rails.root}/public"], # could be an array or a single string
|
195
|
+
|
172
196
|
disable_smart_shrinking: true,
|
173
197
|
use_xserver: true,
|
174
|
-
background: false, #
|
198
|
+
background: false, # background needs to be true to enable background colors to render
|
175
199
|
no_background: true,
|
200
|
+
no_stop_slow_scripts: false,
|
176
201
|
viewport_size: 'TEXT', # available only with use_xserver or patched QT
|
177
202
|
extra: '', # directly inserted into the command to wkhtmltopdf
|
203
|
+
raise_on_all_errors: nil, # raise error for any stderr output. Such as missing media, image assets
|
204
|
+
raise_on_missing_assets: nil, # raise when trying to access a missing asset
|
205
|
+
log_level: 'info', # Available values: none, error, warn, or info - only available with wkhtmltopdf 0.12.5+
|
206
|
+
quiet: false, # `false` is same as `log_level: 'info'`, `true` is same as `log_level: 'none'`
|
178
207
|
outline: { outline: true,
|
179
208
|
outline_depth: LEVEL },
|
180
209
|
margin: { top: SIZE, # default 10 (mm)
|
@@ -230,7 +259,9 @@ class ThingsController < ApplicationController
|
|
230
259
|
disable_links: true,
|
231
260
|
disable_toc_links: true,
|
232
261
|
disable_back_links:true,
|
233
|
-
xsl_style_sheet: 'file.xsl'} # optional XSLT stylesheet to use for styling table of contents
|
262
|
+
xsl_style_sheet: 'file.xsl'}, # optional XSLT stylesheet to use for styling table of contents
|
263
|
+
progress: proc { |output| puts output }, # proc called when console output changes
|
264
|
+
delete_temporary_files: true # explicitly delete temporary files, default false
|
234
265
|
end
|
235
266
|
end
|
236
267
|
end
|
@@ -265,11 +296,22 @@ pdf = WickedPdf.new.pdf_from_html_file('/your/absolute/path/here')
|
|
265
296
|
# create a pdf from a URL
|
266
297
|
pdf = WickedPdf.new.pdf_from_url('https://github.com/mileszs/wicked_pdf')
|
267
298
|
|
268
|
-
# create a pdf from string using templates, layouts and content option for header or footer
|
299
|
+
# create a pdf from string using templates, layouts, and content option for header or footer
|
269
300
|
pdf = WickedPdf.new.pdf_from_string(
|
270
|
-
render_to_string('templates/pdf', layout: 'pdfs/layout_pdf'),
|
301
|
+
render_to_string('templates/pdf', layout: 'pdfs/layout_pdf.html'),
|
271
302
|
footer: {
|
272
|
-
content: render_to_string(
|
303
|
+
content: render_to_string(
|
304
|
+
'templates/footer',
|
305
|
+
layout: 'pdfs/layout_pdf.html'
|
306
|
+
)
|
307
|
+
}
|
308
|
+
)
|
309
|
+
|
310
|
+
# It is possible to use footer/header templates without a layout, in that case you need to provide a valid HTML document
|
311
|
+
pdf = WickedPdf.new.pdf_from_string(
|
312
|
+
render_to_string('templates/full_pdf_template'),
|
313
|
+
header: {
|
314
|
+
content: render_to_string('templates/full_header_template')
|
273
315
|
}
|
274
316
|
)
|
275
317
|
|
@@ -281,12 +323,33 @@ save_path = Rails.root.join('pdfs','filename.pdf')
|
|
281
323
|
File.open(save_path, 'wb') do |file|
|
282
324
|
file << pdf
|
283
325
|
end
|
326
|
+
|
327
|
+
# you can also track progress on your PDF generation, such as when using it from within a Resque job
|
328
|
+
class PdfJob
|
329
|
+
def perform
|
330
|
+
blk = proc { |output|
|
331
|
+
match = output.match(/\[.+\] Page (?<current_page>\d+) of (?<total_pages>\d+)/)
|
332
|
+
if match
|
333
|
+
current_page = match[:current_page].to_i
|
334
|
+
total_pages = match[:total_pages].to_i
|
335
|
+
message = "Generated #{current_page} of #{total_pages} pages"
|
336
|
+
at current_page, total_pages, message
|
337
|
+
end
|
338
|
+
}
|
339
|
+
WickedPdf.new.pdf_from_string(html, progress: blk)
|
340
|
+
end
|
341
|
+
end
|
284
342
|
```
|
285
343
|
If you need to display utf encoded characters, add this to your pdf views or layouts:
|
286
344
|
```html
|
287
345
|
<meta charset="utf-8" />
|
288
346
|
```
|
289
|
-
|
347
|
+
If you need to return a PDF in a controller with Rails in API mode:
|
348
|
+
```ruby
|
349
|
+
pdf_html = ActionController::Base.new.render_to_string(template: 'controller_name/action_name', layout: 'pdf')
|
350
|
+
pdf = WickedPdf.new.pdf_from_string(pdf_html)
|
351
|
+
send_data pdf, filename: 'file.pdf'
|
352
|
+
```
|
290
353
|
### Page Breaks
|
291
354
|
|
292
355
|
You can control page breaks with CSS.
|
@@ -340,7 +403,7 @@ If you would like to have WickedPdf automatically generate PDF views for all (or
|
|
340
403
|
require 'wicked_pdf'
|
341
404
|
config.middleware.use WickedPdf::Middleware
|
342
405
|
```
|
343
|
-
If you want to turn on or off the middleware for certain
|
406
|
+
If you want to turn on or off the middleware for certain URLs, use the `:only` or `:except` conditions like so:
|
344
407
|
```ruby
|
345
408
|
# conditions can be plain strings or regular expressions, and you can supply only one or an array
|
346
409
|
config.middleware.use WickedPdf::Middleware, {}, only: '/invoice'
|
@@ -348,6 +411,19 @@ config.middleware.use WickedPdf::Middleware, {}, except: [ %r[^/admin], '/secret
|
|
348
411
|
```
|
349
412
|
If you use the standard `render pdf: 'some_pdf'` in your app, you will want to exclude those actions from the middleware.
|
350
413
|
|
414
|
+
|
415
|
+
### Include in an email as an attachment
|
416
|
+
|
417
|
+
To include a rendered pdf file in an email you can do the following:
|
418
|
+
|
419
|
+
```ruby
|
420
|
+
attachments['attachment.pdf'] = WickedPdf.new.pdf_from_string(
|
421
|
+
render_to_string('link_to_view.pdf.erb', layout: 'pdf')
|
422
|
+
)
|
423
|
+
```
|
424
|
+
|
425
|
+
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.
|
426
|
+
|
351
427
|
### Further Reading
|
352
428
|
|
353
429
|
Mike Ackerman's post [How To Create PDFs in Rails](https://www.viget.com/articles/how-to-create-pdfs-in-rails)
|
@@ -358,8 +434,22 @@ JESii's post [WickedPDF, wkhtmltopdf, and Heroku...a tricky combination](http://
|
|
358
434
|
|
359
435
|
Berislav Babic's post [Send PDF attachments from Rails with WickedPdf and ActionMailer](http://berislavbabic.com/send-pdf-attachments-from-rails-with-wickedpdf-and-actionmailer/)
|
360
436
|
|
437
|
+
Corsego's 2021 post [Complete guide to generating PDFs with gem wicked_pdf](https://blog.corsego.com/gem-wicked-pdf)
|
438
|
+
|
439
|
+
PDFTron's post [How to Generate PDFs With Ruby on Rails](https://www.pdftron.com/blog/rails/how-to-generate-pdf-with-ruby-on-rails/)
|
440
|
+
|
361
441
|
StackOverflow [questions with the tag "wicked-pdf"](http://stackoverflow.com/questions/tagged/wicked-pdf)
|
362
442
|
|
443
|
+
### Screencasts
|
444
|
+
|
445
|
+
* SupeRails Screencast [EN]
|
446
|
+
|
447
|
+
[![Ruby on Rails #17 generate, save, send PDFs with gem wicked_pdf](https://i3.ytimg.com/vi/tFvtwEmW-GE/hqdefault.jpg)](https://youtu.be/tFvtwEmW-GE)
|
448
|
+
|
449
|
+
* codigofacilito Screencast [ES]
|
450
|
+
|
451
|
+
[![Generar PDF con Ruby on Rails - Tutorial](https://i3.ytimg.com/vi/jeWM_gusmJc/hqdefault.jpg)](https://youtu.be/jeWM_gusmJc)
|
452
|
+
|
363
453
|
### Debugging
|
364
454
|
|
365
455
|
Now you can use a debug param on the URL that shows you the content of the pdf in plain html to design it faster.
|
@@ -370,12 +460,30 @@ http://localhost:3001/CONTROLLER/X.pdf?debug
|
|
370
460
|
|
371
461
|
However, the wicked_pdf_* helpers will use file:/// paths for assets when using :show_as_html, and your browser's cross-domain safety feature will kick in, and not render them. To get around this, you can load your assets like so in your templates:
|
372
462
|
```html
|
373
|
-
|
463
|
+
<%= params.key?('debug') ? image_tag('foo') : wicked_pdf_image_tag('foo') %>
|
374
464
|
```
|
375
465
|
|
376
466
|
#### Gotchas
|
377
467
|
|
378
|
-
If one image from your HTML cannot be found (relative or wrong path for
|
468
|
+
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).
|
469
|
+
|
470
|
+
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.
|
471
|
+
|
472
|
+
### Security considerations
|
473
|
+
|
474
|
+
WickedPdf renders page content on the server by saving HTML and assets to temporary files on disk, then executing `wkhtmltopdf` to convert that HTML to a PDF file.
|
475
|
+
|
476
|
+
It is highly recommended if you allow user-generated HTML/CSS/JS to be converted to PDF, you sanitize it first, or at least disallow requesting content from internal IP addresses and hostnames.
|
477
|
+
|
478
|
+
For example, these could potentially leak internal AWS metadata:
|
479
|
+
```html
|
480
|
+
<iframe src="http://169.254.169.254/latest/meta-data/"></iframe>
|
481
|
+
<object data="http://169.254.169.254/latest/meta-data/" type="text/html">
|
482
|
+
```
|
483
|
+
|
484
|
+
Thank you to Adam Gold from [Snyk](https://snyk.io) for reporting this.
|
485
|
+
We are considering adding host allow & block lists and/or potentially HTML element sanitizing.
|
486
|
+
Please open an issue or PR to help us out with this.
|
379
487
|
|
380
488
|
### Inspiration
|
381
489
|
|
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rails/version'
|
|
5
5
|
require 'bundler/gem_tasks'
|
6
6
|
|
7
7
|
desc 'Default: run unit tests.'
|
8
|
-
task :default => [
|
8
|
+
task :default => %i[setup_and_run_tests rubocop]
|
9
9
|
|
10
10
|
desc 'Test the wicked_pdf plugin.'
|
11
11
|
Rake::TestTask.new(:test) do |t|
|
@@ -17,16 +17,13 @@ end
|
|
17
17
|
|
18
18
|
desc 'Run RuboCop'
|
19
19
|
task :rubocop do
|
20
|
-
next unless RUBY_VERSION >= '2.0.0'
|
21
20
|
require 'rubocop/rake_task'
|
22
21
|
RuboCop::RakeTask.new
|
23
22
|
end
|
24
23
|
|
25
24
|
desc 'Setup and run all tests'
|
26
25
|
task :setup_and_run_tests do
|
27
|
-
unless File.exist?('test/dummy/config/environment.rb')
|
28
|
-
Rake::Task[:dummy_generate].invoke
|
29
|
-
end
|
26
|
+
Rake::Task[:dummy_generate].invoke unless File.exist?('test/dummy/config/environment.rb')
|
30
27
|
Rake::Task[:test].invoke
|
31
28
|
end
|
32
29
|
|
@@ -34,18 +31,24 @@ desc 'Generate dummy application for test cases'
|
|
34
31
|
task :dummy_generate do
|
35
32
|
Rake::Task[:dummy_remove].invoke
|
36
33
|
puts 'Creating dummy application to run tests'
|
37
|
-
|
38
|
-
system("rails #{command} test/dummy")
|
34
|
+
system('rails new test/dummy --database=sqlite3')
|
39
35
|
system('touch test/dummy/db/schema.rb')
|
36
|
+
FileUtils.cp 'test/fixtures/database.yml', 'test/dummy/config/'
|
40
37
|
FileUtils.rm_r Dir.glob('test/dummy/test/*')
|
38
|
+
|
39
|
+
# rails 6 needs this to be present before start:
|
40
|
+
FileUtils.mkdir_p('test/dummy/app/assets/config')
|
41
|
+
FileUtils.mkdir_p('test/dummy/app/assets/javascripts')
|
42
|
+
FileUtils.cp 'test/fixtures/manifest.js', 'test/dummy/app/assets/config/'
|
43
|
+
FileUtils.cp 'test/fixtures/wicked.js', 'test/dummy/app/assets/javascripts/'
|
41
44
|
end
|
42
45
|
|
43
46
|
desc 'Remove dummy application'
|
44
47
|
task :dummy_remove do
|
45
|
-
FileUtils.rm_r Dir.glob('test/dummy
|
48
|
+
FileUtils.rm_r Dir.glob('test/dummy/')
|
46
49
|
end
|
47
50
|
|
48
|
-
desc 'Generate documentation for the wicked_pdf
|
51
|
+
desc 'Generate documentation for the wicked_pdf gem.'
|
49
52
|
RDoc::Task.new(:rdoc) do |rdoc|
|
50
53
|
rdoc.rdoc_dir = 'rdoc'
|
51
54
|
rdoc.title = 'WickedPdf'
|
data/gemfiles/5.0.gemfile
CHANGED
@@ -8,14 +8,23 @@
|
|
8
8
|
#
|
9
9
|
# https://github.com/mileszs/wicked_pdf/blob/master/README.md
|
10
10
|
|
11
|
-
WickedPdf.
|
11
|
+
WickedPdf.configure do |config|
|
12
12
|
# Path to the wkhtmltopdf executable: This usually isn't needed if using
|
13
13
|
# one of the wkhtmltopdf-binary family of gems.
|
14
|
-
# exe_path
|
14
|
+
# config.exe_path = '/usr/local/bin/wkhtmltopdf',
|
15
15
|
# or
|
16
|
-
# exe_path
|
16
|
+
# config.exe_path = Gem.bin_path('wkhtmltopdf-binary', 'wkhtmltopdf')
|
17
|
+
|
18
|
+
# Needed for wkhtmltopdf 0.12.6+ to use many wicked_pdf asset helpers
|
19
|
+
# config.enable_local_file_access = true,
|
17
20
|
|
18
21
|
# Layout file to be used for all PDFs
|
19
22
|
# (but can be overridden in `render :pdf` calls)
|
20
|
-
# layout
|
21
|
-
|
23
|
+
# config.layout = 'pdf.html',
|
24
|
+
|
25
|
+
# Using wkhtmltopdf without an X server can be achieved by enabling the
|
26
|
+
# 'use_xvfb' flag. This will wrap all wkhtmltopdf commands around the
|
27
|
+
# 'xvfb-run' command, in order to simulate an X server.
|
28
|
+
#
|
29
|
+
# config.use_xvfb = true,
|
30
|
+
end
|
@@ -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
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class WickedPdf
|
2
|
+
class Binary
|
3
|
+
EXE_NAME = 'wkhtmltopdf'.freeze
|
4
|
+
|
5
|
+
attr_reader :path, :default_version
|
6
|
+
|
7
|
+
def initialize(binary_path, default_version = WickedPdf::DEFAULT_BINARY_VERSION)
|
8
|
+
@path = binary_path || find_binary_path
|
9
|
+
@default_version = default_version
|
10
|
+
|
11
|
+
raise "Location of #{EXE_NAME} unknown" if @path.empty?
|
12
|
+
raise "Bad #{EXE_NAME}'s path: #{@path}" unless File.exist?(@path)
|
13
|
+
raise "#{EXE_NAME} is not executable" unless File.executable?(@path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
@version ||= retrieve_binary_version
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_version_string(version_info)
|
21
|
+
match_data = /wkhtmltopdf\s*(\d*\.\d*\.\d*\w*)/.match(version_info)
|
22
|
+
if match_data && (match_data.length == 2)
|
23
|
+
Gem::Version.new(match_data[1])
|
24
|
+
else
|
25
|
+
default_version
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def xvfb_run_path
|
30
|
+
path = possible_binary_locations.map { |l| File.expand_path("#{l}/xvfb-run") }.find { |location| File.exist?(location) }
|
31
|
+
raise StandardError, 'Could not find binary xvfb-run on the system.' unless path
|
32
|
+
|
33
|
+
path
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def retrieve_binary_version
|
39
|
+
_stdin, stdout, _stderr = Open3.popen3(@path + ' -V')
|
40
|
+
parse_version_string(stdout.gets(nil))
|
41
|
+
rescue StandardError
|
42
|
+
default_version
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_binary_path
|
46
|
+
exe_path ||= WickedPdf.config[:exe_path] unless WickedPdf.config.empty?
|
47
|
+
exe_path ||= possible_which_path
|
48
|
+
exe_path ||= possible_binary_locations.map { |l| File.expand_path("#{l}/#{EXE_NAME}") }.find { |location| File.exist?(location) }
|
49
|
+
exe_path || ''
|
50
|
+
end
|
51
|
+
|
52
|
+
def possible_which_path
|
53
|
+
detected_path = (defined?(Bundler) ? Bundler.which('wkhtmltopdf') : `which wkhtmltopdf`).chomp
|
54
|
+
detected_path.present? && detected_path
|
55
|
+
rescue StandardError
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
59
|
+
def possible_binary_locations
|
60
|
+
possible_locations = (ENV['PATH'].split(':') + %w[/usr/bin /usr/local/bin]).uniq
|
61
|
+
possible_locations += %w[~/bin] if ENV.key?('HOME')
|
62
|
+
possible_locations
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -80,7 +80,7 @@ class WickedPdf
|
|
80
80
|
|
81
81
|
def set_request_to_render_as_pdf(env)
|
82
82
|
@render_pdf = true
|
83
|
-
%w
|
83
|
+
%w[PATH_INFO REQUEST_URI].each { |e| env[e] = env[e].sub(%r{\.pdf\b}, '') }
|
84
84
|
env['HTTP_ACCEPT'] = concat(env['HTTP_ACCEPT'], Rack::Mime.mime_type('.html'))
|
85
85
|
env['Rack-Middleware-WickedPdf'] = 'true'
|
86
86
|
end
|