Skip to content

Interactive PDF#

Hyperlinks (such as a link to a website) or internal links to a PDF page. When they are stored in a StartStop node that has the action node.ActionHyperlink the hyperlink is extracted and added to the PDF.

type Hyperlink struct {
    URI   string
    Local string

If the Local field is set, the hyperlinks points to a named destination, if the URL field is set the hyperlink points to that URL. In PDF terms, the Local link creates a /GoTo action and the URL creates a /URI action.


Bookmarks, or “outlines” in PDF jargon, are described in the PDF backend.

Depending on your application, it might be convenient to create an outline item in the StartStop node callback. This is especially true if you don't know where the outline item should point to.

startstop := node.NewStartStop()
startstop.Action = node.ActionDest
startstop.Value = 123   // a unique id

When the backend encounters a StartStop node in the PDF output with the Action value of ActionDest, it creates a new Dest object from the value.

The idea now is to retrieve this Dest object and create an outline entry. This can be done using a callback:

startstop.Callback = func(n node.Node) string {
    startStop := n.(*node.StartStop)
    num := startStop.Value.(int)
    destObj := doc.GetNumDest(num)
    outline := &pdf.Outline{
        Title: "a bookmark",
        Dest:  fmt.Sprintf("[ %s /XYZ %f %f 0]", destObj.PageObjectnumber.Ref(), destObj.X, destObj.Y),
        Open:  true,
    // add outline to the PDF writer
    curOutlines := doc.PDFWriter.Outlines
    for i := 1; i < attValues.Level; i++ {
        if len(*curOutlines) == 0 {
            slog.Error(fmt.Sprintf("level %d bookmark does not exist for new bookmark (title %s)", i, title))
        } else {
            curOutlines = &(*curOutlines)[len(*curOutlines)-1].Children
    *curOutlines = append(*curOutlines, outline)
    return ""