adzap-wicked_pdf 2.0.0.beta5 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0e3c7a80eafff7408d840f346daf69875aa08ddf4732dcce26b8d41a293df84
4
- data.tar.gz: 04fe3eb6fbe869899c46faa88eec83ec4abbf2aa7c3dbbb904cda40415a434e3
3
+ metadata.gz: ee59b976a1f8a763eb2a754baf8727f970fe5f06c88194b42735d5c37e3ac6b7
4
+ data.tar.gz: 543153109daf65bcbe75959aecf5416689fd54481dd31b08bf068322de805551
5
5
  SHA512:
6
- metadata.gz: a1f3607db97564707b60ff9427de9c24aa5112144665d53ace67fa667216bea616ddbe78e91a94abaebbee85086b8118d8f36722f00d32532b3a4f7963fa6e7a
7
- data.tar.gz: 62dba9bf7aa036f6f5c4f249190ccee3f4879914a163f22c42e4c2b6fcb33c2b096b6d858a38e10881d9d39262f2af1a7dd2d715fc05a636b3d3561863897a9c
6
+ metadata.gz: bc98c1fbb159ec1c228f320d8d79d805d8c9e85927fd3f6b4f96b7d0927c05da270a55d3e87f348a4c7602f350ce855761c3a65f671d133b7bab6e7712cf4296
7
+ data.tar.gz: 237bef4134c63adb17a206b197888e7a6f8845a7fa4f637454420ab91590c40706766a3d14f1d50f60b3c4df168158751716258b8865ae80c639c4afb75e128c
data/.rubocop.yml CHANGED
@@ -1,9 +1,14 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.3
4
+ TargetRubyVersion: 3.4
5
+ NewCops: disable
6
+ SuggestExtensions: false
5
7
  Exclude:
6
8
  - 'test/dummy/**/*'
9
+ - 'spike/**/*'
10
+ - 'gemfiles/**/*'
11
+ - 'vendor/**/*'
7
12
 
8
13
  Metrics/BlockLength:
9
14
  Exclude:
@@ -19,4 +24,4 @@ Style/SymbolArray:
19
24
  EnforcedStyle: brackets
20
25
 
21
26
  Style/SafeNavigation:
22
- Enabled: false
27
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -28,7 +28,7 @@ Metrics/CyclomaticComplexity:
28
28
 
29
29
  # Offense count: 92
30
30
  # Configuration parameters: AllowURI, URISchemes.
31
- Metrics/LineLength:
31
+ Layout/LineLength:
32
32
  Max: 563
33
33
 
34
34
  # Offense count: 14
@@ -38,7 +38,7 @@ Metrics/MethodLength:
38
38
 
39
39
  # Offense count: 4
40
40
  Metrics/PerceivedComplexity:
41
- Max: 12
41
+ Max: 14
42
42
 
43
43
  # Offense count: 2
44
44
  Naming/AccessorMethodName:
@@ -1,5 +1,5 @@
1
1
  class WickedPdfGenerator < Rails::Generators::Base
2
- source_root(File.expand_path(File.dirname(__FILE__) + '/../../generators/wicked_pdf/templates'))
2
+ source_root(File.expand_path("#{File.dirname(__FILE__)}/../../generators/wicked_pdf/templates"))
3
3
  def copy_initializer
4
4
  copy_file 'wicked_pdf.rb', 'config/initializers/wicked_pdf.rb'
5
5
  end
@@ -0,0 +1,33 @@
1
+ module WickedPdf
2
+ # Process-wide memo for the output of the inlining asset helpers
3
+ # (wicked_pdf_asset_base64, wicked_pdf_stylesheet_link_tag,
4
+ # wicked_pdf_javascript_include_tag).
5
+ #
6
+ # Reading, concatenating and base64-encoding assets is deterministic for a
7
+ # given deployment, but the helpers are invoked once per rendered document —
8
+ # expensive when many documents are rendered in one request (e.g. printing a
9
+ # batch). Enable with `config.cache_assets = true`; disabled by default so
10
+ # environments that recompile assets on change (development) stay live.
11
+ #
12
+ # Cached values are frozen so a stale reference can't be mutated in place.
13
+ class AssetCache
14
+ def initialize
15
+ @store = {}
16
+ @mutex = Mutex.new
17
+ end
18
+
19
+ def fetch(key)
20
+ @mutex.synchronize do
21
+ @store.fetch(key) { @store[key] = yield.freeze }
22
+ end
23
+ end
24
+
25
+ def clear
26
+ @mutex.synchronize { @store.clear }
27
+ end
28
+
29
+ def size
30
+ @mutex.synchronize { @store.size }
31
+ end
32
+ end
33
+ end
@@ -13,25 +13,30 @@ module WickedPdf
13
13
  end
