Skip to content

fix(box): respect terminal widths for Unicode text - #126

Merged
lloydrichards merged 1 commit into
fix/ansi-aligned-clippingfrom
codex/fix-unicode-terminal-width
Sep 6, 2026
Merged

lloydrichards merged 1 commit into
fix/ansi-aligned-clippingfrom
codex/fix-unicode-terminal-width

Conversation

@lloydrichards

Copy link
Copy Markdown
Owner

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

  • Slice and pad strings by terminal columns without splitting grapheme clusters.
  • Apply the shared width logic to plain rendering, cropping, truncation, maximum widths, paragraph flow, and resize helpers.
  • Preserve ANSI style boundaries and resets while clipping wide text.
  • Add public regression coverage for CJK, joined emoji, combining marks, alignment bias, ANSI output, paragraphs, cropping, and resizing.
  • Add a patch changeset for the corrected published behavior.

How to test

  • bun run --cwd packages/effect-boxes test — 545 tests passed.
  • bun run type-check
  • bun run lint
  • bun run docs:check
  • bun 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

  • Gatekeeping: Check correctness, tests, quality, and design before merge.
  • Knowledge sharing: Quick intent and implementation review; light feedback is enough.
  • Pair session: Review the remaining decisions together.

Stack dependencies: #112, #117, and #121.

@vercel

vercel Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
effect-boxes-docs Ready Ready Preview Sep 6, 2026 8:24am UTC

@changeset-bot

changeset-bot Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3134b9c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
effect-boxes Patch

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Comment on lines +474 to +476
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);
@lloydrichards
lloydrichards force-pushed the codex/fix-unicode-terminal-width branch from 2f3f7bd to 3134b9c Compare September 6, 2026 08:23
@lloydrichards
lloydrichards merged commit cd18f2a into main Sep 6, 2026
3 checks passed
@lloydrichards
lloydrichards deleted the codex/fix-unicode-terminal-width branch September 6, 2026 08:34
@github-actions github-actions Bot mentioned this pull request Sep 6, 2026

This branch was successfully deployed

1 active deployment
Preview — 3134b9c4 Deployed Sep 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(width): Unicode output exceeds declared column widths

2 participants