oxedyne/fe2o3/fe2o3_austenite/tests/oracle/fixtures/claim_index_fixture.typ
7.3 KiB, 2 runs
created by r1870400018:58314, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | // The oracle harness's reverse-claim-index fixture -- the corpus's root for the D2 reverse claim-reference |
| 2 | // index. It exercises three things at once: `#claim-label(<code>)` sets a compressed code in the outside |
| 3 | // margin (the A1 marginalia primitive, as `marginalia_fixture.typ` does); `#claim-refs(<code>..)` registers |
| 4 | // a metadata-only reference, setting nothing visible; and a line-leading `#context { ... collect-claim-refs() |
| 5 | // ... }` appendix builds the reverse index -- for each claim code, in byte order, the pages it was referenced |
| 6 | // on. Self-contained -- no `#import` of any shared template -- so it compiles under typst 0.15.1 with no |
| 7 | // symbol-modifier patch, and austenite reads `#claim-label`/`#claim-refs` as builtins and recognises the |
| 8 | // `collect-claim-refs(` signature in the `#context` block without evaluating the block (it is hard-stratified |
| 9 | // and runs no `query`), building the same reverse index from the references it gathered walking the body. |
| 10 | // |
| 11 | // The page geometry is austenite's own `PageGeometry::a4()` (A4, uniform 56.9 pt margins) at the default |
| 12 | // 11 pt Libertinus Serif, so a referenced code lands on the same leaf in both engines. The body references a |
| 13 | // small set of codes spread across two pages, so the reverse index is non-vacuous: at least one code is |
| 14 | // referenced on more than one page, and the codes sort into byte order. The `claim-refs`/`claim-label`/ |
| 15 | // `collect-claim-refs` definitions reproduce the book's `claims.typ` metadata-and-query machinery so Typst |
| 16 | // renders the same index austenite builds from the ledger. |
| 17 | |
| 18 | #set page(width: 595.276pt, height: 841.89pt, margin: 56.9pt) |
| 19 | #set text(size: 11pt, font: "Libertinus Serif") |
| 20 | #set par(justify: true) |
| 21 | |
| 22 | #let claim-ref-tag = "claim-ref" |
| 23 | |
| 24 | // Register one or more claim codes at the current location. No visible output. |
| 25 | #let claim-refs(..codes) = { |
| 26 | let code-strs = codes.pos().map(c => if type(c) == label { str(c) } else { str(c) }) |
| 27 | [#metadata((tag: claim-ref-tag, codes: code-strs))<claim-ref>] |
| 28 | } |
| 29 | |
| 30 | // Query helper -- returns the metadata elements registered by claim-refs/claim-label. |
| 31 | #let collect-claim-refs() = { |
| 32 | query(<claim-ref>) |
| 33 | } |
| 34 | |
| 35 | // Place a compressed claim code in the outside margin AND register its metadata for the reverse index. |
| 36 | #let claim-label(..codes) = { |
| 37 | let strs = codes.pos().map(c => if type(c) == label { str(c) } else { str(c) }) |
| 38 | let display = strs.join(" ") |
| 39 | [#metadata((tag: claim-ref-tag, codes: strs))<claim-ref>] |
| 40 | box(width: 0pt, clip: false, context { |
| 41 | let pos = here().position() |
| 42 | let page-w = 595.276pt |
| 43 | let outside-m = 56.9pt |
| 44 | let content = text(size: 6.5pt, fill: luma(90), hyphenate: false, display) |
| 45 | let m = measure(content) |
| 46 | let sized = box(width: m.width, content) |
| 47 | if calc.odd(counter(page).get().first()) { |
| 48 | place(dx: page-w - outside-m - pos.x, sized) |
| 49 | } else { |
| 50 | place(dx: outside-m - m.width - pos.x, sized) |
| 51 | } |
| 52 | }) |
| 53 | } |
| 54 | |
| 55 | = Reverse Claim Index |
| 56 | |
| 57 | The opening paragraph invokes a foundational claim#claim-refs(<A1>) whose code is registered as a metadata- |
| 58 | only reference, setting nothing in the body column and nothing in the margin, while the reverse index records |
| 59 | the page it fell on. A second proposition#claim-refs(<B2>) is registered on the same leaf, so two distinct |
| 60 | codes share this first page and the index must list each against it. |
| 61 | |
| 62 | A claim reference cannot resolve its own page inline, because the page a mark lands on is a forward layout |
| 63 | fact the paragraph has not yet fixed. The stratified answer is to weave a zero-width anchor at the point of |
| 64 | the reference, record where it lands, and read the page back from the converged ledger when the reverse index |
| 65 | is set as back matter. Nothing about the anchor occupies horizontal space, so the words flow as if it were |
| 66 | absent, and the same code#claim-refs(<A2>) referenced here joins the index under its own entry. |
| 67 | |
| 68 | The compression the visible label applies collapses a run of three or more consecutive codes into a range, |
| 69 | and a single code sets as written. A visible label#claim-label(<C3>) both draws its code in the outside margin |
| 70 | and registers the same metadata for the reverse index, so a label and a bare reference contribute alike to the |
| 71 | page list, the label leaving ink in the margin and the reference leaving none. |
| 72 | |
| 73 | Reproduction is the instrument. Every downstream document that leans on a reverse index is an opportunity to |
| 74 | harden the machinery, to break it against a real page and mend it upstream rather than papering over the gap |
| 75 | in the document that surfaced it. The reverse index is one such exercise, long missing from the reproduction |
| 76 | because a hard-stratified engine could not run the query the appendix is written with, and had to recognise |
| 77 | its shape instead and build the same index from the anchors it recorded walking the body. |
| 78 | |
| 79 | The apparatus of a scholarly page is mostly its cross references, and mostly invisible until it is missing. A |
| 80 | claim referenced in the body and gathered into an appendix is a small thing on any one line and a substantial |
| 81 | thing across a book, the thread that ties a proposition to every place it is invoked. Reproducing it end to |
| 82 | end, from the reference mark to the sorted page list, is the difference between a document that looks right |
| 83 | and one that is right. |
| 84 | |
| 85 | Enough prose now stands above this point to carry the column past the foot of the first page and onto the |
| 86 | second, so that a reference set below falls on a different leaf and the reverse index lists a code against two |
| 87 | distinct pages rather than one. The overlay draws each entry's pages from the same converged ledger the running |
| 88 | head reads, so neither can reopen the fixed point the composition settled on. |
| 89 | |
| 90 | This second-page paragraph invokes the foundational claim#claim-refs(<A1>) once more, on a later leaf than its |
| 91 | first mention, so the index lists that code against two pages and proves the deduplicated, sorted page list is |
| 92 | built from real resolved folios rather than a single occurrence. A further reference#claim-refs(<B1>) registers |
| 93 | a fourth code, so the sorted index carries A1, A2, B1, B2 and C3 in byte order, each followed by the pages it |
| 94 | was referenced on. |
| 95 | |
| 96 | == Index of Body References |
| 97 | |
| 98 | Foundational claims are cited through invisible metadata. The reverse index records the pages where each claim |
| 99 | is invoked. |
| 100 | |
| 101 | #context { |
| 102 | let refs = collect-claim-refs() |
| 103 | if refs.len() == 0 [ |
| 104 | _No body references registered._ |
| 105 | ] else { |
| 106 | let by-code = (:) |
| 107 | for r in refs { |
| 108 | for code in r.value.codes { |
| 109 | if code in by-code { |
| 110 | by-code.insert(code, by-code.at(code) + (r.location(),)) |
| 111 | } else { |
| 112 | by-code.insert(code, (r.location(),)) |
| 113 | } |
| 114 | } |
| 115 | } |
| 116 | let codes = by-code.keys().sorted() |
| 117 | for code in codes { |
| 118 | let locs = by-code.at(code) |
| 119 | let pages = locs.map(loc => str(counter(page).at(loc).first())) |
| 120 | [#strong(code): #pages.join(", ").] |
| 121 | linebreak() |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | |
| 126 | == Sources |
| 127 | |
| 128 | A section set after the reverse index, so its placement pins the listing above. In Typst the |
| 129 | `#context { ... collect-claim-refs() ... }` block sets in flow at its heading, so this section opens directly |
| 130 | beneath the last claim entry. A listing appended as back matter instead -- after every later section -- would |
| 131 | strand these entries below this heading rather than above it, leaving the "Index of Body References" heading |
| 132 | and its intro paragraph orphaned pages ahead of a headless run of codes. The section is here so the reverse |
| 133 | index's in-flow placement is a fact the oracle can see, not an assertion the comment alone carries. |