postext 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/dist/__tests__/exports.test.js +24 -0
  2. package/dist/__tests__/exports.test.js.map +1 -1
  3. package/dist/__tests__/parse/anchors.test.d.ts +2 -0
  4. package/dist/__tests__/parse/anchors.test.d.ts.map +1 -0
  5. package/dist/__tests__/parse/anchors.test.js +71 -0
  6. package/dist/__tests__/parse/anchors.test.js.map +1 -0
  7. package/dist/__tests__/parse/citations.test.d.ts +2 -0
  8. package/dist/__tests__/parse/citations.test.d.ts.map +1 -0
  9. package/dist/__tests__/parse/citations.test.js +98 -0
  10. package/dist/__tests__/parse/citations.test.js.map +1 -0
  11. package/dist/__tests__/parse/containers.test.js +1 -1
  12. package/dist/__tests__/parse/containers.test.js.map +1 -1
  13. package/dist/__tests__/pipeline/crossRefs.test.d.ts +2 -0
  14. package/dist/__tests__/pipeline/crossRefs.test.d.ts.map +1 -0
  15. package/dist/__tests__/pipeline/crossRefs.test.js +170 -0
  16. package/dist/__tests__/pipeline/crossRefs.test.js.map +1 -0
  17. package/dist/bundle/book.d.ts.map +1 -1
  18. package/dist/bundle/book.js +22 -4
  19. package/dist/bundle/book.js.map +1 -1
  20. package/dist/citations/bibtex.d.ts +19 -0
  21. package/dist/citations/bibtex.d.ts.map +1 -0
  22. package/dist/citations/bibtex.js +375 -0
  23. package/dist/citations/bibtex.js.map +1 -0
  24. package/dist/citations/context.d.ts +64 -0
  25. package/dist/citations/context.d.ts.map +1 -0
  26. package/dist/citations/context.js +115 -0
  27. package/dist/citations/context.js.map +1 -0
  28. package/dist/citations/data.d.ts +35 -0
  29. package/dist/citations/data.d.ts.map +1 -0
  30. package/dist/citations/data.js +158 -0
  31. package/dist/citations/data.js.map +1 -0
  32. package/dist/citations/html.d.ts +16 -0
  33. package/dist/citations/html.d.ts.map +1 -0
  34. package/dist/citations/html.js +99 -0
  35. package/dist/citations/html.js.map +1 -0
  36. package/dist/citations/registry.d.ts +30 -0
  37. package/dist/citations/registry.d.ts.map +1 -0
  38. package/dist/citations/registry.js +51 -0
  39. package/dist/citations/registry.js.map +1 -0
  40. package/dist/citations/types.d.ts +132 -0
  41. package/dist/citations/types.d.ts.map +1 -0
  42. package/dist/citations/types.js +9 -0
  43. package/dist/citations/types.js.map +1 -0
  44. package/dist/defaults/citations.d.ts +5 -0
  45. package/dist/defaults/citations.d.ts.map +1 -0
  46. package/dist/defaults/citations.js +99 -0
  47. package/dist/defaults/citations.js.map +1 -0
  48. package/dist/defaults/crossRefs.d.ts +7 -0
  49. package/dist/defaults/crossRefs.d.ts.map +1 -0
  50. package/dist/defaults/crossRefs.js +35 -0
  51. package/dist/defaults/crossRefs.js.map +1 -0
  52. package/dist/defaults/index.d.ts +2 -0
  53. package/dist/defaults/index.d.ts.map +1 -1
  54. package/dist/defaults/index.js +18 -0
  55. package/dist/defaults/index.js.map +1 -1
  56. package/dist/html-backend.d.ts.map +1 -1
  57. package/dist/html-backend.js +79 -19
  58. package/dist/html-backend.js.map +1 -1
  59. package/dist/index.d.ts +10 -4
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +9 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/knuthPlass/richAdapter.d.ts +2 -0
  64. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  65. package/dist/knuthPlass/richAdapter.js +1 -1
  66. package/dist/knuthPlass/richAdapter.js.map +1 -1
  67. package/dist/measure/cache.js +1 -1
  68. package/dist/measure/cache.js.map +1 -1
  69. package/dist/measure/rich.d.ts +4 -0
  70. package/dist/measure/rich.d.ts.map +1 -1
  71. package/dist/measure/rich.js +2 -2
  72. package/dist/measure/rich.js.map +1 -1
  73. package/dist/parse/attrs.d.ts.map +1 -1
  74. package/dist/parse/attrs.js +31 -4
  75. package/dist/parse/attrs.js.map +1 -1
  76. package/dist/parse/blockParser.d.ts.map +1 -1
  77. package/dist/parse/blockParser.js +68 -8
  78. package/dist/parse/blockParser.js.map +1 -1
  79. package/dist/parse/citations.d.ts +41 -0
  80. package/dist/parse/citations.d.ts.map +1 -0
  81. package/dist/parse/citations.js +206 -0
  82. package/dist/parse/citations.js.map +1 -0
  83. package/dist/parse/index.d.ts +1 -1
  84. package/dist/parse/index.d.ts.map +1 -1
  85. package/dist/parse/index.js.map +1 -1
  86. package/dist/parse/indexMarks.d.ts +2 -7
  87. package/dist/parse/indexMarks.d.ts.map +1 -1
  88. package/dist/parse/indexMarks.js +65 -20
  89. package/dist/parse/indexMarks.js.map +1 -1
  90. package/dist/parse/inlineFormatting.d.ts +2 -2
  91. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  92. package/dist/parse/inlineFormatting.js +41 -14
  93. package/dist/parse/inlineFormatting.js.map +1 -1
  94. package/dist/parse/types.d.ts +50 -4
  95. package/dist/parse/types.d.ts.map +1 -1
  96. package/dist/pipeline/anchors.d.ts +28 -0
  97. package/dist/pipeline/anchors.d.ts.map +1 -0
  98. package/dist/pipeline/anchors.js +123 -0
  99. package/dist/pipeline/anchors.js.map +1 -0
  100. package/dist/pipeline/build.d.ts.map +1 -1
  101. package/dist/pipeline/build.js +51 -11
  102. package/dist/pipeline/build.js.map +1 -1
  103. package/dist/pipeline/citations.d.ts +80 -0
  104. package/dist/pipeline/citations.d.ts.map +1 -0
  105. package/dist/pipeline/citations.js +418 -0
  106. package/dist/pipeline/citations.js.map +1 -0
  107. package/dist/pipeline/config.d.ts.map +1 -1
  108. package/dist/pipeline/config.js +3 -1
  109. package/dist/pipeline/config.js.map +1 -1
  110. package/dist/pipeline/contentWarnings.d.ts +7 -1
  111. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  112. package/dist/pipeline/contentWarnings.js +57 -3
  113. package/dist/pipeline/contentWarnings.js.map +1 -1
  114. package/dist/pipeline/continuation.d.ts +2 -1
  115. package/dist/pipeline/continuation.d.ts.map +1 -1
  116. package/dist/pipeline/continuation.js +3 -0
  117. package/dist/pipeline/continuation.js.map +1 -1
  118. package/dist/pipeline/crossRefs.d.ts +79 -0
  119. package/dist/pipeline/crossRefs.d.ts.map +1 -0
  120. package/dist/pipeline/crossRefs.js +207 -0
  121. package/dist/pipeline/crossRefs.js.map +1 -0
  122. package/dist/pipeline/floatPlacement.d.ts.map +1 -1
  123. package/dist/pipeline/floatPlacement.js +2 -1
  124. package/dist/pipeline/floatPlacement.js.map +1 -1
  125. package/dist/pipeline/index.d.ts +2 -1
  126. package/dist/pipeline/index.d.ts.map +1 -1
  127. package/dist/pipeline/index.js +2 -1
  128. package/dist/pipeline/index.js.map +1 -1
  129. package/dist/pipeline/measureContentBlock.d.ts +4 -0
  130. package/dist/pipeline/measureContentBlock.d.ts.map +1 -1
  131. package/dist/pipeline/measureContentBlock.js +1 -0
  132. package/dist/pipeline/measureContentBlock.js.map +1 -1
  133. package/dist/pipeline/outline.d.ts +3 -0
  134. package/dist/pipeline/outline.d.ts.map +1 -1
  135. package/dist/pipeline/outline.js +38 -1
  136. package/dist/pipeline/outline.js.map +1 -1
  137. package/dist/pipeline/resourceLayout.d.ts +13 -1
  138. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  139. package/dist/pipeline/resourceLayout.js +22 -2
  140. package/dist/pipeline/resourceLayout.js.map +1 -1
  141. package/dist/pipeline/resourceNumbering.d.ts.map +1 -1
  142. package/dist/pipeline/resourceNumbering.js +2 -1
  143. package/dist/pipeline/resourceNumbering.js.map +1 -1
  144. package/dist/types.d.ts +133 -2
  145. package/dist/types.d.ts.map +1 -1
  146. package/dist/vdt.d.ts +59 -1
  147. package/dist/vdt.d.ts.map +1 -1
  148. package/dist/vdt.js.map +1 -1
  149. package/dist/worker/layout.worker.js +6 -0
  150. package/dist/worker/layout.worker.js.map +1 -1
  151. package/package.json +1 -1
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Anchors (#261): the points of a document a cross-reference may name —
3
+ * a heading with an identifier (`## Title {#id}`), an anchor set in the
4
+ * text (`:anchor{#id}`, `[text]{#id}`) and a container opened with one
5
+ * (`:::callout{#id}`). After layout each is located: the page it landed on
6
+ * and the top-left of its heading or line, which the renderers turn into
7
+ * link destinations and the sandbox scrolls to.
8
+ */
9
+ import type { ContentBlock } from '../parse';
10
+ import type { VDTAnchor, VDTDocument } from '../vdt';
11
+ /** Whether the parsed content sets any anchor. */
12
+ export declare function hasAnchors(blocks: readonly ContentBlock[]): boolean;
13
+ /**
14
+ * Where each anchor of `blocks` (the parsed markdown body) landed in the
15
+ * laid-out `doc`. A heading's anchor is its first fragment; an inline
16
+ * anchor is the line holding the character it is attached to (as for an
17
+ * index mark, see `locateIndexMarks`), else the nearest line on the side
18
+ * it attaches to. Undefined when the document sets no anchor.
19
+ */
20
+ export declare function locateAnchors(doc: VDTDocument, blocks: readonly ContentBlock[], bodyOffset: number): VDTAnchor[] | undefined;
21
+ /** The identifiers set more than once in `blocks`, each with the source
22
+ * ranges of its second and later settings (`duplicateAnchor`). */
23
+ export declare function duplicateAnchors(blocks: readonly ContentBlock[]): {
24
+ id: string;
25
+ start: number;
26
+ end: number;
27
+ }[];
28
+ //# sourceMappingURL=anchors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchors.d.ts","sourceRoot":"","sources":["../../src/pipeline/anchors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAY,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE/D,kDAAkD;AAClD,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAEnE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,UAAU,EAAE,MAAM,GACjB,SAAS,EAAE,GAAG,SAAS,CAgEzB;AAED;mEACmE;AACnE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAe9G"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Anchors (#261): the points of a document a cross-reference may name —
3
+ * a heading with an identifier (`## Title {#id}`), an anchor set in the
4
+ * text (`:anchor{#id}`, `[text]{#id}`) and a container opened with one
5
+ * (`:::callout{#id}`). After layout each is located: the page it landed on
6
+ * and the top-left of its heading or line, which the renderers turn into
7
+ * link destinations and the sandbox scrolls to.
8
+ */
9
+ /** Whether the parsed content sets any anchor. */
10
+ export function hasAnchors(blocks) {
11
+ return blocks.some((b) => (b.anchorMarks?.length ?? 0) > 0 || (b.type === 'heading' && b.attrs?.id !== undefined));
12
+ }
13
+ /**
14
+ * Where each anchor of `blocks` (the parsed markdown body) landed in the
15
+ * laid-out `doc`. A heading's anchor is its first fragment; an inline
16
+ * anchor is the line holding the character it is attached to (as for an
17
+ * index mark, see `locateIndexMarks`), else the nearest line on the side
18
+ * it attaches to. Undefined when the document sets no anchor.
19
+ */
20
+ export function locateAnchors(doc, blocks, bodyOffset) {
21
+ const marks = blocks.flatMap((b) => b.anchorMarks ?? []);
22
+ const out = [];
23
+ const seenHeading = new Set();
24
+ for (const b of doc.blocks) {
25
+ // A heading an opener design draws (its block hidden) is a target all
26
+ // the same: its block keeps its page and place.
27
+ if (b.type !== 'heading' || b.pageIndex < 0)
28
+ continue;
29
+ const id = b.attrs?.id;
30
+ if (id === undefined || id.length === 0)
31
+ continue;
32
+ // A split heading keeps its attributes on its first part only; the
33
+ // content index guards against a repeated one all the same.
34
+ if (b.contentIndex !== undefined) {
35
+ if (seenHeading.has(b.contentIndex))
36
+ continue;
37
+ seenHeading.add(b.contentIndex);
38
+ }
39
+ out.push({ id, kind: 'heading', pageIndex: b.pageIndex, x: b.bbox.x, y: b.bbox.y });
40
+ }
41
+ // Bibliography entries: the anchors `ref-<key>` citations link to (#269).
42
+ const seenEntry = new Set();
43
+ for (const b of doc.blocks) {
44
+ if (b.bibEntry === undefined || b.pageIndex < 0 || seenEntry.has(b.bibEntry))
45
+ continue;
46
+ seenEntry.add(b.bibEntry);
47
+ out.push({ id: `ref-${b.bibEntry}`, kind: 'anchor', pageIndex: b.pageIndex, x: b.bbox.x, y: b.bbox.y });
48
+ }
49
+ if (marks.length === 0)
50
+ return out.length > 0 ? out : undefined;
51
+ const lines = [];
52
+ const add = (b) => {
53
+ if (b.pageIndex < 0 || b.hidden)
54
+ return;
55
+ for (const l of b.lines) {
56
+ if (l.sourceStart !== undefined && l.sourceEnd !== undefined) {
57
+ lines.push({ start: l.sourceStart, end: l.sourceEnd, page: b.pageIndex, x: l.bbox.x, y: l.bbox.y });
58
+ }
59
+ }
60
+ };
61
+ for (const b of doc.blocks)
62
+ add(b);
63
+ for (const page of doc.pages)
64
+ for (const f of page.floats ?? [])
65
+ add(f);
66
+ lines.sort((a, b) => a.start - b.start || a.page - b.page);
67
+ /** Index of the last line starting at or before `at` (-1: none). */
68
+ const lastAtOrBefore = (at) => {
69
+ let lo = 0;
70
+ let hi = lines.length;
71
+ while (lo < hi) {
72
+ const mid = (lo + hi) >> 1;
73
+ if (lines[mid].start <= at)
74
+ lo = mid + 1;
75
+ else
76
+ hi = mid;
77
+ }
78
+ return lo - 1;
79
+ };
80
+ for (const mark of marks) {
81
+ if (mark.anchor < 0 || lines.length === 0)
82
+ continue;
83
+ const at = mark.anchor + bodyOffset;
84
+ const i = lastAtOrBefore(at);
85
+ let line;
86
+ for (let j = i; j >= 0 && j > i - 64; j--) {
87
+ const l = lines[j];
88
+ if (at >= l.start && at < l.end && (line === undefined || l.page < line.page))
89
+ line = l;
90
+ }
91
+ line ??= mark.attach === 'before' ? lines[i] ?? lines[i + 1] : lines[i + 1] ?? lines[i];
92
+ if (!line)
93
+ continue;
94
+ out.push({ id: mark.anchorId, kind: 'anchor', pageIndex: line.page, x: line.x, y: line.y, sourceStart: mark.sourceStart });
95
+ }
96
+ return out.length > 0 ? out : undefined;
97
+ }
98
+ /** The identifiers set more than once in `blocks`, each with the source
99
+ * ranges of its second and later settings (`duplicateAnchor`). */
100
+ export function duplicateAnchors(blocks) {
101
+ const seen = new Set();
102
+ const out = [];
103
+ const note = (id, start, end) => {
104
+ if (seen.has(id))
105
+ out.push({ id, start, end });
106
+ else
107
+ seen.add(id);
108
+ };
109
+ for (const b of blocks) {
110
+ const marks = b.anchorMarks ?? [];
111
+ // A container's anchor (its fence opens before the block) comes first.
112
+ for (const m of marks)
113
+ if (m.sourceEnd <= b.sourceStart)
114
+ note(m.anchorId, m.sourceStart, m.sourceEnd);
115
+ if (b.type === 'heading' && b.attrs?.id)
116
+ note(b.attrs.id, b.sourceStart, b.attrSources?.id?.end ?? b.sourceEnd);
117
+ for (const m of marks)
118
+ if (m.sourceEnd > b.sourceStart)
119
+ note(m.anchorId, m.sourceStart, m.sourceEnd);
120
+ }
121
+ return out;
122
+ }
123
+ //# sourceMappingURL=anchors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchors.js","sourceRoot":"","sources":["../../src/pipeline/anchors.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/pipeline/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/pipeline/build.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,11 @@ import { getMeasureRegion, getMeasureUprightDigits, getMeasureWritingMode, setMe
13
13
  import { stampCentralBaselines } from './verticalMetrics';
14
14
  import { resolveAllConfig, computeBaselineGrid, resolvedLocale } from './config';
15
15
  import { createHeadingLevelResolver, deriveSectionGeometryConfig, sectionWritingMode, deriveSectionMeasureContext, headingIsHidden, headingIsNumbered, headingMarksFor, headingStyleOf, planHeadingSections, } from './headingStyles';
16
- import { computeOutline, hasIndexDirective, hasTocDirective, headingNumberingOptions, headingTemplatesOf, outlineFromDoc, sameOutline } from './outline';
16
+ import { locateAnchors } from './anchors';
17
+ import { applyCitations, citationLocale, processCitations, withBibliographyStyle } from './citations';
18
+ import { bookCitationContexts, needsCitationContext } from '../citations/context';
19
+ import { anchorTargetsOf, hasAnchorRefs, printsAnchorPages } from './crossRefs';
20
+ import { anchorOutline, computeOutline, hasIndexDirective, hasTocDirective, headingNumberingOptions, headingTemplatesOf, outlineFromDoc, sameOutline } from './outline';
17
21
  import { expandTocDirectives } from './toc';
18
22
  import { expandIndexDirectives, locateIndexMarks } from './indexDirective';
19
23
  import { resolveBodyStyle, resolveBlockquoteStyle, resolveParagraphStyle } from './styles';
@@ -271,7 +275,16 @@ function placeDocumentPass(content, config, cache, options, hints) {
271
275
  // Footnote definitions (`[^id]: …`) leave the flow; the markers are
272
276
  // numbered in citation order. With `placement: 'chapterEnd'` the notes
273
277
  // come back as paragraphs after each chapter's last block.
274
- const footnoteSplit = splitFootnoteDefinitions(headingMarksFor(parseMarkdownMemo(markdownBody), resolved));
278
+ // Citations (#268): formatted against the book's references (or set as
279
+ // notes under a note style) before the notes leave the flow; the
280
+ // bibliography takes `:::bibliography`'s place or follows the text.
281
+ const parsedBody = headingMarksFor(parseMarkdownMemo(markdownBody), resolved);
282
+ const citationContext = content.citations
283
+ ?? (needsCitationContext(parsedBody, frontmatterMeta) ? bookCitationContexts([{ metadata: frontmatterMeta, blocks: parsedBody }])[0] : undefined);
284
+ const citationsApplied = citationContext
285
+ ? applyCitations(parsedBody, citationContext, processCitations(citationContext, resolved, citationLocale(resolved, resolvedLocale(resolved))), resolved, resolvedLocale(resolved))
286
+ : undefined;
287
+ const footnoteSplit = splitFootnoteDefinitions(citationsApplied?.blocks ?? parsedBody);
275
288
  const footnoteDefs = footnoteSplit.defs;
276
289
  // Numbered by page or column (`numbering: 'page'`), a note takes the
277
290
  // number the previous build gave it where it landed; the first build
@@ -293,8 +306,15 @@ function placeDocumentPass(content, config, cache, options, hints) {
293
306
  // first pass; `buildDocument` lays the document out again with them).
294
307
  // `:::index` expands into the entries of the book's index marks, from
295
308
  // the same outline.
309
+ // A reference naming an anchor (#262) reads its number, title and page
310
+ // from the same outline.
311
+ const resourceIds = new Set((content.resources ?? []).map((r) => r.id));
312
+ const anchorRefs = hasAnchorRefs(parsedBlocks, resourceIds);
296
313
  const outline = content.outline
297
- ?? (hasTocDirective(parsedBlocks) || hasIndexDirective(parsedBlocks) ? computeOutline(parsedBlocks, resolved, headingStart) : undefined);
314
+ ?? (hasTocDirective(parsedBlocks) || hasIndexDirective(parsedBlocks) || anchorRefs ? computeOutline(parsedBlocks, resolved, headingStart) : undefined);
315
+ const anchorRefContext = anchorRefs
316
+ ? { targets: anchorTargetsOf(outline), strings: resolved.crossRefs }
317
+ : undefined;
298
318
  const indexExpanded = expandIndexDirectives(expandTocDirectives(parsedBlocks, outline, resolved), outline, resolved);
299
319
  const contentBlocks = indexExpanded.blocks;
300
320
  if (indexExpanded.warnings.length > 0)
@@ -332,7 +352,10 @@ function placeDocumentPass(content, config, cache, options, hints) {
332
352
  const orderedMetrics = computeOrderedListRunMetrics(contentBlocks, resolved, bodyStyle.fontSizePx);
333
353
  const orderedLevelIndentsPx = computeOrderedLevelIndentsPx(resolved, bodyStyle.fontSizePx, orderedMetrics.maxWidthByDepth);
334
354
  // `:::paragraphs{style="…"}` containers, resolved per content-block index.
335
- const paragraphContainers = planParagraphContainers(contentBlocks, chapterEndNotes ? withFootnoteStyle(resolved) : resolved);
355
+ let containerStyles = chapterEndNotes ? withFootnoteStyle(resolved) : resolved;
356
+ if (citationsApplied?.bibliography)
357
+ containerStyles = withBibliographyStyle(containerStyles, citationsApplied.labelChars);
358
+ const paragraphContainers = planParagraphContainers(contentBlocks, containerStyles);
336
359
  // `:::callout` ranges keyed by their start marker index (same rationale).
337
360
  const calloutPlan = planCallouts(contentBlocks);
338
361
  // `:::part` ranges: start/end marker indices and the enclosed blocks.
@@ -1573,6 +1596,7 @@ function placeDocumentPass(content, config, cache, options, hints) {
1573
1596
  floatedIds,
1574
1597
  leftFlow: calloutsOutOfFlow,
1575
1598
  ...(footnoteNumbering.numbers.size > 0 ? { footnoteNumbers: footnoteNumbering.numbers } : {}),
1599
+ ...(anchorRefContext ? { anchorRefs: anchorRefContext } : {}),
1576
1600
  };
1577
1601
  // --- Footnotes at the column foot (`footnotes.placement: 'column'`) ------
1578
1602
  // A text block placed in a column reserves, at the column's foot, the
@@ -1916,6 +1940,8 @@ function placeDocumentPass(content, config, cache, options, hints) {
1916
1940
  }
1917
1941
  if (raw.footnoteNote !== undefined)
1918
1942
  blk.footnoteNote = raw.footnoteNote;
1943
+ if (raw.bibEntry !== undefined)
1944
+ blk.bibEntry = raw.bibEntry;
1919
1945
  if (raw.toc?.kind === 'entry') {
1920
1946
  blk.tocEntry = raw.toc.pageIndex !== undefined ? { pageIndex: raw.toc.pageIndex } : {};
1921
1947
  }
@@ -5295,7 +5321,9 @@ export function* buildDocumentGen(content, config, cache, options) {
5295
5321
  // References and markup the source names wrongly: read from the source
5296
5322
  // once, located on the pages of the finished layout. Kept apart from
5297
5323
  // `doc.warnings`, whose entries keep their postext 1.4 shape.
5298
- const found = [...collectContentWarnings(content.markdown, config, content.resources ?? []), ...(indexWarnings.get(doc) ?? [])];
5324
+ const bookAnchors = content.outline ? new Set(anchorOutline(content.outline).map((e) => e.anchorId)) : undefined;
5325
+ const bookCitationKeys = content.citations ? new Set(content.citations.items.map((i) => i.id)) : undefined;
5326
+ const found = [...collectContentWarnings(content.markdown, config, content.resources ?? [], bookAnchors, bookCitationKeys), ...(indexWarnings.get(doc) ?? [])];
5299
5327
  const located = found.length > 0 ? locateContentWarnings(doc, found) : [];
5300
5328
  // Justified CJK lines the composer could not fill within its tracking cap.
5301
5329
  const loose = cjkLooseLineWarnings(doc);
@@ -5317,12 +5345,17 @@ export function* buildDocumentGen(content, config, cache, options) {
5317
5345
  const indexWarnings = new WeakMap();
5318
5346
  /** `doc` with the page of each of its index marks (`doc.indexMarks`). */
5319
5347
  function withIndexMarks(doc, content) {
5320
- if (!content.markdown.includes(':index'))
5321
- return doc;
5322
5348
  const { content: body, contentOffset } = extractFrontmatter(content.markdown);
5323
- const marks = locateIndexMarks(doc, parseMarkdownMemo(body), contentOffset);
5324
- if (marks)
5325
- doc.indexMarks = marks;
5349
+ const blocks = parseMarkdownMemo(body);
5350
+ if (content.markdown.includes(':index')) {
5351
+ const marks = locateIndexMarks(doc, blocks, contentOffset);
5352
+ if (marks)
5353
+ doc.indexMarks = marks;
5354
+ }
5355
+ // Where every anchor landed (#261), for links and page references.
5356
+ const anchors = locateAnchors(doc, blocks, contentOffset);
5357
+ if (anchors)
5358
+ doc.anchors = anchors;
5326
5359
  return doc;
5327
5360
  }
5328
5361
  /** {@link buildDocumentGen} before the document-wide warnings: the
@@ -5335,7 +5368,14 @@ function* buildDocumentRounds(content, config, cache, options) {
5335
5368
  // it in one extra round.
5336
5369
  if (content.outline === undefined) {
5337
5370
  const parsed = parseMarkdownMemo(extractFrontmatter(content.markdown).content);
5338
- if (hasTocDirective(parsed) || hasIndexDirective(parsed)) {
5371
+ // A reference printing an anchor's page (#263) settles the same way.
5372
+ const pageRefs = () => {
5373
+ if (!hasAnchorRefs(parsed, new Set((content.resources ?? []).map((r) => r.id))))
5374
+ return false;
5375
+ const resolved = resolveAllConfig(config);
5376
+ return printsAnchorPages(parsed, anchorTargetsOf(computeOutline(parsed, resolved, content.continuation?.headings)), resolved.crossRefs.defaultStyle);
5377
+ };
5378
+ if (hasTocDirective(parsed) || hasIndexDirective(parsed) || pageRefs()) {
5339
5379
  let outline = computeOutline(parsed, resolveAllConfig(config), content.continuation?.headings);
5340
5380
  let doc = withIndexMarks(yield* buildDocumentNumbered({ ...content, outline }, config, cache, options, 0), content);
5341
5381
  for (let round = 0; round < MAX_TOC_ROUNDS; round++) {