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
@@ -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
|
@@ -8,7 +8,11 @@ class WickedPdf
|
|
8
8
|
base.class_eval do
|
9
9
|
alias_method_chain :render, :wicked_pdf
|
10
10
|
alias_method_chain :render_to_string, :wicked_pdf
|
11
|
-
|
11
|
+
if respond_to?(:after_action)
|
12
|
+
after_action :clean_temp_files
|
13
|
+
else
|
14
|
+
after_filter :clean_temp_files
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
@@ -19,47 +23,46 @@ class WickedPdf
|
|
19
23
|
|
20
24
|
base.class_eval do
|
21
25
|
after_action :clean_temp_files
|
26
|
+
end
|
27
|
+
end
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def render(options = nil, *args, &block)
|
27
|
-
render_with_wicked_pdf(options, *args, &block)
|
28
|
-
end
|
29
|
+
def render(options = nil, *args, &block)
|
30
|
+
render_with_wicked_pdf(options, *args, &block)
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
end
|
33
|
+
def render_to_string(options = nil, *args, &block)
|
34
|
+
render_to_string_with_wicked_pdf(options, *args, &block)
|
34
35
|
end
|
35
36
|
|
36
37
|
def render_with_wicked_pdf(options = nil, *args, &block)
|
37
38
|
if options.is_a?(Hash) && options.key?(:pdf)
|
38
|
-
log_pdf_creation
|
39
39
|
options[:basic_auth] = set_basic_auth(options)
|
40
40
|
make_and_send_pdf(options.delete(:pdf), (WickedPdf.config || {}).merge(options))
|
41
|
-
|
41
|
+
elsif respond_to?(:render_without_wicked_pdf)
|
42
|
+
# support alias_method_chain (module included)
|
42
43
|
render_without_wicked_pdf(options, *args, &block)
|
44
|
+
else
|
45
|
+
# support inheritance (module prepended)
|
46
|
+
method(:render).super_method.call(options, *args, &block)
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
46
50
|
def render_to_string_with_wicked_pdf(options = nil, *args, &block)
|
47
51
|
if options.is_a?(Hash) && options.key?(:pdf)
|
48
|
-
log_pdf_creation
|
49
52
|
options[:basic_auth] = set_basic_auth(options)
|
50
53
|
options.delete :pdf
|
51
54
|
make_pdf((WickedPdf.config || {}).merge(options))
|
52
|
-
|
55
|
+
elsif respond_to?(:render_to_string_without_wicked_pdf)
|
56
|
+
# support alias_method_chain (module included)
|
53
57
|
render_to_string_without_wicked_pdf(options, *args, &block)
|
58
|
+
else
|
59
|
+
# support inheritance (module prepended)
|
60
|
+
method(:render_to_string).super_method.call(options, *args, &block)
|
54
61
|
end
|
55
62
|
end
|
56
63
|
|
57
64
|
private
|
58
65
|
|
59
|
-
def log_pdf_creation
|
60
|
-
logger.info '*' * 15 + 'WICKED' + '*' * 15 if logger && logger.respond_to?(:info)
|
61
|
-
end
|
62
|
-
|
63
66
|
def set_basic_auth(options = {})
|
64
67
|
options[:basic_auth] ||= WickedPdf.config.fetch(:basic_auth) { false }
|
65
68
|
return unless options[:basic_auth] && request.env['HTTP_AUTHORIZATION']
|
@@ -76,8 +79,10 @@ class WickedPdf
|
|
76
79
|
:template => options[:template],
|
77
80
|
:layout => options[:layout],
|
78
81
|
:formats => options[:formats],
|
79
|
-
:handlers => options[:handlers]
|
82
|
+
:handlers => options[:handlers],
|
83
|
+
:assigns => options[:assigns]
|
80
84
|
}
|
85
|
+
render_opts[:inline] = options[:inline] if options[:inline]
|
81
86
|
render_opts[:locals] = options[:locals] if options[:locals]
|
82
87
|
render_opts[:file] = options[:file] if options[:file]
|
83
88
|
html_string = render_to_string(render_opts)
|
@@ -97,8 +102,10 @@ class WickedPdf
|
|
97
102
|
:layout => options[:layout],
|
98
103
|
:formats => options[:formats],
|
99
104
|
:handlers => options[:handlers],
|
105
|
+
:assigns => options[:assigns],
|
100
106
|
:content_type => 'text/html'
|
101
107
|
}
|
108
|
+
render_opts[:inline] = options[:inline] if options[:inline]
|
102
109
|
render_opts[:locals] = options[:locals] if options[:locals]
|
103
110
|
render_opts[:file] = options[:file] if options[:file]
|
104
111
|
render(render_opts)
|
@@ -121,7 +128,8 @@ class WickedPdf
|
|
121
128
|
:template => options[hf][:html][:template],
|
122
129
|
:layout => options[hf][:html][:layout],
|
123
130
|
:formats => options[hf][:html][:formats],
|
124
|
-
:handlers => options[hf][:html][:handlers]
|
131
|
+
:handlers => options[hf][:html][:handlers],
|
132
|
+
:assigns => options[hf][:html][:assigns]
|
125
133
|
}
|
126
134
|
render_opts[:locals] = options[hf][:html][:locals] if options[hf][:html][:locals]
|
127
135
|
render_opts[:file] = options[hf][:html][:file] if options[:file]
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class WickedPdf
|
2
|
+
module Progress
|
3
|
+
require 'pty' if RbConfig::CONFIG['target_os'] !~ /mswin|mingw/ # no support for windows
|
4
|
+
require 'English'
|
5
|
+
|
6
|
+
def track_progress?(options)
|
7
|
+
options[:progress] && !on_windows?
|
8
|
+
end
|
9
|
+
|
10
|
+
def invoke_with_progress(command, options)
|
11
|
+
output = []
|
12
|
+
begin
|
13
|
+
PTY.spawn(command.join(' ')) do |stdout, _stdin, pid|
|
14
|
+
begin
|
15
|
+
stdout.sync
|
16
|
+
stdout.each_line("\r") do |line|
|
17
|
+
output << line.chomp
|
18
|
+
options[:progress].call(line) if options[:progress]
|
19
|
+
end
|
20
|
+
rescue Errno::EIO # rubocop:disable Lint/HandleExceptions
|
21
|
+
# child process is terminated, this is expected behaviour
|
22
|
+
ensure
|
23
|
+
::Process.wait pid
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue PTY::ChildExited
|
27
|
+
puts 'The child process exited!'
|
28
|
+
end
|
29
|
+
err = output.join('\n')
|
30
|
+
raise "#{command} failed (exitstatus 0). Output was: #{err}" unless $CHILD_STATUS && $CHILD_STATUS.exitstatus.zero?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/wicked_pdf/railtie.rb
CHANGED
@@ -3,48 +3,19 @@ require 'wicked_pdf/wicked_pdf_helper'
|
|
3
3
|
require 'wicked_pdf/wicked_pdf_helper/assets'
|
4
4
|
|
5
5
|
class WickedPdf
|
6
|
-
if defined?(Rails)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
ActionView::Base.send :include, WickedPdfHelper::Assets
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
elsif Rails::VERSION::MAJOR == 4
|
18
|
-
|
19
|
-
class WickedRailtie < Rails::Railtie
|
20
|
-
initializer 'wicked_pdf.register' do |_app|
|
21
|
-
ActionController::Base.send :include, PdfHelper
|
22
|
-
ActionView::Base.send :include, WickedPdfHelper::Assets
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
elsif Rails::VERSION::MAJOR == 3
|
27
|
-
|
28
|
-
class WickedRailtie < Rails::Railtie
|
29
|
-
initializer 'wicked_pdf.register' do |_app|
|
30
|
-
ActionController::Base.send :include, PdfHelper
|
31
|
-
if Rails::VERSION::MINOR > 0 && Rails.configuration.assets.enabled
|
32
|
-
ActionView::Base.send :include, WickedPdfHelper::Assets
|
6
|
+
if defined?(Rails.env)
|
7
|
+
class WickedRailtie < Rails::Railtie
|
8
|
+
initializer 'wicked_pdf.register', :after => 'remotipart.controller_helper' do |_app|
|
9
|
+
ActiveSupport.on_load(:action_controller) do
|
10
|
+
if ActionController::Base.respond_to?(:prepend) &&
|
11
|
+
Object.method(:new).respond_to?(:super_method)
|
12
|
+
ActionController::Base.send :prepend, PdfHelper
|
33
13
|
else
|
34
|
-
|
14
|
+
ActionController::Base.send :include, PdfHelper
|
35
15
|
end
|
16
|
+
ActionView::Base.send :include, WickedPdfHelper::Assets
|
36
17
|
end
|
37
18
|
end
|
38
|
-
|
39
|
-
elsif Rails::VERSION::MAJOR == 2
|
40
|
-
|
41
|
-
unless ActionController::Base.instance_methods.include? 'render_with_wicked_pdf'
|
42
|
-
ActionController::Base.send :include, PdfHelper
|
43
|
-
end
|
44
|
-
unless ActionView::Base.instance_methods.include? 'wicked_pdf_stylesheet_link_tag'
|
45
|
-
ActionView::Base.send :include, WickedPdfHelper
|
46
|
-
end
|
47
|
-
|
48
19
|
end
|
49
20
|
|
50
21
|
if Mime::Type.lookup_by_extension(:pdf).nil?
|
data/lib/wicked_pdf/version.rb
CHANGED
@@ -23,8 +23,9 @@ class WickedPdf
|
|
23
23
|
|
24
24
|
def wicked_pdf_javascript_src_tag(jsfile, options = {})
|
25
25
|
jsfile = WickedPdfHelper.add_extension(jsfile, 'js')
|
26
|
+
type = ::Mime.respond_to?(:[]) ? ::Mime[:js] : ::Mime::JS # ::Mime[:js] cannot be used in Rails 2.3.
|
26
27
|
src = "file:///#{WickedPdfHelper.root_path.join('public', 'javascripts', jsfile)}"
|
27
|
-
content_tag('script', '', { 'type' =>
|
28
|
+
content_tag('script', '', { 'type' => type, 'src' => path_to_javascript(src) }.merge(options))
|
28
29
|
end
|
29
30
|
|
30
31
|
def wicked_pdf_javascript_include_tag(*sources)
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'net/http'
|
2
|
+
# If webpacker is used, need to check for version
|
3
|
+
require 'webpacker/version' if defined?(Webpacker)
|
2
4
|
|
3
5
|
class WickedPdf
|
4
6
|
module WickedPdfHelper
|
@@ -27,6 +29,32 @@ class WickedPdf
|
|
27
29
|
end.html_safe
|
28
30
|
end
|
29
31
|
|
32
|
+
def wicked_pdf_stylesheet_pack_tag(*sources)
|
33
|
+
return unless defined?(Webpacker)
|
34
|
+
if running_in_development?
|
35
|
+
stylesheet_pack_tag(*sources)
|
36
|
+
else
|
37
|
+
css_text = sources.collect do |source|
|
38
|
+
source = WickedPdfHelper.add_extension(source, 'css')
|
39
|
+
wicked_pdf_stylesheet_link_tag(webpacker_source_url(source))
|
40
|
+
end.join("\n")
|
41
|
+
css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def wicked_pdf_javascript_pack_tag(*sources)
|
46
|
+
return unless defined?(Webpacker)
|
47
|
+
|
48
|
+
if running_in_development?
|
49
|
+
javascript_pack_tag(*sources)
|
50
|
+
else
|
51
|
+
sources.collect do |source|
|
52
|
+
source = WickedPdfHelper.add_extension(source, 'js')
|
53
|
+
"<script type='text/javascript'>#{read_asset(webpacker_source_url(source))}</script>"
|
54
|
+
end.join("\n").html_safe
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
30
58
|
def wicked_pdf_image_tag(img, options = {})
|
31
59
|
image_tag wicked_pdf_asset_path(img), options
|
32
60
|
end
|
@@ -51,6 +79,16 @@ class WickedPdf
|
|
51
79
|
end
|
52
80
|
end
|
53
81
|
|
82
|
+
def wicked_pdf_asset_pack_path(asset)
|
83
|
+
return unless defined?(Webpacker)
|
84
|
+
|
85
|
+
if running_in_development?
|
86
|
+
asset_pack_path(asset)
|
87
|
+
else
|
88
|
+
wicked_pdf_asset_path webpacker_source_url(asset)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
54
92
|
private
|
55
93
|
|
56
94
|
# borrowed from actionpack/lib/action_view/helpers/asset_url_helper.rb
|
@@ -68,15 +106,20 @@ class WickedPdf
|
|
68
106
|
end
|
69
107
|
else
|
70
108
|
asset = find_asset(source)
|
71
|
-
|
109
|
+
if asset
|
110
|
+
# older versions need pathname, Sprockets 4 supports only filename
|
111
|
+
asset.respond_to?(:filename) ? asset.filename : asset.pathname
|
112
|
+
else
|
113
|
+
File.join(Rails.public_path, source)
|
114
|
+
end
|
72
115
|
end
|
73
116
|
end
|
74
117
|
|
75
118
|
def find_asset(path)
|
76
119
|
if Rails.application.assets.respond_to?(:find_asset)
|
77
|
-
Rails.application.assets.find_asset(path)
|
120
|
+
Rails.application.assets.find_asset(path, :base_path => Rails.application.root.to_s)
|
78
121
|
else
|
79
|
-
Sprockets::Railtie.build_environment(Rails.application).find_asset(path)
|
122
|
+
Sprockets::Railtie.build_environment(Rails.application).find_asset(path, :base_path => Rails.application.root.to_s)
|
80
123
|
end
|
81
124
|
end
|
82
125
|
|
@@ -93,7 +136,8 @@ class WickedPdf
|
|
93
136
|
end
|
94
137
|
|
95
138
|
def precompiled_or_absolute_asset?(source)
|
96
|
-
Rails.configuration.assets
|
139
|
+
!Rails.configuration.respond_to?(:assets) ||
|
140
|
+
Rails.configuration.assets.compile == false ||
|
97
141
|
source.to_s[0] == '/' ||
|
98
142
|
source.to_s.match(/\Ahttps?\:\/\//)
|
99
143
|
end
|
@@ -112,8 +156,8 @@ class WickedPdf
|
|
112
156
|
end
|
113
157
|
|
114
158
|
def read_from_uri(uri)
|
115
|
-
|
116
|
-
asset
|
159
|
+
asset = Net::HTTP.get(URI(uri))
|
160
|
+
asset.force_encoding('UTF-8') if asset
|
117
161
|
asset = gzip(asset) if WickedPdf.config[:expect_gzipped_remote_assets]
|
118
162
|
asset
|
119
163
|
end
|
@@ -125,6 +169,28 @@ class WickedPdf
|
|
125
169
|
rescue Zlib::GzipFile::Error
|
126
170
|
nil
|
127
171
|
end
|
172
|
+
|
173
|
+
def webpacker_source_url(source)
|
174
|
+
return unless defined?(Webpacker) && defined?(Webpacker::VERSION)
|
175
|
+
# In Webpacker 3.2.0 asset_pack_url is introduced
|
176
|
+
if Webpacker::VERSION >= '3.2.0'
|
177
|
+
asset_pack_url(source)
|
178
|
+
else
|
179
|
+
source_path = asset_pack_path(source)
|
180
|
+
# Remove last slash from root path
|
181
|
+
root_url[0...-1] + source_path
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def running_in_development?
|
186
|
+
return unless defined?(Webpacker)
|
187
|
+
# :dev_server method was added in webpacker 3.0.0
|
188
|
+
if Webpacker.respond_to?(:dev_server)
|
189
|
+
Webpacker.dev_server.running?
|
190
|
+
else
|
191
|
+
Rails.env.development? || Rails.env.test?
|
192
|
+
end
|
193
|
+
end
|
128
194
|
end
|
129
195
|
end
|
130
196
|
end
|
@@ -5,10 +5,32 @@ module ActionController
|
|
5
5
|
def render_to_string(opts = {})
|
6
6
|
opts.to_s
|
7
7
|
end
|
8
|
+
|
9
|
+
def self.alias_method_chain(_target, _feature); end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ActionControllerMock
|
14
|
+
class Base
|
15
|
+
def render(_)
|
16
|
+
[:base]
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_to_string; end
|
20
|
+
|
21
|
+
def self.after_action(_); end
|
8
22
|
end
|
9
23
|
end
|
10
24
|
|
11
25
|
class PdfHelperTest < ActionController::TestCase
|
26
|
+
module SomePatch
|
27
|
+
def render(_)
|
28
|
+
super.tap do |s|
|
29
|
+
s << :patched
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
12
34
|
def setup
|
13
35
|
@ac = ActionController::Base.new
|
14
36
|
end
|
@@ -22,4 +44,53 @@ class PdfHelperTest < ActionController::TestCase
|
|
22
44
|
:header => { :html => { :template => 'hf.html.erb' } })
|
23
45
|
assert_match %r{^file:\/\/\/.*wicked_header_pdf.*\.html}, options[:header][:html][:url]
|
24
46
|
end
|
47
|
+
|
48
|
+
test 'should not interfere with already prepended patches' do
|
49
|
+
# Emulate railtie
|
50
|
+
if Rails::VERSION::MAJOR >= 5
|
51
|
+
# this spec tests the following:
|
52
|
+
# if another gem prepends a render method to ActionController::Base
|
53
|
+
# before wicked_pdf does, does calling render trigger an infinite loop?
|
54
|
+
# this spec fails with 6392bea1fe3a41682dfd7c20fd9c179b5a758f59 because PdfHelper
|
55
|
+
# aliases the render method prepended by the other gem to render_without_pdf, then
|
56
|
+
# base_evals its own definition of render, which calls render_with_pdf -> render_without_pdf.
|
57
|
+
# If the other gem uses the prepend inhertinance pattern (calling super instead of aliasing),
|
58
|
+
# when it calls super it calls the base_eval'd version of render instead of going up the
|
59
|
+
# inheritance chain, causing an infinite loop.
|
60
|
+
|
61
|
+
# This fiddling with consts is required to get around the fact that PdfHelper checks
|
62
|
+
# that it is being prepended to ActionController::Base
|
63
|
+
OriginalBase = ActionController::Base
|
64
|
+
ActionController.send(:remove_const, :Base)
|
65
|
+
ActionController.const_set(:Base, ActionControllerMock::Base)
|
66
|
+
|
67
|
+
# Emulate another gem being loaded before wicked
|
68
|
+
ActionController::Base.prepend(SomePatch)
|
69
|
+
ActionController::Base.prepend(::WickedPdf::PdfHelper)
|
70
|
+
|
71
|
+
begin
|
72
|
+
# test that wicked's render method is actually called
|
73
|
+
ac = ActionController::Base.new
|
74
|
+
ac.expects(:render_with_wicked_pdf)
|
75
|
+
ac.render(:cats)
|
76
|
+
|
77
|
+
# test that calling render does not trigger infinite loop
|
78
|
+
ac = ActionController::Base.new
|
79
|
+
assert_equal [:base, :patched], ac.render(:cats)
|
80
|
+
rescue SystemStackError
|
81
|
+
assert_equal true, false # force spec failure
|
82
|
+
ensure
|
83
|
+
ActionController.send(:remove_const, :Base)
|
84
|
+
ActionController.const_set(:Base, OriginalBase)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
test 'should call after_action instead of after_filter when able' do
|
90
|
+
ActionController::Base.expects(:after_filter).with(:clean_temp_files).never
|
91
|
+
ActionController::Base.expects(:after_action).with(:clean_temp_files).once
|
92
|
+
ActionController::Base.class_eval do
|
93
|
+
include ::WickedPdf::PdfHelper
|
94
|
+
end
|
95
|
+
end
|
25
96
|
end
|