@beyondwork/docx-react-component 1.0.105 → 1.0.108
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 +10 -2
- 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-reference.ts +28 -0
- package/src/api/v3/ai/_audit-time.ts +5 -0
- package/src/api/v3/ai/_pe2-evidence.ts +310 -6
- package/src/api/v3/ai/attach.ts +29 -4
- package/src/api/v3/ai/bundle.ts +6 -2
- package/src/api/v3/ai/inspect.ts +6 -2
- package/src/api/v3/ai/replacement.ts +112 -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 +8 -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 +202 -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 +17 -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 +119 -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 +147 -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 +279 -115
- 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 +661 -16
- 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 +188 -16
- package/src/runtime/layout/layout-facet-types.ts +6 -0
- package/src/runtime/layout/page-graph.ts +23 -4
- package/src/runtime/layout/paginated-layout-engine.ts +149 -15
- package/src/runtime/layout/project-block-fragments.ts +351 -14
- package/src/runtime/layout/public-facet.ts +162 -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 +4 -0
- package/src/runtime/workflow/overlay-lane-types.ts +58 -0
- package/src/runtime/workflow/overlay-lanes.ts +386 -0
- 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 +130 -0
- package/src/ui/ui-controller-factory.ts +17 -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,8 +276,32 @@ 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
|
+
});
|
|
299
|
+
appendPageLocalObjectHandleEntries({
|
|
300
|
+
page,
|
|
301
|
+
entries: objectHandleEntries,
|
|
302
|
+
precision,
|
|
303
|
+
divergenceIdsByObjectId: pageMetadata.divergenceIdsByObjectId,
|
|
304
|
+
});
|
|
262
305
|
}
|
|
263
306
|
|
|
264
307
|
appendScopeReplacementEnvelopeEntries({
|
|
@@ -272,14 +315,18 @@ export function projectGeometryIndexFromFrame(
|
|
|
272
315
|
const coverage: GeometryIndexCoverage = {
|
|
273
316
|
status: "realized",
|
|
274
317
|
pageCount: pages.length,
|
|
318
|
+
pageFrameCompleteness,
|
|
275
319
|
regionCount: regions.length,
|
|
276
320
|
sliceCount: slices.length,
|
|
277
321
|
lineCount: lines.length,
|
|
278
322
|
anchorCount: anchors.length,
|
|
279
323
|
hitTargetCount: hitTargets.length,
|
|
280
324
|
semanticEntryCount: semanticEntries.length,
|
|
325
|
+
pageLocalFieldLedgerCount,
|
|
281
326
|
replacementEnvelopeCount: replacementEnvelopes.length,
|
|
282
327
|
objectHandleCount: objectHandles.length,
|
|
328
|
+
layoutDivergenceObjectCount,
|
|
329
|
+
splitRowCarryCount,
|
|
283
330
|
precision,
|
|
284
331
|
};
|
|
285
332
|
|
|
@@ -307,6 +354,7 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
307
354
|
if (!frame) return createUnavailableGeometryCoverage();
|
|
308
355
|
|
|
309
356
|
const precision = createPrecisionCounts();
|
|
357
|
+
const pageFrameCompleteness = createPageFrameCompletenessCounts();
|
|
310
358
|
let pageCount = 0;
|
|
311
359
|
let regionCount = 0;
|
|
312
360
|
let sliceCount = 0;
|
|
@@ -314,14 +362,25 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
314
362
|
let anchorCount = 0;
|
|
315
363
|
let hitTargetCount = 0;
|
|
316
364
|
let semanticEntryCount = 0;
|
|
365
|
+
let pageLocalFieldLedgerCount = 0;
|
|
366
|
+
let layoutDivergenceObjectCount = 0;
|
|
367
|
+
let splitRowCarryCount = 0;
|
|
317
368
|
|
|
318
369
|
for (const page of frame.pages) {
|
|
370
|
+
const pageMetadata = pageFrameMetadata(page);
|
|
319
371
|
pageCount += 1;
|
|
372
|
+
pageFrameCompleteness[pageMetadata.frameCompleteness] += 1;
|
|
373
|
+
layoutDivergenceObjectCount += pageMetadata.layoutDivergenceObjectIds.length;
|
|
320
374
|
recordPrecision(precision, "exact");
|
|
375
|
+
const pageLocalFieldCount = countPageLocalFieldLedgers(page);
|
|
376
|
+
pageLocalFieldLedgerCount += pageLocalFieldCount;
|
|
377
|
+
semanticEntryCount += pageLocalFieldCount;
|
|
378
|
+
precision["within-tolerance"] += pageLocalFieldCount;
|
|
321
379
|
for (const [region] of collectRegionEntries(page)) {
|
|
322
380
|
regionCount += 1;
|
|
323
381
|
recordPrecision(precision, "exact");
|
|
324
382
|
for (const block of region.blocks) {
|
|
383
|
+
splitRowCarryCount += countSplitRowCarry(block);
|
|
325
384
|
sliceCount += 1;
|
|
326
385
|
recordPrecision(precision, "exact");
|
|
327
386
|
for (const line of block.lines) {
|
|
@@ -350,18 +409,127 @@ export function summarizeGeometryCoverageFromFrame(
|
|
|
350
409
|
return {
|
|
351
410
|
status: "realized",
|
|
352
411
|
pageCount,
|
|
412
|
+
pageFrameCompleteness,
|
|
353
413
|
regionCount,
|
|
354
414
|
sliceCount,
|
|
355
415
|
lineCount,
|
|
356
416
|
anchorCount,
|
|
357
417
|
hitTargetCount,
|
|
358
418
|
semanticEntryCount,
|
|
419
|
+
pageLocalFieldLedgerCount,
|
|
359
420
|
replacementEnvelopeCount: 0,
|
|
360
421
|
objectHandleCount: 0,
|
|
422
|
+
layoutDivergenceObjectCount,
|
|
423
|
+
splitRowCarryCount,
|
|
361
424
|
precision,
|
|
362
425
|
};
|
|
363
426
|
}
|
|
364
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
|
+
|
|
365
533
|
function appendBlockSemanticEntries(input: {
|
|
366
534
|
page: RenderPage;
|
|
367
535
|
region: RenderStoryRegion;
|
|
@@ -373,6 +541,9 @@ function appendBlockSemanticEntries(input: {
|
|
|
373
541
|
entries: SemanticDisplayEntry[];
|
|
374
542
|
projectedBlocksByStory: Map<string, ProjectedScopeBlock[]>;
|
|
375
543
|
precision: GeometryPrecisionCounts;
|
|
544
|
+
frameCompleteness: GeometryPageFrameCompleteness;
|
|
545
|
+
layoutDivergenceIds: readonly string[];
|
|
546
|
+
layoutDivergenceObjectIds: readonly string[];
|
|
376
547
|
}): void {
|
|
377
548
|
const {
|
|
378
549
|
page,
|
|
@@ -385,11 +556,18 @@ function appendBlockSemanticEntries(input: {
|
|
|
385
556
|
entries,
|
|
386
557
|
projectedBlocksByStory,
|
|
387
558
|
precision,
|
|
559
|
+
frameCompleteness,
|
|
560
|
+
layoutDivergenceIds,
|
|
561
|
+
layoutDivergenceObjectIds,
|
|
388
562
|
} = input;
|
|
389
563
|
const tableIdentity = identities?.tableIdentity(
|
|
390
564
|
storyKey,
|
|
391
565
|
block.fragment.blockId,
|
|
392
566
|
);
|
|
567
|
+
const sliceIdentity = identities?.sliceIdentity(
|
|
568
|
+
storyKey,
|
|
569
|
+
block.fragment.blockId,
|
|
570
|
+
);
|
|
393
571
|
const base = {
|
|
394
572
|
pageId: page.page.pageId,
|
|
395
573
|
pageIndex: page.page.pageIndex,
|
|
@@ -400,7 +578,19 @@ function appendBlockSemanticEntries(input: {
|
|
|
400
578
|
fragmentId: block.fragment.fragmentId,
|
|
401
579
|
} as const;
|
|
402
580
|
|
|
581
|
+
appendFragmentLayoutObjectSemanticEntries({
|
|
582
|
+
base,
|
|
583
|
+
block,
|
|
584
|
+
sourceIdentity: sliceIdentity,
|
|
585
|
+
entries,
|
|
586
|
+
precision,
|
|
587
|
+
frameCompleteness,
|
|
588
|
+
layoutDivergenceIds,
|
|
589
|
+
layoutDivergenceObjectIds,
|
|
590
|
+
});
|
|
591
|
+
|
|
403
592
|
if (block.kind === "table") {
|
|
593
|
+
const tableContinuation = tableContinuationMetadata(block);
|
|
404
594
|
entries.push({
|
|
405
595
|
...base,
|
|
406
596
|
entryId: `semantic:table-frame:${sliceId}`,
|
|
@@ -408,6 +598,12 @@ function appendBlockSemanticEntries(input: {
|
|
|
408
598
|
rect: toGeometryRect(block.frame),
|
|
409
599
|
status: "realized",
|
|
410
600
|
precision: "exact",
|
|
601
|
+
frameCompleteness,
|
|
602
|
+
...(layoutDivergenceIds.length > 0 ? { layoutDivergenceIds } : {}),
|
|
603
|
+
...(layoutDivergenceObjectIds.length > 0
|
|
604
|
+
? { layoutDivergenceObjectIds }
|
|
605
|
+
: {}),
|
|
606
|
+
...(tableContinuation ? { tableContinuation } : {}),
|
|
411
607
|
...(tableIdentity
|
|
412
608
|
? { sourceIdentity: tableSourceIdentity(tableIdentity) }
|
|
413
609
|
: {}),
|
|
@@ -416,6 +612,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
416
612
|
|
|
417
613
|
const plan = block.tablePlan;
|
|
418
614
|
if (!plan) return;
|
|
615
|
+
const visibleRows = resolveVisibleTableRows(block);
|
|
419
616
|
if (tableIdentity) {
|
|
420
617
|
recordTableCellScopeBlocks({
|
|
421
618
|
table: tableIdentity,
|
|
@@ -424,20 +621,23 @@ function appendBlockSemanticEntries(input: {
|
|
|
424
621
|
storyKey,
|
|
425
622
|
identities,
|
|
426
623
|
projectedBlocksByStory,
|
|
624
|
+
visibleRows,
|
|
427
625
|
});
|
|
428
626
|
}
|
|
429
|
-
const
|
|
627
|
+
const visibleRowCount = visibleRows.length;
|
|
430
628
|
const rowHeightPx =
|
|
431
|
-
|
|
432
|
-
|
|
629
|
+
visibleRowCount > 0
|
|
630
|
+
? block.frame.heightPx / visibleRowCount
|
|
631
|
+
: block.frame.heightPx;
|
|
632
|
+
for (const row of visibleRows) {
|
|
433
633
|
entries.push({
|
|
434
634
|
...base,
|
|
435
|
-
entryId: `semantic:table-row:${sliceId}:${rowIndex}`,
|
|
635
|
+
entryId: `semantic:table-row:${sliceId}:${row.rowIndex}`,
|
|
436
636
|
kind: "table-row",
|
|
437
|
-
rowIndex,
|
|
637
|
+
rowIndex: row.rowIndex,
|
|
438
638
|
rect: {
|
|
439
639
|
leftPx: block.frame.leftPx,
|
|
440
|
-
topPx: block.frame.topPx +
|
|
640
|
+
topPx: block.frame.topPx + row.visualIndex * rowHeightPx,
|
|
441
641
|
widthPx: block.frame.widthPx,
|
|
442
642
|
heightPx: rowHeightPx,
|
|
443
643
|
space: "frame",
|
|
@@ -445,15 +645,27 @@ function appendBlockSemanticEntries(input: {
|
|
|
445
645
|
},
|
|
446
646
|
status: "realized",
|
|
447
647
|
precision: "within-tolerance",
|
|
648
|
+
frameCompleteness,
|
|
649
|
+
...tableRowContinuationMetadata(block, row.rowIndex),
|
|
448
650
|
...(tableIdentity
|
|
449
|
-
? {
|
|
651
|
+
? {
|
|
652
|
+
sourceIdentity: tableRowSourceIdentity(
|
|
653
|
+
tableIdentity,
|
|
654
|
+
row.rowIndex,
|
|
655
|
+
),
|
|
656
|
+
}
|
|
450
657
|
: {}),
|
|
451
658
|
});
|
|
452
659
|
recordPrecision(precision, "within-tolerance");
|
|
453
660
|
}
|
|
454
661
|
|
|
455
662
|
for (const cell of plan.bandClasses.cells) {
|
|
456
|
-
const rect = pageFrameCellRect(
|
|
663
|
+
const rect = pageFrameCellRect(
|
|
664
|
+
block,
|
|
665
|
+
cell.rowIndex,
|
|
666
|
+
cell.columnIndex,
|
|
667
|
+
visibleRows,
|
|
668
|
+
);
|
|
457
669
|
if (!rect) continue;
|
|
458
670
|
entries.push({
|
|
459
671
|
...base,
|
|
@@ -467,6 +679,8 @@ function appendBlockSemanticEntries(input: {
|
|
|
467
679
|
},
|
|
468
680
|
status: "realized",
|
|
469
681
|
precision: "within-tolerance",
|
|
682
|
+
frameCompleteness,
|
|
683
|
+
...tableRowContinuationMetadata(block, cell.rowIndex),
|
|
470
684
|
...(tableIdentity
|
|
471
685
|
? {
|
|
472
686
|
sourceIdentity: tableCellSourceIdentity(
|
|
@@ -493,6 +707,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
493
707
|
},
|
|
494
708
|
status: "realized",
|
|
495
709
|
precision: "heuristic",
|
|
710
|
+
frameCompleteness,
|
|
496
711
|
});
|
|
497
712
|
recordPrecision(precision, "heuristic");
|
|
498
713
|
return;
|
|
@@ -506,6 +721,7 @@ function appendBlockSemanticEntries(input: {
|
|
|
506
721
|
rect: toGeometryRect(block.frame),
|
|
507
722
|
status: "realized",
|
|
508
723
|
precision: "exact",
|
|
724
|
+
frameCompleteness,
|
|
509
725
|
});
|
|
510
726
|
recordPrecision(precision, "exact");
|
|
511
727
|
return;
|
|
@@ -519,18 +735,189 @@ function appendBlockSemanticEntries(input: {
|
|
|
519
735
|
rect: toGeometryRect(block.frame),
|
|
520
736
|
status: "realized",
|
|
521
737
|
precision: "exact",
|
|
738
|
+
frameCompleteness,
|
|
522
739
|
});
|
|
523
740
|
recordPrecision(precision, "exact");
|
|
524
741
|
}
|
|
525
742
|
}
|
|
526
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
|
+
|
|
527
902
|
function countBlockSemanticEntries(block: RenderBlock): GeometryPrecisionCounts {
|
|
528
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
|
+
}
|
|
529
910
|
if (block.kind === "table") {
|
|
530
911
|
counts.exact += 1;
|
|
531
912
|
if (block.tablePlan) {
|
|
532
|
-
|
|
533
|
-
|
|
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;
|
|
534
921
|
}
|
|
535
922
|
} else if (block.kind === "image-float") {
|
|
536
923
|
counts.heuristic += 1;
|
|
@@ -553,13 +940,134 @@ function resolveTableRowCount(block: RenderBlock): number {
|
|
|
553
940
|
);
|
|
554
941
|
}
|
|
555
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
|
+
|
|
556
1059
|
function pageFrameCellRect(
|
|
557
1060
|
block: RenderBlock,
|
|
558
1061
|
rowIndex: number,
|
|
559
1062
|
columnIndex: number,
|
|
1063
|
+
visibleRows: readonly VisibleTableRow[] = resolveVisibleTableRows(block),
|
|
560
1064
|
): RenderFrameRect | null {
|
|
561
1065
|
const plan = block.tablePlan;
|
|
562
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;
|
|
563
1071
|
const columnCount = plan.columnsTwips.length;
|
|
564
1072
|
const totalWidthTwips = plan.columnsTwips.reduce(
|
|
565
1073
|
(sum, value) => sum + Math.max(0, value),
|
|
@@ -586,12 +1094,12 @@ function pageFrameCellRect(
|
|
|
586
1094
|
for (let i = columnIndex; i < columnIndex + columnSpan; i += 1) {
|
|
587
1095
|
widthPx += (plan.columnsTwips[i] ?? 0) * pxPerTwip;
|
|
588
1096
|
}
|
|
589
|
-
const rowCount =
|
|
1097
|
+
const rowCount = visibleRows.length;
|
|
590
1098
|
const rowHeightPx =
|
|
591
1099
|
rowCount > 0 ? block.frame.heightPx / rowCount : block.frame.heightPx;
|
|
592
1100
|
return {
|
|
593
1101
|
leftPx,
|
|
594
|
-
topPx: block.frame.topPx +
|
|
1102
|
+
topPx: block.frame.topPx + visualRowIndex * rowHeightPx,
|
|
595
1103
|
widthPx,
|
|
596
1104
|
heightPx: rowHeightPx,
|
|
597
1105
|
};
|
|
@@ -706,6 +1214,7 @@ interface MutableObjectHandleEntry {
|
|
|
706
1214
|
rects: GeometryRect[];
|
|
707
1215
|
status: GeometryRehydrationStatus;
|
|
708
1216
|
precision: GeometryPrecision;
|
|
1217
|
+
layoutDivergenceIds?: string[];
|
|
709
1218
|
sourceIdentity?: GeometrySourceIdentity;
|
|
710
1219
|
}
|
|
711
1220
|
|
|
@@ -739,6 +1248,11 @@ function appendCanonicalObjectHandleEntries(input: {
|
|
|
739
1248
|
if (existing) {
|
|
740
1249
|
appendUnique(existing.pageIds, page.page.pageId);
|
|
741
1250
|
existing.rects.push(...handleRects);
|
|
1251
|
+
appendDivergenceIdsForObject(
|
|
1252
|
+
existing,
|
|
1253
|
+
input.page,
|
|
1254
|
+
anchor.objectKey,
|
|
1255
|
+
);
|
|
742
1256
|
if (existing.precision !== "heuristic" && entryPrecision === "heuristic") {
|
|
743
1257
|
existing.precision = "heuristic";
|
|
744
1258
|
existing.status = "requires-rehydration";
|
|
@@ -753,6 +1267,7 @@ function appendCanonicalObjectHandleEntries(input: {
|
|
|
753
1267
|
rects: [...handleRects],
|
|
754
1268
|
status,
|
|
755
1269
|
precision: entryPrecision,
|
|
1270
|
+
...layoutDivergenceIdsForObject(input.page, anchor.objectKey),
|
|
756
1271
|
sourceIdentity: anchorSourceIdentity(
|
|
757
1272
|
anchor,
|
|
758
1273
|
exactObjectRect ? "direct" : "block-scoped",
|
|
@@ -762,6 +1277,80 @@ function appendCanonicalObjectHandleEntries(input: {
|
|
|
762
1277
|
}
|
|
763
1278
|
}
|
|
764
1279
|
|
|
1280
|
+
function appendPageLocalObjectHandleEntries(input: {
|
|
1281
|
+
page: RenderPage;
|
|
1282
|
+
entries: Map<string, MutableObjectHandleEntry>;
|
|
1283
|
+
precision: GeometryPrecisionCounts;
|
|
1284
|
+
divergenceIdsByObjectId: ReadonlyMap<string, readonly string[]>;
|
|
1285
|
+
}): void {
|
|
1286
|
+
const { page, entries, precision, divergenceIdsByObjectId } = input;
|
|
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;
|
|
1292
|
+
for (const story of stories) {
|
|
1293
|
+
const regionFrame =
|
|
1294
|
+
story.kind === "header" ? page.regions.header?.frame : page.regions.footer?.frame;
|
|
1295
|
+
if (!regionFrame) continue;
|
|
1296
|
+
for (const object of story.anchoredObjects) {
|
|
1297
|
+
const objectFrame = pageLocalObjectFrame(
|
|
1298
|
+
regionFrame,
|
|
1299
|
+
object.extentTwips,
|
|
1300
|
+
pxPerTwip,
|
|
1301
|
+
);
|
|
1302
|
+
const handleRects = buildObjectHandleRectsFromRect(objectFrame, "heuristic");
|
|
1303
|
+
const sourceIdentity: GeometrySourceIdentity = {
|
|
1304
|
+
storyKey: story.storyKey,
|
|
1305
|
+
objectKey: object.objectId,
|
|
1306
|
+
objectKind: object.sourceType,
|
|
1307
|
+
editPosture: object.preserveOnly ? "preserve-only" : "editable",
|
|
1308
|
+
joinKind: "block-scoped",
|
|
1309
|
+
};
|
|
1310
|
+
const existing = entries.get(object.objectId);
|
|
1311
|
+
if (existing) {
|
|
1312
|
+
appendUnique(existing.pageIds, page.page.pageId);
|
|
1313
|
+
existing.rects.push(...handleRects);
|
|
1314
|
+
appendDivergenceIds(existing, divergenceIdsByObjectId.get(object.objectId));
|
|
1315
|
+
if (existing.precision !== "heuristic") {
|
|
1316
|
+
existing.precision = "heuristic";
|
|
1317
|
+
existing.status = "requires-rehydration";
|
|
1318
|
+
existing.sourceIdentity = sourceIdentity;
|
|
1319
|
+
}
|
|
1320
|
+
continue;
|
|
1321
|
+
}
|
|
1322
|
+
entries.set(object.objectId, {
|
|
1323
|
+
objectId: object.objectId,
|
|
1324
|
+
pageIds: [page.page.pageId],
|
|
1325
|
+
rects: [...handleRects],
|
|
1326
|
+
status: "requires-rehydration",
|
|
1327
|
+
precision: "heuristic",
|
|
1328
|
+
...mutableLayoutDivergenceIds(divergenceIdsByObjectId.get(object.objectId)),
|
|
1329
|
+
sourceIdentity,
|
|
1330
|
+
});
|
|
1331
|
+
recordPrecision(precision, "heuristic");
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
function pageLocalObjectFrame(
|
|
1337
|
+
regionFrame: RenderFrameRect,
|
|
1338
|
+
extentTwips:
|
|
1339
|
+
| { readonly widthTwips: number; readonly heightTwips: number }
|
|
1340
|
+
| undefined,
|
|
1341
|
+
pxPerTwip: number,
|
|
1342
|
+
): RenderFrameRect {
|
|
1343
|
+
if (!extentTwips) return regionFrame;
|
|
1344
|
+
const widthPx = Math.max(0, extentTwips.widthTwips * pxPerTwip);
|
|
1345
|
+
const heightPx = Math.max(0, extentTwips.heightTwips * pxPerTwip);
|
|
1346
|
+
return {
|
|
1347
|
+
leftPx: regionFrame.leftPx,
|
|
1348
|
+
topPx: regionFrame.topPx,
|
|
1349
|
+
widthPx: widthPx > 0 ? Math.min(widthPx, regionFrame.widthPx) : regionFrame.widthPx,
|
|
1350
|
+
heightPx: heightPx > 0 ? Math.min(heightPx, regionFrame.heightPx) : regionFrame.heightPx,
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
|
|
765
1354
|
function finalizeObjectHandleEntries(
|
|
766
1355
|
entries: ReadonlyMap<string, MutableObjectHandleEntry>,
|
|
767
1356
|
): GeometryObjectHandleEntry[] {
|
|
@@ -771,6 +1360,9 @@ function finalizeObjectHandleEntries(
|
|
|
771
1360
|
rects: entry.rects,
|
|
772
1361
|
status: entry.status,
|
|
773
1362
|
precision: entry.precision,
|
|
1363
|
+
...(entry.layoutDivergenceIds && entry.layoutDivergenceIds.length > 0
|
|
1364
|
+
? { layoutDivergenceIds: [...entry.layoutDivergenceIds] }
|
|
1365
|
+
: {}),
|
|
774
1366
|
...(entry.sourceIdentity ? { sourceIdentity: entry.sourceIdentity } : {}),
|
|
775
1367
|
}));
|
|
776
1368
|
}
|
|
@@ -826,6 +1418,7 @@ function recordTableCellScopeBlocks(input: {
|
|
|
826
1418
|
storyKey: string;
|
|
827
1419
|
identities: GeometryIdentityLookup | null;
|
|
828
1420
|
projectedBlocksByStory: Map<string, ProjectedScopeBlock[]>;
|
|
1421
|
+
visibleRows: readonly VisibleTableRow[];
|
|
829
1422
|
}): void {
|
|
830
1423
|
const {
|
|
831
1424
|
table,
|
|
@@ -834,12 +1427,18 @@ function recordTableCellScopeBlocks(input: {
|
|
|
834
1427
|
storyKey,
|
|
835
1428
|
identities,
|
|
836
1429
|
projectedBlocksByStory,
|
|
1430
|
+
visibleRows,
|
|
837
1431
|
} = input;
|
|
838
1432
|
if (!identities) return;
|
|
839
1433
|
|
|
840
1434
|
for (const row of table.rows) {
|
|
841
1435
|
for (const cell of row.cells) {
|
|
842
|
-
const rect = pageFrameCellRect(
|
|
1436
|
+
const rect = pageFrameCellRect(
|
|
1437
|
+
block,
|
|
1438
|
+
row.rowIndex,
|
|
1439
|
+
cell.gridColumnStart,
|
|
1440
|
+
visibleRows,
|
|
1441
|
+
);
|
|
843
1442
|
if (!rect) continue;
|
|
844
1443
|
for (let blockIndex = 0; blockIndex < cell.blockCount; blockIndex += 1) {
|
|
845
1444
|
const blockPath =
|
|
@@ -1228,6 +1827,10 @@ function toGeometryRect(rect: RenderFrameRect): GeometryRect {
|
|
|
1228
1827
|
};
|
|
1229
1828
|
}
|
|
1230
1829
|
|
|
1830
|
+
function clamp(value: number, min: number, max: number): number {
|
|
1831
|
+
return Math.min(Math.max(value, min), max);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1231
1834
|
function makeRegionId(
|
|
1232
1835
|
page: RenderPage,
|
|
1233
1836
|
region: RenderStoryRegion,
|
|
@@ -1260,6 +1863,48 @@ function createPrecisionCounts(): GeometryPrecisionCounts {
|
|
|
1260
1863
|
};
|
|
1261
1864
|
}
|
|
1262
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
|
+
|
|
1263
1908
|
function recordPrecision(
|
|
1264
1909
|
counts: GeometryPrecisionCounts,
|
|
1265
1910
|
precision: keyof GeometryPrecisionCounts,
|