@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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* content type.
|
|
8
8
|
*
|
|
9
9
|
* Required by:
|
|
10
|
-
*
|
|
10
|
+
* CLAUDE.md (lane status table) §2 A.5
|
|
11
11
|
*
|
|
12
12
|
* Schema shape (ECMA-376 Part 1, Office Extended properties):
|
|
13
13
|
* <Properties xmlns="…/extended-properties" xmlns:vt="…/docPropsVTypes">
|
|
@@ -32,11 +32,16 @@ const V_NS = `xmlns:v="urn:schemas-microsoft-com:vml"`;
|
|
|
32
32
|
const WP_NS = `xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"`;
|
|
33
33
|
const WPS_NS = `xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"`;
|
|
34
34
|
const A_NS = `xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"`;
|
|
35
|
+
// DrawingML pic namespace — required at the part root because inline-image
|
|
36
|
+
// serialization and preserved rawXml both emit pic:pic / pic:spPr elements.
|
|
37
|
+
// Word tolerates undefined prefixes; LibreOffice strict-parses and rejects
|
|
38
|
+
// ("Namespace prefix pic on spPr is not defined", word/footer1.xml).
|
|
39
|
+
const PIC_NS = `xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"`;
|
|
35
40
|
const W10_NS = `xmlns:w10="urn:schemas-microsoft-com:office:word"`;
|
|
36
41
|
const W14_NS = `xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"`;
|
|
37
42
|
const W15_NS = `xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"`;
|
|
38
43
|
const WP14_NS = `xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"`;
|
|
39
|
-
const EXTENDED_ROOT_ATTRS = `${MC_NS} ${O_NS} ${V_NS} ${WP_NS} ${WPS_NS} ${A_NS} ${W10_NS} ${W14_NS} ${W15_NS} ${WP14_NS} mc:Ignorable="wps wp14 w14 w15"`;
|
|
44
|
+
const EXTENDED_ROOT_ATTRS = `${MC_NS} ${O_NS} ${V_NS} ${WP_NS} ${WPS_NS} ${A_NS} ${PIC_NS} ${W10_NS} ${W14_NS} ${W15_NS} ${WP14_NS} mc:Ignorable="wps wp14 w14 w15"`;
|
|
40
45
|
|
|
41
46
|
/**
|
|
42
47
|
* Serialize a HeaderDocument into a headerN.xml string.
|
|
@@ -102,12 +102,28 @@ interface ParagraphSerializationResult {
|
|
|
102
102
|
boundary: RevisionParagraphBoundary;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
type SerializeTelemetryBus = import("../../runtime/debug/telemetry-bus.ts").TelemetryBus;
|
|
106
|
+
let activeSerializeTelemetryBus: SerializeTelemetryBus | undefined;
|
|
107
|
+
|
|
108
|
+
export function setActiveSerializeTelemetryBus(bus: SerializeTelemetryBus | undefined): void {
|
|
109
|
+
activeSerializeTelemetryBus = bus;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function serializePerformanceNow(): number {
|
|
113
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
114
|
+
return performance.now();
|
|
115
|
+
}
|
|
116
|
+
return Date.now();
|
|
117
|
+
}
|
|
118
|
+
|
|
105
119
|
export function serializeMainDocument(
|
|
106
120
|
content: DocumentRootNode,
|
|
107
121
|
preservation: PreservationStore = { opaqueFragments: {}, packageParts: {} },
|
|
108
122
|
existingRelationships: readonly OpcRelationship[] = [],
|
|
109
123
|
options: SerializeMainDocumentOptions = {},
|
|
110
124
|
): SerializedMainDocument {
|
|
125
|
+
const bus = activeSerializeTelemetryBus;
|
|
126
|
+
const started = bus?.isEnabled("serialize") ? serializePerformanceNow() : 0;
|
|
111
127
|
const nextRelationshipIndex =
|
|
112
128
|
existingRelationships.reduce((maxIndex, relationship) => {
|
|
113
129
|
const match = /^rIdHyperlink(\d+)$/.exec(relationship.id);
|
|
@@ -267,6 +283,26 @@ export function serializeMainDocument(
|
|
|
267
283
|
offsetParagraphBoundary(boundary, prefix.length),
|
|
268
284
|
);
|
|
269
285
|
|
|
286
|
+
if (bus?.isEnabled("serialize")) {
|
|
287
|
+
const blockKindCounts: Record<string, number> = Object.create(null);
|
|
288
|
+
for (const node of content.children) {
|
|
289
|
+
const kind = (node as { type?: string }).type ?? "unknown";
|
|
290
|
+
blockKindCounts[kind] = (blockKindCounts[kind] ?? 0) + 1;
|
|
291
|
+
}
|
|
292
|
+
bus.emit({
|
|
293
|
+
channel: "serialize",
|
|
294
|
+
type: "serialize.main_document.completed",
|
|
295
|
+
t: 0,
|
|
296
|
+
payload: {
|
|
297
|
+
blockCount: content.children.length,
|
|
298
|
+
blockKindCounts,
|
|
299
|
+
documentXmlBytes: documentXml.length,
|
|
300
|
+
relationshipCount: state.relationships.length,
|
|
301
|
+
ms: serializePerformanceNow() - started,
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
270
306
|
return {
|
|
271
307
|
documentXml,
|
|
272
308
|
relationships: state.relationships,
|
|
@@ -1664,9 +1700,18 @@ function serializeDocumentAttributes(
|
|
|
1664
1700
|
}
|
|
1665
1701
|
}
|
|
1666
1702
|
|
|
1703
|
+
// DrawingML picture namespace — always declare at the document root. Inline-
|
|
1704
|
+
// image serialization (wp:inline…xmlns:pic=…) locally scopes the pic prefix,
|
|
1705
|
+
// so fresh images are self-contained. But preserved rawXml (opaque_block /
|
|
1706
|
+
// complex objects / headers-footers round-trip) may emit pic:pic / pic:spPr
|
|
1707
|
+
// relying on inherited-scope. Without xmlns:pic at the root, LibreOffice
|
|
1708
|
+
// strict-parses and rejects with "Namespace prefix pic on spPr is not
|
|
1709
|
+
// defined". Declared before the `attributes` spread so a source-document
|
|
1710
|
+
// override (should one exist) wins.
|
|
1667
1711
|
const merged: Record<string, string> = {
|
|
1668
1712
|
"xmlns:r": ns.r,
|
|
1669
1713
|
"xmlns:w": ns.w,
|
|
1714
|
+
"xmlns:pic": "http://schemas.openxmlformats.org/drawingml/2006/picture",
|
|
1670
1715
|
...extensionXmlns,
|
|
1671
1716
|
...(attributes ?? {}),
|
|
1672
1717
|
};
|
|
@@ -30,13 +30,28 @@ export function buildRunPropertiesXml(rPr: CanonicalRunFormatting | undefined):
|
|
|
30
30
|
// 1. rStyle
|
|
31
31
|
if (rPr.characterStyleId) parts.push(`<w:rStyle w:val="${escXml(rPr.characterStyleId)}"/>`);
|
|
32
32
|
|
|
33
|
-
// 2. rFonts
|
|
34
|
-
|
|
33
|
+
// 2. rFonts — concrete names + ECMA-376 §17.3.2.26 theme-slot attrs.
|
|
34
|
+
// The complex-script theme attr is emitted as `w:cstheme` (all
|
|
35
|
+
// lowercase) to match Word's output.
|
|
36
|
+
if (
|
|
37
|
+
rPr.fontFamilyAscii ||
|
|
38
|
+
rPr.fontFamilyHAnsi ||
|
|
39
|
+
rPr.fontFamilyEastAsia ||
|
|
40
|
+
rPr.fontFamilyCs ||
|
|
41
|
+
rPr.asciiTheme ||
|
|
42
|
+
rPr.hAnsiTheme ||
|
|
43
|
+
rPr.eastAsiaTheme ||
|
|
44
|
+
rPr.csTheme
|
|
45
|
+
) {
|
|
35
46
|
const attrs: string[] = [];
|
|
36
47
|
if (rPr.fontFamilyAscii) attrs.push(`w:ascii="${escXml(rPr.fontFamilyAscii)}"`);
|
|
37
48
|
if (rPr.fontFamilyHAnsi) attrs.push(`w:hAnsi="${escXml(rPr.fontFamilyHAnsi)}"`);
|
|
38
49
|
if (rPr.fontFamilyEastAsia) attrs.push(`w:eastAsia="${escXml(rPr.fontFamilyEastAsia)}"`);
|
|
39
50
|
if (rPr.fontFamilyCs) attrs.push(`w:cs="${escXml(rPr.fontFamilyCs)}"`);
|
|
51
|
+
if (rPr.asciiTheme) attrs.push(`w:asciiTheme="${escXml(rPr.asciiTheme)}"`);
|
|
52
|
+
if (rPr.hAnsiTheme) attrs.push(`w:hAnsiTheme="${escXml(rPr.hAnsiTheme)}"`);
|
|
53
|
+
if (rPr.eastAsiaTheme) attrs.push(`w:eastAsiaTheme="${escXml(rPr.eastAsiaTheme)}"`);
|
|
54
|
+
if (rPr.csTheme) attrs.push(`w:cstheme="${escXml(rPr.csTheme)}"`);
|
|
40
55
|
parts.push(`<w:rFonts ${attrs.join(" ")}/>`);
|
|
41
56
|
}
|
|
42
57
|
|
package/src/io/export/twip.ts
CHANGED
|
@@ -4,7 +4,6 @@ import type {
|
|
|
4
4
|
CustomXmlNode,
|
|
5
5
|
DiagnosticStore,
|
|
6
6
|
DocumentRootNode,
|
|
7
|
-
FieldRegistry,
|
|
8
7
|
InlineNode,
|
|
9
8
|
MediaCatalog,
|
|
10
9
|
OpaqueBlockNode,
|
|
@@ -37,21 +36,30 @@ import type {
|
|
|
37
36
|
ParsedTableCellNode,
|
|
38
37
|
ParsedTableRowNode,
|
|
39
38
|
} from "../ooxml/parse-main-document.ts";
|
|
40
|
-
import { classifyFieldInstruction
|
|
39
|
+
import { classifyFieldInstruction } from "../ooxml/parse-fields.ts";
|
|
41
40
|
import {
|
|
42
41
|
type LoadScheduler,
|
|
43
42
|
nowMs,
|
|
44
43
|
shouldYield,
|
|
45
44
|
} from "../load-scheduler.ts";
|
|
46
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Output of `normalizeParsedTextDocument`. Carries content + media +
|
|
48
|
+
* preservation + diagnostics + the ambient section-properties rider,
|
|
49
|
+
* and nothing else. The canonical `fieldRegistry` is NOT produced here
|
|
50
|
+
* because it requires the fully-assembled styles catalog + subParts;
|
|
51
|
+
* it is constructed inside `createImportedCanonicalDocument` (session
|
|
52
|
+
* layer) with all three inputs available. Tests that previously
|
|
53
|
+
* checked `normalized.fieldRegistry` call `buildFieldRegistry` from
|
|
54
|
+
* `src/io/ooxml/parse-fields.ts` directly — that is the canonical
|
|
55
|
+
* field-registry factory.
|
|
56
|
+
*/
|
|
47
57
|
export interface NormalizedTextDocument {
|
|
48
58
|
content: DocumentRootNode;
|
|
49
59
|
media: MediaCatalog;
|
|
50
60
|
preservation: PreservationStore;
|
|
51
61
|
diagnostics: DiagnosticStore;
|
|
52
62
|
finalSectionProperties?: ParsedMainDocument["finalSectionProperties"];
|
|
53
|
-
/** Package-backed field registry built during normalization. */
|
|
54
|
-
fieldRegistry?: FieldRegistry;
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
interface NormalizationState {
|
|
@@ -67,7 +75,6 @@ interface NormalizationState {
|
|
|
67
75
|
export function normalizeParsedTextDocument(
|
|
68
76
|
document: ParsedMainDocument,
|
|
69
77
|
packagePartName = "/word/document.xml",
|
|
70
|
-
options?: { styles?: import("../../model/canonical-document.ts").StylesCatalog },
|
|
71
78
|
): NormalizedTextDocument {
|
|
72
79
|
const state: NormalizationState = {
|
|
73
80
|
nextFragmentIndex: 1,
|
|
@@ -103,13 +110,6 @@ export function normalizeParsedTextDocument(
|
|
|
103
110
|
|
|
104
111
|
const content: DocumentRootNode = { type: "doc", children };
|
|
105
112
|
|
|
106
|
-
// Build the field registry from normalized content.
|
|
107
|
-
// When styles are available, the registry includes full TOC heading resolution.
|
|
108
|
-
// Without styles, it still catalogs all field instances for the supported/preserve-only partition.
|
|
109
|
-
const styles = options?.styles ?? { paragraphs: {}, characters: {}, tables: {} };
|
|
110
|
-
const fieldRegistry = buildFieldRegistry({ content, styles });
|
|
111
|
-
const hasFields = fieldRegistry.supported.length > 0 || fieldRegistry.preserveOnly.length > 0;
|
|
112
|
-
|
|
113
113
|
return {
|
|
114
114
|
content,
|
|
115
115
|
media: state.media,
|
|
@@ -118,7 +118,6 @@ export function normalizeParsedTextDocument(
|
|
|
118
118
|
...(document.finalSectionProperties !== undefined
|
|
119
119
|
? { finalSectionProperties: document.finalSectionProperties }
|
|
120
120
|
: {}),
|
|
121
|
-
...(hasFields ? { fieldRegistry } : {}),
|
|
122
121
|
};
|
|
123
122
|
}
|
|
124
123
|
|
|
@@ -138,7 +137,6 @@ export async function normalizeParsedTextDocumentAsync(
|
|
|
138
137
|
document: ParsedMainDocument,
|
|
139
138
|
packagePartName = "/word/document.xml",
|
|
140
139
|
scheduler: LoadScheduler,
|
|
141
|
-
options?: { styles?: import("../../model/canonical-document.ts").StylesCatalog },
|
|
142
140
|
): Promise<NormalizedTextDocument> {
|
|
143
141
|
const state: NormalizationState = {
|
|
144
142
|
nextFragmentIndex: 1,
|
|
@@ -184,10 +182,6 @@ export async function normalizeParsedTextDocumentAsync(
|
|
|
184
182
|
|
|
185
183
|
const content: DocumentRootNode = { type: "doc", children };
|
|
186
184
|
|
|
187
|
-
const styles = options?.styles ?? { paragraphs: {}, characters: {}, tables: {} };
|
|
188
|
-
const fieldRegistry = buildFieldRegistry({ content, styles });
|
|
189
|
-
const hasFields = fieldRegistry.supported.length > 0 || fieldRegistry.preserveOnly.length > 0;
|
|
190
|
-
|
|
191
185
|
return {
|
|
192
186
|
content,
|
|
193
187
|
media: state.media,
|
|
@@ -196,7 +190,6 @@ export async function normalizeParsedTextDocumentAsync(
|
|
|
196
190
|
...(document.finalSectionProperties !== undefined
|
|
197
191
|
? { finalSectionProperties: document.finalSectionProperties }
|
|
198
192
|
: {}),
|
|
199
|
-
...(hasFields ? { fieldRegistry } : {}),
|
|
200
193
|
};
|
|
201
194
|
}
|
|
202
195
|
|
|
@@ -560,6 +553,18 @@ function normalizeInlineChildren(
|
|
|
560
553
|
bookmarkId: node.bookmarkId,
|
|
561
554
|
});
|
|
562
555
|
break;
|
|
556
|
+
case "scope_marker_start":
|
|
557
|
+
normalized.push({
|
|
558
|
+
type: "scope_marker_start",
|
|
559
|
+
scopeId: node.scopeId,
|
|
560
|
+
});
|
|
561
|
+
break;
|
|
562
|
+
case "scope_marker_end":
|
|
563
|
+
normalized.push({
|
|
564
|
+
type: "scope_marker_end",
|
|
565
|
+
scopeId: node.scopeId,
|
|
566
|
+
});
|
|
567
|
+
break;
|
|
563
568
|
case "footnote_ref":
|
|
564
569
|
normalized.push({
|
|
565
570
|
type: "footnote_ref",
|
|
@@ -672,7 +677,7 @@ function normalizeDrawingFrameNode(
|
|
|
672
677
|
* surface renderer can resolve `previewMediaId` → `previewSrc` the same
|
|
673
678
|
* way it does for inline images. Chart/SmartArt nodes weren't previously
|
|
674
679
|
* registered because only image nodes walked through `normalizeImageNode`.
|
|
675
|
-
* Needed by
|
|
680
|
+
* Needed by CLAUDE.md (lane status table) Stage 0 (real mc:Fallback bitmaps) and
|
|
676
681
|
* Stage 0B (synthesized previews from the demo harness decorator) —
|
|
677
682
|
* without this, previewMediaId sits in the canonical model but
|
|
678
683
|
* `canonicalDocument.media.items` has no corresponding MediaItem and
|
|
@@ -850,6 +855,8 @@ function measureNormalizedInlineDisplayLength(nodes: InlineNode[]): number {
|
|
|
850
855
|
return total + measureNormalizedInlineDisplayLength(node.children);
|
|
851
856
|
case "bookmark_start":
|
|
852
857
|
case "bookmark_end":
|
|
858
|
+
case "scope_marker_start":
|
|
859
|
+
case "scope_marker_end":
|
|
853
860
|
return total;
|
|
854
861
|
default:
|
|
855
862
|
return total + 1;
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "../xml-attr-helpers.ts";
|
|
23
23
|
import type { XmlElementNode } from "../xml-element.ts";
|
|
24
24
|
import { parseXml } from "../xml-parser.ts";
|
|
25
|
-
import { GRADIENT_STOP_UNITS } from "
|
|
25
|
+
import { GRADIENT_STOP_UNITS } from "../units.ts";
|
|
26
26
|
|
|
27
27
|
import type {
|
|
28
28
|
BubbleSeries,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Resolve a `ColorRef` into a concrete sRGB hex string.
|
|
3
3
|
*
|
|
4
4
|
* Implements the second layer of the OOXML chart-color cascade
|
|
5
|
-
* (
|
|
5
|
+
* (CLAUDE.md (lane status table) § 4 Task 2.2): scheme-color and
|
|
6
6
|
* themeLinked references are looked up in `ResolvedTheme.colors`, and
|
|
7
7
|
* OOXML color modifiers (`lumMod`, `lumOff`, `shade`, `tint`, `satMod`,
|
|
8
8
|
* `hueMod`) are applied in declaration order via HSL color math per
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import type { ColorMod, ColorRef } from "./types.ts";
|
|
21
21
|
import type { ResolvedTheme } from "../../../model/canonical-document.ts";
|
|
22
|
-
import { GRADIENT_STOP_UNITS } from "
|
|
22
|
+
import { GRADIENT_STOP_UNITS } from "../units.ts";
|
|
23
23
|
|
|
24
24
|
const FALLBACK_COLOR = "#808080";
|
|
25
25
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Re-export shim. The canonical chart type definitions live in
|
|
5
5
|
* `src/model/chart-types.ts` — that location avoids the former
|
|
6
|
-
* `model → io` backward dependency (see `
|
|
6
|
+
* `model → io` backward dependency (see `CLAUDE.md (lane status table)`
|
|
7
7
|
* §F1). io/ooxml/chart and ui-tailwind/chart consumers can continue
|
|
8
8
|
* importing from this path unchanged.
|
|
9
9
|
*/
|
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
* no side-effects that break the editor. Parser proceeds as today.
|
|
11
11
|
*
|
|
12
12
|
* - **offloadable** — a native OOXML package (Word sub-doc, Excel
|
|
13
|
-
* workbook) that a host-side storage
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* workbook, PowerPoint presentation) that a host-side storage
|
|
14
|
+
* adapter extracts at load (`storeEmbeddedDocument`) and
|
|
15
|
+
* reconstitutes at export (`loadEmbeddedDocument`). Refactor/01
|
|
16
|
+
* Step 7 activated this classification; the offload pipeline lives
|
|
17
|
+
* at `src/session/import/embedded-offload.ts` +
|
|
18
|
+
* `src/session/export/embedded-reconstitute.ts`. When the host
|
|
19
|
+
* does NOT implement the adapter methods, `offloadable` manifests
|
|
20
|
+
* fall through to the opaque-fragment preservation path — the
|
|
21
|
+
* bytes still round-trip byte-identical, they just stay on the
|
|
22
|
+
* parent package.
|
|
18
23
|
*
|
|
19
24
|
* - **store-only** — complex binary or undigestible content (PDF,
|
|
20
25
|
* legacy binary Office, package-embedded docx with icon aspect,
|
|
@@ -45,38 +50,54 @@
|
|
|
45
50
|
* template variants), it is store-only even if ProgID + content-type
|
|
46
51
|
* were both missing. Weak signal but matches file-type intent.
|
|
47
52
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
+
* Classification split (refactor/01 Step 7, 2026-04-22):
|
|
54
|
+
* - Native OOXML ProgIDs → `offloadable`:
|
|
55
|
+
* Word.Document.*, Word.DocumentMacroEnabled.*, Word.Template.*,
|
|
56
|
+
* Excel.Sheet.*, Excel.SheetMacroEnabled.*, Excel.Worksheet.*,
|
|
57
|
+
* Excel.Chart.*, Excel.ChartMacroEnabled.*,
|
|
58
|
+
* PowerPoint.Slide.*, PowerPoint.SlideMacroEnabled.*,
|
|
59
|
+
* PowerPoint.Show.*, PowerPoint.ShowMacroEnabled.*,
|
|
60
|
+
* PowerPoint.Document.*, PowerPoint.Template.*
|
|
61
|
+
* - Binary / opaque ProgIDs → `store-only`:
|
|
62
|
+
* Excel.SheetBinaryMacroEnabled.* (.xlsb),
|
|
63
|
+
* AcroExch.Document.* (PDF), exact `Package` / `Packager.Package`
|
|
64
|
+
* - Content-type override: native OOXML content types →
|
|
65
|
+
* `offloadable`; `application/pdf` → `store-only`.
|
|
66
|
+
* - Target-path fallback: `.docx/.docm/.dotx/.dotm` +
|
|
67
|
+
* `.xlsx/.xlsm/.xltx/.xltm` + `.pptx/.pptm/.potx/.potm` →
|
|
68
|
+
* `offloadable`; `.xlsb` / `.pdf` → `store-only`.
|
|
53
69
|
*
|
|
54
70
|
* See `docs/architecture/01-package-session.md` §P8 for the full
|
|
55
71
|
* contract.
|
|
56
72
|
*/
|
|
57
73
|
|
|
58
|
-
const
|
|
59
|
-
//
|
|
60
|
-
//
|
|
74
|
+
const OFFLOADABLE_PROGID_PREFIXES: readonly string[] = [
|
|
75
|
+
// Native OOXML Word documents — extractable to host storage with
|
|
76
|
+
// the Step 7 adapter, reconstituted byte-identical at export.
|
|
61
77
|
"Word.Document.",
|
|
62
78
|
"Word.DocumentMacroEnabled.",
|
|
63
79
|
"Word.Template.",
|
|
64
|
-
//
|
|
65
|
-
//
|
|
80
|
+
// Native OOXML Excel formats (.xlsx / .xlsm / .xltx / .xltm).
|
|
81
|
+
// `SheetBinaryMacroEnabled` is .xlsb — binary, not OOXML — and
|
|
82
|
+
// lives in the store-only list below.
|
|
66
83
|
"Excel.Sheet.",
|
|
67
84
|
"Excel.SheetMacroEnabled.",
|
|
68
|
-
"Excel.SheetBinaryMacroEnabled.",
|
|
69
85
|
"Excel.Worksheet.",
|
|
70
86
|
"Excel.Chart.",
|
|
71
87
|
"Excel.ChartMacroEnabled.",
|
|
72
|
-
//
|
|
88
|
+
// Native OOXML presentations (.pptx / .pptm / .potx / .potm).
|
|
73
89
|
"PowerPoint.Slide.",
|
|
74
90
|
"PowerPoint.SlideMacroEnabled.",
|
|
75
91
|
"PowerPoint.Show.",
|
|
76
92
|
"PowerPoint.ShowMacroEnabled.",
|
|
77
93
|
"PowerPoint.Document.",
|
|
78
94
|
"PowerPoint.Template.",
|
|
79
|
-
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
const STORE_ONLY_PROGID_PREFIXES: readonly string[] = [
|
|
98
|
+
// Excel's legacy binary format — not OOXML, can't be offloaded.
|
|
99
|
+
"Excel.SheetBinaryMacroEnabled.",
|
|
100
|
+
// PDF via Adobe Acrobat — binary, store-only.
|
|
80
101
|
"AcroExch.Document.",
|
|
81
102
|
];
|
|
82
103
|
|
|
@@ -87,20 +108,24 @@ const STORE_ONLY_PROGID_EXACT: ReadonlySet<string> = new Set([
|
|
|
87
108
|
]);
|
|
88
109
|
|
|
89
110
|
/**
|
|
90
|
-
* Content-type patterns that
|
|
91
|
-
*
|
|
92
|
-
* declared in `[Content_Types].xml` overrides.
|
|
111
|
+
* Content-type patterns that mark native-OOXML embeddings — eligible
|
|
112
|
+
* for offload when the host adapter opts in.
|
|
93
113
|
*/
|
|
94
|
-
const
|
|
95
|
-
// Package-embedded Word document (relationships/package type on a
|
|
96
|
-
// word/embeddings/*.docx part). Catches the CCEP case even if the
|
|
97
|
-
// ProgID is missing or atypical.
|
|
114
|
+
const OFFLOADABLE_CONTENT_TYPES: readonly string[] = [
|
|
98
115
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
99
116
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
|
100
117
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
101
118
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
|
102
119
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
103
120
|
"application/vnd.openxmlformats-officedocument.presentationml.template",
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Content-type patterns that force store-only — binary formats that
|
|
125
|
+
* cannot be re-processed by this codebase and must round-trip as
|
|
126
|
+
* opaque bytes.
|
|
127
|
+
*/
|
|
128
|
+
const STORE_ONLY_CONTENT_TYPES: readonly string[] = [
|
|
104
129
|
"application/pdf",
|
|
105
130
|
];
|
|
106
131
|
|
|
@@ -138,14 +163,22 @@ export function classifyEmbedding(
|
|
|
138
163
|
const contentType = input.contentType?.trim().toLowerCase() ?? "";
|
|
139
164
|
const targetPath = input.targetPath?.toLowerCase() ?? "";
|
|
140
165
|
|
|
141
|
-
// Exact ProgID match.
|
|
166
|
+
// Exact ProgID match — ambiguous `Package` / `Packager.Package`
|
|
167
|
+
// stays store-only (fail-closed: no signal for native OOXML so
|
|
168
|
+
// host storage extraction isn't safe).
|
|
142
169
|
if (progId && STORE_ONLY_PROGID_EXACT.has(progId)) {
|
|
143
170
|
return "store-only";
|
|
144
171
|
}
|
|
145
172
|
|
|
146
|
-
// ProgID prefix match
|
|
147
|
-
//
|
|
173
|
+
// ProgID prefix match — check offloadable families first so
|
|
174
|
+
// native-OOXML embeddings are promoted ahead of the binary
|
|
175
|
+
// fall-through list.
|
|
148
176
|
if (progId) {
|
|
177
|
+
for (const prefix of OFFLOADABLE_PROGID_PREFIXES) {
|
|
178
|
+
if (progId.startsWith(prefix)) {
|
|
179
|
+
return "offloadable";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
149
182
|
for (const prefix of STORE_ONLY_PROGID_PREFIXES) {
|
|
150
183
|
if (progId.startsWith(prefix)) {
|
|
151
184
|
return "store-only";
|
|
@@ -153,8 +186,15 @@ export function classifyEmbedding(
|
|
|
153
186
|
}
|
|
154
187
|
}
|
|
155
188
|
|
|
156
|
-
// Content-type override
|
|
189
|
+
// Content-type override — native-OOXML content types lift to
|
|
190
|
+
// offloadable regardless of ProgID; binary content types stay
|
|
191
|
+
// store-only.
|
|
157
192
|
if (contentType) {
|
|
193
|
+
for (const ct of OFFLOADABLE_CONTENT_TYPES) {
|
|
194
|
+
if (contentType === ct || contentType.startsWith(`${ct};`)) {
|
|
195
|
+
return "offloadable";
|
|
196
|
+
}
|
|
197
|
+
}
|
|
158
198
|
for (const ct of STORE_ONLY_CONTENT_TYPES) {
|
|
159
199
|
if (contentType === ct || contentType.startsWith(`${ct};`)) {
|
|
160
200
|
return "store-only";
|
|
@@ -163,13 +203,21 @@ export function classifyEmbedding(
|
|
|
163
203
|
}
|
|
164
204
|
|
|
165
205
|
// Target-path fallback when we have no progId + no content-type.
|
|
166
|
-
// A
|
|
167
|
-
//
|
|
206
|
+
// A native-OOXML extension in the embeddings folder is a strong
|
|
207
|
+
// signal of an offloadable package payload. `.xlsb` / `.pdf` stay
|
|
208
|
+
// store-only.
|
|
168
209
|
if (targetPath) {
|
|
169
|
-
const
|
|
210
|
+
const offloadableExtensions = [
|
|
211
|
+
".docx", ".docm", ".dotx", ".dotm",
|
|
170
212
|
".xlsx", ".xlsm", ".xltx", ".xltm",
|
|
171
213
|
".pptx", ".pptm", ".potx", ".potm",
|
|
172
|
-
|
|
214
|
+
];
|
|
215
|
+
for (const ext of offloadableExtensions) {
|
|
216
|
+
if (targetPath.endsWith(ext)) {
|
|
217
|
+
return "offloadable";
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const storeOnlyExtensions = [".xlsb", ".pdf"];
|
|
173
221
|
for (const ext of storeOnlyExtensions) {
|
|
174
222
|
if (targetPath.endsWith(ext)) {
|
|
175
223
|
return "store-only";
|
|
@@ -187,7 +235,9 @@ export function classifyEmbedding(
|
|
|
187
235
|
* Exposed for tests. Not part of the public API.
|
|
188
236
|
*/
|
|
189
237
|
export const __internal = {
|
|
238
|
+
OFFLOADABLE_PROGID_PREFIXES,
|
|
190
239
|
STORE_ONLY_PROGID_PREFIXES,
|
|
191
240
|
STORE_ONLY_PROGID_EXACT,
|
|
241
|
+
OFFLOADABLE_CONTENT_TYPES,
|
|
192
242
|
STORE_ONLY_CONTENT_TYPES,
|
|
193
243
|
} as const;
|
|
@@ -284,6 +284,8 @@ export type ParsedInlineNode =
|
|
|
284
284
|
| ParsedOleEmbedInlineNode
|
|
285
285
|
| ParsedBookmarkStartInlineNode
|
|
286
286
|
| ParsedBookmarkEndInlineNode
|
|
287
|
+
| ParsedScopeMarkerStartInlineNode
|
|
288
|
+
| ParsedScopeMarkerEndInlineNode
|
|
287
289
|
| ParsedFootnoteRefInlineNode
|
|
288
290
|
| ParsedFieldInlineNode
|
|
289
291
|
| ParsedPermStartInlineNode
|
|
@@ -425,6 +427,23 @@ export interface ParsedBookmarkEndInlineNode {
|
|
|
425
427
|
rawXml: string;
|
|
426
428
|
}
|
|
427
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Scope-marker inline nodes — produced by `rewriteScopeMarkerBookmarks`
|
|
432
|
+
* post-parse after it sees the `bw:scope:` bookmark prefix. These survive
|
|
433
|
+
* the normalization pass and land in the canonical document as
|
|
434
|
+
* `ScopeMarkerStartNode` / `ScopeMarkerEndNode`. See
|
|
435
|
+
* `src/io/ooxml/parse-scope-markers.ts` for the prefix contract.
|
|
436
|
+
*/
|
|
437
|
+
export interface ParsedScopeMarkerStartInlineNode {
|
|
438
|
+
type: "scope_marker_start";
|
|
439
|
+
scopeId: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export interface ParsedScopeMarkerEndInlineNode {
|
|
443
|
+
type: "scope_marker_end";
|
|
444
|
+
scopeId: string;
|
|
445
|
+
}
|
|
446
|
+
|
|
428
447
|
export interface ParsedFootnoteRefInlineNode {
|
|
429
448
|
type: "footnote_ref";
|
|
430
449
|
noteId: string;
|
|
@@ -618,6 +637,20 @@ const HYPERLINK_RELATIONSHIP_TYPE =
|
|
|
618
637
|
*/
|
|
619
638
|
let activeChartPartLookup: ChartPartLookup | undefined;
|
|
620
639
|
|
|
640
|
+
/**
|
|
641
|
+
* Phase 1 telemetry — optional bus installed by the runtime before a load.
|
|
642
|
+
* Populated via `setActiveParseTelemetryBus(bus)` from
|
|
643
|
+
* `src/io/docx-session.ts`. Emits one `parse.main_document.completed`
|
|
644
|
+
* event per call with element counts. Re-entrancy invariant matches
|
|
645
|
+
* `activeChartPartLookup` above.
|
|
646
|
+
*/
|
|
647
|
+
type ParseTelemetryBus = import("../../runtime/debug/telemetry-bus.ts").TelemetryBus;
|
|
648
|
+
let activeParseTelemetryBus: ParseTelemetryBus | undefined;
|
|
649
|
+
|
|
650
|
+
export function setActiveParseTelemetryBus(bus: ParseTelemetryBus | undefined): void {
|
|
651
|
+
activeParseTelemetryBus = bus;
|
|
652
|
+
}
|
|
653
|
+
|
|
621
654
|
export function parseMainDocumentXml(
|
|
622
655
|
xml: string,
|
|
623
656
|
relationships: readonly OpcRelationship[] = [],
|
|
@@ -626,13 +659,50 @@ export function parseMainDocumentXml(
|
|
|
626
659
|
chartPartLookup?: ChartPartLookup,
|
|
627
660
|
): ParsedMainDocument {
|
|
628
661
|
activeChartPartLookup = chartPartLookup;
|
|
662
|
+
const bus = activeParseTelemetryBus;
|
|
663
|
+
const started = bus?.isEnabled("parse") ? performanceNow() : 0;
|
|
629
664
|
try {
|
|
630
|
-
|
|
665
|
+
const result = parseMainDocumentXmlInner(xml, relationships, mediaParts, sourcePartPath);
|
|
666
|
+
if (bus?.isEnabled("parse")) {
|
|
667
|
+
emitParseSummary(bus, result, sourcePartPath, performanceNow() - started);
|
|
668
|
+
}
|
|
669
|
+
return result;
|
|
631
670
|
} finally {
|
|
632
671
|
activeChartPartLookup = undefined;
|
|
633
672
|
}
|
|
634
673
|
}
|
|
635
674
|
|
|
675
|
+
function performanceNow(): number {
|
|
676
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
677
|
+
return performance.now();
|
|
678
|
+
}
|
|
679
|
+
return Date.now();
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function emitParseSummary(
|
|
683
|
+
bus: ParseTelemetryBus,
|
|
684
|
+
result: ParsedMainDocument,
|
|
685
|
+
partPath: string,
|
|
686
|
+
ms: number,
|
|
687
|
+
): void {
|
|
688
|
+
const counts: Record<string, number> = Object.create(null);
|
|
689
|
+
for (const block of result.blocks) {
|
|
690
|
+
const kind = (block as { type?: string }).type ?? "unknown";
|
|
691
|
+
counts[kind] = (counts[kind] ?? 0) + 1;
|
|
692
|
+
}
|
|
693
|
+
bus.emit({
|
|
694
|
+
channel: "parse",
|
|
695
|
+
type: "parse.main_document.completed",
|
|
696
|
+
t: 0,
|
|
697
|
+
payload: {
|
|
698
|
+
partPath,
|
|
699
|
+
blockCount: result.blocks.length,
|
|
700
|
+
blockKindCounts: counts,
|
|
701
|
+
ms,
|
|
702
|
+
},
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
|
|
636
706
|
/**
|
|
637
707
|
* CO4.5 — Parse a raw `<w:sdt>` XML fragment in isolation, with full drawing-
|
|
638
708
|
* frame support. Used by `parse-picture-sdt.ts` and tests.
|