superdoc 2.22.0-next.13 → 2.22.0-next.15

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 (28) hide show
  1. package/dist/collaboration-upgrade-engine.cjs +1 -1
  2. package/dist/collaboration-upgrade-engine.es.js +1 -1
  3. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +29 -2
  4. package/dist/layout-engine/layout-bridge/src/index.d.ts +3 -3
  5. package/dist/layout-engine/layout-bridge/src/layoutHeaderFooter.d.ts +4 -0
  6. package/dist/layout-engine/layout-engine/src/anchors.d.ts +4 -4
  7. package/dist/layout-engine/layout-engine/src/execution.d.ts +1 -1
  8. package/dist/layout-engine/layout-engine/src/index.d.ts +27 -0
  9. package/dist/layout-engine/layout-engine/src/inline-drawing-alignment.d.ts +4 -1
  10. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +6 -1
  11. package/dist/layout-engine/layout-engine/src/section-props.d.ts +1 -1
  12. package/dist/layout-engine/layout-engine/src/source-preparation.d.ts +52 -0
  13. package/dist/layout-engine/painters/dom/src/page-content.d.ts +6 -0
  14. package/dist/layout-engine/painters/dom/src/paragraph/renderParagraphContent.d.ts +3 -1
  15. package/dist/layout-engine/painters/dom/src/paragraph/renderParagraphFragment.d.ts +3 -1
  16. package/dist/layout-engine/painters/dom/src/persistent-page-surface.d.ts +5 -4
  17. package/dist/layout-engine/painters/dom/src/pm-position-validation.d.ts +1 -0
  18. package/dist/layout-engine/painters/dom/src/render-work.d.ts +3 -0
  19. package/dist/layout-engine/painters/dom/src/renderer.d.ts +28 -5
  20. package/dist/layout-engine/painters/dom/src/runs/render-line.d.ts +3 -1
  21. package/dist/layout-engine/painters/dom/src/runs/tab-run.d.ts +1 -1
  22. package/dist/layout-engine/painters/dom/src/table/renderTableCell.d.ts +3 -1
  23. package/dist/layout-engine/painters/dom/src/table/renderTableFragment.d.ts +3 -1
  24. package/dist/layout-engine/painters/dom/src/table/renderTableRow.d.ts +3 -1
  25. package/dist/superdoc.cjs +2 -2
  26. package/dist/superdoc.es.js +2 -2
  27. package/dist-cdn/superdoc.min.js +3 -3
  28. package/package.json +2 -2
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
19
19
  var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
