# Add a table of contents to a PDF

Get a clickable table of contents (bookmarks) for a PDF that has none: let SumatraPDF build one from the numbered headings for reading, or save real bookmarks into the PDF with a short script.

**Available in [pre-release 3.7](https://www.sumatrapdfreader.org/prerelease)**

**Press `Ctrl + K` and run `Generate Table Of Contents` to get bookmarks for a paper or report without an outline.** At a glance:

- **Generate Table Of Contents** (`CmdAutoGenerateTOC`): builds bookmarks from numbered headings and shows them in the sidebar. Not saved into the file.
- **`AutoGenerateTOC` setting:** does the same every time you open a PDF without an outline.
- **Save bookmarks into the PDF:** `sumatrapdf-tool run add-toc.js in.pdf out.pdf`, a script that writes the outline you list.
- **Show / hide Bookmarks:** `F12`

## Generate a table of contents from headings

1. Open the PDF.
2. Press `Ctrl + K` and run `Generate Table Of Contents` in [Command Palette](Command-Palette.md). The command is only in the Command Palette, and only for PDF-like documents.
3. The **Bookmarks** sidebar opens once the headings are found. On a long document this takes a moment; you can keep reading meanwhile.

If the PDF already has a table of contents, the command just shows it.

SumatraPDF looks for lines that start with a section number and a period, followed by a word that doesn't start with a lowercase letter:

- `1. Introduction`, `2.3. Results`, `1.2 Scope`
- Roman numerals: `IV. Discussion`, `II.A. Setup`

Numbering decides nesting: `2.3.` goes under `2.`, `II.A.` goes under `II.`. Headings without a number (`Chapter One`, `Abstract`) are not found, and a scanned PDF without a text layer gives no headings.

Note: the generated table of contents exists only while the document is open. It is not written into the PDF, so other PDF readers don't see it. To keep bookmarks in the file, see [Save bookmarks into the PDF](#save-bookmarks-into-the-pdf).

### Generate it automatically

To build the table of contents every time you open a PDF that has none, set `AutoGenerateTOC = true` in [advanced settings](Advanced-options-settings.md) (**Settings → Advanced Settings...**). It is off by default because badly scanned (OCRed) text makes the scan slow and the result useless.

## Save bookmarks into the PDF

SumatraPDF can't edit bookmarks in the window. Use the [`run`](Tool-run.md) command-line tool with a script that writes the outline and saves a new PDF.

1. Save this as `add-toc.js` and edit the list: `title` is the bookmark text, `page` the page number (1 is the first page), `children` the nested bookmarks.

   ```js
   // usage: sumatrapdf-tool run add-toc.js in.pdf out.pdf
   var toc = [
       { title: "Chapter 1", page: 1 },
       { title: "Chapter 2", page: 2, children: [
           { title: "Section 2.1", page: 3 },
       ]},
       { title: "Chapter 3", page: 4 },
   ];

   function addItems(it, items) {
       for (var i = 0; i < items.length; i++) {
           var t = items[i];
           it.insert({ title: t.title, uri: "#page=" + t.page, open: true });
           if (t.children) {
               it.prev(); // move to the item just inserted
               it.down(); // its (empty) list of children
               addItems(it, t.children);
               it.up();
               it.next();
           }
       }
   }

   var doc = Document.openDocument(scriptArgs[0]);
   var it = doc.outlineIterator();
   while (it.item()) {
       it.delete(); // remove the existing outline, if any
   }
   addItems(it, toc);
   doc.save(scriptArgs[1], "garbage,compress");
   ```

2. Run it:

   ```
   sumatrapdf-tool run add-toc.js report.pdf report-toc.pdf
   ```

3. Check the result without opening the file:

   ```
   sumatrapdf-tool show report-toc.pdf outline
   ```

   ```
   |	"Chapter 1"	#page=1
   +	"Chapter 2"	#page=2
   |		"Section 2.1"	#page=3
   |	"Chapter 3"	#page=4
   ```

The script replaces any existing outline. To add to it instead, remove the `while` loop: new bookmarks are then inserted before the first existing one.

Use `SumatraPDF.exe run` instead of `sumatrapdf-tool run` if you only have SumatraPDF installed (see [Tools](Tools.md)).

### Make bookmarks from large text

If the headings are set in a bigger font than the body text, this script adds a bookmark for every line at least a given size (18 points by default):

```js
// usage: sumatrapdf-tool run toc-from-headings.js in.pdf out.pdf [min-font-size]
var minSize = scriptArgs.length > 2 ? parseFloat(scriptArgs[2]) : 18;
var doc = Document.openDocument(scriptArgs[0]);
var it = doc.outlineIterator();
while (it.item()) {
    it.delete();
}
var n = doc.countPages();
for (var i = 0; i < n; i++) {
    var text = JSON.parse(doc.loadPage(i).toStructuredText().asJSON(1));
    text.blocks.forEach(function (block) {
        (block.lines || []).forEach(function (line) {
            var title = line.text.trim();
            if (line.font.size >= minSize && title.length > 0) {
                it.insert({ title: title, uri: "#page=" + (i + 1), open: true });
            }
        });
    });
}
doc.save(scriptArgs[1], "garbage,compress");
```

```
sumatrapdf-tool run toc-from-headings.js report.pdf report-toc.pdf 20
```

It makes a flat list. Run `sumatrapdf-tool show report-toc.pdf outline` to see what it picked up, and adjust the size.

## Tips

- Use `Shift + F12` (**Command Palette: Table Of Contents**) to jump to a bookmark by typing part of its title.
- Write the output to a new file. Saving over the PDF you opened fails with `Permission denied`.
- Use `Generate Table Of Contents` first to see which headings a document has, then copy them into `add-toc.js`.
- Open a bookmark from the command line with `-named-dest "Chapter 2"` (see [Open a PDF at a page or search term](Open-PDF-at-page-from-command-line.md)).

## See also

- [sumatrapdf-tool run](Tool-run.md) and the [JavaScript reference](Tool-run-javascript-reference.md) (`OutlineIterator`)
- [sumatrapdf-tool show](Tool-show.md): inspect the outline of a PDF
- [Advanced settings](Advanced-options-settings.md): `AutoGenerateTOC`
- [Command Palette](Command-Palette.md)
