hyper-smart-kit 0.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 +7 -0
- data/hyper-smart-kit.gemspec +11 -0
- data/wicked_pdf-2.8.2/CHANGELOG.md +254 -0
- data/wicked_pdf-2.8.2/Gemfile +3 -0
- data/wicked_pdf-2.8.2/LICENSE.txt +22 -0
- data/wicked_pdf-2.8.2/README.md +504 -0
- data/wicked_pdf-2.8.2/Rakefile +58 -0
- data/wicked_pdf-2.8.2/gemfiles/5.0.gemfile +8 -0
- data/wicked_pdf-2.8.2/gemfiles/5.1.gemfile +8 -0
- data/wicked_pdf-2.8.2/gemfiles/5.2.gemfile +9 -0
- data/wicked_pdf-2.8.2/gemfiles/6.0.gemfile +10 -0
- data/wicked_pdf-2.8.2/gemfiles/6.1.gemfile +11 -0
- data/wicked_pdf-2.8.2/gemfiles/7.0.gemfile +11 -0
- data/wicked_pdf-2.8.2/generators/wicked_pdf/templates/wicked_pdf.rb +30 -0
- data/wicked_pdf-2.8.2/generators/wicked_pdf/wicked_pdf_generator.rb +7 -0
- data/wicked_pdf-2.8.2/init.rb +2 -0
- data/wicked_pdf-2.8.2/lib/generators/wicked_pdf_generator.rb +155 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/binary.rb +65 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/middleware.rb +92 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/option_parser.rb +230 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/pdf_helper.rb +128 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/progress.rb +33 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/railtie.rb +17 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/tempfile.rb +43 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/version.rb +3 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/wicked_pdf_helper/assets.rb +332 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf/wicked_pdf_helper.rb +36 -0
- data/wicked_pdf-2.8.2/lib/wicked_pdf.rb +132 -0
- data/wicked_pdf-2.8.2/test/fixtures/database.yml +4 -0
- data/wicked_pdf-2.8.2/test/fixtures/document_with_long_line.html +16 -0
- data/wicked_pdf-2.8.2/test/fixtures/manifest.js +3 -0
- data/wicked_pdf-2.8.2/test/fixtures/subdirectory/nested.js +1 -0
- data/wicked_pdf-2.8.2/test/fixtures/wicked.css +1 -0
- data/wicked_pdf-2.8.2/test/fixtures/wicked.js +1 -0
- data/wicked_pdf-2.8.2/test/functional/pdf_helper_test.rb +96 -0
- data/wicked_pdf-2.8.2/test/functional/wicked_pdf_helper_assets_test.rb +252 -0
- data/wicked_pdf-2.8.2/test/functional/wicked_pdf_helper_test.rb +28 -0
- data/wicked_pdf-2.8.2/test/test_helper.rb +40 -0
- data/wicked_pdf-2.8.2/test/unit/wicked_pdf_binary_test.rb +26 -0
- data/wicked_pdf-2.8.2/test/unit/wicked_pdf_option_parser_test.rb +133 -0
- data/wicked_pdf-2.8.2/test/unit/wicked_pdf_test.rb +100 -0
- data/wicked_pdf-2.8.2/test/unit/wkhtmltopdf_location_test.rb +48 -0
- data/wicked_pdf-2.8.2/wicked_pdf.gemspec +42 -0
- metadata +82 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
class WickedPdf
|
|
2
|
+
module PdfHelper
|
|
3
|
+
def self.prepended(base)
|
|
4
|
+
# Protect from trying to augment modules that appear
|
|
5
|
+
# as the result of adding other gems.
|
|
6
|
+
return if base != ActionController::Base
|
|
7
|
+
|
|
8
|
+
base.class_eval do
|
|
9
|
+
after_action :clean_temp_files
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render(*args)
|
|
14
|
+
options = args.first
|
|
15
|
+
if options.is_a?(Hash) && options.key?(:pdf)
|
|
16
|
+
render_with_wicked_pdf(options)
|
|
17
|
+
else
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def render_to_string(*args)
|
|
23
|
+
options = args.first
|
|
24
|
+
if options.is_a?(Hash) && options.key?(:pdf)
|
|
25
|
+
render_to_string_with_wicked_pdf(options)
|
|
26
|
+
else
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def render_with_wicked_pdf(options)
|
|
32
|
+
raise ArgumentError, 'missing keyword: pdf' unless options.is_a?(Hash) && options.key?(:pdf)
|
|
33
|
+
|
|
34
|
+
options[:basic_auth] = set_basic_auth(options)
|
|
35
|
+
make_and_send_pdf(options.delete(:pdf), (WickedPdf.config || {}).merge(options))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def render_to_string_with_wicked_pdf(options)
|
|
39
|
+
raise ArgumentError, 'missing keyword: pdf' unless options.is_a?(Hash) && options.key?(:pdf)
|
|
40
|
+
|
|
41
|
+
options[:basic_auth] = set_basic_auth(options)
|
|
42
|
+
options.delete :pdf
|
|
43
|
+
make_pdf((WickedPdf.config || {}).merge(options))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def set_basic_auth(options = {})
|
|
49
|
+
options[:basic_auth] ||= WickedPdf.config.fetch(:basic_auth) { false }
|
|
50
|
+
return unless options[:basic_auth] && request.env['HTTP_AUTHORIZATION']
|
|
51
|
+
|
|
52
|
+
request.env['HTTP_AUTHORIZATION'].split(' ').last
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def clean_temp_files
|
|
56
|
+
return unless defined?(@hf_tempfiles)
|
|
57
|
+
|
|
58
|
+
@hf_tempfiles.each(&:close)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def make_pdf(options = {})
|
|
62
|
+
render_opts = {
|
|
63
|
+
:template => options[:template],
|
|
64
|
+
:layout => options[:layout],
|
|
65
|
+
:formats => options[:formats],
|
|
66
|
+
:handlers => options[:handlers],
|
|
67
|
+
:assigns => options[:assigns]
|
|
68
|
+
}
|
|
69
|
+
render_opts[:inline] = options[:inline] if options[:inline]
|
|
70
|
+
render_opts[:locals] = options[:locals] if options[:locals]
|
|
71
|
+
render_opts[:file] = options[:file] if options[:file]
|
|
72
|
+
html_string = render_to_string(render_opts)
|
|
73
|
+
options = prerender_header_and_footer(options)
|
|
74
|
+
w = WickedPdf.new(options[:wkhtmltopdf])
|
|
75
|
+
w.pdf_from_string(html_string, options)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def make_and_send_pdf(pdf_name, options = {})
|
|
79
|
+
options[:wkhtmltopdf] ||= nil
|
|
80
|
+
options[:layout] ||= false
|
|
81
|
+
options[:template] ||= File.join(controller_path, action_name)
|
|
82
|
+
options[:disposition] ||= 'inline'
|
|
83
|
+
if options[:show_as_html]
|
|
84
|
+
render_opts = {
|
|
85
|
+
:template => options[:template],
|
|
86
|
+
:layout => options[:layout],
|
|
87
|
+
:formats => options[:formats],
|
|
88
|
+
:handlers => options[:handlers],
|
|
89
|
+
:assigns => options[:assigns],
|
|
90
|
+
:content_type => 'text/html'
|
|
91
|
+
}
|
|
92
|
+
render_opts[:inline] = options[:inline] if options[:inline]
|
|
93
|
+
render_opts[:locals] = options[:locals] if options[:locals]
|
|
94
|
+
render_opts[:file] = options[:file] if options[:file]
|
|
95
|
+
render(render_opts)
|
|
96
|
+
else
|
|
97
|
+
pdf_content = make_pdf(options)
|
|
98
|
+
File.open(options[:save_to_file], 'wb') { |file| file << pdf_content } if options[:save_to_file]
|
|
99
|
+
send_data(pdf_content, :filename => pdf_name + '.pdf', :type => 'application/pdf', :disposition => options[:disposition]) unless options[:save_only]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Given an options hash, prerenders content for the header and footer sections
|
|
104
|
+
# to temp files and return a new options hash including the URLs to these files.
|
|
105
|
+
def prerender_header_and_footer(options)
|
|
106
|
+
%i[header footer].each do |hf|
|
|
107
|
+
next unless options[hf] && options[hf][:html] && options[hf][:html][:template]
|
|
108
|
+
|
|
109
|
+
@hf_tempfiles = [] unless defined?(@hf_tempfiles)
|
|
110
|
+
@hf_tempfiles.push(tf = WickedPdf::Tempfile.new("wicked_#{hf}_pdf.html"))
|
|
111
|
+
options[hf][:html][:layout] ||= options[:layout]
|
|
112
|
+
render_opts = {
|
|
113
|
+
:template => options[hf][:html][:template],
|
|
114
|
+
:layout => options[hf][:html][:layout],
|
|
115
|
+
:formats => options[hf][:html][:formats],
|
|
116
|
+
:handlers => options[hf][:html][:handlers],
|
|
117
|
+
:assigns => options[hf][:html][:assigns]
|
|
118
|
+
}
|
|
119
|
+
render_opts[:locals] = options[hf][:html][:locals] if options[hf][:html][:locals]
|
|
120
|
+
render_opts[:file] = options[hf][:html][:file] if options[:file]
|
|
121
|
+
tf.write render_to_string(render_opts)
|
|
122
|
+
tf.flush
|
|
123
|
+
options[hf][:html][:url] = "file:///#{tf.path}"
|
|
124
|
+
end
|
|
125
|
+
options
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class WickedPdf
|
|
2
|
+
module Progress
|
|
3
|
+
require 'pty' if RbConfig::CONFIG['target_os'] !~ /mswin|mingw/ && RUBY_ENGINE != 'truffleruby' # no support for windows and truffleruby
|
|
4
|
+
require 'English'
|
|
5
|
+
|
|
6
|
+
def track_progress?(options)
|
|
7
|
+
options[:progress] && !(on_windows? || RUBY_ENGINE == 'truffleruby')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def invoke_with_progress(command, options)
|
|
11
|
+
output = []
|
|
12
|
+
begin
|
|
13
|
+
PTY.spawn(command.join(' ')) do |stdout, _stdin, pid|
|
|
14
|
+
begin
|
|
15
|
+
stdout.sync
|
|
16
|
+
stdout.each_line("\r") do |line|
|
|
17
|
+
output << line.chomp
|
|
18
|
+
options[:progress].call(line) if options[:progress]
|
|
19
|
+
end
|
|
20
|
+
rescue Errno::EIO # rubocop:disable Lint/HandleExceptions
|
|
21
|
+
# child process is terminated, this is expected behaviour
|
|
22
|
+
ensure
|
|
23
|
+
::Process.wait pid
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
rescue PTY::ChildExited
|
|
27
|
+
puts 'The child process exited!'
|
|
28
|
+
end
|
|
29
|
+
err = output.join('\n')
|
|
30
|
+
raise "#{command} failed (exitstatus 0). Output was: #{err}" unless $CHILD_STATUS && $CHILD_STATUS.exitstatus.zero?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'wicked_pdf/pdf_helper'
|
|
2
|
+
require 'wicked_pdf/wicked_pdf_helper'
|
|
3
|
+
require 'wicked_pdf/wicked_pdf_helper/assets'
|
|
4
|
+
|
|
5
|
+
class WickedPdf
|
|
6
|
+
if defined?(Rails.env)
|
|
7
|
+
class WickedRailtie < Rails::Railtie
|
|
8
|
+
initializer 'wicked_pdf.register', :after => 'remotipart.controller_helper' do |_app|
|
|
9
|
+
ActiveSupport.on_load(:action_controller) { ActionController::Base.send :prepend, PdfHelper }
|
|
10
|
+
ActiveSupport.on_load(:action_view) { include WickedPdfHelper::Assets }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
Mime::Type.register('application/pdf', :pdf) if Mime::Type.lookup_by_extension(:pdf).nil?
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
|
|
4
|
+
class WickedPdf
|
|
5
|
+
class Tempfile < ::Tempfile
|
|
6
|
+
def initialize(filename, temp_dir = nil)
|
|
7
|
+
temp_dir ||= Dir.tmpdir
|
|
8
|
+
extension = File.extname(filename)
|
|
9
|
+
basename = File.basename(filename, extension)
|
|
10
|
+
super([basename, extension], temp_dir)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def write_in_chunks(input_string)
|
|
14
|
+
binmode
|
|
15
|
+
string_io = StringIO.new(input_string)
|
|
16
|
+
write(string_io.read(chunk_size)) until string_io.eof?
|
|
17
|
+
close
|
|
18
|
+
self
|
|
19
|
+
rescue Errno::EINVAL => e
|
|
20
|
+
raise e, file_too_large_message
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def read_in_chunks
|
|
24
|
+
rewind
|
|
25
|
+
binmode
|
|
26
|
+
chunks = []
|
|
27
|
+
chunks << read(chunk_size) until eof?
|
|
28
|
+
chunks.join
|
|
29
|
+
rescue Errno::EINVAL => e
|
|
30
|
+
raise e, file_too_large_message
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def chunk_size
|
|
36
|
+
1024 * 1024
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def file_too_large_message
|
|
40
|
+
'The HTML file is too large! Try reducing the size or using the return_file option instead.'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'delegate'
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
class WickedPdf
|
|
6
|
+
module WickedPdfHelper
|
|
7
|
+
module Assets
|
|
8
|
+
ASSET_URL_REGEX = /url\(['"]?([^'"]+?)['"]?\)/
|
|
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
|
+
|
|
75
|
+
def wicked_pdf_asset_base64(path)
|
|
76
|
+
asset = find_asset(path)
|
|
77
|
+
raise MissingLocalAsset, path if asset.nil?
|
|
78
|
+
|
|
79
|
+
base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
|
|
80
|
+
"data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
|
|
81
|
+
end
|
|
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
|
+
|
|
97
|
+
def wicked_pdf_stylesheet_link_tag(*sources)
|
|
98
|
+
stylesheet_contents = sources.collect do |source|
|
|
99
|
+
source = WickedPdfHelper.add_extension(source, 'css')
|
|
100
|
+
"<style type='text/css'>#{read_asset(source)}</style>"
|
|
101
|
+
end.join("\n")
|
|
102
|
+
|
|
103
|
+
stylesheet_contents.gsub(ASSET_URL_REGEX) do
|
|
104
|
+
if Regexp.last_match[1].starts_with?('data:')
|
|
105
|
+
"url(#{Regexp.last_match[1]})"
|
|
106
|
+
else
|
|
107
|
+
"url(#{wicked_pdf_asset_path(Regexp.last_match[1])})"
|
|
108
|
+
end
|
|
109
|
+
end.html_safe
|
|
110
|
+
end
|
|
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
|
+
|
|
139
|
+
def wicked_pdf_image_tag(img, options = {})
|
|
140
|
+
image_tag wicked_pdf_asset_path(img), options
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def wicked_pdf_javascript_src_tag(jsfile, options = {})
|
|
144
|
+
jsfile = WickedPdfHelper.add_extension(jsfile, 'js')
|
|
145
|
+
javascript_include_tag wicked_pdf_asset_path(jsfile), options
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def wicked_pdf_javascript_include_tag(*sources)
|
|
149
|
+
sources.collect do |source|
|
|
150
|
+
source = WickedPdfHelper.add_extension(source, 'js')
|
|
151
|
+
"<script type='text/javascript'>#{read_asset(source)}</script>"
|
|
152
|
+
end.join("\n").html_safe
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def wicked_pdf_asset_path(asset)
|
|
156
|
+
if (pathname = asset_pathname(asset).to_s) =~ URI_REGEXP
|
|
157
|
+
pathname
|
|
158
|
+
else
|
|
159
|
+
"file:///#{pathname}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
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
|
+
|
|
173
|
+
private
|
|
174
|
+
|
|
175
|
+
# borrowed from actionpack/lib/action_view/helpers/asset_url_helper.rb
|
|
176
|
+
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}
|
|
177
|
+
|
|
178
|
+
def asset_pathname(source)
|
|
179
|
+
if precompiled_or_absolute_asset?(source)
|
|
180
|
+
asset = asset_path(source)
|
|
181
|
+
pathname = prepend_protocol(asset)
|
|
182
|
+
if pathname =~ URI_REGEXP
|
|
183
|
+
# asset_path returns an absolute URL using asset_host if asset_host is set
|
|
184
|
+
pathname
|
|
185
|
+
else
|
|
186
|
+
File.join(Rails.public_path, asset.sub(/\A#{Rails.application.config.action_controller.relative_url_root}/, ''))
|
|
187
|
+
end
|
|
188
|
+
else
|
|
189
|
+
asset = find_asset(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
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def find_asset(path)
|
|
200
|
+
if Rails.application.assets.respond_to?(:find_asset)
|
|
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
|
+
relative_asset_path = get_asset_path_from_manifest(path)
|
|
206
|
+
return unless relative_asset_path
|
|
207
|
+
|
|
208
|
+
asset_path = File.join(Rails.application.assets_manifest.dir, relative_asset_path)
|
|
209
|
+
LocalAsset.new(asset_path) if File.file?(asset_path)
|
|
210
|
+
else
|
|
211
|
+
SprocketsEnvironment.find_asset(path, :base_path => Rails.application.root.to_s)
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def get_asset_path_from_manifest(path)
|
|
216
|
+
assets = Rails.application.assets_manifest.assets
|
|
217
|
+
|
|
218
|
+
if File.extname(path).empty?
|
|
219
|
+
assets.find do |asset, _v|
|
|
220
|
+
directory = File.dirname(asset)
|
|
221
|
+
asset_path = File.basename(asset, File.extname(asset))
|
|
222
|
+
asset_path = File.join(directory, asset_path) if directory != '.'
|
|
223
|
+
|
|
224
|
+
asset_path == path
|
|
225
|
+
end&.last
|
|
226
|
+
else
|
|
227
|
+
assets[path]
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# will prepend a http or default_protocol to a protocol relative URL
|
|
232
|
+
# or when no protcol is set.
|
|
233
|
+
def prepend_protocol(source)
|
|
234
|
+
protocol = WickedPdf.config[:default_protocol] || 'http'
|
|
235
|
+
if source[0, 2] == '//'
|
|
236
|
+
source = [protocol, ':', source].join
|
|
237
|
+
elsif source[0] != '/' && !source[0, 8].include?('://')
|
|
238
|
+
source = [protocol, '://', source].join
|
|
239
|
+
end
|
|
240
|
+
source
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def precompiled_or_absolute_asset?(source)
|
|
244
|
+
!Rails.configuration.respond_to?(:assets) ||
|
|
245
|
+
Rails.configuration.assets.compile == false ||
|
|
246
|
+
source.to_s[0] == '/' ||
|
|
247
|
+
source.to_s.match(/\Ahttps?\:\/\//)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def read_asset(source)
|
|
251
|
+
asset = find_asset(source)
|
|
252
|
+
return asset.to_s.force_encoding('UTF-8') if asset
|
|
253
|
+
|
|
254
|
+
unless precompiled_or_absolute_asset?(source)
|
|
255
|
+
raise MissingLocalAsset, source if WickedPdf.config[:raise_on_missing_assets]
|
|
256
|
+
|
|
257
|
+
return
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
pathname = asset_pathname(source)
|
|
261
|
+
if pathname =~ URI_REGEXP
|
|
262
|
+
read_from_uri(pathname)
|
|
263
|
+
elsif File.file?(pathname)
|
|
264
|
+
IO.read(pathname)
|
|
265
|
+
elsif WickedPdf.config[:raise_on_missing_assets]
|
|
266
|
+
raise MissingLocalAsset, pathname if WickedPdf.config[:raise_on_missing_assets]
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def read_from_uri(uri)
|
|
271
|
+
response = Net::HTTP.get_response(URI(uri))
|
|
272
|
+
|
|
273
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
274
|
+
raise MissingRemoteAsset.new(uri, response) if WickedPdf.config[:raise_on_missing_assets]
|
|
275
|
+
|
|
276
|
+
return
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
asset = response.body
|
|
280
|
+
asset.force_encoding('UTF-8') if asset
|
|
281
|
+
asset = gzip(asset) if WickedPdf.config[:expect_gzipped_remote_assets]
|
|
282
|
+
asset
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def gzip(asset)
|
|
286
|
+
stringified_asset = StringIO.new(asset)
|
|
287
|
+
gzipper = Zlib::GzipReader.new(stringified_asset)
|
|
288
|
+
gzipper.read
|
|
289
|
+
rescue Zlib::GzipFile::Error
|
|
290
|
+
nil
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def webpacker_source_url(source)
|
|
294
|
+
return unless webpacker_version
|
|
295
|
+
|
|
296
|
+
# In Webpacker 3.2.0 asset_pack_url is introduced
|
|
297
|
+
if webpacker_version >= '3.2.0'
|
|
298
|
+
if (host = Rails.application.config.asset_host)
|
|
299
|
+
asset_pack_path(source, :host => host)
|
|
300
|
+
else
|
|
301
|
+
asset_pack_url(source)
|
|
302
|
+
end
|
|
303
|
+
else
|
|
304
|
+
source_path = asset_pack_path(source)
|
|
305
|
+
# Remove last slash from root path
|
|
306
|
+
root_url[0...-1] + source_path
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def running_in_development?
|
|
311
|
+
return unless webpacker_version
|
|
312
|
+
|
|
313
|
+
# :dev_server method was added in webpacker 3.0.0
|
|
314
|
+
if Webpacker.respond_to?(:dev_server)
|
|
315
|
+
Webpacker.dev_server.running?
|
|
316
|
+
else
|
|
317
|
+
Rails.env.development? || Rails.env.test?
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def webpacker_version
|
|
322
|
+
if defined?(Shakapacker)
|
|
323
|
+
require 'shakapacker/version'
|
|
324
|
+
Shakapacker::VERSION
|
|
325
|
+
elsif defined?(Webpacker)
|
|
326
|
+
require 'webpacker/version'
|
|
327
|
+
Webpacker::VERSION
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class WickedPdf
|
|
2
|
+
module WickedPdfHelper
|
|
3
|
+
def self.root_path
|
|
4
|
+
String === Rails.root ? Pathname.new(Rails.root) : Rails.root
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.add_extension(filename, extension)
|
|
8
|
+
filename.to_s.split('.').include?(extension) ? filename : "#{filename}.#{extension}"
|
|
9
|
+
end
|
|
10
|
+
|
|
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
|
|
19
|
+
|
|
20
|
+
def wicked_pdf_image_tag(img, options = {})
|
|
21
|
+
image_tag "file:///#{WickedPdfHelper.root_path.join('public', 'images', img)}", options
|
|
22
|
+
end
|
|
23
|
+
|
|
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
|
|
30
|
+
|
|
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
|
|
35
|
+
end
|
|
36
|
+
end
|