@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
|
@@ -9,6 +9,157 @@
|
|
|
9
9
|
import type { RuntimeApiHandle } from "../_runtime-handle.ts";
|
|
10
10
|
import type { ApiV3FnMetadata, MockPayload } from "../_layer-metadata.ts";
|
|
11
11
|
import { mockPayload } from "../_mocks.ts";
|
|
12
|
+
import type {
|
|
13
|
+
PublicPageFrame,
|
|
14
|
+
PublicPageLocalStoryInstance,
|
|
15
|
+
PublicPageNode,
|
|
16
|
+
PublicPageRegion,
|
|
17
|
+
PublicResolvedStoryField,
|
|
18
|
+
PublicStoryAnchoredObject,
|
|
19
|
+
} from "../../../runtime/layout/public-facet.ts";
|
|
20
|
+
|
|
21
|
+
export interface V3TwipsRect {
|
|
22
|
+
readonly xTwips: number;
|
|
23
|
+
readonly yTwips: number;
|
|
24
|
+
readonly widthTwips: number;
|
|
25
|
+
readonly heightTwips: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface V3PageFrameRegion {
|
|
29
|
+
readonly kind: "body" | "header" | "footer" | "column" | "footnote-area";
|
|
30
|
+
readonly rectTwips: V3TwipsRect;
|
|
31
|
+
readonly fragmentCount: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type V3PageFrameCompleteness = PublicPageFrame["completeness"];
|
|
35
|
+
|
|
36
|
+
export interface V3PageFrame {
|
|
37
|
+
readonly frameId: string;
|
|
38
|
+
readonly pageId: string;
|
|
39
|
+
readonly pageIndex: number;
|
|
40
|
+
readonly sectionIndex: number;
|
|
41
|
+
readonly displayPageNumber: number;
|
|
42
|
+
readonly completeness: V3PageFrameCompleteness;
|
|
43
|
+
readonly physicalBoundsTwips: V3TwipsRect;
|
|
44
|
+
readonly divergenceIds: readonly string[];
|
|
45
|
+
readonly exclusionZoneCount: number;
|
|
46
|
+
readonly regions: readonly V3PageFrameRegion[];
|
|
47
|
+
readonly signature: string;
|
|
48
|
+
readonly source: "layout-public-frame" | "layout-public-facet-fallback";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface V3PageLocalStoryObject {
|
|
52
|
+
readonly objectId: string;
|
|
53
|
+
readonly sourceType:
|
|
54
|
+
| "image"
|
|
55
|
+
| "drawing-frame"
|
|
56
|
+
| "chart-preview"
|
|
57
|
+
| "smartart-preview"
|
|
58
|
+
| "shape"
|
|
59
|
+
| "wordart"
|
|
60
|
+
| "vml-shape"
|
|
61
|
+
| "ole-embed"
|
|
62
|
+
| "opaque-inline";
|
|
63
|
+
readonly display: "inline" | "floating" | "unknown";
|
|
64
|
+
readonly extentTwips?: {
|
|
65
|
+
readonly widthTwips: number;
|
|
66
|
+
readonly heightTwips: number;
|
|
67
|
+
};
|
|
68
|
+
readonly relationshipIds?: readonly string[];
|
|
69
|
+
readonly mediaIds?: readonly string[];
|
|
70
|
+
readonly preserveOnly: boolean;
|
|
71
|
+
readonly divergenceIds: readonly string[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface V3PageLocalStoryField {
|
|
75
|
+
readonly fieldId: string;
|
|
76
|
+
readonly family: PublicResolvedStoryField["family"];
|
|
77
|
+
readonly displayText: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface V3PageLocalStory {
|
|
81
|
+
readonly instanceId: string;
|
|
82
|
+
readonly storyKey: string;
|
|
83
|
+
readonly pageId: string;
|
|
84
|
+
readonly pageIndex: number;
|
|
85
|
+
readonly frameId: string;
|
|
86
|
+
readonly kind: "header" | "footer";
|
|
87
|
+
readonly variant: "default" | "first" | "even" | "odd";
|
|
88
|
+
readonly relationshipId: string;
|
|
89
|
+
readonly sectionIndex?: number;
|
|
90
|
+
readonly resolvedFields: readonly V3PageLocalStoryField[];
|
|
91
|
+
readonly anchoredObjects: readonly V3PageLocalStoryObject[];
|
|
92
|
+
readonly measuredFrameHeightTwips: number;
|
|
93
|
+
readonly signature: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface V3PageLocalStoriesResult {
|
|
97
|
+
readonly status: "available" | "unavailable";
|
|
98
|
+
readonly source: "layout-public-facet" | "layout-public-facet-unavailable";
|
|
99
|
+
readonly pageIndex: number;
|
|
100
|
+
readonly pageId?: string;
|
|
101
|
+
readonly frameId?: string;
|
|
102
|
+
readonly frameCompleteness?: V3PageFrameCompleteness;
|
|
103
|
+
readonly reason?: "layout-unavailable" | "page-not-found" | "frame-unavailable";
|
|
104
|
+
readonly stories: readonly V3PageLocalStory[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface V3PageLocalFieldLedgerEntry extends V3PageLocalStoryField {
|
|
108
|
+
readonly pageId: string;
|
|
109
|
+
readonly pageIndex: number;
|
|
110
|
+
readonly frameId: string;
|
|
111
|
+
readonly instanceId: string;
|
|
112
|
+
readonly storyKey: string;
|
|
113
|
+
readonly kind: "header" | "footer";
|
|
114
|
+
readonly variant: "default" | "first" | "even" | "odd";
|
|
115
|
+
readonly relationshipId: string;
|
|
116
|
+
readonly sectionIndex?: number;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface V3PageLocalFieldLedgerResult {
|
|
120
|
+
readonly status: "available" | "unavailable";
|
|
121
|
+
readonly source: "layout-public-facet" | "layout-public-facet-unavailable";
|
|
122
|
+
readonly pageIndex: number;
|
|
123
|
+
readonly pageId?: string;
|
|
124
|
+
readonly frameId?: string;
|
|
125
|
+
readonly frameCompleteness?: V3PageFrameCompleteness;
|
|
126
|
+
readonly reason?: "layout-unavailable" | "page-not-found" | "frame-unavailable";
|
|
127
|
+
readonly fields: readonly V3PageLocalFieldLedgerEntry[];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface V3LayoutDivergence {
|
|
131
|
+
readonly divergenceId: string;
|
|
132
|
+
readonly pageId: string;
|
|
133
|
+
readonly pageIndex: number;
|
|
134
|
+
readonly frameId?: string;
|
|
135
|
+
readonly kind?: string;
|
|
136
|
+
readonly source?: string;
|
|
137
|
+
readonly severity?: string;
|
|
138
|
+
readonly message?: string;
|
|
139
|
+
readonly regionKinds?: readonly string[];
|
|
140
|
+
readonly fragmentIds?: readonly string[];
|
|
141
|
+
readonly objectIds?: readonly string[];
|
|
142
|
+
readonly detailSource: "page-divergence" | "frame-divergence-id";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface V3LayoutCompleteness {
|
|
146
|
+
readonly status: "realized" | "partial" | "unavailable";
|
|
147
|
+
readonly pageCount: number;
|
|
148
|
+
readonly framedPageCount: number;
|
|
149
|
+
readonly missingFramePageIds: readonly string[];
|
|
150
|
+
readonly frameCompleteness: {
|
|
151
|
+
readonly complete: number;
|
|
152
|
+
readonly partial: number;
|
|
153
|
+
readonly absent: number;
|
|
154
|
+
};
|
|
155
|
+
readonly regionCount: number;
|
|
156
|
+
readonly regionWithRectCount: number;
|
|
157
|
+
readonly missingRectRegionCount: number;
|
|
158
|
+
readonly unknownStoryPageCount: number;
|
|
159
|
+
readonly pageLocalStoryCount: number;
|
|
160
|
+
readonly pageLocalObjectCount: number;
|
|
161
|
+
readonly divergenceCount: number;
|
|
162
|
+
}
|
|
12
163
|
|
|
13
164
|
export const getPageMetadata: ApiV3FnMetadata = {
|
|
14
165
|
name: "runtime.layout.getPage",
|
|
@@ -64,11 +215,179 @@ export const getBlockLayoutMetadata: ApiV3FnMetadata = {
|
|
|
64
215
|
"§Runtime API § runtime.layout.getBlockLayout. Adapter wraps facet.getMeasurement(blockId) → PublicBlockMeasurement; promotes to `live` when the v3 shape matches 1:1.",
|
|
65
216
|
};
|
|
66
217
|
|
|
218
|
+
export const getPageFrameMetadata: ApiV3FnMetadata = {
|
|
219
|
+
name: "runtime.layout.getPageFrame",
|
|
220
|
+
status: "live-with-adapter",
|
|
221
|
+
sourceLayer: "layout-semantics",
|
|
222
|
+
liveEvidence: {
|
|
223
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
224
|
+
commit: "refactor-07-pe2-page-frame-read-surface",
|
|
225
|
+
},
|
|
226
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
227
|
+
agentMetadata: {
|
|
228
|
+
readOrMutate: "read",
|
|
229
|
+
boundedScope: "document",
|
|
230
|
+
auditCategory: "layout-read",
|
|
231
|
+
},
|
|
232
|
+
stateClass: "A-canonical",
|
|
233
|
+
persistsTo: "canonical",
|
|
234
|
+
rwdReference:
|
|
235
|
+
"§Runtime API § runtime.layout.getPageFrame. PE2 read surface over the Layer-04 public page-frame substrate. Adapter projects `PublicPageNode.frame` when populated, preserving frame ids, signatures, completeness, divergence ids, exclusion counts, and region ordering; the legacy page layout/regions composition remains an explicit degraded fallback with completeness:'absent'.",
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
export const getPageFramesMetadata: ApiV3FnMetadata = {
|
|
239
|
+
name: "runtime.layout.getPageFrames",
|
|
240
|
+
status: "live-with-adapter",
|
|
241
|
+
sourceLayer: "layout-semantics",
|
|
242
|
+
liveEvidence: {
|
|
243
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
244
|
+
commit: "refactor-07-pe2-page-frame-read-surface",
|
|
245
|
+
},
|
|
246
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
247
|
+
agentMetadata: {
|
|
248
|
+
readOrMutate: "read",
|
|
249
|
+
boundedScope: "document",
|
|
250
|
+
auditCategory: "layout-read",
|
|
251
|
+
},
|
|
252
|
+
stateClass: "A-canonical",
|
|
253
|
+
persistsTo: "canonical",
|
|
254
|
+
rwdReference:
|
|
255
|
+
"§Runtime API § runtime.layout.getPageFrames. Enumerates PE2 page-frame records from the Layer-04 layout facet, preserving section filter semantics from `layout.getPages({sectionIndex})` and projecting `PublicPageNode.frame` including completeness when populated. Returns [] when the layout facet is absent.",
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export const getPageLocalStoriesMetadata: ApiV3FnMetadata = {
|
|
259
|
+
name: "runtime.layout.getPageLocalStories",
|
|
260
|
+
status: "live-with-adapter",
|
|
261
|
+
sourceLayer: "layout-semantics",
|
|
262
|
+
liveEvidence: {
|
|
263
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
264
|
+
commit: "refactor-07-pe2-page-local-story-divergence-completeness",
|
|
265
|
+
},
|
|
266
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
267
|
+
agentMetadata: {
|
|
268
|
+
readOrMutate: "read",
|
|
269
|
+
boundedScope: "document",
|
|
270
|
+
auditCategory: "layout-read",
|
|
271
|
+
},
|
|
272
|
+
stateClass: "A-canonical",
|
|
273
|
+
persistsTo: "canonical",
|
|
274
|
+
rwdReference:
|
|
275
|
+
"§Runtime API § runtime.layout.getPageLocalStories. PE2 read surface over `PublicPageFrame.pageLocalStories`, exposing page-local header/footer story instances, resolved field ledgers, anchored object ledgers, and L04 frame completeness without leaking runtime graph nodes. Returns an explicit availability envelope so empty page-local stories are distinguishable from an absent L04 frame substrate.",
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
export const getPageLocalFieldLedgerMetadata: ApiV3FnMetadata = {
|
|
279
|
+
name: "runtime.layout.getPageLocalFieldLedger",
|
|
280
|
+
status: "live-with-adapter",
|
|
281
|
+
sourceLayer: "layout-semantics",
|
|
282
|
+
liveEvidence: {
|
|
283
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
284
|
+
commit: "refactor-07-pe2-page-local-field-ledger",
|
|
285
|
+
},
|
|
286
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
287
|
+
agentMetadata: {
|
|
288
|
+
readOrMutate: "read",
|
|
289
|
+
boundedScope: "document",
|
|
290
|
+
auditCategory: "layout-read",
|
|
291
|
+
},
|
|
292
|
+
stateClass: "A-canonical",
|
|
293
|
+
persistsTo: "canonical",
|
|
294
|
+
rwdReference:
|
|
295
|
+
"§Runtime API § runtime.layout.getPageLocalFieldLedger. Public v3 read over L04 `PublicPageLocalStoryInstance.resolvedFields`, keyed by page/frame/story identity and frame completeness so agents can cite page-local header/footer field realization without reaching into layout graph internals.",
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export const getLayoutDivergencesMetadata: ApiV3FnMetadata = {
|
|
299
|
+
name: "runtime.layout.getLayoutDivergences",
|
|
300
|
+
status: "live-with-adapter",
|
|
301
|
+
sourceLayer: "layout-semantics",
|
|
302
|
+
liveEvidence: {
|
|
303
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
304
|
+
commit: "refactor-07-pe2-page-local-story-divergence-completeness",
|
|
305
|
+
},
|
|
306
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
307
|
+
agentMetadata: {
|
|
308
|
+
readOrMutate: "read",
|
|
309
|
+
boundedScope: "document",
|
|
310
|
+
auditCategory: "layout-read",
|
|
311
|
+
},
|
|
312
|
+
stateClass: "A-canonical",
|
|
313
|
+
persistsTo: "canonical",
|
|
314
|
+
rwdReference:
|
|
315
|
+
"§Runtime API § runtime.layout.getLayoutDivergences. Enumerates typed `PublicPageNode.divergences` plus frame-level divergence ids from the L04 public layout facet. Frame ids without page-level details remain id-only records.",
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
export const getLayoutCompletenessMetadata: ApiV3FnMetadata = {
|
|
319
|
+
name: "runtime.layout.getLayoutCompleteness",
|
|
320
|
+
status: "live-with-adapter",
|
|
321
|
+
sourceLayer: "layout-semantics",
|
|
322
|
+
liveEvidence: {
|
|
323
|
+
runnerTest: "test/api/v3/layout-page-frame-read-surface.test.ts",
|
|
324
|
+
commit: "refactor-07-pe2-page-local-story-divergence-completeness",
|
|
325
|
+
},
|
|
326
|
+
uxIntent: { uiVisible: false, expectsUxResponse: "none" },
|
|
327
|
+
agentMetadata: {
|
|
328
|
+
readOrMutate: "read",
|
|
329
|
+
boundedScope: "document",
|
|
330
|
+
auditCategory: "layout-read",
|
|
331
|
+
},
|
|
332
|
+
stateClass: "A-canonical",
|
|
333
|
+
persistsTo: "canonical",
|
|
334
|
+
rwdReference:
|
|
335
|
+
"§Runtime API § runtime.layout.getLayoutCompleteness. Summarizes L04 public page-frame realization, frame completeness counts, region rect coverage, page-local story/object counts, unknown story pages, and divergence ids as a lightweight PE2 layout-read health signal.",
|
|
336
|
+
};
|
|
337
|
+
|
|
67
338
|
export function createLayoutFamily(runtime: RuntimeApiHandle) {
|
|
68
339
|
// Public-facet shape — see src/runtime/layout/public-facet.ts:376+.
|
|
69
340
|
const layout = runtime.layout;
|
|
70
341
|
|
|
71
342
|
return {
|
|
343
|
+
getPageFrame(pageIndex: number): V3PageFrame | null {
|
|
344
|
+
// @endStateApi — live-with-adapter. Prefer the L04 public frame
|
|
345
|
+
// substrate. The legacy composition path is kept only for older or
|
|
346
|
+
// inert facets that have not emitted page.frame yet.
|
|
347
|
+
const page = layout?.getPage(pageIndex);
|
|
348
|
+
return page ? toV3PageFrame(page) : null;
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
getPageFrames(options?: { sectionIndex?: number }): readonly V3PageFrame[] {
|
|
352
|
+
// @endStateApi — live-with-adapter. Mirrors layout.getPages filter
|
|
353
|
+
// semantics and projects each page into the PE2 frame read shape.
|
|
354
|
+
const pages = layout?.getPages(options);
|
|
355
|
+
return pages?.map(toV3PageFrame) ?? [];
|
|
356
|
+
},
|
|
357
|
+
|
|
358
|
+
getPageLocalStories(pageIndex: number): V3PageLocalStoriesResult {
|
|
359
|
+
// @endStateApi — live-with-adapter. Reads the L04 public page-frame
|
|
360
|
+
// story ledger. The envelope distinguishes true empty stories from
|
|
361
|
+
// a missing page-frame substrate.
|
|
362
|
+
const page = layout?.getPage(pageIndex);
|
|
363
|
+
return toV3PageLocalStoriesResult(pageIndex, page, layout === undefined);
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
getPageLocalFieldLedger(pageIndex: number): V3PageLocalFieldLedgerResult {
|
|
367
|
+
// @endStateApi — live-with-adapter. Projects L04 resolved page-local
|
|
368
|
+
// fields as a citation-ready ledger and keeps unavailable frames
|
|
369
|
+
// distinct from available pages with zero resolved fields.
|
|
370
|
+
const page = layout?.getPage(pageIndex);
|
|
371
|
+
return toV3PageLocalFieldLedgerResult(pageIndex, page, layout === undefined);
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
getLayoutDivergences(options?: {
|
|
375
|
+
pageIndex?: number;
|
|
376
|
+
sectionIndex?: number;
|
|
377
|
+
}): readonly V3LayoutDivergence[] {
|
|
378
|
+
// @endStateApi — live-with-adapter. Keeps typed page divergences and
|
|
379
|
+
// id-only frame divergences visible without inventing lower-layer detail.
|
|
380
|
+
const pages = getPagesForLayoutRead(layout, options);
|
|
381
|
+
return pages.flatMap(toV3LayoutDivergences);
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
getLayoutCompleteness(options?: { sectionIndex?: number }): V3LayoutCompleteness {
|
|
385
|
+
// @endStateApi — live-with-adapter. Lightweight page-frame health
|
|
386
|
+
// summary for agents/debug; does not validate Word parity.
|
|
387
|
+
const pages = layout?.getPages(options) ?? [];
|
|
388
|
+
return summarizeLayoutCompleteness(pages);
|
|
389
|
+
},
|
|
390
|
+
|
|
72
391
|
getPage(pageIndex: number) {
|
|
73
392
|
// @endStateApi — live-with-adapter. Wraps the facet's
|
|
74
393
|
// getPage(pageIndex); promotes to `live` when the v3 shape matches
|
|
@@ -106,3 +425,428 @@ export function createLayoutFamily(runtime: RuntimeApiHandle) {
|
|
|
106
425
|
},
|
|
107
426
|
};
|
|
108
427
|
}
|
|
428
|
+
|
|
429
|
+
type LayoutReadFacet = NonNullable<RuntimeApiHandle["layout"]>;
|
|
430
|
+
|
|
431
|
+
function toV3PageFrame(page: PublicPageNode): V3PageFrame {
|
|
432
|
+
if (page.frame) return publicFrameToV3(page.frame);
|
|
433
|
+
return legacyPageToV3PageFrame(page);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function publicFrameToV3(frame: PublicPageFrame): V3PageFrame {
|
|
437
|
+
const regions = frame.regionFrames.flatMap((region): V3PageFrameRegion[] => {
|
|
438
|
+
if (!region.rectTwips) return [];
|
|
439
|
+
return [
|
|
440
|
+
{
|
|
441
|
+
kind: region.kind,
|
|
442
|
+
rectTwips: cloneRect(region.rectTwips),
|
|
443
|
+
fragmentCount: region.fragmentIds.length,
|
|
444
|
+
},
|
|
445
|
+
];
|
|
446
|
+
});
|
|
447
|
+
return {
|
|
448
|
+
frameId: frame.frameId,
|
|
449
|
+
pageId: frame.pageId,
|
|
450
|
+
pageIndex: frame.pageIndex,
|
|
451
|
+
sectionIndex: frame.sectionIndex,
|
|
452
|
+
displayPageNumber: frame.displayPageNumber,
|
|
453
|
+
completeness: frame.completeness,
|
|
454
|
+
physicalBoundsTwips: cloneRect(frame.physicalBoundsTwips),
|
|
455
|
+
divergenceIds: [...frame.divergenceIds],
|
|
456
|
+
exclusionZoneCount: frame.exclusionZoneCount,
|
|
457
|
+
regions,
|
|
458
|
+
signature: frame.signature,
|
|
459
|
+
source: "layout-public-frame",
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function toV3PageLocalStory(
|
|
464
|
+
story: PublicPageLocalStoryInstance,
|
|
465
|
+
frame: PublicPageFrame,
|
|
466
|
+
): V3PageLocalStory {
|
|
467
|
+
return {
|
|
468
|
+
instanceId: story.instanceId,
|
|
469
|
+
storyKey: story.storyKey,
|
|
470
|
+
pageId: story.pageId,
|
|
471
|
+
pageIndex: frame.pageIndex,
|
|
472
|
+
frameId: frame.frameId,
|
|
473
|
+
kind: story.kind,
|
|
474
|
+
variant: story.variant,
|
|
475
|
+
relationshipId: story.relationshipId,
|
|
476
|
+
...(story.sectionIndex !== undefined ? { sectionIndex: story.sectionIndex } : {}),
|
|
477
|
+
resolvedFields: story.resolvedFields.map(toV3PageLocalStoryField),
|
|
478
|
+
anchoredObjects: story.anchoredObjects.map(toV3PageLocalStoryObject),
|
|
479
|
+
measuredFrameHeightTwips: story.measuredFrameHeightTwips,
|
|
480
|
+
signature: story.signature,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function toV3PageLocalStoriesResult(
|
|
485
|
+
pageIndex: number,
|
|
486
|
+
page: PublicPageNode | null | undefined,
|
|
487
|
+
layoutUnavailable: boolean,
|
|
488
|
+
): V3PageLocalStoriesResult {
|
|
489
|
+
if (layoutUnavailable) {
|
|
490
|
+
return unavailablePageLocalStories(pageIndex, "layout-unavailable");
|
|
491
|
+
}
|
|
492
|
+
if (!page) {
|
|
493
|
+
return unavailablePageLocalStories(pageIndex, "page-not-found");
|
|
494
|
+
}
|
|
495
|
+
if (!page.frame) {
|
|
496
|
+
return unavailablePageLocalStories(pageIndex, "frame-unavailable", page);
|
|
497
|
+
}
|
|
498
|
+
return {
|
|
499
|
+
status: "available",
|
|
500
|
+
source: "layout-public-facet",
|
|
501
|
+
pageIndex,
|
|
502
|
+
pageId: page.pageId,
|
|
503
|
+
frameId: page.frame.frameId,
|
|
504
|
+
frameCompleteness: page.frame.completeness,
|
|
505
|
+
stories: page.frame.pageLocalStories.map((story) => toV3PageLocalStory(story, page.frame!)),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
function unavailablePageLocalStories(
|
|
510
|
+
pageIndex: number,
|
|
511
|
+
reason: V3PageLocalStoriesResult["reason"],
|
|
512
|
+
page?: PublicPageNode,
|
|
513
|
+
): V3PageLocalStoriesResult {
|
|
514
|
+
return {
|
|
515
|
+
status: "unavailable",
|
|
516
|
+
source: "layout-public-facet-unavailable",
|
|
517
|
+
pageIndex,
|
|
518
|
+
...(page ? { pageId: page.pageId } : {}),
|
|
519
|
+
...(reason === "frame-unavailable" ? { frameCompleteness: "absent" as const } : {}),
|
|
520
|
+
reason,
|
|
521
|
+
stories: [],
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function toV3PageLocalFieldLedgerResult(
|
|
526
|
+
pageIndex: number,
|
|
527
|
+
page: PublicPageNode | null | undefined,
|
|
528
|
+
layoutUnavailable: boolean,
|
|
529
|
+
): V3PageLocalFieldLedgerResult {
|
|
530
|
+
if (layoutUnavailable) {
|
|
531
|
+
return unavailablePageLocalFieldLedger(pageIndex, "layout-unavailable");
|
|
532
|
+
}
|
|
533
|
+
if (!page) {
|
|
534
|
+
return unavailablePageLocalFieldLedger(pageIndex, "page-not-found");
|
|
535
|
+
}
|
|
536
|
+
if (!page.frame) {
|
|
537
|
+
return unavailablePageLocalFieldLedger(pageIndex, "frame-unavailable", page);
|
|
538
|
+
}
|
|
539
|
+
return {
|
|
540
|
+
status: "available",
|
|
541
|
+
source: "layout-public-facet",
|
|
542
|
+
pageIndex,
|
|
543
|
+
pageId: page.pageId,
|
|
544
|
+
frameId: page.frame.frameId,
|
|
545
|
+
frameCompleteness: page.frame.completeness,
|
|
546
|
+
fields: page.frame.pageLocalStories.flatMap((story) =>
|
|
547
|
+
story.resolvedFields.map((field) => toV3PageLocalFieldLedgerEntry(field, story, page.frame!)),
|
|
548
|
+
),
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function unavailablePageLocalFieldLedger(
|
|
553
|
+
pageIndex: number,
|
|
554
|
+
reason: V3PageLocalFieldLedgerResult["reason"],
|
|
555
|
+
page?: PublicPageNode,
|
|
556
|
+
): V3PageLocalFieldLedgerResult {
|
|
557
|
+
return {
|
|
558
|
+
status: "unavailable",
|
|
559
|
+
source: "layout-public-facet-unavailable",
|
|
560
|
+
pageIndex,
|
|
561
|
+
...(page ? { pageId: page.pageId } : {}),
|
|
562
|
+
...(reason === "frame-unavailable" ? { frameCompleteness: "absent" as const } : {}),
|
|
563
|
+
reason,
|
|
564
|
+
fields: [],
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function toV3PageLocalStoryField(
|
|
569
|
+
field: PublicResolvedStoryField,
|
|
570
|
+
): V3PageLocalStoryField {
|
|
571
|
+
return {
|
|
572
|
+
fieldId: field.fieldId,
|
|
573
|
+
family: field.family,
|
|
574
|
+
displayText: field.displayText,
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function toV3PageLocalFieldLedgerEntry(
|
|
579
|
+
field: PublicResolvedStoryField,
|
|
580
|
+
story: PublicPageLocalStoryInstance,
|
|
581
|
+
frame: PublicPageFrame,
|
|
582
|
+
): V3PageLocalFieldLedgerEntry {
|
|
583
|
+
return {
|
|
584
|
+
...toV3PageLocalStoryField(field),
|
|
585
|
+
pageId: story.pageId,
|
|
586
|
+
pageIndex: frame.pageIndex,
|
|
587
|
+
frameId: frame.frameId,
|
|
588
|
+
instanceId: story.instanceId,
|
|
589
|
+
storyKey: story.storyKey,
|
|
590
|
+
kind: story.kind,
|
|
591
|
+
variant: story.variant,
|
|
592
|
+
relationshipId: story.relationshipId,
|
|
593
|
+
...(story.sectionIndex !== undefined ? { sectionIndex: story.sectionIndex } : {}),
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function toV3PageLocalStoryObject(
|
|
598
|
+
object: PublicStoryAnchoredObject,
|
|
599
|
+
): V3PageLocalStoryObject {
|
|
600
|
+
return {
|
|
601
|
+
objectId: object.objectId,
|
|
602
|
+
sourceType: object.sourceType,
|
|
603
|
+
display: object.display,
|
|
604
|
+
...(object.extentTwips
|
|
605
|
+
? {
|
|
606
|
+
extentTwips: {
|
|
607
|
+
widthTwips: object.extentTwips.widthTwips,
|
|
608
|
+
heightTwips: object.extentTwips.heightTwips,
|
|
609
|
+
},
|
|
610
|
+
}
|
|
611
|
+
: {}),
|
|
612
|
+
...(object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {}),
|
|
613
|
+
...(object.mediaIds ? { mediaIds: [...object.mediaIds] } : {}),
|
|
614
|
+
preserveOnly: object.preserveOnly,
|
|
615
|
+
divergenceIds: [...object.divergenceIds],
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
function getPagesForLayoutRead(
|
|
620
|
+
layout: LayoutReadFacet | undefined,
|
|
621
|
+
options: { pageIndex?: number; sectionIndex?: number } | undefined,
|
|
622
|
+
): readonly PublicPageNode[] {
|
|
623
|
+
if (!layout) return [];
|
|
624
|
+
if (options?.pageIndex !== undefined) {
|
|
625
|
+
const page = layout.getPage(options.pageIndex);
|
|
626
|
+
if (!page) return [];
|
|
627
|
+
if (options.sectionIndex !== undefined && page.sectionIndex !== options.sectionIndex) return [];
|
|
628
|
+
return [page];
|
|
629
|
+
}
|
|
630
|
+
return layout.getPages(
|
|
631
|
+
options?.sectionIndex !== undefined ? { sectionIndex: options.sectionIndex } : undefined,
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function toV3LayoutDivergences(page: PublicPageNode): V3LayoutDivergence[] {
|
|
636
|
+
const out = new Map<string, V3LayoutDivergence>();
|
|
637
|
+
const frameId = page.frame?.frameId;
|
|
638
|
+
|
|
639
|
+
for (const divergence of page.divergences ?? []) {
|
|
640
|
+
out.set(divergence.divergenceId, {
|
|
641
|
+
divergenceId: divergence.divergenceId,
|
|
642
|
+
pageId: page.pageId,
|
|
643
|
+
pageIndex: page.pageIndex,
|
|
644
|
+
...(frameId ? { frameId } : {}),
|
|
645
|
+
kind: divergence.kind,
|
|
646
|
+
source: divergence.source,
|
|
647
|
+
severity: divergence.severity,
|
|
648
|
+
message: divergence.message,
|
|
649
|
+
...(divergence.regionKinds ? { regionKinds: [...divergence.regionKinds] } : {}),
|
|
650
|
+
...(divergence.fragmentIds ? { fragmentIds: [...divergence.fragmentIds] } : {}),
|
|
651
|
+
...(divergence.objectIds ? { objectIds: [...divergence.objectIds] } : {}),
|
|
652
|
+
detailSource: "page-divergence",
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
for (const divergenceId of page.frame?.divergenceIds ?? []) {
|
|
657
|
+
if (out.has(divergenceId)) continue;
|
|
658
|
+
out.set(divergenceId, {
|
|
659
|
+
divergenceId,
|
|
660
|
+
pageId: page.pageId,
|
|
661
|
+
pageIndex: page.pageIndex,
|
|
662
|
+
...(frameId ? { frameId } : {}),
|
|
663
|
+
detailSource: "frame-divergence-id",
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
return [...out.values()];
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function summarizeLayoutCompleteness(pages: readonly PublicPageNode[]): V3LayoutCompleteness {
|
|
671
|
+
let framedPageCount = 0;
|
|
672
|
+
let regionCount = 0;
|
|
673
|
+
let regionWithRectCount = 0;
|
|
674
|
+
let pageLocalStoryCount = 0;
|
|
675
|
+
let pageLocalObjectCount = 0;
|
|
676
|
+
let unknownStoryPageCount = 0;
|
|
677
|
+
const frameCompleteness = {
|
|
678
|
+
complete: 0,
|
|
679
|
+
partial: 0,
|
|
680
|
+
absent: 0,
|
|
681
|
+
};
|
|
682
|
+
const missingFramePageIds: string[] = [];
|
|
683
|
+
const divergenceIds = new Set<string>();
|
|
684
|
+
|
|
685
|
+
for (const page of pages) {
|
|
686
|
+
const frame = page.frame;
|
|
687
|
+
if (!frame) {
|
|
688
|
+
missingFramePageIds.push(page.pageId);
|
|
689
|
+
unknownStoryPageCount += 1;
|
|
690
|
+
frameCompleteness.absent += 1;
|
|
691
|
+
} else {
|
|
692
|
+
framedPageCount += 1;
|
|
693
|
+
frameCompleteness[frame.completeness] += 1;
|
|
694
|
+
pageLocalStoryCount += frame.pageLocalStories.length;
|
|
695
|
+
for (const story of frame.pageLocalStories) {
|
|
696
|
+
pageLocalObjectCount += story.anchoredObjects.length;
|
|
697
|
+
}
|
|
698
|
+
for (const region of frame.regionFrames) {
|
|
699
|
+
regionCount += 1;
|
|
700
|
+
if (region.rectTwips) regionWithRectCount += 1;
|
|
701
|
+
}
|
|
702
|
+
for (const divergenceId of frame.divergenceIds) divergenceIds.add(divergenceId);
|
|
703
|
+
}
|
|
704
|
+
for (const divergence of page.divergences ?? []) divergenceIds.add(divergence.divergenceId);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
const missingRectRegionCount = regionCount - regionWithRectCount;
|
|
708
|
+
return {
|
|
709
|
+
status:
|
|
710
|
+
pages.length === 0
|
|
711
|
+
? "unavailable"
|
|
712
|
+
: missingFramePageIds.length === 0 && missingRectRegionCount === 0
|
|
713
|
+
? "realized"
|
|
714
|
+
: "partial",
|
|
715
|
+
pageCount: pages.length,
|
|
716
|
+
framedPageCount,
|
|
717
|
+
missingFramePageIds,
|
|
718
|
+
frameCompleteness,
|
|
719
|
+
regionCount,
|
|
720
|
+
regionWithRectCount,
|
|
721
|
+
missingRectRegionCount,
|
|
722
|
+
unknownStoryPageCount,
|
|
723
|
+
pageLocalStoryCount,
|
|
724
|
+
pageLocalObjectCount,
|
|
725
|
+
divergenceCount: divergenceIds.size,
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
function legacyPageToV3PageFrame(page: PublicPageNode): V3PageFrame {
|
|
730
|
+
const regions = collectLegacyV3PageFrameRegions(page);
|
|
731
|
+
return {
|
|
732
|
+
frameId: buildFrameId(page),
|
|
733
|
+
pageId: page.pageId,
|
|
734
|
+
pageIndex: page.pageIndex,
|
|
735
|
+
sectionIndex: page.sectionIndex,
|
|
736
|
+
displayPageNumber: page.displayPageNumber,
|
|
737
|
+
completeness: "absent",
|
|
738
|
+
physicalBoundsTwips: rect(0, 0, page.layout.pageWidth, page.layout.pageHeight),
|
|
739
|
+
divergenceIds: page.divergences?.map((divergence) => divergence.divergenceId) ?? [],
|
|
740
|
+
exclusionZoneCount: legacyExclusionZoneCount(page),
|
|
741
|
+
regions,
|
|
742
|
+
signature: buildFrameSignature(page, regions),
|
|
743
|
+
source: "layout-public-facet-fallback",
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
function legacyExclusionZoneCount(page: PublicPageNode): number {
|
|
748
|
+
const carrier = page as PublicPageNode & {
|
|
749
|
+
readonly exclusionZones?: readonly unknown[];
|
|
750
|
+
readonly layout: PublicPageNode["layout"] & {
|
|
751
|
+
readonly exclusionZones?: readonly unknown[];
|
|
752
|
+
};
|
|
753
|
+
};
|
|
754
|
+
if (Array.isArray(carrier.exclusionZones)) return carrier.exclusionZones.length;
|
|
755
|
+
if (Array.isArray(carrier.layout.exclusionZones)) return carrier.layout.exclusionZones.length;
|
|
756
|
+
return 0;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
function collectLegacyV3PageFrameRegions(page: PublicPageNode): readonly V3PageFrameRegion[] {
|
|
760
|
+
const out: V3PageFrameRegion[] = [
|
|
761
|
+
{
|
|
762
|
+
kind: "body",
|
|
763
|
+
rectTwips: rect(
|
|
764
|
+
page.layout.marginLeft,
|
|
765
|
+
page.regions.body.originTwips,
|
|
766
|
+
page.regions.body.widthTwips,
|
|
767
|
+
page.regions.body.heightTwips,
|
|
768
|
+
),
|
|
769
|
+
fragmentCount: page.regions.body.fragmentCount,
|
|
770
|
+
},
|
|
771
|
+
];
|
|
772
|
+
if (page.regions.header) {
|
|
773
|
+
out.push(regionAtMarginLeft(page, page.regions.header));
|
|
774
|
+
}
|
|
775
|
+
if (page.regions.footer) {
|
|
776
|
+
out.push(regionAtMarginLeft(page, page.regions.footer));
|
|
777
|
+
}
|
|
778
|
+
const columns = page.regions.columns ?? [];
|
|
779
|
+
const gap = page.layout.columnDefinitions?.[0]?.space ?? 720;
|
|
780
|
+
for (let i = 0; i < columns.length; i += 1) {
|
|
781
|
+
const column = columns[i]!;
|
|
782
|
+
out.push({
|
|
783
|
+
kind: "column",
|
|
784
|
+
rectTwips: rect(
|
|
785
|
+
page.layout.marginLeft + i * (column.widthTwips + gap),
|
|
786
|
+
column.originTwips,
|
|
787
|
+
column.widthTwips,
|
|
788
|
+
column.heightTwips,
|
|
789
|
+
),
|
|
790
|
+
fragmentCount: column.fragmentCount,
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
for (const footnote of page.regions.footnotes ?? []) {
|
|
794
|
+
out.push(regionAtMarginLeft(page, footnote));
|
|
795
|
+
}
|
|
796
|
+
return out;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function cloneRect(value: V3TwipsRect): V3TwipsRect {
|
|
800
|
+
return rect(value.xTwips, value.yTwips, value.widthTwips, value.heightTwips);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function regionAtMarginLeft(page: PublicPageNode, region: PublicPageRegion): V3PageFrameRegion {
|
|
804
|
+
return {
|
|
805
|
+
kind: region.kind,
|
|
806
|
+
rectTwips: rect(
|
|
807
|
+
page.layout.marginLeft,
|
|
808
|
+
region.originTwips,
|
|
809
|
+
region.widthTwips,
|
|
810
|
+
region.heightTwips,
|
|
811
|
+
),
|
|
812
|
+
fragmentCount: region.fragmentCount,
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function rect(
|
|
817
|
+
xTwips: number,
|
|
818
|
+
yTwips: number,
|
|
819
|
+
widthTwips: number,
|
|
820
|
+
heightTwips: number,
|
|
821
|
+
): V3TwipsRect {
|
|
822
|
+
return { xTwips, yTwips, widthTwips, heightTwips };
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
function buildFrameId(page: PublicPageNode): string {
|
|
826
|
+
return `page-frame-${page.pageIndex}-section-${page.sectionIndex}-display-${page.displayPageNumber}`;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
function buildFrameSignature(
|
|
830
|
+
page: PublicPageNode,
|
|
831
|
+
regions: readonly V3PageFrameRegion[],
|
|
832
|
+
): string {
|
|
833
|
+
const regionParts = regions.map((region) =>
|
|
834
|
+
[
|
|
835
|
+
region.kind,
|
|
836
|
+
region.rectTwips.xTwips,
|
|
837
|
+
region.rectTwips.yTwips,
|
|
838
|
+
region.rectTwips.widthTwips,
|
|
839
|
+
region.rectTwips.heightTwips,
|
|
840
|
+
region.fragmentCount,
|
|
841
|
+
].join(":"),
|
|
842
|
+
);
|
|
843
|
+
return [
|
|
844
|
+
"page-frame",
|
|
845
|
+
page.pageIndex,
|
|
846
|
+
page.sectionIndex,
|
|
847
|
+
page.displayPageNumber,
|
|
848
|
+
page.layout.pageWidth,
|
|
849
|
+
page.layout.pageHeight,
|
|
850
|
+
...regionParts,
|
|
851
|
+
].join("|");
|
|
852
|
+
}
|