wicked_pdf 1.1.0 → 2.8.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.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/.github/issue_template.md +15 -0
  3. data/.github/workflows/ci.yml +56 -0
  4. data/.rubocop.yml +62 -0
  5. data/.rubocop_todo.yml +81 -39
  6. data/CHANGELOG.md +194 -45
  7. data/README.md +136 -28
  8. data/Rakefile +12 -9
  9. data/gemfiles/5.0.gemfile +3 -1
  10. data/gemfiles/5.1.gemfile +8 -0
  11. data/gemfiles/5.2.gemfile +9 -0
  12. data/gemfiles/6.0.gemfile +10 -0
  13. data/gemfiles/6.1.gemfile +11 -0
  14. data/gemfiles/7.0.gemfile +11 -0
  15. data/generators/wicked_pdf/templates/wicked_pdf.rb +14 -5
  16. data/lib/generators/wicked_pdf_generator.rb +5 -9
  17. data/lib/wicked_pdf/binary.rb +65 -0
  18. data/lib/wicked_pdf/middleware.rb +1 -1
  19. data/lib/wicked_pdf/option_parser.rb +230 -0
  20. data/lib/wicked_pdf/pdf_helper.rb +35 -42
  21. data/lib/wicked_pdf/progress.rb +33 -0
  22. data/lib/wicked_pdf/railtie.rb +6 -44
  23. data/lib/wicked_pdf/tempfile.rb +33 -3
  24. data/lib/wicked_pdf/version.rb +1 -1
  25. data/lib/wicked_pdf/wicked_pdf_helper/assets.rb +200 -17
  26. data/lib/wicked_pdf/wicked_pdf_helper.rb +2 -1
  27. data/lib/wicked_pdf.rb +64 -275
  28. data/test/fixtures/database.yml +4 -0
  29. data/test/fixtures/manifest.js +3 -0
  30. data/test/functional/pdf_helper_test.rb +71 -0
  31. data/test/functional/wicked_pdf_helper_assets_test.rb +61 -0
  32. data/test/test_helper.rb +13 -8
  33. data/test/unit/wicked_pdf_binary_test.rb +26 -0
  34. data/test/unit/wicked_pdf_option_parser_test.rb +133 -0
  35. data/test/unit/wicked_pdf_test.rb +25 -146
  36. data/test/unit/wkhtmltopdf_location_test.rb +48 -0
  37. data/wicked_pdf.gemspec +20 -13
  38. metadata +79 -36
  39. data/.travis.yml +0 -57
  40. data/gemfiles/2.3.gemfile +0 -10
  41. data/gemfiles/3.0.gemfile +0 -12
  42. data/gemfiles/3.1.gemfile +0 -13
  43. data/gemfiles/3.2.gemfile +0 -12
  44. data/gemfiles/4.0.gemfile +0 -6
  45. data/gemfiles/4.1.gemfile +0 -6
  46. data/gemfiles/4.2.gemfile +0 -6
  47. data/gemfiles/rails_edge.gemfile +0 -6
@@ -1,17 +1,99 @@
1
- require 'open-uri'
1
+ require 'net/http'
2
+ require 'delegate'
3
+ require 'stringio'
2
4
 
3
5
  class WickedPdf
4
6
  module WickedPdfHelper
5
7
  module Assets
6
8
  ASSET_URL_REGEX = /url\(['"]?([^'"]+?)['"]?\)/
7
9
 
