fix(box): respect terminal widths for Unicode text - #126
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 3134b9c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
🟡 Changes recommended
padPreservingAnsi still treats AlignCenter1 and AlignCenter2 identically for odd padding widths, breaking center-bias semantics and risking divergence from the shared width/alignment logic.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR updates effect-boxes’ terminal-width handling so rendered output and width-constrained operations (truncate/crop/maxWidth/paragraph flow/resize) respect true terminal column widths for Unicode graphemes (CJK, emoji, combining sequences), including ANSI-styled output.
Changes:
- Introduces column-aware slicing/padding helpers (
sliceColumns,fitString,alignmentOffset) and applies them across width-sensitive operations. - Updates plain and ANSI rendering paths to clip/pad by terminal columns without splitting graphemes, and adds targeted Unicode/ANSI regression tests.
- Adds a patch changeset documenting the corrected published behavior.
File summaries
| File | Description |
|---|---|
| packages/effect-boxes/tests/unicode-width.test.ts | Adds regression coverage for Unicode width correctness across truncation, maxWidth, crop, alignment bias, ANSI clipping, paragraph flow, and resizing. |
| packages/effect-boxes/tests/box.test.ts | Updates existing emoji alignment expectations to match the corrected column-based behavior. |
| packages/effect-boxes/src/renderer/PlainRenderer.ts | Routes plain line processing through the shared column-fitting logic. |
| packages/effect-boxes/src/internal/width.ts | Adds shared primitives for column slicing and aligned fitting based on terminal width semantics. |
| packages/effect-boxes/src/internal/box.ts | Switches paragraph flow, cropping, truncation, maxWidth, and resize helpers to use column-aware slicing/fitting. |
| packages/effect-boxes/src/internal/ansi.ts | Updates ANSI truncation/aligned truncation to count columns and handle partially visible wide graphemes via blank fill; simplifies padding. |
| .changeset/calm-widths-fit.md | Records a patch release note for the corrected Unicode width handling. |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| case "AlignCenter1": | ||
| case "AlignCenter2": { | ||
| const leftPad = Math.floor( | ||
| (targetVisibleLength - currentVisibleLength) / 2 | ||
| ); | ||
| const rightPad = targetVisibleLength - currentVisibleLength - leftPad; | ||
| return " ".repeat(leftPad) + str + " ".repeat(rightPad); | ||
| } | ||
| case "AlignCenter2": | ||
| return Math.floor(padding / 2); |
a18bf57 to
2f3f7bd
Compare
2f3f7bd to
3134b9c
Compare
Goal/Scope
Keep rendered and constrained terminal text within the column widths reported by
Box, including CJK characters, emoji, and combining graphemes.HTML rendering is intentionally out of scope because browser text layout does not use terminal-cell width semantics.
Description
How to test
bun run --cwd packages/effect-boxes test— 545 tests passed.bun run type-checkbun run lintbun run docs:checkbun run test— package tests and production documentation build passed.The regressions were first run against the previous production behavior and failed on the reported width mismatches.
Review
Stack dependencies: #112, #117, and #121.