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
@@ -1,11 +1,19 @@
1
- export type ContentBlockType = 'heading' | 'paragraph' | 'blockquote' | 'listItem' | 'mathDisplay' | 'resourceBlock' | 'directive';
1
+ export type ContentBlockType = 'heading' | 'paragraph' | 'blockquote' | 'listItem' | 'mathDisplay' | 'resourceBlock' | 'directive' | 'containerStart' | 'containerEnd';
2
2
  /** Attributes parsed from a `:::name{key="v" other=bare flag}` directive.
3
3
  * Values are kept as strings; directive consumers validate/coerce. A bare
4
4
  * `flag` becomes `{ flag: '' }`. */
5
5
  export type DirectiveAttrs = Record<string, string>;
6
6
  /** Recognized directive names. Unknown names are not parsed as directives —
7
7
  * they fall through to the paragraph branch and surface via warnings. */
8
- export type DirectiveName = 'pagebreak' | 'numbering';
8
+ export type DirectiveName = 'pagebreak' | 'numbering' | 'columnbreak';
9
+ /** Recognized fenced-container names. A container opens with a
10
+ * `:::name{attrs}` line and closes with a bare `:::` line; the blocks in
11
+ * between are parsed as usual and bracketed by a `containerStart` /
12
+ * `containerEnd` marker pair sharing a `containerId`. */
13
+ export type ContainerName = 'callout' | 'paragraphs' | 'part';
14
+ /** Letter-case transform applied to the computed label of an inline `:ref`
15
+ * (never to the number, never to a `text=` override). */
16
+ export type RefCase = 'lower' | 'upper' | 'capitalize';
9
17
  /** Metadata attached to an `InlineSpan` when it represents a math formula.
10
18
  * The span's `text` is a single `\uFFFC` (object replacement character)
11
19
  * acting as a one-char-wide atomic placeholder in the plain text. */
@@ -42,6 +50,9 @@ export interface InlineSpan {
42
50
  style?: 'default' | 'number' | 'full';
43
51
  /** Optional override text to display instead of the computed label. */
44
52
  text?: string;
53
+ /** Optional letter-case transform for the label part (`Fig.` /
54
+ * `Figure`) of the computed label. Ignored when `text` is set. */
55
+ case?: RefCase;
45
56
  };
46
57
  }
47
58
  /** Convenience discriminants for inline span iteration. */
@@ -52,23 +63,51 @@ export type MathSpan = InlineSpan & {
52
63
  math: MathMeta;
53
64
  };
54
65
  export type ListKind = 'unordered' | 'ordered' | 'task';
