@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
|
@@ -187,6 +187,13 @@ import {
|
|
|
187
187
|
createWorkflowCoordinator,
|
|
188
188
|
type WorkflowCoordinator,
|
|
189
189
|
} from "./workflow/coordinator.ts";
|
|
190
|
+
import {
|
|
191
|
+
areWorkflowReviewOverlayLaneSnapshotsEqual,
|
|
192
|
+
shouldRefreshWorkflowReviewOverlayLane,
|
|
193
|
+
type WorkflowReviewOverlayLaneListener,
|
|
194
|
+
type WorkflowReviewOverlayLaneKind,
|
|
195
|
+
type WorkflowReviewOverlayLaneSnapshot,
|
|
196
|
+
} from "./workflow/overlay-lanes.ts";
|
|
190
197
|
import {
|
|
191
198
|
insertScopeMarkers,
|
|
192
199
|
removeScopeMarkers,
|
|
@@ -307,7 +314,7 @@ import { rebuildFieldRegistry } from "./formatting/field/registry.ts";
|
|
|
307
314
|
import {
|
|
308
315
|
incrementInvalidationCounter,
|
|
309
316
|
recordPerfSample,
|
|
310
|
-
} from "
|
|
317
|
+
} from "./telemetry/perf-probe.ts";
|
|
311
318
|
import {
|
|
312
319
|
createLoadScheduler,
|
|
313
320
|
type LoadScheduler,
|
|
@@ -689,6 +696,19 @@ export interface DocumentRuntime {
|
|
|
689
696
|
* kernel is available) primary anchor rects.
|
|
690
697
|
*/
|
|
691
698
|
getAllScopeCardModels(): readonly import("../api/public-types.ts").ScopeCardModel[];
|
|
699
|
+
/**
|
|
700
|
+
* Durable review/workflow overlay lane projection. Presence remains
|
|
701
|
+
* awareness-owned and returns an explicit unavailable snapshot here.
|
|
702
|
+
*/
|
|
703
|
+
getReviewOverlayLane(kind: WorkflowReviewOverlayLaneKind): WorkflowReviewOverlayLaneSnapshot;
|
|
704
|
+
/**
|
|
705
|
+
* Subscribe to durable review/workflow lane changes. The presence lane is
|
|
706
|
+
* awareness-owned and must be subscribed through the awareness/UI source.
|
|
707
|
+
*/
|
|
708
|
+
subscribeReviewOverlayLane(
|
|
709
|
+
kind: WorkflowReviewOverlayLaneKind,
|
|
710
|
+
listener: WorkflowReviewOverlayLaneListener,
|
|
711
|
+
): Unsubscribe;
|
|
692
712
|
};
|
|
693
713
|
/**
|
|
694
714
|
* Runtime-owned geometry facet (Layer 05 · Geometry Projection).
|
|
@@ -756,6 +776,8 @@ export interface DocumentRuntime {
|
|
|
756
776
|
getFootnoteResolver(): FootnoteResolver | undefined;
|
|
757
777
|
updateFields(options?: UpdateFieldsOptions): UpdateFieldsResult;
|
|
758
778
|
updateTableOfContents(options?: TocRefreshOptions): TocRefreshResult;
|
|
779
|
+
/** Runtime wall-clock timestamp source used for audit/event emission. */
|
|
780
|
+
now(): string;
|
|
759
781
|
getSessionState(): EditorSessionState;
|
|
760
782
|
getPersistedSnapshot(): PersistedEditorSnapshot;
|
|
761
783
|
getCompatibilityReport(): CompatibilityReport;
|
|
@@ -774,7 +796,10 @@ export interface DocumentRuntime {
|
|
|
774
796
|
getWorkflowMarkupSnapshot(): WorkflowMarkupSnapshot;
|
|
775
797
|
setWorkflowMetadataDefinitions(definitions: WorkflowMetadataDefinition[]): void;
|
|
776
798
|
clearWorkflowMetadataDefinitions(): void;
|
|
777
|
-
setWorkflowMetadataEntries(
|
|
799
|
+
setWorkflowMetadataEntries(
|
|
800
|
+
entries: WorkflowMetadataEntry[],
|
|
801
|
+
origin?: WorkflowEventOrigin,
|
|
802
|
+
): void;
|
|
778
803
|
clearWorkflowMetadataEntries(): void;
|
|
779
804
|
getWorkflowMetadataSnapshot(): WorkflowMetadataSnapshot;
|
|
780
805
|
/** W10 — class-A overlay-visibility policy (per-kind read). */
|
|
@@ -1015,8 +1040,8 @@ export interface CreateDocumentRuntimeOptions {
|
|
|
1015
1040
|
* L7 Phase 2.5 — prerender cache seed. When set, the internal
|
|
1016
1041
|
* LayoutEngineInstance is seeded with this graph so the first
|
|
1017
1042
|
* `getPageGraph()` call returns it directly, skipping `fullRebuild`.
|
|
1018
|
-
* The seeded graph must have been produced with the current
|
|
1019
|
-
*
|
|
1043
|
+
* The seeded graph must have been produced with the current layout engine
|
|
1044
|
+
* and laycache schema versions (callers rely on the cache-key scheme in
|
|
1020
1045
|
* `src/runtime/prerender/cache-key.ts` to guarantee this).
|
|
1021
1046
|
*
|
|
1022
1047
|
* See CLAUDE.md (lane status table) §Phase 2.5 §3.7.
|
|
@@ -1150,6 +1175,46 @@ function computeReviewStateHash(
|
|
|
1150
1175
|
return `${commentParts.join(",")}|${revisionParts.join(",")}`;
|
|
1151
1176
|
}
|
|
1152
1177
|
|
|
1178
|
+
function normalizeCompatibilityTextNode(text: string): string {
|
|
1179
|
+
return [
|
|
1180
|
+
text.length > 0 ? "nonempty" : "empty",
|
|
1181
|
+
/^\s/u.test(text) ? "leading-space" : "",
|
|
1182
|
+
/\s$/u.test(text) ? "trailing-space" : "",
|
|
1183
|
+
text.includes(" ") ? "double-space" : "",
|
|
1184
|
+
].filter(Boolean).join(":");
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
function normalizeCompatibilityCacheValue(key: string, value: unknown): unknown {
|
|
1188
|
+
if (key === "updatedAt" || key === "generatedAt") {
|
|
1189
|
+
return undefined;
|
|
1190
|
+
}
|
|
1191
|
+
if (
|
|
1192
|
+
value &&
|
|
1193
|
+
typeof value === "object" &&
|
|
1194
|
+
!Array.isArray(value) &&
|
|
1195
|
+
(value as { type?: unknown }).type === "text" &&
|
|
1196
|
+
typeof (value as { text?: unknown }).text === "string"
|
|
1197
|
+
) {
|
|
1198
|
+
return {
|
|
1199
|
+
...value,
|
|
1200
|
+
text: normalizeCompatibilityTextNode((value as { text: string }).text),
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
return value;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
function computeCompatibilityCacheKey(state: EditorState): string {
|
|
1207
|
+
return JSON.stringify(
|
|
1208
|
+
{
|
|
1209
|
+
document: state.document,
|
|
1210
|
+
warnings: state.warnings,
|
|
1211
|
+
fatalError: state.fatalError,
|
|
1212
|
+
baseCompatibility: state.compatibility,
|
|
1213
|
+
},
|
|
1214
|
+
normalizeCompatibilityCacheValue,
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1153
1218
|
export function createDocumentRuntime(
|
|
1154
1219
|
options: CreateDocumentRuntimeOptions,
|
|
1155
1220
|
): DocumentRuntime {
|
|
@@ -1315,7 +1380,7 @@ export function createDocumentRuntime(
|
|
|
1315
1380
|
// runtime's current document identity so `keyEqual` passes without
|
|
1316
1381
|
// triggering a rebuild. The cache-key scheme in
|
|
1317
1382
|
// src/runtime/prerender/cache-key.ts guarantees the seed is produced
|
|
1318
|
-
// by the same
|
|
1383
|
+
// by the same layout engine and laycache schema versions.
|
|
1319
1384
|
layoutEngine.seedCachedGraph(options.seedLayoutCache, state.document);
|
|
1320
1385
|
perfCounters.increment("loadSession.layoutCache.seeded");
|
|
1321
1386
|
}
|
|
@@ -1326,6 +1391,15 @@ export function createDocumentRuntime(
|
|
|
1326
1391
|
// `renderKernelRef` is a forward reference so the facet can reach the
|
|
1327
1392
|
// kernel after it is created below (kernel creation needs the facet).
|
|
1328
1393
|
let renderKernelRef: RenderKernel | null = null;
|
|
1394
|
+
// `runtimeRef` is a forward reference so the facet can call the runtime's
|
|
1395
|
+
// viewport methods without duplicating their implementation.
|
|
1396
|
+
let runtimeRef: DocumentRuntime | null = null;
|
|
1397
|
+
const getRuntimeForLayoutFacet = (): DocumentRuntime => {
|
|
1398
|
+
if (!runtimeRef) {
|
|
1399
|
+
throw new Error("Document runtime viewport methods are not initialized");
|
|
1400
|
+
}
|
|
1401
|
+
return runtimeRef;
|
|
1402
|
+
};
|
|
1329
1403
|
const layoutFacet: WordReviewEditorLayoutFacet = createLayoutFacet({
|
|
1330
1404
|
engine: layoutEngine,
|
|
1331
1405
|
getQueryInput: () => ({
|
|
@@ -1344,24 +1418,15 @@ export function createDocumentRuntime(
|
|
|
1344
1418
|
// input via the getQueryInput + engine accessors above.
|
|
1345
1419
|
// L7 Phase 2 — delegate viewport culling through the facet so the
|
|
1346
1420
|
// workspace (which only holds a `layoutFacet` ref) can drive culling
|
|
1347
|
-
// without a separate `DocumentRuntime` prop.
|
|
1348
|
-
// the runtime's own `setVisibleBlockRange` / `requestViewportRefresh`
|
|
1349
|
-
// implementations which are defined below. Capturing by closure works
|
|
1350
|
-
// because the lambdas are only invoked after the full runtime object is
|
|
1351
|
-
// built and the methods below have been assigned.
|
|
1352
|
-
// TODO(L7 Phase 2 post-merge): this lambda duplicates the setVisibleBlockRange
|
|
1353
|
-
// logic implemented on `runtime` at line ~2874. Consolidate after Phase 2 ships
|
|
1354
|
-
// so the facet forwards to the runtime method. Forward-reference pattern matches
|
|
1355
|
-
// `renderKernelRef` — see that example. See spec-review notes on commit 0b03bfa7.
|
|
1421
|
+
// without a separate `DocumentRuntime` prop.
|
|
1356
1422
|
setVisibleBlockRange: (range) => {
|
|
1357
|
-
|
|
1423
|
+
getRuntimeForLayoutFacet().setVisibleBlockRange(range);
|
|
1358
1424
|
},
|
|
1359
1425
|
setVisibleBlockRanges: (ranges) => {
|
|
1360
|
-
|
|
1426
|
+
getRuntimeForLayoutFacet().setVisibleBlockRanges(ranges);
|
|
1361
1427
|
},
|
|
1362
1428
|
requestViewportRefresh: () => {
|
|
1363
|
-
|
|
1364
|
-
maybeRefreshSurfaceForViewport();
|
|
1429
|
+
getRuntimeForLayoutFacet().requestViewportRefresh();
|
|
1365
1430
|
},
|
|
1366
1431
|
});
|
|
1367
1432
|
// D1 — wire the layout-guard warning emitter so `return []` guard sites
|
|
@@ -1416,7 +1481,14 @@ export function createDocumentRuntime(
|
|
|
1416
1481
|
|
|
1417
1482
|
let cachedSurface:
|
|
1418
1483
|
| {
|
|
1419
|
-
|
|
1484
|
+
content: CanonicalDocumentEnvelope["content"];
|
|
1485
|
+
subParts: CanonicalDocumentEnvelope["subParts"];
|
|
1486
|
+
styles: CanonicalDocumentEnvelope["styles"];
|
|
1487
|
+
numbering: CanonicalDocumentEnvelope["numbering"];
|
|
1488
|
+
media: CanonicalDocumentEnvelope["media"];
|
|
1489
|
+
preservation: CanonicalDocumentEnvelope["preservation"];
|
|
1490
|
+
review: CanonicalDocumentEnvelope["review"];
|
|
1491
|
+
effectiveMarkupModeProvider: typeof effectiveMarkupModeProvider;
|
|
1420
1492
|
activeStoryKey: string;
|
|
1421
1493
|
/**
|
|
1422
1494
|
* Serialized viewport ranges at build time. A surface snapshot is
|
|
@@ -1424,9 +1496,9 @@ export function createDocumentRuntime(
|
|
|
1424
1496
|
* runtime's current `viewportRangesKey` matches — otherwise the
|
|
1425
1497
|
* cached snapshot realizes a different set of blocks as real vs
|
|
1426
1498
|
* placeholder-culled than the current runtime state demands.
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1499
|
+
* Do not key this cache on `revisionToken`: commits can advance the
|
|
1500
|
+
* token without changing the structural inputs surface projection
|
|
1501
|
+
* consumes.
|
|
1430
1502
|
*/
|
|
1431
1503
|
viewportRangesKey: string;
|
|
1432
1504
|
snapshot: RuntimeRenderSnapshot["surface"];
|
|
@@ -1435,10 +1507,7 @@ export function createDocumentRuntime(
|
|
|
1435
1507
|
let cachedCompatibility:
|
|
1436
1508
|
| {
|
|
1437
1509
|
revisionToken: string;
|
|
1438
|
-
|
|
1439
|
-
blockCount: number;
|
|
1440
|
-
/** Warning count at time of rebuild — warnings array gets remapped on every edit. */
|
|
1441
|
-
warningCount: number;
|
|
1510
|
+
structuralKey: string;
|
|
1442
1511
|
warnings: EditorState["warnings"];
|
|
1443
1512
|
fatalError: EditorState["fatalError"];
|
|
1444
1513
|
report: RuntimeRenderSnapshot["compatibility"];
|
|
@@ -1454,7 +1523,7 @@ export function createDocumentRuntime(
|
|
|
1454
1523
|
let cachedTrackedChanges:
|
|
1455
1524
|
| {
|
|
1456
1525
|
revisions: CanonicalDocumentEnvelope["review"]["revisions"];
|
|
1457
|
-
|
|
1526
|
+
comments: CanonicalDocumentEnvelope["review"]["comments"];
|
|
1458
1527
|
snapshot: TrackedChangesSnapshot;
|
|
1459
1528
|
}
|
|
1460
1529
|
| undefined;
|
|
@@ -1534,19 +1603,22 @@ export function createDocumentRuntime(
|
|
|
1534
1603
|
| undefined;
|
|
1535
1604
|
let cachedNavigation:
|
|
1536
1605
|
| {
|
|
1537
|
-
|
|
1606
|
+
document: CanonicalDocumentEnvelope;
|
|
1538
1607
|
activeStoryKey: string;
|
|
1608
|
+
workspaceMode: WorkspaceMode;
|
|
1609
|
+
zoomLevel: ZoomLevel;
|
|
1539
1610
|
selectionHead: number;
|
|
1540
1611
|
snapshot: DocumentNavigationSnapshot;
|
|
1541
1612
|
}
|
|
1542
1613
|
| undefined;
|
|
1543
1614
|
let cachedViewStateSnapshot:
|
|
1544
1615
|
| {
|
|
1545
|
-
revisionToken: string;
|
|
1546
1616
|
activeStoryKey: string;
|
|
1547
1617
|
selection: EditorState["selection"];
|
|
1548
1618
|
viewStateRef: ViewState;
|
|
1619
|
+
surface: RuntimeRenderSnapshot["surface"];
|
|
1549
1620
|
pageLayout: PageLayoutSnapshot | null | undefined;
|
|
1621
|
+
numbering: CanonicalDocumentEnvelope["numbering"];
|
|
1550
1622
|
snapshot: EditorViewStateSnapshot;
|
|
1551
1623
|
}
|
|
1552
1624
|
| undefined;
|
|
@@ -1605,7 +1677,14 @@ export function createDocumentRuntime(
|
|
|
1605
1677
|
: surfaceViewportRangesKey;
|
|
1606
1678
|
if (
|
|
1607
1679
|
cachedSurface &&
|
|
1608
|
-
cachedSurface.
|
|
1680
|
+
cachedSurface.content === document.content &&
|
|
1681
|
+
cachedSurface.subParts === document.subParts &&
|
|
1682
|
+
cachedSurface.styles === document.styles &&
|
|
1683
|
+
cachedSurface.numbering === document.numbering &&
|
|
1684
|
+
cachedSurface.media === document.media &&
|
|
1685
|
+
cachedSurface.preservation === document.preservation &&
|
|
1686
|
+
cachedSurface.review === document.review &&
|
|
1687
|
+
cachedSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider &&
|
|
1609
1688
|
cachedSurface.activeStoryKey === activeStoryKey &&
|
|
1610
1689
|
cachedSurface.viewportRangesKey === surfaceCacheKey
|
|
1611
1690
|
) {
|
|
@@ -1644,7 +1723,14 @@ export function createDocumentRuntime(
|
|
|
1644
1723
|
? snapshot
|
|
1645
1724
|
: enrichCulledPlaceholdersWithHeights(snapshot);
|
|
1646
1725
|
cachedSurface = {
|
|
1647
|
-
|
|
1726
|
+
content: document.content,
|
|
1727
|
+
subParts: document.subParts,
|
|
1728
|
+
styles: document.styles,
|
|
1729
|
+
numbering: document.numbering,
|
|
1730
|
+
media: document.media,
|
|
1731
|
+
preservation: document.preservation,
|
|
1732
|
+
review: document.review,
|
|
1733
|
+
effectiveMarkupModeProvider,
|
|
1648
1734
|
activeStoryKey,
|
|
1649
1735
|
viewportRangesKey: surfaceCacheKey,
|
|
1650
1736
|
snapshot: enrichedSnapshot,
|
|
@@ -1652,7 +1738,7 @@ export function createDocumentRuntime(
|
|
|
1652
1738
|
// Keep the scroll-path fingerprint in lockstep so a subsequent
|
|
1653
1739
|
// `maybeRefreshSurfaceForViewport` sees the freshly-built snapshot
|
|
1654
1740
|
// and short-circuits instead of paying a redundant projection.
|
|
1655
|
-
cachedSurfaceFingerprint = `${
|
|
1741
|
+
cachedSurfaceFingerprint = `${activeStoryKey}|${surfaceCacheKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
|
|
1656
1742
|
return enrichedSnapshot;
|
|
1657
1743
|
}
|
|
1658
1744
|
|
|
@@ -1761,8 +1847,7 @@ export function createDocumentRuntime(
|
|
|
1761
1847
|
function getCachedCompatibilityReport(
|
|
1762
1848
|
nextState: EditorState,
|
|
1763
1849
|
): RuntimeRenderSnapshot["compatibility"] {
|
|
1764
|
-
|
|
1765
|
-
const warningCount = nextState.warnings?.length ?? 0;
|
|
1850
|
+
let structuralKey: string | undefined;
|
|
1766
1851
|
if (cachedCompatibility) {
|
|
1767
1852
|
// Fast path 1: same revisionToken (selection move, surface-only refresh).
|
|
1768
1853
|
if (
|
|
@@ -1772,27 +1857,21 @@ export function createDocumentRuntime(
|
|
|
1772
1857
|
) {
|
|
1773
1858
|
return cachedCompatibility.report;
|
|
1774
1859
|
}
|
|
1775
|
-
|
|
1776
|
-
// count are stable (text-only edit). buildCompatibilityReport reads
|
|
1777
|
-
// block types, review counts, preservation, and warnings — NOT run text.
|
|
1778
|
-
// Block count + warning count + fatalError identity is an O(1) proxy:
|
|
1779
|
-
// if these are stable, the compatibility report output is unchanged.
|
|
1780
|
-
// `warnings` array gets remapped to a new reference on every commit via
|
|
1781
|
-
// remapReviewStateAfterContentChange, so we can't use reference equality.
|
|
1860
|
+
structuralKey = computeCompatibilityCacheKey(nextState);
|
|
1782
1861
|
if (
|
|
1783
|
-
cachedCompatibility.
|
|
1784
|
-
cachedCompatibility.warningCount === warningCount &&
|
|
1785
|
-
cachedCompatibility.fatalError === nextState.fatalError
|
|
1862
|
+
cachedCompatibility.structuralKey === structuralKey
|
|
1786
1863
|
) {
|
|
1787
1864
|
cachedCompatibility = {
|
|
1788
1865
|
...cachedCompatibility,
|
|
1789
1866
|
revisionToken: nextState.revisionToken,
|
|
1790
1867
|
warnings: nextState.warnings,
|
|
1868
|
+
fatalError: nextState.fatalError,
|
|
1791
1869
|
};
|
|
1792
1870
|
return cachedCompatibility.report;
|
|
1793
1871
|
}
|
|
1794
1872
|
}
|
|
1795
1873
|
|
|
1874
|
+
structuralKey ??= computeCompatibilityCacheKey(nextState);
|
|
1796
1875
|
const derived = createDerivedCompatibility(nextState);
|
|
1797
1876
|
recordPerfSample("snapshot.compatibility");
|
|
1798
1877
|
incrementInvalidationCounter("runtime.snapshot.compatibilityMisses");
|
|
@@ -1807,8 +1886,7 @@ export function createDocumentRuntime(
|
|
|
1807
1886
|
};
|
|
1808
1887
|
cachedCompatibility = {
|
|
1809
1888
|
revisionToken: nextState.revisionToken,
|
|
1810
|
-
|
|
1811
|
-
warningCount,
|
|
1889
|
+
structuralKey,
|
|
1812
1890
|
warnings: nextState.warnings,
|
|
1813
1891
|
fatalError: nextState.fatalError,
|
|
1814
1892
|
report,
|
|
@@ -1841,7 +1919,7 @@ export function createDocumentRuntime(
|
|
|
1841
1919
|
if (
|
|
1842
1920
|
cachedTrackedChanges &&
|
|
1843
1921
|
cachedTrackedChanges.revisions === nextState.document.review.revisions &&
|
|
1844
|
-
cachedTrackedChanges.
|
|
1922
|
+
cachedTrackedChanges.comments === nextState.document.review.comments
|
|
1845
1923
|
) {
|
|
1846
1924
|
return cachedTrackedChanges.snapshot;
|
|
1847
1925
|
}
|
|
@@ -1849,7 +1927,7 @@ export function createDocumentRuntime(
|
|
|
1849
1927
|
const snapshot = toPublicTrackedChangesSnapshot(nextState);
|
|
1850
1928
|
cachedTrackedChanges = {
|
|
1851
1929
|
revisions: nextState.document.review.revisions,
|
|
1852
|
-
|
|
1930
|
+
comments: nextState.document.review.comments,
|
|
1853
1931
|
snapshot,
|
|
1854
1932
|
};
|
|
1855
1933
|
return snapshot;
|
|
@@ -1899,8 +1977,10 @@ export function createDocumentRuntime(
|
|
|
1899
1977
|
);
|
|
1900
1978
|
if (
|
|
1901
1979
|
cachedNavigation &&
|
|
1902
|
-
cachedNavigation.
|
|
1903
|
-
cachedNavigation.activeStoryKey === activeStoryKey
|
|
1980
|
+
cachedNavigation.document === nextState.document &&
|
|
1981
|
+
cachedNavigation.activeStoryKey === activeStoryKey &&
|
|
1982
|
+
cachedNavigation.workspaceMode === viewState.workspaceMode &&
|
|
1983
|
+
cachedNavigation.zoomLevel === viewState.zoomLevel
|
|
1904
1984
|
) {
|
|
1905
1985
|
if (cachedNavigation.selectionHead === nextState.selection.head) {
|
|
1906
1986
|
return cachedNavigation.snapshot;
|
|
@@ -1912,16 +1992,20 @@ export function createDocumentRuntime(
|
|
|
1912
1992
|
snapshot.activeSectionIndex === cachedNavigation.snapshot.activeSectionIndex
|
|
1913
1993
|
) {
|
|
1914
1994
|
cachedNavigation = {
|
|
1915
|
-
|
|
1995
|
+
document: nextState.document,
|
|
1916
1996
|
activeStoryKey,
|
|
1997
|
+
workspaceMode: viewState.workspaceMode,
|
|
1998
|
+
zoomLevel: viewState.zoomLevel,
|
|
1917
1999
|
selectionHead: nextState.selection.head,
|
|
1918
2000
|
snapshot: cachedNavigation.snapshot,
|
|
1919
2001
|
};
|
|
1920
2002
|
return cachedNavigation.snapshot;
|
|
1921
2003
|
}
|
|
1922
2004
|
cachedNavigation = {
|
|
1923
|
-
|
|
2005
|
+
document: nextState.document,
|
|
1924
2006
|
activeStoryKey,
|
|
2007
|
+
workspaceMode: viewState.workspaceMode,
|
|
2008
|
+
zoomLevel: viewState.zoomLevel,
|
|
1925
2009
|
selectionHead: nextState.selection.head,
|
|
1926
2010
|
snapshot,
|
|
1927
2011
|
};
|
|
@@ -1932,8 +2016,10 @@ export function createDocumentRuntime(
|
|
|
1932
2016
|
recordPerfSample("snapshot.navigation");
|
|
1933
2017
|
incrementInvalidationCounter("runtime.snapshot.navigationMisses");
|
|
1934
2018
|
cachedNavigation = {
|
|
1935
|
-
|
|
2019
|
+
document: nextState.document,
|
|
1936
2020
|
activeStoryKey,
|
|
2021
|
+
workspaceMode: viewState.workspaceMode,
|
|
2022
|
+
zoomLevel: viewState.zoomLevel,
|
|
1937
2023
|
selectionHead: nextState.selection.head,
|
|
1938
2024
|
snapshot,
|
|
1939
2025
|
};
|
|
@@ -2115,6 +2201,10 @@ export function createDocumentRuntime(
|
|
|
2115
2201
|
}
|
|
2116
2202
|
|
|
2117
2203
|
if (block.kind === "sdt_block") {
|
|
2204
|
+
const lockedSdtMatch = matchWorkflowLockedSurfaceBlock(block, range);
|
|
2205
|
+
if (lockedSdtMatch) {
|
|
2206
|
+
return lockedSdtMatch;
|
|
2207
|
+
}
|
|
2118
2208
|
const match = findSurfaceOpaqueTargetIntersectingRange(block.children, range);
|
|
2119
2209
|
if (match) {
|
|
2120
2210
|
return match;
|
|
@@ -2146,6 +2236,49 @@ export function createDocumentRuntime(
|
|
|
2146
2236
|
return null;
|
|
2147
2237
|
}
|
|
2148
2238
|
|
|
2239
|
+
function matchWorkflowLockedSurfaceBlock(
|
|
2240
|
+
block: Extract<SurfaceBlockSnapshot, { kind: "sdt_block" }>,
|
|
2241
|
+
range: { from: number; to: number },
|
|
2242
|
+
): {
|
|
2243
|
+
from: number;
|
|
2244
|
+
to: number;
|
|
2245
|
+
label: string;
|
|
2246
|
+
blockedReasonCode: "workflow_preserve_only" | "workflow_blocked_import";
|
|
2247
|
+
} | null {
|
|
2248
|
+
if (!block.blockedReasonCode) {
|
|
2249
|
+
return null;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
const blockRange = {
|
|
2253
|
+
from: block.from,
|
|
2254
|
+
to: block.to > block.from ? block.to : block.from + 1,
|
|
2255
|
+
};
|
|
2256
|
+
const targetRange = normalizeCaretRangeForSurfaceIntersection(range);
|
|
2257
|
+
if (!rangesIntersect(blockRange, targetRange)) {
|
|
2258
|
+
return null;
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
return {
|
|
2262
|
+
from: blockRange.from,
|
|
2263
|
+
to: blockRange.to,
|
|
2264
|
+
label: block.label ?? block.alias ?? "Content control",
|
|
2265
|
+
blockedReasonCode: block.blockedReasonCode,
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
function normalizeCaretRangeForSurfaceIntersection(range: {
|
|
2270
|
+
from: number;
|
|
2271
|
+
to: number;
|
|
2272
|
+
}): { from: number; to: number } {
|
|
2273
|
+
if (range.to > range.from) {
|
|
2274
|
+
return range;
|
|
2275
|
+
}
|
|
2276
|
+
return {
|
|
2277
|
+
from: range.from,
|
|
2278
|
+
to: range.from + 1,
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2149
2282
|
function matchOpaqueInlineSegment(
|
|
2150
2283
|
segment: SurfaceInlineSegment,
|
|
2151
2284
|
range: { from: number; to: number },
|
|
@@ -2632,13 +2765,20 @@ export function createDocumentRuntime(
|
|
|
2632
2765
|
: {}),
|
|
2633
2766
|
},
|
|
2634
2767
|
);
|
|
2635
|
-
cachedSurfaceFingerprint = `${
|
|
2768
|
+
cachedSurfaceFingerprint = `${storyTargetKey(activeStory)}|${viewportRangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
|
|
2636
2769
|
// Refresh the cache with the just-built snapshot so a subsequent
|
|
2637
2770
|
// refreshRenderSnapshot (same revisionToken + activeStoryKey) hits cache.
|
|
2638
2771
|
// Without this repopulate, the next non-mutation refresh wastes a second
|
|
2639
2772
|
// createEditorSurfaceSnapshot call on an identical rebuild.
|
|
2640
2773
|
cachedSurface = {
|
|
2641
|
-
|
|
2774
|
+
content: state.document.content,
|
|
2775
|
+
subParts: state.document.subParts,
|
|
2776
|
+
styles: state.document.styles,
|
|
2777
|
+
numbering: state.document.numbering,
|
|
2778
|
+
media: state.document.media,
|
|
2779
|
+
preservation: state.document.preservation,
|
|
2780
|
+
review: state.document.review,
|
|
2781
|
+
effectiveMarkupModeProvider,
|
|
2642
2782
|
activeStoryKey: storyTargetKey(activeStory),
|
|
2643
2783
|
viewportRangesKey,
|
|
2644
2784
|
snapshot: newSurface,
|
|
@@ -2660,12 +2800,12 @@ export function createDocumentRuntime(
|
|
|
2660
2800
|
* a full projection + listener fan-out on every tick.
|
|
2661
2801
|
*
|
|
2662
2802
|
* Safe because every external input that can change the projection
|
|
2663
|
-
* output without
|
|
2664
|
-
* activeStory is wired to call `refreshSurfaceOnly` directly
|
|
2665
|
-
* `setEffectiveMarkupModeProvider`, `invalidateForMarkupModeChange`).
|
|
2803
|
+
* output without changing the tracked selection / viewportRanges /
|
|
2804
|
+
* activeStory tuple is wired to call `refreshSurfaceOnly` directly
|
|
2805
|
+
* (see `setEffectiveMarkupModeProvider`, `invalidateForMarkupModeChange`).
|
|
2666
2806
|
*/
|
|
2667
2807
|
function maybeRefreshSurfaceForViewport(): void {
|
|
2668
|
-
const fingerprint = `${
|
|
2808
|
+
const fingerprint = `${storyTargetKey(activeStory)}|${viewportRangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
|
|
2669
2809
|
if (cachedSurfaceFingerprint === fingerprint && cachedSurface) {
|
|
2670
2810
|
return;
|
|
2671
2811
|
}
|
|
@@ -2722,19 +2862,20 @@ export function createDocumentRuntime(
|
|
|
2722
2862
|
|
|
2723
2863
|
function getCachedViewStateSnapshot(): EditorViewStateSnapshot {
|
|
2724
2864
|
const activeStoryKey = storyTargetKey(activeStory);
|
|
2865
|
+
const surface = cachedRenderSnapshot.surface;
|
|
2725
2866
|
const pageLayout = cachedRenderSnapshot.pageLayout;
|
|
2726
2867
|
if (
|
|
2727
2868
|
cachedViewStateSnapshot &&
|
|
2728
|
-
cachedViewStateSnapshot.revisionToken === state.revisionToken &&
|
|
2729
2869
|
cachedViewStateSnapshot.activeStoryKey === activeStoryKey &&
|
|
2730
2870
|
cachedViewStateSnapshot.selection === state.selection &&
|
|
2731
2871
|
cachedViewStateSnapshot.viewStateRef === viewState &&
|
|
2732
|
-
cachedViewStateSnapshot.
|
|
2872
|
+
cachedViewStateSnapshot.surface === surface &&
|
|
2873
|
+
cachedViewStateSnapshot.pageLayout === pageLayout &&
|
|
2874
|
+
cachedViewStateSnapshot.numbering === state.document.numbering
|
|
2733
2875
|
) {
|
|
2734
2876
|
return cachedViewStateSnapshot.snapshot;
|
|
2735
2877
|
}
|
|
2736
2878
|
|
|
2737
|
-
const surface = cachedRenderSnapshot.surface;
|
|
2738
2879
|
const mainSurface =
|
|
2739
2880
|
activeStory.kind === "main"
|
|
2740
2881
|
? surface
|
|
@@ -2749,11 +2890,12 @@ export function createDocumentRuntime(
|
|
|
2749
2890
|
state.document.numbering,
|
|
2750
2891
|
);
|
|
2751
2892
|
cachedViewStateSnapshot = {
|
|
2752
|
-
revisionToken: state.revisionToken,
|
|
2753
2893
|
activeStoryKey,
|
|
2754
2894
|
selection: state.selection,
|
|
2755
2895
|
viewStateRef: viewState,
|
|
2896
|
+
surface,
|
|
2756
2897
|
pageLayout,
|
|
2898
|
+
numbering: state.document.numbering,
|
|
2757
2899
|
snapshot,
|
|
2758
2900
|
};
|
|
2759
2901
|
return snapshot;
|
|
@@ -3207,7 +3349,9 @@ export function createDocumentRuntime(
|
|
|
3207
3349
|
try {
|
|
3208
3350
|
const timestamp = clock();
|
|
3209
3351
|
const selection = target ? createSelectionFromPublicAnchor(target) : state.selection;
|
|
3352
|
+
const effectiveDocumentMode = workflowCoordinator.getEffectiveDocumentMode(selection);
|
|
3210
3353
|
if (
|
|
3354
|
+
effectiveDocumentMode !== "suggesting" &&
|
|
3211
3355
|
shouldPreserveEquivalentReplacement(formatting) &&
|
|
3212
3356
|
replacementTextMatchesCurrentRange(state.document, activeStory, selection, text)
|
|
3213
3357
|
) {
|
|
@@ -4384,6 +4528,27 @@ export function createDocumentRuntime(
|
|
|
4384
4528
|
getAllScopeCardModels() {
|
|
4385
4529
|
return workflowCoordinator.getAllScopeCardModels();
|
|
4386
4530
|
},
|
|
4531
|
+
getReviewOverlayLane(kind: WorkflowReviewOverlayLaneKind) {
|
|
4532
|
+
return workflowCoordinator.getReviewOverlayLane(kind);
|
|
4533
|
+
},
|
|
4534
|
+
subscribeReviewOverlayLane(
|
|
4535
|
+
kind: WorkflowReviewOverlayLaneKind,
|
|
4536
|
+
listener: WorkflowReviewOverlayLaneListener,
|
|
4537
|
+
) {
|
|
4538
|
+
if (kind === "presence") {
|
|
4539
|
+
throw new Error(
|
|
4540
|
+
"runtime.workflow.subscribeReviewOverlayLane: presence is awareness-owned; use the awareness-backed presence lane source",
|
|
4541
|
+
);
|
|
4542
|
+
}
|
|
4543
|
+
let lastSnapshot = workflowCoordinator.getReviewOverlayLane(kind);
|
|
4544
|
+
return runtime.subscribeToEvents((event) => {
|
|
4545
|
+
if (!shouldRefreshWorkflowReviewOverlayLane(kind, event)) return;
|
|
4546
|
+
const nextSnapshot = workflowCoordinator.getReviewOverlayLane(kind);
|
|
4547
|
+
if (areWorkflowReviewOverlayLaneSnapshotsEqual(lastSnapshot, nextSnapshot)) return;
|
|
4548
|
+
lastSnapshot = nextSnapshot;
|
|
4549
|
+
listener(nextSnapshot);
|
|
4550
|
+
});
|
|
4551
|
+
},
|
|
4387
4552
|
},
|
|
4388
4553
|
geometry: geometryFacet,
|
|
4389
4554
|
getLayoutFacet() {
|
|
@@ -4579,9 +4744,18 @@ export function createDocumentRuntime(
|
|
|
4579
4744
|
protectionSelection: refreshed.protectionSelection,
|
|
4580
4745
|
origin: createOrigin("api", clock()),
|
|
4581
4746
|
});
|
|
4747
|
+
// TOC refresh is an explicit structural API operation, not a typing
|
|
4748
|
+
// hot path. Re-realize the full surface so refreshed generated rows
|
|
4749
|
+
// remain inspectable instead of collapsing to selection-corridor
|
|
4750
|
+
// viewport placeholders immediately after the replacement.
|
|
4751
|
+
applyViewportRanges(null);
|
|
4752
|
+
cachedRenderSnapshot = refreshRenderSnapshot();
|
|
4582
4753
|
}
|
|
4583
4754
|
return refreshed.result;
|
|
4584
4755
|
},
|
|
4756
|
+
now() {
|
|
4757
|
+
return clock();
|
|
4758
|
+
},
|
|
4585
4759
|
getSessionState() {
|
|
4586
4760
|
const compatibility = createDerivedCompatibility(state);
|
|
4587
4761
|
const normalizedWorkflowOverlay = workflowCoordinator.getWorkflowOverlay();
|
|
@@ -4737,8 +4911,8 @@ export function createDocumentRuntime(
|
|
|
4737
4911
|
clearWorkflowMetadataDefinitions() {
|
|
4738
4912
|
workflowCoordinator.clearWorkflowMetadataDefinitions();
|
|
4739
4913
|
},
|
|
4740
|
-
setWorkflowMetadataEntries(entries) {
|
|
4741
|
-
workflowCoordinator.setWorkflowMetadataEntries(entries);
|
|
4914
|
+
setWorkflowMetadataEntries(entries, origin) {
|
|
4915
|
+
workflowCoordinator.setWorkflowMetadataEntries(entries, origin);
|
|
4742
4916
|
},
|
|
4743
4917
|
clearWorkflowMetadataEntries() {
|
|
4744
4918
|
workflowCoordinator.clearWorkflowMetadataEntries();
|
|
@@ -5025,6 +5199,7 @@ export function createDocumentRuntime(
|
|
|
5025
5199
|
maybeRefreshSurfaceForViewport();
|
|
5026
5200
|
},
|
|
5027
5201
|
};
|
|
5202
|
+
runtimeRef = runtime;
|
|
5028
5203
|
|
|
5029
5204
|
// Late-bind the workflow coordinator's dispatch accessor now that
|
|
5030
5205
|
// the runtime object exists. addScope / removeScope / setWorkflowOverlay /
|
|
@@ -5556,30 +5731,6 @@ export function createDocumentRuntime(
|
|
|
5556
5731
|
};
|
|
5557
5732
|
const opId = (command.origin as { opId?: string } | undefined)?.opId;
|
|
5558
5733
|
const selection = textOptions.selection ?? state.selection;
|
|
5559
|
-
if (
|
|
5560
|
-
activeStory.kind !== "main" &&
|
|
5561
|
-
workflowCoordinator.getEffectiveDocumentMode(selection) === "suggesting" &&
|
|
5562
|
-
command.type === "paragraph.split"
|
|
5563
|
-
) {
|
|
5564
|
-
const message = `"${command.type}" is not supported in suggesting mode for this story.`;
|
|
5565
|
-
emit({
|
|
5566
|
-
type: "command_blocked",
|
|
5567
|
-
documentId: state.documentId,
|
|
5568
|
-
command: textOptions.blockedCommandName ?? command.type,
|
|
5569
|
-
reasons: [{
|
|
5570
|
-
code: "suggesting_unsupported",
|
|
5571
|
-
message,
|
|
5572
|
-
storyTarget: activeStory,
|
|
5573
|
-
}],
|
|
5574
|
-
});
|
|
5575
|
-
return completeDispatch({
|
|
5576
|
-
kind: "rejected",
|
|
5577
|
-
refreshClass: "blocked",
|
|
5578
|
-
opId,
|
|
5579
|
-
newRevisionToken: "",
|
|
5580
|
-
blockedReasons: [{ code: "suggesting_unsupported", message }],
|
|
5581
|
-
});
|
|
5582
|
-
}
|
|
5583
5734
|
if (!textOptions.skipWorkflowGuard) {
|
|
5584
5735
|
const blockedReasons = workflowCoordinator.evaluateBlockedReasons(selection, command.type);
|
|
5585
5736
|
if (blockedReasons.length > 0) {
|
|
@@ -7145,14 +7296,6 @@ const NON_MUTATION_COMMANDS = new Set([
|
|
|
7145
7296
|
/** Mutation commands that are not yet supported in suggesting mode. */
|
|
7146
7297
|
const SUGGESTING_UNSUPPORTED_COMMANDS = new Set<string>([]);
|
|
7147
7298
|
|
|
7148
|
-
const SUGGESTING_SECONDARY_STORY_UNSUPPORTED_COMMANDS = new Set<string>([
|
|
7149
|
-
"text.insert",
|
|
7150
|
-
"text.delete-backward",
|
|
7151
|
-
"text.delete-forward",
|
|
7152
|
-
"text.insert-tab",
|
|
7153
|
-
"text.insert-hard-break",
|
|
7154
|
-
]);
|
|
7155
|
-
|
|
7156
7299
|
function isMutationCommand(command: EditorCommand): boolean {
|
|
7157
7300
|
return !NON_MUTATION_COMMANDS.has(command.type);
|
|
7158
7301
|
}
|
|
@@ -47,6 +47,17 @@ export function dispatchTextCommand(
|
|
|
47
47
|
}]);
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
+
if (
|
|
51
|
+
effectiveSelectionMode === "suggest" &&
|
|
52
|
+
command.type === "split-paragraph" &&
|
|
53
|
+
context.activeStory.kind !== "main"
|
|
54
|
+
) {
|
|
55
|
+
runtime.emitBlockedCommand(getMountedTextCommandName(command), [{
|
|
56
|
+
code: "suggesting_unsupported",
|
|
57
|
+
message: "Structural suggestions are only supported in the main story.",
|
|
58
|
+
}]);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
50
61
|
|
|
51
62
|
if (listAwareResult) {
|
|
52
63
|
deps.dispatchStoryMutationResult(runtime, context, listAwareResult, context.timestamp);
|