@beyondwork/docx-react-component 1.0.67 → 1.0.70
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/README.md +75 -932
- package/package.json +26 -27
- package/src/api/anchor-conversion.ts +43 -0
- package/src/api/editor-state-types.ts +2 -1
- package/src/api/public-types.ts +504 -101
- package/src/api/session-state.ts +4 -0
- package/src/api/v3/README.md +91 -0
- package/src/api/v3/_create.ts +146 -0
- package/src/api/v3/_layer-metadata.ts +362 -0
- package/src/api/v3/_mocks.ts +84 -0
- package/src/api/v3/_runtime-handle.ts +162 -0
- package/src/api/v3/_ux-response.ts +73 -0
- package/src/api/v3/ai/_metadata-audit.ts +225 -0
- package/src/api/v3/ai/attach.ts +235 -0
- package/src/api/v3/ai/bundle.ts +132 -0
- package/src/api/v3/ai/explain.ts +144 -0
- package/src/api/v3/ai/export.ts +54 -0
- package/src/api/v3/ai/inspect.ts +118 -0
- package/src/api/v3/ai/policy.ts +77 -0
- package/src/api/v3/ai/replacement.ts +341 -0
- package/src/api/v3/ai/resolve.ts +133 -0
- package/src/api/v3/index.ts +79 -0
- package/src/api/v3/runtime/chart.ts +310 -0
- package/src/api/v3/runtime/clipboard.ts +81 -0
- package/src/api/v3/runtime/collab.ts +331 -0
- package/src/api/v3/runtime/content.ts +236 -0
- package/src/api/v3/runtime/document.ts +282 -0
- package/src/api/v3/runtime/formatting.ts +186 -0
- package/src/api/v3/runtime/geometry.ts +349 -0
- package/src/api/v3/runtime/layout.ts +108 -0
- package/src/api/v3/runtime/review.ts +129 -0
- package/src/api/v3/runtime/search.ts +74 -0
- package/src/api/v3/runtime/table.ts +63 -0
- package/src/api/v3/runtime/workflow.ts +434 -0
- package/src/api/v3/ui/_context.ts +86 -0
- package/src/api/v3/ui/_create.ts +65 -0
- package/src/api/v3/ui/_types.ts +520 -0
- package/src/api/v3/ui/chrome-composition.ts +342 -0
- package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
- package/src/api/v3/ui/chrome.ts +476 -0
- package/src/api/v3/ui/debug.ts +124 -0
- package/src/api/v3/ui/index.ts +64 -0
- package/src/api/v3/ui/overlays-visibility.ts +170 -0
- package/src/api/v3/ui/overlays.ts +427 -0
- package/src/api/v3/ui/scope.ts +71 -0
- package/src/api/v3/ui/session.ts +100 -0
- package/src/api/v3/ui/surface.ts +170 -0
- package/src/api/v3/ui/viewport.ts +303 -0
- package/src/core/commands/index.ts +28 -6
- package/src/core/commands/list-commands.ts +3 -2
- package/src/core/commands/section-layout-commands.ts +9 -8
- package/src/core/schema/text-schema.ts +16 -0
- package/src/core/selection/mapping.ts +33 -72
- package/src/core/state/editor-state.ts +96 -189
- package/src/index.ts +23 -4
- package/src/io/chart-preview-resolver.ts +1 -1
- package/src/io/docx-session.ts +36 -4797
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +1 -1
- package/src/io/export/serialize-headers-footers.ts +6 -1
- package/src/io/export/serialize-main-document.ts +45 -0
- package/src/io/export/serialize-run-formatting.ts +17 -2
- package/src/io/export/twip.ts +1 -1
- package/src/io/normalize/normalize-text.ts +27 -20
- package/src/io/ooxml/chart/parse-series.ts +1 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +1 -1
- package/src/io/ooxml/classify-embedding.ts +83 -33
- package/src/io/ooxml/parse-fill.ts +1 -1
- package/src/io/ooxml/parse-main-document.ts +71 -1
- package/src/io/ooxml/parse-object.ts +14 -10
- package/src/io/ooxml/parse-run-formatting.ts +47 -1
- package/src/io/ooxml/property-grab-bag.ts +2 -2
- package/src/io/ooxml/units.ts +11 -0
- package/src/io/ooxml/workflow-payload.ts +282 -7
- package/src/model/anchor.ts +85 -0
- package/src/model/canonical-document.ts +351 -15
- package/src/model/chart-types.ts +1 -1
- package/src/model/layout/index.ts +83 -0
- package/src/model/layout/page-graph-types.ts +181 -0
- package/src/model/layout/page-layout-snapshot.ts +105 -0
- package/src/model/layout/resolved-layout-types.ts +47 -0
- package/src/model/layout/runtime-page-graph-types.ts +102 -0
- package/src/model/paragraph-scope-ids.ts +72 -0
- package/src/model/review/comment-types.ts +112 -0
- package/src/model/review/index.ts +2 -0
- package/src/model/review/revision-types.ts +215 -0
- package/src/model/snapshot.ts +32 -0
- package/src/review/store/comment-store.ts +21 -47
- package/src/review/store/revision-types.ts +40 -198
- package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
- package/src/runtime/collab/runtime-collab-sync.ts +13 -3
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
- package/src/runtime/debug/event-ring-buffer.ts +64 -0
- package/src/runtime/debug/probability-sampler.ts +18 -0
- package/src/runtime/debug/runtime-debug-facet.ts +67 -0
- package/src/runtime/debug/stage-tokens.ts +31 -0
- package/src/runtime/debug/telemetry-bus.ts +271 -0
- package/src/runtime/debug/types.ts +275 -0
- package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
- package/src/runtime/document-layout.ts +8 -6
- package/src/runtime/document-runtime.ts +843 -1141
- package/src/runtime/document-search.ts +1 -1
- package/src/runtime/edit-ops/index.ts +1 -1
- package/src/runtime/external-send-runtime.ts +1 -1
- package/src/runtime/formatting/document-lookup.ts +235 -0
- package/src/runtime/formatting/field/registry.ts +41 -0
- package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
- package/src/runtime/formatting/font-resolution.ts +83 -0
- package/src/runtime/formatting/formatting-context.ts +903 -0
- package/src/runtime/formatting/formatting-types.ts +157 -0
- package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
- package/src/runtime/formatting/index.ts +125 -0
- package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
- package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
- package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
- package/src/runtime/formatting/projector.ts +75 -0
- package/src/runtime/formatting/resolve-effective.ts +407 -0
- package/src/runtime/formatting/revision-display.ts +105 -0
- package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
- package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
- package/src/runtime/formatting/telemetry-bridge.ts +106 -0
- package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
- package/src/runtime/geometry/caret-geometry.ts +164 -0
- package/src/runtime/geometry/geometry-facet.ts +364 -0
- package/src/runtime/geometry/geometry-types.ts +256 -0
- package/src/runtime/geometry/hit-test.ts +125 -0
- package/src/runtime/geometry/index.ts +71 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
- package/src/runtime/geometry/invalidation.ts +35 -0
- package/src/runtime/geometry/object-handles.ts +77 -0
- package/src/runtime/geometry/overlay-rects.ts +85 -0
- package/src/runtime/geometry/project-anchors.ts +100 -0
- package/src/runtime/geometry/project-fragments.ts +216 -0
- package/src/runtime/geometry/projector.ts +129 -0
- package/src/runtime/geometry/replacement-envelope.ts +130 -0
- package/src/runtime/geometry/viewport.ts +218 -0
- package/src/runtime/layout/compat-input-ledger.ts +211 -0
- package/src/runtime/layout/index.ts +6 -1
- package/src/runtime/layout/inert-layout-facet.ts +12 -7
- package/src/runtime/layout/layout-engine-instance.ts +189 -11
- package/src/runtime/layout/layout-engine-version.ts +450 -1
- package/src/runtime/layout/layout-facet-types.ts +60 -0
- package/src/runtime/layout/layout-measurement-provider.ts +13 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
- package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
- package/src/runtime/layout/page-graph.ts +62 -209
- package/src/runtime/layout/page-story-resolver.ts +7 -12
- package/src/runtime/layout/paginated-layout-engine.ts +186 -11
- package/src/runtime/layout/project-block-fragments.ts +11 -0
- package/src/runtime/layout/projector.ts +90 -0
- package/src/runtime/layout/public-facet.ts +187 -442
- package/src/runtime/layout/resolved-formatting-state.ts +158 -26
- package/src/runtime/layout/table-render-plan.ts +1 -1
- package/src/runtime/prerender/cache-envelope.ts +6 -1
- package/src/runtime/prerender/prerender-document.ts +18 -23
- package/src/runtime/render/decoration-resolver.ts +1 -1
- package/src/runtime/render/render-frame-types.ts +20 -0
- package/src/runtime/render/render-kernel.ts +94 -25
- package/src/runtime/scopes/_formatting-seam.ts +262 -0
- package/src/runtime/scopes/_scope-dependencies.ts +49 -0
- package/src/runtime/scopes/action-validation.ts +356 -0
- package/src/runtime/scopes/attach-explanation.ts +102 -0
- package/src/runtime/scopes/audit-bundle.ts +71 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
- package/src/runtime/scopes/compile-scope.ts +262 -0
- package/src/runtime/scopes/compiler-service.ts +431 -0
- package/src/runtime/scopes/create-issue.ts +107 -0
- package/src/runtime/scopes/enumerate-scopes.ts +543 -0
- package/src/runtime/scopes/evidence.ts +233 -0
- package/src/runtime/scopes/index.ts +150 -0
- package/src/runtime/scopes/position-map.ts +214 -0
- package/src/runtime/scopes/preservation-boundary.ts +91 -0
- package/src/runtime/scopes/projector.ts +49 -0
- package/src/runtime/scopes/replaceability.ts +87 -0
- package/src/runtime/scopes/replacement/apply.ts +228 -0
- package/src/runtime/scopes/replacement/compile.ts +59 -0
- package/src/runtime/scopes/replacement/propose.ts +42 -0
- package/src/runtime/scopes/resolve-reference.ts +347 -0
- package/src/runtime/scopes/review-bundle.ts +141 -0
- package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
- package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
- package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
- package/src/runtime/scopes/scope-kinds/field.ts +65 -0
- package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
- package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
- package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
- package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
- package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
- package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
- package/src/runtime/scopes/scope-kinds/table.ts +55 -0
- package/src/runtime/scopes/scope-range.ts +208 -0
- package/src/runtime/scopes/semantic-scope-types.ts +454 -0
- package/src/runtime/scopes/workflow-overlap.ts +92 -0
- package/src/runtime/selection/index.ts +1 -1
- package/src/runtime/structure-ops/fragment-insert.ts +1 -1
- package/src/runtime/structure-ops/index.ts +1 -1
- package/src/runtime/surface-projection.ts +232 -262
- package/src/runtime/units.ts +4 -2
- package/src/runtime/workflow/coordinator.ts +1348 -0
- package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
- package/src/runtime/workflow/index.ts +25 -0
- package/src/runtime/workflow/markup-mode-policy.ts +98 -0
- package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
- package/src/runtime/workflow/metadata-persistence.ts +306 -0
- package/src/runtime/workflow/metadata-writer.ts +123 -0
- package/src/runtime/workflow/overlay-store.ts +690 -0
- package/src/runtime/workflow/projector.ts +127 -0
- package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
- package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
- package/src/runtime/workflow/rail/types.ts +198 -0
- package/src/runtime/workflow/scope-rail-composer.ts +39 -0
- package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
- package/src/runtime/workflow/scope-writer.ts +188 -0
- package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
- package/src/runtime/workflow/visibility-policy.ts +129 -0
- package/src/session/_sync-legacy.ts +66 -0
- package/src/session/export/embedded-reconstitute.ts +104 -0
- package/src/session/export/export-diagnostics.ts +85 -0
- package/src/session/export/export-validation.ts +110 -0
- package/src/session/export/index.ts +34 -0
- package/src/session/export/preservation-reattach.ts +30 -0
- package/src/session/export/serialize-dispatch.ts +165 -0
- package/src/session/export/stateful-export-pipeline.ts +432 -0
- package/src/session/export/stateful-export.ts +684 -0
- package/src/session/import/canonical-assembly.ts +227 -0
- package/src/session/import/diagnostics-session.ts +54 -0
- package/src/session/import/embedded-discovery.ts +225 -0
- package/src/session/import/embedded-offload.ts +337 -0
- package/src/session/import/import-diagnostics.ts +69 -0
- package/src/session/import/loader-types.ts +313 -0
- package/src/session/import/loader.ts +1834 -0
- package/src/session/import/normalize.ts +195 -0
- package/src/session/import/package-parts.ts +217 -0
- package/src/session/import/package-read.ts +195 -0
- package/src/session/import/parse-orchestration.ts +105 -0
- package/src/session/import/part-constants.ts +70 -0
- package/src/session/import/part-discovery.ts +94 -0
- package/src/session/import/preservation-index.ts +46 -0
- package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
- package/src/session/import/review-import.ts +508 -0
- package/src/session/import/styles-consolidation.ts +281 -0
- package/src/session/import/workflow-scope-import.ts +256 -0
- package/src/session/index.ts +37 -0
- package/src/session/session-state.ts +69 -0
- package/src/session/session.ts +532 -0
- package/src/session/shared/protection.ts +228 -0
- package/src/session/shared/session-utils.ts +82 -0
- package/src/session/types.ts +499 -0
- package/src/shell/chart-snapshots.ts +96 -0
- package/src/shell/media-previews.ts +85 -0
- package/src/shell/overlay-anchor-bridge.ts +53 -0
- package/src/shell/paste-adapter.ts +23 -0
- package/src/shell/ref-commands.ts +1697 -0
- package/src/shell/ref-utilities.ts +48 -0
- package/src/shell/search.ts +51 -0
- package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
- package/src/shell/ui-subscriber-channels.ts +81 -0
- package/src/shell/use-collab-sync.ts +116 -0
- package/src/ui/WordReviewEditor.tsx +496 -2051
- package/src/ui/editor-shell-view.tsx +30 -1
- package/src/ui/editor-surface-controller.tsx +49 -1
- package/src/ui/headless/revision-decoration-model.ts +83 -0
- package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
- package/src/ui/headless/scoped-chrome-policy.ts +2 -2
- package/src/ui/headless/selection-tool-context.ts +1 -1
- package/src/ui/headless/selection-tool-resolver.ts +1 -1
- package/src/ui/runtime-shortcut-dispatch.ts +46 -1
- package/src/ui/ui-controller-factory.ts +221 -0
- package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
- package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
- package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
- package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
- package/src/ui-tailwind/chart/render/area.tsx +3 -3
- package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
- package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
- package/src/ui-tailwind/chart/render/combo.tsx +2 -2
- package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
- package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
- package/src/ui-tailwind/chart/render/line.tsx +3 -3
- package/src/ui-tailwind/chart/render/pie.tsx +6 -6
- package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
- package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
- package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
- package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
- package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
- package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
- package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
- package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
- package/src/ui-tailwind/debug/README.md +57 -0
- package/src/ui-tailwind/debug/index.ts +3 -0
- package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
- package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
- package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
- package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
- package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
- package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
- package/src/ui-tailwind/index.ts +0 -5
- package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
- package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
- package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
- package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
- package/src/ui-tailwind/review-workspace/types.ts +408 -0
- package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
- package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
- package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
- package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
- package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
- package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
- package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
- package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
- package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
- package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
- package/src/ui-tailwind/ui-api-context.tsx +43 -0
- package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
- package/src/validation/compatibility-engine.ts +6 -6
- package/src/runtime/styles-cascade.ts +0 -33
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
- /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
- /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
- /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slice 1+2 enumeration — walks the canonical document and yields one
|
|
3
|
+
* `EnumeratedScope` per paragraph, heading, list-item, table, table-row,
|
|
4
|
+
* table-cell, field, comment-thread, or revision.
|
|
5
|
+
*
|
|
6
|
+
* ## Generic substrate (post 2026-04-22 taxonomy-genericization pass)
|
|
7
|
+
*
|
|
8
|
+
* The compiler does NOT carry any vertical vocabulary in its kind
|
|
9
|
+
* taxonomy. A paragraph that a host has wrapped in a marker-backed
|
|
10
|
+
* overlay scope (for example a CLM clause marker) stays `kind:
|
|
11
|
+
* "paragraph"` — but its `provenance` is `"marker-backed"` and the
|
|
12
|
+
* compiler propagates the overlay's metadata as generic `classifications`
|
|
13
|
+
* on the compiled scope. Hosts read classifications to drive
|
|
14
|
+
* vertical behaviour (CLM legal clause treatment, compliance
|
|
15
|
+
* annotations, etc.) without the compiler encoding that vocabulary.
|
|
16
|
+
*
|
|
17
|
+
* See `docs/wiki/use-case-domains/clm/semantic-scope-usage.md` for the
|
|
18
|
+
* CLM worked example.
|
|
19
|
+
*
|
|
20
|
+
* S3 (determinism): for identical inputs this function yields an
|
|
21
|
+
* identical handle sequence. Handle ids derive from structural position;
|
|
22
|
+
* no ambient state, no timestamps, no random ids.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type {
|
|
26
|
+
CanonicalDocument,
|
|
27
|
+
CommentThread,
|
|
28
|
+
DocumentRootNode,
|
|
29
|
+
FieldNode,
|
|
30
|
+
InlineNode,
|
|
31
|
+
ParagraphNode,
|
|
32
|
+
RevisionRecord,
|
|
33
|
+
TableCellNode,
|
|
34
|
+
TableNode,
|
|
35
|
+
TableRowNode,
|
|
36
|
+
} from "../../model/canonical-document.ts";
|
|
37
|
+
import {
|
|
38
|
+
buildParagraphScopeId,
|
|
39
|
+
detectParagraphKind,
|
|
40
|
+
} from "../../model/paragraph-scope-ids.ts";
|
|
41
|
+
export {
|
|
42
|
+
buildParagraphScopeId,
|
|
43
|
+
detectParagraphKind,
|
|
44
|
+
} from "../../model/paragraph-scope-ids.ts";
|
|
45
|
+
import type { CanonicalDocumentEnvelope } from "../../core/state/editor-state.ts";
|
|
46
|
+
import type {
|
|
47
|
+
WorkflowOverlay,
|
|
48
|
+
WorkflowScope,
|
|
49
|
+
WorkflowScopeMetadataField,
|
|
50
|
+
} from "./_scope-dependencies.ts";
|
|
51
|
+
|
|
52
|
+
import type { ScopeHandle, SemanticScopeKind } from "./semantic-scope-types.ts";
|
|
53
|
+
|
|
54
|
+
const MAIN_STORY = { kind: "main" as const };
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Paragraph-bearing variant — paragraph / heading / list-item.
|
|
58
|
+
*
|
|
59
|
+
* Classifications are collected from the overlay scope the paragraph
|
|
60
|
+
* belongs to (if marker-backed). Empty array when no overlay match.
|
|
61
|
+
*/
|
|
62
|
+
export interface ParagraphLikeEnumeratedScope {
|
|
63
|
+
readonly kind: "paragraph" | "heading" | "list-item";
|
|
64
|
+
readonly handle: ScopeHandle;
|
|
65
|
+
readonly paragraph: ParagraphNode;
|
|
66
|
+
readonly blockIndex: number;
|
|
67
|
+
readonly classifications: readonly string[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface TableEnumeratedScope {
|
|
71
|
+
readonly kind: "table";
|
|
72
|
+
readonly handle: ScopeHandle;
|
|
73
|
+
readonly table: TableNode;
|
|
74
|
+
readonly blockIndex: number;
|
|
75
|
+
readonly classifications: readonly string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface TableRowEnumeratedScope {
|
|
79
|
+
readonly kind: "table-row";
|
|
80
|
+
readonly handle: ScopeHandle;
|
|
81
|
+
readonly row: TableRowNode;
|
|
82
|
+
readonly table: TableNode;
|
|
83
|
+
readonly blockIndex: number;
|
|
84
|
+
readonly rowIndex: number;
|
|
85
|
+
readonly classifications: readonly string[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface TableCellEnumeratedScope {
|
|
89
|
+
readonly kind: "table-cell";
|
|
90
|
+
readonly handle: ScopeHandle;
|
|
91
|
+
readonly cell: TableCellNode;
|
|
92
|
+
readonly row: TableRowNode;
|
|
93
|
+
readonly table: TableNode;
|
|
94
|
+
readonly blockIndex: number;
|
|
95
|
+
readonly rowIndex: number;
|
|
96
|
+
readonly cellIndex: number;
|
|
97
|
+
readonly classifications: readonly string[];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface FieldEnumeratedScope {
|
|
101
|
+
readonly kind: "field";
|
|
102
|
+
readonly handle: ScopeHandle;
|
|
103
|
+
readonly field: FieldNode;
|
|
104
|
+
readonly paragraph: ParagraphNode;
|
|
105
|
+
readonly blockIndex: number;
|
|
106
|
+
readonly inlineIndex: number;
|
|
107
|
+
readonly classifications: readonly string[];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface CommentThreadEnumeratedScope {
|
|
111
|
+
readonly kind: "comment-thread";
|
|
112
|
+
readonly handle: ScopeHandle;
|
|
113
|
+
readonly thread: CommentThread;
|
|
114
|
+
readonly classifications: readonly string[];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface RevisionEnumeratedScope {
|
|
118
|
+
readonly kind: "revision";
|
|
119
|
+
readonly handle: ScopeHandle;
|
|
120
|
+
readonly revision: RevisionRecord;
|
|
121
|
+
readonly classifications: readonly string[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Discriminated by `kind`. Paragraph-bearing entries carry `paragraph`;
|
|
126
|
+
* table-bearing entries carry the matching canonical node; field entries
|
|
127
|
+
* carry the inline `FieldNode` + containing paragraph; review-store
|
|
128
|
+
* entries carry the thread / revision record directly.
|
|
129
|
+
*/
|
|
130
|
+
export type EnumeratedScope =
|
|
131
|
+
| ParagraphLikeEnumeratedScope
|
|
132
|
+
| TableEnumeratedScope
|
|
133
|
+
| TableRowEnumeratedScope
|
|
134
|
+
| TableCellEnumeratedScope
|
|
135
|
+
| FieldEnumeratedScope
|
|
136
|
+
| CommentThreadEnumeratedScope
|
|
137
|
+
| RevisionEnumeratedScope;
|
|
138
|
+
|
|
139
|
+
export interface EnumerateScopesInputs {
|
|
140
|
+
readonly overlay?: WorkflowOverlay | null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function buildParagraphSemanticPath(
|
|
144
|
+
kind: "paragraph" | "heading" | "list-item",
|
|
145
|
+
blockIndex: number,
|
|
146
|
+
paragraph: ParagraphNode,
|
|
147
|
+
): readonly string[] {
|
|
148
|
+
switch (kind) {
|
|
149
|
+
case "heading":
|
|
150
|
+
return [
|
|
151
|
+
"body",
|
|
152
|
+
"heading",
|
|
153
|
+
String(paragraph.outlineLevel ?? 0),
|
|
154
|
+
String(blockIndex),
|
|
155
|
+
];
|
|
156
|
+
case "list-item":
|
|
157
|
+
return [
|
|
158
|
+
"body",
|
|
159
|
+
"list-item",
|
|
160
|
+
paragraph.numbering?.numberingInstanceId ?? "unknown",
|
|
161
|
+
String(paragraph.numbering?.level ?? 0),
|
|
162
|
+
String(blockIndex),
|
|
163
|
+
];
|
|
164
|
+
case "paragraph":
|
|
165
|
+
default:
|
|
166
|
+
return ["body", "paragraph", String(blockIndex)];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function buildHandle(
|
|
171
|
+
scopeId: string,
|
|
172
|
+
documentId: string,
|
|
173
|
+
semanticPath: readonly string[],
|
|
174
|
+
provenance: ScopeHandle["provenance"],
|
|
175
|
+
rangePrecision: ScopeHandle["rangePrecision"],
|
|
176
|
+
parentScopeId?: string,
|
|
177
|
+
stableRef?: ScopeHandle["stableRef"],
|
|
178
|
+
): ScopeHandle {
|
|
179
|
+
return {
|
|
180
|
+
scopeId,
|
|
181
|
+
documentId,
|
|
182
|
+
storyTarget: MAIN_STORY,
|
|
183
|
+
semanticPath,
|
|
184
|
+
...(parentScopeId !== undefined ? { parentScopeId } : {}),
|
|
185
|
+
stableRef: stableRef ?? {
|
|
186
|
+
kind: "semantic-path",
|
|
187
|
+
value: semanticPath.join("/"),
|
|
188
|
+
},
|
|
189
|
+
provenance,
|
|
190
|
+
...(rangePrecision ? { rangePrecision } : {}),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Collect generic classification tags from a workflow overlay scope.
|
|
196
|
+
* The compiler does NOT interpret these strings — it surfaces them
|
|
197
|
+
* verbatim. Hosts define the vocabulary: CLM hosts use `"clause"`,
|
|
198
|
+
* `"domain:legal"`, `"label:Liability"`; compliance hosts may use
|
|
199
|
+
* `"issue"`, `"severity:high"`; etc.
|
|
200
|
+
*
|
|
201
|
+
* Grammar (convention, not enforced):
|
|
202
|
+
* - bare strings (`"clause"`, `"issue"`) for primary classifications
|
|
203
|
+
* - `key:value` pairs (`"domain:legal"`, `"label:Liability"`) for
|
|
204
|
+
* structured metadata
|
|
205
|
+
*
|
|
206
|
+
* Order is stable: `kind` field first (if present), then `domain`,
|
|
207
|
+
* then `label`, then remaining metadata keys sorted alphabetically.
|
|
208
|
+
* This keeps classification arrays byte-stable across compiles for
|
|
209
|
+
* identical inputs (S3 determinism).
|
|
210
|
+
*/
|
|
211
|
+
function classificationsFromOverlayScope(
|
|
212
|
+
scope: WorkflowScope,
|
|
213
|
+
): readonly string[] {
|
|
214
|
+
const tags: string[] = [];
|
|
215
|
+
const metadata = scope.metadata ?? [];
|
|
216
|
+
|
|
217
|
+
const kindField = metadata.find(
|
|
218
|
+
(f: WorkflowScopeMetadataField) => f.key === "kind",
|
|
219
|
+
);
|
|
220
|
+
if (kindField && typeof kindField.value === "string") {
|
|
221
|
+
tags.push(kindField.value);
|
|
222
|
+
}
|
|
223
|
+
if (typeof scope.domain === "string" && scope.domain.length > 0) {
|
|
224
|
+
tags.push(`domain:${scope.domain}`);
|
|
225
|
+
}
|
|
226
|
+
if (typeof scope.label === "string" && scope.label.length > 0) {
|
|
227
|
+
tags.push(`label:${scope.label}`);
|
|
228
|
+
}
|
|
229
|
+
const remaining = metadata
|
|
230
|
+
.filter(
|
|
231
|
+
(f: WorkflowScopeMetadataField) =>
|
|
232
|
+
f.key !== "kind" && typeof f.value === "string",
|
|
233
|
+
)
|
|
234
|
+
.sort((a, b) => a.key.localeCompare(b.key));
|
|
235
|
+
for (const field of remaining) {
|
|
236
|
+
if (typeof field.value === "string") {
|
|
237
|
+
tags.push(`${field.key}:${field.value}`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return Object.freeze(tags);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* For each marker-backed overlay scope, map scopeId → classifications.
|
|
245
|
+
* Built once per enumeration; reused across every paragraph / table /
|
|
246
|
+
* row / cell that might be marker-backed by one of these scopes.
|
|
247
|
+
*/
|
|
248
|
+
function buildClassificationIndex(
|
|
249
|
+
overlay: WorkflowOverlay | null | undefined,
|
|
250
|
+
): Map<string, readonly string[]> {
|
|
251
|
+
const out = new Map<string, readonly string[]>();
|
|
252
|
+
if (!overlay) return out;
|
|
253
|
+
for (const scope of overlay.scopes as readonly WorkflowScope[]) {
|
|
254
|
+
out.set(scope.scopeId, classificationsFromOverlayScope(scope));
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Walk paragraph children and return the first scope-marker id that
|
|
261
|
+
* *starts* inside the paragraph. When a paragraph carries multiple
|
|
262
|
+
* nested marker starts, the outermost structural interpretation is the
|
|
263
|
+
* first start marker — consistent with OOXML document order.
|
|
264
|
+
*
|
|
265
|
+
* Hosts that need richer multi-marker semantics should compose
|
|
266
|
+
* `classifications` from the matching overlay scope themselves.
|
|
267
|
+
*/
|
|
268
|
+
function paragraphFirstMarkerStart(
|
|
269
|
+
paragraph: ParagraphNode,
|
|
270
|
+
knownScopeIds: ReadonlySet<string>,
|
|
271
|
+
): string | null {
|
|
272
|
+
if (knownScopeIds.size === 0) return null;
|
|
273
|
+
for (const child of paragraph.children) {
|
|
274
|
+
if (
|
|
275
|
+
child.type === "scope_marker_start" &&
|
|
276
|
+
knownScopeIds.has(child.scopeId)
|
|
277
|
+
) {
|
|
278
|
+
return child.scopeId;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function enumerateFieldsInParagraph(
|
|
285
|
+
paragraph: ParagraphNode,
|
|
286
|
+
blockIndex: number,
|
|
287
|
+
documentId: string,
|
|
288
|
+
parentScopeId: string,
|
|
289
|
+
): FieldEnumeratedScope[] {
|
|
290
|
+
const out: FieldEnumeratedScope[] = [];
|
|
291
|
+
for (let i = 0; i < paragraph.children.length; i += 1) {
|
|
292
|
+
const child = paragraph.children[i] as InlineNode;
|
|
293
|
+
if (child.type !== "field") continue;
|
|
294
|
+
const semanticPath = [
|
|
295
|
+
"body",
|
|
296
|
+
"paragraph",
|
|
297
|
+
String(blockIndex),
|
|
298
|
+
"field",
|
|
299
|
+
String(i),
|
|
300
|
+
];
|
|
301
|
+
const scopeId = `field:${blockIndex}:${i}`;
|
|
302
|
+
const handle: ScopeHandle = {
|
|
303
|
+
scopeId,
|
|
304
|
+
documentId,
|
|
305
|
+
storyTarget: MAIN_STORY,
|
|
306
|
+
semanticPath,
|
|
307
|
+
parentScopeId,
|
|
308
|
+
stableRef: { kind: "semantic-path", value: semanticPath.join("/") },
|
|
309
|
+
provenance: "derived",
|
|
310
|
+
rangePrecision: "canonical",
|
|
311
|
+
};
|
|
312
|
+
out.push({
|
|
313
|
+
kind: "field",
|
|
314
|
+
handle,
|
|
315
|
+
field: child,
|
|
316
|
+
paragraph,
|
|
317
|
+
blockIndex,
|
|
318
|
+
inlineIndex: i,
|
|
319
|
+
classifications: Object.freeze<string[]>([]),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
return out;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function enumerateCommentThreads(
|
|
326
|
+
document: Pick<CanonicalDocument, "review"> | CanonicalDocumentEnvelope,
|
|
327
|
+
documentId: string,
|
|
328
|
+
): CommentThreadEnumeratedScope[] {
|
|
329
|
+
const review = (document as { review?: { comments?: Record<string, CommentThread> } }).review;
|
|
330
|
+
const comments = review?.comments;
|
|
331
|
+
if (!comments) return [];
|
|
332
|
+
const entries = Object.values(comments);
|
|
333
|
+
entries.sort((a, b) => a.commentId.localeCompare(b.commentId));
|
|
334
|
+
return entries.map((thread) => {
|
|
335
|
+
const semanticPath = ["review", "comment-thread", thread.commentId];
|
|
336
|
+
const provenance: ScopeHandle["provenance"] =
|
|
337
|
+
thread.anchor.kind === "detached" ? "detached" : "marker-backed";
|
|
338
|
+
const handle: ScopeHandle = {
|
|
339
|
+
scopeId: thread.commentId,
|
|
340
|
+
documentId,
|
|
341
|
+
storyTarget: MAIN_STORY,
|
|
342
|
+
semanticPath,
|
|
343
|
+
stableRef: { kind: "scope-id", value: thread.commentId },
|
|
344
|
+
provenance,
|
|
345
|
+
rangePrecision: "marker-backed",
|
|
346
|
+
};
|
|
347
|
+
return {
|
|
348
|
+
kind: "comment-thread",
|
|
349
|
+
handle,
|
|
350
|
+
thread,
|
|
351
|
+
classifications: Object.freeze<string[]>([]),
|
|
352
|
+
} as CommentThreadEnumeratedScope;
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function enumerateRevisions(
|
|
357
|
+
document: Pick<CanonicalDocument, "review"> | CanonicalDocumentEnvelope,
|
|
358
|
+
documentId: string,
|
|
359
|
+
): RevisionEnumeratedScope[] {
|
|
360
|
+
const review = (document as { review?: { revisions?: Record<string, RevisionRecord> } }).review;
|
|
361
|
+
const revisions = review?.revisions;
|
|
362
|
+
if (!revisions) return [];
|
|
363
|
+
const entries = Object.values(revisions);
|
|
364
|
+
entries.sort((a, b) => a.changeId.localeCompare(b.changeId));
|
|
365
|
+
return entries.map((revision) => {
|
|
366
|
+
const semanticPath = ["review", "revision", revision.changeId];
|
|
367
|
+
const provenance: ScopeHandle["provenance"] =
|
|
368
|
+
revision.anchor.kind === "detached" ? "detached" : "marker-backed";
|
|
369
|
+
const handle: ScopeHandle = {
|
|
370
|
+
scopeId: revision.changeId,
|
|
371
|
+
documentId,
|
|
372
|
+
storyTarget: MAIN_STORY,
|
|
373
|
+
semanticPath,
|
|
374
|
+
stableRef: { kind: "scope-id", value: revision.changeId },
|
|
375
|
+
provenance,
|
|
376
|
+
rangePrecision: "marker-backed",
|
|
377
|
+
};
|
|
378
|
+
return {
|
|
379
|
+
kind: "revision",
|
|
380
|
+
handle,
|
|
381
|
+
revision,
|
|
382
|
+
classifications: Object.freeze<string[]>([]),
|
|
383
|
+
} as RevisionEnumeratedScope;
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export function enumerateScopes(
|
|
388
|
+
document: Pick<CanonicalDocument, "content" | "docId" | "review"> | CanonicalDocumentEnvelope,
|
|
389
|
+
inputs: EnumerateScopesInputs = {},
|
|
390
|
+
): EnumeratedScope[] {
|
|
391
|
+
const envelope = document as CanonicalDocumentEnvelope;
|
|
392
|
+
const root: DocumentRootNode =
|
|
393
|
+
"content" in envelope
|
|
394
|
+
? (envelope.content as DocumentRootNode)
|
|
395
|
+
: (document as unknown as DocumentRootNode);
|
|
396
|
+
const documentId = (envelope.docId as unknown as string) ?? "";
|
|
397
|
+
const classificationIndex = buildClassificationIndex(inputs.overlay);
|
|
398
|
+
const knownOverlayScopeIds = new Set(classificationIndex.keys());
|
|
399
|
+
|
|
400
|
+
const results: EnumeratedScope[] = [];
|
|
401
|
+
for (let index = 0; index < root.children.length; index += 1) {
|
|
402
|
+
const block = root.children[index];
|
|
403
|
+
if (!block) continue;
|
|
404
|
+
|
|
405
|
+
if (block.type === "paragraph") {
|
|
406
|
+
const markerScopeId = paragraphFirstMarkerStart(
|
|
407
|
+
block,
|
|
408
|
+
knownOverlayScopeIds,
|
|
409
|
+
);
|
|
410
|
+
const kind = detectParagraphKind(block);
|
|
411
|
+
const semanticPath = buildParagraphSemanticPath(kind, index, block);
|
|
412
|
+
const scopeId =
|
|
413
|
+
markerScopeId !== null
|
|
414
|
+
? markerScopeId
|
|
415
|
+
: buildParagraphScopeId(kind, index, block);
|
|
416
|
+
const provenance: ScopeHandle["provenance"] =
|
|
417
|
+
markerScopeId !== null ? "marker-backed" : "derived";
|
|
418
|
+
const rangePrecision: ScopeHandle["rangePrecision"] =
|
|
419
|
+
markerScopeId !== null ? "marker-backed" : "canonical";
|
|
420
|
+
const handle = buildHandle(
|
|
421
|
+
scopeId,
|
|
422
|
+
documentId,
|
|
423
|
+
semanticPath,
|
|
424
|
+
provenance,
|
|
425
|
+
rangePrecision,
|
|
426
|
+
undefined,
|
|
427
|
+
markerScopeId !== null
|
|
428
|
+
? { kind: "scope-id", value: markerScopeId }
|
|
429
|
+
: undefined,
|
|
430
|
+
);
|
|
431
|
+
const classifications =
|
|
432
|
+
markerScopeId !== null
|
|
433
|
+
? (classificationIndex.get(markerScopeId) ?? Object.freeze<string[]>([]))
|
|
434
|
+
: Object.freeze<string[]>([]);
|
|
435
|
+
results.push({
|
|
436
|
+
kind,
|
|
437
|
+
handle,
|
|
438
|
+
paragraph: block,
|
|
439
|
+
blockIndex: index,
|
|
440
|
+
classifications,
|
|
441
|
+
});
|
|
442
|
+
// Fields inside this paragraph carry the paragraph's real scopeId
|
|
443
|
+
// as their parent — NOT a hardcoded `para:${index}`, which would
|
|
444
|
+
// be wrong whenever the paragraph upgraded to heading / list-item.
|
|
445
|
+
const fields = enumerateFieldsInParagraph(block, index, documentId, scopeId);
|
|
446
|
+
for (const field of fields) results.push(field);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (block.type === "table") {
|
|
451
|
+
const tableSemanticPath = ["body", "table", String(index)];
|
|
452
|
+
const tableScopeId = `table:${index}`;
|
|
453
|
+
const tableHandle = buildHandle(
|
|
454
|
+
tableScopeId,
|
|
455
|
+
documentId,
|
|
456
|
+
tableSemanticPath,
|
|
457
|
+
"derived",
|
|
458
|
+
"canonical",
|
|
459
|
+
);
|
|
460
|
+
results.push({
|
|
461
|
+
kind: "table",
|
|
462
|
+
handle: tableHandle,
|
|
463
|
+
table: block,
|
|
464
|
+
blockIndex: index,
|
|
465
|
+
classifications: Object.freeze<string[]>([]),
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
for (let rowIdx = 0; rowIdx < block.rows.length; rowIdx += 1) {
|
|
469
|
+
const row = block.rows[rowIdx]!;
|
|
470
|
+
const rowSemanticPath = [
|
|
471
|
+
"body",
|
|
472
|
+
"table",
|
|
473
|
+
String(index),
|
|
474
|
+
"row",
|
|
475
|
+
String(rowIdx),
|
|
476
|
+
];
|
|
477
|
+
const rowScopeId = `row:${index}:${rowIdx}`;
|
|
478
|
+
const rowHandle = buildHandle(
|
|
479
|
+
rowScopeId,
|
|
480
|
+
documentId,
|
|
481
|
+
rowSemanticPath,
|
|
482
|
+
"derived",
|
|
483
|
+
"synthetic",
|
|
484
|
+
tableScopeId,
|
|
485
|
+
);
|
|
486
|
+
results.push({
|
|
487
|
+
kind: "table-row",
|
|
488
|
+
handle: rowHandle,
|
|
489
|
+
row,
|
|
490
|
+
table: block,
|
|
491
|
+
blockIndex: index,
|
|
492
|
+
rowIndex: rowIdx,
|
|
493
|
+
classifications: Object.freeze<string[]>([]),
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx += 1) {
|
|
497
|
+
const cell = row.cells[cellIdx]!;
|
|
498
|
+
const cellSemanticPath = [
|
|
499
|
+
"body",
|
|
500
|
+
"table",
|
|
501
|
+
String(index),
|
|
502
|
+
"row",
|
|
503
|
+
String(rowIdx),
|
|
504
|
+
"cell",
|
|
505
|
+
String(cellIdx),
|
|
506
|
+
];
|
|
507
|
+
const cellScopeId = `cell:${index}:${rowIdx}:${cellIdx}`;
|
|
508
|
+
const cellHandle = buildHandle(
|
|
509
|
+
cellScopeId,
|
|
510
|
+
documentId,
|
|
511
|
+
cellSemanticPath,
|
|
512
|
+
"derived",
|
|
513
|
+
"synthetic",
|
|
514
|
+
rowScopeId,
|
|
515
|
+
);
|
|
516
|
+
results.push({
|
|
517
|
+
kind: "table-cell",
|
|
518
|
+
handle: cellHandle,
|
|
519
|
+
cell,
|
|
520
|
+
row,
|
|
521
|
+
table: block,
|
|
522
|
+
blockIndex: index,
|
|
523
|
+
rowIndex: rowIdx,
|
|
524
|
+
cellIndex: cellIdx,
|
|
525
|
+
classifications: Object.freeze<string[]>([]),
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Review-store scopes — threads + revisions — enumerate after document
|
|
533
|
+
// walk so their block ordering in `results` stays stable (all block scopes
|
|
534
|
+
// first, then review).
|
|
535
|
+
for (const thread of enumerateCommentThreads(document, documentId)) {
|
|
536
|
+
results.push(thread);
|
|
537
|
+
}
|
|
538
|
+
for (const revision of enumerateRevisions(document, documentId)) {
|
|
539
|
+
results.push(revision);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return results;
|
|
543
|
+
}
|