Skip to content

Commit

Permalink
Add support for builder spec 0.11.0-dev
Browse files Browse the repository at this point in the history
This adds support for a number of things:

* Different scheme families
* New universal palette scheme format
* scheme-slug-underscored is now official
* New filename option in template config
  • Loading branch information
belak committed Jul 12, 2022
1 parent aa52ccf commit d505a40
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 83 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ require (
github.com/cbroglie/mustache v1.3.1
github.com/nlepage/go-tarfs v1.1.0
github.com/sirupsen/logrus v1.8.1
golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nlepage/go-tarfs v1.1.0 h1:bsACOiZMB/zFjYG/sE01070i9Fl26MnRpw0L6WuyfVs=
github.com/nlepage/go-tarfs v1.1.0/go.mod h1:IhxRcLhLkawBetnwu/JNuoPkq/6cclAllhgEa6SmzS8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -20,12 +20,14 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983 h1:sUweFwmLOje8KNfXAVqGGAsmgJ/F8jJ6wBLJDt4BTKY=
golang.org/x/exp v0.0.0-20220706164943-b4a6d9510983/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/sirupsen/logrus"
)

//go:embed schemes/*.yaml
//go:embed schemes/*/*.yaml
var schemesFS embed.FS

var (
Expand Down
204 changes: 143 additions & 61 deletions scheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,36 @@ import (
yaml "gopkg.in/yaml.v3"
)

var bases = []string{
"00", "01", "02", "03", "04", "05", "06", "07",
"08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
var base16Bases = []string{
"base00", "base01", "base02", "base03", "base04", "base05", "base06", "base07",
"base08", "base09", "base0A", "base0B", "base0C", "base0D", "base0E", "base0F",
}

type scheme struct {
Slug string `yaml:"-"`
var base24Bases = []string{
"base10", "base11", "base12", "base13", "base14", "base15", "base16", "base17",
}

Scheme string `yaml:"scheme"`
Author string `yaml:"author"`
Description string `yaml:"description"`
// legacyScheme contains only the fields which are different between a base16
// scheme and our universal scheme format.
type legacyScheme struct {
Scheme string `yaml:"scheme"`

// Colors will hold all the "base*" variables.
Colors map[string]color `yaml:",inline"`
}

func schemeFromFile(schemesFS fs.FS, fileName string) (*scheme, bool) {
ret := &scheme{}
type universalScheme struct {
Slug string `yaml:"-"`

Name string `yaml:"name"`
Author string `yaml:"author"`
System string `yaml:"system"`
Description string `yaml:"description"`
Palette map[string]color `yaml:"palette"`
}

func schemeFromFile(schemesFS fs.FS, fileName string) (*universalScheme, bool) {
ret := &universalScheme{}

logger := log.WithField("file", fileName)

Expand All @@ -47,9 +59,60 @@ func schemeFromFile(schemesFS fs.FS, fileName string) (*scheme, bool) {
return nil, false
}

// If there's no scheme system defined, we assume this is either a base16 or
// base24 style scheme, so we need to parse it again as the legacy format
// and convert it.
if ret.System == "" {
var legacy legacyScheme
err = yaml.Unmarshal(data, &legacy)
if err != nil {
logger.Error(err)
return nil, false
}

// The name was previously called "scheme".
ret.Name = legacy.Scheme

var missingColors []string

for _, baseKey := range base16Bases {
if val, ok := legacy.Colors[baseKey]; ok {
ret.Palette[baseKey] = val
} else {
missingColors = append(missingColors, baseKey)
}
}

// At this point we've checked all of the original 16 bases (which are
// included in both base16 and base24), so if we don't have all 16
// colors, it's an error.
if len(ret.Palette) != 16 {
logger.Errorf("Missing colors from base16 pallete: %s", strings.Join(missingColors, ", "))
return nil, false
}

for _, baseKey := range base24Bases {
if val, ok := legacy.Colors[baseKey]; ok {
ret.Palette[baseKey] = val
} else {
missingColors = append(missingColors, baseKey)
}
}

// Infer the palette based on how many colors we ended up with.
if len(ret.Palette) == 16 {
ret.System = "base16"
} else if len(ret.Palette) == 24 {
ret.System = "base24"
} else {
logger.Errorf("Missing colors from base24 pallete: %s", strings.Join(missingColors, ", "))
return nil, false
}
}

// Now that we have the data, we can sanitize it
ok := true
if ret.Scheme == "" {
if ret.Name == "" {
logger.Error("Scheme name cannot be empty")
ok = false
}
Expand All @@ -60,98 +123,117 @@ func schemeFromFile(schemesFS fs.FS, fileName string) (*scheme, bool) {
logger.Warn("Scheme author should not be empty")
}

if len(bases) != len(ret.Colors) {
logger.Error("Wrong number of colors in scheme")
ok = false
}

// Sanitize any fields which were added later
if ret.Description == "" {
ret.Description = ret.Scheme
ret.Description = ret.Name
}

// Now that we've got all that out of the way, we can start
// processing stuff.

// Take the last path component and chop off .yaml
ret.Slug = filepath.Base(strings.TrimSuffix(fileName, ".yaml"))

for _, base := range bases {
baseKey := "base" + base
if _, innerOk := ret.Colors[baseKey]; !innerOk {
logger.Errorf("Scheme missing %q", baseKey)
ok = false
continue
}
}

return ret, ok
}

func (s *scheme) mustacheContext() map[string]interface{} {
func (s *universalScheme) mustacheContext() map[string]interface{} {
ret := map[string]interface{}{
"scheme-name": s.Scheme,
"scheme-author": s.Author,
"scheme-slug": s.Slug,
"scheme-description": s.Description,

// Any extensions on the spec should go here
"scheme-name": s.Name,
"scheme-author": s.Author,
"scheme-slug": s.Slug,
"scheme-system": s.System,
"scheme-description": s.Description,
"scheme-slug-underscored": strings.Replace(s.Slug, "-", "_", -1),
}

for _, base := range bases {
baseKey := "base" + base
baseVal := s.Colors[baseKey]

for colorKey, colorVal := range s.Palette {
// Note that we only lowercase the output of this to match the reference
// repo.
ret[baseKey+"-hex"] = fmt.Sprintf("%02x%02x%02x", baseVal.R, baseVal.G, baseVal.B)
ret[baseKey+"-hex-bgr"] = fmt.Sprintf("%02x%02x%02x", baseVal.B, baseVal.G, baseVal.R)

ret[baseKey+"-rgb-r"] = baseVal.R
ret[baseKey+"-rgb-g"] = baseVal.G
ret[baseKey+"-rgb-b"] = baseVal.B
ret[baseKey+"-dec-r"] = float32(baseVal.R) / 255
ret[baseKey+"-dec-g"] = float32(baseVal.G) / 255
ret[baseKey+"-dec-b"] = float32(baseVal.B) / 255
ret[baseKey+"-hex-r"] = fmt.Sprintf("%02x", baseVal.R)
ret[baseKey+"-hex-g"] = fmt.Sprintf("%02x", baseVal.G)
ret[baseKey+"-hex-b"] = fmt.Sprintf("%02x", baseVal.B)
ret[colorKey+"-hex"] = fmt.Sprintf("%02x%02x%02x", colorVal.R, colorVal.G, colorVal.B)
ret[colorKey+"-hex-bgr"] = fmt.Sprintf("%02x%02x%02x", colorVal.B, colorVal.G, colorVal.R)

ret[colorKey+"-rgb-r"] = colorVal.R
ret[colorKey+"-rgb-g"] = colorVal.G
ret[colorKey+"-rgb-b"] = colorVal.B
ret[colorKey+"-dec-r"] = float32(colorVal.R) / 255
ret[colorKey+"-dec-g"] = float32(colorVal.G) / 255
ret[colorKey+"-dec-b"] = float32(colorVal.B) / 255
ret[colorKey+"-hex-r"] = fmt.Sprintf("%02x", colorVal.R)
ret[colorKey+"-hex-g"] = fmt.Sprintf("%02x", colorVal.G)
ret[colorKey+"-hex-b"] = fmt.Sprintf("%02x", colorVal.B)
}

return ret
}

func loadSchemes(schemesFS fs.FS) ([]*scheme, bool) {
schemes := make(map[string]*scheme)
func loadSchemes(schemesFS fs.FS) ([]*universalScheme, bool) {
schemes := make(map[string]map[string]*universalScheme)

// Pre-create some of our special cases to make it easier later
schemes["base16"] = make(map[string]*universalScheme)
schemes["base17"] = make(map[string]*universalScheme)

schemePaths, err := fs.Glob(schemesFS, "*.yaml")
if err != nil {
log.Error(err)
return nil, false
}

additionalSchemePaths, err := fs.Glob(schemesFS, "*/*.yaml")
if err != nil {
log.Error(err)
return nil, false
}

schemePaths = append(schemePaths, additionalSchemePaths...)

for _, schemePath := range schemePaths {
scheme, ok := schemeFromFile(schemesFS, schemePath)
if !ok {
log.Errorf("Failed to load scheme")
return nil, false
}

// XXX: this should never happen because it's now a single schemes dir,
// but we include this check just in case someone messed something up.
if _, ok := schemes[scheme.Slug]; ok {
if _, ok := schemes[scheme.System]; !ok {
schemes[scheme.System] = make(map[string]*universalScheme)
}

if _, ok := schemes[scheme.System][scheme.Slug]; ok {
log.WithField("scheme", scheme.Slug).Warnf("Conflicting scheme")
}

log.Debugf("Found scheme %q", scheme.Slug)

schemes[scheme.Slug] = scheme
schemes[scheme.System][scheme.Slug] = scheme
}

// Copy all base17 schemes to base16 which are missing
for _, scheme := range schemes["base17"] {
if _, ok := schemes["base16"][scheme.Slug]; ok {
continue
}

// Copy the scheme and update the "system"
var newScheme universalScheme = *scheme
newScheme.System = "base16"
schemes["base16"][scheme.Slug] = &newScheme
}

ret := []*scheme{}
for _, scheme := range schemes {
ret = append(ret, scheme)
// Copy all base16 schemes to base17 which are missing
for _, scheme := range schemes["base16"] {
if _, ok := schemes["base17"][scheme.Slug]; ok {
continue
}

// Copy the scheme and update the "system"
var newScheme universalScheme = *scheme
newScheme.System = "base17"
schemes["base17"][scheme.Slug] = &newScheme
}

var ret []*universalScheme
for _, system := range schemes {
for _, scheme := range system {
ret = append(ret, scheme)
}
}

return ret, true
Expand Down
2 changes: 1 addition & 1 deletion schemes
Loading

0 comments on commit d505a40

Please sign in to comment.