14
14
 
15
15
  def wicked_pdf_asset_base64(path)
16
- asset = find_asset(path)
17
- raise "Could not find asset '#{path}'" if asset.nil?
18
- base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
19
- "data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
16
+ wicked_pdf_asset_cache(:base64, path) do
17
+ asset = find_asset(path)
18
+ raise "Could not find asset '#{path}'" if asset.nil?
19
+
20
+ base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
21
+ "data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
22
+ end
20
23
  end
21
24
 
22
25
  def wicked_pdf_stylesheet_link_tag(*sources)
23
- stylesheet_contents = sources.collect do |source|
24
- source = WickedPdf::AssetHelper.add_extension(source, 'css')
25
- "<style type='text/css'>#{read_asset(source)}</style>"
26
- end.join("\n")
27
-
28
- stylesheet_contents.gsub(ASSET_URL_REGEX) do
29
- if Regexp.last_match[1].starts_with?('data:')
30
- "url(#{Regexp.last_match[1]})"
31
- else
32
- "url(#{wicked_pdf_asset_path(Regexp.last_match[1])})"
33
- end
34
- end.html_safe
26
+ wicked_pdf_asset_cache(:stylesheet, *sources) do
27
+ stylesheet_contents = sources.collect do |source|
28
+ source = WickedPdf::AssetHelper.add_extension(source, 'css')
29
+ "<style type='text/css'>#{read_asset(source)}</style>"
30
+ end.join("\n")
31
+
32
+ stylesheet_contents.gsub(ASSET_URL_REGEX) do
33
+ if Regexp.last_match[1].starts_with?('data:')
34
+ "url(#{Regexp.last_match[1]})"
35
+ else
36
+ "url(#{wicked_pdf_asset_path(Regexp.last_match[1])})"
37
+ end
38
+ end.html_safe
39
+ end
35
40
  end
36
41
 
37
42
  def wicked_pdf_image_tag(img, options = {})
@@ -44,10 +49,12 @@ module WickedPdf
44
49
  end
45
50
 
46
51
  def wicked_pdf_javascript_include_tag(*sources)
47
- sources.collect do |source|
48
- source = WickedPdf::AssetHelper.add_extension(source, 'js')
49
- "<script type='text/javascript'>#{read_asset(source)}</script>"
50
- end.join("\n").html_safe
52
+ wicked_pdf_asset_cache(:javascript, *sources) do
53
+ sources.collect do |source|
54
+ source = WickedPdf::AssetHelper.add_extension(source, 'js')
55
+ "<script type='text/javascript'>#{read_asset(source)}</script>"
56
+ end.join("\n").html_safe
57
+ end
51
58
  end
52
59
 
53
60
  def wicked_pdf_asset_path(asset)
@@ -63,6 +70,11 @@ module WickedPdf
63
70
  # borrowed from actionpack/lib/action_view/helpers/asset_url_helper.rb
64
71
  URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}
65
72
 
73
+ # Inlined asset output is deterministic per deployment; memoized process-wide when config.cache_assets is on.
74
+ def wicked_pdf_asset_cache(*key, &block)
75
+ WickedPdf.config.cache_assets ? WickedPdf.asset_cache.fetch(key, &block) : yield
76
+ end
77
+
66
78
  def asset_pathname(source)
67
79
  if precompiled_or_absolute_asset?(source)
68
80
  asset = asset_path(source)
@@ -95,7 +107,7 @@ module WickedPdf
95
107
  # will prepend a http or default_protocol to a protocol relative URL
96
108
  # or when no protcol is set.
97
109
  def prepend_protocol(source)
