postext 0.3.19 → 0.3.21

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 (297) hide show
  1. package/dist/__tests__/columnBalancing.test.js +36 -2
  2. package/dist/__tests__/columnBalancing.test.js.map +1 -1
  3. package/dist/__tests__/defaults/calloutStyles.test.d.ts +2 -0
  4. package/dist/__tests__/defaults/calloutStyles.test.d.ts.map +1 -0
  5. package/dist/__tests__/defaults/calloutStyles.test.js +201 -0
  6. package/dist/__tests__/defaults/calloutStyles.test.js.map +1 -0
  7. package/dist/__tests__/defaults/captionStyle.test.d.ts +2 -0
  8. package/dist/__tests__/defaults/captionStyle.test.d.ts.map +1 -0
  9. package/dist/__tests__/defaults/captionStyle.test.js +87 -0
  10. package/dist/__tests__/defaults/captionStyle.test.js.map +1 -0
  11. package/dist/__tests__/defaults/pageSizePreset.test.d.ts +2 -0
  12. package/dist/__tests__/defaults/pageSizePreset.test.d.ts.map +1 -0
  13. package/dist/__tests__/defaults/pageSizePreset.test.js +24 -0
  14. package/dist/__tests__/defaults/pageSizePreset.test.js.map +1 -0
  15. package/dist/__tests__/defaults/paragraphStyles.test.d.ts +2 -0
  16. package/dist/__tests__/defaults/paragraphStyles.test.d.ts.map +1 -0
  17. package/dist/__tests__/defaults/paragraphStyles.test.js +93 -0
  18. package/dist/__tests__/defaults/paragraphStyles.test.js.map +1 -0
  19. package/dist/__tests__/design/pageAnchors.test.d.ts +2 -0
  20. package/dist/__tests__/design/pageAnchors.test.d.ts.map +1 -0
  21. package/dist/__tests__/design/pageAnchors.test.js +140 -0
  22. package/dist/__tests__/design/pageAnchors.test.js.map +1 -0
  23. package/dist/__tests__/directives.test.js +58 -0
  24. package/dist/__tests__/directives.test.js.map +1 -1
  25. package/dist/__tests__/exports.test.js +19 -0
  26. package/dist/__tests__/exports.test.js.map +1 -1
  27. package/dist/__tests__/mirroredMargins.test.d.ts +2 -0
  28. package/dist/__tests__/mirroredMargins.test.d.ts.map +1 -0
  29. package/dist/__tests__/mirroredMargins.test.js +136 -0
  30. package/dist/__tests__/mirroredMargins.test.js.map +1 -0
  31. package/dist/__tests__/numbering.test.js +54 -0
  32. package/dist/__tests__/numbering.test.js.map +1 -1
  33. package/dist/__tests__/openerTitleSource.test.d.ts +2 -0
  34. package/dist/__tests__/openerTitleSource.test.d.ts.map +1 -0
  35. package/dist/__tests__/openerTitleSource.test.js +108 -0
  36. package/dist/__tests__/openerTitleSource.test.js.map +1 -0
  37. package/dist/__tests__/overStretch.test.d.ts +2 -0
  38. package/dist/__tests__/overStretch.test.d.ts.map +1 -0
  39. package/dist/__tests__/overStretch.test.js +35 -0
  40. package/dist/__tests__/overStretch.test.js.map +1 -0
  41. package/dist/__tests__/pageRoles.test.d.ts +2 -0
  42. package/dist/__tests__/pageRoles.test.d.ts.map +1 -0
  43. package/dist/__tests__/pageRoles.test.js +95 -0
  44. package/dist/__tests__/pageRoles.test.js.map +1 -0
  45. package/dist/__tests__/parse/containers.test.d.ts +2 -0
  46. package/dist/__tests__/parse/containers.test.d.ts.map +1 -0
  47. package/dist/__tests__/parse/containers.test.js +204 -0
  48. package/dist/__tests__/parse/containers.test.js.map +1 -0
  49. package/dist/__tests__/parse/headingAttrs.test.d.ts +2 -0
  50. package/dist/__tests__/parse/headingAttrs.test.d.ts.map +1 -0
  51. package/dist/__tests__/parse/headingAttrs.test.js +62 -0
  52. package/dist/__tests__/parse/headingAttrs.test.js.map +1 -0
  53. package/dist/__tests__/parse/inlineRef.test.js +26 -0
  54. package/dist/__tests__/parse/inlineRef.test.js.map +1 -1
  55. package/dist/__tests__/parts.test.d.ts +2 -0
  56. package/dist/__tests__/parts.test.d.ts.map +1 -0
  57. package/dist/__tests__/parts.test.js +405 -0
  58. package/dist/__tests__/parts.test.js.map +1 -0
  59. package/dist/__tests__/pipeline/calloutLayout.test.d.ts +2 -0
  60. package/dist/__tests__/pipeline/calloutLayout.test.d.ts.map +1 -0
  61. package/dist/__tests__/pipeline/calloutLayout.test.js +273 -0
  62. package/dist/__tests__/pipeline/calloutLayout.test.js.map +1 -0
  63. package/dist/__tests__/pipeline/calloutPlacement.test.d.ts +2 -0
  64. package/dist/__tests__/pipeline/calloutPlacement.test.d.ts.map +1 -0
  65. package/dist/__tests__/pipeline/calloutPlacement.test.js +239 -0
  66. package/dist/__tests__/pipeline/calloutPlacement.test.js.map +1 -0
  67. package/dist/__tests__/pipeline/captionLayout.test.d.ts +2 -0
  68. package/dist/__tests__/pipeline/captionLayout.test.d.ts.map +1 -0
  69. package/dist/__tests__/pipeline/captionLayout.test.js +269 -0
  70. package/dist/__tests__/pipeline/captionLayout.test.js.map +1 -0
  71. package/dist/__tests__/pipeline/inlineRefRender.test.js +53 -0
  72. package/dist/__tests__/pipeline/inlineRefRender.test.js.map +1 -1
  73. package/dist/__tests__/pipeline/orderedSeparator.test.d.ts +2 -0
  74. package/dist/__tests__/pipeline/orderedSeparator.test.d.ts.map +1 -0
  75. package/dist/__tests__/pipeline/orderedSeparator.test.js +196 -0
  76. package/dist/__tests__/pipeline/orderedSeparator.test.js.map +1 -0
  77. package/dist/__tests__/pipeline/paragraphStyles.test.d.ts +2 -0
  78. package/dist/__tests__/pipeline/paragraphStyles.test.d.ts.map +1 -0
  79. package/dist/__tests__/pipeline/paragraphStyles.test.js +172 -0
  80. package/dist/__tests__/pipeline/paragraphStyles.test.js.map +1 -0
  81. package/dist/__tests__/pipeline/spanBands.test.d.ts +2 -0
  82. package/dist/__tests__/pipeline/spanBands.test.d.ts.map +1 -0
  83. package/dist/__tests__/pipeline/spanBands.test.js +303 -0
  84. package/dist/__tests__/pipeline/spanBands.test.js.map +1 -0
  85. package/dist/__tests__/pipeline/spanBlocks.test.d.ts +2 -0
  86. package/dist/__tests__/pipeline/spanBlocks.test.d.ts.map +1 -0
  87. package/dist/__tests__/pipeline/spanBlocks.test.js +407 -0
  88. package/dist/__tests__/pipeline/spanBlocks.test.js.map +1 -0
  89. package/dist/__tests__/placeholders.test.d.ts +2 -0
  90. package/dist/__tests__/placeholders.test.d.ts.map +1 -0
  91. package/dist/__tests__/placeholders.test.js +130 -0
  92. package/dist/__tests__/placeholders.test.js.map +1 -0
  93. package/dist/__tests__/table/model.test.js +24 -0
  94. package/dist/__tests__/table/model.test.js.map +1 -1
  95. package/dist/__tests__/tracking.test.d.ts +2 -0
  96. package/dist/__tests__/tracking.test.d.ts.map +1 -0
  97. package/dist/__tests__/tracking.test.js +37 -0
  98. package/dist/__tests__/tracking.test.js.map +1 -0
  99. package/dist/__tests__/urlBreaks.test.d.ts +2 -0
  100. package/dist/__tests__/urlBreaks.test.d.ts.map +1 -0
  101. package/dist/__tests__/urlBreaks.test.js +57 -0
  102. package/dist/__tests__/urlBreaks.test.js.map +1 -0
  103. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  104. package/dist/canvas-backend/blockRender.js +20 -1
  105. package/dist/canvas-backend/blockRender.js.map +1 -1
  106. package/dist/canvas-backend/decorations.d.ts +3 -0
  107. package/dist/canvas-backend/decorations.d.ts.map +1 -1
  108. package/dist/canvas-backend/decorations.js +14 -8
  109. package/dist/canvas-backend/decorations.js.map +1 -1
  110. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  111. package/dist/canvas-backend/headerFooter.js +23 -0
  112. package/dist/canvas-backend/headerFooter.js.map +1 -1
  113. package/dist/canvas-backend/index.d.ts.map +1 -1
  114. package/dist/canvas-backend/index.js +4 -2
  115. package/dist/canvas-backend/index.js.map +1 -1
  116. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -1
  117. package/dist/canvas-backend/renderResourceBlock.js +33 -5
  118. package/dist/canvas-backend/renderResourceBlock.js.map +1 -1
  119. package/dist/columnRule.d.ts +19 -0
  120. package/dist/columnRule.d.ts.map +1 -0
  121. package/dist/columnRule.js +36 -0
  122. package/dist/columnRule.js.map +1 -0
  123. package/dist/defaults/bodyText.js +1 -1
  124. package/dist/defaults/bodyText.js.map +1 -1
  125. package/dist/defaults/calloutStyles.d.ts +61 -0
  126. package/dist/defaults/calloutStyles.d.ts.map +1 -0
  127. package/dist/defaults/calloutStyles.js +292 -0
  128. package/dist/defaults/calloutStyles.js.map +1 -0
  129. package/dist/defaults/captionStyle.d.ts +11 -1
  130. package/dist/defaults/captionStyle.d.ts.map +1 -1
  131. package/dist/defaults/captionStyle.js +127 -2
  132. package/dist/defaults/captionStyle.js.map +1 -1
  133. package/dist/defaults/headerFooter.d.ts.map +1 -1
  134. package/dist/defaults/headerFooter.js +3 -0
  135. package/dist/defaults/headerFooter.js.map +1 -1
  136. package/dist/defaults/headings.d.ts +3 -0
  137. package/dist/defaults/headings.d.ts.map +1 -1
  138. package/dist/defaults/headings.js +33 -6
  139. package/dist/defaults/headings.js.map +1 -1
  140. package/dist/defaults/index.d.ts +4 -1
  141. package/dist/defaults/index.d.ts.map +1 -1
  142. package/dist/defaults/index.js +28 -1
  143. package/dist/defaults/index.js.map +1 -1
  144. package/dist/defaults/orderedLists.d.ts +9 -8
  145. package/dist/defaults/orderedLists.d.ts.map +1 -1
  146. package/dist/defaults/orderedLists.js +66 -4
  147. package/dist/defaults/orderedLists.js.map +1 -1
  148. package/dist/defaults/page.d.ts.map +1 -1
  149. package/dist/defaults/page.js +14 -3
  150. package/dist/defaults/page.js.map +1 -1
  151. package/dist/defaults/paragraphStyles.d.ts +10 -0
  152. package/dist/defaults/paragraphStyles.d.ts.map +1 -0
  153. package/dist/defaults/paragraphStyles.js +67 -0
  154. package/dist/defaults/paragraphStyles.js.map +1 -0
  155. package/dist/defaults/parts.d.ts +22 -0
  156. package/dist/defaults/parts.d.ts.map +1 -0
  157. package/dist/defaults/parts.js +139 -0
  158. package/dist/defaults/parts.js.map +1 -0
  159. package/dist/defaults/shared.d.ts.map +1 -1
  160. package/dist/defaults/shared.js +110 -17
  161. package/dist/defaults/shared.js.map +1 -1
  162. package/dist/defaults/tableStyle.d.ts.map +1 -1
  163. package/dist/defaults/tableStyle.js +6 -0
  164. package/dist/defaults/tableStyle.js.map +1 -1
  165. package/dist/design/layout.d.ts +27 -1
  166. package/dist/design/layout.d.ts.map +1 -1
  167. package/dist/design/layout.js +39 -8
  168. package/dist/design/layout.js.map +1 -1
  169. package/dist/design/placeholders.d.ts +21 -4
  170. package/dist/design/placeholders.d.ts.map +1 -1
  171. package/dist/design/placeholders.js +38 -7
  172. package/dist/design/placeholders.js.map +1 -1
  173. package/dist/html-backend.d.ts.map +1 -1
  174. package/dist/html-backend.js +75 -16
  175. package/dist/html-backend.js.map +1 -1
  176. package/dist/index.d.ts +13 -9
  177. package/dist/index.d.ts.map +1 -1
  178. package/dist/index.js +7 -4
  179. package/dist/index.js.map +1 -1
  180. package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
  181. package/dist/knuthPlass/breakpoints.js +4 -2
  182. package/dist/knuthPlass/breakpoints.js.map +1 -1
  183. package/dist/knuthPlass/constants.d.ts +7 -0
  184. package/dist/knuthPlass/constants.d.ts.map +1 -1
  185. package/dist/knuthPlass/constants.js +7 -0
  186. package/dist/knuthPlass/constants.js.map +1 -1
  187. package/dist/knuthPlass/richAdapter.d.ts +2 -0
  188. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  189. package/dist/knuthPlass/richAdapter.js +6 -6
  190. package/dist/knuthPlass/richAdapter.js.map +1 -1
  191. package/dist/measure/cache.js +2 -2
  192. package/dist/measure/cache.js.map +1 -1
  193. package/dist/measure/rich.d.ts +8 -0
  194. package/dist/measure/rich.d.ts.map +1 -1
  195. package/dist/measure/rich.js +54 -10
  196. package/dist/measure/rich.js.map +1 -1
  197. package/dist/measure/types.d.ts +4 -0
  198. package/dist/measure/types.d.ts.map +1 -1
  199. package/dist/measure/types.js.map +1 -1
  200. package/dist/parse/attrs.d.ts +10 -0
  201. package/dist/parse/attrs.d.ts.map +1 -0
  202. package/dist/parse/attrs.js +20 -0
  203. package/dist/parse/attrs.js.map +1 -0
  204. package/dist/parse/blockParser.d.ts +8 -4
  205. package/dist/parse/blockParser.d.ts.map +1 -1
  206. package/dist/parse/blockParser.js +134 -20
  207. package/dist/parse/blockParser.js.map +1 -1
  208. package/dist/parse/index.d.ts +2 -2
  209. package/dist/parse/index.d.ts.map +1 -1
  210. package/dist/parse/index.js +1 -1
  211. package/dist/parse/index.js.map +1 -1
  212. package/dist/parse/inlineFormatting.d.ts +17 -1
  213. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  214. package/dist/parse/inlineFormatting.js +56 -7
  215. package/dist/parse/inlineFormatting.js.map +1 -1
  216. package/dist/parse/sourceMapping.d.ts.map +1 -1
  217. package/dist/parse/sourceMapping.js +13 -1
  218. package/dist/parse/sourceMapping.js.map +1 -1
  219. package/dist/parse/types.d.ts +55 -5
  220. package/dist/parse/types.d.ts.map +1 -1
  221. package/dist/pipeline/bandCaps.d.ts +86 -0
  222. package/dist/pipeline/bandCaps.d.ts.map +1 -0
  223. package/dist/pipeline/bandCaps.js +142 -0
  224. package/dist/pipeline/bandCaps.js.map +1 -0
  225. package/dist/pipeline/build.d.ts +41 -0
  226. package/dist/pipeline/build.d.ts.map +1 -1
  227. package/dist/pipeline/build.js +675 -168
  228. package/dist/pipeline/build.js.map +1 -1
  229. package/dist/pipeline/buildBlockKind.d.ts +8 -0
  230. package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
  231. package/dist/pipeline/buildBlockKind.js +40 -11
  232. package/dist/pipeline/buildBlockKind.js.map +1 -1
  233. package/dist/pipeline/buildHelpers.d.ts +23 -1
  234. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  235. package/dist/pipeline/buildHelpers.js +50 -6
  236. package/dist/pipeline/buildHelpers.js.map +1 -1
  237. package/dist/pipeline/calloutLayout.d.ts +107 -0
  238. package/dist/pipeline/calloutLayout.d.ts.map +1 -0
  239. package/dist/pipeline/calloutLayout.js +498 -0
  240. package/dist/pipeline/calloutLayout.js.map +1 -0
  241. package/dist/pipeline/columnBalancing.d.ts +26 -8
  242. package/dist/pipeline/columnBalancing.d.ts.map +1 -1
  243. package/dist/pipeline/columnBalancing.js +50 -18
  244. package/dist/pipeline/columnBalancing.js.map +1 -1
  245. package/dist/pipeline/config.d.ts.map +1 -1
  246. package/dist/pipeline/config.js +17 -5
  247. package/dist/pipeline/config.js.map +1 -1
  248. package/dist/pipeline/headerFooter.d.ts +37 -2
  249. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  250. package/dist/pipeline/headerFooter.js +231 -15
  251. package/dist/pipeline/headerFooter.js.map +1 -1
  252. package/dist/pipeline/lists.d.ts +15 -0
  253. package/dist/pipeline/lists.d.ts.map +1 -1
  254. package/dist/pipeline/lists.js +73 -16
  255. package/dist/pipeline/lists.js.map +1 -1
  256. package/dist/pipeline/measureContentBlock.d.ts +65 -0
  257. package/dist/pipeline/measureContentBlock.d.ts.map +1 -0
  258. package/dist/pipeline/measureContentBlock.js +134 -0
  259. package/dist/pipeline/measureContentBlock.js.map +1 -0
  260. package/dist/pipeline/pageRoles.d.ts +23 -0
  261. package/dist/pipeline/pageRoles.d.ts.map +1 -0
  262. package/dist/pipeline/pageRoles.js +54 -0
  263. package/dist/pipeline/pageRoles.js.map +1 -0
  264. package/dist/pipeline/paragraphContainers.d.ts +32 -0
  265. package/dist/pipeline/paragraphContainers.d.ts.map +1 -0
  266. package/dist/pipeline/paragraphContainers.js +61 -0
  267. package/dist/pipeline/paragraphContainers.js.map +1 -0
  268. package/dist/pipeline/parts.d.ts +47 -0
  269. package/dist/pipeline/parts.d.ts.map +1 -0
  270. package/dist/pipeline/parts.js +230 -0
  271. package/dist/pipeline/parts.js.map +1 -0
  272. package/dist/pipeline/placeholders.d.ts +46 -1
  273. package/dist/pipeline/placeholders.d.ts.map +1 -1
  274. package/dist/pipeline/placeholders.js +93 -11
  275. package/dist/pipeline/placeholders.js.map +1 -1
  276. package/dist/pipeline/placement.d.ts +61 -7
  277. package/dist/pipeline/placement.d.ts.map +1 -1
  278. package/dist/pipeline/placement.js +151 -12
  279. package/dist/pipeline/placement.js.map +1 -1
  280. package/dist/pipeline/resourceLayout.d.ts +18 -5
  281. package/dist/pipeline/resourceLayout.d.ts.map +1 -1
  282. package/dist/pipeline/resourceLayout.js +145 -23
  283. package/dist/pipeline/resourceLayout.js.map +1 -1
  284. package/dist/pipeline/styles.d.ts +9 -1
  285. package/dist/pipeline/styles.d.ts.map +1 -1
  286. package/dist/pipeline/styles.js +50 -0
  287. package/dist/pipeline/styles.js.map +1 -1
  288. package/dist/table/model.d.ts.map +1 -1
  289. package/dist/table/model.js +16 -2
  290. package/dist/table/model.js.map +1 -1
  291. package/dist/types.d.ts +468 -2
  292. package/dist/types.d.ts.map +1 -1
  293. package/dist/vdt.d.ts +132 -4
  294. package/dist/vdt.d.ts.map +1 -1
  295. package/dist/vdt.js +2 -1
  296. package/dist/vdt.js.map +1 -1
  297. package/package.json +8 -8
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Pre-pass and derived typography for `:::part{number="…" title="…"}`
3
+ * containers. Like the other container plans, part ranges are resolved up
4
+ * front per content-block index (the placement loop rewinds `blockIdx` on
5
+ * keep-with-next rollbacks and replays the markers in between).
6
+ */
7
+ import { dimensionsEqual } from '../defaults/shared';
8
+ import { resolveBodyStyle, resolveBlockquoteStyle } from './styles';
9
+ import { computeLevelIndentsPx, computeOrderedLevelIndentsPx, computeOrderedListRunMetrics, } from './lists';
10
+ export function planParts(contentBlocks) {
11
+ const byStart = new Map();
12
+ const byEnd = new Map();
13
+ const byBlock = new Array(contentBlocks.length);
14
+ let open;
15
+ for (let i = 0; i < contentBlocks.length; i++) {
16
+ const b = contentBlocks[i];
17
+ if (b.type === 'containerStart' && b.containerName === 'part' && b.containerId !== undefined) {
18
+ if (open) {
19
+ open.depth++;
20
+ continue;
21
+ }
22
+ const attrs = b.containerAttrs ?? {};
23
+ const part = {
24
+ startIdx: i,
25
+ endIdx: -1,
26
+ containerId: b.containerId,
27
+ number: (attrs.number ?? '').trim(),
28
+ title: (attrs.title ?? '').trim(),
29
+ };
30
+ open = { part, depth: 0 };
31
+ continue;
32
+ }
33
+ if (b.type === 'containerEnd' && b.containerName === 'part') {
34
+ if (!open)
35
+ continue;
36
+ if (open.depth > 0) {
37
+ open.depth--;
38
+ continue;
39
+ }
40
+ open.part.endIdx = i;
41
+ byStart.set(open.part.startIdx, open.part);
42
+ byEnd.set(i, open.part);
43
+ open = undefined;
44
+ continue;
45
+ }
46
+ if (open)
47
+ byBlock[i] = open.part;
48
+ }
49
+ return { byStart, byEnd, byBlock };
50
+ }
51
+ const ROMAN_RE = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i;
52
+ const ROMAN_VALUES = {
53
+ M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1,
54
+ };
55
+ /** Numeric value of a part number written as a decimal (`'3'`) or a roman
56
+ * numeral (`'III'`, `'iv'`), so `{numberDecimal}` / `{numberRoman}` work
57
+ * whichever way the author wrote it. `undefined` for anything else. */
58
+ export function parsePartNumber(raw) {
59
+ const s = raw.trim();
60
+ if (s.length === 0)
61
+ return undefined;
62
+ if (/^\d+$/.test(s)) {
63
+ const n = Number(s);
64
+ return Number.isSafeInteger(n) ? n : undefined;
65
+ }
66
+ if (!ROMAN_RE.test(s))
67
+ return undefined;
68
+ const u = s.toUpperCase();
69
+ let total = 0;
70
+ for (let i = 0; i < u.length; i++) {
71
+ const v = ROMAN_VALUES[u[i]];
72
+ const next = i + 1 < u.length ? ROMAN_VALUES[u[i + 1]] : 0;
73
+ total += v < next ? -v : v;
74
+ }
75
+ return total;
76
+ }
77
+ const eqStrict = (a, b) => a === b;
78
+ const eqDim = (a, b) => a !== undefined && b !== undefined && dimensionsEqual(a, b);
79
+ const eqColor = (a, b) => a !== undefined && b !== undefined && a.hex === b.hex;
80
+ const UNORDERED_FIELDS = [
81
+ { key: 'fontFamily', levelKey: 'fontFamily', eq: eqStrict },
82
+ { key: 'color', levelKey: 'color', eq: eqColor },
83
+ { key: 'fontWeight', levelKey: 'fontWeight', eq: eqStrict },
84
+ { key: 'italic', levelKey: 'italic', eq: eqStrict },
85
+ { key: 'bulletChar', levelKey: 'bulletChar', eq: eqStrict },
86
+ { key: 'bulletFontSize', levelKey: 'fontSize', eq: eqDim },
87
+ { key: 'gap', eq: eqDim },
88
+ { key: 'indent', levelKey: 'indent', eq: eqDim },
89
+ { key: 'bulletVerticalOffset', levelKey: 'verticalOffset', eq: eqDim },
90
+ { key: 'marginTop', eq: eqDim },
91
+ { key: 'marginBottom', eq: eqDim },
92
+ { key: 'itemSpacing', eq: eqDim },
93
+ { key: 'hangingIndent', eq: eqStrict },
94
+ { key: 'taskCheckboxChar', eq: eqStrict },
95
+ { key: 'taskCheckedChar', eq: eqStrict },
96
+ { key: 'taskCompletedStrikethrough', eq: eqStrict },
97
+ { key: 'taskCompletedColor', eq: eqColor },
98
+ ];
99
+ const ORDERED_FIELDS = [
100
+ {
101
+ key: 'fontFamily', levelKey: 'fontFamily', eq: eqStrict,
102
+ dependents: [{ key: 'separatorFontFamily', levelKey: 'separatorFontFamily' }],
103
+ },
104
+ {
105
+ key: 'color', levelKey: 'color', eq: eqColor,
106
+ dependents: [{ key: 'separatorColor', levelKey: 'separatorColor' }],
107
+ },
108
+ {
109
+ key: 'fontWeight', levelKey: 'fontWeight', eq: eqStrict,
110
+ dependents: [{ key: 'separatorFontWeight', levelKey: 'separatorFontWeight' }],
111
+ },
112
+ {
113
+ key: 'italic', levelKey: 'italic', eq: eqStrict,
114
+ dependents: [{ key: 'separatorItalic', levelKey: 'separatorItalic' }],
115
+ },
116
+ { key: 'numberFormat', levelKey: 'numberFormat', eq: eqStrict },
117
+ { key: 'separator', levelKey: 'separator', eq: eqStrict },
118
+ { key: 'numberFontSize', levelKey: 'fontSize', eq: eqDim },
119
+ { key: 'gap', eq: eqDim },
120
+ { key: 'indent', levelKey: 'indent', eq: eqDim },
121
+ { key: 'numberVerticalOffset', levelKey: 'verticalOffset', eq: eqDim },
122
+ { key: 'marginTop', eq: eqDim },
123
+ { key: 'marginBottom', eq: eqDim },
124
+ { key: 'itemSpacing', eq: eqDim },
125
+ { key: 'hangingIndent', eq: eqStrict },
126
+ { key: 'separatorFontFamily', levelKey: 'separatorFontFamily', eq: eqStrict, inheritsFrom: 'fontFamily' },
127
+ { key: 'separatorFontWeight', levelKey: 'separatorFontWeight', eq: eqStrict, inheritsFrom: 'fontWeight' },
128
+ { key: 'separatorItalic', levelKey: 'separatorItalic', eq: eqStrict, inheritsFrom: 'italic' },
129
+ { key: 'separatorColor', levelKey: 'separatorColor', eq: eqColor, inheritsFrom: 'color' },
130
+ { key: 'separatorGap', levelKey: 'separatorGap', eq: eqDim },
131
+ ];
132
+ /**
133
+ * Apply a partial list config on top of a resolved one. A list-wide value
134
+ * propagates to every level (and dependent field) whose current value still
135
+ * equals the value it was resolved from — a level with its own value keeps
136
+ * it (the same heuristic the callout overrides use). Entries in `levels`
137
+ * then apply directly to their level.
138
+ */
139
+ function applyListOverrides(base, override, specs) {
140
+ if (!override)
141
+ return base;
142
+ const ov = override;
143
+ const out = { ...base };
144
+ const levels = base.levels.map((l) => ({ ...l }));
145
+ const setField = (target, spec, onLevel, value) => {
146
+ const key = onLevel ? spec.levelKey : spec.key;
147
+ const prev = target[key];
148
+ target[key] = value;
149
+ for (const dep of spec.dependents ?? []) {
150
+ const depKey = onLevel ? dep.levelKey : dep.key;
151
+ if (spec.eq(target[depKey], prev))
152
+ target[depKey] = value;
153
+ }
154
+ };
155
+ for (const spec of specs) {
156
+ const value = ov[spec.key];
157
+ if (value === undefined)
158
+ continue;
159
+ const prevGeneral = out[spec.key];
160
+ setField(out, spec, false, value);
161
+ if (!spec.levelKey)
162
+ continue;
163
+ for (const l of levels) {
164
+ const current = l[spec.levelKey];
165
+ const inherited = spec.eq(current, prevGeneral) ||
166
+ (spec.inheritsFrom !== undefined && spec.eq(current, l[spec.inheritsFrom]));
167
+ if (inherited)
168
+ setField(l, spec, true, value);
169
+ }
170
+ }
171
+ const levelOverrides = ov.levels ?? [];
172
+ for (const lo of levelOverrides) {
173
+ const target = levels.find((l) => l.level === lo.level);
174
+ if (!target)
175
+ continue;
176
+ for (const spec of specs) {
177
+ if (!spec.levelKey)
178
+ continue;
179
+ const value = lo[spec.levelKey];
180
+ if (value !== undefined)
181
+ setField(target, spec, true, value);
182
+ }
183
+ }
184
+ out.levels = levels;
185
+ return out;
186
+ }
187
+ /** Shallow copy of `resolved` whose `bodyText` and list configs carry the
188
+ * `parts.bodyStyle` overrides, so the body/list resolvers yield the part
189
+ * typography without any part-specific branches (the callout approach).
190
+ * Ordered-list numbers are set bold in `numberColor`; bullets take
191
+ * `bulletColor`. Level-specific values only follow an override when they
192
+ * still equal the general value they were resolved from. The
193
+ * `bodyStyle.unorderedLists` / `orderedLists` partials apply last. */
194
+ export function derivePartResolvedConfig(resolved) {
195
+ const { bodyStyle } = resolved.parts;
196
+ const bold = resolved.bodyText.boldFontWeight;
197
+ const unorderedLists = applyListOverrides(applyListOverrides(resolved.unorderedLists, { color: bodyStyle.bulletColor }, UNORDERED_FIELDS), bodyStyle.unorderedLists, UNORDERED_FIELDS);
198
+ const orderedLists = applyListOverrides(applyListOverrides(resolved.orderedLists, { color: bodyStyle.numberColor, fontWeight: bold }, ORDERED_FIELDS), bodyStyle.orderedLists, ORDERED_FIELDS);
199
+ return {
200
+ ...resolved,
201
+ bodyText: {
202
+ ...resolved.bodyText,
203
+ fontFamily: bodyStyle.fontFamily,
204
+ fontSize: bodyStyle.fontSize,
205
+ lineHeight: bodyStyle.lineHeight,
206
+ color: bodyStyle.color,
207
+ textAlign: bodyStyle.textAlign,
208
+ },
209
+ unorderedLists,
210
+ orderedLists,
211
+ };
212
+ }
213
+ /** Measurement context for the blocks inside a part: the derived config
214
+ * plus the body / blockquote styles, list indents and ordered-list number
215
+ * widths recomputed from it. */
216
+ export function derivePartMeasureContext(ctx) {
217
+ const resolved = derivePartResolvedConfig(ctx.resolved);
218
+ const bodyStyle = resolveBodyStyle(resolved);
219
+ const orderedMetrics = computeOrderedListRunMetrics([...ctx.contentBlocks], resolved, bodyStyle.fontSizePx);
220
+ return {
221
+ ...ctx,
222
+ resolved,
223
+ bodyStyle,
224
+ blockquoteStyle: resolveBlockquoteStyle(resolved),
225
+ listLevelIndentsPx: computeLevelIndentsPx(resolved, bodyStyle.fontSizePx),
226
+ orderedMetrics,
227
+ orderedLevelIndentsPx: computeOrderedLevelIndentsPx(resolved, bodyStyle.fontSizePx, orderedMetrics.maxWidthByDepth),
228
+ };
229
+ }
230
+ //# sourceMappingURL=parts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parts.js","sourceRoot":"","sources":["../../src/pipeline/parts.ts"],"names":[],"mappings":"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"}
@@ -18,12 +18,30 @@ export interface PlaceholderContext {
18
18
  metadata: DocumentMetadata;
19
19
  /** Chapter title per page index (most recent H1 at or before each page). */
20
20
  chapterTitleByPageIndex: string[];
21
+ /** Heading attributes of the current chapter's H1 per page index (see
22
+ * `computeChapterAttrs`). Backs `{attr.<key>}` in header/footer slots. A
23
+ * missing entry or key resolves to `''`. */
24
+ chapterAttrsByPageIndex?: Record<string, string>[];
25
+ /** Current part title / number per page index (see `computePartValues`).
26
+ * Back `{partTitle}` / `{partNumber}`; a missing entry resolves to `''`. */
27
+ partTitleByPageIndex?: string[];
28
+ partNumberByPageIndex?: string[];
29
+ /** Current chapter number per page index (see `computeChapterNumbers`).
30
+ * Backs `{chapterNumber}` in header/footer slots. */
31
+ chapterNumberByPageIndex?: string[];
21
32
  }
