@beyondwork/docx-react-component 1.0.110 → 1.0.111
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/model/layout/page-graph-types.ts +33 -0
- package/src/runtime/geometry/adjacent-geometry-intake.ts +373 -5
- package/src/runtime/geometry/caret-geometry.ts +219 -7
- package/src/runtime/geometry/geometry-index.ts +35 -10
- package/src/runtime/geometry/object-handles.ts +42 -1
- package/src/runtime/layout/index.ts +3 -0
- package/src/runtime/layout/inert-layout-facet.ts +13 -0
- package/src/runtime/layout/layout-engine-instance.ts +2 -0
- package/src/runtime/layout/layout-engine-version.ts +32 -2
- package/src/runtime/layout/layout-facet-types.ts +3 -0
- package/src/runtime/layout/page-graph.ts +81 -7
- package/src/runtime/layout/project-block-fragments.ts +144 -1
- package/src/runtime/layout/public-facet.ts +160 -0
- package/src/runtime/scopes/adjacent-geometry-evidence.ts +456 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +8 -0
- package/src/runtime/scopes/evidence.ts +16 -0
- package/src/runtime/scopes/index.ts +13 -0
- package/src/runtime/scopes/semantic-scope-types.ts +67 -0
- package/src/ui-tailwind/debug/layer11-consumer-readiness.ts +104 -0
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +50 -5
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +26 -0
- package/src/README.md +0 -85
- package/src/api/README.md +0 -26
- package/src/api/v3/README.md +0 -91
- package/src/component-inventory.md +0 -99
- package/src/core/README.md +0 -10
- package/src/core/commands/README.md +0 -3
- package/src/core/schema/README.md +0 -3
- package/src/core/selection/README.md +0 -3
- package/src/core/state/README.md +0 -3
- package/src/io/README.md +0 -10
- package/src/io/export/README.md +0 -3
- package/src/io/normalize/README.md +0 -3
- package/src/io/ooxml/README.md +0 -3
- package/src/io/opc/README.md +0 -3
- package/src/model/README.md +0 -3
- package/src/preservation/README.md +0 -3
- package/src/review/README.md +0 -16
- package/src/review/store/README.md +0 -3
- package/src/runtime/README.md +0 -3
- package/src/ui/README.md +0 -30
- package/src/ui/comments/README.md +0 -3
- package/src/ui/compatibility/README.md +0 -3
- package/src/ui/editor-surface/README.md +0 -3
- package/src/ui/review/README.md +0 -3
- package/src/ui/status/README.md +0 -3
- package/src/ui/theme/README.md +0 -3
- package/src/ui/toolbar/README.md +0 -3
- package/src/ui-tailwind/debug/README.md +0 -22
- package/src/validation/README.md +0 -3
|
@@ -23,6 +23,7 @@ import type {
|
|
|
23
23
|
DocumentPageSnapshot,
|
|
24
24
|
EditorSurfaceSnapshot,
|
|
25
25
|
SurfaceBlockSnapshot,
|
|
26
|
+
SurfaceInlineSegment,
|
|
26
27
|
} from "../../api/public-types";
|
|
27
28
|
import type {
|
|
28
29
|
CanonicalFieldRegionIdentity,
|
|
@@ -31,7 +32,9 @@ import type { RuntimeBlockFragment } from "./page-graph.ts";
|
|
|
31
32
|
import type {
|
|
32
33
|
RuntimeFieldRegionLayoutFacts,
|
|
33
34
|
RuntimeLineBox,
|
|
35
|
+
RuntimeLineRunAnchor,
|
|
34
36
|
RuntimeNumberingLayoutFacts,
|
|
37
|
+
RuntimeTwipsRect,
|
|
35
38
|
} from "../../model/layout/page-graph-types.ts";
|
|
36
39
|
import type {
|
|
37
40
|
BlockSplits,
|
|
@@ -185,8 +188,12 @@ export function projectLineBoxesForPageFragments(
|
|
|
185
188
|
ReadonlyArray<Omit<RuntimeBlockFragment, "pageId">>
|
|
186
189
|
>,
|
|
187
190
|
fragmentMeasurementsByPageIndex?: ReadonlyMap<number, ReadonlyMap<string, FragmentMeasurement>>,
|
|
191
|
+
surface?: EditorSurfaceSnapshot,
|
|
188
192
|
): Map<number, RuntimeLineBox[]> {
|
|
189
193
|
const byPage = new Map<number, RuntimeLineBox[]>();
|
|
194
|
+
const blocksById = surface
|
|
195
|
+
? new Map(surface.blocks.map((block) => [block.blockId, block] as const))
|
|
196
|
+
: new Map<string, SurfaceBlockSnapshot>();
|
|
190
197
|
for (const page of pages) {
|
|
191
198
|
const fragments = [...(fragmentsByPageIndex.get(page.pageIndex) ?? [])]
|
|
192
199
|
.filter((fragment) => fragment.regionKind === "body")
|
|
@@ -224,12 +231,33 @@ export function projectLineBoxesForPageFragments(
|
|
|
224
231
|
page.layout.gutter,
|
|
225
232
|
);
|
|
226
233
|
for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
|
|
234
|
+
const lineTopTwips = cursorTwips + lineIndex * lineHeight;
|
|
235
|
+
const rectTwips = lineRectForFragment(page, fragment, lineTopTwips, widthTwips, lineHeight);
|
|
236
|
+
const baselinePageYTwips = rectTwips.yTwips + Math.round(lineHeight * 0.8);
|
|
237
|
+
const block = blocksById.get(fragment.blockId);
|
|
238
|
+
const direction = block?.kind === "paragraph" && block.bidi === true ? "rtl" : "ltr";
|
|
227
239
|
lines.push({
|
|
228
240
|
fragmentId: fragment.fragmentId,
|
|
229
241
|
lineIndex,
|
|
230
|
-
baselineTwips:
|
|
242
|
+
baselineTwips: lineTopTwips,
|
|
243
|
+
baselinePageYTwips,
|
|
231
244
|
heightTwips: lineHeight,
|
|
232
245
|
widthTwips,
|
|
246
|
+
rectTwips,
|
|
247
|
+
direction,
|
|
248
|
+
...(block?.kind === "paragraph"
|
|
249
|
+
? {
|
|
250
|
+
runAnchors: buildRunAnchorsForLine({
|
|
251
|
+
block,
|
|
252
|
+
fragment,
|
|
253
|
+
lineIndex,
|
|
254
|
+
lineCount,
|
|
255
|
+
rectTwips,
|
|
256
|
+
baselinePageYTwips,
|
|
257
|
+
direction,
|
|
258
|
+
}),
|
|
259
|
+
}
|
|
260
|
+
: {}),
|
|
233
261
|
});
|
|
234
262
|
}
|
|
235
263
|
cursorTwips += Math.max(0, fragment.heightTwips);
|
|
@@ -241,6 +269,121 @@ export function projectLineBoxesForPageFragments(
|
|
|
241
269
|
return byPage;
|
|
242
270
|
}
|
|
243
271
|
|
|
272
|
+
function lineRectForFragment(
|
|
273
|
+
page: DocumentPageSnapshot,
|
|
274
|
+
fragment: Omit<RuntimeBlockFragment, "pageId">,
|
|
275
|
+
lineTopTwips: number,
|
|
276
|
+
widthTwips: number,
|
|
277
|
+
heightTwips: number,
|
|
278
|
+
): RuntimeTwipsRect {
|
|
279
|
+
const bodyX = page.layout.marginLeft + page.layout.gutter;
|
|
280
|
+
const bodyY = page.layout.marginTop;
|
|
281
|
+
const columnIndex = Math.max(0, fragment.columnIndex ?? 0);
|
|
282
|
+
const columnOffset = columnIndex > 0 ? columnIndex * Math.max(0, widthTwips) : 0;
|
|
283
|
+
return {
|
|
284
|
+
xTwips: bodyX + columnOffset,
|
|
285
|
+
yTwips: bodyY + lineTopTwips,
|
|
286
|
+
widthTwips: Math.max(0, widthTwips),
|
|
287
|
+
heightTwips: Math.max(0, heightTwips),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function buildRunAnchorsForLine(input: {
|
|
292
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>;
|
|
293
|
+
fragment: Omit<RuntimeBlockFragment, "pageId">;
|
|
294
|
+
lineIndex: number;
|
|
295
|
+
lineCount: number;
|
|
296
|
+
rectTwips: RuntimeTwipsRect;
|
|
297
|
+
baselinePageYTwips: number;
|
|
298
|
+
direction: "ltr" | "rtl";
|
|
299
|
+
}): RuntimeLineRunAnchor[] {
|
|
300
|
+
const textSegments = input.block.segments.filter(
|
|
301
|
+
(segment): segment is Extract<SurfaceInlineSegment, { kind: "text" }> =>
|
|
302
|
+
segment.kind === "text" && segment.text.length > 0,
|
|
303
|
+
);
|
|
304
|
+
if (textSegments.length === 0) return [];
|
|
305
|
+
|
|
306
|
+
const totalChars = Math.max(
|
|
307
|
+
1,
|
|
308
|
+
textSegments.reduce((sum, segment) => sum + Array.from(segment.text).length, 0),
|
|
309
|
+
);
|
|
310
|
+
const totalLineCount =
|
|
311
|
+
input.fragment.kind === "paragraph-slice" && input.fragment.paragraphLineRange
|
|
312
|
+
? Math.max(1, input.fragment.paragraphLineRange.totalLines)
|
|
313
|
+
: Math.max(1, input.lineCount);
|
|
314
|
+
const globalLineIndex =
|
|
315
|
+
(input.fragment.kind === "paragraph-slice" && input.fragment.paragraphLineRange
|
|
316
|
+
? input.fragment.paragraphLineRange.from
|
|
317
|
+
: 0) + input.lineIndex;
|
|
318
|
+
const charsPerLine = Math.max(1, Math.ceil(totalChars / totalLineCount));
|
|
319
|
+
const lineCharStart = globalLineIndex * charsPerLine;
|
|
320
|
+
const lineCharEnd = Math.min(totalChars, lineCharStart + charsPerLine);
|
|
321
|
+
if (lineCharEnd <= lineCharStart) return [];
|
|
322
|
+
|
|
323
|
+
const charWidth = Math.max(1, input.rectTwips.widthTwips / charsPerLine);
|
|
324
|
+
const anchors: RuntimeLineRunAnchor[] = [];
|
|
325
|
+
let charCursor = 0;
|
|
326
|
+
for (const segment of textSegments) {
|
|
327
|
+
const segmentLength = Array.from(segment.text).length;
|
|
328
|
+
const segmentStart = charCursor;
|
|
329
|
+
const segmentEnd = charCursor + segmentLength;
|
|
330
|
+
charCursor = segmentEnd;
|
|
331
|
+
|
|
332
|
+
const overlapStart = Math.max(segmentStart, lineCharStart);
|
|
333
|
+
const overlapEnd = Math.min(segmentEnd, lineCharEnd);
|
|
334
|
+
if (overlapEnd <= overlapStart) continue;
|
|
335
|
+
|
|
336
|
+
const startInLine = overlapStart - lineCharStart;
|
|
337
|
+
const glyphCount = Math.max(1, overlapEnd - overlapStart);
|
|
338
|
+
const runWidthTwips = Math.max(1, Math.round(glyphCount * charWidth));
|
|
339
|
+
const startOffsetTwips = Math.round(startInLine * charWidth);
|
|
340
|
+
const xTwips =
|
|
341
|
+
input.direction === "rtl"
|
|
342
|
+
? input.rectTwips.xTwips + input.rectTwips.widthTwips - startOffsetTwips - runWidthTwips
|
|
343
|
+
: input.rectTwips.xTwips + startOffsetTwips;
|
|
344
|
+
const glyphWidthTwips = Math.max(1, Math.round(charWidth));
|
|
345
|
+
const runRectTwips: RuntimeTwipsRect = {
|
|
346
|
+
xTwips,
|
|
347
|
+
yTwips: input.rectTwips.yTwips,
|
|
348
|
+
widthTwips: runWidthTwips,
|
|
349
|
+
heightTwips: input.rectTwips.heightTwips,
|
|
350
|
+
};
|
|
351
|
+
const firstGlyphRectTwips: RuntimeTwipsRect =
|
|
352
|
+
input.direction === "rtl"
|
|
353
|
+
? {
|
|
354
|
+
...runRectTwips,
|
|
355
|
+
xTwips: xTwips + Math.max(0, runWidthTwips - glyphWidthTwips),
|
|
356
|
+
widthTwips: glyphWidthTwips,
|
|
357
|
+
}
|
|
358
|
+
: { ...runRectTwips, widthTwips: glyphWidthTwips };
|
|
359
|
+
const lastGlyphRectTwips: RuntimeTwipsRect =
|
|
360
|
+
input.direction === "rtl"
|
|
361
|
+
? { ...runRectTwips, widthTwips: glyphWidthTwips }
|
|
362
|
+
: {
|
|
363
|
+
...runRectTwips,
|
|
364
|
+
xTwips: xTwips + Math.max(0, runWidthTwips - glyphWidthTwips),
|
|
365
|
+
widthTwips: glyphWidthTwips,
|
|
366
|
+
};
|
|
367
|
+
const runId = `${input.block.blockId}:${segment.segmentId}`;
|
|
368
|
+
anchors.push({
|
|
369
|
+
anchorId: `${input.fragment.fragmentId}:line-${input.lineIndex}:${segment.segmentId}`,
|
|
370
|
+
runId,
|
|
371
|
+
segmentId: segment.segmentId,
|
|
372
|
+
blockId: input.block.blockId,
|
|
373
|
+
fragmentId: input.fragment.fragmentId,
|
|
374
|
+
lineIndex: input.lineIndex,
|
|
375
|
+
direction: input.direction,
|
|
376
|
+
baselinePageYTwips: input.baselinePageYTwips,
|
|
377
|
+
lineRectTwips: { ...input.rectTwips },
|
|
378
|
+
firstGlyphRectTwips,
|
|
379
|
+
lastGlyphRectTwips,
|
|
380
|
+
runRectTwips,
|
|
381
|
+
precision: "layout-estimate",
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return anchors;
|
|
385
|
+
}
|
|
386
|
+
|
|
244
387
|
/**
|
|
245
388
|
* Emit one fragment per slice for a paragraph that pagination split across
|
|
246
389
|
* pages. The source `block` offset range stays intact on every slice; the
|
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
RuntimePageNode,
|
|
35
35
|
RuntimePageRegion,
|
|
36
36
|
RuntimePageRegions,
|
|
37
|
+
RuntimeLineRunAnchor,
|
|
37
38
|
RuntimeStoryAnchoredObject,
|
|
38
39
|
RuntimeTwipsRect,
|
|
39
40
|
} from "./page-graph.ts";
|
|
@@ -189,6 +190,7 @@ export interface PublicStoryAnchoredObject {
|
|
|
189
190
|
widthTwips: number;
|
|
190
191
|
heightTwips: number;
|
|
191
192
|
};
|
|
193
|
+
anchorRectTwips?: PublicTwipsRect;
|
|
192
194
|
relationshipIds?: readonly string[];
|
|
193
195
|
mediaIds?: readonly string[];
|
|
194
196
|
preserveOnly: boolean;
|
|
@@ -325,8 +327,28 @@ export interface PublicLineBox {
|
|
|
325
327
|
fragmentId: string;
|
|
326
328
|
lineIndex: number;
|
|
327
329
|
baselineTwips: number;
|
|
330
|
+
baselinePageYTwips?: number;
|
|
328
331
|
heightTwips: number;
|
|
329
332
|
widthTwips: number;
|
|
333
|
+
rectTwips?: PublicTwipsRect;
|
|
334
|
+
direction?: "ltr" | "rtl";
|
|
335
|
+
runAnchors?: readonly PublicLineRunAnchor[];
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export interface PublicLineRunAnchor {
|
|
339
|
+
anchorId: string;
|
|
340
|
+
runId: string;
|
|
341
|
+
segmentId: string;
|
|
342
|
+
blockId: string;
|
|
343
|
+
fragmentId: string;
|
|
344
|
+
lineIndex: number;
|
|
345
|
+
direction: "ltr" | "rtl";
|
|
346
|
+
baselinePageYTwips: number;
|
|
347
|
+
lineRectTwips: PublicTwipsRect;
|
|
348
|
+
firstGlyphRectTwips: PublicTwipsRect;
|
|
349
|
+
lastGlyphRectTwips: PublicTwipsRect;
|
|
350
|
+
runRectTwips: PublicTwipsRect;
|
|
351
|
+
precision: RuntimeLineRunAnchor["precision"];
|
|
330
352
|
}
|
|
331
353
|
|
|
332
354
|
export interface PublicNoteAllocation {
|
|
@@ -350,6 +372,36 @@ export interface PublicPageSpan {
|
|
|
350
372
|
pageCount: number;
|
|
351
373
|
}
|
|
352
374
|
|
|
375
|
+
export interface PublicPagePaginationTelemetry {
|
|
376
|
+
pageId: string;
|
|
377
|
+
pageIndex: number;
|
|
378
|
+
startOffset: number;
|
|
379
|
+
endOffset: number;
|
|
380
|
+
isBlankFiller: boolean;
|
|
381
|
+
materialization: NonNullable<RuntimePageNode["materialization"]>;
|
|
382
|
+
bodyFragmentCount: number;
|
|
383
|
+
/**
|
|
384
|
+
* Unique body block ids referenced by this page. Split blocks count once
|
|
385
|
+
* on each page they occupy, which makes this the useful page-window
|
|
386
|
+
* estimator for block-index based viewport callers.
|
|
387
|
+
*/
|
|
388
|
+
bodyBlockReferenceCount: number;
|
|
389
|
+
lineBoxCount: number;
|
|
390
|
+
noteAllocationCount: number;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export interface PublicPaginationTelemetry {
|
|
394
|
+
revision: number;
|
|
395
|
+
pageCount: number;
|
|
396
|
+
materializedPageCount: number;
|
|
397
|
+
unpaginatedPageCount: number;
|
|
398
|
+
bodyFragmentCount: number;
|
|
399
|
+
bodyBlockReferenceCount: number;
|
|
400
|
+
averageBodyFragmentsPerMaterializedPage: number;
|
|
401
|
+
averageBodyBlockReferencesPerMaterializedPage: number;
|
|
402
|
+
pages: readonly PublicPagePaginationTelemetry[];
|
|
403
|
+
}
|
|
404
|
+
|
|
353
405
|
export interface PublicSectionNode {
|
|
354
406
|
sectionIndex: number;
|
|
355
407
|
startOffset: number;
|
|
@@ -558,6 +610,13 @@ export interface WordReviewEditorLayoutFacet {
|
|
|
558
610
|
*/
|
|
559
611
|
getStoryRegionsOnPage(pageIndex: number): readonly PublicPageRegion[];
|
|
560
612
|
getFragmentsForPage(pageIndex: number): PublicBlockFragment[];
|
|
613
|
+
/**
|
|
614
|
+
* Per-page materialization and body block/fragment counts derived from the
|
|
615
|
+
* current page graph. Consumers that only have block-index viewport ranges
|
|
616
|
+
* can use this to estimate page windows from the actual document instead
|
|
617
|
+
* of hardcoded blocks-per-page constants.
|
|
618
|
+
*/
|
|
619
|
+
getPaginationTelemetry(): PublicPaginationTelemetry;
|
|
561
620
|
|
|
562
621
|
/**
|
|
563
622
|
* P8 — Returns per-region block snapshots for a page. Body resolves the
|
|
@@ -1231,6 +1290,10 @@ export function createLayoutFacet(
|
|
|
1231
1290
|
.map((f) => toPublicBlockFragment(f, graph));
|
|
1232
1291
|
},
|
|
1233
1292
|
|
|
1293
|
+
getPaginationTelemetry() {
|
|
1294
|
+
return toPublicPaginationTelemetry(currentGraph());
|
|
1295
|
+
},
|
|
1296
|
+
|
|
1234
1297
|
getResolvedFormatting(blockId) {
|
|
1235
1298
|
const state = currentFormatting();
|
|
1236
1299
|
const formatting = state.paragraphs.get(blockId);
|
|
@@ -1557,6 +1620,9 @@ function toPublicStoryAnchoredObject(
|
|
|
1557
1620
|
},
|
|
1558
1621
|
}
|
|
1559
1622
|
: {}),
|
|
1623
|
+
...(object.anchorRectTwips
|
|
1624
|
+
? { anchorRectTwips: toPublicTwipsRect(object.anchorRectTwips) }
|
|
1625
|
+
: {}),
|
|
1560
1626
|
...(object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {}),
|
|
1561
1627
|
...(object.mediaIds ? { mediaIds: [...object.mediaIds] } : {}),
|
|
1562
1628
|
preserveOnly: object.preserveOnly,
|
|
@@ -1646,6 +1712,76 @@ function toPublicBlockFragment(
|
|
|
1646
1712
|
};
|
|
1647
1713
|
}
|
|
1648
1714
|
|
|
1715
|
+
function bodyFragmentsForPage(
|
|
1716
|
+
node: RuntimePageNode,
|
|
1717
|
+
graph: RuntimePageGraph,
|
|
1718
|
+
): RuntimeBlockFragment[] {
|
|
1719
|
+
const bodyFragmentIds = new Set(node.regions.body.fragmentIds);
|
|
1720
|
+
return graph.fragments.filter((fragment) =>
|
|
1721
|
+
bodyFragmentIds.has(fragment.fragmentId),
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
function toPublicPagePaginationTelemetry(
|
|
1726
|
+
node: RuntimePageNode,
|
|
1727
|
+
graph: RuntimePageGraph,
|
|
1728
|
+
): PublicPagePaginationTelemetry {
|
|
1729
|
+
const bodyFragments = bodyFragmentsForPage(node, graph);
|
|
1730
|
+
const bodyBlockIds = new Set(bodyFragments.map((fragment) => fragment.blockId));
|
|
1731
|
+
return {
|
|
1732
|
+
pageId: node.pageId,
|
|
1733
|
+
pageIndex: node.pageIndex,
|
|
1734
|
+
startOffset: node.startOffset,
|
|
1735
|
+
endOffset: node.endOffset,
|
|
1736
|
+
isBlankFiller: node.isBlankFiller,
|
|
1737
|
+
materialization: node.materialization ?? "paginated",
|
|
1738
|
+
bodyFragmentCount: bodyFragments.length,
|
|
1739
|
+
bodyBlockReferenceCount: bodyBlockIds.size,
|
|
1740
|
+
lineBoxCount: node.lineBoxes.length,
|
|
1741
|
+
noteAllocationCount: node.noteAllocations.length,
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
function average(count: number, divisor: number): number {
|
|
1746
|
+
return divisor > 0 ? count / divisor : 0;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
function toPublicPaginationTelemetry(
|
|
1750
|
+
graph: RuntimePageGraph,
|
|
1751
|
+
): PublicPaginationTelemetry {
|
|
1752
|
+
const pages = graph.pages.map((node) =>
|
|
1753
|
+
toPublicPagePaginationTelemetry(node, graph),
|
|
1754
|
+
);
|
|
1755
|
+
const materializedPages = pages.filter(
|
|
1756
|
+
(page) => page.materialization === "paginated",
|
|
1757
|
+
);
|
|
1758
|
+
const bodyFragmentCount = materializedPages.reduce(
|
|
1759
|
+
(total, page) => total + page.bodyFragmentCount,
|
|
1760
|
+
0,
|
|
1761
|
+
);
|
|
1762
|
+
const bodyBlockReferenceCount = materializedPages.reduce(
|
|
1763
|
+
(total, page) => total + page.bodyBlockReferenceCount,
|
|
1764
|
+
0,
|
|
1765
|
+
);
|
|
1766
|
+
return {
|
|
1767
|
+
revision: graph.revision,
|
|
1768
|
+
pageCount: pages.length,
|
|
1769
|
+
materializedPageCount: materializedPages.length,
|
|
1770
|
+
unpaginatedPageCount: pages.length - materializedPages.length,
|
|
1771
|
+
bodyFragmentCount,
|
|
1772
|
+
bodyBlockReferenceCount,
|
|
1773
|
+
averageBodyFragmentsPerMaterializedPage: average(
|
|
1774
|
+
bodyFragmentCount,
|
|
1775
|
+
materializedPages.length,
|
|
1776
|
+
),
|
|
1777
|
+
averageBodyBlockReferencesPerMaterializedPage: average(
|
|
1778
|
+
bodyBlockReferenceCount,
|
|
1779
|
+
materializedPages.length,
|
|
1780
|
+
),
|
|
1781
|
+
pages,
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1649
1785
|
function cloneContinuationCursor(
|
|
1650
1786
|
cursor: RuntimeLayoutContinuationCursor,
|
|
1651
1787
|
): RuntimeLayoutContinuationCursor {
|
|
@@ -1724,8 +1860,32 @@ function toPublicLineBox(box: RuntimeLineBox): PublicLineBox {
|
|
|
1724
1860
|
fragmentId: box.fragmentId,
|
|
1725
1861
|
lineIndex: box.lineIndex,
|
|
1726
1862
|
baselineTwips: box.baselineTwips,
|
|
1863
|
+
...(box.baselinePageYTwips !== undefined
|
|
1864
|
+
? { baselinePageYTwips: box.baselinePageYTwips }
|
|
1865
|
+
: {}),
|
|
1727
1866
|
heightTwips: box.heightTwips,
|
|
1728
1867
|
widthTwips: box.widthTwips,
|
|
1868
|
+
...(box.rectTwips ? { rectTwips: toPublicTwipsRect(box.rectTwips) } : {}),
|
|
1869
|
+
...(box.direction ? { direction: box.direction } : {}),
|
|
1870
|
+
...(box.runAnchors ? { runAnchors: box.runAnchors.map(toPublicLineRunAnchor) } : {}),
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
function toPublicLineRunAnchor(anchor: RuntimeLineRunAnchor): PublicLineRunAnchor {
|
|
1875
|
+
return {
|
|
1876
|
+
anchorId: anchor.anchorId,
|
|
1877
|
+
runId: anchor.runId,
|
|
1878
|
+
segmentId: anchor.segmentId,
|
|
1879
|
+
blockId: anchor.blockId,
|
|
1880
|
+
fragmentId: anchor.fragmentId,
|
|
1881
|
+
lineIndex: anchor.lineIndex,
|
|
1882
|
+
direction: anchor.direction,
|
|
1883
|
+
baselinePageYTwips: anchor.baselinePageYTwips,
|
|
1884
|
+
lineRectTwips: toPublicTwipsRect(anchor.lineRectTwips),
|
|
1885
|
+
firstGlyphRectTwips: toPublicTwipsRect(anchor.firstGlyphRectTwips),
|
|
1886
|
+
lastGlyphRectTwips: toPublicTwipsRect(anchor.lastGlyphRectTwips),
|
|
1887
|
+
runRectTwips: toPublicTwipsRect(anchor.runRectTwips),
|
|
1888
|
+
precision: anchor.precision,
|
|
1729
1889
|
};
|
|
1730
1890
|
}
|
|
1731
1891
|
|