lib/pdfkit/pdfkit.rb in pdfkit-0.3.3 vs lib/pdfkit/pdfkit.rb in pdfkit-0.4.0

- old
+ new

@@ -1,10 +1,12 @@ class PDFKit - + class NoExecutableError < StandardError def initialize - super('Could not locate wkhtmltopdf-proxy executable') + msg = "No wkhtmltopdf executable found at #{PDFKit.configuration.wkhtmltopdf}\n" + msg << ">> Install wkhtmltopdf by hand or try running `pdfkit --install-wkhtmltopdf`" + super(msg) end end class ImproperSourceError < StandardError def initialize(msg) @@ -26,50 +28,73 @@ :margin_top => '0.75in', :margin_right => '0.75in', :margin_bottom => '0.75in', :margin_left => '0.75in' } - @options = normalize_options(default_options.merge(options)) + + @options = options.dup + unless source.url? + @options.merge! find_options_in_meta(url_file_or_html) + end + @options = normalize_options(default_options.merge(@options)) - raise NoExecutableError.new if wkhtmltopdf.nil? || wkhtmltopdf == '' + raise NoExecutableError.new unless File.exists?(PDFKit.configuration.wkhtmltopdf) end def command - args = [wkhtmltopdf] + args = [PDFKit.configuration.wkhtmltopdf] 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.join(' ') + args end def to_pdf append_stylesheets - pdf = IO.popen(command, "w+") + 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}" if result.to_s.strip.empty? return result end def to_file(path) File.open(path,'w') {|file| file << self.to_pdf} end protected - - def wkhtmltopdf - @wkhtmltopdf ||= `which wkhtmltopdf-proxy`.chomp + + 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 + found.merge(name => tag.attributes["content"]) + end end + + def pdfkit_meta_tags(body) + require 'rexml/document' + xml_body = REXML::Document.new(body) + found = [] + xml_body.elements.each("html/head/meta") do |tag| + found << tag if tag.attributes['name'].to_s =~ /^#{PDFKit.configuration.meta_tag_prefix}/ + end + found + rescue # rexml random crash on invalid xml + [] + end def style_tag_for(stylesheet) "<style>#{File.read(stylesheet)}</style>" end @@ -85,10 +110,11 @@ 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 @@ -101,11 +127,9 @@ def normalize_value(value) case value when TrueClass nil - when String - value.match(/\s/) ? "\"#{value}\"" : value else value end end \ No newline at end of file