Skip to content

fix(markdown-compose): measure table cells by display width#2477

Merged
sinelaw merged 1 commit into
masterfrom
fix/markdown-compose-emoji-width
Jun 23, 2026
Merged

fix(markdown-compose): measure table cells by display width#2477
sinelaw merged 1 commit into
masterfrom
fix/markdown-compose-emoji-width

Conversation

@sinelaw

@sinelaw sinelaw commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

In Markdown compose/preview mode, the right border of a rendered table is drawn one column too far right on any row whose last cell ends in a 2-cell-wide glyph (emoji such as , CJK, …). Because the current (cursor) line is rendered raw and stays correctly aligned, the border appears to flicker/pop as the cursor moves over each emoji row. Rows without a wide trailing glyph are unaffected. Fixes #2475.

Root cause

The markdown_compose plugin measured cell text with JS String.length (UTF-16 code units), so (U+2705) counted as 1 column while the renderer lays it out as 2. Non-cursor rows were therefore padded one column too wide, pushing their right past the ┌┐└┘├┼┤ box frame.

Fix

Add a small displayWidth() helper backed by editor.stringWidth — the plugin API added in #2401, itself backed by fresh_core::display_width — so the plugin measures cells exactly as the editor lays out terminal cells. Routed the four width-measuring sites through it:

  • column max-width in processTableAlignment
  • cell padding width
  • the truncation overflow check
  • the wrapped-cell padding
// Terminal column width (wide glyphs = 2), matching the renderer's layout.
function displayWidth(text: string): number {
  return editor.stringWidth(text);
}

Verification

Reproduced and verified in tmux (110×30, xterm-256color) with the example file from #2475:

  • Before: emoji rows draw their right border at column 45 (protruding) except the cursor's row at 44.
  • After: every emoji row sits at column 44 — flush with the box — at all cursor positions (Ln1–Ln18); no misalignment, no pop. The no-emoji control table is unchanged.

Plugin type checks pass (plugins/check-types.sh).

Related

🤖 Generated with Claude Code

Table column sizing and cell padding measured text with JS `String.length`
(UTF-16 code units), so a trailing 2-cell-wide glyph (emoji such as `✅`, CJK,
…) counted as 1 column while it renders as 2. Non-cursor rows were padded one
column too wide, pushing their right border past the box frame; the cursor's
own row (rendered raw) stayed correct, so the border appeared to flicker as the
cursor moved over it.

Route the four width-measuring sites through a `displayWidth()` helper backed
by `editor.stringWidth` (added in #2401, itself backed by
`fresh_core::display_width`), so the plugin measures cells exactly as the
renderer lays them out.

Fixes #2475

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sinelaw sinelaw merged commit a38e1e1 into master Jun 23, 2026
8 checks passed
@sinelaw sinelaw deleted the fix/markdown-compose-emoji-width branch June 23, 2026 19:58
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.

Markdown preview: table right border flickers/misaligns while scrolling on rows ending in an emoji

1 participant