pax_global_header 0000666 0000000 0000000 00000000064 15202373470 0014515 g ustar 00root root 0000000 0000000 52 comment=0fb7826462abc12f0955d7a7ed28f310e4116c35
golang-github-leaanthony-go-ansi-parser-1.6.1/ 0000775 0000000 0000000 00000000000 15202373470 0021236 5 ustar 00root root 0000000 0000000 golang-github-leaanthony-go-ansi-parser-1.6.1/LICENSE 0000664 0000000 0000000 00000002064 15202373470 0022245 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2021-Present Lea Anthony
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
golang-github-leaanthony-go-ansi-parser-1.6.1/README.md 0000664 0000000 0000000 00000005625 15202373470 0022525 0 ustar 00root root 0000000 0000000

A library for parsing ANSI encoded strings
Go ANSI Parser converts strings with [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
into a slice of structs that represent styled text. Features:
* Can parse ANSI 16, 256 and TrueColor
* Supports all styles: Regular, Bold, Faint, Italic, Blinking, Inversed, Invisible, Underlined, Strikethrough
* Provides RGB, Hex, HSL, ANSI ID and Name for parsed colours
* Truncation - works with emojis and grapheme clusters
* Length - works with emojis and grapheme clusters
* Cleanse - removes the ansi escape codes
* Configurable colour map for customisation
* 100% Test Coverage
# Installation
```shell
go get github.com/leaanthony/go-ansi-parser
```
## Usage
### Parse
```go
text, err := ansi.Parse("\u001b[1;31;40mHello World\033[0m")
// is the equivalent of...
text := []*ansi.StyledText{
{
Label: "Hello World",
FgCol: &ansi.Col{
Id: 9,
Hex: "#ff0000",
Rgb: &ansi.Rgb{ R: 255, G: 0, B: 0 },
Hsl: &ansi.Hsl{ H: 0, S: 100, L: 50 },
Name: "Red",
},
BgCol: &ansi.Col{
Id: 0,
Hex: "#000000",
Rgb: &ansi.Rgb{0, 0, 0},
Hsl: &ansi.Hsl{0, 0, 0},
Name: "Black",
},
Style: 1,
},
}
```
### Truncating
```go
shorter, err := ansi.Truncate("\u001b[1;31;40mHello\033[0m \u001b[0;30mWorld!\033[0m", 8)
// is the equivalent of...
shorter := "\u001b[1;31;40mHello\033[0m \u001b[0;30mWo\033[0m"
```
### Cleanse
```go
cleaner, err := ansi.Cleanse("\u001b[1;31;40mHello\033[0m \u001b[0;30mWorld!\033[0m")
// is the equivalent of...
cleaner := "Hello World!"
```
### Length
```go
length, err := ansi.Length("\u001b[1;31;40mHello\033[0m \u001b[0;30mWorld!\033[0m")
// is the equivalent of...
length := 12
// Works with grapheme clusters and emoji
length, err := ansi.Length("\u001b[1;31;40m👩🏽🔧😎\033[0m") // 2
```
golang-github-leaanthony-go-ansi-parser-1.6.1/ansi.go 0000664 0000000 0000000 00000033272 15202373470 0022526 0 ustar 00root root 0000000 0000000 package ansi
import (
"fmt"
"strconv"
"strings"
"github.com/rivo/uniseg"
)
// TextStyle is a type representing the
// ansi text styles
type TextStyle int
const (
// Bold Style
Bold TextStyle = 1 << 0
// Faint Style
Faint TextStyle = 1 << 1
// Italic Style
Italic TextStyle = 1 << 2
// Blinking Style
Blinking TextStyle = 1 << 3
// Inversed Style
Inversed TextStyle = 1 << 4
// Invisible Style
Invisible TextStyle = 1 << 5
// Underlined Style
Underlined TextStyle = 1 << 6
// Strikethrough Style
Strikethrough TextStyle = 1 << 7
// Bright Style
Bright TextStyle = 1 << 8
)
type ColourMode int
const (
Default ColourMode = 0
TwoFiveSix ColourMode = 1
TrueColour ColourMode = 2
)
var invalid = fmt.Errorf("invalid ansi string")
var missingTerminator = fmt.Errorf("missing escape terminator 'm'")
var invalidTrueColorSequence = fmt.Errorf("invalid TrueColor sequence")
var invalid256ColSequence = fmt.Errorf("invalid 256 colour sequence")
const (
// Default colors uses foreground color codes [30-37].
// See ColourMap and case for background colors.
defaultForegroundColor = "37"
defaultBackgroundColor = "30"
)
// StyledText represents a single formatted string
type StyledText struct {
Label string
FgCol *Col
BgCol *Col
Style TextStyle
ColourMode ColourMode
// Offset is the offset into the input string where the StyledText begins
Offset int
// Len is the length in bytes of the substring of the input text that
// contains the styled text
Len int
}
func (s *StyledText) styleToParams() []string {
var params []string
if s.Bold() {
params = append(params, "1")
}
if s.Faint() {
params = append(params, "2")
}
if s.Italic() {
params = append(params, "3")
}
if s.Underlined() {
params = append(params, "4")
}
if s.Blinking() {
params = append(params, "5")
}
if s.Inversed() {
params = append(params, "7")
}
if s.Invisible() {
params = append(params, "8")
}
if s.Strikethrough() {
params = append(params, "9")
}
if s.FgCol != nil {
// Do we have an ID?
switch s.ColourMode {
case Default:
offset := 30
id := s.FgCol.Id
// Adjust when bold has been applied to the id
if (s.Bold() || s.Bright()) && id > 7 && id < 16 {
id -= 8
}
if s.Bright() {
offset = 90
}
params = append(params, fmt.Sprintf("%d", id+offset))
case TwoFiveSix:
params = append(params, []string{"38", "5", fmt.Sprintf("%d", s.FgCol.Id)}...)
case TrueColour:
r := fmt.Sprintf("%d", s.FgCol.Rgb.R)
g := fmt.Sprintf("%d", s.FgCol.Rgb.G)
b := fmt.Sprintf("%d", s.FgCol.Rgb.B)
params = append(params, []string{"38", "2", r, g, b}...)
}
}
if s.BgCol != nil {
// Do we have an ID?
switch s.ColourMode {
case Default:
id := s.BgCol.Id
offset := 40
if s.Bright() {
offset = 100
}
// Adjust when bold has been applied to the id
if (s.Bold() || s.Bright()) && id > 7 && id < 16 {
id -= 8
}
params = append(params, fmt.Sprintf("%d", id+offset))
case TwoFiveSix:
params = append(params, []string{"48", "5", fmt.Sprintf("%d", s.BgCol.Id)}...)
case TrueColour:
r := fmt.Sprintf("%d", s.BgCol.Rgb.R)
g := fmt.Sprintf("%d", s.BgCol.Rgb.G)
b := fmt.Sprintf("%d", s.BgCol.Rgb.B)
params = append(params, []string{"48", "2", r, g, b}...)
}
}
return params
}
func (s *StyledText) String() string {
params := strings.Join(s.styleToParams(), ";")
return "\033[0;" + params + "m" + s.Label + "\033[0m"
}
// Bold will return true if the text has a Bold style
func (s *StyledText) Bold() bool {
return s.Style&Bold == Bold
}
// Faint will return true if the text has a Faint style
func (s *StyledText) Faint() bool {
return s.Style&Faint == Faint
}
// Italic will return true if the text has an Italic style
func (s *StyledText) Italic() bool {
return s.Style&Italic == Italic
}
// Blinking will return true if the text has a Blinking style
func (s *StyledText) Blinking() bool {
return s.Style&Blinking == Blinking
}
// Inversed will return true if the text has an Inversed style
func (s *StyledText) Inversed() bool {
return s.Style&Inversed == Inversed
}
// Invisible will return true if the text has an Invisible style
func (s *StyledText) Invisible() bool {
return s.Style&Invisible == Invisible
}
// Underlined will return true if the text has an Underlined style
func (s *StyledText) Underlined() bool {
return s.Style&Underlined == Underlined
}
// Strikethrough will return true if the text has a Strikethrough style
func (s *StyledText) Strikethrough() bool {
return s.Style&Strikethrough == Strikethrough
}
// Bright will return true if the text has a Bright style
func (s *StyledText) Bright() bool {
return s.Style&Bright == Bright
}
// ColourMap maps ansi identifiers to a colour
var ColourMap = map[string]map[string]*Col{
"Regular": {
"30": Cols[0],
"31": Cols[1],
"32": Cols[2],
"33": Cols[3],
"34": Cols[4],
"35": Cols[5],
"36": Cols[6],
"37": Cols[7],
"90": Cols[8],
"91": Cols[9],
"92": Cols[10],
"93": Cols[11],
"94": Cols[12],
"95": Cols[13],
"96": Cols[14],
"97": Cols[15],
"100": Cols[8],
"101": Cols[9],
"102": Cols[10],
"103": Cols[11],
"104": Cols[12],
"105": Cols[13],
"106": Cols[14],
"107": Cols[15],
},
"Bold": {
"30": Cols[8],
"31": Cols[9],
"32": Cols[10],
"33": Cols[11],
"34": Cols[12],
"35": Cols[13],
"36": Cols[14],
"37": Cols[15],
"90": Cols[8],
"91": Cols[9],
"92": Cols[10],
"93": Cols[11],
"94": Cols[12],
"95": Cols[13],
"96": Cols[14],
"97": Cols[15],
"100": Cols[8],
"101": Cols[9],
"102": Cols[10],
"103": Cols[11],
"104": Cols[12],
"105": Cols[13],
"106": Cols[14],
"107": Cols[15],
},
"Faint": {
"30": Cols[0],
"31": Cols[1],
"32": Cols[2],
"33": Cols[3],
"34": Cols[4],
"35": Cols[5],
"36": Cols[6],
"37": Cols[7],
},
}
// Parse will convert an ansi encoded string and return
// a slice of StyledText structs that represent the text.
// If parsing is unsuccessful, an error is returned.
func Parse(input string, options ...ParseOption) ([]*StyledText, error) {
var result []*StyledText
index := 0
offset := 0
escapeCodeLen := 0
var currentStyledText = &StyledText{}
if len(input) == 0 {
return []*StyledText{currentStyledText}, nil
}
for {
// Read all chars to next escape code
esc := strings.Index(input, "\033[")
// If no more esc chars, save what's left and return
if esc == -1 {
text := input[index:]
if len(text) > 0 {
currentStyledText.Label = text
currentStyledText.Offset = offset
currentStyledText.Len = len(text) + escapeCodeLen
result = append(result, currentStyledText)
}
return result, nil
}
label := input[:esc]
if len(label) > 0 {
currentStyledText.Label = label
currentStyledText.Offset = offset
currentStyledText.Len = len(label) + escapeCodeLen
offset += currentStyledText.Len
result = append(result, currentStyledText)
currentStyledText = &StyledText{
Label: "",
FgCol: currentStyledText.FgCol,
BgCol: currentStyledText.BgCol,
Style: currentStyledText.Style,
}
escapeCodeLen = 0
}
input = input[esc:]
// skip
input = input[2:]
// Read in params
endesc := strings.Index(input, "m")
if endesc == -1 {
return nil, missingTerminator
}
paramText := input[:endesc]
input = input[endesc+1:]
escapeCodeLen += 2 + endesc + 1
params := strings.Split(paramText, ";")
colourMap := ColourMap["Regular"]
skip := 0
for index, param := range params {
if skip > 0 {
skip--
continue
}
param = stripLeadingZeros(param)
switch param {
case "0", "":
colourMap = ColourMap["Regular"]
currentStyledText.Style = 0
currentStyledText.FgCol = nil
currentStyledText.BgCol = nil
case "1":
// Bold
colourMap = ColourMap["Bold"]
currentStyledText.Style |= Bold
case "2":
// Dim/Feint
colourMap = ColourMap["Faint"]
currentStyledText.Style |= Faint
case "3":
// Italic
currentStyledText.Style |= Italic
case "4":
// Underlined
currentStyledText.Style |= Underlined
case "5":
// Blinking
currentStyledText.Style |= Blinking
case "7":
// Inversed
currentStyledText.Style |= Inversed
case "8":
// Invisible
currentStyledText.Style |= Invisible
case "9":
// Strikethrough
currentStyledText.Style |= Strikethrough
case "30", "31", "32", "33", "34", "35", "36", "37":
currentStyledText.FgCol = colourMap[param]
case "90", "91", "92", "93", "94", "95", "96", "97":
currentStyledText.FgCol = colourMap[param]
currentStyledText.Style |= Bright
case "100", "101", "102", "103", "104", "105", "106", "107":
currentStyledText.BgCol = colourMap[param]
currentStyledText.Style |= Bright
case "40", "41", "42", "43", "44", "45", "46", "47":
bgcol := "3" + param[1:] // Equivalent of -10
currentStyledText.BgCol = colourMap[bgcol]
case "38", "48":
if len(params)-index < 3 {
return nil, invalid
}
// 256 colours
param1 := stripLeadingZeros(params[index+1])
if param1 == "5" {
skip = 2
colIndexText := stripLeadingZeros(params[index+2])
colIndex, err := strconv.Atoi(colIndexText)
if err != nil {
return nil, invalid256ColSequence
}
if colIndex < 0 || colIndex > 255 {
return nil, invalid256ColSequence
}
currentStyledText.ColourMode = TwoFiveSix
if param == "38" {
currentStyledText.FgCol = Cols[colIndex]
continue
}
currentStyledText.BgCol = Cols[colIndex]
continue
}
// we must have 4 params left
if len(params)-index < 5 {
return nil, invalidTrueColorSequence
}
if param1 != "2" {
return nil, invalidTrueColorSequence
}
var r, g, b uint8
ri, err := strconv.Atoi(params[index+2])
if err != nil {
return nil, invalidTrueColorSequence
}
gi, err := strconv.Atoi(params[index+3])
if err != nil {
return nil, invalidTrueColorSequence
}
bi, err := strconv.Atoi(params[index+4])
if err != nil {
return nil, invalidTrueColorSequence
}
if bi > 255 || gi > 255 || ri > 255 {
return nil, invalidTrueColorSequence
}
if bi < 0 || gi < 0 || ri < 0 {
return nil, invalidTrueColorSequence
}
r = uint8(ri)
g = uint8(gi)
b = uint8(bi)
skip = 4
colvalue := fmt.Sprintf("#%02x%02x%02x", r, g, b)
currentStyledText.ColourMode = TrueColour
if param == "38" {
currentStyledText.FgCol = &Col{Id: 256, Hex: colvalue, Rgb: Rgb{r, g, b}}
continue
}
currentStyledText.BgCol = &Col{Id: 256, Hex: colvalue, Rgb: Rgb{r, g, b}}
case "39":
// Lookup for default foreground color.
foregroundColor := colourMap[defaultForegroundColor]
for _, option := range options {
if option.ansiForegroundColor != "" {
foregroundColor = colourMap[option.ansiForegroundColor]
break
}
}
// Set selected foreground color.
currentStyledText.FgCol = foregroundColor
case "49":
// Lookup for default background color.
backgroundColor := colourMap[defaultBackgroundColor]
for _, option := range options {
if option.ansiBackgroundColor != "" {
backgroundColor = colourMap[option.ansiBackgroundColor]
break
}
}
// Set selected background color.
currentStyledText.BgCol = backgroundColor
default:
// Unexpected codes may be ignored.
unexpectedCodeIgnored := false
for _, option := range options {
if option.ignoreUnexpectedCode {
unexpectedCodeIgnored = true
break
}
}
if !unexpectedCodeIgnored {
return nil, invalid
}
}
}
}
}
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
}
// String builds an ANSI string for specified StyledText slice.
func String(input []*StyledText) string {
var result strings.Builder
for _, text := range input {
params := text.styleToParams()
if len(params) == 0 {
result.WriteString(text.Label)
continue
}
result.WriteString(text.String())
}
return result.String()
}
// Truncate truncates text to length but preserves control symbols in ANSI string.
func Truncate(input string, maxChars int, options ...ParseOption) (string, error) {
parsed, err := Parse(input, options...)
if err != nil {
return "", err
}
charsLeft := maxChars
var result []*StyledText
for _, element := range parsed {
userPerceivedChars := uniseg.GraphemeClusterCount(element.Label)
if userPerceivedChars >= charsLeft {
var newLabel []rune
graphemes := uniseg.NewGraphemes(element.Label)
for graphemes.Next() {
newLabel = append(newLabel, graphemes.Runes()...)
charsLeft--
if charsLeft == 0 {
element.Label = string(newLabel)
result = append(result, element)
return String(result), nil
}
}
}
result = append(result, element)
charsLeft -= userPerceivedChars
}
return String(result), nil
}
// Cleanse removes ANSI control symbols from the string.
func Cleanse(input string, options ...ParseOption) (string, error) {
if input == "" {
return "", nil
}
parsed, err := Parse(input, options...)
if err != nil {
return "", err
}
var result strings.Builder
for _, element := range parsed {
result.WriteString(element.Label)
}
return result.String(), nil
}
// Length calculates count of user-perceived characters in ANSI string.
func Length(input string, options ...ParseOption) (int, error) {
if input == "" {
return 0, nil
}
parsed, err := Parse(input, options...)
if err != nil {
return -1, err
}
var result int
for _, element := range parsed {
userPerceivedChars := uniseg.GraphemeClusterCount(element.Label)
result += userPerceivedChars
}
return result, nil
}
golang-github-leaanthony-go-ansi-parser-1.6.1/ansi_test.go 0000664 0000000 0000000 00000071353 15202373470 0023567 0 ustar 00root root 0000000 0000000 package ansi
import (
"testing"
is "github.com/matryer/is"
)
func TestParseAnsi16Styles(t *testing.T) {
is2 := is.New(t)
var got []*StyledText
var err error
// Bold
got, err = Parse("\u001b[1;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Bold())
is2.Equal(got[0].Len, 18)
is2.Equal(got[0].Offset, 0)
// Faint
got, err = Parse("\u001b[2;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Faint())
// Italic
got, err = Parse("\u001b[3;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Italic())
// Underlined
got, err = Parse("\u001b[4;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Underlined())
// Blinking
got, err = Parse("\u001b[5;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Blinking())
// Inversed
got, err = Parse("\u001b[7;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Inversed())
// Invisible
got, err = Parse("\u001b[8;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Invisible())
// Strikethrough
got, err = Parse("\u001b[9;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.True(got[0].Strikethrough())
}
func TestParseAnsi16Swap(t *testing.T) {
is2 := is.New(t)
var got []*StyledText
var err error
// Swap single
c0ffee := &Col{
Id: 0,
Hex: "c0ffee",
Name: "Coffee",
}
original := ColourMap["Regular"]["30"]
ColourMap["Regular"]["30"] = c0ffee
got, err = Parse("\u001b[0;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.Equal(got[0].FgCol.Name, "Coffee")
// Restore
ColourMap["Regular"]["30"] = original
got, err = Parse("\u001b[0;30mHello World\033[0m")
is2.NoErr(err)
is2.Equal(len(got), 1)
is2.Equal(got[0].FgCol.Name, "Black")
}
func TestParseAnsi16SingleColour(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
wantText string
wantColor string
wantErr bool
}{
{"No formatting", "Hello World", "Hello World", "", false},
{"Black", "\u001b[0;30mHello World\033[0m", "Hello World", "Black", false},
{"Red", "\u001b[0;31mHello World\033[0m", "Hello World", "Maroon", false},
{"Green", "\u001b[0;32mGreen\033[0m", "Green", "Green", false},
{"Yellow", "\u001b[0;33m😀\033[0m", "😀", "Olive", false},
{"Blue", "\u001b[0;34m123\033[0m", "123", "Navy", false},
{"Purple", "\u001b[0;35m👩🏽🔧\u001B[0m", "👩🏽🔧", "Purple", false},
{"Cyan", "\033[0;36m😀\033[0m", "😀", "Teal", false},
{"White", "\u001b[0;37m[0;37m\033[0m", "[0;37m", "Silver", false},
{"Black Bold", "\u001b[1;30mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bold", "\u001b[1;31mHello World\033[0m", "Hello World", "Red", false},
{"Green Bold", "\u001b[1;32mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bold", "\u001b[1;33m😀\033[0m", "😀", "Yellow", false},
{"Blue Bold", "\u001b[1;34m123\033[0m", "123", "Blue", false},
{"Purple Bold", "\u001b[1;35m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bold", "\033[1;36m😀\033[0m", "😀", "Aqua", false},
{"White Bold", "\u001b[1;37m[0;37m\033[0m", "[0;37m", "White", false},
{"Black Bold & Bright", "\u001b[1;90mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bold & Bright", "\u001b[1;91mHello World\033[0m", "Hello World", "Red", false},
{"Green Bold & Bright", "\u001b[1;92mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bold & Bright", "\u001b[1;93m😀\033[0m", "😀", "Yellow", false},
{"Blue Bold & Bright", "\u001b[1;94m123\033[0m", "123", "Blue", false},
{"Purple Bold & Bright", "\u001b[1;95m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bold & Bright", "\033[1;96m😀\033[0m", "😀", "Aqua", false},
{"White Bold & Bright", "\u001b[1;97m[0;37m\033[0m", "[0;37m", "White", false},
{"Black Bright", "\u001b[90mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bright", "\u001b[91mHello World\033[0m", "Hello World", "Red", false},
{"Green Bright", "\u001b[92mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bright", "\u001b[93m😀\033[0m", "😀", "Yellow", false},
{"Blue Bright", "\u001b[94m123\033[0m", "123", "Blue", false},
{"Purple Bright", "\u001b[95m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bright", "\033[96m😀\033[0m", "😀", "Aqua", false},
{"White Bright", "\u001b[97m[0;37m\033[0m", "[0;37m", "White", false},
{"Black Bold & Bright Background", "\u001b[1;100mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bold & Bright Background", "\u001b[1;101mHello World\033[0m", "Hello World", "Red", false},
{"Green Bold & Bright Background", "\u001b[1;102mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bold & Bright Background", "\u001b[1;103m😀\033[0m", "😀", "Yellow", false},
{"Blue Bold & Bright Background", "\u001b[1;104m123\033[0m", "123", "Blue", false},
{"Purple Bold & Bright Background", "\u001b[1;105m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bold & Bright Background", "\033[1;106m😀\033[0m", "😀", "Aqua", false},
{"White Bold & Bright Background", "\u001b[1;107m[0;37m\033[0m", "[0;37m", "White", false},
{"Black Bright Background", "\u001b[100mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bright Background", "\u001b[101mHello World\033[0m", "Hello World", "Red", false},
{"Green Bright Background", "\u001b[102mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bright Background", "\u001b[103m😀\033[0m", "😀", "Yellow", false},
{"Blue Bright Background", "\u001b[104m123\033[0m", "123", "Blue", false},
{"Purple Bright Background", "\u001b[105m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bright Background", "\033[106m😀\033[0m", "😀", "Aqua", false},
{"White Bright Background", "\u001b[107m[0;37m\033[0m", "[0;37m", "White", false},
{"Blank", "", "", "", false},
{"Emoji", "😀👩🏽🔧", "😀👩🏽🔧", "", false},
{"Spaces", " ", " ", "", false},
{"Bad code", "\u001b[1 ", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
expectedLength := 1
if tt.wantErr {
expectedLength = 0
}
is2.Equal(len(got), expectedLength)
if expectedLength == 1 {
if len(tt.wantColor) > 0 {
if got[0].FgCol != nil {
is2.Equal(got[0].FgCol.Name, tt.wantColor)
} else {
is2.Equal(got[0].BgCol.Name, tt.wantColor)
}
}
}
})
}
}
func TestParseAnsi16SingleBGColour(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
wantText string
wantColor string
wantErr bool
}{
{"No formatting", "Hello World", "Hello World", "", false},
{"Black", "\u001b[0;40mHello World\033[0m", "Hello World", "Black", false},
{"Red", "\u001b[0;41mHello World\033[0m", "Hello World", "Maroon", false},
{"Green", "\u001b[0;42mGreen\033[0m", "Green", "Green", false},
{"Yellow", "\u001b[0;43m😀\033[0m", "😀", "Olive", false},
{"Blue", "\u001b[0;44m123\033[0m", "123", "Navy", false},
{"Purple", "\u001b[0;45m👩🏽🔧\u001B[0m", "👩🏽🔧", "Purple", false},
{"Cyan", "\033[0;46m😀\033[0m", "😀", "Teal", false},
{"White", "\u001b[0;47m[0;47m\033[0m", "[0;47m", "Silver", false},
{"Black Bold", "\u001b[1;40mHello World\033[0m", "Hello World", "Grey", false},
{"Red Bold", "\u001b[1;41mHello World\033[0m", "Hello World", "Red", false},
{"Green Bold", "\u001b[1;42mGreen\033[0m", "Green", "Lime", false},
{"Yellow Bold", "\u001b[1;43m😀\033[0m", "😀", "Yellow", false},
{"Blue Bold", "\u001b[1;44m123\033[0m", "123", "Blue", false},
{"Purple Bold", "\u001b[1;45m👩🏽🔧\u001B[0m", "👩🏽🔧", "Fuchsia", false},
{"Cyan Bold", "\033[1;46m😀\033[0m", "😀", "Aqua", false},
{"White Bold", "\u001b[1;47m[0;47m\033[0m", "[0;47m", "White", false},
{"Pre text", "Hello\u001b[0m", "Hello", "", false},
{"Blank", "", "", "", false},
{"Emoji", "😀👩🏽🔧", "😀👩🏽🔧", "", false},
{"Spaces", " ", " ", "", false},
{"Bad code", "\u001b[1 ", "", "", true},
{"No colour", "\033[m\033[40m \033[0m", " ", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
expectedLength := 1
if tt.wantErr {
expectedLength = 0
}
is2.Equal(len(got), expectedLength)
if expectedLength == 1 {
if len(tt.wantColor) > 0 {
is2.True(got[0].BgCol != nil)
is2.Equal(got[0].BgCol.Name, tt.wantColor)
}
}
})
}
}
func TestParseAnsi16MultiColour(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want []*StyledText
wantErr bool
}{
{"Black & Red", "\u001B[0;30mHello World\u001B[0m\u001B[0;31mHello World\u001B[0m", []*StyledText{
{Label: "Hello World", FgCol: &Col{Name: "Black"}, Offset: 0, Len: 18},
{Label: "Hello World", FgCol: &Col{Name: "Maroon"}, Offset: 18, Len: 22},
}, false},
{"Text then Black & Red", "This is great!\u001B[0;30mHello World\u001B[0m\u001B[0;31mHello World\u001B[0m", []*StyledText{
{Label: "This is great!", Offset: 0, Len: 14},
{Label: "Hello World", FgCol: &Col{Name: "Black"}, Offset: 14, Len: 18},
{Label: "Hello World", FgCol: &Col{Name: "Maroon"}, Offset: 32, Len: 22},
}, false},
{"Text Reset then Black & Red", "This is great!\u001B[0m\u001B[0;30mHello World\u001B[0m\u001B[0;31mHello World\u001B[0m", []*StyledText{
{Label: "This is great!", Offset: 0, Len: 14},
{Label: "Hello World", FgCol: &Col{Name: "Black"}, Offset: 14, Len: 22},
{Label: "Hello World", FgCol: &Col{Name: "Maroon"}, Offset: 36, Len: 22},
}, false},
{"Text Reset then Black & Red", "This is great!\u001B[0m", []*StyledText{
{Label: "This is great!", Offset: 0, Len: 14},
}, false},
{"Black & Red no reset", "\u001B[0;30mHello World\u001B[0;31mHello World", []*StyledText{
{Label: "Hello World", FgCol: &Col{Name: "Black"}, Offset: 0, Len: 18},
{Label: "Hello World", FgCol: &Col{Name: "Maroon"}, Offset: 18, Len: 18},
}, false},
{"Black,space,Red", "\u001B[0;30mHello World\u001B[0m \u001B[0;31mHello World\u001B[0m", []*StyledText{
{Label: "Hello World", FgCol: &Col{Name: "Black"}, Offset: 0, Len: 18},
{Label: " ", Offset: 18, Len: 5},
{Label: "Hello World", FgCol: &Col{Name: "Maroon"}, Offset: 23, Len: 18},
}, false},
{"Black,Red,Blue,Green underlined", "\033[4;30mBlack\u001B[0m\u001B[4;31mRed\u001B[0m\u001B[4;34mBlue\u001B[0m\u001B[4;32mGreen\u001B[0m", []*StyledText{
{Label: "Black", FgCol: &Col{Name: "Black"}, Style: Underlined, Offset: 0, Len: 12},
{Label: "Red", FgCol: &Col{Name: "Maroon"}, Style: Underlined, Offset: 12, Len: 14},
{Label: "Blue", FgCol: &Col{Name: "Navy"}, Style: Underlined, Offset: 26, Len: 15},
{Label: "Green", FgCol: &Col{Name: "Green"}, Style: Underlined, Offset: 41, Len: 16},
}, false},
{"Black,Red,Blue,Green bold", "\033[1;30mBlack\u001B[0m\u001B[1;31mRed\u001B[0m\u001B[1;34mBlue\u001B[0m\u001B[1;32mGreen\u001B[0m", []*StyledText{
{Label: "Black", FgCol: &Col{Name: "Grey"}, Style: Bold, Offset: 0, Len: 12},
{Label: "Red", FgCol: &Col{Name: "Red"}, Style: Bold, Offset: 12, Len: 14},
{Label: "Blue", FgCol: &Col{Name: "Blue"}, Style: Bold, Offset: 26, Len: 15},
{Label: "Green", FgCol: &Col{Name: "Lime"}, Style: Bold, Offset: 41, Len: 16},
}, false},
{"Green Feint & Yellow Italic", "\u001B[2;32m👩🏽🔧\u001B[0m\u001B[0;3;33m👩🏽🔧\u001B[0m", []*StyledText{
{Label: "👩🏽🔧", FgCol: &Col{Name: "Green"}, Style: Faint, Offset: 0, Len: len("👩🏽🔧") + 7},
{Label: "👩🏽🔧", FgCol: &Col{Name: "Olive"}, Style: Italic, Offset: len("👩🏽🔧") + 7, Len: len("👩🏽🔧") + 13},
}, false},
{"Green Blinking & Yellow Inversed", "\u001B[5;32m👩🏽🔧\u001B[0m\u001B[0;7;33m👩🏽🔧\u001B[0m", []*StyledText{
{Label: "👩🏽🔧", FgCol: &Col{Name: "Green"}, Style: Blinking, Offset: 0, Len: len("👩🏽🔧") + 7},
{Label: "👩🏽🔧", FgCol: &Col{Name: "Olive"}, Style: Inversed, Offset: len("👩🏽🔧") + 7, Len: len("👩🏽🔧") + 13},
}, false},
{"Green Invisible & Yellow Invisible & Strikethrough", "\u001B[8;32m👩🏽🔧\u001B[9;33m👩🏽🔧\u001B[0m", []*StyledText{
{Label: "👩🏽🔧", FgCol: &Col{Name: "Green"}, Style: Invisible, Offset: 0, Len: len("👩🏽🔧") + 7},
{Label: "👩🏽🔧", FgCol: &Col{Name: "Olive"}, Style: Invisible | Strikethrough, Offset: len("👩🏽🔧") + 7, Len: len("👩🏽🔧") + 7},
}, false},
{"Red Foregraound & Black Background", "\u001b[1;31;40mHello World\033[0m", []*StyledText{
{Label: "Hello World", FgCol: &Col{Name: "Red"}, BgCol: &Col{Name: "Black"}, Style: Bold, Offset: 0, Len: 21},
}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
for index, w := range tt.want {
is2.Equal(got[index].Label, w.Label)
if w.FgCol != nil {
is2.Equal(got[index].FgCol.Name, w.FgCol.Name)
}
is2.Equal(got[index].Style, w.Style)
is2.Equal(got[index].Offset, w.Offset)
is2.Equal(got[index].Len, w.Len)
}
})
}
}
func TestParseAnsi256(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want []*StyledText
wantErr bool
}{
{"Grey93 & DarkViolet", "\u001B[38;5;255mGrey93\u001B[0m\u001B[38;5;128mDarkViolet\u001B[0m", []*StyledText{
{Label: "Grey93", FgCol: &Col{Name: "Grey93"}},
{Label: "DarkViolet", FgCol: &Col{Name: "DarkViolet"}},
}, false},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;38;5;255mGrey93\u001B[0m\u001B[0;3;38;5;128mDarkViolet\u001B[0m", []*StyledText{
{Label: "Grey93", FgCol: &Col{Name: "Grey93"}, Style: Bold},
{Label: "DarkViolet", FgCol: &Col{Name: "DarkViolet"}, Style: Italic},
}, false},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;38;5;256mGrey93\u001B[0m", nil, true},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;38;5;-1mGrey93\u001B[0m", nil, true},
{"Bad No of Params", "\u001B[0;1;38;5mGrey93\u001B[0m", nil, true},
{"Bad Params", "\u001B[0;1;38;fivemGrey93\u001B[0m", nil, true},
{"Bad Params 2", "\u001B[0;1;38;3mGrey93\u001B[0m", nil, true},
{"Bad Params 3", "\u001B[0;1;38;5;fivemGrey93\u001B[0m", nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
for index, w := range tt.want {
is2.Equal(got[index].Label, w.Label)
if w.FgCol != nil {
is2.Equal(got[index].FgCol.Name, w.FgCol.Name)
}
is2.Equal(got[index].Style, w.Style)
}
})
}
}
func TestRoundtripAnsi16(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
}{
{"No formatting", "Hello World"},
{"Black", "\u001b[0;30mHello World\033[0m"},
{"Red", "\u001b[0;31mHello World\033[0m"},
{"Green", "\u001b[0;32mGreen\033[0m"},
{"Yellow", "\u001b[0;33m😀\033[0m"},
{"Blue", "\u001b[0;34m123\033[0m"},
{"Purple", "\u001b[0;35m👩🏽🔧\u001B[0m"},
{"Cyan", "\033[0;36m😀\033[0m"},
{"White", "\u001b[0;37m[0;37m\033[0m"},
{"Black Bold", "\u001b[0;1;30mHello World\033[0m"},
{"Red Bold", "\u001b[0;1;31mHello World\033[0m"},
{"Green Bold", "\u001b[0;1;32mGreen\033[0m"},
{"Yellow Bold", "\u001b[0;1;33m😀\033[0m"},
{"Blue Bold", "\u001b[0;1;34m123\033[0m"},
{"Purple Bold", "\u001b[0;1;35m👩🏽🔧\u001B[0m"},
{"Cyan Bold", "\033[0;1;36m😀\033[0m"},
{"White Bold", "\u001b[0;1;37m[0;37m\033[0m"},
{"Black Bright", "\u001b[0;90mHello World\033[0m"},
{"Red Bright", "\u001b[0;91mHello World\033[0m"},
{"Green Bright", "\u001b[0;92mGreen\033[0m"},
{"Yellow Bright", "\u001b[0;93m😀\033[0m"},
{"Blue Bright", "\u001b[0;94m123\033[0m"},
{"Purple Bright", "\u001b[0;95m👩🏽🔧\u001B[0m"},
{"Cyan Bright", "\033[0;96m😀\033[0m"},
{"White Bright", "\u001b[0;97m[0;37m\033[0m"},
{"Black Bright Background", "\u001b[0;100mHello World\033[0m"},
{"Red Bright Background", "\u001b[0;101mHello World\033[0m"},
{"Green Bright Background", "\u001b[0;102mGreen\033[0m"},
{"Yellow Bright Background", "\u001b[0;103m😀\033[0m"},
{"Blue Bright Background", "\u001b[0;104m123\033[0m"},
{"Purple Bright Background", "\u001b[0;105m👩🏽🔧\u001B[0m"},
{"Cyan Bright Background", "\033[0;106m😀\033[0m"},
{"White Bright Background", "\u001b[0;107m[0;37m\033[0m"},
{"Blank", ""},
{"Emoji", "😀👩🏽🔧"},
{"Spaces", " "},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.NoErr(err)
output := String(got)
is2.Equal(output, tt.input)
})
}
}
func TestRoundtripAnsi256(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
}{
{"Grey93 & DarkViolet", "\u001B[0;38;5;255mGrey93\u001B[0m\u001B[0;38;5;128mDarkViolet\u001B[0m"},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;38;5;255mGrey93\u001B[0m\u001B[0;3;38;5;128mDarkViolet\u001B[0m"},
{"White", "\u001B[0;38;5;15mWhite\u001B[0m\u001B[0;3;38;5;128mDarkViolet\u001B[0m"},
{"White Bold", "\u001B[0;1;38;5;15mWhite\u001B[0m\u001B[0;3;38;5;128mDarkViolet\u001B[0m"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.NoErr(err)
output := String(got)
is2.Equal(output, tt.input)
})
}
}
func TestParseAnsiBG256(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want []*StyledText
wantErr bool
}{
{"Grey93 & DarkViolet", "\u001B[48;5;255mGrey93\u001B[0m\u001B[48;5;128mDarkViolet\u001B[0m", []*StyledText{
{Label: "Grey93", BgCol: &Col{Name: "Grey93"}},
{Label: "DarkViolet", BgCol: &Col{Name: "DarkViolet"}},
}, false},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;48;5;255mGrey93\u001B[0m\u001B[0;3;48;5;128mDarkViolet\u001B[0m", []*StyledText{
{Label: "Grey93", BgCol: &Col{Name: "Grey93"}, Style: Bold},
{Label: "DarkViolet", BgCol: &Col{Name: "DarkViolet"}, Style: Italic},
}, false},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;48;5;256mGrey93\u001B[0m", nil, true},
{"Grey93 Bold & DarkViolet Italic", "\u001B[0;1;48;5;-1mGrey93\u001B[0m", nil, true},
{"Bad No of Params", "\u001B[0;1;48;5mGrey93\u001B[0m", nil, true},
{"Bad Params", "\u001B[0;1;48;fivemGrey93\u001B[0m", nil, true},
{"Bad Params 2", "\u001B[0;1;48;3mGrey93\u001B[0m", nil, true},
{"Bad Params 2", "\u001B[0;1;50;3mGrey93\u001B[0m", nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
for index, w := range tt.want {
is2.Equal(got[index].Label, w.Label)
if w.FgCol != nil {
is2.Equal(got[index].BgCol.Name, w.BgCol.Name)
}
is2.Equal(got[index].Style, w.Style)
}
})
}
}
func TestParseAnsiTrueColor(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want []*StyledText
wantErr bool
}{
{"Red", "\u001B[38;2;255;0;0mRed\u001B[0m", []*StyledText{
{Label: "Red", FgCol: &Col{Rgb: Rgb{255, 0, 0}, Hex: "#ff0000"}},
}, false},
{"Red BG", "\u001B[48;2;255;0;0mRed\u001B[0m", []*StyledText{
{Label: "Red", BgCol: &Col{Rgb: Rgb{255, 0, 0}, Hex: "#ff0000"}},
}, false},
{"Red, text, Green", "\u001B[38;2;255;0;0mRed\u001B[0mI am plain text\u001B[38;2;0;255;0mGreen\u001B[0m", []*StyledText{
{Label: "Red", FgCol: &Col{Rgb: Rgb{255, 0, 0}, Hex: "#ff0000"}},
{Label: "I am plain text"},
{Label: "Green", FgCol: &Col{Rgb: Rgb{0, 255, 0}, Hex: "#00ff00"}},
}, false},
{"Bad 1", "\u001B[38;2;256;0;0mRed\u001B[0m", nil, true},
{"Bad 2", "\u001B[38;2;-1;0;0mRed\u001B[0m", nil, true},
{"Bad no of params", "\u001B[38;2;0;0mRed\u001B[0m", nil, true},
{"Bad params", "\u001B[38;2;0;onemRed\u001B[0m", nil, true},
{"Bad params 2", "\u001B[38;2;red;0;0mRed\u001B[0m", nil, true},
{"Bad params 3", "\u001B[38;2;0;red;0mRed\u001B[0m", nil, true},
{"Bad params 4", "\u001B[38;2;0;0;redmRed\u001B[0m", nil, true},
{"Bad params 4", "\u001B[38;3;0;0;redmRed\u001B[0m", nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
is2.Equal(err != nil, tt.wantErr)
for index, w := range tt.want {
is2.Equal(got[index].Label, w.Label)
if w.FgCol != nil {
is2.Equal(got[index].FgCol.Hex, w.FgCol.Hex)
is2.Equal(got[index].FgCol.Rgb, w.FgCol.Rgb)
}
if w.BgCol != nil {
is2.Equal(got[index].BgCol.Hex, w.BgCol.Hex)
is2.Equal(got[index].BgCol.Rgb, w.BgCol.Rgb)
}
is2.Equal(got[index].Style, w.Style)
}
})
}
}
func TestParseAnsiWithOptions(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
options []ParseOption
want []*StyledText
wantErr bool
}{
{
"Unexpected code errored", "\u001b[0;99mHello World\033[0m",
nil, nil, true,
},
{
"Unexpected code ignored", "\u001b[0;99mHello World\033[0m",
[]ParseOption{WithIgnoreInvalidCodes()},
[]*StyledText{{Label: "Hello World"}}, false,
},
{
"Foreground code default", "\u001b[0;39mHello World\033[0m", nil,
[]*StyledText{{Label: "Hello World", FgCol: Cols[7]}}, false,
},
{
"Foreground code specified", "\u001b[0;39mHello World\033[0m",
[]ParseOption{WithDefaultForegroundColor("35")},
[]*StyledText{{Label: "Hello World", FgCol: Cols[5]}}, false,
},
{
"Background code default", "\u001b[0;49mHello World\033[0m", nil,
[]*StyledText{{Label: "Hello World", BgCol: Cols[0]}}, false,
},
{
"Background code specified", "\u001b[0;49mHello World\033[0m",
[]ParseOption{WithDefaultBackgroundColor("36")},
[]*StyledText{{Label: "Hello World", BgCol: Cols[6]}}, false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input, tt.options...)
is2.Equal(err != nil, tt.wantErr)
for index, w := range tt.want {
is2.Equal(got[index].Label, w.Label)
if w.FgCol != nil {
is2.Equal(got[index].FgCol.Name, w.FgCol.Name)
}
if w.BgCol != nil {
is2.Equal(got[index].BgCol.Name, w.BgCol.Name)
}
is2.Equal(got[index].Style, w.Style)
}
})
}
}
func TestHasEscapeCodes(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want bool
}{
{"yes", "\u001B[0;30mHello World\033[0m\u001B[0;31mHello World\u001B[0m", true},
{"no", "This is great!", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := HasEscapeCodes(tt.input)
is2.Equal(got, tt.want)
})
}
}
func TestString(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input []*StyledText
want string
}{
{"Blank", []*StyledText{}, ""},
{"ANSI16 Fg", []*StyledText{{Label: "Red", FgCol: Cols[1]}}, "\033[0;31mRed\033[0m"},
{"ANSI16 Fg Bold", []*StyledText{{Label: "Red", FgCol: Cols[1], Style: Bold}}, "\033[0;1;31mRed\033[0m"},
{"ANSI16 Fg Strikethrough", []*StyledText{{Label: "Red", FgCol: Cols[1], Style: Strikethrough}}, "\033[0;9;31mRed\033[0m"},
{"ANSI16 Fg Bold & Italic", []*StyledText{{Label: "Red", FgCol: Cols[1], Style: Bold | Italic}}, "\033[0;1;3;31mRed\033[0m"},
{"ANSI16 Bg", []*StyledText{{Label: "Black", BgCol: Cols[0]}}, "\033[0;40mBlack\033[0m"},
{"ANSI16 Mixed", []*StyledText{{Label: "Mixed", FgCol: Cols[1], BgCol: Cols[0]}}, "\033[0;31;40mMixed\033[0m"},
{"ANSI256 Fg", []*StyledText{{ColourMode: TwoFiveSix, Label: "Dark Blue", FgCol: Cols[18]}}, "\033[0;38;5;18mDark Blue\033[0m"},
{"ANSI256 Fg Bold", []*StyledText{{ColourMode: TwoFiveSix, Label: "Dark Blue", FgCol: Cols[18], Style: Bold}}, "\033[0;1;38;5;18mDark Blue\033[0m"},
{"ANSI256 Bg", []*StyledText{{ColourMode: TwoFiveSix, Label: "Dark Blue", BgCol: Cols[18]}}, "\033[0;48;5;18mDark Blue\033[0m"},
{"ANSI256 Bg Bold", []*StyledText{{ColourMode: TwoFiveSix, Label: "Dark Blue", BgCol: Cols[18], Style: Bold}}, "\033[0;1;48;5;18mDark Blue\033[0m"},
{"Truecolor Fg", []*StyledText{{ColourMode: TrueColour, Label: "TrueColor!", FgCol: &Col{Id: 256, Rgb: Rgb{R: 128, G: 127, B: 126}}}}, "\033[0;38;2;128;127;126mTrueColor!\033[0m"},
{"Truecolor Fg Bold", []*StyledText{{ColourMode: TrueColour, Label: "TrueColor!", FgCol: &Col{Id: 256, Rgb: Rgb{R: 128, G: 127, B: 126}}, Style: Bold}}, "\033[0;1;38;2;128;127;126mTrueColor!\033[0m"},
{"Truecolor Bg", []*StyledText{{ColourMode: TrueColour, Label: "TrueColor!", BgCol: &Col{Id: 256, Rgb: Rgb{R: 128, G: 127, B: 126}}}}, "\033[0;48;2;128;127;126mTrueColor!\033[0m"},
{"Truecolor Bg Bold", []*StyledText{{ColourMode: TrueColour, Label: "TrueColor!", BgCol: &Col{Id: 256, Rgb: Rgb{R: 128, G: 127, B: 126}}, Style: Bold}}, "\033[0;1;48;2;128;127;126mTrueColor!\033[0m"},
{"Truecolor Mixed", []*StyledText{{ColourMode: TrueColour, Label: "TrueColor!", FgCol: &Col{Id: 256, Rgb: Rgb{R: 90, G: 91, B: 92}}, BgCol: &Col{Id: 256, Rgb: Rgb{R: 128, G: 127, B: 126}}, Style: Bold | Faint | Underlined | Strikethrough | Italic | Invisible | Blinking | Inversed}}, "\033[0;1;2;3;4;5;7;8;9;38;2;90;91;92;48;2;128;127;126mTrueColor!\033[0m"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := String(tt.input)
is2.Equal(got, tt.want)
})
}
}
func TestTruncate(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
maxChars int
want string
wantErr bool
}{
{"No formatting", "Hello World", 11, "Hello World", false},
{"No formatting truncated", "Hello World", 5, "Hello", false},
{"No formatting many chars", "Hello World", 50, "Hello World", false},
{"Black", "\u001b[0;30mHello World\033[0m", 5, "\u001B[0;30mHello\u001B[0m", false},
{"Red Bold", "\u001b[0;1;31mHello World\033[0m", 5, "\033[0;1;31mHello\033[0m", false},
{"Red Bold & Black", "\u001b[0;1;31mI am Red\033[0m\u001B[0;30mI am Black\u001B[0m", 12, "\u001B[0;1;31mI am Red\u001B[0m\u001B[0;30mI am\u001B[0m", false},
{"Red Bold & text & Black", "\u001b[0;1;31mI am Red\033[0m and \u001B[0;30mI am Black\u001B[0m", 17, "\u001B[0;1;31mI am Red\u001B[0m and \u001B[0;30mI am\u001B[0m", false},
{"Emoji", "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", 1, "\u001B[0;1;31m😀\u001B[0m", false},
{"Emoji 2", "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", 2, "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", false},
{"Emoji 3", "\u001B[0;1;31m😀👩🏽🔧😀\u001B[0m", 2, "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", false},
{"Bad", "\033[44;32;12", 10, "", true},
//{"Spaces", " ", " ", "", false},
//{"Bad code", "\u001b[1 ", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Truncate(tt.input, tt.maxChars)
is2.Equal(err != nil, tt.wantErr)
is2.Equal(got, tt.want)
})
}
}
func TestCleanse(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"Blank", "", "", false},
{"No formatting", "Hello World", "Hello World", false},
{"ANSI16 Fg", "\033[0;31mRed\033[0m", "Red", false},
{"Black", "\u001b[0;30mHello World\033[0m", "Hello World", false},
{"Red Bold & Black", "\u001b[0;1;31mI am Red\033[0m & \u001B[0;30mI am Black\u001B[0m", "I am Red & I am Black", false},
{"Red All the styles", "\u001b[0;1;2;3;4;5;7;8;9;31mI am Red\033[0m", "I am Red", false},
{"Emoji", "\u001B[0;1;31m😀\u001B[0m", "😀", false},
{"Emoji 2", "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", "😀👩🏽🔧", false},
{"Bad", "\033[44;32;12", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Cleanse(tt.input)
is2.Equal(err != nil, tt.wantErr)
is2.Equal(got, tt.want)
})
}
}
func TestLength(t *testing.T) {
is2 := is.New(t)
tests := []struct {
name string
input string
want int
wantErr bool
}{
{"Blank", "", 0, false},
{"No formatting", "Hello World", 11, false},
{"ANSI16 Fg", "\033[0;31mRed\033[0m", 3, false},
{"Zero chats", "\u001b[0;30m\033[0m", 0, false},
{"Red Bold & Black", "\u001b[0;1;31mI am Red\033[0m & \u001B[0;30mI am Black\u001B[0m", 21, false},
{"Red All the styles", "\u001b[0;1;2;3;4;5;7;8;9;31mI am Red\033[0m", 8, false},
{"Emoji", "\u001B[0;1;31m😀\u001B[0m", 1, false},
{"Emoji 2", "\u001B[0;1;31m😀👩🏽🔧\u001B[0m", 2, false},
{"Bad", "\033[44;32;12", -1, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Length(tt.input)
is2.Equal(err != nil, tt.wantErr)
is2.Equal(got, tt.want)
})
}
}
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)
})
}
}
golang-github-leaanthony-go-ansi-parser-1.6.1/cols.go 0000775 0000000 0000000 00000072636 15202373470 0022546 0 ustar 00root root 0000000 0000000 package ansi
// Rgb represents an RGB colour value
// with 8bits per channel
type Rgb struct {
R uint8 `json:"r"`
G uint8 `json:"g"`
B uint8 `json:"b"`
}
// Hsl represents the HSL value of the colour
type Hsl struct {
H float64 `json:"h"`
S float64 `json:"s"`
L float64 `json:"l"`
}
// Col represents a colour value.
// The Id is the ANSI colour ID.
type Col struct {
Id int `json:"id"`
Hex string `json:"hex"`
Rgb Rgb `json:"rgb"`
Hsl Hsl `json:"hsl"`
Name string `json:"name"`
}
// Cols represents the default colour definitions
// used by the library. This may be overridden.
var Cols = []*Col{
{
Id: 0,
Hex: "#000000",
Rgb: Rgb{0, 0, 0},
Hsl: Hsl{0, 0, 0},
Name: "Black",
},
{
Id: 1,
Hex: "#800000",
Rgb: Rgb{128, 0, 0},
Hsl: Hsl{0, 100, 25},
Name: "Maroon",
},
{
Id: 2,
Hex: "#008000",
Rgb: Rgb{0, 128, 0},
Hsl: Hsl{120, 100, 25},
Name: "Green",
},
{
Id: 3,
Hex: "#808000",
Rgb: Rgb{128, 128, 0},
Hsl: Hsl{60, 100, 25},
Name: "Olive",
},
{
Id: 4,
Hex: "#000080",
Rgb: Rgb{0, 0, 128},
Hsl: Hsl{240, 100, 25},
Name: "Navy",
},
{
Id: 5,
Hex: "#800080",
Rgb: Rgb{128, 0, 128},
Hsl: Hsl{300, 100, 25},
Name: "Purple",
},
{
Id: 6,
Hex: "#008080",
Rgb: Rgb{0, 128, 128},
Hsl: Hsl{180, 100, 25},
Name: "Teal",
},
{
Id: 7,
Hex: "#c0c0c0",
Rgb: Rgb{192, 192, 192},
Hsl: Hsl{0, 0, 75},
Name: "Silver",
},
{
Id: 8,
Hex: "#808080",
Rgb: Rgb{128, 128, 128},
Hsl: Hsl{0, 0, 50},
Name: "Grey",
},
{
Id: 9,
Hex: "#ff0000",
Rgb: Rgb{255, 0, 0},
Hsl: Hsl{0, 100, 50},
Name: "Red",
},
{
Id: 10,
Hex: "#00ff00",
Rgb: Rgb{0, 255, 0},
Hsl: Hsl{120, 100, 50},
Name: "Lime",
},
{
Id: 11,
Hex: "#ffff00",
Rgb: Rgb{255, 255, 0},
Hsl: Hsl{60, 100, 50},
Name: "Yellow",
},
{
Id: 12,
Hex: "#0000ff",
Rgb: Rgb{0, 0, 255},
Hsl: Hsl{240, 100, 50},
Name: "Blue",
},
{
Id: 13,
Hex: "#ff00ff",
Rgb: Rgb{255, 0, 255},
Hsl: Hsl{300, 100, 50},
Name: "Fuchsia",
},
{
Id: 14,
Hex: "#00ffff",
Rgb: Rgb{0, 255, 255},
Hsl: Hsl{180, 100, 50},
Name: "Aqua",
},
{
Id: 15,
Hex: "#ffffff",
Rgb: Rgb{255, 255, 255},
Hsl: Hsl{0, 0, 100},
Name: "White",
},
{
Id: 16,
Hex: "#000000",
Rgb: Rgb{0, 0, 0},
Hsl: Hsl{0, 0, 0},
Name: "Grey0",
},
{
Id: 17,
Hex: "#00005f",
Rgb: Rgb{0, 0, 95},
Hsl: Hsl{240, 100, 18},
Name: "NavyBlue",
},
{
Id: 18,
Hex: "#000087",
Rgb: Rgb{0, 0, 135},
Hsl: Hsl{240, 100, 26},
Name: "DarkBlue",
},
{
Id: 19,
Hex: "#0000af",
Rgb: Rgb{0, 0, 175},
Hsl: Hsl{240, 100, 34},
Name: "Blue3",
},
{
Id: 20,
Hex: "#0000d7",
Rgb: Rgb{0, 0, 215},
Hsl: Hsl{240, 100, 42},
Name: "Blue3",
},
{
Id: 21,
Hex: "#0000ff",
Rgb: Rgb{0, 0, 255},
Hsl: Hsl{240, 100, 50},
Name: "Blue1",
},
{
Id: 22,
Hex: "#005f00",
Rgb: Rgb{0, 95, 0},
Hsl: Hsl{120, 100, 18},
Name: "DarkGreen",
},
{
Id: 23,
Hex: "#005f5f",
Rgb: Rgb{0, 95, 95},
Hsl: Hsl{180, 100, 18},
Name: "DeepSkyBlue4",
},
{
Id: 24,
Hex: "#005f87",
Rgb: Rgb{0, 95, 135},
Hsl: Hsl{197.777777777778, 100, 26},
Name: "DeepSkyBlue4",
},
{
Id: 25,
Hex: "#005faf",
Rgb: Rgb{0, 95, 175},
Hsl: Hsl{207.428571428571, 100, 34},
Name: "DeepSkyBlue4",
},
{
Id: 26,
Hex: "#005fd7",
Rgb: Rgb{0, 95, 215},
Hsl: Hsl{213.488372093023, 100, 42},
Name: "DodgerBlue3",
},
{
Id: 27,
Hex: "#005fff",
Rgb: Rgb{0, 95, 255},
Hsl: Hsl{217.647058823529, 100, 50},
Name: "DodgerBlue2",
},
{
Id: 28,
Hex: "#008700",
Rgb: Rgb{0, 135, 0},
Hsl: Hsl{120, 100, 26},
Name: "Green4",
},
{
Id: 29,
Hex: "#00875f",
Rgb: Rgb{0, 135, 95},
Hsl: Hsl{162.222222222222, 100, 26},
Name: "SpringGreen4",
},
{
Id: 30,
Hex: "#008787",
Rgb: Rgb{0, 135, 135},
Hsl: Hsl{180, 100, 26},
Name: "Turquoise4",
},
{
Id: 31,
Hex: "#0087af",
Rgb: Rgb{0, 135, 175},
Hsl: Hsl{193.714285714286, 100, 34},
Name: "DeepSkyBlue3",
},
{
Id: 32,
Hex: "#0087d7",
Rgb: Rgb{0, 135, 215},
Hsl: Hsl{202.325581395349, 100, 42},
Name: "DeepSkyBlue3",
},
{
Id: 33,
Hex: "#0087ff",
Rgb: Rgb{0, 135, 255},
Hsl: Hsl{208.235294117647, 100, 50},
Name: "DodgerBlue1",
},
{
Id: 34,
Hex: "#00af00",
Rgb: Rgb{0, 175, 0},
Hsl: Hsl{120, 100, 34},
Name: "Green3",
},
{
Id: 35,
Hex: "#00af5f",
Rgb: Rgb{0, 175, 95},
Hsl: Hsl{152.571428571429, 100, 34},
Name: "SpringGreen3",
},
{
Id: 36,
Hex: "#00af87",
Rgb: Rgb{0, 175, 135},
Hsl: Hsl{166.285714285714, 100, 34},
Name: "DarkCyan",
},
{
Id: 37,
Hex: "#00afaf",
Rgb: Rgb{0, 175, 175},
Hsl: Hsl{180, 100, 34},
Name: "LightSeaGreen",
},
{
Id: 38,
Hex: "#00afd7",
Rgb: Rgb{0, 175, 215},
Hsl: Hsl{191.162790697674, 100, 42},
Name: "DeepSkyBlue2",
},
{
Id: 39,
Hex: "#00afff",
Rgb: Rgb{0, 175, 255},
Hsl: Hsl{198.823529411765, 100, 50},
Name: "DeepSkyBlue1",
},
{
Id: 40,
Hex: "#00d700",
Rgb: Rgb{0, 215, 0},
Hsl: Hsl{120, 100, 42},
Name: "Green3",
},
{
Id: 41,
Hex: "#00d75f",
Rgb: Rgb{0, 215, 95},
Hsl: Hsl{146.511627906977, 100, 42},
Name: "SpringGreen3",
},
{
Id: 42,
Hex: "#00d787",
Rgb: Rgb{0, 215, 135},
Hsl: Hsl{157.674418604651, 100, 42},
Name: "SpringGreen2",
},
{
Id: 43,
Hex: "#00d7af",
Rgb: Rgb{0, 215, 175},
Hsl: Hsl{168.837209302326, 100, 42},
Name: "Cyan3",
},
{
Id: 44,
Hex: "#00d7d7",
Rgb: Rgb{0, 215, 215},
Hsl: Hsl{180, 100, 42},
Name: "DarkTurquoise",
},
{
Id: 45,
Hex: "#00d7ff",
Rgb: Rgb{0, 215, 255},
Hsl: Hsl{189.411764705882, 100, 50},
Name: "Turquoise2",
},
{
Id: 46,
Hex: "#00ff00",
Rgb: Rgb{0, 255, 0},
Hsl: Hsl{120, 100, 50},
Name: "Green1",
},
{
Id: 47,
Hex: "#00ff5f",
Rgb: Rgb{0, 255, 95},
Hsl: Hsl{142.352941176471, 100, 50},
Name: "SpringGreen2",
},
{
Id: 48,
Hex: "#00ff87",
Rgb: Rgb{0, 255, 135},
Hsl: Hsl{151.764705882353, 100, 50},
Name: "SpringGreen1",
},
{
Id: 49,
Hex: "#00ffaf",
Rgb: Rgb{0, 255, 175},
Hsl: Hsl{161.176470588235, 100, 50},
Name: "MediumSpringGreen",
},
{
Id: 50,
Hex: "#00ffd7",
Rgb: Rgb{0, 255, 215},
Hsl: Hsl{170.588235294118, 100, 50},
Name: "Cyan2",
},
{
Id: 51,
Hex: "#00ffff",
Rgb: Rgb{0, 255, 255},
Hsl: Hsl{180, 100, 50},
Name: "Cyan1",
},
{
Id: 52,
Hex: "#5f0000",
Rgb: Rgb{95, 0, 0},
Hsl: Hsl{0, 100, 18},
Name: "DarkRed",
},
{
Id: 53,
Hex: "#5f005f",
Rgb: Rgb{95, 0, 95},
Hsl: Hsl{300, 100, 18},
Name: "DeepPink4",
},
{
Id: 54,
Hex: "#5f0087",
Rgb: Rgb{95, 0, 135},
Hsl: Hsl{282.222222222222, 100, 26},
Name: "Purple4",
},
{
Id: 55,
Hex: "#5f00af",
Rgb: Rgb{95, 0, 175},
Hsl: Hsl{272.571428571429, 100, 34},
Name: "Purple4",
},
{
Id: 56,
Hex: "#5f00d7",
Rgb: Rgb{95, 0, 215},
Hsl: Hsl{266.511627906977, 100, 42},
Name: "Purple3",
},
{
Id: 57,
Hex: "#5f00ff",
Rgb: Rgb{95, 0, 255},
Hsl: Hsl{262.352941176471, 100, 50},
Name: "BlueViolet",
},
{
Id: 58,
Hex: "#5f5f00",
Rgb: Rgb{95, 95, 0},
Hsl: Hsl{60, 100, 18},
Name: "Orange4",
},
{
Id: 59,
Hex: "#5f5f5f",
Rgb: Rgb{95, 95, 95},
Hsl: Hsl{0, 0, 37},
Name: "Grey37",
},
{
Id: 60,
Hex: "#5f5f87",
Rgb: Rgb{95, 95, 135},
Hsl: Hsl{240, 17, 45},
Name: "MediumPurple4",
},
{
Id: 61,
Hex: "#5f5faf",
Rgb: Rgb{95, 95, 175},
Hsl: Hsl{240, 33, 52},
Name: "SlateBlue3",
},
{
Id: 62,
Hex: "#5f5fd7",
Rgb: Rgb{95, 95, 215},
Hsl: Hsl{240, 60, 60},
Name: "SlateBlue3",
},
{
Id: 63,
Hex: "#5f5fff",
Rgb: Rgb{95, 95, 255},
Hsl: Hsl{240, 100, 68},
Name: "RoyalBlue1",
},
{
Id: 64,
Hex: "#5f8700",
Rgb: Rgb{95, 135, 0},
Hsl: Hsl{77.7777777777778, 100, 26},
Name: "Chartreuse4",
},
{
Id: 65,
Hex: "#5f875f",
Rgb: Rgb{95, 135, 95},
Hsl: Hsl{120, 17, 45},
Name: "DarkSeaGreen4",
},
{
Id: 66,
Hex: "#5f8787",
Rgb: Rgb{95, 135, 135},
Hsl: Hsl{180, 17, 45},
Name: "PaleTurquoise4",
},
{
Id: 67,
Hex: "#5f87af",
Rgb: Rgb{95, 135, 175},
Hsl: Hsl{210, 33, 52},
Name: "SteelBlue",
},
{
Id: 68,
Hex: "#5f87d7",
Rgb: Rgb{95, 135, 215},
Hsl: Hsl{220, 60, 60},
Name: "SteelBlue3",
},
{
Id: 69,
Hex: "#5f87ff",
Rgb: Rgb{95, 135, 255},
Hsl: Hsl{225, 100, 68},
Name: "CornflowerBlue",
},
{
Id: 70,
Hex: "#5faf00",
Rgb: Rgb{95, 175, 0},
Hsl: Hsl{87.4285714285714, 100, 34},
Name: "Chartreuse3",
},
{
Id: 71,
Hex: "#5faf5f",
Rgb: Rgb{95, 175, 95},
Hsl: Hsl{120, 33, 52},
Name: "DarkSeaGreen4",
},
{
Id: 72,
Hex: "#5faf87",
Rgb: Rgb{95, 175, 135},
Hsl: Hsl{150, 33, 52},
Name: "CadetBlue",
},
{
Id: 73,
Hex: "#5fafaf",
Rgb: Rgb{95, 175, 175},
Hsl: Hsl{180, 33, 52},
Name: "CadetBlue",
},
{
Id: 74,
Hex: "#5fafd7",
Rgb: Rgb{95, 175, 215},
Hsl: Hsl{200, 60, 60},
Name: "SkyBlue3",
},
{
Id: 75,
Hex: "#5fafff",
Rgb: Rgb{95, 175, 255},
Hsl: Hsl{210, 100, 68},
Name: "SteelBlue1",
},
{
Id: 76,
Hex: "#5fd700",
Rgb: Rgb{95, 215, 0},
Hsl: Hsl{93.4883720930233, 100, 42},
Name: "Chartreuse3",
},
{
Id: 77,
Hex: "#5fd75f",
Rgb: Rgb{95, 215, 95},
Hsl: Hsl{120, 60, 60},
Name: "PaleGreen3",
},
{
Id: 78,
Hex: "#5fd787",
Rgb: Rgb{95, 215, 135},
Hsl: Hsl{140, 60, 60},
Name: "SeaGreen3",
},
{
Id: 79,
Hex: "#5fd7af",
Rgb: Rgb{95, 215, 175},
Hsl: Hsl{160, 60, 60},
Name: "Aquamarine3",
},
{
Id: 80,
Hex: "#5fd7d7",
Rgb: Rgb{95, 215, 215},
Hsl: Hsl{180, 60, 60},
Name: "MediumTurquoise",
},
{
Id: 81,
Hex: "#5fd7ff",
Rgb: Rgb{95, 215, 255},
Hsl: Hsl{195, 100, 68},
Name: "SteelBlue1",
},
{
Id: 82,
Hex: "#5fff00",
Rgb: Rgb{95, 255, 0},
Hsl: Hsl{97.6470588235294, 100, 50},
Name: "Chartreuse2",
},
{
Id: 83,
Hex: "#5fff5f",
Rgb: Rgb{95, 255, 95},
Hsl: Hsl{120, 100, 68},
Name: "SeaGreen2",
},
{
Id: 84,
Hex: "#5fff87",
Rgb: Rgb{95, 255, 135},
Hsl: Hsl{135, 100, 68},
Name: "SeaGreen1",
},
{
Id: 85,
Hex: "#5fffaf",
Rgb: Rgb{95, 255, 175},
Hsl: Hsl{150, 100, 68},
Name: "SeaGreen1",
},
{
Id: 86,
Hex: "#5fffd7",
Rgb: Rgb{95, 255, 215},
Hsl: Hsl{165, 100, 68},
Name: "Aquamarine1",
},
{
Id: 87,
Hex: "#5fffff",
Rgb: Rgb{95, 255, 255},
Hsl: Hsl{180, 100, 68},
Name: "DarkSlateGray2",
},
{
Id: 88,
Hex: "#870000",
Rgb: Rgb{135, 0, 0},
Hsl: Hsl{0, 100, 26},
Name: "DarkRed",
},
{
Id: 89,
Hex: "#87005f",
Rgb: Rgb{135, 0, 95},
Hsl: Hsl{317.777777777778, 100, 26},
Name: "DeepPink4",
},
{
Id: 90,
Hex: "#870087",
Rgb: Rgb{135, 0, 135},
Hsl: Hsl{300, 100, 26},
Name: "DarkMagenta",
},
{
Id: 91,
Hex: "#8700af",
Rgb: Rgb{135, 0, 175},
Hsl: Hsl{286.285714285714, 100, 34},
Name: "DarkMagenta",
},
{
Id: 92,
Hex: "#8700d7",
Rgb: Rgb{135, 0, 215},
Hsl: Hsl{277.674418604651, 100, 42},
Name: "DarkViolet",
},
{
Id: 93,
Hex: "#8700ff",
Rgb: Rgb{135, 0, 255},
Hsl: Hsl{271.764705882353, 100, 50},
Name: "Purple",
},
{
Id: 94,
Hex: "#875f00",
Rgb: Rgb{135, 95, 0},
Hsl: Hsl{42.2222222222222, 100, 26},
Name: "Orange4",
},
{
Id: 95,
Hex: "#875f5f",
Rgb: Rgb{135, 95, 95},
Hsl: Hsl{0, 17, 45},
Name: "LightPink4",
},
{
Id: 96,
Hex: "#875f87",
Rgb: Rgb{135, 95, 135},
Hsl: Hsl{300, 17, 45},
Name: "Plum4",
},
{
Id: 97,
Hex: "#875faf",
Rgb: Rgb{135, 95, 175},
Hsl: Hsl{270, 33, 52},
Name: "MediumPurple3",
},
{
Id: 98,
Hex: "#875fd7",
Rgb: Rgb{135, 95, 215},
Hsl: Hsl{260, 60, 60},
Name: "MediumPurple3",
},
{
Id: 99,
Hex: "#875fff",
Rgb: Rgb{135, 95, 255},
Hsl: Hsl{255, 100, 68},
Name: "SlateBlue1",
},
{
Id: 100,
Hex: "#878700",
Rgb: Rgb{135, 135, 0},
Hsl: Hsl{60, 100, 26},
Name: "Yellow4",
},
{
Id: 101,
Hex: "#87875f",
Rgb: Rgb{135, 135, 95},
Hsl: Hsl{60, 17, 45},
Name: "Wheat4",
},
{
Id: 102,
Hex: "#878787",
Rgb: Rgb{135, 135, 135},
Hsl: Hsl{0, 0, 52},
Name: "Grey53",
},
{
Id: 103,
Hex: "#8787af",
Rgb: Rgb{135, 135, 175},
Hsl: Hsl{240, 20, 60},
Name: "LightSlateGrey",
},
{
Id: 104,
Hex: "#8787d7",
Rgb: Rgb{135, 135, 215},
Hsl: Hsl{240, 50, 68},
Name: "MediumPurple",
},
{
Id: 105,
Hex: "#8787ff",
Rgb: Rgb{135, 135, 255},
Hsl: Hsl{240, 100, 76},
Name: "LightSlateBlue",
},
{
Id: 106,
Hex: "#87af00",
Rgb: Rgb{135, 175, 0},
Hsl: Hsl{73.7142857142857, 100, 34},
Name: "Yellow4",
},
{
Id: 107,
Hex: "#87af5f",
Rgb: Rgb{135, 175, 95},
Hsl: Hsl{90, 33, 52},
Name: "DarkOliveGreen3",
},
{
Id: 108,
Hex: "#87af87",
Rgb: Rgb{135, 175, 135},
Hsl: Hsl{120, 20, 60},
Name: "DarkSeaGreen",
},
{
Id: 109,
Hex: "#87afaf",
Rgb: Rgb{135, 175, 175},
Hsl: Hsl{180, 20, 60},
Name: "LightSkyBlue3",
},
{
Id: 110,
Hex: "#87afd7",
Rgb: Rgb{135, 175, 215},
Hsl: Hsl{210, 50, 68},
Name: "LightSkyBlue3",
},
{
Id: 111,
Hex: "#87afff",
Rgb: Rgb{135, 175, 255},
Hsl: Hsl{220, 100, 76},
Name: "SkyBlue2",
},
{
Id: 112,
Hex: "#87d700",
Rgb: Rgb{135, 215, 0},
Hsl: Hsl{82.3255813953488, 100, 42},
Name: "Chartreuse2",
},
{
Id: 113,
Hex: "#87d75f",
Rgb: Rgb{135, 215, 95},
Hsl: Hsl{100, 60, 60},
Name: "DarkOliveGreen3",
},
{
Id: 114,
Hex: "#87d787",
Rgb: Rgb{135, 215, 135},
Hsl: Hsl{120, 50, 68},
Name: "PaleGreen3",
},
{
Id: 115,
Hex: "#87d7af",
Rgb: Rgb{135, 215, 175},
Hsl: Hsl{150, 50, 68},
Name: "DarkSeaGreen3",
},
{
Id: 116,
Hex: "#87d7d7",
Rgb: Rgb{135, 215, 215},
Hsl: Hsl{180, 50, 68},
Name: "DarkSlateGray3",
},
{
Id: 117,
Hex: "#87d7ff",
Rgb: Rgb{135, 215, 255},
Hsl: Hsl{200, 100, 76},
Name: "SkyBlue1",
},
{
Id: 118,
Hex: "#87ff00",
Rgb: Rgb{135, 255, 0},
Hsl: Hsl{88.2352941176471, 100, 50},
Name: "Chartreuse1",
},
{
Id: 119,
Hex: "#87ff5f",
Rgb: Rgb{135, 255, 95},
Hsl: Hsl{105, 100, 68},
Name: "LightGreen",
},
{
Id: 120,
Hex: "#87ff87",
Rgb: Rgb{135, 255, 135},
Hsl: Hsl{120, 100, 76},
Name: "LightGreen",
},
{
Id: 121,
Hex: "#87ffaf",
Rgb: Rgb{135, 255, 175},
Hsl: Hsl{140, 100, 76},
Name: "PaleGreen1",
},
{
Id: 122,
Hex: "#87ffd7",
Rgb: Rgb{135, 255, 215},
Hsl: Hsl{160, 100, 76},
Name: "Aquamarine1",
},
{
Id: 123,
Hex: "#87ffff",
Rgb: Rgb{135, 255, 255},
Hsl: Hsl{180, 100, 76},
Name: "DarkSlateGray1",
},
{
Id: 124,
Hex: "#af0000",
Rgb: Rgb{175, 0, 0},
Hsl: Hsl{0, 100, 34},
Name: "Red3",
},
{
Id: 125,
Hex: "#af005f",
Rgb: Rgb{175, 0, 95},
Hsl: Hsl{327.428571428571, 100, 34},
Name: "DeepPink4",
},
{
Id: 126,
Hex: "#af0087",
Rgb: Rgb{175, 0, 135},
Hsl: Hsl{313.714285714286, 100, 34},
Name: "MediumVioletRed",
},
{
Id: 127,
Hex: "#af00af",
Rgb: Rgb{175, 0, 175},
Hsl: Hsl{300, 100, 34},
Name: "Magenta3",
},
{
Id: 128,
Hex: "#af00d7",
Rgb: Rgb{175, 0, 215},
Hsl: Hsl{288.837209302326, 100, 42},
Name: "DarkViolet",
},
{
Id: 129,
Hex: "#af00ff",
Rgb: Rgb{175, 0, 255},
Hsl: Hsl{281.176470588235, 100, 50},
Name: "Purple",
},
{
Id: 130,
Hex: "#af5f00",
Rgb: Rgb{175, 95, 0},
Hsl: Hsl{32.5714285714286, 100, 34},
Name: "DarkOrange3",
},
{
Id: 131,
Hex: "#af5f5f",
Rgb: Rgb{175, 95, 95},
Hsl: Hsl{0, 33, 52},
Name: "IndianRed",
},
{
Id: 132,
Hex: "#af5f87",
Rgb: Rgb{175, 95, 135},
Hsl: Hsl{330, 33, 52},
Name: "HotPink3",
},
{
Id: 133,
Hex: "#af5faf",
Rgb: Rgb{175, 95, 175},
Hsl: Hsl{300, 33, 52},
Name: "MediumOrchid3",
},
{
Id: 134,
Hex: "#af5fd7",
Rgb: Rgb{175, 95, 215},
Hsl: Hsl{280, 60, 60},
Name: "MediumOrchid",
},
{
Id: 135,
Hex: "#af5fff",
Rgb: Rgb{175, 95, 255},
Hsl: Hsl{270, 100, 68},
Name: "MediumPurple2",
},
{
Id: 136,
Hex: "#af8700",
Rgb: Rgb{175, 135, 0},
Hsl: Hsl{46.2857142857143, 100, 34},
Name: "DarkGoldenrod",
},
{
Id: 137,
Hex: "#af875f",
Rgb: Rgb{175, 135, 95},
Hsl: Hsl{30, 33, 52},
Name: "LightSalmon3",
},
{
Id: 138,
Hex: "#af8787",
Rgb: Rgb{175, 135, 135},
Hsl: Hsl{0, 20, 60},
Name: "RosyBrown",
},
{
Id: 139,
Hex: "#af87af",
Rgb: Rgb{175, 135, 175},
Hsl: Hsl{300, 20, 60},
Name: "Grey63",
},
{
Id: 140,
Hex: "#af87d7",
Rgb: Rgb{175, 135, 215},
Hsl: Hsl{270, 50, 68},
Name: "MediumPurple2",
},
{
Id: 141,
Hex: "#af87ff",
Rgb: Rgb{175, 135, 255},
Hsl: Hsl{260, 100, 76},
Name: "MediumPurple1",
},
{
Id: 142,
Hex: "#afaf00",
Rgb: Rgb{175, 175, 0},
Hsl: Hsl{60, 100, 34},
Name: "Gold3",
},
{
Id: 143,
Hex: "#afaf5f",
Rgb: Rgb{175, 175, 95},
Hsl: Hsl{60, 33, 52},
Name: "DarkKhaki",
},
{
Id: 144,
Hex: "#afaf87",
Rgb: Rgb{175, 175, 135},
Hsl: Hsl{60, 20, 60},
Name: "NavajoWhite3",
},
{
Id: 145,
Hex: "#afafaf",
Rgb: Rgb{175, 175, 175},
Hsl: Hsl{0, 0, 68},
Name: "Grey69",
},
{
Id: 146,
Hex: "#afafd7",
Rgb: Rgb{175, 175, 215},
Hsl: Hsl{240, 33, 76},
Name: "LightSteelBlue3",
},
{
Id: 147,
Hex: "#afafff",
Rgb: Rgb{175, 175, 255},
Hsl: Hsl{240, 100, 84},
Name: "LightSteelBlue",
},
{
Id: 148,
Hex: "#afd700",
Rgb: Rgb{175, 215, 0},
Hsl: Hsl{71.1627906976744, 100, 42},
Name: "Yellow3",
},
{
Id: 149,
Hex: "#afd75f",
Rgb: Rgb{175, 215, 95},
Hsl: Hsl{80, 60, 60},
Name: "DarkOliveGreen3",
},
{
Id: 150,
Hex: "#afd787",
Rgb: Rgb{175, 215, 135},
Hsl: Hsl{90, 50, 68},
Name: "DarkSeaGreen3",
},
{
Id: 151,
Hex: "#afd7af",
Rgb: Rgb{175, 215, 175},
Hsl: Hsl{120, 33, 76},
Name: "DarkSeaGreen2",
},
{
Id: 152,
Hex: "#afd7d7",
Rgb: Rgb{175, 215, 215},
Hsl: Hsl{180, 33, 76},
Name: "LightCyan3",
},
{
Id: 153,
Hex: "#afd7ff",
Rgb: Rgb{175, 215, 255},
Hsl: Hsl{210, 100, 84},
Name: "LightSkyBlue1",
},
{
Id: 154,
Hex: "#afff00",
Rgb: Rgb{175, 255, 0},
Hsl: Hsl{78.8235294117647, 100, 50},
Name: "GreenYellow",
},
{
Id: 155,
Hex: "#afff5f",
Rgb: Rgb{175, 255, 95},
Hsl: Hsl{90, 100, 68},
Name: "DarkOliveGreen2",
},
{
Id: 156,
Hex: "#afff87",
Rgb: Rgb{175, 255, 135},
Hsl: Hsl{100, 100, 76},
Name: "PaleGreen1",
},
{
Id: 157,
Hex: "#afffaf",
Rgb: Rgb{175, 255, 175},
Hsl: Hsl{120, 100, 84},
Name: "DarkSeaGreen2",
},
{
Id: 158,
Hex: "#afffd7",
Rgb: Rgb{175, 255, 215},
Hsl: Hsl{150, 100, 84},
Name: "DarkSeaGreen1",
},
{
Id: 159,
Hex: "#afffff",
Rgb: Rgb{175, 255, 255},
Hsl: Hsl{180, 100, 84},
Name: "PaleTurquoise1",
},
{
Id: 160,
Hex: "#d70000",
Rgb: Rgb{215, 0, 0},
Hsl: Hsl{0, 100, 42},
Name: "Red3",
},
{
Id: 161,
Hex: "#d7005f",
Rgb: Rgb{215, 0, 95},
Hsl: Hsl{333.488372093023, 100, 42},
Name: "DeepPink3",
},
{
Id: 162,
Hex: "#d70087",
Rgb: Rgb{215, 0, 135},
Hsl: Hsl{322.325581395349, 100, 42},
Name: "DeepPink3",
},
{
Id: 163,
Hex: "#d700af",
Rgb: Rgb{215, 0, 175},
Hsl: Hsl{311.162790697674, 100, 42},
Name: "Magenta3",
},
{
Id: 164,
Hex: "#d700d7",
Rgb: Rgb{215, 0, 215},
Hsl: Hsl{300, 100, 42},
Name: "Magenta3",
},
{
Id: 165,
Hex: "#d700ff",
Rgb: Rgb{215, 0, 255},
Hsl: Hsl{290.588235294118, 100, 50},
Name: "Magenta2",
},
{
Id: 166,
Hex: "#d75f00",
Rgb: Rgb{215, 95, 0},
Hsl: Hsl{26.5116279069767, 100, 42},
Name: "DarkOrange3",
},
{
Id: 167,
Hex: "#d75f5f",
Rgb: Rgb{215, 95, 95},
Hsl: Hsl{0, 60, 60},
Name: "IndianRed",
},
{
Id: 168,
Hex: "#d75f87",
Rgb: Rgb{215, 95, 135},
Hsl: Hsl{340, 60, 60},
Name: "HotPink3",
},
{
Id: 169,
Hex: "#d75faf",
Rgb: Rgb{215, 95, 175},
Hsl: Hsl{320, 60, 60},
Name: "HotPink2",
},
{
Id: 170,
Hex: "#d75fd7",
Rgb: Rgb{215, 95, 215},
Hsl: Hsl{300, 60, 60},
Name: "Orchid",
},
{
Id: 171,
Hex: "#d75fff",
Rgb: Rgb{215, 95, 255},
Hsl: Hsl{285, 100, 68},
Name: "MediumOrchid1",
},
{
Id: 172,
Hex: "#d78700",
Rgb: Rgb{215, 135, 0},
Hsl: Hsl{37.6744186046512, 100, 42},
Name: "Orange3",
},
{
Id: 173,
Hex: "#d7875f",
Rgb: Rgb{215, 135, 95},
Hsl: Hsl{20, 60, 60},
Name: "LightSalmon3",
},
{
Id: 174,
Hex: "#d78787",
Rgb: Rgb{215, 135, 135},
Hsl: Hsl{0, 50, 68},
Name: "LightPink3",
},
{
Id: 175,
Hex: "#d787af",
Rgb: Rgb{215, 135, 175},
Hsl: Hsl{330, 50, 68},
Name: "Pink3",
},
{
Id: 176,
Hex: "#d787d7",
Rgb: Rgb{215, 135, 215},
Hsl: Hsl{300, 50, 68},
Name: "Plum3",
},
{
Id: 177,
Hex: "#d787ff",
Rgb: Rgb{215, 135, 255},
Hsl: Hsl{280, 100, 76},
Name: "Violet",
},
{
Id: 178,
Hex: "#d7af00",
Rgb: Rgb{215, 175, 0},
Hsl: Hsl{48.8372093023256, 100, 42},
Name: "Gold3",
},
{
Id: 179,
Hex: "#d7af5f",
Rgb: Rgb{215, 175, 95},
Hsl: Hsl{40, 60, 60},
Name: "LightGoldenrod3",
},
{
Id: 180,
Hex: "#d7af87",
Rgb: Rgb{215, 175, 135},
Hsl: Hsl{30, 50, 68},
Name: "Tan",
},
{
Id: 181,
Hex: "#d7afaf",
Rgb: Rgb{215, 175, 175},
Hsl: Hsl{0, 33, 76},
Name: "MistyRose3",
},
{
Id: 182,
Hex: "#d7afd7",
Rgb: Rgb{215, 175, 215},
Hsl: Hsl{300, 33, 76},
Name: "Thistle3",
},
{
Id: 183,
Hex: "#d7afff",
Rgb: Rgb{215, 175, 255},
Hsl: Hsl{270, 100, 84},
Name: "Plum2",
},
{
Id: 184,
Hex: "#d7d700",
Rgb: Rgb{215, 215, 0},
Hsl: Hsl{60, 100, 42},
Name: "Yellow3",
},
{
Id: 185,
Hex: "#d7d75f",
Rgb: Rgb{215, 215, 95},
Hsl: Hsl{60, 60, 60},
Name: "Khaki3",
},
{
Id: 186,
Hex: "#d7d787",
Rgb: Rgb{215, 215, 135},
Hsl: Hsl{60, 50, 68},
Name: "LightGoldenrod2",
},
{
Id: 187,
Hex: "#d7d7af",
Rgb: Rgb{215, 215, 175},
Hsl: Hsl{60, 33, 76},
Name: "LightYellow3",
},
{
Id: 188,
Hex: "#d7d7d7",
Rgb: Rgb{215, 215, 215},
Hsl: Hsl{0, 0, 84},
Name: "Grey84",
},
{
Id: 189,
Hex: "#d7d7ff",
Rgb: Rgb{215, 215, 255},
Hsl: Hsl{240, 100, 92},
Name: "LightSteelBlue1",
},
{
Id: 190,
Hex: "#d7ff00",
Rgb: Rgb{215, 255, 0},
Hsl: Hsl{69.4117647058823, 100, 50},
Name: "Yellow2",
},
{
Id: 191,
Hex: "#d7ff5f",
Rgb: Rgb{215, 255, 95},
Hsl: Hsl{75, 100, 68},
Name: "DarkOliveGreen1",
},
{
Id: 192,
Hex: "#d7ff87",
Rgb: Rgb{215, 255, 135},
Hsl: Hsl{80, 100, 76},
Name: "DarkOliveGreen1",
},
{
Id: 193,
Hex: "#d7ffaf",
Rgb: Rgb{215, 255, 175},
Hsl: Hsl{90, 100, 84},
Name: "DarkSeaGreen1",
},
{
Id: 194,
Hex: "#d7ffd7",
Rgb: Rgb{215, 255, 215},
Hsl: Hsl{120, 100, 92},
Name: "Honeydew2",
},
{
Id: 195,
Hex: "#d7ffff",
Rgb: Rgb{215, 255, 255},
Hsl: Hsl{180, 100, 92},
Name: "LightCyan1",
},
{
Id: 196,
Hex: "#ff0000",
Rgb: Rgb{255, 0, 0},
Hsl: Hsl{0, 100, 50},
Name: "Red1",
},
{
Id: 197,
Hex: "#ff005f",
Rgb: Rgb{255, 0, 95},
Hsl: Hsl{337.647058823529, 100, 50},
Name: "DeepPink2",
},
{
Id: 198,
Hex: "#ff0087",
Rgb: Rgb{255, 0, 135},
Hsl: Hsl{328.235294117647, 100, 50},
Name: "DeepPink1",
},
{
Id: 199,
Hex: "#ff00af",
Rgb: Rgb{255, 0, 175},
Hsl: Hsl{318.823529411765, 100, 50},
Name: "DeepPink1",
},
{
Id: 200,
Hex: "#ff00d7",
Rgb: Rgb{255, 0, 215},
Hsl: Hsl{309.411764705882, 100, 50},
Name: "Magenta2",
},
{
Id: 201,
Hex: "#ff00ff",
Rgb: Rgb{255, 0, 255},
Hsl: Hsl{300, 100, 50},
Name: "Magenta1",
},
{
Id: 202,
Hex: "#ff5f00",
Rgb: Rgb{255, 95, 0},
Hsl: Hsl{22.3529411764706, 100, 50},
Name: "OrangeRed1",
},
{
Id: 203,
Hex: "#ff5f5f",
Rgb: Rgb{255, 95, 95},
Hsl: Hsl{0, 100, 68},
Name: "IndianRed1",
},
{
Id: 204,
Hex: "#ff5f87",
Rgb: Rgb{255, 95, 135},
Hsl: Hsl{345, 100, 68},
Name: "IndianRed1",
},
{
Id: 205,
Hex: "#ff5faf",
Rgb: Rgb{255, 95, 175},
Hsl: Hsl{330, 100, 68},
Name: "HotPink",
},
{
Id: 206,
Hex: "#ff5fd7",
Rgb: Rgb{255, 95, 215},
Hsl: Hsl{315, 100, 68},
Name: "HotPink",
},
{
Id: 207,
Hex: "#ff5fff",
Rgb: Rgb{255, 95, 255},
Hsl: Hsl{300, 100, 68},
Name: "MediumOrchid1",
},
{
Id: 208,
Hex: "#ff8700",
Rgb: Rgb{255, 135, 0},
Hsl: Hsl{31.7647058823529, 100, 50},
Name: "DarkOrange",
},
{
Id: 209,
Hex: "#ff875f",
Rgb: Rgb{255, 135, 95},
Hsl: Hsl{15, 100, 68},
Name: "Salmon1",
},
{
Id: 210,
Hex: "#ff8787",
Rgb: Rgb{255, 135, 135},
Hsl: Hsl{0, 100, 76},
Name: "LightCoral",
},
{
Id: 211,
Hex: "#ff87af",
Rgb: Rgb{255, 135, 175},
Hsl: Hsl{340, 100, 76},
Name: "PaleVioletRed1",
},
{
Id: 212,
Hex: "#ff87d7",
Rgb: Rgb{255, 135, 215},
Hsl: Hsl{320, 100, 76},
Name: "Orchid2",
},
{
Id: 213,
Hex: "#ff87ff",
Rgb: Rgb{255, 135, 255},
Hsl: Hsl{300, 100, 76},
Name: "Orchid1",
},
{
Id: 214,
Hex: "#ffaf00",
Rgb: Rgb{255, 175, 0},
Hsl: Hsl{41.1764705882353, 100, 50},
Name: "Orange1",
},
{
Id: 215,
Hex: "#ffaf5f",
Rgb: Rgb{255, 175, 95},
Hsl: Hsl{30, 100, 68},
Name: "SandyBrown",
},
{
Id: 216,
Hex: "#ffaf87",
Rgb: Rgb{255, 175, 135},
Hsl: Hsl{20, 100, 76},
Name: "LightSalmon1",
},
{
Id: 217,
Hex: "#ffafaf",
Rgb: Rgb{255, 175, 175},
Hsl: Hsl{0, 100, 84},
Name: "LightPink1",
},
{
Id: 218,
Hex: "#ffafd7",
Rgb: Rgb{255, 175, 215},
Hsl: Hsl{330, 100, 84},
Name: "Pink1",
},
{
Id: 219,
Hex: "#ffafff",
Rgb: Rgb{255, 175, 255},
Hsl: Hsl{300, 100, 84},
Name: "Plum1",
},
{
Id: 220,
Hex: "#ffd700",
Rgb: Rgb{255, 215, 0},
Hsl: Hsl{50.5882352941176, 100, 50},
Name: "Gold1",
},
{
Id: 221,
Hex: "#ffd75f",
Rgb: Rgb{255, 215, 95},
Hsl: Hsl{45, 100, 68},
Name: "LightGoldenrod2",
},
{
Id: 222,
Hex: "#ffd787",
Rgb: Rgb{255, 215, 135},
Hsl: Hsl{40, 100, 76},
Name: "LightGoldenrod2",
},
{
Id: 223,
Hex: "#ffd7af",
Rgb: Rgb{255, 215, 175},
Hsl: Hsl{30, 100, 84},
Name: "NavajoWhite1",
},
{
Id: 224,
Hex: "#ffd7d7",
Rgb: Rgb{255, 215, 215},
Hsl: Hsl{0, 100, 92},
Name: "MistyRose1",
},
{
Id: 225,
Hex: "#ffd7ff",
Rgb: Rgb{255, 215, 255},
Hsl: Hsl{300, 100, 92},
Name: "Thistle1",
},
{
Id: 226,
Hex: "#ffff00",
Rgb: Rgb{255, 255, 0},
Hsl: Hsl{60, 100, 50},
Name: "Yellow1",
},
{
Id: 227,
Hex: "#ffff5f",
Rgb: Rgb{255, 255, 95},
Hsl: Hsl{60, 100, 68},
Name: "LightGoldenrod1",
},
{
Id: 228,
Hex: "#ffff87",
Rgb: Rgb{255, 255, 135},
Hsl: Hsl{60, 100, 76},
Name: "Khaki1",
},
{
Id: 229,
Hex: "#ffffaf",
Rgb: Rgb{255, 255, 175},
Hsl: Hsl{60, 100, 84},
Name: "Wheat1",
},
{
Id: 230,
Hex: "#ffffd7",
Rgb: Rgb{255, 255, 215},
Hsl: Hsl{60, 100, 92},
Name: "Cornsilk1",
},
{
Id: 231,
Hex: "#ffffff",
Rgb: Rgb{255, 255, 255},
Hsl: Hsl{0, 0, 100},
Name: "Grey100",
},
{
Id: 232,
Hex: "#080808",
Rgb: Rgb{8, 8, 8},
Hsl: Hsl{0, 0, 3},
Name: "Grey3",
},
{
Id: 233,
Hex: "#121212",
Rgb: Rgb{18, 18, 18},
Hsl: Hsl{0, 0, 7},
Name: "Grey7",
},
{
Id: 234,
Hex: "#1c1c1c",
Rgb: Rgb{28, 28, 28},
Hsl: Hsl{0, 0, 10},
Name: "Grey11",
},
{
Id: 235,
Hex: "#262626",
Rgb: Rgb{38, 38, 38},
Hsl: Hsl{0, 0, 14},
Name: "Grey15",
},
{
Id: 236,
Hex: "#303030",
Rgb: Rgb{48, 48, 48},
Hsl: Hsl{0, 0, 18},
Name: "Grey19",
},
{
Id: 237,
Hex: "#3a3a3a",
Rgb: Rgb{58, 58, 58},
Hsl: Hsl{0, 0, 22},
Name: "Grey23",
},
{
Id: 238,
Hex: "#444444",
Rgb: Rgb{68, 68, 68},
Hsl: Hsl{0, 0, 26},
Name: "Grey27",
},
{
Id: 239,
Hex: "#4e4e4e",
Rgb: Rgb{78, 78, 78},
Hsl: Hsl{0, 0, 30},
Name: "Grey30",
},
{
Id: 240,
Hex: "#585858",
Rgb: Rgb{88, 88, 88},
Hsl: Hsl{0, 0, 34},
Name: "Grey35",
},
{
Id: 241,
Hex: "#626262",
Rgb: Rgb{98, 98, 98},
Hsl: Hsl{0, 0, 37},
Name: "Grey39",
},
{
Id: 242,
Hex: "#6c6c6c",
Rgb: Rgb{108, 108, 108},
Hsl: Hsl{0, 0, 40},
Name: "Grey42",
},
{
Id: 243,
Hex: "#767676",
Rgb: Rgb{118, 118, 118},
Hsl: Hsl{0, 0, 46},
Name: "Grey46",
},
{
Id: 244,
Hex: "#808080",
Rgb: Rgb{128, 128, 128},
Hsl: Hsl{0, 0, 50},
Name: "Grey50",
},
{
Id: 245,
Hex: "#8a8a8a",
Rgb: Rgb{138, 138, 138},
Hsl: Hsl{0, 0, 54},
Name: "Grey54",
},
{
Id: 246,
Hex: "#949494",
Rgb: Rgb{148, 148, 148},
Hsl: Hsl{0, 0, 58},
Name: "Grey58",
},
{
Id: 247,
Hex: "#9e9e9e",
Rgb: Rgb{158, 158, 158},
Hsl: Hsl{0, 0, 61},
Name: "Grey62",
},
{
Id: 248,
Hex: "#a8a8a8",
Rgb: Rgb{168, 168, 168},
Hsl: Hsl{0, 0, 65},
Name: "Grey66",
},
{
Id: 249,
Hex: "#b2b2b2",
Rgb: Rgb{178, 178, 178},
Hsl: Hsl{0, 0, 69},
Name: "Grey70",
},
{
Id: 250,
Hex: "#bcbcbc",
Rgb: Rgb{188, 188, 188},
Hsl: Hsl{0, 0, 73},
Name: "Grey74",
},
{
Id: 251,
Hex: "#c6c6c6",
Rgb: Rgb{198, 198, 198},
Hsl: Hsl{0, 0, 77},
Name: "Grey78",
},
{
Id: 252,
Hex: "#d0d0d0",
Rgb: Rgb{208, 208, 208},
Hsl: Hsl{0, 0, 81},
Name: "Grey82",
},
{
Id: 253,
Hex: "#dadada",
Rgb: Rgb{218, 218, 218},
Hsl: Hsl{0, 0, 85},
Name: "Grey85",
},
{
Id: 254,
Hex: "#e4e4e4",
Rgb: Rgb{228, 228, 228},
Hsl: Hsl{0, 0, 89},
Name: "Grey89",
},
{
Id: 255,
Hex: "#eeeeee",
Rgb: Rgb{238, 238, 238},
Hsl: Hsl{0, 0, 93},
Name: "Grey93",
},
}
golang-github-leaanthony-go-ansi-parser-1.6.1/go.mod 0000664 0000000 0000000 00000000177 15202373470 0022351 0 ustar 00root root 0000000 0000000 module github.com/leaanthony/go-ansi-parser
go 1.16
require (
github.com/matryer/is v1.4.0
github.com/rivo/uniseg v0.2.0
)
golang-github-leaanthony-go-ansi-parser-1.6.1/go.sum 0000664 0000000 0000000 00000000504 15202373470 0022370 0 ustar 00root root 0000000 0000000 github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang-github-leaanthony-go-ansi-parser-1.6.1/logo.png 0000664 0000000 0000000 00000024172 15202373470 0022712 0 ustar 00root root 0000000 0000000 PNG
IHDR D PX PLTE 333TTTGGGfffppp555\\\888֘ NNNxxx::: mmmiii|||JJJ @@@ ===444sssEEE dddYYYRRR ``` ]]]
VVVbbbBBB <<< Ϲ --- [[[111 '''### п ʺ Q %wIDATx `'(/:>ʵ@Q ĄH] A081ttq0q4qޗѽ/-\Υܣg(Á%""""""""""""""""""""""""""""""""""""""""""zR[+A-a825SߚY_ՋLC#w)Gʣfmp6;BD-Z$ljp;oUpO1[$\-ad"fbn QJb
Q|~Z"A3O3p+DEc8@tG(tb QlbۀQDeU(F:E^_D1$M@("
$;VQl+$z/E ^QB(rS<(+D@nF ۔YAVbɂ[I?>GŘUSE N%vaZ
Ÿjp$O2x Q}(`+)j'HKi(noEϪH\HY6L4pSH(b.l,OB۽` Sa(+Fq hEYNHU+-
00R}ba9-6-^DN-t
RbrZ)=~"lBD`9taz-`:RbRE[`y#:h90%ӣxˉRaM_K9EٚRekz$a)EqQ$z4;s.aJ%])1=K#uFK1
Q