@beyondwork/docx-react-component 1.0.66 → 1.0.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -931
- package/package.json +26 -27
- package/src/api/anchor-conversion.ts +43 -0
- package/src/api/editor-state-types.ts +2 -1
- package/src/api/public-types.ts +504 -101
- package/src/api/session-state.ts +4 -0
- package/src/api/v3/README.md +91 -0
- package/src/api/v3/_create.ts +146 -0
- package/src/api/v3/_layer-metadata.ts +362 -0
- package/src/api/v3/_mocks.ts +84 -0
- package/src/api/v3/_runtime-handle.ts +162 -0
- package/src/api/v3/_ux-response.ts +73 -0
- package/src/api/v3/ai/_metadata-audit.ts +225 -0
- package/src/api/v3/ai/attach.ts +235 -0
- package/src/api/v3/ai/bundle.ts +132 -0
- package/src/api/v3/ai/explain.ts +144 -0
- package/src/api/v3/ai/export.ts +54 -0
- package/src/api/v3/ai/inspect.ts +118 -0
- package/src/api/v3/ai/policy.ts +77 -0
- package/src/api/v3/ai/replacement.ts +341 -0
- package/src/api/v3/ai/resolve.ts +133 -0
- package/src/api/v3/index.ts +79 -0
- package/src/api/v3/runtime/chart.ts +310 -0
- package/src/api/v3/runtime/clipboard.ts +81 -0
- package/src/api/v3/runtime/collab.ts +331 -0
- package/src/api/v3/runtime/content.ts +236 -0
- package/src/api/v3/runtime/document.ts +282 -0
- package/src/api/v3/runtime/formatting.ts +186 -0
- package/src/api/v3/runtime/geometry.ts +349 -0
- package/src/api/v3/runtime/layout.ts +108 -0
- package/src/api/v3/runtime/review.ts +129 -0
- package/src/api/v3/runtime/search.ts +74 -0
- package/src/api/v3/runtime/table.ts +63 -0
- package/src/api/v3/runtime/workflow.ts +434 -0
- package/src/api/v3/ui/_context.ts +86 -0
- package/src/api/v3/ui/_create.ts +65 -0
- package/src/api/v3/ui/_types.ts +520 -0
- package/src/api/v3/ui/chrome-composition.ts +342 -0
- package/src/{ui-tailwind/chrome → api/v3/ui}/chrome-preset-model.ts +11 -1
- package/src/api/v3/ui/chrome.ts +476 -0
- package/src/api/v3/ui/debug.ts +124 -0
- package/src/api/v3/ui/index.ts +64 -0
- package/src/api/v3/ui/overlays-visibility.ts +170 -0
- package/src/api/v3/ui/overlays.ts +427 -0
- package/src/api/v3/ui/scope.ts +71 -0
- package/src/api/v3/ui/session.ts +100 -0
- package/src/api/v3/ui/surface.ts +170 -0
- package/src/api/v3/ui/viewport.ts +303 -0
- package/src/core/commands/index.ts +28 -6
- package/src/core/commands/list-commands.ts +3 -2
- package/src/core/commands/section-layout-commands.ts +9 -8
- package/src/core/schema/text-schema.ts +16 -0
- package/src/core/selection/mapping.ts +33 -72
- package/src/core/state/editor-state.ts +96 -189
- package/src/index.ts +23 -4
- package/src/io/chart-preview-resolver.ts +1 -1
- package/src/io/docx-session.ts +36 -4795
- package/src/io/export/build-app-properties-xml.ts +1 -1
- package/src/io/export/serialize-comments.ts +1 -1
- package/src/io/export/serialize-headers-footers.ts +6 -1
- package/src/io/export/serialize-main-document.ts +45 -0
- package/src/io/export/serialize-run-formatting.ts +17 -2
- package/src/io/export/twip.ts +1 -1
- package/src/io/normalize/normalize-text.ts +27 -20
- package/src/io/ooxml/chart/parse-series.ts +1 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +1 -1
- package/src/io/ooxml/classify-embedding.ts +83 -33
- package/src/io/ooxml/parse-fill.ts +1 -1
- package/src/io/ooxml/parse-main-document.ts +71 -1
- package/src/io/ooxml/parse-object.ts +14 -10
- package/src/io/ooxml/parse-run-formatting.ts +47 -1
- package/src/io/ooxml/property-grab-bag.ts +2 -2
- package/src/io/ooxml/units.ts +11 -0
- package/src/io/ooxml/workflow-payload.ts +282 -7
- package/src/model/anchor.ts +85 -0
- package/src/model/canonical-document.ts +351 -15
- package/src/model/chart-types.ts +1 -1
- package/src/model/layout/index.ts +83 -0
- package/src/model/layout/page-graph-types.ts +181 -0
- package/src/model/layout/page-layout-snapshot.ts +105 -0
- package/src/model/layout/resolved-layout-types.ts +47 -0
- package/src/model/layout/runtime-page-graph-types.ts +102 -0
- package/src/model/paragraph-scope-ids.ts +72 -0
- package/src/model/review/comment-types.ts +112 -0
- package/src/model/review/index.ts +2 -0
- package/src/model/review/revision-types.ts +215 -0
- package/src/model/snapshot.ts +32 -0
- package/src/review/store/comment-store.ts +21 -47
- package/src/review/store/revision-types.ts +40 -198
- package/src/runtime/collab/base-doc-fingerprint.ts +6 -1
- package/src/runtime/collab/runtime-collab-sync.ts +13 -3
- package/src/runtime/collab-session.ts +1 -1
- package/src/runtime/debug/build-debug-inspector-snapshot.ts +686 -0
- package/src/runtime/debug/event-ring-buffer.ts +64 -0
- package/src/runtime/debug/probability-sampler.ts +18 -0
- package/src/runtime/debug/runtime-debug-facet.ts +67 -0
- package/src/runtime/debug/stage-tokens.ts +31 -0
- package/src/runtime/debug/telemetry-bus.ts +271 -0
- package/src/runtime/debug/types.ts +275 -0
- package/src/runtime/debug/wrap-ref-for-telemetry.ts +118 -0
- package/src/runtime/document-layout.ts +8 -6
- package/src/runtime/document-runtime.ts +843 -1141
- package/src/runtime/document-search.ts +1 -1
- package/src/runtime/edit-ops/index.ts +1 -1
- package/src/runtime/external-send-runtime.ts +1 -1
- package/src/runtime/formatting/document-lookup.ts +235 -0
- package/src/runtime/formatting/field/registry.ts +41 -0
- package/src/runtime/{field-resolver.ts → formatting/field/resolver.ts} +27 -2
- package/src/runtime/formatting/font-resolution.ts +83 -0
- package/src/runtime/formatting/formatting-context.ts +903 -0
- package/src/runtime/formatting/formatting-types.ts +157 -0
- package/src/runtime/{hyperlink-color-resolver.ts → formatting/hyperlink-color.ts} +2 -2
- package/src/runtime/formatting/index.ts +125 -0
- package/src/runtime/{resolved-numbering-geometry.ts → formatting/numbering/geometry.ts} +1 -1
- package/src/runtime/{numbering-prefix.ts → formatting/numbering/prefix.ts} +170 -3
- package/src/runtime/formatting/paragraph-style-resolver.ts +92 -0
- package/src/runtime/formatting/projector.ts +75 -0
- package/src/runtime/formatting/resolve-effective.ts +407 -0
- package/src/runtime/formatting/revision-display.ts +105 -0
- package/src/runtime/{paragraph-style-resolver.ts → formatting/style-cascade.ts} +84 -141
- package/src/runtime/{table-style-resolver.ts → formatting/table-style-resolver.ts} +1 -1
- package/src/runtime/formatting/telemetry-bridge.ts +106 -0
- package/src/runtime/{theme-color-resolver.ts → formatting/theme-color.ts} +2 -30
- package/src/runtime/geometry/caret-geometry.ts +164 -0
- package/src/runtime/geometry/geometry-facet.ts +364 -0
- package/src/runtime/geometry/geometry-types.ts +256 -0
- package/src/runtime/geometry/hit-test.ts +125 -0
- package/src/runtime/geometry/index.ts +71 -0
- package/src/runtime/geometry/inert-geometry-facet.ts +43 -0
- package/src/runtime/geometry/invalidation.ts +35 -0
- package/src/runtime/geometry/object-handles.ts +77 -0
- package/src/runtime/geometry/overlay-rects.ts +85 -0
- package/src/runtime/geometry/project-anchors.ts +100 -0
- package/src/runtime/geometry/project-fragments.ts +216 -0
- package/src/runtime/geometry/projector.ts +129 -0
- package/src/runtime/geometry/replacement-envelope.ts +130 -0
- package/src/runtime/geometry/viewport.ts +218 -0
- package/src/runtime/layout/compat-input-ledger.ts +211 -0
- package/src/runtime/layout/index.ts +6 -1
- package/src/runtime/layout/inert-layout-facet.ts +12 -7
- package/src/runtime/layout/layout-engine-instance.ts +189 -11
- package/src/runtime/layout/layout-engine-version.ts +450 -1
- package/src/runtime/layout/layout-facet-types.ts +60 -0
- package/src/runtime/layout/layout-measurement-provider.ts +13 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +14 -2
- package/src/runtime/layout/measurement-backend-empirical.ts +23 -4
- package/src/runtime/layout/page-graph.ts +62 -209
- package/src/runtime/layout/page-story-resolver.ts +7 -12
- package/src/runtime/layout/paginated-layout-engine.ts +186 -11
- package/src/runtime/layout/project-block-fragments.ts +11 -0
- package/src/runtime/layout/projector.ts +90 -0
- package/src/runtime/layout/public-facet.ts +187 -442
- package/src/runtime/layout/resolved-formatting-state.ts +158 -26
- package/src/runtime/layout/table-render-plan.ts +1 -1
- package/src/runtime/prerender/cache-envelope.ts +6 -1
- package/src/runtime/prerender/prerender-document.ts +18 -23
- package/src/runtime/render/decoration-resolver.ts +1 -1
- package/src/runtime/render/render-frame-types.ts +20 -0
- package/src/runtime/render/render-kernel.ts +94 -25
- package/src/runtime/scopes/_formatting-seam.ts +262 -0
- package/src/runtime/scopes/_scope-dependencies.ts +49 -0
- package/src/runtime/scopes/action-validation.ts +356 -0
- package/src/runtime/scopes/attach-explanation.ts +102 -0
- package/src/runtime/scopes/audit-bundle.ts +71 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +163 -0
- package/src/runtime/scopes/compile-scope.ts +262 -0
- package/src/runtime/scopes/compiler-service.ts +431 -0
- package/src/runtime/scopes/create-issue.ts +107 -0
- package/src/runtime/scopes/enumerate-scopes.ts +543 -0
- package/src/runtime/scopes/evidence.ts +233 -0
- package/src/runtime/scopes/index.ts +150 -0
- package/src/runtime/scopes/position-map.ts +214 -0
- package/src/runtime/scopes/preservation-boundary.ts +91 -0
- package/src/runtime/scopes/projector.ts +49 -0
- package/src/runtime/scopes/replaceability.ts +87 -0
- package/src/runtime/scopes/replacement/apply.ts +228 -0
- package/src/runtime/scopes/replacement/compile.ts +59 -0
- package/src/runtime/scopes/replacement/propose.ts +42 -0
- package/src/runtime/scopes/resolve-reference.ts +347 -0
- package/src/runtime/scopes/review-bundle.ts +141 -0
- package/src/runtime/scopes/scope-kinds/_paragraph-text.ts +57 -0
- package/src/runtime/scopes/scope-kinds/_table-text.ts +42 -0
- package/src/runtime/scopes/scope-kinds/comment-thread.ts +59 -0
- package/src/runtime/scopes/scope-kinds/field.ts +65 -0
- package/src/runtime/scopes/scope-kinds/heading.ts +84 -0
- package/src/runtime/scopes/scope-kinds/list-item.ts +77 -0
- package/src/runtime/scopes/scope-kinds/paragraph.ts +182 -0
- package/src/runtime/scopes/scope-kinds/revision.ts +62 -0
- package/src/runtime/scopes/scope-kinds/table-cell.ts +57 -0
- package/src/runtime/scopes/scope-kinds/table-row.ts +61 -0
- package/src/runtime/scopes/scope-kinds/table.ts +55 -0
- package/src/runtime/scopes/scope-range.ts +208 -0
- package/src/runtime/scopes/semantic-scope-types.ts +454 -0
- package/src/runtime/scopes/workflow-overlap.ts +92 -0
- package/src/runtime/selection/index.ts +1 -1
- package/src/runtime/structure-ops/fragment-insert.ts +1 -1
- package/src/runtime/structure-ops/index.ts +1 -1
- package/src/runtime/surface-projection.ts +232 -262
- package/src/runtime/units.ts +4 -2
- package/src/runtime/workflow/coordinator.ts +1348 -0
- package/src/runtime/workflow/derived-scope-resolver.ts +125 -0
- package/src/runtime/workflow/index.ts +25 -0
- package/src/runtime/workflow/markup-mode-policy.ts +98 -0
- package/src/runtime/{workflow-markup.ts → workflow/markup.ts} +6 -6
- package/src/runtime/workflow/metadata-persistence.ts +306 -0
- package/src/runtime/workflow/metadata-writer.ts +123 -0
- package/src/runtime/workflow/overlay-store.ts +690 -0
- package/src/runtime/workflow/projector.ts +127 -0
- package/src/runtime/{query-scopes.ts → workflow/query-scopes.ts} +3 -3
- package/src/runtime/{workflow-rail-segments.ts → workflow/rail/compose.ts} +60 -165
- package/src/runtime/workflow/rail/types.ts +198 -0
- package/src/runtime/workflow/scope-rail-composer.ts +39 -0
- package/src/runtime/{scope-resolver.ts → workflow/scope-resolver.ts} +3 -3
- package/src/runtime/workflow/scope-writer.ts +188 -0
- package/src/runtime/{tamper-gate.ts → workflow/tamper-gate.ts} +1 -1
- package/src/runtime/workflow/visibility-policy.ts +129 -0
- package/src/session/_sync-legacy.ts +66 -0
- package/src/session/export/embedded-reconstitute.ts +104 -0
- package/src/session/export/export-diagnostics.ts +85 -0
- package/src/session/export/export-validation.ts +110 -0
- package/src/session/export/index.ts +34 -0
- package/src/session/export/preservation-reattach.ts +30 -0
- package/src/session/export/serialize-dispatch.ts +165 -0
- package/src/session/export/stateful-export-pipeline.ts +432 -0
- package/src/session/export/stateful-export.ts +684 -0
- package/src/session/import/canonical-assembly.ts +227 -0
- package/src/session/import/diagnostics-session.ts +54 -0
- package/src/session/import/embedded-discovery.ts +225 -0
- package/src/session/import/embedded-offload.ts +337 -0
- package/src/session/import/import-diagnostics.ts +69 -0
- package/src/session/import/loader-types.ts +313 -0
- package/src/session/import/loader.ts +1834 -0
- package/src/session/import/normalize.ts +195 -0
- package/src/session/import/package-parts.ts +217 -0
- package/src/session/import/package-read.ts +195 -0
- package/src/session/import/parse-orchestration.ts +105 -0
- package/src/session/import/part-constants.ts +70 -0
- package/src/session/import/part-discovery.ts +94 -0
- package/src/session/import/preservation-index.ts +46 -0
- package/src/{runtime/read-only-diagnostics-runtime.ts → session/import/read-only-diagnostics.ts} +24 -3
- package/src/session/import/review-import.ts +508 -0
- package/src/session/import/styles-consolidation.ts +281 -0
- package/src/session/import/workflow-scope-import.ts +256 -0
- package/src/session/index.ts +37 -0
- package/src/session/session-state.ts +69 -0
- package/src/session/session.ts +532 -0
- package/src/session/shared/protection.ts +228 -0
- package/src/session/shared/session-utils.ts +82 -0
- package/src/session/types.ts +499 -0
- package/src/shell/chart-snapshots.ts +96 -0
- package/src/shell/media-previews.ts +85 -0
- package/src/shell/overlay-anchor-bridge.ts +53 -0
- package/src/shell/paste-adapter.ts +23 -0
- package/src/shell/ref-commands.ts +1697 -0
- package/src/shell/ref-utilities.ts +48 -0
- package/src/shell/search.ts +51 -0
- package/src/{ui/editor-runtime-boundary.ts → shell/session-bootstrap.ts} +243 -67
- package/src/shell/ui-subscriber-channels.ts +81 -0
- package/src/shell/use-collab-sync.ts +116 -0
- package/src/ui/WordReviewEditor.tsx +496 -2051
- package/src/ui/editor-shell-view.tsx +30 -1
- package/src/ui/editor-surface-controller.tsx +49 -1
- package/src/ui/headless/revision-decoration-model.ts +83 -0
- package/src/{ui-tailwind/chrome → ui/headless}/role-action-sets.ts +1 -1
- package/src/ui/headless/scoped-chrome-policy.ts +2 -2
- package/src/ui/headless/selection-tool-context.ts +1 -1
- package/src/ui/headless/selection-tool-resolver.ts +1 -1
- package/src/ui/runtime-shortcut-dispatch.ts +46 -1
- package/src/ui/ui-controller-factory.ts +221 -0
- package/src/ui-tailwind/chart/ChartSurface.tsx +2 -2
- package/src/ui-tailwind/chart/layout/legend-layout.ts +1 -1
- package/src/ui-tailwind/chart/layout/plot-area.ts +2 -2
- package/src/ui-tailwind/chart/layout/title-layout.ts +1 -1
- package/src/ui-tailwind/chart/render/area.tsx +3 -3
- package/src/ui-tailwind/chart/render/bar-column.tsx +3 -3
- package/src/ui-tailwind/chart/render/bubble.tsx +3 -3
- package/src/ui-tailwind/chart/render/combo.tsx +2 -2
- package/src/ui-tailwind/chart/render/data-labels.tsx +2 -2
- package/src/ui-tailwind/chart/render/font-metrics.ts +2 -2
- package/src/ui-tailwind/chart/render/line.tsx +3 -3
- package/src/ui-tailwind/chart/render/pie.tsx +6 -6
- package/src/ui-tailwind/chart/render/scatter.tsx +3 -3
- package/src/ui-tailwind/chart/render/svg-primitives.ts +3 -3
- package/src/ui-tailwind/chart/render/unsupported.tsx +2 -2
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +88 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-send-to-supplier-button.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +1 -1
- package/src/ui-tailwind/chrome/collab-top-nav-container.tsx +1 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +553 -0
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +182 -0
- package/src/ui-tailwind/chrome/local-surface-arbiter.ts +534 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +226 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-context-band.tsx +125 -0
- package/src/ui-tailwind/chrome/tw-context-menu-portal.tsx +248 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +42 -1
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +8 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +38 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +104 -6
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +66 -7
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +54 -8
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +7 -1
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +33 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +78 -1
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +16 -8
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +276 -0
- package/src/ui-tailwind/chrome/use-context-menu-controller.ts +201 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +22 -4
- package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +11 -5
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +197 -3
- package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +1 -1
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +35 -6
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +24 -16
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +1 -1
- package/src/ui-tailwind/debug/README.md +57 -0
- package/src/ui-tailwind/debug/index.ts +3 -0
- package/src/ui-tailwind/debug/tw-debug-overlay.tsx +186 -0
- package/src/ui-tailwind/debug/tw-debug-presentation.tsx +80 -0
- package/src/ui-tailwind/debug/tw-debug-top-bar.tsx +83 -0
- package/src/ui-tailwind/editor-surface/chart-node-view.tsx +2 -2
- package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +135 -10
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +40 -13
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-schema.ts +1 -1
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +3 -3
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +1 -1
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +2 -2
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +91 -9
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +1 -1
- package/src/ui-tailwind/editor-surface/surface-layer.ts +1 -1
- package/src/ui-tailwind/editor-surface/tw-opaque-block.tsx +1 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +23 -6
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -22
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +1 -1
- package/src/ui-tailwind/index.ts +0 -5
- package/src/ui-tailwind/overlay-anchor-bridge-context.tsx +33 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +66 -29
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +25 -2
- package/src/ui-tailwind/review/comment-markdown-renderer.tsx +15 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +92 -4
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +1 -1
- package/src/ui-tailwind/review-workspace/page-chrome.ts +210 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +101 -0
- package/src/ui-tailwind/review-workspace/paragraph-layout.ts +115 -0
- package/src/ui-tailwind/review-workspace/selection-toolbar-placement.ts +97 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-navigator.tsx +130 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-page-toolbar.tsx +240 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +59 -0
- package/src/ui-tailwind/review-workspace/types.ts +408 -0
- package/src/ui-tailwind/review-workspace/use-chrome-policy.ts +104 -0
- package/src/ui-tailwind/review-workspace/use-derived-view-state.ts +151 -0
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +70 -0
- package/src/ui-tailwind/review-workspace/use-grabbed-segment-offsets.ts +40 -0
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +130 -0
- package/src/ui-tailwind/review-workspace/use-pm-surface-capture.ts +60 -0
- package/src/ui-tailwind/review-workspace/use-review-rail-state.ts +63 -0
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +170 -0
- package/src/ui-tailwind/review-workspace/use-scroll-root-capture.ts +28 -0
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +113 -0
- package/src/ui-tailwind/review-workspace/use-shell-selection-anchor-bridge.ts +120 -0
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +55 -0
- package/src/ui-tailwind/review-workspace/use-viewport-dimensions.ts +43 -0
- package/src/ui-tailwind/review-workspace/use-workspace-arbiter.ts +25 -0
- package/src/ui-tailwind/review-workspace/use-workspace-composition.ts +86 -0
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +150 -0
- package/src/ui-tailwind/theme/editor-theme.css +25 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +61 -98
- package/src/ui-tailwind/tw-review-workspace.tsx +521 -1802
- package/src/ui-tailwind/ui-api-context.tsx +43 -0
- package/src/ui-tailwind/ui-shell-channels-context.tsx +49 -0
- package/src/validation/compatibility-engine.ts +6 -6
- package/src/runtime/styles-cascade.ts +0 -33
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +0 -85
- /package/src/runtime/{page-number-format.ts → formatting/field/page-number-format.ts} +0 -0
- /package/src/runtime/{ai-action-policy.ts → workflow/ai-action-policy.ts} +0 -0
- /package/src/runtime/{scope-tag-registry.ts → workflow/scope-tag-registry.ts} +0 -0
|
@@ -221,8 +221,457 @@
|
|
|
221
221
|
* `resolved-formatting-document`, and `resolved-formatting-state`.
|
|
222
222
|
* Persisted prerender/layout caches must invalidate so geometry derived
|
|
223
223
|
* under v23 is never reused against the merged layout pipeline.
|
|
224
|
+
* 25 — Debug-infra D1 public-facet widening. `src/runtime/layout/public-facet.ts`
|
|
225
|
+
* adds module-level `setActiveLayoutWarningEmitter` setter + private
|
|
226
|
+
* `emitLayoutGuardWarning` helper, with call-site probes at the 10
|
|
227
|
+
* silent-success `return []` guards (powers D1 stage-token lineage
|
|
228
|
+
* for the `warning` telemetry channel). `src/runtime/layout/index.ts`
|
|
229
|
+
* re-exports `setActiveLayoutWarningEmitter`. No pixel-geometry
|
|
230
|
+
* change; the facet interface widened (new exported function), so
|
|
231
|
+
* persisted envelopes from v24 should invalidate cleanly.
|
|
232
|
+
* 26 — Layer-03 Phase D (formatting-semantics refactor, earned bump).
|
|
233
|
+
* `src/runtime/layout/table-render-plan.ts` +
|
|
234
|
+
* `src/runtime/layout/public-facet.ts` flipped their imports from
|
|
235
|
+
* the legacy `src/runtime/table-style-resolver.ts` to the canonical
|
|
236
|
+
* `src/runtime/formatting/table-style-resolver.ts`. The 9 legacy
|
|
237
|
+
* shim files at `src/runtime/*-resolver.ts` + friends were deleted.
|
|
238
|
+
* No pixel-geometry change; cache envelopes from v25 invalidate
|
|
239
|
+
* because the layout-engine import graph materially changed shape.
|
|
240
|
+
* NOTE on prior unearned bumps: Layer-03 Slices 2 + 3 had previously
|
|
241
|
+
* assigned 24 → 25 → 26 as "defensive" versions while the refactor
|
|
242
|
+
* was under way; on code review those bumps were found to be
|
|
243
|
+
* unearned and Phase A1 reverted to 24. With upstream having since
|
|
244
|
+
* re-claimed 25 for debug-infra D1, this earned Layer-03 bump
|
|
245
|
+
* lands at 26.
|
|
246
|
+
* 27 — Refactor/05 Slice 1: reserve `src/runtime/geometry/**` as its own
|
|
247
|
+
* layer. New modules `geometry-types.ts`, `geometry-facet.ts` (thin
|
|
248
|
+
* proxy over the existing layout facet + render kernel), `viewport.ts`
|
|
249
|
+
* (stubbed), `invalidation.ts` (cache-key helper), and barrel
|
|
250
|
+
* `index.ts`. The layout-engine-version CI guard's WATCHED_PREFIXES
|
|
251
|
+
* now includes `src/runtime/geometry/` so future slices must bump
|
|
252
|
+
* this constant when they touch the tree. The companion guard
|
|
253
|
+
* `scripts/ci-check-geometry-no-dom-authority.mjs` ships alongside
|
|
254
|
+
* (enforces G2 — DOM-origin reads forbidden outside `viewport.ts`).
|
|
255
|
+
* No behavior change: the geometry facet delegates to the layout
|
|
256
|
+
* facet's existing `hitTest` / `getAnchorRects`, and caret / envelope
|
|
257
|
+
* / handle methods return null / empty stubs pending Slices 4–5.
|
|
258
|
+
* Cache envelopes from v26 invalidate because the runtime's exported
|
|
259
|
+
* module set changed (new `src/runtime/geometry/index.ts` barrel)
|
|
260
|
+
* even though pixel geometry did not.
|
|
261
|
+
* 28 — Refactor/05 Slice 2a: move `resolveHitTest`, `hitTestRegion`,
|
|
262
|
+
* `containsPoint`, and `resolveAnchorRects` from
|
|
263
|
+
* `src/runtime/layout/public-facet.ts` into
|
|
264
|
+
* `src/runtime/geometry/hit-test.ts` and
|
|
265
|
+
* `src/runtime/geometry/project-anchors.ts`. Layout facet imports
|
|
266
|
+
* from the new locations; its `hitTest` / `getAnchorRects` methods
|
|
267
|
+
* remain wrapping those calls (deprecation + deletion lands in
|
|
268
|
+
* Slice 6). `createGeometryFacet` gains an optional `renderKernel`
|
|
269
|
+
* getter — when supplied, geometry resolves directly against the
|
|
270
|
+
* kernel's current frame, bypassing the layout-facet proxy. New
|
|
271
|
+
* CI guard `scripts/ci-check-no-layout-geometry-leak.mjs` rejects
|
|
272
|
+
* DOM-origin reads inside `src/runtime/layout/**` +
|
|
273
|
+
* `src/runtime/render/**` (dual of the geometry-no-dom-authority
|
|
274
|
+
* guard). No pixel-geometry change; cache envelopes from v27
|
|
275
|
+
* invalidate because the runtime's module exports and the layout
|
|
276
|
+
* facet's internal dependency set changed.
|
|
277
|
+
* 29 — Refactor/05 Slice 2b: move `collectLineBoxesForRegion`,
|
|
278
|
+
* `resolveRegionEntry`, `EMPTY_LINE_BOXES`, and the
|
|
279
|
+
* `RuntimeLineBoxAlias` type from `public-facet.ts` into
|
|
280
|
+
* `src/runtime/geometry/project-fragments.ts`; move
|
|
281
|
+
* `collectScopeRailSegmentsForQuery` into
|
|
282
|
+
* `src/runtime/geometry/project-anchors.ts` (with D1 warning probe
|
|
283
|
+
* ported alongside). Layout facet imports from the new locations.
|
|
284
|
+
* `GeometryFacet` gains `getBlockRects` (new impl — walks the render
|
|
285
|
+
* frame, tags rects `space: "frame"`; required by Slice 5's
|
|
286
|
+
* `v3 runtime.geometry.getBlockRects` live promotion), `getLineBoxes`,
|
|
287
|
+
* `getScopeRailSegments`, and `getAllScopeRailSegments` methods —
|
|
288
|
+
* the line-box and rail-segment methods delegate to the layout
|
|
289
|
+
* facet's orchestration for now and flip to direct engine/graph
|
|
290
|
+
* access during Slice 6. No pixel-geometry change; cache envelopes
|
|
291
|
+
* from v28 invalidate because the layout facet's internal import
|
|
292
|
+
* set changed again.
|
|
293
|
+
* 30 — Refactor/05 Slice 3a: real `src/runtime/geometry/viewport.ts`
|
|
294
|
+
* implementation. `createViewportFromRoot({ root, pxPerTwip })`
|
|
295
|
+
* attaches passive scroll + ResizeObserver listeners to the editor
|
|
296
|
+
* root and rAF-coalesces fanouts — consumers subscribe via
|
|
297
|
+
* `geometryFacet.subscribeViewport`. The Slice-1 stub
|
|
298
|
+
* `createViewport()` is preserved for tests and unwired call sites.
|
|
299
|
+
* `RootViewportHandle.setPxPerTwip` propagates zoom changes
|
|
300
|
+
* synchronously so chrome overlays re-project without waiting for a
|
|
301
|
+
* scroll event. Architecture 05 contract G2 exception is honored:
|
|
302
|
+
* only `scrollLeft` / `scrollTop` are read here, and only from
|
|
303
|
+
* inside `viewport.ts` (enforced by
|
|
304
|
+
* `scripts/ci-check-geometry-no-dom-authority.mjs`).
|
|
305
|
+
*
|
|
306
|
+
* `GeometryFacet` gains `getPage(target)` and `getBlock(blockId)` —
|
|
307
|
+
* the substrate Slice 3b (overlay + scroll-anchor rewire) consumes
|
|
308
|
+
* in place of DOM reads. Implementations are thin projections over
|
|
309
|
+
* `frame.pages` / `frame.pages[*].regions.*.blocks`, tagged
|
|
310
|
+
* `space: "frame"` per G5.
|
|
311
|
+
*
|
|
312
|
+
* No pixel-geometry change; cache envelopes from v29 invalidate
|
|
313
|
+
* because the facet surface widened (new `getPage` / `getBlock`
|
|
314
|
+
* methods + `createViewportFromRoot` export) even though pixel
|
|
315
|
+
* output is unchanged.
|
|
316
|
+
* 31 — Refactor/05 Slice 3b: rewire chrome consumers off DOM authority.
|
|
317
|
+
* `src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx`
|
|
318
|
+
* gains an optional `geometryFacet` prop; when wired (and
|
|
319
|
+
* `getPage(0)` resolves through the kernel), the overlay reads
|
|
320
|
+
* page rects directly from the render frame via the new exported
|
|
321
|
+
* helper `resolvePageOverlayRectsFromGeometry` — zero DOM reads,
|
|
322
|
+
* zero forced layouts. The DOM-measurement path
|
|
323
|
+
* (`measureWidgetsViaBoundingRect` / `ViaOffsetChain`) is kept as
|
|
324
|
+
* the cold-open fallback per architecture 05 Slice 3 exit
|
|
325
|
+
* criteria.
|
|
326
|
+
*
|
|
327
|
+
* `src/ui-tailwind/editor-surface/scroll-anchor.ts` —
|
|
328
|
+
* `findScrollAnchor` + `restoreScrollAnchor` gain an optional
|
|
329
|
+
* `{ geometryFacet, prepaintFallback }` options arg. When wired,
|
|
330
|
+
* block positions are computed from the kernel's frame coordinates
|
|
331
|
+
* (`geometryFacet.getBlock(blockId).rects[0]`); the DOM path runs
|
|
332
|
+
* only on cold-open or when `prepaintFallback: true` is
|
|
333
|
+
* explicitly requested.
|
|
334
|
+
*
|
|
335
|
+
* `scripts/ci-check-geometry-no-dom-authority.mjs` extends
|
|
336
|
+
* `SCOPED_FILES` + `ALLOWED_FILES` to both chrome files so
|
|
337
|
+
* additions to them are tracked; Slice 6 narrows `ALLOWED_FILES`
|
|
338
|
+
* back to `viewport.ts` only.
|
|
339
|
+
*
|
|
340
|
+
* No pixel-geometry change — the geometry-path rects are
|
|
341
|
+
* byte-identical to the kernel frame rects they project from, and
|
|
342
|
+
* the DOM fallback path is unchanged. Cache envelopes from v30
|
|
343
|
+
* invalidate because the overlay and scroll-anchor public
|
|
344
|
+
* signatures widened.
|
|
345
|
+
* 32 — Refactor/05 Slice-3 cleanup: relocate
|
|
346
|
+
* `resolvePageOverlayRectsFromGeometry` from the overlay's `.tsx`
|
|
347
|
+
* into `src/runtime/geometry/overlay-rects.ts` so the projection
|
|
348
|
+
* math lives inside L05. Adds a classifier rule for
|
|
349
|
+
* `test/runtime/geometry/` in `scripts/test-bundles.mjs` (previously
|
|
350
|
+
* the bundle was empty because tests fell through the catch-all).
|
|
351
|
+
* No behavior change; the overlay component re-exports the moved
|
|
352
|
+
* symbol under its original name. Cache envelopes from v31
|
|
353
|
+
* invalidate because the geometry layer's export surface widened
|
|
354
|
+
* (new `overlay-rects.ts` module + new barrel export).
|
|
355
|
+
* 33 — Refactor/05 Slice 4: caret geometry as a first-class operation.
|
|
356
|
+
* `src/runtime/geometry/caret-geometry.ts` ships
|
|
357
|
+
* `resolveCaretGeometry(frame, offset, story?)` and
|
|
358
|
+
* `resolveSelectionRects(frame, range)`. `GeometryFacet.getCaret`
|
|
359
|
+
* and `getSelectionRects` replace their Slice-1 null/[] stubs
|
|
360
|
+
* with real implementations routed through `frame.anchorIndex`
|
|
361
|
+
* (the working substrate for offset-to-rect projection even when
|
|
362
|
+
* per-line `RenderLine` anchors aren't populated).
|
|
363
|
+
*
|
|
364
|
+
* Known Slice-4 caveats (documented in `caret-geometry.ts`):
|
|
365
|
+
* `direction` is always `"ltr"` until run-level writing-direction
|
|
366
|
+
* metadata arrives in a later slice; `getSelectionRects`
|
|
367
|
+
* non-collapsed range returns the kernel's union rect (single
|
|
368
|
+
* entry) until per-line anchors land and enable one-rect-per-line
|
|
369
|
+
* enumeration. `baseline` is approximated at 0.8× height via the
|
|
370
|
+
* cap-height heuristic.
|
|
371
|
+
*
|
|
372
|
+
* No pixel-geometry change — caret rects are byte-identical to
|
|
373
|
+
* the anchor index's projections, just reshaped into
|
|
374
|
+
* `CaretGeometry`. Cache envelopes from v32 invalidate because
|
|
375
|
+
* the geometry facet surface widened.
|
|
376
|
+
* 34 — Refactor/05 Slice 5: replacement envelope + object handles as
|
|
377
|
+
* first-class operations.
|
|
378
|
+
* `src/runtime/geometry/replacement-envelope.ts` ships
|
|
379
|
+
* `resolveReplacementEnvelope(frame, scope, story?)` →
|
|
380
|
+
* `EnvelopeBundle | null`. Range scopes produce `confidence:
|
|
381
|
+
* "exact"`; detached scopes project the `lastKnownRange` with
|
|
382
|
+
* `confidence: "detached"`. `scopeRects` routes through the
|
|
383
|
+
* Slice-4 `resolveSelectionRects` helper so the envelope upgrades
|
|
384
|
+
* to one-rect-per-line automatically when per-run anchors land.
|
|
385
|
+
* `src/runtime/geometry/object-handles.ts` ships
|
|
386
|
+
* `resolveObjectHandles(frame, objectId)` producing 9 zero-size
|
|
387
|
+
* handle points (4 corners + 4 edge midpoints + 1 rotate anchor
|
|
388
|
+
* 20 px above the top-center) projected from the block bbox via
|
|
389
|
+
* `frame.anchorIndex.byBlockId`.
|
|
390
|
+
* `GeometryFacet` adds a `getCanonicalDocument?` input used by
|
|
391
|
+
* `getReplacementEnvelope(scopeId)` to resolve scopes through
|
|
392
|
+
* `src/runtime/workflow/scope-resolver.ts::resolveScope`. `getObjectHandles`
|
|
393
|
+
* routes directly through the kernel frame.
|
|
394
|
+
* v3 promotion: `src/api/v3/runtime/geometry.ts::getBlockRectsMetadata`
|
|
395
|
+
* flips from `mock` to `live-with-adapter`; adapter wraps
|
|
396
|
+
* `layout.getAnchorRects({kind:'block-id', value})` into
|
|
397
|
+
* `BlockRectEntry.rects[]`. Mock shape retained as the headless
|
|
398
|
+
* fallback.
|
|
399
|
+
* No pixel-geometry change — envelope and handle rects are
|
|
400
|
+
* byte-identical projections of existing anchor-index outputs.
|
|
401
|
+
* Cache envelopes from v33 invalidate because the geometry facet
|
|
402
|
+
* surface widened again (new `getCanonicalDocument` input + new
|
|
403
|
+
* export `ReplacementScope`).
|
|
404
|
+
* 35 — Refactor/05 Slice 6 (layer closure): `GeometryDebugEntry` +
|
|
405
|
+
* `buildGeometryDebugEntry` ship at
|
|
406
|
+
* `src/runtime/geometry/projector.ts`, mirroring
|
|
407
|
+
* `src/runtime/formatting/projector.ts`. The entry is wired into
|
|
408
|
+
* `DebugInspectorSnapshot.geometry` as an optional field gated by
|
|
409
|
+
* the `layout` telemetry channel (consumers must call
|
|
410
|
+
* `bus.isEnabled("layout")` before materializing).
|
|
411
|
+
* Plan frontmatter flips `status: PROPOSED → CLOSED` with
|
|
412
|
+
* explicitly-documented deferred follow-ups (consumer flip +
|
|
413
|
+
* gap reconciliation, wrapper deletion, CI-guard tightening,
|
|
414
|
+
* `geometry.projected` emit, per-run anchors, v3 promotions).
|
|
415
|
+
* Wiki pages `rendering-pipeline.md` + `selection-and-cursor.md`
|
|
416
|
+
* bump `lastCuratedCommit` and gain closure status notes.
|
|
417
|
+
* Closure evidence artifact lands at
|
|
418
|
+
* `docs/reference/layer-05-geometry-projection-evidence-2026-04-22.{md,json}`.
|
|
419
|
+
* No pixel-geometry change; cache envelopes from v34 invalidate
|
|
420
|
+
* because a new debug-snapshot optional field is now part of the
|
|
421
|
+
* runtime's exported shape.
|
|
422
|
+
* 36 — Layer-03 production-boundary pass §B. `resolved-formatting-state.ts
|
|
423
|
+
* ::resolveDominantFont` now reads from `segment.resolvedRunFormatting`
|
|
424
|
+
* (canonical L03 output) first, with `segment.markAttrs` fallback only
|
|
425
|
+
* for viewport-culled blocks where the resolved output is absent.
|
|
426
|
+
* Before: layout reconstructed dominant font from the surface
|
|
427
|
+
* projection intermediate (`markAttrs`), bypassing the L03 cascade.
|
|
428
|
+
* After: L04 measurement-path reads authoritative L03 output, matching
|
|
429
|
+
* architecture §C2 ("formatting, layout, and geometry are separate
|
|
430
|
+
* layers"). Pixel-identical on documents whose markAttrs agreed with
|
|
431
|
+
* the cascade; fixes cases where the cascade carried a
|
|
432
|
+
* character-style-chain font (`Heading 1` → `Cambria`) but markAttrs
|
|
433
|
+
* lacked the override — line-height + avg-char-width now inherit the
|
|
434
|
+
* cascade-resolved font. Cache envelopes from v35 invalidate because
|
|
435
|
+
* dominant-font inputs to line-height + widow/keep-next measurement
|
|
436
|
+
* changed shape.
|
|
437
|
+
* 37 — Refactor/04 Slice 3: activate the reserved `layout` telemetry
|
|
438
|
+
* channel. `createLayoutEngine({ telemetryBus })` forwards the
|
|
439
|
+
* granular `page_count_changed` / `page_field_dirtied` /
|
|
440
|
+
* `layout_committed` events to the bus and additionally emits
|
|
441
|
+
* `layout.recompute.completed` at the end of `fullRebuild` /
|
|
442
|
+
* `incrementalRelayout` with `{ layoutEngineVersion, reasonKind,
|
|
443
|
+
* scope, pageCountBefore, pageCountAfter, durationMs }`. Adds a
|
|
444
|
+
* `LayoutDebugEntry` projector + `DebugInspectorSnapshot.layoutDebug`
|
|
445
|
+
* section, both gated on `bus.isEnabled("layout")` — complementing
|
|
446
|
+
* the `geometry?` section that v35 already gates on the same
|
|
447
|
+
* channel. Zero cost when the channel is off (bitmap short-circuit
|
|
448
|
+
* on every emit, `recomputeStart` sample skipped on the cold
|
|
449
|
+
* path). No behavior change to pagination itself. Cache envelopes
|
|
450
|
+
* from v36 invalidate because the `createLayoutEngine` options
|
|
451
|
+
* shape widened (new optional `telemetryBus`) and a new optional
|
|
452
|
+
* debug-snapshot field is now part of the runtime's exported
|
|
453
|
+
* shape.
|
|
454
|
+
* 38 — Refactor/04 Slice 4. Multi-column `nextColumn` + column-aware
|
|
455
|
+
* fragment routing. Pagination now tracks a per-block column
|
|
456
|
+
* placement (`columnByBlockIdByPageIndex`) when the section layout
|
|
457
|
+
* has `columns > 1`. `RuntimeBlockFragment.columnIndex` carries
|
|
458
|
+
* that placement onto every fragment; `buildRegions` partitions
|
|
459
|
+
* fragment ids into `RuntimePageRegions.columns[i].fragmentIds`
|
|
460
|
+
* rather than leaving the per-column lists empty. Behavioral
|
|
461
|
+
* changes: block-level `<w:br w:type="column"/>` inside a multi-
|
|
462
|
+
* column section now routes subsequent fragments into the
|
|
463
|
+
* advanced column region; column overflow pushes a new page that
|
|
464
|
+
* inherits the section's column layout with the active column
|
|
465
|
+
* reset to 0; single-column sections continue to route every
|
|
466
|
+
* fragment to `regions.body` and leave `regions.columns`
|
|
467
|
+
* undefined (F01 + 10 single-column CCEP regression preserved).
|
|
468
|
+
* Section-level `<w:type w:val="nextColumn"/>` still degrades to
|
|
469
|
+
* `continuous`-style page merging — cross-section column-state
|
|
470
|
+
* carry is explicit follow-up work (tracked on react-refactor).
|
|
471
|
+
* Cache envelopes from v37 invalidate because the per-page
|
|
472
|
+
* fragment routing under multi-column layouts changes; single-
|
|
473
|
+
* column envelopes remain shape-compatible but the version bump
|
|
474
|
+
* ensures consumers re-derive regions rather than trust a stale
|
|
475
|
+
* empty `columns[*].fragmentIds`.
|
|
476
|
+
* 39 — Refactor/05 Slice 6 wrapper-deletion pass (2026-04-22). Deletes
|
|
477
|
+
* `hitTest` + `getAnchorRects` from `WordReviewEditorLayoutFacet`
|
|
478
|
+
* interface + impl + inert stub. Geometry consumers now read through
|
|
479
|
+
* `runtime.geometry.hitTest` / `.getAnchorRects`. The geometry-facet's
|
|
480
|
+
* own layout-facet fallback paths were also deleted; unwired facet
|
|
481
|
+
* returns null / [] directly. Persisted LayCache envelopes from v38
|
|
482
|
+
* invalidate because the facet's interface shape changed.
|
|
483
|
+
* 40 — Refactor/06 Slice 4C rail-seam inversion (2026-04-22). The
|
|
484
|
+
* layout facet's `getScopeRailSegments` / `getAllScopeRailSegments`
|
|
485
|
+
* / `getAllScopeCardModels` methods are removed; rail + scope-
|
|
486
|
+
* card composition is now Layer-06-owned via
|
|
487
|
+
* `runtime.workflow.*`. The `getWorkflowRailInput` /
|
|
488
|
+
* `getWorkflowMarkupMetadata` / `getSuggestionsSnapshot` config
|
|
489
|
+
* hooks on `CreateLayoutFacetInput` are removed since the facet
|
|
490
|
+
* no longer consumes workflow state. Geometry-facet's
|
|
491
|
+
* `getScopeRailSegments` / `getAllScopeRailSegments` proxies are
|
|
492
|
+
* removed. No pixel-geometry change, but the public layout
|
|
493
|
+
* surface shape changed, so cache envelopes from v39 invalidate.
|
|
494
|
+
*/
|
|
495
|
+
/*
|
|
496
|
+
* v40 (2026-04-22) — refactor/04 post-Slice-4 cross-section column
|
|
497
|
+
* carry. Section-level `<w:type w:val="nextColumn"/>` between two
|
|
498
|
+
* matching multi-column sections now advances column state across
|
|
499
|
+
* the boundary: section N is seeded with `startColumnIndex =
|
|
500
|
+
* prevEndColumn + 1` when prev ended with room; otherwise a new
|
|
501
|
+
* page pushes with column index 0 (matching Word's behavior).
|
|
502
|
+
* Single-column sections still degrade to `continuous` (F01 + CCEP
|
|
503
|
+
* regression preserved). Mismatched column counts degrade to
|
|
504
|
+
* `nextPage`. New optional `startColumnIndex` parameter on
|
|
505
|
+
* `paginateSectionBlocksWithSplits`; new
|
|
506
|
+
* `endColumnByGlobalPageIndex` tracking in
|
|
507
|
+
* `paginateAllSectionsWithSplits` feeds the decision. Persisted
|
|
508
|
+
* LayCache envelopes from v39 invalidate because documents with
|
|
509
|
+
* cross-section multi-column content paginate differently under
|
|
510
|
+
* v40 (blocks that previously landed at `columnIndex: 0` after a
|
|
511
|
+
* `nextColumn` section break now land at `columnIndex: 1+`).
|
|
512
|
+
* Single-column documents are pagination-identical to v39.
|
|
513
|
+
*/
|
|
514
|
+
/*
|
|
515
|
+
* v41 (2026-04-22) — refactor/05 cross-lane-coord pass. Adds
|
|
516
|
+
* `getRenderFrame` + `getRenderZoom` to `GeometryFacet` (passthrough
|
|
517
|
+
* to the render kernel) so UI chrome consumers can flip their reads
|
|
518
|
+
* off the layout-facet's now-@deprecated `getRenderFrame` /
|
|
519
|
+
* `getRenderZoom` methods without losing access to the underlying
|
|
520
|
+
* kernel primitives. Per Layer 04's cross-layer-coord §1.1 ask:
|
|
521
|
+
* those two methods are the last remaining geometry-shaped
|
|
522
|
+
* accessors on the layout facet; they exit once UI consumers flip.
|
|
523
|
+
* Shape change on `GeometryFacet` invalidates persisted v40 cache
|
|
524
|
+
* envelopes via the top-level version discriminator.
|
|
525
|
+
*/
|
|
526
|
+
/*
|
|
527
|
+
* v42 (2026-04-22) — refactor/05 cross-lane-coord §8.4–§8.6 completion.
|
|
528
|
+
* Deletes `getRenderFrame` + `getRenderZoom` from the layout facet
|
|
529
|
+
* interface + impl + inert stub. Consumers (5 UI chrome files + 4
|
|
530
|
+
* tests) were migrated in the same pass to read through
|
|
531
|
+
* `runtime.geometry.getRenderFrame` / `.getRenderZoom`. Per L04's
|
|
532
|
+
* cross-layer-coord §1.1, the layout facet now exposes layout-only
|
|
533
|
+
* reads — no more geometry-shaped accessors. Cache envelopes from
|
|
534
|
+
* v41 invalidate via the top-level version discriminator.
|
|
535
|
+
*/
|
|
536
|
+
/*
|
|
537
|
+
* v43 (2026-04-22) — refactor/04 post-closure Task 4: endnote reservation
|
|
538
|
+
* bug fix. `estimateFootnoteReservation` in `paginated-layout-engine.ts`
|
|
539
|
+
* now skips `noteKind === "endnote"` during per-page reservation math,
|
|
540
|
+
* matching the pre-existing skip in `snapshotNoteAllocations` (the
|
|
541
|
+
* emission path). Prior behavior inflated `reservedNoteHeight` with
|
|
542
|
+
* endnote body estimates on every page that referenced an endnote,
|
|
543
|
+
* squeezing body content onto additional pages even though endnotes
|
|
544
|
+
* flow to the document-end endnote area (P8.2, `getDocumentEndnoteBlocks`).
|
|
545
|
+
* Footnote behavior is unchanged. Cache envelopes from v42 invalidate
|
|
546
|
+
* because documents containing endnotes paginate differently under v43
|
|
547
|
+
* (fewer body pages when endnote bodies are large); footnote-only and
|
|
548
|
+
* note-free documents are pagination-identical to v42.
|
|
549
|
+
*/
|
|
550
|
+
/*
|
|
551
|
+
* v44 (2026-04-22) — refactor/04 cross-layer-coord §1.12 Pass 2. Pure
|
|
552
|
+
* type relocation: `RuntimePageGraph`, `RuntimePageNode`, and
|
|
553
|
+
* `BuildPageGraphInput` move from `src/runtime/layout/page-graph.ts`
|
|
554
|
+
* into `src/model/layout/runtime-page-graph-types.ts`, along with
|
|
555
|
+
* their dependencies (`PageLayoutSnapshot`, `EditorStoryTarget`,
|
|
556
|
+
* `DocumentPageSnapshot`, `ResolvedPageStories`,
|
|
557
|
+
* `ResolvedDocumentSection` — the first three re-exported from
|
|
558
|
+
* `src/api/public-types.ts`, the latter two from their prior runtime
|
|
559
|
+
* homes, for consumer-import stability). `src/runtime/prerender/
|
|
560
|
+
* cache-envelope.ts` now imports `RuntimePageGraph` from model
|
|
561
|
+
* rather than runtime — cutting Layer 01's session→runtime transit
|
|
562
|
+
* through `CacheEnvelope` (L01 coord §1 primary ask). Graph
|
|
563
|
+
* construction (`buildPageGraph`, `spliceGraph`, `graphRevision`)
|
|
564
|
+
* stays in `src/runtime/layout/page-graph.ts`. Zero behavior change;
|
|
565
|
+
* cache envelopes from v43 invalidate because the layout-engine
|
|
566
|
+
* import graph materially changed shape (page-graph.ts's type
|
|
567
|
+
* declarations are now re-exports from model).
|
|
568
|
+
*/
|
|
569
|
+
/*
|
|
570
|
+
* v47 (2026-04-23) — refactor/04 coord §1.15 / §1.18 — `FONT_AVG_CHAR_WIDTH`
|
|
571
|
+
* calibration against OpenType xAvgCharWidth. Pre-calibration values
|
|
572
|
+
* (Calibri 9.0 twips/half-point, TNR 9.2, etc.) were ~80% higher than
|
|
573
|
+
* published font metrics, producing a 50-73% runtime page overcount
|
|
574
|
+
* vs LibreOffice on CCEP contracts. Post truth-baseline's 2026-04-23
|
|
575
|
+
* oracle re-extraction (bundle 34d860831fe32b38) the miscalibration
|
|
576
|
+
* was isolated to the empirical measurement backend; the canvas
|
|
577
|
+
* backend measures real glyph widths via Canvas2D and is unaffected.
|
|
578
|
+
*
|
|
579
|
+
* New values are derived from each font's published xAvgCharWidth
|
|
580
|
+
* (OpenType OS/2 table) expressed as em-fraction × twips-per-em at
|
|
581
|
+
* the given font size. For Calibri: xAvgCharWidth = 1037/2048 em ≈
|
|
582
|
+
* 0.506em → at 11pt (22 half-points) = 5.57pt = 111 twips per char,
|
|
583
|
+
* matching the new factor of 5.0 × 22 = 110. The remaining 16 fonts
|
|
584
|
+
* in the table were recalibrated on the same basis.
|
|
585
|
+
*
|
|
586
|
+
* Impact on the 5 CCEP docs with re-extracted oracles:
|
|
587
|
+
* aps-short-form-supply-of-services 39 → 25 pages (−3.8% vs oracle 26)
|
|
588
|
+
* aps-supply-of-services 45 → 29 pages (+11.5% vs oracle 26)
|
|
589
|
+
* eu-global-consultancy-services 61 → 40 pages (+5.3% vs oracle 38)
|
|
590
|
+
* eu-global-supply-of-services 41 → 27 pages (+12.5% vs oracle 24)
|
|
591
|
+
* eu-tactical-sourcing-team-agreement 7 → 5 pages (−16.7% vs oracle 6)
|
|
592
|
+
*
|
|
593
|
+
* Baseline was 50-73% overcount across the four large docs; post-
|
|
594
|
+
* calibration deltas are −16.7% to +12.5%. 2/5 docs now within ±10%
|
|
595
|
+
* of oracle; residual over/under is attributable to secondary
|
|
596
|
+
* factors (widow/orphan, keep-with-next, minor per-font refinement).
|
|
597
|
+
*
|
|
598
|
+
* New `test/runtime/layout/ccep-multi-doc-parity-probe.test.ts`
|
|
599
|
+
* loads oracle page counts from the trusted-oracle dumps at
|
|
600
|
+
* `services/debug/scripts/.reports/diagnose-oracle-raw-*.json` at
|
|
601
|
+
* read time — the probe is single-source-of-truth: no oracle page
|
|
602
|
+
* counts are hardcoded anywhere in the runtime or the probe.
|
|
603
|
+
*
|
|
604
|
+
* Two factor-encoding unit tests in
|
|
605
|
+
* `test/runtime/layout/paginated-layout-engine.test.ts` were
|
|
606
|
+
* updated to the new expected values; one `pagination-state.test.ts`
|
|
607
|
+
* test was narrowed to its structural-invariant assertion (the
|
|
608
|
+
* column-definitions survive) rather than the measurement-specific
|
|
609
|
+
* page-count/offset values it had encoded. Cache envelopes from v46
|
|
610
|
+
* invalidate because pagination output changes for every document
|
|
611
|
+
* whose dominant font has a corrected factor (which is effectively
|
|
612
|
+
* all documents — the `DEFAULT_FONT_AVG_CHAR_WIDTH` fallback also
|
|
613
|
+
* shifted 10.0 → 5.5).
|
|
614
|
+
*/
|
|
615
|
+
/*
|
|
616
|
+
* v46 (2026-04-23) — refactor/04 post-closure Task 5: compat-input
|
|
617
|
+
* ledger + projector exposure. New module
|
|
618
|
+
* `src/runtime/layout/compat-input-ledger.ts` exports
|
|
619
|
+
* `resolveLayoutCompatInputs(settings)` → typed `LayoutCompatInputs`
|
|
620
|
+
* snapshot covering seven named compat fields (compatibilityMode,
|
|
621
|
+
* doNotExpandShiftReturn, useWord97LineBreakRules, useFELayout,
|
|
622
|
+
* doNotUseHTMLParagraphAutoSpacing,
|
|
623
|
+
* overrideTableStyleFontSizeAndJustification,
|
|
624
|
+
* differentiateMultirowTableHeaders) plus passthrough buckets for
|
|
625
|
+
* every unknown `<w:compatSetting>` / `<w:compat>` boolean flag.
|
|
626
|
+
* `src/runtime/layout/projector.ts::buildLayoutDebugEntry` gains an
|
|
627
|
+
* optional `settings` input; when supplied, the entry's new
|
|
628
|
+
* `compatInputs` field surfaces the resolved ledger.
|
|
629
|
+
* `src/runtime/debug/build-debug-inspector-snapshot.ts` threads
|
|
630
|
+
* `document.subParts.settings` into the projector. LayoutDebugEntry
|
|
631
|
+
* `schemaVersion` bumps 1 → 2. Zero pagination behavior change —
|
|
632
|
+
* the ledger is pure diagnostic wiring today; future behavioral
|
|
633
|
+
* branches that gate on a compat flag now have a canonical access
|
|
634
|
+
* point instead of ad-hoc `settings.compatFlags?.[...]` reads.
|
|
635
|
+
* Cache envelopes from v45 invalidate because the layout module
|
|
636
|
+
* export surface widened (new `compat-input-ledger.ts` module + new
|
|
637
|
+
* optional projector field).
|
|
638
|
+
*/
|
|
639
|
+
/*
|
|
640
|
+
* v45 (2026-04-23) — refactor/04 post-closure Task 3: measurement
|
|
641
|
+
* provider becomes authoritative. Three changes land under
|
|
642
|
+
* `src/runtime/layout/**`:
|
|
643
|
+
*
|
|
644
|
+
* 1. `paginated-layout-engine.ts` threads a real
|
|
645
|
+
* `Map<RunId, ResolvedRunFormatting>` into both
|
|
646
|
+
* `measureLineFragments` call sites via the new
|
|
647
|
+
* `buildRunFormattingMap(block)` helper in
|
|
648
|
+
* `resolved-formatting-state.ts`. The empirical backend still
|
|
649
|
+
* ignores `runs` (paragraph-level metrics suffice — same
|
|
650
|
+
* numerical output), but the canvas backend now reads
|
|
651
|
+
* `runs.get("${blockId}:${segmentId}")` for per-run font
|
|
652
|
+
* metrics so paragraphs with mixed inline fonts / sizes /
|
|
653
|
+
* weights produce accurate canvas-measured line counts.
|
|
654
|
+
* 2. `measurement-backend-empirical.ts` + `measurement-backend-
|
|
655
|
+
* canvas.ts` `measureLineFragments` now delegate image-segment
|
|
656
|
+
* line-displacement to their own `measureInlineObject` method
|
|
657
|
+
* instead of inlining `display === "floating" ? 2 : 1`. Zero
|
|
658
|
+
* numerical change; the provider method is now live inside
|
|
659
|
+
* each backend, so future work can specialize displacement
|
|
660
|
+
* math (e.g., canvas-backend ceil(heightTwips/lineHeight))
|
|
661
|
+
* without touching the line-fragments inner loop.
|
|
662
|
+
* 3. `layout-measurement-provider.ts` docstring clarifies that
|
|
663
|
+
* `measureTableBlock` is a coarse standalone helper and
|
|
664
|
+
* production table measurement goes through
|
|
665
|
+
* `src/runtime/layout/table-row-split.ts::measureTableRowHeights`
|
|
666
|
+
* (which already threads this provider through for per-cell
|
|
667
|
+
* paragraph measurement).
|
|
668
|
+
*
|
|
669
|
+
* Persisted envelopes from v44 invalidate because the runs-map
|
|
670
|
+
* input to canvas `measureLineFragments` and the backend
|
|
671
|
+
* dispatch topology changed shape. Empirical-backend numerical
|
|
672
|
+
* output is identical.
|
|
224
673
|
*/
|
|
225
|
-
export const LAYOUT_ENGINE_VERSION =
|
|
674
|
+
export const LAYOUT_ENGINE_VERSION = 47 as const;
|
|
226
675
|
|
|
227
676
|
/**
|
|
228
677
|
* Serialization schema version for the LayCache payload (the cache envelope
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 04 — `LayoutFacet` type surface.
|
|
3
|
+
*
|
|
4
|
+
* Per `docs/architecture/04-layout-semantics.md` and refactor plan Slice 2,
|
|
5
|
+
* `LayoutFacet` is the refactor-era structural name for the semantic layout
|
|
6
|
+
* surface consumers type against. The factory lives at
|
|
7
|
+
* `createLayoutFacet` in `./public-facet.ts`; the interface itself continues
|
|
8
|
+
* to be declared there as `WordReviewEditorLayoutFacet` — the long-standing
|
|
9
|
+
* public-API name — and `LayoutFacet` is a type alias.
|
|
10
|
+
*
|
|
11
|
+
* Why alias rather than relocate:
|
|
12
|
+
* - `WordReviewEditorLayoutFacet` is part of the package's public type
|
|
13
|
+
* surface and is imported by 49 sites plus the consumer-facing public-API
|
|
14
|
+
* reference. Relocating the declaration would churn all of them with no
|
|
15
|
+
* behavioral gain.
|
|
16
|
+
* - Declaring `LayoutFacet` as an alias at a stable import path gives
|
|
17
|
+
* consumers (runtime API, stateless services, debug inspectors, tests)
|
|
18
|
+
* a single short name to depend on during the refactor, independent of
|
|
19
|
+
* the public type that continues to anchor the public API.
|
|
20
|
+
*
|
|
21
|
+
* Consumers imported `WordReviewEditorLayoutFacet` from `./public-facet.ts`
|
|
22
|
+
* before Slice 2; they may switch to `LayoutFacet` from
|
|
23
|
+
* `./layout-facet-types.ts` at their own cadence. Both names resolve to
|
|
24
|
+
* the identical interface and remain assignment-compatible in both
|
|
25
|
+
* directions.
|
|
26
|
+
*
|
|
27
|
+
* Associated read-model types referenced in facet signatures are
|
|
28
|
+
* re-exported here so consumers can pull the whole type surface from one
|
|
29
|
+
* module.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export type {
|
|
33
|
+
// Facet surface --------------------------------------------------------
|
|
34
|
+
WordReviewEditorLayoutFacet as LayoutFacet,
|
|
35
|
+
WordReviewEditorLayoutFacet,
|
|
36
|
+
|
|
37
|
+
// Read-model types ----------------------------------------------------
|
|
38
|
+
PublicPageNode,
|
|
39
|
+
PublicPageRegions,
|
|
40
|
+
PublicPageRegion,
|
|
41
|
+
PublicRegionBlock,
|
|
42
|
+
PublicRegionKind,
|
|
43
|
+
PublicBlockFragment,
|
|
44
|
+
PublicLineBox,
|
|
45
|
+
PublicNoteAllocation,
|
|
46
|
+
PublicPageAnchor,
|
|
47
|
+
PublicPageSpan,
|
|
48
|
+
PublicSectionNode,
|
|
49
|
+
PublicResolvedPageStories,
|
|
50
|
+
PublicResolvedParagraphFormatting,
|
|
51
|
+
PublicResolvedRunFormatting,
|
|
52
|
+
PublicBlockMeasurement,
|
|
53
|
+
PublicMeasurementFidelity,
|
|
54
|
+
PublicFieldDirtinessReport,
|
|
55
|
+
|
|
56
|
+
// Events + invalidation ----------------------------------------------
|
|
57
|
+
LayoutFacetEvent,
|
|
58
|
+
LayoutFacetInvalidationReason,
|
|
59
|
+
RenderZoomSummary,
|
|
60
|
+
} from "./public-facet.ts";
|
|
@@ -74,6 +74,19 @@ export interface MeasuredTableBlock {
|
|
|
74
74
|
rowHeights: number[];
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Task 3 (2026-04-23) note on `measureTableBlock`: the production
|
|
79
|
+
* table-measurement path is `src/runtime/layout/table-row-split.ts
|
|
80
|
+
* ::measureTableRowHeights`, which threads this provider through for
|
|
81
|
+
* per-cell paragraph measurement and integrates with `findTableRowSplit`
|
|
82
|
+
* for pagination. `measureTableBlock` on this contract remains a
|
|
83
|
+
* coarse standalone helper (used when a table's height is needed
|
|
84
|
+
* without row-split context). Both empirical and canvas backends
|
|
85
|
+
* implement it with the same lightweight estimation; consumers that
|
|
86
|
+
* need accurate per-cell measurement should call `measureTableRowHeights`
|
|
87
|
+
* directly.
|
|
88
|
+
*/
|
|
89
|
+
|
|
77
90
|
export interface LayoutMeasurementProvider {
|
|
78
91
|
readonly fidelity: MeasurementFidelity;
|
|
79
92
|
/**
|
|
@@ -214,11 +214,23 @@ export function createCanvasBackend(
|
|
|
214
214
|
currentLineWidth = 0;
|
|
215
215
|
currentCapacity = subsequentLineWidth;
|
|
216
216
|
break;
|
|
217
|
-
case "image":
|
|
218
|
-
|
|
217
|
+
case "image": {
|
|
218
|
+
// Route through this backend's own `measureInlineObject` so
|
|
219
|
+
// the provider contract is live inside the canvas backend
|
|
220
|
+
// (Task 3, 2026-04-23). Intrinsic dimensions are not carried
|
|
221
|
+
// on the surface segment here; backends that later want
|
|
222
|
+
// glyph-height-aware displacement can resolve from the
|
|
223
|
+
// segment's `anchor.extent` at the caller.
|
|
224
|
+
const measured = measureInlineObject({
|
|
225
|
+
widthTwips: 0,
|
|
226
|
+
heightTwips: 0,
|
|
227
|
+
display: segment.display === "floating" ? "floating" : "inline",
|
|
228
|
+
});
|
|
229
|
+
lineCount += Math.max(1, measured.displacedLineCount);
|
|
219
230
|
currentLineWidth = 0;
|
|
220
231
|
currentCapacity = subsequentLineWidth;
|
|
221
232
|
break;
|
|
233
|
+
}
|
|
222
234
|
case "note_ref":
|
|
223
235
|
case "opaque_inline":
|
|
224
236
|
// Treat as a single narrow character.
|
|
@@ -31,24 +31,37 @@ const TABLE_ROW_PADDING_TWIPS = 120;
|
|
|
31
31
|
|
|
32
32
|
export function createEmpiricalBackend(): LayoutMeasurementProvider {
|
|
33
33
|
const fidelity: MeasurementFidelity = "empirical";
|
|
34
|
-
|
|
34
|
+
// `measureLineFragments` dispatches through the backend object's own
|
|
35
|
+
// `measureInlineObject` method at call time (not via closure capture)
|
|
36
|
+
// so consumers can swap the inline measurement strategy after
|
|
37
|
+
// construction — Task 3 (2026-04-23) routed image segments through
|
|
38
|
+
// the provider contract instead of hardcoded displacement math.
|
|
39
|
+
const backend: LayoutMeasurementProvider = {
|
|
35
40
|
get fidelity() {
|
|
36
41
|
return fidelity;
|
|
37
42
|
},
|
|
38
43
|
whenReady() {
|
|
39
44
|
return Promise.resolve();
|
|
40
45
|
},
|
|
41
|
-
measureLineFragments
|
|
46
|
+
measureLineFragments(input) {
|
|
47
|
+
return measureLineFragments(input, (objectInput) =>
|
|
48
|
+
backend.measureInlineObject(objectInput),
|
|
49
|
+
);
|
|
50
|
+
},
|
|
42
51
|
measureInlineObject,
|
|
43
52
|
measureTableBlock,
|
|
44
53
|
invalidateCache() {
|
|
45
54
|
/* no cache in empirical mode */
|
|
46
55
|
},
|
|
47
56
|
};
|
|
57
|
+
return backend;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
function measureLineFragments(
|
|
51
61
|
input: MeasureLineFragmentsInput,
|
|
62
|
+
inlineObjectMeasurer: (
|
|
63
|
+
objectInput: MeasureInlineObjectInput,
|
|
64
|
+
) => MeasuredInlineObject,
|
|
52
65
|
): MeasuredLineFragments {
|
|
53
66
|
const { block, formatting, columnWidth } = input;
|
|
54
67
|
const firstLineWidth = resolveTextWidth(formatting, columnWidth, true);
|
|
@@ -93,11 +106,17 @@ function measureLineFragments(
|
|
|
93
106
|
currentLineChars = 0;
|
|
94
107
|
currentLineCapacity = subsequentLineCapacity;
|
|
95
108
|
break;
|
|
96
|
-
case "image":
|
|
97
|
-
|
|
109
|
+
case "image": {
|
|
110
|
+
const measured = inlineObjectMeasurer({
|
|
111
|
+
widthTwips: 0,
|
|
112
|
+
heightTwips: 0,
|
|
113
|
+
display: segment.display === "floating" ? "floating" : "inline",
|
|
114
|
+
});
|
|
115
|
+
lineCount += Math.max(1, measured.displacedLineCount);
|
|
98
116
|
currentLineChars = 0;
|
|
99
117
|
currentLineCapacity = subsequentLineCapacity;
|
|
100
118
|
break;
|
|
119
|
+
}
|
|
101
120
|
case "note_ref":
|
|
102
121
|
currentLineChars += 1;
|
|
103
122
|
if (currentLineChars > currentLineCapacity) {
|