lib/pdfkit/pdfkit.rb in pdfkit-0.4.6 vs lib/pdfkit/pdfkit.rb in pdfkit-0.5.0
- old
+ new
@@ -1,49 +1,50 @@
class PDFKit
class NoExecutableError < StandardError
def initialize
msg = "No wkhtmltopdf executable found at #{PDFKit.configuration.wkhtmltopdf}\n"
- msg << ">> Install wkhtmltopdf by hand or try running `pdfkit --install-wkhtmltopdf`"
+ msg << ">> Please install wkhtmltopdf - https://github.com/jdpace/PDFKit/wiki/Installing-WKHTMLTOPDF"
super(msg)
end
end
-
+
class ImproperSourceError < StandardError
def initialize(msg)
super("Improper Source: #{msg}")
end
end
-
+
attr_accessor :source, :stylesheets
attr_reader :options
-
+
def initialize(url_file_or_html, options = {})
@source = Source.new(url_file_or_html)
-
+
@stylesheets = []
@options = PDFKit.configuration.default_options.merge(options)
@options.merge! find_options_in_meta(url_file_or_html) unless source.url?
@options = normalize_options(@options)
-
+
raise NoExecutableError.new unless File.exists?(PDFKit.configuration.wkhtmltopdf)
end
-
- def command
+
+ def command(path = nil)
args = [executable]
args += @options.to_a.flatten.compact
args << '--quiet'
-
+
if @source.html?
args << '-' # Get HTML from stdin
else
args << @source.to_s
end
-
- args << '-' # Read PDF from stdout
- args
+
+ args << (path || '-') # Write to file or stdout
+
+ args.map {|arg| %Q{"#{arg.gsub('"', '\"')}"}}
end
def executable
default = PDFKit.configuration.wkhtmltopdf
return default if default !~ /^\// # its not a path, so nothing we can do
@@ -51,29 +52,33 @@
default
else
default.split('/').last
end
end
-
- def to_pdf
+
+ def to_pdf(path=nil)
append_stylesheets
-
- pdf = Kernel.open('|-', "w+")
- exec(*command) if pdf.nil?
- pdf.puts(@source.to_s) if @source.html?
- pdf.close_write
- result = pdf.gets(nil)
- pdf.close_read
- raise "command failed: #{command.join(' ')}" if result.to_s.strip.empty?
+ args = command(path)
+ invoke = args.join(' ')
+
+ result = IO.popen(invoke, "w+") do |pdf|
+ pdf.puts(@source.to_s) if @source.html?
+ pdf.close_write
+ pdf.gets(nil)
+ end
+ result = File.read(path) if path
+
+ raise "command failed: #{invoke}" if result.to_s.strip.empty?
return result
end
-
+
def to_file(path)
- File.open(path,'w') {|file| file << self.to_pdf}
+ self.to_pdf(path)
+ File.new(path)
end
-
+
protected
def find_options_in_meta(body)
pdfkit_meta_tags(body).inject({}) do |found, tag|
name = tag.attributes["name"].sub(/^#{PDFKit.configuration.meta_tag_prefix}/, '').to_sym
@@ -90,47 +95,47 @@
end
found
rescue # rexml random crash on invalid xml
[]
end
-
+
def style_tag_for(stylesheet)
"<style>#{File.read(stylesheet)}</style>"
end
-
+
def append_stylesheets
raise ImproperSourceError.new('Stylesheets may only be added to an HTML source') if stylesheets.any? && !@source.html?
-
+
stylesheets.each do |stylesheet|
if @source.to_s.match(/<\/head>/)
@source.to_s.gsub!(/(<\/head>)/, style_tag_for(stylesheet)+'\1')
else
@source.to_s.insert(0, style_tag_for(stylesheet))
end
end
end
-
+
def normalize_options(options)
normalized_options = {}
options.each do |key, value|
next if !value
normalized_key = "--#{normalize_arg key}"
normalized_options[normalized_key] = normalize_value(value)
end
normalized_options
end
-
+
def normalize_arg(arg)
arg.to_s.downcase.gsub(/[^a-z0-9]/,'-')
end
-
+
def normalize_value(value)
case value
when TrueClass
nil
else
value.to_s
end
end
-
-end
\ No newline at end of file
+
+end