22
33
  export interface PlaceholderResult {
23
34
  text: string;
24
35
  unknownPlaceholders: string[];
25
36
  missingMetadata: string[];
26
37
  }
38
+ /** Placeholder grammar: `name` or `name.key` — the dotted form is reserved
39
+ * for namespaced lookups such as `{attr.author}` (heading attributes). */
40
+ export declare const PLACEHOLDER_NAME_RE: RegExp;
41
+ /** Namespace of the heading-attribute placeholders (`{attr.<key>}`). */
42
+ export declare const ATTR_PLACEHOLDER_PREFIX = "attr.";
43
+ /** When `name` is an `attr.<key>` placeholder, returns `<key>`. */
44
+ export declare function attrPlaceholderKey(name: string): string | undefined;
27
45
  /**
28
46
  * Precompute chapter titles (most recent H1 text) for each page index by
29
47
  * walking blocks once. Returns an array where `result[pageIndex]` is the plain
@@ -43,9 +61,36 @@ export declare function computeChapterTitles(blocks: VDTBlock[], totalPages: num
43
61
  * `{chapterNumber}` in heading-context slots resolves to the current chapter.
44
62
  */
45
63
  export declare function computeChapterNumbers(blocks: VDTBlock[], totalPages: number, pages?: ChapterTitlePageInfo[]): string[];
