superdoc 2.4.0-next.9 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +12 -90
  2. package/dist/chunks/{FindReplaceSurface-9VkPw_-X.cjs → FindReplaceSurface-0p7EtMZh.cjs} +4 -3
  3. package/dist/chunks/{FindReplaceSurface-BuvaIrQ5.es.js → FindReplaceSurface-40AnrqWk.es.js} +4 -2
  4. package/dist/chunks/{PasswordPromptSurface-Bu5xHm91.cjs → PasswordPromptSurface-31lYPcCK.cjs} +4 -3
  5. package/dist/chunks/{PasswordPromptSurface-Bz9_sKhX.es.js → PasswordPromptSurface-CwYeO3iQ.es.js} +4 -2
  6. package/dist/chunks/{PdfViewer-CdVGB6Fe.es.js → PdfViewer-D8h7LRZy.es.js} +103 -19
  7. package/dist/chunks/{PdfViewer-D4eD2dV1.cjs → PdfViewer-Dug6yDRC.cjs} +105 -20
  8. package/dist/chunks/_plugin-vue_export-helper-BOaGB7Aw.es.js +8 -0
  9. package/dist/chunks/_plugin-vue_export-helper-SDR04tiH.cjs +13 -0
  10. package/dist/chunks/{blank-docx-DP8RUPW-.cjs → blank-docx-BuFAbRjs.cjs} +2 -0
  11. package/dist/chunks/{blank-docx-XRX6Ker2.es.js → blank-docx-DzQccOlW.es.js} +2 -0
  12. package/dist/chunks/constants-B6VBlmKp.es.js +4 -0
  13. package/dist/chunks/constants-DpXuDx_g.cjs +9 -0
  14. package/dist/chunks/{create-super-doc-ui-ByvmsAAG.cjs → create-super-doc-ui-Bom7oDPv.cjs} +2027 -1158
  15. package/dist/chunks/{create-super-doc-ui-DBXOhHdW.es.js → create-super-doc-ui-DbzVC0rr.es.js} +2216 -1107
  16. package/dist/chunks/{eventemitter3-Bt2s0X0a.es.js → eventemitter3-CMOjDs74.es.js} +124 -16
  17. package/dist/chunks/{eventemitter3-DqY4aSMf.cjs → eventemitter3-D38u8ta_.cjs} +125 -16
  18. package/dist/chunks/jszip-RC64TPzL.cjs +4758 -0
  19. package/dist/chunks/jszip-VxCFV9YS.es.js +4717 -0
  20. package/dist/chunks/{rolldown-runtime-D7PMmH3s.es.js → rolldown-runtime-B5TtN50X.es.js} +13 -4
  21. package/dist/chunks/{rolldown-runtime-1Y-nnZJ3.cjs → rolldown-runtime-DtsSbkrh.cjs} +12 -3
  22. package/dist/chunks/{uuid-CFp0WGVU.cjs → uuid-BhG0ngwk.cjs} +10 -6
  23. package/dist/chunks/{uuid-B2Sqk-3p.es.js → uuid-H0Xcmmhy.es.js} +8 -3
  24. package/dist/collaboration-upgrade-engine.cjs +34 -9
  25. package/dist/collaboration-upgrade-engine.es.js +30 -5
  26. package/dist/document-api/src/citations/citations.types.d.ts +9 -0
  27. package/dist/document-api/src/comments/comments.types.d.ts +7 -0
  28. package/dist/document-api/src/types/receipt.d.ts +9 -5
  29. package/dist/document-api/src/types/track-changes.types.d.ts +17 -0
  30. package/dist/layout-engine/contracts/src/graphic-placement.d.ts +35 -6
  31. package/dist/layout-engine/contracts/src/incremental-dependency.d.ts +22 -2
  32. package/dist/layout-engine/contracts/src/index.d.ts +370 -15
  33. package/dist/layout-engine/contracts/src/inline-box.d.ts +19 -0
  34. package/dist/layout-engine/contracts/src/paragraph-visible-text.d.ts +19 -0
  35. package/dist/layout-engine/contracts/src/resolved-layout.d.ts +5 -0
  36. package/dist/layout-engine/dom-contract/src/class-names.d.ts +2 -0
  37. package/dist/layout-engine/layout-bridge/src/footnote-scorer.d.ts +1 -1
  38. package/dist/layout-engine/layout-bridge/src/hydrateTableTextboxMeasures.d.ts +9 -0
  39. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +42 -11
  40. package/dist/layout-engine/layout-bridge/src/index.d.ts +4 -2
  41. package/dist/layout-engine/layout-bridge/src/inline-box-key.d.ts +3 -0
  42. package/dist/layout-engine/layout-bridge/src/layoutHeaderFooter.d.ts +11 -4
  43. package/dist/layout-engine/layout-bridge/src/remeasure.d.ts +2 -2
  44. package/dist/layout-engine/layout-bridge/src/run-visual-marks.d.ts +2 -0
  45. package/dist/layout-engine/layout-bridge/src/text-measurement.d.ts +0 -12
  46. package/dist/layout-engine/layout-engine/src/anchors.d.ts +4 -0
  47. package/dist/layout-engine/layout-engine/src/execution.d.ts +21 -0
  48. package/dist/layout-engine/layout-engine/src/floating-objects.d.ts +15 -2
  49. package/dist/layout-engine/layout-engine/src/floating-table-anchor.d.ts +2 -0
  50. package/dist/layout-engine/layout-engine/src/footnote-anchor-index.d.ts +17 -0
  51. package/dist/layout-engine/layout-engine/src/index.d.ts +13 -10
  52. package/dist/layout-engine/layout-engine/src/inline-drawing-alignment.d.ts +9 -0
  53. package/dist/layout-engine/layout-engine/src/layout-drawing.d.ts +3 -3
  54. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +2 -2
  55. package/dist/layout-engine/layout-engine/src/layout-textbox.d.ts +3 -3
  56. package/dist/layout-engine/layout-engine/src/pageNumbering.d.ts +3 -41
  57. package/dist/layout-engine/layout-engine/src/paginator.d.ts +7 -2
  58. package/dist/layout-engine/layout-engine/src/resolvePageTokens.d.ts +2 -0
  59. package/dist/layout-engine/layout-engine/src/section-breaks.d.ts +1 -0
  60. package/dist/layout-engine/layout-engine/src/section-props.d.ts +5 -0
  61. package/dist/layout-engine/painters/dom/src/chart-renderer.d.ts +3 -3
  62. package/dist/layout-engine/painters/dom/src/images/image-outline.d.ts +7 -0
  63. package/dist/layout-engine/painters/dom/src/images/render-placeholder.d.ts +12 -0
  64. package/dist/layout-engine/painters/dom/src/renderer.d.ts +54 -0
  65. package/dist/layout-engine/painters/dom/src/runs/inline-box.d.ts +8 -0
  66. package/dist/layout-engine/painters/dom/src/runs/text-effects.d.ts +30 -0
  67. package/dist/layout-engine/painters/dom/src/runs/text-run.d.ts +6 -4
  68. package/dist/layout-engine/painters/dom/src/shapes/preset-text-warp-data.d.ts +32 -0
  69. package/dist/layout-engine/painters/dom/src/shapes/wordart-warp.d.ts +39 -0
  70. package/dist/layout-engine/painters/dom/src/table/border-utils.d.ts +20 -27
  71. package/dist/layout-engine/painters/dom/src/table/renderTableFragment.d.ts +1 -1
  72. package/dist/layout-engine/style-engine/src/ooxml/word-style-model/parse-theme.d.ts +7 -0
  73. package/dist/public/ui-react.cjs +66 -2
  74. package/dist/public/ui-react.es.js +66 -1
  75. package/dist/public/ui.cjs +1 -1
  76. package/dist/public/ui.es.js +1 -1
  77. package/dist/style.css +134 -98
  78. package/dist/style.layered.css +134 -98
  79. package/dist/superdoc/src/components/CommentsLayer/CommentDialog.vue.d.ts +2 -0
  80. package/dist/superdoc/src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue.d.ts +16 -0
  81. package/dist/superdoc/src/components/CommentsLayer/commentsList/commentsList.vue.d.ts +3 -1
  82. package/dist/superdoc/src/components/CommentsLayer/commentsList/super-comments-list.d.ts +12 -0
  83. package/dist/superdoc/src/core/SuperDoc.d.ts +10 -7
  84. package/dist/superdoc/src/core/config/normalize-ui-config.d.ts +5 -0
  85. package/dist/superdoc/src/core/extensions/index.d.ts +1 -1
  86. package/dist/superdoc/src/core/extensions/types.d.ts +63 -5
  87. package/dist/superdoc/src/core/types/index.d.ts +423 -37
  88. package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +3 -3
  89. package/dist/superdoc/src/helpers/comment-small-screen.d.ts +10 -0
  90. package/dist/superdoc/src/helpers/v2-review-mutation-impact.d.ts +3 -5
  91. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButton.vue.d.ts +4 -4
  92. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +11 -0
  93. package/dist/superdoc/src/internal/toolbar/compatibility-catalog.d.ts +1 -1
  94. package/dist/superdoc/src/public/index.d.cts +20 -0
  95. package/dist/superdoc/src/public/index.d.ts +10 -0
  96. package/dist/superdoc/src/public/ui/types.d.ts +5 -5
  97. package/dist/superdoc/src/stores/comments-store.d.ts +81 -78
  98. package/dist/superdoc/src/stores/superdoc-store.d.ts +243 -234
  99. package/dist/superdoc.cjs +6748 -2162
  100. package/dist/superdoc.es.js +6621 -2035
  101. package/dist-cdn/style.layered.css +1 -1
  102. package/dist-cdn/superdoc.min.css +1 -1
  103. package/dist-cdn/superdoc.min.js +37 -37
  104. package/package.json +14 -18
  105. package/AGENTS.md +0 -337
  106. package/dist/chunks/_plugin-vue_export-helper-CZ1Nl59K.cjs +0 -11
  107. package/dist/chunks/_plugin-vue_export-helper-DSMAhhwD.es.js +0 -6
  108. package/dist/chunks/constants-BfH0br5u.es.js +0 -3
  109. package/dist/chunks/constants-D7TNtyJd.cjs +0 -14
  110. package/dist/chunks/jszip-C8srOKAO.es.js +0 -4650
  111. package/dist/chunks/jszip-Cs9JBLlJ.cjs +0 -4691
  112. package/dist/superdoc/src/helpers/v2-remote-review-hydration.d.ts +0 -12
  113. package/dist/superdoc/src/helpers/v2-review-mutation-reconciler.d.ts +0 -19
