@beyondwork/docx-react-component 1.0.67 → 1.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -932
- package/package.json +26 -27
- package/src/api/anchor-conversion.ts +43 -0
- package/src/api/editor-state-types.ts +2 -1
- package/src/api/public-types.ts +504 -101
- package/src/api/session-state.ts +4 -0
- package/src/api/v3/README.md +91 -0
- package/src/api/v3/_create.ts +146 -0
- package/src/api/v3/_layer-metadata.ts +362 -0
- package/src/api/v3/_mocks.ts +84 -0
- package/src/api/v3/_runtime-handle.ts +162 -0
- package/src/api/v3/_ux-response.ts +73 -0
- package/src/api/v3/ai/_metadata-audit.ts +225 -0
- package/src/api/v3/ai/attach.ts +235 -0
- package/src/api/v3/ai/bundle.ts +132 -0
- package/src/api/v3/ai/explain.ts +144 -0
- package/src/api/v3/ai/export.ts +54 -0
- package/src/api/v3/ai/inspect.ts +118 -0
- package/src/api/v3/ai/policy.ts +77 -0
- package/src/api/v3/ai/replacement.ts +341 -0
- package/src/api/v3/ai/resolve.ts +133 -0
- package/src/api/v3/index.ts +79 -0
- package/src/api/v3/runtime/chart.ts +310 -0
- package/src/api/v3/runtime/clipboard.ts +81 -0
- package/src/api/v3/runtime/collab.ts +331 -0
- package/src/api/v3/runtime/content.ts +236 -0
- package/src/api/v3/runtime/document.ts +282 -0
- package/src/api/v3/runtime/formatting.ts +186 -0
- package/src/api/v3/runtime/geometry.ts +349 -0
- package/src/api/v3/runtime/layout.ts +108 -0
- package/src/api/v3/runtime/review.ts +129 -0
- package/src/api/v3/runtime/search.ts +74 -0
- package/src/api/v3/runtime/table.ts +63 -0
- package/src/api/v3/runtime/workflow.ts +434 -0
- package/src/api/v3/ui/_context.ts +86 -0
- package/src/api/v3/ui/_create.ts +65 -0
- package/src/api/v3/ui/_types.ts +520 -0
- package/src/api/v3/ui/chrome-composition.ts +342 -0
- package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
- package/src/api/v3/ui/chrome.ts +476 -0
- package/src/api/v3/ui/debug.ts +124 -0
- package/src/api/v3/ui/index.ts +64 -0
- package/src/api/v3/ui/overlays-visibility.ts +170 -0
- package/src/api/v3/ui/overlays.ts +427 -0
- package/src/api/v3/ui/scope.ts +71 -0
- package/src/api/v3/ui/session.ts +100 -0
- package/src/api/v3/ui/surface.ts +170 -0
- package/src/api/v3/ui/viewport.ts +303 -0
- package/src/core/commands/index.ts +28 -6
- package/src/core/commands/list-commands.ts +3 -2
- package/src/core/commands/section-layout-commands.ts +9 -8
- package/src/core/schema/text-schema.ts +16 -0
- package/src/core/selection/mapping.ts +33 -72
- package/src/core/state/editor-state.ts +96 -189
- package/src/index.ts +23 -4
- package/src/io/chart-preview-resolver.ts +1 -1
- package/src/io/docx-session.ts +36 -4797
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +1 -1
- package/src/io/export/serialize-headers-footers.ts +6 -1
- package/src/io/export/serialize-main-document.ts +45 -0
- package/src/io/export/serialize-run-formatting.ts +17 -2
- package/src/io/export/twip.ts +1 -1
- package/src/io/normalize/normalize-text.ts +27 -20
- package/src/io/ooxml/chart/parse-series.ts +1 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +1 -1
- package/src/io/ooxml/classify-embedding.ts +83 -33
- package/src/io/ooxml/parse-fill.ts +1 -1
- package/src/io/ooxml/parse-main-document.ts +71 -1
- package/src/io/ooxml/parse-object.ts +14 -10
- package/src/io/ooxml/parse-run-formatting.ts +47 -1
- package/src/io/ooxml/property-grab-bag.ts +2 -2
- package/src/io/ooxml/units.ts +11 -0
- package/src/io/ooxml/workflow-payload.ts +282 -7
- package/src/model/anchor.ts +85 -0
- package/src/model/canonical-document.ts +351 -15
- package/src/model/chart-types.ts +1 -1
- package/src/model/layout/index.ts +83 -0
- package/src/model/layout/page-graph-types.ts +181 -0
- package/src/model/layout/page-layout-snapshot.ts +105 -0
- package/src/model/layout/resolved-layout-types.ts +47 -0
- package/src/model/layout/runtime-page-graph-types.ts +102 -0
- package/src/model/paragraph-scope-ids.ts +72 -0
- package/src/model/review/comment-types.ts +112 -0
- package/src/model/review/index.ts +2 -0
- package/src/model/review/revision-types.ts +215 -0
- package/src/model/snapshot.ts +32 -0
- package/src/review/store/comment-store.ts +21 -47
- package/src/review/store/revision-types.ts +40 -198
- package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
- package/src/runtime/collab/runtime-collab-sync.ts +13 -3
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
- package/src/runtime/debug/event-ring-buffer.ts +64 -0
- package/src/runtime/debug/probability-sampler.ts +18 -0
- package/src/runtime/debug/runtime-debug-facet.ts +67 -0
- package/src/runtime/debug/stage-tokens.ts +31 -0
- package/src/runtime/debug/telemetry-bus.ts +271 -0
- package/src/runtime/debug/types.ts +275 -0
- package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
- package/src/runtime/document-layout.ts +8 -6
- package/src/runtime/document-runtime.ts +843 -1141
- package/src/runtime/document-search.ts +1 -1
- package/src/runtime/edit-ops/index.ts +1 -1
- package/src/runtime/external-send-runtime.ts +1 -1
- package/src/runtime/formatting/document-lookup.ts +235 -0
- package/src/runtime/formatting/field/registry.ts +41 -0
- package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
- package/src/runtime/formatting/font-resolution.ts +83 -0
- package/src/runtime/formatting/formatting-context.ts +903 -0
- package/src/runtime/formatting/formatting-types.ts +157 -0
- package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
- package/src/runtime/formatting/index.ts +125 -0
- package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
- package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
- package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
- package/src/runtime/formatting/projector.ts +75 -0
- package/src/runtime/formatting/resolve-effective.ts +407 -0
- package/src/runtime/formatting/revision-display.ts +105 -0
- package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
- package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
- package/src/runtime/formatting/telemetry-bridge.ts +106 -0
- package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
- package/src/runtime/geometry/caret-geometry.ts +164 -0
- package/src/runtime/geometry/geometry-facet.ts +364 -0
- package/src/runtime/geometry/geometry-types.ts +256 -0
- package/src/runtime/geometry/hit-test.ts +125 -0
- package/src/runtime/geometry/index.ts +71 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
- package/src/runtime/geometry/invalidation.ts +35 -0
- package/src/runtime/geometry/object-handles.ts +77 -0
- package/src/runtime/geometry/overlay-rects.ts +85 -0
- package/src/runtime/geometry/project-anchors.ts +100 -0
- package/src/runtime/geometry/project-fragments.ts +216 -0
- package/src/runtime/geometry/projector.ts +129 -0
- package/src/runtime/geometry/replacement-envelope.ts +130 -0
- package/src/runtime/geometry/viewport.ts +218 -0
- package/src/runtime/layout/compat-input-ledger.ts +211 -0
- package/src/runtime/layout/index.ts +6 -1
- package/src/runtime/layout/inert-layout-facet.ts +12 -7
- package/src/runtime/layout/layout-engine-instance.ts +189 -11
- package/src/runtime/layout/layout-engine-version.ts +450 -1
- package/src/runtime/layout/layout-facet-types.ts +60 -0
- package/src/runtime/layout/layout-measurement-provider.ts +13 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
- package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
- package/src/runtime/layout/page-graph.ts +62 -209
- package/src/runtime/layout/page-story-resolver.ts +7 -12
- package/src/runtime/layout/paginated-layout-engine.ts +186 -11
- package/src/runtime/layout/project-block-fragments.ts +11 -0
- package/src/runtime/layout/projector.ts +90 -0
- package/src/runtime/layout/public-facet.ts +187 -442
- package/src/runtime/layout/resolved-formatting-state.ts +158 -26
- package/src/runtime/layout/table-render-plan.ts +1 -1
- package/src/runtime/prerender/cache-envelope.ts +6 -1
- package/src/runtime/prerender/prerender-document.ts +18 -23
- package/src/runtime/render/decoration-resolver.ts +1 -1
- package/src/runtime/render/render-frame-types.ts +20 -0
- package/src/runtime/render/render-kernel.ts +94 -25
- package/src/runtime/scopes/_formatting-seam.ts +262 -0
- package/src/runtime/scopes/_scope-dependencies.ts +49 -0
- package/src/runtime/scopes/action-validation.ts +356 -0
- package/src/runtime/scopes/attach-explanation.ts +102 -0
- package/src/runtime/scopes/audit-bundle.ts +71 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
- package/src/runtime/scopes/compile-scope.ts +262 -0
- package/src/runtime/scopes/compiler-service.ts +431 -0
- package/src/runtime/scopes/create-issue.ts +107 -0
- package/src/runtime/scopes/enumerate-scopes.ts +543 -0
- package/src/runtime/scopes/evidence.ts +233 -0
- package/src/runtime/scopes/index.ts +150 -0
- package/src/runtime/scopes/position-map.ts +214 -0
- package/src/runtime/scopes/preservation-boundary.ts +91 -0
- package/src/runtime/scopes/projector.ts +49 -0
- package/src/runtime/scopes/replaceability.ts +87 -0
- package/src/runtime/scopes/replacement/apply.ts +228 -0
- package/src/runtime/scopes/replacement/compile.ts +59 -0
- package/src/runtime/scopes/replacement/propose.ts +42 -0
- package/src/runtime/scopes/resolve-reference.ts +347 -0
- package/src/runtime/scopes/review-bundle.ts +141 -0
- package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
- package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
- package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
- package/src/runtime/scopes/scope-kinds/field.ts +65 -0
- package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
- package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
- package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
- package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
- package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
- package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
- package/src/runtime/scopes/scope-kinds/table.ts +55 -0
- package/src/runtime/scopes/scope-range.ts +208 -0
- package/src/runtime/scopes/semantic-scope-types.ts +454 -0
- package/src/runtime/scopes/workflow-overlap.ts +92 -0
- package/src/runtime/selection/index.ts +1 -1
- package/src/runtime/structure-ops/fragment-insert.ts +1 -1
- package/src/runtime/structure-ops/index.ts +1 -1
- package/src/runtime/surface-projection.ts +232 -262
- package/src/runtime/units.ts +4 -2
- package/src/runtime/workflow/coordinator.ts +1348 -0
- package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
- package/src/runtime/workflow/index.ts +25 -0
- package/src/runtime/workflow/markup-mode-policy.ts +98 -0
- package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
- package/src/runtime/workflow/metadata-persistence.ts +306 -0
- package/src/runtime/workflow/metadata-writer.ts +123 -0
- package/src/runtime/workflow/overlay-store.ts +690 -0
- package/src/runtime/workflow/projector.ts +127 -0
- package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
- package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
- package/src/runtime/workflow/rail/types.ts +198 -0
- package/src/runtime/workflow/scope-rail-composer.ts +39 -0
- package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
- package/src/runtime/workflow/scope-writer.ts +188 -0
- package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
- package/src/runtime/workflow/visibility-policy.ts +129 -0
- package/src/session/_sync-legacy.ts +66 -0
- package/src/session/export/embedded-reconstitute.ts +104 -0
- package/src/session/export/export-diagnostics.ts +85 -0
- package/src/session/export/export-validation.ts +110 -0
- package/src/session/export/index.ts +34 -0
- package/src/session/export/preservation-reattach.ts +30 -0
- package/src/session/export/serialize-dispatch.ts +165 -0
- package/src/session/export/stateful-export-pipeline.ts +432 -0
- package/src/session/export/stateful-export.ts +684 -0
- package/src/session/import/canonical-assembly.ts +227 -0
- package/src/session/import/diagnostics-session.ts +54 -0
- package/src/session/import/embedded-discovery.ts +225 -0
- package/src/session/import/embedded-offload.ts +337 -0
- package/src/session/import/import-diagnostics.ts +69 -0
- package/src/session/import/loader-types.ts +313 -0
- package/src/session/import/loader.ts +1834 -0
- package/src/session/import/normalize.ts +195 -0
- package/src/session/import/package-parts.ts +217 -0
- package/src/session/import/package-read.ts +195 -0
- package/src/session/import/parse-orchestration.ts +105 -0
- package/src/session/import/part-constants.ts +70 -0
- package/src/session/import/part-discovery.ts +94 -0
- package/src/session/import/preservation-index.ts +46 -0
- package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
- package/src/session/import/review-import.ts +508 -0
- package/src/session/import/styles-consolidation.ts +281 -0
- package/src/session/import/workflow-scope-import.ts +256 -0
- package/src/session/index.ts +37 -0
- package/src/session/session-state.ts +69 -0
- package/src/session/session.ts +532 -0
- package/src/session/shared/protection.ts +228 -0
- package/src/session/shared/session-utils.ts +82 -0
- package/src/session/types.ts +499 -0
- package/src/shell/chart-snapshots.ts +96 -0
- package/src/shell/media-previews.ts +85 -0
- package/src/shell/overlay-anchor-bridge.ts +53 -0
- package/src/shell/paste-adapter.ts +23 -0
- package/src/shell/ref-commands.ts +1697 -0
- package/src/shell/ref-utilities.ts +48 -0
- package/src/shell/search.ts +51 -0
- package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
- package/src/shell/ui-subscriber-channels.ts +81 -0
- package/src/shell/use-collab-sync.ts +116 -0
- package/src/ui/WordReviewEditor.tsx +496 -2051
- package/src/ui/editor-shell-view.tsx +30 -1
- package/src/ui/editor-surface-controller.tsx +49 -1
- package/src/ui/headless/revision-decoration-model.ts +83 -0
- package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
- package/src/ui/headless/scoped-chrome-policy.ts +2 -2
- package/src/ui/headless/selection-tool-context.ts +1 -1
- package/src/ui/headless/selection-tool-resolver.ts +1 -1
- package/src/ui/runtime-shortcut-dispatch.ts +46 -1
- package/src/ui/ui-controller-factory.ts +221 -0
- package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
- package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
- package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
- package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
- package/src/ui-tailwind/chart/render/area.tsx +3 -3
- package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
- package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
- package/src/ui-tailwind/chart/render/combo.tsx +2 -2
- package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
- package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
- package/src/ui-tailwind/chart/render/line.tsx +3 -3
- package/src/ui-tailwind/chart/render/pie.tsx +6 -6
- package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
- package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
- package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
- package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
- package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
- package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
- package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
- package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
- package/src/ui-tailwind/debug/README.md +57 -0
- package/src/ui-tailwind/debug/index.ts +3 -0
- package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
- package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
- package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
- package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
- package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
- package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
- package/src/ui-tailwind/index.ts +0 -5
- package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
- package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
- package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
- package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
- package/src/ui-tailwind/review-workspace/types.ts +408 -0
- package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
- package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
- package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
- package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
- package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
- package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
- package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
- package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
- package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
- package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
- package/src/ui-tailwind/ui-api-context.tsx +43 -0
- package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
- package/src/validation/compatibility-engine.ts +6 -6
- package/src/runtime/styles-cascade.ts +0 -33
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
- /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
- /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
- /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
resolveSectionForStoryTarget,
|
|
29
29
|
} from "./document-layout.ts";
|
|
30
30
|
import { createEditorSurfaceSnapshot } from "./surface-projection.ts";
|
|
31
|
-
import { resolveScope } from "./scope-resolver.ts";
|
|
31
|
+
import { resolveScope } from "./workflow/scope-resolver.ts";
|
|
32
32
|
|
|
33
33
|
export function searchDocument(
|
|
34
34
|
document: CanonicalDocumentEnvelope,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* R.2 EditLayer — named module for atomic content mutations. See
|
|
3
|
-
* `
|
|
3
|
+
* `CLAUDE.md (lane status table)` §R.2.
|
|
4
4
|
*
|
|
5
5
|
* The layer is a thin named seam over the existing pure functions in
|
|
6
6
|
* `src/core/commands/text-commands.ts`. Each method delegates verbatim — no
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
import type { CollabSessionBridge } from "./collab-session-bridge.ts";
|
|
10
10
|
import { resignPayload } from "./resign-payload.ts";
|
|
11
11
|
import type { PayloadSigner } from "../io/ooxml/payload-signature.ts";
|
|
12
|
-
import type { TamperGate } from "./tamper-gate.ts";
|
|
12
|
+
import type { TamperGate } from "./workflow/tamper-gate.ts";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Runtime-level composition of the P7 pure pipeline with:
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 03 — canonical-document lookup helpers.
|
|
3
|
+
*
|
|
4
|
+
* Pure, side-effect-free utilities for resolving a `NodeRef` (blockId +
|
|
5
|
+
* runId/inlineId) back to the canonical paragraph/table/inline node. Each
|
|
6
|
+
* helper mirrors the synthesis conventions used by
|
|
7
|
+
* `src/runtime/surface-projection.ts`:
|
|
8
|
+
*
|
|
9
|
+
* - `blockId` is `"paragraph-${N}"` / `"table-${N}"` where N counts
|
|
10
|
+
* blocks of that type in `doc.content.children` order (see
|
|
11
|
+
* `surface-projection.ts:951` + `:572`).
|
|
12
|
+
* - `runId` (a.k.a. `segmentId`) is `"${blockId}-segment-${N}"` where N
|
|
13
|
+
* counts segments emitted from a paragraph's inline walk (see
|
|
14
|
+
* `surface-projection.ts:1225` + surrounding segment pushes).
|
|
15
|
+
*
|
|
16
|
+
* These helpers also accept a `"run-${N}"` legacy form for test
|
|
17
|
+
* convenience (Slice 1 + 2 test fixtures used it); Slice-4 closure
|
|
18
|
+
* documents the canonical form in doc comments.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type {
|
|
22
|
+
CanonicalDocument,
|
|
23
|
+
CanonicalRunFormatting,
|
|
24
|
+
InlineNode,
|
|
25
|
+
ParagraphNode,
|
|
26
|
+
TableNode,
|
|
27
|
+
TextMark,
|
|
28
|
+
TextNode,
|
|
29
|
+
} from "../../model/canonical-document.ts";
|
|
30
|
+
|
|
31
|
+
export interface FoundParagraph {
|
|
32
|
+
readonly paragraph: ParagraphNode;
|
|
33
|
+
/** Paragraph-type block index, matching `paragraph-${N}` synthesis. */
|
|
34
|
+
readonly paragraphIndex: number;
|
|
35
|
+
/** Flat index into `doc.content.children` (for callers that need it). */
|
|
36
|
+
readonly childIndex: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface FoundTable {
|
|
40
|
+
readonly table: TableNode;
|
|
41
|
+
readonly tableIndex: number;
|
|
42
|
+
readonly childIndex: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface FoundInline {
|
|
46
|
+
readonly inline: InlineNode;
|
|
47
|
+
/** Segment index (matches `paragraph.segments[].segmentId` trailing counter). */
|
|
48
|
+
readonly segmentIndex: number;
|
|
49
|
+
/** Flat index into `paragraph.children`. */
|
|
50
|
+
readonly inlineIndex: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function findParagraphByBlockId(
|
|
54
|
+
doc: CanonicalDocument,
|
|
55
|
+
blockId: string,
|
|
56
|
+
): FoundParagraph | undefined {
|
|
57
|
+
const match = /^paragraph-(\d+)$/.exec(blockId);
|
|
58
|
+
if (!match) return undefined;
|
|
59
|
+
const target = Number(match[1]);
|
|
60
|
+
let paragraphIndex = 0;
|
|
61
|
+
for (let i = 0; i < doc.content.children.length; i += 1) {
|
|
62
|
+
const child = doc.content.children[i]!;
|
|
63
|
+
if (child.type !== "paragraph") continue;
|
|
64
|
+
if (paragraphIndex === target) {
|
|
65
|
+
return { paragraph: child, paragraphIndex, childIndex: i };
|
|
66
|
+
}
|
|
67
|
+
paragraphIndex += 1;
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function findTableByBlockId(
|
|
73
|
+
doc: CanonicalDocument,
|
|
74
|
+
blockId: string,
|
|
75
|
+
): FoundTable | undefined {
|
|
76
|
+
const match = /^table-(\d+)$/.exec(blockId);
|
|
77
|
+
if (!match) return undefined;
|
|
78
|
+
const target = Number(match[1]);
|
|
79
|
+
let tableIndex = 0;
|
|
80
|
+
for (let i = 0; i < doc.content.children.length; i += 1) {
|
|
81
|
+
const child = doc.content.children[i]!;
|
|
82
|
+
if (child.type !== "table") continue;
|
|
83
|
+
if (tableIndex === target) {
|
|
84
|
+
return { table: child, tableIndex, childIndex: i };
|
|
85
|
+
}
|
|
86
|
+
tableIndex += 1;
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse the trailing segment counter from a runId, accepting:
|
|
93
|
+
* - canonical form `${blockId}-segment-${N}` (matches surface-projection)
|
|
94
|
+
* - legacy form `run-${N}` (used by Slice 1–2 tests; deprecated)
|
|
95
|
+
* - bare `${N}` (for programmatic lookups in tests)
|
|
96
|
+
*
|
|
97
|
+
* Returns `undefined` when no recognized shape matches — callers must
|
|
98
|
+
* treat that as a hard miss, not as segment 0.
|
|
99
|
+
*/
|
|
100
|
+
export function parseSegmentIndex(runId: string): number | undefined {
|
|
101
|
+
const segmentMatch = /-segment-(\d+)$/.exec(runId);
|
|
102
|
+
if (segmentMatch) return Number(segmentMatch[1]);
|
|
103
|
+
const runMatch = /^run-(\d+)$/.exec(runId);
|
|
104
|
+
if (runMatch) return Number(runMatch[1]);
|
|
105
|
+
if (/^\d+$/.test(runId)) return Number(runId);
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Inlines that do NOT emit surface segments (i.e., they advance no
|
|
111
|
+
* document-character cursor). Mirrors `surface-projection.ts:1524–1527`:
|
|
112
|
+
* bookmark start/end and scope marker start/end are pure markers; they
|
|
113
|
+
* contribute zero to the segment index.
|
|
114
|
+
*/
|
|
115
|
+
function emitsSegment(inline: InlineNode): boolean {
|
|
116
|
+
switch (inline.type) {
|
|
117
|
+
case "bookmark_start":
|
|
118
|
+
case "bookmark_end":
|
|
119
|
+
case "scope_marker_start":
|
|
120
|
+
case "scope_marker_end":
|
|
121
|
+
return false;
|
|
122
|
+
default:
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Locate the inline at a given segment index within a paragraph. Walks
|
|
129
|
+
* `paragraph.children` skipping non-segment-emitters; returns the first
|
|
130
|
+
* inline whose 0-indexed position among segment-emitters matches
|
|
131
|
+
* `segmentIndex`. For compound inlines (hyperlinks, fields) that expand
|
|
132
|
+
* to multiple surface segments, this returns the wrapper inline — the
|
|
133
|
+
* caller's cascade then sees the wrapper's direct formatting (if any).
|
|
134
|
+
*
|
|
135
|
+
* Returns `undefined` when the segment index is out of range.
|
|
136
|
+
*/
|
|
137
|
+
export function findInlineBySegmentIndex(
|
|
138
|
+
paragraph: ParagraphNode,
|
|
139
|
+
segmentIndex: number,
|
|
140
|
+
): FoundInline | undefined {
|
|
141
|
+
let s = 0;
|
|
142
|
+
for (let i = 0; i < paragraph.children.length; i += 1) {
|
|
143
|
+
const inline = paragraph.children[i]!;
|
|
144
|
+
if (!emitsSegment(inline)) continue;
|
|
145
|
+
if (s === segmentIndex) {
|
|
146
|
+
return { inline, segmentIndex, inlineIndex: i };
|
|
147
|
+
}
|
|
148
|
+
s += 1;
|
|
149
|
+
}
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Project a canonical `TextNode.marks` union + `markAttrs`-equivalent
|
|
155
|
+
* into a `CanonicalRunFormatting`. Mirrors
|
|
156
|
+
* `surface-projection.ts::buildDirectRunFormattingFromMarks` but
|
|
157
|
+
* consumes the canonical `TextMark[]` discriminated-union form
|
|
158
|
+
* directly (surface-projection works with the cloned/flattened form).
|
|
159
|
+
*
|
|
160
|
+
* Returns `undefined` when the inline has no marks that map to direct
|
|
161
|
+
* formatting — so `RunResolveInput.direct` stays `undefined` and the
|
|
162
|
+
* cascade falls through to paragraph/character/docDefaults as designed.
|
|
163
|
+
*/
|
|
164
|
+
export function canonicalMarksToRunFormatting(
|
|
165
|
+
marks: readonly TextMark[] | undefined,
|
|
166
|
+
): CanonicalRunFormatting | undefined {
|
|
167
|
+
if (!marks || marks.length === 0) return undefined;
|
|
168
|
+
const direct: CanonicalRunFormatting = {};
|
|
169
|
+
for (const mark of marks) {
|
|
170
|
+
switch (mark.type) {
|
|
171
|
+
case "bold":
|
|
172
|
+
direct.bold = true;
|
|
173
|
+
break;
|
|
174
|
+
case "italic":
|
|
175
|
+
direct.italic = true;
|
|
176
|
+
break;
|
|
177
|
+
case "underline":
|
|
178
|
+
direct.underline = "single";
|
|
179
|
+
break;
|
|
180
|
+
case "strikethrough":
|
|
181
|
+
direct.strikethrough = true;
|
|
182
|
+
break;
|
|
183
|
+
case "doubleStrikethrough":
|
|
184
|
+
direct.doubleStrikethrough = true;
|
|
185
|
+
break;
|
|
186
|
+
case "vanish":
|
|
187
|
+
direct.vanish = true;
|
|
188
|
+
break;
|
|
189
|
+
case "smallCaps":
|
|
190
|
+
direct.smallCaps = true;
|
|
191
|
+
break;
|
|
192
|
+
case "fontFamily":
|
|
193
|
+
direct.fontFamily = mark.val;
|
|
194
|
+
direct.fontFamilyAscii = mark.val;
|
|
195
|
+
break;
|
|
196
|
+
case "fontSize":
|
|
197
|
+
direct.fontSizeHalfPoints = mark.val;
|
|
198
|
+
break;
|
|
199
|
+
case "textColor":
|
|
200
|
+
direct.colorHex = mark.color.replace(/^#/, "");
|
|
201
|
+
break;
|
|
202
|
+
case "highlight":
|
|
203
|
+
direct.highlight = mark.val;
|
|
204
|
+
break;
|
|
205
|
+
case "backgroundColor":
|
|
206
|
+
direct.highlight = mark.color;
|
|
207
|
+
break;
|
|
208
|
+
// Marks without direct CanonicalRunFormatting fields are preserved
|
|
209
|
+
// on the canonical node for round-trip but don't participate in
|
|
210
|
+
// cascade direct-formatting: charSpacing, kerning, position, lang,
|
|
211
|
+
// emboss, imprint, shadow, textFill — kept round-trip only.
|
|
212
|
+
default:
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return Object.keys(direct).length > 0 ? direct : undefined;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Convenience: extract direct run formatting for a segmentId lookup.
|
|
221
|
+
* Returns `undefined` when the segmentId is unparseable, out of range,
|
|
222
|
+
* or points at a non-text inline (e.g., a hyperlink wrapper).
|
|
223
|
+
*/
|
|
224
|
+
export function resolveDirectRunFormattingAtSegment(
|
|
225
|
+
paragraph: ParagraphNode,
|
|
226
|
+
runId: string,
|
|
227
|
+
): CanonicalRunFormatting | undefined {
|
|
228
|
+
const segmentIndex = parseSegmentIndex(runId);
|
|
229
|
+
if (segmentIndex === undefined) return undefined;
|
|
230
|
+
const found = findInlineBySegmentIndex(paragraph, segmentIndex);
|
|
231
|
+
if (!found) return undefined;
|
|
232
|
+
if (found.inline.type !== "text") return undefined;
|
|
233
|
+
const textNode = found.inline as TextNode;
|
|
234
|
+
return canonicalMarksToRunFormatting(textNode.marks);
|
|
235
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L03 field-registry rebuild entry point.
|
|
3
|
+
*
|
|
4
|
+
* L03 owns field resolution (PAGE / NUMPAGES / PAGEREF / REF / STYLEREF —
|
|
5
|
+
* see `./resolver.ts`). The registry that feeds the resolver is built
|
|
6
|
+
* from canonical document content by walking every `field`-kind node
|
|
7
|
+
* and classifying each by family. The walker + classification helpers
|
|
8
|
+
* live in `src/io/ooxml/parse-fields.ts` because they share FLDCHAR
|
|
9
|
+
* parsers + TOC-structure builders with the import path; relocating
|
|
10
|
+
* the whole file would drag io-local machinery into L03 and widen the
|
|
11
|
+
* F7 purity seam far beyond what the registry needs.
|
|
12
|
+
*
|
|
13
|
+
* This module provides the L03-owned entry point so consumers
|
|
14
|
+
* (`document-runtime.ts`, `session/import/canonical-assembly.ts`)
|
|
15
|
+
* import from L03, not from io. Internally it delegates to the io
|
|
16
|
+
* function — a narrow F7 allowlist entry in
|
|
17
|
+
* `ci-check-formatting-layer-purity.mjs` records the exception.
|
|
18
|
+
*
|
|
19
|
+
* Cross-layer coord: discharges `docs/plans/cross-layer-coord-03.md
|
|
20
|
+
* §7b` (L02 ask to route registry rebuild through L03). A future
|
|
21
|
+
* follow-up that splits the io-local FLDCHAR parsers out of
|
|
22
|
+
* `parse-fields.ts` can collapse this wrapper — the public API
|
|
23
|
+
* (`rebuildFieldRegistry`) stays stable.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { buildFieldRegistry } from "../../../io/ooxml/parse-fields.ts";
|
|
27
|
+
import type { CanonicalDocument, FieldRegistry, SubPartsCatalog } from "../../../model/canonical-document.ts";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Rebuild a field registry from the canonical document state. Consumers
|
|
31
|
+
* call this when the document content has changed (import, merge, edit
|
|
32
|
+
* commit) so the registry reflects the current field set. Pure
|
|
33
|
+
* function — no caching, no side effects.
|
|
34
|
+
*/
|
|
35
|
+
export function rebuildFieldRegistry(
|
|
36
|
+
document: Pick<CanonicalDocument, "content" | "styles"> & {
|
|
37
|
+
subParts?: SubPartsCatalog;
|
|
38
|
+
},
|
|
39
|
+
): FieldRegistry {
|
|
40
|
+
return buildFieldRegistry(document);
|
|
41
|
+
}
|
|
@@ -12,8 +12,18 @@ import type {
|
|
|
12
12
|
InlineNode,
|
|
13
13
|
ParagraphNode,
|
|
14
14
|
StylesCatalog,
|
|
15
|
-
} from "
|
|
16
|
-
import type { RuntimePageGraph, RuntimePageNode } from "
|
|
15
|
+
} from "../../../model/canonical-document.ts";
|
|
16
|
+
import type { RuntimePageGraph, RuntimePageNode } from "../../layout/page-graph.ts";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Layer-03 alias for the layout module's `RuntimePageGraph`. Exists so
|
|
20
|
+
* that other formatting-layer files (`resolve-effective.ts`) can
|
|
21
|
+
* reference the page-graph shape without breaking the F7/F8 purity
|
|
22
|
+
* guard's "one file, one layout import" discipline — this file is the
|
|
23
|
+
* single documented F8 exception. Re-exports preserve structural identity
|
|
24
|
+
* at the type level; there is no runtime value.
|
|
25
|
+
*/
|
|
26
|
+
export type { RuntimePageGraph as FieldPageGraph } from "../../layout/page-graph.ts";
|
|
17
27
|
|
|
18
28
|
// ---------------------------------------------------------------------------
|
|
19
29
|
// Public types
|
|
@@ -171,6 +181,21 @@ export function createFieldResolver(input: FieldResolverInput): FieldResolver {
|
|
|
171
181
|
// preserve the existing display text unchanged.
|
|
172
182
|
return undefined;
|
|
173
183
|
|
|
184
|
+
case "NOTEREF":
|
|
185
|
+
case "SECTIONPAGES":
|
|
186
|
+
// These families are classified as SupportedFieldFamily (see
|
|
187
|
+
// `src/model/canonical-document.ts::SupportedFieldFamily`) but
|
|
188
|
+
// are NOT implemented in the resolver yet. Returning
|
|
189
|
+
// `refreshStatus: "unresolvable"` is the honest answer — the
|
|
190
|
+
// caller knows the family is recognized but the runtime has
|
|
191
|
+
// no resolution path. This distinguishes them from TOC
|
|
192
|
+
// (intentional `undefined` = preserve existing display) and
|
|
193
|
+
// from PreserveOnlyFieldFamily (parse-only, no refresh slot).
|
|
194
|
+
// Tracked in L03 audit 2026-04-22 as Task-4 follow-up: implement
|
|
195
|
+
// NOTEREF via footnote/endnote anchor lookup + SECTIONPAGES via
|
|
196
|
+
// pageGraph section-scoped page-count walk.
|
|
197
|
+
return { displayText: "", refreshStatus: "unresolvable" };
|
|
198
|
+
|
|
174
199
|
default:
|
|
175
200
|
return undefined;
|
|
176
201
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECMA-376 §17.3.2.26 `<w:rFonts>` family-name precedence.
|
|
3
|
+
*
|
|
4
|
+
* Walks `ascii → hAnsi → eastAsia → cs` on the effective run cascade,
|
|
5
|
+
* with a caller-supplied `themeMinorFont` fallback (Word's default body
|
|
6
|
+
* typeface). The `fontTable` parameter is reserved for Lane 3a's
|
|
7
|
+
* measurement backend (substitution based on `w:pitch`); kept on the
|
|
8
|
+
* signature so the single call site does not change when substitution
|
|
9
|
+
* ships.
|
|
10
|
+
*
|
|
11
|
+
* Extracted from `paragraph-style-resolver.ts` in Slice 2 of the
|
|
12
|
+
* layer-03 refactor. See `docs/plans/refactor/03-formatting-semantics.md`.
|
|
13
|
+
*
|
|
14
|
+
* Theme-slot resolution (L03 audit §A2, 2026-04-23): when a run binds
|
|
15
|
+
* a typeface via `<w:rFonts w:asciiTheme="majorHAnsi"/>` the resolver
|
|
16
|
+
* resolves the slot through the optional `themeFontScheme` argument
|
|
17
|
+
* (caller passes `doc.subParts?.canonicalTheme?.fontScheme`). Concrete
|
|
18
|
+
* names always win over theme slots per ECMA-376; theme slots only
|
|
19
|
+
* contribute when the concrete name for the same script is absent.
|
|
20
|
+
*
|
|
21
|
+
* Limitation: `ThemeFontScheme` today captures only one `majorFont` +
|
|
22
|
+
* one `minorFont` typeface (Latin-script). Script-specific slots
|
|
23
|
+
* (`asciiTheme` vs `eastAsiaTheme` vs `csTheme`) all resolve to the
|
|
24
|
+
* same concrete font within their major/minor family. Extending the
|
|
25
|
+
* scheme with per-script typefaces is an L02 follow-up.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type {
|
|
29
|
+
CanonicalFontTable,
|
|
30
|
+
StylesCatalog,
|
|
31
|
+
ThemeFontScheme,
|
|
32
|
+
ThemeFontSlot,
|
|
33
|
+
} from "../../model/canonical-document.ts";
|
|
34
|
+
import {
|
|
35
|
+
resolveEffectiveRunFormatting,
|
|
36
|
+
type RunResolveInput,
|
|
37
|
+
} from "./paragraph-style-resolver.ts";
|
|
38
|
+
|
|
39
|
+
export function resolveRunFontFamily(
|
|
40
|
+
input: RunResolveInput,
|
|
41
|
+
catalog: StylesCatalog | undefined,
|
|
42
|
+
themeMinorFont: string | undefined,
|
|
43
|
+
fontTable?: CanonicalFontTable | undefined,
|
|
44
|
+
themeFontScheme?: ThemeFontScheme,
|
|
45
|
+
): string | undefined {
|
|
46
|
+
void fontTable;
|
|
47
|
+
const resolved = resolveEffectiveRunFormatting(input, catalog);
|
|
48
|
+
|
|
49
|
+
// Concrete name → theme slot → convenience alias → caller fallback.
|
|
50
|
+
// Each script gets its own concrete-vs-theme decision so a run with
|
|
51
|
+
// `asciiTheme` but concrete `fontFamilyEastAsia` still picks the
|
|
52
|
+
// concrete East-Asian name over the theme-resolved Ascii name (ECMA-
|
|
53
|
+
// 376 §17.3.2.26 script precedence: ascii → hAnsi → eastAsia → cs).
|
|
54
|
+
const ascii =
|
|
55
|
+
resolved.fontFamilyAscii ?? resolveSlot(resolved.asciiTheme, themeFontScheme);
|
|
56
|
+
if (ascii) return ascii;
|
|
57
|
+
|
|
58
|
+
const hAnsi =
|
|
59
|
+
resolved.fontFamilyHAnsi ?? resolveSlot(resolved.hAnsiTheme, themeFontScheme);
|
|
60
|
+
if (hAnsi) return hAnsi;
|
|
61
|
+
|
|
62
|
+
const eastAsia =
|
|
63
|
+
resolved.fontFamilyEastAsia ??
|
|
64
|
+
resolveSlot(resolved.eastAsiaTheme, themeFontScheme);
|
|
65
|
+
if (eastAsia) return eastAsia;
|
|
66
|
+
|
|
67
|
+
const cs = resolved.fontFamilyCs ?? resolveSlot(resolved.csTheme, themeFontScheme);
|
|
68
|
+
if (cs) return cs;
|
|
69
|
+
|
|
70
|
+
return resolved.fontFamily ?? themeMinorFont;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resolveSlot(
|
|
74
|
+
slot: ThemeFontSlot | undefined,
|
|
75
|
+
scheme: ThemeFontScheme | undefined,
|
|
76
|
+
): string | undefined {
|
|
77
|
+
if (!slot || !scheme) return undefined;
|
|
78
|
+
// The slot's `major*` vs `minor*` prefix picks which family face.
|
|
79
|
+
// Script suffix (`*Ascii`, `*HAnsi`, `*EastAsia`, `*Bidi`) is retained
|
|
80
|
+
// on the canonical for round-trip + future per-script resolution but
|
|
81
|
+
// does not change the lookup today (see file-level limitation note).
|
|
82
|
+
return slot.startsWith("major") ? scheme.majorFont : scheme.minorFont;
|
|
83
|
+
}
|