From 8ce94eca5bfdc2c2526ca09cc176da05c99a06aa Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Thu, 8 Jun 2023 09:49:05 -0400 Subject: [PATCH] Tolerate leading zeros in numeric color parameters --- ansi.go | 18 ++++++++++++++---- ansi_test.go | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/ansi.go b/ansi.go index ddfdb94..7a2ae7a 100644 --- a/ansi.go +++ b/ansi.go @@ -2,9 +2,10 @@ package ansi import ( "fmt" - "github.com/rivo/uniseg" "strconv" "strings" + + "github.com/rivo/uniseg" ) // TextStyle is a type representing the @@ -321,6 +322,7 @@ func Parse(input string, options ...ParseOption) ([]*StyledText, error) { skip-- continue } + param = stripLeadingZeros(param) switch param { case "0", "": colourMap = ColourMap["Regular"] @@ -369,9 +371,10 @@ func Parse(input string, options ...ParseOption) ([]*StyledText, error) { return nil, invalid } // 256 colours - if params[index+1] == "5" { + param1 := stripLeadingZeros(params[index+1]) + if param1 == "5" { skip = 2 - colIndexText := params[index+2] + colIndexText := stripLeadingZeros(params[index+2]) colIndex, err := strconv.Atoi(colIndexText) if err != nil { return nil, invalid256ColSequence @@ -391,7 +394,7 @@ func Parse(input string, options ...ParseOption) ([]*StyledText, error) { if len(params)-index < 5 { return nil, invalidTrueColorSequence } - if params[index+1] != "2" { + if param1 != "2" { return nil, invalidTrueColorSequence } var r, g, b uint8 @@ -465,6 +468,13 @@ func Parse(input string, options ...ParseOption) ([]*StyledText, error) { } } +func stripLeadingZeros(s string) string { + if len(s) < 2 { + return s + } + return strings.TrimLeft(s, "0") +} + // HasEscapeCodes tests that input has escape codes. func HasEscapeCodes(input string) bool { return strings.IndexAny(input, "\033[") != -1 diff --git a/ansi_test.go b/ansi_test.go index 113a0cf..cd90267 100644 --- a/ansi_test.go +++ b/ansi_test.go @@ -687,3 +687,25 @@ func TestLength(t *testing.T) { }) } } + +func TestStripLeadingZeros(t *testing.T) { + is2 := is.New(t) + tests := []struct { + name string + input string + want string + }{ + {"Blank", "", ""}, + {"One rune not 0", "4", "4"}, + {"Only 0", "0", "0"}, + {"Multi-digit non-0", "35", "35"}, + {"Two-digit leading 0", "05", "5"}, + {"Three-digit leading 0", "045", "45"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := stripLeadingZeros(tt.input) + is2.Equal(got, tt.want) + }) + } +}