postext 0.3.15 → 0.3.17

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 (175) hide show
  1. package/dist/__tests__/createLayout.test.js +12 -13
  2. package/dist/__tests__/createLayout.test.js.map +1 -1
  3. package/dist/__tests__/defaults/resourceTypes.test.d.ts +2 -0
  4. package/dist/__tests__/defaults/resourceTypes.test.d.ts.map +1 -0
  5. package/dist/__tests__/defaults/resourceTypes.test.js +69 -0
  6. package/dist/__tests__/defaults/resourceTypes.test.js.map +1 -0
  7. package/dist/__tests__/exports.test.js +54 -0
  8. package/dist/__tests__/exports.test.js.map +1 -1
  9. package/dist/__tests__/parse/inlineRef.test.d.ts +2 -0
  10. package/dist/__tests__/parse/inlineRef.test.d.ts.map +1 -0
  11. package/dist/__tests__/parse/inlineRef.test.js +83 -0
  12. package/dist/__tests__/parse/inlineRef.test.js.map +1 -0
  13. package/dist/__tests__/parse/resourceDirective.test.d.ts +2 -0
  14. package/dist/__tests__/parse/resourceDirective.test.d.ts.map +1 -0
  15. package/dist/__tests__/parse/resourceDirective.test.js +55 -0
  16. package/dist/__tests__/parse/resourceDirective.test.js.map +1 -0
  17. package/dist/__tests__/pipeline/floatPlacement.test.d.ts +2 -0
  18. package/dist/__tests__/pipeline/floatPlacement.test.d.ts.map +1 -0
  19. package/dist/__tests__/pipeline/floatPlacement.test.js +141 -0
  20. package/dist/__tests__/pipeline/floatPlacement.test.js.map +1 -0
  21. package/dist/__tests__/pipeline/inlineRefRender.test.d.ts +2 -0
  22. package/dist/__tests__/pipeline/inlineRefRender.test.d.ts.map +1 -0
  23. package/dist/__tests__/pipeline/inlineRefRender.test.js +107 -0
  24. package/dist/__tests__/pipeline/inlineRefRender.test.js.map +1 -0
  25. package/dist/__tests__/pipeline/resourceNumbering.test.d.ts +2 -0
  26. package/dist/__tests__/pipeline/resourceNumbering.test.d.ts.map +1 -0
  27. package/dist/__tests__/pipeline/resourceNumbering.test.js +186 -0
  28. package/dist/__tests__/pipeline/resourceNumbering.test.js.map +1 -0
  29. package/dist/__tests__/table/model.test.d.ts +2 -0
  30. package/dist/__tests__/table/model.test.d.ts.map +1 -0
  31. package/dist/__tests__/table/model.test.js +187 -0
  32. package/dist/__tests__/table/model.test.js.map +1 -0
  33. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  34. package/dist/canvas-backend/blockRender.js +25 -6
  35. package/dist/canvas-backend/blockRender.js.map +1 -1
  36. package/dist/canvas-backend/headerFooter.d.ts +3 -2
  37. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  38. package/dist/canvas-backend/headerFooter.js +63 -2
  39. package/dist/canvas-backend/headerFooter.js.map +1 -1
  40. package/dist/canvas-backend/index.d.ts +2 -0
  41. package/dist/canvas-backend/index.d.ts.map +1 -1
  42. package/dist/canvas-backend/index.js +11 -0
  43. package/dist/canvas-backend/index.js.map +1 -1
  44. package/dist/canvas-backend/renderResourceBlock.d.ts +28 -0
  45. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -0
  46. package/dist/canvas-backend/renderResourceBlock.js +146 -0
  47. package/dist/canvas-backend/renderResourceBlock.js.map +1 -0
  48. package/dist/defaults/bodyText.d.ts.map +1 -1
  49. package/dist/defaults/bodyText.js +30 -0
  50. package/dist/defaults/bodyText.js.map +1 -1
  51. package/dist/defaults/captionStyle.d.ts +9 -0
  52. package/dist/defaults/captionStyle.d.ts.map +1 -0
  53. package/dist/defaults/captionStyle.js +74 -0
  54. package/dist/defaults/captionStyle.js.map +1 -0
  55. package/dist/defaults/debug.d.ts.map +1 -1
  56. package/dist/defaults/debug.js +6 -0
  57. package/dist/defaults/debug.js.map +1 -1
  58. package/dist/defaults/headerFooter.d.ts +20 -18
  59. package/dist/defaults/headerFooter.d.ts.map +1 -1
  60. package/dist/defaults/headerFooter.js +269 -165
  61. package/dist/defaults/headerFooter.js.map +1 -1
  62. package/dist/defaults/headings.d.ts.map +1 -1
  63. package/dist/defaults/headings.js +29 -6
  64. package/dist/defaults/headings.js.map +1 -1
  65. package/dist/defaults/index.d.ts +3 -0
  66. package/dist/defaults/index.d.ts.map +1 -1
  67. package/dist/defaults/index.js +19 -0
  68. package/dist/defaults/index.js.map +1 -1
  69. package/dist/defaults/resourceTypes.d.ts +8 -0
  70. package/dist/defaults/resourceTypes.d.ts.map +1 -0
  71. package/dist/defaults/resourceTypes.js +43 -0
  72. package/dist/defaults/resourceTypes.js.map +1 -0
  73. package/dist/defaults/shared.d.ts.map +1 -1
  74. package/dist/defaults/shared.js +30 -0
  75. package/dist/defaults/shared.js.map +1 -1
  76. package/dist/defaults/tableStyle.d.ts +11 -0
  77. package/dist/defaults/tableStyle.d.ts.map +1 -0
  78. package/dist/defaults/tableStyle.js +114 -0
  79. package/dist/defaults/tableStyle.js.map +1 -0
  80. package/dist/design/layout.d.ts +94 -0
  81. package/dist/design/layout.d.ts.map +1 -0
  82. package/dist/design/layout.js +642 -0
  83. package/dist/design/layout.js.map +1 -0
  84. package/dist/design/placeholders.d.ts +29 -0
  85. package/dist/design/placeholders.d.ts.map +1 -0
  86. package/dist/design/placeholders.js +126 -0
  87. package/dist/design/placeholders.js.map +1 -0
  88. package/dist/html-backend.d.ts.map +1 -1
  89. package/dist/html-backend.js +91 -1
  90. package/dist/html-backend.js.map +1 -1
  91. package/dist/index.d.ts +12 -5
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +6 -2
  94. package/dist/index.js.map +1 -1
  95. package/dist/knuthPlass/richAdapter.d.ts +1 -0
  96. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  97. package/dist/knuthPlass/richAdapter.js +2 -1
  98. package/dist/knuthPlass/richAdapter.js.map +1 -1
  99. package/dist/measure/cache.js +1 -1
  100. package/dist/measure/cache.js.map +1 -1
  101. package/dist/measure/rich.d.ts +7 -0
  102. package/dist/measure/rich.d.ts.map +1 -1
  103. package/dist/measure/rich.js +30 -0
  104. package/dist/measure/rich.js.map +1 -1
  105. package/dist/numbering.d.ts +16 -0
  106. package/dist/numbering.d.ts.map +1 -1
  107. package/dist/numbering.js +28 -18
  108. package/dist/numbering.js.map +1 -1
  109. package/dist/parse/blockParser.d.ts.map +1 -1
  110. package/dist/parse/blockParser.js +37 -9
  111. package/dist/parse/blockParser.js.map +1 -1
  112. package/dist/parse/inlineFormatting.d.ts +38 -0
  113. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  114. package/dist/parse/inlineFormatting.js +84 -0
  115. package/dist/parse/inlineFormatting.js.map +1 -1
  116. package/dist/parse/sourceMapping.d.ts.map +1 -1
  117. package/dist/parse/sourceMapping.js +20 -0
  118. package/dist/parse/sourceMapping.js.map +1 -1
  119. package/dist/parse/types.d.ts +20 -1
  120. package/dist/parse/types.d.ts.map +1 -1
  121. package/dist/pipeline/build.d.ts.map +1 -1
  122. package/dist/pipeline/build.js +389 -17
  123. package/dist/pipeline/build.js.map +1 -1
  124. package/dist/pipeline/buildBlockKind.d.ts +14 -0
  125. package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
  126. package/dist/pipeline/buildBlockKind.js +16 -1
  127. package/dist/pipeline/buildBlockKind.js.map +1 -1
  128. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  129. package/dist/pipeline/buildHelpers.js +7 -1
  130. package/dist/pipeline/buildHelpers.js.map +1 -1
  131. package/dist/pipeline/buildMeasurement.d.ts +17 -1
  132. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  133. package/dist/pipeline/buildMeasurement.js +32 -0
  134. package/dist/pipeline/buildMeasurement.js.map +1 -1
  135. package/dist/pipeline/config.d.ts.map +1 -1
  136. package/dist/pipeline/config.js +3 -1
  137. package/dist/pipeline/config.js.map +1 -1
  138. package/dist/pipeline/floatPlacement.d.ts +45 -0
  139. package/dist/pipeline/floatPlacement.d.ts.map +1 -0
  140. package/dist/pipeline/floatPlacement.js +68 -0
  141. package/dist/pipeline/floatPlacement.js.map +1 -0
  142. package/dist/pipeline/headerFooter.d.ts +23 -7
  143. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  144. package/dist/pipeline/headerFooter.js +258 -100
  145. package/dist/pipeline/headerFooter.js.map +1 -1
  146. package/dist/pipeline/placeholders.d.ts +6 -0
  147. package/dist/pipeline/placeholders.d.ts.map +1 -1
  148. package/dist/pipeline/placeholders.js +46 -0
  149. package/dist/pipeline/placeholders.js.map +1 -1
  150. package/dist/pipeline/placement.d.ts +15 -2
  151. package/dist/pipeline/placement.d.ts.map +1 -1
  152. package/dist/pipeline/placement.js +38 -3
  153. package/dist/pipeline/placement.js.map +1 -1
  154. package/dist/pipeline/resourceLayout.d.ts +58 -0
  155. package/dist/pipeline/resourceLayout.d.ts.map +1 -0
  156. package/dist/pipeline/resourceLayout.js +338 -0
  157. package/dist/pipeline/resourceLayout.js.map +1 -0
  158. package/dist/pipeline/resourceNumbering.d.ts +54 -0
  159. package/dist/pipeline/resourceNumbering.d.ts.map +1 -0
  160. package/dist/pipeline/resourceNumbering.js +218 -0
  161. package/dist/pipeline/resourceNumbering.js.map +1 -0
  162. package/dist/pipeline/styles.d.ts +6 -0
  163. package/dist/pipeline/styles.d.ts.map +1 -1
  164. package/dist/pipeline/styles.js +1 -1
  165. package/dist/pipeline/styles.js.map +1 -1
  166. package/dist/table/model.d.ts +53 -0
  167. package/dist/table/model.d.ts.map +1 -0
  168. package/dist/table/model.js +253 -0
  169. package/dist/table/model.js.map +1 -0
  170. package/dist/types.d.ts +397 -41
  171. package/dist/types.d.ts.map +1 -1
  172. package/dist/vdt.d.ts +165 -18
  173. package/dist/vdt.d.ts.map +1 -1
  174. package/dist/vdt.js.map +1 -1
  175. package/package.json +1 -1
