Skip to content

Index (PDF only)

prodockit.index marks important terms where they are discussed and uses those markers to build an alphabetised, PDF-only back-of-book index with page numbers. The marked words remain ordinary inline text on the website, where readers can use Zensical's site search instead.

Use this extension for concepts a printed reader may need to find again. Use Acronyms and glossary when a term needs a separate definition that readers can follow as a link. The actual index page is generated by prodockit.pdf; marking terms alone does not add that page.

Before you start

Install the optional index support before generating a PDF index:

python -m pip install 'prodockit[index]'

Enable the extension

Enable it in zensical.toml:

[project.markdown_extensions."prodockit.index"]
include = true

Mark a term

Mark a term with \index{Term}:

A \index{widget} is the basic unit of work.

Later, this \index{widget} gets combined with a \index{gadget}.

A widget is the basic unit of work.

Later, this widget gets combined with a gadget.

Every marked term renders inline exactly as written - \index{widget} becomes plain "widget" text, nothing more, on the live website. The marker only has an effect on the PDF, and only once include = true is set - see Generating the index below for the generated index page itself.

Marking the same term more than once creates one index entry with all of its page numbers.

Configure the generated index

Set include = true in the extension's zensical.toml table for a traditional, two-column back-of-book index - terms grouped under a bold letter heading (A, B, C, ...), each followed by the page number(s) it appears on - appended as its own page(s) at the very end of the document:

[project.markdown_extensions."prodockit.index"]
include = true
title = "Index"
Setting Default What it controls
include false Whether prodockit pdf generates the index pages.
title "Index" Heading shown on the first generated index page.

You can leave out title when “Index” is the heading you want.

The \index{widget}/\index{gadget} example above renders to an index page like:

Index

G
Gadget, 3

W
Widget, 1, 3

with its own page list deduplicated and sorted; consecutive pages collapse into an en-dash range (67–70) rather than listing every page individually, and non-consecutive pages/ranges are comma-separated (64, 175) - standard back-of-book index convention.

A term is alphabetised (and letter-grouped) ignoring any leading punctuation - --set-upstream option (git push) and -u option (git branch) are filed under S and U respectively (matching where "set-upstream"/"u" itself would sort), not lumped into a separate "symbols" section, the same way a technical book's own index treats command-line options.

Add sub-entries

\index{Parent!Child!Grandchild} - ! separates up to three levels in practice, matching LaTeX makeidx's own long-established \index{primary!secondary!tertiary} convention - nests a term under another, the same way a printed book's own index groups related entries together (e.g. "staging area" with "adding"/"modified" indented beneath it) rather than listing every term as one flat alphabetical run:

Now generate the \index{Git!ssh keys} to use for authentication.

Now generate the ssh keys to use for authentication.

Only the last segment displays inline (ssh keys above) - wherever the term is actually mentioned in your prose - the earlier segments (Git) are only ever used to build the generated index's own nesting, and never appear inline themselves. Renders a nested entry like:

G

Git
    ssh keys, 13, 89

A parent with no marker of its own anywhere (like Git above) still gets its own line - a bare category label with no trailing page list - so its children have somewhere to nest under.

Add code-styled terms

Backticks around the last segment mark a command or other code term - it displays inline in a real <code> element instead of plain text, and the generated index entry renders the same way:

Run \index{`git commit`} to save your changes.

Run git commit to save your changes.

Combine this with sub-entries by putting the backticks around just the last segment - nesting a code-styled git commit entry under a plain Git one:

\index{Git!`git commit`}

Both render an index entry in your document's own monospace font, matching how the term already displays inline:

G

Git
    git commit, 13, 89

Showing this syntax as literal example text

Unlike a plain \index{Term} (protected by a real code span, the same way this page's own examples above are written), the code-styled pattern has to run before Python-Markdown's own backtick handling, so it can recognise its own inner backticks - a side effect is that wrapping the whole call in inline backticks doesn't protect it the way it does for the plain syntax. A fenced code block (as every example on this page already uses) still works, since it's stashed before any inline pattern - this one included - ever runs.

Add linked terms

A term can be a Markdown link. The link remains clickable in the text while the index files it under the visible link text:

\index{[Git](https://git-scm.com/)} is a version control system.

Git is a version control system.

attr_list ({target="_blank"}) doesn't combine cleanly

Do not put {target="_blank"} after a linked index marker; it attaches to the marker rather than the link. If the link must open a new tab, use a raw inline <a> tag:

\index{<a href="https://git-scm.com/" target="_blank">Git</a>} is a version control system.

Reference

Syntax Inline result Index structure
\index{Term} Term One flat entry
\index{Parent!Child} Child Child nested under Parent
\index{Parent!Child!Grandchild} Grandchild Up to three levels
\index{`command`} Code-styled command Code-styled flat entry
\index{Parent!`command`} Code-styled command Code-styled child entry
\index{[Text](url)} Linked Text Entry filed as Text

Important constraints:

  • ! separates hierarchy levels; only the final segment appears in the prose.
  • Backticks for code styling belong around the final segment.
  • Use a fenced code block, not an inline code span, when documenting the code-styled marker literally.
  • attr_list attributes do not attach cleanly to a Markdown link inside an index marker; use a raw <a> element when a linked term needs attributes.

How index generation works

Index generation uses two PDF passes. The first pass determines the page of each marked term; the second adds the completed, deduplicated index. Document authors do not need to configure those passes. Contributors changing the pipeline should read Extension integration.

Customise with a CSS style sheet

Every marked term has the class index. Target .index if you want marked terms to look different on the website. A code-styled term also contains a normal <code> element, so it keeps the project's existing code style.

The attributes used to construct the generated PDF index are an internal pipeline contract. Contributors changing them should read Extension integration.