@beyondwork/docx-react-component 1.0.104 → 1.0.106
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.
- package/package.json +1 -1
- package/src/api/public-types.ts +3 -0
- package/src/api/v3/_create.ts +9 -2
- package/src/api/v3/ai/_audit-reference.ts +28 -0
- package/src/api/v3/ai/_pe2-evidence.ts +419 -0
- package/src/api/v3/ai/attach.ts +22 -2
- package/src/api/v3/ai/bundle.ts +18 -6
- package/src/api/v3/ai/inspect.ts +12 -2
- package/src/api/v3/ai/replacement.ts +124 -0
- package/src/api/v3/index.ts +7 -0
- package/src/api/v3/ui/_types.ts +139 -0
- package/src/api/v3/ui/index.ts +9 -0
- package/src/api/v3/ui/overlays.ts +104 -0
- package/src/api/v3/ui/viewport.ts +97 -0
- package/src/model/layout/index.ts +3 -0
- package/src/model/layout/page-graph-types.ts +118 -0
- package/src/model/layout/runtime-page-graph-types.ts +13 -0
- package/src/runtime/document-runtime.ts +39 -18
- package/src/runtime/event-refresh-hints.ts +33 -6
- package/src/runtime/geometry/geometry-facet.ts +9 -1
- package/src/runtime/geometry/geometry-index.ts +461 -10
- package/src/runtime/geometry/geometry-types.ts +6 -0
- package/src/runtime/geometry/object-handles.ts +7 -4
- package/src/runtime/layout/layout-engine-instance.ts +2 -0
- package/src/runtime/layout/layout-engine-version.ts +36 -1
- package/src/runtime/layout/page-graph.ts +697 -10
- package/src/runtime/layout/paginated-layout-engine.ts +10 -0
- package/src/runtime/layout/project-block-fragments.ts +187 -8
- package/src/runtime/layout/public-facet.ts +236 -0
- package/src/runtime/prerender/graph-canonicalize.ts +14 -0
- package/src/runtime/workflow/index.ts +1 -0
- package/src/runtime/workflow/overlay-lanes.ts +228 -0
- package/src/ui/presence-overlay-lane.ts +131 -0
- package/src/ui/ui-controller-factory.ts +21 -0
|
@@ -1791,6 +1791,16 @@ export function paginateSectionBlocksWithSplits(
|
|
|
1791
1791
|
to: refRange.blockTo,
|
|
1792
1792
|
heightTwips: heightTwips + FOOTNOTE_REFERENCE_RESERVATION_TWIPS,
|
|
1793
1793
|
kind: "whole",
|
|
1794
|
+
layoutObject: {
|
|
1795
|
+
objectId: `footnote-body:${fragmentId}`,
|
|
1796
|
+
kind: "footnote-body",
|
|
1797
|
+
sourceBlockId: `note-body-${noteKind}-${noteId}`,
|
|
1798
|
+
paginationRole: "whole",
|
|
1799
|
+
measuredExtentTwips: {
|
|
1800
|
+
heightTwips: heightTwips + FOOTNOTE_REFERENCE_RESERVATION_TWIPS,
|
|
1801
|
+
widthTwips: effectiveColumnWidth,
|
|
1802
|
+
},
|
|
1803
|
+
},
|
|
1794
1804
|
};
|
|
1795
1805
|
|
|
1796
1806
|
allocations.push(allocation);
|
|
@@ -126,6 +126,14 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
126
126
|
if (pageIndex === null) continue;
|
|
127
127
|
|
|
128
128
|
const columnIndex = columnIndexFor(pageIndex, block.blockId);
|
|
129
|
+
const heightTwips = measuredHeightFor(
|
|
130
|
+
pageIndex,
|
|
131
|
+
block.blockId,
|
|
132
|
+
estimateBlockHeightFromSpan(block),
|
|
133
|
+
);
|
|
134
|
+
const widthTwips = fragmentMeasurementsByPageIndex
|
|
135
|
+
?.get(pageIndex)
|
|
136
|
+
?.get(block.blockId)?.widthTwips;
|
|
129
137
|
const fragment: FragmentWithoutPageId = {
|
|
130
138
|
fragmentId: `fragment-${block.blockId}`,
|
|
131
139
|
blockId: block.blockId,
|
|
@@ -133,13 +141,16 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
133
141
|
regionKind: "body",
|
|
134
142
|
from: block.from,
|
|
135
143
|
to: block.to,
|
|
136
|
-
heightTwips
|
|
137
|
-
pageIndex,
|
|
138
|
-
block.blockId,
|
|
139
|
-
estimateBlockHeightFromSpan(block),
|
|
140
|
-
),
|
|
144
|
+
heightTwips,
|
|
141
145
|
...deriveStyleMetadata(block),
|
|
142
146
|
kind: "whole",
|
|
147
|
+
layoutObject: buildFragmentLayoutObject({
|
|
148
|
+
block,
|
|
149
|
+
fragmentId: `fragment-${block.blockId}`,
|
|
150
|
+
heightTwips,
|
|
151
|
+
widthTwips,
|
|
152
|
+
paginationRole: "whole",
|
|
153
|
+
}),
|
|
143
154
|
...(columnIndex !== undefined ? { columnIndex } : {}),
|
|
144
155
|
};
|
|
145
156
|
|
|
@@ -224,6 +235,7 @@ function emitSlicedParagraph(
|
|
|
224
235
|
): void {
|
|
225
236
|
for (let i = 0; i < slices.length; i += 1) {
|
|
226
237
|
const slice = slices[i]!;
|
|
238
|
+
const heightTwips = slice.heightTwips ?? estimateSliceHeightFromLines(slice.lineRange);
|
|
227
239
|
const fragment: FragmentWithoutPageId = {
|
|
228
240
|
fragmentId: `fragment-${block.blockId}-slice-${i}`,
|
|
229
241
|
blockId: block.blockId,
|
|
@@ -231,15 +243,38 @@ function emitSlicedParagraph(
|
|
|
231
243
|
regionKind: "body",
|
|
232
244
|
from: block.from,
|
|
233
245
|
to: block.to,
|
|
234
|
-
heightTwips
|
|
246
|
+
heightTwips,
|
|
235
247
|
...deriveStyleMetadata(block),
|
|
236
248
|
kind: "paragraph-slice",
|
|
237
249
|
paragraphLineRange: slice.lineRange,
|
|
250
|
+
continuation: buildParagraphContinuationCursor(slice, i, slices.length),
|
|
251
|
+
layoutObject: buildFragmentLayoutObject({
|
|
252
|
+
block,
|
|
253
|
+
fragmentId: `fragment-${block.blockId}-slice-${i}`,
|
|
254
|
+
heightTwips,
|
|
255
|
+
widthTwips: slice.widthTwips,
|
|
256
|
+
paginationRole: slice.lineRange.from > 0 ? "continuation" : "slice",
|
|
257
|
+
}),
|
|
238
258
|
};
|
|
239
259
|
emit(slice.pageIndex, fragment);
|
|
240
260
|
}
|
|
241
261
|
}
|
|
242
262
|
|
|
263
|
+
function buildParagraphContinuationCursor(
|
|
264
|
+
slice: ParagraphLineSlice,
|
|
265
|
+
sequenceIndex: number,
|
|
266
|
+
sliceCount: number,
|
|
267
|
+
): NonNullable<RuntimeBlockFragment["continuation"]> {
|
|
268
|
+
return {
|
|
269
|
+
kind: "paragraph",
|
|
270
|
+
sequenceIndex,
|
|
271
|
+
sliceCount,
|
|
272
|
+
lineRange: slice.lineRange,
|
|
273
|
+
continuesFromPreviousPage: slice.lineRange.from > 0,
|
|
274
|
+
continuesToNextPage: slice.lineRange.to < slice.lineRange.totalLines,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
243
278
|
function estimateSliceHeightFromLines(lineRange: {
|
|
244
279
|
from: number;
|
|
245
280
|
to: number;
|
|
@@ -259,12 +294,13 @@ function estimateSliceHeightFromLines(lineRange: {
|
|
|
259
294
|
* every continuation page.
|
|
260
295
|
*/
|
|
261
296
|
function emitSlicedTable(
|
|
262
|
-
block: SurfaceBlockSnapshot,
|
|
297
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
263
298
|
slices: readonly TableRowSlice[],
|
|
264
299
|
emit: (pageIndex: number, fragment: FragmentWithoutPageId) => void,
|
|
265
300
|
): void {
|
|
266
301
|
for (let i = 0; i < slices.length; i += 1) {
|
|
267
302
|
const slice = slices[i]!;
|
|
303
|
+
const heightTwips = slice.heightTwips ?? estimateSliceHeightFromRows(slice.rowRange);
|
|
268
304
|
const fragment: FragmentWithoutPageId = {
|
|
269
305
|
fragmentId: `fragment-${block.blockId}-rowslice-${i}`,
|
|
270
306
|
blockId: block.blockId,
|
|
@@ -272,16 +308,106 @@ function emitSlicedTable(
|
|
|
272
308
|
regionKind: "body",
|
|
273
309
|
from: block.from,
|
|
274
310
|
to: block.to,
|
|
275
|
-
heightTwips
|
|
311
|
+
heightTwips,
|
|
276
312
|
...deriveStyleMetadata(block),
|
|
277
313
|
kind: "table-slice",
|
|
278
314
|
tableRowRange: slice.rowRange,
|
|
315
|
+
continuation: buildTableContinuationCursor(block, slice, i, slices.length),
|
|
316
|
+
layoutObject: buildFragmentLayoutObject({
|
|
317
|
+
block,
|
|
318
|
+
fragmentId: `fragment-${block.blockId}-rowslice-${i}`,
|
|
319
|
+
heightTwips,
|
|
320
|
+
paginationRole: slice.rowRange.from > 0 ? "continuation" : "slice",
|
|
321
|
+
}),
|
|
279
322
|
...(slice.columnIndex !== undefined ? { columnIndex: slice.columnIndex } : {}),
|
|
280
323
|
};
|
|
281
324
|
emit(slice.pageIndex, fragment);
|
|
282
325
|
}
|
|
283
326
|
}
|
|
284
327
|
|
|
328
|
+
function buildTableContinuationCursor(
|
|
329
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
330
|
+
slice: TableRowSlice,
|
|
331
|
+
sequenceIndex: number,
|
|
332
|
+
sliceCount: number,
|
|
333
|
+
): NonNullable<RuntimeBlockFragment["continuation"]> {
|
|
334
|
+
return {
|
|
335
|
+
kind: "table",
|
|
336
|
+
sequenceIndex,
|
|
337
|
+
sliceCount,
|
|
338
|
+
rowRange: slice.rowRange,
|
|
339
|
+
continuesFromPreviousPage: slice.rowRange.from > 0,
|
|
340
|
+
continuesToNextPage: slice.rowRange.to < slice.rowRange.totalRows,
|
|
341
|
+
repeatedHeaderRowIndexes:
|
|
342
|
+
slice.rowRange.from > 0
|
|
343
|
+
? collectRepeatedHeaderRowIndexes(block, slice.rowRange.from)
|
|
344
|
+
: [],
|
|
345
|
+
verticalMergeCarry: collectVerticalMergeCarry(block, slice.rowRange.from),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function collectRepeatedHeaderRowIndexes(
|
|
350
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
351
|
+
startRow: number,
|
|
352
|
+
): number[] {
|
|
353
|
+
const headerRows: number[] = [];
|
|
354
|
+
for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
|
|
355
|
+
if (rowIndex >= startRow) break;
|
|
356
|
+
if (block.rows[rowIndex]?.isHeader === true) headerRows.push(rowIndex);
|
|
357
|
+
}
|
|
358
|
+
return headerRows;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function collectVerticalMergeCarry(
|
|
362
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
363
|
+
startRow: number,
|
|
364
|
+
): Array<{ columnIndex: number; restartRowIndex: number }> {
|
|
365
|
+
if (startRow <= 0) return [];
|
|
366
|
+
|
|
367
|
+
const activeByColumn = new Map<number, number>();
|
|
368
|
+
for (let rowIndex = 0; rowIndex < startRow; rowIndex += 1) {
|
|
369
|
+
visitRowCells(block.rows[rowIndex], (columnIndex, span, verticalMerge) => {
|
|
370
|
+
for (let column = columnIndex; column < columnIndex + span; column += 1) {
|
|
371
|
+
if (verticalMerge === "restart") {
|
|
372
|
+
activeByColumn.set(column, rowIndex);
|
|
373
|
+
} else if (verticalMerge !== "continue") {
|
|
374
|
+
activeByColumn.delete(column);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const carried = new Map<number, number>();
|
|
381
|
+
visitRowCells(block.rows[startRow], (columnIndex, span, verticalMerge) => {
|
|
382
|
+
if (verticalMerge !== "continue") return;
|
|
383
|
+
for (let column = columnIndex; column < columnIndex + span; column += 1) {
|
|
384
|
+
const restartRowIndex = activeByColumn.get(column);
|
|
385
|
+
if (restartRowIndex !== undefined) carried.set(column, restartRowIndex);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
return [...carried]
|
|
390
|
+
.sort(([a], [b]) => a - b)
|
|
391
|
+
.map(([columnIndex, restartRowIndex]) => ({ columnIndex, restartRowIndex }));
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function visitRowCells(
|
|
395
|
+
row: Extract<SurfaceBlockSnapshot, { kind: "table" }>["rows"][number] | undefined,
|
|
396
|
+
visit: (
|
|
397
|
+
columnIndex: number,
|
|
398
|
+
span: number,
|
|
399
|
+
verticalMerge: "restart" | "continue" | null,
|
|
400
|
+
) => void,
|
|
401
|
+
): void {
|
|
402
|
+
if (!row) return;
|
|
403
|
+
let columnIndex = Math.max(0, row.gridBefore ?? 0);
|
|
404
|
+
for (const cell of row.cells) {
|
|
405
|
+
const span = Math.max(1, cell.gridSpan || cell.colspan || 1);
|
|
406
|
+
visit(columnIndex, span, cell.verticalMerge);
|
|
407
|
+
columnIndex += span;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
285
411
|
function estimateSliceHeightFromRows(rowRange: {
|
|
286
412
|
from: number;
|
|
287
413
|
to: number;
|
|
@@ -291,6 +417,59 @@ function estimateSliceHeightFromRows(rowRange: {
|
|
|
291
417
|
return rows * 360; // ~1 line + padding per row, approximate
|
|
292
418
|
}
|
|
293
419
|
|
|
420
|
+
function buildFragmentLayoutObject(input: {
|
|
421
|
+
block: SurfaceBlockSnapshot;
|
|
422
|
+
fragmentId: string;
|
|
423
|
+
heightTwips: number;
|
|
424
|
+
widthTwips?: number;
|
|
425
|
+
paginationRole: NonNullable<RuntimeBlockFragment["layoutObject"]>["paginationRole"];
|
|
426
|
+
}): NonNullable<RuntimeBlockFragment["layoutObject"]> {
|
|
427
|
+
const fieldFamilies = collectFieldFamilies(input.block);
|
|
428
|
+
const kind = resolveFragmentLayoutObjectKind(input.block, fieldFamilies);
|
|
429
|
+
return {
|
|
430
|
+
objectId: `${kind}:${input.fragmentId}`,
|
|
431
|
+
kind,
|
|
432
|
+
sourceBlockId: input.block.blockId,
|
|
433
|
+
paginationRole: input.paginationRole,
|
|
434
|
+
measuredExtentTwips: {
|
|
435
|
+
heightTwips: Math.max(0, input.heightTwips),
|
|
436
|
+
...(input.widthTwips !== undefined
|
|
437
|
+
? { widthTwips: Math.max(0, input.widthTwips) }
|
|
438
|
+
: {}),
|
|
439
|
+
},
|
|
440
|
+
...(fieldFamilies.length > 0 ? { fieldFamilies } : {}),
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
function resolveFragmentLayoutObjectKind(
|
|
445
|
+
block: SurfaceBlockSnapshot,
|
|
446
|
+
fieldFamilies: readonly string[],
|
|
447
|
+
): NonNullable<RuntimeBlockFragment["layoutObject"]>["kind"] {
|
|
448
|
+
switch (block.kind) {
|
|
449
|
+
case "paragraph":
|
|
450
|
+
if (fieldFamilies.length > 0) return "field-region";
|
|
451
|
+
return block.numbering ? "numbered-paragraph" : "paragraph";
|
|
452
|
+
case "table":
|
|
453
|
+
return "table";
|
|
454
|
+
case "sdt_block":
|
|
455
|
+
return "sdt-block";
|
|
456
|
+
case "opaque_block":
|
|
457
|
+
return "opaque-block";
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function collectFieldFamilies(block: SurfaceBlockSnapshot): string[] {
|
|
462
|
+
if (block.kind !== "paragraph") return [];
|
|
463
|
+
const families: string[] = [];
|
|
464
|
+
const seen = new Set<string>();
|
|
465
|
+
for (const segment of block.segments) {
|
|
466
|
+
if (segment.kind !== "field_ref" || seen.has(segment.fieldFamily)) continue;
|
|
467
|
+
seen.add(segment.fieldFamily);
|
|
468
|
+
families.push(segment.fieldFamily);
|
|
469
|
+
}
|
|
470
|
+
return families;
|
|
471
|
+
}
|
|
472
|
+
|
|
294
473
|
function findPageIndexForOffset(
|
|
295
474
|
pages: readonly DocumentPageSnapshot[],
|
|
296
475
|
offset: number,
|
|
@@ -25,12 +25,17 @@ import type {
|
|
|
25
25
|
} from "./page-story-resolver.ts";
|
|
26
26
|
import type {
|
|
27
27
|
RuntimeBlockFragment,
|
|
28
|
+
RuntimeLayoutContinuationCursor,
|
|
29
|
+
RuntimeLayoutDivergence,
|
|
28
30
|
RuntimeLineBox,
|
|
29
31
|
RuntimeNoteAllocation,
|
|
32
|
+
RuntimePageFrame,
|
|
30
33
|
RuntimePageGraph,
|
|
31
34
|
RuntimePageNode,
|
|
32
35
|
RuntimePageRegion,
|
|
33
36
|
RuntimePageRegions,
|
|
37
|
+
RuntimeStoryAnchoredObject,
|
|
38
|
+
RuntimeTwipsRect,
|
|
34
39
|
} from "./page-graph.ts";
|
|
35
40
|
import type {
|
|
36
41
|
ResolvedFormattingState,
|
|
@@ -132,6 +137,67 @@ export function emitLayoutGuardWarning(
|
|
|
132
137
|
// Public read model types (shape-stable, cloned at the facet boundary)
|
|
133
138
|
// ---------------------------------------------------------------------------
|
|
134
139
|
|
|
140
|
+
export interface PublicTwipsRect {
|
|
141
|
+
xTwips: number;
|
|
142
|
+
yTwips: number;
|
|
143
|
+
widthTwips: number;
|
|
144
|
+
heightTwips: number;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface PublicLayoutDivergence {
|
|
148
|
+
divergenceId: string;
|
|
149
|
+
kind: RuntimeLayoutDivergence["kind"];
|
|
150
|
+
source: RuntimeLayoutDivergence["source"];
|
|
151
|
+
severity: RuntimeLayoutDivergence["severity"];
|
|
152
|
+
message: string;
|
|
153
|
+
regionKinds?: readonly RuntimePageRegion["kind"][];
|
|
154
|
+
fragmentIds?: readonly string[];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface PublicPageFrame {
|
|
158
|
+
frameId: string;
|
|
159
|
+
pageId: string;
|
|
160
|
+
pageIndex: number;
|
|
161
|
+
sectionIndex: number;
|
|
162
|
+
displayPageNumber: number;
|
|
163
|
+
physicalBoundsTwips: PublicTwipsRect;
|
|
164
|
+
divergenceIds: readonly string[];
|
|
165
|
+
signature: string;
|
|
166
|
+
exclusionZoneCount: number;
|
|
167
|
+
regionFrames: readonly {
|
|
168
|
+
kind: RuntimePageRegion["kind"];
|
|
169
|
+
rectTwips?: PublicTwipsRect;
|
|
170
|
+
fragmentIds: readonly string[];
|
|
171
|
+
}[];
|
|
172
|
+
pageLocalStories: readonly PublicPageLocalStoryInstance[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface PublicPageLocalStoryInstance {
|
|
176
|
+
instanceId: string;
|
|
177
|
+
storyKey: string;
|
|
178
|
+
pageId: string;
|
|
179
|
+
kind: "header" | "footer";
|
|
180
|
+
variant: "default" | "first" | "even" | "odd";
|
|
181
|
+
relationshipId: string;
|
|
182
|
+
sectionIndex?: number;
|
|
183
|
+
anchoredObjects: readonly PublicStoryAnchoredObject[];
|
|
184
|
+
measuredFrameHeightTwips: number;
|
|
185
|
+
signature: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface PublicStoryAnchoredObject {
|
|
189
|
+
objectId: string;
|
|
190
|
+
sourceType: RuntimeStoryAnchoredObject["sourceType"];
|
|
191
|
+
display: RuntimeStoryAnchoredObject["display"];
|
|
192
|
+
extentTwips?: {
|
|
193
|
+
widthTwips: number;
|
|
194
|
+
heightTwips: number;
|
|
195
|
+
};
|
|
196
|
+
relationshipIds?: readonly string[];
|
|
197
|
+
preserveOnly: boolean;
|
|
198
|
+
divergenceIds: readonly string[];
|
|
199
|
+
}
|
|
200
|
+
|
|
135
201
|
export interface PublicPageNode {
|
|
136
202
|
pageId: string;
|
|
137
203
|
pageIndex: number;
|
|
@@ -157,6 +223,10 @@ export interface PublicPageNode {
|
|
|
157
223
|
lineBoxCount: number;
|
|
158
224
|
/** Footnotes reserved at the bottom of the page, if any. */
|
|
159
225
|
noteAllocations: readonly PublicNoteAllocation[];
|
|
226
|
+
/** PE2 page-frame graph projection, when emitted by the L04 graph. */
|
|
227
|
+
frame?: PublicPageFrame;
|
|
228
|
+
/** Typed layout divergences detected while building this page. */
|
|
229
|
+
divergences?: readonly PublicLayoutDivergence[];
|
|
160
230
|
}
|
|
161
231
|
|
|
162
232
|
export interface PublicResolvedPageStories {
|
|
@@ -187,6 +257,8 @@ export interface PublicPageRegion {
|
|
|
187
257
|
widthTwips: number;
|
|
188
258
|
heightTwips: number;
|
|
189
259
|
fragmentCount: number;
|
|
260
|
+
/** PE2 semantic twips rect, when populated by the L04 page-frame graph. */
|
|
261
|
+
rectTwips?: PublicTwipsRect;
|
|
190
262
|
}
|
|
191
263
|
|
|
192
264
|
/**
|
|
@@ -208,8 +280,25 @@ export interface PublicBlockFragment {
|
|
|
208
280
|
to: number;
|
|
209
281
|
heightTwips: number;
|
|
210
282
|
orderInRegion: number;
|
|
283
|
+
kind?: "whole" | "paragraph-slice" | "table-slice";
|
|
284
|
+
paragraphLineRange?: {
|
|
285
|
+
from: number;
|
|
286
|
+
to: number;
|
|
287
|
+
totalLines: number;
|
|
288
|
+
};
|
|
289
|
+
tableRowRange?: {
|
|
290
|
+
from: number;
|
|
291
|
+
to: number;
|
|
292
|
+
totalRows: number;
|
|
293
|
+
};
|
|
294
|
+
columnIndex?: number;
|
|
295
|
+
continuation?: PublicLayoutContinuationCursor;
|
|
296
|
+
layoutObject?: PublicFragmentLayoutObject;
|
|
211
297
|
}
|
|
212
298
|
|
|
299
|
+
export type PublicLayoutContinuationCursor = RuntimeLayoutContinuationCursor;
|
|
300
|
+
export type PublicFragmentLayoutObject = NonNullable<RuntimeBlockFragment["layoutObject"]>;
|
|
301
|
+
|
|
213
302
|
/**
|
|
214
303
|
* P8 — One block snapshot rendered into a region of a page. Returned by
|
|
215
304
|
* `WordReviewEditorLayoutFacet.getStoryBlocksForRegion` and
|
|
@@ -245,6 +334,7 @@ export interface PublicNoteAllocation {
|
|
|
245
334
|
noteKind: "footnote" | "endnote";
|
|
246
335
|
noteId: string;
|
|
247
336
|
reservedHeightTwips: number;
|
|
337
|
+
fragmentId?: string;
|
|
248
338
|
}
|
|
249
339
|
|
|
250
340
|
export interface PublicPageAnchor {
|
|
@@ -1367,12 +1457,113 @@ function toPublicPageNode(
|
|
|
1367
1457
|
regions: toPublicPageRegions(node.regions),
|
|
1368
1458
|
lineBoxCount: node.lineBoxes.length,
|
|
1369
1459
|
noteAllocations: node.noteAllocations.map(toPublicNoteAllocation),
|
|
1460
|
+
...(node.frame ? { frame: toPublicPageFrame(node.frame) } : {}),
|
|
1461
|
+
...(node.divergences && node.divergences.length > 0
|
|
1462
|
+
? { divergences: node.divergences.map(toPublicLayoutDivergence) }
|
|
1463
|
+
: {}),
|
|
1370
1464
|
};
|
|
1371
1465
|
publicPageNodeCache.set(node, built);
|
|
1372
1466
|
void graph; // reserved for future cross-page derivations
|
|
1373
1467
|
return built;
|
|
1374
1468
|
}
|
|
1375
1469
|
|
|
1470
|
+
function toPublicTwipsRect(rect: RuntimeTwipsRect): PublicTwipsRect {
|
|
1471
|
+
return {
|
|
1472
|
+
xTwips: rect.xTwips,
|
|
1473
|
+
yTwips: rect.yTwips,
|
|
1474
|
+
widthTwips: rect.widthTwips,
|
|
1475
|
+
heightTwips: rect.heightTwips,
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function frameRegionEntries(
|
|
1480
|
+
frame: RuntimePageFrame,
|
|
1481
|
+
): PublicPageFrame["regionFrames"] {
|
|
1482
|
+
const regions: PublicPageFrame["regionFrames"][number][] = [];
|
|
1483
|
+
const push = (region: RuntimePageRegion | undefined) => {
|
|
1484
|
+
if (!region) return;
|
|
1485
|
+
regions.push({
|
|
1486
|
+
kind: region.kind,
|
|
1487
|
+
...(region.rectTwips ? { rectTwips: toPublicTwipsRect(region.rectTwips) } : {}),
|
|
1488
|
+
fragmentIds: [...region.fragmentIds],
|
|
1489
|
+
});
|
|
1490
|
+
};
|
|
1491
|
+
push(frame.regions.header);
|
|
1492
|
+
push(frame.regions.body);
|
|
1493
|
+
for (const column of frame.regions.columns ?? []) push(column);
|
|
1494
|
+
push(frame.regions.footer);
|
|
1495
|
+
for (const footnote of frame.regions.footnotes ?? []) push(footnote);
|
|
1496
|
+
return regions;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
function toPublicPageFrame(frame: RuntimePageFrame): PublicPageFrame {
|
|
1500
|
+
return {
|
|
1501
|
+
frameId: frame.frameId,
|
|
1502
|
+
pageId: frame.pageId,
|
|
1503
|
+
pageIndex: frame.pageIndex,
|
|
1504
|
+
sectionIndex: frame.sectionIndex,
|
|
1505
|
+
displayPageNumber: frame.displayPageNumber,
|
|
1506
|
+
physicalBoundsTwips: toPublicTwipsRect(frame.physicalBoundsTwips),
|
|
1507
|
+
divergenceIds: [...frame.divergenceIds],
|
|
1508
|
+
signature: frame.signature,
|
|
1509
|
+
exclusionZoneCount: frame.regions.exclusionZones.length,
|
|
1510
|
+
regionFrames: frameRegionEntries(frame),
|
|
1511
|
+
pageLocalStories: frame.pageLocalStories.map(toPublicPageLocalStory),
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
function toPublicPageLocalStory(
|
|
1516
|
+
story: RuntimePageFrame["pageLocalStories"][number],
|
|
1517
|
+
): PublicPageLocalStoryInstance {
|
|
1518
|
+
return {
|
|
1519
|
+
instanceId: story.instanceId,
|
|
1520
|
+
storyKey: story.storyKey,
|
|
1521
|
+
pageId: story.pageId,
|
|
1522
|
+
kind: story.kind,
|
|
1523
|
+
variant: story.variant,
|
|
1524
|
+
relationshipId: story.relationshipId,
|
|
1525
|
+
...(story.sectionIndex !== undefined ? { sectionIndex: story.sectionIndex } : {}),
|
|
1526
|
+
anchoredObjects: story.anchoredObjects.map(toPublicStoryAnchoredObject),
|
|
1527
|
+
measuredFrameHeightTwips: story.measuredFrameHeightTwips,
|
|
1528
|
+
signature: story.signature,
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
function toPublicStoryAnchoredObject(
|
|
1533
|
+
object: RuntimeStoryAnchoredObject,
|
|
1534
|
+
): PublicStoryAnchoredObject {
|
|
1535
|
+
return {
|
|
1536
|
+
objectId: object.objectId,
|
|
1537
|
+
sourceType: object.sourceType,
|
|
1538
|
+
display: object.display,
|
|
1539
|
+
...(object.extentTwips
|
|
1540
|
+
? {
|
|
1541
|
+
extentTwips: {
|
|
1542
|
+
widthTwips: object.extentTwips.widthTwips,
|
|
1543
|
+
heightTwips: object.extentTwips.heightTwips,
|
|
1544
|
+
},
|
|
1545
|
+
}
|
|
1546
|
+
: {}),
|
|
1547
|
+
...(object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {}),
|
|
1548
|
+
preserveOnly: object.preserveOnly,
|
|
1549
|
+
divergenceIds: [...object.divergenceIds],
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
function toPublicLayoutDivergence(
|
|
1554
|
+
divergence: RuntimeLayoutDivergence,
|
|
1555
|
+
): PublicLayoutDivergence {
|
|
1556
|
+
return {
|
|
1557
|
+
divergenceId: divergence.divergenceId,
|
|
1558
|
+
kind: divergence.kind,
|
|
1559
|
+
source: divergence.source,
|
|
1560
|
+
severity: divergence.severity,
|
|
1561
|
+
message: divergence.message,
|
|
1562
|
+
...(divergence.regionKinds !== undefined ? { regionKinds: [...divergence.regionKinds] } : {}),
|
|
1563
|
+
...(divergence.fragmentIds !== undefined ? { fragmentIds: [...divergence.fragmentIds] } : {}),
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1376
1567
|
function toPublicResolvedPageStories(
|
|
1377
1568
|
stories: ResolvedPageStories,
|
|
1378
1569
|
): PublicResolvedPageStories {
|
|
@@ -1404,6 +1595,7 @@ function toPublicPageRegion(region: RuntimePageRegion): PublicPageRegion {
|
|
|
1404
1595
|
widthTwips: region.widthTwips,
|
|
1405
1596
|
heightTwips: region.heightTwips,
|
|
1406
1597
|
fragmentCount: region.fragmentIds.length,
|
|
1598
|
+
...(region.rectTwips ? { rectTwips: toPublicTwipsRect(region.rectTwips) } : {}),
|
|
1407
1599
|
};
|
|
1408
1600
|
}
|
|
1409
1601
|
|
|
@@ -1422,6 +1614,49 @@ function toPublicBlockFragment(
|
|
|
1422
1614
|
to: fragment.to,
|
|
1423
1615
|
heightTwips: fragment.heightTwips,
|
|
1424
1616
|
orderInRegion: fragment.orderInRegion,
|
|
1617
|
+
...(fragment.kind !== undefined ? { kind: fragment.kind } : {}),
|
|
1618
|
+
...(fragment.paragraphLineRange !== undefined
|
|
1619
|
+
? { paragraphLineRange: { ...fragment.paragraphLineRange } }
|
|
1620
|
+
: {}),
|
|
1621
|
+
...(fragment.tableRowRange !== undefined
|
|
1622
|
+
? { tableRowRange: { ...fragment.tableRowRange } }
|
|
1623
|
+
: {}),
|
|
1624
|
+
...(fragment.columnIndex !== undefined ? { columnIndex: fragment.columnIndex } : {}),
|
|
1625
|
+
...(fragment.continuation !== undefined
|
|
1626
|
+
? { continuation: cloneContinuationCursor(fragment.continuation) }
|
|
1627
|
+
: {}),
|
|
1628
|
+
...(fragment.layoutObject !== undefined
|
|
1629
|
+
? { layoutObject: cloneFragmentLayoutObject(fragment.layoutObject) }
|
|
1630
|
+
: {}),
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
function cloneContinuationCursor(
|
|
1635
|
+
cursor: RuntimeLayoutContinuationCursor,
|
|
1636
|
+
): RuntimeLayoutContinuationCursor {
|
|
1637
|
+
if (cursor.kind === "paragraph") {
|
|
1638
|
+
return {
|
|
1639
|
+
...cursor,
|
|
1640
|
+
lineRange: { ...cursor.lineRange },
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
return {
|
|
1644
|
+
...cursor,
|
|
1645
|
+
rowRange: { ...cursor.rowRange },
|
|
1646
|
+
repeatedHeaderRowIndexes: [...cursor.repeatedHeaderRowIndexes],
|
|
1647
|
+
verticalMergeCarry: cursor.verticalMergeCarry.map((carry) => ({ ...carry })),
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
function cloneFragmentLayoutObject(
|
|
1652
|
+
layoutObject: NonNullable<RuntimeBlockFragment["layoutObject"]>,
|
|
1653
|
+
): NonNullable<RuntimeBlockFragment["layoutObject"]> {
|
|
1654
|
+
return {
|
|
1655
|
+
...layoutObject,
|
|
1656
|
+
measuredExtentTwips: { ...layoutObject.measuredExtentTwips },
|
|
1657
|
+
...(layoutObject.fieldFamilies !== undefined
|
|
1658
|
+
? { fieldFamilies: [...layoutObject.fieldFamilies] }
|
|
1659
|
+
: {}),
|
|
1425
1660
|
};
|
|
1426
1661
|
}
|
|
1427
1662
|
|
|
@@ -1440,6 +1675,7 @@ function toPublicNoteAllocation(note: RuntimeNoteAllocation): PublicNoteAllocati
|
|
|
1440
1675
|
noteKind: note.noteKind,
|
|
1441
1676
|
noteId: note.noteId,
|
|
1442
1677
|
reservedHeightTwips: note.reservedHeightTwips,
|
|
1678
|
+
...(note.fragmentId !== undefined ? { fragmentId: note.fragmentId } : {}),
|
|
1443
1679
|
};
|
|
1444
1680
|
}
|
|
1445
1681
|
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
RuntimePageAnchor,
|
|
4
4
|
RuntimePageFrame,
|
|
5
5
|
RuntimePageGraph,
|
|
6
|
+
RuntimePageLocalStoryInstance,
|
|
6
7
|
RuntimePageNode,
|
|
7
8
|
RuntimePageRegion,
|
|
8
9
|
RuntimePageRegions,
|
|
@@ -97,6 +98,9 @@ function rewriteFrame(
|
|
|
97
98
|
return {
|
|
98
99
|
...frame,
|
|
99
100
|
pageId: rewriteId(frame.pageId),
|
|
101
|
+
pageLocalStories: frame.pageLocalStories.map((story) =>
|
|
102
|
+
rewritePageLocalStoryInstance(story, rewriteId),
|
|
103
|
+
),
|
|
100
104
|
regions: {
|
|
101
105
|
...frame.regions,
|
|
102
106
|
body: rewriteRegion(frame.regions.body, rewriteId),
|
|
@@ -116,6 +120,16 @@ function rewriteFrame(
|
|
|
116
120
|
};
|
|
117
121
|
}
|
|
118
122
|
|
|
123
|
+
function rewritePageLocalStoryInstance(
|
|
124
|
+
story: RuntimePageLocalStoryInstance,
|
|
125
|
+
rewriteId: (id: string) => string,
|
|
126
|
+
): RuntimePageLocalStoryInstance {
|
|
127
|
+
return {
|
|
128
|
+
...story,
|
|
129
|
+
pageId: rewriteId(story.pageId),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
119
133
|
function rewriteRegions(
|
|
120
134
|
regions: RuntimePageRegions,
|
|
121
135
|
rewriteId: (id: string) => string,
|
|
@@ -19,6 +19,7 @@ export * from "./scope-writer.ts";
|
|
|
19
19
|
export * from "./metadata-writer.ts";
|
|
20
20
|
export * from "./projector.ts";
|
|
21
21
|
export * from "./overlay-store.ts";
|
|
22
|
+
export * from "./overlay-lanes.ts";
|
|
22
23
|
export * from "./coordinator.ts";
|
|
23
24
|
export * from "./visibility-policy.ts";
|
|
24
25
|
export * from "./markup-mode-policy.ts";
|