From 727d39305d48560eb0c47f8bad2b15246f5731bc Mon Sep 17 00:00:00 2001 From: bashbunni <15822994+bashbunni@users.noreply.github.com> Date: Thu, 9 Jan 2025 08:00:28 -0800 Subject: [PATCH] fix!: style size to include borders (#451) * fix(width): include border in width * fix: include borders in style block size * fix(examples): base col widths on page width * fixup! merge v2-exp * docs(examples): correct official rom for bulbasaur evolutions --- examples/layout/main.go | 8 +++--- examples/table/pokemon/main.go | 6 ++-- style.go | 7 +++++ style_test.go | 50 ++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/examples/layout/main.go b/examples/layout/main.go index 73dc01bc..71cdd362 100644 --- a/examples/layout/main.go +++ b/examples/layout/main.go @@ -142,9 +142,9 @@ func main() { list = lipgloss.NewStyle(). Border(lipgloss.NormalBorder(), false, true, false, false). BorderForeground(subtle). - MarginRight(2). + MarginRight(1). Height(8). - Width(columnWidth + 1) + Width(width / 3) listHeader = lipgloss.NewStyle(). BorderStyle(lipgloss.NormalBorder()). @@ -308,7 +308,7 @@ func main() { listItem("Pomelo"), ), ), - list.Width(columnWidth).Render( + list.Render( lipgloss.JoinVertical(lipgloss.Left, listHeader("Actual Lip Gloss Vendors"), listItem("Glossier"), @@ -320,7 +320,7 @@ func main() { ), ) - doc.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, lists, colors)) + doc.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, lists, lipgloss.NewStyle().MarginLeft(1).Render(colors))) // Marmalade history. { diff --git a/examples/table/pokemon/main.go b/examples/table/pokemon/main.go index be7fb08c..e7bd9f46 100644 --- a/examples/table/pokemon/main.go +++ b/examples/table/pokemon/main.go @@ -38,9 +38,9 @@ func main() { headers := []string{"#", "Name", "Type 1", "Type 2", "Japanese", "Official Rom."} data := [][]string{ - {"1", "Bulbasaur", "Grass", "Poison", "フシギダネ", "Bulbasaur"}, - {"2", "Ivysaur", "Grass", "Poison", "フシギソウ", "Ivysaur"}, - {"3", "Venusaur", "Grass", "Poison", "フシギバナ", "Venusaur"}, + {"1", "Bulbasaur", "Grass", "Poison", "フシギダネ", "Fushigidane"}, + {"2", "Ivysaur", "Grass", "Poison", "フシギソウ", "Fushigisou"}, + {"3", "Venusaur", "Grass", "Poison", "フシギバナ", "Fushigibana"}, {"4", "Charmander", "Fire", "", "ヒトカゲ", "Hitokage"}, {"5", "Charmeleon", "Fire", "", "リザード", "Lizardo"}, {"6", "Charizard", "Fire", "Flying", "リザードン", "Lizardon"}, diff --git a/style.go b/style.go index 0f342cd8..033b99a6 100644 --- a/style.go +++ b/style.go @@ -252,6 +252,9 @@ func (s Style) Render(strs ...string) string { bottomPadding = s.getAsInt(paddingBottomKey) leftPadding = s.getAsInt(paddingLeftKey) + horizontalBorderSize = s.GetHorizontalBorderSize() + verticalBorderSize = s.GetVerticalBorderSize() + colorWhitespace = s.getAsBool(colorWhitespaceKey, true) inline = s.getAsBool(inlineKey, false) maxWidth = s.getAsInt(maxWidthKey) @@ -342,6 +345,10 @@ func (s Style) Render(strs ...string) string { str = strings.ReplaceAll(str, "\n", "") } + // Include borders in block size. + width -= horizontalBorderSize + height -= verticalBorderSize + // Word wrap if !inline && width > 0 { wrapAt := width - leftPadding - rightPadding diff --git a/style_test.go b/style_test.go index c660b907..7104b453 100644 --- a/style_test.go +++ b/style_test.go @@ -512,3 +512,53 @@ func TestCarriageReturnInRender(t *testing.T) { t.Fatalf("got(string):\n%s\nwant(string):\n%s", got, want) } } + +func TestWidth(t *testing.T) { + tests := []struct { + name string + style Style + }{ + {"width with borders", NewStyle().Padding(0, 2).Border(NormalBorder(), true)}, + {"width no borders", NewStyle().Padding(0, 2)}, + {"width unset borders", NewStyle().Padding(0, 2).Border(NormalBorder(), true).BorderLeft(false).BorderRight(false)}, + {"width single-sided border", NewStyle().Padding(0, 2).Border(NormalBorder(), true).UnsetBorderBottom().UnsetBorderTop().UnsetBorderRight()}, + } + { + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + content := "The Romans learned from the Greeks that quinces slowly cooked with honey would “set” when cool. The Apicius gives a recipe for preserving whole quinces, stems and leaves attached, in a bath of honey diluted with defrutum: Roman marmalade. Preserves of quince and lemon appear (along with rose, apple, plum and pear) in the Book of ceremonies of the Byzantine Emperor Constantine VII Porphyrogennetos." + contentWidth := 80 - tc.style.GetHorizontalFrameSize() + rendered := tc.style.Width(contentWidth).Render(content) + if Width(rendered) != contentWidth { + t.Log("\n" + rendered) + t.Fatalf("got: %d\n, want: %d", Width(rendered), contentWidth) + } + }) + } + } +} + +func TestHeight(t *testing.T) { + tests := []struct { + name string + style Style + }{ + {"height with borders", NewStyle().Width(80).Padding(0, 2).Border(NormalBorder(), true)}, + {"height no borders", NewStyle().Width(80).Padding(0, 2)}, + {"height unset borders", NewStyle().Width(80).Padding(0, 2).Border(NormalBorder(), true).BorderBottom(false).BorderTop(false)}, + {"height single-sided border", NewStyle().Width(80).Padding(0, 2).Border(NormalBorder(), true).UnsetBorderLeft().UnsetBorderBottom().UnsetBorderRight()}, + } + { + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + content := "The Romans learned from the Greeks that quinces slowly cooked with honey would “set” when cool. The Apicius gives a recipe for preserving whole quinces, stems and leaves attached, in a bath of honey diluted with defrutum: Roman marmalade. Preserves of quince and lemon appear (along with rose, apple, plum and pear) in the Book of ceremonies of the Byzantine Emperor Constantine VII Porphyrogennetos." + contentHeight := 20 - tc.style.GetVerticalFrameSize() + rendered := tc.style.Height(contentHeight).Render(content) + if Height(rendered) != contentHeight { + t.Log("\n" + rendered) + t.Fatalf("got: %d\n, want: %d", Height(rendered), contentHeight) + } + }) + } + } +}