class Tilt::PDFTemplate

Public Instance Methods

evaluate(scope, locals, &block) click to toggle source
# File lib/tilt/pdf.rb, line 14
def evaluate(scope, locals, &block)
  files = aux_files
  files << main_html_file
  render_to_tmp(*files, scope, locals, block) do |tmp|
    opts = pdfkit_options

    if header
      htmp = tmp.select { |_, f, _| f == header }.first[2]
      opts.merge!('header-html' => htmp) if header
    end

    if footer
      ftmp = tmp.select { |_, f, _| f == footer }.first[2]
      opts.merge!('footer-html' => ftmp) if footer
    end

    main = tmp.select { |_, f, _| f == main_html_file }.first[2]
    kit = PDFKit.new(File.read(main), opts)

    @output = kit.to_pdf
  end

  @output
end
prepare() click to toggle source
# File lib/tilt/pdf.rb, line 12
def prepare; end

Private Instance Methods

absolutize(path) click to toggle source
# File lib/tilt/pdf.rb, line 41
def absolutize(path)
  Pathname.new(path).absolute? ? path : File.join(dirname, path)
end
append_to_head!(document, tag) click to toggle source
# File lib/tilt/pdf.rb, line 144
def append_to_head!(document, tag)
  if document.match(/<\/head>/)
    document.gsub!(/(<\/head>)/) { |s| tag + s }
  else
    document.insert(0, tag)
  end
end
aux_files() click to toggle source
# File lib/tilt/pdf.rb, line 49
def aux_files
  files = []
  files.concat css_files
  files.concat js_files
  files << header if header
  files << footer if footer

  files
end
config() click to toggle source
# File lib/tilt/pdf.rb, line 45
def config
  @config = (YAML.load(data) || {})
end
css_files() click to toggle source
# File lib/tilt/pdf.rb, line 81
def css_files
  css_from_config || find_css
end
css_from_config() click to toggle source
# File lib/tilt/pdf.rb, line 85
def css_from_config
  return unless config.key?('stylesheets')

  config.fetch('stylesheets', []).map { |f| absolutize(f) }
end
dirname() click to toggle source
# File lib/tilt/pdf.rb, line 116
def dirname
  File.dirname(eval_file)
end
find_css() click to toggle source
# File lib/tilt/pdf.rb, line 124
def find_css
  Dir.glob(File.join(dirname, name + '.css*'))
end
find_html() click to toggle source
# File lib/tilt/pdf.rb, line 120
def find_html
  Dir.glob(File.join(dirname, name + '.html*')).first
end
find_js() click to toggle source
# File lib/tilt/pdf.rb, line 128
def find_js
  Dir.glob(File.join(dirname, name + '.js*'))
end
header() click to toggle source
# File lib/tilt/pdf.rb, line 59
def header
  if (f = config['header'])
    absolutize(f)
  end
end
inject_css!(document, stylesheet) click to toggle source
# File lib/tilt/pdf.rb, line 136
def inject_css!(document, stylesheet)
  append_to_head!(document, "<style>#{stylesheet}</style>")
end
inject_js!(document, script) click to toggle source
# File lib/tilt/pdf.rb, line 140
def inject_js!(document, script)
  append_to_head!(document, "<script>#{script}</script>")
end
js_files() click to toggle source
# File lib/tilt/pdf.rb, line 91
def js_files
  js_from_config || find_js
end
js_from_config() click to toggle source
# File lib/tilt/pdf.rb, line 95
def js_from_config
  return unless config.key?('javascripts')

  config.fetch('javascripts', []).map { |f| absolutize(f) }
end
main_html_file() click to toggle source
# File lib/tilt/pdf.rb, line 71
def main_html_file
  main_html_from_config || find_html
end
main_html_from_config() click to toggle source
# File lib/tilt/pdf.rb, line 75
def main_html_from_config
  if (f = config['main'])
    absolutize(f)
  end
end
pdfkit_options() click to toggle source
# File lib/tilt/pdf.rb, line 101
def pdfkit_options
  toplevel_options = %w[title
                        orientation
                        grayscale
                        page-size
                        margin-left
                        margin-right
                        margin-top
                        margin-bottom]

  options = config.select { |k, _| toplevel_options.include?(k) }

  options.merge config.fetch('pdfkit', {})
end
render_html(file, scope, locals, &block) click to toggle source
# File lib/tilt/pdf.rb, line 132
def render_html(file, scope, locals, &block)
  Tilt.new(file).render(scope, locals, &block)
end
render_to_tmp(*files, scope, locals, block) { |result| ... } click to toggle source
# File lib/tilt/pdf.rb, line 152
def render_to_tmp(*files, scope, locals, block)
  tmps = []
  no_tilt = %w[html css js]

  result = files.map do |file|
    ext = File.extname(file).sub(/^\./, '')
    if no_tilt.include?(ext)
      mime = case ext
             when 'js', 'javascript' then 'application/javascript'
             else "text/#{ext}"
             end
      rendered = File.read(file)
    else
      template = Tilt.new(file)
      mime = template.class.default_mime_type
      ext = mime.split('/').last
      rendered = template.render(scope, locals, &block)
    end

    [ext, mime, file, rendered]
  end

  result.sort! do |a, b|
    a[1] <=> b[1]  # css < html
  end

  styles = result.select { |_, mime, _, _| mime == 'text/css' }
  scripts = result.select { |_, mime, _, _| mime == 'application/javascript' }
  result.map! do |ext, mime, file, rendered|
    if mime == 'text/html'
      styles.each do |_, _, _, style|
        inject_css!(rendered, style)
      end
      scripts.each do |_, _, _, script|
        inject_js!(rendered, script)
      end
    end

    [ext, mime, file, rendered]
  end

  result.map! do |ext, mime, file, rendered|
    tmp = Tempfile.new([File.basename(file), '.' + ext])
    tmps << tmp
    tmp.write(rendered)
    tmp.close

    path = tmp.path

    [mime, file, path]
  end

  yield result
ensure
  tmps.each { |tmp| tmp.close! }
end