10
+ class MissingAsset < StandardError; end
11
+
12
+ class MissingLocalAsset < MissingAsset
13
+ attr_reader :path
14
+
15
+ def initialize(path)
16
+ @path = path
17
+ super("Could not find asset '#{path}'")
18
+ end
19
+ end
20
+
21
+ class MissingRemoteAsset < MissingAsset
22
+ attr_reader :url, :response
23
+
24
+ def initialize(url, response)
25
+ @url = url
26
+ @response = response
27
+ super("Could not fetch asset '#{url}': server responded with #{response.code} #{response.message}")
28
+ end
29
+ end
30
+
31
+ class PropshaftAsset < SimpleDelegator
32
+ def content_type
33
+ super.to_s
34
+ end
35
+
36
+ def to_s
37
+ content
38
+ end
39
+
40
+ def filename
41
+ path.to_s
42
+ end
43
+ end
44
+
45
+ class SprocketsEnvironment
46
+ def self.instance
47
+ @instance ||= Sprockets::Railtie.build_environment(Rails.application)
48
+ end
49
+
50
+ def self.find_asset(*args)
51
+ instance.find_asset(*args)
52
+ end
53
+ end
54
+
55
+ class LocalAsset
56
+ attr_reader :path
57
+
58
+ def initialize(path)
59
+ @path = path
60
+ end
61
+
62
+ def content_type
63
+ Mime::Type.lookup_by_extension(File.extname(path).delete('.'))
64
+ end
65
+
66
+ def to_s
67
+ IO.read(path)
68
+ end
69
+
70
+ def filename
71
+ path.to_s
72
+ end
73
+ end
74
+
8
75
  def wicked_pdf_asset_base64(path)
9
76
  asset = find_asset(path)
10
- raise "Could not find asset '#{path}'" if asset.nil?
77
+ raise MissingLocalAsset, path if asset.nil?
78
+
11
79
  base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
12
80
  "data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
13
81
  end
14
82
 
83
+ # Using `image_tag` with URLs when generating PDFs (specifically large PDFs with lots of pages) can cause buffer/stack overflows.
84
+ #
85
+ def wicked_pdf_url_base64(url)
86
+ response = Net::HTTP.get_response(URI(url))
87
+
88
+ if response.is_a?(Net::HTTPSuccess)
89
+ base64 = Base64.encode64(response.body).gsub(/\s+/, '')
90
+ "data:#{response.content_type};base64,#{Rack::Utils.escape(base64)}"
91
+ else
92
+ Rails.logger.warn("[wicked_pdf] #{response.code} #{response.message}: #{url}")
93
+ nil
94
+ end
95
+ end
96
+
15
97
  def wicked_pdf_stylesheet_link_tag(*sources)
16
98
  stylesheet_contents = sources.collect do |source|
17
99
  source = WickedPdfHelper.add_extension(source, 'css')
@@ -27,6 +109,33 @@ class WickedPdf
27
109
  end.html_safe
28
110
  end
29
111
 
112
+ def wicked_pdf_stylesheet_pack_tag(*sources)
113
+ return unless defined?(Webpacker)
114
+
115
+ if running_in_development?
116
+ stylesheet_pack_tag(*sources)
117
+ else
118
+ css_text = sources.collect do |source|
119
+ source = WickedPdfHelper.add_extension(source, 'css')
120
+ wicked_pdf_stylesheet_link_tag(webpacker_source_url(source))
121
+ end.join("\n")
122
+ css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
123
+ end
124
+ end
125
+
126
+ def wicked_pdf_javascript_pack_tag(*sources)
127
+ return unless defined?(Webpacker)
128
+
129
+ if running_in_development?
130
+ javascript_pack_tag(*sources)
131
+ else
132
+ sources.collect do |source|
133
+ source = WickedPdfHelper.add_extension(source, 'js')
134
+ "<script type='text/javascript'>#{read_asset(webpacker_source_url(source))}</script>"
135
+ end.join("\n").html_safe
136
+ end
137
+ end
138
+
30
139
  def wicked_pdf_image_tag(img, options = {})
31
140
  image_tag wicked_pdf_asset_path(img), options
32
141
  end
@@ -51,6 +160,16 @@ class WickedPdf
51
160
  end
52
161
  end
53
162
 
163
+ def wicked_pdf_asset_pack_path(asset)
164
+ return unless defined?(Webpacker)
165
+
166
+ if running_in_development?
167
+ asset_pack_path(asset)
168
+ else
169
+ wicked_pdf_asset_path webpacker_source_url(asset)
170
+ end
171
+ end
172
+
54
173
  private
55
174
 
