superdoc 2.4.0-next.5 → 2.4.0-next.51

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 (101) hide show
  1. package/AGENTS.md +13 -13
  2. package/README.md +19 -22
  3. package/dist/chunks/{FindReplaceSurface-C-I4GcRE.cjs → FindReplaceSurface-0p7EtMZh.cjs} +4 -4
  4. package/dist/chunks/{FindReplaceSurface-B_1Ksbr0.es.js → FindReplaceSurface-40AnrqWk.es.js} +5 -4
  5. package/dist/chunks/{PasswordPromptSurface-Bu5xHm91.cjs → PasswordPromptSurface-31lYPcCK.cjs} +4 -3
  6. package/dist/chunks/{PasswordPromptSurface-Bz9_sKhX.es.js → PasswordPromptSurface-CwYeO3iQ.es.js} +4 -2
  7. package/dist/chunks/{PdfViewer-CdVGB6Fe.es.js → PdfViewer-D8h7LRZy.es.js} +103 -19
  8. package/dist/chunks/{PdfViewer-D4eD2dV1.cjs → PdfViewer-Dug6yDRC.cjs} +105 -20
  9. package/dist/chunks/_plugin-vue_export-helper-BOaGB7Aw.es.js +8 -0
  10. package/dist/chunks/_plugin-vue_export-helper-SDR04tiH.cjs +13 -0
  11. package/dist/chunks/{blank-docx-DP8RUPW-.cjs → blank-docx-BuFAbRjs.cjs} +2 -0
  12. package/dist/chunks/{blank-docx-XRX6Ker2.es.js → blank-docx-DzQccOlW.es.js} +2 -0
  13. package/dist/chunks/constants-B6VBlmKp.es.js +4 -0
  14. package/dist/chunks/constants-DpXuDx_g.cjs +9 -0
  15. package/dist/chunks/{create-super-doc-ui-BquF8bnZ.es.js → create-super-doc-ui-B_1l545i.es.js} +2134 -1099
  16. package/dist/chunks/{create-super-doc-ui-sMXbYzhs.cjs → create-super-doc-ui-DNtHxzz_.cjs} +1945 -1150
  17. package/dist/chunks/{eventemitter3-Bt2s0X0a.es.js → eventemitter3-CMOjDs74.es.js} +124 -16
  18. package/dist/chunks/{eventemitter3-DqY4aSMf.cjs → eventemitter3-D38u8ta_.cjs} +125 -16
  19. package/dist/chunks/jszip-RC64TPzL.cjs +4758 -0
  20. package/dist/chunks/jszip-VxCFV9YS.es.js +4717 -0
  21. package/dist/chunks/{rolldown-runtime-D7PMmH3s.es.js → rolldown-runtime-B5TtN50X.es.js} +13 -4
  22. package/dist/chunks/{rolldown-runtime-1Y-nnZJ3.cjs → rolldown-runtime-DtsSbkrh.cjs} +12 -3
  23. package/dist/chunks/{uuid-CFp0WGVU.cjs → uuid-BhG0ngwk.cjs} +10 -6
  24. package/dist/chunks/{uuid-B2Sqk-3p.es.js → uuid-H0Xcmmhy.es.js} +8 -3
  25. package/dist/collaboration-upgrade-engine.cjs +34 -9
  26. package/dist/collaboration-upgrade-engine.es.js +30 -5
  27. package/dist/document-api/src/citations/citations.types.d.ts +9 -0
  28. package/dist/document-api/src/comments/comments.types.d.ts +7 -0
  29. package/dist/document-api/src/types/receipt.d.ts +9 -5
  30. package/dist/document-api/src/types/track-changes.types.d.ts +18 -3
  31. package/dist/layout-engine/contracts/src/graphic-placement.d.ts +35 -6
  32. package/dist/layout-engine/contracts/src/incremental-dependency.d.ts +22 -2
  33. package/dist/layout-engine/contracts/src/index.d.ts +164 -8
  34. package/dist/layout-engine/contracts/src/inline-box.d.ts +19 -0
  35. package/dist/layout-engine/contracts/src/paragraph-visible-text.d.ts +19 -0
  36. package/dist/layout-engine/contracts/src/resolved-layout.d.ts +5 -0
  37. package/dist/layout-engine/dom-contract/src/class-names.d.ts +2 -0
  38. package/dist/layout-engine/layout-bridge/src/footnote-scorer.d.ts +1 -1
  39. package/dist/layout-engine/layout-bridge/src/hydrateTableTextboxMeasures.d.ts +9 -0
  40. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +28 -10
  41. package/dist/layout-engine/layout-bridge/src/index.d.ts +4 -2
  42. package/dist/layout-engine/layout-bridge/src/inline-box-key.d.ts +3 -0
  43. package/dist/layout-engine/layout-bridge/src/layoutHeaderFooter.d.ts +11 -4
  44. package/dist/layout-engine/layout-bridge/src/remeasure.d.ts +2 -2
  45. package/dist/layout-engine/layout-bridge/src/run-visual-marks.d.ts +2 -0
  46. package/dist/layout-engine/layout-bridge/src/text-measurement.d.ts +0 -12
  47. package/dist/layout-engine/layout-engine/src/anchors.d.ts +4 -0
  48. package/dist/layout-engine/layout-engine/src/execution.d.ts +21 -0
  49. package/dist/layout-engine/layout-engine/src/floating-objects.d.ts +15 -2
  50. package/dist/layout-engine/layout-engine/src/floating-table-anchor.d.ts +2 -0
  51. package/dist/layout-engine/layout-engine/src/footnote-anchor-index.d.ts +17 -0
  52. package/dist/layout-engine/layout-engine/src/index.d.ts +13 -10
  53. package/dist/layout-engine/layout-engine/src/inline-drawing-alignment.d.ts +9 -0
  54. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +2 -2
  55. package/dist/layout-engine/layout-engine/src/pageNumbering.d.ts +3 -41
  56. package/dist/layout-engine/layout-engine/src/resolvePageTokens.d.ts +2 -0
  57. package/dist/layout-engine/layout-engine/src/section-props.d.ts +5 -0
  58. package/dist/layout-engine/painters/dom/src/renderer.d.ts +6 -0
  59. package/dist/layout-engine/painters/dom/src/runs/inline-box.d.ts +8 -0
  60. package/dist/layout-engine/painters/dom/src/runs/text-run.d.ts +6 -4
  61. package/dist/layout-engine/painters/dom/src/table/border-utils.d.ts +20 -27
  62. package/dist/layout-engine/style-engine/src/ooxml/word-style-model/parse-theme.d.ts +6 -0
  63. package/dist/public/ui-react.cjs +66 -2
  64. package/dist/public/ui-react.es.js +66 -1
  65. package/dist/public/ui.cjs +1 -1
  66. package/dist/public/ui.es.js +1 -1
  67. package/dist/style.css +174 -138
  68. package/dist/style.layered.css +174 -138
  69. package/dist/superdoc/src/components/CommentsLayer/CommentDialog.vue.d.ts +2 -0
  70. package/dist/superdoc/src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue.d.ts +16 -0
  71. package/dist/superdoc/src/components/CommentsLayer/commentsList/commentsList.vue.d.ts +3 -1
  72. package/dist/superdoc/src/components/CommentsLayer/commentsList/super-comments-list.d.ts +12 -0
  73. package/dist/superdoc/src/core/SuperDoc.d.ts +10 -7
  74. package/dist/superdoc/src/core/extensions/index.d.ts +1 -1
  75. package/dist/superdoc/src/core/extensions/types.d.ts +63 -5
  76. package/dist/superdoc/src/core/types/index.d.ts +535 -42
  77. package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +3 -3
  78. package/dist/superdoc/src/helpers/comment-small-screen.d.ts +10 -0
  79. package/dist/superdoc/src/helpers/v2-review-mutation-impact.d.ts +3 -5
  80. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButton.vue.d.ts +4 -4
  81. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +11 -0
  82. package/dist/superdoc/src/internal/toolbar/compatibility-catalog.d.ts +1 -1
  83. package/dist/superdoc/src/public/index.d.cts +28 -0
  84. package/dist/superdoc/src/public/index.d.ts +14 -0
  85. package/dist/superdoc/src/public/ui/types.d.ts +30 -6
  86. package/dist/superdoc/src/stores/comments-store.d.ts +81 -78
  87. package/dist/superdoc/src/stores/superdoc-store.d.ts +243 -234
  88. package/dist/superdoc.cjs +6743 -2169
  89. package/dist/superdoc.es.js +6616 -2042
  90. package/dist-cdn/style.layered.css +1 -1
  91. package/dist-cdn/superdoc.min.css +1 -1
  92. package/dist-cdn/superdoc.min.js +37 -37
  93. package/package.json +14 -17
  94. package/dist/chunks/_plugin-vue_export-helper-CZ1Nl59K.cjs +0 -11
  95. package/dist/chunks/_plugin-vue_export-helper-DSMAhhwD.es.js +0 -6
  96. package/dist/chunks/constants-BfH0br5u.es.js +0 -3
  97. package/dist/chunks/constants-D7TNtyJd.cjs +0 -14
  98. package/dist/chunks/jszip-C8srOKAO.es.js +0 -4650
  99. package/dist/chunks/jszip-Cs9JBLlJ.cjs +0 -4691
  100. package/dist/superdoc/src/helpers/v2-remote-review-hydration.d.ts +0 -12
  101. package/dist/superdoc/src/helpers/v2-review-mutation-reconciler.d.ts +0 -19
