Prawn: Table of Contents How To
Prawn is a ruby library for generating PDF documents. Although the library is still in beta state, it already has many useful features. Sometimes lack of documentation makes it hard to find right methods/properties.
Recently I needed to generate PDF documents with table of contents for my current project. It took me several hours of reading the source code and disassembling PDF documents to figure out how to do that. So I wanted to post short how-to here for me to remember and hopefully for others to save their time.
To build a table of contents you will need to create a dictionary of named destinations. Because at the time you render table of contents at the beginning of a document you don’t yet know at what page will be your 7th section. To add an entry to the Dests dictionary you use method ‘add_dest’. For example:
# page.dictionary means current page
# There are several dest_* methods to create a destination
add_dest('s34', dest_fit(page.dictionary))
And there are two ways to create a link to a named destination. The first one is to use text inline format:
text "<link anchor='s34'>Section 34</link>", :inline_format => true
This will create a clickable link to move the viewport to the defined destination. The second way is to use ‘link_annotation’ method. It allows you to create a clickable rectangular area defined by coordinates. You can specify a border as well. For example:
link_annotation([40,600,200,640], :Border=>[0,0,1], :Dest=>'s34')
Here you need to know the coordinates, but it’s the only way to create links on images.
The full example that you can try and run yourself follows:
require "#{File.dirname(__FILE__)}/example_helper.rb"
Prawn::Document.generate("toc.pdf") do
font_size 14
pad 10 do
text "Table of Contents", :size=>20
end
text "* <link anchor='section1'>Section 1</link>", :inline_format=>true
text "* <link anchor='section2'>Section 2</link>", :inline_format=>true
link_annotation([40,600,200,640], :Border=>[0,0,1], :Dest=>'section3')
start_new_page
text "Section 1", :size=>20
text 'Lorem ipsum dolor sit amet'
add_dest('section1', dest_fit_horizontally(cursor, page.dictionary))
move_down 300
text "Section 2", :size=>20
text 'Lorem ipsum dolor sit amet'
add_dest('section2', dest_fit_horizontally(cursor, page.dictionary))
start_new_page
text "Section 3", :size=>20
text 'Lorem ipsum dolor sit amet'
add_dest('section3', dest_fit_horizontally(cursor, page.dictionary))
end
Permalink Comments off