56
175
  # borrowed from actionpack/lib/action_view/helpers/asset_url_helper.rb
@@ -68,15 +187,25 @@ class WickedPdf
68
187
  end
69
188
  else
70
189
  asset = find_asset(source)
71
- asset ? asset.pathname : File.join(Rails.public_path, source)
190
+ if asset
191
+ # older versions need pathname, Sprockets 4 supports only filename
192
+ asset.respond_to?(:filename) ? asset.filename : asset.pathname
193
+ else
194
+ File.join(Rails.public_path, source)
195
+ end
72
196
  end
73
197
  end
74
198
 
75
199
  def find_asset(path)
76
200
  if Rails.application.assets.respond_to?(:find_asset)
77
- Rails.application.assets.find_asset(path)
201
+ Rails.application.assets.find_asset(path, :base_path => Rails.application.root.to_s)
202
+ elsif defined?(Propshaft::Assembly) && Rails.application.assets.is_a?(Propshaft::Assembly)
203
+ PropshaftAsset.new(Rails.application.assets.load_path.find(path))
204
+ elsif Rails.application.respond_to?(:assets_manifest)
205
+ asset_path = File.join(Rails.application.assets_manifest.dir, Rails.application.assets_manifest.assets[path])
206
+ LocalAsset.new(asset_path) if File.file?(asset_path)
78
207
  else
79
- Sprockets::Railtie.build_environment(Rails.application).find_asset(path)
208
+ SprocketsEnvironment.find_asset(path, :base_path => Rails.application.root.to_s)
80
209
  end
81
210
  end
82
211
 
@@ -93,27 +222,43 @@ class WickedPdf
93
222
  end
94
223
 
95
224
  def precompiled_or_absolute_asset?(source)
96
- Rails.configuration.assets.compile == false ||
225
+ !Rails.configuration.respond_to?(:assets) ||
226
+ Rails.configuration.assets.compile == false ||
97
227
  source.to_s[0] == '/' ||
98
228
  source.to_s.match(/\Ahttps?\:\/\//)
99
229
  end
100
230
 
101
231
  def read_asset(source)
102
- if precompiled_or_absolute_asset?(source)
103
- pathname = asset_pathname(source)
104
- if pathname =~ URI_REGEXP
105
- read_from_uri(pathname)
106
- elsif File.file?(pathname)
107
- IO.read(pathname)
108
- end
109
- else
110
- find_asset(source).to_s
232
+ asset = find_asset(source)
233
+ return asset.to_s.force_encoding('UTF-8') if asset
234
+
235
+ unless precompiled_or_absolute_asset?(source)
236
+ raise MissingLocalAsset, source if WickedPdf.config[:raise_on_missing_assets]
237
+
238
+ return
239
+ end
240
+
241
+ pathname = asset_pathname(source)
242
+ if pathname =~ URI_REGEXP
243
+ read_from_uri(pathname)
244
+ elsif File.file?(pathname)
245
+ IO.read(pathname)
246
+ elsif WickedPdf.config[:raise_on_missing_assets]
247
+ raise MissingLocalAsset, pathname if WickedPdf.config[:raise_on_missing_assets]
111
248
  end
112
249
  end
113
250
 
114
251
  def read_from_uri(uri)
115
- encoding = ':UTF-8' if RUBY_VERSION > '1.8'
116
- asset = open(uri, "r#{encoding}", &:read)
252
+ response = Net::HTTP.get_response(URI(uri))
253
+
254
+ unless response.is_a?(Net::HTTPSuccess)
255
+ raise MissingRemoteAsset.new(uri, response) if WickedPdf.config[:raise_on_missing_assets]
256
+
257
+ return
258
+ end
259
+
260
+ asset = response.body
261
+ asset.force_encoding('UTF-8') if asset
117
262
  asset = gzip(asset) if WickedPdf.config[:expect_gzipped_remote_assets]
118
263
  asset
119
264
  end
@@ -125,6 +270,44 @@ class WickedPdf
125
270
  rescue Zlib::GzipFile::Error
126
271
  nil
127
272
  end
273
+
274
+ def webpacker_source_url(source)
275
+ return unless webpacker_version
276
+
277
+ # In Webpacker 3.2.0 asset_pack_url is introduced
278
+ if webpacker_version >= '3.2.0'
279
+ if (host = Rails.application.config.asset_host)
280
+ asset_pack_path(source, :host => host)
281
+ else
282
+ asset_pack_url(source)
283
+ end
284
+ else
285
+ source_path = asset_pack_path(source)
286
+ # Remove last slash from root path
287
+ root_url[0...-1] + source_path
288
+ end
289
+ end
290
+
291
+ def running_in_development?
292
+ return unless webpacker_version
293
+
294
+ # :dev_server method was added in webpacker 3.0.0
295
+ if Webpacker.respond_to?(:dev_server)
296
+ Webpacker.dev_server.running?
297
+ else
298
+ Rails.env.development? || Rails.env.test?
299
+ end
300
+ end
301
+
302
+ def webpacker_version
303
+ if defined?(Shakapacker)
304
+ require 'shakapacker/version'
305
+ Shakapacker::VERSION
306
+ elsif defined?(Webpacker)
307
+ require 'webpacker/version'
308
+ Webpacker::VERSION
309
+ end
310
+ end
128
311
  end
129
312
  end
130
313
  end
@@ -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' => Mime::JS, 'src' => path_to_javascript(src) }.merge(options))
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)
data/lib/wicked_pdf.rb CHANGED
@@ -1,48 +1,52 @@
1
1
  # wkhtml2pdf Ruby interface