55
- export type ParseIssueKind = 'unclosedMath' | 'unclosedMathBlock';
56
- export interface ParseIssue {
66
+ export type ParseIssueKind = 'unclosedMath' | 'unclosedMathBlock' | 'unclosedContainer';
67
+ interface ParseIssueBase {
57
68
  kind: ParseIssueKind;
58
- delimiter: '$' | '$$';
69
+ delimiter: '$' | '$$' | ':::';
59
70
  /** Absolute source offset of the unmatched opening delimiter. */
60
71
  sourceStart: number;
61
72
  /** End of the scanned region (usually the line or block end). */
62
73
  sourceEnd: number;
74
+ }
75
+ /** An inline `$…` or display `$$…` formula whose closing delimiter is
76
+ * missing. */
77
+ export interface UnclosedMathIssue extends ParseIssueBase {
78
+ kind: 'unclosedMath' | 'unclosedMathBlock';
79
+ delimiter: '$' | '$$';
63
80
  /** Raw TeX captured up to the end of the scanned region, for warning
64
81
  * messages — may be empty. */
65
82
  tex: string;
66
83
  }
84
+ /** A `:::name` container fence that was still open at end of input. The
85
+ * parser auto-closes it; `sourceStart`/`sourceEnd` cover the opening line. */
86
+ export interface UnclosedContainerIssue extends ParseIssueBase {
87
+ kind: 'unclosedContainer';
88
+ delimiter: ':::';
89
+ containerName: ContainerName;
90
+ containerId: number;
91
+ }
92
+ export type ParseIssue = UnclosedMathIssue | UnclosedContainerIssue;
67
93
  export interface ContentBlock {
68
94
  type: ContentBlockType;
69
95
  text: string;
70
96
  spans: InlineSpan[];
71
97
  level?: number;
98
+ /** For `heading` blocks: attributes parsed from a trailing
99
+ * `{key="value" other=bare}` on the heading line (e.g.
100
+ * `# Title {author="I. Zango"}`). The braces and their content are
101
+ * removed from `text`. Absent when the heading carries no attributes. */
102
+ attrs?: DirectiveAttrs;
103
+ /** Absolute source range of each quoted attribute value, so editors can
104
+ * map text rendered from `{attr.<key>}` back to the markdown. */
105
+ attrSources?: Record<string, {
106
+ start: number;
107
+ end: number;
108
+ }>;
109
+ /** Plain-text indices of forced title breaks (`\\` in the source). */
110
+ titleBreaks?: number[];
72
111
  /** Depth (1-based) for listItem blocks. Level 1 = outermost. */
73
112
  depth?: number;
74
113
  /** Discriminator for listItem blocks. Defaults to 'unordered' when absent. */
@@ -85,6 +124,16 @@ export interface ContentBlock {
85
124
  directiveAttrs?: DirectiveAttrs;
86
125
  /** For `resourceBlock` blocks: the referenced `Resource.id`. */
87
126
  resourceId?: string;
127
+ /** For `containerStart` / `containerEnd` marker blocks: the container
128
+ * name (`'callout'`, `'paragraphs'`, `'part'`). */
129
+ containerName?: ContainerName;
130
+ /** For `containerStart` blocks: attributes parsed from the opening fence.
131
+ * Always present on a start marker (empty object when the fence carries
132
+ * no `{…}`). */
133
+ containerAttrs?: DirectiveAttrs;
134
+ /** For container marker blocks: identifier shared by the matching
135
+ * start/end pair. Ids start at 1 and increase per parse. */
136
+ containerId?: number;
88
137
  /** Character offset of the first source character of this block in the original markdown */
89
138
  sourceStart: number;
90
139
  /** Character offset just past the last source character of this block */
@@ -96,4 +145,5 @@ export interface ContentBlock {
96
145
  */
97
146
  sourceMap: number[];
98
147
  }
148
+ export {};
99
149
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parse/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,WAAW,GACX,YAAY,GACZ,UAAU,GACV,aAAa,GACb,eAAe,GACf,WAAW,CAAC;AAEhB;;qCAEqC;AACrC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEpD;0EAC0E;AAC1E,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;AAEtD;;sEAEsE;AACtE,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB;;kDAE8C;IAC9C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;uEACmE;IACnE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;8DAC0D;IAC1D,UAAU,CAAC,EAAE,OAAO,eAAe,EAAE,UAAU,CAAC;IAChD;;kDAE8C;IAC9C,GAAG,CAAC,EAAE;QACJ,oCAAoC;QACpC,UAAU,EAAE,MAAM,CAAC;QACnB;;sBAEc;QACd,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;QACtC,uEAAuE;QACvE,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AACzD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,mBAAmB,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,GAAG,GAAG,IAAI,CAAC;IACtB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB;mCAC+B;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,iDAAiD;IACjD,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4FAA4F;IAC5F,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parse/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Band caps — page-span blocks, stage 2 (mid-page bands).
3
+ *
4
+ * Stage 1 (`placement.ts`) only inserts a page-span block where the current
5
+ * column band is *level*; a block arriving with the columns uneven moves to
6
+ * the top of the next page. Stage 2 lets it land mid-page the way a
7
+ * compositor would set it: the text above the box is cut level across all
8
+ * columns, the box spans the page, and the columns resume below it.
9
+ *
10
+ * Rather than redistributing already-placed blocks in place (which would
11
+ * bypass orphan / widow / keep-with-next), the engine re-runs the placement
12
+ * pass with a **band cap**: the columns of the band that opens with a given
13
+ * content block are shortened to `lines` grid lines, so they fill and
14
+ * overflow into each other naturally — every placement rule keeps applying
15
+ * — and end level at `bandTop + lines·grid`, where the span block then cuts
16
+ * the band. A cap is proposed by the pass that saw the block arrive in an
17
+ * uneven band with room below (`lines = ceil(Σ used px / N / grid)`), and
18
+ * consumed by the next pass. When the capped band overflows differently
19
+ * (e.g. keep-with-next moved a heading and the text no longer fits above
20
+ * the cut), the cap is retried one line taller a bounded number of times,
21
+ * then dropped — the block falls back to stage 1.
22
+ */
23
+ import type { VDTColumn } from '../vdt';
24
+ /** Cap on the band that opens with content block `startContentIndex`
25
+ * (part `startPart` — a split paragraph's continuation can open a band
26
+ * too), keyed in `bandCaps` by the span block's own content index. */
27
+ export interface BandCap {
28
+ startContentIndex: number;
29
+ /** Part index of the band's opening block (`0` unless it is the
30
+ * continuation of a paragraph split across columns / pages). */
31
+ startPart: number;
32
+ /** Height of the capped band in baseline-grid lines. */
33
+ lines: number;
34
+ /** Times the cap has been grown by one line after an overflow. */
35
+ retries: number;
36
+ }
37
+ /** Maximum number of extra placement passes the band-cap driver may run on
38
+ * top of the initial pass (proposals + retries). */
39
+ export declare const MAX_BAND_PASSES = 4;
40
+ /** Maximum number of `lines + 1` retries for a cap whose band overflowed. */
41
+ export declare const MAX_BAND_CAP_RETRIES = 3;
42
+ /** What a placement pass reports back to the band-cap driver. */
43
+ export interface BandPassReport {
44
+ /** New caps, keyed by the proposing span block's content index. */
45
+ bandCapProposals: ReadonlyMap<number, BandCap>;
46
+ /** Span blocks inserted in the band their cap was applied to. */
47
+ spanPlacedInBand: ReadonlySet<number>;
48
+ /** Caps whose opening block did open a band in this pass. */
49
+ bandCapsApplied: ReadonlySet<number>;
50
+ }
51
+ /** Shorten every column of a (still empty) band to `capPx`, remembering
52
+ * each column's true bottom in `uncappedBottoms` so the band can be
53
+ * restored (`uncapBand`) when the span block cuts it. Idempotent; a column
54
+ * already shorter than the cap (bottom float) is left alone. A column that
55
+ * already holds content keeps its used height — the cap then only trims
56
+ * what is left. */
57
+ export declare function applyBandCap(cols: readonly VDTColumn[], capPx: number, uncappedBottoms: Map<VDTColumn, number>): void;
58
+ /** Give capped columns their true bottom back (the slack below the cap
59
+ * returns to `availableHeight`). */
60
+ export declare function uncapBand(cols: readonly VDTColumn[], uncappedBottoms: Map<VDTColumn, number>): void;
61
+ /** True bottom of a column — the remembered one while it is capped. */
62
+ export declare function columnBottom(col: VDTColumn, uncappedBottoms: ReadonlyMap<VDTColumn, number>): number;
63
+ /** Grid lines a level cut of the band would need: the content spread over
64
+ * the band's columns evenly, rounded up to whole lines. */
65
+ export declare function bandCapLines(cols: readonly VDTColumn[], gridPx: number): number;
66
+ /**
67
+ * Drive the band-cap passes. `initial` is the plain first pass; `runPass`
68
+ * re-places the document with the given caps. Returns the layout to carry
69
+ * into column balancing, the caps it was built with, and the number of
70
+ * passes run (including the initial one).
71
+ *
72
+ * Each round first settles the caps of the previous pass — a cap whose
73
+ * block was not inserted in its band is retried one line taller (while it
74
+ * did apply and `retries` allows), otherwise dropped — then adopts the new
75
+ * proposals (never one already tried). Rounds stop when nothing changes or
76
+ * `MAX_BAND_PASSES` extra passes were run. The layout returned never carries
77
+ * an undelivered cap: failing caps are removed and, when none survive, the
78
+ * initial pass is returned untouched — a document whose span blocks all
79
+ * fit stage 1 costs no extra pass at all.
80
+ */
81
+ export declare function resolveBandCaps<T extends BandPassReport>(initial: T, runPass: (bandCaps: ReadonlyMap<number, BandCap>) => T): {
82
+ result: T;
83
+ bandCaps: Map<number, BandCap>;
84
+ passCount: number;
85
+ };
86
+ //# sourceMappingURL=bandCaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bandCaps.d.ts","sourceRoot":"","sources":["../../src/pipeline/bandCaps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC;;uEAEuE;AACvE,MAAM,WAAW,OAAO;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;qEACiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;qDACqD;AACrD,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,iEAAiE;IACjE,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,6DAA6D;IAC7D,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;;;oBAKoB;AACpB,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,GACtC,IAAI,CAQN;AAED;qCACqC;AACrC,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,SAAS,EAAE,EAC1B,eAAe,EAAE,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,GACtC,IAAI,CASN;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,MAAM,CAEpG;AAED;4DAC4D;AAC5D,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAI/E;AAKD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,cAAc,EACtD,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,GACrD;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAiDlE"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Band caps — page-span blocks, stage 2 (mid-page bands).
3
+ *
4
+ * Stage 1 (`placement.ts`) only inserts a page-span block where the current
5
+ * column band is *level*; a block arriving with the columns uneven moves to
6
+ * the top of the next page. Stage 2 lets it land mid-page the way a
7
+ * compositor would set it: the text above the box is cut level across all
8
+ * columns, the box spans the page, and the columns resume below it.
9
+ *
10
+ * Rather than redistributing already-placed blocks in place (which would
11
+ * bypass orphan / widow / keep-with-next), the engine re-runs the placement
12
+ * pass with a **band cap**: the columns of the band that opens with a given
13
+ * content block are shortened to `lines` grid lines, so they fill and
14
+ * overflow into each other naturally — every placement rule keeps applying
15
+ * — and end level at `bandTop + lines·grid`, where the span block then cuts
16
+ * the band. A cap is proposed by the pass that saw the block arrive in an
17
+ * uneven band with room below (`lines = ceil(Σ used px / N / grid)`), and
18
+ * consumed by the next pass. When the capped band overflows differently
19
+ * (e.g. keep-with-next moved a heading and the text no longer fits above
20
+ * the cut), the cap is retried one line taller a bounded number of times,
21
+ * then dropped — the block falls back to stage 1.
22
+ */
23
+ /** Maximum number of extra placement passes the band-cap driver may run on
24
+ * top of the initial pass (proposals + retries). */
25
+ export const MAX_BAND_PASSES = 4;
26
+ /** Maximum number of `lines + 1` retries for a cap whose band overflowed. */
27
+ export const MAX_BAND_CAP_RETRIES = 3;
28
+ /** Shorten every column of a (still empty) band to `capPx`, remembering
29
+ * each column's true bottom in `uncappedBottoms` so the band can be
30
+ * restored (`uncapBand`) when the span block cuts it. Idempotent; a column
31
+ * already shorter than the cap (bottom float) is left alone. A column that
32
+ * already holds content keeps its used height — the cap then only trims
33
+ * what is left. */
34
+ export function applyBandCap(cols, capPx, uncappedBottoms) {
35
+ for (const c of cols) {
36
+ if (c.bbox.height <= capPx + 0.01)
37
+ continue;
38
+ if (!uncappedBottoms.has(c))
39
+ uncappedBottoms.set(c, c.bbox.y + c.bbox.height);
40
+ const trimmed = c.bbox.height - capPx;
41
+ c.bbox.height = capPx;
42
+ c.availableHeight = Math.max(0, c.availableHeight - trimmed);
43
+ }
44
+ }
45
+ /** Give capped columns their true bottom back (the slack below the cap
46
+ * returns to `availableHeight`). */
47
+ export function uncapBand(cols, uncappedBottoms) {
48
+ for (const c of cols) {
49
+ const bottom = uncappedBottoms.get(c);
50
+ if (bottom === undefined)
51
+ continue;
52
+ const height = bottom - c.bbox.y;
53
+ c.availableHeight += height - c.bbox.height;
54
+ c.bbox.height = height;
55
+ uncappedBottoms.delete(c);
56
+ }
57
+ }
58
+ /** True bottom of a column — the remembered one while it is capped. */
59
+ export function columnBottom(col, uncappedBottoms) {
60
+ return uncappedBottoms.get(col) ?? col.bbox.y + col.bbox.height;
61
+ }
62
+ /** Grid lines a level cut of the band would need: the content spread over
63
+ * the band's columns evenly, rounded up to whole lines. */
64
+ export function bandCapLines(cols, gridPx) {
65
+ let total = 0;
66
+ for (const c of cols)
67
+ total += c.bbox.height - c.availableHeight;
68
+ return Math.max(1, Math.ceil((total / cols.length - 0.01) / gridPx));
69
+ }
70
+ const capKey = (spanIndex, cap) => `${spanIndex}:${cap.startContentIndex}:${cap.startPart}:${cap.lines}`;
71
+ /**
72
+ * Drive the band-cap passes. `initial` is the plain first pass; `runPass`
73
+ * re-places the document with the given caps. Returns the layout to carry
74
+ * into column balancing, the caps it was built with, and the number of
75
+ * passes run (including the initial one).
76
+ *
77
+ * Each round first settles the caps of the previous pass — a cap whose
78
+ * block was not inserted in its band is retried one line taller (while it
79
+ * did apply and `retries` allows), otherwise dropped — then adopts the new
80
+ * proposals (never one already tried). Rounds stop when nothing changes or
81
+ * `MAX_BAND_PASSES` extra passes were run. The layout returned never carries
82
+ * an undelivered cap: failing caps are removed and, when none survive, the
83
+ * initial pass is returned untouched — a document whose span blocks all
84
+ * fit stage 1 costs no extra pass at all.
85
+ */
86
+ export function resolveBandCaps(initial, runPass) {
87
+ const caps = new Map();
88
+ let result = initial;
89
+ let passCount = 1;
90
+ if (initial.bandCapProposals.size === 0)
91
+ return { result, bandCaps: caps, passCount };
92
+ const tried = new Set();
93
+ for (let extra = 0; extra < MAX_BAND_PASSES; extra++) {
94
+ let changed = false;
95
+ for (const [spanIndex, cap] of [...caps]) {
96
+ if (result.spanPlacedInBand.has(spanIndex))
97
+ continue;
98
+ changed = true;
99
+ if (result.bandCapsApplied.has(spanIndex) && cap.retries < MAX_BAND_CAP_RETRIES) {
100
+ caps.set(spanIndex, { ...cap, lines: cap.lines + 1, retries: cap.retries + 1 });
101
+ }
102
+ else {
103
+ caps.delete(spanIndex);
104
+ }
105
+ }
106
+ for (const [spanIndex, cap] of result.bandCapProposals) {
107
+ if (caps.has(spanIndex) || tried.has(capKey(spanIndex, cap)))
108
+ continue;
109
+ caps.set(spanIndex, { ...cap });
110
+ changed = true;
111
+ }
112
+ if (!changed)
113
+ break;
114
+ if (caps.size === 0) {
115
+ // Every cap was dropped and nothing new came up: the plain layout.
116
+ result = initial;
117
+ break;
118
+ }
119
+ for (const [spanIndex, cap] of caps)
120
+ tried.add(capKey(spanIndex, cap));
121
+ result = runPass(caps);
122
+ passCount++;
123
+ }
124
+ // Never hand back a layout whose columns were capped for a box that did
125
+ // not arrive: strip the failing caps (dropping an earlier cap can unsettle
126
+ // a later one, hence the loop — each round removes at least one).
127
+ while (caps.size > 0) {
128
+ const failing = [...caps.keys()].filter((i) => !result.spanPlacedInBand.has(i));
129
+ if (failing.length === 0)
130
+ break;
131
+ for (const i of failing)
132
+ caps.delete(i);
133
+ if (caps.size === 0) {
134
+ result = initial;
135
+ break;
136
+ }
137
+ result = runPass(caps);
138
+ passCount++;
139
+ }
140
+ return { result, bandCaps: caps, passCount };
141
+ }
142
+ //# sourceMappingURL=bandCaps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bandCaps.js","sourceRoot":"","sources":["../../src/pipeline/bandCaps.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import type { PostextContent, PostextConfig } from '../types';
2
2
  import { type VDTDocument } from '../vdt';
3
3
  import type { MeasurementCache } from '../measure';
4
+ import { type LooseBudget } from './columnBalancing';
5
+ import { type BandCap, type BandPassReport } from './bandCaps';
4
6
  export interface BuildDocumentOptions {
5
7
  /**
6
8
  * Cooperative cancellation hook. Called once per top-level content block
@@ -13,5 +15,44 @@ export interface BuildDocumentOptions {
13
15
  export declare class BuildCancelledError extends Error {
14
16
  constructor();
15
17
  }
18
+ /** Cross-pass hints a placement pass consumes. All keyed by content-block
19
+ * index; every map is optional so the plain first pass carries none. */
20
+ export interface PassHints {
21
+ /** Column balancing: extra top spacing (px) per heading / list-end target. */
22
+ balanceExtraPx?: ReadonlyMap<number, number>;
23
+ /** Column balancing: K-P looseness per paragraph re-broken one line longer. */
24
+ balanceLooseness?: ReadonlyMap<number, number>;
25
+ /** Column balancing: shared budget of the loose candidates offered together
26
+ * (the pass stops loosening a column once it gained what it needs). */
27
+ balanceLooseBudget?: ReadonlyMap<number, LooseBudget>;
28
+ /** Band caps keyed by the span block's content index (see `bandCaps.ts`). */
29
+ bandCaps?: ReadonlyMap<number, BandCap>;
30
+ }
31
+ export interface PassResult extends BandPassReport {
32
+ doc: VDTDocument;
33
+ /** Pages whose break into the next page was explicit (`:::pagebreak`,
34
+ * heading `breakBefore`, chapter opener) rather than natural content
35
+ * overflow — those pages keep their short last column. */
36
+ forcedBreakPages: Set<number>;
37
+ bandCapProposals: Map<number, BandCap>;
38
+ spanPlacedInBand: Set<number>;
39
+ bandCapsApplied: Set<number>;
40
+ /** Column balancing: per loose paragraph tried in this pass, the tracking
41
+ * (thousandths of an em) that gained its extra line — `null` when no rung
42
+ * of the ladder did, so the driver can blacklist it. Candidates left
43
+ * untried because their column's budget was already met are absent. */
44
+ looseOutcome: Map<number, number | null>;
45
+ }
46
+ /**
47
+ * Single placement pass. `hints` carries the cross-pass adjustments: the
48
+ * column-balancing spacing / looseness and the band caps of page-span
49
+ * blocks. Besides the document it reports `forcedBreakPages` (for
50
+ * balancing) and the band-cap bookkeeping the driver in `buildDocument`
51
+ * needs — new cap proposals, the span blocks that landed in their capped
52
+ * band, and the caps that were actually applied.
53
+ *
54
+ * @internal Exposed for tests only; use `buildDocument`.
55
+ */
56
+ export declare function buildDocumentPass(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions, hints?: PassHints): PassResult;
16
57
  export declare function buildDocument(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions): VDTDocument;
17
58
  //# sourceMappingURL=build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/pipeline/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAA0B,MAAM,UAAU,CAAC;AAGtF,OAAO,EAIL,KAAK,WAAW,EAIjB,MAAM,QAAQ,CAAC;AAWhB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAkDnD,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAK7C;AAmjCD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,WAAW,CA8Db"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/pipeline/build.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAA8C,MAAM,UAAU,CAAC;AAG1G,OAAO,EAIL,KAAK,WAAW,EAKjB,MAAM,QAAQ,CAAC;AAWhB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2DnD,OAAO,EAGL,KAAK,WAAW,EAGjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;;CAK7C;AAWD;yEACyE;AACzE,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C;4EACwE;IACxE,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACtD,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,GAAG,EAAE,WAAW,CAAC;IACjB;;+DAE2D;IAC3D,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B;;;4EAGwE;IACxE,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CAC1C;AAuCD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,oBAAoB,EAC9B,KAAK,GAAE,SAAc,GACpB,UAAU,CAu9CZ;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,cAAc,EACvB,MAAM,CAAC,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,WAAW,CA6Fb"}