@beyondwork/docx-react-component 1.0.66 → 1.0.69
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 -931
- 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 -4795
- 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,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Styles-catalog + secondary-story media-catalog consolidation helpers.
|
|
3
|
+
*
|
|
4
|
+
* Slice 5e-6b of refactor/01 package-session. Extracted from
|
|
5
|
+
* `src/io/docx-session.ts`:
|
|
6
|
+
*
|
|
7
|
+
* - `buildStylesCatalog` — build the final `styles` facet from the
|
|
8
|
+
* parsed `styles.xml` (or a synthetic fallback) plus any referenced
|
|
9
|
+
* style ids the package didn't define.
|
|
10
|
+
* - `filterValidStyleIds` — narrow a parsed catalog to entries whose
|
|
11
|
+
* styleId matches the canonical model pattern.
|
|
12
|
+
* - `mergeSecondaryStoryMediaCatalog` — walk header / footer / footnote
|
|
13
|
+
* / endnote blocks and register every referenced media id into the
|
|
14
|
+
* media catalog (so images referenced only from a secondary story
|
|
15
|
+
* surface in `MediaCatalog.items`).
|
|
16
|
+
*
|
|
17
|
+
* Plus the one supporting helper these three compose over:
|
|
18
|
+
* `collectReferencedParagraphStyleIds`.
|
|
19
|
+
*
|
|
20
|
+
* Contract P6 clean: depends only on `src/model/**` + `src/io/**`
|
|
21
|
+
* type surfaces. No runtime / UI / core / review imports.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
BlockNode,
|
|
26
|
+
CanonicalDocument,
|
|
27
|
+
FootnoteCollection,
|
|
28
|
+
FooterDocument,
|
|
29
|
+
HeaderDocument,
|
|
30
|
+
InlineNode,
|
|
31
|
+
MediaCatalog,
|
|
32
|
+
SubPartsCatalog,
|
|
33
|
+
} from "../../model/canonical-document.ts";
|
|
34
|
+
import type { ParseStylesResult } from "../../io/ooxml/parse-styles.ts";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Canonical model styleId validation pattern — styleIds that don't match
|
|
38
|
+
* are excluded from the catalog to avoid snapshot validation failures.
|
|
39
|
+
*/
|
|
40
|
+
export const VALID_STYLE_ID = /^[A-Za-z_][A-Za-z0-9._-]{0,127}$/;
|
|
41
|
+
|
|
42
|
+
/** Walk the canonical content tree (and optional sub-parts) and collect
|
|
43
|
+
* every `styleId` referenced by a paragraph / table / structural block. */
|
|
44
|
+
export function collectReferencedParagraphStyleIds(
|
|
45
|
+
content: CanonicalDocument["content"],
|
|
46
|
+
subParts?: SubPartsCatalog,
|
|
47
|
+
): Set<string> {
|
|
48
|
+
const styleIds = new Set<string>();
|
|
49
|
+
|
|
50
|
+
const visitBlocks = (blocks: ReadonlyArray<BlockNode>) => {
|
|
51
|
+
for (const block of blocks) {
|
|
52
|
+
if ("styleId" in block && typeof block.styleId === "string" && block.styleId.length > 0) {
|
|
53
|
+
styleIds.add(block.styleId);
|
|
54
|
+
}
|
|
55
|
+
if (block.type === "table") {
|
|
56
|
+
for (const row of block.rows) {
|
|
57
|
+
for (const cell of row.cells) {
|
|
58
|
+
visitBlocks(cell.children);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} else if (block.type === "sdt" || block.type === "custom_xml") {
|
|
62
|
+
visitBlocks(block.children);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
visitBlocks(content.children);
|
|
68
|
+
if (subParts) {
|
|
69
|
+
for (const header of subParts.headers) {
|
|
70
|
+
visitBlocks(header.blocks);
|
|
71
|
+
}
|
|
72
|
+
for (const footer of subParts.footers) {
|
|
73
|
+
visitBlocks(footer.blocks);
|
|
74
|
+
}
|
|
75
|
+
if (subParts.footnoteCollection) {
|
|
76
|
+
for (const note of Object.values(subParts.footnoteCollection.footnotes)) {
|
|
77
|
+
visitBlocks(note.blocks);
|
|
78
|
+
}
|
|
79
|
+
for (const note of Object.values(subParts.footnoteCollection.endnotes)) {
|
|
80
|
+
visitBlocks(note.blocks);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return styleIds;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Narrow a parsed catalog to entries whose styleId matches the
|
|
89
|
+
* canonical model pattern. Used defensively when the package
|
|
90
|
+
* `styles.xml` carries legacy entries (e.g. numeric-only ids from Word). */
|
|
91
|
+
export function filterValidStyleIds(
|
|
92
|
+
catalog: CanonicalDocument["styles"],
|
|
93
|
+
): CanonicalDocument["styles"] {
|
|
94
|
+
const filterRecord = <T extends { styleId: string }>(
|
|
95
|
+
record: Record<string, T>,
|
|
96
|
+
): Record<string, T> => {
|
|
97
|
+
const result: Record<string, T> = {};
|
|
98
|
+
for (const [key, value] of Object.entries(record)) {
|
|
99
|
+
if (VALID_STYLE_ID.test(key)) {
|
|
100
|
+
result[key] = value;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
paragraphs: filterRecord(catalog.paragraphs),
|
|
108
|
+
characters: filterRecord(catalog.characters),
|
|
109
|
+
tables: filterRecord(catalog.tables),
|
|
110
|
+
...(catalog.latentStyles ? { latentStyles: catalog.latentStyles } : {}),
|
|
111
|
+
...(catalog.docDefaults ? { docDefaults: catalog.docDefaults } : {}),
|
|
112
|
+
...(catalog.fromPackage !== undefined ? { fromPackage: catalog.fromPackage } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Build the `styles` facet. When the package shipped a `styles.xml`,
|
|
117
|
+
* the parsed catalog is filtered through {@link filterValidStyleIds}
|
|
118
|
+
* and any referenced-but-undefined style ids are synthesized as
|
|
119
|
+
* default entries. When there is no `styles.xml`, every referenced
|
|
120
|
+
* paragraph style becomes a synthetic entry. */
|
|
121
|
+
export function buildStylesCatalog(
|
|
122
|
+
parsedStyles: ParseStylesResult | undefined,
|
|
123
|
+
content: CanonicalDocument["content"],
|
|
124
|
+
subParts?: SubPartsCatalog,
|
|
125
|
+
): CanonicalDocument["styles"] {
|
|
126
|
+
if (parsedStyles?.fromPackage) {
|
|
127
|
+
const catalog = filterValidStyleIds(parsedStyles.catalog);
|
|
128
|
+
|
|
129
|
+
const referencedIds = collectReferencedParagraphStyleIds(content, subParts);
|
|
130
|
+
for (const styleId of referencedIds) {
|
|
131
|
+
if (!catalog.paragraphs[styleId] && VALID_STYLE_ID.test(styleId)) {
|
|
132
|
+
catalog.paragraphs[styleId] = {
|
|
133
|
+
styleId,
|
|
134
|
+
displayName: styleId,
|
|
135
|
+
kind: "paragraph",
|
|
136
|
+
isDefault: styleId === "Normal",
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
...catalog,
|
|
142
|
+
fromPackage: true,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const paragraphStyles = Object.fromEntries(
|
|
147
|
+
[...collectReferencedParagraphStyleIds(content, subParts)]
|
|
148
|
+
.sort((left, right) => left.localeCompare(right))
|
|
149
|
+
.filter((styleId) => VALID_STYLE_ID.test(styleId))
|
|
150
|
+
.map((styleId) => [
|
|
151
|
+
styleId,
|
|
152
|
+
{
|
|
153
|
+
styleId,
|
|
154
|
+
displayName: styleId,
|
|
155
|
+
kind: "paragraph" as const,
|
|
156
|
+
isDefault: styleId === "Normal",
|
|
157
|
+
},
|
|
158
|
+
]),
|
|
159
|
+
);
|
|
160
|
+
return {
|
|
161
|
+
paragraphs: paragraphStyles,
|
|
162
|
+
characters: {},
|
|
163
|
+
tables: {},
|
|
164
|
+
fromPackage: false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Walk the secondary-story blocks (headers, footers, footnotes,
|
|
169
|
+
* endnotes) and register every referenced image / drawing-frame
|
|
170
|
+
* media id into the media catalog. Called after the primary story
|
|
171
|
+
* has contributed its own entries so we only ADD here — existing
|
|
172
|
+
* entries win. */
|
|
173
|
+
export function mergeSecondaryStoryMediaCatalog(
|
|
174
|
+
media: MediaCatalog,
|
|
175
|
+
input: {
|
|
176
|
+
headers: readonly HeaderDocument[];
|
|
177
|
+
footers: readonly FooterDocument[];
|
|
178
|
+
footnoteCollection?: FootnoteCollection;
|
|
179
|
+
mediaParts: ReadonlyMap<string, { path: string; contentType: string }>;
|
|
180
|
+
},
|
|
181
|
+
): MediaCatalog {
|
|
182
|
+
const items = { ...media.items };
|
|
183
|
+
let changed = false;
|
|
184
|
+
|
|
185
|
+
const registerMediaItem = (
|
|
186
|
+
mediaId: string,
|
|
187
|
+
record: Omit<NonNullable<MediaCatalog["items"][string]>, "mediaId">,
|
|
188
|
+
) => {
|
|
189
|
+
const existing = items[mediaId];
|
|
190
|
+
items[mediaId] = existing
|
|
191
|
+
? {
|
|
192
|
+
...existing,
|
|
193
|
+
...record,
|
|
194
|
+
mediaId,
|
|
195
|
+
}
|
|
196
|
+
: {
|
|
197
|
+
mediaId,
|
|
198
|
+
...record,
|
|
199
|
+
};
|
|
200
|
+
changed = true;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const visitInline = (node: InlineNode) => {
|
|
204
|
+
if (node.type === "image") {
|
|
205
|
+
const packagePartName = `/${node.mediaId.slice("media:".length)}`;
|
|
206
|
+
registerMediaItem(node.mediaId, {
|
|
207
|
+
contentType:
|
|
208
|
+
items[node.mediaId]?.contentType ??
|
|
209
|
+
input.mediaParts.get(packagePartName)?.contentType ??
|
|
210
|
+
"application/octet-stream",
|
|
211
|
+
filename: packagePartName.slice(packagePartName.lastIndexOf("/") + 1) || "image.bin",
|
|
212
|
+
packagePartName,
|
|
213
|
+
...(node.altText ? { altText: node.altText } : {}),
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (node.type === "drawing_frame" && node.content.type === "picture" && node.content.mediaId) {
|
|
218
|
+
const packagePartName =
|
|
219
|
+
typeof node.content.packagePartName === "string" && node.content.packagePartName.length > 0
|
|
220
|
+
? node.content.packagePartName
|
|
221
|
+
: `/${node.content.mediaId.slice("media:".length)}`;
|
|
222
|
+
registerMediaItem(node.content.mediaId, {
|
|
223
|
+
contentType:
|
|
224
|
+
items[node.content.mediaId]?.contentType ??
|
|
225
|
+
input.mediaParts.get(packagePartName)?.contentType ??
|
|
226
|
+
"application/octet-stream",
|
|
227
|
+
filename: packagePartName.slice(packagePartName.lastIndexOf("/") + 1) || "image.bin",
|
|
228
|
+
packagePartName,
|
|
229
|
+
relationshipId: node.content.blipRef,
|
|
230
|
+
...(node.anchor.docPr?.descr ? { altText: node.anchor.docPr.descr } : {}),
|
|
231
|
+
widthEmu: node.anchor.extent.widthEmu,
|
|
232
|
+
heightEmu: node.anchor.extent.heightEmu,
|
|
233
|
+
});
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (node.type === "hyperlink" || node.type === "field") {
|
|
237
|
+
for (const child of node.children) {
|
|
238
|
+
visitInline(child);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const visitBlocks = (blocks: ReadonlyArray<BlockNode>) => {
|
|
244
|
+
for (const block of blocks) {
|
|
245
|
+
if (block.type === "paragraph") {
|
|
246
|
+
for (const child of block.children) {
|
|
247
|
+
visitInline(child);
|
|
248
|
+
}
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (block.type === "table") {
|
|
252
|
+
for (const row of block.rows) {
|
|
253
|
+
for (const cell of row.cells) {
|
|
254
|
+
visitBlocks(cell.children);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (block.type === "sdt" || block.type === "custom_xml") {
|
|
260
|
+
visitBlocks(block.children);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
for (const header of input.headers) {
|
|
266
|
+
visitBlocks(header.blocks);
|
|
267
|
+
}
|
|
268
|
+
for (const footer of input.footers) {
|
|
269
|
+
visitBlocks(footer.blocks);
|
|
270
|
+
}
|
|
271
|
+
if (input.footnoteCollection) {
|
|
272
|
+
for (const note of Object.values(input.footnoteCollection.footnotes)) {
|
|
273
|
+
visitBlocks(note.blocks);
|
|
274
|
+
}
|
|
275
|
+
for (const note of Object.values(input.footnoteCollection.endnotes)) {
|
|
276
|
+
visitBlocks(note.blocks);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return changed ? { ...media, items } : media;
|
|
281
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLM-workflow translation helpers extracted from `src/io/docx-session.ts`
|
|
3
|
+
* (slice 5e-6e). These functions lift `CLM:<TAG>:<description>` comment
|
|
4
|
+
* directives into workflow scopes + work items on a `WorkflowOverlay`,
|
|
5
|
+
* and auto-resolve the originating comment threads.
|
|
6
|
+
*
|
|
7
|
+
* P6-clean: `CommentThread` reaches through `src/model/review/`; every
|
|
8
|
+
* workflow type comes from `src/api/public-types.ts` (an allowed surface
|
|
9
|
+
* for the session layer). Anchor-shape conversion reaches through the
|
|
10
|
+
* shared boundary helper at `src/api/anchor-conversion.ts` (relocated in
|
|
11
|
+
* slice 5e-6g).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { toPublicAnchorProjection } from "../../api/anchor-conversion.ts";
|
|
15
|
+
import type {
|
|
16
|
+
WorkflowMetadataSnapshot,
|
|
17
|
+
WorkflowOverlay,
|
|
18
|
+
WorkflowScope,
|
|
19
|
+
WorkflowScopeMetadataField,
|
|
20
|
+
WorkflowWorkItem,
|
|
21
|
+
} from "../../api/public-types.ts";
|
|
22
|
+
import type { CommentThread } from "../../model/review/comment-types.ts";
|
|
23
|
+
import {
|
|
24
|
+
rangesIntersect,
|
|
25
|
+
resolveImportedCommentThreadOnTranslation,
|
|
26
|
+
} from "./review-import.ts";
|
|
27
|
+
|
|
28
|
+
export function translateClmCommentsToWorkflow(input: {
|
|
29
|
+
comments: readonly CommentThread[];
|
|
30
|
+
workflowOverlay?: WorkflowOverlay;
|
|
31
|
+
workflowMetadata?: WorkflowMetadataSnapshot;
|
|
32
|
+
timestamp: string;
|
|
33
|
+
}): {
|
|
34
|
+
comments: CommentThread[];
|
|
35
|
+
workflowOverlay?: WorkflowOverlay;
|
|
36
|
+
workflowMetadata?: WorkflowMetadataSnapshot;
|
|
37
|
+
} {
|
|
38
|
+
const nextComments = input.comments.map((thread) => structuredClone(thread));
|
|
39
|
+
let nextOverlay = input.workflowOverlay ? structuredClone(input.workflowOverlay) : undefined;
|
|
40
|
+
let overlayChanged = false;
|
|
41
|
+
|
|
42
|
+
for (const [index, thread] of nextComments.entries()) {
|
|
43
|
+
const directive = parseClmCommentDirective(thread);
|
|
44
|
+
if (!directive || thread.anchor.kind !== "range") {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!nextOverlay) {
|
|
49
|
+
nextOverlay = {
|
|
50
|
+
overlayVersion: "workflow-overlay/1",
|
|
51
|
+
scopes: [],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const existingScope = findExistingClmScope(nextOverlay.scopes, directive);
|
|
56
|
+
if (!existingScope) {
|
|
57
|
+
const version = getNextClmScopeVersion(nextOverlay.scopes, thread.anchor);
|
|
58
|
+
const scopeId = `clm-scope-${thread.commentId}-v${version}`;
|
|
59
|
+
const workItem = directive.tag === "TASK"
|
|
60
|
+
? createClmWorkflowWorkItem(thread, directive.description, scopeId)
|
|
61
|
+
: undefined;
|
|
62
|
+
const scope = createClmWorkflowScope(thread, directive, version, scopeId, workItem?.workItemId);
|
|
63
|
+
|
|
64
|
+
nextOverlay.scopes = [...nextOverlay.scopes, scope];
|
|
65
|
+
if (workItem) {
|
|
66
|
+
nextOverlay.workItems = [...(nextOverlay.workItems ?? []), workItem];
|
|
67
|
+
if (!nextOverlay.activeWorkItemId) {
|
|
68
|
+
nextOverlay.activeWorkItemId = workItem.workItemId;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
overlayChanged = true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
nextComments[index] = resolveImportedCommentThreadOnTranslation(thread, input.timestamp);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
comments: nextComments,
|
|
79
|
+
workflowOverlay: overlayChanged || input.workflowOverlay ? nextOverlay : undefined,
|
|
80
|
+
workflowMetadata: input.workflowMetadata,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function parseClmCommentDirective(
|
|
85
|
+
thread: CommentThread,
|
|
86
|
+
): { tag: "TASK" | "READ" | "COMMENT" | "EDIT"; description: string; sourceCommentId: string; sourceCommentDurableId?: string; sourceCommentParaId?: string; mode: WorkflowScope["mode"] } | undefined {
|
|
87
|
+
if (thread.metadata?.rootParaId === undefined && thread.entries[0]?.metadata?.parentParaId) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const firstMeaningfulLine = thread.entries
|
|
91
|
+
.flatMap((entry) => entry.body.split(/\r?\n/u))
|
|
92
|
+
.map((line) => line.trim())
|
|
93
|
+
.find((line) => line.length > 0);
|
|
94
|
+
if (!firstMeaningfulLine) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const match = /^CLM:([A-Z]+):(.*)$/u.exec(firstMeaningfulLine);
|
|
98
|
+
if (!match) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const tag = match[1] as "TASK" | "READ" | "COMMENT" | "EDIT";
|
|
102
|
+
const description = (match[2] ?? "").trim();
|
|
103
|
+
const mode = getClmWorkflowScopeMode(tag);
|
|
104
|
+
if (!mode || description.length === 0) {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
tag,
|
|
109
|
+
description,
|
|
110
|
+
sourceCommentId: thread.metadata?.rootOoxmlCommentId ?? thread.commentId,
|
|
111
|
+
sourceCommentDurableId: thread.entries[0]?.metadata?.durableId,
|
|
112
|
+
sourceCommentParaId: thread.metadata?.rootParaId ?? thread.entries[0]?.metadata?.paraId,
|
|
113
|
+
mode,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function getClmWorkflowScopeMode(tag: string): WorkflowScope["mode"] | undefined {
|
|
118
|
+
switch (tag) {
|
|
119
|
+
case "TASK":
|
|
120
|
+
return "suggest";
|
|
121
|
+
case "READ":
|
|
122
|
+
return "view";
|
|
123
|
+
case "COMMENT":
|
|
124
|
+
return "comment";
|
|
125
|
+
case "EDIT":
|
|
126
|
+
return "edit";
|
|
127
|
+
default:
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function createClmWorkflowWorkItem(
|
|
133
|
+
thread: CommentThread,
|
|
134
|
+
description: string,
|
|
135
|
+
scopeId: string,
|
|
136
|
+
): WorkflowWorkItem {
|
|
137
|
+
return {
|
|
138
|
+
workItemId: `clm-task-${thread.commentId}`,
|
|
139
|
+
title: description,
|
|
140
|
+
description,
|
|
141
|
+
status: "pending",
|
|
142
|
+
scopeIds: [scopeId],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function createClmWorkflowScope(
|
|
147
|
+
thread: CommentThread,
|
|
148
|
+
directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
|
|
149
|
+
version: number,
|
|
150
|
+
scopeId: string,
|
|
151
|
+
workItemId?: string,
|
|
152
|
+
): WorkflowScope {
|
|
153
|
+
if (workItemId) {
|
|
154
|
+
return {
|
|
155
|
+
scopeId,
|
|
156
|
+
version,
|
|
157
|
+
mode: directive.mode,
|
|
158
|
+
anchor: toPublicAnchorProjection(thread.anchor),
|
|
159
|
+
storyTarget: { kind: "main" },
|
|
160
|
+
workItemId,
|
|
161
|
+
label: directive.description,
|
|
162
|
+
metadata: createClmScopeMetadata(directive),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
scopeId,
|
|
167
|
+
version,
|
|
168
|
+
mode: directive.mode,
|
|
169
|
+
anchor: toPublicAnchorProjection(thread.anchor),
|
|
170
|
+
storyTarget: { kind: "main" },
|
|
171
|
+
label: directive.description,
|
|
172
|
+
metadata: createClmScopeMetadata(directive),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export function createClmScopeMetadata(
|
|
177
|
+
directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
|
|
178
|
+
): WorkflowScopeMetadataField[] {
|
|
179
|
+
return [
|
|
180
|
+
{
|
|
181
|
+
key: "workblock.clm.tag",
|
|
182
|
+
valueType: "string",
|
|
183
|
+
value: directive.tag,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
key: "workblock.clm.description",
|
|
187
|
+
valueType: "string",
|
|
188
|
+
value: directive.description,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
key: "workblock.sourceCommentId",
|
|
192
|
+
valueType: "string",
|
|
193
|
+
value: directive.sourceCommentId,
|
|
194
|
+
},
|
|
195
|
+
...(directive.sourceCommentDurableId
|
|
196
|
+
? [{
|
|
197
|
+
key: "workblock.sourceCommentDurableId",
|
|
198
|
+
valueType: "string" as const,
|
|
199
|
+
value: directive.sourceCommentDurableId,
|
|
200
|
+
}]
|
|
201
|
+
: []),
|
|
202
|
+
...(directive.sourceCommentParaId
|
|
203
|
+
? [{
|
|
204
|
+
key: "workblock.sourceCommentParaId",
|
|
205
|
+
valueType: "string" as const,
|
|
206
|
+
value: directive.sourceCommentParaId,
|
|
207
|
+
}]
|
|
208
|
+
: []),
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function findExistingClmScope(
|
|
213
|
+
scopes: readonly WorkflowScope[],
|
|
214
|
+
directive: NonNullable<ReturnType<typeof parseClmCommentDirective>>,
|
|
215
|
+
): WorkflowScope | undefined {
|
|
216
|
+
return scopes.find((scope) => {
|
|
217
|
+
const sourceCommentId = getWorkflowScopeMetadataValue(scope.metadata, "workblock.sourceCommentId");
|
|
218
|
+
const sourceCommentDurableId = getWorkflowScopeMetadataValue(
|
|
219
|
+
scope.metadata,
|
|
220
|
+
"workblock.sourceCommentDurableId",
|
|
221
|
+
);
|
|
222
|
+
return (
|
|
223
|
+
sourceCommentId === directive.sourceCommentId ||
|
|
224
|
+
(directive.sourceCommentDurableId !== undefined &&
|
|
225
|
+
sourceCommentDurableId === directive.sourceCommentDurableId)
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function getWorkflowScopeMetadataValue(
|
|
231
|
+
metadata: WorkflowScope["metadata"] | undefined,
|
|
232
|
+
key: string,
|
|
233
|
+
): string | undefined {
|
|
234
|
+
const field = metadata?.find((entry) => entry.key === key);
|
|
235
|
+
return typeof field?.value === "string" ? field.value : undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function getNextClmScopeVersion(
|
|
239
|
+
scopes: readonly WorkflowScope[],
|
|
240
|
+
anchor: Extract<CommentThread["anchor"], { kind: "range" }>,
|
|
241
|
+
): number {
|
|
242
|
+
const anchorRange = {
|
|
243
|
+
from: anchor.range.from,
|
|
244
|
+
to: anchor.range.to,
|
|
245
|
+
};
|
|
246
|
+
const overlappingVersions = scopes.flatMap((scope) => {
|
|
247
|
+
if (scope.anchor.kind !== "range") {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
return rangesIntersect(scope.anchor, anchorRange) && typeof scope.version === "number"
|
|
251
|
+
? [scope.version]
|
|
252
|
+
: [];
|
|
253
|
+
});
|
|
254
|
+
return overlappingVersions.length > 0 ? Math.max(...overlappingVersions) + 1 : 1;
|
|
255
|
+
}
|
|
256
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public barrel for Layer 01 (package / session).
|
|
3
|
+
*
|
|
4
|
+
* Reserved shape — matches `docs/architecture/01-package-session.md`
|
|
5
|
+
* § Public entry points. Consumers should import from `src/session`
|
|
6
|
+
* (or the `@beyondwork/docx-react-component/session` package subpath)
|
|
7
|
+
* rather than reaching into `src/io/docx-session.ts`. The legacy entry
|
|
8
|
+
* points remain exported from the root barrel for back-compat until
|
|
9
|
+
* Slice 5 deletes them.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
DocxSession,
|
|
14
|
+
SessionNotOpenError,
|
|
15
|
+
SessionNotWiredError,
|
|
16
|
+
} from "./session.ts";
|
|
17
|
+
export { isReopenBarrier } from "./types.ts";
|
|
18
|
+
export type { EditorSessionState } from "./session-state.ts";
|
|
19
|
+
export type {
|
|
20
|
+
// Reserved Layer-01 contract types.
|
|
21
|
+
OpenOptions,
|
|
22
|
+
OpenResult,
|
|
23
|
+
ExportOptions,
|
|
24
|
+
ValidateOptions,
|
|
25
|
+
ValidationReport,
|
|
26
|
+
ValidationFinding,
|
|
27
|
+
PreservationSnapshot,
|
|
28
|
+
EmbeddedDocumentManifest,
|
|
29
|
+
// P8 Step 7 offload surface.
|
|
30
|
+
ReopenBarrier,
|
|
31
|
+
// Transitional re-exports from the legacy IO layer.
|
|
32
|
+
ExportResult,
|
|
33
|
+
EditorHostAdapter,
|
|
34
|
+
ExportDocxOptions,
|
|
35
|
+
LoadStage,
|
|
36
|
+
PersistedEditorSnapshot,
|
|
37
|
+
} from "./types.ts";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical definition of `EditorSessionState` — the host-facing session
|
|
3
|
+
* contract produced by Layer 01 on open and consumed on export.
|
|
4
|
+
*
|
|
5
|
+
* Moved here from `src/api/public-types.ts` in refactor/01 slice 3f
|
|
6
|
+
* (F5). `src/api/public-types.ts` now re-exports for back-compat; the
|
|
7
|
+
* owning module is this file.
|
|
8
|
+
*
|
|
9
|
+
* P6 clean: imports only from `src/model/**` (allowed) and `src/api/**`
|
|
10
|
+
* (allowed; type-only to avoid runtime coupling with the presentation
|
|
11
|
+
* surface).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { PersistedEditorSnapshot as ModelPersistedEditorSnapshot } from "../model/snapshot.ts";
|
|
15
|
+
import type {
|
|
16
|
+
CompatibilityReport,
|
|
17
|
+
EditorWarning,
|
|
18
|
+
OverlayVisibilityPolicy,
|
|
19
|
+
ProtectionSnapshot,
|
|
20
|
+
WorkflowMarkupModePolicy,
|
|
21
|
+
WorkflowMetadataSnapshot,
|
|
22
|
+
WorkflowOverlay,
|
|
23
|
+
} from "../api/public-types.ts";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Durable projection of an editor session suitable for persistence and
|
|
27
|
+
* rehydration. The shape is versioned independently from the model
|
|
28
|
+
* snapshot so that host-facing fields (e.g. `editorBuild`, warning log)
|
|
29
|
+
* can evolve without forcing model-layer version bumps.
|
|
30
|
+
*
|
|
31
|
+
* Semantic contract:
|
|
32
|
+
* - `canonicalDocument` round-trips exactly through the `src/model/**`
|
|
33
|
+
* serializer/validator. Layer 01 does not mutate canonical fields
|
|
34
|
+
* during open/export.
|
|
35
|
+
* - `sourcePackage`, when present, carries the opaque OPC package
|
|
36
|
+
* reference the session opened from. Omit to materialize a session
|
|
37
|
+
* with no byte-source (host-authored content, test fixtures).
|
|
38
|
+
*/
|
|
39
|
+
export interface EditorSessionState {
|
|
40
|
+
sessionVersion: "editor-session-state/1";
|
|
41
|
+
schemaVersion: ModelPersistedEditorSnapshot["schemaVersion"];
|
|
42
|
+
documentId: string;
|
|
43
|
+
docId: string;
|
|
44
|
+
createdAt: string;
|
|
45
|
+
updatedAt: string;
|
|
46
|
+
editorBuild: string;
|
|
47
|
+
canonicalDocument: ModelPersistedEditorSnapshot["canonicalDocument"];
|
|
48
|
+
compatibility: CompatibilityReport;
|
|
49
|
+
warningLog: EditorWarning[];
|
|
50
|
+
protectionSnapshot?: ProtectionSnapshot;
|
|
51
|
+
sourcePackage?: ModelPersistedEditorSnapshot["sourcePackage"];
|
|
52
|
+
workflowOverlay?: WorkflowOverlay;
|
|
53
|
+
workflowMetadata?: WorkflowMetadataSnapshot;
|
|
54
|
+
/**
|
|
55
|
+
* W10 — class-A overlay-visibility policies. Zero or more entries,
|
|
56
|
+
* at most one per `OverlayKind`. Empty array when the document
|
|
57
|
+
* carries no authored policy (consumers fall back to class-C local
|
|
58
|
+
* preference defaults). Persists via `customXml/item1.xml` under the
|
|
59
|
+
* `bw:overlayVisibility` namespace.
|
|
60
|
+
*/
|
|
61
|
+
visibilityPolicies?: readonly OverlayVisibilityPolicy[];
|
|
62
|
+
/**
|
|
63
|
+
* X5 — class-A markup-mode policy. Single record; `undefined` when
|
|
64
|
+
* the document carries no authored mode (consumers fall back to the
|
|
65
|
+
* class-C local preference). Persists via `customXml/item1.xml`
|
|
66
|
+
* under the `bw:markupModePolicy` namespace.
|
|
67
|
+
*/
|
|
68
|
+
markupModePolicy?: WorkflowMarkupModePolicy;
|
|
69
|
+
}
|