2
- # http://code.google.com/p/wkhtmltopdf/
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
- if (RbConfig::CONFIG['target_os'] =~ /mswin|mingw/) && (RUBY_VERSION < '1.9')
9
- require 'win32/open3'
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'
14
+ require 'wicked_pdf/option_parser'
28
15
  require 'wicked_pdf/tempfile'
16
+ require 'wicked_pdf/binary'
29
17
  require 'wicked_pdf/middleware'
18
+ require 'wicked_pdf/progress'
30
19
 
31
20
  class WickedPdf
32
21
  DEFAULT_BINARY_VERSION = Gem::Version.new('0.9.9')
33
- BINARY_VERSION_WITHOUT_DASHES = Gem::Version.new('0.12.0')
34
- EXE_NAME = 'wkhtmltopdf'.freeze
35
22
  @@config = {}
36
- cattr_accessor :config
37
- attr_accessor :binary_version
23
+ cattr_accessor :config, :silence_deprecations
24
+
25
+ include Progress
26
+
27
+ def self.config=(config)
28
+ ::Kernel.warn 'WickedPdf.config= is deprecated and will be removed in future versions. Use WickedPdf.configure instead.' unless @@silence_deprecations
29
+
30
+ @@config = config
31
+ end
32
+
33
+ def self.configure
34
+ config = OpenStruct.new(@@config)
35
+ yield config
36
+
37
+ @@config.merge! config.to_h
38
+ end
39
+
40
+ def self.clear_config
41
+ @@config = {}
42
+ end
38
43
 
39
44
  def initialize(wkhtmltopdf_binary_path = nil)
40
- @exe_path = wkhtmltopdf_binary_path || find_wkhtmltopdf_binary_path
41
- raise "Location of #{EXE_NAME} unknown" if @exe_path.empty?
42
- raise "Bad #{EXE_NAME}'s path: #{@exe_path}" unless File.exist?(@exe_path)
43
- raise "#{EXE_NAME} is not executable" unless File.executable?(@exe_path)
45
+ @binary = Binary.new(wkhtmltopdf_binary_path, DEFAULT_BINARY_VERSION)
46
+ end
44
47
 
45
- retrieve_binary_version
48
+ def binary_version
49
+ @binary.version
46
50
  end
47
51
 
48
52
  def pdf_from_html_file(filepath, options = {})
@@ -52,51 +56,58 @@ class WickedPdf
52
56
  def pdf_from_string(string, options = {})
53
57
  options = options.dup
