wicked_pdf 2.1.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +56 -0
- data/.rubocop.yml +50 -1
- data/.rubocop_todo.yml +7 -86
- data/CHANGELOG.md +54 -3
- data/README.md +44 -13
- data/Rakefile +3 -10
- data/gemfiles/5.0.gemfile +2 -2
- data/gemfiles/5.1.gemfile +2 -2
- data/gemfiles/5.2.gemfile +3 -4
- data/gemfiles/6.0.gemfile +3 -4
- data/gemfiles/6.1.gemfile +12 -0
- data/gemfiles/7.0.gemfile +12 -0
- data/generators/wicked_pdf/templates/wicked_pdf.rb +3 -0
- data/lib/wicked_pdf/binary.rb +65 -0
- data/lib/wicked_pdf/option_parser.rb +229 -0
- data/lib/wicked_pdf/pdf_helper.rb +29 -44
- data/lib/wicked_pdf/railtie.rb +3 -12
- data/lib/wicked_pdf/tempfile.rb +32 -3
- data/lib/wicked_pdf/version.rb +1 -1
- data/lib/wicked_pdf/wicked_pdf_helper/assets.rb +51 -6
- data/lib/wicked_pdf.rb +19 -271
- data/test/functional/pdf_helper_test.rb +1 -1
- 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 +0 -157
- data/test/unit/wkhtmltopdf_location_test.rb +0 -2
- data/wicked_pdf.gemspec +3 -4
- metadata +33 -29
- data/.travis.yml +0 -79
- data/gemfiles/4.0.gemfile +0 -7
- data/gemfiles/4.1.gemfile +0 -7
- data/gemfiles/4.2.gemfile +0 -9
- data/gemfiles/rails_edge.gemfile +0 -9
data/lib/wicked_pdf.rb
CHANGED
@@ -11,27 +11,25 @@ require 'active_support/core_ext/object/blank'
|
|
11
11
|
|
12
12
|
require 'wicked_pdf/version'
|
13
13
|
require 'wicked_pdf/railtie'
|
14
|
+
require 'wicked_pdf/option_parser'
|
14
15
|
require 'wicked_pdf/tempfile'
|
16
|
+
require 'wicked_pdf/binary'
|
15
17
|
require 'wicked_pdf/middleware'
|
16
18
|
require 'wicked_pdf/progress'
|
17
19
|
|
18
20
|
class WickedPdf
|
19
21
|
DEFAULT_BINARY_VERSION = Gem::Version.new('0.9.9')
|
20
|
-
BINARY_VERSION_WITHOUT_DASHES = Gem::Version.new('0.12.0')
|
21
|
-
EXE_NAME = 'wkhtmltopdf'.freeze
|
22
22
|
@@config = {}
|
23
23
|
cattr_accessor :config
|
24
|
-
attr_accessor :binary_version
|
25
24
|
|
26
25
|
include Progress
|
27
26
|
|
28
27
|
def initialize(wkhtmltopdf_binary_path = nil)
|
29
|
-
@
|
30
|
-
|
31
|
-
raise "Bad #{EXE_NAME}'s path: #{@exe_path}" unless File.exist?(@exe_path)
|
32
|
-
raise "#{EXE_NAME} is not executable" unless File.executable?(@exe_path)
|
28
|
+
@binary = Binary.new(wkhtmltopdf_binary_path, DEFAULT_BINARY_VERSION)
|
29
|
+
end
|
33
30
|
|
34
|
-
|
31
|
+
def binary_version
|
32
|
+
@binary.version
|
35
33
|
end
|
36
34
|
|
37
35
|
def pdf_from_html_file(filepath, options = {})
|
@@ -41,23 +39,19 @@ class WickedPdf
|
|
41
39
|
def pdf_from_string(string, options = {})
|
42
40
|
options = options.dup
|
43
41
|
options.merge!(WickedPdf.config) { |_key, option, _config| option }
|
44
|
-
string_file =
|
45
|
-
string_file.
|
46
|
-
string_file.
|
47
|
-
string_file.close
|
48
|
-
|
49
|
-
pdf = pdf_from_html_file(string_file.path, options)
|
50
|
-
pdf
|
42
|
+
string_file = WickedPdf::Tempfile.new('wicked_pdf.html', options[:temp_path])
|
43
|
+
string_file.write_in_chunks(string)
|
44
|
+
pdf_from_html_file(string_file.path, options)
|
51
45
|
ensure
|
52
|
-
string_file.close
|
46
|
+
string_file.close if string_file
|
53
47
|
end
|
54
48
|
|
55
49
|
def pdf_from_url(url, options = {})
|
56
50
|
# merge in global config options
|
57
51
|
options.merge!(WickedPdf.config) { |_key, option, _config| option }
|
58
|
-
generated_pdf_file =
|
59
|
-
command = [@
|
60
|
-
command.unshift(
|
52
|
+
generated_pdf_file = WickedPdf::Tempfile.new('wicked_pdf_generated_file.pdf', options[:temp_path])
|
53
|
+
command = [@binary.path]
|
54
|
+
command.unshift(@binary.xvfb_run_path) if options[:use_xvfb]
|
61
55
|
command += parse_options(options)
|
62
56
|
command << url
|
63
57
|
command << generated_pdf_file.path.to_s
|
@@ -75,11 +69,12 @@ class WickedPdf
|
|
75
69
|
return_file = options.delete(:return_file)
|
76
70
|
return generated_pdf_file
|
77
71
|
end
|
78
|
-
|
79
|
-
generated_pdf_file.
|
80
|
-
|
72
|
+
|
73
|
+
pdf = generated_pdf_file.read_in_chunks
|
74
|
+
|
81
75
|
raise "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?
|
82
76
|
raise "PDF could not be generated!\n Command Error: #{err}" if pdf && pdf.rstrip.empty?
|
77
|
+
|
83
78
|
pdf
|
84
79
|
rescue StandardError => e
|
85
80
|
raise "Failed to execute:\n#{command}\nError: #{e}"
|
@@ -91,6 +86,7 @@ class WickedPdf
|
|
91
86
|
|
92
87
|
def in_development_mode?
|
93
88
|
return Rails.env == 'development' if defined?(Rails.env)
|
89
|
+
|
94
90
|
RAILS_ENV == 'development' if defined?(RAILS_ENV)
|
95
91
|
end
|
96
92
|
|
@@ -102,255 +98,7 @@ class WickedPdf
|
|
102
98
|
Rails.logger.debug '[wicked_pdf]: ' + cmd
|
103
99
|
end
|
104
100
|
|
105
|
-
def retrieve_binary_version
|
106
|
-
_stdin, stdout, _stderr = Open3.popen3(@exe_path + ' -V')
|
107
|
-
@binary_version = parse_version(stdout.gets(nil))
|
108
|
-
rescue StandardError
|
109
|
-
DEFAULT_BINARY_VERSION
|
110
|
-
end
|
111
|
-
|
112
|
-
def parse_version(version_info)
|
113
|
-
match_data = /wkhtmltopdf\s*(\d*\.\d*\.\d*\w*)/.match(version_info)
|
114
|
-
if match_data && (match_data.length == 2)
|
115
|
-
Gem::Version.new(match_data[1])
|
116
|
-
else
|
117
|
-
DEFAULT_BINARY_VERSION
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
101
|
def parse_options(options)
|
122
|
-
|
123
|
-
parse_extra(options),
|
124
|
-
parse_others(options),
|
125
|
-
parse_global(options),
|
126
|
-
parse_outline(options.delete(:outline)),
|
127
|
-
parse_header_footer(:header => options.delete(:header),
|
128
|
-
:footer => options.delete(:footer),
|
129
|
-
:layout => options[:layout]),
|
130
|
-
parse_cover(options.delete(:cover)),
|
131
|
-
parse_toc(options.delete(:toc)),
|
132
|
-
parse_basic_auth(options)
|
133
|
-
].flatten
|
134
|
-
end
|
135
|
-
|
136
|
-
def parse_extra(options)
|
137
|
-
return [] if options[:extra].nil?
|
138
|
-
return options[:extra].split if options[:extra].respond_to?(:split)
|
139
|
-
options[:extra]
|
140
|
-
end
|
141
|
-
|
142
|
-
def parse_basic_auth(options)
|
143
|
-
if options[:basic_auth]
|
144
|
-
user, passwd = Base64.decode64(options[:basic_auth]).split(':')
|
145
|
-
['--username', user, '--password', passwd]
|
146
|
-
else
|
147
|
-
[]
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def make_option(name, value, type = :string)
|
152
|
-
if value.is_a?(Array)
|
153
|
-
return value.collect { |v| make_option(name, v, type) }
|
154
|
-
end
|
155
|
-
if type == :name_value
|
156
|
-
parts = value.to_s.split(' ')
|
157
|
-
["--#{name.tr('_', '-')}", *parts]
|
158
|
-
elsif type == :boolean
|
159
|
-
if value
|
160
|
-
["--#{name.tr('_', '-')}"]
|
161
|
-
else
|
162
|
-
[]
|
163
|
-
end
|
164
|
-
else
|
165
|
-
["--#{name.tr('_', '-')}", value.to_s]
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
def valid_option(name)
|
170
|
-
if binary_version < BINARY_VERSION_WITHOUT_DASHES
|
171
|
-
"--#{name}"
|
172
|
-
else
|
173
|
-
name
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def make_options(options, names, prefix = '', type = :string)
|
178
|
-
return [] if options.nil?
|
179
|
-
names.collect do |o|
|
180
|
-
if options[o].blank?
|
181
|
-
[]
|
182
|
-
else
|
183
|
-
make_option("#{prefix.blank? ? '' : prefix + '-'}#{o}",
|
184
|
-
options[o],
|
185
|
-
type)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def parse_header_footer(options)
|
191
|
-
r = []
|
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
|
210
|
-
end
|
211
|
-
end
|
212
|
-
r
|
213
|
-
end
|
214
|
-
|
215
|
-
def parse_cover(argument)
|
216
|
-
arg = argument.to_s
|
217
|
-
return [] if arg.blank?
|
218
|
-
# Filesystem path or URL - hand off to wkhtmltopdf
|
219
|
-
if argument.is_a?(Pathname) || (arg[0, 4] == 'http')
|
220
|
-
[valid_option('cover'), arg]
|
221
|
-
else # HTML content
|
222
|
-
@hf_tempfiles ||= []
|
223
|
-
@hf_tempfiles << tf = WickedPdfTempfile.new('wicked_cover_pdf.html')
|
224
|
-
tf.write arg
|
225
|
-
tf.flush
|
226
|
-
[valid_option('cover'), tf.path]
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def parse_toc(options)
|
231
|
-
return [] if options.nil?
|
232
|
-
r = [valid_option('toc')]
|
233
|
-
unless options.blank?
|
234
|
-
r += make_options(options, [:font_name, :header_text], 'toc')
|
235
|
-
r += make_options(options, [:xsl_style_sheet])
|
236
|
-
r += make_options(options, [:depth,
|
237
|
-
:header_fs,
|
238
|
-
:text_size_shrink,
|
239
|
-
:l1_font_size,
|
240
|
-
:l2_font_size,
|
241
|
-
:l3_font_size,
|
242
|
-
:l4_font_size,
|
243
|
-
:l5_font_size,
|
244
|
-
:l6_font_size,
|
245
|
-
:l7_font_size,
|
246
|
-
:level_indentation,
|
247
|
-
:l1_indentation,
|
248
|
-
:l2_indentation,
|
249
|
-
:l3_indentation,
|
250
|
-
:l4_indentation,
|
251
|
-
:l5_indentation,
|
252
|
-
:l6_indentation,
|
253
|
-
:l7_indentation], 'toc', :numeric)
|
254
|
-
r += make_options(options, [:no_dots,
|
255
|
-
:disable_links,
|
256
|
-
:disable_back_links], 'toc', :boolean)
|
257
|
-
r += make_options(options, [:disable_dotted_lines,
|
258
|
-
:disable_toc_links], nil, :boolean)
|
259
|
-
end
|
260
|
-
r
|
261
|
-
end
|
262
|
-
|
263
|
-
def parse_outline(options)
|
264
|
-
r = []
|
265
|
-
unless options.blank?
|
266
|
-
r = make_options(options, [:outline], '', :boolean)
|
267
|
-
r += make_options(options, [:outline_depth], '', :numeric)
|
268
|
-
end
|
269
|
-
r
|
270
|
-
end
|
271
|
-
|
272
|
-
def parse_margins(options)
|
273
|
-
make_options(options, [:top, :bottom, :left, :right], 'margin', :numeric)
|
274
|
-
end
|
275
|
-
|
276
|
-
def parse_global(options)
|
277
|
-
r = []
|
278
|
-
unless options.blank?
|
279
|
-
r += make_options(options, [:orientation,
|
280
|
-
:dpi,
|
281
|
-
:page_size,
|
282
|
-
:page_width,
|
283
|
-
:title,
|
284
|
-
:log_level])
|
285
|
-
r += make_options(options, [:lowquality,
|
286
|
-
:grayscale,
|
287
|
-
:no_pdf_compression,
|
288
|
-
:quiet], '', :boolean)
|
289
|
-
r += make_options(options, [:image_dpi,
|
290
|
-
:image_quality,
|
291
|
-
:page_height], '', :numeric)
|
292
|
-
r += parse_margins(options.delete(:margin))
|
293
|
-
end
|
294
|
-
r
|
295
|
-
end
|
296
|
-
|
297
|
-
def parse_others(options)
|
298
|
-
r = []
|
299
|
-
unless options.blank?
|
300
|
-
r += make_options(options, [:proxy,
|
301
|
-
:username,
|
302
|
-
:password,
|
303
|
-
:encoding,
|
304
|
-
:user_style_sheet,
|
305
|
-
:viewport_size,
|
306
|
-
:window_status])
|
307
|
-
r += make_options(options, [:cookie,
|
308
|
-
:post], '', :name_value)
|
309
|
-
r += make_options(options, [:redirect_delay,
|
310
|
-
:zoom,
|
311
|
-
:page_offset,
|
312
|
-
:javascript_delay], '', :numeric)
|
313
|
-
r += make_options(options, [:book,
|
314
|
-
:default_header,
|
315
|
-
:disable_javascript,
|
316
|
-
:enable_plugins,
|
317
|
-
:disable_internal_links,
|
318
|
-
:disable_external_links,
|
319
|
-
:print_media_type,
|
320
|
-
:disable_local_file_access,
|
321
|
-
:enable_local_file_access,
|
322
|
-
:disable_smart_shrinking,
|
323
|
-
:use_xserver,
|
324
|
-
:no_background,
|
325
|
-
:images,
|
326
|
-
:no_images,
|
327
|
-
:no_stop_slow_scripts], '', :boolean)
|
328
|
-
end
|
329
|
-
r
|
330
|
-
end
|
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
|
-
|
337
|
-
def find_wkhtmltopdf_binary_path
|
338
|
-
possible_locations = possible_binary_locations
|
339
|
-
exe_path ||= WickedPdf.config[:exe_path] unless WickedPdf.config.empty?
|
340
|
-
exe_path ||= begin
|
341
|
-
detected_path = (defined?(Bundler) ? Bundler.which('wkhtmltopdf') : `which wkhtmltopdf`).chomp
|
342
|
-
detected_path.present? && detected_path
|
343
|
-
rescue StandardError
|
344
|
-
nil
|
345
|
-
end
|
346
|
-
exe_path ||= possible_locations.map { |l| File.expand_path("#{l}/#{EXE_NAME}") }.find { |location| File.exist?(location) }
|
347
|
-
exe_path || ''
|
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
|
102
|
+
OptionParser.new(binary_version).parse(options)
|
355
103
|
end
|
356
104
|
end
|
@@ -76,7 +76,7 @@ class PdfHelperTest < ActionController::TestCase
|
|
76
76
|
|
77
77
|
# test that calling render does not trigger infinite loop
|
78
78
|
ac = ActionController::Base.new
|
79
|
-
assert_equal [
|
79
|
+
assert_equal %i[base patched], ac.render(:cats)
|
80
80
|
rescue SystemStackError
|
81
81
|
assert_equal true, false # force spec failure
|
82
82
|
ensure
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class WickedPdfBinaryTest < ActiveSupport::TestCase
|
4
|
+
test 'should extract old wkhtmltopdf version' do
|
5
|
+
version_info_sample = "Name:\n wkhtmltopdf 0.9.9\n\nLicense:\n Copyright (C) 2008,2009 Wkhtmltopdf Authors.\n\n\n\n License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n This is free software: you are free to change and redistribute it. There is NO\n WARRANTY, to the extent permitted by law.\n\nAuthors:\n Written by Jakob Truelsen. Patches by Mrio Silva, Benoit Garret and Emmanuel\n Bouthenot.\n"
|
6
|
+
assert_equal WickedPdf::DEFAULT_BINARY_VERSION, binary.parse_version_string(version_info_sample)
|
7
|
+
end
|
8
|
+
|
9
|
+
test 'should extract new wkhtmltopdf version' do
|
10
|
+
version_info_sample = "Name:\n wkhtmltopdf 0.11.0 rc2\n\nLicense:\n Copyright (C) 2010 wkhtmltopdf/wkhtmltoimage Authors.\n\n\n\n License LGPLv3+: GNU Lesser General Public License version 3 or later\n <http://gnu.org/licenses/lgpl.html>. This is free software: you are free to\n change and redistribute it. There is NO WARRANTY, to the extent permitted by\n law.\n\nAuthors:\n Written by Jan Habermann, Christian Sciberras and Jakob Truelsen. Patches by\n Mehdi Abbad, Lyes Amazouz, Pascal Bach, Emmanuel Bouthenot, Benoit Garret and\n Mario Silva."
|
11
|
+
assert_equal Gem::Version.new('0.11.0'), binary.parse_version_string(version_info_sample)
|
12
|
+
end
|
13
|
+
|
14
|
+
test 'should extract wkhtmltopdf version with nondigit symbols' do
|
15
|
+
version_info_sample = "Name:\n wkhtmltopdf 0.10.4b\n\nLicense:\n Copyright (C) 2008,2009 Wkhtmltopdf Authors.\n\n\n\n License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n This is free software: you are free to change and redistribute it. There is NO\n WARRANTY, to the extent permitted by law.\n\nAuthors:\n Written by Jakob Truelsen. Patches by Mrio Silva, Benoit Garret and Emmanuel\n Bouthenot.\n"
|
16
|
+
assert_equal Gem::Version.new('0.10.4b'), binary.parse_version_string(version_info_sample)
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'should fallback to default version on parse error' do
|
20
|
+
assert_equal WickedPdf::DEFAULT_BINARY_VERSION, binary.parse_version_string('')
|
21
|
+
end
|
22
|
+
|
23
|
+
def binary(path = nil)
|
24
|
+
WickedPdf::Binary.new(path)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class WickedPdfOptionParserTest < ActiveSupport::TestCase
|
4
|
+
test 'should parse header and footer options' do
|
5
|
+
%i[header footer].each do |hf|
|
6
|
+
%i[center font_name left right].each do |o|
|
7
|
+
assert_equal "--#{hf}-#{o.to_s.tr('_', '-')} header_footer",
|
8
|
+
parse_options(hf => { o => 'header_footer' }).strip
|
9
|
+
end
|
10
|
+
|
11
|
+
%i[font_size spacing].each do |o|
|
12
|
+
assert_equal "--#{hf}-#{o.to_s.tr('_', '-')} 12",
|
13
|
+
parse_options(hf => { o => '12' }).strip
|
14
|
+
end
|
15
|
+
|
16
|
+
assert_equal "--#{hf}-line",
|
17
|
+
parse_options(hf => { :line => true }).strip
|
18
|
+
assert_equal "--#{hf}-html http://www.abc.com",
|
19
|
+
parse_options(hf => { :html => { :url => 'http://www.abc.com' } }).strip
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'should parse toc options' do
|
24
|
+
toc_option = option_parser.valid_option('toc')
|
25
|
+
|
26
|
+
%i[font_name header_text].each do |o|
|
27
|
+
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')} toc",
|
28
|
+
parse_options(:toc => { o => 'toc' }).strip
|
29
|
+
end
|
30
|
+
|
31
|
+
%i[
|
32
|
+
depth header_fs l1_font_size l2_font_size l3_font_size l4_font_size
|
33
|
+
l5_font_size l6_font_size l7_font_size l1_indentation l2_indentation
|
34
|
+
l3_indentation l4_indentation l5_indentation l6_indentation l7_indentation
|
35
|
+
].each do |o|
|
36
|
+
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')} 5",
|
37
|
+
parse_options(:toc => { o => 5 }).strip
|
38
|
+
end
|
39
|
+
|
40
|
+
%i[no_dots disable_links disable_back_links].each do |o|
|
41
|
+
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')}",
|
42
|
+
parse_options(:toc => { o => true }).strip
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'should parse outline options' do
|
47
|
+
assert_equal '--outline', parse_options(:outline => { :outline => true }).strip
|
48
|
+
assert_equal '--outline-depth 5', parse_options(:outline => { :outline_depth => 5 }).strip
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'should parse no_images option' do
|
52
|
+
assert_equal '--no-images', parse_options(:no_images => true).strip
|
53
|
+
assert_equal '--images', parse_options(:images => true).strip
|
54
|
+
end
|
55
|
+
|
56
|
+
test 'should parse margins options' do
|
57
|
+
%i[top bottom left right].each do |o|
|
58
|
+
assert_equal "--margin-#{o} 12", parse_options(:margin => { o => '12' }).strip
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test 'should parse cover' do
|
63
|
+
cover_option = option_parser.valid_option('cover')
|
64
|
+
|
65
|
+
pathname = Rails.root.join('app', 'views', 'pdf', 'file.html')
|
66
|
+
assert_equal "#{cover_option} http://example.org", parse_options(:cover => 'http://example.org').strip, 'URL'
|
67
|
+
assert_equal "#{cover_option} #{pathname}", parse_options(:cover => pathname).strip, 'Pathname'
|
68
|
+
assert_match(/#{cover_option} .+wicked_cover_pdf.+\.html/, parse_options(:cover => '<html><body>HELLO</body></html>').strip, 'HTML')
|
69
|
+
end
|
70
|
+
|
71
|
+
test 'should parse other options' do
|
72
|
+
%i[
|
73
|
+
orientation page_size proxy username password dpi
|
74
|
+
encoding user_style_sheet
|
75
|
+
].each do |o|
|
76
|
+
assert_equal "--#{o.to_s.tr('_', '-')} opts", parse_options(o => 'opts').strip
|
77
|
+
end
|
78
|
+
|
79
|
+
%i[cookie post].each do |o|
|
80
|
+
assert_equal "--#{o.to_s.tr('_', '-')} name value", parse_options(o => 'name value').strip
|
81
|
+
|
82
|
+
nv_formatter = proc { |number| "--#{o.to_s.tr('_', '-')} par#{number} val#{number}" }
|
83
|
+
assert_equal "#{nv_formatter.call(1)} #{nv_formatter.call(2)}", parse_options(o => ['par1 val1', 'par2 val2']).strip
|
84
|
+
end
|
85
|
+
|
86
|
+
%i[redirect_delay zoom page_offset].each do |o|
|
87
|
+
assert_equal "--#{o.to_s.tr('_', '-')} 5", parse_options(o => 5).strip
|
88
|
+
end
|
89
|
+
|
90
|
+
%i[
|
91
|
+
book default_header disable_javascript grayscale lowquality
|
92
|
+
enable_plugins disable_internal_links disable_external_links
|
93
|
+
print_media_type disable_smart_shrinking use_xserver no_background
|
94
|
+
].each do |o|
|
95
|
+
assert_equal "--#{o.to_s.tr('_', '-')}", parse_options(o => true).strip
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
test 'should not use double dash options for version without dashes' do
|
100
|
+
op = option_parser(WickedPdf::OptionParser::BINARY_VERSION_WITHOUT_DASHES)
|
101
|
+
|
102
|
+
%w[toc cover].each do |name|
|
103
|
+
assert_equal op.valid_option(name), name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
test 'should use double dash options for version with dashes' do
|
108
|
+
op = option_parser(Gem::Version.new('0.11.0'))
|
109
|
+
|
110
|
+
%w[toc cover].each do |name|
|
111
|
+
assert_equal op.valid_option(name), "--#{name}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
test '-- options should not be given after object' do
|
116
|
+
options = { :header => { :center => 3 }, :cover => 'http://example.org', :disable_javascript => true }
|
117
|
+
cover_option = option_parser.valid_option('cover')
|
118
|
+
assert_equal parse_options(options), "--disable-javascript --header-center 3 #{cover_option} http://example.org"
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse_options(options, version = WickedPdf::DEFAULT_BINARY_VERSION)
|
122
|
+
option_parser(version).parse(options).join(' ')
|
123
|
+
end
|
124
|
+
|
125
|
+
def option_parser(version = WickedPdf::DEFAULT_BINARY_VERSION)
|
126
|
+
WickedPdf::OptionParser.new(version)
|
127
|
+
end
|
128
|
+
end
|
@@ -2,23 +2,6 @@ require 'test_helper'
|
|
2
2
|
WickedPdf.config = { :exe_path => ENV['WKHTMLTOPDF_BIN'] || '/usr/local/bin/wkhtmltopdf' }
|
3
3
|
HTML_DOCUMENT = '<html><body>Hello World</body></html>'.freeze
|
4
4
|
|
5
|
-
# Provide a public accessor to the normally-private parse_options function.
|
6
|
-
# Also, smash the returned array of options into a single string for
|
7
|
-
# convenience in testing below.
|
8
|
-
class WickedPdf
|
9
|
-
undef :binary_version
|
10
|
-
undef :binary_version=
|
11
|
-
attr_accessor :binary_version
|
12
|
-
|
13
|
-
def get_parsed_options(opts)
|
14
|
-
parse_options(opts).join(' ')
|
15
|
-
end
|
16
|
-
|
17
|
-
def get_valid_option(name)
|
18
|
-
valid_option(name)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
5
|
class WickedPdfTest < ActiveSupport::TestCase
|
23
6
|
def setup
|
24
7
|
@wp = WickedPdf.new
|
@@ -86,146 +69,6 @@ class WickedPdfTest < ActiveSupport::TestCase
|
|
86
69
|
end
|
87
70
|
end
|
88
71
|
|
89
|
-
test 'should parse header and footer options' do
|
90
|
-
[:header, :footer].each do |hf|
|
91
|
-
[:center, :font_name, :left, :right].each do |o|
|
92
|
-
assert_equal "--#{hf}-#{o.to_s.tr('_', '-')} header_footer",
|
93
|
-
@wp.get_parsed_options(hf => { o => 'header_footer' }).strip
|
94
|
-
end
|
95
|
-
|
96
|
-
[:font_size, :spacing].each do |o|
|
97
|
-
assert_equal "--#{hf}-#{o.to_s.tr('_', '-')} 12",
|
98
|
-
@wp.get_parsed_options(hf => { o => '12' }).strip
|
99
|
-
end
|
100
|
-
|
101
|
-
assert_equal "--#{hf}-line",
|
102
|
-
@wp.get_parsed_options(hf => { :line => true }).strip
|
103
|
-
assert_equal "--#{hf}-html http://www.abc.com",
|
104
|
-
@wp.get_parsed_options(hf => { :html => { :url => 'http://www.abc.com' } }).strip
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
test 'should parse toc options' do
|
109
|
-
toc_option = @wp.get_valid_option('toc')
|
110
|
-
|
111
|
-
[:font_name, :header_text].each do |o|
|
112
|
-
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')} toc",
|
113
|
-
@wp.get_parsed_options(:toc => { o => 'toc' }).strip
|
114
|
-
end
|
115
|
-
|
116
|
-
[
|
117
|
-
:depth, :header_fs, :l1_font_size, :l2_font_size, :l3_font_size, :l4_font_size,
|
118
|
-
:l5_font_size, :l6_font_size, :l7_font_size, :l1_indentation, :l2_indentation,
|
119
|
-
:l3_indentation, :l4_indentation, :l5_indentation, :l6_indentation, :l7_indentation
|
120
|
-
].each do |o|
|
121
|
-
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')} 5",
|
122
|
-
@wp.get_parsed_options(:toc => { o => 5 }).strip
|
123
|
-
end
|
124
|
-
|
125
|
-
[:no_dots, :disable_links, :disable_back_links].each do |o|
|
126
|
-
assert_equal "#{toc_option} --toc-#{o.to_s.tr('_', '-')}",
|
127
|
-
@wp.get_parsed_options(:toc => { o => true }).strip
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
test 'should parse outline options' do
|
132
|
-
assert_equal '--outline', @wp.get_parsed_options(:outline => { :outline => true }).strip
|
133
|
-
assert_equal '--outline-depth 5', @wp.get_parsed_options(:outline => { :outline_depth => 5 }).strip
|
134
|
-
end
|
135
|
-
|
136
|
-
test 'should parse no_images option' do
|
137
|
-
assert_equal '--no-images', @wp.get_parsed_options(:no_images => true).strip
|
138
|
-
assert_equal '--images', @wp.get_parsed_options(:images => true).strip
|
139
|
-
end
|
140
|
-
|
141
|
-
test 'should parse margins options' do
|
142
|
-
[:top, :bottom, :left, :right].each do |o|
|
143
|
-
assert_equal "--margin-#{o} 12", @wp.get_parsed_options(:margin => { o => '12' }).strip
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
test 'should parse cover' do
|
148
|
-
cover_option = @wp.get_valid_option('cover')
|
149
|
-
|
150
|
-
pathname = Rails.root.join('app', 'views', 'pdf', 'file.html')
|
151
|
-
assert_equal "#{cover_option} http://example.org", @wp.get_parsed_options(:cover => 'http://example.org').strip, 'URL'
|
152
|
-
assert_equal "#{cover_option} #{pathname}", @wp.get_parsed_options(:cover => pathname).strip, 'Pathname'
|
153
|
-
assert_match %r{#{cover_option} .+wicked_cover_pdf.+\.html}, @wp.get_parsed_options(:cover => '<html><body>HELLO</body></html>').strip, 'HTML'
|
154
|
-
end
|
155
|
-
|
156
|
-
test 'should parse other options' do
|
157
|
-
[
|
158
|
-
:orientation, :page_size, :proxy, :username, :password, :dpi,
|
159
|
-
:encoding, :user_style_sheet
|
160
|
-
].each do |o|
|
161
|
-
assert_equal "--#{o.to_s.tr('_', '-')} opts", @wp.get_parsed_options(o => 'opts').strip
|
162
|
-
end
|
163
|
-
|
164
|
-
[:cookie, :post].each do |o|
|
165
|
-
assert_equal "--#{o.to_s.tr('_', '-')} name value", @wp.get_parsed_options(o => 'name value').strip
|
166
|
-
|
167
|
-
nv_formatter = proc { |number| "--#{o.to_s.tr('_', '-')} par#{number} val#{number}" }
|
168
|
-
assert_equal "#{nv_formatter.call(1)} #{nv_formatter.call(2)}", @wp.get_parsed_options(o => ['par1 val1', 'par2 val2']).strip
|
169
|
-
end
|
170
|
-
|
171
|
-
[:redirect_delay, :zoom, :page_offset].each do |o|
|
172
|
-
assert_equal "--#{o.to_s.tr('_', '-')} 5", @wp.get_parsed_options(o => 5).strip
|
173
|
-
end
|
174
|
-
|
175
|
-
[
|
176
|
-
:book, :default_header, :disable_javascript, :grayscale, :lowquality,
|
177
|
-
:enable_plugins, :disable_internal_links, :disable_external_links,
|
178
|
-
:print_media_type, :disable_smart_shrinking, :use_xserver, :no_background
|
179
|
-
].each do |o|
|
180
|
-
assert_equal "--#{o.to_s.tr('_', '-')}", @wp.get_parsed_options(o => true).strip
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
test 'should extract old wkhtmltopdf version' do
|
185
|
-
version_info_sample = "Name:\n wkhtmltopdf 0.9.9\n\nLicense:\n Copyright (C) 2008,2009 Wkhtmltopdf Authors.\n\n\n\n License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n This is free software: you are free to change and redistribute it. There is NO\n WARRANTY, to the extent permitted by law.\n\nAuthors:\n Written by Jakob Truelsen. Patches by Mrio Silva, Benoit Garret and Emmanuel\n Bouthenot.\n"
|
186
|
-
assert_equal WickedPdf::DEFAULT_BINARY_VERSION, @wp.send(:parse_version, version_info_sample)
|
187
|
-
end
|
188
|
-
|
189
|
-
test 'should extract new wkhtmltopdf version' do
|
190
|
-
version_info_sample = "Name:\n wkhtmltopdf 0.11.0 rc2\n\nLicense:\n Copyright (C) 2010 wkhtmltopdf/wkhtmltoimage Authors.\n\n\n\n License LGPLv3+: GNU Lesser General Public License version 3 or later\n <http://gnu.org/licenses/lgpl.html>. This is free software: you are free to\n change and redistribute it. There is NO WARRANTY, to the extent permitted by\n law.\n\nAuthors:\n Written by Jan Habermann, Christian Sciberras and Jakob Truelsen. Patches by\n Mehdi Abbad, Lyes Amazouz, Pascal Bach, Emmanuel Bouthenot, Benoit Garret and\n Mario Silva."
|
191
|
-
assert_equal Gem::Version.new('0.11.0'), @wp.send(:parse_version, version_info_sample)
|
192
|
-
end
|
193
|
-
|
194
|
-
test 'should extract wkhtmltopdf version with nondigit symbols' do
|
195
|
-
version_info_sample = "Name:\n wkhtmltopdf 0.10.4b\n\nLicense:\n Copyright (C) 2008,2009 Wkhtmltopdf Authors.\n\n\n\n License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n This is free software: you are free to change and redistribute it. There is NO\n WARRANTY, to the extent permitted by law.\n\nAuthors:\n Written by Jakob Truelsen. Patches by Mrio Silva, Benoit Garret and Emmanuel\n Bouthenot.\n"
|
196
|
-
assert_equal Gem::Version.new('0.10.4b'), @wp.send(:parse_version, version_info_sample)
|
197
|
-
end
|
198
|
-
|
199
|
-
test 'should fallback to default version on parse error' do
|
200
|
-
assert_equal WickedPdf::DEFAULT_BINARY_VERSION, @wp.send(:parse_version, '')
|
201
|
-
end
|
202
|
-
|
203
|
-
test 'should set version on initialize' do
|
204
|
-
assert_not_equal @wp.send(:binary_version), ''
|
205
|
-
end
|
206
|
-
|
207
|
-
test 'should not use double dash options for version without dashes' do
|
208
|
-
@wp.binary_version = WickedPdf::BINARY_VERSION_WITHOUT_DASHES
|
209
|
-
|
210
|
-
%w[toc cover].each do |name|
|
211
|
-
assert_equal @wp.get_valid_option(name), name
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
test 'should use double dash options for version with dashes' do
|
216
|
-
@wp.binary_version = Gem::Version.new('0.11.0')
|
217
|
-
|
218
|
-
%w[toc cover].each do |name|
|
219
|
-
assert_equal @wp.get_valid_option(name), "--#{name}"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
test '-- options should not be given after object' do
|
224
|
-
options = { :header => { :center => 3 }, :cover => 'http://example.org', :disable_javascript => true }
|
225
|
-
cover_option = @wp.get_valid_option('cover')
|
226
|
-
assert_equal @wp.get_parsed_options(options), "--disable-javascript --header-center 3 #{cover_option} http://example.org"
|
227
|
-
end
|
228
|
-
|
229
72
|
test 'should output progress when creating pdfs on compatible hosts' do
|
230
73
|
wp = WickedPdf.new
|
231
74
|
output = []
|