Skip to content

Commit

Permalink
chore: drop go-colorful dependency (but it's a great lib)
Browse files Browse the repository at this point in the history
  • Loading branch information
meowgorithm committed Aug 18, 2022
1 parent e8297c4 commit 1fb1fb9
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 16 deletions.
57 changes: 43 additions & 14 deletions color.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package lipgloss

import (
"image/color"
"sync"

"github.com/lucasb-eyer/go-colorful"
"github.com/muesli/termenv"
)

Expand Down Expand Up @@ -144,17 +144,11 @@ func (c Color) color() termenv.Color {
// RGBA returns the RGBA value of this color. This satisfies the Go Color
// interface. Note that on error we return black with 100% opacity, or:
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
//
// This is inline with go-colorful's default behavior.
func (c Color) RGBA() (r, g, b, a uint32) {
cf, err := colorful.Hex(c.value())
if err != nil {
// If we ignore the return behavior and simply return what go-colorful
// give us for the color value we'd be returning exactly this, however
// we're being explicit here for the sake of clarity.
return colorful.Color{}.RGBA()
}
cf := hexToColor(c.value())
return cf.RGBA()
}

Expand Down Expand Up @@ -185,13 +179,48 @@ func (ac AdaptiveColor) color() termenv.Color {
// RGBA returns the RGBA value of this color. This satisfies the Go Color
// interface. Note that on error we return black with 100% opacity, or:
//
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF
// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFF.
//
// This is inline with go-colorful's default behavior.
func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) {
cf, err := colorful.Hex(ac.value())
if err != nil {
return colorful.Color{}.RGBA()
}
cf := hexToColor(ac.value())
return cf.RGBA()
}

// hexToColor translates a hex color string (#RRGGBB or #RGB) into a color.RGB,
// which satisfies the color.Color interface. If an invalid string is passed
// black with 100% opacity will be returned: or, in hex format, 0x000000FF.
func hexToColor(hex string) (c color.RGBA) {
c.A = 0xFF

if hex == "" || hex[0] != '#' {
return c
}

switch len(hex) {
case 7: // #RRGGBB
c.R = hexToByte(hex[1])<<4 + hexToByte(hex[2])
c.G = hexToByte(hex[3])<<4 + hexToByte(hex[4])
c.B = hexToByte(hex[5])<<4 + hexToByte(hex[6])
case 4: // #RGB
const offset = 0x11
c.R = hexToByte(hex[1]) * offset
c.G = hexToByte(hex[2]) * offset
c.B = hexToByte(hex[3]) * offset
}

return c
}

func hexToByte(b byte) byte {
switch {
case b >= '0' && b <= '9':
return b - '0'
case b >= 'a' && b <= 'f':
return b - 'a' + 10
case b >= 'A' && b <= 'F':
return b - 'A' + 10
}
// Invalid, but just return 0.
return 0
}
34 changes: 34 additions & 0 deletions color_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,37 @@ func TestSetColorProfile(t *testing.T) {
}
}
}

func TestHexToColor(t *testing.T) {
t.Parallel()

tt := []struct {
input string
expected uint
}{
{
"#FF0000",
0xFF0000,
},
{
"#00F",
0x0000FF,
},
{
"#6B50FF",
0x6B50FF,
},
{
"invalid color",
0x0,
},
}

for i, tc := range tt {
h := hexToColor(tc.input)
o := uint(h.R)<<16 + uint(h.G)<<8 + uint(h.B)
if o != tc.expected {
t.Errorf("expected %X, got %X (test #%d)", o, tc.expected, i+1)
}
}
}
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ module github.com/charmbracelet/lipgloss
go 1.15

require (
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mattn/go-runewidth v0.0.13
github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68
github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c
)

0 comments on commit 1fb1fb9

Please sign in to comment.