54
58
  options.merge!(WickedPdf.config) { |_key, option, _config| option }
55
- string_file = WickedPdfTempfile.new('wicked_pdf.html', options[:temp_path])
56
- string_file.binmode
57
- string_file.write(string)
58
- string_file.close
59
-
60
- pdf = pdf_from_html_file(string_file.path, options)
61
- pdf
59
+ string_file = WickedPdf::Tempfile.new('wicked_pdf.html', options[:temp_path])
60
+ string_file.write_in_chunks(string)
61
+ pdf_from_html_file(string_file.path, options)
62
62
  ensure
63
- string_file.close! if string_file
63
+ if options[:delete_temporary_files] && string_file
64
+ string_file.close!
65
+ elsif string_file
66
+ string_file.close
67
+ end
64
68
  end
65
69
 
66
- def pdf_from_url(url, options = {})
70
+ def pdf_from_url(url, options = {}) # rubocop:disable Metrics/CyclomaticComplexity
67
71
  # merge in global config options
68
72
  options.merge!(WickedPdf.config) { |_key, option, _config| option }
69
- generated_pdf_file = WickedPdfTempfile.new('wicked_pdf_generated_file.pdf', options[:temp_path])
70
- command = [@exe_path]
71
- command << '-q' unless on_windows? # suppress errors on stdout
72
- command += parse_options(options)
73
+ generated_pdf_file = WickedPdf::Tempfile.new('wicked_pdf_generated_file.pdf', options[:temp_path])
74
+ command = [@binary.path]
75
+ command.unshift(@binary.xvfb_run_path) if options[:use_xvfb]
76
+ command += option_parser.parse(options)
73
77
  command << url
74
78
  command << generated_pdf_file.path.to_s
75
79
 
76
80
  print_command(command.inspect) if in_development_mode?
77
81
 
78
- err = Open3.popen3(*command) do |_stdin, _stdout, stderr|
79
- stderr.read
82
+ if track_progress?(options)
83
+ invoke_with_progress(command, options)
84
+ else
85
+ _out, err, status = Open3.capture3(*command)
86
+ err = [status.to_s, err].join("\n") if !err.empty? || !status.success?
80
87
  end
81
88
  if options[:return_file]
82
89
  return_file = options.delete(:return_file)
83
90
  return generated_pdf_file
84
91
  end
85
- generated_pdf_file.rewind
86
- generated_pdf_file.binmode
87
- pdf = generated_pdf_file.read
92
+
93
+ pdf = generated_pdf_file.read_in_chunks
94
+
95
+ raise "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?
88
96
  raise "PDF could not be generated!\n Command Error: #{err}" if pdf && pdf.rstrip.empty?
97
+
89
98
  pdf
90
- rescue => e
99
+ rescue StandardError => e
91
100
  raise "Failed to execute:\n#{command}\nError: #{e}"
92
101
  ensure
102
+ clean_temp_files
93
103
  generated_pdf_file.close! if generated_pdf_file && !return_file
94
104
  end
95
105
 
96
106
  private
97
107
 
98
108
  def in_development_mode?
99
- return Rails.env == 'development' if defined?(Rails)
109
+ return Rails.env == 'development' if defined?(Rails.env)
110
+
100
111
  RAILS_ENV == 'development' if defined?(RAILS_ENV)
101
112
  end
102
113
 
@@ -105,238 +116,16 @@ class WickedPdf
105
116
  end
106
117
 
107
118
  def print_command(cmd)
