@beyondwork/docx-react-component 1.0.106 → 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 +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
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
export interface AdjacentGeometryRect {
|
|
2
|
+
readonly x: number;
|
|
3
|
+
readonly y: number;
|
|
4
|
+
readonly width: number;
|
|
5
|
+
readonly height: number;
|
|
6
|
+
readonly unit: "screenPx" | string;
|
|
7
|
+
readonly approxTwips?: {
|
|
8
|
+
readonly x?: number;
|
|
9
|
+
readonly y?: number;
|
|
10
|
+
readonly width?: number;
|
|
11
|
+
readonly height?: number;
|
|
12
|
+
readonly unit?: "twipsApproxFromScreen" | string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AdjacentGeometryTwipsRect {
|
|
17
|
+
readonly xTwips?: number;
|
|
18
|
+
readonly yTwips?: number;
|
|
19
|
+
readonly widthTwips?: number;
|
|
20
|
+
readonly heightTwips?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AdjacentGeometryPageSpan {
|
|
24
|
+
readonly startPage?: number | null;
|
|
25
|
+
readonly endPage?: number | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AdjacentGeometryPageLocalNumberingGeometry {
|
|
29
|
+
readonly wordPage?: number;
|
|
30
|
+
readonly runtimePageIndex?: number;
|
|
31
|
+
readonly runtimeFragmentId?: string;
|
|
32
|
+
readonly markerLane?: AdjacentGeometryTwipsRect;
|
|
33
|
+
readonly textColumn?: AdjacentGeometryTwipsRect;
|
|
34
|
+
readonly coordinateSpace: "word-page-twips";
|
|
35
|
+
readonly precision: "word-page-local-calibration";
|
|
36
|
+
readonly normalizationStatus:
|
|
37
|
+
| "word-page-local-awaiting-l04-frame-projection"
|
|
38
|
+
| "missing-word-page-local-lane";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AdjacentGeometryPageLocalFieldGeometry {
|
|
42
|
+
readonly expectedPageSpan?: AdjacentGeometryPageSpan;
|
|
43
|
+
readonly normalizedWordPageIndexSpan?: AdjacentGeometryPageSpan;
|
|
44
|
+
readonly runtimePageSpan?: AdjacentGeometryPageSpan;
|
|
45
|
+
readonly pageSpanStatus:
|
|
46
|
+
| "matches-runtime"
|
|
47
|
+
| "contained-in-runtime"
|
|
48
|
+
| "differs-from-runtime"
|
|
49
|
+
| "runtime-missing"
|
|
50
|
+
| "expected-missing";
|
|
51
|
+
readonly startAnchorTwips?: {
|
|
52
|
+
readonly x?: number;
|
|
53
|
+
readonly y?: number;
|
|
54
|
+
};
|
|
55
|
+
readonly endAnchorTwips?: {
|
|
56
|
+
readonly x?: number;
|
|
57
|
+
readonly y?: number;
|
|
58
|
+
};
|
|
59
|
+
readonly coordinateSpace: "word-page-twips";
|
|
60
|
+
readonly precision: "word-page-local-calibration";
|
|
61
|
+
readonly normalizationStatus:
|
|
62
|
+
| "word-page-local-awaiting-l04-frame-projection"
|
|
63
|
+
| "missing-word-placement";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface AdjacentGeometryNumberingRowSummary {
|
|
67
|
+
readonly docId: string;
|
|
68
|
+
readonly wordParagraphOrdinalGlobal?: number;
|
|
69
|
+
readonly canonicalBlockId?: string;
|
|
70
|
+
readonly runtimeBlockId?: string;
|
|
71
|
+
readonly runtimeFragmentId?: string;
|
|
72
|
+
readonly runtimePageIndex?: number;
|
|
73
|
+
readonly sourceParagraphPath?: string;
|
|
74
|
+
readonly canonicalNumberingInstanceId?: string;
|
|
75
|
+
readonly canonicalLevel?: number;
|
|
76
|
+
readonly markerKind?: string;
|
|
77
|
+
readonly markerSuffix?: string;
|
|
78
|
+
readonly wordStartPage?: number;
|
|
79
|
+
readonly paragraphLineRectCount: number;
|
|
80
|
+
readonly textOnlyLineRectCount: number;
|
|
81
|
+
readonly rawMarkerRectCount: number;
|
|
82
|
+
readonly markerRectCount: number;
|
|
83
|
+
readonly wrappedLineCount: number;
|
|
84
|
+
readonly markerLane?: {
|
|
85
|
+
readonly xTwips?: number;
|
|
86
|
+
readonly yTwips?: number;
|
|
87
|
+
readonly widthTwips?: number;
|
|
88
|
+
readonly heightTwips?: number;
|
|
89
|
+
};
|
|
90
|
+
readonly textColumn?: {
|
|
91
|
+
readonly xTwips?: number;
|
|
92
|
+
readonly yTwips?: number;
|
|
93
|
+
readonly widthTwips?: number;
|
|
94
|
+
readonly heightTwips?: number;
|
|
95
|
+
};
|
|
96
|
+
readonly pageLocalGeometry: AdjacentGeometryPageLocalNumberingGeometry;
|
|
97
|
+
readonly rangeMappingMethod?: string;
|
|
98
|
+
readonly coordinateSpace: "screen-px";
|
|
99
|
+
readonly precision: "screen-space-approximate";
|
|
100
|
+
readonly normalizationStatus: "awaiting-l04-page-frame-normalization";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface AdjacentGeometryFieldRegionRowSummary {
|
|
104
|
+
readonly docId: string;
|
|
105
|
+
readonly wordFieldOrdinalGlobal?: number;
|
|
106
|
+
readonly canonicalFieldId?: string;
|
|
107
|
+
readonly canonicalBlockId?: string;
|
|
108
|
+
readonly runtimeFieldRegionId?: string;
|
|
109
|
+
readonly runtimeFragmentId?: string;
|
|
110
|
+
readonly runtimePageSpan?: {
|
|
111
|
+
readonly startPage?: number | null;
|
|
112
|
+
readonly endPage?: number | null;
|
|
113
|
+
};
|
|
114
|
+
readonly expectedPageSpan?: {
|
|
115
|
+
readonly startPage?: number | null;
|
|
116
|
+
readonly endPage?: number | null;
|
|
117
|
+
};
|
|
118
|
+
readonly pageLocalGeometry: AdjacentGeometryPageLocalFieldGeometry;
|
|
119
|
+
readonly instructionFamily?: string;
|
|
120
|
+
readonly resultLineRectCount: number;
|
|
121
|
+
readonly wordPlacement?: {
|
|
122
|
+
readonly startPage?: number;
|
|
123
|
+
readonly endPage?: number;
|
|
124
|
+
readonly startXYTwips?: {
|
|
125
|
+
readonly x?: number;
|
|
126
|
+
readonly y?: number;
|
|
127
|
+
};
|
|
128
|
+
readonly endXYTwips?: {
|
|
129
|
+
readonly x?: number;
|
|
130
|
+
readonly y?: number;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
readonly coordinateSpace: "screen-px";
|
|
134
|
+
readonly precision: "screen-space-approximate";
|
|
135
|
+
readonly normalizationStatus:
|
|
136
|
+
| "runtime-id-paired-awaiting-page-frame-normalization"
|
|
137
|
+
| "awaiting-runtime-field-region-id";
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface AdjacentGeometryDocumentSummary {
|
|
141
|
+
readonly docId: string;
|
|
142
|
+
readonly numberingRows: number;
|
|
143
|
+
readonly numberingRowsWithRuntimeFragment: number;
|
|
144
|
+
readonly numberingParagraphLineRects: number;
|
|
145
|
+
readonly numberingTextOnlyLineRects: number;
|
|
146
|
+
readonly numberingRawMarkerRectRows: number;
|
|
147
|
+
readonly numberingMarkerRects: number;
|
|
148
|
+
readonly numberingRowsWithMissingMarkerRectGeometry: number;
|
|
149
|
+
readonly numberingWrappedRows: number;
|
|
150
|
+
readonly numberingRowsWithUiaCapture: number;
|
|
151
|
+
readonly numberingRowsWithPageLocalMarkerLane: number;
|
|
152
|
+
readonly numberingRowsWithPageLocalTextColumn: number;
|
|
153
|
+
readonly fieldRegionRows: number;
|
|
154
|
+
readonly fieldRegionRowsWithRuntimeId: number;
|
|
155
|
+
readonly fieldRegionResultLineRects: number;
|
|
156
|
+
readonly fieldRegionRowsWithUiaCapture: number;
|
|
157
|
+
readonly fieldRegionRowsWithWordPlacement: number;
|
|
158
|
+
readonly fieldRegionRowsWithRuntimePageMatch: number;
|
|
159
|
+
readonly fieldRegionRowsWithRuntimePageContainment: number;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface AdjacentGeometryIntakeSummary {
|
|
163
|
+
readonly schemaVersion: "layer-05-adjacent-geometry-intake/v0";
|
|
164
|
+
readonly generatedAtUtc: string;
|
|
165
|
+
readonly sourceRuns: {
|
|
166
|
+
readonly adjacentLiveWordJoins: string;
|
|
167
|
+
readonly adjacentUiaNumberingRects: string;
|
|
168
|
+
readonly fieldRegionRuntimeReadbackVm: string;
|
|
169
|
+
};
|
|
170
|
+
readonly totals: {
|
|
171
|
+
readonly numberingRows: number;
|
|
172
|
+
readonly numberingRowsWithRuntimeFragment: number;
|
|
173
|
+
readonly numberingParagraphLineRects: number;
|
|
174
|
+
readonly numberingTextOnlyLineRects: number;
|
|
175
|
+
readonly numberingRawMarkerRectRows: number;
|
|
176
|
+
readonly numberingMarkerRects: number;
|
|
177
|
+
readonly numberingRowsWithMissingMarkerRectGeometry: number;
|
|
178
|
+
readonly numberingWrappedRows: number;
|
|
179
|
+
readonly numberingRowsWithUiaCapture: number;
|
|
180
|
+
readonly numberingRowsWithPageLocalMarkerLane: number;
|
|
181
|
+
readonly numberingRowsWithPageLocalTextColumn: number;
|
|
182
|
+
readonly fieldRegionRows: number;
|
|
183
|
+
readonly fieldRegionRowsWithRuntimeId: number;
|
|
184
|
+
readonly fieldRegionResultLineRects: number;
|
|
185
|
+
readonly fieldRegionRowsWithUiaCapture: number;
|
|
186
|
+
readonly fieldRegionRowsWithWordPlacement: number;
|
|
187
|
+
readonly fieldRegionRowsWithRuntimePageMatch: number;
|
|
188
|
+
readonly fieldRegionRowsWithRuntimePageContainment: number;
|
|
189
|
+
};
|
|
190
|
+
readonly routing: {
|
|
191
|
+
readonly routedTo: "L05";
|
|
192
|
+
readonly axes: readonly ["numbering-marker-geometry", "field-result-geometry"];
|
|
193
|
+
readonly coordinateSpace: "screen-px";
|
|
194
|
+
readonly precision: "screen-space-approximate";
|
|
195
|
+
readonly requiredUpstreamFact: "L04 page/frame normalization";
|
|
196
|
+
};
|
|
197
|
+
readonly pageLocalNormalization: {
|
|
198
|
+
readonly coordinateSpace: "word-page-twips";
|
|
199
|
+
readonly precision: "word-page-local-calibration";
|
|
200
|
+
readonly requiredUpstreamFact: "L04 frame-to-pixel projection";
|
|
201
|
+
readonly compositorReady: false;
|
|
202
|
+
};
|
|
203
|
+
readonly documents: readonly AdjacentGeometryDocumentSummary[];
|
|
204
|
+
readonly numberingRows: readonly AdjacentGeometryNumberingRowSummary[];
|
|
205
|
+
readonly fieldRegionRows: readonly AdjacentGeometryFieldRegionRowSummary[];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function summarizeAdjacentGeometryIntake(input: {
|
|
209
|
+
readonly generatedAtUtc: string;
|
|
210
|
+
readonly sourceRuns: AdjacentGeometryIntakeSummary["sourceRuns"];
|
|
211
|
+
readonly numberingArtifact: unknown;
|
|
212
|
+
readonly numberingLiveJoinArtifacts: readonly unknown[];
|
|
213
|
+
readonly fieldRegionRuntimeReadback: unknown;
|
|
214
|
+
readonly fieldRegionLiveJoinArtifacts: readonly unknown[];
|
|
215
|
+
}): AdjacentGeometryIntakeSummary {
|
|
216
|
+
const numberingRows = summarizeNumberingRows(
|
|
217
|
+
input.numberingArtifact,
|
|
218
|
+
input.numberingLiveJoinArtifacts,
|
|
219
|
+
);
|
|
220
|
+
const fieldRegionRows = summarizeFieldRegionRows(
|
|
221
|
+
input.fieldRegionRuntimeReadback,
|
|
222
|
+
input.fieldRegionLiveJoinArtifacts,
|
|
223
|
+
);
|
|
224
|
+
const docIds = [
|
|
225
|
+
...new Set([
|
|
226
|
+
...numberingRows.map((row) => row.docId),
|
|
227
|
+
...fieldRegionRows.map((row) => row.docId),
|
|
228
|
+
]),
|
|
229
|
+
].sort();
|
|
230
|
+
return {
|
|
231
|
+
schemaVersion: "layer-05-adjacent-geometry-intake/v0",
|
|
232
|
+
generatedAtUtc: input.generatedAtUtc,
|
|
233
|
+
sourceRuns: input.sourceRuns,
|
|
234
|
+
totals: {
|
|
235
|
+
numberingRows: numberingRows.length,
|
|
236
|
+
numberingRowsWithRuntimeFragment: numberingRows.filter(
|
|
237
|
+
(row) => row.runtimeFragmentId !== undefined,
|
|
238
|
+
).length,
|
|
239
|
+
numberingParagraphLineRects: sum(
|
|
240
|
+
numberingRows,
|
|
241
|
+
(row) => row.paragraphLineRectCount,
|
|
242
|
+
),
|
|
243
|
+
numberingTextOnlyLineRects: sum(
|
|
244
|
+
numberingRows,
|
|
245
|
+
(row) => row.textOnlyLineRectCount,
|
|
246
|
+
),
|
|
247
|
+
numberingRawMarkerRectRows: sum(numberingRows, (row) => row.rawMarkerRectCount),
|
|
248
|
+
numberingMarkerRects: sum(numberingRows, (row) => row.markerRectCount),
|
|
249
|
+
numberingRowsWithMissingMarkerRectGeometry: numberingRows.filter(
|
|
250
|
+
(row) => row.rawMarkerRectCount > row.markerRectCount,
|
|
251
|
+
).length,
|
|
252
|
+
numberingWrappedRows: numberingRows.filter((row) => row.wrappedLineCount > 1)
|
|
253
|
+
.length,
|
|
254
|
+
numberingRowsWithUiaCapture: numberingRows.filter(hasNumberingUiaCapture).length,
|
|
255
|
+
numberingRowsWithPageLocalMarkerLane: numberingRows.filter(
|
|
256
|
+
(row) => row.pageLocalGeometry.markerLane !== undefined,
|
|
257
|
+
).length,
|
|
258
|
+
numberingRowsWithPageLocalTextColumn: numberingRows.filter(
|
|
259
|
+
(row) => row.pageLocalGeometry.textColumn !== undefined,
|
|
260
|
+
).length,
|
|
261
|
+
fieldRegionRows: fieldRegionRows.length,
|
|
262
|
+
fieldRegionRowsWithRuntimeId: fieldRegionRows.filter(
|
|
263
|
+
(row) => row.runtimeFieldRegionId !== undefined,
|
|
264
|
+
).length,
|
|
265
|
+
fieldRegionResultLineRects: sum(
|
|
266
|
+
fieldRegionRows,
|
|
267
|
+
(row) => row.resultLineRectCount,
|
|
268
|
+
),
|
|
269
|
+
fieldRegionRowsWithUiaCapture: fieldRegionRows.filter(
|
|
270
|
+
(row) => row.resultLineRectCount > 0,
|
|
271
|
+
).length,
|
|
272
|
+
fieldRegionRowsWithWordPlacement: fieldRegionRows.filter(
|
|
273
|
+
(row) => row.pageLocalGeometry.startAnchorTwips !== undefined,
|
|
274
|
+
).length,
|
|
275
|
+
fieldRegionRowsWithRuntimePageMatch: fieldRegionRows.filter(
|
|
276
|
+
(row) => row.pageLocalGeometry.pageSpanStatus === "matches-runtime",
|
|
277
|
+
).length,
|
|
278
|
+
fieldRegionRowsWithRuntimePageContainment: fieldRegionRows.filter(
|
|
279
|
+
(row) => row.pageLocalGeometry.pageSpanStatus === "contained-in-runtime",
|
|
280
|
+
).length,
|
|
281
|
+
},
|
|
282
|
+
routing: {
|
|
283
|
+
routedTo: "L05",
|
|
284
|
+
axes: ["numbering-marker-geometry", "field-result-geometry"],
|
|
285
|
+
coordinateSpace: "screen-px",
|
|
286
|
+
precision: "screen-space-approximate",
|
|
287
|
+
requiredUpstreamFact: "L04 page/frame normalization",
|
|
288
|
+
},
|
|
289
|
+
pageLocalNormalization: {
|
|
290
|
+
coordinateSpace: "word-page-twips",
|
|
291
|
+
precision: "word-page-local-calibration",
|
|
292
|
+
requiredUpstreamFact: "L04 frame-to-pixel projection",
|
|
293
|
+
compositorReady: false,
|
|
294
|
+
},
|
|
295
|
+
documents: docIds.map((docId) =>
|
|
296
|
+
summarizeDocument(
|
|
297
|
+
docId,
|
|
298
|
+
numberingRows.filter((row) => row.docId === docId),
|
|
299
|
+
fieldRegionRows.filter((row) => row.docId === docId),
|
|
300
|
+
),
|
|
301
|
+
),
|
|
302
|
+
numberingRows,
|
|
303
|
+
fieldRegionRows,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function summarizeNumberingRows(
|
|
308
|
+
artifact: unknown,
|
|
309
|
+
liveJoinArtifacts: readonly unknown[],
|
|
310
|
+
): readonly AdjacentGeometryNumberingRowSummary[] {
|
|
311
|
+
const uiaRowsByKey = new Map<string, Record<string, unknown>>();
|
|
312
|
+
for (const raw of array(record(artifact).rows)) {
|
|
313
|
+
const row = record(raw);
|
|
314
|
+
const key = numberingKey(
|
|
315
|
+
stringValue(row.docId) ?? stringValue(record(row.targetJoin).docId),
|
|
316
|
+
numberValue(row.wordParagraphOrdinalGlobal) ??
|
|
317
|
+
numberValue(record(row.targetJoin).wordParagraphOrdinalGlobal),
|
|
318
|
+
);
|
|
319
|
+
if (key) uiaRowsByKey.set(key, row);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const liveRows = liveJoinArtifacts.flatMap((artifact) =>
|
|
323
|
+
array(record(artifact).numberingRows).map(record),
|
|
324
|
+
);
|
|
325
|
+
const rows = liveRows.length > 0
|
|
326
|
+
? liveRows.filter((row) => stringValue(row.runtimeFragmentId) !== undefined)
|
|
327
|
+
: array(record(artifact).rows).map(record);
|
|
328
|
+
|
|
329
|
+
return rows
|
|
330
|
+
.map((raw) => {
|
|
331
|
+
const row = record(raw);
|
|
332
|
+
const rowTargetJoin = record(row.targetJoin);
|
|
333
|
+
const docId =
|
|
334
|
+
stringValue(row.docId) ?? stringValue(rowTargetJoin.docId) ?? "unknown";
|
|
335
|
+
const wordParagraphOrdinalGlobal =
|
|
336
|
+
numberValue(row.wordParagraphOrdinalGlobal) ??
|
|
337
|
+
numberValue(rowTargetJoin.wordParagraphOrdinalGlobal);
|
|
338
|
+
const uiaRow =
|
|
339
|
+
uiaRowsByKey.get(numberingKey(docId, wordParagraphOrdinalGlobal) ?? "") ??
|
|
340
|
+
{};
|
|
341
|
+
const uiaTargetJoin = record(uiaRow.targetJoin);
|
|
342
|
+
const paragraphLineRects = chooseRects(
|
|
343
|
+
uiaRow.paragraphLineRects,
|
|
344
|
+
row.paragraphLineRects,
|
|
345
|
+
);
|
|
346
|
+
const textOnlyLineRects = chooseRects(
|
|
347
|
+
uiaRow.textOnlyLineRects,
|
|
348
|
+
row.textOnlyLineRects,
|
|
349
|
+
);
|
|
350
|
+
const rawMarkerRects = chooseRawArray(uiaRow.markerRects, row.markerRects);
|
|
351
|
+
const markerRects = chooseRects(uiaRow.markerRects, row.markerRects);
|
|
352
|
+
const markerLane =
|
|
353
|
+
normalizeTwipsRect(row.markerLane) ?? normalizeTwipsRect(uiaTargetJoin.markerLane);
|
|
354
|
+
const textColumn =
|
|
355
|
+
normalizeTwipsRect(row.textColumn) ?? normalizeTwipsRect(uiaTargetJoin.textColumn);
|
|
356
|
+
const runtimeFragmentId =
|
|
357
|
+
stringValue(row.runtimeFragmentId) ?? stringValue(uiaTargetJoin.runtimeFragmentId);
|
|
358
|
+
const runtimePageIndex =
|
|
359
|
+
numberValue(row.runtimePageIndex) ?? numberValue(uiaTargetJoin.runtimePageIndex);
|
|
360
|
+
const wordStartPage =
|
|
361
|
+
numberValue(record(row.pageSpan).startPage) ??
|
|
362
|
+
numberValue(row.wordStartPage) ??
|
|
363
|
+
numberValue(uiaRow.wordStartPage);
|
|
364
|
+
const pageLocalGeometry: AdjacentGeometryPageLocalNumberingGeometry = {
|
|
365
|
+
wordPage: wordStartPage,
|
|
366
|
+
runtimePageIndex,
|
|
367
|
+
runtimeFragmentId,
|
|
368
|
+
markerLane,
|
|
369
|
+
textColumn,
|
|
370
|
+
coordinateSpace: "word-page-twips",
|
|
371
|
+
precision: "word-page-local-calibration",
|
|
372
|
+
normalizationStatus:
|
|
373
|
+
markerLane || textColumn
|
|
374
|
+
? "word-page-local-awaiting-l04-frame-projection"
|
|
375
|
+
: "missing-word-page-local-lane",
|
|
376
|
+
};
|
|
377
|
+
return {
|
|
378
|
+
docId,
|
|
379
|
+
wordParagraphOrdinalGlobal,
|
|
380
|
+
canonicalBlockId:
|
|
381
|
+
stringValue(row.canonicalBlockId) ?? stringValue(uiaTargetJoin.canonicalBlockId),
|
|
382
|
+
runtimeBlockId:
|
|
383
|
+
stringValue(row.runtimeBlockId) ?? stringValue(uiaTargetJoin.runtimeBlockId),
|
|
384
|
+
runtimeFragmentId,
|
|
385
|
+
runtimePageIndex,
|
|
386
|
+
sourceParagraphPath:
|
|
387
|
+
stringValue(row.sourceParagraphPath) ??
|
|
388
|
+
stringValue(uiaTargetJoin.sourceParagraphPath),
|
|
389
|
+
canonicalNumberingInstanceId:
|
|
390
|
+
stringValue(row.canonicalNumberingInstanceId) ??
|
|
391
|
+
stringValue(uiaTargetJoin.canonicalNumberingInstanceId),
|
|
392
|
+
canonicalLevel:
|
|
393
|
+
numberValue(row.canonicalLevel) ?? numberValue(uiaTargetJoin.canonicalLevel),
|
|
394
|
+
markerKind: stringValue(row.markerKind) ?? stringValue(uiaTargetJoin.markerKind),
|
|
395
|
+
markerSuffix:
|
|
396
|
+
stringValue(row.markerSuffix) ?? stringValue(uiaTargetJoin.markerSuffix),
|
|
397
|
+
wordStartPage,
|
|
398
|
+
paragraphLineRectCount: paragraphLineRects.length,
|
|
399
|
+
textOnlyLineRectCount: textOnlyLineRects.length,
|
|
400
|
+
rawMarkerRectCount: rawMarkerRects.length,
|
|
401
|
+
markerRectCount: markerRects.length,
|
|
402
|
+
wrappedLineCount: Math.max(paragraphLineRects.length, textOnlyLineRects.length),
|
|
403
|
+
markerLane,
|
|
404
|
+
textColumn,
|
|
405
|
+
pageLocalGeometry,
|
|
406
|
+
rangeMappingMethod:
|
|
407
|
+
stringValue(uiaRow.rangeMappingMethod) ?? stringValue(row.rangeMappingMethod),
|
|
408
|
+
coordinateSpace: "screen-px" as const,
|
|
409
|
+
precision: "screen-space-approximate" as const,
|
|
410
|
+
normalizationStatus: "awaiting-l04-page-frame-normalization" as const,
|
|
411
|
+
};
|
|
412
|
+
})
|
|
413
|
+
.sort(
|
|
414
|
+
(a, b) =>
|
|
415
|
+
a.docId.localeCompare(b.docId) ||
|
|
416
|
+
compareOptionalNumber(
|
|
417
|
+
a.wordParagraphOrdinalGlobal,
|
|
418
|
+
b.wordParagraphOrdinalGlobal,
|
|
419
|
+
),
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function summarizeFieldRegionRows(
|
|
424
|
+
runtimeReadback: unknown,
|
|
425
|
+
liveJoinArtifacts: readonly unknown[],
|
|
426
|
+
): readonly AdjacentGeometryFieldRegionRowSummary[] {
|
|
427
|
+
const liveJoinByOrdinalKey = new Map<string, Record<string, unknown>>();
|
|
428
|
+
const uniqueLiveJoinRows: Record<string, unknown>[] = [];
|
|
429
|
+
const seenRuntimeKeys = new Set<string>();
|
|
430
|
+
for (const artifact of liveJoinArtifacts) {
|
|
431
|
+
for (const raw of array(record(artifact).fields)) {
|
|
432
|
+
const row = record(raw);
|
|
433
|
+
const key = fieldKey(
|
|
434
|
+
stringValue(row.docId),
|
|
435
|
+
numberValue(row.wordFieldOrdinalGlobal),
|
|
436
|
+
);
|
|
437
|
+
if (key) liveJoinByOrdinalKey.set(key, row);
|
|
438
|
+
const runtimeKey = fieldRuntimeKey(
|
|
439
|
+
stringValue(row.docId),
|
|
440
|
+
stringValue(row.runtimeFieldRegionId),
|
|
441
|
+
);
|
|
442
|
+
if (!runtimeKey || seenRuntimeKeys.has(runtimeKey)) continue;
|
|
443
|
+
seenRuntimeKeys.add(runtimeKey);
|
|
444
|
+
uniqueLiveJoinRows.push(row);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const readbackByKey = new Map<string, Record<string, unknown>>();
|
|
449
|
+
for (const raw of array(record(runtimeReadback).rows)) {
|
|
450
|
+
const row = record(raw);
|
|
451
|
+
const key = fieldKey(
|
|
452
|
+
stringValue(row.docId) ?? stringValue(record(row.targetJoin).docId),
|
|
453
|
+
numberValue(row.wordFieldOrdinalGlobal) ??
|
|
454
|
+
numberValue(record(row.targetJoin).wordFieldOrdinalGlobal),
|
|
455
|
+
);
|
|
456
|
+
if (key) readbackByKey.set(key, row);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const rows = uniqueLiveJoinRows.length > 0
|
|
460
|
+
? uniqueLiveJoinRows
|
|
461
|
+
: array(record(runtimeReadback).rows).map(record);
|
|
462
|
+
|
|
463
|
+
return rows
|
|
464
|
+
.map((raw) => {
|
|
465
|
+
const liveJoinCandidate = record(raw);
|
|
466
|
+
const docId = stringValue(liveJoinCandidate.docId) ?? "unknown";
|
|
467
|
+
const wordFieldOrdinalGlobal = numberValue(
|
|
468
|
+
liveJoinCandidate.wordFieldOrdinalGlobal,
|
|
469
|
+
);
|
|
470
|
+
const readbackRow =
|
|
471
|
+
readbackByKey.get(fieldKey(docId, wordFieldOrdinalGlobal) ?? "") ?? {};
|
|
472
|
+
const targetJoin = record(readbackRow.targetJoin);
|
|
473
|
+
const liveJoin =
|
|
474
|
+
liveJoinByOrdinalKey.get(fieldKey(docId, wordFieldOrdinalGlobal) ?? "") ??
|
|
475
|
+
liveJoinCandidate;
|
|
476
|
+
const liveRuntimePageSpan = record(liveJoin.runtimePageSpan);
|
|
477
|
+
const runtimePageSpan = normalizePageSpan(
|
|
478
|
+
liveRuntimePageSpan,
|
|
479
|
+
record(record(readbackRow.runtime).runtimePageSpan),
|
|
480
|
+
record(targetJoin.runtimePageSpan),
|
|
481
|
+
);
|
|
482
|
+
const expectedGraphOutput = record(readbackRow.expectedGraphOutput);
|
|
483
|
+
const expectedPageSpan = normalizePageSpan(
|
|
484
|
+
record(liveJoin.resultPageSpan),
|
|
485
|
+
record(readbackRow.wordResultPlacement),
|
|
486
|
+
record(expectedGraphOutput.expectedPageSpan),
|
|
487
|
+
record(targetJoin.resultPageSpan),
|
|
488
|
+
);
|
|
489
|
+
const normalizedWordPageIndexSpan = normalizeWordPageSpanToPageIndexSpan(
|
|
490
|
+
expectedPageSpan,
|
|
491
|
+
);
|
|
492
|
+
const uia = record(readbackRow.uia);
|
|
493
|
+
const resultLineRects = normalizeRects(uia.resultLineRectsScreen);
|
|
494
|
+
const hasRuntimeFieldRegionId =
|
|
495
|
+
stringValue(liveJoin.runtimeFieldRegionId) !== undefined;
|
|
496
|
+
const normalizationStatus: AdjacentGeometryFieldRegionRowSummary["normalizationStatus"] =
|
|
497
|
+
hasRuntimeFieldRegionId
|
|
498
|
+
? "runtime-id-paired-awaiting-page-frame-normalization"
|
|
499
|
+
: "awaiting-runtime-field-region-id";
|
|
500
|
+
const wordPlacement = normalizeWordPlacement(
|
|
501
|
+
record(readbackRow.wordResultPlacement),
|
|
502
|
+
);
|
|
503
|
+
const pageLocalGeometry: AdjacentGeometryPageLocalFieldGeometry = {
|
|
504
|
+
expectedPageSpan,
|
|
505
|
+
normalizedWordPageIndexSpan,
|
|
506
|
+
runtimePageSpan,
|
|
507
|
+
pageSpanStatus: classifyPageSpan(normalizedWordPageIndexSpan, runtimePageSpan),
|
|
508
|
+
startAnchorTwips: wordPlacement?.startXYTwips,
|
|
509
|
+
endAnchorTwips: wordPlacement?.endXYTwips,
|
|
510
|
+
coordinateSpace: "word-page-twips",
|
|
511
|
+
precision: "word-page-local-calibration",
|
|
512
|
+
normalizationStatus:
|
|
513
|
+
wordPlacement?.startXYTwips || wordPlacement?.endXYTwips
|
|
514
|
+
? "word-page-local-awaiting-l04-frame-projection"
|
|
515
|
+
: "missing-word-placement",
|
|
516
|
+
};
|
|
517
|
+
return {
|
|
518
|
+
docId,
|
|
519
|
+
wordFieldOrdinalGlobal,
|
|
520
|
+
canonicalFieldId:
|
|
521
|
+
stringValue(liveJoin.canonicalFieldId) ??
|
|
522
|
+
stringValue(targetJoin.canonicalFieldId),
|
|
523
|
+
canonicalBlockId:
|
|
524
|
+
stringValue(liveJoin.canonicalBlockId) ??
|
|
525
|
+
stringValue(targetJoin.canonicalBlockId),
|
|
526
|
+
runtimeFieldRegionId:
|
|
527
|
+
stringValue(liveJoin.runtimeFieldRegionId) ??
|
|
528
|
+
stringValue(targetJoin.runtimeFieldRegionId) ??
|
|
529
|
+
stringValue(record(readbackRow.runtime).runtimeFieldRegionId),
|
|
530
|
+
runtimeFragmentId:
|
|
531
|
+
stringValue(liveJoin.runtimeFragmentId) ??
|
|
532
|
+
stringValue(targetJoin.runtimeFragmentId) ??
|
|
533
|
+
stringValue(record(readbackRow.runtime).runtimeFragmentId),
|
|
534
|
+
runtimePageSpan,
|
|
535
|
+
expectedPageSpan,
|
|
536
|
+
pageLocalGeometry,
|
|
537
|
+
instructionFamily:
|
|
538
|
+
stringValue(liveJoin.instructionFamily) ??
|
|
539
|
+
stringValue(targetJoin.instructionFamily),
|
|
540
|
+
resultLineRectCount: resultLineRects.length,
|
|
541
|
+
wordPlacement,
|
|
542
|
+
coordinateSpace: "screen-px" as const,
|
|
543
|
+
precision: "screen-space-approximate" as const,
|
|
544
|
+
normalizationStatus,
|
|
545
|
+
};
|
|
546
|
+
})
|
|
547
|
+
.sort(
|
|
548
|
+
(a, b) =>
|
|
549
|
+
a.docId.localeCompare(b.docId) ||
|
|
550
|
+
compareOptionalNumber(a.wordFieldOrdinalGlobal, b.wordFieldOrdinalGlobal),
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
function summarizeDocument(
|
|
555
|
+
docId: string,
|
|
556
|
+
numberingRows: readonly AdjacentGeometryNumberingRowSummary[],
|
|
557
|
+
fieldRegionRows: readonly AdjacentGeometryFieldRegionRowSummary[],
|
|
558
|
+
): AdjacentGeometryDocumentSummary {
|
|
559
|
+
return {
|
|
560
|
+
docId,
|
|
561
|
+
numberingRows: numberingRows.length,
|
|
562
|
+
numberingRowsWithRuntimeFragment: numberingRows.filter(
|
|
563
|
+
(row) => row.runtimeFragmentId !== undefined,
|
|
564
|
+
).length,
|
|
565
|
+
numberingParagraphLineRects: sum(
|
|
566
|
+
numberingRows,
|
|
567
|
+
(row) => row.paragraphLineRectCount,
|
|
568
|
+
),
|
|
569
|
+
numberingTextOnlyLineRects: sum(
|
|
570
|
+
numberingRows,
|
|
571
|
+
(row) => row.textOnlyLineRectCount,
|
|
572
|
+
),
|
|
573
|
+
numberingRawMarkerRectRows: sum(numberingRows, (row) => row.rawMarkerRectCount),
|
|
574
|
+
numberingMarkerRects: sum(numberingRows, (row) => row.markerRectCount),
|
|
575
|
+
numberingRowsWithMissingMarkerRectGeometry: numberingRows.filter(
|
|
576
|
+
(row) => row.rawMarkerRectCount > row.markerRectCount,
|
|
577
|
+
).length,
|
|
578
|
+
numberingWrappedRows: numberingRows.filter((row) => row.wrappedLineCount > 1)
|
|
579
|
+
.length,
|
|
580
|
+
numberingRowsWithUiaCapture: numberingRows.filter(hasNumberingUiaCapture).length,
|
|
581
|
+
numberingRowsWithPageLocalMarkerLane: numberingRows.filter(
|
|
582
|
+
(row) => row.pageLocalGeometry.markerLane !== undefined,
|
|
583
|
+
).length,
|
|
584
|
+
numberingRowsWithPageLocalTextColumn: numberingRows.filter(
|
|
585
|
+
(row) => row.pageLocalGeometry.textColumn !== undefined,
|
|
586
|
+
).length,
|
|
587
|
+
fieldRegionRows: fieldRegionRows.length,
|
|
588
|
+
fieldRegionRowsWithRuntimeId: fieldRegionRows.filter(
|
|
589
|
+
(row) => row.runtimeFieldRegionId !== undefined,
|
|
590
|
+
).length,
|
|
591
|
+
fieldRegionResultLineRects: sum(
|
|
592
|
+
fieldRegionRows,
|
|
593
|
+
(row) => row.resultLineRectCount,
|
|
594
|
+
),
|
|
595
|
+
fieldRegionRowsWithUiaCapture: fieldRegionRows.filter(
|
|
596
|
+
(row) => row.resultLineRectCount > 0,
|
|
597
|
+
).length,
|
|
598
|
+
fieldRegionRowsWithWordPlacement: fieldRegionRows.filter(
|
|
599
|
+
(row) => row.pageLocalGeometry.startAnchorTwips !== undefined,
|
|
600
|
+
).length,
|
|
601
|
+
fieldRegionRowsWithRuntimePageMatch: fieldRegionRows.filter(
|
|
602
|
+
(row) => row.pageLocalGeometry.pageSpanStatus === "matches-runtime",
|
|
603
|
+
).length,
|
|
604
|
+
fieldRegionRowsWithRuntimePageContainment: fieldRegionRows.filter(
|
|
605
|
+
(row) => row.pageLocalGeometry.pageSpanStatus === "contained-in-runtime",
|
|
606
|
+
).length,
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function hasNumberingUiaCapture(row: AdjacentGeometryNumberingRowSummary): boolean {
|
|
611
|
+
return (
|
|
612
|
+
row.paragraphLineRectCount > 0 ||
|
|
613
|
+
row.textOnlyLineRectCount > 0 ||
|
|
614
|
+
row.rawMarkerRectCount > 0
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function normalizeRects(raw: unknown): readonly AdjacentGeometryRect[] {
|
|
619
|
+
if (Array.isArray(raw)) return raw.map(normalizeRect).filter(isRect);
|
|
620
|
+
const maybeRect = normalizeRect(raw);
|
|
621
|
+
return isRect(maybeRect) ? [maybeRect] : [];
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function chooseRects(primary: unknown, fallback: unknown): readonly AdjacentGeometryRect[] {
|
|
625
|
+
const primaryRects = normalizeRects(primary);
|
|
626
|
+
return primaryRects.length > 0 ? primaryRects : normalizeRects(fallback);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
function chooseRawArray(primary: unknown, fallback: unknown): readonly unknown[] {
|
|
630
|
+
const primaryArray = array(primary);
|
|
631
|
+
return primaryArray.length > 0 ? primaryArray : array(fallback);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function normalizeRect(raw: unknown): AdjacentGeometryRect | undefined {
|
|
635
|
+
const rect = record(raw);
|
|
636
|
+
const x = numberValue(rect.x);
|
|
637
|
+
const y = numberValue(rect.y);
|
|
638
|
+
const width = numberValue(rect.width);
|
|
639
|
+
const height = numberValue(rect.height);
|
|
640
|
+
if (x === undefined || y === undefined || width === undefined || height === undefined) {
|
|
641
|
+
return undefined;
|
|
642
|
+
}
|
|
643
|
+
const approxTwips = record(rect.approxTwips);
|
|
644
|
+
const normalizedApproxTwips = {
|
|
645
|
+
x: numberValue(approxTwips.x),
|
|
646
|
+
y: numberValue(approxTwips.y),
|
|
647
|
+
width: numberValue(approxTwips.width),
|
|
648
|
+
height: numberValue(approxTwips.height),
|
|
649
|
+
unit: stringValue(approxTwips.unit),
|
|
650
|
+
};
|
|
651
|
+
const hasApproxTwips = Object.values(normalizedApproxTwips).some(
|
|
652
|
+
(value) => value !== undefined,
|
|
653
|
+
);
|
|
654
|
+
return {
|
|
655
|
+
x,
|
|
656
|
+
y,
|
|
657
|
+
width,
|
|
658
|
+
height,
|
|
659
|
+
unit: stringValue(rect.unit) ?? "screenPx",
|
|
660
|
+
approxTwips: hasApproxTwips ? normalizedApproxTwips : undefined,
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function normalizeTwipsRect(raw: unknown):
|
|
665
|
+
| {
|
|
666
|
+
readonly xTwips?: number;
|
|
667
|
+
readonly yTwips?: number;
|
|
668
|
+
readonly widthTwips?: number;
|
|
669
|
+
readonly heightTwips?: number;
|
|
670
|
+
}
|
|
671
|
+
| undefined {
|
|
672
|
+
const rect = record(raw);
|
|
673
|
+
const normalized = {
|
|
674
|
+
xTwips: numberValue(rect.xTwips),
|
|
675
|
+
yTwips: numberValue(rect.yTwips),
|
|
676
|
+
widthTwips: numberValue(rect.widthTwips),
|
|
677
|
+
heightTwips: numberValue(rect.heightTwips),
|
|
678
|
+
};
|
|
679
|
+
return Object.values(normalized).some((value) => value !== undefined)
|
|
680
|
+
? normalized
|
|
681
|
+
: undefined;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function normalizePageSpan(
|
|
685
|
+
...candidates: readonly Record<string, unknown>[]
|
|
686
|
+
):
|
|
687
|
+
| {
|
|
688
|
+
readonly startPage?: number | null;
|
|
689
|
+
readonly endPage?: number | null;
|
|
690
|
+
}
|
|
691
|
+
| undefined {
|
|
692
|
+
for (const candidate of candidates) {
|
|
693
|
+
const startPage = nullableNumberValue(candidate.startPage);
|
|
694
|
+
const endPage = nullableNumberValue(candidate.endPage);
|
|
695
|
+
if (startPage !== undefined || endPage !== undefined) {
|
|
696
|
+
return { startPage, endPage };
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
return undefined;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
function normalizeWordPageSpanToPageIndexSpan(
|
|
703
|
+
span: AdjacentGeometryPageSpan | undefined,
|
|
704
|
+
): AdjacentGeometryPageSpan | undefined {
|
|
705
|
+
if (!span || (span.startPage == null && span.endPage == null)) return undefined;
|
|
706
|
+
return {
|
|
707
|
+
startPage: span.startPage == null ? span.startPage : span.startPage - 1,
|
|
708
|
+
endPage: span.endPage == null ? span.endPage : span.endPage - 1,
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function classifyPageSpan(
|
|
713
|
+
normalizedExpected: AdjacentGeometryPageSpan | undefined,
|
|
714
|
+
runtime: AdjacentGeometryPageSpan | undefined,
|
|
715
|
+
): AdjacentGeometryPageLocalFieldGeometry["pageSpanStatus"] {
|
|
716
|
+
if (
|
|
717
|
+
!normalizedExpected ||
|
|
718
|
+
(normalizedExpected.startPage == null && normalizedExpected.endPage == null)
|
|
719
|
+
) {
|
|
720
|
+
return "expected-missing";
|
|
721
|
+
}
|
|
722
|
+
if (!runtime || (runtime.startPage == null && runtime.endPage == null)) {
|
|
723
|
+
return "runtime-missing";
|
|
724
|
+
}
|
|
725
|
+
if (
|
|
726
|
+
normalizedExpected.startPage === runtime.startPage &&
|
|
727
|
+
normalizedExpected.endPage === runtime.endPage
|
|
728
|
+
) {
|
|
729
|
+
return "matches-runtime";
|
|
730
|
+
}
|
|
731
|
+
if (
|
|
732
|
+
normalizedExpected.startPage != null &&
|
|
733
|
+
normalizedExpected.endPage != null &&
|
|
734
|
+
runtime.startPage != null &&
|
|
735
|
+
runtime.endPage != null &&
|
|
736
|
+
normalizedExpected.startPage >= runtime.startPage &&
|
|
737
|
+
normalizedExpected.endPage <= runtime.endPage
|
|
738
|
+
) {
|
|
739
|
+
return "contained-in-runtime";
|
|
740
|
+
}
|
|
741
|
+
return "differs-from-runtime";
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function normalizeWordPlacement(raw: Record<string, unknown>):
|
|
745
|
+
| AdjacentGeometryFieldRegionRowSummary["wordPlacement"]
|
|
746
|
+
| undefined {
|
|
747
|
+
const startXYTwips = record(raw.startXYTwips);
|
|
748
|
+
const endXYTwips = record(raw.endXYTwips);
|
|
749
|
+
const normalized = {
|
|
750
|
+
startPage: numberValue(raw.startPage),
|
|
751
|
+
endPage: numberValue(raw.endPage),
|
|
752
|
+
startXYTwips: {
|
|
753
|
+
x: numberValue(startXYTwips.x),
|
|
754
|
+
y: numberValue(startXYTwips.y),
|
|
755
|
+
},
|
|
756
|
+
endXYTwips: {
|
|
757
|
+
x: numberValue(endXYTwips.x),
|
|
758
|
+
y: numberValue(endXYTwips.y),
|
|
759
|
+
},
|
|
760
|
+
};
|
|
761
|
+
const hasStart = Object.values(normalized.startXYTwips).some(
|
|
762
|
+
(value) => value !== undefined,
|
|
763
|
+
);
|
|
764
|
+
const hasEnd = Object.values(normalized.endXYTwips).some(
|
|
765
|
+
(value) => value !== undefined,
|
|
766
|
+
);
|
|
767
|
+
if (
|
|
768
|
+
normalized.startPage === undefined &&
|
|
769
|
+
normalized.endPage === undefined &&
|
|
770
|
+
!hasStart &&
|
|
771
|
+
!hasEnd
|
|
772
|
+
) {
|
|
773
|
+
return undefined;
|
|
774
|
+
}
|
|
775
|
+
return {
|
|
776
|
+
startPage: normalized.startPage,
|
|
777
|
+
endPage: normalized.endPage,
|
|
778
|
+
startXYTwips: hasStart ? normalized.startXYTwips : undefined,
|
|
779
|
+
endXYTwips: hasEnd ? normalized.endXYTwips : undefined,
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function fieldKey(docId: string | undefined, ordinal: number | undefined): string | undefined {
|
|
784
|
+
return docId && ordinal !== undefined ? `${docId}\0${ordinal}` : undefined;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function fieldRuntimeKey(
|
|
788
|
+
docId: string | undefined,
|
|
789
|
+
runtimeFieldRegionId: string | undefined,
|
|
790
|
+
): string | undefined {
|
|
791
|
+
return docId && runtimeFieldRegionId ? `${docId}\0${runtimeFieldRegionId}` : undefined;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function numberingKey(docId: string | undefined, ordinal: number | undefined):
|
|
795
|
+
| string
|
|
796
|
+
| undefined {
|
|
797
|
+
return docId && ordinal !== undefined ? `${docId}\0${ordinal}` : undefined;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
function isRect(value: AdjacentGeometryRect | undefined): value is AdjacentGeometryRect {
|
|
801
|
+
return value !== undefined;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function record(value: unknown): Record<string, unknown> {
|
|
805
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
806
|
+
? value as Record<string, unknown>
|
|
807
|
+
: {};
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
function array(value: unknown): readonly unknown[] {
|
|
811
|
+
return Array.isArray(value) ? value : [];
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function stringValue(value: unknown): string | undefined {
|
|
815
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
function numberValue(value: unknown): number | undefined {
|
|
819
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
function nullableNumberValue(value: unknown): number | null | undefined {
|
|
823
|
+
return value === null ? null : numberValue(value);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function compareOptionalNumber(a: number | undefined, b: number | undefined): number {
|
|
827
|
+
if (a === undefined && b === undefined) return 0;
|
|
828
|
+
if (a === undefined) return 1;
|
|
829
|
+
if (b === undefined) return -1;
|
|
830
|
+
return a - b;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function sum<T>(items: readonly T[], read: (item: T) => number): number {
|
|
834
|
+
return items.reduce((total, item) => total + read(item), 0);
|
|
835
|
+
}
|