Permalink
Browse files

First commit

  • Loading branch information...
0 parents commit 71de10b6e223c6746d8defbe4e13c39bf0995c5e @brynary committed May 17, 2010
Showing with 428 additions and 0 deletions.
  1. +4 −0 History.txt
  2. +11 −0 Manifest.txt
  3. +108 −0 README.txt
  4. +18 −0 Rakefile
  5. +83 −0 bin/badger
  6. +21 −0 data/fields.rfdf
  7. +8 −0 lib/badger.rb
  8. +91 −0 lib/badger/driver.rb
  9. +52 −0 lib/badger/fields.rb
  10. +32 −0 lib/badger/template.rb
  11. 0 test/test_badger.rb
@@ -0,0 +1,4 @@
+== 1.0.0 / 2006-12-07
+
+* Initial release
+
@@ -0,0 +1,11 @@
+History.txt
+Manifest.txt
+README.txt
+Rakefile
+bin/badger
+lib/badger.rb
+lib/badger/driver.rb
+lib/badger/fields.rb
+lib/badger/template.rb
+data/fields.rfdf
+test/test_badger.rb
@@ -0,0 +1,108 @@
+badger
+ http://codefluency.rubyforge.org/badger
+ by Bruce Williams (http://codefluency.com)
+
+== DESCRIPTION:
+
+Badger is a library used to generate badge sheets for events, given a PDF template
+and data for the badges.
+
+== FEATURES/PROBLEMS:
+
+It's free, it's quick, and it's easy. That being said, it requires a few things:
+
+* That you have the [free] PDF Toolkit (http://accesspdf.com/pdftk) installed
+* That you have a way to create the PDF template (using the full version of Adobe Acrobat, for instance)
+
+== SYNOPSYS:
+
+The process of creating badges is easy.
+
+* Create a one-page PDF template with the badge design
+* Create a file containing information on the people attending the event
+* Run badger
+
+Here's the details:
+
+=== The PDF Template
+
+Create a one-page PDF with the badge design you'd like to use. Fit as many
+badges in the page as you'd like.
+
+For each badge, make fields as in the following example:
+
+ For the first badge, fields "first_name1", "last_name1", "company1", "role1"
+ .. badges 2 - 5 ...
+ For the sixth badge, fields "first_name6", "last_name6", "company6", "role6"
+
+You can use Adobe Acrobat to create the fields.
+
+* Fields should be named consecutively from 1 to the number of the last badge on the page. If the last
+ badge has a field like "last_name8" it's assumed there are fields "last_name1" through "last_name7" somewhere
+ on the page.
+* What order the badges are in is completely up to you; left-to-right, top-to-bottom, etc
+* With the exception of "first_name," use whatever field [base]names you like. If you use "role" fields, however,
+ keep in mind that, by default, it will be filled to "Attendee" if there if no data provided for the badge (you
+ can override the default, as well, see "badger -h")
+
+=== The Data Source
+
+Create a YAML document. Inside the document should be an array of hashes, as in the following example:
+
+ ---
+ - first_name: Foo
+ last_name: Bar
+ company: Foo Bar, Inc.
+ role: Speaker
+ - first_name: Jane
+ last_name: Jungle
+ - first_name: Yukihiro
+ last_name: Matsumoto
+ role: matz
+
+You don't need to break them up by pages, or have them in any special order.
+
+=== Building the badges
+
+Assuming you have pdftk (in your PATH) and badger installed:
+
+ badger -t your_template.pdf your_data.yml
+
+See badger -h for more information about the possible options.
+
+== REQUIREMENTS:
+
+PDF Toolkit, freely available from http://accesspdf.com/pdftk
+* The pdftk executable must be in your PATH
+
+Ruby requirements: activesupport
+
+== INSTALL:
+
+Install PDF Toolkit (http://accesspdf.com/pdftk)
+sudo gem install badger
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) 2006 Bruce Williams
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
+# -*- ruby -*-
+
+require 'rubygems'
+require 'hoe'
+require './lib/badger.rb'
+
+Hoe.new('badger', Badger::VERSION) do |p|
+ p.rubyforge_name = 'codefluency'
+ p.summary = "Badger is a library used to generate badge sheets for events, given a PDF template and data for the badges."
+ p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
+ p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
+ p.extra_deps = [['activesupport', '>= 1.3.1']]
+ p.email = %q{bruce@codefluency.com}
+ p.author = "Bruce Williams"
+end
+
+# vim: syntax=Ruby
@@ -0,0 +1,83 @@
+#!/usr/bin/env ruby
+# ===================
+# = Check for pdftk =
+# ===================
+
+require 'rubygems'
+require 'optparse'
+require 'ostruct'
+require 'pathname'
+
+gem "activesupport", "~> 2.3"
+
+$LOAD_PATH << Pathname.new(__FILE__).join("..", "..", "lib").expand_path
+require 'badger'
+require 'badger/fields'
+require 'badger/driver'
+require 'badger/template'
+
+# =================
+# = Parse options =
+# =================
+
+options = OpenStruct.new
+
+opts = OptionParser.new do |opt|
+
+ opt.banner = <<-EOB
+
+USAGE: badger -t TEMPLATE_FILE DATA_FILE [OPTIONS]"
+
+ For information on how to build the template and data files, see
+ the documentation for the 'badger' RubyGem or read the local copy of the README
+ located at:
+ #{File.expand_path(File.join(File.dirname(__FILE__), '../README.txt'))}
+
+ OPTIONS
+
+EOB
+
+ opt.on('-r DEFAULT_ROLE', '--default-role DEFAULT_ROLE', "Modify the default role (or uses '#{Badger::Fields::DEFAULT_ROLE}')") do |r|
+ options.default_role = r
+ end
+
+ opt.on('-t TEMPLATE_FILE', '--template TEMPLATE_FILE', "REQUIRED: Template file (pdf with fields)") do |f|
+ if File.file?(f)
+ options.template_file = f
+ else
+ $stderr.puts "Invalid template file: #{f}"
+ exit
+ end
+ end
+
+ opt.on('-o OUTPUT_FILE', '--output-file OUTPUT_FILE', "OPTIONAL: Set output filename (pdf)") do |o|
+ options.output_file = o
+ end
+
+ opt.on_tail('-h', '--help', "Show this message") do |section|
+ if section == 'template'
+
+ else
+ puts opt
+ end
+ exit
+ end
+
+end
+opts.parse!
+
+# ===================
+# = Go! (ok, maybe) =
+# ===================
+
+if ARGV.empty? || !File.exists?(ARGV[0])
+ $stderr.puts "ERROR: Missing input file"
+ puts opts
+elsif !options.template_file
+ $stderr.puts "ERROR: Missing template file"
+ puts opts
+else
+ output = Badger::Driver.new(ARGV[0], options).run
+ puts "Output #{output}"
+end
+
@@ -0,0 +1,21 @@
+%FDF-1.2
+1 0 obj
+<<
+/FDF
+<<
+/Fields [
+<% people.each_with_index do |person,person_index|
+ next unless person
+ person.each do |field_base, value|
+%>
+<< /T (<%= field_base %><%= person_index + 1 %>) /V (<%= escape_value value %>) >>
+<%
+ end
+end %>
+]
+/F (<%= @template.absolute_path %>) >>
+ >>
+endobj
+trailer
+<< /Root 1 0 R >>
+%%EOF
@@ -0,0 +1,8 @@
+require 'active_support'
+require 'fileutils'
+require 'yaml'
+require 'erb'
+
+module Badger
+ VERSION = '1.0.1'
+end
@@ -0,0 +1,91 @@
+module Badger
+
+ DEFAULT_OUTPUT_FILE = 'badges.pdf'
+ BUILD_BASE = 'build'
+
+ ::Time::DATE_FORMATS[:build_number] = '%Y%m%d%H%M%S'
+
+ class Driver
+
+ class BuildError < ::StandardError; end
+
+ def initialize(input_file, options)
+ @options = options
+ @template = Template.new(options.template_file)
+ @fields = Fields.new(input_file, @template, options.default_role)
+ @number_of_pages = @fields.size / @template.badges_per_page
+ @number_of_pages += 1 if @fields.size % @template.badges_per_page > 0
+ @build_number = Time.now.to_s(:build_number)
+ end
+
+ def run
+ setup
+ archive_template_and_data
+ $stderr.puts "Building in #{build_dir}"
+ write_fdfs
+ build_pages
+ append_pages
+ end
+
+ #######
+ private
+ #######
+
+ def archive_template_and_data
+ FileUtils.cp @template.filename, build_path('src/template.yml')
+ FileUtils.cp @fields.filename, build_path('src/fields.yml')
+ end
+
+ def write_fdfs
+ @fields.in_pages_of(@template.badges_per_page) do |fdf, page_number|
+ File.open(build_path("src/page#{page_number}.fdf"), 'w'){|f| f.puts(fdf) }
+ end
+ end
+
+ def build_pages
+ 1.upto(@number_of_pages){|n| build_page(n) }
+ end
+
+ def build_page(number)
+ pdf = build_path("src/page#{number}.pdf")
+ args = ["pdftk", @template.filename,
+ 'fill_form', build_path("src/page#{number}.fdf"),
+ "output", pdf,
+ "flatten"]
+ puts args.join(" ")
+ unless system(*args) && File.file?(pdf)
+ raise BuildError, "Could not build Page ##{number} (bad response from pdftk)"
+ end
+ end
+
+ def append_pages
+ pdf = @options.output_file || build_path(DEFAULT_OUTPUT_FILE)
+ if @number_of_pages > 1
+ $stderr.puts "Appending pages..."
+ args = ["pdftk", Dir[build_path('src/page*.pdf')] , "cat", "output", pdf].flatten
+ puts args.join(" ")
+ unless system(*args) && File.file?(pdf)
+ raise BuildError, "Could not append pages to #{pdf} (bad response from pdftk)"
+ end
+ else
+ $stderr.puts "Only one page, skipping append..."
+ FileUtils.cp build_path("src/page1.pdf"), pdf
+ end
+ pdf
+ end
+
+ def setup
+ FileUtils.mkdir_p build_path('src')
+ end
+
+ def build_path(basename)
+ File.join(build_dir, basename)
+ end
+
+ def build_dir
+ File.join(BUILD_BASE, @build_number)
+ end
+
+ end
+
+end
Oops, something went wrong.

0 comments on commit 71de10b

Please sign in to comment.