@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
|
@@ -24,14 +24,22 @@ import type {
|
|
|
24
24
|
EditorSurfaceSnapshot,
|
|
25
25
|
SurfaceBlockSnapshot,
|
|
26
26
|
} from "../../api/public-types";
|
|
27
|
+
import type {
|
|
28
|
+
CanonicalFieldRegionIdentity,
|
|
29
|
+
} from "../../model/canonical-layout-inputs.ts";
|
|
27
30
|
import type { RuntimeBlockFragment } from "./page-graph.ts";
|
|
28
|
-
import type {
|
|
31
|
+
import type {
|
|
32
|
+
RuntimeFieldRegionLayoutFacts,
|
|
33
|
+
RuntimeLineBox,
|
|
34
|
+
RuntimeNumberingLayoutFacts,
|
|
35
|
+
} from "../../model/layout/page-graph-types.ts";
|
|
29
36
|
import type {
|
|
30
37
|
BlockSplits,
|
|
31
38
|
FragmentMeasurement,
|
|
32
39
|
ParagraphLineSlice,
|
|
33
40
|
TableRowSlice,
|
|
34
41
|
} from "./paginated-layout-engine.ts";
|
|
42
|
+
import { collectSplitRowCarryForPage } from "./table-row-continuation-contract.ts";
|
|
35
43
|
|
|
36
44
|
type FragmentWithoutPageId = Omit<RuntimeBlockFragment, "pageId">;
|
|
37
45
|
|
|
@@ -41,9 +49,11 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
41
49
|
splits?: BlockSplits,
|
|
42
50
|
columnByBlockIdByPageIndex?: ReadonlyMap<number, ReadonlyMap<string, number>>,
|
|
43
51
|
fragmentMeasurementsByPageIndex?: ReadonlyMap<number, ReadonlyMap<string, FragmentMeasurement>>,
|
|
52
|
+
fieldRegions: readonly CanonicalFieldRegionIdentity[] = [],
|
|
44
53
|
): Map<number, FragmentWithoutPageId[]> {
|
|
45
54
|
const byPage = new Map<number, FragmentWithoutPageId[]>();
|
|
46
55
|
const perPageCounter = new Map<number, number>();
|
|
56
|
+
const fieldRegionsByParagraphIndex = buildFieldRegionsByParagraphIndex(fieldRegions);
|
|
47
57
|
|
|
48
58
|
const pushFragment = (
|
|
49
59
|
pageIndex: number,
|
|
@@ -74,7 +84,9 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
74
84
|
fragmentMeasurementsByPageIndex?.get(pageIndex)?.get(blockId)?.heightTwips ??
|
|
75
85
|
fallback;
|
|
76
86
|
|
|
77
|
-
for (
|
|
87
|
+
for (let blockIndex = 0; blockIndex < surface.blocks.length; blockIndex += 1) {
|
|
88
|
+
const block = surface.blocks[blockIndex]!;
|
|
89
|
+
const blockPath = `main/block[${blockIndex}]`;
|
|
78
90
|
// R3: table split across pages — emit one fragment per row slice.
|
|
79
91
|
// Consumers read `tableRowRange` and prepend header rows when from > 0.
|
|
80
92
|
if (block.kind === "table") {
|
|
@@ -93,9 +105,11 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
93
105
|
? { columnIndex: fragment.columnIndex }
|
|
94
106
|
: columnIndex !== undefined
|
|
95
107
|
? { columnIndex }
|
|
96
|
-
|
|
108
|
+
: {}),
|
|
97
109
|
});
|
|
98
110
|
},
|
|
111
|
+
fieldRegionsByParagraphIndex,
|
|
112
|
+
blockPath,
|
|
99
113
|
);
|
|
100
114
|
continue;
|
|
101
115
|
}
|
|
@@ -116,6 +130,8 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
116
130
|
...(columnIndex !== undefined ? { columnIndex } : {}),
|
|
117
131
|
});
|
|
118
132
|
},
|
|
133
|
+
fieldRegionsByParagraphIndex,
|
|
134
|
+
blockPath,
|
|
119
135
|
);
|
|
120
136
|
continue;
|
|
121
137
|
}
|
|
@@ -126,6 +142,14 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
126
142
|
if (pageIndex === null) continue;
|
|
127
143
|
|
|
128
144
|
const columnIndex = columnIndexFor(pageIndex, block.blockId);
|
|
145
|
+
const heightTwips = measuredHeightFor(
|
|
146
|
+
pageIndex,
|
|
147
|
+
block.blockId,
|
|
148
|
+
estimateBlockHeightFromSpan(block),
|
|
149
|
+
);
|
|
150
|
+
const widthTwips = fragmentMeasurementsByPageIndex
|
|
151
|
+
?.get(pageIndex)
|
|
152
|
+
?.get(block.blockId)?.widthTwips;
|
|
129
153
|
const fragment: FragmentWithoutPageId = {
|
|
130
154
|
fragmentId: `fragment-${block.blockId}`,
|
|
131
155
|
blockId: block.blockId,
|
|
@@ -133,13 +157,18 @@ export function projectSurfaceBlocksToPageFragments(
|
|
|
133
157
|
regionKind: "body",
|
|
134
158
|
from: block.from,
|
|
135
159
|
to: block.to,
|
|
136
|
-
heightTwips
|
|
137
|
-
pageIndex,
|
|
138
|
-
block.blockId,
|
|
139
|
-
estimateBlockHeightFromSpan(block),
|
|
140
|
-
),
|
|
160
|
+
heightTwips,
|
|
141
161
|
...deriveStyleMetadata(block),
|
|
142
162
|
kind: "whole",
|
|
163
|
+
layoutObject: buildFragmentLayoutObject({
|
|
164
|
+
block,
|
|
165
|
+
fragmentId: `fragment-${block.blockId}`,
|
|
166
|
+
heightTwips,
|
|
167
|
+
widthTwips,
|
|
168
|
+
paginationRole: "whole",
|
|
169
|
+
fieldRegionsByParagraphIndex,
|
|
170
|
+
blockPath,
|
|
171
|
+
}),
|
|
143
172
|
...(columnIndex !== undefined ? { columnIndex } : {}),
|
|
144
173
|
};
|
|
145
174
|
|
|
@@ -221,9 +250,12 @@ function emitSlicedParagraph(
|
|
|
221
250
|
block: SurfaceBlockSnapshot,
|
|
222
251
|
slices: readonly ParagraphLineSlice[],
|
|
223
252
|
emit: (pageIndex: number, fragment: FragmentWithoutPageId) => void,
|
|
253
|
+
fieldRegionsByParagraphIndex: ReadonlyMap<number, readonly CanonicalFieldRegionIdentity[]> = new Map(),
|
|
254
|
+
blockPath?: string,
|
|
224
255
|
): void {
|
|
225
256
|
for (let i = 0; i < slices.length; i += 1) {
|
|
226
257
|
const slice = slices[i]!;
|
|
258
|
+
const heightTwips = slice.heightTwips ?? estimateSliceHeightFromLines(slice.lineRange);
|
|
227
259
|
const fragment: FragmentWithoutPageId = {
|
|
228
260
|
fragmentId: `fragment-${block.blockId}-slice-${i}`,
|
|
229
261
|
blockId: block.blockId,
|
|
@@ -231,11 +263,20 @@ function emitSlicedParagraph(
|
|
|
231
263
|
regionKind: "body",
|
|
232
264
|
from: block.from,
|
|
233
265
|
to: block.to,
|
|
234
|
-
heightTwips
|
|
266
|
+
heightTwips,
|
|
235
267
|
...deriveStyleMetadata(block),
|
|
236
268
|
kind: "paragraph-slice",
|
|
237
269
|
paragraphLineRange: slice.lineRange,
|
|
238
270
|
continuation: buildParagraphContinuationCursor(slice, i, slices.length),
|
|
271
|
+
layoutObject: buildFragmentLayoutObject({
|
|
272
|
+
block,
|
|
273
|
+
fragmentId: `fragment-${block.blockId}-slice-${i}`,
|
|
274
|
+
heightTwips,
|
|
275
|
+
widthTwips: slice.widthTwips,
|
|
276
|
+
paginationRole: slice.lineRange.from > 0 ? "continuation" : "slice",
|
|
277
|
+
fieldRegionsByParagraphIndex,
|
|
278
|
+
blockPath,
|
|
279
|
+
}),
|
|
239
280
|
};
|
|
240
281
|
emit(slice.pageIndex, fragment);
|
|
241
282
|
}
|
|
@@ -278,9 +319,12 @@ function emitSlicedTable(
|
|
|
278
319
|
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
279
320
|
slices: readonly TableRowSlice[],
|
|
280
321
|
emit: (pageIndex: number, fragment: FragmentWithoutPageId) => void,
|
|
322
|
+
fieldRegionsByParagraphIndex: ReadonlyMap<number, readonly CanonicalFieldRegionIdentity[]> = new Map(),
|
|
323
|
+
blockPath?: string,
|
|
281
324
|
): void {
|
|
282
325
|
for (let i = 0; i < slices.length; i += 1) {
|
|
283
326
|
const slice = slices[i]!;
|
|
327
|
+
const heightTwips = slice.heightTwips ?? estimateSliceHeightFromRows(slice.rowRange);
|
|
284
328
|
const fragment: FragmentWithoutPageId = {
|
|
285
329
|
fragmentId: `fragment-${block.blockId}-rowslice-${i}`,
|
|
286
330
|
blockId: block.blockId,
|
|
@@ -288,11 +332,19 @@ function emitSlicedTable(
|
|
|
288
332
|
regionKind: "body",
|
|
289
333
|
from: block.from,
|
|
290
334
|
to: block.to,
|
|
291
|
-
heightTwips
|
|
335
|
+
heightTwips,
|
|
292
336
|
...deriveStyleMetadata(block),
|
|
293
337
|
kind: "table-slice",
|
|
294
338
|
tableRowRange: slice.rowRange,
|
|
295
|
-
continuation: buildTableContinuationCursor(block,
|
|
339
|
+
continuation: buildTableContinuationCursor(block, slices, i),
|
|
340
|
+
layoutObject: buildFragmentLayoutObject({
|
|
341
|
+
block,
|
|
342
|
+
fragmentId: `fragment-${block.blockId}-rowslice-${i}`,
|
|
343
|
+
heightTwips,
|
|
344
|
+
paginationRole: slice.rowRange.from > 0 ? "continuation" : "slice",
|
|
345
|
+
fieldRegionsByParagraphIndex,
|
|
346
|
+
blockPath,
|
|
347
|
+
}),
|
|
296
348
|
...(slice.columnIndex !== undefined ? { columnIndex: slice.columnIndex } : {}),
|
|
297
349
|
};
|
|
298
350
|
emit(slice.pageIndex, fragment);
|
|
@@ -301,14 +353,15 @@ function emitSlicedTable(
|
|
|
301
353
|
|
|
302
354
|
function buildTableContinuationCursor(
|
|
303
355
|
block: Extract<SurfaceBlockSnapshot, { kind: "table" }>,
|
|
304
|
-
|
|
356
|
+
slices: readonly TableRowSlice[],
|
|
305
357
|
sequenceIndex: number,
|
|
306
|
-
sliceCount: number,
|
|
307
358
|
): NonNullable<RuntimeBlockFragment["continuation"]> {
|
|
359
|
+
const slice = slices[sequenceIndex]!;
|
|
360
|
+
const splitRowCarry = collectSplitRowCarryForPage(slices, sequenceIndex);
|
|
308
361
|
return {
|
|
309
362
|
kind: "table",
|
|
310
363
|
sequenceIndex,
|
|
311
|
-
sliceCount,
|
|
364
|
+
sliceCount: slices.length,
|
|
312
365
|
rowRange: slice.rowRange,
|
|
313
366
|
continuesFromPreviousPage: slice.rowRange.from > 0,
|
|
314
367
|
continuesToNextPage: slice.rowRange.to < slice.rowRange.totalRows,
|
|
@@ -316,6 +369,7 @@ function buildTableContinuationCursor(
|
|
|
316
369
|
slice.rowRange.from > 0
|
|
317
370
|
? collectRepeatedHeaderRowIndexes(block, slice.rowRange.from)
|
|
318
371
|
: [],
|
|
372
|
+
...(splitRowCarry.length > 0 ? { splitRowCarry } : {}),
|
|
319
373
|
verticalMergeCarry: collectVerticalMergeCarry(block, slice.rowRange.from),
|
|
320
374
|
};
|
|
321
375
|
}
|
|
@@ -391,6 +445,289 @@ function estimateSliceHeightFromRows(rowRange: {
|
|
|
391
445
|
return rows * 360; // ~1 line + padding per row, approximate
|
|
392
446
|
}
|
|
393
447
|
|
|
448
|
+
function buildFragmentLayoutObject(input: {
|
|
449
|
+
block: SurfaceBlockSnapshot;
|
|
450
|
+
fragmentId: string;
|
|
451
|
+
heightTwips: number;
|
|
452
|
+
widthTwips?: number;
|
|
453
|
+
paginationRole: NonNullable<RuntimeBlockFragment["layoutObject"]>["paginationRole"];
|
|
454
|
+
fieldRegionsByParagraphIndex?: ReadonlyMap<number, readonly CanonicalFieldRegionIdentity[]>;
|
|
455
|
+
blockPath?: string;
|
|
456
|
+
}): NonNullable<RuntimeBlockFragment["layoutObject"]> {
|
|
457
|
+
const fieldFamilies = collectFieldFamilies(input.block);
|
|
458
|
+
const kind = resolveFragmentLayoutObjectKind(input.block, fieldFamilies);
|
|
459
|
+
const numberingRows = collectNumberingLayoutFactsForBlock(input.block, input.blockPath);
|
|
460
|
+
const numbering = input.block.kind === "paragraph" ? numberingRows[0] : undefined;
|
|
461
|
+
const fieldRegions = collectFieldRegionLayoutFacts(
|
|
462
|
+
input.block,
|
|
463
|
+
input.fragmentId,
|
|
464
|
+
input.fieldRegionsByParagraphIndex,
|
|
465
|
+
);
|
|
466
|
+
return {
|
|
467
|
+
objectId: `${kind}:${input.fragmentId}`,
|
|
468
|
+
kind,
|
|
469
|
+
sourceBlockId: input.block.blockId,
|
|
470
|
+
paginationRole: input.paginationRole,
|
|
471
|
+
measuredExtentTwips: {
|
|
472
|
+
heightTwips: Math.max(0, input.heightTwips),
|
|
473
|
+
...(input.widthTwips !== undefined
|
|
474
|
+
? { widthTwips: Math.max(0, input.widthTwips) }
|
|
475
|
+
: {}),
|
|
476
|
+
},
|
|
477
|
+
...(fieldFamilies.length > 0 ? { fieldFamilies } : {}),
|
|
478
|
+
...(fieldRegions.length > 0 ? { fieldRegions } : {}),
|
|
479
|
+
...(numbering ? { numbering } : {}),
|
|
480
|
+
...(numberingRows.length > 0 ? { numberingRows } : {}),
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function resolveFragmentLayoutObjectKind(
|
|
485
|
+
block: SurfaceBlockSnapshot,
|
|
486
|
+
fieldFamilies: readonly string[],
|
|
487
|
+
): NonNullable<RuntimeBlockFragment["layoutObject"]>["kind"] {
|
|
488
|
+
switch (block.kind) {
|
|
489
|
+
case "paragraph":
|
|
490
|
+
if (fieldFamilies.length > 0) return "field-region";
|
|
491
|
+
return block.numbering ? "numbered-paragraph" : "paragraph";
|
|
492
|
+
case "table":
|
|
493
|
+
return "table";
|
|
494
|
+
case "sdt_block":
|
|
495
|
+
return "sdt-block";
|
|
496
|
+
case "opaque_block":
|
|
497
|
+
return "opaque-block";
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function collectFieldFamilies(block: SurfaceBlockSnapshot): string[] {
|
|
502
|
+
if (block.kind !== "paragraph") return [];
|
|
503
|
+
const families: string[] = [];
|
|
504
|
+
const seen = new Set<string>();
|
|
505
|
+
for (const segment of block.segments) {
|
|
506
|
+
if (segment.kind !== "field_ref" || seen.has(segment.fieldFamily)) continue;
|
|
507
|
+
seen.add(segment.fieldFamily);
|
|
508
|
+
families.push(segment.fieldFamily);
|
|
509
|
+
}
|
|
510
|
+
return families;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function buildFieldRegionsByParagraphIndex(
|
|
514
|
+
regions: readonly CanonicalFieldRegionIdentity[],
|
|
515
|
+
): Map<number, CanonicalFieldRegionIdentity[]> {
|
|
516
|
+
const byParagraph = new Map<number, CanonicalFieldRegionIdentity[]>();
|
|
517
|
+
for (const region of regions) {
|
|
518
|
+
const bucket = byParagraph.get(region.paragraphIndex);
|
|
519
|
+
if (bucket) bucket.push(region);
|
|
520
|
+
else byParagraph.set(region.paragraphIndex, [region]);
|
|
521
|
+
}
|
|
522
|
+
return byParagraph;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function collectFieldRegionLayoutFacts(
|
|
526
|
+
block: SurfaceBlockSnapshot,
|
|
527
|
+
fragmentId: string,
|
|
528
|
+
fieldRegionsByParagraphIndex:
|
|
529
|
+
| ReadonlyMap<number, readonly CanonicalFieldRegionIdentity[]>
|
|
530
|
+
| undefined,
|
|
531
|
+
): RuntimeFieldRegionLayoutFacts[] {
|
|
532
|
+
if (!fieldRegionsByParagraphIndex || fieldRegionsByParagraphIndex.size === 0) {
|
|
533
|
+
return [];
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
const paragraphIndexes = collectParagraphIndexesForBlock(block);
|
|
537
|
+
if (paragraphIndexes.length === 0) return [];
|
|
538
|
+
|
|
539
|
+
const facts: RuntimeFieldRegionLayoutFacts[] = [];
|
|
540
|
+
const seen = new Set<string>();
|
|
541
|
+
for (const paragraphIndex of paragraphIndexes) {
|
|
542
|
+
for (const region of fieldRegionsByParagraphIndex.get(paragraphIndex) ?? []) {
|
|
543
|
+
const fieldRegionId = `field-region:${region.canonicalFieldId}`;
|
|
544
|
+
const key = `${fieldRegionId}:${fragmentId}`;
|
|
545
|
+
if (seen.has(key)) continue;
|
|
546
|
+
seen.add(key);
|
|
547
|
+
facts.push(toRuntimeFieldRegionLayoutFacts(region, fieldRegionId));
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return facts;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function collectParagraphIndexesForBlock(block: SurfaceBlockSnapshot): number[] {
|
|
554
|
+
const indexes: number[] = [];
|
|
555
|
+
visitParagraphBlocks(block, (paragraph) => {
|
|
556
|
+
const index = parseParagraphBlockIndex(paragraph.blockId);
|
|
557
|
+
if (index !== undefined) indexes.push(index);
|
|
558
|
+
});
|
|
559
|
+
return indexes;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function visitParagraphBlocks(
|
|
563
|
+
block: SurfaceBlockSnapshot,
|
|
564
|
+
visit: (
|
|
565
|
+
paragraph: Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>,
|
|
566
|
+
context: { readonly path?: string },
|
|
567
|
+
) => void,
|
|
568
|
+
path?: string,
|
|
569
|
+
): void {
|
|
570
|
+
switch (block.kind) {
|
|
571
|
+
case "paragraph":
|
|
572
|
+
visit(block, path !== undefined ? { path } : {});
|
|
573
|
+
return;
|
|
574
|
+
case "table":
|
|
575
|
+
for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
|
|
576
|
+
const row = block.rows[rowIndex]!;
|
|
577
|
+
for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex += 1) {
|
|
578
|
+
const cell = row.cells[cellIndex]!;
|
|
579
|
+
for (let childIndex = 0; childIndex < cell.content.length; childIndex += 1) {
|
|
580
|
+
const child = cell.content[childIndex]!;
|
|
581
|
+
visitParagraphBlocks(
|
|
582
|
+
child,
|
|
583
|
+
visit,
|
|
584
|
+
path !== undefined
|
|
585
|
+
? `${path}/row[${rowIndex}]/cell[${cellIndex}]/block[${childIndex}]`
|
|
586
|
+
: undefined,
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return;
|
|
592
|
+
case "sdt_block":
|
|
593
|
+
for (let childIndex = 0; childIndex < block.children.length; childIndex += 1) {
|
|
594
|
+
const child = block.children[childIndex]!;
|
|
595
|
+
visitParagraphBlocks(
|
|
596
|
+
child,
|
|
597
|
+
visit,
|
|
598
|
+
path !== undefined ? `${path}/block[${childIndex}]` : undefined,
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
return;
|
|
602
|
+
case "opaque_block":
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function parseParagraphBlockIndex(blockId: string): number | undefined {
|
|
608
|
+
const match = /^paragraph-(\d+)$/.exec(blockId);
|
|
609
|
+
return match ? Number(match[1]) : undefined;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
function toRuntimeFieldRegionLayoutFacts(
|
|
613
|
+
region: CanonicalFieldRegionIdentity,
|
|
614
|
+
fieldRegionId: string,
|
|
615
|
+
): RuntimeFieldRegionLayoutFacts {
|
|
616
|
+
return {
|
|
617
|
+
fieldRegionId,
|
|
618
|
+
regionId: region.regionId,
|
|
619
|
+
canonicalFieldId: region.canonicalFieldId,
|
|
620
|
+
regionKind: region.kind,
|
|
621
|
+
storyKey: region.storyKey,
|
|
622
|
+
fieldIndex: region.fieldIndex,
|
|
623
|
+
paragraphIndex: region.paragraphIndex,
|
|
624
|
+
fieldFamily: region.fieldFamily,
|
|
625
|
+
refreshStatus: region.refreshStatus,
|
|
626
|
+
...(region.sourceRef !== undefined ? { sourceRef: { ...region.sourceRef } } : {}),
|
|
627
|
+
...(region.fieldEvidence !== undefined
|
|
628
|
+
? {
|
|
629
|
+
fieldEvidence: {
|
|
630
|
+
...region.fieldEvidence,
|
|
631
|
+
...(region.fieldEvidence.sourceRef !== undefined
|
|
632
|
+
? { sourceRef: { ...region.fieldEvidence.sourceRef } }
|
|
633
|
+
: {}),
|
|
634
|
+
},
|
|
635
|
+
}
|
|
636
|
+
: {}),
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function collectNumberingLayoutFacts(
|
|
641
|
+
block: SurfaceBlockSnapshot,
|
|
642
|
+
): RuntimeNumberingLayoutFacts | undefined {
|
|
643
|
+
if (block.kind !== "paragraph") return undefined;
|
|
644
|
+
if (!block.numbering && !block.resolvedNumbering && block.numberingPrefix === undefined) {
|
|
645
|
+
return undefined;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const markerLane = block.resolvedNumbering?.geometry.markerLane;
|
|
649
|
+
const textColumn = block.resolvedNumbering?.geometry.textColumn;
|
|
650
|
+
const tabStops = block.resolvedNumbering?.geometry.tabStops;
|
|
651
|
+
return {
|
|
652
|
+
...(block.numbering?.numberingInstanceId !== undefined
|
|
653
|
+
? { numberingInstanceId: block.numbering.numberingInstanceId }
|
|
654
|
+
: {}),
|
|
655
|
+
...(block.numbering?.level !== undefined ? { level: block.numbering.level } : {}),
|
|
656
|
+
...(block.resolvedNumbering?.format !== undefined
|
|
657
|
+
? { format: block.resolvedNumbering.format }
|
|
658
|
+
: {}),
|
|
659
|
+
...(block.numberingPrefix !== undefined ? { markerText: block.numberingPrefix } : {}),
|
|
660
|
+
...(block.numberingSuffix !== undefined ? { markerSuffix: block.numberingSuffix } : {}),
|
|
661
|
+
...(block.resolvedNumbering?.geometry.markerJustification !== undefined
|
|
662
|
+
? { markerJustification: block.resolvedNumbering.geometry.markerJustification }
|
|
663
|
+
: {}),
|
|
664
|
+
...(markerLane
|
|
665
|
+
? {
|
|
666
|
+
markerLane: {
|
|
667
|
+
startTwips: markerLane.start,
|
|
668
|
+
widthTwips: markerLane.width,
|
|
669
|
+
textStartTwips: markerLane.textStart,
|
|
670
|
+
},
|
|
671
|
+
}
|
|
672
|
+
: {}),
|
|
673
|
+
...(textColumn
|
|
674
|
+
? {
|
|
675
|
+
textColumn: {
|
|
676
|
+
startTwips: textColumn.start,
|
|
677
|
+
...(textColumn.right !== undefined ? { rightTwips: textColumn.right } : {}),
|
|
678
|
+
...(textColumn.firstLine !== undefined
|
|
679
|
+
? { firstLineTwips: textColumn.firstLine }
|
|
680
|
+
: {}),
|
|
681
|
+
...(textColumn.hanging !== undefined ? { hangingTwips: textColumn.hanging } : {}),
|
|
682
|
+
},
|
|
683
|
+
}
|
|
684
|
+
: {}),
|
|
685
|
+
...(tabStops && tabStops.length > 0
|
|
686
|
+
? {
|
|
687
|
+
tabStops: tabStops.map((tab) => ({
|
|
688
|
+
positionTwips: tab.pos,
|
|
689
|
+
...(tab.val !== undefined ? { align: tab.val } : {}),
|
|
690
|
+
...(tab.leader !== undefined ? { leader: tab.leader } : {}),
|
|
691
|
+
})),
|
|
692
|
+
}
|
|
693
|
+
: {}),
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function collectNumberingLayoutFactsForBlock(
|
|
698
|
+
block: SurfaceBlockSnapshot,
|
|
699
|
+
blockPath?: string,
|
|
700
|
+
): RuntimeNumberingLayoutFacts[] {
|
|
701
|
+
const rows: RuntimeNumberingLayoutFacts[] = [];
|
|
702
|
+
const seen = new Set<string>();
|
|
703
|
+
visitParagraphBlocks(block, (paragraph, context) => {
|
|
704
|
+
const numbering = collectNumberingLayoutFacts(paragraph);
|
|
705
|
+
if (!numbering) return;
|
|
706
|
+
const paragraphIndex = parseParagraphBlockIndex(paragraph.blockId);
|
|
707
|
+
const numberingKey =
|
|
708
|
+
context.path !== undefined ? `main:${context.path}:numbering` : undefined;
|
|
709
|
+
const numberingLayoutId =
|
|
710
|
+
numberingKey ??
|
|
711
|
+
[
|
|
712
|
+
"numbering",
|
|
713
|
+
paragraph.blockId,
|
|
714
|
+
numbering.numberingInstanceId ?? "unknown-instance",
|
|
715
|
+
numbering.level ?? "unknown-level",
|
|
716
|
+
].join(":");
|
|
717
|
+
if (seen.has(numberingLayoutId)) return;
|
|
718
|
+
seen.add(numberingLayoutId);
|
|
719
|
+
rows.push({
|
|
720
|
+
numberingLayoutId,
|
|
721
|
+
...(numberingKey !== undefined ? { numberingKey } : {}),
|
|
722
|
+
...(context.path !== undefined ? { sourceBlockPath: context.path } : {}),
|
|
723
|
+
sourceBlockId: paragraph.blockId,
|
|
724
|
+
...(paragraphIndex !== undefined ? { paragraphIndex } : {}),
|
|
725
|
+
...numbering,
|
|
726
|
+
});
|
|
727
|
+
}, blockPath);
|
|
728
|
+
return rows;
|
|
729
|
+
}
|
|
730
|
+
|
|
394
731
|
function findPageIndexForOffset(
|
|
395
732
|
pages: readonly DocumentPageSnapshot[],
|
|
396
733
|
offset: number,
|