98
- protocol = WickedPdf.config[:default_protocol] || 'http'
110
+ protocol = WickedPdf.config.default_protocol || 'http'
99
111
  if source[0, 2] == '//'
100
112
  source = [protocol, ':', source].join
101
113
  elsif source[0] != '/' && !source[0, 8].include?('://')
@@ -107,7 +119,7 @@ module WickedPdf
107
119
  def precompiled_or_absolute_asset?(source)
108
120
  Rails.configuration.assets.compile == false ||
109
121
  source.to_s[0] == '/' ||
110
- source.to_s.match(/\Ahttps?\:\/\//)
122
+ source.to_s.match(/\Ahttps?:\/\//)
111
123
  end
112
124
 
113
125
  def read_asset(source)
@@ -125,7 +137,7 @@ module WickedPdf
125
137
 
126
138
  def read_from_uri(uri)
127
139
  asset = Net::HTTP.get(URI(uri))
128
- asset = gzip(asset) if WickedPdf.config[:expect_gzipped_remote_assets]
140
+ asset = gzip(asset) if WickedPdf.config.expect_gzipped_remote_assets
129
141
  asset
130
142
  end
131
143
 
@@ -5,6 +5,21 @@ module WickedPdf
5
5
 
6
6
  attr_reader :path, :version
7
7
 
8
+ # Shared instance, so the version check (`wkhtmltopdf -V` subprocess) runs
9
+ # once instead of once per render. Re-resolved whenever config.exe_path
10
+ # changes — including back to nil (automatic path detection).
11
+ def self.default
12
+ configured_path = WickedPdf.config.exe_path
13
+ @default = nil if @default && @default_configured_path != configured_path
14
+ @default_configured_path = configured_path
15
+ @default ||= new
16
+ end
17
+
18
+ def self.reset_default!
19
+ @default = nil
20
+ @default_configured_path = nil
21
+ end
22
+
8
23
  def initialize(binary_path = nil)
9
24
  @path = binary_path || find_binary_path
10
25
  @version = retrieve_binary_version
@@ -27,14 +42,15 @@ module WickedPdf
27
42
  private
28
43
 
29
44
  def retrieve_binary_version
30
- _stdin, stdout, _stderr = Open3.popen3(@path + ' -V')
31
- parse_version_string(stdout.gets(nil))
45
+ # argv form: no shell parsing, so paths with spaces work.
46
+ stdout, = Open3.capture3(@path, '-V')
47
+ parse_version_string(stdout)
32
48
  rescue StandardError
33
49
  MINIMUM_BINARY_VERSION
34
50
  end
35
51
 
36
52
  def find_binary_path
37
- return WickedPdf.config[:exe_path] if WickedPdf.config[:exe_path]
53
+ return WickedPdf.config.exe_path if WickedPdf.config.exe_path
38
54
 
39
55
  begin
40
56
  detected_path = (defined?(Bundler) ? Bundler.which('wkhtmltopdf') : `which wkhtmltopdf`).chomp
@@ -2,14 +2,14 @@ module WickedPdf
2
2
  class Command
3
3
  attr_reader :binary, :option_parser
4
4
 
5
- def initialize(binary: Binary.new, option_parser: OptionParser.new)
5
+ def initialize(binary: Binary.default, option_parser: OptionParser.new)
6
6
  @binary = binary
7
7
  @option_parser = option_parser
8
8
  end
9
9
 
10
10
  def execute(options, *args)
11
11
  command = [binary.path]
12
- command << '--enable-local-file-access' # FIXME should be set as config
12
+ command += global_argv
13
13
  command += option_parser.parse(options)
14
14
  command += args
15
15
 
@@ -18,28 +18,168 @@ module WickedPdf
18
18
  if track_progress?(options)
19
19
  Progress.new(options[:progress]).execute(command)
20
20
  else
21
- begin
22
- err = Open3.popen3(*command) do |_stdin, _stdout, stderr|
23
- stderr.read
24
- end
21
+ err = run_process(command)
22
+
23
+ raise GenerationError, "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?
24
+
25
+ err
26
+ end
27
+ end
28
+
29
+ # Runs several conversions through shared wkhtmltopdf processes using
30
+ # --read-args-from-stdin, avoiding one process boot per document.
31
+ #
32
+ # Each job is a Hash with:
33
+ # options: wkhtmltopdf options for this conversion only
34
+ # url: input URL (file:///... for local files)
35
+ # output_path: file the PDF is written to
36
+ #
37
+ # Jobs are split into `concurrency` contiguous slices, each processed by
38
+ # its own wkhtmltopdf process. wkhtmltopdf aborts a batch at the first
39
+ # failing conversion, so the failed job is retried as a normal single
40
+ # invocation (for a proper error) and the batch resumed with the rest.
41
+ # Raises WickedPdf::GenerationError if a job cannot be rendered.
42
+ #
43
+ # All argv compilation happens here on the calling thread: OptionParser
44
+ # is not thread-safe (it accumulates tempfile state for inline
45
+ # header/footer content), so worker threads only ever see frozen strings.
46
+ def execute_batch(jobs, concurrency: 1)
47
+ return if jobs.empty?
48
+
49
+ compiled = jobs.map { |job| BatchJob.new(job, batch_argv(job)) }
50
+
51
+ slices = compiled.each_slice(batch_slice_size(jobs.size, concurrency)).to_a
52
+ errors = Array.new(slices.size)
53
+
54
+ slices.each_with_index.map do |slice, index|
55
+ Thread.new do
56
+ process_batch_slice(slice)
25
57
  rescue StandardError => e
26
- raise "Failed to execute:\n#{command}\nError: #{e}"
58
+ errors[index] = e
27
59
  end
60
+ end.each(&:join)
28
61
 
29
- raise "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?
30
- err
62
+ error = errors.compact.first
63
+ raise error if error
64
+ end
65
+
66
+ # A batch job with its argv compiled up front (thread-safe to run).
67
+ BatchJob = Struct.new(:job, :argv) do
68
+ def output_path
69
+ job[:output_path]
70
+ end
71
+
72
+ def line
73
+ @line ||= argv.join(' ')
31
74
  end
32
75
  end
33
76
 
34
77
  private
35
78
 
79
+ def batch_slice_size(job_count, concurrency)
80
+ concurrency = concurrency.clamp(1, job_count)
81
+ (job_count.to_f / concurrency).ceil
82
+ end
83
+
84
+ def process_batch_slice(batch_jobs)
85
+ pending = batch_jobs
86
+ until pending.empty?
87
+ run_batch_process(pending.map(&:line))
88
+ pending = pending.drop_while { |batch_job| batch_output_complete?(batch_job) }
89
+ break if pending.empty?
90
+
91
+ retry_batch_job(pending.shift)
92
+ end
93
+ end
94
+
95
+ # A failed conversion aborts its batch process, leaving this job and all
96
+ # jobs after it unrendered. Retrying it individually either renders it
97
+ # (transient failure) or produces a proper single-invocation error.
98
+ def retry_batch_job(batch_job)
99
+ command = [binary.path] + batch_job.argv.map { |token| unquote_batch_token(token) }
100
+ print_command(command.inspect) if in_development_mode?
101
+
102
+ err = run_process(command)
103
+ return if batch_output_complete?(batch_job)
104
+
105
+ raise GenerationError, "Error generating PDF for #{batch_job.output_path}\n Command Error: #{err}"
106
+ end
107
+
108
+ # wkhtmltopdf aborts a failing batch conversion partway, which can leave
109
+ # a non-empty but truncated file behind. Only a well-formed PDF (header
110
+ # and end-of-file marker) counts as done; anything else is retried.
111
+ def batch_output_complete?(batch_job)
112
+ size = File.size?(batch_job.output_path)
113
+ return false unless size
114
+
115
+ File.open(batch_job.output_path, 'rb') do |file|
116
+ return false unless file.read(5) == '%PDF-'
117
+
118
+ file.seek([size - 64, 0].max)
119
+ file.read.include?('%%EOF')
120
+ end
121
+ end
122
+
123
+ def batch_argv(job)
124
+ argv = global_argv
125
+ argv += option_parser.parse(job[:options].dup)
126
+ argv += [job[:url], job[:output_path]]
127
+ argv.map { |arg| batch_token(arg.to_s) }
128
+ end
129
+
130
+ # Flags controlled by gem configuration rather than per-render options.
131
+ def global_argv
132
+ WickedPdf.config.enable_local_file_access ? ['--enable-local-file-access'] : []
133
+ end
134
+
135
+ # wkhtmltopdf tokenises each stdin line itself: spaces separate arguments
136
+ # unless quoted. Only quoted-space handling is verified, so reject
137
+ # characters with unknown escaping semantics rather than corrupt a line.
138
+ def batch_token(arg)
139
+ raise ArgumentError, "Unsupported character in wkhtmltopdf batch argument: #{arg.inspect}" if arg.match?(/["\n\r]/)
140
+
141
+ arg.include?(' ') ? %("#{arg}") : arg
142
+ end
143
+
144
+ # Reverses batch_token quoting when a compiled token is passed directly
145
+ # as a process argument instead of through the stdin line protocol.
146
+ def unquote_batch_token(token)
147
+ token.start_with?('"') && token.end_with?('"') ? token[1..-2] : token
148
+ end
149
+
150
+ def run_process(command)
151
+ Open3.popen3(*command) do |_stdin, _stdout, stderr|
152
+ stderr.read
153
+ end
154
+ rescue StandardError => e
155
+ raise Error, "Failed to execute:\n#{command}\nError: #{e}"
156
+ end
157
+
158
+ def run_batch_process(lines)
159
+ print_command(lines.inspect) if in_development_mode?
160
+
161
+ err = nil
162
+ Open3.popen3(binary.path, '--read-args-from-stdin') do |stdin, stdout, stderr, wait_thr|
163
+ stdout_reader = Thread.new { stdout.read }
164
+ stderr_reader = Thread.new { stderr.read }
165
+ lines.each { |line| stdin.puts(line) }
166
+ stdin.close
167
+ stdout_reader.value
168
+ err = stderr_reader.value
169
+ wait_thr.value
170
+ end
171
+ err
172
+ rescue StandardError => e
173
+ raise Error, "Failed to execute wkhtmltopdf batch:\n#{lines.inspect}\nError: #{e}"
174
+ end
175
+
36
176
  def in_development_mode?
37
177
  defined?(Rails.env) && Rails.env.development?
38
178
  end
39
179
 
40
180
  def print_command(cmd)
41
181
  # TODO: if no Rails what then?
42
- Rails.logger.debug '[wicked_pdf]: ' + cmd
182
+ Rails.logger.debug "[wicked_pdf]: #{cmd}"
43
183
  end
44
184
 
45
185
  def track_progress?(options)
@@ -0,0 +1,62 @@
1
+ module WickedPdf
2
+ # Global gem configuration, set via WickedPdf.configure or by assigning a
3
+ # Hash to WickedPdf.config (kept for backward compatibility).
4
+ #
5
+ # Two kinds of values live here:
6
+ #
7
+ # * Typed settings, declared as accessors below, which control the gem
8
+ # itself (binary location, middleware URLs, asset handling).
9
+ # * default_options, a Hash of wkhtmltopdf render options (:footer,
10
+ # :orientation, :dpi, ...) merged under every render's own options.
11
+ # Unknown keys assigned through a Hash or #[]= land here.
12
+ class Configuration
13
+ SETTINGS = [
14
+ :exe_path,
15
+ :basic_auth,
16
+ :root_url,
17
+ :default_protocol,
18
+ :expect_gzipped_remote_assets,
19
+ :enable_local_file_access,
20
+ :cache_assets
21
+ ].freeze
22
+
23
+ attr_accessor(*SETTINGS)
24
+ attr_reader :default_options
25
+
26
+ def self.from_hash(hash)
27
+ new.tap do |config|
28
+ (hash || {}).each { |key, value| config[key] = value }
29
+ end
30
+ end
31
+
32
+ def initialize
33
+ @basic_auth = false
34
+ @enable_local_file_access = true
35
+ @cache_assets = false
36
+ @default_options = {}
37
+ end
38
+
39
+ def []=(key, value)
40
+ if setting?(key)
41
+ public_send("#{key}=", value)
42
+ else
43
+ default_options[key.to_sym] = value
44
+ end
45
+ end
46
+
47
+ def [](key)
48
+ setting?(key) ? public_send(key) : default_options[key.to_sym]
49
+ end
50
+
51
+ def to_h
52
+ settings = SETTINGS.to_h { |key| [key, public_send(key)] }
53
+ settings.compact.merge(default_options)
54
+ end
55
+
56
+ private
57
+
58
+ def setting?(key)
59
+ SETTINGS.include?(key.to_sym)
60
+ end
61
+ end
62
+ end
@@ -10,7 +10,7 @@ module WickedPdf
10
10
 
11
11
  def pdf_from_string(string, options = {})
12
12
  options = options.dup
13
- options.merge!(WickedPdf.config) { |_key, option, _config| option }
13
+ options.merge!(WickedPdf.config.default_options) { |_key, option, _config| option }
14
14
  string_file = WickedPdf::Tempfile.new('wicked_pdf.html', options[:temp_path])
15
15
  string_file.write_in_chunks(string)
16
16
 
@@ -22,21 +22,52 @@ module WickedPdf
22
22
  string_file.close! if string_file
23
23
  end
24
24
 
25
+ # Renders many HTML strings via Command#execute_batch (shared wkhtmltopdf
26
+ # processes instead of one boot per document). Items are Hashes of
27
+ # { html: String, options: Hash }; each item's options apply to that
28
+ # conversion only. Returns the PDF strings in item order.
29
+ def pdfs_from_strings(items, concurrency: 1)
30
+ tempfiles = []
31
+
32
+ jobs = items.map do |item|
33
+ options = (item[:options] || {}).dup
34
+ options.merge!(WickedPdf.config.default_options) { |_key, option, _config| option }
35
+
36
+ input = WickedPdf::Tempfile.new('wicked_pdf_batch.html', options[:temp_path])
37
+ tempfiles << input
38
+ input.write_in_chunks(item.fetch(:html))
39
+
40
+ output = WickedPdf::Tempfile.new('wicked_pdf_batch.pdf', options[:temp_path])
41
+ tempfiles << output
42
+
43
+ { options: options, url: "file:///#{input.path}", output_path: output.path, output_file: output }
44
+ end
45
+
46
+ @command.execute_batch(jobs, concurrency: concurrency)
47
+
48
+ jobs.map do |job|
49
+ pdf = job[:output_file].read_in_chunks
50
+ raise GenerationError, "PDF could not be generated!\n Output: #{job[:output_path]}" if pdf.rstrip.empty?
51
+
52
+ pdf
53
+ end
54
+ ensure
55
+ tempfiles.each(&:close!)
56
+ end
57
+
25
58
  def pdf_from_url(url, options = {})
26
59
  # merge in global config options
27
- options.merge!(WickedPdf.config) { |_key, option, _config| option }
60
+ options.merge!(WickedPdf.config.default_options) { |_key, option, _config| option }
28
61
  generated_pdf_file = WickedPdf::Tempfile.new('wicked_pdf_generated_file.pdf', options[:temp_path])
29
62
  return_file = options.delete(:return_file)
30
63
 
31
64
  err = @command.execute(options, url, generated_pdf_file.path.to_s)
32
65
 
33
- if return_file
34
- return generated_pdf_file
35
- end
66
+ return generated_pdf_file if return_file
36
67
 
37
68
  pdf = generated_pdf_file.read_in_chunks
38
69
 
39
- raise "PDF could not be generated!\n Command Error: #{err}" if pdf && pdf.rstrip.empty?
70
+ raise GenerationError, "PDF could not be generated!\n Command Error: #{err}" if pdf && pdf.rstrip.empty?
40
71
 
41
72
  pdf
42
73
  rescue Errno::EINVAL => e
@@ -2,7 +2,7 @@ module WickedPdf
2
2
  class Middleware
3
3
  def initialize(app, options = {}, conditions = {})
4
4
  @app = app
5
- @options = (WickedPdf.config || {}).merge(options)
5
+ @options = WickedPdf.config.default_options.merge(options)
6
6
  @conditions = conditions
7
7
  @command = command(options[:wkhtmltopdf])
8
8
  end
@@ -42,9 +42,9 @@ module WickedPdf
42
42
  # Change relative paths to absolute
43
43
  def translate_paths(body, env)
44
44
  # Host with protocol
45
- root = WickedPdf.config[:root_url] || "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/"
45
+ root = WickedPdf.config.root_url || "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/"
46
46
 
47
- body.gsub(/(href|src)=(['"])\/([^\"']*|[^"']*)['"]/, '\1=\2' + root + '\3\2')
47
+ body.gsub(/(href|src)=(['"])\/([^"']*|[^"']*)['"]/, "\\1=\\2#{root}\\3\\2")
48
48
  end
49
49
 
50
50
  def rendering_pdf?
@@ -73,7 +73,7 @@ module WickedPdf
73
73
  end
74
74
  end
75
75
 
76
- return true
76
+ true
77
77
  else
78
78
  request_path_is_pdf
79
79
  end
@@ -20,6 +20,7 @@ module WickedPdf
20
20
  def parse_extra(options)
21
21
  return [] if options[:extra].nil?
22
22
  return options[:extra].split if options[:extra].respond_to?(:split)
23
+
23
24
  options[:extra]
24
25
  end
25
26
 
@@ -37,6 +38,7 @@ module WickedPdf
37
38
  unless options.blank?
38
39
  [:header, :footer].collect do |hf|
39
40
  next if options[hf].blank?
41
+
40
42
  opt_hf = options[hf]
41
43
  r += make_options(opt_hf, [:center, :font_name, :left, :right], hf.to_s)
42
44
  r += make_options(opt_hf, [:font_size, :spacing], hf.to_s, :numeric)
@@ -49,9 +51,7 @@ module WickedPdf
49
51
  options[hf][:html] = {}
50
52
  options[hf][:html][:url] = "file:///#{tf.path}"
51
53
  end
52
- unless opt_hf[:html].blank?
53
- r += make_option("#{hf}-html", opt_hf[:html][:url]) unless opt_hf[:html][:url].blank?
54
- end
54
+ r += make_option("#{hf}-html", opt_hf[:html][:url]) if !opt_hf[:html].blank? && !opt_hf[:html][:url].blank?
55
55
  end
56
56
  end
57
57
  r
@@ -60,6 +60,7 @@ module WickedPdf
60
60
  def parse_cover(argument)
61
61
  arg = argument.to_s
62
62
  return [] if arg.blank?
63
+
63
64
  # Filesystem path or URL - hand off to wkhtmltopdf
64
65
  if argument.is_a?(Pathname) || (arg[0, 4] == 'http')
65
66
  ['cover', arg]
@@ -74,6 +75,7 @@ module WickedPdf
74
75
 
75
76
  def parse_toc(options)
76
77
  return [] if options.nil?
78
+
77
79
  r = ['toc']
78
80
  unless options.blank?
79
81
  r += make_options(options, [:font_name, :header_text], 'toc')
@@ -172,11 +174,12 @@ module WickedPdf
172
174
 
173
175
  def make_options(options, names, prefix = '', type = :string)
174
176
  return [] if options.nil?
177
+
175
178
  names.collect do |o|
176
179
  if options[o].blank?
177
180
  []
178
181
  else
179
- make_option("#{prefix.blank? ? '' : prefix + '-'}#{o}",
182
+ make_option("#{prefix.blank? ? '' : "#{prefix}-"}#{o}",
180
183
  options[o],
181
184
  type)
182
185
  end
@@ -184,9 +187,8 @@ module WickedPdf
184
187
  end
185
188
 
186
189
  def make_option(name, value, type = :string)
187
- if value.is_a?(Array)
188
- return value.collect { |v| make_option(name, v, type) }
189
- end
190
+ return value.collect { |v| make_option(name, v, type) } if value.is_a?(Array)
191
+
190
192
  if type == :name_value
191
193
  parts = value.to_s.split(' ')
192
194
  ["--#{name.tr('_', '-')}", *parts]
@@ -3,7 +3,7 @@ module WickedPdf
3
3
  def self.prepended(base)
4
4
  # Protect from trying to augment modules that appear
5
5
  # as the result of adding other gems.
6
- return if base != ActionController::Base
6
+ nil if base != ActionController::Base
7
7
  end
8
8
 
9
9
  def render_to_string(options = nil, *args, &block)