@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
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 03 — effective-formatting types.
|
|
3
|
+
*
|
|
4
|
+
* Output shapes of `resolveEffectiveFormatting`. Each type represents the
|
|
5
|
+
* post-cascade result for a given node kind — what the caller sees after
|
|
6
|
+
* the four-tier cascade + theme concretization + revision-display posture
|
|
7
|
+
* + (for paragraphs) resolved numbering have all been applied.
|
|
8
|
+
*
|
|
9
|
+
* Architecture reference: `docs/architecture/03-formatting-semantics.md`
|
|
10
|
+
* §"Entry point signature" + §"Contracts" F1–F6.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
CanonicalParagraphFormatting,
|
|
15
|
+
CanonicalRunFormatting,
|
|
16
|
+
} from "../../model/canonical-document.ts";
|
|
17
|
+
import type { ResolvedTableStyleResolution } from "./table-style-resolver.ts";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolved paragraph formatting. Extends the canonical shape with:
|
|
21
|
+
*
|
|
22
|
+
* - `numbering` — resolved numbering marker + geometry when the paragraph
|
|
23
|
+
* has `paragraph.numbering?: { numberingInstanceId, level }`. Populated
|
|
24
|
+
* by the entry's `"paragraph"` branch when a numbering context is
|
|
25
|
+
* available (either `opts.numberingPrefixResolver` or a freshly built
|
|
26
|
+
* one).
|
|
27
|
+
* - `paragraphMarkRun` — the paragraph-mark rPr cascade, concretized
|
|
28
|
+
* with theme colors when a `ThemeColorResolver` is threaded through
|
|
29
|
+
* `opts.themeResolver`. Mirrors the canonical
|
|
30
|
+
* `paragraphMarkRunProperties` field but carries post-cascade values
|
|
31
|
+
* (bold/italic resolved, colorHex populated from theme slots, etc.).
|
|
32
|
+
*
|
|
33
|
+
* Extends rather than aliases `CanonicalParagraphFormatting` so callers
|
|
34
|
+
* can discriminate "post-cascade effective" from "raw canonical" at the
|
|
35
|
+
* type level — contract F1 is violated when render-path code consumes
|
|
36
|
+
* raw canonical values and re-does the cascade inline.
|
|
37
|
+
*/
|
|
38
|
+
export interface EffectiveParagraphFormatting extends CanonicalParagraphFormatting {
|
|
39
|
+
readonly numbering?: EffectiveNumbering;
|
|
40
|
+
readonly paragraphMarkRun?: EffectiveRunFormatting;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolved run formatting. Extends the canonical run shape with
|
|
45
|
+
* `revisionDisplay` — populated when `opts.revisionMarkupMode` is set
|
|
46
|
+
* AND the run has an attached revision (insertion/deletion/formatting/
|
|
47
|
+
* property-change/move).
|
|
48
|
+
*
|
|
49
|
+
* `colorHex` is post-concretization: theme slots have already been
|
|
50
|
+
* mapped through `ThemeColorResolver.resolveWordThemeColor` when a
|
|
51
|
+
* theme resolver is available. Raw `colorThemeSlot` / `colorThemeTint`
|
|
52
|
+
* / `colorThemeShade` fields are preserved for round-trip on export.
|
|
53
|
+
*/
|
|
54
|
+
export interface EffectiveRunFormatting extends CanonicalRunFormatting {
|
|
55
|
+
readonly revisionDisplay?: RevisionDisplayFlags;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type EffectiveTableFormatting = ResolvedTableStyleResolution;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolved numbering output for a paragraph with numbering context.
|
|
62
|
+
*
|
|
63
|
+
* - `marker` — the formatted marker glyph (e.g. `"1."`, `"a)"`,
|
|
64
|
+
* `"•"`). Produced by `NumberingPrefixResolver.resolve`.
|
|
65
|
+
* - `level` — 0-indexed list depth (matches `<w:ilvl w:val>`).
|
|
66
|
+
* - `markerRunFormatting` — rPr cascade for the marker glyph (ECMA-376
|
|
67
|
+
* §17.9: docDefaults → paragraph-style chain → paragraph-mark rPr →
|
|
68
|
+
* level rPr).
|
|
69
|
+
* - `indentation` — merged indent + tab geometry from level def +
|
|
70
|
+
* paragraph overrides. Consumers (layout, render) read this instead
|
|
71
|
+
* of reading numbering level + paragraph indentation separately.
|
|
72
|
+
* - `pictureBulletRef` — relationship id for picture-bullet glyph
|
|
73
|
+
* when the numbering format is `"bullet"` with a pic mode.
|
|
74
|
+
*/
|
|
75
|
+
export interface EffectiveNumbering {
|
|
76
|
+
readonly marker?: string;
|
|
77
|
+
readonly level?: number;
|
|
78
|
+
readonly markerRunFormatting?: CanonicalRunFormatting;
|
|
79
|
+
readonly indentation?: {
|
|
80
|
+
readonly left?: number;
|
|
81
|
+
readonly hanging?: number;
|
|
82
|
+
readonly firstLine?: number;
|
|
83
|
+
readonly tab?: number;
|
|
84
|
+
};
|
|
85
|
+
readonly pictureBulletRef?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Field-display output. `displayText` is the rendered string (e.g.
|
|
90
|
+
* `"1"` / `"3"` for PAGE, `"Heading 1"` for STYLEREF).
|
|
91
|
+
*
|
|
92
|
+
* - `"resolved"` — text populated, safe to render.
|
|
93
|
+
* - `"unresolved"` — field exists but resolution deferred (e.g. no
|
|
94
|
+
* page graph yet; PAGE/NUMPAGES in prerender).
|
|
95
|
+
* - `"unresolvable"` — permanent failure (e.g. REF to a missing
|
|
96
|
+
* bookmark; STYLEREF to a non-existent style).
|
|
97
|
+
*/
|
|
98
|
+
export interface EffectiveFieldDisplay {
|
|
99
|
+
readonly displayText?: string;
|
|
100
|
+
readonly refreshStatus: "resolved" | "unresolved" | "unresolvable";
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Revision-display posture flags applied per run. Owned by layer 03's
|
|
105
|
+
* `applyRevisionDisplay(run, revision, markupMode)`. Architecture
|
|
106
|
+
* reference: contract F6.
|
|
107
|
+
*
|
|
108
|
+
* `markupMode` echoes the input so consumers can branch without
|
|
109
|
+
* re-reading opts. Other flags are posture hints — consumers decide the
|
|
110
|
+
* visual vocabulary (CSS class, inline style, decoration).
|
|
111
|
+
*/
|
|
112
|
+
export interface RevisionDisplayFlags {
|
|
113
|
+
readonly markupMode: "clean" | "simple" | "all";
|
|
114
|
+
/** Hide the run entirely (e.g. open deletion in "clean" mode). */
|
|
115
|
+
readonly hidden?: boolean;
|
|
116
|
+
/** Render with strikethrough (deletion in "all" mode). */
|
|
117
|
+
readonly strikethrough?: boolean;
|
|
118
|
+
/** Render with insertion-underline (insertion in "all" mode). */
|
|
119
|
+
readonly insertionUnderline?: boolean;
|
|
120
|
+
/** Render de-emphasized (all revision kinds in "simple" mode). */
|
|
121
|
+
readonly deemphasize?: boolean;
|
|
122
|
+
/** Author color for change-bar / inline marker rendering. */
|
|
123
|
+
readonly authorColor?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Discriminated union of per-node effective-formatting outputs. The
|
|
128
|
+
* entry dispatches by `nodeRef.kind` and returns the matching variant.
|
|
129
|
+
*/
|
|
130
|
+
export type EffectiveFormatting =
|
|
131
|
+
| {
|
|
132
|
+
readonly kind: "paragraph";
|
|
133
|
+
readonly paragraph: EffectiveParagraphFormatting;
|
|
134
|
+
}
|
|
135
|
+
| {
|
|
136
|
+
readonly kind: "run";
|
|
137
|
+
readonly run: EffectiveRunFormatting;
|
|
138
|
+
}
|
|
139
|
+
| {
|
|
140
|
+
readonly kind: "table";
|
|
141
|
+
readonly table: EffectiveTableFormatting;
|
|
142
|
+
}
|
|
143
|
+
| {
|
|
144
|
+
readonly kind: "table-cell";
|
|
145
|
+
readonly paragraph: EffectiveParagraphFormatting;
|
|
146
|
+
readonly run: EffectiveRunFormatting;
|
|
147
|
+
}
|
|
148
|
+
| {
|
|
149
|
+
readonly kind: "field";
|
|
150
|
+
readonly run: EffectiveRunFormatting;
|
|
151
|
+
readonly field: EffectiveFieldDisplay;
|
|
152
|
+
}
|
|
153
|
+
| {
|
|
154
|
+
readonly kind: "drawing-frame";
|
|
155
|
+
/** Resolved run-level formatting at the inline anchor. */
|
|
156
|
+
readonly run: EffectiveRunFormatting;
|
|
157
|
+
};
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
import type {
|
|
34
34
|
CanonicalRunFormatting,
|
|
35
35
|
StylesCatalog,
|
|
36
|
-
} from "
|
|
37
|
-
import { ThemeColorResolver } from "./theme-color
|
|
36
|
+
} from "../../model/canonical-document.ts";
|
|
37
|
+
import { ThemeColorResolver } from "./theme-color.ts";
|
|
38
38
|
import {
|
|
39
39
|
resolveEffectiveRunFormatting,
|
|
40
40
|
type RunResolveInput,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 03 — Formatting Semantics.
|
|
3
|
+
*
|
|
4
|
+
* Canonical entry point is `resolveEffectiveFormatting`. Sub-resolvers
|
|
5
|
+
* (paragraph, table, theme-color, hyperlink-color, font-family) are
|
|
6
|
+
* re-exported here so consumers can migrate off the legacy
|
|
7
|
+
* `src/runtime/*-resolver.ts` paths; the legacy files remain as
|
|
8
|
+
* `@deprecated` shims until Slice 4.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
resolveEffectiveFormatting,
|
|
13
|
+
type NodeRef,
|
|
14
|
+
type ResolveEffectiveFormattingOptions,
|
|
15
|
+
} from "./resolve-effective.ts";
|
|
16
|
+
|
|
17
|
+
// Production orchestrator — the real hot-path boundary. `resolveEffectiveFormatting`
|
|
18
|
+
// above is a thin façade over this context for external/test callers that prefer
|
|
19
|
+
// a `doc + nodeRef` API. Every in-repo production consumer goes through the
|
|
20
|
+
// context directly for amortized per-document resolver construction.
|
|
21
|
+
export {
|
|
22
|
+
createFormattingContext,
|
|
23
|
+
type FormattingContext,
|
|
24
|
+
type FormattingContextOptions,
|
|
25
|
+
type ProjectedRunMarks,
|
|
26
|
+
type ProjectedSurfaceMark,
|
|
27
|
+
type NumberingResolution,
|
|
28
|
+
type RunResolvedProperty,
|
|
29
|
+
type RunProvenance,
|
|
30
|
+
} from "./formatting-context.ts";
|
|
31
|
+
|
|
32
|
+
export type {
|
|
33
|
+
EffectiveFormatting,
|
|
34
|
+
EffectiveParagraphFormatting,
|
|
35
|
+
EffectiveRunFormatting,
|
|
36
|
+
EffectiveTableFormatting,
|
|
37
|
+
EffectiveNumbering,
|
|
38
|
+
EffectiveFieldDisplay,
|
|
39
|
+
RevisionDisplayFlags,
|
|
40
|
+
} from "./formatting-types.ts";
|
|
41
|
+
|
|
42
|
+
// ── Sub-resolvers ─────────────────────────────────────────────────────────
|
|
43
|
+
export {
|
|
44
|
+
resolveParagraphStyleChain,
|
|
45
|
+
resolveCharacterStyleChain,
|
|
46
|
+
resolveEffectiveParagraphFormatting,
|
|
47
|
+
resolveEffectiveRunFormatting,
|
|
48
|
+
resolveNumberingMarkerRunFormatting,
|
|
49
|
+
resolveTableCellTextFormatting,
|
|
50
|
+
getNextStyleId,
|
|
51
|
+
type ParagraphResolveInput,
|
|
52
|
+
type RunResolveInput,
|
|
53
|
+
type MarkerResolveInput,
|
|
54
|
+
} from "./paragraph-style-resolver.ts";
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
resolveTableStyleResolution,
|
|
58
|
+
type ResolvedTableCellStyle,
|
|
59
|
+
type ResolvedTableRowStyle,
|
|
60
|
+
type ResolvedTableLevelProperties,
|
|
61
|
+
type ResolvedTableStyleResolution,
|
|
62
|
+
} from "./table-style-resolver.ts";
|
|
63
|
+
|
|
64
|
+
export { resolveRunFontFamily } from "./font-resolution.ts";
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
applyThemeTintShade,
|
|
68
|
+
ThemeColorResolver,
|
|
69
|
+
concretizeThemeColors,
|
|
70
|
+
type DrawingMlColorMod,
|
|
71
|
+
} from "./theme-color.ts";
|
|
72
|
+
|
|
73
|
+
export { resolveHyperlinkRunFormatting } from "./hyperlink-color.ts";
|
|
74
|
+
|
|
75
|
+
export { mergeRun, mergeParagraph } from "./style-cascade.ts";
|
|
76
|
+
|
|
77
|
+
// ── Numbering (Slice 3) ───────────────────────────────────────────────────
|
|
78
|
+
export {
|
|
79
|
+
createNumberingPrefixResolver,
|
|
80
|
+
formatCounter,
|
|
81
|
+
isSupportedNumberingFormat,
|
|
82
|
+
type NumberingPrefixResolver,
|
|
83
|
+
type NumberingPrefixResult,
|
|
84
|
+
} from "./numbering/prefix.ts";
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
resolveNumberingDefinitionSet,
|
|
88
|
+
DEFAULT_NUMBERING_START_AT,
|
|
89
|
+
type ResolvedNumberingGeometry,
|
|
90
|
+
type ResolvedNumberingDefinitionSet,
|
|
91
|
+
} from "./numbering/geometry.ts";
|
|
92
|
+
|
|
93
|
+
// ── Fields (Slice 3) ──────────────────────────────────────────────────────
|
|
94
|
+
export {
|
|
95
|
+
createFieldResolver,
|
|
96
|
+
type FieldResolver,
|
|
97
|
+
type FieldResolverInput,
|
|
98
|
+
type ResolvedField,
|
|
99
|
+
type DocumentContainerNode,
|
|
100
|
+
} from "./field/resolver.ts";
|
|
101
|
+
|
|
102
|
+
export { formatPageNumber } from "./field/page-number-format.ts";
|
|
103
|
+
|
|
104
|
+
export { rebuildFieldRegistry } from "./field/registry.ts";
|
|
105
|
+
|
|
106
|
+
// ── Debug projector (Slice 3) ─────────────────────────────────────────────
|
|
107
|
+
export {
|
|
108
|
+
buildFormattingDebugEntry,
|
|
109
|
+
type FormattingDebugEntry,
|
|
110
|
+
} from "./projector.ts";
|
|
111
|
+
|
|
112
|
+
// ── Revision display (Slice 4) ────────────────────────────────────────────
|
|
113
|
+
export {
|
|
114
|
+
applyRevisionDisplay,
|
|
115
|
+
type RevisionMarkupMode,
|
|
116
|
+
} from "./revision-display.ts";
|
|
117
|
+
|
|
118
|
+
// ── Telemetry bridge (Phase C3) ───────────────────────────────────────────
|
|
119
|
+
export {
|
|
120
|
+
buildFormattingTelemetryBridge,
|
|
121
|
+
emitRevisionDisplayModeChanged,
|
|
122
|
+
type FormattingTelemetryBridgeOptions,
|
|
123
|
+
} from "./telemetry-bridge.ts";
|
|
124
|
+
|
|
125
|
+
export type { FormattingTelemetryEvent } from "./resolve-effective.ts";
|
|
@@ -3,12 +3,12 @@ import type {
|
|
|
3
3
|
NumberingCatalog,
|
|
4
4
|
NumberingLevelDefinition,
|
|
5
5
|
ParagraphNode,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../../../model/canonical-document.ts";
|
|
7
7
|
import {
|
|
8
8
|
DEFAULT_NUMBERING_START_AT,
|
|
9
9
|
resolveNumberingDefinitionSet,
|
|
10
10
|
type ResolvedNumberingGeometry,
|
|
11
|
-
} from "./
|
|
11
|
+
} from "./geometry.ts";
|
|
12
12
|
|
|
13
13
|
interface NumberingSequenceState {
|
|
14
14
|
counters: Array<number | undefined>;
|
|
@@ -221,7 +221,43 @@ function renderLevelText(
|
|
|
221
221
|
return rendered.trim().length > 0 ? rendered : null;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Formats the runtime has dedicated implementations for. Anything outside
|
|
226
|
+
* this set falls through to `decimal` — documented dishonestly-silent
|
|
227
|
+
* behavior pending ECMA-376 §17.9.7 full coverage. L03 audit
|
|
228
|
+
* (2026-04-22) tracks this as Task-5. When a format NOT in this set
|
|
229
|
+
* is requested, we still return `String(value)` so user-visible
|
|
230
|
+
* rendering doesn't collapse, but consumers should treat unknown
|
|
231
|
+
* formats as a fidelity gap.
|
|
232
|
+
*/
|
|
233
|
+
const SUPPORTED_NUMBERING_FORMATS = new Set<string>([
|
|
234
|
+
"decimal",
|
|
235
|
+
"decimalZero",
|
|
236
|
+
"upperLetter",
|
|
237
|
+
"lowerLetter",
|
|
238
|
+
"upperRoman",
|
|
239
|
+
"lowerRoman",
|
|
240
|
+
"hex",
|
|
241
|
+
"ordinal",
|
|
242
|
+
"cardinalText",
|
|
243
|
+
"ordinalText",
|
|
244
|
+
"chicago",
|
|
245
|
+
"bullet",
|
|
246
|
+
"none",
|
|
247
|
+
]);
|
|
248
|
+
|
|
249
|
+
export function isSupportedNumberingFormat(format: string): boolean {
|
|
250
|
+
return SUPPORTED_NUMBERING_FORMATS.has(format);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Internal helper exported for targeted testing. Consumers should drive
|
|
255
|
+
* the full `createNumberingPrefixResolver(catalog).resolveParagraph(...)`
|
|
256
|
+
* path in production code — this raw entry exists so parity tests can
|
|
257
|
+
* assert format-by-format behavior without constructing a full
|
|
258
|
+
* `NumberingCatalog`.
|
|
259
|
+
*/
|
|
260
|
+
export function formatCounter(value: number, format: string): string {
|
|
225
261
|
switch (format) {
|
|
226
262
|
case "decimal":
|
|
227
263
|
return String(value);
|
|
@@ -235,13 +271,60 @@ function formatCounter(value: number, format: string): string {
|
|
|
235
271
|
return toRoman(value).toUpperCase();
|
|
236
272
|
case "lowerRoman":
|
|
237
273
|
return toRoman(value).toLowerCase();
|
|
274
|
+
case "hex":
|
|
275
|
+
// ECMA-376 §17.9.7: hexadecimal numbering. Uppercase matches
|
|
276
|
+
// Word's rendered output on round-tripped documents.
|
|
277
|
+
return value >= 0 ? value.toString(16).toUpperCase() : String(value);
|
|
278
|
+
case "ordinal":
|
|
279
|
+
// ECMA-376 §17.9.7: English ordinal suffix. 11/12/13 are the
|
|
280
|
+
// special cases that take "th" regardless of last digit.
|
|
281
|
+
return toOrdinal(value);
|
|
282
|
+
case "cardinalText":
|
|
283
|
+
// ECMA-376 §17.9.7: English cardinal-word numbering. Coverage is
|
|
284
|
+
// 1–999; values outside fall through to decimal (String(value)).
|
|
285
|
+
return toCardinalText(value);
|
|
286
|
+
case "ordinalText":
|
|
287
|
+
// ECMA-376 §17.9.7: English ordinal-word numbering.
|
|
288
|
+
return toOrdinalText(value);
|
|
289
|
+
case "chicago":
|
|
290
|
+
// ECMA-376 §17.9.7: Chicago-manual-style symbol cycle. *, †, ‡,
|
|
291
|
+
// §, ‖, ¶, then each doubles for the 7–12 pass, triples for
|
|
292
|
+
// 13–18, and so on.
|
|
293
|
+
return toChicago(value);
|
|
294
|
+
case "bullet":
|
|
295
|
+
// ECMA-376 §17.9.7: bullet numbering — level.text carries the
|
|
296
|
+
// literal glyph (or picture-bullet reference). `%1` placeholders
|
|
297
|
+
// must interpolate to "" so the glyph is the only visible
|
|
298
|
+
// output; matches the `none` behavior.
|
|
299
|
+
return "";
|
|
238
300
|
case "none":
|
|
239
301
|
return "";
|
|
240
302
|
default:
|
|
303
|
+
// Unsupported format — fall through to decimal for visible output.
|
|
304
|
+
// Callers that care about fidelity should gate on
|
|
305
|
+
// `isSupportedNumberingFormat(format)` first.
|
|
241
306
|
return String(value);
|
|
242
307
|
}
|
|
243
308
|
}
|
|
244
309
|
|
|
310
|
+
function toOrdinal(value: number): string {
|
|
311
|
+
if (value <= 0) return String(value);
|
|
312
|
+
const lastTwo = value % 100;
|
|
313
|
+
const lastOne = value % 10;
|
|
314
|
+
// Teens: 11th, 12th, 13th (not 11st/12nd/13rd).
|
|
315
|
+
if (lastTwo >= 11 && lastTwo <= 13) return `${value}th`;
|
|
316
|
+
switch (lastOne) {
|
|
317
|
+
case 1:
|
|
318
|
+
return `${value}st`;
|
|
319
|
+
case 2:
|
|
320
|
+
return `${value}nd`;
|
|
321
|
+
case 3:
|
|
322
|
+
return `${value}rd`;
|
|
323
|
+
default:
|
|
324
|
+
return `${value}th`;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
245
328
|
function toAlphabetic(value: number): string {
|
|
246
329
|
if (value <= 0) {
|
|
247
330
|
return String(value);
|
|
@@ -288,3 +371,87 @@ function toRoman(value: number): string {
|
|
|
288
371
|
}
|
|
289
372
|
return result;
|
|
290
373
|
}
|
|
374
|
+
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
// ECMA-376 §17.9.7 English number-word helpers (cardinalText / ordinalText).
|
|
377
|
+
// Coverage is 1–999; values outside the supported range fall through to
|
|
378
|
+
// `String(value)` so rendered output is never empty. Callers that care
|
|
379
|
+
// about fidelity beyond 999 should gate on the value range before invoking
|
|
380
|
+
// these formats.
|
|
381
|
+
// ---------------------------------------------------------------------------
|
|
382
|
+
|
|
383
|
+
const ONES_CARDINAL = [
|
|
384
|
+
"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
|
385
|
+
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen",
|
|
386
|
+
"seventeen", "eighteen", "nineteen",
|
|
387
|
+
] as const;
|
|
388
|
+
|
|
389
|
+
const TENS_CARDINAL = [
|
|
390
|
+
"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty",
|
|
391
|
+
"ninety",
|
|
392
|
+
] as const;
|
|
393
|
+
|
|
394
|
+
function toCardinalText(value: number): string {
|
|
395
|
+
if (!Number.isInteger(value) || value < 1 || value > 999) return String(value);
|
|
396
|
+
return cardinalBelowThousand(value);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function cardinalBelowThousand(value: number): string {
|
|
400
|
+
if (value < 20) return ONES_CARDINAL[value]!;
|
|
401
|
+
if (value < 100) {
|
|
402
|
+
const tens = Math.floor(value / 10);
|
|
403
|
+
const rest = value % 10;
|
|
404
|
+
return rest === 0
|
|
405
|
+
? TENS_CARDINAL[tens]!
|
|
406
|
+
: `${TENS_CARDINAL[tens]}-${ONES_CARDINAL[rest]}`;
|
|
407
|
+
}
|
|
408
|
+
const hundreds = Math.floor(value / 100);
|
|
409
|
+
const rest = value % 100;
|
|
410
|
+
const base = `${ONES_CARDINAL[hundreds]} hundred`;
|
|
411
|
+
if (rest === 0) return base;
|
|
412
|
+
return `${base} ${cardinalBelowThousand(rest)}`;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Standalone ordinal-word map for ones 1–19 where the ordinal differs from
|
|
416
|
+
// the cardinal (e.g. "one" → "first", not "oneth").
|
|
417
|
+
const ONES_ORDINAL = [
|
|
418
|
+
"", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
|
|
419
|
+
"eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
|
|
420
|
+
"fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth",
|
|
421
|
+
"nineteenth",
|
|
422
|
+
] as const;
|
|
423
|
+
|
|
424
|
+
// Tens endings (20 → "twentieth", 30 → "thirtieth", …). Standalone decades
|
|
425
|
+
// swap their trailing `y` for `ieth`.
|
|
426
|
+
const TENS_ORDINAL = [
|
|
427
|
+
"", "", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
|
|
428
|
+
"seventieth", "eightieth", "ninetieth",
|
|
429
|
+
] as const;
|
|
430
|
+
|
|
431
|
+
function toOrdinalText(value: number): string {
|
|
432
|
+
if (!Number.isInteger(value) || value < 1 || value > 999) return String(value);
|
|
433
|
+
if (value < 20) return ONES_ORDINAL[value]!;
|
|
434
|
+
if (value < 100) {
|
|
435
|
+
const tens = Math.floor(value / 10);
|
|
436
|
+
const rest = value % 10;
|
|
437
|
+
return rest === 0
|
|
438
|
+
? TENS_ORDINAL[tens]!
|
|
439
|
+
: `${TENS_CARDINAL[tens]}-${ONES_ORDINAL[rest]}`;
|
|
440
|
+
}
|
|
441
|
+
const hundreds = Math.floor(value / 100);
|
|
442
|
+
const rest = value % 100;
|
|
443
|
+
if (rest === 0) return `${ONES_CARDINAL[hundreds]} hundredth`;
|
|
444
|
+
return `${ONES_CARDINAL[hundreds]} hundred ${toOrdinalText(rest)}`;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ECMA-376 §17.9.7 chicago cycle. 6-symbol sequence; each pass through the
|
|
448
|
+
// cycle repeats the symbol once more. Value 1 → "*", 6 → "¶", 7 → "**",
|
|
449
|
+
// 12 → "¶¶", 13 → "***", etc. Non-positive values fall through to decimal.
|
|
450
|
+
const CHICAGO_GLYPHS = ["*", "†", "‡", "§", "‖", "¶"] as const;
|
|
451
|
+
|
|
452
|
+
function toChicago(value: number): string {
|
|
453
|
+
if (!Number.isInteger(value) || value < 1) return String(value);
|
|
454
|
+
const index = (value - 1) % CHICAGO_GLYPHS.length;
|
|
455
|
+
const repeat = Math.floor((value - 1) / CHICAGO_GLYPHS.length) + 1;
|
|
456
|
+
return CHICAGO_GLYPHS[index]!.repeat(repeat);
|
|
457
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paragraph + character style chain walkers.
|
|
3
|
+
*
|
|
4
|
+
* Owns ONLY the `basedOn`-chain traversal functions
|
|
5
|
+
* (`resolveParagraphStyleChain`, `resolveCharacterStyleChain`) and the small
|
|
6
|
+
* utility `getNextStyleId`. The four-tier cascade drivers
|
|
7
|
+
* (`resolveEffective*Formatting`, `resolveNumberingMarkerRunFormatting`,
|
|
8
|
+
* `resolveTableCellTextFormatting`) and the merge primitives live in
|
|
9
|
+
* `./style-cascade.ts`; they are re-exported here for back-compat with
|
|
10
|
+
* consumers migrating off the legacy import path.
|
|
11
|
+
*
|
|
12
|
+
* Returned chains are leaf-first (most-specific style at index 0, root at
|
|
13
|
+
* the end). Cycles break at the first re-encounter. Dangling `basedOn`
|
|
14
|
+
* references stop the walk silently (the leaf is still returned).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
CharacterStyleDefinition,
|
|
19
|
+
ParagraphStyleDefinition,
|
|
20
|
+
StylesCatalog,
|
|
21
|
+
} from "../../model/canonical-document.ts";
|
|
22
|
+
|
|
23
|
+
export function resolveParagraphStyleChain(
|
|
24
|
+
styleId: string,
|
|
25
|
+
catalog: StylesCatalog | undefined,
|
|
26
|
+
): string[] {
|
|
27
|
+
const chain: string[] = [];
|
|
28
|
+
if (!catalog) return chain;
|
|
29
|
+
const visited = new Set<string>();
|
|
30
|
+
let current: string | undefined = styleId;
|
|
31
|
+
while (current && !visited.has(current)) {
|
|
32
|
+
visited.add(current);
|
|
33
|
+
const def: ParagraphStyleDefinition | undefined = catalog.paragraphs[current];
|
|
34
|
+
if (!def) break;
|
|
35
|
+
chain.push(current);
|
|
36
|
+
current = def.basedOn;
|
|
37
|
+
}
|
|
38
|
+
return chain;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function resolveCharacterStyleChain(
|
|
42
|
+
styleId: string,
|
|
43
|
+
catalog: StylesCatalog | undefined,
|
|
44
|
+
): string[] {
|
|
45
|
+
const chain: string[] = [];
|
|
46
|
+
if (!catalog) return chain;
|
|
47
|
+
const visited = new Set<string>();
|
|
48
|
+
let current: string | undefined = styleId;
|
|
49
|
+
while (current && !visited.has(current)) {
|
|
50
|
+
visited.add(current);
|
|
51
|
+
const def: CharacterStyleDefinition | undefined = catalog.characters[current];
|
|
52
|
+
if (!def) break;
|
|
53
|
+
chain.push(current);
|
|
54
|
+
current = def.basedOn;
|
|
55
|
+
}
|
|
56
|
+
return chain;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Return the `w:next` style ID for `styleId` — the paragraph style Word
|
|
61
|
+
* applies after pressing Enter at the end of a paragraph of this style.
|
|
62
|
+
*/
|
|
63
|
+
export function getNextStyleId(
|
|
64
|
+
styleId: string,
|
|
65
|
+
catalog: StylesCatalog | undefined,
|
|
66
|
+
): string | undefined {
|
|
67
|
+
return catalog?.paragraphs[styleId]?.nextStyle;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Back-compat re-exports
|
|
72
|
+
//
|
|
73
|
+
// The cascade drivers + merge primitives moved to `./style-cascade.ts` in
|
|
74
|
+
// Phase B1 of the layer-03 refactor (completes the Slice-2 "four-tier
|
|
75
|
+
// cascade core extract" plan row). Re-exported here so consumers that
|
|
76
|
+
// import from `paragraph-style-resolver.ts` continue to compile during
|
|
77
|
+
// the Phase-D consumer migration.
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
resolveEffectiveParagraphFormatting,
|
|
82
|
+
resolveEffectiveRunFormatting,
|
|
83
|
+
resolveNumberingMarkerRunFormatting,
|
|
84
|
+
resolveTableCellTextFormatting,
|
|
85
|
+
mergeParagraph,
|
|
86
|
+
mergeRun,
|
|
87
|
+
type ParagraphResolveInput,
|
|
88
|
+
type RunResolveInput,
|
|
89
|
+
type MarkerResolveInput,
|
|
90
|
+
} from "./style-cascade.ts";
|
|
91
|
+
|
|
92
|
+
export { resolveRunFontFamily } from "./font-resolution.ts";
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 03 — formatting debug projector.
|
|
3
|
+
*
|
|
4
|
+
* Produces a `FormattingDebugEntry` for the debug-inspector snapshot when
|
|
5
|
+
* the `formatting` telemetry channel is on. Architecture reference:
|
|
6
|
+
* docs/architecture/03-formatting-semantics.md §"Projector and oracle surfaces".
|
|
7
|
+
*
|
|
8
|
+
* The projector is strict about cost: when the `formatting` channel is
|
|
9
|
+
* off, consumers must not call `buildFormattingDebugEntry`. The channel
|
|
10
|
+
* toggle lives on the telemetry bus; callers gate the call through
|
|
11
|
+
* `bus.isEnabled("formatting")` before paying the summary cost.
|
|
12
|
+
*
|
|
13
|
+
* Slice 3 lands the minimum-viable summary: catalog population, cascade
|
|
14
|
+
* cache-hit counters, and a probability-gated sample of the last N
|
|
15
|
+
* resolutions. Slice 4 extends it with revision-display posture counts.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { CanonicalDocument } from "../../model/canonical-document.ts";
|
|
19
|
+
|
|
20
|
+
export interface FormattingCatalogSummary {
|
|
21
|
+
readonly paragraphStyles: number;
|
|
22
|
+
readonly characterStyles: number;
|
|
23
|
+
readonly tableStyles: number;
|
|
24
|
+
readonly numberingInstances: number;
|
|
25
|
+
readonly numberingAbstracts: number;
|
|
26
|
+
readonly hasTheme: boolean;
|
|
27
|
+
readonly hasFontTable: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface FormattingResolutionSample {
|
|
31
|
+
readonly t: number;
|
|
32
|
+
readonly kind:
|
|
33
|
+
| "paragraph"
|
|
34
|
+
| "run"
|
|
35
|
+
| "table"
|
|
36
|
+
| "table-cell"
|
|
37
|
+
| "field"
|
|
38
|
+
| "drawing-frame";
|
|
39
|
+
readonly blockId: string;
|
|
40
|
+
readonly resolvedStyleChainDepth?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface FormattingDebugEntry {
|
|
44
|
+
readonly schemaVersion: 1;
|
|
45
|
+
readonly catalog: FormattingCatalogSummary;
|
|
46
|
+
readonly revisionMarkupMode?: "clean" | "simple" | "all";
|
|
47
|
+
readonly recentSamples: readonly FormattingResolutionSample[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface BuildFormattingDebugEntryInputs {
|
|
51
|
+
readonly doc: CanonicalDocument;
|
|
52
|
+
readonly revisionMarkupMode?: "clean" | "simple" | "all";
|
|
53
|
+
readonly recentSamples?: readonly FormattingResolutionSample[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function buildFormattingDebugEntry(
|
|
57
|
+
inputs: BuildFormattingDebugEntryInputs,
|
|
58
|
+
): FormattingDebugEntry {
|
|
59
|
+
const { doc, revisionMarkupMode, recentSamples } = inputs;
|
|
60
|
+
const catalog: FormattingCatalogSummary = {
|
|
61
|
+
paragraphStyles: Object.keys(doc.styles.paragraphs ?? {}).length,
|
|
62
|
+
characterStyles: Object.keys(doc.styles.characters ?? {}).length,
|
|
63
|
+
tableStyles: Object.keys(doc.styles.tables ?? {}).length,
|
|
64
|
+
numberingInstances: Object.keys(doc.numbering?.instances ?? {}).length,
|
|
65
|
+
numberingAbstracts: Object.keys(doc.numbering?.abstractDefinitions ?? {}).length,
|
|
66
|
+
hasTheme: Boolean(doc.subParts?.canonicalTheme),
|
|
67
|
+
hasFontTable: Boolean(doc.fontTable),
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
schemaVersion: 1,
|
|
71
|
+
catalog,
|
|
72
|
+
revisionMarkupMode,
|
|
73
|
+
recentSamples: recentSamples ?? [],
|
|
74
|
+
};
|
|
75
|
+
}
|