64
+ /**
65
+ * Precompute the heading attributes (`# Title {key="value"}`) of the most
66
+ * recent H1 per page. Backs `{attr.<key>}` in header/footer slots; pages
67
+ * before the first H1 get an empty record.
68
+ */
69
+ export declare function computeChapterAttrs(blocks: VDTBlock[], totalPages: number, pages?: ChapterTitlePageInfo[]): Record<string, string>[];
70
+ /** The page fields `computePartValues` reads. */
71
+ export interface PartPageInfo extends ChapterTitlePageInfo {
72
+ partInfo?: {
73
+ number: string;
74
+ title: string;
75
+ };
76
+ }
77
+ /**
78
+ * Precompute the current part title and number per page index. A page with
79
+ * `partInfo` (a `:::part` divider page) starts a new part that runs until
80
+ * the next one; pages before the first part get `''`. Blank parity pages
81
+ * immediately preceding a part page belong to the upcoming part (they exist
82
+ * only to push it onto the right parity); a `blankForForce` page stops the
83
+ * walk — it belongs to the previous part, the same rule as chapters.
84
+ */
85
+ export declare function computePartValues(pages: readonly PartPageInfo[]): {
86
+ partTitleByPageIndex: string[];
87
+ partNumberByPageIndex: string[];
88
+ };
46
89
  /**
47
90
  * Resolve placeholder templates. Grammar:
48
- * - `{name}` with name matching `[a-zA-Z][a-zA-Z0-9]*` is a placeholder.
91
+ * - `{name}` with name matching `[a-zA-Z][a-zA-Z0-9]*` is a placeholder;
92
+ * - `{name.key}` is a namespaced placeholder — `{attr.<key>}` reads the
93
+ * current chapter's heading attributes (missing → `''`, no warning);
49
94
  * - `{{` and `}}` are literal braces.
50
95
  */
