Outlines

Outlines (sometimes also called bookmarks) are shown in a the PDF viewer aside of the page, allowing for navigation within the document.

Creating outlines

Outlines can be created from scratch, e.g. when assembling a set of PDF files into a single document.

The following example adds outline entries referring to the 1st, 3rd and 9th page of an existing PDF.

In [1]: from pikepdf import Pdf, OutlineItem

In [2]: pdf = Pdf.open('document.pdf')

In [3]: with pdf.open_outline() as outline:
   ...:     outline.root.extend([
   ...:         # Page counts are zero-based
   ...:         OutlineItem('Section One', 0),
   ...:         OutlineItem('Section Two', 2),
   ...:         OutlineItem('Section Three', 8)
   ...:     ])
   ...: 

In [4]: pdf.save('document_with_outline.pdf')

Another example, for automatically adding an entry for each file in a merged document:

In [5]: from glob import glob

In [6]: pdf = Pdf.new()

In [7]: page_count = 0

In [8]: with pdf.open_outline() as outline:
   ...:     for file in glob('*.pdf'):
   ...:         src = Pdf.open(file)
   ...:         oi = OutlineItem(file, page_count)
   ...:         outline.root.append(oi)
   ...:         page_count += len(src.pages)
   ...:         pdf.pages.extend(src.pages)
   ...: 

In [9]: pdf.save('merged.pdf')

Editing outlines

Existing outlines can be edited. Entries can be moved and renamed without affecting the targets they refer to.

Destinations

Destinations tell the PDF viewer where to go when navigating through outline items. The simplest case is a reference to a page, together with the page location, e.g. Fit (default). However, named destinations can also be assigned.

The PDF specification allows for either use of a destination (Dest attribute) or an action (A attribute), but not both on the same element. OutlineItem elements handle this as follows:

  • When creating new outline entries passing in a page number or reference name, the Dest attribute is used.
  • When editing an existing entry with an assigned action, it is left as-is, unless a destination is set. The latter is preferred if both are present.

Creating a more detailed destination with page location:

In [10]: oi = OutlineItem('First', 0, 'FitB', top=1000)

The above will call make_page_destination when saving to a Pdf document, roughly equivalent to the following:

In [11]: oi.destination = make_page_destination(pdf, 0, 'FitB', top=1000)

Outline structure

For nesting outlines, add items to the children list of another OutlineItem.

In [12]: with pdf.open_outline() as outline:
   ....:     main_item = OutlineItem('Main', 0)
   ....:     outline.root.append(main_item)
   ....:     main_item.children.append(OutlineItem('A', 1))
   ....: