Books
A Quarto book gets one index for the whole book, not one per chapter — and every index the book declares, in every format, each printed where its own marker stands. See Named indexes for how a book declares more than one. Write the placement marker in the chapter that should hold it:
::: {.qi-index-here}
:::Everything below, down to the last section, is about the HTML book: it is the one Quarto renders a chapter at a time. A PDF or EPUB book goes through a single Pandoc process, so none of it applies — see the last section.
Put that chapter last. Quarto renders an HTML book’s chapters in order, and each chapter is a separate render that cannot see the others, so the index is built from the chapters that ran before the one holding the marker. Put the marker anywhere else and the chapters after it are represented by whatever the previous render recorded: on a first render they are read back from their own sources, without the links into their pages that a record carries, and after an edit their entries can name terms the chapter no longer marks and link to anchors its page no longer has. The extension names those chapters every time it builds the index, so this is loud rather than silent — but the fix is to move the marker, not to render twice.
In the HTML book, each entry’s locators link to the chapters that mark the term, in book order — across files, and across subdirectories, from wherever the index chapter sits. A cross-reference links to its target entry whenever some chapter in the book contributes it, so see= works across chapters exactly as it does inside one document.
A book that declares several indexes prints each index some chapter files a mark in, each at the first marker naming it — in whichever chapter that marker stands — and any index no marker names after them, in declared order, at the end of the book’s last chapter. Every judgement the extension makes across chapters is made inside one index, so a see= written in one index that names a term only another index marks is reported as naming nothing indexed, and the report says which index it was judged in.
The last chapter is where an index no marker names goes whatever the book’s markers say, provided some chapter of the book places an index at all. That chapter is the end of the book’s own chapter list, which every chapter of every render reads the same way, so which chapter carries the section does not change from one render to the next. Where the last chapter carries a marker of its own, the section follows the ones its markers place; where it carries none, the section goes at the end of that chapter. A book with no marker anywhere places no index and grows no section in its last chapter either.
Adding or moving a placement marker takes effect on the very next render: a chapter that gains a marker for an index prints that index from then on. An index no marker names stays in the last chapter throughout — unless the marker you add or remove is the book’s only one, since the proviso above turns every such section on or off with it.
Two things worth knowing:
- Render the whole book when you publish. Rendering a single chapter updates that chapter’s marks only; the index is rebuilt from what the last full render recorded for the others.
quarto renderwith no file argument is what makes the index current. - A book with marks but no marker chapter gets no index, and says so once per render, naming the marker to add. The extension will not choose a chapter for you.
Each chapter records its marks in .quarto/quarto-index/ inside your project — Quarto’s own scratch directory, alongside the caches Quarto keeps there, and never copied into _book/. There is nothing to configure. A project created with quarto create project already ignores /.quarto/ in git; a book whose _quarto.yml you wrote by hand may not, and that one line is worth adding.
If a chapter’s record cannot be written or read back — a read-only project tree, a stale file where the directory belongs, a record left by an older version of this extension — the book still renders, and the extension names the chapter the report is about. Rendering that chapter again is the fix. A record that names an index you have since removed from indexes: costs nothing: its marks are filed in the first index the book still declares, and the report names the chapter and the name.
Where the record was there to open and could not be used, that chapter’s own .qmd is read and parsed instead, and the terms it marks — and the placement markers it carries — join the book’s index. The report says so: it names the chapter and says its terms came from that chapter’s source rather than from a record. Where the source parses and carries no mark this route can reach — a chapter whose marks all arrive through an include, say — the report says that instead, so nothing tells you terms came back when none did.
Which chapter files this route reads is a shorter list than the ones a book can hold: a chapter named .qmd, .md, .markdown or .Rmd, and no other kind. A notebook chapter is one Quarto executes to produce its markdown, and the file on disk is JSON; read as markdown it yields marks whose attribute values carry that file’s own quoting, so its terms are filed under names nothing in the book answers to. Such a chapter is refused and reported by a wording of its own naming the file, and none of its terms reach any index until it is rendered again. This route reads a chapter’s source only where that chapter’s record could not be used or was never written, so a notebook chapter whose record is there and readable is read from that record like any other, which is what a whole-book render leaves behind.
What comes back is what you wrote. An entry= naming several levels rebuilds its sub-entry and the parent it hangs under; a sort= still files the term where it asks; and see= and see-also= still print their lines, neither carrying a page number, as neither does on an ordinary render. An id you wrote on the mark yourself comes back too, and the recovered locator links to it, so following it lands at the passage you marked. A mark you gave no id is anchored at one minted while its chapter renders, and only that chapter’s record carries it: a minted id is settled against every id on the finished page, which this route cannot see from one chapter’s source, so a recovered term you gave no id links to the chapter’s page and nothing after it. A mark written in the chapter’s YAML front matter comes back with the marks in its body: an ordinary render indexes one written there, so this route reads a chapter’s front matter as well as its body and the two file the same entry in the same index. A mark written in the chapter’s front matter files one locator, the chapter’s page with no fragment, whether the chapter is read from its record or from its source: whether the page prints that field at all, and where, is the title-block template’s choice rather than this extension’s, so a link into the field could land nowhere, and the index links to the page instead. (A single document that is not a book chapter is different — its front matter is printed on the same page, and a mark there keeps its own anchor. A mark in the chapter’s title: is the other exception: Quarto copies the title into every page’s sidebar and page navigation, and each copy still files a locator of its own.) What does not come back is anything the chapter worked out for itself while it rendered.
Four things recovery does not return.
- Nothing that reaches the chapter through an include shortcode or an executed cell. Quarto expands both before any filter runs, and what is read here is the file on disk.
- Nothing inside a block or span carrying
.content-visibleor.content-hidden. Quarto settles those by the format being rendered, the active profile, or a metadata value, and the file on disk records none of that — so recovery takes such a block or span out whole, whatever itswhen-orunless-attributes say. A term marked inside one is left out even where this render would have printed it. - Nothing at all, where Pandoc’s markdown reader cannot read the chapter source. The report then says the source could not be read either, and that chapter’s terms are missing from the index until it is rendered again. It says so in the words of the state the record was in: where a record was written and could not be read, the report names both files; where no render has written one, it says that instead, and names the source alone — the record it names as never written rather than as unreadable, so the source is the only file it calls unreadable.
- A page range, and a principal locator. Whether two marks are the two ends of one range, and which locator a
mention="principal"emphasizes, are settled inside that chapter’s own render against the anchors it produced. A recovered mark indexes as thoughrange=andmention=were absent: both ends of a range print that chapter’s page, each at the id you wrote on it where you wrote one, and the role prints as an undeclared one does.
A record that is simply absent — a chapter no render has written one for — is read back only where its terms would otherwise be lost from a section this chapter itself prints. Two chapters qualify, and between them they are every chapter that can print one: a chapter carrying a placement marker of its own, and the book’s last chapter, which takes on every index no marker names. Both read the sources of the chapters no record has been written for, and every other chapter reads such a record as absent and says nothing about it.
So a book rendered chapter by chapter, or into a tree whose records never survive, still prints an index carrying every chapter’s terms rather than one short of them — with the same limits every recovered chapter carries. A whole-book render prints the index it always printed, because by the time a chapter reads the store the chapters before it have written their records: the ordinary first render of a book whose marker sits in its last chapter reads no source at all and says nothing. Where the marker sits earlier, the chapters behind it have not rendered yet, so that chapter reads their sources and reports them in one line naming each — the same index either way, and the next render silent.
A chapter with no record whose source parses and reaches no index mark is passed over in silence. It has lost nothing — a chapter that marks nothing looks exactly like this — and reporting it would say so for most of a correct book on every render. Where the source cannot be read at all, the report naming that outcome is drawn — its own wording, saying that no render has written the record and that the chapter’s source could not be read either. The report for a record that WAS written and could not be read says a record was there, which on this path would be a file no render ever made.
One case that looks absent and is not: a record that is there and cannot be opened. What tells the two apart is the listing of the directory the record belongs in — a record whose filename is among that directory’s entries was written there, whatever opening it does, so it is out of reach rather than unwritten and its chapter is read back from its source. That covers one record whose permissions have been cleared, a store directory that has lost the search bit its records are opened through, and the store directory itself being out of reach — replaced by a file, or with its read permission gone — where every record under it is out of reach and every chapter is read back. The book still gets a complete index, with the unusable-record report drawn for each such chapter by every chapter that looks for its record. The fix is whichever put the path out of reach: taking away whatever stands in its place, or restoring permissions.
The listing is the only evidence there is, so a file merely named like a record and unopenable counts as one that was written — a broken symlink left at that path by hand, say. Nothing this extension writes produces a file of that name it cannot open, so the case arises only where something else made it, and what it costs is a chapter read back from its source rather than dropped. A record whose name the directory does not list is absent exactly as before.
The reports repeat on rules of their own. The one for a record no render has written is drawn once for every chapter that builds an index section, which is what such a record costs it; a chapter that builds none draws it too where the records it read show no chapter of the book placing an index. It is drawn once however many such records that chapter met, and names every chapter it covers: a chapter reading a store no render has written meets every other chapter of the book at once, and a report for each of them said one thing several times over. The one for a record that could not be read is drawn by every chapter that opens it — every chapter of the book but the one whose record it is, since a chapter reads the store before it writes its own. The one for a record left by a different version of this extension is drawn once for every chapter that builds an index section, which is what that record costs it; a chapter that builds none draws it too where the records it read show no chapter of the book placing an index — a book with no placement marker anywhere, and equally a chapter rendered while the record of the chapter carrying the marker cannot itself be read.
The one for a chapter whose source this route will not read follows whichever report it stands in for, so a book carrying such a chapter hears about it as often as it would have heard about that chapter’s record. Where the record was left by a different version — which is what a record carrying a version this render can read as a number and does not itself write is read as, and only that: a record file that decodes to a table carrying no version at all, or one holding something other than a number, evidences no version and is read as a record that could not be used — it is drawn on the rule just given: once for every chapter that builds an index section, and once by a chapter that builds none where the records it read show no chapter placing an index. Where no render has written the record, it is drawn on that same rule — once for every chapter that builds an index section, and once by a chapter that builds none where the records it read show no chapter placing an index — in the one line that names every such chapter. And where the record is there and cannot be used — unopenable, holding bytes that do not decode at all, or decoding to a table that names no version this render can read as one — it is drawn by every chapter that looks for it.
The merged books: PDF and EPUB
A PDF book and an EPUB book need none of the above. Quarto renders each as one merged document, so the extension sees every chapter’s marks at once: there is no per-chapter record, nothing to keep current, and the marker may go in any chapter. A PDF book’s makeindex has always had every chapter’s marks at once, and the printed index gathers page numbers from all of them. An EPUB book prints every index its indexes: metadata declares, each under its own title, and a page range opened in one chapter and closed in another pairs — see the EPUB page.
A Typst book is merged the same way. It prints every declared index that holds at least one mark, each under its own title, with page numbers gathered from every chapter, and a page range opened in one chapter and closed in another pairs. Typst books were tested on Quarto 1.10.18. Quarto 1.5.52 does not render a Typst book. See the Typst page, which also notes the author: key Quarto’s Typst book template needs.