108
- p '*' * 15 + cmd + '*' * 15
109
- end
110
-
111
- def retrieve_binary_version
112
- _stdin, stdout, _stderr = Open3.popen3(@exe_path + ' -V')
113
- @binary_version = parse_version(stdout.gets(nil))
114
- rescue
115
- DEFAULT_BINARY_VERSION
116
- end
117
-
118
- def parse_version(version_info)
119
- match_data = /wkhtmltopdf\s*(\d*\.\d*\.\d*\w*)/.match(version_info)
120
- if match_data && (2 == match_data.length)
121
- Gem::Version.new(match_data[1])
122
- else
123
- DEFAULT_BINARY_VERSION
124
- end
125
- end
126
-
127
- def parse_options(options)
128
- [
129
- parse_extra(options),
130
- parse_others(options),
131
- parse_global(options),
132
- parse_outline(options.delete(:outline)),
133
- parse_header_footer(:header => options.delete(:header),
134
- :footer => options.delete(:footer),
135
- :layout => options[:layout]),
136
- parse_cover(options.delete(:cover)),
137
- parse_toc(options.delete(:toc)),
138
- parse_basic_auth(options)
139
- ].flatten
140
- end
141
-
142
- def parse_extra(options)
143
- return [] if options[:extra].nil?
144
- return options[:extra].split if options[:extra].respond_to?(:split)
145
- options[:extra]
119
+ Rails.logger.debug '[wicked_pdf]: ' + cmd
146
120
  end
147
121
 
148
- def parse_basic_auth(options)
149
- if options[:basic_auth]
150
- user, passwd = Base64.decode64(options[:basic_auth]).split(':')
151
- ['--username', user, '--password', passwd]
152
- else
153
- []
154
- end
122
+ def option_parser
123
+ @option_parser ||= OptionParser.new(binary_version)
155
124
  end
156
125
 
157
- def make_option(name, value, type = :string)
158
- if value.is_a?(Array)
159
- return value.collect { |v| make_option(name, v, type) }
160
- end
161
- if type == :name_value
162
- parts = value.to_s.split(' ')
163
- ["--#{name.tr('_', '-')}", *parts]
164
- elsif type == :boolean
165
- if value
166
- ["--#{name.tr('_', '-')}"]
167
- else
168
- []
169
- end
170
- else
171
- ["--#{name.tr('_', '-')}", value.to_s]
172
- end
173
- end
126
+ def clean_temp_files
127
+ return unless option_parser.hf_tempfiles.present?
174
128
 