20
20
  var ENGINE_INFO = Object.freeze({
21
21
  ...PRIVATE_ENGINE_INFO,
22
- superdocVersion: "2.22.0-next.13",
22
+ superdocVersion: "2.22.0-next.15",
23
23
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
24
24
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
25
25
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
18
18
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
19
19
  var ENGINE_INFO = Object.freeze({
20
20
  ...PRIVATE_ENGINE_INFO,
21
- superdocVersion: "2.22.0-next.13",
21
+ superdocVersion: "2.22.0-next.15",
22
22
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
23
23
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
24
24
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -1,6 +1,6 @@
1
1
  import { NonFlowingPageRelativeAnchorDependencyProof, PageCheckpointDependencyClass, FlowBlock, Layout, LayoutBlockResumeCheckpoint, Measure, Page, HeaderFooterLayout, ColumnLayout } from '../../contracts/src/index.js';
2
2
  import { FontMeasureCapabilities, FontMeasureContext } from '../../../shared/font-system/src/index.js';
3
- import { LayoutOptions, HeaderFooterConstraints, LayoutExecutionCheckpoint } from '../../layout-engine/src/index.js';
3
+ import { LayoutContinuationResume, 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';
@@ -127,8 +127,28 @@ export type IncrementalLayoutResult = {
127
127
  * and `pageTokenTotalMs` includes token remeasure/relayout details.
128
128
  */
129
129
  bridgeTiming: IncrementalLayoutBridgeTiming;
130
+ progressive?: {
131
+ status: 'pending';
132
+ completedPageRange: {
133
+ startPageIndex: number;
134
+ endPageIndexExclusive: number;
135
+ };
136
+ completedRanges: readonly {
137
+ startOrdinal: number;
138
+ endOrdinalExclusive: number;
139
+ }[];
140
+ resume: LayoutContinuationResume;
141
+ continuation: IncrementalLayoutContinuation;
142
+ pageCountFieldsExact: false;
143
+ };
144
+ progressiveFallbackReason?: string;
145
+ };
146
+ export type IncrementalLayoutContinuation = {
147
+ advance(execution?: IncrementalLayoutExecutionControl): Promise<IncrementalLayoutResult>;
148
+ dispose(): void;
130
149
  };
131
150
  export type IncrementalLayoutBridgeTiming = {
151
+ paginationPreparationRejection?: string;
132
152
  /** Content-free reason a document used the conservative note fallback. */
133
153
  footnoteCoupledRejection?: string;
134
154
  totalMs: number;
@@ -184,6 +204,7 @@ export type IncrementalLayoutBridgeTiming = {
184
204
  pagesPaginated: number | null;
185
205
  pagesSplicedByReuse: number;
186
206
  paginationPasses: number;
207
+ paginationPreparationReuses?: number;
187
208
  pageTokenRelayouts: number;
188
209
  headerFooterPreLayoutReuses: number;
189
210
  headerFooterPreLayoutBodyBlocksEnumerated: number;
@@ -513,8 +534,14 @@ export interface IncrementalLayoutExecutionControl {
513
534
  yieldEveryBlocks?: number;
514
535
  /** Time-aware mounted probe. Null is the allocation-free under-budget path. */
515
536
  checkpointIfDue?: (checkpoint?: LayoutExecutionCheckpoint) => Promise<void> | null;
537
+ progressive?: {
538
+ firstBatchPageCount?: number;
539
+ restartBeforeBlockIndex?: number;
540
+ restartBeforePageIndex?: number;
541
+ };
516
542
  }
517
- export declare function incrementalLayout(previousBlocks: FlowBlock[], _previousLayout: Layout | null, nextBlocks: FlowBlock[], options: LayoutOptions, measureBlock: (block: FlowBlock, constraints: {
543
+ export declare function incrementalLayout(...args: Parameters<typeof incrementalLayoutComplete>): Promise<IncrementalLayoutResult>;
544
+ declare function incrementalLayoutComplete(previousBlocks: FlowBlock[], _previousLayout: Layout | null, nextBlocks: FlowBlock[], options: LayoutOptions, measureBlock: (block: FlowBlock, constraints: {
518
545
  maxWidth: number;
519
546
  maxHeight: number;
520
547
  }) => Promise<Measure>, headerFooter?: {
@@ -4,9 +4,9 @@ export type { HeaderFooterType } from '../../contracts/src/index.js';
4
4
  export { selectHeaderFooterVariantForPage, resolveEffectiveHeaderFooterRef, type HeaderFooterKind, type HeaderFooterVariant, type HeaderFooterSectionRefs, type HeaderFooterResolutionSection, type HeaderFooterVariantSelectionInput, type HeaderFooterEffectiveRefInput, type HeaderFooterEffectiveRefResult, } from '../../contracts/src/index.js';
5
5
  export { extractIdentifierFromConverter, getHeaderFooterType, defaultHeaderFooterIdentifier, resolveHeaderFooterForPage, buildMultiSectionIdentifier, defaultMultiSectionIdentifier, getHeaderFooterTypeForSection, getHeaderFooterIdForPage, resolveHeaderFooterForPageAndSection, } from './headerFooterUtils.js';
6
6
  export type { HeaderFooterIdentifier, MultiSectionHeaderFooterIdentifier, SectionHeaderFooterIds, } from './headerFooterUtils.js';
7
- export { layoutHeaderFooterWithCache, invalidateHeaderFooterMeasureCache, type HeaderFooterBatchResult, getBucketForPageNumber, getBucketRepresentative, } from './layoutHeaderFooter.js';
7
+ export { layoutHeaderFooterWithCache, createRetainedHeaderFooterPageReader, invalidateHeaderFooterMeasureCache, type HeaderFooterBatchResult, getBucketForPageNumber, getBucketRepresentative, } from './layoutHeaderFooter.js';
8
8
  export type { HeaderFooterBatch, DigitBucket } from './layoutHeaderFooter.js';
9
- export { resolveHeaderFooterTokens, PROVISIONAL_PAGE_COUNT_PLACEHOLDER, type ResolveHeaderFooterTokensOptions, } from './resolveHeaderFooterTokens.js';
9
+ export { resolveHeaderFooterTokens, cloneHeaderFooterBlocks, PROVISIONAL_PAGE_COUNT_PLACEHOLDER, type ResolveHeaderFooterTokensOptions, } from './resolveHeaderFooterTokens.js';
10
10
  export { buildPageStyleReferenceResolver, flowBlocksContainCrossReferenceMetadata, type PageStyleReferenceResolver, } from './resolveLiveCrossReferences.js';
11
11
  export { findWordBoundaries, findParagraphBoundaries } from './text-boundaries.js';
12
12
  export type { BoundaryRange } from './text-boundaries.js';
@@ -14,7 +14,7 @@ export { buildSectionAwareHeaderFooterLayoutKey, buildSectionContentWidth, build
14
14
  export type { HeaderFooterSectionKind, HeaderFooterRefs, SectionAwareHeaderFooterMeasurementGroup, } from './sectionAwareHeaderFooter.js';
15
15
  export { clearIncrementalModuleState, incrementalLayout, measureCache, normalizeMargin } from './incrementalLayout.js';
16
16
  export { hashMeasureContent } from './cache.js';
17
- export type { HeaderFooterLayoutResult, HeaderFooterGeometrySeed, IncrementalLayoutBridgeTiming, IncrementalLayoutResult, IncrementalLayoutExecutionControl, IncrementalMeasureReuseProof, IncrementalLayoutReuseOptions, IncrementalLayoutReuseSummary, IncrementalSectionPageNumberTransform, IncrementalLayoutTailAdoption, IncrementalLayoutTailDisposition, IncrementalPaginationProof, LayoutPositionTransform, FootnoteReserveSeed, } from './incrementalLayout.js';
17
+ export type { HeaderFooterLayoutResult, HeaderFooterGeometrySeed, IncrementalLayoutBridgeTiming, IncrementalLayoutResult, IncrementalLayoutExecutionControl, IncrementalLayoutContinuation, IncrementalMeasureReuseProof, IncrementalLayoutReuseOptions, IncrementalLayoutReuseSummary, IncrementalSectionPageNumberTransform, IncrementalLayoutTailAdoption, IncrementalLayoutTailDisposition, IncrementalPaginationProof, LayoutPositionTransform, FootnoteReserveSeed, } from './incrementalLayout.js';
18
18
  export { collectFootnoteLedgers, getPreferredReserveCandidates, getPreferredReserveTrialTargets, isMandatoryOnlyFootnotePage, scoreFootnoteWindow, summarizeFootnoteWindow, } from './footnote-scorer.js';
19
19
  export type { FootnotePreferredReserveCandidate, FootnoteWindowScoreInput, FootnoteWindowScoreReason, FootnoteWindowScoreResult, FootnoteWindowStats, } from './footnote-scorer.js';
20
20
  export { computeDisplayPageNumber } from '../../layout-engine/src/index.js';
@@ -85,6 +85,9 @@ export declare function getBucketForPageNumber(pageNumber: number): DigitBucket;
85
85
  * ```
86
86
  */
87
87
  export declare function getBucketRepresentative(bucket: DigitBucket): number;
88
+ type RetainedBucketContext = ReturnType<PageResolver>;
89
+ /** Reads only a measured bucket issued by this canonical layout operation. */
90
+ export declare function createRetainedHeaderFooterPageReader(layout: HeaderFooterLayout, blocks: FlowBlock[], constraints: HeaderFooterConstraints, fontSignature: string): ((context: RetainedBucketContext) => HeaderFooterLayout['pages'][number] | null) | null;
88
91
  export declare class HeaderFooterLayoutCache {
89
92
  private readonly cache;
90
93
  /** Drop every cached header/footer measure (equivalence-oracle cold start). */
@@ -128,3 +131,4 @@ export declare function invalidateHeaderFooterMeasureCache(blockIds: string[]):
128
131
  * @returns Batch result with layouts, blocks, and measures for each variant
129
132
  */
130
133
  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>;
134
+ export {};
@@ -40,19 +40,19 @@ export type AnchoredTableCollection = {
40
40
  * @param measures - Corresponding measures for each block
41
41
  * @returns Array of anchored drawings that should be pre-registered
42
42
  */
43
- export declare function collectPreRegisteredAnchorsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredDrawing[], void>;
43
+ export declare function collectPreRegisteredAnchorsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null, candidateIndices?: readonly number[]): Generator<LayoutWorkCheckpoint, AnchoredDrawing[], void>;
44
44
  export declare function collectPreRegisteredAnchors(blocks: FlowBlock[], measures: Measure[]): AnchoredDrawing[];
45
45
  /** Collect page- or margin-relative floating tables before paragraph layout. */
46
- export declare function collectPreRegisteredTablesSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredTable[], void>;
46
+ export declare function collectPreRegisteredTablesSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null, candidateIndices?: readonly number[]): Generator<LayoutWorkCheckpoint, AnchoredTable[], void>;
47
47
  /**
48
48
  * Collect anchored drawings (images/drawings) mapped to their anchor paragraph index.
49
49
  * Map of paragraph block index -> anchored images/drawings associated with that paragraph.
50
50
  */
51
- export declare function collectAnchoredDrawingsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredDrawingCollection, void>;
51
+ export declare function collectAnchoredDrawingsSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null, preparedParagraphIndexById?: Map<string, number>, candidateIndices?: readonly number[]): Generator<LayoutWorkCheckpoint, AnchoredDrawingCollection, void>;
52
52
  export declare function collectAnchoredDrawings(blocks: FlowBlock[], measures: Measure[]): AnchoredDrawingCollection;
53
53
  /**
54
54
  * Collect anchored/floating tables mapped to their anchor paragraph index.
55
55
  * Also returns anchored tables that have no paragraph to attach to.
56
56
  */
57
- export declare function collectAnchoredTablesSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null): Generator<LayoutWorkCheckpoint, AnchoredTableCollection, void>;
57
+ export declare function collectAnchoredTablesSteps(blocks: FlowBlock[], measures: Measure[], checkpointEveryBlocks?: number | null, preparedParagraphIndexById?: Map<string, number>, candidateIndices?: readonly number[]): Generator<LayoutWorkCheckpoint, AnchoredTableCollection, void>;
58
58
  export declare function collectAnchoredTables(blocks: FlowBlock[], measures: Measure[]): AnchoredTableCollection;
@@ -1,4 +1,4 @@
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:table-fragment' | 'layout-document:footnote-continuation' | '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';
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:paragraph-fragment' | 'layout-document:table-fragment' | 'layout-document:footnote-continuation' | '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
2
  export type LayoutExecutionCheckpoint = {
3
3
  phase: LayoutExecutionPhase;
4
4
  index?: number;
@@ -275,6 +275,33 @@ export type HeaderFooterConstraints = {
275
275
  */
276
276
  export declare function layoutDocument(blocks: FlowBlock[], measures: Measure[], options?: LayoutOptions): Layout;
277
277
  export declare function layoutDocumentCooperatively(blocks: FlowBlock[], measures: Measure[], options?: LayoutOptions, execution?: LayoutExecutionControl): Promise<Layout>;
278
+ export type LayoutContinuationResume = {
279
+ nextBlockIndex: number;
280
+ nextPageIndex: number;
281
+ pageIndex: number;
282
+ checkpointIdentity: object;
283
+ paragraphLineIndex?: number;
284
+ tableRowIndex?: number;
285
+ };
286
+ export type LayoutContinuationBatch = {
287
+ layout: Layout;
288
+ pageRange: {
289
+ startPageIndex: number;
290
+ endPageIndexExclusive: number;
291
+ };
292
+ status: 'pending' | 'complete';
293
+ resume: LayoutContinuationResume;
294
+ completeReason?: string;
295
+ };
296
+ export type LayoutDocumentContinuation = {
297
+ advance(input?: {
298
+ pageCount?: number;
299
+ execution?: LayoutExecutionControl;
300
+ }): Promise<LayoutContinuationBatch>;
301
+ dispose(): void;
302
+ };
303
+ /** AIDEV-NOTE: The handle owns one live paginator; advancing never replays a stopped prefix. */
304
+ export declare function createLayoutDocumentContinuation(blocks: FlowBlock[], measures: Measure[], options?: LayoutOptions, execution?: LayoutExecutionControl): LayoutDocumentContinuation;
278
305
  export type LayoutRangeBoundaryPolicy = 'conservative-context' | 'overscan' | 'degraded-on-incomplete-state';
279
306
  export type LayoutRangeExactness = 'exact' | 'pending-layout' | 'degraded-unsupported' | 'stale';
280
307
  export type LayoutRangeSourceRange = {
@@ -6,4 +6,7 @@ import { FlowBlock, Measure, Page } from '../../contracts/src/index.js';
6
6
  * is laid out. Reposition only its paint fragment once that carrier's measured
7
7
  * baseline is known; later flow remains untouched.
8
8
  */
9
- export declare function alignInlineZeroHeightDrawingFragments(pages: Page[], blocks: FlowBlock[], measures: Measure[]): void;
9
+ export declare function alignInlineZeroHeightDrawingFragments(pages: Page[], blocks: FlowBlock[], measures: Measure[], indices?: {
10
+ blockById: ReadonlyMap<string, FlowBlock>;
11
+ measureById: ReadonlyMap<string, Measure | undefined>;
12
+ }): void;
@@ -1,7 +1,7 @@
1
1
  import { FloatingObjectManager } from './floating-objects.js';
2
2
  import { PageState } from './paginator.js';
3
3
  import { FootnotePageFlow } from './footnote-page-flow.js';
4
- import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure, ParagraphLineRegion, ColumnLayoutForAnchor } from '../../contracts/src/index.js';
4
+ import { PageMargins, ParagraphBlock, ParagraphMeasure, ImageBlock, ImageMeasure, DrawingBlock, DrawingMeasure, TableBlock, TableMeasure, ParagraphLineRegion, ColumnLayoutForAnchor } from '../../contracts/src/index.js';
5
5
  import { AnchoredTable } from './anchors.js';
6
6
  /**
7
7
  * SD-2656: ordered footnote anchor entry. The body slicer reads the candidate
@@ -99,6 +99,7 @@ export type AnchoredDrawingEntry = {
99
99
  export type ParagraphAnchorsContext = {
100
100
  anchoredDrawings?: AnchoredDrawingEntry[];
101
101
  anchoredTables?: AnchoredTable[];
102
+ resolveCurrentTable?: (id: string, measure: TableMeasure) => TableBlock;
102
103
  columnWidth: number;
103
104
  pageWidth: number;
104
105
  pageMargins: PageMargins;
@@ -106,4 +107,8 @@ export type ParagraphAnchorsContext = {
106
107
  columns: ColumnLayoutForAnchor;
107
108
  placedAnchoredIds: Set<string>;
108
109
  };
110
+ export declare function layoutParagraphBlockSteps(ctx: ParagraphLayoutContext, anchors?: ParagraphAnchorsContext): Generator<{
111
+ index: number;
112
+ total: number;
113
+ }, void, void>;
109
114
  export declare function layoutParagraphBlock(ctx: ParagraphLayoutContext, anchors?: ParagraphAnchorsContext): void;
@@ -66,5 +66,5 @@ export type SectionPropsScanCheckpoint = {
66
66
  index: number;
67
67
  total: number;
68
68
  };
69
- export declare function computeNextSectionPropsAtBreakSteps(blocks: FlowBlock[], checkpointEveryBlocks?: number | null): Generator<SectionPropsScanCheckpoint, Map<number, SectionProps>, void>;
69
+ export declare function computeNextSectionPropsAtBreakSteps(blocks: FlowBlock[], checkpointEveryBlocks?: number | null, candidateIndices?: readonly number[]): Generator<SectionPropsScanCheckpoint, Map<number, SectionProps>, void>;
70
70
  export declare function computeNextSectionPropsAtBreak(blocks: FlowBlock[]): Map<number, SectionProps>;
@@ -0,0 +1,52 @@
1
+ import { FlowBlock, Measure } from '../../contracts/src/index.js';
2
+ export type CanonicalPaginationSourceSplice = {
3
+ readonly previous: readonly FlowBlock[];
4
+ readonly current: readonly FlowBlock[];
5
+ readonly authoredChangedBlockIds: readonly string[];
6
+ readonly replacements: readonly {
7
+ start: number;
8
+ deleteCount: number;
9
+ insertCount: number;
10
+ }[];
11
+ };
12
+ export type PaginationSourceScan = {
13
+ readonly blocks: FlowBlock[];
14
+ readonly measures: Measure[];
15
+ readonly indexById: ReadonlyMap<string, number>;
16
+ readonly candidateIds: readonly string[];
17
+ readonly dependencyIds?: readonly string[];
18
+ readonly offset: number;
19
+ readonly isCurrent?: () => boolean;
20
+ };
21
+ /**
22
+ * Trusted internal dependency injection for the canonical host source issuer.
23
+ * This constructor is intentionally absent from the engine's main exports;
24
+ * opaque tokens offered by generic bridge callers have no authority here.
25
+ */
26
+ export declare function createCanonicalPaginationSourceReader(read: (previous: readonly FlowBlock[], current: readonly FlowBlock[]) => CanonicalPaginationSourceSplice | null, owns: (source: readonly FlowBlock[]) => boolean): object;
27
+ export declare function isPaginationPreparationCandidate(block: FlowBlock): boolean;
28
+ /** Only the engine's completed input validation issues a scan plan. */
29
+ export declare function retainPaginationSourceScan(blocks: FlowBlock[], measures: Measure[], indexById: ReadonlyMap<string, number>, candidateIds: readonly string[]): void;
30
+ export declare function readPaginationSourceScan(blocks: FlowBlock[], measures: Measure[], requirePrepared?: boolean): PaginationSourceScan | null;
31
+ /**
32
+ * The canonical owner certifies the exact immutable source recipe. The bridge
33
+ * separately proves its current dirty measures and index rewrites before calling.
34
+ * Foreign/copy tokens and mismatched source or measure vectors lose the shortcut.
35
+ */
36
+ export declare function prepareCanonicalPaginationSource(input: {
37
+ reader: object;
38
+ previousBlocks: FlowBlock[];
39
+ blocks: FlowBlock[];
40
+ previousMeasures: Measure[];
41
+ measures: Measure[];
42
+ dirtyBlockIds: readonly string[];
43
+ currentIndexById: ReadonlyMap<string, number>;
44
+ previousToCurrentBlockId?: ReadonlyMap<string, string> | null;
45
+ onReject?: (reason: string) => void;
46
+ }): boolean;
47
+ /** Only an owned prepared scan may substitute metadata for a clean table preflight read. */
48
+ export declare function createPreparedPaginationMetadataView(blocks: FlowBlock[], measures: Measure[]): FlowBlock[];
49
+ export declare function createPreparedPaginationSuffix(blocks: FlowBlock[], measures: Measure[], start: number, end: number): {
50
+ blocks: FlowBlock[];
51
+ measures: Measure[];
52
+ } | null;
@@ -276,3 +276,9 @@ export type WindowPositionRemapPlan = {
276
276
  * sequences — no per-paint key strings or Maps on the steady-state path.
277
277
  */
278
278
  export declare function planWindowPositionRemap(state: PageDomState, resolvedPage: ResolvedPage): WindowPositionRemapPlan;
279
+ export declare function planDetachedPageFragments(ctx: PageContentContext, state: PageDomState | undefined, page: ResolvedPage, pageIndex: number): Generator<void, {
280
+ item: ResolvedPaintItem;
281
+ context: FragmentRenderContext;
282
+ sdtBoundary?: SdtBoundaryOptions;
283
+ betweenInfo?: BetweenBorderInfo;
284
+ }[], void>;
@@ -1,3 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { DropCapDescriptor, Line, ParagraphBlock, ParagraphMeasure, ResolvedParagraphContent, Run, SdtMetadata, SourceAnchor } from '../../../../contracts/src/index.js';
2
3
  import { MinimalWordLayout } from '../../../../../../shared/common/list-marker-utils';
3
4
  import { ResolvePhysicalFamily } from '../../../../../shared/font-system/src/index.js';
@@ -20,7 +21,7 @@ export type ParagraphRenderLineInput = {
20
21
  indentOffsetOverride?: number;
21
22
  paragraphMarkLeftOffsetOverride?: number;
22
23
  };
23
- export type ParagraphRenderLine = (input: ParagraphRenderLineInput) => HTMLElement;
24
+ export type ParagraphRenderLine = (input: ParagraphRenderLineInput) => HTMLElement | RenderWork<HTMLElement>;
24
25
  export type ParagraphRenderDropCap = (descriptor: DropCapDescriptor, measure?: {
25
26
  width: number;
26
27
  height: number;
@@ -83,5 +84,6 @@ export type RenderParagraphContentResult = {
83
84
  totalHeight: number;
84
85
  renderedLines: RenderedParagraphLineInfo[];
85
86
  };
87
+ export declare function renderParagraphContentWork(params: RenderParagraphContentParams): RenderWork<RenderParagraphContentResult>;
86
88
  export declare const renderParagraphContent: (params: RenderParagraphContentParams) => RenderParagraphContentResult;
87
89
  export {};
@@ -1,3 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { ParaFragment, ResolvedFragmentItem, SdtMetadata } from '../../../../contracts/src/index.js';
2
3
  import { ResolvePhysicalFamily } from '../../../../../shared/font-system/src/index.js';
3
4
  import { SdtBoundaryOptions } from '../sdt/container.js';
@@ -15,7 +16,7 @@ type RenderParagraphFragmentParams = {
15
16
  applyFragmentFrame: (el: HTMLElement, fragment: ParaFragment) => void;
16
17
  applySdtDataset: (el: HTMLElement | null, metadata?: SdtMetadata | null) => void;
17
18
  applyContainerSdtDataset: (el: HTMLElement | null, metadata?: SdtMetadata | null) => void;
18
- renderLine: (input: ParagraphRenderLineInput) => HTMLElement;
19
+ renderLine: (input: ParagraphRenderLineInput) => HTMLElement | RenderWork<HTMLElement>;
19
20
  captureLineSnapshot: (lineEl: HTMLElement, options?: {
20
21
  sourceAnchor?: ResolvedFragmentItem['sourceAnchor'];
21
22
  wrapperEl?: HTMLElement;
@@ -29,5 +30,6 @@ type RenderParagraphFragmentParams = {
29
30
  */
30
31
  resolvePhysical?: ResolvePhysicalFamily;
31
32
  };
33
+ export declare function renderParagraphFragmentWork(params: RenderParagraphFragmentParams): RenderWork<HTMLElement>;
32
34
  export declare const renderParagraphFragment: (params: RenderParagraphFragmentParams) => HTMLElement;
33
35
  export {};
@@ -75,8 +75,8 @@ export type DomPainterPersistentPageInput = {
75
75
  };
76
76
  /** Shell registry entry: the persistent page root and its geometry/style reuse key. */
77
77
  export type PersistentShellEntry = {
78
- element: HTMLElement;
79
- shellKey: string;
78
+ readonly element: HTMLElement;
79
+ readonly shellKey: string;
80
80
  };
81
81
  /** Bounded content state for one hydrated page. */
82
82
  export type PersistentContentEntry = {
@@ -94,9 +94,10 @@ export type PersistentPageSurfaceState = {
94
94
  mount: HTMLElement;
95
95
  /** The committed scaffold; reference identity gates the O(1) skip. */
96
96
  scaffold: DomPainterPersistentScaffold;
97
- shells: Map<number, PersistentShellEntry>;
97
+ shells: ReadonlyMap<number, PersistentShellEntry>;
98
98
  content: Map<number, PersistentContentEntry>;
99
99
  integrity: PersistentSurfaceIntegrity;
100
+ shellStyleSignature: string;
100
101
  };
101
102
  /**
102
103
  * The narrow renderer capabilities this module consumes. The deep
@@ -141,6 +142,6 @@ export declare function disposePersistentPageSurfaceState(state: PersistentPageS
141
142
  * shell registry by page index; the content window reconciles every call.
142
143
  */
143
144
  export declare function reconcilePersistentPageSurface(ctx: PersistentSurfaceRenderContext, previous: PersistentPageSurfaceState | null, input: DomPainterPersistentPageInput, mount: HTMLElement): PersistentPageSurfaceState;
144
- /** Deep-clone the retained planes for the painter's rollback snapshot. */
145
+ /** Snapshot mutable content metadata; scaffold reconciliation replaces the shell registry. */
145
146
  export declare function clonePersistentPageSurfaceState(state: PersistentPageSurfaceState | null, clonePageState: (pageState: PageDomState) => PageDomState): PersistentPageSurfaceState | null;
146
147
  export {};
@@ -135,6 +135,7 @@ export declare class PositionValidationCollector {
135
135
  private verboseLines;
136
136
  private suppressedConsole;
137
137
  constructor(options?: PositionValidationOptions);
138
+ clone(policy?: PositionValidationConsolePolicy): PositionValidationCollector;
138
139
  get isEnabled(): boolean;
139
140
  record(obs: RunPositionObservation): void;
140
141
  /** Verbose-mode: one content-free warning per NEW structural key, capped. */
@@ -0,0 +1,3 @@
1
+ export type RenderWork<T> = Generator<void, T, void>;
2
+ export declare function completeRenderWork<T>(work: RenderWork<T>): T;
3
+ export declare function resolveRenderWork<T>(value: T | RenderWork<T>): RenderWork<T>;
@@ -236,6 +236,7 @@ type PainterFragmentFailure = {
236
236
  readonly code: 'painter-fragment-unavailable';
237
237
  };
238
238
  type PersistentPagePainterTransaction = {
239
+ prepareCommit(): void;
239
240
  commit(): void;
240
241
  rollback(): void;
241
242
  readFragmentFailures(): readonly PainterFragmentFailure[];
@@ -254,6 +255,11 @@ export declare class DomPainter {
254
255
  private totalPages;
255
256
  private sectionPageCounts;
256
257
  private linkIdCounter;
258
+ private retainedPaintRevision;
259
+ private preparedDecorations;
260
+ private preparedFragments;
261
+ private detachedPreparationActive;
262
+ private detachedFragmentFailures;
257
263
  private shapeImageFillCounter;
258
264
  private wordArtPathCounter;
259
265
  private sdtLabelsRendered;
@@ -306,7 +312,7 @@ export declare class DomPainter {
306
312
  * live persistent surface and fresh-state oracle never mix counts.
307
313
  * Dark unless enabled via options; when dark, `record()` is a single branch.
308
314
  */
309
- private readonly positionValidation;
315
+ private positionValidation;
310
316
  private paintSnapshotBuilder;
311
317
  private lastPaintSnapshot;
312
318
  private onPaintSnapshotCallback;
@@ -316,7 +322,7 @@ export declare class DomPainter {
316
322
  * from the public DomPainterHandle contract.
317
323
  */
318
324
  private activePersistentPageTransaction;
319
- private persistentPageIndices;
325
+ private persistentPageCount;
320
326
  /** Resolved layout for the next-gen paint pipeline. */
321
327
  private resolvedLayout;
322
328
  private showFormattingMarks;
@@ -358,8 +364,7 @@ export declare class DomPainter {
358
364
  beginPersistentPageTransaction(): PersistentPagePainterTransaction;
359
365
  private capturePersistentPagePainterState;
360
366
  private restorePersistentPagePainterState;
361
- private createAllPageIndices;
362
- private setPersistentPageIndices;
367
+ private setPersistentPageCount;
363
368
  private emitPaintSnapshot;
364
369
  private beginPaintSnapshot;
365
370
  private finalizePaintSnapshotFromBuilder;
@@ -367,6 +372,19 @@ export declare class DomPainter {
367
372
  private collectPaintSnapshotFromDomRoot;
368
373
  /** Semantic continuous paint. Paginated flow has only `paintPersistentPages()`. */
369
374
  paint(input: DomPainterInput, mount: HTMLElement, mapping?: PositionMapping): void;
375
+ /** Prepare detached content before the host opens its atomic visible transaction. */
376
+ preparePersistentPages(input: DomPainterPersistentPageInput, options: {
377
+ mount: HTMLElement;
378
+ signal?: AbortSignal;
379
+ yieldToHost?: (checkpoint: {
380
+ phase: 'paint:content';
381
+ index: number;
382
+ total: number;
383
+ }) => Promise<void>;
384
+ }): Promise<{
385
+ input: DomPainterPersistentPageInput;
386
+ discard(): void;
387
+ }>;
370
388
  /**
371
389
  * The persistent paginated reconcile (default persistent page geometry
372
390
  * plan, Unit 1): one generation-scoped scaffold owns every page root for
@@ -414,6 +432,7 @@ export declare class DomPainter {
414
432
  */
415
433
  private resolveSeparatorColumnGeometry;
416
434
  private renderDecorationsForPage;
435
+ private renderDecorationsForPageWork;
417
436
  /**
418
437
  * Check if a fragment is vertically anchored to the page.
419
438
  * Used to determine special Y positioning for page-relative anchored content
@@ -434,7 +453,7 @@ export declare class DomPainter {
434
453
  */
435
454
  private getDecorationAnchorPageOriginY;
436
455
  private getFooterFragmentAnchorPageOriginY;
437
- private renderDecorationSection;
456
+ private renderDecorationSectionWork;
438
457
  private resetState;
439
458
  dispose(): void;
440
459
  private getSectionPageCount;
@@ -467,6 +486,7 @@ export declare class DomPainter {
467
486
  private applySemanticPageOverrides;
468
487
  private getEffectivePageStyles;
469
488
  private renderFragment;
489
+ private renderFragmentWork;
470
490
  /**
471
491
  * Renders a paragraph fragment with defensive error handling.
472
492
  * Falls back to error placeholder on rendering errors to prevent full paint failure.
@@ -477,6 +497,7 @@ export declare class DomPainter {
477
497
  * @returns HTMLElement containing the rendered fragment or error placeholder
478
498
  */
479
499
  private renderParagraphFragment;
500
+ private renderParagraphFragmentWork;
480
501
  private createErrorPlaceholder;
481
502
  private renderImageFragment;
482
503
  /**
@@ -606,7 +627,9 @@ export declare class DomPainter {
606
627
  /** Render drawing content nested in any canonical table, including a textbox-owned table. */
607
628
  private renderDrawingContentForTable;
608
629
  private renderTableFragment;
630
+ private renderTableFragmentWork;
609
631
  private renderLine;
632
+ private renderLineWork;
610
633
  private createRunRenderContext;
611
634
  private defaultFragmentRenderContext;
612
635
  /**
@@ -1,2 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { RenderLineParams } from './types.js';
2
- export declare const renderLine: ({ block, line, context, availableWidthOverride, lineIndex, skipJustify, preExpandedRuns, resolvedListTextStartPx, indentOffsetOverride, paragraphMarkLeftOffsetOverride, runContext, }: RenderLineParams) => HTMLElement;
3
+ export declare function renderLineWork({ block, line, context, availableWidthOverride, lineIndex, skipJustify, preExpandedRuns, resolvedListTextStartPx, indentOffsetOverride, paragraphMarkLeftOffsetOverride, runContext, }: RenderLineParams): RenderWork<HTMLElement>;
4
+ export declare const renderLine: (params: RenderLineParams) => HTMLElement;
@@ -46,7 +46,7 @@ export declare const renderInlineTabRun: (run: Extract<Run, {
46
46
  tabWidthFromCache?: number) => HTMLElement;
47
47
  export declare const renderPositionedTabRun: (run: Extract<Run, {
48
48
  kind: "tab";
49
- }>, line: Line, doc: Document, layoutEpoch: number, tabStartX: number, indentOffset: number, immediateNextSegment?: LineSegment, styleId?: string, paintUnderline?: boolean) => {
49
+ }>, line: Line, doc: Document, layoutEpoch: number, tabStartX: number, indentOffset: number, immediateNextSegment?: LineSegment, styleId?: string, paintUnderline?: boolean, tabWidthFromCache?: number) => {
50
50
  element: HTMLElement;
51
51
  tabEndX: number;
52
52
  actualTabWidth: number;
@@ -1,3 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { CellBorders, DrawingBlock, DrawingMeasure, ImageBlock, Line, ParagraphBlock, SdtMetadata, TableBlock, TableCell, TableMeasure } from '../../../../contracts/src/index.js';
2
3
  import { ResolvePhysicalFamily } from '../../../../../shared/font-system/src/index.js';
3
4
  import { FragmentRenderContext } from '../renderer.js';
@@ -57,7 +58,7 @@ type TableCellRenderDependencies = {
57
58
  /** Whether to apply default border if no borders specified */
58
59
  useDefaultBorder?: boolean;
59
60
  /** Function to render a line of paragraph content */
60
- renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean, resolvedListTextStartPx?: number) => HTMLElement;
61
+ renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean, resolvedListTextStartPx?: number) => HTMLElement | RenderWork<HTMLElement>;
61
62
  /** Optional callback invoked after a table line's final styles/markers are applied. */
62
63
  captureLineSnapshot?: (lineEl: HTMLElement, context: FragmentRenderContext, options?: {
63
64
  inTableParagraph?: boolean;
@@ -166,5 +167,6 @@ export type TableCellRenderResult = {
166
167
  * container.appendChild(cellElement);
167
168
  * ```
168
169
  */
170
+ export declare function renderTableCellWork(deps: TableCellRenderDependencies): RenderWork<TableCellRenderResult>;
169
171
  export declare const renderTableCell: (deps: TableCellRenderDependencies) => TableCellRenderResult;
170
172
  export {};
@@ -1,3 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { DrawingBlock, DrawingMeasure, Fragment, Line, ParagraphBlock, SdtMetadata, TableBlock, TableFragment, TableMeasure } from '../../../../contracts/src/index.js';
2
3
  import { ResolvePhysicalFamily } from '../../../../../shared/font-system/src/index.js';
3
4
  import { FragmentRenderContext } from '../renderer.js';
@@ -39,7 +40,7 @@ export type TableRenderDependencies = {
39
40
  /** Built-in SDT chrome rendering mode. */
40
41
  chrome?: 'default' | 'none';
41
42
  /** Function to render a line of paragraph content */
42
- renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean, resolvedListTextStartPx?: number) => HTMLElement;
43
+ renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean, resolvedListTextStartPx?: number) => HTMLElement | RenderWork<HTMLElement>;
43
44
  /** Optional callback invoked after a table line's final styles/markers are applied. */
44
45
  captureLineSnapshot?: (lineEl: HTMLElement, context: FragmentRenderContext, options?: {
45
46
  inTableParagraph?: boolean;
@@ -128,5 +129,6 @@ export type TableRenderDependencies = {
128
129
  * container.appendChild(tableElement);
129
130
  * ```
130
131
  */
132
+ export declare function renderTableFragmentWork(deps: TableRenderDependencies): RenderWork<HTMLElement>;
131
133
  export declare const renderTableFragment: (deps: TableRenderDependencies) => HTMLElement;
132
134
  export {};
@@ -1,3 +1,4 @@
1
+ import { RenderWork } from '../render-work.js';
1
2
  import { DrawingBlock, DrawingMeasure, Line, ParagraphBlock, PartialRowInfo, SdtMetadata, TableBlock, TableBorders, TableMeasure } from '../../../../contracts/src/index.js';
2
3
  import { ResolvePhysicalFamily } from '../../../../../shared/font-system/src/index.js';
3
4
  import { FragmentRenderContext } from '../renderer.js';
@@ -59,7 +60,7 @@ type TableRowRenderDependencies = {
59
60
  /** Rendering context */
60
61
  context: FragmentRenderContext;
61
62
  /** Function to render a line of paragraph content */
62
- renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean) => HTMLElement;
63
+ renderLine: (block: ParagraphBlock, line: Line, context: FragmentRenderContext, lineIndex: number, isLastLine: boolean) => HTMLElement | RenderWork<HTMLElement>;
63
64
  /** Optional callback invoked after a table line's final styles/markers are applied. */
64
65
  captureLineSnapshot?: (lineEl: HTMLElement, context: FragmentRenderContext, options?: {
65
66
  inTableParagraph?: boolean;
@@ -145,5 +146,6 @@ type TableRowRenderDependencies = {
145
146
  * // Appends all cell elements to container
146
147
  * ```
147
148
  */
149
+ export declare function renderTableRowWork(deps: TableRowRenderDependencies): RenderWork<void>;
148
150
  export declare const renderTableRow: (deps: TableRowRenderDependencies) => void;
149
151
  export {};
package/dist/superdoc.cjs CHANGED
@@ -316,7 +316,7 @@ var shuffleArray = (array) => {
316
316
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
317
317
  function getSuperdocVersion() {
318
318
  try {
319
- return "2.22.0-next.13";
319
+ return "2.22.0-next.15";
320
320
  } catch {
321
321
  return "unknown";
322
322
  }
@@ -46382,7 +46382,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46382
46382
  this.config.colors = shuffleArray(this.config.colors);
46383
46383
  this.userColorMap = /* @__PURE__ */ new Map();
46384
46384
  this.colorIndex = 0;
46385
- this.version = "2.22.0-next.13";
46385
+ this.version = "2.22.0-next.15";
46386
46386
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46387
46387
  this.superdocId = config.superdocId || require_uuid.v4();
46388
46388
  this.colors = this.config.colors ?? [];
@@ -314,7 +314,7 @@ var shuffleArray = (array) => {
314
314
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
315
315
  function getSuperdocVersion() {
316
316
  try {
317
- return "2.22.0-next.13";
317
+ return "2.22.0-next.15";
318
318
  } catch {
319
319
  return "unknown";
320
320
  }
@@ -46311,7 +46311,7 @@ var SuperDoc = class extends import_eventemitter3.default {
46311
46311
  this.config.colors = shuffleArray(this.config.colors);
46312
46312
  this.userColorMap = /* @__PURE__ */ new Map();
46313
46313
  this.colorIndex = 0;
46314
- this.version = "2.22.0-next.13";
46314
+ this.version = "2.22.0-next.15";
46315
46315
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46316
46316
  this.superdocId = config.superdocId || v4();
46317
46317
  this.colors = this.config.colors ?? [];