@@ -1,134 +1,292 @@
1
1
  import { createBoundingBox, } from '../vdt';
2
- import { dimensionToPx } from '../units';
3
- import { buildFontString, measureTextWidth } from '../measure';
4
- import { computeChapterTitles, resolvePlaceholders } from './placeholders';
2
+ import { computeChapterTitles, computeChapterNumbers } from './placeholders';
5
3
  import { computePageMetrics } from './buildHelpers';
6
- function pageMatchesParity(pageIndex, parity) {
7
- if (parity === 'all')
8
- return true;
9
- // Convention: use page-number parity (page 1 = odd).
10
- const pageNumber = pageIndex + 1;
11
- const isOdd = pageNumber % 2 === 1;
12
- return parity === 'odd' ? isOdd : !isOdd;
13
- }
14
- function elementHeightPx(el, dpi) {
15
- if (el.kind === 'text') {
16
- const fontSizePx = dimensionToPx(el.fontSize, dpi);
17
- // Approximate line height as 1.2 × font size.
18
- return fontSizePx * 1.2;
19
- }
20
- return dimensionToPx(el.thickness, dpi);
4
+ import { layoutDesignSlot, } from '../design/layout';
5
+ /** Slots live in the page margin area between the body edge and the page
6
+ * edge. Header slot container: from `top-margin` edge down to body top.
7
+ * Footer slot container: from body bottom down to `bottom-margin` edge.
8
+ *
9
+ * We use a larger container (the full page vertical extent of the margin
10
+ * area) so that anchors like `bottom-center` / `bottom-right` for headers
11
+ * and `top-*` for footers align with the body edge (the body-facing side
12
+ * of the margin area) rather than the outer page edge.
13
+ *
14
+ * This matches the legacy semantics: `marginFromBody` was "distance from
15
+ * body edge" the migration translates that to an offset of the same
16
+ * magnitude from the body-facing edge. */
17
+ function headerContainerBbox(contentArea, _pageHeight) {
18
+ // Header: spans from top of page to body top.
19
+ return { x: contentArea.x, y: 0, width: contentArea.width, height: contentArea.y };
21
20
  }
22
- function filterElementsByParity(slot, pageIndex) {
23
- return slot.elements.filter((el) => pageMatchesParity(pageIndex, el.parity));
21
+ function footerContainerBbox(contentArea, pageHeight) {
22
+ const bodyBottom = contentArea.y + contentArea.height;
23
+ return {
24
+ x: contentArea.x,
25
+ y: bodyBottom,
26
+ width: contentArea.width,
27
+ height: Math.max(0, pageHeight - bodyBottom),
28
+ };
24
29
  }
25
- function xForAlign(align, contentX, contentWidth, elementWidth, edgeInsetPx) {
30
+ function textAlignOffsetX(align, contentWidth, lineWidth) {
26
31
  if (align === 'left')
27
- return contentX + edgeInsetPx;
32
+ return 0;
28
33
  if (align === 'right')
29
- return contentX + contentWidth - elementWidth - edgeInsetPx;
30
- return contentX + (contentWidth - elementWidth) / 2;
34
+ return Math.max(0, contentWidth - lineWidth);
35
+ return Math.max(0, (contentWidth - lineWidth) / 2);
36
+ }
37
+ function primitiveToBlock(prim) {
38
+ if (prim.kind === 'text')
39
+ return textPrimitiveToBlock(prim);
40
+ if (prim.kind === 'rule')
41
+ return rulePrimitiveToBlock(prim);
42
+ return boxPrimitiveToBlock(prim);
31
43
  }
32
- function buildTextBlock(el, resolvedText, contentX, contentWidth, elementTop, dpi) {
33
- const fontSizePx = dimensionToPx(el.fontSize, dpi);
34
- const weight = el.fontWeight === 400 ? 'normal' : String(el.fontWeight);
35
- const style = el.italic ? 'italic' : 'normal';
36
- const fontString = buildFontString(el.fontFamily, fontSizePx, weight, style);
37
- const textWidth = measureTextWidth(resolvedText, fontString);
38
- const blockHeight = fontSizePx * 1.2;
39
- const edgeInsetPx = dimensionToPx(el.marginFromEdge, dpi);
40
- const x = xForAlign(el.align, contentX, contentWidth, textWidth, edgeInsetPx);
41
- // Baseline at ~0.8 of the block height, matching body text convention.
42
- const baseline = elementTop + blockHeight * 0.8;
44
+ function textPrimitiveToBlock(prim) {
45
+ const totalContentHeight = prim.lines.reduce((s, l) => Math.max(s, l.topY + l.height), 0);
46
+ const vOffset = prim.verticalAlign === 'top' ? 0
47
+ : prim.verticalAlign === 'bottom' ? Math.max(0, prim.contentHeight - totalContentHeight)
48
+ : Math.max(0, (prim.contentHeight - totalContentHeight) / 2);
49
+ const lines = prim.lines.map((l) => ({
50
+ text: l.text,
51
+ xOffset: prim.contentX + textAlignOffsetX(prim.align, prim.contentWidth, l.width),
52
+ baselineY: prim.y + prim.contentY + vOffset + l.baselineY,
53
+ width: l.width,
54
+ }));
43
55
  return {
44
56
  kind: 'text',
45
- bbox: createBoundingBox(x, elementTop, textWidth, blockHeight),
46
- text: resolvedText,
47
- align: el.align,
48
- fontString,
49
- color: el.color.hex,
50
- baseline,
57
+ bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
58
+ fontString: prim.fontString,
59
+ color: prim.color,
60
+ lines,
61
+ box: prim.box
62
+ ? {
63
+ backgroundColor: prim.box.backgroundColor,
64
+ borderColor: prim.box.borderColor,
65
+ borderWidthPx: prim.box.borderWidthPx,
66
+ borderRadiusPx: prim.box.borderRadiusPx,
67
+ }
68
+ : undefined,
69
+ clip: prim.needsClip,
51
70
  };
52
71
  }
53
- function buildRuleBlock(el, contentX, contentWidth, elementTop, dpi) {
54
- const thicknessPx = dimensionToPx(el.thickness, dpi);
55
- const widthPx = el.width === 'full' ? contentWidth : dimensionToPx(el.width, dpi);
56
- // `marginFromEdge` only meaningful for non-full rules — a full-width rule
57
- // already spans the content, so the inset would just crop it asymmetrically.
58
- const edgeInsetPx = el.width === 'full' ? 0 : dimensionToPx(el.marginFromEdge, dpi);
59
- const x = xForAlign(el.align, contentX, contentWidth, widthPx, edgeInsetPx);
72
+ function rulePrimitiveToBlock(prim) {
60
73
  return {
61
74
  kind: 'rule',
62
- bbox: createBoundingBox(x, elementTop, widthPx, thicknessPx),
63
- color: el.color.hex,
64
- thicknessPx,
75
+ bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
76
+ color: prim.color,
77
+ thicknessPx: prim.thicknessPx,
78
+ direction: prim.direction,
65
79
  };
66
80
  }
67
- /**
68
- * Layout elements for one slot on one page.
69
- *
70
- * Each element's `marginFromBody` is an absolute distance between its
71
- * body-facing edge and the body edge — elements are independent and never
72
- * push each other. Two elements with the same `marginFromBody` will overlap;
73
- * that's on the author to avoid.
74
- */
75
- function layoutSlot(slot, pageIndex, contentX, contentWidth, anchor, anchorY, metadata, allPages, chapterTitleByPageIndex, dpi) {
76
- const elements = filterElementsByParity(slot, pageIndex);
77
- if (elements.length === 0)
78
- return undefined;
79
- const page = allPages[pageIndex];
80
- const ctx = {
81
- page,
82
- allPages,
81
+ function boxPrimitiveToBlock(prim) {
82
+ return {
83
+ kind: 'box',
84
+ bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
85
+ box: {
86
+ backgroundColor: prim.box.backgroundColor,
87
+ borderColor: prim.box.borderColor,
88
+ borderWidthPx: prim.box.borderWidthPx,
89
+ borderRadiusPx: prim.box.borderRadiusPx,
90
+ },
91
+ };
92
+ }
93
+ /** Measure the natural bottom of a heading's advanced-design slot when laid
94
+ * out against a container of the given `width` with unbounded height.
95
+ * Returns 0 if the level has no advanced design or the slot is empty. Used
96
+ * during body layout to enlarge a heading block's reserved height so
97
+ * subsequent blocks sit below the actual bottom of the design content
98
+ * rather than below the natural text bottom. Applies to both in-column
99
+ * headings (overlay in block bbox) and page-spanning openers (width is the
100
+ * full content area; passed in by the caller). */
101
+ export function measureHeadingAdvancedDesignHeight(level, heading, width, dpi, metadata, pageIndex) {
102
+ if (!level.advancedDesign.enabled)
103
+ return 0;
104
+ if (level.advancedDesign.slot.elements.length === 0)
105
+ return 0;
106
+ const stubPage = { index: pageIndex, pageLabel: '1' };
107
+ const placeholders = {
108
+ kind: 'heading',
109
+ page: stubPage,
110
+ allPages: [stubPage],
83
111
  metadata,
84
- chapterTitleByPageIndex,
112
+ chapterTitleByPageIndex: [],
113
+ heading,
85
114
  };
86
- const blocks = [];
87
- let minY = anchorY;
88
- let maxBottom = anchorY;
89
- for (const el of elements) {
90
- const height = elementHeightPx(el, dpi);
91
- const marginPx = dimensionToPx(el.marginFromBody, dpi);
92
- // For a header (anchor='bottom' at body top): element's bottom edge sits
93
- // `marginPx` above the body. For a footer (anchor='top' at body bottom):
94
- // element's top edge sits `marginPx` below the body.
95
- const elementTop = anchor === 'bottom' ? anchorY - marginPx - height : anchorY + marginPx;
96
- if (el.kind === 'text') {
97
- const { text } = resolvePlaceholders(el.content, ctx);
98
- if (text.length > 0) {
99
- blocks.push(buildTextBlock(el, text, contentX, contentWidth, elementTop, dpi));
100
- }
101
- }
102
- else {
103
- blocks.push(buildRuleBlock(el, contentX, contentWidth, elementTop, dpi));
104
- }
105
- minY = Math.min(minY, elementTop);
106
- maxBottom = Math.max(maxBottom, elementTop + height);
115
+ const result = layoutDesignSlot(level.advancedDesign.slot, { container: { x: 0, y: 0, width, height: 1e6 }, dpi, placeholders }, pageIndex);
116
+ let bottom = 0;
117
+ for (const prim of result.primitives) {
118
+ bottom = Math.max(bottom, prim.y + prim.height);
107
119
  }
108
- if (blocks.length === 0)
120
+ return bottom;
121
+ }
122
+ export function layoutSlotToVdt(slot, container, pageIndex, placeholders, dpi) {
123
+ const result = layoutDesignSlot(slot, { container, dpi, placeholders }, pageIndex);
124
+ if (result.primitives.length === 0)
109
125
  return undefined;
110
- const slotBbox = createBoundingBox(contentX, minY, contentWidth, maxBottom - minY);
111
- return { bbox: slotBbox, blocks };
126
+ const blocks = result.primitives.map(primitiveToBlock);
127
+ return {
128
+ bbox: createBoundingBox(container.x, container.y, container.width, container.height),
129
+ blocks,
130
+ };
131
+ }
132
+ /** Container bbox for a page-spanning heading opener band: occupies the
133
+ * vertical band the heading block reserved in its column, extended
134
+ * horizontally across the full content area (both columns) — but NOT beyond
135
+ * the page margins. */
136
+ function openerContainerBbox(block, contentArea) {
137
+ return { x: contentArea.x, y: block.bbox.y, width: contentArea.width, height: block.bbox.height };
138
+ }
139
+ /** Find the first heading block on `page` that belongs to a level with
140
+ * `span === 'page'`. Returns the block and info needed to resolve
141
+ * placeholders in the design slot. Triggers regardless of whether
142
+ * `advancedDesign.enabled` is true — when false, the pipeline synthesises
143
+ * a default slot from the heading level typography. */
144
+ function findOpenerHeading(page, doc) {
145
+ for (const col of page.columns) {
146
+ for (const block of col.blocks) {
147
+ if (block.type !== 'heading' || !block.headingLevel)
148
+ continue;
149
+ const lvl = doc.config.headings.levels.find((l) => l.level === block.headingLevel);
150
+ if (!lvl)
151
+ continue;
152
+ if (lvl.span !== 'page')
153
+ continue;
154
+ const full = block.lines
155
+ .map((ln) => (ln.segments ?? []).map((s) => s.text).join(''))
156
+ .join(' ');
157
+ const pref = block.numberPrefix ?? '';
158
+ const title = pref && full.startsWith(`${pref} `) ? full.slice(pref.length + 1) : full;
159
+ return { block, level: block.headingLevel, titleText: title, numberPrefix: pref };
160
+ }
161
+ }
162
+ return undefined;
163
+ }
164
+ /** Build a synthesised default design slot for a `span: 'page'` heading when
165
+ * the user has not configured an `advancedDesign.slot`. Renders as a single
166
+ * text element, anchored to fill the full-page-width container, using the
167
+ * heading level's resolved typography. Emits `{formattedNumber} {titleText}`
168
+ * when the heading carries a numberPrefix, otherwise `{titleText}`. */
169
+ function synthesiseDefaultOpenerSlot(level, hasNumberPrefix) {
170
+ const content = hasNumberPrefix ? '{formattedNumber} {titleText}' : '{titleText}';
171
+ const textEl = {
172
+ kind: 'text',
173
+ id: 'defaultHeadingOpener',
174
+ parity: 'all',
175
+ placement: {
176
+ anchor: { to: 'container', edge: 'top-left' },
177
+ offset: { x: { value: 0, unit: 'pt' }, y: { value: 0, unit: 'pt' } },
178
+ size: { width: 'fill', height: 'fill' },
179
+ },
180
+ content,
181
+ fontFamily: level.fontFamily,
182
+ fontSize: level.fontSize,
183
+ fontWeight: level.fontWeight,
184
+ italic: level.italic,
185
+ color: level.color,
186
+ align: 'left',
187
+ verticalAlign: 'middle',
188
+ lineHeight: level.lineHeight.unit === 'em' ? level.lineHeight.value : 1.2,
189
+ overflow: 'wrap',
190
+ hyphenate: true,
191
+ };
192
+ return { elements: [textEl] };
112
193
  }
113
194
  /**
114
- * After body placement finishes, attach header/footer slots (with their
115
- * rendered text/rule blocks) to every page of the document.
116
- *
117
- * Headers and footers are rendered inside the existing page margins — they
118
- * do not consume body space. Header elements stack upward from the body's
119
- * top edge; footer elements stack downward from the body's bottom edge.
195
+ * After body placement finishes, attach header/footer slots to every page.
120
196
  */
121
197
  export function buildHeadersAndFooters(doc) {
122
198
  const resolved = doc.config;
123
199
  const dpi = resolved.page.dpi;
124
200
  const { contentArea } = computePageMetrics(resolved);
125
201
  const chapterTitleByPageIndex = computeChapterTitles(doc.blocks, doc.pages.length, doc.pages);
202
+ const chapterNumberByPageIndex = computeChapterNumbers(doc.blocks, doc.pages.length, doc.pages);
126
203
  for (const page of doc.pages) {
127
204
  if (resolved.header.elements.length > 0) {
128
- page.header = layoutSlot(resolved.header, page.index, contentArea.x, contentArea.width, 'bottom', contentArea.y, doc.metadata, doc.pages, chapterTitleByPageIndex, dpi);
205
+ const placeholders = {
206
+ kind: 'header',
207
+ page,
208
+ allPages: doc.pages,
209
+ metadata: doc.metadata,
210
+ chapterTitleByPageIndex,
211
+ };
212
+ page.header = layoutSlotToVdt(resolved.header, headerContainerBbox(contentArea, page.height), page.index, placeholders, dpi);
213
+ }
214
+ const opener = findOpenerHeading(page, doc);
215
+ if (opener) {
216
+ const level = resolved.headings.levels.find((l) => l.level === opener.level);
217
+ if (level) {
218
+ const slot = level.advancedDesign.enabled && level.advancedDesign.slot.elements.length > 0
219
+ ? level.advancedDesign.slot
220
+ : synthesiseDefaultOpenerSlot(level, opener.numberPrefix.length > 0);
221
+ const placeholders = {
222
+ kind: 'heading',
223
+ page,
224
+ allPages: doc.pages,
225
+ metadata: doc.metadata,
226
+ chapterTitleByPageIndex,
227
+ heading: {
228
+ titleText: opener.titleText,
229
+ formattedNumber: opener.numberPrefix,
230
+ chapterNumber: chapterNumberByPageIndex[page.index] ?? '',
231
+ },
232
+ };
233
+ page.openerBand = layoutSlotToVdt(slot, openerContainerBbox(opener.block, contentArea), page.index, placeholders, dpi);
234
+ if (page.openerBand) {
235
+ opener.block.hidden = true;
236
+ }
237
+ }
238
+ }
239
+ // In-column heading advanced-design overlays: any heading whose level
240
+ // has `advancedDesign.enabled` and a non-empty slot gets its default
241
+ // text rendering replaced with a design overlay laid out inside the
242
+ // block's bbox. `span: 'page'` headings are handled via `openerBand`
243
+ // above (and are already `hidden`), so they're skipped here.
244
+ for (const col of page.columns) {
245
+ for (const block of col.blocks) {
246
+ if (block.hidden)
247
+ continue;
248
+ if (block.type !== 'heading' || !block.headingLevel)
249
+ continue;
250
+ const lvl = resolved.headings.levels.find((l) => l.level === block.headingLevel);
251
+ if (!lvl)
252
+ continue;
253
+ if (lvl.span === 'page')
254
+ continue;
255
+ if (!lvl.advancedDesign.enabled)
256
+ continue;
257
+ if (lvl.advancedDesign.slot.elements.length === 0)
258
+ continue;
259
+ const full = block.lines
260
+ .map((ln) => (ln.segments ?? []).map((s) => s.text).join(''))
261
+ .join(' ');
262
+ const pref = block.numberPrefix ?? '';
263
+ const title = pref && full.startsWith(`${pref} `) ? full.slice(pref.length + 1) : full;
264
+ const placeholders = {
265
+ kind: 'heading',
266
+ page,
267
+ allPages: doc.pages,
268
+ metadata: doc.metadata,
269
+ chapterTitleByPageIndex,
270
+ heading: {
271
+ titleText: title,
272
+ formattedNumber: pref,
273
+ chapterNumber: chapterNumberByPageIndex[page.index] ?? '',
274
+ },
275
+ };
276
+ const overlay = layoutSlotToVdt(lvl.advancedDesign.slot, { x: block.bbox.x, y: block.bbox.y, width: block.bbox.width, height: block.bbox.height }, page.index, placeholders, dpi);
277
+ if (overlay)
278
+ block.designOverlay = overlay;
279
+ }
129
280
  }
130
281
  if (resolved.footer.elements.length > 0) {
131
- page.footer = layoutSlot(resolved.footer, page.index, contentArea.x, contentArea.width, 'top', contentArea.y + contentArea.height, doc.metadata, doc.pages, chapterTitleByPageIndex, dpi);
282
+ const placeholders = {
283
+ kind: 'footer',
284
+ page,
285
+ allPages: doc.pages,
286
+ metadata: doc.metadata,
287
+ chapterTitleByPageIndex,
288
+ };
289
+ page.footer = layoutSlotToVdt(resolved.footer, footerContainerBbox(contentArea, page.height), page.index, placeholders, dpi);
132
290
  }
133
291
  }
134
292
  }
@@ -1 +1 @@
1
- {"version":3,"file":"headerFooter.js","sourceRoot":"","sources":["../../src/pipeline/headerFooter.ts"],"names":[],"mappings":"AASA,OAAO,EACL,iBAAiB,GAOlB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAA2B,MAAM,gBAAgB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,SAAS,iBAAiB,CAAC,SAAiB,EAAE,MAAkB;IAC9D,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClC,qDAAqD;IACrD,MAAM,UAAU,GAAG,SAAS,GAAG,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3C,CAAC;AAED,SAAS,eAAe,CAAC,EAA+B,EAAE,GAAW;IACnE,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACnD,8CAA8C;QAC9C,OAAO,UAAU,GAAG,GAAG,CAAC;IAC1B,CAAC;IACD,OAAO,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAA8B,EAC9B,SAAiB;IAEjB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,SAAS,CAChB,KAAyB,EACzB,QAAgB,EAChB,YAAoB,EACpB,YAAoB,EACpB,WAAmB;IAEnB,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,QAAQ,GAAG,WAAW,CAAC;IACpD,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,QAAQ,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;IACnF,OAAO,QAAQ,GAAG,CAAC,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,cAAc,CACrB,EAAmC,EACnC,YAAoB,EACpB,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,GAAW;IAEX,MAAM,UAAU,GAAG,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC9C,MAAM,UAAU,GAAG,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,gBAAgB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,UAAU,GAAG,GAAG,CAAC;IACrC,MAAM,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9E,uEAAuE;IACvE,MAAM,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,GAAG,CAAC;IAChD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC;QAC9D,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,UAAU;QACV,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG;QACnB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,EAAmC,EACnC,QAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,GAAW;IAEX,MAAM,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClF,0EAA0E;IAC1E,6EAA6E;IAC7E,MAAM,WAAW,GAAG,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAC5E,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,iBAAiB,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC;QAC5D,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG;QACnB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,UAAU,CACjB,IAA8B,EAC9B,SAAiB,EACjB,QAAgB,EAChB,YAAoB,EACpB,MAAwB,EACxB,OAAe,EACf,QAA0B,EAC1B,QAAmB,EACnB,uBAAiC,EACjC,GAAW;IAEX,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE5C,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAE,CAAC;IAClC,MAAM,GAAG,GAAuB;QAC9B,IAAI;QACJ,QAAQ;QACR,QAAQ;QACR,uBAAuB;KACxB,CAAC;IAEF,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,IAAI,GAAG,OAAO,CAAC;IACnB,IAAI,SAAS,GAAG,OAAO,CAAC;IAExB,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,aAAa,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACvD,yEAAyE;QACzE,yEAAyE;QACzE,qDAAqD;QACrD,MAAM,UAAU,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC;QAC1F,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACvB,MAAM,EAAE,IAAI,EAAE,GAAG,mBAAmB,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAClC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,QAAQ,GAAG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC;IACnF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAgB;IACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC;IAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;IAC9B,MAAM,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAErD,MAAM,uBAAuB,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IAE9F,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,GAAG,UAAU,CACtB,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,KAAK,EACV,WAAW,CAAC,CAAC,EACb,WAAW,CAAC,KAAK,EACjB,QAAQ,EACR,WAAW,CAAC,CAAC,EACb,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,KAAK,EACT,uBAAuB,EACvB,GAAG,CACJ,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,GAAG,UAAU,CACtB,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,KAAK,EACV,WAAW,CAAC,CAAC,EACb,WAAW,CAAC,KAAK,EACjB,KAAK,EACL,WAAW,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAClC,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,KAAK,EACT,uBAAuB,EACvB,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"headerFooter.js","sourceRoot":"","sources":["../../src/pipeline/headerFooter.ts"],"names":[],"mappings":"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"}
@@ -37,6 +37,12 @@ export interface PlaceholderResult {
37
37
  * in its header, not the previous chapter's.
38
38
  */
39
39
  export declare function computeChapterTitles(blocks: VDTBlock[], totalPages: number, pages?: ChapterTitlePageInfo[]): string[];
40
+ /**
41
+ * Precompute chapter numbers (most recent H1 `numberPrefix`) per page. Mirrors
42
+ * `computeChapterTitles` but tracks the numeric prefix (e.g. `"1"`, `"2"`) so
43
+ * `{chapterNumber}` in heading-context slots resolves to the current chapter.
44
+ */
45
+ export declare function computeChapterNumbers(blocks: VDTBlock[], totalPages: number, pages?: ChapterTitlePageInfo[]): string[];
40
46
  /**
41
47
  * Resolve placeholder templates. Grammar:
42
48
  * - `{name}` with name matching `[a-zA-Z][a-zA-Z0-9]*` is a placeholder.
@@ -1 +1 @@
1
- {"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEhD;;;;;;;oEAOoE;AACpE,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,4EAA4E;IAC5E,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAgDV;AAWD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,kBAAkB,GACtB,iBAAiB,CAgDnB;AAuBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBlE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D"}
1
+ {"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEhD;;;;;;;oEAOoE;AACpE,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,4EAA4E;IAC5E,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAgDV;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAkCV;AAWD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,kBAAkB,GACtB,iBAAiB,CAgDnB;AAuBD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBlE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D"}
@@ -74,6 +74,52 @@ export function computeChapterTitles(blocks, totalPages, pages) {
74
74
  }
75
75
  return out;
76
76
  }
77
+ /**
78
+ * Precompute chapter numbers (most recent H1 `numberPrefix`) per page. Mirrors
79
+ * `computeChapterTitles` but tracks the numeric prefix (e.g. `"1"`, `"2"`) so
80
+ * `{chapterNumber}` in heading-context slots resolves to the current chapter.
81
+ */
82
+ export function computeChapterNumbers(blocks, totalPages, pages) {
83
+ const out = new Array(totalPages).fill('');
84
+ const byPage = new Map();
85
+ let current = '';
86
+ let lastPageIndex = -1;
87
+ const h1PageIndices = [];
88
+ for (const b of blocks) {
89
+ if (b.pageIndex < 0)
90
+ continue;
91
+ while (lastPageIndex < b.pageIndex) {
92
+ lastPageIndex++;
93
+ byPage.set(lastPageIndex, current);
94
+ }
95
+ if (b.headingLevel === 1) {
96
+ current = b.numberPrefix ?? '';
97
+ byPage.set(b.pageIndex, current);
98
+ h1PageIndices.push({ pageIndex: b.pageIndex, number: current });
99
+ }
100
+ }
101
+ for (let p = 0; p < totalPages; p++) {
102
+ if (byPage.has(p))
103
+ out[p] = byPage.get(p);
104
+ else if (p > 0)
105
+ out[p] = out[p - 1];
106
+ }
107
+ if (pages) {
108
+ for (const { pageIndex, number } of h1PageIndices) {
109
+ for (let p = pageIndex - 1; p >= 0; p--) {
110
+ const info = pages[p];
111
+ if (!info)
112
+ break;
113
+ if (info.blankForForce)
114
+ break;
115
+ if (!info.blankForParity)
116
+ break;
117
+ out[p] = number;
118
+ }
119
+ }
120
+ }
121
+ return out;
122
+ }
77
123
  function plainTextOfBlock(block) {
78
124
  // Strip any numbering prefix that was prepended during build.
79
125
  const lines = block.lines.map((l) => l.text).join(' ');
@@ -1 +1 @@
1
- {"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"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"}
@@ -7,12 +7,12 @@ export interface PlacementCursor {
7
7
  export declare function resetLinePositions(lines: VDTLine[], lineHeightPx: number): VDTLine[];
8
8
  export declare function createPageWithColumns(pageIndex: number, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): VDTPage;
9
9
  export declare function currentColumn(doc: VDTDocument, cursor: PlacementCursor): VDTColumn;
10
- export declare function advanceToNextColumn(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): void;
10
+ export declare function advanceToNextColumn(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number, onNewPage?: (page: VDTPage) => void): void;
11
11
  /** Advance `cursor` forward until it points to the first column of a new
12
12
  * page. No-op when the current page is empty (nothing placed yet) — avoids
13
13
  * emitting a blank leading page when a `:::pagebreak` directive lands
14
14
  * before any content. */
15
- export declare function advanceToNextPageBoundary(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): void;
15
+ export declare function advanceToNextPageBoundary(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number, onNewPage?: (page: VDTPage) => void): void;
16
16
  /** After a forced page break, make sure the page we're sitting on has the
17
17
  * requested parity. If not, flag the current page as a blank-for-parity
18
18
  * placeholder and advance to the next page. Repeats until parity matches
@@ -25,5 +25,18 @@ export declare function advanceToNextPageBoundary(doc: VDTDocument, cursor: Plac
25
25
  * between the previous content and the new chapter, regardless of
26
26
  * whether the natural next page already matched the requested parity. */
27
27
  export declare function enforcePageParity(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number, parity: HeadingBreakParity): void;
28
+ /**
29
+ * Place a resource block (image / svg / table + caption) keeping it together as
30
+ * one atomic unit (issue #49 §7 — Placement). Resources never split mid-content
31
+ * for v1: if the group's combined height fits the remaining column space it is
32
+ * placed there; otherwise the cursor advances to the next column/page (without
33
+ * emitting a leading blank page when the current column is empty), and the
34
+ * resource is force-placed there even when it exceeds a single column's height.
35
+ *
36
+ * `spacingBefore` is consumed from the target column's available height before
37
+ * placement (collapsed against the previous block's bottom margin by the
38
+ * caller). Returns the height actually reserved for the block.
39
+ */
40
+ export declare function placeResourceBlock(block: VDTBlock, groupHeight: number, spacingBefore: number, cursor: PlacementCursor, doc: VDTDocument, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): number;
28
41
  export declare function placeBlockInColumn(block: VDTBlock, blockHeight: number, col: VDTColumn, cursor: PlacementCursor): void;
29
42
  //# sourceMappingURL=placement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"placement.d.ts","sourceRoot":"","sources":["../../src/pipeline/placement.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,SAAS,EACf,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EAAE,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,EAAE,CAMX;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAOT;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAElF;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI,CAiBN;AAED;;;0BAG0B;AAC1B,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI,CAQN;AAED;;;;;;;;;;0EAU0E;AAC1E,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAqCN;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,eAAe,GACtB,IAAI,CAeN"}
1
+ {"version":3,"file":"placement.d.ts","sourceRoot":"","sources":["../../src/pipeline/placement.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,OAAO,EACZ,KAAK,SAAS,EACf,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAGnD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EAAE,EAChB,YAAY,EAAE,MAAM,GACnB,OAAO,EAAE,CAMX;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAOT;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,SAAS,CAElF;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAClC,IAAI,CAsBN;AAED;;;0BAG0B;AAC1B,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAClC,IAAI,CAQN;AAED;;;;;;;;;;0EAU0E;AAC1E,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,kBAAkB,GACzB,IAAI,CAqCN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,CAkBR;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,eAAe,GACtB,IAAI,CAeN"}