@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
|
@@ -67,17 +67,21 @@ export function parseObject(
|
|
|
67
67
|
|
|
68
68
|
// hotfix/ole-digestibility-guard — classify the embedding before
|
|
69
69
|
// constructing a canonical node. When the classifier returns
|
|
70
|
-
//
|
|
71
|
-
// embeddings, unknown ProgIDs), return undefined so
|
|
72
|
-
// existing opaque-fragment fallback preserves both
|
|
73
|
-
// and its r:id verbatim. Binary preservation is
|
|
74
|
-
// collectPreservedPackageParts indexes embedding
|
|
75
|
-
// by canonical-tree reference.
|
|
70
|
+
// `store-only` OR `offloadable` (nested Word docs, PDF OLE, Excel/
|
|
71
|
+
// PowerPoint embeddings, unknown ProgIDs), return undefined so
|
|
72
|
+
// the caller's existing opaque-fragment fallback preserves both
|
|
73
|
+
// `<w:object>` XML and its r:id verbatim. Binary preservation is
|
|
74
|
+
// unaffected — `collectPreservedPackageParts` indexes embedding
|
|
75
|
+
// parts by path, not by canonical-tree reference.
|
|
76
76
|
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
77
|
+
// Offload handling: the session layer runs `processEmbeddedOffload`
|
|
78
|
+
// (`src/session/import/embedded-offload.ts`) AFTER this parse step
|
|
79
|
+
// and AFTER the preservation index is built. For `offloadable`
|
|
80
|
+
// manifests with an opted-in host adapter, the session removes the
|
|
81
|
+
// corresponding part path from preservation (via the offload
|
|
82
|
+
// `ownedPartPaths` list fed into `buildImportPreservation`) and
|
|
83
|
+
// reconstitutes at export time. This parser stays agnostic.
|
|
84
|
+
// Shipped in refactor/01 Step 7 (Slice 5e-10).
|
|
81
85
|
const kind = classifyEmbedding({
|
|
82
86
|
progId,
|
|
83
87
|
relationshipType: resolved.relationshipType,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
CanonicalRunFormatting,
|
|
3
|
+
ThemeFontSlot,
|
|
4
|
+
} from "../../model/canonical-document.ts";
|
|
2
5
|
import { findChildOptional, readIntVal, readOnOff, readStringAttr } from "./xml-attr-helpers.ts";
|
|
3
6
|
import type { XmlElementNode } from "./xml-element.ts";
|
|
4
7
|
import {
|
|
@@ -124,6 +127,33 @@ export function readRunProperties(
|
|
|
124
127
|
if (cs) rPr.fontFamilyCs = cs;
|
|
125
128
|
const primary = ascii ?? hAnsi ?? eastAsia ?? cs;
|
|
126
129
|
if (primary) rPr.fontFamily = primary;
|
|
130
|
+
|
|
131
|
+
// ECMA-376 §17.3.2.26 theme-slot attrs. Unknown slot values are
|
|
132
|
+
// dropped (enumeration is closed); parsers that see an ECMA-376-
|
|
133
|
+
// valid slot we don't model land in the grab bag and round-trip
|
|
134
|
+
// through a different path.
|
|
135
|
+
const asciiTheme = toThemeFontSlot(
|
|
136
|
+
rFonts.attributes["w:asciiTheme"] ?? rFonts.attributes.asciiTheme,
|
|
137
|
+
);
|
|
138
|
+
const hAnsiTheme = toThemeFontSlot(
|
|
139
|
+
rFonts.attributes["w:hAnsiTheme"] ?? rFonts.attributes.hAnsiTheme,
|
|
140
|
+
);
|
|
141
|
+
const eastAsiaTheme = toThemeFontSlot(
|
|
142
|
+
rFonts.attributes["w:eastAsiaTheme"] ?? rFonts.attributes.eastAsiaTheme,
|
|
143
|
+
);
|
|
144
|
+
// ECMA-376: the complex-script theme attr is "cstheme" (all lower)
|
|
145
|
+
// — not "csTheme" — and Word emits that form. Both casings are
|
|
146
|
+
// handled defensively.
|
|
147
|
+
const csTheme = toThemeFontSlot(
|
|
148
|
+
rFonts.attributes["w:cstheme"] ??
|
|
149
|
+
rFonts.attributes.cstheme ??
|
|
150
|
+
rFonts.attributes["w:csTheme"] ??
|
|
151
|
+
rFonts.attributes.csTheme,
|
|
152
|
+
);
|
|
153
|
+
if (asciiTheme) rPr.asciiTheme = asciiTheme;
|
|
154
|
+
if (hAnsiTheme) rPr.hAnsiTheme = hAnsiTheme;
|
|
155
|
+
if (eastAsiaTheme) rPr.eastAsiaTheme = eastAsiaTheme;
|
|
156
|
+
if (csTheme) rPr.csTheme = csTheme;
|
|
127
157
|
}
|
|
128
158
|
|
|
129
159
|
const sz = readIntVal(findChildOptional(node, "sz"));
|
|
@@ -176,3 +206,19 @@ export function readRunProperties(
|
|
|
176
206
|
|
|
177
207
|
return Object.keys(rPr).length > 0 ? rPr : undefined;
|
|
178
208
|
}
|
|
209
|
+
|
|
210
|
+
const THEME_FONT_SLOTS = new Set<string>([
|
|
211
|
+
"majorAscii",
|
|
212
|
+
"minorAscii",
|
|
213
|
+
"majorHAnsi",
|
|
214
|
+
"minorHAnsi",
|
|
215
|
+
"majorEastAsia",
|
|
216
|
+
"minorEastAsia",
|
|
217
|
+
"majorBidi",
|
|
218
|
+
"minorBidi",
|
|
219
|
+
]);
|
|
220
|
+
|
|
221
|
+
function toThemeFontSlot(value: string | undefined): ThemeFontSlot | undefined {
|
|
222
|
+
if (value === undefined) return undefined;
|
|
223
|
+
return THEME_FONT_SLOTS.has(value) ? (value as ThemeFontSlot) : undefined;
|
|
224
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* property container (`<w:pPr>`, `<w:rPr>`, `<w:tcPr>`, `<w:trPr>`,
|
|
6
6
|
* `<w:tblPr>`, `<w:sectPr>`) via per-container "grab bags" keyed by
|
|
7
7
|
* element name — see `PropertyMap.hxx:82` and
|
|
8
|
-
* `libreoffice-analysis.md` §2 for the mechanism. On export, every grab
|
|
8
|
+
* `docs/reference/libreoffice-analysis.md` §2 for the mechanism. On export, every grab
|
|
9
9
|
* bag re-emits verbatim inside its container so the round-trip pipeline
|
|
10
10
|
* does not silently drop extension-namespace properties (`w15:collapsed`,
|
|
11
11
|
* `w16cex:...`, etc.) or attributes Word adds after we parsed its schema.
|
|
@@ -95,7 +95,7 @@ export interface PropertyGrabBagDescriptor {
|
|
|
95
95
|
* `TableCellNode.propertiesXml`. That path cannot participate in the
|
|
96
96
|
* attribute-level grab-bag slice until it is retrofit to emit
|
|
97
97
|
* `UnknownPropertyChild[]` through this descriptor. Tracked as a Lane 3
|
|
98
|
-
* Tier-2 backlog entry — see `
|
|
98
|
+
* Tier-2 backlog entry — see `CLAUDE.md (lane status table)`.
|
|
99
99
|
*/
|
|
100
100
|
modelledChildAttributes: ReadonlyMap<string, ReadonlySet<string>>;
|
|
101
101
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OOXML unit constants used by the IO layer's parsers.
|
|
3
|
+
*
|
|
4
|
+
* Slice 3 of refactor/01 package-session. Migrated from
|
|
5
|
+
* src/runtime/units.ts (drift fix #5 — IO-layer constants must not
|
|
6
|
+
* live under src/runtime/**). The runtime module keeps a re-export
|
|
7
|
+
* alias for one-release back-compat.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** OOXML gradient-stop and crop-offset unit (100 000 = 100%). */
|
|
11
|
+
export const GRADIENT_STOP_UNITS = 100_000;
|
|
@@ -5,6 +5,12 @@ import type {
|
|
|
5
5
|
} from "./part-manifest.ts";
|
|
6
6
|
import type {
|
|
7
7
|
EditorAnchorProjection,
|
|
8
|
+
OverlayKind,
|
|
9
|
+
OverlayVisibilityEnforcement,
|
|
10
|
+
OverlayVisibilityPolicy,
|
|
11
|
+
WorkflowMarkupMode,
|
|
12
|
+
WorkflowMarkupModeEnforcement,
|
|
13
|
+
WorkflowMarkupModePolicy,
|
|
8
14
|
WorkflowOverlay,
|
|
9
15
|
WorkflowMetadataDefinition,
|
|
10
16
|
WorkflowMetadataEntry,
|
|
@@ -92,6 +98,17 @@ export interface WorkflowPayloadEnvelope {
|
|
|
92
98
|
workflowOverlay?: WorkflowOverlay;
|
|
93
99
|
/** Present only when the payload was version 1.2+ and carried a non-empty <bw:editorState> block. */
|
|
94
100
|
editorState?: EditorStatePayload;
|
|
101
|
+
/**
|
|
102
|
+
* W10 — class-A overlay-visibility policies, one per `OverlayKind` at
|
|
103
|
+
* most. Empty array when the payload carried no `<bw:overlayVisibility>`
|
|
104
|
+
* block (documents predating the schema read as "no policy").
|
|
105
|
+
*/
|
|
106
|
+
visibilityPolicies?: readonly OverlayVisibilityPolicy[];
|
|
107
|
+
/**
|
|
108
|
+
* X5 — class-A markup-mode policy (single record). `null` when the
|
|
109
|
+
* payload carried no `<bw:markupModePolicy>` block.
|
|
110
|
+
*/
|
|
111
|
+
markupModePolicy?: WorkflowMarkupModePolicy | null;
|
|
95
112
|
validatorIssues?: readonly ValidatorIssue[];
|
|
96
113
|
}
|
|
97
114
|
|
|
@@ -119,6 +136,19 @@ export function buildWorkflowPayloadParts(input: {
|
|
|
119
136
|
workflowOverlay?: WorkflowOverlay;
|
|
120
137
|
/** Optional schema 1.2 editor-state block. Omitted when empty. */
|
|
121
138
|
editorState?: EditorStatePayload;
|
|
139
|
+
/**
|
|
140
|
+
* W10 — class-A overlay-visibility policies. When non-empty, emitted
|
|
141
|
+
* as a `<bw:overlayVisibility>` block inside the workflow payload and
|
|
142
|
+
* forces the customXml part to be written (even when no overlay /
|
|
143
|
+
* metadata / editorState content would otherwise require it).
|
|
144
|
+
*/
|
|
145
|
+
visibilityPolicies?: readonly OverlayVisibilityPolicy[];
|
|
146
|
+
/**
|
|
147
|
+
* X5 — class-A markup-mode policy. When non-null, emitted as a
|
|
148
|
+
* `<bw:markupModePolicy>` block and forces customXml rewrite (same
|
|
149
|
+
* pattern as visibility policies).
|
|
150
|
+
*/
|
|
151
|
+
markupModePolicy?: WorkflowMarkupModePolicy | null;
|
|
122
152
|
documentId: string;
|
|
123
153
|
createdAt: string;
|
|
124
154
|
updatedAt: string;
|
|
@@ -139,13 +169,29 @@ export function buildWorkflowPayloadParts(input: {
|
|
|
139
169
|
: undefined;
|
|
140
170
|
const sourceHasRuntimeOwnedPayloadContent = Boolean(
|
|
141
171
|
existingPayloadEnvelope?.workflowOverlay ||
|
|
142
|
-
(existingPayloadEnvelope?.workflowMetadata.definitions.length ?? 0) > 0
|
|
172
|
+
(existingPayloadEnvelope?.workflowMetadata.definitions.length ?? 0) > 0 ||
|
|
173
|
+
(existingPayloadEnvelope?.visibilityPolicies?.length ?? 0) > 0 ||
|
|
174
|
+
existingPayloadEnvelope?.markupModePolicy != null,
|
|
143
175
|
);
|
|
176
|
+
// Schema 1.2: the editorState block carries the runtime's full workflow
|
|
177
|
+
// state (definitions + entries including `metadataPersistence: "internal"`
|
|
178
|
+
// that do NOT pass the document-backed filter). When the runtime has any
|
|
179
|
+
// such state, the customXml part MUST be emitted — otherwise a caller who
|
|
180
|
+
// only uses `setWorkflowMetadataEntries` / `addScope({ persistence: ...})`
|
|
181
|
+
// ships docs with silently-dropped entries.
|
|
182
|
+
const hasEditorStateContent = hasNonEmptyEditorState(input.editorState);
|
|
183
|
+
const visibilityPolicies = input.visibilityPolicies ?? [];
|
|
184
|
+
const hasVisibilityPolicies = visibilityPolicies.length > 0;
|
|
185
|
+
const markupModePolicy = input.markupModePolicy ?? null;
|
|
186
|
+
const hasMarkupModePolicy = markupModePolicy !== null;
|
|
144
187
|
if (
|
|
145
188
|
workflowMetadata.definitions.length === 0 &&
|
|
146
189
|
workflowMetadata.entries.length === 0 &&
|
|
147
190
|
!input.workflowOverlay &&
|
|
148
|
-
!sourceHasRuntimeOwnedPayloadContent
|
|
191
|
+
!sourceHasRuntimeOwnedPayloadContent &&
|
|
192
|
+
!hasEditorStateContent &&
|
|
193
|
+
!hasVisibilityPolicies &&
|
|
194
|
+
!hasMarkupModePolicy
|
|
149
195
|
) {
|
|
150
196
|
return null;
|
|
151
197
|
}
|
|
@@ -159,6 +205,8 @@ export function buildWorkflowPayloadParts(input: {
|
|
|
159
205
|
workflowMetadata,
|
|
160
206
|
workflowOverlay: input.workflowOverlay,
|
|
161
207
|
editorState: input.editorState,
|
|
208
|
+
visibilityPolicies,
|
|
209
|
+
markupModePolicy,
|
|
162
210
|
preservedExtensionsXml: getPreservedExtensionsXml(input.sourcePackage, descriptor.payloadPartPath),
|
|
163
211
|
});
|
|
164
212
|
const itemPropsXml = buildItemPropsXml(descriptor.itemId);
|
|
@@ -272,17 +320,80 @@ export function parseWorkflowPayloadEnvelopeFromPackage(
|
|
|
272
320
|
|
|
273
321
|
const validatorIssues = validateWorkflowPayloadEnvelope(xml);
|
|
274
322
|
const editorState = parseEditorStateXml(xml);
|
|
323
|
+
// Schema 1.2: the `<bw:editorState>` `workflowMetadata` namespace carries
|
|
324
|
+
// the full runtime snapshot (including entries whose effective persistence
|
|
325
|
+
// is `"internal"`, which do NOT survive the `<bw:entry>` / document-backed
|
|
326
|
+
// filter). Fold its entries + definitions in here so the reload path sees
|
|
327
|
+
// the authoritative state. Existing `<bw:entry>`-extracted data wins on
|
|
328
|
+
// metadataId collision — it represents the external/document-backed view.
|
|
329
|
+
const merged = mergeEditorStateWorkflowMetadata(
|
|
330
|
+
{ definitions, entries },
|
|
331
|
+
editorState,
|
|
332
|
+
);
|
|
333
|
+
const visibilityPolicies = parseOverlayVisibilityBlock(xml);
|
|
334
|
+
const markupModePolicy = parseMarkupModePolicyBlock(xml);
|
|
275
335
|
return {
|
|
276
|
-
workflowMetadata:
|
|
277
|
-
definitions,
|
|
278
|
-
entries,
|
|
279
|
-
},
|
|
336
|
+
workflowMetadata: merged,
|
|
280
337
|
workflowOverlay: parseWorkflowOverlay(xml),
|
|
281
338
|
...(editorState !== undefined ? { editorState } : {}),
|
|
339
|
+
...(visibilityPolicies.length > 0 ? { visibilityPolicies } : {}),
|
|
340
|
+
...(markupModePolicy !== null ? { markupModePolicy } : {}),
|
|
282
341
|
...(validatorIssues.length > 0 ? { validatorIssues } : {}),
|
|
283
342
|
};
|
|
284
343
|
}
|
|
285
344
|
|
|
345
|
+
function mergeEditorStateWorkflowMetadata(
|
|
346
|
+
base: WorkflowMetadataSnapshot,
|
|
347
|
+
editorState: EditorStatePayload | undefined,
|
|
348
|
+
): WorkflowMetadataSnapshot {
|
|
349
|
+
if (!editorState) {
|
|
350
|
+
return base;
|
|
351
|
+
}
|
|
352
|
+
const inlineEntry = editorState.entries.find(
|
|
353
|
+
(candidate) => candidate.namespace === "workflowMetadata" && candidate.inline !== undefined,
|
|
354
|
+
);
|
|
355
|
+
if (!inlineEntry || typeof inlineEntry.inline !== "object" || inlineEntry.inline === null) {
|
|
356
|
+
return base;
|
|
357
|
+
}
|
|
358
|
+
const inlinePayload = inlineEntry.inline as {
|
|
359
|
+
definitions?: WorkflowMetadataDefinition[];
|
|
360
|
+
entries?: WorkflowMetadataEntry[];
|
|
361
|
+
};
|
|
362
|
+
const inlineDefinitions = Array.isArray(inlinePayload.definitions) ? inlinePayload.definitions : [];
|
|
363
|
+
const inlineEntries = Array.isArray(inlinePayload.entries) ? inlinePayload.entries : [];
|
|
364
|
+
|
|
365
|
+
const baseDefinitionIds = new Set(base.definitions.map((definition) => definition.metadataId));
|
|
366
|
+
const baseEntryKeys = new Set(
|
|
367
|
+
base.entries.map((entry) => `${entry.entryId}${entry.metadataId}`),
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const mergedDefinitions = [
|
|
371
|
+
...base.definitions,
|
|
372
|
+
...inlineDefinitions.filter(
|
|
373
|
+
(definition) =>
|
|
374
|
+
definition !== null &&
|
|
375
|
+
typeof definition === "object" &&
|
|
376
|
+
typeof definition.metadataId === "string" &&
|
|
377
|
+
!baseDefinitionIds.has(definition.metadataId),
|
|
378
|
+
),
|
|
379
|
+
];
|
|
380
|
+
const mergedEntries = [
|
|
381
|
+
...base.entries,
|
|
382
|
+
...inlineEntries.filter(
|
|
383
|
+
(entry) =>
|
|
384
|
+
entry !== null &&
|
|
385
|
+
typeof entry === "object" &&
|
|
386
|
+
typeof entry.entryId === "string" &&
|
|
387
|
+
typeof entry.metadataId === "string" &&
|
|
388
|
+
!baseEntryKeys.has(`${entry.entryId}${entry.metadataId}`),
|
|
389
|
+
),
|
|
390
|
+
];
|
|
391
|
+
return {
|
|
392
|
+
definitions: mergedDefinitions,
|
|
393
|
+
entries: mergedEntries,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
286
397
|
function needsSchemaV11(input: {
|
|
287
398
|
workflowMetadata: WorkflowMetadataSnapshot;
|
|
288
399
|
workflowOverlay?: WorkflowOverlay;
|
|
@@ -460,10 +571,16 @@ function buildPayloadXml(input: {
|
|
|
460
571
|
workflowMetadata: WorkflowMetadataSnapshot;
|
|
461
572
|
workflowOverlay?: WorkflowOverlay;
|
|
462
573
|
editorState?: EditorStatePayload;
|
|
574
|
+
/** W10 — class-A overlay-visibility policies. Empty = block omitted. */
|
|
575
|
+
visibilityPolicies: readonly OverlayVisibilityPolicy[];
|
|
576
|
+
/** X5 — class-A markup-mode policy. `null` = block omitted. */
|
|
577
|
+
markupModePolicy: WorkflowMarkupModePolicy | null;
|
|
463
578
|
preservedExtensionsXml: string;
|
|
464
579
|
}): string {
|
|
465
580
|
const hasEditorState = hasNonEmptyEditorState(input.editorState);
|
|
466
|
-
const
|
|
581
|
+
const hasVisibilityPolicies = input.visibilityPolicies.length > 0;
|
|
582
|
+
const hasMarkupModePolicy = input.markupModePolicy !== null;
|
|
583
|
+
const schemaVersion = hasEditorState || hasVisibilityPolicies || hasMarkupModePolicy
|
|
467
584
|
? "1.2"
|
|
468
585
|
: needsSchemaV11(input)
|
|
469
586
|
? "1.1"
|
|
@@ -523,6 +640,12 @@ function buildPayloadXml(input: {
|
|
|
523
640
|
.join("\n");
|
|
524
641
|
|
|
525
642
|
const editorStateXml = hasEditorState ? buildEditorStateXml(input.editorState!) : "";
|
|
643
|
+
const overlayVisibilityXml = hasVisibilityPolicies
|
|
644
|
+
? buildOverlayVisibilityXml(input.visibilityPolicies)
|
|
645
|
+
: "";
|
|
646
|
+
const markupModePolicyXml = input.markupModePolicy
|
|
647
|
+
? buildMarkupModePolicyXml(input.markupModePolicy)
|
|
648
|
+
: "";
|
|
526
649
|
|
|
527
650
|
return [
|
|
528
651
|
`<?xml version="1.0" encoding="UTF-8"?>`,
|
|
@@ -535,6 +658,8 @@ function buildPayloadXml(input: {
|
|
|
535
658
|
definitionEntriesXml ? indentLines(definitionEntriesXml, 4) : "",
|
|
536
659
|
metadataEntriesXml ? indentLines(metadataEntriesXml, 4) : "",
|
|
537
660
|
` </bw:metadata>`,
|
|
661
|
+
overlayVisibilityXml,
|
|
662
|
+
markupModePolicyXml,
|
|
538
663
|
editorStateXml,
|
|
539
664
|
extensionsXml
|
|
540
665
|
? ` <bw:extensions>\n${indentLines(extensionsXml, 4)}\n </bw:extensions>`
|
|
@@ -543,6 +668,156 @@ function buildPayloadXml(input: {
|
|
|
543
668
|
].filter((line) => line.length > 0).join("\n");
|
|
544
669
|
}
|
|
545
670
|
|
|
671
|
+
// ---------------------------------------------------------------------------
|
|
672
|
+
// W10 · <bw:overlayVisibility> block
|
|
673
|
+
//
|
|
674
|
+
// Fixed OverlayKind order for byte-identical round-trip. See
|
|
675
|
+
// `src/runtime/workflow/visibility-policy.ts` for the canonical order.
|
|
676
|
+
// ---------------------------------------------------------------------------
|
|
677
|
+
|
|
678
|
+
const OVERLAY_KIND_ORDER: readonly OverlayKind[] = [
|
|
679
|
+
"scope-rail",
|
|
680
|
+
"comments",
|
|
681
|
+
"tracked-changes",
|
|
682
|
+
"suggestions",
|
|
683
|
+
"debug-panel",
|
|
684
|
+
"presence",
|
|
685
|
+
];
|
|
686
|
+
|
|
687
|
+
function buildOverlayVisibilityXml(
|
|
688
|
+
policies: readonly OverlayVisibilityPolicy[],
|
|
689
|
+
): string {
|
|
690
|
+
if (policies.length === 0) return "";
|
|
691
|
+
const index = (kind: OverlayKind): number => OVERLAY_KIND_ORDER.indexOf(kind);
|
|
692
|
+
const ordered = [...policies].sort((a, b) => index(a.kind) - index(b.kind));
|
|
693
|
+
const body = ordered.map(formatOverlayVisibilityPolicy).join("\n");
|
|
694
|
+
return ` <bw:overlayVisibility>\n${body}\n </bw:overlayVisibility>`;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function formatOverlayVisibilityPolicy(policy: OverlayVisibilityPolicy): string {
|
|
698
|
+
const attrs = [
|
|
699
|
+
` kind="${escapeXml(policy.kind)}"`,
|
|
700
|
+
` enforcement="${escapeXml(policy.enforcement)}"`,
|
|
701
|
+
` defaultOn="${policy.defaultOn ? "true" : "false"}"`,
|
|
702
|
+
].join("");
|
|
703
|
+
if (!policy.authoredBy) {
|
|
704
|
+
return ` <bw:policy${attrs}/>`;
|
|
705
|
+
}
|
|
706
|
+
return [
|
|
707
|
+
` <bw:policy${attrs}>`,
|
|
708
|
+
` <bw:authoredBy actorId="${escapeXml(policy.authoredBy.actorId)}" at="${escapeXml(policy.authoredBy.at)}"/>`,
|
|
709
|
+
` </bw:policy>`,
|
|
710
|
+
].join("\n");
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
const VALID_OVERLAY_KINDS: ReadonlySet<OverlayKind> = new Set(OVERLAY_KIND_ORDER);
|
|
714
|
+
const VALID_ENFORCEMENT: ReadonlySet<OverlayVisibilityEnforcement> = new Set([
|
|
715
|
+
"authored-default",
|
|
716
|
+
"always",
|
|
717
|
+
"never",
|
|
718
|
+
]);
|
|
719
|
+
|
|
720
|
+
// ---------------------------------------------------------------------------
|
|
721
|
+
// X5 · <bw:markupModePolicy> block
|
|
722
|
+
//
|
|
723
|
+
// Single-record policy; no ordering concerns. Byte-identical round-trip
|
|
724
|
+
// when unchanged: same attribute ordering (mode, enforcement, optional
|
|
725
|
+
// authoredBy child) every emit.
|
|
726
|
+
// ---------------------------------------------------------------------------
|
|
727
|
+
|
|
728
|
+
const VALID_MARKUP_MODES: ReadonlySet<WorkflowMarkupMode> = new Set([
|
|
729
|
+
"clean",
|
|
730
|
+
"simple",
|
|
731
|
+
"all",
|
|
732
|
+
]);
|
|
733
|
+
const VALID_MARKUP_ENFORCEMENT: ReadonlySet<WorkflowMarkupModeEnforcement> = new Set([
|
|
734
|
+
"authored-default",
|
|
735
|
+
"always",
|
|
736
|
+
]);
|
|
737
|
+
|
|
738
|
+
function buildMarkupModePolicyXml(policy: WorkflowMarkupModePolicy): string {
|
|
739
|
+
const attrs = [
|
|
740
|
+
` mode="${escapeXml(policy.mode)}"`,
|
|
741
|
+
` enforcement="${escapeXml(policy.enforcement)}"`,
|
|
742
|
+
].join("");
|
|
743
|
+
if (!policy.authoredBy) {
|
|
744
|
+
return ` <bw:markupModePolicy${attrs}/>`;
|
|
745
|
+
}
|
|
746
|
+
return [
|
|
747
|
+
` <bw:markupModePolicy${attrs}>`,
|
|
748
|
+
` <bw:authoredBy actorId="${escapeXml(policy.authoredBy.actorId)}" at="${escapeXml(policy.authoredBy.at)}"/>`,
|
|
749
|
+
` </bw:markupModePolicy>`,
|
|
750
|
+
].join("\n");
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function parseMarkupModePolicyBlock(xml: string): WorkflowMarkupModePolicy | null {
|
|
754
|
+
const match = xml.match(
|
|
755
|
+
/<bw:markupModePolicy\b([^>]*?)(?:\/>|>([\s\S]*?)<\/bw:markupModePolicy>)/u,
|
|
756
|
+
);
|
|
757
|
+
if (!match) return null;
|
|
758
|
+
const attrs = parseAttributes(match[1] ?? "");
|
|
759
|
+
const mode = attrs.mode;
|
|
760
|
+
const enforcement = attrs.enforcement;
|
|
761
|
+
if (!mode || !VALID_MARKUP_MODES.has(mode as WorkflowMarkupMode)) return null;
|
|
762
|
+
if (!enforcement || !VALID_MARKUP_ENFORCEMENT.has(enforcement as WorkflowMarkupModeEnforcement)) {
|
|
763
|
+
return null;
|
|
764
|
+
}
|
|
765
|
+
const childXml = match[2] ?? "";
|
|
766
|
+
const authoredMatch = childXml.match(/<bw:authoredBy\b([^>]*)\/>/u);
|
|
767
|
+
const authoredAttrs = authoredMatch
|
|
768
|
+
? parseAttributes(authoredMatch[1] ?? "")
|
|
769
|
+
: undefined;
|
|
770
|
+
const authoredBy =
|
|
771
|
+
authoredAttrs?.actorId && authoredAttrs?.at
|
|
772
|
+
? { actorId: authoredAttrs.actorId, at: authoredAttrs.at }
|
|
773
|
+
: undefined;
|
|
774
|
+
return {
|
|
775
|
+
mode: mode as WorkflowMarkupMode,
|
|
776
|
+
enforcement: enforcement as WorkflowMarkupModeEnforcement,
|
|
777
|
+
...(authoredBy ? { authoredBy } : {}),
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
function parseOverlayVisibilityBlock(
|
|
782
|
+
xml: string,
|
|
783
|
+
): readonly OverlayVisibilityPolicy[] {
|
|
784
|
+
const block = xml.match(
|
|
785
|
+
/<bw:overlayVisibility\b[^>]*>([\s\S]*?)<\/bw:overlayVisibility>/u,
|
|
786
|
+
);
|
|
787
|
+
if (!block) return [];
|
|
788
|
+
const body = block[1] ?? "";
|
|
789
|
+
const policies: OverlayVisibilityPolicy[] = [];
|
|
790
|
+
const pattern =
|
|
791
|
+
/<bw:policy\b([^>]*?)(?:\/>|>([\s\S]*?)<\/bw:policy>)/gu;
|
|
792
|
+
for (const match of body.matchAll(pattern)) {
|
|
793
|
+
const attrs = parseAttributes(match[1] ?? "");
|
|
794
|
+
const kind = attrs.kind;
|
|
795
|
+
const enforcement = attrs.enforcement;
|
|
796
|
+
const defaultOnRaw = attrs.defaultOn;
|
|
797
|
+
if (!kind || !VALID_OVERLAY_KINDS.has(kind as OverlayKind)) continue;
|
|
798
|
+
if (!enforcement || !VALID_ENFORCEMENT.has(enforcement as OverlayVisibilityEnforcement)) continue;
|
|
799
|
+
if (defaultOnRaw !== "true" && defaultOnRaw !== "false") continue;
|
|
800
|
+
|
|
801
|
+
const childXml = match[2] ?? "";
|
|
802
|
+
const authoredMatch = childXml.match(/<bw:authoredBy\b([^>]*)\/>/u);
|
|
803
|
+
const authoredAttrs = authoredMatch
|
|
804
|
+
? parseAttributes(authoredMatch[1] ?? "")
|
|
805
|
+
: undefined;
|
|
806
|
+
const authoredBy =
|
|
807
|
+
authoredAttrs?.actorId && authoredAttrs?.at
|
|
808
|
+
? { actorId: authoredAttrs.actorId, at: authoredAttrs.at }
|
|
809
|
+
: undefined;
|
|
810
|
+
|
|
811
|
+
policies.push({
|
|
812
|
+
kind: kind as OverlayKind,
|
|
813
|
+
enforcement: enforcement as OverlayVisibilityEnforcement,
|
|
814
|
+
defaultOn: defaultOnRaw === "true",
|
|
815
|
+
...(authoredBy ? { authoredBy } : {}),
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
return policies;
|
|
819
|
+
}
|
|
820
|
+
|
|
546
821
|
function buildItemPropsXml(itemId: string): string {
|
|
547
822
|
return [
|
|
548
823
|
`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`,
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure-data anchor shapes shared by the review-record types in
|
|
3
|
+
* `src/model/review/**` and the mapping mechanism in
|
|
4
|
+
* `src/core/selection/mapping.ts`. Anchors are model-level concerns — they
|
|
5
|
+
* describe where on a `CanonicalDocument` a revision or comment is
|
|
6
|
+
* attached — while the mapping / remap engine that evolves anchors across
|
|
7
|
+
* transactions remains in core.
|
|
8
|
+
*
|
|
9
|
+
* Moved here from `src/core/selection/mapping.ts` so the model layer can
|
|
10
|
+
* define `RevisionRecord` + `CommentThread` without importing up into core.
|
|
11
|
+
* The old mapping module re-exports every symbol in this file for
|
|
12
|
+
* back-compat; existing call-sites continue to work unchanged.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type Position = number;
|
|
16
|
+
export type Assoc = -1 | 1;
|
|
17
|
+
|
|
18
|
+
export interface DocRange {
|
|
19
|
+
from: Position;
|
|
20
|
+
to: Position;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface BoundaryAssoc {
|
|
24
|
+
start: Assoc;
|
|
25
|
+
end: Assoc;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RangeAnchor {
|
|
29
|
+
kind: "range";
|
|
30
|
+
range: DocRange;
|
|
31
|
+
assoc: BoundaryAssoc;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface NodeAnchor {
|
|
35
|
+
kind: "node";
|
|
36
|
+
at: Position;
|
|
37
|
+
assoc: Assoc;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface DetachedAnchor {
|
|
41
|
+
kind: "detached";
|
|
42
|
+
lastKnownRange: DocRange;
|
|
43
|
+
reason: "deleted" | "invalidatedByStructureChange" | "importAmbiguity";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Internal representation of an anchor projection — uses `DocRange` so
|
|
48
|
+
* mapping helpers compose ranges independently of assoc semantics. The
|
|
49
|
+
* public-facing shape lives at `src/api/public-types.ts` (same simple name
|
|
50
|
+
* `EditorAnchorProjection`) and is flat (`{ kind: "range", from, to, assoc }`).
|
|
51
|
+
* Conversion between the two goes through `src/core/selection/anchor-conversion.ts`.
|
|
52
|
+
*/
|
|
53
|
+
export type InternalEditorAnchorProjection = RangeAnchor | NodeAnchor | DetachedAnchor;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @deprecated X3 Phase 5 — prefer `InternalEditorAnchorProjection` to avoid
|
|
57
|
+
* name-collision with the public `EditorAnchorProjection` from
|
|
58
|
+
* `src/api/public-types.ts`. Internal call-sites have migrated (via
|
|
59
|
+
* `import type { EditorAnchorProjection as InternalEditorAnchorProjection }`
|
|
60
|
+
* aliasing in `document-runtime.ts`). This alias stays for one release cycle
|
|
61
|
+
* so third-party internal consumers don't break. Remove in v2.1+.
|
|
62
|
+
*/
|
|
63
|
+
export type EditorAnchorProjection = InternalEditorAnchorProjection;
|
|
64
|
+
|
|
65
|
+
export const DEFAULT_BOUNDARY_ASSOC: BoundaryAssoc = {
|
|
66
|
+
start: 1,
|
|
67
|
+
end: -1,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function normalizeRange(range: DocRange): DocRange {
|
|
71
|
+
return range.from <= range.to
|
|
72
|
+
? { from: range.from, to: range.to }
|
|
73
|
+
: { from: range.to, to: range.from };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function createDetachedAnchor(
|
|
77
|
+
lastKnownRange: DocRange,
|
|
78
|
+
reason: DetachedAnchor["reason"],
|
|
79
|
+
): DetachedAnchor {
|
|
80
|
+
return {
|
|
81
|
+
kind: "detached",
|
|
82
|
+
lastKnownRange: normalizeRange(lastKnownRange),
|
|
83
|
+
reason,
|
|
84
|
+
};
|
|
85
|
+
}
|