@@ -1,6 +1,7 @@
1
1
  import { TabStop } from './engines/tabs.js';
2
2
  import { PageNumberChapterSeparator, PageNumberFieldFormat, PageNumberFormat } from './page-number-formatting.js';
3
3
  import { TrackedChangeSemanticColorKey } from './semantic-colors.js';
4
+ import { AnchorAlignH, AnchorAlignV, AnchorHRelative, AnchorVRelative } from './graphic-placement.js';
4
5
  import { ParagraphDirectionContext, RunBidiContext, RunScriptContext, TableDirectionContext } from './direction-context.js';
5
6
  import { LayoutSourceIdentity } from './layout-identity.js';
6
7
  export { computeTabStops, layoutWithTabs, calculateTabWidth } from './engines/tabs.js';
@@ -17,7 +18,7 @@ export { shouldApplyJustify, calculateJustifySpacing, getFirstLineIndentOffset,
17
18
  export { parseInsetClipPathForScale, formatInsetClipPathTransform, type InsetClipPathScale, } from './clip-path-inset.js';
18
19
  export { SUBSCRIPT_SUPERSCRIPT_SCALE, normalizeBaselineShift, hasExplicitBaselineShift, isSuperscriptOrSubscript, usesDefaultScriptLayout, scaleFontSizeForVerticalText, resolveBaseFontSizeForVerticalText, type VerticalTextAlign, } from './vertical-text.js';
19
20
  export { computeFragmentPmRange, computeLinePmRange, type LinePmRange } from './pm-range.js';
20
- export { resolveAnchoredGraphicY, resolveAnchoredGraphicX, resolveFooterPageFrameOriginY, isPositionedParagraphFrame, isPagePositionedParagraphFrame, type ColumnLayoutForAnchor, type ResolveAnchoredGraphicYInput, } from './graphic-placement.js';
21
+ export { resolveAnchoredGraphicY, resolveAnchoredGraphicX, resolveFooterPageFrameOriginY, isPositionedParagraphFrame, isPagePositionedParagraphFrame, isAnchorHRelative, isAnchorVRelative, isAnchorAlignH, isAnchorAlignV, ANCHOR_H_RELATIVE_VALUES, ANCHOR_V_RELATIVE_VALUES, ANCHOR_H_ALIGN_VALUES, ANCHOR_V_ALIGN_VALUES, type ColumnLayoutForAnchor, type ResolveAnchoredGraphicYInput, type ResolveAnchoredGraphicXContext, type AnchorHRelative, type AnchorVRelative, type AnchorAlignH, type AnchorAlignV, } from './graphic-placement.js';
21
22
  export { LAYOUT_BOUNDARY_SCHEMA, bodyStoryLocator, namedStoryLocator, computeLayoutFragmentId, buildLayoutSourceIdentity, buildLayoutSourceIdentityForFragment, } from './layout-identity.js';
22
23
  export type { LayoutBlockRef, LayoutFragmentId, LayoutPartialRowIdentity, LayoutSourceIdentity, LayoutStoryKind, LayoutStoryLocator, } from './layout-identity.js';
23
24
  export { LAYOUT_SEGMENT_GEOMETRY_SCHEMA } from './segment-geometry.js';
@@ -120,7 +121,7 @@ export type DocPartMetadata = {
120
121
  * - Doc parts: special objects like tables of contents
121
122
  */
122
123
  export type SdtMetadata = FieldAnnotationMetadata | StructuredContentMetadata | DocumentSectionMetadata | DocPartMetadata;
123
- export declare const CONTRACTS_VERSION = "1.1.0";
124
+ export declare const CONTRACTS_VERSION = "1.2.0";
124
125
  /** Unique identifier for a block in the document. Format: `${pos}-${type}`. */
125
126
  export type BlockId = string;
126
127
  /**
@@ -655,12 +656,58 @@ export type MathRun = {
655
656
  sdt?: SdtMetadata;
656
657
  };
657
658
  export type Run = TextRun | TabRun | ImageRun | LineBreakRun | BreakRun | FieldAnnotationRun | MathRun;
659
+ /** Layout-affecting inline-box values, resolved to logical CSS pixel sides. */
660
+ export type ResolvedInlineBoxLayout = {
661
+ paddingInlineStart: number;
662
+ paddingInlineEnd: number;
663
+ paddingBlockStart: number;
664
+ paddingBlockEnd: number;
665
+ gapBefore: number;
666
+ gapAfter: number;
667
+ borderWidth: number;
668
+ };
669
+ /** Sanitized, paint-only inline-box appearance. */
670
+ export type ResolvedInlineBoxAppearance = {
671
+ backgroundColor?: string;
672
+ borderColor?: string;
673
+ borderStyle?: 'solid' | 'dashed' | 'dotted';
674
+ borderRadius?: number;
675
+ color?: string;
676
+ };
677
+ /** Paint-ready inline-box style emitted on measured line slices. */
678
+ export type ResolvedInlineBoxStyle = ResolvedInlineBoxLayout & ResolvedInlineBoxAppearance;
679
+ /**
680
+ * An internal, layout-aware presentation over a paragraph-visible text range.
681
+ *
682
+ * The proof uses leaf styling (D1): measurement creates box-edge segment
683
+ * boundaries and the painter styles the canonical text leaves. The fallback
684
+ * sibling layer was not needed. Extension-authored boxes reach this internal
685
+ * layout contract through the v2 host bridge. RTL input is ignored (D12), and
686
+ * the synchronous paragraph remeasurer does not consume this field (D14).
687
+ */
688
+ export type InlineBoxSpan = {
689
+ id: string;
690
+ /**
691
+ * UTF-16 offsets over the paragraph's flattened visible text. Every
692
+ * non-text run contributes one placeholder character. These offsets never
693
+ * alter run PM ranges, run indices, source anchors, or document identity.
694
+ */
695
+ from: number;
696
+ to: number;
697
+ layout: ResolvedInlineBoxLayout;
698
+ appearance: ResolvedInlineBoxAppearance;
699
+ className?: string;
700
+ data?: Record<string, string>;
701
+ cursor?: 'default' | 'pointer' | 'text' | 'help';
702
+ };
658
703
  export type ParagraphBlock = {
659
704
  kind: 'paragraph';
660
705
  id: BlockId;
661
706
  runs: Run[];
662
707
  attrs?: ParagraphAttrs;
663
708
  sourceAnchor?: SourceAnchor;
709
+ /** @internal Layout-aware presentation projected from the extension API by the v2 host. */
710
+ inlineBoxes?: InlineBoxSpan[];
664
711
  };
665
712
  /** Border style (subset of OOXML ST_Border). */
666
713
  export type BorderStyle = 'none' | 'single' | 'double' | 'dashed' | 'dotted' | 'thick' | 'triple' | 'dotDash' | 'dotDotDash' | 'wave' | 'doubleWave';
@@ -671,6 +718,12 @@ export type BorderSpec = {
671
718
  color?: string;
672
719
  space?: number;
673
720
  };
721
+ /**
722
+ * Returns the complete painted width of an OOXML table border in CSS pixels.
723
+ * `w:sz` is the width of the complete border, including compound styles such
724
+ * as double. `thick` retains the existing table-painter minimum used in V2.
725
+ */
726
+ export declare const getRenderedTableBorderWidthPx: (border: Pick<BorderSpec, "style" | "width"> | undefined, defaultWidth?: number) => number;
674
727
  /**
675
728
  * Three-state border value for table borders.
676
729
  * - `null`: inherit from table style
@@ -696,6 +749,16 @@ export type CellBorders = {
696
749
  bottom?: BorderSpec;
697
750
  left?: BorderSpec;
698
751
  };
752
+ /** True when a normalized border contributes a visible edge. */
753
+ export declare const isPresentBorder: (border?: BorderSpec) => border is BorderSpec;
754
+ /** True when the source explicitly suppresses an edge rather than omitting it. */
755
+ export declare const isExplicitNoneBorder: (border?: unknown) => boolean;
756
+ /**
757
+ * Resolve the single visible edge shared by two cells according to
758
+ * ECMA-376 Part 1 §17.4.66. Kept in the editor-neutral contract package so
759
+ * import and DOM paint use one conflict algorithm.
760
+ */
761
+ export declare const resolveBorderConflict: (first?: BorderSpec, second?: BorderSpec) => BorderSpec | undefined;
699
762
  export type TableCellAttrs = {
700
763
  borders?: CellBorders;
701
764
  padding?: BoxSpacing;
@@ -928,6 +991,13 @@ export type TextFormatting = {
928
991
  export type TextPart = {
929
992
  text: string;
930
993
  formatting?: TextFormatting;
994
+ /**
995
+ * Paragraph properties carried by the first visible part of a shape-text
996
+ * paragraph. Shape text is intentionally flattened into `parts`, so this
997
+ * marker preserves the authored block geometry without introducing a second
998
+ * competing text model.
999
+ */
1000
+ paragraphProperties?: ShapeTextParagraphProperties;
931
1001
  /** Optional field token (e.g., PAGE/NUMPAGES/SECTIONPAGES) resolved at render time. */
932
1002
  fieldType?: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES';
933
1003
  /** PAGE/SECTIONPAGES field-local value formatting override. */
@@ -953,6 +1023,17 @@ export type TextPart = {
953
1023
  height?: number;
954
1024
  alt?: string;
955
1025
  };
1026
+ /** Paragraph geometry used by flattened DrawingML/VML shape text. */
1027
+ export type ShapeTextParagraphProperties = {
1028
+ horizontalAlign?: 'left' | 'center' | 'right' | 'justify';
1029
+ spacingBefore?: number;
1030
+ spacingAfter?: number;
1031
+ line?: number;
1032
+ lineUnit?: 'px' | 'multiplier';
1033
+ leftIndent?: number;
1034
+ rightIndent?: number;
1035
+ firstLineIndent?: number;
1036
+ };
956
1037
  /** Text content configuration for shapes. */
957
1038
  export type ShapeTextContent = {
958
1039
  /** Array of text parts with individual formatting. */
@@ -979,6 +1060,8 @@ export type VectorShapeStyle = {
979
1060
  fillColor?: FillColor;
980
1061
  strokeColor?: StrokeColor;
981
1062
  strokeWidth?: number;
1063
+ /** Optional per-edge frame used by render-only table cells inside legacy shape groups. */
1064
+ borders?: CellBorders;
982
1065
  lineEnds?: LineEnds;
983
1066
  textContent?: ShapeTextContent;
984
1067
  textAlign?: string;
@@ -1078,6 +1161,8 @@ export type VectorShapeDrawing = DrawingBlockBase & {
1078
1161
  export type TextboxDrawing = DrawingBlockBase & {
1079
1162
  drawingKind: 'textboxShape';
1080
1163
  geometry: DrawingGeometry;
1164
+ /** `a:spAutoFit`: resize the shape height to its measured text content. */
1165
+ autoFit?: boolean;
1081
1166
  shapeKind?: string;
1082
1167
  customGeometry?: CustomGeometryData;
1083
1168
  fillColor?: FillColor;
@@ -1266,10 +1351,21 @@ export type ColumnBreakBlock = {
1266
1351
  /** Positioning for anchored images (offsets in CSS px). */
1267
1352
  export type ImageAnchor = {
1268
1353
  isAnchored?: boolean;
1269
- hRelativeFrom?: 'column' | 'page' | 'margin';
1270
- vRelativeFrom?: 'paragraph' | 'page' | 'margin';
1271
- alignH?: 'left' | 'center' | 'right';
1272
- alignV?: 'top' | 'center' | 'bottom';
1354
+ /**
1355
+ * Page-space coordinates from `wp:simplePos` in CSS px.
1356
+ * ECMA-376 Part 1 §20.4.2.13: when present because `wp:anchor/@simplePos`
1357
+ * is true, these coordinates override positionH/positionV.
1358
+ */
1359
+ simplePos?: {
1360
+ x: number;
1361
+ y: number;
1362
+ };
1363
+ /** Keep the anchored object inside its table cell and resize the cell as needed. */
1364
+ layoutInCell?: boolean;
1365
+ hRelativeFrom?: AnchorHRelative;
1366
+ vRelativeFrom?: AnchorVRelative;
1367
+ alignH?: AnchorAlignH;
1368
+ alignV?: AnchorAlignV;
1273
1369
  offsetH?: number;
1274
1370
  offsetV?: number;
1275
1371
  behindDoc?: boolean;
@@ -1285,6 +1381,7 @@ export type ImageAnchor = {
1285
1381
  */
1286
1382
  export declare function isPageRelativeAnchor(input: {
1287
1383
  anchor?: {
1384
+ simplePos?: unknown;
1288
1385
  vRelativeFrom?: unknown;
1289
1386
  } | null;
1290
1387
  } | null | undefined): boolean;
@@ -1372,7 +1469,7 @@ export type ExclusionZone = {
1372
1469
  left: number;
1373
1470
  right: number;
1374
1471
  };
1375
- wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest';
1472
+ wrapMode: 'left' | 'right' | 'both' | 'none' | 'largest' | 'topBottom';
1376
1473
  polygon?: number[][];
1377
1474
  };
1378
1475
  export type ParagraphSpacing = {
@@ -1645,6 +1742,8 @@ export type ParagraphAttrs = {
1645
1742
  tabIntervalTwips?: number;
1646
1743
  keepNext?: boolean;
1647
1744
  keepLines?: boolean;
1745
+ /** Prevent a single first or last paragraph line from appearing alone on a page. Defaults to true. */
1746
+ widowControl?: boolean;
1648
1747
  pageBreakBefore?: boolean;
1649
1748
  trackedChangesMode?: TrackedChangesMode;
1650
1749
  trackedChangesEnabled?: boolean;
@@ -1761,6 +1860,13 @@ export declare const isForcedSectPrSectionBreak: (block: FlowBlock | undefined)
1761
1860
  * accepted only when their source/anchor proves they belong to the same filler
1762
1861
  * run.
1763
1862
  */
1863
+ export type SectionBoundaryFillerScanCheckpoint = {
1864
+ index: number;
1865
+ total: number;
1866
+ };
1867
+ export declare function collectSectionBoundaryFillerBlockIdsSteps(blocks: readonly FlowBlock[], options?: {
1868
+ isTinyInlineBoundaryDrawing?: (block: DrawingBlock, index: number) => boolean;
1869
+ }, checkpointEveryBlocks?: number | null): Generator<SectionBoundaryFillerScanCheckpoint, ReadonlySet<string>, void>;
1764
1870
  export declare const collectSectionBoundaryFillerBlockIds: (blocks: readonly FlowBlock[], options?: {
1765
1871
  isTinyInlineBoundaryDrawing?: (block: DrawingBlock, index: number) => boolean;
1766
1872
  }) => ReadonlySet<string>;
@@ -1813,6 +1919,28 @@ export type LineInlineImageAlignment = {
1813
1919
  runIndex: number;
1814
1920
  verticalAlign: ImageRunVerticalAlign;
1815
1921
  };
1922
+ /**
1923
+ * Paint-ready geometry for one inline-box slice on a measured line.
1924
+ *
1925
+ * Measurement owns the slice geometry and resolved style. The painter consumes
1926
+ * these values directly and never normalizes logical sides or measures the DOM.
1927
+ */
1928
+ export type LineInlineBox = {
1929
+ id: string;
1930
+ /** Line-relative UTF-16 offsets covered by this slice. */
1931
+ from: number;
1932
+ to: number;
1933
+ x: number;
1934
+ width: number;
1935
+ top: number;
1936
+ height: number;
1937
+ startsRange: boolean;
1938
+ endsRange: boolean;
1939
+ style: ResolvedInlineBoxStyle;
1940
+ className?: string;
1941
+ data?: Record<string, string>;
1942
+ cursor?: 'default' | 'pointer' | 'text' | 'help';
1943
+ };
1816
1944
  export type Line = {
1817
1945
  fromRun: number;
1818
1946
  fromChar: number;
@@ -1843,6 +1971,8 @@ export type Line = {
1843
1971
  * wins over the entry here.
1844
1972
  */
1845
1973
  inlineImageAlignments?: LineInlineImageAlignment[];
1974
+ /** Paint-ready inline-box slices emitted by measurement. */
1975
+ inlineBoxes?: LineInlineBox[];
1846
1976
  /**
1847
1977
  * Measured tab widths keyed by tab run `pmStart`, stored alongside the
1848
1978
  * `ParagraphMeasure` so the painter can read them even after FlowBlock
@@ -1851,6 +1981,18 @@ export type Line = {
1851
1981
  */
1852
1982
  tabWidths?: Record<number, number>;
1853
1983
  };
1984
+ /**
1985
+ * One contiguous horizontal region available to a measured paragraph line.
1986
+ *
1987
+ * Coordinates are relative to the paragraph fragment's content origin. A line
1988
+ * can expose multiple regions when text wraps on both sides of a floating
1989
+ * object. Measuring owns the line breaks inside these regions; layout owns
1990
+ * deriving the regions from page/column float geometry.
1991
+ */
1992
+ export type ParagraphLineRegion = {
1993
+ offsetX: number;
1994
+ width: number;
1995
+ };
1854
1996
  export type LineSegment = {
1855
1997
  runIndex: number;
1856
1998
  fromChar: number;
@@ -2345,6 +2487,18 @@ export type HeaderFooterType = 'default' | 'first' | 'even' | 'odd';
2345
2487
  export type HeaderFooterPage = {
2346
2488
  number: number;
2347
2489
  fragments: Fragment[];
2490
+ /**
2491
+ * Measurement height for this page's resolved story content. PAGE/NUMPAGES
2492
+ * fields can wrap differently across physical pages, so paint alignment must
2493
+ * not substitute the layout-wide maximum for this value.
2494
+ */
2495
+ measurementHeight?: number;
2496
+ /** Per-page minimum rendered y, including out-of-band decorations. */
2497
+ minY?: number;
2498
+ /** Per-page maximum rendered y + fragment height. */
2499
+ maxY?: number;
2500
+ /** Per-page visual extent (`maxY - minY`). */
2501
+ renderHeight?: number;
2348
2502
  numberText?: string;
2349
2503
  /** Section-aware numeric page value before formatting. */
2350
2504
  displayNumber?: number;
@@ -2455,5 +2609,7 @@ export declare const extractHeaderFooterSpace: (margins?: PageMargins | null) =>
2455
2609
  export type { ResolvedLayout, ResolvedPage, ResolvedPaintItem, ResolvedGroupItem, ResolvedFragmentItem, ResolvedParagraphContent, ResolvedTextLineItem, ResolvedDropCapItem, ResolvedListMarkerItem, ResolvedTableItem, ResolvedImageItem, ResolvedDrawingItem, ResolvedHeaderFooterPage, ResolvedHeaderFooterLayout, } from './resolved-layout.js';
2456
2610
  export { isResolvedTableItem, isResolvedImageItem, isResolvedDrawingItem } from './resolved-layout.js';
2457
2611
  export { expandRunsForInlineNewlines, isEmptyInlineSdtPlaceholderRun, isEmptySdtPlaceholderRun, sliceRunsForLine, } from './run-helpers.js';
2458
- export { PAGE_CHECKPOINT_DEPENDENCY_CLASSES, areValidPageCheckpointDependencyClasses, type PageCheckpointDependencyClass, } from './incremental-dependency.js';
2612
+ export { INLINE_OBJECT_REPLACEMENT_CHARACTER, flattenParagraphVisibleText, mapVisibleRangeToRunSlices, type ParagraphVisibleRunSlice, } from './paragraph-visible-text.js';
2613
+ export { inlineBoxStyleSignature, isFiniteNonNegativeInteger, normalizeInlineBoxLogicalSides, type InlineBoxLogicalSides, type ResolvedInlineBoxLogicalSides, } from './inline-box.js';
2614
+ export { PAGE_CHECKPOINT_DEPENDENCY_CLASSES, areValidPageCheckpointDependencyClasses, type NonFlowingPageRelativeAnchorDependencyProof, type PageCheckpointDependencyClass, } from './incremental-dependency.js';
2459
2615
  export * as Engines from './engines/index.js';
@@ -0,0 +1,19 @@
1
+ import { ResolvedInlineBoxStyle } from './index.js';
2
+ export type InlineBoxLogicalSides = number | {
3
+ start: number;
4
+ end: number;
5
+ };
6
+ export type ResolvedInlineBoxLogicalSides = {
7
+ start: number;
8
+ end: number;
9
+ };
10
+ /** True for finite, non-negative integer CSS pixel values. */
11
+ export declare const isFiniteNonNegativeInteger: (value: unknown) => value is number;
12
+ /**
13
+ * Expands a scalar logical value into explicit start/end values.
14
+ *
15
+ * Undefined resolves to zero. Invalid or non-integer input fails closed.
16
+ */
17
+ export declare const normalizeInlineBoxLogicalSides: (value: InlineBoxLogicalSides | undefined) => ResolvedInlineBoxLogicalSides | null;
18
+ /** Stable signature for every metric and appearance value consumed by paint. */
19
+ export declare const inlineBoxStyleSignature: (style: ResolvedInlineBoxStyle) => string;
@@ -0,0 +1,19 @@
1
+ import { ParagraphBlock } from './index.js';
2
+ export declare const INLINE_OBJECT_REPLACEMENT_CHARACTER = "\uFFFC";
3
+ export type ParagraphVisibleRunSlice = {
4
+ runIndex: number;
5
+ fromChar: number;
6
+ toChar: number;
7
+ };
8
+ /**
9
+ * Flattens a paragraph into Document API visible-text coordinates.
10
+ *
11
+ * Text is preserved verbatim in UTF-16. Every non-text run contributes one
12
+ * U+FFFC object-replacement character, regardless of its rendered label.
13
+ */
14
+ export declare const flattenParagraphVisibleText: (block: ParagraphBlock) => string;
15
+ /**
16
+ * Maps a validated visible-text range to slices in the paragraph's run space.
17
+ * Returns null for non-integer, reversed, negative, or out-of-bounds ranges.
18
+ */
19
+ export declare const mapVisibleRangeToRunSlices: (block: ParagraphBlock, from: number, to: number) => ParagraphVisibleRunSlice[] | null;
@@ -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[];
@@ -117,6 +119,16 @@ export type IncrementalLayoutBridgeTiming = {
117
119
  measuresAdopted: number;
118
120
  pagesPaginated: number | null;
119
121
  pagesSplicedByReuse: number;
122
+ paginationPasses: number;
123
+ pageTokenRelayouts: number;
124
+ footnoteRelayouts: number;
125
+ footnoteReserveRelayouts: number;
126
+ footnoteGrowRelayouts: number;
127
+ footnoteTightenRelayouts: number;
128
+ footnotePreferredRelayouts: number;
129
+ footnoteWidowRelayouts: number;
130
+ footnoteRevertRelayouts: number;
131
+ footnoteOtherRelayouts: number;
120
132
  };
121
133
  };
122
134
  /**
@@ -168,6 +180,13 @@ export type IncrementalSectionPageNumberTransform = {
168
180
  /** Difference between target and source section-relative page positions. */
169
181
  delta: number;
170
182
  };
183
+ export type IncrementalDisplayPageNumberTransform = {
184
+ /** First section whose retained display-page values inherit the local page delta. */
185
+ startSectionIndex: number;
186
+ /** First later section with an explicit numbering restart. */
187
+ endSectionIndexExclusive: number;
188
+ delta: number;
189
+ };
171
190
  export type IncrementalLayoutTailAdoption = {
172
191
  startPageIndex: number;
173
192
  endPageIndexExclusive: number;
@@ -175,6 +194,7 @@ export type IncrementalLayoutTailAdoption = {
175
194
  sourcePageEndIndexExclusive: number;
176
195
  pageIndexDelta: number;
177
196
  sectionPageNumberTransform: IncrementalSectionPageNumberTransform | null;
197
+ displayPageNumberTransform?: IncrementalDisplayPageNumberTransform | null;
178
198
  sourceLayoutEpoch: number | null;
179
199
  positionTransforms: readonly LayoutPositionTransform[];
180
200
  /** Lazy old->current block-id rekeys for an ordinal-changing structural splice. */
@@ -207,6 +227,7 @@ export type IncrementalPaginationProof = IncrementalPaginationProofBase & ({
207
227
  globalDependenciesAbsent: false;
208
228
  globalDependenciesFencedByPageCheckpoint: true;
209
229
  admittedDependencyClasses: readonly PageCheckpointDependencyClass[];
230
+ nonFlowingPageRelativeAnchorDependency?: NonFlowingPageRelativeAnchorDependencyProof;
210
231
  localKeepDependencyClosure?: {
211
232
  checkpointPageIndex: number;
212
233
  checkpointBlockId: string | null;
@@ -276,10 +297,13 @@ export declare const measureCache: MeasureCache<Measure>;
276
297
  */
277
298
  export declare function clearIncrementalModuleState(): void;
278
299
  export interface IncrementalLayoutExecutionControl {
300
+ signal?: AbortSignal;
279
301
  /** Budget-aware host-task yield; may resolve immediately. */
280
- yieldToHost?: () => Promise<void>;
281
- /** Checkpoint cadence for the block measurement loop. Defaults to 32. */
302
+ yieldToHost?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void>;
303
+ /** Measurement checkpoints default to 32 blocks; nested layout checkpoints default to 16. */
282
304
  yieldEveryBlocks?: number;
305
+ /** Time-aware mounted probe. Null is the allocation-free under-budget path. */
306
+ checkpointIfDue?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void> | null;
283
307
  }
284
308
  export declare function incrementalLayout(previousBlocks: FlowBlock[], _previousLayout: Layout | null, nextBlocks: FlowBlock[], options: LayoutOptions, measureBlock: (block: FlowBlock, constraints: {
285
309
  maxWidth: number;
@@ -325,12 +349,6 @@ export declare function incrementalLayout(previousBlocks: FlowBlock[], _previous
325
349
  * @returns The normalized margin value (guaranteed to be finite)
326
350
  */
327
351
  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
352
  /**
335
353
  * Resolves the maximum measurement constraints (width and height) needed for measuring blocks
336
354
  * 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>;