51
96
  export declare function resolvePlaceholders(template: string, ctx: PlaceholderContext): PlaceholderResult;
@@ -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,CAEV;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAEV;AAoED;;;;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":"AACA,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;IAClC;;iDAE6C;IAC7C,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACnD;iFAC6E;IAC7E,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC;0DACsD;IACtD,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAiBD;2EAC2E;AAC3E,eAAO,MAAM,mBAAmB,QAAyD,CAAC;AAE1F,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAE/C,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAInE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAEV;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,EAAE,CAmBV;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,QAAQ,EAAE,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAC7B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAE1B;AA6DD,iDAAiD;AACjD,MAAM,WAAW,YAAa,SAAQ,oBAAoB;IACxD,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,YAAY,EAAE,GAC7B;IAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAAC,qBAAqB,EAAE,MAAM,EAAE,CAAA;CAAE,CAqBrE;AAWD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,kBAAkB,GACtB,iBAAiB,CAsDnB;AA6BD;;;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,3 +1,4 @@
1
+ import { TITLE_BREAK_RE } from '../parse/inlineFormatting';
1
2
  const PLACEHOLDER_NAMES = new Set([
2
3
  'pageNumber',
3
4
  'totalPages',
@@ -6,8 +7,23 @@ const PLACEHOLDER_NAMES = new Set([
6
7
  'author',
7
8
  'publishDate',
8
9
  'chapterTitle',
10
+ 'chapterNumber',
11
+ 'partTitle',
12
+ 'partNumber',
9
13
  ]);
10
14
  const METADATA_PLACEHOLDERS = new Set(['title', 'subtitle', 'author', 'publishDate']);
15
+ /** Placeholder grammar: `name` or `name.key` — the dotted form is reserved
16
+ * for namespaced lookups such as `{attr.author}` (heading attributes). */
17
+ export const PLACEHOLDER_NAME_RE = /^[a-zA-Z][a-zA-Z0-9]*(?:\.[a-zA-Z_][a-zA-Z0-9_-]*)?$/;
18
+ /** Namespace of the heading-attribute placeholders (`{attr.<key>}`). */
19
+ export const ATTR_PLACEHOLDER_PREFIX = 'attr.';
20
+ /** When `name` is an `attr.<key>` placeholder, returns `<key>`. */
21
+ export function attrPlaceholderKey(name) {
22
+ if (!name.startsWith(ATTR_PLACEHOLDER_PREFIX))
23
+ return undefined;
24
+ const key = name.slice(ATTR_PLACEHOLDER_PREFIX.length);
25
+ return key.length > 0 ? key : undefined;
26
+ }
11
27
  /**
12
28
  * Precompute chapter titles (most recent H1 text) for each page index by
13
29
  * walking blocks once. Returns an array where `result[pageIndex]` is the plain
@@ -21,7 +37,7 @@ const METADATA_PLACEHOLDERS = new Set(['title', 'subtitle', 'author', 'publishDa
21
37
  * in its header, not the previous chapter's.
22
38
  */
23
39
  export function computeChapterTitles(blocks, totalPages, pages) {
24
- return computeChapterValues(blocks, totalPages, pages, plainTextOfBlock);
40
+ return computeChapterValues(blocks, totalPages, pages, plainTextOfBlock, '');
25
41
  }
26
42
  /**
27
43
  * Precompute chapter numbers (most recent H1 `numberPrefix`) per page. Mirrors
@@ -29,14 +45,35 @@ export function computeChapterTitles(blocks, totalPages, pages) {
29
45
  * `{chapterNumber}` in heading-context slots resolves to the current chapter.
30
46
  */
31
47
  export function computeChapterNumbers(blocks, totalPages, pages) {
32
- return computeChapterValues(blocks, totalPages, pages, (b) => b.numberPrefix ?? '');
48
+ // Without a level-1 numbering template the prefix is empty; fall back to
49
+ // the chapter's ordinal so `{chapterNumber}` still counts chapters.
50
+ let ordinal = 0;
51
+ let lastContentIndex;
52
+ return computeChapterValues(blocks, totalPages, pages, (b) => {
53
+ // A heading split across columns yields several blocks with the same
54
+ // content index; count the chapter once.
55
+ if (b.contentIndex === undefined || b.contentIndex !== lastContentIndex)
56
+ ordinal++;
57
+ lastContentIndex = b.contentIndex;
58
+ const prefix = b.numberPrefix?.trim() ?? '';
59
+ return prefix.length > 0 ? prefix : String(ordinal);
60
+ }, '');
61
+ }
62
+ /**
63
+ * Precompute the heading attributes (`# Title {key="value"}`) of the most
64
+ * recent H1 per page. Backs `{attr.<key>}` in header/footer slots; pages
65
+ * before the first H1 get an empty record.
66
+ */
67
+ export function computeChapterAttrs(blocks, totalPages, pages) {
68
+ return computeChapterValues(blocks, totalPages, pages, (b) => b.attrs ?? {}, {});
33
69
  }
34
- /** Shared walker behind `computeChapterTitles` / `computeChapterNumbers`:
35
- * tracks the most recent H1's extracted value per page. */
36
- function computeChapterValues(blocks, totalPages, pages, extract) {
37
- const out = new Array(totalPages).fill('');
70
+ /** Shared walker behind `computeChapterTitles` / `computeChapterNumbers` /
71
+ * `computeChapterAttrs`: tracks the most recent H1's extracted value per
72
+ * page, starting from `empty` before the first H1. */
73
+ function computeChapterValues(blocks, totalPages, pages, extract, empty) {
74
+ const out = new Array(totalPages).fill(empty);
38
75
  const byPage = new Map();
39
- let current = '';
76
+ let current = empty;
40
77
  // Walk blocks in page/column order. The VDT `doc.blocks` array is already
41
78
  // insertion-ordered by placement, so pages are in increasing index.
42
79
  let lastPageIndex = -1;
@@ -87,6 +124,37 @@ function computeChapterValues(blocks, totalPages, pages, extract) {
87
124
  }
88
125
  return out;
89
126
  }
127
+ /**
128
+ * Precompute the current part title and number per page index. A page with
129
+ * `partInfo` (a `:::part` divider page) starts a new part that runs until
130
+ * the next one; pages before the first part get `''`. Blank parity pages
131
+ * immediately preceding a part page belong to the upcoming part (they exist
132
+ * only to push it onto the right parity); a `blankForForce` page stops the
133
+ * walk — it belongs to the previous part, the same rule as chapters.
134
+ */
135
+ export function computePartValues(pages) {
136
+ const partTitleByPageIndex = new Array(pages.length).fill('');
137
+ const partNumberByPageIndex = new Array(pages.length).fill('');
138
+ let title = '';
139
+ let number = '';
140
+ for (let p = 0; p < pages.length; p++) {
141
+ const info = pages[p].partInfo;
142
+ if (info) {
143
+ title = info.title.replace(TITLE_BREAK_RE, ' ');
144
+ number = info.number;
145
+ for (let q = p - 1; q >= 0; q--) {
146
+ const prev = pages[q];
147
+ if (prev.blankForForce || !prev.blankForParity)
148
+ break;
149
+ partTitleByPageIndex[q] = title;
150
+ partNumberByPageIndex[q] = number;
151
+ }
152
+ }
153
+ partTitleByPageIndex[p] = title;
154
+ partNumberByPageIndex[p] = number;
155
+ }
156
+ return { partTitleByPageIndex, partNumberByPageIndex };
157
+ }
90
158
  function plainTextOfBlock(block) {
91
159
  // Strip any numbering prefix that was prepended during build.
92
160
  const lines = block.lines.map((l) => l.text).join(' ');
@@ -97,7 +165,9 @@ function plainTextOfBlock(block) {
97
165
  }
98
166
  /**
99
167
  * Resolve placeholder templates. Grammar:
100
- * - `{name}` with name matching `[a-zA-Z][a-zA-Z0-9]*` is a placeholder.
168
+ * - `{name}` with name matching `[a-zA-Z][a-zA-Z0-9]*` is a placeholder;
169
+ * - `{name.key}` is a namespaced placeholder — `{attr.<key>}` reads the
170
+ * current chapter's heading attributes (missing → `''`, no warning);
101
171
  * - `{{` and `}}` are literal braces.
102
172
  */
103
173
  export function resolvePlaceholders(template, ctx) {
@@ -126,11 +196,17 @@ export function resolvePlaceholders(template, ctx) {
126
196
  continue;
127
197
  }
128
198
  const name = template.slice(i + 1, end);
129
- if (!/^[a-zA-Z][a-zA-Z0-9]*$/.test(name)) {
199
+ if (!PLACEHOLDER_NAME_RE.test(name)) {
130
200
  out += template.slice(i, end + 1);
131
201
  i = end + 1;
132
202
  continue;
133
203
  }
204
+ const attrKey = attrPlaceholderKey(name);
205
+ if (attrKey !== undefined) {
206
+ out += ctx.chapterAttrsByPageIndex?.[ctx.page.index]?.[attrKey] ?? '';
207
+ i = end + 1;
208
+ continue;
209
+ }
134
210
  if (!PLACEHOLDER_NAMES.has(name)) {
135
211
  unknown.push(name);
136
212
  i = end + 1;
@@ -165,6 +241,12 @@ function resolveName(name, ctx) {
165
241
  return typeof ctx.metadata.publishDate === 'string' ? ctx.metadata.publishDate : '';
166
242
  case 'chapterTitle':
167
243
  return ctx.chapterTitleByPageIndex[ctx.page.index] ?? '';
244
+ case 'partTitle':
245
+ return ctx.partTitleByPageIndex?.[ctx.page.index] ?? '';
246
+ case 'partNumber':
247
+ return ctx.partNumberByPageIndex?.[ctx.page.index] ?? '';
248
+ case 'chapterNumber':
249
+ return ctx.chapterNumberByPageIndex?.[ctx.page.index] ?? '';
168
250
  default:
169
251
  return '';
170
252
  }
@@ -191,7 +273,7 @@ export function collectPlaceholderNames(template) {
191
273
  if (end === -1)
192
274
  break;
193
275
  const name = template.slice(i + 1, end);
194
- if (/^[a-zA-Z][a-zA-Z0-9]*$/.test(name))
276
+ if (PLACEHOLDER_NAME_RE.test(name))
195
277
  names.add(name);
196
278
  i = end + 1;
197
279
  continue;
@@ -201,7 +283,7 @@ export function collectPlaceholderNames(template) {
201
283
  return [...names];
202
284
  }
203
285
  export function isKnownPlaceholder(name) {
204
- return PLACEHOLDER_NAMES.has(name);
286
+ return PLACEHOLDER_NAMES.has(name) || attrPlaceholderKey(name) !== undefined;
205
287
  }
206
288
  export function isMetadataPlaceholder(name) {
207
289
  return METADATA_PLACEHOLDERS.has(name);
@@ -1 +1 @@
1
- {"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"AA8BA,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,YAAY;IACZ,YAAY;IACZ,OAAO;IACP,UAAU;IACV,QAAQ;IACR,aAAa;IACb,cAAc;CACf,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;AAEtF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAkB,EAClB,UAAkB,EAClB,KAA8B;IAE9B,OAAO,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;AAC3E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAkB,EAClB,UAAkB,EAClB,KAA8B;IAE9B,OAAO,oBAAoB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;AACtF,CAAC;AAED;4DAC4D;AAC5D,SAAS,oBAAoB,CAC3B,MAAkB,EAClB,UAAkB,EAClB,KAAyC,EACzC,OAAoC;IAEpC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,0EAA0E;IAC1E,oEAAoE;IACpE,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;IACvB,oEAAoE;IACpE,qBAAqB;IACrB,MAAM,aAAa,GAAgD,EAAE,CAAC;IACtE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC;YAAE,SAAS;QAC9B,OAAO,aAAa,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;YACnC,aAAa,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACjC,aAAa,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACD,oEAAoE;IACpE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAE,CAAC;QAC1B,CAAC;aAAM,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QACvB,CAAC;IACH,CAAC;IACD,kEAAkE;IAClE,kEAAkE;IAClE,mEAAmE;IACnE,oEAAoE;IACpE,mEAAmE;IACnE,oBAAoB;IACpB,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,aAAa,EAAE,CAAC;YACjD,KAAK,IAAI,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,IAAI,CAAC,IAAI;oBAAE,MAAM;gBACjB,IAAI,IAAI,CAAC,aAAa;oBAAE,MAAM;gBAC9B,IAAI,CAAC,IAAI,CAAC,cAAc;oBAAE,MAAM;gBAChC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAe;IACvC,8DAA8D;IAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,GAAuB;IAEvB,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QACxB,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC1C,GAAG,IAAI,GAAG,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAC1C,GAAG,IAAI,GAAG,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,kCAAkC;gBAClC,GAAG,IAAI,EAAE,CAAC;gBACV,CAAC,EAAE,CAAC;gBACJ,SAAS;YACX,CAAC;YACD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;gBAClC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;gBACZ,SAAS;YACX,CAAC;YACD,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;gBACZ,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACrC,IAAI,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACpD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;YACD,GAAG,IAAI,KAAK,CAAC;YACb,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;YACZ,SAAS;QACX,CAAC;QACD,GAAG,IAAI,EAAE,CAAC;QACV,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,mBAAmB,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC;AAC/E,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,GAAuB;IACxD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,YAAY;YACf,OAAO,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAC5B,KAAK,YAAY;YACf,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,OAAO;YACV,OAAO,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,KAAK,UAAU;YACb,OAAO,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,KAAK,QAAQ;YACX,OAAO,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,KAAK,aAAa;YAChB,OAAO,OAAO,GAAG,CAAC,QAAQ,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,KAAK,cAAc;YACjB,OAAO,GAAG,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3D;YACE,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB;IACtD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QACxB,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAAC,CAAC,IAAI,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAChE,IAAI,EAAE,KAAK,GAAG,IAAI,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAAC,CAAC,IAAI,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QAChE,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,MAAM;YACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzD,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;YACZ,SAAS;QACX,CAAC;QACD,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../src/pipeline/placeholders.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,63 @@
1
1
  import { type BoundingBox, type ResolvedConfig, type VDTDocument, type VDTBlock, type VDTLine, type VDTPage, type VDTColumn } from '../vdt';
2
2
  import type { HeadingBreakParity } from '../types';
3
+ import { type PageMetrics } from './buildHelpers';
3
4
  export interface PlacementCursor {
4
5
  pageIndex: number;
5
6
  columnIndex: number;
6
7
  }
7
8
  export declare function resetLinePositions(lines: VDTLine[], lineHeightPx: number): VDTLine[];
8
9
  export declare function createPageWithColumns(pageIndex: number, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): VDTPage;
10
+ /** Turn a freshly opened (empty) page into a part-divider page: a single
11
+ * body column inset from the trim box by `parts.margins` (mirrored on even
12
+ * pages when `parts.margins.mirror` is on), `page.contentArea` set to that
13
+ * area, `partInfo` stamped and the role fixed to `'part'`. The opener
14
+ * design is laid out later by `buildHeadersAndFooters` against the full
15
+ * trim box and never reserves body space. */
16
+ export declare function createPartPage(page: VDTPage, metrics: Pick<PageMetrics, 'trimBox' | 'pageWidthPx'>, resolved: ResolvedConfig, info: {
17
+ number: string;
18
+ title: string;
19
+ titleSourceStart?: number;
20
+ titleSourceEnd?: number;
21
+ }): VDTPage;
9
22
  export declare function currentColumn(doc: VDTDocument, cursor: PlacementCursor): VDTColumn;
23
+ /** Whether any column of the page — text or span — holds a placed block.
24
+ * Floats live outside the columns and do not count. */
25
+ export declare function pageHasContent(page: VDTPage): boolean;
26
+ /** Text columns of `band` in reading order (span columns excluded). */
27
+ export declare function bandColumns(page: VDTPage, band: number): VDTColumn[];
28
+ /** Band the cursor's column belongs to (`0` for the plain single-band page). */
29
+ export declare function currentBand(page: VDTPage, cursor: PlacementCursor): number;
30
+ /** True when every column of the band has consumed the same height (within
31
+ * 0.5px) — the page top, right after an opener heading (which reserves its
32
+ * band in every column), right after another span block, or right after a
33
+ * top float band. Used height = `bbox.height − availableHeight`. */
34
+ export declare function isBandLevel(cols: readonly VDTColumn[]): boolean;
35
+ /** Lowest used bottom (absolute y) across the band's columns — where a
36
+ * full-width block can start without covering placed content. */
37
+ export declare function bandUsedBottom(cols: readonly VDTColumn[]): number;
38
+ /**
39
+ * Close the band formed by `cols` at `cutY`, insert a full-width span column
40
+ * holding `block` right below the cut, and open a fresh band of text columns
41
+ * under it. The band's columns are clamped to `cutY` — a column whose top
42
+ * already sits at the cut becomes zero-height — and keep only the slack
43
+ * between their used bottom and the cut in `availableHeight` (zero when the
44
+ * band is level on the grid; whole lines when a band cap cut the band with
45
+ * its last column short, so column balancing can still fill them). The span
46
+ * column is `{ kind: 'span', band }` at `contentArea.x / width`, `needPx`
47
+ * tall (the block plus its spacing, already rounded to the grid by the
48
+ * caller); `block` is placed inside it at `spacingBefore` below the cut with
49
+ * height `blockHeight` (default: the rest of the band), so `block.pageIndex`
50
+ * / `columnIndex` address the span column.
51
+ *
52
+ * The new text columns (`band + 1`) copy each closed column's x / width and
53
+ * keep its original bottom (so a bottom float band reserved on one column
54
+ * still constrains its successor). A column with no room left (bottom
55
+ * within 0.5px of the new band's top) is not created; when none is, the
56
+ * cursor stays on the span column — which is full — so the next placement
57
+ * advances to a new page. Otherwise the cursor moves to the first new
58
+ * column. Returns the span column.
59
+ */
60
+ export declare function closeBandAndInsertSpan(page: VDTPage, cols: readonly VDTColumn[], cutY: number, block: VDTBlock, needPx: number, cursor: PlacementCursor, spacingBefore?: number, blockHeight?: number): VDTColumn;
10
61
  export declare function advanceToNextColumn(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number, onNewPage?: (page: VDTPage) => void): void;
11
62
  /** Advance `cursor` forward until it points to the first column of a new
12
63
  * page. No-op when the current page is empty (nothing placed yet) — avoids
@@ -26,17 +77,20 @@ export declare function advanceToNextPageBoundary(doc: VDTDocument, cursor: Plac
26
77
  * whether the natural next page already matched the requested parity. */
27
78
  export declare function enforcePageParity(doc: VDTDocument, cursor: PlacementCursor, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number, parity: HeadingBreakParity): void;
28
79
  /**
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.
80
+ * Place an atomic block — a resource group (image / svg / table + caption,
81
+ * issue #49 §7) or a callout frame keeping it together as one unit. Atomic
82
+ * blocks never split mid-content for v1: if the group's combined height fits
83
+ * the remaining column space it is placed there; otherwise the cursor advances
84
+ * to the next column/page (without emitting a leading blank page when the
85
+ * current column is empty), and the block is force-placed there even when it
86
+ * exceeds a single column's height.
35
87
  *
36
88
  * `spacingBefore` is consumed from the target column's available height before
37
89
  * placement (collapsed against the previous block's bottom margin by the
38
90
  * caller). Returns the height actually reserved for the block.
39
91
  */
40
- export declare function placeResourceBlock(block: VDTBlock, groupHeight: number, spacingBefore: number, cursor: PlacementCursor, doc: VDTDocument, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): number;
92
+ export declare function placeAtomicBlock(block: VDTBlock, groupHeight: number, spacingBefore: number, cursor: PlacementCursor, doc: VDTDocument, resolved: ResolvedConfig, contentArea: BoundingBox, pageWidthPx: number, pageHeightPx: number): number;
93
+ /** @deprecated Use {@link placeAtomicBlock}. */
94
+ export declare const placeResourceBlock: typeof placeAtomicBlock;
41
95
  export declare function placeBlockInColumn(block: VDTBlock, blockHeight: number, col: VDTColumn, cursor: PlacementCursor): void;
42
96
  //# sourceMappingURL=placement.d.ts.map