Fix release note wrapping
- commit
- 1c2b2f0686f8b7da0e82d9e4320e035561ab43b4
- author
- patriceckhart · · 2026-07-30 05:34 UTC
- parent
- 2de7f3f
- signature
- unsigned
2 files · +32 -12
M packages/agent/modes/changelog_dialog.go +6 -12
| @@ -88,16 +88,12 @@ func (d *changelogDialog) Render(th tui.Theme, width int) []string { | |||
| 88 | 88 | if strings.HasPrefix(l, "\x00H:") { | |
| 89 | 89 | // Heading: render in accent color, bold. | |
| 90 | 90 | heading := strings.TrimPrefix(l, "\x00H:") | |
| 91 | - | bodyLines = append(bodyLines, th.FG256(th.Accent, tui.Bold(heading))) | |
| 91 | + | styled := th.FG256(th.Accent, tui.Bold(heading)) | |
| 92 | + | bodyLines = append(bodyLines, wrapDialogTextRows(styled, width)...) | |
| 92 | 93 | } else { | |
| 93 | - | // Regular line: render through markdown for bullet points etc. | |
| 94 | - | rendered := tui.RenderMarkdown(l, th, width-4) | |
| 95 | - | for _, rl := range strings.Split(rendered, "\n") { | |
| 96 | - | if len(rl) > 0 && rl[0] == tui.FlushLeftSentinel { | |
| 97 | - | rl = rl[1:] | |
| 98 | - | } | |
| 99 | - | bodyLines = append(bodyLines, rl) | |
| 100 | - | } | |
| 94 | + | // Regular line: render and wrap through the shared dialog | |
| 95 | + | // markdown path so ANSI styling does not affect display width. | |
| 96 | + | bodyLines = append(bodyLines, renderDialogMarkdownRows(l, th, width)...) | |
| 101 | 97 | } | |
| 102 | 98 | } | |
| 103 | 99 | ||
| @@ -112,9 +108,7 @@ func (d *changelogDialog) Render(th tui.Theme, width int) []string { | |||
| 112 | 108 | if end > len(bodyLines) { | |
| 113 | 109 | end = len(bodyLines) | |
| 114 | 110 | } | |
| 115 | - | for _, line := range bodyLines[d.scroll:end] { | |
| 116 | - | out = append(out, " "+line) | |
| 117 | - | } | |
| 111 | + | out = append(out, bodyLines[d.scroll:end]...) | |
| 118 | 112 | if end < len(bodyLines) { | |
| 119 | 113 | out = append(out, " "+th.FG256(th.Muted, fmt.Sprintf("\u2193 %d more lines (down/pgdn)", len(bodyLines)-end))) | |
| 120 | 114 | } | |
| @@ -88,16 +88,12 @@ func (d *changelogDialog) Render(th tui.Theme, width int) []string { | |||||
| 88 | if strings.HasPrefix(l, "\x00H:") { | 88 | if strings.HasPrefix(l, "\x00H:") { | ||
| 89 | // Heading: render in accent color, bold. | 89 | // Heading: render in accent color, bold. | ||
| 90 | heading := strings.TrimPrefix(l, "\x00H:") | 90 | heading := strings.TrimPrefix(l, "\x00H:") | ||
| 91 | - | bodyLines = append(bodyLines, th.FG256(th.Accent, tui.Bold(heading))) | 91 | + | styled := th.FG256(th.Accent, tui.Bold(heading)) |
| 92 | + | bodyLines = append(bodyLines, wrapDialogTextRows(styled, width)...) | |||
| 92 | } else { | 93 | } else { | ||
| 93 | - | // Regular line: render through markdown for bullet points etc. | 94 | + | // Regular line: render and wrap through the shared dialog |
| 94 | - | rendered := tui.RenderMarkdown(l, th, width-4) | 95 | + | // markdown path so ANSI styling does not affect display width. |
| 95 | - | for _, rl := range strings.Split(rendered, "\n") { | 96 | + | bodyLines = append(bodyLines, renderDialogMarkdownRows(l, th, width)...) |
| 96 | - | if len(rl) > 0 && rl[0] == tui.FlushLeftSentinel { | |||
| 97 | - | rl = rl[1:] | |||
| 98 | - | } | |||
| 99 | - | bodyLines = append(bodyLines, rl) | |||
| 100 | - | } | |||
| 101 | } | 97 | } | ||
| 102 | } | 98 | } | ||
| 103 | 99 | ||||
| @@ -112,9 +108,7 @@ func (d *changelogDialog) Render(th tui.Theme, width int) []string { | |||||
| 112 | if end > len(bodyLines) { | 108 | if end > len(bodyLines) { | ||
| 113 | end = len(bodyLines) | 109 | end = len(bodyLines) | ||
| 114 | } | 110 | } | ||
| 115 | - | for _, line := range bodyLines[d.scroll:end] { | 111 | + | out = append(out, bodyLines[d.scroll:end]...) |
| 116 | - | out = append(out, " "+line) | |||
| 117 | - | } | |||
| 118 | if end < len(bodyLines) { | 112 | if end < len(bodyLines) { | ||
| 119 | out = append(out, " "+th.FG256(th.Muted, fmt.Sprintf("\u2193 %d more lines (down/pgdn)", len(bodyLines)-end))) | 113 | out = append(out, " "+th.FG256(th.Muted, fmt.Sprintf("\u2193 %d more lines (down/pgdn)", len(bodyLines)-end))) | ||
| 120 | } | 114 | } | ||
A packages/agent/modes/changelog_dialog_test.go +26 -0
| @@ -0,0 +1,26 @@ | |||
| 1 | + | package modes | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "strings" | |
| 5 | + | "testing" | |
| 6 | + | ||
| 7 | + | "github.com/patriceckhart/zot/packages/tui" | |
| 8 | + | ) | |
| 9 | + | ||
| 10 | + | func TestChangelogDialogWrapsReleaseNotes(t *testing.T) { | |
| 11 | + | const width = 64 | |
| 12 | + | body := "\x00H:Other improvements for terminals with constrained display widths\n" + | |
| 13 | + | "- Add MiniMax-M3 to direct MiniMax global and China catalogs with compatibility for narrow terminal layouts" | |
| 14 | + | d := newChangelogDialog() | |
| 15 | + | d.Open("0.3.25", "", body) | |
| 16 | + | ||
| 17 | + | rows := d.Render(tui.Theme{}, width) | |
| 18 | + | assertRowsFitWidth(t, rows, width) | |
| 19 | + | ||
| 20 | + | plain := strings.Join(rows, "\n") | |
| 21 | + | for _, word := range strings.Fields(strings.ReplaceAll(body, "\x00H:", "")) { | |
| 22 | + | if !strings.Contains(plain, word) { | |
| 23 | + | t.Fatalf("wrapped release notes lost word %q:\n%s", word, plain) | |
| 24 | + | } | |
| 25 | + | } | |
| 26 | + | } | |
| @@ -0,0 +1,26 @@ | |||||
| 1 | + | package modes | |||
| 2 | + | ||||
| 3 | + | import ( | |||
| 4 | + | "strings" | |||
| 5 | + | "testing" | |||
| 6 | + | ||||
| 7 | + | "github.com/patriceckhart/zot/packages/tui" | |||
| 8 | + | ) | |||
| 9 | + | ||||
| 10 | + | func TestChangelogDialogWrapsReleaseNotes(t *testing.T) { | |||
| 11 | + | const width = 64 | |||
| 12 | + | body := "\x00H:Other improvements for terminals with constrained display widths\n" + | |||
| 13 | + | "- Add MiniMax-M3 to direct MiniMax global and China catalogs with compatibility for narrow terminal layouts" | |||
| 14 | + | d := newChangelogDialog() | |||
| 15 | + | d.Open("0.3.25", "", body) | |||
| 16 | + | ||||
| 17 | + | rows := d.Render(tui.Theme{}, width) | |||
| 18 | + | assertRowsFitWidth(t, rows, width) | |||
| 19 | + | ||||
| 20 | + | plain := strings.Join(rows, "\n") | |||
| 21 | + | for _, word := range strings.Fields(strings.ReplaceAll(body, "\x00H:", "")) { | |||
| 22 | + | if !strings.Contains(plain, word) { | |||
| 23 | + | t.Fatalf("wrapped release notes lost word %q:\n%s", word, plain) | |||
| 24 | + | } | |||
| 25 | + | } | |||
| 26 | + | } | |||