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