HTML

For HTML the extension adds an index of its own at the end of the body, or at your placement marker if the document has one: an unnumbered level-one heading — Index, or your document language’s word for it where the extension covers that language — in a section whose id is qi-index where the document has not taken that name and a minted one where it has (see below), listed in the table of contents, followed by a nested bullet list of the entries. It is built out of Pandoc’s own document nodes rather than out of HTML text, so Pandoc’s writer does the escaping. No stylesheet is added; the class names below are hooks for styling it yourself.

Each mark that contributes a locator needs somewhere for its locator to link to:

  • a mark carrying an id of your own keeps it, as long as nothing else on the page carries that same name, and the index links to that id;
  • every other mark gets an anchor on its own span — qi-mark-1, qi-mark-2 and so on, numbered in the order the marks are written.

In a book, a chapter read back from its own source rather than from a record is the one place the first rule is not settled against a rendered page: that route never sees one, so it links to the id you wrote whether or not something else on the page carries that name. A mark in a book chapter’s front matter is a second exception — it links to the chapter’s page either way, and it keeps whatever id you wrote on it, contested or not, with nothing reported: the filter cannot see which of the title-block fields Quarto prints, so it cannot tell whether that name reaches the page at all. A mark this filter cannot index at all is the third — one with no visible text and no entry=, which it reports as unindexable and then leaves exactly as you wrote it, id and all. Such a mark keeps a contested name, so the name stays on two elements and nothing further is said about it; its id is still moved out of a heading, which is the one thing that would put it on the page twice on its own.

Where something else on the page does carry that name, the mark gives it up: one id names one element, and a name on two of them sends every link to whichever one the browser picks. The element you wrote the name on keeps it — the extension renames nothing of yours but its own mark spans — and the mark is given a minted id instead, which for a mark that files a locator is where that locator then points. Between two marks written with one name, the one whose locator links to the name keeps it, whichever you wrote first; between two of a kind the first in the document keeps it and the rest yield. A mark that only points at another entry has no locator to move, but it carries an id like any other span and gives a contested one up the same way. Each yield is reported as the render runs, naming the id given up and what the mark files under — the term it prints, or the entry you wrote for it — so nothing moves out from under a link of your own in silence.

An id counts where it is an attribute of an opening tag, and nowhere else. One written inside a comment is on nothing the rendered page carries, so it contests nothing: a mark written with that name keeps it. So is one written on a closing tag, whose attributes a browser reads and drops — </p id="mine"> puts mine on nothing at all. And so is one written in the text content of script, style, xmp, iframe, noembed, noframes or textarea: a browser reads those seven elements’ content as text rather than as markup, and so does this reading, which steps over that text and goes on with the markup after it. A name on a real element standing after one of the seven, in that same raw HTML block, is counted like any other.

A comment is more than a <!--, and this reading ends one where a browser ends one. A <! opening anything else, a <?, and a </ before anything but a letter each run to the next > and put no element on the page — a comment to a browser, or in the <! case a doctype — so <!ok>, <?ok>, <![CDATA[ok]]> and </ ok> are stepped over here as well. That first > is where each of them ends, whatever comes after it inside: in <![CDATA[a > <p id="mine">]]> the > after the a closes the construct, so mine is on a real element and is counted like any other name. A <!-- ends at a -->, and at an immediate >, an immediate -> and a --!> besides. Past any of those closes, in that same raw HTML block, the markup is markup again: a name on a real element there is counted like any other.

An element whose content a browser reads as text rather than as markup, but which this reading does not step over, is not covered by that: an id= written inside one is read as markup and counted against a mark, which then yields the name to a carrier the page does not have. title is one such element — a name written in a document title’s own text costs a mark that name and leaves the author’s link to it pointing at nothing. The seven above are the ones this reading steps over; how many others there are is not stated here.

A template element’s content is stepped over too: a browser parses it into a document fragment of its own, so the page carries no element for a name written in there, however deeply the templates nest. The element’s own opening tag is markup like any other, and the template on the page carries whatever id you wrote on it — as a script or a style carries one written on theirs.

Inside a script element’s text, a <!-- starts an escaped run and a <script> opened inside that run doubles it: the first </script> after that returns the run to merely escaped rather than ending the element, and this reading holds the element open there as a browser does, so a name written between the two closes is script text and is not counted.

A shape this reading may still get wrong sits inside svg or math, where a browser reads markup by rules of its own: there a <![CDATA[a > <p id="mine">]]> runs to its ]]>, while this reading ends it at the first > and counts mine, which the page then carries no element of. That difference is taken from the HTML specification and is not checked against a browser here. How many such shapes there are is not stated here either.

One kind of name is missed by that reading, and a mark written with it keeps it whatever else carries it, with nothing reported: a name Quarto’s own writer makes up after this extension has run — a footnote’s fn1, a code block’s cb1, title-block-header — does not exist yet when the reading is taken, so writing one of those on a mark still leaves it on two elements.

A heading is the one place an anchor cannot sit, because Quarto copies a heading’s contents into the sidebar table of contents, and an id in there would end up in the page twice. So a heading mark’s anchor — your own id or a minted one — is placed on an invisible element just after the heading, and the locator lands at the start of that section. Such a mark is numbered where its anchor lands; a mark inside a footnote written in that same heading keeps its anchor with the footnote’s text and numbers ahead of it.

Each entry carries an id too, qi-entry-1 onward, so that a cross-reference can link to it. Both kinds of generated id skip any name an element of the rendered page carries — written as an attribute of your own element, or in raw HTML in your source — so writing qi-mark-1 yourself is safe: the numbering steps over it and your element keeps the name. That leaves gaps in the sequence, which is harmless — the numbers are link targets, not a count of anything. The section id is minted the same way: qi-index where the name is free, and qi-index-1, qi-index-2 and so on where the document has taken it. Two kinds of name sit outside that promise. An id injected around the document at render time is never seen by the filter (include-in-header and its relatives). And a name written where the page renders no element — inside a comment of any of the spellings above, on a closing tag, in the text content of one of the seven elements above, inside a template element’s content or in a script’s escaped run — is a name the numbering may mint: nothing of yours is displaced by that, there being no element of yours to displace.

An entry’s locators are numbered links to those anchors: 1, 2, 3 for the first, second and third time the term is marked, restarting at 1 for each entry. So pandoc, 1, 2, 3 in an HTML index means what three page numbers mean in a printed one. The pieces carry these classes:

Class On
qi-term the entry’s own text
qi-locators the run of numbered links
qi-xref, with qi-see or qi-see-also one cross-reference
qi-target the target text inside a cross-reference

A document with no marks gets no index section and no anchors.