wicked_pdf 1.0.6 → 2.6.3
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/.github/workflows/ci.yml +56 -0
- data/.rubocop.yml +60 -0
- data/.rubocop_todo.yml +83 -29
- data/CHANGELOG.md +182 -35
- data/README.md +188 -30
- data/Rakefile +13 -10
- data/gemfiles/5.0.gemfile +8 -0
- 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 +12 -0
- data/gemfiles/7.0.gemfile +12 -0
- data/generators/wicked_pdf/templates/wicked_pdf.rb +9 -0
- 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 +229 -0
- data/lib/wicked_pdf/pdf_helper.rb +99 -85
- data/lib/wicked_pdf/progress.rb +33 -0
- data/lib/wicked_pdf/railtie.rb +6 -33
- data/lib/wicked_pdf/tempfile.rb +38 -7
- data/lib/wicked_pdf/version.rb +1 -1
- data/lib/wicked_pdf/wicked_pdf_helper/assets.rb +213 -91
- data/lib/wicked_pdf/wicked_pdf_helper.rb +29 -26
- data/lib/wicked_pdf.rb +37 -272
- data/test/fixtures/database.yml +4 -0
- data/test/fixtures/manifest.js +3 -0
- data/test/fixtures/wicked.js +1 -0
- data/test/functional/pdf_helper_test.rb +74 -5
- data/test/functional/wicked_pdf_helper_assets_test.rb +27 -9
- data/test/functional/wicked_pdf_helper_test.rb +15 -13
- data/test/test_helper.rb +16 -7
- data/test/unit/wicked_pdf_binary_test.rb +26 -0
- data/test/unit/wicked_pdf_option_parser_test.rb +128 -0
- data/test/unit/wicked_pdf_test.rb +11 -149
- data/test/unit/wkhtmltopdf_location_test.rb +48 -0
- data/wicked_pdf.gemspec +21 -14
- metadata +68 -37
- data/.travis.yml +0 -66
- data/gemfiles/2.3.gemfile +0 -10
- data/gemfiles/3.0.gemfile +0 -7
- data/gemfiles/3.1.gemfile +0 -8
- data/gemfiles/3.2.gemfile +0 -7
- 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
@@ -1,120 +1,242 @@
|
|
1
|
-
require '
|
1
|
+
require 'net/http'
|
2
|
+
require 'delegate'
|
2
3
|
|
3
|
-
|
4
|
-
module
|
5
|
-
|
4
|
+
class WickedPdf
|
5
|
+
module WickedPdfHelper
|
6
|
+
module Assets
|
7
|
+
ASSET_URL_REGEX = /url\(['"]?([^'"]+?)['"]?\)/
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
class PropshaftAsset < SimpleDelegator
|
10
|
+
def content_type
|
11
|
+
super.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
content
|
16
|
+
end
|
17
|
+
|
18
|
+
def filename
|
19
|
+
path.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def wicked_pdf_asset_base64(path)
|
24
|
+
asset = find_asset(path)
|
25
|
+
raise "Could not find asset '#{path}'" if asset.nil?
|
13
26
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
27
|
+
base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
|
28
|
+
"data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Using `image_tag` with URLs when generating PDFs (specifically large PDFs with lots of pages) can cause buffer/stack overflows.
|
32
|
+
#
|
33
|
+
def wicked_pdf_url_base64(url)
|
34
|
+
response = Net::HTTP.get_response(URI(url))
|
19
35
|
|
20
|
-
|
21
|
-
|
22
|
-
"
|
36
|
+
if response.is_a?(Net::HTTPSuccess)
|
37
|
+
base64 = Base64.encode64(response.body).gsub(/\s+/, '')
|
38
|
+
"data:#{response.content_type};base64,#{Rack::Utils.escape(base64)}"
|
23
39
|
else
|
24
|
-
"
|
40
|
+
Rails.logger.warn("[wicked_pdf] #{response.code} #{response.message}: #{url}")
|
41
|
+
nil
|
25
42
|
end
|
26
|
-
end
|
27
|
-
end
|
43
|
+
end
|
28
44
|
|
29
|
-
|
30
|
-
|
31
|
-
|
45
|
+
def wicked_pdf_stylesheet_link_tag(*sources)
|
46
|
+
stylesheet_contents = sources.collect do |source|
|
47
|
+
source = WickedPdfHelper.add_extension(source, 'css')
|
48
|
+
"<style type='text/css'>#{read_asset(source)}</style>"
|
49
|
+
end.join("\n")
|
50
|
+
|
51
|
+
stylesheet_contents.gsub(ASSET_URL_REGEX) do
|
52
|
+
if Regexp.last_match[1].starts_with?('data:')
|
53
|
+
"url(#{Regexp.last_match[1]})"
|
54
|
+
else
|
55
|
+
"url(#{wicked_pdf_asset_path(Regexp.last_match[1])})"
|
56
|
+
end
|
57
|
+
end.html_safe
|
58
|
+
end
|
32
59
|
|
33
|
-
|
34
|
-
|
35
|
-
javascript_include_tag wicked_pdf_asset_path(jsfile), options
|
36
|
-
end
|
60
|
+
def wicked_pdf_stylesheet_pack_tag(*sources)
|
61
|
+
return unless defined?(Webpacker)
|
37
62
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
63
|
+
if running_in_development?
|
64
|
+
stylesheet_pack_tag(*sources)
|
65
|
+
else
|
66
|
+
css_text = sources.collect do |source|
|
67
|
+
source = WickedPdfHelper.add_extension(source, 'css')
|
68
|
+
wicked_pdf_stylesheet_link_tag(webpacker_source_url(source))
|
69
|
+
end.join("\n")
|
70
|
+
css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def wicked_pdf_javascript_pack_tag(*sources)
|
75
|
+
return unless defined?(Webpacker)
|
44
76
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
77
|
+
if running_in_development?
|
78
|
+
javascript_pack_tag(*sources)
|
79
|
+
else
|
80
|
+
sources.collect do |source|
|
81
|
+
source = WickedPdfHelper.add_extension(source, 'js')
|
82
|
+
"<script type='text/javascript'>#{read_asset(webpacker_source_url(source))}</script>"
|
83
|
+
end.join("\n").html_safe
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def wicked_pdf_image_tag(img, options = {})
|
88
|
+
image_tag wicked_pdf_asset_path(img), options
|
50
89
|
end
|
51
|
-
end
|
52
90
|
|
53
|
-
|
91
|
+
def wicked_pdf_javascript_src_tag(jsfile, options = {})
|
92
|
+
jsfile = WickedPdfHelper.add_extension(jsfile, 'js')
|
93
|
+
javascript_include_tag wicked_pdf_asset_path(jsfile), options
|
94
|
+
end
|
54
95
|
|
55
|
-
|
56
|
-
|
96
|
+
def wicked_pdf_javascript_include_tag(*sources)
|
97
|
+
sources.collect do |source|
|
98
|
+
source = WickedPdfHelper.add_extension(source, 'js')
|
99
|
+
"<script type='text/javascript'>#{read_asset(source)}</script>"
|
100
|
+
end.join("\n").html_safe
|
101
|
+
end
|
57
102
|
|
58
|
-
|
59
|
-
|
60
|
-
asset = asset_path(source)
|
61
|
-
pathname = prepend_protocol(asset)
|
62
|
-
if pathname =~ URI_REGEXP
|
63
|
-
# asset_path returns an absolute URL using asset_host if asset_host is set
|
103
|
+
def wicked_pdf_asset_path(asset)
|
104
|
+
if (pathname = asset_pathname(asset).to_s) =~ URI_REGEXP
|
64
105
|
pathname
|
65
106
|
else
|
66
|
-
|
107
|
+
"file:///#{pathname}"
|
67
108
|
end
|
68
|
-
else
|
69
|
-
asset = Rails.application.assets.find_asset(source)
|
70
|
-
asset ? asset.pathname : File.join(Rails.public_path, source)
|
71
109
|
end
|
72
|
-
end
|
73
110
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
111
|
+
def wicked_pdf_asset_pack_path(asset)
|
112
|
+
return unless defined?(Webpacker)
|
113
|
+
|
114
|
+
if running_in_development?
|
115
|
+
asset_pack_path(asset)
|
116
|
+
else
|
117
|
+
wicked_pdf_asset_path webpacker_source_url(asset)
|
118
|
+
end
|
82
119
|
end
|
83
|
-
source
|
84
|
-
end
|
85
120
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
121
|
+
private
|
122
|
+
|
123
|
+
# borrowed from actionpack/lib/action_view/helpers/asset_url_helper.rb
|
124
|
+
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}
|
125
|
+
|
126
|
+
def asset_pathname(source)
|
127
|
+
if precompiled_or_absolute_asset?(source)
|
128
|
+
asset = asset_path(source)
|
129
|
+
pathname = prepend_protocol(asset)
|
130
|
+
if pathname =~ URI_REGEXP
|
131
|
+
# asset_path returns an absolute URL using asset_host if asset_host is set
|
132
|
+
pathname
|
133
|
+
else
|
134
|
+
File.join(Rails.public_path, asset.sub(/\A#{Rails.application.config.action_controller.relative_url_root}/, ''))
|
135
|
+
end
|
136
|
+
else
|
137
|
+
asset = find_asset(source)
|
138
|
+
if asset
|
139
|
+
# older versions need pathname, Sprockets 4 supports only filename
|
140
|
+
asset.respond_to?(:filename) ? asset.filename : asset.pathname
|
141
|
+
else
|
142
|
+
File.join(Rails.public_path, source)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
91
146
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
147
|
+
def find_asset(path)
|
148
|
+
if Rails.application.assets.respond_to?(:find_asset)
|
149
|
+
Rails.application.assets.find_asset(path, :base_path => Rails.application.root.to_s)
|
150
|
+
elsif defined?(Propshaft::Assembly) && Rails.application.assets.is_a?(Propshaft::Assembly)
|
151
|
+
PropshaftAsset.new(Rails.application.assets.load_path.find(path))
|
152
|
+
else
|
153
|
+
Sprockets::Railtie.build_environment(Rails.application).find_asset(path, :base_path => Rails.application.root.to_s)
|
99
154
|
end
|
100
|
-
else
|
101
|
-
Rails.application.assets.find_asset(source).to_s
|
102
155
|
end
|
103
|
-
end
|
104
156
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
157
|
+
# will prepend a http or default_protocol to a protocol relative URL
|
158
|
+
# or when no protcol is set.
|
159
|
+
def prepend_protocol(source)
|
160
|
+
protocol = WickedPdf.config[:default_protocol] || 'http'
|
161
|
+
if source[0, 2] == '//'
|
162
|
+
source = [protocol, ':', source].join
|
163
|
+
elsif source[0] != '/' && !source[0, 8].include?('://')
|
164
|
+
source = [protocol, '://', source].join
|
165
|
+
end
|
166
|
+
source
|
167
|
+
end
|
168
|
+
|
169
|
+
def precompiled_or_absolute_asset?(source)
|
170
|
+
!Rails.configuration.respond_to?(:assets) ||
|
171
|
+
Rails.configuration.assets.compile == false ||
|
172
|
+
source.to_s[0] == '/' ||
|
173
|
+
source.to_s.match(/\Ahttps?\:\/\//)
|
174
|
+
end
|
175
|
+
|
176
|
+
def read_asset(source)
|
177
|
+
if precompiled_or_absolute_asset?(source)
|
178
|
+
pathname = asset_pathname(source)
|
179
|
+
if pathname =~ URI_REGEXP
|
180
|
+
read_from_uri(pathname)
|
181
|
+
elsif File.file?(pathname)
|
182
|
+
IO.read(pathname)
|
183
|
+
end
|
184
|
+
else
|
185
|
+
find_asset(source).to_s
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def read_from_uri(uri)
|
190
|
+
asset = Net::HTTP.get(URI(uri))
|
191
|
+
asset.force_encoding('UTF-8') if asset
|
192
|
+
asset = gzip(asset) if WickedPdf.config[:expect_gzipped_remote_assets]
|
193
|
+
asset
|
194
|
+
end
|
195
|
+
|
196
|
+
def gzip(asset)
|
197
|
+
stringified_asset = StringIO.new(asset)
|
198
|
+
gzipper = Zlib::GzipReader.new(stringified_asset)
|
199
|
+
gzipper.read
|
200
|
+
rescue Zlib::GzipFile::Error
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
|
204
|
+
def webpacker_source_url(source)
|
205
|
+
return unless webpacker_version
|
206
|
+
|
207
|
+
# In Webpacker 3.2.0 asset_pack_url is introduced
|
208
|
+
if webpacker_version >= '3.2.0'
|
209
|
+
if (host = Rails.application.config.asset_host)
|
210
|
+
asset_pack_path(source, :host => host)
|
211
|
+
else
|
212
|
+
asset_pack_url(source)
|
213
|
+
end
|
214
|
+
else
|
215
|
+
source_path = asset_pack_path(source)
|
216
|
+
# Remove last slash from root path
|
217
|
+
root_url[0...-1] + source_path
|
218
|
+
end
|
219
|
+
end
|
111
220
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
221
|
+
def running_in_development?
|
222
|
+
return unless webpacker_version
|
223
|
+
|
224
|
+
# :dev_server method was added in webpacker 3.0.0
|
225
|
+
if Webpacker.respond_to?(:dev_server)
|
226
|
+
Webpacker.dev_server.running?
|
227
|
+
else
|
228
|
+
Rails.env.development? || Rails.env.test?
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def webpacker_version
|
233
|
+
return unless defined?(Webpacker)
|
234
|
+
|
235
|
+
# If webpacker is used, need to check for version
|
236
|
+
require 'webpacker/version'
|
237
|
+
|
238
|
+
Webpacker::VERSION
|
239
|
+
end
|
118
240
|
end
|
119
241
|
end
|
120
242
|
end
|
@@ -1,33 +1,36 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
class WickedPdf
|
2
|
+
module WickedPdfHelper
|
3
|
+
def self.root_path
|
4
|
+
String === Rails.root ? Pathname.new(Rails.root) : Rails.root
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def self.add_extension(filename, extension)
|
8
|
+
filename.to_s.split('.').include?(extension) ? filename : "#{filename}.#{extension}"
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def wicked_pdf_stylesheet_link_tag(*sources)
|
12
|
+
css_dir = WickedPdfHelper.root_path.join('public', 'stylesheets')
|
13
|
+
css_text = sources.collect do |source|
|
14
|
+
source = WickedPdfHelper.add_extension(source, 'css')
|
15
|
+
"<style type='text/css'>#{File.read(css_dir.join(source))}</style>"
|
16
|
+
end.join("\n")
|
17
|
+
css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def wicked_pdf_image_tag(img, options = {})
|
21
|
+
image_tag "file:///#{WickedPdfHelper.root_path.join('public', 'images', img)}", options
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def wicked_pdf_javascript_src_tag(jsfile, options = {})
|
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.
|
27
|
+
src = "file:///#{WickedPdfHelper.root_path.join('public', 'javascripts', jsfile)}"
|
28
|
+
content_tag('script', '', { 'type' => type, 'src' => path_to_javascript(src) }.merge(options))
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
def wicked_pdf_javascript_include_tag(*sources)
|
32
|
+
js_text = sources.collect { |source| wicked_pdf_javascript_src_tag(source, {}) }.join("\n")
|
33
|
+
js_text.respond_to?(:html_safe) ? js_text.html_safe : js_text
|
34
|
+
end
|
32
35
|
end
|
33
36
|
end
|