From a690dce6151a42edc27d18255afdb2a605fe1933 Mon Sep 17 00:00:00 2001 From: wheelibin Date: Thu, 4 Jun 2026 14:52:26 +0100 Subject: [PATCH] fix: handle hyphen wrapping bug --- table/row.go | 4 ++++ table/view_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/table/row.go b/table/row.go index 0fa4129..f672aba 100644 --- a/table/row.go +++ b/table/row.go @@ -137,6 +137,10 @@ func (m Model) renderRowColumnData(row Row, column Column, rowStyle lipgloss.Sty if m.multiline { str = ansi.Wordwrap(str, contentWidth, "") + // a bug in Wordwrap means when hyphens are used as a breakpoint, the wrap is done AFTER the hyphen + // resulting in a line that exceeds the column width + // Hardwrap as a seconds step avoids this + str = ansi.Hardwrap(str, contentWidth, false) cellStyle = cellStyle.Align(lipgloss.Top) } else { str = limitStr(str, contentWidth) diff --git a/table/view_test.go b/table/view_test.go index eaf85b4..20ca47c 100644 --- a/table/view_test.go +++ b/table/view_test.go @@ -1779,6 +1779,30 @@ func TestMultilineDisabledExplicite(t *testing.T) { assert.Equal(t, expectedTable, rendered) } +func TestMultilineHyphenDoesNotOverflowColumnWidth(t *testing.T) { + // Wordwrap treats hyphens as break points and places the hyphen at the END + // of the wrapped line (e.g. "abcdefgh-" = 9 chars for a width-8 column). + // The Hardwrap pass that follows must clip that back to the column width so + // the cell never overflows. + model := New([]Column{ + NewColumn("content", "Content", 8), + }). + WithRows([]Row{ + NewRow(RowData{"content": "abcdefgh-tail"}), + }). + WithMultiline(true) + + const expected = `┏━━━━━━━━┓ +┃ Content┃ +┣━━━━━━━━┫ +┃abcdefgh┃ +┃- ┃ +┃tail ┃ +┗━━━━━━━━┛` + + assert.Equal(t, expected, model.View()) +} + func TestRowBorder3x3(t *testing.T) { model := New([]Column{ NewColumn("1", "1", 4),