175
- def valid_option(name)
176
- if binary_version < BINARY_VERSION_WITHOUT_DASHES
177
- "--#{name}"
178
- else
179
- name
180
- end
181
- end
182
-
183
- def make_options(options, names, prefix = '', type = :string)
184
- return [] if options.nil?
185
- names.collect do |o|
186
- if options[o].blank?
187
- []
188
- else
189
- make_option("#{prefix.blank? ? '' : prefix + '-'}#{o}",
190
- options[o],
191
- type)
192
- end
193
- end
194
- end
195
-
196
- def parse_header_footer(options)
197
- r = []
198
- [:header, :footer].collect do |hf|
199
- next if options[hf].blank?
200
- opt_hf = options[hf]
201
- r += make_options(opt_hf, [:center, :font_name, :left, :right], hf.to_s)
202
- r += make_options(opt_hf, [:font_size, :spacing], hf.to_s, :numeric)
203
- r += make_options(opt_hf, [:line], hf.to_s, :boolean)
204
- if options[hf] && options[hf][:content]
205
- @hf_tempfiles = [] unless defined?(@hf_tempfiles)
206
- @hf_tempfiles.push(tf = WickedPdfTempfile.new("wicked_#{hf}_pdf.html"))
207
- tf.write options[hf][:content]
208
- tf.flush
209
- options[hf][:html] = {}
210
- options[hf][:html][:url] = "file:///#{tf.path}"
211
- end
212
- unless opt_hf[:html].blank?
213
- r += make_option("#{hf}-html", opt_hf[:html][:url]) unless opt_hf[:html][:url].blank?
214
- end
215
- end unless options.blank?
216
- r
217
- end
218
-
219
- def parse_cover(argument)
220
- arg = argument.to_s
221
- return [] if arg.blank?
222
- # Filesystem path or URL - hand off to wkhtmltopdf
223
- if argument.is_a?(Pathname) || (arg[0, 4] == 'http')
224
- [valid_option('cover'), arg]
225
- else # HTML content
226
- @hf_tempfiles ||= []
227
- @hf_tempfiles << tf = WickedPdfTempfile.new('wicked_cover_pdf.html')
228
- tf.write arg
229
- tf.flush
230
- [valid_option('cover'), tf.path]
231
- end
232
- end
233
-
234
- def parse_toc(options)
235
- return [] if options.nil?
236
- r = [valid_option('toc')]
237
- unless options.blank?
238
- r += make_options(options, [:font_name, :header_text], 'toc')
239
- r += make_options(options, [:xsl_style_sheet])
240
- r += make_options(options, [:depth,
241
- :header_fs,
242
- :text_size_shrink,
243
- :l1_font_size,
244
- :l2_font_size,
245
- :l3_font_size,
246
- :l4_font_size,
247
- :l5_font_size,
248
- :l6_font_size,
249
- :l7_font_size,
250
- :level_indentation,
251
- :l1_indentation,
252
- :l2_indentation,
253
- :l3_indentation,
254
- :l4_indentation,
255
- :l5_indentation,
256
- :l6_indentation,
257
- :l7_indentation], 'toc', :numeric)
258
- r += make_options(options, [:no_dots,
259
- :disable_links,
260
- :disable_back_links], 'toc', :boolean)
261
- r += make_options(options, [:disable_dotted_lines,
262
- :disable_toc_links], nil, :boolean)
263
- end
264
- r
265
- end
266
-
267
- def parse_outline(options)
268
- r = []
269
- unless options.blank?
270
- r = make_options(options, [:outline], '', :boolean)
271
- r += make_options(options, [:outline_depth], '', :numeric)
272
- end
273
- r
274
- end
275
-
276
- def parse_margins(options)
277
- make_options(options, [:top, :bottom, :left, :right], 'margin', :numeric)
278
- end
279
-
280
- def parse_global(options)
281
- r = []
282
- unless options.blank?
283
- r += make_options(options, [:orientation,
284
- :dpi,
285
- :page_size,
286
- :page_width,
287
- :title])
288
- r += make_options(options, [:lowquality,
289
- :grayscale,
290
- :no_pdf_compression], '', :boolean)
291
- r += make_options(options, [:image_dpi,
292
- :image_quality,
293
- :page_height], '', :numeric)
294
- r += parse_margins(options.delete(:margin))
295
- end
296
- r
297
- end
298
-
299
- def parse_others(options)
300
- r = []
301
- unless options.blank?
302
- r += make_options(options, [:proxy,
303
- :username,
304
- :password,
305
- :encoding,
306
- :user_style_sheet,
307
- :viewport_size,
308
- :window_status])
309
- r += make_options(options, [:cookie,
310
- :post], '', :name_value)
311
- r += make_options(options, [:redirect_delay,
312
- :zoom,
313
- :page_offset,
314
- :javascript_delay], '', :numeric)
315
- r += make_options(options, [:book,
316
- :default_header,
317
- :disable_javascript,
318
- :enable_plugins,
319
- :disable_internal_links,
320
- :disable_external_links,
321
- :print_media_type,
322
- :disable_smart_shrinking,
323
- :use_xserver,
324
- :no_background,
325
- :no_stop_slow_scripts], '', :boolean)
326
- end
327
- r
328
- end
329
-
330
- def find_wkhtmltopdf_binary_path
331
- possible_locations = (ENV['PATH'].split(':') + %w(/usr/bin /usr/local/bin ~/bin)).uniq
332
- exe_path ||= WickedPdf.config[:exe_path] unless WickedPdf.config.empty?
333
- exe_path ||= begin
334
- detected_path = (defined?(Bundler) ? `bundle exec which wkhtmltopdf` : `which wkhtmltopdf`).chomp
335
- detected_path.present? && detected_path
336
- rescue
337
- nil
338
- end
339
- exe_path ||= possible_locations.map { |l| File.expand_path("#{l}/#{EXE_NAME}") }.find { |location| File.exist?(location) }
340
- exe_path || ''
129
+ option_parser.hf_tempfiles.each { |file| File.delete(file) }
341
130
  end
342
131
  end
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+ timeout: 500