@beyondwork/docx-react-component 1.0.106 → 1.0.109
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 +19 -5
- package/src/api/geometry-overlay-rects.ts +5 -0
- package/src/api/package-version.ts +1 -1
- package/src/api/page-anchor-id.ts +5 -0
- package/src/api/public-types.ts +16 -9
- package/src/api/table-node-specs.ts +6 -0
- package/src/api/v3/_create.ts +2 -1
- package/src/api/v3/_page-anchor-id.ts +52 -0
- package/src/api/v3/_runtime-handle.ts +92 -1
- package/src/api/v3/ai/_audit-time.ts +5 -0
- package/src/api/v3/ai/_pe2-evidence.ts +38 -0
- package/src/api/v3/ai/attach.ts +7 -2
- package/src/api/v3/ai/replacement.ts +101 -18
- package/src/api/v3/ai/resolve.ts +2 -2
- package/src/api/v3/ai/review.ts +177 -3
- package/src/api/v3/index.ts +1 -0
- package/src/api/v3/runtime/collab.ts +462 -0
- package/src/api/v3/runtime/document.ts +503 -20
- package/src/api/v3/runtime/geometry.ts +97 -0
- package/src/api/v3/runtime/layout.ts +744 -0
- package/src/api/v3/runtime/perf-probe.ts +14 -0
- package/src/api/v3/runtime/viewport.ts +9 -8
- package/src/api/v3/ui/_types.ts +149 -55
- package/src/api/v3/ui/chrome-preset-model.ts +5 -5
- package/src/api/v3/ui/debug.ts +115 -2
- package/src/api/v3/ui/index.ts +13 -0
- package/src/api/v3/ui/overlays.ts +0 -8
- package/src/api/v3/ui/surface.ts +56 -0
- package/src/api/v3/ui/viewport.ts +22 -9
- package/src/core/commands/image-commands.ts +1 -0
- package/src/core/commands/index.ts +6 -0
- package/src/core/schema/text-schema.ts +43 -5
- package/src/core/selection/mapping.ts +8 -1
- package/src/core/selection/review-anchors.ts +5 -1
- package/src/core/state/text-transaction.ts +8 -2
- package/src/io/export/serialize-revisions.ts +149 -1
- package/src/io/normalize/normalize-text.ts +6 -0
- package/src/io/ooxml/parse-bookmark-references.ts +55 -0
- package/src/io/ooxml/parse-fields.ts +24 -2
- package/src/io/ooxml/parse-headers-footers.ts +38 -5
- package/src/io/ooxml/parse-main-document.ts +153 -9
- package/src/io/ooxml/parse-numbering.ts +20 -0
- package/src/io/ooxml/parse-revisions.ts +19 -8
- package/src/io/opc/package-reader.ts +98 -8
- package/src/model/anchor.ts +4 -3
- package/src/model/canonical-document.ts +220 -2
- package/src/model/canonical-hash.ts +221 -0
- package/src/model/canonical-layout-inputs.ts +245 -6
- package/src/model/layout/index.ts +1 -0
- package/src/model/layout/page-graph-types.ts +118 -1
- package/src/model/review/revision-types.ts +14 -3
- package/src/preservation/store.ts +20 -4
- package/src/review/README.md +1 -1
- package/src/review/store/revision-actions.ts +14 -2
- package/src/runtime/collab/event-types.ts +67 -1
- package/src/runtime/collab/runtime-collab-sync.ts +177 -5
- package/src/runtime/diagnostics/layout-guard-warning.ts +18 -0
- package/src/runtime/document-heading-outline.ts +147 -0
- package/src/runtime/document-navigation.ts +8 -243
- package/src/runtime/document-runtime.ts +240 -97
- package/src/runtime/edit-dispatch/dispatch-text-command.ts +11 -0
- package/src/runtime/formatting/layout-inputs.ts +38 -5
- package/src/runtime/formatting/numbering/geometry.ts +28 -2
- package/src/runtime/geometry/adjacent-geometry-intake.ts +835 -0
- package/src/runtime/geometry/caret-geometry.ts +5 -6
- package/src/runtime/geometry/geometry-facet.ts +60 -10
- package/src/runtime/geometry/geometry-index.ts +591 -20
- package/src/runtime/geometry/geometry-types.ts +59 -0
- package/src/runtime/geometry/hit-test.ts +11 -1
- package/src/runtime/geometry/overlay-rects.ts +5 -3
- package/src/runtime/geometry/project-anchors.ts +1 -1
- package/src/runtime/geometry/word-layout-v2-line-intake.ts +323 -0
- package/src/runtime/layout/index.ts +6 -0
- package/src/runtime/layout/layout-engine-instance.ts +6 -1
- package/src/runtime/layout/layout-engine-version.ts +181 -16
- package/src/runtime/layout/layout-facet-types.ts +6 -0
- package/src/runtime/layout/page-graph.ts +21 -4
- package/src/runtime/layout/paginated-layout-engine.ts +139 -15
- package/src/runtime/layout/project-block-fragments.ts +265 -7
- package/src/runtime/layout/public-facet.ts +78 -24
- package/src/runtime/layout/table-row-continuation-contract.ts +107 -0
- package/src/runtime/layout/table-row-split.ts +92 -35
- package/src/runtime/prerender/cache-envelope.ts +2 -2
- package/src/runtime/prerender/cache-key.ts +5 -4
- package/src/runtime/prerender/customxml-cache.ts +0 -1
- package/src/runtime/render/render-kernel.ts +1 -1
- package/src/runtime/revision-runtime.ts +112 -10
- package/src/runtime/scopes/_scope-dependencies.ts +1 -0
- package/src/runtime/scopes/action-validation.ts +22 -2
- package/src/runtime/scopes/capabilities.ts +316 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +14 -0
- package/src/runtime/scopes/compiler-service.ts +108 -4
- package/src/runtime/scopes/content-control-evidence.ts +79 -0
- package/src/runtime/scopes/create-issue.ts +5 -5
- package/src/runtime/scopes/evidence.ts +91 -0
- package/src/runtime/scopes/formatting/apply.ts +2 -0
- package/src/runtime/scopes/geometry-evidence.ts +130 -0
- package/src/runtime/scopes/index.ts +54 -0
- package/src/runtime/scopes/issue-lifecycle.ts +224 -0
- package/src/runtime/scopes/layout-evidence.ts +374 -0
- package/src/runtime/scopes/multi-paragraph-refusal.ts +37 -0
- package/src/runtime/scopes/preservation-boundary.ts +7 -1
- package/src/runtime/scopes/replacement/apply.ts +97 -34
- package/src/runtime/scopes/scope-kinds/paragraph.ts +108 -12
- package/src/runtime/scopes/semantic-scope-types.ts +242 -3
- package/src/runtime/scopes/visualization.ts +28 -0
- package/src/runtime/surface-projection.ts +44 -5
- package/src/runtime/telemetry/perf-probe.ts +216 -0
- package/src/runtime/virtualized-rendering.ts +36 -1
- package/src/runtime/workflow/ai-issue-lifecycle.ts +253 -0
- package/src/runtime/workflow/coordinator.ts +39 -11
- package/src/runtime/workflow/derived-scope-resolver.ts +63 -9
- package/src/runtime/workflow/index.ts +3 -0
- package/src/runtime/workflow/overlay-lane-types.ts +58 -0
- package/src/runtime/workflow/overlay-lanes.ts +168 -10
- package/src/runtime/workflow/overlay-store.ts +2 -2
- package/src/runtime/workflow/redline-posture-calibration.ts +257 -0
- package/src/runtime/workflow/word-field-matrix-calibration.ts +231 -0
- package/src/session/_sync-legacy.ts +17 -27
- package/src/session/import/loader.ts +6 -4
- package/src/session/import/source-package-evidence.ts +186 -2
- package/src/session/index.ts +5 -6
- package/src/session/session.ts +30 -56
- package/src/session/types.ts +8 -13
- package/src/shell/session-bootstrap.ts +155 -81
- package/src/ui/WordReviewEditor.tsx +520 -12
- package/src/ui/editor-shell-view.tsx +14 -4
- package/src/ui/editor-surface-controller.tsx +5 -3
- package/src/ui/headless/selection-tool-resolver.ts +1 -2
- package/src/ui/presence-overlay-lane.ts +0 -1
- package/src/ui/ui-controller-factory.ts +7 -0
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +5 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +105 -5
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +7 -0
- package/src/ui-tailwind/chrome/layer-debug-contracts.ts +208 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +13 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +11 -3
- package/src/ui-tailwind/chrome/tw-command-palette.tsx +36 -6
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +6 -1
- package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +42 -109
- package/src/ui-tailwind/chrome/tw-inline-find-bar.tsx +26 -6
- package/src/ui-tailwind/chrome/tw-navigation-command-bar.tsx +328 -0
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +8 -4
- package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +129 -1
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +19 -5
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +5 -1
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +28 -12
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +30 -3
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +116 -10
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +223 -94
- package/src/ui-tailwind/chrome-overlay/tw-presence-overlay-lane.tsx +157 -0
- package/src/ui-tailwind/chrome-overlay/tw-review-overlay-lane-markers.tsx +259 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +5 -2
- package/src/ui-tailwind/chrome-overlay/tw-substrate-overlay-lanes.tsx +314 -0
- package/src/ui-tailwind/debug/README.md +4 -1
- package/src/ui-tailwind/debug/layer11-consumer-readiness.ts +272 -0
- package/src/ui-tailwind/debug/layer11-word-field-matrix-evidence.ts +160 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +14 -215
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +42 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +38 -2
- package/src/ui-tailwind/editor-surface/pm-schema.ts +14 -4
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +34 -5
- package/src/ui-tailwind/editor-surface/runtime-decoration-plugin.ts +9 -19
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -2
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +145 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +16 -11
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +8 -10
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +3 -0
- package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +4 -2
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +60 -20
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +16 -11
- package/src/ui-tailwind/review/tw-health-panel.tsx +36 -17
- package/src/ui-tailwind/review/tw-review-rail.tsx +7 -4
- package/src/ui-tailwind/review-workspace/diagnostics-visibility.ts +44 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +11 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +16 -1
- package/src/ui-tailwind/review-workspace/types.ts +26 -12
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +40 -11
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +15 -26
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +35 -18
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +41 -32
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +2 -1
- package/src/ui-tailwind/status/tw-status-bar.tsx +6 -5
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +52 -80
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +12 -48
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +9 -4
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +328 -361
- package/src/ui-tailwind/tw-review-workspace.tsx +152 -286
|
@@ -44,12 +44,15 @@ import type {
|
|
|
44
44
|
GeometryIndexRegion,
|
|
45
45
|
GeometryIndexSlice,
|
|
46
46
|
GeometryObjectHandleEntry,
|
|
47
|
+
GeometryPageFrameCompleteness,
|
|
48
|
+
GeometryPageFrameCompletenessCounts,
|
|
47
49
|
GeometryPrecision,
|
|
48
50
|
GeometryPrecisionCounts,
|
|
49
51
|
GeometryRect,
|
|
50
52
|
GeometryRehydrationStatus,
|
|
51
53
|
GeometryReplacementEnvelopeEntry,
|
|
52
54
|
GeometrySourceIdentity,
|
|
55
|
+
GeometryTableContinuation,
|
|
53
56
|
SemanticDisplayEntry,
|
|
54
57
|
} from "./geometry-types.ts";
|
|
55
58
|
import { buildObjectHandleRectsFromRect } from "./object-handles.ts";
|
|
@@ -63,14 +66,18 @@ export function createUnavailableGeometryCoverage(): GeometryIndexCoverage {
|
|
|
63
66
|
return {
|
|
64
67
|
status: "unavailable",
|
|
65
68
|
pageCount: 0,
|
|
69
|
+
pageFrameCompleteness: createPageFrameCompletenessCounts(),
|
|
66
70
|
regionCount: 0,
|
|
67
71
|
sliceCount: 0,
|
|
68
72
|
lineCount: 0,
|
|
69
73
|
anchorCount: 0,
|
|
70
74
|
hitTargetCount: 0,
|
|
71
75
|
semanticEntryCount: 0,
|
|
76
|
+
pageLocalFieldLedgerCount: 0,
|
|
72
77
|
replacementEnvelopeCount: 0,
|
|
73
78
|
objectHandleCount: 0,
|
|
79
|
+
layoutDivergenceObjectCount: 0,
|
|
80
|
+
splitRowCarryCount: 0,
|
|
74
81
|
precision: createPrecisionCounts(),
|
|
75
82
|
};
|
|
76
83
|
}
|
|
@@ -93,8 +100,15 @@ export function projectGeometryIndexFromFrame(
|
|
|
93
100
|
const objectHandleEntries = new Map<string, MutableObjectHandleEntry>();
|
|
94
101
|
const projectedBlocksByStory = new Map<string, ProjectedScopeBlock[]>();
|
|
95
102
|
const precision = createPrecisionCounts();
|
|
103
|
+
const pageFrameCompleteness = createPageFrameCompletenessCounts();
|
|
104
|
+
let pageLocalFieldLedgerCount = 0;
|
|
105
|
+
let layoutDivergenceObjectCount = 0;
|
|
106
|
+
let splitRowCarryCount = 0;
|
|
96
107
|
|
|
97
108
|
for (const page of frame.pages) {
|
|
109
|
+
const pageMetadata = pageFrameMetadata(page);
|
|
110
|
+
pageFrameCompleteness[pageMetadata.frameCompleteness] += 1;
|
|
111
|
+
layoutDivergenceObjectCount += pageMetadata.layoutDivergenceObjectIds.length;
|
|
98
112
|
const regionEntries = collectRegionEntries(page);
|
|
99
113
|
const regionIds: string[] = [];
|
|
100
114
|
|
|
@@ -107,6 +121,7 @@ export function projectGeometryIndexFromFrame(
|
|
|
107
121
|
const sliceIds: string[] = [];
|
|
108
122
|
|
|
109
123
|
for (const block of region.blocks) {
|
|
124
|
+
splitRowCarryCount += countSplitRowCarry(block);
|
|
110
125
|
const sliceId = makeSliceId(regionId, block.fragment.fragmentId);
|
|
111
126
|
const sliceIdentity = identities?.sliceIdentity(
|
|
112
127
|
storyKey,
|
|
@@ -142,7 +157,7 @@ export function projectGeometryIndexFromFrame(
|
|
|
142
157
|
fragmentId: anchor.fragmentId,
|
|
143
158
|
lineId,
|
|
144
159
|
runtimeOffset: anchor.runtimeOffset,
|
|
145
|
-
rect: toGeometryRect(anchor.frame),
|
|
160
|
+
rect: { ...toGeometryRect(anchor.frame), precision: "exact" },
|
|
146
161
|
precision: "exact",
|
|
147
162
|
...(anchorIdentity ? { sourceIdentity: anchorIdentity } : {}),
|
|
148
163
|
});
|
|
@@ -158,7 +173,7 @@ export function projectGeometryIndexFromFrame(
|
|
|
158
173
|
blockId: block.fragment.blockId,
|
|
159
174
|
fragmentId: block.fragment.fragmentId,
|
|
160
175
|
lineIndex: line.line.lineIndex,
|
|
161
|
-
rect: toGeometryRect(line.frame),
|
|
176
|
+
rect: { ...toGeometryRect(line.frame), precision: "exact" },
|
|
162
177
|
anchorIds,
|
|
163
178
|
});
|
|
164
179
|
recordPrecision(precision, "exact");
|
|
@@ -171,7 +186,7 @@ export function projectGeometryIndexFromFrame(
|
|
|
171
186
|
blockId: block.fragment.blockId,
|
|
172
187
|
fragmentId: block.fragment.fragmentId,
|
|
173
188
|
lineIndex: line.line.lineIndex,
|
|
174
|
-
rect: toGeometryRect(line.frame),
|
|
189
|
+
rect: { ...toGeometryRect(line.frame), precision: "exact" },
|
|
175
190
|
precision: "exact",
|
|
176
191
|
});
|
|
177
192
|
recordPrecision(precision, "exact");
|
|
@@ -189,6 +204,7 @@ export function projectGeometryIndexFromFrame(
|
|
|
189
204
|
rect: toGeometryRect(line.frame),
|
|
190
205
|
status: "realized",
|
|
191
206
|
precision: "exact",
|
|
207
|
+
frameCompleteness: pageMetadata.frameCompleteness,
|
|
192
208
|
});
|
|
193
209
|
recordPrecision(precision, "exact");
|
|
194
210
|
}
|
|
@@ -237,6 +253,9 @@ export function projectGeometryIndexFromFrame(
|
|
|
237
253
|
entries: semanticEntries,
|
|
238
254
|
projectedBlocksByStory,
|
|
239
255
|
precision,
|
|
256
|
+
frameCompleteness: pageMetadata.frameCompleteness,
|
|
257
|
+
layoutDivergenceIds: pageMetadata.layoutDivergenceIds,
|
|
258
|
+
layoutDivergenceObjectIds: pageMetadata.layoutDivergenceObjectIds,
|
|
240
259
|
});
|
|
241
260
|
}
|
|
242
261
|
|
|
@@ -257,12 +276,31 @@ export function projectGeometryIndexFromFrame(
|
|
|
257
276
|
pageIndex: page.page.pageIndex,
|
|
258
277
|
rect: toGeometryRect(page.frame),
|
|
259
278
|
regionIds,
|
|
279
|
+
frameCompleteness: pageMetadata.frameCompleteness,
|
|
280
|
+
...(pageMetadata.displayPageNumber !== undefined
|
|
281
|
+
? { displayPageNumber: pageMetadata.displayPageNumber }
|
|
282
|
+
: {}),
|
|
283
|
+
...(pageMetadata.layoutDivergenceIds.length > 0
|
|
284
|
+
? { layoutDivergenceIds: pageMetadata.layoutDivergenceIds }
|
|
285
|
+
: {}),
|
|
286
|
+
...(pageMetadata.layoutDivergenceObjectIds.length > 0
|
|
287
|
+
? { layoutDivergenceObjectIds: pageMetadata.layoutDivergenceObjectIds }
|
|
288
|
+
: {}),
|
|
260
289
|
});
|
|
261
290
|
recordPrecision(precision, "exact");
|
|
291
|
+
pageLocalFieldLedgerCount += appendPageLocalFieldLedgerSemanticEntries({
|
|
292
|
+
page,
|
|
293
|
+
entries: semanticEntries,
|
|
294
|
+
precision,
|
|
295
|
+
frameCompleteness: pageMetadata.frameCompleteness,
|
|
296
|
+
layoutDivergenceIds: pageMetadata.layoutDivergenceIds,
|
|
297
|
+
layoutDivergenceObjectIds: pageMetadata.layoutDivergenceObjectIds,
|
|
298
|
+
});
|
|
262
299
|
appendPageLocalObjectHandleEntries({
|
|
263
300
|
page,
|
|
264
301
|
entries: objectHandleEntries,
|
|
265
302
|
precision,
|
|
303
|
+
divergenceIdsByObjectId: pageMetadata.divergenceIdsByObjectId,
|
|
266
304
|
});
|
|
267
305
|
}
|
|
268
306
|
|
|
@@ -277,14 +315,18 @@ export function projectGeometryIndexFromFrame(
|
|
|
277
315
|
const coverage: GeometryIndexCoverage = {
|
|
278
316
|
status: "realized",
|
|
279
317
|
pageCount: pages.length,
|
|
318
|
+
pageFrameCompleteness,
|
|
280
319
|
regionCount: regions.length,
|
|
281
320
|
sliceCount: slices.length,
|
|
282
321
|
lineCount: lines.length,
|
|
283
322
|
anchorCount: anchors.length,
|
|
284
323
|
hitTargetCount: hitTargets.length,
|
|
285
324
|
semanticEntryCount: semanticEntries.length,
|
|
325
|
+
pageLocalFieldLedgerCount,
|
|
286
326
|
replacementEnvelopeCount: replacementEnvelopes.length,
|
|
287
327
|
objectHandleCount: objectHandles.length,
|
|
328
|
+
layoutDivergenceObjectCount,
|
|
329
|
+
splitRowCarryCount,
|
|
288
330
|
precision,
|
|
289
331
|
};
|
|
290
332
|
|
|
@@ -312,6 +354,7 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
312
354
|
if (!frame) return createUnavailableGeometryCoverage();
|
|
313
355
|
|
|
314
356
|
const precision = createPrecisionCounts();
|
|
357
|
+
const pageFrameCompleteness = createPageFrameCompletenessCounts();
|
|
315
358
|
let pageCount = 0;
|
|
316
359
|
let regionCount = 0;
|
|
317
360
|
let sliceCount = 0;
|
|
@@ -319,14 +362,25 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
319
362
|
let anchorCount = 0;
|
|
320
363
|
let hitTargetCount = 0;
|
|
321
364
|
let semanticEntryCount = 0;
|
|
365
|
+
let pageLocalFieldLedgerCount = 0;
|
|
366
|
+
let layoutDivergenceObjectCount = 0;
|
|
367
|
+
let splitRowCarryCount = 0;
|
|
322
368
|
|
|
323
369
|
for (const page of frame.pages) {
|
|
370
|
+
const pageMetadata = pageFrameMetadata(page);
|
|
324
371
|
pageCount += 1;
|
|
372
|
+
pageFrameCompleteness[pageMetadata.frameCompleteness] += 1;
|
|
373
|
+
layoutDivergenceObjectCount += pageMetadata.layoutDivergenceObjectIds.length;
|
|
325
374
|
recordPrecision(precision, "exact");
|
|
375
|
+
const pageLocalFieldCount = countPageLocalFieldLedgers(page);
|
|
376
|
+
pageLocalFieldLedgerCount += pageLocalFieldCount;
|
|
377
|
+
semanticEntryCount += pageLocalFieldCount;
|
|
378
|
+
precision["within-tolerance"] += pageLocalFieldCount;
|
|
326
379
|
for (const [region] of collectRegionEntries(page)) {
|
|
327
380
|
regionCount += 1;
|
|
328
381
|
recordPrecision(precision, "exact");
|
|
329
382
|
for (const block of region.blocks) {
|
|
383
|
+
splitRowCarryCount += countSplitRowCarry(block);
|
|
330
384
|
sliceCount += 1;
|
|
331
385
|
recordPrecision(precision, "exact");
|
|
332
386
|
for (const line of block.lines) {
|
|
@@ -355,18 +409,127 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
355
409
|
return {
|
|
356
410
|
status: "realized",
|
|
357
411
|
pageCount,
|
|
412
|
+
pageFrameCompleteness,
|
|
358
413
|
regionCount,
|
|
359
414
|
sliceCount,
|
|
360
415
|
lineCount,
|
|
361
416
|
anchorCount,
|
|
362
417
|
hitTargetCount,
|
|
363
418
|
semanticEntryCount,
|
|
419
|
+
pageLocalFieldLedgerCount,
|
|
364
420
|
replacementEnvelopeCount: 0,
|
|
365
421
|
objectHandleCount: 0,
|
|
422
|
+
layoutDivergenceObjectCount,
|
|
423
|
+
splitRowCarryCount,
|
|
366
424
|
precision,
|
|
367
425
|
};
|
|
368
426
|
}
|
|
369
427
|
|
|
428
|
+
interface PageFrameMetadata {
|
|
429
|
+
frameCompleteness: GeometryPageFrameCompleteness;
|
|
430
|
+
displayPageNumber?: number;
|
|
431
|
+
layoutDivergenceIds: readonly string[];
|
|
432
|
+
layoutDivergenceObjectIds: readonly string[];
|
|
433
|
+
divergenceIdsByObjectId: ReadonlyMap<string, readonly string[]>;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function pageFrameMetadata(page: RenderPage): PageFrameMetadata {
|
|
437
|
+
const frame = page.page.frame;
|
|
438
|
+
const divergenceIds = frame?.divergenceIds ? [...frame.divergenceIds] : [];
|
|
439
|
+
const divergenceIdsByObjectId = new Map<string, string[]>();
|
|
440
|
+
for (const divergence of page.page.divergences ?? []) {
|
|
441
|
+
for (const objectId of divergence.objectIds ?? []) {
|
|
442
|
+
const list = divergenceIdsByObjectId.get(objectId);
|
|
443
|
+
if (list) {
|
|
444
|
+
appendUnique(list, divergence.divergenceId);
|
|
445
|
+
} else {
|
|
446
|
+
divergenceIdsByObjectId.set(objectId, [divergence.divergenceId]);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
const objectIds = Array.from(divergenceIdsByObjectId.keys()).sort();
|
|
451
|
+
return {
|
|
452
|
+
frameCompleteness: frame?.completeness ?? "absent",
|
|
453
|
+
...(frame?.displayPageNumber !== undefined
|
|
454
|
+
? { displayPageNumber: frame.displayPageNumber }
|
|
455
|
+
: {}),
|
|
456
|
+
layoutDivergenceIds: divergenceIds,
|
|
457
|
+
layoutDivergenceObjectIds: objectIds,
|
|
458
|
+
divergenceIdsByObjectId,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function appendPageLocalFieldLedgerSemanticEntries(input: {
|
|
463
|
+
page: RenderPage;
|
|
464
|
+
entries: SemanticDisplayEntry[];
|
|
465
|
+
precision: GeometryPrecisionCounts;
|
|
466
|
+
frameCompleteness: GeometryPageFrameCompleteness;
|
|
467
|
+
layoutDivergenceIds: readonly string[];
|
|
468
|
+
layoutDivergenceObjectIds: readonly string[];
|
|
469
|
+
}): number {
|
|
470
|
+
const {
|
|
471
|
+
page,
|
|
472
|
+
entries,
|
|
473
|
+
precision,
|
|
474
|
+
frameCompleteness,
|
|
475
|
+
layoutDivergenceIds,
|
|
476
|
+
layoutDivergenceObjectIds,
|
|
477
|
+
} = input;
|
|
478
|
+
let count = 0;
|
|
479
|
+
for (const story of page.page.frame?.pageLocalStories ?? []) {
|
|
480
|
+
if (story.resolvedFields.length === 0) continue;
|
|
481
|
+
const region =
|
|
482
|
+
story.kind === "header" ? page.regions.header : page.regions.footer;
|
|
483
|
+
if (!region) continue;
|
|
484
|
+
for (const field of story.resolvedFields) {
|
|
485
|
+
entries.push({
|
|
486
|
+
entryId: `semantic:page-local-field-ledger:${page.page.pageId}:${story.instanceId}:${field.fieldId}`,
|
|
487
|
+
kind: "page-local-field-ledger",
|
|
488
|
+
pageId: page.page.pageId,
|
|
489
|
+
pageIndex: page.page.pageIndex,
|
|
490
|
+
regionKind: region.region.kind,
|
|
491
|
+
pageLocalStoryId: story.instanceId,
|
|
492
|
+
pageLocalStoryKind: story.kind,
|
|
493
|
+
pageLocalStoryVariant: story.variant,
|
|
494
|
+
resolvedFieldId: field.fieldId,
|
|
495
|
+
resolvedFieldFamily: field.family,
|
|
496
|
+
resolvedFieldDisplayText: field.displayText,
|
|
497
|
+
frameCompleteness,
|
|
498
|
+
...(layoutDivergenceIds.length > 0 ? { layoutDivergenceIds } : {}),
|
|
499
|
+
...(layoutDivergenceObjectIds.length > 0
|
|
500
|
+
? { layoutDivergenceObjectIds }
|
|
501
|
+
: {}),
|
|
502
|
+
rect: {
|
|
503
|
+
...toGeometryRect(region.frame),
|
|
504
|
+
precision: "within-tolerance",
|
|
505
|
+
},
|
|
506
|
+
status: "realized",
|
|
507
|
+
precision: "within-tolerance",
|
|
508
|
+
});
|
|
509
|
+
recordPrecision(precision, "within-tolerance");
|
|
510
|
+
count += 1;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return count;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function countPageLocalFieldLedgers(page: RenderPage): number {
|
|
517
|
+
let count = 0;
|
|
518
|
+
for (const story of page.page.frame?.pageLocalStories ?? []) {
|
|
519
|
+
const region =
|
|
520
|
+
story.kind === "header" ? page.regions.header : page.regions.footer;
|
|
521
|
+
if (!region) continue;
|
|
522
|
+
count += story.resolvedFields.length;
|
|
523
|
+
}
|
|
524
|
+
return count;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function countSplitRowCarry(block: RenderBlock): number {
|
|
528
|
+
return block.fragment.continuation?.kind === "table"
|
|
529
|
+
? block.fragment.continuation.splitRowCarry?.length ?? 0
|
|
530
|
+
: 0;
|
|
531
|
+
}
|
|
532
|
+
|
|
370
533
|
function appendBlockSemanticEntries(input: {
|
|
371
534
|
page: RenderPage;
|
|
372
535
|
region: RenderStoryRegion;
|
|
@@ -378,6 +541,9 @@ function appendBlockSemanticEntries(input: {
|
|
|
378
541
|
entries: SemanticDisplayEntry[];
|
|
379
542
|
projectedBlocksByStory: Map<string, ProjectedScopeBlock[]>;
|
|
380
543
|
precision: GeometryPrecisionCounts;
|
|
544
|
+
frameCompleteness: GeometryPageFrameCompleteness;
|
|
545
|
+
layoutDivergenceIds: readonly string[];
|
|
546
|
+
layoutDivergenceObjectIds: readonly string[];
|
|
381
547
|
}): void {
|
|
382
548
|
const {
|
|
383
549
|
page,
|
|
@@ -390,11 +556,18 @@ function appendBlockSemanticEntries(input: {
|
|
|
390
556
|
entries,
|
|
391
557
|
projectedBlocksByStory,
|
|
392
558
|
precision,
|
|
559
|
+
frameCompleteness,
|
|
560
|
+
layoutDivergenceIds,
|
|
561
|
+
layoutDivergenceObjectIds,
|
|
393
562
|
} = input;
|
|
394
563
|
const tableIdentity = identities?.tableIdentity(
|
|
395
564
|
storyKey,
|
|
396
565
|
block.fragment.blockId,
|
|
397
566
|
);
|
|
567
|
+
const sliceIdentity = identities?.sliceIdentity(
|
|
568
|
+
storyKey,
|
|
569
|
+
block.fragment.blockId,
|
|
570
|
+
);
|
|
398
571
|
const base = {
|
|
399
572
|
pageId: page.page.pageId,
|
|
400
573
|
pageIndex: page.page.pageIndex,
|
|
@@ -405,7 +578,19 @@ function appendBlockSemanticEntries(input: {
|
|
|
405
578
|
fragmentId: block.fragment.fragmentId,
|
|
406
579
|
} as const;
|
|
407
580
|
|
|
581
|
+
appendFragmentLayoutObjectSemanticEntries({
|
|
582
|
+
base,
|
|
583
|
+
block,
|
|
584
|
+
sourceIdentity: sliceIdentity,
|
|
585
|
+
entries,
|
|
586
|
+
precision,
|
|
587
|
+
frameCompleteness,
|
|
588
|
+
layoutDivergenceIds,
|
|
589
|
+
layoutDivergenceObjectIds,
|
|
590
|
+
});
|
|
591
|
+
|
|
408
592
|
if (block.kind === "table") {
|
|
593
|
+
const tableContinuation = tableContinuationMetadata(block);
|
|
409
594
|
entries.push({
|
|
410
595
|
...base,
|
|
411
596
|
entryId: `semantic:table-frame:${sliceId}`,
|
|
@@ -413,6 +598,12 @@ function appendBlockSemanticEntries(input: {
|
|
|
413
598
|
rect: toGeometryRect(block.frame),
|
|
414
599
|
status: "realized",
|
|
415
600
|
precision: "exact",
|
|
601
|
+
frameCompleteness,
|
|
602
|
+
...(layoutDivergenceIds.length > 0 ? { layoutDivergenceIds } : {}),
|
|
603
|
+
...(layoutDivergenceObjectIds.length > 0
|
|
604
|
+
? { layoutDivergenceObjectIds }
|
|
605
|
+
: {}),
|
|
606
|
+
...(tableContinuation ? { tableContinuation } : {}),
|
|
416
607
|
...(tableIdentity
|
|
417
608
|
? { sourceIdentity: tableSourceIdentity(tableIdentity) }
|
|
418
609
|
: {}),
|
|
@@ -421,6 +612,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
421
612
|
|
|
422
613
|
const plan = block.tablePlan;
|
|
423
614
|
if (!plan) return;
|
|
615
|
+
const visibleRows = resolveVisibleTableRows(block);
|
|
424
616
|
if (tableIdentity) {
|
|
425
617
|
recordTableCellScopeBlocks({
|
|
426
618
|
table: tableIdentity,
|
|
@@ -429,20 +621,23 @@ function appendBlockSemanticEntries(input: {
|
|
|
429
621
|
storyKey,
|
|
430
622
|
identities,
|
|
431
623
|
projectedBlocksByStory,
|
|
624
|
+
visibleRows,
|
|
432
625
|
});
|
|
433
626
|
}
|
|
434
|
-
const
|
|
627
|
+
const visibleRowCount = visibleRows.length;
|
|
435
628
|
const rowHeightPx =
|
|
436
|
-
|
|
437
|
-
|
|
629
|
+
visibleRowCount > 0
|
|
630
|
+
? block.frame.heightPx / visibleRowCount
|
|
631
|
+
: block.frame.heightPx;
|
|
632
|
+
for (const row of visibleRows) {
|
|
438
633
|
entries.push({
|
|
439
634
|
...base,
|
|
440
|
-
entryId: `semantic:table-row:${sliceId}:${rowIndex}`,
|
|
635
|
+
entryId: `semantic:table-row:${sliceId}:${row.rowIndex}`,
|
|
441
636
|
kind: "table-row",
|
|
442
|
-
rowIndex,
|
|
637
|
+
rowIndex: row.rowIndex,
|
|
443
638
|
rect: {
|
|
444
639
|
leftPx: block.frame.leftPx,
|
|
445
|
-
topPx: block.frame.topPx +
|
|
640
|
+
topPx: block.frame.topPx + row.visualIndex * rowHeightPx,
|
|
446
641
|
widthPx: block.frame.widthPx,
|
|
447
642
|
heightPx: rowHeightPx,
|
|
448
643
|
space: "frame",
|
|
@@ -450,15 +645,27 @@ function appendBlockSemanticEntries(input: {
|
|
|
450
645
|
},
|
|
451
646
|
status: "realized",
|
|
452
647
|
precision: "within-tolerance",
|
|
648
|
+
frameCompleteness,
|
|
649
|
+
...tableRowContinuationMetadata(block, row.rowIndex),
|
|
453
650
|
...(tableIdentity
|
|
454
|
-
? {
|
|
651
|
+
? {
|
|
652
|
+
sourceIdentity: tableRowSourceIdentity(
|
|
653
|
+
tableIdentity,
|
|
654
|
+
row.rowIndex,
|
|
655
|
+
),
|
|
656
|
+
}
|
|
455
657
|
: {}),
|
|
456
658
|
});
|
|
457
659
|
recordPrecision(precision, "within-tolerance");
|
|
458
660
|
}
|
|
459
661
|
|
|
460
662
|
for (const cell of plan.bandClasses.cells) {
|
|
461
|
-
const rect = pageFrameCellRect(
|
|
663
|
+
const rect = pageFrameCellRect(
|
|
664
|
+
block,
|
|
665
|
+
cell.rowIndex,
|
|
666
|
+
cell.columnIndex,
|
|
667
|
+
visibleRows,
|
|
668
|
+
);
|
|
462
669
|
if (!rect) continue;
|
|
463
670
|
entries.push({
|
|
464
671
|
...base,
|
|
@@ -472,6 +679,8 @@ function appendBlockSemanticEntries(input: {
|
|
|
472
679
|
},
|
|
473
680
|
status: "realized",
|
|
474
681
|
precision: "within-tolerance",
|
|
682
|
+
frameCompleteness,
|
|
683
|
+
...tableRowContinuationMetadata(block, cell.rowIndex),
|
|
475
684
|
...(tableIdentity
|
|
476
685
|
? {
|
|
477
686
|
sourceIdentity: tableCellSourceIdentity(
|
|
@@ -498,6 +707,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
498
707
|
},
|
|
499
708
|
status: "realized",
|
|
500
709
|
precision: "heuristic",
|
|
710
|
+
frameCompleteness,
|
|
501
711
|
});
|
|
502
712
|
recordPrecision(precision, "heuristic");
|
|
503
713
|
return;
|
|
@@ -511,6 +721,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
511
721
|
rect: toGeometryRect(block.frame),
|
|
512
722
|
status: "realized",
|
|
513
723
|
precision: "exact",
|
|
724
|
+
frameCompleteness,
|
|
514
725
|
});
|
|
515
726
|
recordPrecision(precision, "exact");
|
|
516
727
|
return;
|
|
@@ -524,18 +735,189 @@ function appendBlockSemanticEntries(input: {
|
|
|
524
735
|
rect: toGeometryRect(block.frame),
|
|
525
736
|
status: "realized",
|
|
526
737
|
precision: "exact",
|
|
738
|
+
frameCompleteness,
|
|
527
739
|
});
|
|
528
740
|
recordPrecision(precision, "exact");
|
|
529
741
|
}
|
|
530
742
|
}
|
|
531
743
|
|
|
744
|
+
function appendFragmentLayoutObjectSemanticEntries(input: {
|
|
745
|
+
base: {
|
|
746
|
+
pageId: string;
|
|
747
|
+
pageIndex: number;
|
|
748
|
+
regionId: string;
|
|
749
|
+
regionKind: RenderStoryRegion["region"]["kind"];
|
|
750
|
+
sliceId: string;
|
|
751
|
+
blockId: string;
|
|
752
|
+
fragmentId: string;
|
|
753
|
+
};
|
|
754
|
+
block: RenderBlock;
|
|
755
|
+
sourceIdentity: GeometrySourceIdentity | undefined;
|
|
756
|
+
entries: SemanticDisplayEntry[];
|
|
757
|
+
precision: GeometryPrecisionCounts;
|
|
758
|
+
frameCompleteness: GeometryPageFrameCompleteness;
|
|
759
|
+
layoutDivergenceIds: readonly string[];
|
|
760
|
+
layoutDivergenceObjectIds: readonly string[];
|
|
761
|
+
}): void {
|
|
762
|
+
const {
|
|
763
|
+
base,
|
|
764
|
+
block,
|
|
765
|
+
sourceIdentity,
|
|
766
|
+
entries,
|
|
767
|
+
precision,
|
|
768
|
+
frameCompleteness,
|
|
769
|
+
layoutDivergenceIds,
|
|
770
|
+
layoutDivergenceObjectIds,
|
|
771
|
+
} = input;
|
|
772
|
+
const layoutObject = block.fragment.layoutObject;
|
|
773
|
+
if (!layoutObject) return;
|
|
774
|
+
|
|
775
|
+
if (layoutObject.kind === "field-region") {
|
|
776
|
+
entries.push({
|
|
777
|
+
...base,
|
|
778
|
+
entryId: `semantic:field-region:${base.sliceId}`,
|
|
779
|
+
kind: "field-region",
|
|
780
|
+
layoutObjectId: layoutObject.objectId,
|
|
781
|
+
...(layoutObject.fieldFamilies !== undefined
|
|
782
|
+
? { fieldFamilies: [...layoutObject.fieldFamilies] }
|
|
783
|
+
: {}),
|
|
784
|
+
rect: {
|
|
785
|
+
...toGeometryRect(block.frame),
|
|
786
|
+
precision: "within-tolerance",
|
|
787
|
+
},
|
|
788
|
+
status: "realized",
|
|
789
|
+
precision: "within-tolerance",
|
|
790
|
+
frameCompleteness,
|
|
791
|
+
...(layoutDivergenceIds.length > 0 ? { layoutDivergenceIds } : {}),
|
|
792
|
+
...(layoutDivergenceObjectIds.length > 0
|
|
793
|
+
? { layoutDivergenceObjectIds }
|
|
794
|
+
: {}),
|
|
795
|
+
...(sourceIdentity ? { sourceIdentity } : {}),
|
|
796
|
+
});
|
|
797
|
+
recordPrecision(precision, "within-tolerance");
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (layoutObject.kind === "numbered-paragraph") {
|
|
802
|
+
const markerProjection = resolveNumberingMarkerProjection(block);
|
|
803
|
+
entries.push({
|
|
804
|
+
...base,
|
|
805
|
+
entryId: `semantic:numbering-marker:${base.sliceId}`,
|
|
806
|
+
kind: "numbering-marker",
|
|
807
|
+
layoutObjectId: layoutObject.objectId,
|
|
808
|
+
rect: markerProjection.rect,
|
|
809
|
+
status: markerProjection.status,
|
|
810
|
+
precision: markerProjection.precision,
|
|
811
|
+
frameCompleteness,
|
|
812
|
+
...(sourceIdentity ? { sourceIdentity } : {}),
|
|
813
|
+
});
|
|
814
|
+
recordPrecision(precision, markerProjection.precision);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function resolveNumberingMarkerProjection(block: RenderBlock): {
|
|
819
|
+
rect: GeometryRect;
|
|
820
|
+
precision: GeometryPrecision;
|
|
821
|
+
status: GeometryRehydrationStatus;
|
|
822
|
+
} {
|
|
823
|
+
const metadata = resolveNumberingMarkerProjectionMetadata(block);
|
|
824
|
+
const blockFrame = block.frame;
|
|
825
|
+
if (metadata.markerLane && metadata.measuredWidthTwips !== undefined) {
|
|
826
|
+
const markerLane = metadata.markerLane;
|
|
827
|
+
const pxPerTwip = blockFrame.widthPx / metadata.measuredWidthTwips;
|
|
828
|
+
const blockLeftPx = blockFrame.leftPx;
|
|
829
|
+
const blockRightPx = blockFrame.leftPx + Math.max(0, blockFrame.widthPx);
|
|
830
|
+
const rawLeftPx = blockFrame.leftPx + markerLane.startTwips * pxPerTwip;
|
|
831
|
+
const rawRightPx = rawLeftPx + markerLane.widthTwips * pxPerTwip;
|
|
832
|
+
const leftPx = clamp(rawLeftPx, blockLeftPx, blockRightPx);
|
|
833
|
+
const rightPx = clamp(rawRightPx, leftPx, blockRightPx);
|
|
834
|
+
return {
|
|
835
|
+
rect: {
|
|
836
|
+
leftPx,
|
|
837
|
+
topPx: blockFrame.topPx,
|
|
838
|
+
widthPx: rightPx - leftPx,
|
|
839
|
+
heightPx: blockFrame.heightPx,
|
|
840
|
+
space: "frame",
|
|
841
|
+
precision: metadata.precision,
|
|
842
|
+
},
|
|
843
|
+
precision: metadata.precision,
|
|
844
|
+
status: metadata.status,
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
const widthPx = Math.min(
|
|
849
|
+
Math.max(0, blockFrame.heightPx),
|
|
850
|
+
Math.max(0, blockFrame.widthPx),
|
|
851
|
+
);
|
|
852
|
+
return {
|
|
853
|
+
rect: {
|
|
854
|
+
leftPx: blockFrame.leftPx,
|
|
855
|
+
topPx: blockFrame.topPx,
|
|
856
|
+
widthPx,
|
|
857
|
+
heightPx: blockFrame.heightPx,
|
|
858
|
+
space: "frame",
|
|
859
|
+
precision: metadata.precision,
|
|
860
|
+
},
|
|
861
|
+
precision: metadata.precision,
|
|
862
|
+
status: metadata.status,
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
function resolveNumberingMarkerProjectionMetadata(block: RenderBlock): {
|
|
867
|
+
precision: GeometryPrecision;
|
|
868
|
+
status: GeometryRehydrationStatus;
|
|
869
|
+
markerLane?: {
|
|
870
|
+
readonly startTwips: number;
|
|
871
|
+
readonly widthTwips: number;
|
|
872
|
+
};
|
|
873
|
+
measuredWidthTwips?: number;
|
|
874
|
+
} {
|
|
875
|
+
const blockFrame = block.frame;
|
|
876
|
+
const layoutObject = block.fragment.layoutObject;
|
|
877
|
+
const markerLane =
|
|
878
|
+
layoutObject?.kind === "numbered-paragraph"
|
|
879
|
+
? layoutObject.numbering?.markerLane
|
|
880
|
+
: undefined;
|
|
881
|
+
const measuredWidthTwips = layoutObject?.measuredExtentTwips.widthTwips;
|
|
882
|
+
if (
|
|
883
|
+
markerLane &&
|
|
884
|
+
markerLane.widthTwips > 0 &&
|
|
885
|
+
measuredWidthTwips !== undefined &&
|
|
886
|
+
measuredWidthTwips > 0 &&
|
|
887
|
+
Number.isFinite(blockFrame.widthPx)
|
|
888
|
+
) {
|
|
889
|
+
return {
|
|
890
|
+
precision: "within-tolerance",
|
|
891
|
+
status: "realized",
|
|
892
|
+
markerLane,
|
|
893
|
+
measuredWidthTwips,
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
return {
|
|
897
|
+
precision: "heuristic",
|
|
898
|
+
status: "requires-rehydration",
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
|
|
532
902
|
function countBlockSemanticEntries(block: RenderBlock): GeometryPrecisionCounts {
|
|
533
903
|
const counts = createPrecisionCounts();
|
|
904
|
+
const layoutObject = block.fragment.layoutObject;
|
|
905
|
+
if (layoutObject?.kind === "field-region") {
|
|
906
|
+
counts["within-tolerance"] += 1;
|
|
907
|
+
} else if (layoutObject?.kind === "numbered-paragraph") {
|
|
908
|
+
counts[resolveNumberingMarkerProjectionMetadata(block).precision] += 1;
|
|
909
|
+
}
|
|
534
910
|
if (block.kind === "table") {
|
|
535
911
|
counts.exact += 1;
|
|
536
912
|
if (block.tablePlan) {
|
|
537
|
-
|
|
538
|
-
|
|
913
|
+
const visibleRows = resolveVisibleTableRows(block);
|
|
914
|
+
const visibleRowIndexes = new Set(
|
|
915
|
+
visibleRows.map((row) => row.rowIndex),
|
|
916
|
+
);
|
|
917
|
+
counts["within-tolerance"] += visibleRows.length;
|
|
918
|
+
counts["within-tolerance"] += block.tablePlan.bandClasses.cells.filter(
|
|
919
|
+
(cell) => visibleRowIndexes.has(cell.rowIndex),
|
|
920
|
+
).length;
|
|
539
921
|
}
|
|
540
922
|
} else if (block.kind === "image-float") {
|
|
541
923
|
counts.heuristic += 1;
|
|
@@ -558,13 +940,134 @@ function resolveTableRowCount(block: RenderBlock): number {
|
|
|
558
940
|
);
|
|
559
941
|
}
|
|
560
942
|
|
|
943
|
+
interface VisibleTableRow {
|
|
944
|
+
rowIndex: number;
|
|
945
|
+
visualIndex: number;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function tableContinuationMetadata(
|
|
949
|
+
block: RenderBlock,
|
|
950
|
+
): GeometryTableContinuation | null {
|
|
951
|
+
const continuation =
|
|
952
|
+
block.fragment.continuation?.kind === "table"
|
|
953
|
+
? block.fragment.continuation
|
|
954
|
+
: null;
|
|
955
|
+
const rowRange = block.fragment.tableRowRange ?? continuation?.rowRange;
|
|
956
|
+
if (!continuation && !rowRange) return null;
|
|
957
|
+
|
|
958
|
+
return {
|
|
959
|
+
...(continuation
|
|
960
|
+
? {
|
|
961
|
+
sequenceIndex: continuation.sequenceIndex,
|
|
962
|
+
sliceCount: continuation.sliceCount,
|
|
963
|
+
continuesFromPreviousPage: continuation.continuesFromPreviousPage,
|
|
964
|
+
continuesToNextPage: continuation.continuesToNextPage,
|
|
965
|
+
}
|
|
966
|
+
: {}),
|
|
967
|
+
...(rowRange ? { rowRange: { ...rowRange } } : {}),
|
|
968
|
+
...(continuation?.repeatedHeaderRowIndexes.length
|
|
969
|
+
? {
|
|
970
|
+
repeatedHeaderRowIndexes: [
|
|
971
|
+
...continuation.repeatedHeaderRowIndexes,
|
|
972
|
+
],
|
|
973
|
+
}
|
|
974
|
+
: {}),
|
|
975
|
+
...(continuation?.splitRowCarry?.length
|
|
976
|
+
? {
|
|
977
|
+
splitRowCarry: continuation.splitRowCarry.map((carry) => ({
|
|
978
|
+
...carry,
|
|
979
|
+
})),
|
|
980
|
+
}
|
|
981
|
+
: {}),
|
|
982
|
+
...(continuation?.verticalMergeCarry.length
|
|
983
|
+
? {
|
|
984
|
+
verticalMergeCarry: continuation.verticalMergeCarry.map((carry) => ({
|
|
985
|
+
...carry,
|
|
986
|
+
})),
|
|
987
|
+
}
|
|
988
|
+
: {}),
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function tableRowContinuationMetadata(
|
|
993
|
+
block: RenderBlock,
|
|
994
|
+
rowIndex: number,
|
|
995
|
+
): Pick<SemanticDisplayEntry, "tableContinuation"> {
|
|
996
|
+
const tableContinuation = tableContinuationMetadata(block);
|
|
997
|
+
if (!tableContinuation) return {};
|
|
998
|
+
const repeatedHeaderRowIndexes =
|
|
999
|
+
tableContinuation.repeatedHeaderRowIndexes?.includes(rowIndex) === true
|
|
1000
|
+
? [rowIndex]
|
|
1001
|
+
: undefined;
|
|
1002
|
+
const splitRowCarry = tableContinuation.splitRowCarry?.filter(
|
|
1003
|
+
(carry) => carry.rowIndex === rowIndex,
|
|
1004
|
+
);
|
|
1005
|
+
|
|
1006
|
+
if (
|
|
1007
|
+
repeatedHeaderRowIndexes === undefined &&
|
|
1008
|
+
(!splitRowCarry || splitRowCarry.length === 0)
|
|
1009
|
+
) {
|
|
1010
|
+
return {};
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
return {
|
|
1014
|
+
tableContinuation: {
|
|
1015
|
+
...(repeatedHeaderRowIndexes ? { repeatedHeaderRowIndexes } : {}),
|
|
1016
|
+
...(splitRowCarry && splitRowCarry.length > 0
|
|
1017
|
+
? { splitRowCarry: splitRowCarry.map((carry) => ({ ...carry })) }
|
|
1018
|
+
: {}),
|
|
1019
|
+
},
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
function resolveVisibleTableRows(block: RenderBlock): readonly VisibleTableRow[] {
|
|
1024
|
+
const rowCount = resolveTableRowCount(block);
|
|
1025
|
+
if (rowCount <= 0) return [];
|
|
1026
|
+
const continuation =
|
|
1027
|
+
block.fragment.continuation?.kind === "table"
|
|
1028
|
+
? block.fragment.continuation
|
|
1029
|
+
: null;
|
|
1030
|
+
const rowRange = block.fragment.tableRowRange ?? continuation?.rowRange;
|
|
1031
|
+
if (!rowRange) {
|
|
1032
|
+
return Array.from({ length: rowCount }, (_, rowIndex) => ({
|
|
1033
|
+
rowIndex,
|
|
1034
|
+
visualIndex: rowIndex,
|
|
1035
|
+
}));
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
const start = Math.max(0, Math.min(rowCount, rowRange.from));
|
|
1039
|
+
const end = Math.max(start, Math.min(rowCount, rowRange.to));
|
|
1040
|
+
const rowIndexes: number[] = [];
|
|
1041
|
+
const seenRowIndexes = new Set<number>();
|
|
1042
|
+
const addRow = (rowIndex: number): void => {
|
|
1043
|
+
if (rowIndex < 0 || rowIndex >= rowCount) return;
|
|
1044
|
+
if (seenRowIndexes.has(rowIndex)) return;
|
|
1045
|
+
seenRowIndexes.add(rowIndex);
|
|
1046
|
+
rowIndexes.push(rowIndex);
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
for (const rowIndex of continuation?.repeatedHeaderRowIndexes ?? []) {
|
|
1050
|
+
addRow(rowIndex);
|
|
1051
|
+
}
|
|
1052
|
+
for (let rowIndex = start; rowIndex < end; rowIndex += 1) {
|
|
1053
|
+
addRow(rowIndex);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
return rowIndexes.map((rowIndex, visualIndex) => ({ rowIndex, visualIndex }));
|
|
1057
|
+
}
|
|
1058
|
+
|
|
561
1059
|
function pageFrameCellRect(
|
|
562
1060
|
block: RenderBlock,
|
|
563
1061
|
rowIndex: number,
|
|
564
1062
|
columnIndex: number,
|
|
1063
|
+
visibleRows: readonly VisibleTableRow[] = resolveVisibleTableRows(block),
|
|
565
1064
|
): RenderFrameRect | null {
|
|
566
1065
|
const plan = block.tablePlan;
|
|
567
1066
|
if (!plan || plan.columnsTwips.length === 0) return null;
|
|
1067
|
+
const visualRowIndex = visibleRows.findIndex(
|
|
1068
|
+
(row) => row.rowIndex === rowIndex,
|
|
1069
|
+
);
|
|
1070
|
+
if (visualRowIndex < 0) return null;
|
|
568
1071
|
const columnCount = plan.columnsTwips.length;
|
|
569
1072
|
const totalWidthTwips = plan.columnsTwips.reduce(
|
|
570
1073
|
(sum, value) => sum + Math.max(0, value),
|
|
@@ -591,12 +1094,12 @@ function pageFrameCellRect(
|
|
|
591
1094
|
for (let i = columnIndex; i < columnIndex + columnSpan; i += 1) {
|
|
592
1095
|
widthPx += (plan.columnsTwips[i] ?? 0) * pxPerTwip;
|
|
593
1096
|
}
|
|
594
|
-
const rowCount =
|
|
1097
|
+
const rowCount = visibleRows.length;
|
|
595
1098
|
const rowHeightPx =
|
|
596
1099
|
rowCount > 0 ? block.frame.heightPx / rowCount : block.frame.heightPx;
|
|
597
1100
|
return {
|
|
598
1101
|
leftPx,
|
|
599
|
-
topPx: block.frame.topPx +
|
|
1102
|
+
topPx: block.frame.topPx + visualRowIndex * rowHeightPx,
|
|
600
1103
|
widthPx,
|
|
601
1104
|
heightPx: rowHeightPx,
|
|
602
1105
|
};
|
|
@@ -711,6 +1214,7 @@ interface MutableObjectHandleEntry {
|
|
|
711
1214
|
rects: GeometryRect[];
|
|
712
1215
|
status: GeometryRehydrationStatus;
|
|
713
1216
|
precision: GeometryPrecision;
|
|
1217
|
+
layoutDivergenceIds?: string[];
|
|
714
1218
|
sourceIdentity?: GeometrySourceIdentity;
|
|
715
1219
|
}
|
|
716
1220
|
|
|
@@ -744,6 +1248,11 @@ function appendCanonicalObjectHandleEntries(input: {
|
|
|
744
1248
|
if (existing) {
|
|
745
1249
|
appendUnique(existing.pageIds, page.page.pageId);
|
|
746
1250
|
existing.rects.push(...handleRects);
|
|
1251
|
+
appendDivergenceIdsForObject(
|
|
1252
|
+
existing,
|
|
1253
|
+
input.page,
|
|
1254
|
+
anchor.objectKey,
|
|
1255
|
+
);
|
|
747
1256
|
if (existing.precision !== "heuristic" && entryPrecision === "heuristic") {
|
|
748
1257
|
existing.precision = "heuristic";
|
|
749
1258
|
existing.status = "requires-rehydration";
|
|
@@ -758,6 +1267,7 @@ function appendCanonicalObjectHandleEntries(input: {
|
|
|
758
1267
|
rects: [...handleRects],
|
|
759
1268
|
status,
|
|
760
1269
|
precision: entryPrecision,
|
|
1270
|
+
...layoutDivergenceIdsForObject(input.page, anchor.objectKey),
|
|
761
1271
|
sourceIdentity: anchorSourceIdentity(
|
|
762
1272
|
anchor,
|
|
763
1273
|
exactObjectRect ? "direct" : "block-scoped",
|
|
@@ -771,9 +1281,14 @@ function appendPageLocalObjectHandleEntries(input: {
|
|
|
771
1281
|
page: RenderPage;
|
|
772
1282
|
entries: Map<string, MutableObjectHandleEntry>;
|
|
773
1283
|
precision: GeometryPrecisionCounts;
|
|
1284
|
+
divergenceIdsByObjectId: ReadonlyMap<string, readonly string[]>;
|
|
774
1285
|
}): void {
|
|
775
|
-
const { page, entries, precision } = input;
|
|
1286
|
+
const { page, entries, precision, divergenceIdsByObjectId } = input;
|
|
776
1287
|
const stories = page.page.frame?.pageLocalStories ?? [];
|
|
1288
|
+
const pxPerTwip =
|
|
1289
|
+
page.page.layout.pageWidth > 0
|
|
1290
|
+
? page.frame.widthPx / page.page.layout.pageWidth
|
|
1291
|
+
: 1;
|
|
777
1292
|
for (const story of stories) {
|
|
778
1293
|
const regionFrame =
|
|
779
1294
|
story.kind === "header" ? page.regions.header?.frame : page.regions.footer?.frame;
|
|
@@ -782,9 +1297,7 @@ function appendPageLocalObjectHandleEntries(input: {
|
|
|
782
1297
|
const objectFrame = pageLocalObjectFrame(
|
|
783
1298
|
regionFrame,
|
|
784
1299
|
object.extentTwips,
|
|
785
|
-
|
|
786
|
-
? page.frame.widthPx / page.page.layout.pageWidth
|
|
787
|
-
: 1,
|
|
1300
|
+
pxPerTwip,
|
|
788
1301
|
);
|
|
789
1302
|
const handleRects = buildObjectHandleRectsFromRect(objectFrame, "heuristic");
|
|
790
1303
|
const sourceIdentity: GeometrySourceIdentity = {
|
|
@@ -798,6 +1311,7 @@ function appendPageLocalObjectHandleEntries(input: {
|
|
|
798
1311
|
if (existing) {
|
|
799
1312
|
appendUnique(existing.pageIds, page.page.pageId);
|
|
800
1313
|
existing.rects.push(...handleRects);
|
|
1314
|
+
appendDivergenceIds(existing, divergenceIdsByObjectId.get(object.objectId));
|
|
801
1315
|
if (existing.precision !== "heuristic") {
|
|
802
1316
|
existing.precision = "heuristic";
|
|
803
1317
|
existing.status = "requires-rehydration";
|
|
@@ -811,6 +1325,7 @@ function appendPageLocalObjectHandleEntries(input: {
|
|
|
811
1325
|
rects: [...handleRects],
|
|
812
1326
|
status: "requires-rehydration",
|
|
813
1327
|
precision: "heuristic",
|
|
1328
|
+
...mutableLayoutDivergenceIds(divergenceIdsByObjectId.get(object.objectId)),
|
|
814
1329
|
sourceIdentity,
|
|
815
1330
|
});
|
|
816
1331
|
recordPrecision(precision, "heuristic");
|
|
@@ -845,6 +1360,9 @@ function finalizeObjectHandleEntries(
|
|
|
845
1360
|
rects: entry.rects,
|
|
846
1361
|
status: entry.status,
|
|
847
1362
|
precision: entry.precision,
|
|
1363
|
+
...(entry.layoutDivergenceIds && entry.layoutDivergenceIds.length > 0
|
|
1364
|
+
? { layoutDivergenceIds: [...entry.layoutDivergenceIds] }
|
|
1365
|
+
: {}),
|
|
848
1366
|
...(entry.sourceIdentity ? { sourceIdentity: entry.sourceIdentity } : {}),
|
|
849
1367
|
}));
|
|
850
1368
|
}
|
|
@@ -900,6 +1418,7 @@ function recordTableCellScopeBlocks(input: {
|
|
|
900
1418
|
storyKey: string;
|
|
901
1419
|
identities: GeometryIdentityLookup | null;
|
|
902
1420
|
projectedBlocksByStory: Map<string, ProjectedScopeBlock[]>;
|
|
1421
|
+
visibleRows: readonly VisibleTableRow[];
|
|
903
1422
|
}): void {
|
|
904
1423
|
const {
|
|
905
1424
|
table,
|
|
@@ -908,12 +1427,18 @@ function recordTableCellScopeBlocks(input: {
|
|
|
908
1427
|
storyKey,
|
|
909
1428
|
identities,
|
|
910
1429
|
projectedBlocksByStory,
|
|
1430
|
+
visibleRows,
|
|
911
1431
|
} = input;
|
|
912
1432
|
if (!identities) return;
|
|
913
1433
|
|
|
914
1434
|
for (const row of table.rows) {
|
|
915
1435
|
for (const cell of row.cells) {
|
|
916
|
-
const rect = pageFrameCellRect(
|
|
1436
|
+
const rect = pageFrameCellRect(
|
|
1437
|
+
block,
|
|
1438
|
+
row.rowIndex,
|
|
1439
|
+
cell.gridColumnStart,
|
|
1440
|
+
visibleRows,
|
|
1441
|
+
);
|
|
917
1442
|
if (!rect) continue;
|
|
918
1443
|
for (let blockIndex = 0; blockIndex < cell.blockCount; blockIndex += 1) {
|
|
919
1444
|
const blockPath =
|
|
@@ -1302,6 +1827,10 @@ function toGeometryRect(rect: RenderFrameRect): GeometryRect {
|
|
|
1302
1827
|
};
|
|
1303
1828
|
}
|
|
1304
1829
|
|
|
1830
|
+
function clamp(value: number, min: number, max: number): number {
|
|
1831
|
+
return Math.min(Math.max(value, min), max);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1305
1834
|
function makeRegionId(
|
|
1306
1835
|
page: RenderPage,
|
|
1307
1836
|
region: RenderStoryRegion,
|
|
@@ -1334,6 +1863,48 @@ function createPrecisionCounts(): GeometryPrecisionCounts {
|
|
|
1334
1863
|
};
|
|
1335
1864
|
}
|
|
1336
1865
|
|
|
1866
|
+
function createPageFrameCompletenessCounts(): GeometryPageFrameCompletenessCounts {
|
|
1867
|
+
return {
|
|
1868
|
+
complete: 0,
|
|
1869
|
+
partial: 0,
|
|
1870
|
+
absent: 0,
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
function layoutDivergenceIdsForObject(
|
|
1875
|
+
page: RenderPage,
|
|
1876
|
+
objectId: string,
|
|
1877
|
+
): { readonly layoutDivergenceIds?: string[] } {
|
|
1878
|
+
const ids = page.page.divergences
|
|
1879
|
+
?.filter((divergence) => divergence.objectIds?.includes(objectId) === true)
|
|
1880
|
+
.map((divergence) => divergence.divergenceId);
|
|
1881
|
+
return ids && ids.length > 0 ? { layoutDivergenceIds: ids } : {};
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
function mutableLayoutDivergenceIds(
|
|
1885
|
+
ids: readonly string[] | undefined,
|
|
1886
|
+
): { readonly layoutDivergenceIds?: string[] } {
|
|
1887
|
+
return ids && ids.length > 0 ? { layoutDivergenceIds: [...ids] } : {};
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
function appendDivergenceIdsForObject(
|
|
1891
|
+
entry: MutableObjectHandleEntry,
|
|
1892
|
+
page: RenderPage,
|
|
1893
|
+
objectId: string,
|
|
1894
|
+
): void {
|
|
1895
|
+
const ids = layoutDivergenceIdsForObject(page, objectId).layoutDivergenceIds;
|
|
1896
|
+
appendDivergenceIds(entry, ids);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
function appendDivergenceIds(
|
|
1900
|
+
entry: MutableObjectHandleEntry,
|
|
1901
|
+
ids: readonly string[] | undefined,
|
|
1902
|
+
): void {
|
|
1903
|
+
if (!ids || ids.length === 0) return;
|
|
1904
|
+
if (!entry.layoutDivergenceIds) entry.layoutDivergenceIds = [];
|
|
1905
|
+
for (const id of ids) appendUnique(entry.layoutDivergenceIds, id);
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1337
1908
|
function recordPrecision(
|
|
1338
1909
|
counts: GeometryPrecisionCounts,
|
|
1339
1910
|
precision: keyof GeometryPrecisionCounts,
|