Bumps the go-modules-updates group in /backend with 8 updates: | Package | From | To | | --- | --- | --- | | [github.com/PuerkitoBio/goquery](https://github.com/PuerkitoBio/goquery) | `1.10.1` | `1.10.2` | | [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) | `2.14.0` | `2.15.0` | | [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) | `5.2.0` | `5.2.1` | | [github.com/go-pkgz/jrpc](https://github.com/go-pkgz/jrpc) | `0.3.0` | `0.3.1` | | [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) | `1.3.11` | `1.4.0` | | [golang.org/x/crypto](https://github.com/golang/crypto) | `0.31.0` | `0.33.0` | | [golang.org/x/image](https://github.com/golang/image) | `0.23.0` | `0.25.0` | | [golang.org/x/net](https://github.com/golang/net) | `0.33.0` | `0.35.0` | Updates `github.com/PuerkitoBio/goquery` from 1.10.1 to 1.10.2 - [Release notes](https://github.com/PuerkitoBio/goquery/releases) - [Commits](https://github.com/PuerkitoBio/goquery/compare/v1.10.1...v1.10.2) Updates `github.com/alecthomas/chroma/v2` from 2.14.0 to 2.15.0 - [Release notes](https://github.com/alecthomas/chroma/releases) - [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml) - [Commits](https://github.com/alecthomas/chroma/compare/v2.14.0...v2.15.0) Updates `github.com/go-chi/chi/v5` from 5.2.0 to 5.2.1 - [Release notes](https://github.com/go-chi/chi/releases) - [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md) - [Commits](https://github.com/go-chi/chi/compare/v5.2.0...v5.2.1) Updates `github.com/go-pkgz/jrpc` from 0.3.0 to 0.3.1 - [Release notes](https://github.com/go-pkgz/jrpc/releases) - [Commits](https://github.com/go-pkgz/jrpc/compare/v0.3.0...v0.3.1) Updates `go.etcd.io/bbolt` from 1.3.11 to 1.4.0 - [Release notes](https://github.com/etcd-io/bbolt/releases) - [Commits](https://github.com/etcd-io/bbolt/compare/v1.3.11...v1.4.0) Updates `golang.org/x/crypto` from 0.31.0 to 0.33.0 - [Commits](https://github.com/golang/crypto/compare/v0.31.0...v0.33.0) Updates `golang.org/x/image` from 0.23.0 to 0.25.0 - [Commits](https://github.com/golang/image/compare/v0.23.0...v0.25.0) Updates `golang.org/x/net` from 0.33.0 to 0.35.0 - [Commits](https://github.com/golang/net/compare/v0.33.0...v0.35.0) --- updated-dependencies: - dependency-name: github.com/PuerkitoBio/goquery dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/alecthomas/chroma/v2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: github.com/go-chi/chi/v5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: github.com/go-pkgz/jrpc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-modules-updates - dependency-name: go.etcd.io/bbolt dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: golang.org/x/image dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates - dependency-name: golang.org/x/net dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-modules-updates ... Signed-off-by: dependabot[bot] <support@github.com>
193 lines
5.4 KiB
Go
193 lines
5.4 KiB
Go
package chroma
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ANSI2RGB maps ANSI colour names, as supported by Chroma, to hex RGB values.
|
|
var ANSI2RGB = map[string]string{
|
|
"#ansiblack": "000000",
|
|
"#ansidarkred": "7f0000",
|
|
"#ansidarkgreen": "007f00",
|
|
"#ansibrown": "7f7fe0",
|
|
"#ansidarkblue": "00007f",
|
|
"#ansipurple": "7f007f",
|
|
"#ansiteal": "007f7f",
|
|
"#ansilightgray": "e5e5e5",
|
|
// Normal
|
|
"#ansidarkgray": "555555",
|
|
"#ansired": "ff0000",
|
|
"#ansigreen": "00ff00",
|
|
"#ansiyellow": "ffff00",
|
|
"#ansiblue": "0000ff",
|
|
"#ansifuchsia": "ff00ff",
|
|
"#ansiturquoise": "00ffff",
|
|
"#ansiwhite": "ffffff",
|
|
|
|
// Aliases without the "ansi" prefix, because...why?
|
|
"#black": "000000",
|
|
"#darkred": "7f0000",
|
|
"#darkgreen": "007f00",
|
|
"#brown": "7f7fe0",
|
|
"#darkblue": "00007f",
|
|
"#purple": "7f007f",
|
|
"#teal": "007f7f",
|
|
"#lightgray": "e5e5e5",
|
|
// Normal
|
|
"#darkgray": "555555",
|
|
"#red": "ff0000",
|
|
"#green": "00ff00",
|
|
"#yellow": "ffff00",
|
|
"#blue": "0000ff",
|
|
"#fuchsia": "ff00ff",
|
|
"#turquoise": "00ffff",
|
|
"#white": "ffffff",
|
|
}
|
|
|
|
// Colour represents an RGB colour.
|
|
type Colour int32
|
|
|
|
// NewColour creates a Colour directly from RGB values.
|
|
func NewColour(r, g, b uint8) Colour {
|
|
return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b))
|
|
}
|
|
|
|
// Distance between this colour and another.
|
|
//
|
|
// This uses the approach described here (https://www.compuphase.com/cmetric.htm).
|
|
// This is not as accurate as LAB, et. al. but is *vastly* simpler and sufficient for our needs.
|
|
func (c Colour) Distance(e2 Colour) float64 {
|
|
ar, ag, ab := int64(c.Red()), int64(c.Green()), int64(c.Blue())
|
|
br, bg, bb := int64(e2.Red()), int64(e2.Green()), int64(e2.Blue())
|
|
rmean := (ar + br) / 2
|
|
r := ar - br
|
|
g := ag - bg
|
|
b := ab - bb
|
|
return math.Sqrt(float64((((512 + rmean) * r * r) >> 8) + 4*g*g + (((767 - rmean) * b * b) >> 8)))
|
|
}
|
|
|
|
// Brighten returns a copy of this colour with its brightness adjusted.
|
|
//
|
|
// If factor is negative, the colour is darkened.
|
|
//
|
|
// Uses approach described here (http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html).
|
|
func (c Colour) Brighten(factor float64) Colour {
|
|
r := float64(c.Red())
|
|
g := float64(c.Green())
|
|
b := float64(c.Blue())
|
|
|
|
if factor < 0 {
|
|
factor++
|
|
r *= factor
|
|
g *= factor
|
|
b *= factor
|
|
} else {
|
|
r = (255-r)*factor + r
|
|
g = (255-g)*factor + g
|
|
b = (255-b)*factor + b
|
|
}
|
|
return NewColour(uint8(r), uint8(g), uint8(b))
|
|
}
|
|
|
|
// BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness.
|
|
func (c Colour) BrightenOrDarken(factor float64) Colour {
|
|
if c.Brightness() < 0.5 {
|
|
return c.Brighten(factor)
|
|
}
|
|
return c.Brighten(-factor)
|
|
}
|
|
|
|
// ClampBrightness returns a copy of this colour with its brightness adjusted such that
|
|
// it falls within the range [min, max] (or very close to it due to rounding errors).
|
|
// The supplied values use the same [0.0, 1.0] range as Brightness.
|
|
func (c Colour) ClampBrightness(min, max float64) Colour {
|
|
if !c.IsSet() {
|
|
return c
|
|
}
|
|
|
|
min = math.Max(min, 0)
|
|
max = math.Min(max, 1)
|
|
current := c.Brightness()
|
|
target := math.Min(math.Max(current, min), max)
|
|
if current == target {
|
|
return c
|
|
}
|
|
|
|
r := float64(c.Red())
|
|
g := float64(c.Green())
|
|
b := float64(c.Blue())
|
|
rgb := r + g + b
|
|
if target > current {
|
|
// Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3
|
|
return c.Brighten((target*255*3 - rgb) / (255*3 - rgb))
|
|
}
|
|
// Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3
|
|
return c.Brighten((target*255*3)/rgb - 1)
|
|
}
|
|
|
|
// Brightness of the colour (roughly) in the range 0.0 to 1.0.
|
|
func (c Colour) Brightness() float64 {
|
|
return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0
|
|
}
|
|
|
|
// ParseColour in the forms #rgb, #rrggbb, #ansi<colour>, or #<colour>.
|
|
// Will return an "unset" colour if invalid.
|
|
func ParseColour(colour string) Colour {
|
|
colour = normaliseColour(colour)
|
|
n, err := strconv.ParseUint(colour, 16, 32)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return Colour(n + 1) //nolint:gosec
|
|
}
|
|
|
|
// MustParseColour is like ParseColour except it panics if the colour is invalid.
|
|
//
|
|
// Will panic if colour is in an invalid format.
|
|
func MustParseColour(colour string) Colour {
|
|
parsed := ParseColour(colour)
|
|
if !parsed.IsSet() {
|
|
panic(fmt.Errorf("invalid colour %q", colour))
|
|
}
|
|
return parsed
|
|
}
|
|
|
|
// IsSet returns true if the colour is set.
|
|
func (c Colour) IsSet() bool { return c != 0 }
|
|
|
|
func (c Colour) String() string { return fmt.Sprintf("#%06x", int(c-1)) }
|
|
func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) }
|
|
|
|
// Red component of colour.
|
|
func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) } //nolint:gosec
|
|
|
|
// Green component of colour.
|
|
func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) } //nolint:gosec
|
|
|
|
// Blue component of colour.
|
|
func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) } //nolint:gosec
|
|
|
|
// Colours is an orderable set of colours.
|
|
type Colours []Colour
|
|
|
|
func (c Colours) Len() int { return len(c) }
|
|
func (c Colours) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
|
func (c Colours) Less(i, j int) bool { return c[i] < c[j] }
|
|
|
|
// Convert colours to #rrggbb.
|
|
func normaliseColour(colour string) string {
|
|
if ansi, ok := ANSI2RGB[colour]; ok {
|
|
return ansi
|
|
}
|
|
if strings.HasPrefix(colour, "#") {
|
|
colour = colour[1:]
|
|
if len(colour) == 3 {
|
|
return colour[0:1] + colour[0:1] + colour[1:2] + colour[1:2] + colour[2:3] + colour[2:3]
|
|
}
|
|
}
|
|
return colour
|
|
}
|