From 9c355f1ea3f8ba4989043c103a2ef626d904a2ef Mon Sep 17 00:00:00 2001 From: Charles Click Date: Tue, 16 Jun 2026 11:37:15 -0400 Subject: [PATCH] Fix: Fix wrapping logic in panels so that content always fits within the panel width. Also add two test cases `AllLinesFitInsideWidth` and `AllLinesFitInsideWidthWithMismatchedWrap`. The first one simply tests that given a large line of text and a small panel width the lines fit within the panel width. The second one tests that passing a larger WrapWidth than the panel width doesn't produce oversized lines. --- internal/templates/panel.go | 9 ++++++--- internal/templates/panel_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/internal/templates/panel.go b/internal/templates/panel.go index 6cf24787f..1a2a7a91d 100644 --- a/internal/templates/panel.go +++ b/internal/templates/panel.go @@ -941,12 +941,15 @@ func renderSingleColumnLines(p *Panel, row PanelRow, inner int, isFirst, isLast // WrapWidth < 0 disables wrapping entirely for this row. // WrapWidth > 0 uses that as the explicit wrap width. // WrapWidth == 0 falls back to the panel's target width. + // If your wrap is greater than visible width it is adjusted. effectiveWrap := row.WrapWidth + visibleWidth := inner - lw - 1 if effectiveWrap == 0 && p.width > 0 { - availForValue := inner - lw - 1 - if availForValue > 0 { - effectiveWrap = availForValue + if visibleWidth > 0 { + effectiveWrap = visibleWidth } + } else if effectiveWrap > visibleWidth { + effectiveWrap = visibleWidth } var chunks []string diff --git a/internal/templates/panel_test.go b/internal/templates/panel_test.go index b67a4aec9..8e6629045 100644 --- a/internal/templates/panel_test.go +++ b/internal/templates/panel_test.go @@ -198,6 +198,30 @@ func TestRenderPanel_AllLinesEqualVisualWidth(t *testing.T) { } } +func TestRenderPanel_AllLinesFitInsideWidth(t *testing.T) { + p := makePanel("x", "X", 20, borderFull, []PanelRow{ + {FullLabel: "Short:", ShortLabel: "S:", Value: "This is a short description."}, + {FullLabel: "HowItBe:", ShortLabel: "HIB:", Value: "This is an extremely long line of text. It is unnecessarily long. There's no reason for it to be this long, but we want to make sure wrapping is working correctly, so I will continue to make this line longer as necessary to get back good testing data."}, + }) + got := renderPanel(p) + for i, line := range got { + assert.LessOrEqual(t, panelVisualWidth(line), p.width, "line %d is longer than panel width", i) + } +} + +func TestRenderPanel_AllLinesFitInsideWidthWithMismatchedWrap(t *testing.T) { + p := makePanel("x", "X", 20, borderFull, []PanelRow{ + {FullLabel: "Short:", ShortLabel: "S:", Value: "This is a short description."}, + {FullLabel: "HowItBe:", ShortLabel: "HIB:", WrapWidth: 50, Value: "This is an extremely long line of text. It is unnecessarily long. There's no reason for it to be this long, but we want to make sure wrapping is working correctly, so I will continue to make this line longer as necessary to get back good testing data."}, + {FullLabel: "HowItBe:", ShortLabel: "HIB:", WrapWidth: 15, Value: "This is an extremely long line of text. It is unnecessarily long. There's no reason for it to be this long, but we want to make sure wrapping is working correctly, so I will continue to make this line longer as necessary to get back good testing data."}, + {FullLabel: "HowItBe:", ShortLabel: "HIB:", WrapWidth: 20, Value: "This is an extremely long line of text. It is unnecessarily long. There's no reason for it to be this long, but we want to make sure wrapping is working correctly, so I will continue to make this line longer as necessary to get back good testing data."}, + }) + got := renderPanel(p) + for i, line := range got { + assert.LessOrEqual(t, panelVisualWidth(line), p.width, "line %d is longer than panel width", i) + } +} + func TestRenderPanel_AnsiTagsDoNotAffectWidth(t *testing.T) { p := makePanel("x", "X", 19, borderFull, []PanelRow{ {FullLabel: `Name:`, ShortLabel: "N:", Value: `Alice`},