Skip to content

Instantly share code, notes, and snippets.

@egardner
Last active October 7, 2022 09:54
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save egardner/e6f8cb683c5dc50132de to your computer and use it in GitHub Desktop.
Save egardner/e6f8cb683c5dc50132de to your computer and use it in GitHub Desktop.
PDF Output for Middleman
# Only the relevant parts of config.rb are included here
require "extensions/pdf"
# ...
configure :build do
activate :pdf do |pdf|
pdf.print_template = "/catalogue/print-template.html"
end
end
class PDF < Middleman::Extension
option :print_template
def initialize(app, options_hash={}, &block)
super
app.after_build do |builder|
input_path = "extensions/filelist.txt"
output_path = "pdf/terracottas.pdf"
puts `prince --input-list=#{input_path} -o #{output_path}`
end
end
def after_configuration
pdf_proxy(app.data.catalogue)
end
def manipulate_resource_list(resources)
pagelist = generate_pagelist
baseurl = "build/"
frontmatter, entries, backmatter = sort_contents(resources)
frontmatter.each { |p| pagelist.puts baseurl + p.destination_path }
entries.each { |p| pagelist.puts baseurl + p.destination_path }
backmatter.each { |p| pagelist.puts baseurl + p.destination_path }
pagelist.close
# return value of this method becomes the new sitemap
resources
end
private
def generate_pagelist
f = File.new("./extensions/filelist.txt", "w")
end
def pdf_proxy(collection)
collection.each do |cat, entry|
app.proxy "/print-catalogue/#{cat}.html", options.print_template,
:locals => { :entry => entry }, :ignore => true
end
end
def sort_contents(resources)
pages = resources.find_all { |p| p.data.sort_order }
frontmatter = pages.find_all { |p| p.data.sort_order < 100 }
backmatter = pages.find_all { |p| p.data.sort_order >= 100 }
entries = resources.find_all { |p| p.data.catalogue == true }
entries.select! { |p| p.destination_path.include? "print-catalogue"}
frontmatter.sort_by! { |p| p.data.sort_order }
backmatter.sort_by! { |p| p.data.sort_order }
entries.sort_by! { |p| p.metadata[:locals][:entry][:info][:cat] }
return frontmatter, entries, backmatter
end
end
::Middleman::Extensions.register(:pdf, PDF)
@egardner
Copy link
Author

Middleman PDF Generator

This is a basic example of how a Middleman extension can programatically create a PDF version of a static website.

Requirements

This extension assumes the Prince PDF generator is being used (it has the best output of any command-line tool by far). However, you could swap out the command in the after_build callback to use any other program which can take a list of files as input.

Usage

First, you must require the extension in config.rb. Default place for it to live is in extensions/.
Then, define a template for the printed versions of any dynamic pages (this setup assumes that dynamic pages are being used, and that the data lives in data/catalogue/). Using a separte template means that interactive elements can be replaced with things that make sense in a printed format (plain img elements instead of dynamic JS-enhanced versions, etc).

The extension will automatically run when the middleman build command is given, and a PDF will appear in the /pdf folder when generation is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment