tilt-pdf-rails/lib/tilt/pdf.rb

100 lines
1.9 KiB
Ruby

require 'pdfkit'
require 'tilt'
require 'tilt/template'
require 'yaml'
require 'tempfile'
module Tilt
class PDFTemplate < Template
self.default_mime_type = 'application/pdf'
def prepare; end
def evaluate(scope, locals, &block)
main = render_html(main_html_file, scope, locals, &block)
render_css(*css_files, scope, locals, block) do |css|
kit = PDFKit.new(main, pdfkit_options)
css.each { |f| kit.stylesheets << f }
@output = kit.to_pdf
end
@output
end
private
def absolutize(path)
Pathname.new(path).absolute? ? path : File.join(dirname, path)
end
def config
@config = (YAML.load(data) || {})
end
def main_html_file
main_html_from_config || find_html
end
def main_html_from_config
if (f = config['main'])
absolutize(f)
end
end
def css_files
css_from_config || find_css
end
def css_from_config
return unless config.key?('stylesheets')
config.fetch('stylesheets', []).map { |f| absolutize(f) }
end
def pdfkit_options
config.fetch('pdfkit', {})
end
def dirname
File.dirname(eval_file)
end
def find_html
Dir.glob(File.join(dirname, name + '.html*')).first
end
def find_css
Dir.glob(File.join(dirname, name + '.css*'))
end
def render_html(file, scope, locals, &block)
Tilt.new(file).render(scope, locals, &block)
end
def render_css(*files, scope, locals, block)
tmps = []
css = files.map do |file|
case file
when /.*\.css$/
file
else
tmp = Tempfile.new(File.basename(file))
tmps << tmp
css = Tilt.new(file).render(scope, locals, &block)
tmp.write(css)
tmp.close
tmp.path
end
end
yield css
ensure
tmps.each { |tmp| tmp.close! }
end
end
end
Tilt.register Tilt::PDFTemplate, 'rpdf'