@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,684 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `runStatefulExport` — session-layer owner of the stateful export
|
|
3
|
+
* pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Slice 5e-7.f relocates the body of `exportDocxEditorSession` from
|
|
6
|
+
* `src/io/docx-session.ts` into this module. Legacy callers reach the
|
|
7
|
+
* pipeline through `LoadedDocxEditorSession.exportDocx` (closure
|
|
8
|
+
* captured at open time by the session-layer loader) or directly via
|
|
9
|
+
* `DocxSession.export()` — no public `exportDocxEditorSession` export
|
|
10
|
+
* exists anymore; the function was private to `docx-session.ts`.
|
|
11
|
+
*
|
|
12
|
+
* Stateful: the pipeline needs the `ImportedDocxState` captured at
|
|
13
|
+
* open time (source bytes, `OpcPackage`, per-part relationships,
|
|
14
|
+
* preserved-part manifest, `sourceDocumentRelationships`,
|
|
15
|
+
* `sourceDocumentAttributes`, `initialCanonicalSignature`, etc.). The
|
|
16
|
+
* byte-reuse fast path (signature match + `canReuseSourceBytesForCurrentDocument`)
|
|
17
|
+
* returns the original bytes unchanged when no edits have been made.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type {
|
|
21
|
+
EditorSessionState,
|
|
22
|
+
ExportDocxOptions,
|
|
23
|
+
ExportResult,
|
|
24
|
+
PersistedEditorSnapshot,
|
|
25
|
+
} from "../../api/public-types.ts";
|
|
26
|
+
import type {
|
|
27
|
+
CanonicalDocument,
|
|
28
|
+
MediaCatalog,
|
|
29
|
+
NumberingCatalog,
|
|
30
|
+
SubPartsCatalog,
|
|
31
|
+
} from "../../model/canonical-document.ts";
|
|
32
|
+
import {
|
|
33
|
+
commentRecordsToReviewThreads,
|
|
34
|
+
} from "../../model/review/comment-types.ts";
|
|
35
|
+
import {
|
|
36
|
+
getRevisionActionability,
|
|
37
|
+
} from "../../model/review/revision-types.ts";
|
|
38
|
+
import { DOCX_MIME_TYPE } from "../../io/opc/docx-package.ts";
|
|
39
|
+
import { createExportSession } from "../../io/export/export-session.ts";
|
|
40
|
+
import { serializeMainDocument } from "../../io/export/serialize-main-document.ts";
|
|
41
|
+
import {
|
|
42
|
+
serializeSettingsXml,
|
|
43
|
+
WORD_SETTINGS_CONTENT_TYPE,
|
|
44
|
+
} from "../../io/export/serialize-settings.ts";
|
|
45
|
+
import {
|
|
46
|
+
createCommentExportIdMap,
|
|
47
|
+
serializeCommentAnchorsIntoDocumentXml,
|
|
48
|
+
serializeMergedCommentsXml,
|
|
49
|
+
} from "../../io/export/serialize-comments.ts";
|
|
50
|
+
import { splitDocumentAtReviewBoundaries } from "../../io/export/split-review-boundaries.ts";
|
|
51
|
+
import { splitStoryBlocksForRuntimeRevisions } from "../../io/export/split-story-blocks-for-runtime-revisions.ts";
|
|
52
|
+
import {
|
|
53
|
+
serializeRuntimeRevisionsIntoDocumentXml,
|
|
54
|
+
} from "../../io/export/serialize-runtime-revisions.ts";
|
|
55
|
+
import {
|
|
56
|
+
WORD_NUMBERING_CONTENT_TYPE,
|
|
57
|
+
hasSerializableNumberingEntries,
|
|
58
|
+
serializeNumberingXml,
|
|
59
|
+
} from "../../io/export/serialize-numbering.ts";
|
|
60
|
+
import {
|
|
61
|
+
serializeHeaderXmlWithRevisions,
|
|
62
|
+
serializeFooterXmlWithRevisions,
|
|
63
|
+
WORD_HEADER_CONTENT_TYPE,
|
|
64
|
+
WORD_FOOTER_CONTENT_TYPE,
|
|
65
|
+
} from "../../io/export/serialize-headers-footers.ts";
|
|
66
|
+
import {
|
|
67
|
+
serializeFootnotesXml,
|
|
68
|
+
serializeEndnotesXml,
|
|
69
|
+
WORD_FOOTNOTES_CONTENT_TYPE,
|
|
70
|
+
WORD_ENDNOTES_CONTENT_TYPE,
|
|
71
|
+
} from "../../io/export/serialize-footnotes.ts";
|
|
72
|
+
import {
|
|
73
|
+
getDocumentBackedWorkflowMetadata,
|
|
74
|
+
resolvePayloadPartPath,
|
|
75
|
+
resolveWorkflowPayloadPartPaths,
|
|
76
|
+
WORKFLOW_PAYLOAD_CUSTOM_PROPS_PART_PATH,
|
|
77
|
+
} from "../../io/ooxml/workflow-payload.ts";
|
|
78
|
+
import {
|
|
79
|
+
serializeSecondaryStoryWithRuntimeRevisions,
|
|
80
|
+
stripCommentMarkup,
|
|
81
|
+
toReviewRevisionRecords,
|
|
82
|
+
} from "../import/review-import.ts";
|
|
83
|
+
import { toEditorSessionState } from "../import/canonical-assembly.ts";
|
|
84
|
+
import {
|
|
85
|
+
serializeCanonicalDocumentForExport,
|
|
86
|
+
} from "../shared/session-utils.ts";
|
|
87
|
+
import { withDocumentRelatedParts } from "../import/package-parts.ts";
|
|
88
|
+
import {
|
|
89
|
+
APP_PROPERTIES_PART_PATH,
|
|
90
|
+
CORE_PROPERTIES_PART_PATH,
|
|
91
|
+
canReuseSourceBytesForCurrentDocument,
|
|
92
|
+
ensureHostMetadataParts,
|
|
93
|
+
ensureWorkflowPayloadParts,
|
|
94
|
+
serializeProtectionRangesIntoDocumentXml,
|
|
95
|
+
} from "./stateful-export-pipeline.ts";
|
|
96
|
+
import {
|
|
97
|
+
assertExportNotBlockedByCompatibility,
|
|
98
|
+
assertNoBlockingPreservedComments,
|
|
99
|
+
assertNoBlockingSkippedComments,
|
|
100
|
+
assertNoSkippedRevisions,
|
|
101
|
+
} from "./export-validation.ts";
|
|
102
|
+
import {
|
|
103
|
+
groupFooterRevisionsByPartPath,
|
|
104
|
+
groupHeaderRevisionsByPartPath,
|
|
105
|
+
groupNoteRevisionsByNoteId,
|
|
106
|
+
} from "./serialize-dispatch.ts";
|
|
107
|
+
import {
|
|
108
|
+
COMMENTS_CONTENT_TYPE,
|
|
109
|
+
COMMENTS_EXTENDED_CONTENT_TYPE,
|
|
110
|
+
COMMENTS_EXTENDED_PART_PATH,
|
|
111
|
+
COMMENTS_EXTENDED_RELATIONSHIP_TYPE,
|
|
112
|
+
COMMENTS_IDS_CONTENT_TYPE,
|
|
113
|
+
COMMENTS_IDS_PART_PATH,
|
|
114
|
+
COMMENTS_IDS_RELATIONSHIP_TYPE,
|
|
115
|
+
MAIN_DOCUMENT_CONTENT_TYPE,
|
|
116
|
+
NUMBERING_PART_PATH,
|
|
117
|
+
NUMBERING_RELATIONSHIP_TYPE,
|
|
118
|
+
PEOPLE_CONTENT_TYPE,
|
|
119
|
+
PEOPLE_PART_PATH,
|
|
120
|
+
PEOPLE_RELATIONSHIP_TYPE,
|
|
121
|
+
SETTINGS_PART_PATH,
|
|
122
|
+
} from "../import/part-constants.ts";
|
|
123
|
+
import {
|
|
124
|
+
COMMENTS_PART_PATH,
|
|
125
|
+
COMMENTS_RELATIONSHIP_TYPE,
|
|
126
|
+
} from "../import/part-discovery.ts";
|
|
127
|
+
import type { ImportedDocxState } from "../import/loader-types.ts";
|
|
128
|
+
import {
|
|
129
|
+
buildEmbeddingsInlinePayload,
|
|
130
|
+
type EmbeddingOffloadEntry,
|
|
131
|
+
} from "../import/embedded-offload.ts";
|
|
132
|
+
import { reconstituteEmbeddedDocuments } from "./embedded-reconstitute.ts";
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Stateful export orchestrator. Body is byte-for-byte the pre-5e-7.f
|
|
136
|
+
* `exportDocxEditorSession` that was private to
|
|
137
|
+
* `src/io/docx-session.ts`; only the imports were redirected to
|
|
138
|
+
* session-layer homes.
|
|
139
|
+
*/
|
|
140
|
+
export async function runStatefulExport(
|
|
141
|
+
state: ImportedDocxState,
|
|
142
|
+
sessionStateOrSnapshot: EditorSessionState | PersistedEditorSnapshot,
|
|
143
|
+
options?: ExportDocxOptions,
|
|
144
|
+
): Promise<ExportResult> {
|
|
145
|
+
const sessionState = toEditorSessionState(sessionStateOrSnapshot);
|
|
146
|
+
|
|
147
|
+
assertExportNotBlockedByCompatibility(sessionState.compatibility);
|
|
148
|
+
|
|
149
|
+
const currentDocument = sessionState.canonicalDocument as CanonicalDocument;
|
|
150
|
+
const signatureMatch = serializeCanonicalDocumentForExport(currentDocument) ===
|
|
151
|
+
state.initialCanonicalSignature;
|
|
152
|
+
const canReuse = canReuseSourceBytesForCurrentDocument(state, currentDocument);
|
|
153
|
+
const durableWorkflowMetadata = getDocumentBackedWorkflowMetadata(sessionState.workflowMetadata);
|
|
154
|
+
const hasWorkflowOverlay = Boolean(sessionState.workflowOverlay);
|
|
155
|
+
const sourceHasWorkflowPayload = resolvePayloadPartPath(state.sourcePackage) !== null;
|
|
156
|
+
// Schema 1.2: runtime may have registered metadata entries via
|
|
157
|
+
// `setWorkflowMetadataEntries` (or `addScope({persistence:'document-metadata'})`)
|
|
158
|
+
// that don't pass the document-backed filter but still represent session
|
|
159
|
+
// state that must survive export → reload via the editorState namespace.
|
|
160
|
+
// W10: class-A overlay-visibility policies also force a rewrite —
|
|
161
|
+
// otherwise authored policy set via `handle.workflow.setVisibilityPolicy`
|
|
162
|
+
// on an unchanged document silently drops on export.
|
|
163
|
+
const hasRuntimeWorkflowMetadata = Boolean(
|
|
164
|
+
(sessionState.workflowMetadata?.definitions.length ?? 0) > 0 ||
|
|
165
|
+
(sessionState.workflowMetadata?.entries.length ?? 0) > 0 ||
|
|
166
|
+
(sessionState.visibilityPolicies?.length ?? 0) > 0 ||
|
|
167
|
+
sessionState.markupModePolicy != null,
|
|
168
|
+
);
|
|
169
|
+
const commentCount = Object.keys(currentDocument.review?.comments ?? {}).length;
|
|
170
|
+
const currentRevisions = toReviewRevisionRecords(currentDocument.review.revisions);
|
|
171
|
+
const hasActiveImportedPreserveOnlyRevisions = currentRevisions.some(
|
|
172
|
+
(revision) =>
|
|
173
|
+
revision.status === "active" &&
|
|
174
|
+
revision.metadata.source === "import" &&
|
|
175
|
+
typeof revision.metadata.preserveOnlyReason === "string" &&
|
|
176
|
+
revision.metadata.preserveOnlyReason.length > 0,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
if (
|
|
180
|
+
signatureMatch &&
|
|
181
|
+
canReuse &&
|
|
182
|
+
durableWorkflowMetadata.definitions.length === 0 &&
|
|
183
|
+
durableWorkflowMetadata.entries.length === 0 &&
|
|
184
|
+
!hasWorkflowOverlay &&
|
|
185
|
+
!sourceHasWorkflowPayload &&
|
|
186
|
+
!hasRuntimeWorkflowMetadata
|
|
187
|
+
) {
|
|
188
|
+
return {
|
|
189
|
+
bytes: new Uint8Array(state.sourceBytes),
|
|
190
|
+
mimeType: DOCX_MIME_TYPE,
|
|
191
|
+
fileName: options?.fileName ?? `${sessionState.documentId}.docx`,
|
|
192
|
+
delivery: {
|
|
193
|
+
mode: "exported-bytes-only",
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const preservedCommentIds = new Set(
|
|
198
|
+
state.preservedCommentDefinitions.map((definition) => definition.commentId),
|
|
199
|
+
);
|
|
200
|
+
const blockingCommentCount = Math.max(
|
|
201
|
+
state.blockingCommentDiagnostics.length,
|
|
202
|
+
preservedCommentIds.size,
|
|
203
|
+
);
|
|
204
|
+
assertNoBlockingPreservedComments(
|
|
205
|
+
blockingCommentCount,
|
|
206
|
+
[...preservedCommentIds],
|
|
207
|
+
);
|
|
208
|
+
const actionableRevisions = currentRevisions.filter(
|
|
209
|
+
(revision) => getRevisionActionability(revision) === "actionable",
|
|
210
|
+
);
|
|
211
|
+
const mainStoryActionableRevisions = actionableRevisions.filter((revision) =>
|
|
212
|
+
!revision.metadata.storyTarget?.kind || revision.metadata.storyTarget.kind === "main"
|
|
213
|
+
);
|
|
214
|
+
const commentThreads = commentRecordsToReviewThreads(
|
|
215
|
+
currentDocument.review.comments,
|
|
216
|
+
);
|
|
217
|
+
const ownedCommentThreads = commentThreads.filter(
|
|
218
|
+
(thread) => !preservedCommentIds.has(thread.commentId),
|
|
219
|
+
);
|
|
220
|
+
const revisionReadyMainContent = {
|
|
221
|
+
...currentDocument.content,
|
|
222
|
+
children: splitStoryBlocksForRuntimeRevisions(
|
|
223
|
+
currentDocument.content.children,
|
|
224
|
+
mainStoryActionableRevisions,
|
|
225
|
+
),
|
|
226
|
+
};
|
|
227
|
+
const serialized = serializeMainDocument(
|
|
228
|
+
splitDocumentAtReviewBoundaries(
|
|
229
|
+
revisionReadyMainContent as never,
|
|
230
|
+
ownedCommentThreads,
|
|
231
|
+
mainStoryActionableRevisions,
|
|
232
|
+
) as never,
|
|
233
|
+
currentDocument.preservation as never,
|
|
234
|
+
state.sourceDocumentRelationships,
|
|
235
|
+
{
|
|
236
|
+
documentAttributes: state.sourceDocumentAttributes,
|
|
237
|
+
media: currentDocument.media as MediaCatalog,
|
|
238
|
+
finalSectionProperties: currentDocument.subParts?.finalSectionProperties,
|
|
239
|
+
namespaceFlavor: options?.exportStrictOoxml ? "strict" : "transitional",
|
|
240
|
+
},
|
|
241
|
+
);
|
|
242
|
+
const revisionDocument = serializeRuntimeRevisionsIntoDocumentXml(
|
|
243
|
+
serialized.documentXml,
|
|
244
|
+
mainStoryActionableRevisions,
|
|
245
|
+
);
|
|
246
|
+
assertNoSkippedRevisions(revisionDocument.skippedRevisionIds);
|
|
247
|
+
|
|
248
|
+
const strippedDocumentXml = stripCommentMarkup(
|
|
249
|
+
revisionDocument.documentXml,
|
|
250
|
+
ownedCommentThreads.map((thread) => thread.commentId),
|
|
251
|
+
);
|
|
252
|
+
const exportCommentIds = createCommentExportIdMap(
|
|
253
|
+
ownedCommentThreads,
|
|
254
|
+
state.preservedCommentDefinitions,
|
|
255
|
+
);
|
|
256
|
+
const serializedComments = serializeMergedCommentsXml(ownedCommentThreads, {
|
|
257
|
+
exportCommentIds,
|
|
258
|
+
preservedDefinitions: state.preservedCommentDefinitions,
|
|
259
|
+
sourceRootTag: state.sourceCommentsRootTag,
|
|
260
|
+
sourceExtendedRootTag: state.sourceCommentsExtendedRootTag,
|
|
261
|
+
sourceIdsRootTag: state.sourceCommentsIdsRootTag,
|
|
262
|
+
sourcePeopleRootTag: state.sourcePeopleRootTag,
|
|
263
|
+
peopleAuthors: state.sourcePeopleAuthors,
|
|
264
|
+
});
|
|
265
|
+
const annotatedDocument = serializeCommentAnchorsIntoDocumentXml(
|
|
266
|
+
strippedDocumentXml,
|
|
267
|
+
ownedCommentThreads,
|
|
268
|
+
undefined,
|
|
269
|
+
{
|
|
270
|
+
exportCommentIds,
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
const protectedDocumentXml = serializeProtectionRangesIntoDocumentXml(
|
|
274
|
+
annotatedDocument.documentXml,
|
|
275
|
+
state.protectionSnapshot,
|
|
276
|
+
);
|
|
277
|
+
const blockingSkippedCommentIds = annotatedDocument.skippedCommentIds.filter((commentId) => {
|
|
278
|
+
const thread = ownedCommentThreads.find((candidate) => candidate.commentId === commentId);
|
|
279
|
+
return !thread || thread.anchor.kind !== "detached";
|
|
280
|
+
});
|
|
281
|
+
assertNoBlockingSkippedComments(blockingSkippedCommentIds);
|
|
282
|
+
const commentsPartPath =
|
|
283
|
+
state.sourceCommentsPartPath ?? COMMENTS_PART_PATH;
|
|
284
|
+
const commentsExtendedPartPath =
|
|
285
|
+
state.sourceCommentsExtendedPartPath ?? COMMENTS_EXTENDED_PART_PATH;
|
|
286
|
+
const commentsIdsPartPath =
|
|
287
|
+
state.sourceCommentsIdsPartPath ?? COMMENTS_IDS_PART_PATH;
|
|
288
|
+
const peoplePartPath =
|
|
289
|
+
state.sourcePeoplePartPath ?? PEOPLE_PART_PATH;
|
|
290
|
+
const numberingPartPath =
|
|
291
|
+
state.sourceNumberingPartPath ?? NUMBERING_PART_PATH;
|
|
292
|
+
const serializedNumberingXml = hasSerializableNumberingEntries(
|
|
293
|
+
currentDocument.numbering as NumberingCatalog,
|
|
294
|
+
)
|
|
295
|
+
? serializeNumberingXml(currentDocument.numbering as NumberingCatalog)
|
|
296
|
+
: undefined;
|
|
297
|
+
const nextRelationships = withDocumentRelatedParts(
|
|
298
|
+
serialized.relationships,
|
|
299
|
+
[
|
|
300
|
+
{
|
|
301
|
+
relationshipType: NUMBERING_RELATIONSHIP_TYPE,
|
|
302
|
+
partPath: numberingPartPath,
|
|
303
|
+
existingRelationshipId: state.sourceNumberingRelationshipId,
|
|
304
|
+
include:
|
|
305
|
+
Boolean(serializedNumberingXml) ||
|
|
306
|
+
Boolean(state.sourceNumberingPartPath),
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
relationshipType: COMMENTS_RELATIONSHIP_TYPE,
|
|
310
|
+
partPath: commentsPartPath,
|
|
311
|
+
existingRelationshipId: state.sourceCommentsRelationshipId,
|
|
312
|
+
include:
|
|
313
|
+
serializedComments.serializedCommentIds.length > 0 ||
|
|
314
|
+
Boolean(state.sourceCommentsPartPath),
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
relationshipType: COMMENTS_EXTENDED_RELATIONSHIP_TYPE,
|
|
318
|
+
partPath: commentsExtendedPartPath,
|
|
319
|
+
existingRelationshipId: state.sourceCommentsExtendedRelationshipId,
|
|
320
|
+
include:
|
|
321
|
+
Boolean(serializedComments.commentsExtendedXml) ||
|
|
322
|
+
Boolean(state.sourceCommentsExtendedPartPath),
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
relationshipType: COMMENTS_IDS_RELATIONSHIP_TYPE,
|
|
326
|
+
partPath: commentsIdsPartPath,
|
|
327
|
+
existingRelationshipId: state.sourceCommentsIdsRelationshipId,
|
|
328
|
+
include:
|
|
329
|
+
Boolean(serializedComments.commentsIdsXml) ||
|
|
330
|
+
Boolean(state.sourceCommentsIdsPartPath),
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
relationshipType: PEOPLE_RELATIONSHIP_TYPE,
|
|
334
|
+
partPath: peoplePartPath,
|
|
335
|
+
existingRelationshipId: state.sourcePeopleRelationshipId,
|
|
336
|
+
include:
|
|
337
|
+
Boolean(serializedComments.peopleXml) ||
|
|
338
|
+
Boolean(state.sourcePeoplePartPath),
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
const exportedSubParts = currentDocument.subParts as SubPartsCatalog | undefined;
|
|
344
|
+
const subPartOwnedPaths: string[] = [];
|
|
345
|
+
if (exportedSubParts) {
|
|
346
|
+
for (const header of exportedSubParts.headers) {
|
|
347
|
+
subPartOwnedPaths.push(header.partPath);
|
|
348
|
+
}
|
|
349
|
+
for (const footer of exportedSubParts.footers) {
|
|
350
|
+
subPartOwnedPaths.push(footer.partPath);
|
|
351
|
+
}
|
|
352
|
+
if (exportedSubParts.footnoteCollection) {
|
|
353
|
+
if (state.sourceSubPartPaths.footnotesPartPath) {
|
|
354
|
+
subPartOwnedPaths.push(state.sourceSubPartPaths.footnotesPartPath);
|
|
355
|
+
}
|
|
356
|
+
if (state.sourceSubPartPaths.endnotesPartPath) {
|
|
357
|
+
subPartOwnedPaths.push(state.sourceSubPartPaths.endnotesPartPath);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (exportedSubParts.theme && state.sourceSubPartPaths.themePartPath) {
|
|
361
|
+
subPartOwnedPaths.push(state.sourceSubPartPaths.themePartPath);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Settings.xml is owned when the source package carried one OR the canonical
|
|
366
|
+
// model carries settings we need to re-emit. The `canReuse && signatureMatch`
|
|
367
|
+
// short-circuit above already skips re-export entirely for no-edit sessions,
|
|
368
|
+
// so every path that reaches here is willing to emit a rebuilt settings.xml.
|
|
369
|
+
const settingsPartPath =
|
|
370
|
+
state.sourceSettingsPartPath ?? SETTINGS_PART_PATH;
|
|
371
|
+
const hasSettingsSurface =
|
|
372
|
+
Boolean(state.sourceSettingsPartPath) ||
|
|
373
|
+
exportedSubParts?.settings !== undefined;
|
|
374
|
+
const workflowPayloadPartPaths = resolveWorkflowPayloadPartPaths(
|
|
375
|
+
state.sourcePackage,
|
|
376
|
+
sessionState.documentId,
|
|
377
|
+
);
|
|
378
|
+
const internalEditorState = (
|
|
379
|
+
options as { _editorState?: import("../../io/ooxml/workflow-payload.ts").EditorStatePayload } | undefined
|
|
380
|
+
)?._editorState;
|
|
381
|
+
|
|
382
|
+
// P8 Step 7: narrow the opaque `state.embeddingOffloadEntries` list
|
|
383
|
+
// (typed `readonly unknown[]` on `ImportedDocxState` to keep the
|
|
384
|
+
// session-layer types file P6-clean) into the concrete entry shape
|
|
385
|
+
// the reconstitute pass needs. The entries were already validated
|
|
386
|
+
// by `hydrateOffloadEntriesFromPayload` or produced by
|
|
387
|
+
// `processEmbeddedOffload` — they are structurally sound.
|
|
388
|
+
const offloadEntries = state.embeddingOffloadEntries as readonly EmbeddingOffloadEntry[];
|
|
389
|
+
const offloadOwnedPaths = offloadEntries.map((entry) => entry.sourcePartPath);
|
|
390
|
+
|
|
391
|
+
const exportSession = createExportSession(state.sourcePackage, [
|
|
392
|
+
state.sourceDocumentPartPath,
|
|
393
|
+
APP_PROPERTIES_PART_PATH,
|
|
394
|
+
CORE_PROPERTIES_PART_PATH,
|
|
395
|
+
workflowPayloadPartPaths.payloadPartPath,
|
|
396
|
+
workflowPayloadPartPaths.itemPropsPartPath,
|
|
397
|
+
WORKFLOW_PAYLOAD_CUSTOM_PROPS_PART_PATH,
|
|
398
|
+
numberingPartPath,
|
|
399
|
+
commentsPartPath,
|
|
400
|
+
commentsExtendedPartPath,
|
|
401
|
+
commentsIdsPartPath,
|
|
402
|
+
peoplePartPath,
|
|
403
|
+
...(hasSettingsSurface ? [settingsPartPath] : []),
|
|
404
|
+
...subPartOwnedPaths,
|
|
405
|
+
...offloadOwnedPaths,
|
|
406
|
+
]);
|
|
407
|
+
|
|
408
|
+
const mainDocumentXmlForExport =
|
|
409
|
+
signatureMatch &&
|
|
410
|
+
durableWorkflowMetadata.definitions.length === 0 &&
|
|
411
|
+
durableWorkflowMetadata.entries.length === 0 &&
|
|
412
|
+
!hasWorkflowOverlay &&
|
|
413
|
+
commentCount === 0 &&
|
|
414
|
+
hasActiveImportedPreserveOnlyRevisions
|
|
415
|
+
? state.sourceDocumentXml
|
|
416
|
+
: protectedDocumentXml;
|
|
417
|
+
|
|
418
|
+
exportSession.replaceOwnedPart({
|
|
419
|
+
path: state.sourceDocumentPartPath,
|
|
420
|
+
bytes: new TextEncoder().encode(mainDocumentXmlForExport),
|
|
421
|
+
contentType: MAIN_DOCUMENT_CONTENT_TYPE,
|
|
422
|
+
relationships: nextRelationships,
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
if (serializedNumberingXml || state.sourceNumberingPartPath) {
|
|
426
|
+
exportSession.replaceOwnedPart({
|
|
427
|
+
path: numberingPartPath,
|
|
428
|
+
bytes: new TextEncoder().encode(
|
|
429
|
+
serializedNumberingXml ??
|
|
430
|
+
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"></w:numbering>`,
|
|
431
|
+
),
|
|
432
|
+
contentType:
|
|
433
|
+
state.sourcePackage.parts.get(numberingPartPath)?.contentType ??
|
|
434
|
+
WORD_NUMBERING_CONTENT_TYPE,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (hasSettingsSurface) {
|
|
439
|
+
// Canonical settings ∅ + no source settings → omit the owned-part write
|
|
440
|
+
// (hasSettingsSurface is already false in that case). Otherwise route
|
|
441
|
+
// through the graft serializer so unmodelled children round-trip via
|
|
442
|
+
// source bytes while canonical mutations land.
|
|
443
|
+
const canonicalSettings = exportedSubParts?.settings ?? {};
|
|
444
|
+
const settingsXml = serializeSettingsXml(canonicalSettings, state.sourceSettingsXml);
|
|
445
|
+
exportSession.replaceOwnedPart({
|
|
446
|
+
path: settingsPartPath,
|
|
447
|
+
bytes: new TextEncoder().encode(settingsXml),
|
|
448
|
+
contentType:
|
|
449
|
+
state.sourcePackage.parts.get(settingsPartPath)?.contentType ??
|
|
450
|
+
WORD_SETTINGS_CONTENT_TYPE,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (serializedComments.serializedCommentIds.length > 0 || state.sourceCommentsPartPath) {
|
|
455
|
+
exportSession.replaceOwnedPart({
|
|
456
|
+
path: commentsPartPath,
|
|
457
|
+
bytes: new TextEncoder().encode(serializedComments.commentsXml),
|
|
458
|
+
contentType:
|
|
459
|
+
state.sourcePackage.parts.get(commentsPartPath)?.contentType ?? COMMENTS_CONTENT_TYPE,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (serializedComments.commentsExtendedXml || state.sourceCommentsExtendedPartPath) {
|
|
464
|
+
exportSession.replaceOwnedPart({
|
|
465
|
+
path: commentsExtendedPartPath,
|
|
466
|
+
bytes: new TextEncoder().encode(
|
|
467
|
+
serializedComments.commentsExtendedXml ?? `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w15:commentsEx xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"></w15:commentsEx>`,
|
|
468
|
+
),
|
|
469
|
+
contentType:
|
|
470
|
+
state.sourcePackage.parts.get(commentsExtendedPartPath)?.contentType ??
|
|
471
|
+
COMMENTS_EXTENDED_CONTENT_TYPE,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (serializedComments.commentsIdsXml || state.sourceCommentsIdsPartPath) {
|
|
476
|
+
exportSession.replaceOwnedPart({
|
|
477
|
+
path: commentsIdsPartPath,
|
|
478
|
+
bytes: new TextEncoder().encode(
|
|
479
|
+
serializedComments.commentsIdsXml ?? `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w16cid:commentsIds xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"></w16cid:commentsIds>`,
|
|
480
|
+
),
|
|
481
|
+
contentType:
|
|
482
|
+
state.sourcePackage.parts.get(commentsIdsPartPath)?.contentType ??
|
|
483
|
+
COMMENTS_IDS_CONTENT_TYPE,
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (serializedComments.peopleXml || state.sourcePeoplePartPath) {
|
|
488
|
+
exportSession.replaceOwnedPart({
|
|
489
|
+
path: peoplePartPath,
|
|
490
|
+
bytes: new TextEncoder().encode(
|
|
491
|
+
serializedComments.peopleXml ?? `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<w15:people xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"></w15:people>`,
|
|
492
|
+
),
|
|
493
|
+
contentType:
|
|
494
|
+
state.sourcePackage.parts.get(peoplePartPath)?.contentType ??
|
|
495
|
+
PEOPLE_CONTENT_TYPE,
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (exportedSubParts) {
|
|
500
|
+
const headersByPartPath = groupHeaderRevisionsByPartPath(
|
|
501
|
+
exportedSubParts.headers,
|
|
502
|
+
actionableRevisions,
|
|
503
|
+
(revision) => revision.metadata.storyTarget,
|
|
504
|
+
);
|
|
505
|
+
for (const { header, revisions } of headersByPartPath.values()) {
|
|
506
|
+
const serializedHeaderXml = serializeSecondaryStoryWithRuntimeRevisions(
|
|
507
|
+
serializeHeaderXmlWithRevisions(header, revisions),
|
|
508
|
+
revisions,
|
|
509
|
+
`header ${header.partPath}`,
|
|
510
|
+
);
|
|
511
|
+
exportSession.replaceOwnedPart({
|
|
512
|
+
path: header.partPath,
|
|
513
|
+
bytes: new TextEncoder().encode(serializedHeaderXml),
|
|
514
|
+
contentType:
|
|
515
|
+
state.sourcePackage.parts.get(header.partPath)?.contentType ?? WORD_HEADER_CONTENT_TYPE,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
const footersByPartPath = groupFooterRevisionsByPartPath(
|
|
519
|
+
exportedSubParts.footers,
|
|
520
|
+
actionableRevisions,
|
|
521
|
+
(revision) => revision.metadata.storyTarget,
|
|
522
|
+
);
|
|
523
|
+
for (const { footer, revisions } of footersByPartPath.values()) {
|
|
524
|
+
const serializedFooterXml = serializeSecondaryStoryWithRuntimeRevisions(
|
|
525
|
+
serializeFooterXmlWithRevisions(footer, revisions),
|
|
526
|
+
revisions,
|
|
527
|
+
`footer ${footer.partPath}`,
|
|
528
|
+
);
|
|
529
|
+
exportSession.replaceOwnedPart({
|
|
530
|
+
path: footer.partPath,
|
|
531
|
+
bytes: new TextEncoder().encode(serializedFooterXml),
|
|
532
|
+
contentType:
|
|
533
|
+
state.sourcePackage.parts.get(footer.partPath)?.contentType ?? WORD_FOOTER_CONTENT_TYPE,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
if (exportedSubParts.footnoteCollection) {
|
|
537
|
+
if (state.sourceSubPartPaths.footnotesPartPath) {
|
|
538
|
+
const serializedFootnotesXml = serializeFootnotesXml(
|
|
539
|
+
exportedSubParts.footnoteCollection,
|
|
540
|
+
groupNoteRevisionsByNoteId(
|
|
541
|
+
actionableRevisions,
|
|
542
|
+
"footnote",
|
|
543
|
+
(revision) => revision.metadata.storyTarget,
|
|
544
|
+
),
|
|
545
|
+
);
|
|
546
|
+
exportSession.replaceOwnedPart({
|
|
547
|
+
path: state.sourceSubPartPaths.footnotesPartPath,
|
|
548
|
+
bytes: new TextEncoder().encode(serializedFootnotesXml),
|
|
549
|
+
contentType:
|
|
550
|
+
state.sourcePackage.parts.get(state.sourceSubPartPaths.footnotesPartPath)?.contentType ??
|
|
551
|
+
WORD_FOOTNOTES_CONTENT_TYPE,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
if (state.sourceSubPartPaths.endnotesPartPath) {
|
|
555
|
+
const serializedEndnotesXml = serializeEndnotesXml(
|
|
556
|
+
exportedSubParts.footnoteCollection,
|
|
557
|
+
groupNoteRevisionsByNoteId(
|
|
558
|
+
actionableRevisions,
|
|
559
|
+
"endnote",
|
|
560
|
+
(revision) => revision.metadata.storyTarget,
|
|
561
|
+
),
|
|
562
|
+
);
|
|
563
|
+
exportSession.replaceOwnedPart({
|
|
564
|
+
path: state.sourceSubPartPaths.endnotesPartPath,
|
|
565
|
+
bytes: new TextEncoder().encode(serializedEndnotesXml),
|
|
566
|
+
contentType:
|
|
567
|
+
state.sourcePackage.parts.get(state.sourceSubPartPaths.endnotesPartPath)?.contentType ??
|
|
568
|
+
WORD_ENDNOTES_CONTENT_TYPE,
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (exportedSubParts.theme && state.sourceSubPartPaths.themePartPath) {
|
|
573
|
+
const sourceThemePart = state.sourcePackage.parts.get(state.sourceSubPartPaths.themePartPath);
|
|
574
|
+
if (sourceThemePart) {
|
|
575
|
+
exportSession.replaceOwnedPart({
|
|
576
|
+
path: state.sourceSubPartPaths.themePartPath,
|
|
577
|
+
bytes: sourceThemePart.bytes,
|
|
578
|
+
contentType:
|
|
579
|
+
sourceThemePart.contentType ??
|
|
580
|
+
"application/vnd.openxmlformats-officedocument.theme+xml",
|
|
581
|
+
relationships: sourceThemePart.relationships,
|
|
582
|
+
compression: sourceThemePart.compression,
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
ensureHostMetadataParts(exportSession, state.sourcePackage, currentDocument);
|
|
589
|
+
|
|
590
|
+
// P8 Step 7: reconstitute offloaded embedded documents back into
|
|
591
|
+
// the OPC package. For each entry captured at open time, try the
|
|
592
|
+
// host's `loadEmbeddedDocument` first; on null / rejection / throw,
|
|
593
|
+
// fall back to the inline-bytes base64 copy the entry carries. The
|
|
594
|
+
// source part paths were added to the export-session owned list
|
|
595
|
+
// above so `replaceOwnedPart` is valid. No-op when `offloadEntries`
|
|
596
|
+
// is empty (no offload occurred or the package carried no
|
|
597
|
+
// offloadable embeddings).
|
|
598
|
+
await reconstituteEmbeddedDocuments({
|
|
599
|
+
exportSession,
|
|
600
|
+
entries: offloadEntries,
|
|
601
|
+
hostAdapter: state.hostAdapter,
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
// P8 Step 7: fold the offload entries into the editor-state payload
|
|
605
|
+
// so the `bw:embeddings` customXml namespace round-trips to the
|
|
606
|
+
// next open. When no offload happened we pass through whatever the
|
|
607
|
+
// runtime collected unchanged.
|
|
608
|
+
const editorStateWithEmbeddings = extendEditorStateWithEmbeddings(
|
|
609
|
+
internalEditorState,
|
|
610
|
+
offloadEntries,
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
// Schema 1.2: pass through editorState payload collected by the
|
|
614
|
+
// runtime channel, with any offload entries folded in above.
|
|
615
|
+
ensureWorkflowPayloadParts(
|
|
616
|
+
exportSession,
|
|
617
|
+
sessionState,
|
|
618
|
+
currentDocument,
|
|
619
|
+
state.sourcePackage,
|
|
620
|
+
workflowPayloadPartPaths,
|
|
621
|
+
editorStateWithEmbeddings,
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
return {
|
|
625
|
+
bytes: exportSession.serialize(),
|
|
626
|
+
mimeType: DOCX_MIME_TYPE,
|
|
627
|
+
fileName: options?.fileName ?? `${sessionState.documentId}.docx`,
|
|
628
|
+
delivery: {
|
|
629
|
+
mode: "exported-bytes-only",
|
|
630
|
+
},
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Fold P8 offload entries into the editor-state payload that
|
|
636
|
+
* `ensureWorkflowPayloadParts` writes into `customXml/item1.xml`.
|
|
637
|
+
*
|
|
638
|
+
* Schema: the `"embeddings"` namespace entry carries an inline JSON
|
|
639
|
+
* blob matching `EmbeddingsInlineSchema` (shape:
|
|
640
|
+
* `{ version: 1, entries: EmbeddingOffloadEntry[] }`). On reopen,
|
|
641
|
+
* `hydrateOffloadEntriesFromPayload` parses it back and the session
|
|
642
|
+
* skips the fresh `storeEmbeddedDocument` pass.
|
|
643
|
+
*
|
|
644
|
+
* Three cases:
|
|
645
|
+
* 1. No offload entries AND no existing payload — return undefined;
|
|
646
|
+
* nothing to write, the customXml namespace is omitted.
|
|
647
|
+
* 2. No offload entries BUT there is a runtime-supplied payload —
|
|
648
|
+
* pass it through unchanged.
|
|
649
|
+
* 3. Offload entries present — ensure the payload has an
|
|
650
|
+
* `"embeddings"` namespace entry with the inline schema. Any
|
|
651
|
+
* runtime-supplied `"embeddings"` entry is replaced (the
|
|
652
|
+
* session owns this namespace per §P8).
|
|
653
|
+
*/
|
|
654
|
+
function extendEditorStateWithEmbeddings(
|
|
655
|
+
payload:
|
|
656
|
+
| import("../../io/ooxml/workflow-payload.ts").EditorStatePayload
|
|
657
|
+
| undefined,
|
|
658
|
+
offloadEntries: readonly EmbeddingOffloadEntry[],
|
|
659
|
+
):
|
|
660
|
+
| import("../../io/ooxml/workflow-payload.ts").EditorStatePayload
|
|
661
|
+
| undefined {
|
|
662
|
+
if (offloadEntries.length === 0) {
|
|
663
|
+
return payload;
|
|
664
|
+
}
|
|
665
|
+
const inlineSchema = buildEmbeddingsInlinePayload(offloadEntries);
|
|
666
|
+
const embeddingsEntry: import(
|
|
667
|
+
"../../io/ooxml/workflow-payload.ts"
|
|
668
|
+
).EditorStatePayloadNamespaceEntry = {
|
|
669
|
+
namespace: "embeddings",
|
|
670
|
+
schemaVersion: "bw-embeddings/1",
|
|
671
|
+
inline: inlineSchema,
|
|
672
|
+
};
|
|
673
|
+
if (!payload) {
|
|
674
|
+
return { entries: [embeddingsEntry] };
|
|
675
|
+
}
|
|
676
|
+
const filtered = payload.entries.filter(
|
|
677
|
+
(entry) => entry.namespace !== "embeddings",
|
|
678
|
+
);
|
|
679
|
+
const next = {
|
|
680
|
+
...payload,
|
|
681
|
+
entries: [...filtered, embeddingsEntry],
|
|
682
|
+
};
|
|
683
|
+
return next;
|
|
684
|
+
}
|