@@ -476,6 +476,11 @@ export declare function isResolvedDrawingItem(item: ResolvedPaintItem): item is
476
476
  /** A resolved header/footer page — mirrors HeaderFooterPage but with resolved items. */
477
477
  export type ResolvedHeaderFooterPage = {
478
478
  number: number;
479
+ /** Page-local measurement height; see `HeaderFooterPage.measurementHeight`. */
480
+ measurementHeight?: number;
481
+ minY?: number;
482
+ maxY?: number;
483
+ renderHeight?: number;
479
484
  numberText?: string;
480
485
  /** Section-aware numeric page value before formatting. */
481
486
  displayNumber?: number;
@@ -12,6 +12,8 @@ export declare const DOM_CLASS_NAMES: {
12
12
  readonly PAGE: "superdoc-page";
13
13
  /** Fragment container (paragraph, table, image block, etc.). */
14
14
  readonly FRAGMENT: "superdoc-fragment";
15
+ /** Non-flowing fragment whose visual position must not define body flow geometry. */
16
+ readonly FLOATING_FRAGMENT: "superdoc-floating-fragment";
15
17
  /** Line container within a fragment. */
16
18
  readonly LINE: "superdoc-line";
17
19
  /**
@@ -42,7 +42,7 @@ export type FootnoteWindowScoreResult = {
42
42
  };
43
43
  export declare const isMandatoryOnlyFootnotePage: (ledger: FootnotePageLedger, preferredDeltaThresholdPx?: number, mandatoryOnlyTolerancePx?: number) => boolean;
44
44
  /**
45
- * SD-2656 (post-Vivienne-feedback): a page whose LAST anchor partially rendered
45
+ * SD-2656: a page whose LAST anchor partially rendered
46
46
  * but spilled to a later page. The user-visible bug is a footnote split across
47
47
  * pages even when the preferred reserve would fit the whole anchor on the
48
48
  * anchor page (Word does keep it together).
@@ -0,0 +1,9 @@
1
+ import { FlowBlock, ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
2
+ type TextboxRemeasure = (block: ParagraphBlock, maxWidth: number) => ParagraphMeasure;
3
+ /**
4
+ * Derives table-cell textbox measurements without mutating the projection
5
+ * plane supplied by the caller. Only the textbox and its table ancestry are
6
+ * copied; documents without table textboxes retain their original identities.
7
+ */
8
+ export declare function hydrateTableTextboxMeasures(blocks: FlowBlock[], remeasure: TextboxRemeasure): FlowBlock[];
9
+ export {};
@@ -1,6 +1,6 @@
1
- import { PageCheckpointDependencyClass, FlowBlock, Layout, Measure, HeaderFooterLayout, ParagraphBlock, ParagraphMeasure, ColumnLayout } from '../../contracts/src/index.js';
1
+ import { NonFlowingPageRelativeAnchorDependencyProof, PageCheckpointDependencyClass, FlowBlock, Layout, Measure, HeaderFooterLayout, ColumnLayout } from '../../contracts/src/index.js';
2
2
  import { FontMeasureContext } from '../../../shared/font-system/src/index.js';
3
- import { LayoutOptions, HeaderFooterConstraints } from '../../layout-engine/src/index.js';
3
+ import { LayoutOptions, HeaderFooterConstraints, LayoutExecutionCheckpoint } from '../../layout-engine/src/index.js';
4
4
  import { computeDirtyRegions } from './diff.js';
5
5
  import { MeasureCache } from './cache.js';
6
6
  import { HeaderFooterBatch } from './layoutHeaderFooter.js';
@@ -52,6 +52,8 @@ export type FootnoteReserveSeed = {
52
52
  };
53
53
  export type IncrementalLayoutResult = {
54
54
  layout: Layout;
55
+ /** Pass-owned block plane after derived layout annotations are attached. */
56
+ blocks: FlowBlock[];
55
57
  measures: Measure[];
56
58
  dirty: ReturnType<typeof computeDirtyRegions>;
57
59
  headers?: HeaderFooterLayoutResult[];
@@ -68,9 +70,11 @@ export type IncrementalLayoutResult = {
68
70
  * out no footnotes) — the next run then starts cold.
69
71
  */
70
72
  footnoteReserveSeed?: FootnoteReserveSeed | null;
73
+ /** Canonical pre-layout furniture heights that can affect body margins. */
74
+ headerFooterGeometryFingerprint: string;
71
75
  layoutReuse?: IncrementalLayoutReuseSummary;
72
76
  measureReuse?: {
73
- mode: 'full-scan' | 'proved-dirty-only';
77
+ mode: 'full-scan' | 'proved-dirty-only' | 'body-stable';
74
78
  blocksMeasured: number;
75
79
  measuresAdopted: number;
76
80
  reason: string;
@@ -117,6 +121,16 @@ export type IncrementalLayoutBridgeTiming = {
117
121
  measuresAdopted: number;
118
122
  pagesPaginated: number | null;
119
123
  pagesSplicedByReuse: number;
124
+ paginationPasses: number;
125
+ pageTokenRelayouts: number;
126
+ footnoteRelayouts: number;
127
+ footnoteReserveRelayouts: number;
128
+ footnoteGrowRelayouts: number;
129
+ footnoteTightenRelayouts: number;
130
+ footnotePreferredRelayouts: number;
131
+ footnoteWidowRelayouts: number;
132
+ footnoteRevertRelayouts: number;
133
+ footnoteOtherRelayouts: number;
120
134
  };
121
135
  };
122
136
  /**
@@ -168,6 +182,13 @@ export type IncrementalSectionPageNumberTransform = {
168
182
  /** Difference between target and source section-relative page positions. */
169
183
  delta: number;
170
184
  };
185
+ export type IncrementalDisplayPageNumberTransform = {
186
+ /** First section whose retained display-page values inherit the local page delta. */
187
+ startSectionIndex: number;
188
+ /** First later section with an explicit numbering restart. */
189
+ endSectionIndexExclusive: number;
190
+ delta: number;
191
+ };
171
192
  export type IncrementalLayoutTailAdoption = {
172
193
  startPageIndex: number;
173
194
  endPageIndexExclusive: number;
@@ -175,6 +196,9 @@ export type IncrementalLayoutTailAdoption = {
175
196
  sourcePageEndIndexExclusive: number;
176
197
  pageIndexDelta: number;
177
198
  sectionPageNumberTransform: IncrementalSectionPageNumberTransform | null;
199
+ displayPageNumberTransform?: IncrementalDisplayPageNumberTransform | null;
200
+ /** Exact proof that PAGEREF page/numbering locations are unchanged in the adopted tail. */
201
+ pageReferenceLocationsStable: boolean;
178
202
  sourceLayoutEpoch: number | null;
179
203
  positionTransforms: readonly LayoutPositionTransform[];
180
204
  /** Lazy old->current block-id rekeys for an ordinal-changing structural splice. */
@@ -207,6 +231,7 @@ export type IncrementalPaginationProof = IncrementalPaginationProofBase & ({
207
231
  globalDependenciesAbsent: false;
208
232
  globalDependenciesFencedByPageCheckpoint: true;
209
233
  admittedDependencyClasses: readonly PageCheckpointDependencyClass[];
234
+ nonFlowingPageRelativeAnchorDependency?: NonFlowingPageRelativeAnchorDependencyProof;
210
235
  localKeepDependencyClosure?: {
211
236
  checkpointPageIndex: number;
212
237
  checkpointBlockId: string | null;
@@ -265,6 +290,15 @@ export type IncrementalLayoutReuseOptions = {
265
290
  noteIds: readonly string[];
266
291
  bodyReferenceBlockIds: readonly string[];
267
292
  };
293
+ /**
294
+ * Host-proved header/footer-only refresh. The bridge still compares the
295
+ * current pre-layout height fingerprint before retaining body pagination.
296
+ */
297
+ provedHeaderFooterOnlyRefresh?: {
298
+ bodyProjectionRetainedExact: true;
299
+ bodyLayoutInputsUnchanged: true;
300
+ previousGeometryFingerprint: string;
301
+ };
268
302
  };
269
303
  export declare const measureCache: MeasureCache<Measure>;
270
304
  /**
@@ -276,10 +310,13 @@ export declare const measureCache: MeasureCache<Measure>;
276
310
  */
277
311
  export declare function clearIncrementalModuleState(): void;
278
312
  export interface IncrementalLayoutExecutionControl {
313
+ signal?: AbortSignal;
279
314
  /** Budget-aware host-task yield; may resolve immediately. */
280
- yieldToHost?: () => Promise<void>;
281
- /** Checkpoint cadence for the block measurement loop. Defaults to 32. */
315
+ yieldToHost?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void>;
316
+ /** Measurement checkpoints default to 32 blocks; nested layout checkpoints default to 16. */
282
317
  yieldEveryBlocks?: number;
318
+ /** Time-aware mounted probe. Null is the allocation-free under-budget path. */
319
+ checkpointIfDue?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void> | null;
283
320
  }
284
321
  export declare function incrementalLayout(previousBlocks: FlowBlock[], _previousLayout: Layout | null, nextBlocks: FlowBlock[], options: LayoutOptions, measureBlock: (block: FlowBlock, constraints: {
285
322
  maxWidth: number;
@@ -325,12 +362,6 @@ export declare function incrementalLayout(previousBlocks: FlowBlock[], _previous
325
362
  * @returns The normalized margin value (guaranteed to be finite)
326
363
  */
327
364
  export declare const normalizeMargin: (value: number | undefined, fallback: number) => number;
328
- /**
329
- * Walks table blocks (including nested tables) and computes `contentMeasures` for any
330
- * `textboxShape` drawings found in table cells. Stores results directly on the block so
331
- * the painter can read them without a `DrawingFragment` (table-cell drawings have none).
332
- */
333
- export declare function hydrateTableTextboxMeasures(blocks: FlowBlock[], remeasure: (block: ParagraphBlock, maxWidth: number) => ParagraphMeasure): void;
334
365
  /**
335
366
  * Resolves the maximum measurement constraints (width and height) needed for measuring blocks
336
367
  * across all sections in a document.
@@ -11,8 +11,10 @@ export { findWordBoundaries, findParagraphBoundaries } from './text-boundaries.j
11
11
  export type { BoundaryRange } from './text-boundaries.js';
12
12
  export { buildSectionAwareHeaderFooterLayoutKey, buildSectionContentWidth, buildEffectiveHeaderFooterRefsBySection, collectReferencedHeaderFooterRIds, buildSectionAwareHeaderFooterMeasurementGroups, } from './sectionAwareHeaderFooter.js';
13
13
  export type { HeaderFooterSectionKind, HeaderFooterRefs, SectionAwareHeaderFooterMeasurementGroup, } from './sectionAwareHeaderFooter.js';
14
- export { clearIncrementalModuleState, incrementalLayout, measureCache, normalizeMargin, hydrateTableTextboxMeasures, } from './incrementalLayout.js';
15
- export type { HeaderFooterLayoutResult, IncrementalLayoutBridgeTiming, IncrementalLayoutResult, IncrementalMeasureReuseProof, IncrementalLayoutReuseOptions, IncrementalLayoutReuseSummary, IncrementalSectionPageNumberTransform, IncrementalLayoutTailAdoption, IncrementalLayoutTailDisposition, IncrementalPaginationProof, LayoutPositionTransform, FootnoteReserveSeed, } from './incrementalLayout.js';
14
+ export { clearIncrementalModuleState, incrementalLayout, measureCache, normalizeMargin } from './incrementalLayout.js';
15
+ export { hydrateTableTextboxMeasures } from './hydrateTableTextboxMeasures.js';
16
+ export { hashMeasureContent } from './cache.js';
17
+ export type { HeaderFooterLayoutResult, IncrementalLayoutBridgeTiming, IncrementalLayoutResult, IncrementalLayoutExecutionControl, IncrementalMeasureReuseProof, IncrementalLayoutReuseOptions, IncrementalLayoutReuseSummary, IncrementalSectionPageNumberTransform, IncrementalLayoutTailAdoption, IncrementalLayoutTailDisposition, IncrementalPaginationProof, LayoutPositionTransform, FootnoteReserveSeed, } from './incrementalLayout.js';
16
18
  export { collectFootnoteLedgers, getPreferredReserveCandidates, getPreferredReserveTrialTargets, isMandatoryOnlyFootnotePage, scoreFootnoteWindow, summarizeFootnoteWindow, } from './footnote-scorer.js';
17
19
  export type { FootnotePreferredReserveCandidate, FootnoteWindowScoreInput, FootnoteWindowScoreReason, FootnoteWindowScoreResult, FootnoteWindowStats, } from './footnote-scorer.js';
18
20
  export { computeDisplayPageNumber } from '../../layout-engine/src/index.js';
@@ -0,0 +1,3 @@
1
+ import { InlineBoxSpan } from '../../contracts/src/index.js';
2
+ /** Shared inline-box identity for measure-cache and dirty-region decisions. */
3
+ export declare const inlineBoxKey: (box: InlineBoxSpan) => string;
@@ -1,5 +1,5 @@
1
- import { FlowBlock, HeaderFooterLayout, Measure, PageNumberChapterSeparator, PageNumberFormat, ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
2
- import { HeaderFooterConstraints } from '../../layout-engine/src/index.js';
1
+ import { FlowBlock, HeaderFooterLayout, Measure, PageNumberChapterSeparator, PageNumberFormat, ParagraphBlock, ParagraphLineRegion, ParagraphMeasure } from '../../contracts/src/index.js';
2
+ import { HeaderFooterConstraints, LayoutExecutionCheckpoint, LayoutExecutionControl } from '../../layout-engine/src/index.js';
3
3
  import { MeasureCache } from './cache.js';
4
4
  import { ResolveHeaderFooterTokensOptions } from './resolveHeaderFooterTokens.js';
5
5
  export type HeaderFooterBatch = Partial<Record<'default' | 'first' | 'even' | 'odd', FlowBlock[]>>;
@@ -28,6 +28,13 @@ export type PageResolver = (pageNumber: number) => {
28
28
  chapterNumberText?: string;
29
29
  chapterSeparator?: PageNumberChapterSeparator;
30
30
  };
31
+ /** Optional cooperative execution hooks for browser-owned furniture builds. */
32
+ export interface HeaderFooterLayoutExecution extends LayoutExecutionControl {
33
+ /** Time-aware mounted probe. Null is the allocation-free under-budget path. */
34
+ checkpointIfDue?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void> | null;
35
+ /** Exact physical pages whose PAGE contexts are missing from a retained layout entry. */
36
+ pageNumbers?: readonly number[];
37
+ }
31
38
  /**
32
39
  * Digit bucket for page number caching strategy.
33
40
  * Different digit lengths require different measurements due to width changes.
@@ -85,7 +92,7 @@ export declare class HeaderFooterLayoutCache {
85
92
  measureBlocks(blocks: FlowBlock[], constraints: {
86
93
  width: number;
87
94
  height: number;
88
- }, measureBlock: MeasureResolver, fontSignature?: string): Promise<Measure[]>;
95
+ }, measureBlock: MeasureResolver, fontSignature?: string, execution?: LayoutExecutionControl): Promise<Measure[]>;
89
96
  invalidate(blockIds: string[]): void;
90
97
  /**
91
98
  * Gets cache statistics for monitoring and debugging.
@@ -120,4 +127,4 @@ export declare function invalidateHeaderFooterMeasureCache(blockIds: string[]):
120
127
  * @param pageResolver - Callback to resolve display page info for a physical page number
121
128
  * @returns Batch result with layouts, blocks, and measures for each variant
122
129
  */
123
- export declare function layoutHeaderFooterWithCache(sections: HeaderFooterBatch, constraints: HeaderFooterConstraints, measureBlock: MeasureResolver, cache?: HeaderFooterLayoutCache, totalPages?: number, pageResolver?: PageResolver, kind?: 'header' | 'footer', fontSignature?: string, remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure, options?: ResolveHeaderFooterTokensOptions): Promise<HeaderFooterBatchResult>;
130
+ export declare function layoutHeaderFooterWithCache(sections: HeaderFooterBatch, constraints: HeaderFooterConstraints, measureBlock: MeasureResolver, cache?: HeaderFooterLayoutCache, totalPages?: number, pageResolver?: PageResolver, kind?: 'header' | 'footer', fontSignature?: string, remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure, options?: ResolveHeaderFooterTokensOptions, execution?: HeaderFooterLayoutExecution): Promise<HeaderFooterBatchResult>;
@@ -1,4 +1,4 @@
1
- import { ParagraphBlock, ParagraphMeasure } from '../../contracts/src/index.js';
1
+ import { ParagraphBlock, ParagraphMeasure, ParagraphLineRegion } from '../../contracts/src/index.js';
2
2
  /** Drop cached text widths and the canvas context. Call when registered font faces may have changed. */
3
3
  export declare function clearRemeasureTextCaches(): void;
4
4
  /**
@@ -72,4 +72,4 @@ export declare function clearRemeasureTextCaches(): void;
72
72
  * // First line has only 170px available (200 - 30), subsequent lines have full 200px
73
73
  * ```
74
74
  */
75
- export declare function remeasureParagraph(block: ParagraphBlock, maxWidth: number, firstLineIndent?: number): ParagraphMeasure;
75
+ export declare function remeasureParagraph(block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]): ParagraphMeasure;
@@ -5,6 +5,8 @@ import { Run } from '../../contracts/src/index.js';
5
5
  * Include every run property that affects text measurement or painted output but is not
6
6
  * covered elsewhere (e.g. tracked-change / comment keys). When adding a new visual
7
7
  * property, update this function only — `cache.ts` and `diff.ts` both depend on it.
8
+ * Paragraph-scoped inline boxes are deliberately keyed by `inline-box-key.ts`,
9
+ * not by this run-scoped helper.
8
10
  *
9
11
  * @param run - Flow run (text, tab, image, etc.); unknown fields are ignored safely.
10
12
  * @returns Stable string encoding bold/italic/underline/strike/color/font/highlight/link.
@@ -7,18 +7,6 @@ import { FontMeasureContext } from '../../../shared/font-system/src/index.js';
7
7
  * @returns CSS font string (e.g., "italic bold 16px Arial")
8
8
  */
9
9
  export declare function getRunFontString(run: Run, fontContext?: FontMeasureContext): string;
10
- /**
11
- * Measure the X position for a specific character offset within a line.
12
- * Uses Canvas measureText for pixel-perfect accuracy.
13
- *
14
- * @param block - The paragraph block containing the line
15
- * @param line - The line to measure within
16
- * @param charOffset - Character offset from the start of the line (0-based)
17
- * @param availableWidthOverride - Optional override for available width
18
- * @param alignmentOverride - Optional override for text alignment (e.g., 'left' for list items
19
- * which are always rendered left-aligned in the DOM regardless of paragraph alignment)
20
- * @returns The X coordinate (in pixels) from the start of the line
21
- */
22
10
  export declare function measureCharacterX(block: FlowBlock, line: Line, charOffset: number, availableWidthOverride?: number, alignmentOverride?: string, fontContext?: FontMeasureContext): number;
23
11
  /**
24
12
  * Convert a character offset within a line back to a ProseMirror position.
@@ -1,5 +1,6 @@
1
1
  import { FlowBlock, ImageBlock, ImageMeasure, Measure, DrawingBlock, DrawingMeasure, TableBlock, TableMeasure, isPageRelativeAnchor } from '../../contracts/src/index.js';
2
2
  import { resolveFloatingTableAnchorResolution } from './floating-table-anchor.js';
3
+ import { LayoutWorkCheckpoint } from './execution.js';
3
4
  export type { FloatingTableAnchorResolution } from './floating-table-anchor.js';
4
5
  export { resolveFloatingTableAnchorResolution };
5
6
  export { isPageRelativeAnchor };
@@ -39,14 +40,17 @@ export type AnchoredTableCollection = {
39
40
  * @param measures - Corresponding measures for each block
40
41
  * @returns Array of anchored drawings that should be pre-registered
41
42
  */
43
+ export declare function collectPreRegisteredAnchorsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredDrawing[], void>;
42
44
  export declare function collectPreRegisteredAnchors(blocks: FlowBlock[], measures: Measure[]): AnchoredDrawing[];
43
45
  /**
44
46
  * Collect anchored drawings (images/drawings) mapped to their anchor paragraph index.
45
47
  * Map of paragraph block index -> anchored images/drawings associated with that paragraph.
46
48
  */
49
+ export declare function collectAnchoredDrawingsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredDrawingCollection, void>;
47
50
  export declare function collectAnchoredDrawings(blocks: FlowBlock[], measures: Measure[]): AnchoredDrawingCollection;
48
51
  /**
49
52
  * Collect anchored/floating tables mapped to their anchor paragraph index.
50
53
  * Also returns anchored tables that have no paragraph to attach to.
51
54
  */
55
+ export declare function collectAnchoredTablesSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredTableCollection, void>;
52
56
  export declare function collectAnchoredTables(blocks: FlowBlock[], measures: Measure[]): AnchoredTableCollection;
@@ -0,0 +1,21 @@
1
+ export type LayoutExecutionPhase = 'measure:block' | 'layout-document:prepare' | 'layout-document:preflight-section' | 'layout-document:preflight-footnote' | 'layout-document:preflight-anchor' | 'layout-document:preflight-keep-next' | 'layout-document:block' | 'layout-document:finalize-page' | 'layout-document:finalize-section' | 'page-token:prepare' | 'page-token:page' | 'numbering-context:chapter' | 'numbering-context:page' | 'footnote:phase' | 'header-footer:variant' | 'header-footer:block' | 'header-footer:page';
2
+ export type LayoutExecutionCheckpoint = {
3
+ phase: LayoutExecutionPhase;
4
+ index?: number;
5
+ total?: number;
6
+ };
7
+ /** Phase-agnostic progress emitted by resumable layout helpers. */
8
+ export type LayoutWorkCheckpoint = {
9
+ index: number;
10
+ total?: number;
11
+ };
12
+ export interface LayoutExecutionControl {
13
+ signal?: AbortSignal;
14
+ /** Host-owned task boundary. It may resolve immediately while the current budget remains. */
15
+ yieldToHost?: (checkpoint: LayoutExecutionCheckpoint) => Promise<void>;
16
+ /** Work cadence for document/block loops. Defaults to 16. */
17
+ checkpointEveryBlocks?: number;
18
+ }
19
+ export declare function layoutExecutionCheckpointEveryBlocks(execution: LayoutExecutionControl | undefined): number;
20
+ export declare function throwIfLayoutExecutionAborted(execution: LayoutExecutionControl | undefined): void;
21
+ export declare function checkpointLayoutExecution(execution: LayoutExecutionControl | undefined, checkpoint: LayoutExecutionCheckpoint): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { ImageBlock, ImageMeasure, ExclusionZone, DrawingBlock, DrawingMeasure, TableBlock, TableMeasure, ColumnLayoutForAnchor } from '../../contracts/src/index.js';
1
+ import { ImageBlock, ImageMeasure, ExclusionZone, DrawingBlock, DrawingMeasure, TableBlock, TableMeasure, ColumnLayoutForAnchor, ResolveAnchoredGraphicXContext } from '../../contracts/src/index.js';
2
2
  type FloatBlock = ImageBlock | DrawingBlock;
3
3
  type FloatMeasure = ImageMeasure | DrawingMeasure;
4
4
  export type FloatingObjectManager = {
@@ -31,6 +31,19 @@ export type FloatingObjectManager = {
31
31
  width: number;
32
32
  offsetX: number;
33
33
  };
34
+ /**
35
+ * Compute every contiguous horizontal region available to a line.
36
+ * Unlike computeAvailableWidth, this preserves both sides of a centered
37
+ * `wrapText="bothSides"` object instead of collapsing them to one side.
38
+ */
39
+ computeAvailableRegions(lineY: number, lineHeight: number, baseWidth: number, columnIndex: number, pageNumber: number): Array<{
40
+ offsetX: number;
41
+ width: number;
42
+ }>;
43
+ /**
44
+ * Return the first Y coordinate below every overlapping TopAndBottom float.
45
+ */
46
+ computeVerticalClearance(lineY: number, lineHeight: number, columnIndex: number, pageNumber: number): number | null;
34
47
  /**
35
48
  * Get all floating images for a page (for debugging/painting).
36
49
  */
@@ -56,5 +69,5 @@ export declare function createFloatingObjectManager(columns: ColumnLayout, margi
56
69
  export declare function computeAnchorX(anchor: NonNullable<ImageBlock['anchor']>, columnIndex: number, columns: ColumnLayout, imageWidth: number, margins?: {
57
70
  left?: number;
58
71
  right?: number;
59
- }, pageWidth?: number): number;
72
+ }, pageWidth?: number, context?: ResolveAnchoredGraphicXContext): number;
60
73
  export {};
@@ -1,4 +1,5 @@
1
1
  import { FlowBlock, Measure, TableBlock, TableMeasure } from '../../contracts/src/index.js';
2
+ import { LayoutWorkCheckpoint } from './execution.js';
2
3
  export type FloatingTableAnchorResolution = {
3
4
  paragraphIndex: number;
4
5
  offsetV: number;
@@ -18,4 +19,5 @@ export declare function isAnchoredTableFullWidth(block: TableBlock, measure: Tab
18
19
  /**
19
20
  * Resolve anchor paragraph + vertical offset for a block-level floating table.
20
21
  */
22
+ export declare function resolveFloatingTableAnchorResolutionSteps(blocks: FlowBlock[], measures: Measure[], len: number, tableIndex: number, tableBlock: TableBlock, paragraphIndexById: Map<string, number>, checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, FloatingTableAnchorResolution | null, void>;
21
23
  export declare function resolveFloatingTableAnchorResolution(blocks: FlowBlock[], measures: Measure[], len: number, tableIndex: number, tableBlock: TableBlock, paragraphIndexById: Map<string, number>): FloatingTableAnchorResolution | null;
@@ -0,0 +1,17 @@
1
+ import { FlowBlock } from '../../contracts/src/index.js';
2
+ import { LayoutWorkCheckpoint } from './execution.js';
3
+ import { FootnoteAnchorRef } from './layout-paragraph.js';
4
+ export type FootnoteAnchorIndexInput = {
5
+ refs?: Array<{
6
+ id: string;
7
+ pos: number;
8
+ }>;
9
+ bodyHeightById?: Map<string, number>;
10
+ firstLineHeightById?: Map<string, number>;
11
+ };
12
+ export type FootnoteAnchorIndexDiagnostics = {
13
+ rangeComparisons: number;
14
+ lowerBoundComparisons: number;
15
+ legacyComparisons: number;
16
+ };
17
+ export declare function buildFootnoteAnchorIndexSteps(blocks: FlowBlock[], footnotes: FootnoteAnchorIndexInput | undefined, checkpointEveryBlocks: number | null, diagnostics?: FootnoteAnchorIndexDiagnostics): Generator<LayoutWorkCheckpoint, Map<string, FootnoteAnchorRef[]>, void>;
@@ -1,5 +1,6 @@
1
- import { ColumnLayout, FlowBlock, HeaderFooterLayout, Layout, Measure, Page, ParagraphBlock, ParagraphMeasure, SectionMetadata, FlowMode, DocumentBackground } from '../../contracts/src/index.js';
1
+ import { ColumnLayout, FlowBlock, HeaderFooterLayout, Layout, Measure, Page, ParagraphBlock, ParagraphMeasure, SectionMetadata, FlowMode, DocumentBackground, ParagraphLineRegion } from '../../contracts/src/index.js';
2
2
  import { PageState, ConstraintBoundary } from './paginator.js';
3
+ import { LayoutExecutionControl } from './execution.js';
3
4
  type PageSize = {
4
5
  w: number;
5
6
  h: number;
@@ -30,7 +31,7 @@ export type LayoutOptions = {
30
31
  marginTop?: number;
31
32
  marginBottom?: number;
32
33
  };
33
- remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure;
34
+ remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure;
34
35
  /** @internal Positioned paragraph frames that render without advancing the story cursor. */
35
36
  nonFlowPositionedParagraphFrameIds?: ReadonlySet<string>;
36
37
  sectionMetadata?: SectionMetadata[];
@@ -258,13 +259,12 @@ export type HeaderFooterConstraints = {
258
259
  overflowBaseHeight?: number;
259
260
  };
260
261
  /**
261
- * Layout FlowBlocks into paginated fragments using measured line data.
262
- *
263
- * The function is intentionally deterministic: it walks the provided
264
- * FlowBlocks in order, consumes their Measure objects (same index),
265
- * and greedily stacks fragments inside the content box of each page/column.
262
+ * The synchronous API drains the same resumable state machine without host
263
+ * turns. Mounted orchestration uses `layoutDocumentCooperatively`; keeping one
264
+ * algorithm prevents cancellation support from becoming a second paginator.
266
265
  */
267
266
  export declare function layoutDocument(blocks: FlowBlock[], measures: Measure[], options?: LayoutOptions): Layout;
267
+ export declare function layoutDocumentCooperatively(blocks: FlowBlock[], measures: Measure[], options?: LayoutOptions, execution?: LayoutExecutionControl): Promise<Layout>;
268
268
  export type LayoutRangeBoundaryPolicy = 'conservative-context' | 'overscan' | 'degraded-on-incomplete-state';
269
269
  export type LayoutRangeExactness = 'exact' | 'pending-layout' | 'degraded-unsupported' | 'stale';
270
270
  export type LayoutRangeSourceRange = {
@@ -337,13 +337,16 @@ export declare function layoutDocumentRange(input: LayoutRangeInput): LayoutRang
337
337
  * Returns separate measurement bounds (for pagination) and render bounds
338
338
  * (for overlay shift). See the Coordinate Contract in the fix plan for details.
339
339
  */
340
- export declare function layoutHeaderFooter(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure): HeaderFooterLayout;
340
+ export declare function layoutHeaderFooter(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: LayoutOptions['remeasureParagraph']): HeaderFooterLayout;
341
+ export declare function layoutHeaderFooterCooperatively(blocks: FlowBlock[], measures: Measure[], constraints: HeaderFooterConstraints, kind?: 'header' | 'footer', remeasureParagraph?: LayoutOptions['remeasureParagraph'], execution?: LayoutExecutionControl): Promise<HeaderFooterLayout>;
341
342
  export { buildAnchorMap, resolvePageRefTokens, getTocBlocksForRemeasurement } from './resolvePageRefs.js';
342
- export { buildChapterContextByPage, computeDisplayPageNumber, formatPageNumber, formatPageNumberFieldValue, formatSectionPageNumberText, normalizeChapterMarkerText, } from './pageNumbering.js';
343
+ export { buildChapterContextByPage, buildChapterContextByPageCooperatively, computeDisplayPageNumber, computeDisplayPageNumberCooperatively, formatPageNumber, formatPageNumberFieldValue, formatSectionPageNumberText, normalizeChapterMarkerText, } from './pageNumbering.js';
343
344
  export type { ChapterPageInfo, DisplayPageInfo, PageNumberFormat } from './pageNumbering.js';
344
- export { resolvePageNumberTokens } from './resolvePageTokens.js';
345
+ export { resolvePageNumberTokens, resolvePageNumberTokensCooperatively } from './resolvePageTokens.js';
345
346
  export type { NumberingContext, ResolvePageTokensResult, ResolvePageTokensOptions } from './resolvePageTokens.js';
346
347
  export { getCellLines, getEmbeddedRowLines, resolveTableFrame, resolveRenderedTableWidth } from './layout-table.js';
347
348
  export { describeCellRenderBlocks, computeCellSliceContentHeight } from './table-cell-slice.js';
348
349
  export { layoutTextboxContent, resolveTextboxContentMeasures } from './layout-textbox.js';
349
350
  export { SINGLE_COLUMN_DEFAULT } from './section-breaks.js';
351
+ export { checkpointLayoutExecution, throwIfLayoutExecutionAborted } from './execution.js';
352
+ export type { LayoutExecutionCheckpoint, LayoutExecutionControl, LayoutExecutionPhase } from './execution.js';
@@ -0,0 +1,9 @@
1
+ import { FlowBlock, Measure, Page } from '../../contracts/src/index.js';
2
+ /**
3
+ * Word baseline-aligns an inline zero-height connector with the run that owns
4
+ * it. Projection keeps vector drawings as sibling blocks, so the connector has
5
+ * already reserved its authored flow height before the empty carrier paragraph
6
+ * is laid out. Reposition only its paint fragment once that carrier's measured
7
+ * baseline is known; later flow remains untouched.
8
+ */
9
+ export declare function alignInlineZeroHeightDrawingFragments(pages: Page[], blocks: FlowBlock[], measures: Measure[]): void;
@@ -1,4 +1,4 @@
1
- import { DrawingBlock, DrawingMeasure, ParagraphMeasure } from '../../contracts/src/index.js';
1
+ import { DrawingBlock, DrawingMeasure, TextboxContentMeasure } from '../../contracts/src/index.js';
2
2
  import { NormalizedColumns } from './layout-image.js';
3
3
  import { PageState } from './paginator.js';
4
4
  /**
@@ -21,8 +21,8 @@ export type DrawingLayoutContext = {
21
21
  advanceColumn: (state: PageState) => PageState;
22
22
  /** Computes the X coordinate for a column in the given page state (SD-2629). */
23
23
  columnX: (state: PageState, columnIndex?: number) => number;
24
- /** Optional textbox paragraph measurements carried alongside textbox drawings. */
25
- textboxContentMeasures?: ParagraphMeasure[];
24
+ /** Optional canonical textbox block measurements carried alongside textbox drawings. */
25
+ textboxContentMeasures?: TextboxContentMeasure[];
26
26
  };
27
27
  /**
28
28
  * Layout a drawing block (vector shape) within the document flow.
@@ -1,6 +1,6 @@
1
1
  import { FloatingObjectManager } from './floating-objects.js';
2
2
  import { PageState } from './paginator.js';
3
- import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure } from '../../contracts/src/index.js';
3
+ import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure, ParagraphLineRegion } from '../../contracts/src/index.js';
4
4
  import { AnchoredTable } from './anchors.js';
5
5
  /**
6
6
  * SD-2656: ordered footnote anchor entry. The body slicer reads the candidate
@@ -21,7 +21,7 @@ export type ParagraphLayoutContext = {
21
21
  advanceColumn: (state: PageState) => PageState;
22
22
  columnX: (state: PageState, columnIndex?: number) => number;
23
23
  floatManager: FloatingObjectManager;
24
- remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number) => ParagraphMeasure;
24
+ remeasureParagraph?: (block: ParagraphBlock, maxWidth: number, firstLineIndent?: number, lineRegions?: readonly (readonly ParagraphLineRegion[])[]) => ParagraphMeasure;
25
25
  /**
26
26
  * Override the paragraph's spacing-after value. Used when contextual spacing
27
27
  * should suppress spacing between this paragraph and the next (same-style) paragraph.
@@ -1,4 +1,4 @@
1
- import { DrawingMeasure, ParagraphMeasure, TextboxDrawing } from '../../contracts/src/index.js';
2
- export declare function layoutTextboxContent(block: TextboxDrawing, remeasureParagraph: (block: TextboxDrawing['contentBlocks'][number], maxWidth: number) => ParagraphMeasure): ParagraphMeasure[];
1
+ import { DrawingMeasure, ParagraphBlock, ParagraphMeasure, TextboxContentMeasure, TextboxDrawing } from '../../contracts/src/index.js';
2
+ export declare function layoutTextboxContent(block: TextboxDrawing, remeasureParagraph: (block: ParagraphBlock, maxWidth: number) => ParagraphMeasure): ParagraphMeasure[] | undefined;
3
3
  /** Prefer canonical measurement output, retaining the synchronous bridge as a legacy fallback. */
4
- export declare function resolveTextboxContentMeasures(block: TextboxDrawing, measure: DrawingMeasure, remeasureParagraph?: (block: TextboxDrawing['contentBlocks'][number], maxWidth: number) => ParagraphMeasure): ParagraphMeasure[] | undefined;
4
+ export declare function resolveTextboxContentMeasures(block: TextboxDrawing, measure: DrawingMeasure, remeasureParagraph?: (block: ParagraphBlock, maxWidth: number) => ParagraphMeasure): TextboxContentMeasure[] | undefined;
@@ -1,4 +1,5 @@
1
1
  import { formatPageNumber, formatPageNumberFieldValue, formatSectionPageNumberText, FlowBlock, Layout, Page, PageNumberChapterSeparator, PageNumberFormat, SectionMetadata } from '../../contracts/src/index.js';
2
+ import { LayoutExecutionControl } from './execution.js';
2
3
  export { formatPageNumber, formatPageNumberFieldValue, formatSectionPageNumberText };
3
4
  export type { PageNumberFormat };
4
5
  export interface ChapterPageInfo {
@@ -29,45 +30,6 @@ export interface DisplayPageInfo {
29
30
  }
30
31
  export declare function normalizeChapterMarkerText(markerText: unknown): string | undefined;
31
32
  export declare function buildChapterContextByPage(layout: Layout, blocks: FlowBlock[] | ReadonlyMap<string, FlowBlock>, sections: SectionMetadata[]): Map<number, ChapterPageInfo>;
32
- /**
33
- * Computes section-aware display page numbers for all pages in a document.
34
- *
35
- * This function implements MS Word's section numbering behavior:
36
- * - Each section can have its own page number format
37
- * - Sections can restart numbering at a specific value
38
- * - Continuous sections inherit the previous section's running count unless restart is set
39
- * - Display numbers are calculated as: pageIndexWithinSection + offset (or restart value)
40
- * - Display numbers are never less than 1
41
- *
42
- * Algorithm:
43
- * 1. Map each page to its owning section
44
- * 2. For each section:
45
- * - If restart/start is set, begin counting from that value
46
- * - Otherwise, continue from previous section's count
47
- * 3. For each page within a section:
48
- * - Calculate displayIndex = pageIndexWithinSection + offset
49
- * - Clamp displayNumber = max(1, displayIndex)
50
- * - Format displayText using the section's number format
51
- *
52
- * @param pages - Array of pages from the layout (with page.number 1-indexed)
53
- * @param sections - Array of section metadata (aligned by sectionIndex)
54
- * @returns Array of display page information for each page
55
- *
56
- * @example
57
- * ```typescript
58
- * const pages = [
59
- * { number: 1, ... },
60
- * { number: 2, ... },
61
- * { number: 3, ... },
62
- * ];
63
- * const sections = [
64
- * { sectionIndex: 0, numbering: { format: 'lowerRoman', start: 1 } },
65
- * { sectionIndex: 1, numbering: { format: 'decimal', start: 1 } },
66
- * ];
67
- * const displayInfo = computeDisplayPageNumber(pages, sections);
68
- * // displayInfo[0]: { physicalPage: 1, displayNumber: 1, displayText: "i", sectionIndex: 0 }
69
- * // displayInfo[1]: { physicalPage: 2, displayNumber: 2, displayText: "ii", sectionIndex: 0 }
70
- * // displayInfo[2]: { physicalPage: 3, displayNumber: 1, displayText: "1", sectionIndex: 1 }
71
- * ```
72
- */
33
+ export declare function buildChapterContextByPageCooperatively(layout: Layout, blocks: FlowBlock[] | ReadonlyMap<string, FlowBlock>, sections: SectionMetadata[], execution?: LayoutExecutionControl): Promise<Map<number, ChapterPageInfo>>;
73
34
  export declare function computeDisplayPageNumber(pages: Page[], sections: SectionMetadata[], chapterInfoByPage?: ReadonlyMap<number, ChapterPageInfo>): DisplayPageInfo[];
35
+ export declare function computeDisplayPageNumberCooperatively(pages: Page[], sections: SectionMetadata[], chapterInfoByPage: ReadonlyMap<number, ChapterPageInfo> | undefined, execution?: LayoutExecutionControl): Promise<DisplayPageInfo[]>;
@@ -94,7 +94,9 @@ export type PaginatorOptions = {
94
94
  w: number;
95
95
  h: number;
96
96
  }): Page;
97
- onNewPage?: (state: PageState) => void;
97
+ onNewPage?: (state: PageState | undefined, options?: {
98
+ applyPendingSection: boolean;
99
+ }) => void;
98
100
  shouldStopBeforeNewPage?: (input: {
99
101
  completedPageIndex: number;
100
102
  pages: readonly Page[];
@@ -122,7 +124,10 @@ export declare function breakParagraphAdjacency(state: PageState): void;
122
124
  export declare function createPaginator(opts: PaginatorOptions): {
123
125
  readonly pages: Page[];
124
126
  readonly states: PageState[];
125
- readonly startNewPage: () => PageState;
127
+ readonly startNewPage: (options?: {
128
+ applyPendingSection?: boolean;
129
+ replaceCurrentPage?: boolean;
130
+ }) => PageState;
126
131
  readonly ensurePage: () => PageState;
127
132
  readonly advanceColumn: (state: PageState) => PageState;
128
133
  readonly getActiveColumnsForState: (state: PageState) => ColumnLayout;
@@ -1,5 +1,6 @@
1
1
  import { Layout, FlowBlock, ParagraphBlock, Measure } from '../../contracts/src/index.js';
2
2
  import { DisplayPageInfo } from './pageNumbering.js';
3
+ import { LayoutExecutionControl } from './execution.js';
3
4
  /**
4
5
  * Numbering context for page token resolution.
5
6
  * Contains display page information for each physical page in the document.
@@ -59,6 +60,7 @@ export interface ResolvePageTokensOptions {
59
60
  pageCountFieldsExact?: boolean;
60
61
  }
61
62
  export declare function resolvePageNumberTokens(layout: Layout, blocks: FlowBlock[], measures: Measure[], numberingCtx: NumberingContext, options?: ResolvePageTokensOptions): ResolvePageTokensResult;
63
+ export declare function resolvePageNumberTokensCooperatively(layout: Layout, blocks: FlowBlock[], measures: Measure[], numberingCtx: NumberingContext, options?: ResolvePageTokensOptions, execution?: LayoutExecutionControl): Promise<ResolvePageTokensResult>;
62
64
  /**
63
65
  * Resolves page number tokens in paragraph blocks.
64
66
  *
@@ -28,6 +28,7 @@ export type SectionState = {
28
28
  };
29
29
  export type BreakDecision = {
30
30
  forcePageBreak: boolean;
31
+ forceColumnBreak?: boolean;
31
32
  forceMidPageRegion: boolean;
32
33
  requiredParity?: 'even' | 'odd';
33
34
  };
@@ -62,4 +62,9 @@ export type SectionProps = {
62
62
  * }
63
63
  * ```
64
64
  */
65
+ export type SectionPropsScanCheckpoint = {
66
+ index: number;
67
+ total: number;
68
+ };
69
+ export declare function computeNextSectionPropsAtBreakSteps(blocks: FlowBlock[], checkpointEveryBlocks?: number | null): Generator<SectionPropsScanCheckpoint, Map<number, SectionProps>, void>;
65
70
  export declare function computeNextSectionPropsAtBreak(blocks: FlowBlock[]): Map<number, SectionProps>;