summaryrefslogtreecommitdiff
path: root/vendor/github.com/tdewolff/minify/v2/css
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-10-25 00:47:47 +0200
commitc6cc0108ca7738023b45e0eeac0fa2390532dd93 (patch)
tree36890e6cd3091bbab8efbe686cc56f467f645bfd /vendor/github.com/tdewolff/minify/v2/css
parent0130404a1dc663d4aa68d780c9bcb23a4243e68d (diff)
downloadjbmafp-master.tar.gz
Added vendor lock on depsHEADmaster
Diffstat (limited to 'vendor/github.com/tdewolff/minify/v2/css')
-rw-r--r--vendor/github.com/tdewolff/minify/v2/css/css.go1549
-rw-r--r--vendor/github.com/tdewolff/minify/v2/css/hash.go1392
-rw-r--r--vendor/github.com/tdewolff/minify/v2/css/table.go198
-rw-r--r--vendor/github.com/tdewolff/minify/v2/css/util.go55
4 files changed, 3194 insertions, 0 deletions
diff --git a/vendor/github.com/tdewolff/minify/v2/css/css.go b/vendor/github.com/tdewolff/minify/v2/css/css.go
new file mode 100644
index 0000000..4929609
--- /dev/null
+++ b/vendor/github.com/tdewolff/minify/v2/css/css.go
@@ -0,0 +1,1549 @@
+// Package css minifies CSS3 following the specifications at http://www.w3.org/TR/css-syntax-3/.
+package css
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/tdewolff/minify/v2"
+ "github.com/tdewolff/parse/v2"
+ "github.com/tdewolff/parse/v2/css"
+ strconvParse "github.com/tdewolff/parse/v2/strconv"
+)
+
+var (
+ spaceBytes = []byte(" ")
+ colonBytes = []byte(":")
+ semicolonBytes = []byte(";")
+ commaBytes = []byte(",")
+ leftBracketBytes = []byte("{")
+ rightBracketBytes = []byte("}")
+ rightParenBytes = []byte(")")
+ urlBytes = []byte("url(")
+ zeroBytes = []byte("0")
+ oneBytes = []byte("1")
+ transparentBytes = []byte("transparent")
+ blackBytes = []byte("#0000")
+ initialBytes = []byte("initial")
+ noneBytes = []byte("none")
+ autoBytes = []byte("auto")
+ leftBytes = []byte("left")
+ topBytes = []byte("top")
+ n400Bytes = []byte("400")
+ n700Bytes = []byte("700")
+ n50pBytes = []byte("50%")
+ n100pBytes = []byte("100%")
+ repeatXBytes = []byte("repeat-x")
+ repeatYBytes = []byte("repeat-y")
+ importantBytes = []byte("!important")
+ dataSchemeBytes = []byte("data:")
+)
+
+type cssMinifier struct {
+ m *minify.M
+ w io.Writer
+ p *css.Parser
+ o *Minifier
+
+ tokenBuffer []Token
+ tokensLevel int
+}
+
+////////////////////////////////////////////////////////////////
+
+// Minifier is a CSS minifier.
+type Minifier struct {
+ KeepCSS2 bool
+ Precision int // number of significant digits
+ newPrecision int // precision for new numbers
+}
+
+// Minify minifies CSS data, it reads from r and writes to w.
+func Minify(m *minify.M, w io.Writer, r io.Reader, params map[string]string) error {
+ return (&Minifier{}).Minify(m, w, r, params)
+}
+
+// Token is a parsed token with extra information for functions.
+type Token struct {
+ css.TokenType
+ Data []byte
+ Args []Token // only filled for functions
+ Fun, Ident Hash // only filled for functions and identifiers respectively
+}
+
+func (t Token) String() string {
+ if len(t.Args) == 0 {
+ return t.TokenType.String() + "(" + string(t.Data) + ")"
+ }
+ return fmt.Sprint(t.Args)
+}
+
+// Equal returns true if both tokens are equal.
+func (t Token) Equal(t2 Token) bool {
+ if t.TokenType == t2.TokenType && bytes.Equal(t.Data, t2.Data) && len(t.Args) == len(t2.Args) {
+ for i := 0; i < len(t.Args); i++ {
+ if t.Args[i].TokenType != t2.Args[i].TokenType || !bytes.Equal(t.Args[i].Data, t2.Args[i].Data) {
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+// IsZero return true if a dimension, percentage, or number token is zero.
+func (t Token) IsZero() bool {
+ // as each number is already minified, starting with a zero means it is zero
+ return (t.TokenType == css.DimensionToken || t.TokenType == css.PercentageToken || t.TokenType == css.NumberToken) && t.Data[0] == '0'
+}
+
+// IsLength returns true if the token is a length.
+func (t Token) IsLength() bool {
+ if t.TokenType == css.DimensionToken {
+ return true
+ } else if t.TokenType == css.NumberToken && t.Data[0] == '0' {
+ return true
+ } else if t.TokenType == css.FunctionToken {
+ fun := ToHash(t.Data[:len(t.Data)-1])
+ if fun == Calc || fun == Min || fun == Max || fun == Clamp || fun == Attr || fun == Var || fun == Env {
+ return true
+ }
+ }
+ return false
+}
+
+// IsLengthPercentage returns true if the token is a length or percentage token.
+func (t Token) IsLengthPercentage() bool {
+ return t.TokenType == css.PercentageToken || t.IsLength()
+}
+
+////////////////////////////////////////////////////////////////
+
+// Minify minifies CSS data, it reads from r and writes to w.
+func (o *Minifier) Minify(m *minify.M, w io.Writer, r io.Reader, params map[string]string) error {
+ o.newPrecision = o.Precision
+ if o.newPrecision <= 0 || 15 < o.newPrecision {
+ o.newPrecision = 15 // minimum number of digits a double can represent exactly
+ }
+
+ z := parse.NewInput(r)
+ defer z.Restore()
+
+ isInline := params != nil && params["inline"] == "1"
+ c := &cssMinifier{
+ m: m,
+ w: w,
+ p: css.NewParser(z, isInline),
+ o: o,
+ }
+ c.minifyGrammar()
+
+ if _, err := w.Write(nil); err != nil {
+ return err
+ }
+ if c.p.Err() == io.EOF {
+ return nil
+ }
+ return c.p.Err()
+}
+
+func (c *cssMinifier) minifyGrammar() {
+ semicolonQueued := false
+ for {
+ gt, _, data := c.p.Next()
+ switch gt {
+ case css.ErrorGrammar:
+ if c.p.HasParseError() {
+ if semicolonQueued {
+ c.w.Write(semicolonBytes)
+ }
+
+ // write out the offending declaration (but save the semicolon)
+ vals := c.p.Values()
+ if len(vals) > 0 && vals[len(vals)-1].TokenType == css.SemicolonToken {
+ vals = vals[:len(vals)-1]
+ semicolonQueued = true
+ }
+ for _, val := range vals {
+ c.w.Write(val.Data)
+ }
+ continue
+ }
+ return
+ case css.EndAtRuleGrammar, css.EndRulesetGrammar:
+ c.w.Write(rightBracketBytes)
+ semicolonQueued = false
+ continue
+ }
+
+ if semicolonQueued {
+ c.w.Write(semicolonBytes)
+ semicolonQueued = false
+ }
+
+ switch gt {
+ case css.AtRuleGrammar:
+ c.w.Write(data)
+ values := c.p.Values()
+ if ToHash(data[1:]) == Import && len(values) == 2 && values[1].TokenType == css.URLToken && 4 < len(values[1].Data) && values[1].Data[len(values[1].Data)-1] == ')' {
+ url := values[1].Data
+ if url[4] != '"' && url[4] != '\'' {
+ a := 4
+ for parse.IsWhitespace(url[a]) || parse.IsNewline(url[a]) {
+ a++
+ }
+ b := len(url) - 2
+ for a < b && (parse.IsWhitespace(url[b]) || parse.IsNewline(url[b])) {
+ b--
+ }
+ if a == b {
+ url = url[:2]
+ } else {
+ url = url[a-1 : b+2]
+ }
+ url[0] = '"'
+ url[len(url)-1] = '"'
+ } else {
+ url = url[4 : len(url)-1]
+ }
+ values[1].Data = url
+ }
+ for _, val := range values {
+ c.w.Write(val.Data)
+ }
+ semicolonQueued = true
+ case css.BeginAtRuleGrammar:
+ c.w.Write(data)
+ for _, val := range c.p.Values() {
+ c.w.Write(val.Data)
+ }
+ c.w.Write(leftBracketBytes)
+ case css.QualifiedRuleGrammar:
+ c.minifySelectors(data, c.p.Values())
+ c.w.Write(commaBytes)
+ case css.BeginRulesetGrammar:
+ c.minifySelectors(data, c.p.Values())
+ c.w.Write(leftBracketBytes)
+ case css.DeclarationGrammar:
+ c.minifyDeclaration(data, c.p.Values())
+ semicolonQueued = true
+ case css.CustomPropertyGrammar:
+ c.w.Write(data)
+ c.w.Write(colonBytes)
+ value := parse.TrimWhitespace(c.p.Values()[0].Data)
+ if len(c.p.Values()[0].Data) != 0 && len(value) == 0 {
+ value = spaceBytes
+ }
+ c.w.Write(value)
+ semicolonQueued = true
+ case css.CommentGrammar:
+ if len(data) > 5 && data[1] == '*' && data[2] == '!' {
+ c.w.Write(data[:3])
+ comment := parse.TrimWhitespace(parse.ReplaceMultipleWhitespace(data[3 : len(data)-2]))
+ c.w.Write(comment)
+ c.w.Write(data[len(data)-2:])
+ }
+ default:
+ c.w.Write(data)
+ }
+ }
+}
+
+func (c *cssMinifier) minifySelectors(property []byte, values []css.Token) {
+ inAttr := false
+ isClass := false
+ for _, val := range c.p.Values() {
+ if !inAttr {
+ if val.TokenType == css.IdentToken {
+ if !isClass {
+ parse.ToLower(val.Data)
+ }
+ isClass = false
+ } else if val.TokenType == css.DelimToken && val.Data[0] == '.' {
+ isClass = true
+ } else if val.TokenType == css.LeftBracketToken {
+ inAttr = true
+ }
+ } else {
+ if val.TokenType == css.StringToken && len(val.Data) > 2 {
+ s := val.Data[1 : len(val.Data)-1]
+ if css.IsIdent(s) {
+ c.w.Write(s)
+ continue
+ }
+ } else if val.TokenType == css.RightBracketToken {
+ inAttr = false
+ } else if val.TokenType == css.IdentToken && len(val.Data) == 1 && (val.Data[0] == 'i' || val.Data[0] == 'I') {
+ c.w.Write(spaceBytes)
+ }
+ }
+ c.w.Write(val.Data)
+ }
+}
+
+func (c *cssMinifier) parseFunction(values []css.Token) ([]Token, int) {
+ i := 1
+ level := 0
+ args := []Token{}
+ for ; i < len(values); i++ {
+ tt := values[i].TokenType
+ data := values[i].Data
+ if tt == css.LeftParenthesisToken {
+ level++
+ } else if tt == css.RightParenthesisToken {
+ if level == 0 {
+ i++
+ break
+ }
+ level--
+ }
+ if tt == css.FunctionToken {
+ subArgs, di := c.parseFunction(values[i:])
+ h := ToHash(parse.ToLower(parse.Copy(data[:len(data)-1]))) // TODO: use ToHashFold
+ args = append(args, Token{tt, data, subArgs, h, 0})
+ i += di - 1
+ } else {
+ var h Hash
+ if tt == css.IdentToken {
+ h = ToHash(parse.ToLower(parse.Copy(data))) // TODO: use ToHashFold
+ }
+ args = append(args, Token{tt, data, nil, 0, h})
+ }
+ }
+ return args, i
+}
+
+func (c *cssMinifier) parseDeclaration(values []css.Token) []Token {
+ // Check if this is a simple list of values separated by whitespace or commas, otherwise we'll not be processing
+ prevSep := true
+ tokens := c.tokenBuffer[:0]
+ for i := 0; i < len(values); i++ {
+ tt := values[i].TokenType
+ data := values[i].Data
+ if tt == css.LeftParenthesisToken || tt == css.LeftBraceToken || tt == css.LeftBracketToken ||
+ tt == css.RightParenthesisToken || tt == css.RightBraceToken || tt == css.RightBracketToken {
+ return nil
+ }
+
+ if !prevSep && tt != css.WhitespaceToken && tt != css.CommaToken && (tt != css.DelimToken || values[i].Data[0] != '/') {
+ return nil
+ }
+
+ if tt == css.WhitespaceToken || tt == css.CommaToken || tt == css.DelimToken && values[i].Data[0] == '/' {
+ if tt != css.WhitespaceToken {
+ tokens = append(tokens, Token{tt, data, nil, 0, 0})
+ }
+ prevSep = true
+ } else if tt == css.FunctionToken {
+ args, di := c.parseFunction(values[i:])
+ h := ToHash(parse.ToLower(parse.Copy(data[:len(data)-1]))) // TODO: use ToHashFold
+ tokens = append(tokens, Token{tt, data, args, h, 0})
+ prevSep = true
+ i += di - 1
+ } else {
+ var h Hash
+ if tt == css.IdentToken {
+ h = ToHash(parse.ToLower(parse.Copy(data))) // TODO: use ToHashFold
+ }
+ tokens = append(tokens, Token{tt, data, nil, 0, h})
+ prevSep = tt == css.URLToken
+ }
+ }
+ c.tokenBuffer = tokens // update buffer size for memory reuse
+ return tokens
+}
+
+func (c *cssMinifier) minifyDeclaration(property []byte, components []css.Token) {
+ c.w.Write(property)
+ c.w.Write(colonBytes)
+
+ if len(components) == 0 {
+ return
+ }
+
+ // Strip !important from the component list, this will be added later separately
+ important := false
+ if len(components) > 2 && components[len(components)-2].TokenType == css.DelimToken && components[len(components)-2].Data[0] == '!' && ToHash(components[len(components)-1].Data) == Important {
+ components = components[:len(components)-2]
+ important = true
+ }
+
+ prop := ToHash(property)
+ values := c.parseDeclaration(components)
+
+ // Do not process complex values (eg. containing blocks or is not alternated between whitespace/commas and flat values
+ if values == nil {
+ if prop == Filter && len(components) == 11 {
+ if bytes.Equal(components[0].Data, []byte("progid")) &&
+ components[1].TokenType == css.ColonToken &&
+ bytes.Equal(components[2].Data, []byte("DXImageTransform")) &&
+ components[3].Data[0] == '.' &&
+ bytes.Equal(components[4].Data, []byte("Microsoft")) &&
+ components[5].Data[0] == '.' &&
+ bytes.Equal(components[6].Data, []byte("Alpha(")) &&
+ bytes.Equal(parse.ToLower(components[7].Data), []byte("opacity")) &&
+ components[8].Data[0] == '=' &&
+ components[10].Data[0] == ')' {
+ components = components[6:]
+ components[0].Data = []byte("alpha(")
+ }
+ }
+
+ for _, component := range components {
+ c.w.Write(component.Data)
+ }
+ if important {
+ c.w.Write(importantBytes)
+ }
+ return
+ }
+
+ values = c.minifyTokens(prop, 0, values)
+ if len(values) > 0 {
+ values = c.minifyProperty(prop, values)
+ }
+ c.writeDeclaration(values, important)
+}
+
+func (c *cssMinifier) writeFunction(args []Token) {
+ for _, arg := range args {
+ c.w.Write(arg.Data)
+ if arg.TokenType == css.FunctionToken {
+ c.writeFunction(arg.Args)
+ c.w.Write(rightParenBytes)
+ }
+ }
+}
+
+func (c *cssMinifier) writeDeclaration(values []Token, important bool) {
+ prevSep := true
+ for _, value := range values {
+ if !prevSep && value.TokenType != css.CommaToken && (value.TokenType != css.DelimToken || value.Data[0] != '/') {
+ c.w.Write(spaceBytes)
+ }
+
+ c.w.Write(value.Data)
+ if value.TokenType == css.FunctionToken {
+ c.writeFunction(value.Args)
+ c.w.Write(rightParenBytes)
+ }
+
+ if value.TokenType == css.CommaToken || value.TokenType == css.DelimToken && value.Data[0] == '/' || value.TokenType == css.FunctionToken || value.TokenType == css.URLToken {
+ prevSep = true
+ } else {
+ prevSep = false
+ }
+ }
+
+ if important {
+ c.w.Write(importantBytes)
+ }
+}
+
+func (c *cssMinifier) minifyTokens(prop Hash, fun Hash, values []Token) []Token {
+ if 100 < c.tokensLevel+1 {
+ return values
+ }
+ c.tokensLevel++
+
+ for i, value := range values {
+ tt := value.TokenType
+ switch tt {
+ case css.NumberToken:
+ if prop == Z_Index || prop == Counter_Increment || prop == Counter_Reset || prop == Orphans || prop == Widows {
+ break // integers
+ }
+ if c.o.KeepCSS2 {
+ values[i].Data = minify.Decimal(values[i].Data, c.o.Precision) // don't use exponents
+ } else {
+ values[i].Data = minify.Number(values[i].Data, c.o.Precision)
+ }
+ case css.PercentageToken:
+ n := len(values[i].Data) - 1
+ if c.o.KeepCSS2 {
+ values[i].Data = minify.Decimal(values[i].Data[:n], c.o.Precision) // don't use exponents
+ } else {
+ values[i].Data = minify.Number(values[i].Data[:n], c.o.Precision)
+ }
+ values[i].Data = append(values[i].Data, '%')
+ case css.DimensionToken:
+ var dim []byte
+ values[i], dim = c.minifyDimension(values[i])
+ if 1 < len(values[i].Data) && values[i].Data[0] == '0' && optionalZeroDimension[string(dim)] && prop != Flex && fun == 0 {
+ // cut dimension for zero value, TODO: don't hardcode check for Flex and remove the dimension in minifyDimension
+ values[i].Data = values[i].Data[:1]
+ }
+ case css.StringToken:
+ values[i].Data = removeMarkupNewlines(values[i].Data)
+ case css.URLToken:
+ if 10 < len(values[i].Data) {
+ uri := parse.TrimWhitespace(values[i].Data[4 : len(values[i].Data)-1])
+ delim := byte('"')
+ if 1 < len(uri) && (uri[0] == '\'' || uri[0] == '"') {
+ delim = uri[0]
+ uri = removeMarkupNewlines(uri)
+ uri = uri[1 : len(uri)-1]
+ }
+ if 4 < len(uri) && parse.EqualFold(uri[:5], dataSchemeBytes) {
+ uri = minify.DataURI(c.m, uri)
+ }
+ if css.IsURLUnquoted(uri) {
+ values[i].Data = append(append(urlBytes, uri...), ')')
+ } else {
+ values[i].Data = append(append(append(urlBytes, delim), uri...), delim, ')')
+ }
+ }
+ case css.FunctionToken:
+ values[i].Args = c.minifyTokens(prop, values[i].Fun, values[i].Args)
+
+ fun := values[i].Fun
+ args := values[i].Args
+ if fun == Rgb || fun == Rgba || fun == Hsl || fun == Hsla {
+ valid := true
+ vals := []float64{}
+ for i, arg := range args {
+ numeric := arg.TokenType == css.NumberToken || arg.TokenType == css.PercentageToken
+ separator := arg.TokenType == css.CommaToken || i != 5 && arg.TokenType == css.WhitespaceToken || i == 5 && arg.TokenType == css.DelimToken && arg.Data[0] == '/'
+ if i%2 == 0 && !numeric || i%2 == 1 && !separator {
+ valid = false
+ break
+ } else if numeric {
+ var d float64
+ if arg.TokenType == css.PercentageToken {
+ var err error
+ d, err = strconv.ParseFloat(string(arg.Data[:len(arg.Data)-1]), 32) // can overflow
+ if err != nil {
+ valid = false
+ break
+ }
+ d /= 100.0
+ if d < minify.Epsilon {
+ d = 0.0
+ } else if 1.0-minify.Epsilon < d {
+ d = 1.0
+ }
+ } else {
+ var err error
+ d, err = strconv.ParseFloat(string(arg.Data), 32) // can overflow
+ if err != nil {
+ valid = false
+ break
+ }
+ }
+ vals = append(vals, d)
+ }
+ }
+ if !valid {
+ break
+ }
+
+ a := 1.0
+ if len(vals) == 4 {
+ if vals[0] < minify.Epsilon && vals[1] < minify.Epsilon && vals[2] < minify.Epsilon && vals[3] < minify.Epsilon {
+ values[i] = Token{css.IdentToken, transparentBytes, nil, 0, Transparent}
+ break
+ } else if 1.0-minify.Epsilon < vals[3] {
+ vals = vals[:3]
+ values[i].Args = values[i].Args[:len(values[i].Args)-2]
+ if fun == Rgba || fun == Hsla {
+ values[i].Data = values[i].Data[:len(values[i].Data)-1]
+ values[i].Data[len(values[i].Data)-1] = '('
+ }
+ } else {
+ a = vals[3]
+ }
+ }
+
+ if a == 1.0 && (len(vals) == 3 || len(vals) == 4) { // only minify color if fully opaque
+ if fun == Rgb || fun == Rgba {
+ for j := 0; j < 3; j++ {
+ if args[j*2].TokenType == css.NumberToken {
+ vals[j] /= 255.0
+ if vals[j] < minify.Epsilon {
+ vals[j] = 0.0
+ } else if 1.0-minify.Epsilon < vals[j] {
+ vals[j] = 1.0
+ }
+ }
+ }
+ values[i] = rgbToToken(vals[0], vals[1], vals[2])
+ break
+ } else if fun == Hsl || fun == Hsla && args[0].TokenType == css.NumberToken && args[2].TokenType == css.PercentageToken && args[4].TokenType == css.PercentageToken {
+ vals[0] /= 360.0
+ _, vals[0] = math.Modf(vals[0])
+ if vals[0] < 0.0 {
+ vals[0] = 1.0 + vals[0]
+ }
+ r, g, b := css.HSL2RGB(vals[0], vals[1], vals[2])
+ values[i] = rgbToToken(r, g, b)
+ break
+ }
+ } else if len(vals) == 4 {
+ args[6] = minifyNumberPercentage(args[6])
+ }
+
+ if 3 <= len(vals) && (fun == Rgb || fun == Rgba) {
+ // 0%, 20%, 40%, 60%, 80% and 100% can be represented exactly as, 51, 102, 153, 204, and 255 respectively
+ removePercentage := true
+ for j := 0; j < 3; j++ {
+ if args[j*2].TokenType != css.PercentageToken || 2.0*minify.Epsilon <= math.Mod(vals[j]+minify.Epsilon, 0.2) {
+ removePercentage = false
+ break
+ }
+ }
+ if removePercentage {
+ for j := 0; j < 3; j++ {
+ args[j*2].TokenType = css.NumberToken
+ if vals[j] < minify.Epsilon {
+ args[j*2].Data = zeroBytes
+ } else if math.Abs(vals[j]-0.2) < minify.Epsilon {
+ args[j*2].Data = []byte("51")
+ } else if math.Abs(vals[j]-0.4) < minify.Epsilon {
+ args[j*2].Data = []byte("102")
+ } else if math.Abs(vals[j]-0.6) < minify.Epsilon {
+ args[j*2].Data = []byte("153")
+ } else if math.Abs(vals[j]-0.8) < minify.Epsilon {
+ args[j*2].Data = []byte("204")
+ } else if math.Abs(vals[j]-1.0) < minify.Epsilon {
+ args[j*2].Data = []byte("255")
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ c.tokensLevel--
+ return values
+}
+
+func (c *cssMinifier) minifyProperty(prop Hash, values []Token) []Token {
+ // limit maximum to prevent slow recursions (e.g. for background's append)
+ if 100 < len(values) {
+ return values
+ }
+
+ switch prop {
+ case Font:
+ if len(values) > 1 { // must contain atleast font-size and font-family
+ // the font-families are separated by commas and are at the end of font
+ // get index for last token before font family names
+ i := len(values) - 1
+ for j, value := range values[2:] {
+ if value.TokenType == css.CommaToken {
+ i = 2 + j - 1 // identifier before first comma is a font-family
+ break
+ }
+ }
+ i--
+
+ // advance i while still at font-families when they contain spaces but no quotes
+ for ; i > 0; i-- { // i cannot be 0, font-family must be prepended by font-size
+ if values[i-1].TokenType == css.DelimToken && values[i-1].Data[0] == '/' {
+ break
+ } else if values[i].TokenType != css.IdentToken && values[i].TokenType != css.StringToken {
+ break
+ } else if h := values[i].Ident; h == Xx_Small || h == X_Small || h == Small || h == Medium || h == Large || h == X_Large || h == Xx_Large || h == Smaller || h == Larger || h == Inherit || h == Initial || h == Unset {
+ // inherit, initial and unset are followed by an IdentToken/StringToken, so must be for font-size
+ break
+ }
+ }
+
+ // font-family minified in place
+ values = append(values[:i+1], c.minifyProperty(Font_Family, values[i+1:])...)
+
+ // fix for IE9, IE10, IE11: font name starting with `-` is not recognized
+ if values[i+1].Data[0] == '-' {
+ v := make([]byte, len(values[i+1].Data)+2)
+ v[0] = '\''
+ copy(v[1:], values[i+1].Data)
+ v[len(v)-1] = '\''
+ values[i+1].Data = v
+ }
+
+ if i > 0 {
+ // line-height
+ if i > 1 && values[i-1].TokenType == css.DelimToken && values[i-1].Data[0] == '/' {
+ if values[i].Ident == Normal {
+ values = append(values[:i-1], values[i+1:]...)
+ }
+ i -= 2
+ }
+
+ // font-size
+ i--
+
+ for ; i > -1; i-- {
+ if values[i].Ident == Normal {
+ values = append(values[:i], values[i+1:]...)
+ } else if values[i].Ident == Bold {
+ values[i].TokenType = css.NumberToken
+ values[i].Data = n700Bytes
+ } else if values[i].TokenType == css.NumberToken && bytes.Equal(values[i].Data, n400Bytes) {
+ values = append(values[:i], values[i+1:]...)
+ }
+ }
+ }
+ }
+ case Font_Family:
+ for i, value := range values {
+ if value.TokenType == css.StringToken && 2 < len(value.Data) {
+ unquote := true
+ parse.ToLower(value.Data)
+ s := value.Data[1 : len(value.Data)-1]
+ if 0 < len(s) {
+ for _, split := range bytes.Split(s, spaceBytes) {
+ // if len is zero, it contains two consecutive spaces
+ if len(split) == 0 || !css.IsIdent(split) {
+ unquote = false
+ break
+ }
+ }
+ }
+ if unquote {
+ values[i].Data = s
+ }
+ }
+ }
+ case Font_Weight:
+ if values[0].Ident == Normal {
+ values[0].TokenType = css.NumberToken
+ values[0].Data = n400Bytes
+ } else if values[0].Ident == Bold {
+ values[0].TokenType = css.NumberToken
+ values[0].Data = n700Bytes
+ }
+ case Url:
+ for i := 0; i < len(values); i++ {
+ if values[i].TokenType == css.FunctionToken && len(values[i].Args) == 1 {
+ fun := values[i].Fun
+ data := values[i].Args[0].Data
+ if fun == Local && (data[0] == '\'' || data[0] == '"') {
+ if css.IsURLUnquoted(data[1 : len(data)-1]) {
+ data = data[1 : len(data)-1]
+ }
+ values[i].Args[0].Data = data
+ }
+ }
+ }
+ case Margin, Padding, Border_Width:
+ switch len(values) {
+ case 2:
+ if values[0].Equal(values[1]) {
+ values = values[:1]
+ }
+ case 3:
+ if values[0].Equal(values[1]) && values[0].Equal(values[2]) {
+ values = values[:1]
+ } else if values[0].Equal(values[2]) {
+ values = values[:2]
+ }
+ case 4:
+ if values[0].Equal(values[1]) && values[0].Equal(values[2]) && values[0].Equal(values[3]) {
+ values = values[:1]
+ } else if values[0].Equal(values[2]) && values[1].Equal(values[3]) {
+ values = values[:2]
+ } else if values[1].Equal(values[3]) {
+ values = values[:3]
+ }
+ }
+ case Border, Border_Bottom, Border_Left, Border_Right, Border_Top:
+ for i := 0; i < len(values); i++ {
+ if values[i].Ident == None || values[i].Ident == Currentcolor || values[i].Ident == Medium {
+ values = append(values[:i], values[i+1:]...)
+ i--
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ }
+ if len(values) == 0 {
+ values = []Token{{css.IdentToken, noneBytes, nil, 0, None}}
+ }
+ case Outline:
+ for i := 0; i < len(values); i++ {
+ if values[i].Ident == Invert || values[i].Ident == None || values[i].Ident == Medium {
+ values = append(values[:i], values[i+1:]...)
+ i--
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ }
+ if len(values) == 0 {
+ values = []Token{{css.IdentToken, noneBytes, nil, 0, None}}
+ }
+ case Background:
+ start := 0
+ for end := 0; end <= len(values); end++ { // loop over comma-separated lists
+ if end != len(values) && values[end].TokenType != css.CommaToken {
+ continue
+ } else if start == end {
+ start++
+ continue
+ }
+
+ // minify background-size and lowercase all identifiers
+ for i := start; i < end; i++ {
+ if values[i].TokenType == css.DelimToken && values[i].Data[0] == '/' {
+ // background-size consists of either [<length-percentage> | auto | cover | contain] or [<length-percentage> | auto]{2}
+ // we can only minify the latter
+ if i+1 < end && (values[i+1].TokenType == css.NumberToken || values[i+1].IsLengthPercentage() || values[i+1].Ident == Auto) {
+ if i+2 < end && (values[i+2].TokenType == css.NumberToken || values[i+2].IsLengthPercentage() || values[i+2].Ident == Auto) {
+ sizeValues := c.minifyProperty(Background_Size, values[i+1:i+3])
+ if len(sizeValues) == 1 && sizeValues[0].Ident == Auto {
+ // remove background-size if it is '/ auto' after minifying the property
+ values = append(values[:i], values[i+3:]...)
+ end -= 3
+ i--
+ } else {
+ values = append(values[:i+1], append(sizeValues, values[i+3:]...)...)
+ end -= 2 - len(sizeValues)
+ i += len(sizeValues) - 1
+ }
+ } else if values[i+1].Ident == Auto {
+ // remove background-size if it is '/ auto'
+ values = append(values[:i], values[i+2:]...)
+ end -= 2
+ i--
+ }
+ }
+ }
+ }
+
+ // minify all other values
+ iPaddingBox := -1 // position of background-origin that is padding-box
+ for i := start; i < end; i++ {
+ h := values[i].Ident
+ values[i] = minifyColor(values[i])
+ if values[i].TokenType == css.IdentToken {
+ if i+1 < end && values[i+1].TokenType == css.IdentToken && (h == Space || h == Round || h == Repeat || h == No_Repeat) {
+ if h2 := values[i+1].Ident; h2 == Space || h2 == Round || h2 == Repeat || h2 == No_Repeat {
+ repeatValues := c.minifyProperty(Background_Repeat, values[i:i+2])
+ if len(repeatValues) == 1 && repeatValues[0].Ident == Repeat {
+ values = append(values[:i], values[i+2:]...)
+ end -= 2
+ i--
+ } else {
+ values = append(values[:i], append(repeatValues, values[i+2:]...)...)
+ end -= 2 - len(repeatValues)
+ i += len(repeatValues) - 1
+ }
+ continue
+ }
+ } else if h == None || h == Scroll || h == Transparent {
+ values = append(values[:i], values[i+1:]...)
+ end--
+ i--
+ continue
+ } else if h == Border_Box || h == Padding_Box {
+ if iPaddingBox == -1 && h == Padding_Box { // background-origin
+ iPaddingBox = i
+ } else if iPaddingBox != -1 && h == Border_Box { // background-clip
+ values = append(values[:i], values[i+1:]...)
+ values = append(values[:iPaddingBox], values[iPaddingBox+1:]...)
+ end -= 2
+ i -= 2
+ }
+ continue
+ }
+ } else if values[i].TokenType == css.HashToken && bytes.Equal(values[i].Data, blackBytes) {
+ values = append(values[:i], values[i+1:]...)
+ end--
+ i--
+ continue
+ }
+
+ // further minify background-position and background-size combination
+ if values[i].TokenType == css.NumberToken || values[i].IsLengthPercentage() || h == Left || h == Right || h == Top || h == Bottom || h == Center {
+ j := i + 1
+ for ; j < len(values); j++ {
+ if h := values[j].Ident; h == Left || h == Right || h == Top || h == Bottom || h == Center {
+ continue
+ } else if values[j].TokenType == css.NumberToken || values[j].IsLengthPercentage() {
+ continue
+ }
+ break
+ }
+
+ positionValues := c.minifyProperty(Background_Position, values[i:j])
+ hasSize := j < len(values) && values[j].TokenType == css.DelimToken && values[j].Data[0] == '/'
+ if !hasSize && len(positionValues) == 2 && positionValues[0].IsZero() && positionValues[1].IsZero() {
+ if end-start == 2 {
+ values[i] = Token{css.NumberToken, zeroBytes, nil, 0, 0}
+ values[i+1] = Token{css.NumberToken, zeroBytes, nil, 0, 0}
+ i++
+ } else {
+ values = append(values[:i], values[j:]...)
+ end -= j - i
+ i--
+ }
+ } else {
+ if len(positionValues) == j-i {
+ for k, positionValue := range positionValues {
+ values[i+k] = positionValue
+ }
+ } else {
+ values = append(values[:i], append(positionValues, values[j:]...)...)
+ end -= j - i - len(positionValues)
+ }
+ i += len(positionValues) - 1
+ }
+ }
+ }
+
+ if end-start == 0 {
+ values = append(values[:start], append([]Token{{css.NumberToken, zeroBytes, nil, 0, 0}, {css.NumberToken, zeroBytes, nil, 0, 0}}, values[end:]...)...)
+ end += 2
+ }
+ start = end + 1
+ }
+ case Background_Size:
+ start := 0
+ for end := 0; end <= len(values); end++ { // loop over comma-separated lists
+ if end != len(values) && values[end].TokenType != css.CommaToken {
+ continue
+ } else if start == end {
+ start++
+ continue
+ }
+
+ if end-start == 2 && values[start+1].Ident == Auto {
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ }
+ start = end + 1
+ }
+ case Background_Repeat:
+ start := 0
+ for end := 0; end <= len(values); end++ { // loop over comma-separated lists
+ if end != len(values) && values[end].TokenType != css.CommaToken {
+ continue
+ } else if start == end {
+ start++
+ continue
+ }
+
+ if end-start == 2 && values[start].TokenType == css.IdentToken && values[start+1].TokenType == css.IdentToken {
+ if values[start].Ident == values[start+1].Ident {
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ } else if values[start].Ident == Repeat && values[start+1].Ident == No_Repeat {
+ values[start].Data = repeatXBytes
+ values[start].Ident = Repeat_X
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ } else if values[start].Ident == No_Repeat && values[start+1].Ident == Repeat {
+ values[start].Data = repeatYBytes
+ values[start].Ident = Repeat_Y
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ }
+ }
+ start = end + 1
+ }
+ case Background_Position:
+ start := 0
+ for end := 0; end <= len(values); end++ { // loop over comma-separated lists
+ if end != len(values) && values[end].TokenType != css.CommaToken {
+ continue
+ } else if start == end {
+ start++
+ continue
+ }
+
+ if end-start == 3 || end-start == 4 {
+ // remove zero offsets
+ for _, i := range []int{end - start - 1, start + 1} {
+ if 2 < end-start && values[i].IsZero() {
+ values = append(values[:i], values[i+1:]...)
+ end--
+ }
+ }
+
+ j := start + 1 // position of second set of horizontal/vertical values
+ if 2 < end-start && values[start+2].TokenType == css.IdentToken {
+ j = start + 2
+ }
+
+ b := make([]byte, 0, 4)
+ offsets := make([]Token, 2)
+ for _, i := range []int{j, start} {
+ if i+1 < end && i+1 != j {
+ if values[i+1].TokenType == css.PercentageToken {
+ // change right or bottom with percentage offset to left or top respectively
+ if values[i].Ident == Right || values[i].Ident == Bottom {
+ n, _ := strconvParse.ParseInt(values[i+1].Data[:len(values[i+1].Data)-1])
+ b = strconv.AppendInt(b[:0], 100-n, 10)
+ b = append(b, '%')
+ values[i+1].Data = b
+ if values[i].Ident == Right {
+ values[i].Data = leftBytes
+ values[i].Ident = Left
+ } else {
+ values[i].Data = topBytes
+ values[i].Ident = Top
+ }
+ }
+ }
+ if values[i].Ident == Left {
+ offsets[0] = values[i+1]
+ } else if values[i].Ident == Top {
+ offsets[1] = values[i+1]
+ }
+ } else if values[i].Ident == Left {
+ offsets[0] = Token{css.NumberToken, zeroBytes, nil, 0, 0}
+ } else if values[i].Ident == Top {
+ offsets[1] = Token{css.NumberToken, zeroBytes, nil, 0, 0}
+ } else if values[i].Ident == Right {
+ offsets[0] = Token{css.PercentageToken, n100pBytes, nil, 0, 0}
+ values[i].Ident = Left
+ } else if values[i].Ident == Bottom {
+ offsets[1] = Token{css.PercentageToken, n100pBytes, nil, 0, 0}
+ values[i].Ident = Top
+ }
+ }
+
+ if values[start].Ident == Center || values[j].Ident == Center {
+ if values[start].Ident == Left || values[j].Ident == Left {
+ offsets = offsets[:1]
+ } else if values[start].Ident == Top || values[j].Ident == Top {
+ offsets[0] = Token{css.NumberToken, n50pBytes, nil, 0, 0}
+ }
+ }
+
+ if offsets[0].Data != nil && (len(offsets) == 1 || offsets[1].Data != nil) {
+ values = append(append(values[:start], offsets...), values[end:]...)
+ end -= end - start - len(offsets)
+ }
+ }
+ // removing zero offsets in the previous loop might make it eligible for the next loop
+ if end-start == 1 || end-start == 2 {
+ if end-start == 1 && (values[start].Ident == Top || values[start].Ident == Bottom) {
+ // we can't make this smaller, and converting to a number will break it
+ // (https://github.com/tdewolff/minify/issues/221#issuecomment-415419918)
+ break
+ }
+
+ if end-start == 2 && (values[start].Ident == Top || values[start].Ident == Bottom || values[start+1].Ident == Left || values[start+1].Ident == Right) {
+ // if it's a vertical position keyword, swap it with the next element
+ // since otherwise converted number positions won't be valid anymore
+ // (https://github.com/tdewolff/minify/issues/221#issue-353067229)
+ values[start], values[start+1] = values[start+1], values[start]
+ }
+
+ // transform keywords to lengths|percentages
+ for i := start; i < end; i++ {
+ if values[i].TokenType == css.IdentToken {
+ if values[i].Ident == Left || values[i].Ident == Top {
+ values[i].TokenType = css.NumberToken
+ values[i].Data = zeroBytes
+ values[i].Ident = 0
+ } else if values[i].Ident == Right || values[i].Ident == Bottom {
+ values[i].TokenType = css.PercentageToken
+ values[i].Data = n100pBytes
+ values[i].Ident = 0
+ } else if values[i].Ident == Center {
+ if i == start {
+ values[i].TokenType = css.PercentageToken
+ values[i].Data = n50pBytes
+ values[i].Ident = 0
+ } else {
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ }
+ }
+ } else if i == start+1 && values[i].TokenType == css.PercentageToken && bytes.Equal(values[i].Data, n50pBytes) {
+ values = append(values[:start+1], values[start+2:]...)
+ end--
+ } else if values[i].TokenType == css.PercentageToken && values[i].Data[0] == '0' {
+ values[i].TokenType = css.NumberToken
+ values[i].Data = zeroBytes
+ values[i].Ident = 0
+ }
+ }
+ }
+ start = end + 1
+ }
+ case Box_Shadow:
+ start := 0
+ for end := 0; end <= len(values); end++ { // loop over comma-separated lists
+ if end != len(values) && values[end].TokenType != css.CommaToken {
+ continue
+ } else if start == end {
+ start++
+ continue
+ }
+
+ if end-start == 1 && values[start].Ident == Initial {
+ values[start].Ident = None
+ values[start].Data = noneBytes
+ } else {
+ numbers := []int{}
+ for i := start; i < end; i++ {
+ if values[i].IsLength() {
+ numbers = append(numbers, i)
+ }
+ }
+ if len(numbers) == 4 && values[numbers[3]].IsZero() {
+ values = append(values[:numbers[3]], values[numbers[3]+1:]...)
+ numbers = numbers[:3]
+ end--
+ }
+ if len(numbers) == 3 && values[numbers[2]].IsZero() {
+ values = append(values[:numbers[2]], values[numbers[2]+1:]...)
+ end--
+ }
+ }
+ start = end + 1
+ }
+ case Ms_Filter:
+ alpha := []byte("progid:DXImageTransform.Microsoft.Alpha(Opacity=")
+ if values[0].TokenType == css.StringToken && 2 < len(values[0].Data) && bytes.HasPrefix(values[0].Data[1:len(values[0].Data)-1], alpha) {
+ values[0].Data = append(append([]byte{values[0].Data[0]}, []byte("alpha(opacity=")...), values[0].Data[1+len(alpha):]...)
+ }
+ case Color:
+ values[0] = minifyColor(values[0])
+ case Background_Color:
+ values[0] = minifyColor(values[0])
+ if !c.o.KeepCSS2 {
+ if values[0].Ident == Transparent {
+ values[0].Data = initialBytes
+ values[0].Ident = Initial
+ }
+ }
+ case Border_Color:
+ sameValues := true
+ for i := range values {
+ if values[i].Ident == Currentcolor {
+ values[i].Data = initialBytes
+ values[i].Ident = Initial
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ if 0 < i && sameValues && !bytes.Equal(values[0].Data, values[i].Data) {
+ sameValues = false
+ }
+ }
+ if sameValues {
+ values = values[:1]
+ }
+ case Border_Left_Color, Border_Right_Color, Border_Top_Color, Border_Bottom_Color, Text_Decoration_Color, Text_Emphasis_Color:
+ if values[0].Ident == Currentcolor {
+ values[0].Data = initialBytes
+ values[0].Ident = Initial
+ } else {
+ values[0] = minifyColor(values[0])
+ }
+ case Caret_Color, Outline_Color, Fill, Stroke:
+ values[0] = minifyColor(values[0])
+ case Column_Rule:
+ for i := 0; i < len(values); i++ {
+ if values[i].Ident == Currentcolor || values[i].Ident == None || values[i].Ident == Medium {
+ values = append(values[:i], values[i+1:]...)
+ i--
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ }
+ if len(values) == 0 {
+ values = []Token{{css.IdentToken, noneBytes, nil, 0, None}}
+ }
+ case Text_Shadow:
+ // TODO: minify better (can be comma separated list)
+ for i := 0; i < len(values); i++ {
+ values[i] = minifyColor(values[i])
+ }
+ case Text_Decoration:
+ for i := 0; i < len(values); i++ {
+ if values[i].Ident == Currentcolor || values[i].Ident == None || values[i].Ident == Solid {
+ values = append(values[:i], values[i+1:]...)
+ i--
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ }
+ if len(values) == 0 {
+ values = []Token{{css.IdentToken, noneBytes, nil, 0, None}}
+ }
+ case Text_Emphasis:
+ for i := 0; i < len(values); i++ {
+ if values[i].Ident == Currentcolor || values[i].Ident == None {
+ values = append(values[:i], values[i+1:]...)
+ i--
+ } else {
+ values[i] = minifyColor(values[i])
+ }
+ }
+ if len(values) == 0 {
+ values = []Token{{css.IdentToken, noneBytes, nil, 0, None}}
+ }
+ case Flex:
+ if len(values) == 2 && values[0].TokenType == css.NumberToken {
+ if values[1].TokenType != css.NumberToken && values[1].IsZero() {
+ values = values[:1] // remove <flex-basis> if it is zero
+ }
+ } else if len(values) == 3 && values[0].TokenType == css.NumberToken && values[1].TokenType == css.NumberToken {
+ if len(values[0].Data) == 1 && len(values[1].Data) == 1 {
+ if values[2].Ident == Auto {
+ if values[0].Data[0] == '0' && values[1].Data[0] == '1' {
+ values = values[:1]
+ values[0].TokenType = css.IdentToken
+ values[0].Data = initialBytes
+ values[0].Ident = Initial
+ } else if values[0].Data[0] == '1' && values[1].Data[0] == '1' {
+ values = values[:1]
+ values[0].TokenType = css.IdentToken
+ values[0].Data = autoBytes
+ values[0].Ident = Auto
+ } else if values[0].Data[0] == '0' && values[1].Data[0] == '0' {
+ values = values[:1]
+ values[0].TokenType = css.IdentToken
+ values[0].Data = noneBytes
+ values[0].Ident = None
+ }
+ } else if values[1].Data[0] == '1' && values[2].IsZero() {
+ values = values[:1] // remove <flex-shrink> and <flex-basis> if they are 1 and 0 respectively
+ } else if values[2].IsZero() {
+ values = values[:2] // remove auto to write 2-value syntax of <flex-grow> <flex-shrink>
+ } else {
+ values[2] = minifyLengthPercentage(values[2])
+ }
+ }
+ }
+ case Flex_Basis:
+ if values[0].Ident == Initial {
+ values[0].Data = autoBytes
+ values[0].Ident = Auto
+ } else {
+ values[0] = minifyLengthPercentage(values[0])
+ }
+ case Order, Flex_Grow:
+ if values[0].Ident == Initial {
+ values[0].TokenType = css.NumberToken
+ values[0].Data = zeroBytes
+ values[0].Ident = 0
+ }
+ case Flex_Shrink:
+ if values[0].Ident == Initial {
+ values[0].TokenType = css.NumberToken
+ values[0].Data = oneBytes
+ values[0].Ident = 0
+ }
+ case Unicode_Range:
+ ranges := [][2]int{}
+ for _, value := range values {
+ if value.TokenType == css.CommaToken {
+ continue
+ } else if value.TokenType != css.UnicodeRangeToken {
+ return values
+ }
+
+ i := 2
+ iWildcard := 0
+ start := 0
+ for i < len(value.Data) && value.Data[i] != '-' {
+ start *= 16
+ if '0' <= value.Data[i] && value.Data[i] <= '9' {
+ start += int(value.Data[i] - '0')
+ } else if 'a' <= value.Data[i]|32 && value.Data[i]|32 <= 'f' {
+ start += int(value.Data[i]|32-'a') + 10
+ } else if iWildcard == 0 && value.Data[i] == '?' {
+ iWildcard = i
+ }
+ i++
+ }
+ end := start
+ if iWildcard != 0 {
+ end = start + int(math.Pow(16.0, float64(len(value.Data)-iWildcard))) - 1
+ } else if i < len(value.Data) && value.Data[i] == '-' {
+ i++
+ end = 0
+ for i < len(value.Data) {
+ end *= 16
+ if '0' <= value.Data[i] && value.Data[i] <= '9' {
+ end += int(value.Data[i] - '0')
+ } else if 'a' <= value.Data[i]|32 && value.Data[i]|32 <= 'f' {
+ end += int(value.Data[i]|32-'a') + 10
+ }
+ i++
+ }
+ if end <= start {
+ end = start
+ }
+ }
+ ranges = append(ranges, [2]int{start, end})
+ }
+
+ // sort and remove overlapping ranges
+ sort.Slice(ranges, func(i, j int) bool { return ranges[i][0] < ranges[j][0] })
+ for i := 0; i < len(ranges)-1; i++ {
+ if ranges[i+1][1] <= ranges[i][1] {
+ // next range is fully contained in the current range
+ ranges = append(ranges[:i+1], ranges[i+2:]...)
+ } else if ranges[i+1][0] <= ranges[i][1]+1 {
+ // next range is partially covering the current range
+ ranges[i][1] = ranges[i+1][1]
+ ranges = append(ranges[:i+1], ranges[i+2:]...)
+ }
+ }
+
+ values = values[:0]
+ for i, ran := range ranges {
+ if i != 0 {
+ values = append(values, Token{css.CommaToken, commaBytes, nil, 0, None})
+ }
+ if ran[0] == ran[1] {
+ urange := []byte(fmt.Sprintf("U+%X", ran[0]))
+ values = append(values, Token{css.UnicodeRangeToken, urange, nil, 0, None})
+ } else if ran[0] == 0 && ran[1] == 0x10FFFF {
+ values = append(values, Token{css.IdentToken, initialBytes, nil, 0, None})
+ } else {
+ k := 0
+ for k < 6 && (ran[0]>>(k*4))&0xF == 0 && (ran[1]>>(k*4))&0xF == 0xF {
+ k++
+ }
+ wildcards := k
+ for k < 6 {
+ if (ran[0]>>(k*4))&0xF != (ran[1]>>(k*4))&0xF {
+ wildcards = 0
+ break
+ }
+ k++
+ }
+ var urange []byte
+ if wildcards != 0 {
+ if ran[0]>>(wildcards*4) == 0 {
+ urange = []byte(fmt.Sprintf("U+%s", strings.Repeat("?", wildcards)))
+ } else {
+ urange = []byte(fmt.Sprintf("U+%X%s", ran[0]>>(wildcards*4), strings.Repeat("?", wildcards)))
+ }
+ } else {
+ urange = []byte(fmt.Sprintf("U+%X-%X", ran[0], ran[1]))
+ }
+ values = append(values, Token{css.UnicodeRangeToken, urange, nil, 0, None})
+ }
+ }
+ }
+ return values
+}
+
+func minifyColor(value Token) Token {
+ data := value.Data
+ if value.TokenType == css.IdentToken {
+ if hexValue, ok := ShortenColorName[value.Ident]; ok {
+ value.TokenType = css.HashToken
+ value.Data = hexValue
+ }
+ } else if value.TokenType == css.HashToken {
+ parse.ToLower(data[1:])
+ if len(data) == 9 && data[7] == data[8] {
+ if data[7] == 'f' {
+ data = data[:7]
+ } else if data[7] == '0' {
+ data = blackBytes
+ }
+ }
+ if ident, ok := ShortenColorHex[string(data)]; ok {
+ value.TokenType = css.IdentToken
+ data = ident
+ } else if len(data) == 7 && data[1] == data[2] && data[3] == data[4] && data[5] == data[6] {
+ value.TokenType = css.HashToken
+ data[2] = data[3]
+ data[3] = data[5]
+ data = data[:4]
+ } else if len(data) == 9 && data[1] == data[2] && data[3] == data[4] && data[5] == data[6] && data[7] == data[8] {
+ // from working draft Color Module Level 4
+ value.TokenType = css.HashToken
+ data[2] = data[3]
+ data[3] = data[5]
+ data[4] = data[7]
+ data = data[:5]
+ }
+ value.Data = data
+ }
+ return value
+}
+
+func minifyNumberPercentage(value Token) Token {
+ // assumes input already minified
+ if value.TokenType == css.PercentageToken && len(value.Data) == 3 && value.Data[len(value.Data)-2] == '0' {
+ value.Data[1] = value.Data[0]
+ value.Data[0] = '.'
+ value.Data = value.Data[:2]
+ value.TokenType = css.NumberToken
+ } else if value.TokenType == css.NumberToken && 2 < len(value.Data) && value.Data[0] == '.' && value.Data[1] == '0' {
+ if value.Data[2] == '0' {
+ value.Data[0] = '.'
+ copy(value.Data[1:], value.Data[3:])
+ value.Data[len(value.Data)-2] = '%'
+ value.Data = value.Data[:len(value.Data)-1]
+ value.TokenType = css.PercentageToken
+ } else if len(value.Data) == 3 {
+ value.Data[0] = value.Data[2]
+ value.Data[1] = '%'
+ value.Data = value.Data[:2]
+ value.TokenType = css.PercentageToken
+ }
+ }
+ return value
+}
+
+func minifyLengthPercentage(value Token) Token {
+ if value.TokenType != css.NumberToken && value.IsZero() {
+ value.TokenType = css.NumberToken
+ value.Data = value.Data[:1] // remove dimension for zero value
+ }
+ return value
+}
+
+func (c *cssMinifier) minifyDimension(value Token) (Token, []byte) {
+ // TODO: add check for zero value
+ var dim []byte
+ if value.TokenType == css.DimensionToken {
+ n := len(value.Data)
+ for 0 < n {
+ lower := 'a' <= value.Data[n-1] && value.Data[n-1] <= 'z'
+ upper := 'A' <= value.Data[n-1] && value.Data[n-1] <= 'Z'
+ if !lower && !upper {
+ break
+ } else if upper {
+ value.Data[n-1] = value.Data[n-1] + ('a' - 'A')
+ }
+ n--
+ }
+
+ num := value.Data[:n]
+ if c.o.KeepCSS2 {
+ num = minify.Decimal(num, c.o.Precision) // don't use exponents
+ } else {
+ num = minify.Number(num, c.o.Precision)
+ }
+ dim = value.Data[n:]
+ value.Data = append(num, dim...)
+ }
+ return value, dim
+
+ // TODO: optimize
+ //if value.TokenType == css.DimensionToken {
+ // // TODO: reverse; parse dim not number
+ // n := parse.Number(value.Data)
+ // num := value.Data[:n]
+ // dim = value.Data[n:]
+ // parse.ToLower(dim)
+
+ // if c.o.KeepCSS2 {
+ // num = minify.Decimal(num, c.o.Precision) // don't use exponents
+ // } else {
+ // num = minify.Number(num, c.o.Precision)
+ // }
+
+ // // change dimension to compress number
+ // h := ToHash(dim)
+ // if h == Px || h == Pt || h == Pc || h == In || h == Mm || h == Cm || h == Q || h == Deg || h == Grad || h == Rad || h == Turn || h == S || h == Ms || h == Hz || h == Khz || h == Dpi || h == Dpcm || h == Dppx {
+ // d, _ := strconv.ParseFloat(string(num), 64) // can never fail
+ // var dimensions []Hash
+ // var multipliers []float64
+ // switch h {
+ // case Px:
+ // //dimensions = []Hash{In, Cm, Pc, Mm, Pt, Q}
+ // //multipliers = []float64{0.010416666666666667, 0.026458333333333333, 0.0625, 0.26458333333333333, 0.75, 1.0583333333333333}
+ // dimensions = []Hash{In, Pc, Pt}
+ // multipliers = []float64{0.010416666666666667, 0.0625, 0.75}
+ // case Pt:
+ // //dimensions = []Hash{In, Cm, Pc, Mm, Px, Q}
+ // //multipliers = []float64{0.013888888888888889, 0.035277777777777778, 0.083333333333333333, 0.35277777777777778, 1.3333333333333333, 1.4111111111111111}
+ // dimensions = []Hash{In, Pc, Px}
+ // multipliers = []float64{0.013888888888888889, 0.083333333333333333, 1.3333333333333333}
+ // case Pc:
+ // //dimensions = []Hash{In, Cm, Mm, Pt, Px, Q}
+ // //multipliers = []float64{0.16666666666666667, 0.42333333333333333, 4.2333333333333333, 12.0, 16.0, 16.933333333333333}
+ // dimensions = []Hash{In, Pt, Px}
+ // multipliers = []float64{0.16666666666666667, 12.0, 16.0}
+ // case In:
+ // //dimensions = []Hash{Cm, Pc, Mm, Pt, Px, Q}
+ // //multipliers = []float64{2.54, 6.0, 25.4, 72.0, 96.0, 101.6}
+ // dimensions = []Hash{Pc, Pt, Px}
+ // multipliers = []float64{6.0, 72.0, 96.0}
+ // case Cm:
+ // //dimensions = []Hash{In, Pc, Mm, Pt, Px, Q}
+ // //multipliers = []float64{0.39370078740157480, 2.3622047244094488, 10.0, 28.346456692913386, 37.795275590551181, 40.0}
+ // dimensions = []Hash{Mm, Q}
+ // multipliers = []float64{10.0, 40.0}
+ // case Mm:
+ // //dimensions = []Hash{In, Cm, Pc, Pt, Px, Q}
+ // //multipliers = []float64{0.039370078740157480, 0.1, 0.23622047244094488, 2.8346456692913386, 3.7795275590551181, 4.0}
+ // dimensions = []Hash{Cm, Q}
+ // multipliers = []float64{0.1, 4.0}
+ // case Q:
+ // //dimensions = []Hash{In, Cm, Pc, Pt, Px} // Q to mm is never smaller
+ // //multipliers = []float64{0.0098425196850393701, 0.025, 0.059055118110236220, 0.70866141732283465, 0.94488188976377953}
+ // dimensions = []Hash{Cm} // Q to mm is never smaller
+ // multipliers = []float64{0.025}
+ // case Deg:
+ // //dimensions = []Hash{Turn, Rad, Grad}
+ // //multipliers = []float64{0.0027777777777777778, 0.017453292519943296, 1.1111111111111111}
+ // dimensions = []Hash{Turn, Grad}
+ // multipliers = []float64{0.0027777777777777778, 1.1111111111111111}
+ // case Grad:
+ // //dimensions = []Hash{Turn, Rad, Deg}
+ // //multipliers = []float64{0.0025, 0.015707963267948966, 0.9}
+ // dimensions = []Hash{Turn, Deg}
+ // multipliers = []float64{0.0025, 0.9}
+ // case Turn:
+ // //dimensions = []Hash{Rad, Deg, Grad}
+ // //multipliers = []float64{6.2831853071795865, 360.0, 400.0}
+ // dimensions = []Hash{Deg, Grad}
+ // multipliers = []float64{360.0, 400.0}
+ // case Rad:
+ // //dimensions = []Hash{Turn, Deg, Grad}
+ // //multipliers = []float64{0.15915494309189534, 57.295779513082321, 63.661977236758134}
+ // case S:
+ // dimensions = []Hash{Ms}
+ // multipliers = []float64{1000.0}
+ // case Ms:
+ // dimensions = []Hash{S}
+ // multipliers = []float64{0.001}
+ // case Hz:
+ // dimensions = []Hash{Khz}
+ // multipliers = []float64{0.001}
+ // case Khz:
+ // dimensions = []Hash{Hz}
+ // multipliers = []float64{1000.0}
+ // case Dpi:
+ // dimensions = []Hash{Dppx, Dpcm}
+ // multipliers = []float64{0.010416666666666667, 0.39370078740157480}
+ // case Dpcm:
+ // //dimensions = []Hash{Dppx, Dpi}
+ // //multipliers = []float64{0.026458333333333333, 2.54}
+ // dimensions = []Hash{Dpi}
+ // multipliers = []float64{2.54}
+ // case Dppx:
+ // //dimensions = []Hash{Dpcm, Dpi}
+ // //multipliers = []float64{37.795275590551181, 96.0}
+ // dimensions = []Hash{Dpi}
+ // multipliers = []float64{96.0}
+ // }
+ // for i := range dimensions {
+ // if dimensions[i] != h { //&& (d < 1.0) == (multipliers[i] > 1.0) {
+ // b, _ := strconvParse.AppendFloat([]byte{}, d*multipliers[i], -1)
+ // if c.o.KeepCSS2 {
+ // b = minify.Decimal(b, c.o.newPrecision) // don't use exponents
+ // } else {
+ // b = minify.Number(b, c.o.newPrecision)
+ // }
+ // newDim := []byte(dimensions[i].String())
+ // if len(b)+len(newDim) < len(num)+len(dim) {
+ // num = b
+ // dim = newDim
+ // }
+ // }
+ // }
+ // }
+ // value.Data = append(num, dim...)
+ //}
+ //return value, dim
+}
diff --git a/vendor/github.com/tdewolff/minify/v2/css/hash.go b/vendor/github.com/tdewolff/minify/v2/css/hash.go
new file mode 100644
index 0000000..98692c8
--- /dev/null
+++ b/vendor/github.com/tdewolff/minify/v2/css/hash.go
@@ -0,0 +1,1392 @@
+package css
+
+// uses github.com/tdewolff/hasher
+//go:generate hasher -type=Hash -file=hash.go
+
+// Hash defines perfect hashes for a predefined list of strings
+type Hash uint32
+
+// Identifiers for the hashes associated with the text in the comments.
+const (
+ Ms_Filter Hash = 0xa // -ms-filter
+ Accelerator Hash = 0x3760b // accelerator
+ Aliceblue Hash = 0x7a209 // aliceblue
+ Align_Content Hash = 0xd980d // align-content
+ Align_Items Hash = 0x7ef0b // align-items
+ Align_Self Hash = 0x8cb0a // align-self
+ All Hash = 0x69103 // all
+ Alpha Hash = 0x37205 // alpha
+ Animation Hash = 0xca09 // animation
+ Animation_Delay Hash = 0x2050f // animation-delay
+ Animation_Direction Hash = 0x8e913 // animation-direction
+ Animation_Duration Hash = 0x35d12 // animation-duration
+ Animation_Fill_Mode Hash = 0x66c13 // animation-fill-mode
+ Animation_Iteration_Count Hash = 0xd4919 // animation-iteration-count
+ Animation_Name Hash = 0xca0e // animation-name
+ Animation_Play_State Hash = 0xfc14 // animation-play-state
+ Animation_Timing_Function Hash = 0x14119 // animation-timing-function
+ Antiquewhite Hash = 0x6490c // antiquewhite
+ Aquamarine Hash = 0x9ec0a // aquamarine
+ Attr Hash = 0x59804 // attr
+ Auto Hash = 0x44504 // auto
+ Azimuth Hash = 0x15a07 // azimuth
+ Background Hash = 0x2b0a // background
+ Background_Attachment Hash = 0x2b15 // background-attachment
+ Background_Clip Hash = 0xb6e0f // background-clip
+ Background_Color Hash = 0x21710 // background-color
+ Background_Image Hash = 0x5ad10 // background-image
+ Background_Origin Hash = 0x17111 // background-origin
+ Background_Position Hash = 0x18e13 // background-position
+ Background_Position_X Hash = 0x18e15 // background-position-x
+ Background_Position_Y Hash = 0x1a315 // background-position-y
+ Background_Repeat Hash = 0x1b811 // background-repeat
+ Background_Size Hash = 0x1cb0f // background-size
+ Behavior Hash = 0x1da08 // behavior
+ Black Hash = 0x1e205 // black
+ Blanchedalmond Hash = 0x1e70e // blanchedalmond
+ Blueviolet Hash = 0x7a70a // blueviolet
+ Bold Hash = 0x1fc04 // bold
+ Border Hash = 0x22706 // border
+ Border_Bottom Hash = 0x2270d // border-bottom
+ Border_Bottom_Color Hash = 0x22713 // border-bottom-color
+ Border_Bottom_Style Hash = 0x23a13 // border-bottom-style
+ Border_Bottom_Width Hash = 0x25d13 // border-bottom-width
+ Border_Box Hash = 0x27e0a // border-box
+ Border_Collapse Hash = 0x2b60f // border-collapse
+ Border_Color Hash = 0x2d30c // border-color
+ Border_Left Hash = 0x2df0b // border-left
+ Border_Left_Color Hash = 0x2df11 // border-left-color
+ Border_Left_Style Hash = 0x2f011 // border-left-style
+ Border_Left_Width Hash = 0x30111 // border-left-width
+ Border_Right Hash = 0x3120c // border-right
+ Border_Right_Color Hash = 0x31212 // border-right-color
+ Border_Right_Style Hash = 0x32412 // border-right-style
+ Border_Right_Width Hash = 0x33612 // border-right-width
+ Border_Spacing Hash = 0x3480e // border-spacing
+ Border_Style Hash = 0x3ab0c // border-style
+ Border_Top Hash = 0x3b70a // border-top
+ Border_Top_Color Hash = 0x3b710 // border-top-color
+ Border_Top_Style Hash = 0x3c710 // border-top-style
+ Border_Top_Width Hash = 0x3d710 // border-top-width
+ Border_Width Hash = 0x3e70c // border-width
+ Bottom Hash = 0x22e06 // bottom
+ Box_Shadow Hash = 0x2850a // box-shadow
+ Burlywood Hash = 0x3f309 // burlywood
+ Cadetblue Hash = 0x9c609 // cadetblue
+ Calc Hash = 0x9c304 // calc
+ Caption_Side Hash = 0x40f0c // caption-side
+ Caret_Color Hash = 0x4240b // caret-color
+ Center Hash = 0xdb06 // center
+ Charset Hash = 0x62f07 // charset
+ Chartreuse Hash = 0x42f0a // chartreuse
+ Chocolate Hash = 0x43909 // chocolate
+ Clamp Hash = 0x44e05 // clamp
+ Clear Hash = 0x45d05 // clear
+ Clip Hash = 0xb7904 // clip
+ Cm Hash = 0x53802 // cm
+ Color Hash = 0x2505 // color
+ Column_Count Hash = 0x4620c // column-count
+ Column_Gap Hash = 0x6a30a // column-gap
+ Column_Rule Hash = 0x4880b // column-rule
+ Column_Rule_Color Hash = 0x48811 // column-rule-color
+ Column_Rule_Style Hash = 0x49911 // column-rule-style
+ Column_Rule_Width Hash = 0x4aa11 // column-rule-width
+ Column_Width Hash = 0x4bb0c // column-width
+ Columns Hash = 0x74607 // columns
+ Content Hash = 0x5607 // content
+ Cornflowerblue Hash = 0x4c70e // cornflowerblue
+ Cornsilk Hash = 0x4d508 // cornsilk
+ Counter_Increment Hash = 0xd5d11 // counter-increment
+ Counter_Reset Hash = 0x4690d // counter-reset
+ Cue Hash = 0x4dd03 // cue
+ Cue_After Hash = 0x4dd09 // cue-after
+ Cue_Before Hash = 0x4e60a // cue-before
+ Currentcolor Hash = 0x5010c // currentcolor
+ Cursive Hash = 0x50d07 // cursive
+ Cursor Hash = 0x51406 // cursor
+ Darkblue Hash = 0x1f408 // darkblue
+ Darkcyan Hash = 0x1ff08 // darkcyan
+ Darkgoldenrod Hash = 0x3fb0d // darkgoldenrod
+ Darkgray Hash = 0x40708 // darkgray
+ Darkgreen Hash = 0x75c09 // darkgreen
+ Darkkhaki Hash = 0xa1409 // darkkhaki
+ Darkmagenta Hash = 0xce90b // darkmagenta
+ Darkolivegreen Hash = 0x6d90e // darkolivegreen
+ Darkorange Hash = 0x7500a // darkorange
+ Darkorchid Hash = 0xa0b0a // darkorchid
+ Darksalmon Hash = 0xa990a // darksalmon
+ Darkseagreen Hash = 0xb110c // darkseagreen
+ Darkslateblue Hash = 0xc1c0d // darkslateblue
+ Darkslategray Hash = 0xbfa0d // darkslategray
+ Darkturquoise Hash = 0xcaa0d // darkturquoise
+ Darkviolet Hash = 0x51a0a // darkviolet
+ Deeppink Hash = 0x67d08 // deeppink
+ Deepskyblue Hash = 0x4190b // deepskyblue
+ Default Hash = 0xa2207 // default
+ Deg Hash = 0x70103 // deg
+ Direction Hash = 0x8d909 // direction
+ Display Hash = 0xcce07 // display
+ Document Hash = 0x52408 // document
+ Dodgerblue Hash = 0x52c0a // dodgerblue
+ Dpcm Hash = 0x53604 // dpcm
+ Dpi Hash = 0x54f03 // dpi
+ Dppx Hash = 0x55b04 // dppx
+ Elevation Hash = 0x6d09 // elevation
+ Empty_Cells Hash = 0x3910b // empty-cells
+ Env Hash = 0x4f503 // env
+ Fantasy Hash = 0x3a407 // fantasy
+ Fill Hash = 0x67604 // fill
+ Filter Hash = 0x406 // filter
+ Firebrick Hash = 0x83509 // firebrick
+ Flex Hash = 0x55f04 // flex
+ Flex_Basis Hash = 0x89d0a // flex-basis
+ Flex_Direction Hash = 0x8d40e // flex-direction
+ Flex_Flow Hash = 0xc8709 // flex-flow
+ Flex_Grow Hash = 0x55f09 // flex-grow
+ Flex_Shrink Hash = 0x5680b // flex-shrink
+ Flex_Wrap Hash = 0x57309 // flex-wrap
+ Float Hash = 0x59505 // float
+ Floralwhite Hash = 0x5bd0b // floralwhite
+ Font Hash = 0x25404 // font
+ Font_Face Hash = 0x25409 // font-face
+ Font_Family Hash = 0x5ee0b // font-family
+ Font_Size Hash = 0x5f909 // font-size
+ Font_Size_Adjust Hash = 0x5f910 // font-size-adjust
+ Font_Stretch Hash = 0x6250c // font-stretch
+ Font_Style Hash = 0x6360a // font-style
+ Font_Variant Hash = 0x6400c // font-variant
+ Font_Weight Hash = 0x65b0b // font-weight
+ Forestgreen Hash = 0x4ec0b // forestgreen
+ Fuchsia Hash = 0x66607 // fuchsia
+ Function Hash = 0x15208 // function
+ Gainsboro Hash = 0xec09 // gainsboro
+ Ghostwhite Hash = 0x2990a // ghostwhite
+ Goldenrod Hash = 0x3ff09 // goldenrod
+ Grad Hash = 0x1004 // grad
+ Greenyellow Hash = 0x7600b // greenyellow
+ Grid Hash = 0x35504 // grid
+ Grid_Area Hash = 0x35509 // grid-area
+ Grid_Auto_Columns Hash = 0x7bb11 // grid-auto-columns
+ Grid_Auto_Flow Hash = 0x81c0e // grid-auto-flow
+ Grid_Auto_Rows Hash = 0x8640e // grid-auto-rows
+ Grid_Column Hash = 0x69e0b // grid-column
+ Grid_Column_End Hash = 0xcdb0f // grid-column-end
+ Grid_Column_Gap Hash = 0x69e0f // grid-column-gap
+ Grid_Column_Start Hash = 0x6bd11 // grid-column-start
+ Grid_Row Hash = 0x6ce08 // grid-row
+ Grid_Row_End Hash = 0x6ce0c // grid-row-end
+ Grid_Row_Gap Hash = 0x6e70c // grid-row-gap
+ Grid_Row_Start Hash = 0x7030e // grid-row-start
+ Grid_Template Hash = 0x7110d // grid-template
+ Grid_Template_Areas Hash = 0x71113 // grid-template-areas
+ Grid_Template_Columns Hash = 0x73815 // grid-template-columns
+ Grid_Template_Rows Hash = 0x77012 // grid-template-rows
+ Height Hash = 0x9306 // height
+ Honeydew Hash = 0x16008 // honeydew
+ Hsl Hash = 0x26f03 // hsl
+ Hsla Hash = 0x26f04 // hsla
+ Hz Hash = 0x68502 // hz
+ Ime_Mode Hash = 0xa1c08 // ime-mode
+ Import Hash = 0x78d06 // import
+ Important Hash = 0x78d09 // important
+ In Hash = 0x4402 // in
+ Include_Source Hash = 0x1800e // include-source
+ Indianred Hash = 0xb0909 // indianred
+ Inherit Hash = 0x79607 // inherit
+ Initial Hash = 0x79d07 // initial
+ Invert Hash = 0x7e406 // invert
+ Justify_Content Hash = 0x4e0f // justify-content
+ Justify_Items Hash = 0x6050d // justify-items
+ Justify_Self Hash = 0x82a0c // justify-self
+ Keyframes Hash = 0x5cb09 // keyframes
+ Khz Hash = 0x68403 // khz
+ Large Hash = 0xa905 // large
+ Larger Hash = 0xa906 // larger
+ Lavender Hash = 0x27108 // lavender
+ Lavenderblush Hash = 0x2710d // lavenderblush
+ Lawngreen Hash = 0x2ca09 // lawngreen
+ Layer_Background_Color Hash = 0x21116 // layer-background-color
+ Layer_Background_Image Hash = 0x5a716 // layer-background-image
+ Layout_Flow Hash = 0xcf80b // layout-flow
+ Layout_Grid Hash = 0x8050b // layout-grid
+ Layout_Grid_Char Hash = 0x80510 // layout-grid-char
+ Layout_Grid_Char_Spacing Hash = 0x80518 // layout-grid-char-spacing
+ Layout_Grid_Line Hash = 0x83e10 // layout-grid-line
+ Layout_Grid_Mode Hash = 0x85410 // layout-grid-mode
+ Layout_Grid_Type Hash = 0x88710 // layout-grid-type
+ Left Hash = 0x2e604 // left
+ Lemonchiffon Hash = 0x24b0c // lemonchiffon
+ Letter_Spacing Hash = 0x7ae0e // letter-spacing
+ Lightblue Hash = 0x8ba09 // lightblue
+ Lightcoral Hash = 0x8c30a // lightcoral
+ Lightcyan Hash = 0x8e209 // lightcyan
+ Lightgoldenrodyellow Hash = 0x8fc14 // lightgoldenrodyellow
+ Lightgray Hash = 0x91009 // lightgray
+ Lightgreen Hash = 0x9190a // lightgreen
+ Lightpink Hash = 0x92309 // lightpink
+ Lightsalmon Hash = 0x92c0b // lightsalmon
+ Lightseagreen Hash = 0x9370d // lightseagreen
+ Lightskyblue Hash = 0x9440c // lightskyblue
+ Lightslateblue Hash = 0x9500e // lightslateblue
+ Lightsteelblue Hash = 0x95e0e // lightsteelblue
+ Lightyellow Hash = 0x96c0b // lightyellow
+ Limegreen Hash = 0x97709 // limegreen
+ Line_Break Hash = 0x84a0a // line-break
+ Line_Height Hash = 0x8e0b // line-height
+ Linear_Gradient Hash = 0x9800f // linear-gradient
+ List_Style Hash = 0x98f0a // list-style
+ List_Style_Image Hash = 0x98f10 // list-style-image
+ List_Style_Position Hash = 0x99f13 // list-style-position
+ List_Style_Type Hash = 0x9b20f // list-style-type
+ Local Hash = 0x9c105 // local
+ Magenta Hash = 0xced07 // magenta
+ Margin Hash = 0x53906 // margin
+ Margin_Bottom Hash = 0xdb10d // margin-bottom
+ Margin_Left Hash = 0xdbd0b // margin-left
+ Margin_Right Hash = 0xb890c // margin-right
+ Margin_Top Hash = 0x5390a // margin-top
+ Marker_Offset Hash = 0xad00d // marker-offset
+ Marks Hash = 0xaee05 // marks
+ Mask Hash = 0x9cf04 // mask
+ Max Hash = 0x9d303 // max
+ Max_Height Hash = 0x9d30a // max-height
+ Max_Width Hash = 0x9dd09 // max-width
+ Media Hash = 0xd4505 // media
+ Medium Hash = 0x9e606 // medium
+ Mediumaquamarine Hash = 0x9e610 // mediumaquamarine
+ Mediumblue Hash = 0x9f60a // mediumblue
+ Mediumorchid Hash = 0xa000c // mediumorchid
+ Mediumpurple Hash = 0xa420c // mediumpurple
+ Mediumseagreen Hash = 0xa4e0e // mediumseagreen
+ Mediumslateblue Hash = 0xa5c0f // mediumslateblue
+ Mediumspringgreen Hash = 0xa6b11 // mediumspringgreen
+ Mediumturquoise Hash = 0xa7c0f // mediumturquoise
+ Mediumvioletred Hash = 0xa8b0f // mediumvioletred
+ Midnightblue Hash = 0xaa90c // midnightblue
+ Min Hash = 0x14d03 // min
+ Min_Height Hash = 0xab50a // min-height
+ Min_Width Hash = 0xabf09 // min-width
+ Mintcream Hash = 0xac809 // mintcream
+ Mistyrose Hash = 0xae409 // mistyrose
+ Mm Hash = 0xaed02 // mm
+ Moccasin Hash = 0xb0308 // moccasin
+ Monospace Hash = 0xaa009 // monospace
+ Ms Hash = 0x102 // ms
+ Namespace Hash = 0xd409 // namespace
+ Navajowhite Hash = 0x750b // navajowhite
+ No_Repeat Hash = 0xbf09 // no-repeat
+ None Hash = 0x38e04 // none
+ Normal Hash = 0x36e06 // normal
+ Offset Hash = 0xad706 // offset
+ Offset_Anchor Hash = 0xad70d // offset-anchor
+ Offset_Distance Hash = 0xb1d0f // offset-distance
+ Offset_Path Hash = 0xb2c0b // offset-path
+ Offset_Position Hash = 0xb370f // offset-position
+ Offset_Rotate Hash = 0xb460d // offset-rotate
+ Olivedrab Hash = 0xb6609 // olivedrab
+ Orangered Hash = 0x75409 // orangered
+ Order Hash = 0x22805 // order
+ Orphans Hash = 0x37f07 // orphans
+ Outline Hash = 0xba707 // outline
+ Outline_Color Hash = 0xba70d // outline-color
+ Outline_Style Hash = 0xbb40d // outline-style
+ Outline_Width Hash = 0xbc10d // outline-width
+ Overflow Hash = 0x9d08 // overflow
+ Overflow_X Hash = 0x9d0a // overflow-x
+ Overflow_Y Hash = 0xbce0a // overflow-y
+ Padding Hash = 0x45207 // padding
+ Padding_Bottom Hash = 0xb7c0e // padding-bottom
+ Padding_Box Hash = 0x4520b // padding-box
+ Padding_Left Hash = 0xd0a0c // padding-left
+ Padding_Right Hash = 0x5420d // padding-right
+ Padding_Top Hash = 0x57b0b // padding-top
+ Page Hash = 0x58504 // page
+ Page_Break_After Hash = 0x58510 // page-break-after
+ Page_Break_Before Hash = 0x6ac11 // page-break-before
+ Page_Break_Inside Hash = 0x6f211 // page-break-inside
+ Palegoldenrod Hash = 0xc100d // palegoldenrod
+ Palegreen Hash = 0xbd809 // palegreen
+ Paleturquoise Hash = 0xbe10d // paleturquoise
+ Palevioletred Hash = 0xbee0d // palevioletred
+ Papayawhip Hash = 0xc070a // papayawhip
+ Pause Hash = 0xc2905 // pause
+ Pause_After Hash = 0xc290b // pause-after
+ Pause_Before Hash = 0xc340c // pause-before
+ Pc Hash = 0x53702 // pc
+ Peachpuff Hash = 0x89509 // peachpuff
+ Pitch Hash = 0x55005 // pitch
+ Pitch_Range Hash = 0x5500b // pitch-range
+ Place_Content Hash = 0xc400d // place-content
+ Place_Items Hash = 0xc4d0b // place-items
+ Place_Self Hash = 0xc7e0a // place-self
+ Play_During Hash = 0xcd10b // play-during
+ Position Hash = 0x13908 // position
+ Powderblue Hash = 0xc9b0a // powderblue
+ Progid Hash = 0xca506 // progid
+ Pt Hash = 0x39302 // pt
+ Px Hash = 0x55d02 // px
+ Q Hash = 0x64d01 // q
+ Quotes Hash = 0xcb706 // quotes
+ Rad Hash = 0x903 // rad
+ Radial_Gradient Hash = 0x90f // radial-gradient
+ Repeat Hash = 0xc206 // repeat
+ Repeat_X Hash = 0x1c308 // repeat-x
+ Repeat_Y Hash = 0xc208 // repeat-y
+ Rgb Hash = 0x2903 // rgb
+ Rgba Hash = 0x2904 // rgba
+ Richness Hash = 0xae08 // richness
+ Right Hash = 0x31905 // right
+ Rosybrown Hash = 0xf309 // rosybrown
+ Round Hash = 0x3005 // round
+ Row_Gap Hash = 0x6ec07 // row-gap
+ Royalblue Hash = 0x69509 // royalblue
+ Ruby_Align Hash = 0xd930a // ruby-align
+ Ruby_Overhang Hash = 0xe00d // ruby-overhang
+ Ruby_Position Hash = 0x1340d // ruby-position
+ S Hash = 0x201 // s
+ Saddlebrown Hash = 0xb50b // saddlebrown
+ Sandybrown Hash = 0x3850a // sandybrown
+ Sans_Serif Hash = 0x39b0a // sans-serif
+ Scroll Hash = 0x12006 // scroll
+ Scrollbar_3d_Light_Color Hash = 0xd7c18 // scrollbar-3d-light-color
+ Scrollbar_Arrow_Color Hash = 0x12015 // scrollbar-arrow-color
+ Scrollbar_Base_Color Hash = 0x8a614 // scrollbar-base-color
+ Scrollbar_Dark_Shadow_Color Hash = 0x5d31b // scrollbar-dark-shadow-color
+ Scrollbar_Face_Color Hash = 0x61114 // scrollbar-face-color
+ Scrollbar_Highlight_Color Hash = 0x7cb19 // scrollbar-highlight-color
+ Scrollbar_Shadow_Color Hash = 0x87116 // scrollbar-shadow-color
+ Scrollbar_Track_Color Hash = 0x72315 // scrollbar-track-color
+ Seagreen Hash = 0x93c08 // seagreen
+ Seashell Hash = 0x2c308 // seashell
+ Serif Hash = 0x3a005 // serif
+ Size Hash = 0x1d604 // size
+ Slateblue Hash = 0x95509 // slateblue
+ Slategray Hash = 0xbfe09 // slategray
+ Small Hash = 0x68f05 // small
+ Smaller Hash = 0x68f07 // smaller
+ Solid Hash = 0x74c05 // solid
+ Space Hash = 0x6905 // space
+ Speak Hash = 0x78105 // speak
+ Speak_Header Hash = 0x7810c // speak-header
+ Speak_Numeral Hash = 0x7f90d // speak-numeral
+ Speak_Punctuation Hash = 0xaf211 // speak-punctuation
+ Speech_Rate Hash = 0xc570b // speech-rate
+ Springgreen Hash = 0xa710b // springgreen
+ Steelblue Hash = 0x96309 // steelblue
+ Stress Hash = 0x11b06 // stress
+ Stroke Hash = 0xc7806 // stroke
+ Supports Hash = 0xcbc08 // supports
+ Table_Layout Hash = 0xcf20c // table-layout
+ Text_Align Hash = 0x10e0a // text-align
+ Text_Align_Last Hash = 0x10e0f // text-align-last
+ Text_Autospace Hash = 0x4400e // text-autospace
+ Text_Decoration Hash = 0x7e0f // text-decoration
+ Text_Decoration_Color Hash = 0x2a115 // text-decoration-color
+ Text_Decoration_Line Hash = 0x7e14 // text-decoration-line
+ Text_Decoration_Style Hash = 0xb5115 // text-decoration-style
+ Text_Decoration_Thickness Hash = 0xc6019 // text-decoration-thickness
+ Text_Emphasis Hash = 0x170d // text-emphasis
+ Text_Emphasis_Color Hash = 0x1713 // text-emphasis-color
+ Text_Indent Hash = 0x3f0b // text-indent
+ Text_Justify Hash = 0x490c // text-justify
+ Text_Kashida_Space Hash = 0x5c12 // text-kashida-space
+ Text_Overflow Hash = 0x980d // text-overflow
+ Text_Shadow Hash = 0xd6d0b // text-shadow
+ Text_Transform Hash = 0xda40e // text-transform
+ Text_Underline_Position Hash = 0xdc717 // text-underline-position
+ Top Hash = 0x3be03 // top
+ Transition Hash = 0x4750a // transition
+ Transition_Delay Hash = 0x59a10 // transition-delay
+ Transition_Duration Hash = 0xb9413 // transition-duration
+ Transition_Property Hash = 0x47513 // transition-property
+ Transition_Timing_Function Hash = 0xa281a // transition-timing-function
+ Transparent Hash = 0xd150b // transparent
+ Turn Hash = 0xd1f04 // turn
+ Turquoise Hash = 0xa8209 // turquoise
+ Unicode_Bidi Hash = 0xcc40c // unicode-bidi
+ Unicode_Range Hash = 0xd230d // unicode-range
+ Unset Hash = 0xd3005 // unset
+ Url Hash = 0x3f403 // url
+ Var Hash = 0x64503 // var
+ Vertical_Align Hash = 0x7e60e // vertical-align
+ Visibility Hash = 0x4f70a // visibility
+ Voice_Family Hash = 0xd350c // voice-family
+ Volume Hash = 0xd4106 // volume
+ White Hash = 0x7b05 // white
+ White_Space Hash = 0x6500b // white-space
+ Whitesmoke Hash = 0x5c30a // whitesmoke
+ Widows Hash = 0xd7706 // widows
+ Width Hash = 0x26b05 // width
+ Word_Break Hash = 0x1670a // word-break
+ Word_Spacing Hash = 0x28e0c // word-spacing
+ Word_Wrap Hash = 0xd0209 // word-wrap
+ Writing_Mode Hash = 0xc8f0c // writing-mode
+ X_Large Hash = 0xa707 // x-large
+ X_Small Hash = 0x68d07 // x-small
+ Xx_Large Hash = 0xa608 // xx-large
+ Xx_Small Hash = 0x68c08 // xx-small
+ Yellow Hash = 0x76506 // yellow
+ Yellowgreen Hash = 0x7650b // yellowgreen
+ Z_Index Hash = 0x68607 // z-index
+)
+
+//var HashMap = map[string]Hash{
+// "-ms-filter": Ms_Filter,
+// "accelerator": Accelerator,
+// "aliceblue": Aliceblue,
+// "align-content": Align_Content,
+// "align-items": Align_Items,
+// "align-self": Align_Self,
+// "all": All,
+// "alpha": Alpha,
+// "animation": Animation,
+// "animation-delay": Animation_Delay,
+// "animation-direction": Animation_Direction,
+// "animation-duration": Animation_Duration,
+// "animation-fill-mode": Animation_Fill_Mode,
+// "animation-iteration-count": Animation_Iteration_Count,
+// "animation-name": Animation_Name,
+// "animation-play-state": Animation_Play_State,
+// "animation-timing-function": Animation_Timing_Function,
+// "antiquewhite": Antiquewhite,
+// "aquamarine": Aquamarine,
+// "attr": Attr,
+// "auto": Auto,
+// "azimuth": Azimuth,
+// "background": Background,
+// "background-attachment": Background_Attachment,
+// "background-clip": Background_Clip,
+// "background-color": Background_Color,
+// "background-image": Background_Image,
+// "background-origin": Background_Origin,
+// "background-position": Background_Position,
+// "background-position-x": Background_Position_X,
+// "background-position-y": Background_Position_Y,
+// "background-repeat": Background_Repeat,
+// "background-size": Background_Size,
+// "behavior": Behavior,
+// "black": Black,
+// "blanchedalmond": Blanchedalmond,
+// "blueviolet": Blueviolet,
+// "bold": Bold,
+// "border": Border,
+// "border-bottom": Border_Bottom,
+// "border-bottom-color": Border_Bottom_Color,
+// "border-bottom-style": Border_Bottom_Style,
+// "border-bottom-width": Border_Bottom_Width,
+// "border-box": Border_Box,
+// "border-collapse": Border_Collapse,
+// "border-color": Border_Color,
+// "border-left": Border_Left,
+// "border-left-color": Border_Left_Color,
+// "border-left-style": Border_Left_Style,
+// "border-left-width": Border_Left_Width,
+// "border-right": Border_Right,
+// "border-right-color": Border_Right_Color,
+// "border-right-style": Border_Right_Style,
+// "border-right-width": Border_Right_Width,
+// "border-spacing": Border_Spacing,
+// "border-style": Border_Style,
+// "border-top": Border_Top,
+// "border-top-color": Border_Top_Color,
+// "border-top-style": Border_Top_Style,
+// "border-top-width": Border_Top_Width,
+// "border-width": Border_Width,
+// "bottom": Bottom,
+// "box-shadow": Box_Shadow,
+// "burlywood": Burlywood,
+// "cadetblue": Cadetblue,
+// "calc": Calc,
+// "caption-side": Caption_Side,
+// "caret-color": Caret_Color,
+// "center": Center,
+// "charset": Charset,
+// "chartreuse": Chartreuse,
+// "chocolate": Chocolate,
+// "clamp": Clamp,
+// "clear": Clear,
+// "clip": Clip,
+// "cm": Cm,
+// "color": Color,
+// "column-count": Column_Count,
+// "column-gap": Column_Gap,
+// "column-rule": Column_Rule,
+// "column-rule-color": Column_Rule_Color,
+// "column-rule-style": Column_Rule_Style,
+// "column-rule-width": Column_Rule_Width,
+// "column-width": Column_Width,
+// "columns": Columns,
+// "content": Content,
+// "cornflowerblue": Cornflowerblue,
+// "cornsilk": Cornsilk,
+// "counter-increment": Counter_Increment,
+// "counter-reset": Counter_Reset,
+// "cue": Cue,
+// "cue-after": Cue_After,
+// "cue-before": Cue_Before,
+// "currentcolor": Currentcolor,
+// "cursive": Cursive,
+// "cursor": Cursor,
+// "darkblue": Darkblue,
+// "darkcyan": Darkcyan,
+// "darkgoldenrod": Darkgoldenrod,
+// "darkgray": Darkgray,
+// "darkgreen": Darkgreen,
+// "darkkhaki": Darkkhaki,
+// "darkmagenta": Darkmagenta,
+// "darkolivegreen": Darkolivegreen,
+// "darkorange": Darkorange,
+// "darkorchid": Darkorchid,
+// "darksalmon": Darksalmon,
+// "darkseagreen": Darkseagreen,
+// "darkslateblue": Darkslateblue,
+// "darkslategray": Darkslategray,
+// "darkturquoise": Darkturquoise,
+// "darkviolet": Darkviolet,
+// "deeppink": Deeppink,
+// "deepskyblue": Deepskyblue,
+// "default": Default,
+// "deg": Deg,
+// "direction": Direction,
+// "display": Display,
+// "document": Document,
+// "dodgerblue": Dodgerblue,
+// "dpcm": Dpcm,
+// "dpi": Dpi,
+// "dppx": Dppx,
+// "elevation": Elevation,
+// "empty-cells": Empty_Cells,
+// "env": Env,
+// "fantasy": Fantasy,
+// "fill": Fill,
+// "filter": Filter,
+// "firebrick": Firebrick,
+// "flex": Flex,
+// "flex-basis": Flex_Basis,
+// "flex-direction": Flex_Direction,
+// "flex-flow": Flex_Flow,
+// "flex-grow": Flex_Grow,
+// "flex-shrink": Flex_Shrink,
+// "flex-wrap": Flex_Wrap,
+// "float": Float,
+// "floralwhite": Floralwhite,
+// "font": Font,
+// "font-face": Font_Face,
+// "font-family": Font_Family,
+// "font-size": Font_Size,
+// "font-size-adjust": Font_Size_Adjust,
+// "font-stretch": Font_Stretch,
+// "font-style": Font_Style,
+// "font-variant": Font_Variant,
+// "font-weight": Font_Weight,
+// "forestgreen": Forestgreen,
+// "fuchsia": Fuchsia,
+// "function": Function,
+// "gainsboro": Gainsboro,
+// "ghostwhite": Ghostwhite,
+// "goldenrod": Goldenrod,
+// "grad": Grad,
+// "greenyellow": Greenyellow,
+// "grid": Grid,
+// "grid-area": Grid_Area,
+// "grid-auto-columns": Grid_Auto_Columns,
+// "grid-auto-flow": Grid_Auto_Flow,
+// "grid-auto-rows": Grid_Auto_Rows,
+// "grid-column": Grid_Column,
+// "grid-column-end": Grid_Column_End,
+// "grid-column-gap": Grid_Column_Gap,
+// "grid-column-start": Grid_Column_Start,
+// "grid-row": Grid_Row,
+// "grid-row-end": Grid_Row_End,
+// "grid-row-gap": Grid_Row_Gap,
+// "grid-row-start": Grid_Row_Start,
+// "grid-template": Grid_Template,
+// "grid-template-areas": Grid_Template_Areas,
+// "grid-template-columns": Grid_Template_Columns,
+// "grid-template-rows": Grid_Template_Rows,
+// "height": Height,
+// "honeydew": Honeydew,
+// "hsl": Hsl,
+// "hsla": Hsla,
+// "hz": Hz,
+// "ime-mode": Ime_Mode,
+// "import": Import,
+// "important": Important,
+// "in": In,
+// "include-source": Include_Source,
+// "indianred": Indianred,
+// "inherit": Inherit,
+// "initial": Initial,
+// "invert": Invert,
+// "justify-content": Justify_Content,
+// "justify-items": Justify_Items,
+// "justify-self": Justify_Self,
+// "keyframes": Keyframes,
+// "khz": Khz,
+// "large": Large,
+// "larger": Larger,
+// "lavender": Lavender,
+// "lavenderblush": Lavenderblush,
+// "lawngreen": Lawngreen,
+// "layer-background-color": Layer_Background_Color,
+// "layer-background-image": Layer_Background_Image,
+// "layout-flow": Layout_Flow,
+// "layout-grid": Layout_Grid,
+// "layout-grid-char": Layout_Grid_Char,
+// "layout-grid-char-spacing": Layout_Grid_Char_Spacing,
+// "layout-grid-line": Layout_Grid_Line,
+// "layout-grid-mode": Layout_Grid_Mode,
+// "layout-grid-type": Layout_Grid_Type,
+// "left": Left,
+// "lemonchiffon": Lemonchiffon,
+// "letter-spacing": Letter_Spacing,
+// "lightblue": Lightblue,
+// "lightcoral": Lightcoral,
+// "lightcyan": Lightcyan,
+// "lightgoldenrodyellow": Lightgoldenrodyellow,
+// "lightgray": Lightgray,
+// "lightgreen": Lightgreen,
+// "lightpink": Lightpink,
+// "lightsalmon": Lightsalmon,
+// "lightseagreen": Lightseagreen,
+// "lightskyblue": Lightskyblue,
+// "lightslateblue": Lightslateblue,
+// "lightsteelblue": Lightsteelblue,
+// "lightyellow": Lightyellow,
+// "limegreen": Limegreen,
+// "line-break": Line_Break,
+// "line-height": Line_Height,
+// "linear-gradient": Linear_Gradient,
+// "list-style": List_Style,
+// "list-style-image": List_Style_Image,
+// "list-style-position": List_Style_Position,
+// "list-style-type": List_Style_Type,
+// "local": Local,
+// "magenta": Magenta,
+// "margin": Margin,
+// "margin-bottom": Margin_Bottom,
+// "margin-left": Margin_Left,
+// "margin-right": Margin_Right,
+// "margin-top": Margin_Top,
+// "marker-offset": Marker_Offset,
+// "marks": Marks,
+// "mask": Mask,
+// "max": Max,
+// "max-height": Max_Height,
+// "max-width": Max_Width,
+// "media": Media,
+// "medium": Medium,
+// "mediumaquamarine": Mediumaquamarine,
+// "mediumblue": Mediumblue,
+// "mediumorchid": Mediumorchid,
+// "mediumpurple": Mediumpurple,
+// "mediumseagreen": Mediumseagreen,
+// "mediumslateblue": Mediumslateblue,
+// "mediumspringgreen": Mediumspringgreen,
+// "mediumturquoise": Mediumturquoise,
+// "mediumvioletred": Mediumvioletred,
+// "midnightblue": Midnightblue,
+// "min": Min,
+// "min-height": Min_Height,
+// "min-width": Min_Width,
+// "mintcream": Mintcream,
+// "mistyrose": Mistyrose,
+// "mm": Mm,
+// "moccasin": Moccasin,
+// "monospace": Monospace,
+// "ms": Ms,
+// "namespace": Namespace,
+// "navajowhite": Navajowhite,
+// "no-repeat": No_Repeat,
+// "none": None,
+// "normal": Normal,
+// "offset": Offset,
+// "offset-anchor": Offset_Anchor,
+// "offset-distance": Offset_Distance,
+// "offset-path": Offset_Path,
+// "offset-position": Offset_Position,
+// "offset-rotate": Offset_Rotate,
+// "olivedrab": Olivedrab,
+// "orangered": Orangered,
+// "order": Order,
+// "orphans": Orphans,
+// "outline": Outline,
+// "outline-color": Outline_Color,
+// "outline-style": Outline_Style,
+// "outline-width": Outline_Width,
+// "overflow": Overflow,
+// "overflow-x": Overflow_X,
+// "overflow-y": Overflow_Y,
+// "padding": Padding,
+// "padding-bottom": Padding_Bottom,
+// "padding-box": Padding_Box,
+// "padding-left": Padding_Left,
+// "padding-right": Padding_Right,
+// "padding-top": Padding_Top,
+// "page": Page,
+// "page-break-after": Page_Break_After,
+// "page-break-before": Page_Break_Before,
+// "page-break-inside": Page_Break_Inside,
+// "palegoldenrod": Palegoldenrod,
+// "palegreen": Palegreen,
+// "paleturquoise": Paleturquoise,
+// "palevioletred": Palevioletred,
+// "papayawhip": Papayawhip,
+// "pause": Pause,
+// "pause-after": Pause_After,
+// "pause-before": Pause_Before,
+// "pc": Pc,
+// "peachpuff": Peachpuff,
+// "pitch": Pitch,
+// "pitch-range": Pitch_Range,
+// "place-content": Place_Content,
+// "place-items": Place_Items,
+// "place-self": Place_Self,
+// "play-during": Play_During,
+// "position": Position,
+// "powderblue": Powderblue,
+// "progid": Progid,
+// "pt": Pt,
+// "px": Px,
+// "q": Q,
+// "quotes": Quotes,
+// "rad": Rad,
+// "radial-gradient": Radial_Gradient,
+// "repeat": Repeat,
+// "repeat-x": Repeat_X,
+// "repeat-y": Repeat_Y,
+// "rgb": Rgb,
+// "rgba": Rgba,
+// "richness": Richness,
+// "right": Right,
+// "rosybrown": Rosybrown,
+// "round": Round,
+// "row-gap": Row_Gap,
+// "royalblue": Royalblue,
+// "ruby-align": Ruby_Align,
+// "ruby-overhang": Ruby_Overhang,
+// "ruby-position": Ruby_Position,
+// "s": S,
+// "saddlebrown": Saddlebrown,
+// "sandybrown": Sandybrown,
+// "sans-serif": Sans_Serif,
+// "scroll": Scroll,
+// "scrollbar-3d-light-color": Scrollbar_3d_Light_Color,
+// "scrollbar-arrow-color": Scrollbar_Arrow_Color,
+// "scrollbar-base-color": Scrollbar_Base_Color,
+// "scrollbar-dark-shadow-color": Scrollbar_Dark_Shadow_Color,
+// "scrollbar-face-color": Scrollbar_Face_Color,
+// "scrollbar-highlight-color": Scrollbar_Highlight_Color,
+// "scrollbar-shadow-color": Scrollbar_Shadow_Color,
+// "scrollbar-track-color": Scrollbar_Track_Color,
+// "seagreen": Seagreen,
+// "seashell": Seashell,
+// "serif": Serif,
+// "size": Size,
+// "slateblue": Slateblue,
+// "slategray": Slategray,
+// "small": Small,
+// "smaller": Smaller,
+// "solid": Solid,
+// "space": Space,
+// "speak": Speak,
+// "speak-header": Speak_Header,
+// "speak-numeral": Speak_Numeral,
+// "speak-punctuation": Speak_Punctuation,
+// "speech-rate": Speech_Rate,
+// "springgreen": Springgreen,
+// "steelblue": Steelblue,
+// "stress": Stress,
+// "stroke": Stroke,
+// "supports": Supports,
+// "table-layout": Table_Layout,
+// "text-align": Text_Align,
+// "text-align-last": Text_Align_Last,
+// "text-autospace": Text_Autospace,
+// "text-decoration": Text_Decoration,
+// "text-decoration-color": Text_Decoration_Color,
+// "text-decoration-line": Text_Decoration_Line,
+// "text-decoration-style": Text_Decoration_Style,
+// "text-decoration-thickness": Text_Decoration_Thickness,
+// "text-emphasis": Text_Emphasis,
+// "text-emphasis-color": Text_Emphasis_Color,
+// "text-indent": Text_Indent,
+// "text-justify": Text_Justify,
+// "text-kashida-space": Text_Kashida_Space,
+// "text-overflow": Text_Overflow,
+// "text-shadow": Text_Shadow,
+// "text-transform": Text_Transform,
+// "text-underline-position": Text_Underline_Position,
+// "top": Top,
+// "transition": Transition,
+// "transition-delay": Transition_Delay,
+// "transition-duration": Transition_Duration,
+// "transition-property": Transition_Property,
+// "transition-timing-function": Transition_Timing_Function,
+// "transparent": Transparent,
+// "turn": Turn,
+// "turquoise": Turquoise,
+// "unicode-bidi": Unicode_Bidi,
+// "unicode-range": UnicodeRange,
+// "unset": Unset,
+// "url": Url,
+// "var": Var,
+// "vertical-align": Vertical_Align,
+// "visibility": Visibility,
+// "voice-family": Voice_Family,
+// "volume": Volume,
+// "white": White,
+// "white-space": White_Space,
+// "whitesmoke": Whitesmoke,
+// "widows": Widows,
+// "width": Width,
+// "word-break": Word_Break,
+// "word-spacing": Word_Spacing,
+// "word-wrap": Word_Wrap,
+// "writing-mode": Writing_Mode,
+// "x-large": X_Large,
+// "x-small": X_Small,
+// "xx-large": Xx_Large,
+// "xx-small": Xx_Small,
+// "yellow": Yellow,
+// "yellowgreen": Yellowgreen,
+// "z-index": Z_Index,
+//}
+
+// String returns the text associated with the hash.
+func (i Hash) String() string {
+ return string(i.Bytes())
+}
+
+// Bytes returns the text associated with the hash.
+func (i Hash) Bytes() []byte {
+ start := uint32(i >> 8)
+ n := uint32(i & 0xff)
+ if start+n > uint32(len(_Hash_text)) {
+ return []byte{}
+ }
+ return _Hash_text[start : start+n]
+}
+
+// ToHash returns a hash Hash for a given []byte. Hash is a uint32 that is associated with the text in []byte. It returns zero if no match found.
+func ToHash(s []byte) Hash {
+ if len(s) == 0 || len(s) > _Hash_maxLen {
+ return 0
+ }
+ //if 3 < len(s) {
+ // return HashMap[string(s)]
+ //}
+ h := uint32(_Hash_hash0)
+ for i := 0; i < len(s); i++ {
+ h ^= uint32(s[i])
+ h *= 16777619
+ }
+ if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) {
+ t := _Hash_text[i>>8 : i>>8+i&0xff]
+ for i := 0; i < len(s); i++ {
+ if t[i] != s[i] {
+ goto NEXT
+ }
+ }
+ return i
+ }
+NEXT:
+ if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) {
+ t := _Hash_text[i>>8 : i>>8+i&0xff]
+ for i := 0; i < len(s); i++ {
+ if t[i] != s[i] {
+ return 0
+ }
+ }
+ return i
+ }
+ return 0
+}
+
+const _Hash_hash0 = 0x9acb0442
+const _Hash_maxLen = 27
+
+var _Hash_text = []byte("" +
+ "-ms-filteradial-gradientext-emphasis-colorgbackground-attach" +
+ "mentext-indentext-justify-contentext-kashida-spacelevationav" +
+ "ajowhitext-decoration-line-heightext-overflow-xx-largerichne" +
+ "ssaddlebrowno-repeat-yanimation-namespacenteruby-overhangain" +
+ "sborosybrownanimation-play-statext-align-lastresscrollbar-ar" +
+ "row-coloruby-positionanimation-timing-functionazimuthoneydew" +
+ "ord-breakbackground-originclude-sourcebackground-position-xb" +
+ "ackground-position-ybackground-repeat-xbackground-sizebehavi" +
+ "orblackblanchedalmondarkblueboldarkcyanimation-delayer-backg" +
+ "round-colorborder-bottom-colorborder-bottom-stylemonchiffont" +
+ "-faceborder-bottom-widthslavenderblushborder-box-shadoword-s" +
+ "pacinghostwhitext-decoration-colorborder-collapseashellawngr" +
+ "eenborder-colorborder-left-colorborder-left-styleborder-left" +
+ "-widthborder-right-colorborder-right-styleborder-right-width" +
+ "border-spacingrid-areanimation-durationormalphacceleratorpha" +
+ "nsandybrownonempty-cellsans-serifantasyborder-styleborder-to" +
+ "p-colorborder-top-styleborder-top-widthborder-widthburlywood" +
+ "arkgoldenrodarkgraycaption-sideepskybluecaret-colorchartreus" +
+ "echocolatext-autospaceclampadding-boxclearcolumn-counter-res" +
+ "etransition-propertycolumn-rule-colorcolumn-rule-stylecolumn" +
+ "-rule-widthcolumn-widthcornflowerbluecornsilkcue-aftercue-be" +
+ "forestgreenvisibilitycurrentcolorcursivecursordarkvioletdocu" +
+ "mentdodgerbluedpcmargin-topadding-rightdpitch-rangedppxflex-" +
+ "growflex-shrinkflex-wrapadding-topage-break-afterfloattransi" +
+ "tion-delayer-background-imagefloralwhitesmokeyframescrollbar" +
+ "-dark-shadow-colorfont-familyfont-size-adjustify-itemscrollb" +
+ "ar-face-colorfont-stretcharsetfont-stylefont-variantiquewhit" +
+ "e-spacefont-weightfuchsianimation-fill-modeeppinkhz-indexx-s" +
+ "malleroyalbluegrid-column-gapage-break-beforegrid-column-sta" +
+ "rtgrid-row-endarkolivegreengrid-row-gapage-break-insidegrid-" +
+ "row-startgrid-template-areascrollbar-track-colorgrid-templat" +
+ "e-columnsolidarkorangeredarkgreenyellowgreengrid-template-ro" +
+ "wspeak-headerimportantinheritinitialicebluevioletter-spacing" +
+ "rid-auto-columnscrollbar-highlight-colorinvertical-align-ite" +
+ "mspeak-numeralayout-grid-char-spacingrid-auto-flowjustify-se" +
+ "lfirebricklayout-grid-line-breaklayout-grid-modegrid-auto-ro" +
+ "wscrollbar-shadow-colorlayout-grid-typeachpufflex-basiscroll" +
+ "bar-base-colorlightbluelightcoralign-selflex-directionlightc" +
+ "yanimation-directionlightgoldenrodyellowlightgraylightgreenl" +
+ "ightpinklightsalmonlightseagreenlightskybluelightslateblueli" +
+ "ghtsteelbluelightyellowlimegreenlinear-gradientlist-style-im" +
+ "agelist-style-positionlist-style-typelocalcadetbluemaskmax-h" +
+ "eightmax-widthmediumaquamarinemediumbluemediumorchidarkorchi" +
+ "darkkhakime-modefaultransition-timing-functionmediumpurpleme" +
+ "diumseagreenmediumslatebluemediumspringgreenmediumturquoisem" +
+ "ediumvioletredarksalmonospacemidnightbluemin-heightmin-width" +
+ "mintcreamarker-offset-anchormistyrosemmarkspeak-punctuationm" +
+ "occasindianredarkseagreenoffset-distanceoffset-pathoffset-po" +
+ "sitionoffset-rotatext-decoration-styleolivedrabackground-cli" +
+ "padding-bottomargin-rightransition-durationoutline-coloroutl" +
+ "ine-styleoutline-widthoverflow-ypalegreenpaleturquoisepalevi" +
+ "oletredarkslategraypapayawhipalegoldenrodarkslatebluepause-a" +
+ "fterpause-beforeplace-contentplace-itemspeech-ratext-decorat" +
+ "ion-thicknesstrokeplace-selflex-flowriting-modepowderbluepro" +
+ "gidarkturquoisequotesupportsunicode-bidisplay-duringrid-colu" +
+ "mn-endarkmagentable-layout-floword-wrapadding-leftransparent" +
+ "urnunicode-rangeunsetvoice-familyvolumedianimation-iteration" +
+ "-counter-incrementext-shadowidowscrollbar-3d-light-coloruby-" +
+ "align-contentext-transformargin-bottomargin-leftext-underlin" +
+ "e-position")
+
+var _Hash_table = [1 << 10]Hash{
+ 0x3: 0xc290b, // pause-after
+ 0x6: 0xd5d11, // counter-increment
+ 0x8: 0xcce07, // display
+ 0x9: 0x51a0a, // darkviolet
+ 0xb: 0xbf09, // no-repeat
+ 0xd: 0x4402, // in
+ 0x14: 0x6f211, // page-break-inside
+ 0x15: 0x6250c, // font-stretch
+ 0x19: 0x5f910, // font-size-adjust
+ 0x1a: 0x47513, // transition-property
+ 0x1c: 0x78105, // speak
+ 0x1f: 0x82a0c, // justify-self
+ 0x20: 0x61114, // scrollbar-face-color
+ 0x24: 0x2b60f, // border-collapse
+ 0x25: 0x68607, // z-index
+ 0x27: 0xd980d, // align-content
+ 0x2a: 0x99f13, // list-style-position
+ 0x2b: 0xcdb0f, // grid-column-end
+ 0x2c: 0x14119, // animation-timing-function
+ 0x30: 0xb0909, // indianred
+ 0x34: 0x97709, // limegreen
+ 0x35: 0xbc10d, // outline-width
+ 0x3f: 0x15a07, // azimuth
+ 0x40: 0x1e70e, // blanchedalmond
+ 0x41: 0x84a0a, // line-break
+ 0x42: 0x7a209, // aliceblue
+ 0x43: 0xf309, // rosybrown
+ 0x46: 0xa7c0f, // mediumturquoise
+ 0x49: 0xd7706, // widows
+ 0x4b: 0xb370f, // offset-position
+ 0x4d: 0xd150b, // transparent
+ 0x4e: 0x79d07, // initial
+ 0x52: 0x1cb0f, // background-size
+ 0x55: 0x2505, // color
+ 0x56: 0x59a10, // transition-delay
+ 0x5a: 0x750b, // navajowhite
+ 0x5b: 0x7110d, // grid-template
+ 0x5c: 0x3b710, // border-top-color
+ 0x62: 0xbce0a, // overflow-y
+ 0x64: 0x9370d, // lightseagreen
+ 0x6c: 0x10e0f, // text-align-last
+ 0x6f: 0x8050b, // layout-grid
+ 0x70: 0xca09, // animation
+ 0x71: 0x1da08, // behavior
+ 0x72: 0x5390a, // margin-top
+ 0x74: 0x3ab0c, // border-style
+ 0x78: 0x5d31b, // scrollbar-dark-shadow-color
+ 0x79: 0x69103, // all
+ 0x7a: 0x3f0b, // text-indent
+ 0x7b: 0xbe10d, // paleturquoise
+ 0x7e: 0x58510, // page-break-after
+ 0x80: 0x5420d, // padding-right
+ 0x84: 0x7e60e, // vertical-align
+ 0x85: 0x50d07, // cursive
+ 0x8a: 0x7030e, // grid-row-start
+ 0x8c: 0xae08, // richness
+ 0x8e: 0x3b70a, // border-top
+ 0x94: 0x35509, // grid-area
+ 0x95: 0x85410, // layout-grid-mode
+ 0x96: 0xaee05, // marks
+ 0x97: 0x64d01, // q
+ 0x98: 0x78d09, // important
+ 0x9c: 0x406, // filter
+ 0x9d: 0xa8b0f, // mediumvioletred
+ 0xa5: 0xc570b, // speech-rate
+ 0xa8: 0x53702, // pc
+ 0xab: 0x90f, // radial-gradient
+ 0xae: 0x11b06, // stress
+ 0xb4: 0x6050d, // justify-items
+ 0xb7: 0x9500e, // lightslateblue
+ 0xba: 0x35504, // grid
+ 0xbb: 0xb0308, // moccasin
+ 0xbe: 0xd0209, // word-wrap
+ 0xc0: 0x6d90e, // darkolivegreen
+ 0xc5: 0xc6019, // text-decoration-thickness
+ 0xc7: 0xdb06, // center
+ 0xc8: 0x2a115, // text-decoration-color
+ 0xcb: 0xabf09, // min-width
+ 0xce: 0x5ee0b, // font-family
+ 0xd1: 0xa1c08, // ime-mode
+ 0xd3: 0x3d710, // border-top-width
+ 0xd4: 0x53906, // margin
+ 0xd9: 0x4880b, // column-rule
+ 0xda: 0x98f0a, // list-style
+ 0xdf: 0x6ce0c, // grid-row-end
+ 0xe4: 0x2050f, // animation-delay
+ 0xe8: 0x4aa11, // column-rule-width
+ 0xec: 0x57309, // flex-wrap
+ 0xed: 0xced07, // magenta
+ 0xee: 0x88710, // layout-grid-type
+ 0xef: 0x4520b, // padding-box
+ 0xf0: 0x7e14, // text-decoration-line
+ 0xf2: 0x4dd09, // cue-after
+ 0xf4: 0x8640e, // grid-auto-rows
+ 0xf5: 0x7650b, // yellowgreen
+ 0xf8: 0x89509, // peachpuff
+ 0xf9: 0x74607, // columns
+ 0xfa: 0x22805, // order
+ 0xfb: 0x3120c, // border-right
+ 0x100: 0x1800e, // include-source
+ 0x104: 0xc2905, // pause
+ 0x105: 0x1fc04, // bold
+ 0x106: 0xcc40c, // unicode-bidi
+ 0x108: 0x67604, // fill
+ 0x109: 0x75c09, // darkgreen
+ 0x10b: 0x45d05, // clear
+ 0x10c: 0x67d08, // deeppink
+ 0x110: 0x8e913, // animation-direction
+ 0x112: 0x1b811, // background-repeat
+ 0x117: 0xca506, // progid
+ 0x11d: 0x8a614, // scrollbar-base-color
+ 0x11e: 0xa, // -ms-filter
+ 0x11f: 0x2ca09, // lawngreen
+ 0x120: 0x51406, // cursor
+ 0x121: 0x44e05, // clamp
+ 0x123: 0x48811, // column-rule-color
+ 0x128: 0x40f0c, // caption-side
+ 0x12a: 0xc9b0a, // powderblue
+ 0x12b: 0xdc717, // text-underline-position
+ 0x12d: 0x72315, // scrollbar-track-color
+ 0x131: 0x81c0e, // grid-auto-flow
+ 0x132: 0x7810c, // speak-header
+ 0x133: 0x25409, // font-face
+ 0x136: 0xa710b, // springgreen
+ 0x13a: 0xc7e0a, // place-self
+ 0x13d: 0xc206, // repeat
+ 0x13e: 0x9800f, // linear-gradient
+ 0x142: 0x5010c, // currentcolor
+ 0x145: 0xad706, // offset
+ 0x14a: 0x69e0f, // grid-column-gap
+ 0x14c: 0x6905, // space
+ 0x14e: 0x39b0a, // sans-serif
+ 0x14f: 0x6360a, // font-style
+ 0x153: 0x66607, // fuchsia
+ 0x154: 0xb7904, // clip
+ 0x155: 0xae409, // mistyrose
+ 0x158: 0x9d08, // overflow
+ 0x15d: 0xc7806, // stroke
+ 0x162: 0x80510, // layout-grid-char
+ 0x163: 0xa420c, // mediumpurple
+ 0x165: 0x4f503, // env
+ 0x168: 0x4690d, // counter-reset
+ 0x16b: 0x5cb09, // keyframes
+ 0x16f: 0x7b05, // white
+ 0x172: 0x1004, // grad
+ 0x174: 0xdb10d, // margin-bottom
+ 0x175: 0x31212, // border-right-color
+ 0x177: 0x25404, // font
+ 0x178: 0xc100d, // palegoldenrod
+ 0x179: 0x73815, // grid-template-columns
+ 0x17a: 0x7e0f, // text-decoration
+ 0x17e: 0x89d0a, // flex-basis
+ 0x186: 0x7ef0b, // align-items
+ 0x189: 0x4bb0c, // column-width
+ 0x18a: 0x3c710, // border-top-style
+ 0x18b: 0x1d604, // size
+ 0x18c: 0xd4505, // media
+ 0x191: 0xb7c0e, // padding-bottom
+ 0x194: 0x2df11, // border-left-color
+ 0x195: 0x7a70a, // blueviolet
+ 0x198: 0x92c0b, // lightsalmon
+ 0x19d: 0x27108, // lavender
+ 0x19e: 0x5a716, // layer-background-image
+ 0x1a0: 0x6500b, // white-space
+ 0x1a3: 0xe00d, // ruby-overhang
+ 0x1a4: 0x24b0c, // lemonchiffon
+ 0x1a5: 0x3be03, // top
+ 0x1a9: 0x2c308, // seashell
+ 0x1aa: 0x7ae0e, // letter-spacing
+ 0x1ac: 0x2b0a, // background
+ 0x1af: 0x64503, // var
+ 0x1b0: 0xaed02, // mm
+ 0x1b6: 0x12015, // scrollbar-arrow-color
+ 0x1b8: 0xda40e, // text-transform
+ 0x1b9: 0x65b0b, // font-weight
+ 0x1ba: 0x53802, // cm
+ 0x1bb: 0x12006, // scroll
+ 0x1c0: 0x21710, // background-color
+ 0x1c1: 0x2710d, // lavenderblush
+ 0x1c6: 0xb5115, // text-decoration-style
+ 0x1c9: 0x79607, // inherit
+ 0x1cf: 0x2e604, // left
+ 0x1d0: 0x6490c, // antiquewhite
+ 0x1d4: 0xb6609, // olivedrab
+ 0x1da: 0x2990a, // ghostwhite
+ 0x1dd: 0x91009, // lightgray
+ 0x1e2: 0x26f04, // hsla
+ 0x1e3: 0x26f03, // hsl
+ 0x1e4: 0xbd809, // palegreen
+ 0x1e5: 0x4190b, // deepskyblue
+ 0x1e8: 0xac809, // mintcream
+ 0x1ea: 0x7e406, // invert
+ 0x1eb: 0x6400c, // font-variant
+ 0x1ec: 0x8fc14, // lightgoldenrodyellow
+ 0x1ee: 0x62f07, // charset
+ 0x1ef: 0xc8f0c, // writing-mode
+ 0x1f0: 0x5c30a, // whitesmoke
+ 0x1f5: 0x9d0a, // overflow-x
+ 0x1f6: 0xaa90c, // midnightblue
+ 0x1f7: 0xcb706, // quotes
+ 0x1f8: 0x22706, // border
+ 0x1fa: 0x42f0a, // chartreuse
+ 0x1fc: 0xba707, // outline
+ 0x1fd: 0xa281a, // transition-timing-function
+ 0x1fe: 0xcbc08, // supports
+ 0x204: 0x1670a, // word-break
+ 0x205: 0xaa009, // monospace
+ 0x206: 0x2850a, // box-shadow
+ 0x209: 0x5680b, // flex-shrink
+ 0x20f: 0xd0a0c, // padding-left
+ 0x214: 0xc4d0b, // place-items
+ 0x216: 0xc070a, // papayawhip
+ 0x217: 0x17111, // background-origin
+ 0x218: 0x52408, // document
+ 0x219: 0x52c0a, // dodgerblue
+ 0x21c: 0x9440c, // lightskyblue
+ 0x21e: 0x6bd11, // grid-column-start
+ 0x221: 0x30111, // border-left-width
+ 0x224: 0x68c08, // xx-small
+ 0x226: 0x1f408, // darkblue
+ 0x229: 0x25d13, // border-bottom-width
+ 0x22a: 0x98f10, // list-style-image
+ 0x22d: 0x44504, // auto
+ 0x230: 0x1e205, // black
+ 0x231: 0xaf211, // speak-punctuation
+ 0x232: 0x13908, // position
+ 0x234: 0xc340c, // pause-before
+ 0x236: 0x95e0e, // lightsteelblue
+ 0x23a: 0xcd10b, // play-during
+ 0x23f: 0x83509, // firebrick
+ 0x249: 0x6ce08, // grid-row
+ 0x24a: 0x55d02, // px
+ 0x24c: 0x1a315, // background-position-y
+ 0x251: 0xd1f04, // turn
+ 0x256: 0xba70d, // outline-color
+ 0x257: 0x9c304, // calc
+ 0x258: 0xd4919, // animation-iteration-count
+ 0x259: 0xad70d, // offset-anchor
+ 0x25b: 0xa4e0e, // mediumseagreen
+ 0x25e: 0x4620c, // column-count
+ 0x263: 0x10e0a, // text-align
+ 0x266: 0x66c13, // animation-fill-mode
+ 0x267: 0x32412, // border-right-style
+ 0x268: 0xa707, // x-large
+ 0x269: 0x8d40e, // flex-direction
+ 0x26a: 0x4f70a, // visibility
+ 0x26f: 0xb2c0b, // offset-path
+ 0x270: 0x27e0a, // border-box
+ 0x276: 0x70103, // deg
+ 0x278: 0x1713, // text-emphasis-color
+ 0x27f: 0xc1c0d, // darkslateblue
+ 0x283: 0x55f09, // flex-grow
+ 0x285: 0x8e209, // lightcyan
+ 0x28a: 0x102, // ms
+ 0x28d: 0xa906, // larger
+ 0x28e: 0xa990a, // darksalmon
+ 0x292: 0x2f011, // border-left-style
+ 0x293: 0xa8209, // turquoise
+ 0x294: 0x3a407, // fantasy
+ 0x296: 0xec09, // gainsboro
+ 0x297: 0x201, // s
+ 0x298: 0x23a13, // border-bottom-style
+ 0x299: 0xce90b, // darkmagenta
+ 0x29b: 0xb50b, // saddlebrown
+ 0x2a0: 0x59505, // float
+ 0x2a3: 0x6ec07, // row-gap
+ 0x2a5: 0xd4106, // volume
+ 0x2a6: 0xab50a, // min-height
+ 0x2a7: 0x77012, // grid-template-rows
+ 0x2a9: 0x3760b, // accelerator
+ 0x2b0: 0x68f05, // small
+ 0x2b1: 0x59804, // attr
+ 0x2b2: 0x28e0c, // word-spacing
+ 0x2b3: 0x35d12, // animation-duration
+ 0x2b5: 0x4dd03, // cue
+ 0x2b6: 0x95509, // slateblue
+ 0x2b8: 0x38e04, // none
+ 0x2b9: 0x6a30a, // column-gap
+ 0x2ba: 0x4e0f, // justify-content
+ 0x2bb: 0x5607, // content
+ 0x2bd: 0x54f03, // dpi
+ 0x2be: 0x87116, // scrollbar-shadow-color
+ 0x2bf: 0x78d06, // import
+ 0x2c0: 0xc8709, // flex-flow
+ 0x2c1: 0x69509, // royalblue
+ 0x2c3: 0x9c609, // cadetblue
+ 0x2c4: 0x490c, // text-justify
+ 0x2cb: 0x8c30a, // lightcoral
+ 0x2cf: 0xb890c, // margin-right
+ 0x2d2: 0x76506, // yellow
+ 0x2d3: 0x26b05, // width
+ 0x2d6: 0x14d03, // min
+ 0x2da: 0x1340d, // ruby-position
+ 0x2dc: 0x40708, // darkgray
+ 0x2e2: 0x69e0b, // grid-column
+ 0x2e4: 0xa1409, // darkkhaki
+ 0x2e5: 0xc400d, // place-content
+ 0x2e7: 0xbee0d, // palevioletred
+ 0x2ea: 0x5bd0b, // floralwhite
+ 0x2eb: 0xc208, // repeat-y
+ 0x2ee: 0x980d, // text-overflow
+ 0x2f1: 0xca0e, // animation-name
+ 0x2fb: 0x7cb19, // scrollbar-highlight-color
+ 0x2fe: 0x5500b, // pitch-range
+ 0x302: 0x3005, // round
+ 0x305: 0x4c70e, // cornflowerblue
+ 0x307: 0x7f90d, // speak-numeral
+ 0x308: 0x9e606, // medium
+ 0x30a: 0x170d, // text-emphasis
+ 0x30d: 0x9dd09, // max-width
+ 0x311: 0x36e06, // normal
+ 0x312: 0x68403, // khz
+ 0x315: 0x2903, // rgb
+ 0x316: 0x8ba09, // lightblue
+ 0x317: 0x8d909, // direction
+ 0x31a: 0xd350c, // voice-family
+ 0x31c: 0x3480e, // border-spacing
+ 0x321: 0x6d09, // elevation
+ 0x323: 0x1c308, // repeat-x
+ 0x324: 0x83e10, // layout-grid-line
+ 0x326: 0xa000c, // mediumorchid
+ 0x32b: 0xa6b11, // mediumspringgreen
+ 0x32d: 0xa905, // large
+ 0x32e: 0xd930a, // ruby-align
+ 0x330: 0xbfa0d, // darkslategray
+ 0x332: 0x5c12, // text-kashida-space
+ 0x334: 0xbb40d, // outline-style
+ 0x336: 0x3a005, // serif
+ 0x337: 0x4240b, // caret-color
+ 0x33a: 0x37205, // alpha
+ 0x33c: 0x71113, // grid-template-areas
+ 0x33d: 0x49911, // column-rule-style
+ 0x33f: 0xcf80b, // layout-flow
+ 0x340: 0x31905, // right
+ 0x341: 0x3e70c, // border-width
+ 0x343: 0xb6e0f, // background-clip
+ 0x344: 0xd230d, // unicode-range
+ 0x345: 0x74c05, // solid
+ 0x346: 0x2df0b, // border-left
+ 0x348: 0x9ec0a, // aquamarine
+ 0x349: 0x3850a, // sandybrown
+ 0x34a: 0x16008, // honeydew
+ 0x34b: 0x75409, // orangered
+ 0x34c: 0xb110c, // darkseagreen
+ 0x34d: 0x37f07, // orphans
+ 0x34e: 0x6e70c, // grid-row-gap
+ 0x351: 0x22e06, // bottom
+ 0x359: 0x9c105, // local
+ 0x35c: 0x8cb0a, // align-self
+ 0x35e: 0x33612, // border-right-width
+ 0x360: 0x2b15, // background-attachment
+ 0x364: 0x9190a, // lightgreen
+ 0x366: 0x39302, // pt
+ 0x368: 0x4400e, // text-autospace
+ 0x36b: 0x3f403, // url
+ 0x36c: 0x68502, // hz
+ 0x371: 0x9306, // height
+ 0x372: 0x5ad10, // background-image
+ 0x377: 0x903, // rad
+ 0x37c: 0x21116, // layer-background-color
+ 0x37d: 0x1ff08, // darkcyan
+ 0x382: 0x18e13, // background-position
+ 0x384: 0x9d303, // max
+ 0x38c: 0xa608, // xx-large
+ 0x38d: 0x3f309, // burlywood
+ 0x38f: 0xd7c18, // scrollbar-3d-light-color
+ 0x390: 0x3ff09, // goldenrod
+ 0x392: 0x92309, // lightpink
+ 0x393: 0x8e0b, // line-height
+ 0x396: 0x22713, // border-bottom-color
+ 0x398: 0x80518, // layout-grid-char-spacing
+ 0x39c: 0x2904, // rgba
+ 0x3a1: 0x9f60a, // mediumblue
+ 0x3a3: 0x9d30a, // max-height
+ 0x3a4: 0x7bb11, // grid-auto-columns
+ 0x3a5: 0xa0b0a, // darkorchid
+ 0x3a9: 0x7600b, // greenyellow
+ 0x3ae: 0x96c0b, // lightyellow
+ 0x3b1: 0x4750a, // transition
+ 0x3b3: 0x4e60a, // cue-before
+ 0x3b6: 0x15208, // function
+ 0x3b9: 0x96309, // steelblue
+ 0x3be: 0xa5c0f, // mediumslateblue
+ 0x3bf: 0xcaa0d, // darkturquoise
+ 0x3c0: 0x43909, // chocolate
+ 0x3c3: 0x5f909, // font-size
+ 0x3c5: 0x55f04, // flex
+ 0x3c7: 0xd3005, // unset
+ 0x3c8: 0xd6d0b, // text-shadow
+ 0x3ca: 0x4ec0b, // forestgreen
+ 0x3cc: 0xbfe09, // slategray
+ 0x3cd: 0x6ac11, // page-break-before
+ 0x3ce: 0x55b04, // dppx
+ 0x3d0: 0x2270d, // border-bottom
+ 0x3d3: 0xb1d0f, // offset-distance
+ 0x3d4: 0x3fb0d, // darkgoldenrod
+ 0x3d6: 0x53604, // dpcm
+ 0x3d8: 0x7500a, // darkorange
+ 0x3dc: 0xb9413, // transition-duration
+ 0x3de: 0x2d30c, // border-color
+ 0x3df: 0x18e15, // background-position-x
+ 0x3e0: 0x55005, // pitch
+ 0x3e2: 0xdbd0b, // margin-left
+ 0x3e3: 0x58504, // page
+ 0x3e5: 0x57b0b, // padding-top
+ 0x3e7: 0xb460d, // offset-rotate
+ 0x3e8: 0x93c08, // seagreen
+ 0x3e9: 0x4d508, // cornsilk
+ 0x3ea: 0x68f07, // smaller
+ 0x3ec: 0xcf20c, // table-layout
+ 0x3ed: 0xfc14, // animation-play-state
+ 0x3ef: 0xa2207, // default
+ 0x3f0: 0x68d07, // x-small
+ 0x3f3: 0x9e610, // mediumaquamarine
+ 0x3f4: 0xad00d, // marker-offset
+ 0x3f9: 0xd409, // namespace
+ 0x3fa: 0x9cf04, // mask
+ 0x3fb: 0x45207, // padding
+ 0x3fd: 0x9b20f, // list-style-type
+ 0x3ff: 0x3910b, // empty-cells
+}
diff --git a/vendor/github.com/tdewolff/minify/v2/css/table.go b/vendor/github.com/tdewolff/minify/v2/css/table.go
new file mode 100644
index 0000000..b7ecb84
--- /dev/null
+++ b/vendor/github.com/tdewolff/minify/v2/css/table.go
@@ -0,0 +1,198 @@
+package css
+
+var optionalZeroDimension = map[string]bool{
+ "px": true,
+ "mm": true,
+ "q": true,
+ "cm": true,
+ "in": true,
+ "pt": true,
+ "pc": true,
+ "ch": true,
+ "em": true,
+ "ex": true,
+ "rem": true,
+ "vh": true,
+ "vw": true,
+ "vmin": true,
+ "vmax": true,
+ "deg": true,
+ "grad": true,
+ "rad": true,
+ "turn": true,
+}
+
+// Uses http://www.w3.org/TR/2010/PR-css3-color-20101028/ for colors
+
+// ShortenColorHex maps a color hexcode to its shorter name
+var ShortenColorHex = map[string][]byte{
+ "#000080": []byte("navy"),
+ "#008000": []byte("green"),
+ "#008080": []byte("teal"),
+ "#4b0082": []byte("indigo"),
+ "#800000": []byte("maroon"),
+ "#800080": []byte("purple"),
+ "#808000": []byte("olive"),
+ "#808080": []byte("gray"),
+ "#a0522d": []byte("sienna"),
+ "#a52a2a": []byte("brown"),
+ "#c0c0c0": []byte("silver"),
+ "#cd853f": []byte("peru"),
+ "#d2b48c": []byte("tan"),
+ "#da70d6": []byte("orchid"),
+ "#dda0dd": []byte("plum"),
+ "#ee82ee": []byte("violet"),
+ "#f0e68c": []byte("khaki"),
+ "#f0ffff": []byte("azure"),
+ "#f5deb3": []byte("wheat"),
+ "#f5f5dc": []byte("beige"),
+ "#fa8072": []byte("salmon"),
+ "#faf0e6": []byte("linen"),
+ "#ff6347": []byte("tomato"),
+ "#ff7f50": []byte("coral"),
+ "#ffa500": []byte("orange"),
+ "#ffc0cb": []byte("pink"),
+ "#ffd700": []byte("gold"),
+ "#ffe4c4": []byte("bisque"),
+ "#fffafa": []byte("snow"),
+ "#fffff0": []byte("ivory"),
+ "#ff0000": []byte("red"),
+ "#f00": []byte("red"),
+}
+
+// ShortenColorName maps a color name to its shorter hexcode
+var ShortenColorName = map[Hash][]byte{
+ Black: []byte("#000"),
+ Darkblue: []byte("#00008b"),
+ Mediumblue: []byte("#0000cd"),
+ Darkgreen: []byte("#006400"),
+ Darkcyan: []byte("#008b8b"),
+ Deepskyblue: []byte("#00bfff"),
+ Darkturquoise: []byte("#00ced1"),
+ Mediumspringgreen: []byte("#00fa9a"),
+ Springgreen: []byte("#00ff7f"),
+ Midnightblue: []byte("#191970"),
+ Dodgerblue: []byte("#1e90ff"),
+ Lightseagreen: []byte("#20b2aa"),
+ Forestgreen: []byte("#228b22"),
+ Seagreen: []byte("#2e8b57"),
+ Darkslategray: []byte("#2f4f4f"),
+ Limegreen: []byte("#32cd32"),
+ Mediumseagreen: []byte("#3cb371"),
+ Turquoise: []byte("#40e0d0"),
+ Royalblue: []byte("#4169e1"),
+ Steelblue: []byte("#4682b4"),
+ Darkslateblue: []byte("#483d8b"),
+ Mediumturquoise: []byte("#48d1cc"),
+ Darkolivegreen: []byte("#556b2f"),
+ Cadetblue: []byte("#5f9ea0"),
+ Cornflowerblue: []byte("#6495ed"),
+ Mediumaquamarine: []byte("#66cdaa"),
+ Slateblue: []byte("#6a5acd"),
+ Olivedrab: []byte("#6b8e23"),
+ Slategray: []byte("#708090"),
+ Lightslateblue: []byte("#789"),
+ Mediumslateblue: []byte("#7b68ee"),
+ Lawngreen: []byte("#7cfc00"),
+ Chartreuse: []byte("#7fff00"),
+ Aquamarine: []byte("#7fffd4"),
+ Lightskyblue: []byte("#87cefa"),
+ Blueviolet: []byte("#8a2be2"),
+ Darkmagenta: []byte("#8b008b"),
+ Saddlebrown: []byte("#8b4513"),
+ Darkseagreen: []byte("#8fbc8f"),
+ Lightgreen: []byte("#90ee90"),
+ Mediumpurple: []byte("#9370db"),
+ Darkviolet: []byte("#9400d3"),
+ Palegreen: []byte("#98fb98"),
+ Darkorchid: []byte("#9932cc"),
+ Yellowgreen: []byte("#9acd32"),
+ Darkgray: []byte("#a9a9a9"),
+ Lightblue: []byte("#add8e6"),
+ Greenyellow: []byte("#adff2f"),
+ Paleturquoise: []byte("#afeeee"),
+ Lightsteelblue: []byte("#b0c4de"),
+ Powderblue: []byte("#b0e0e6"),
+ Firebrick: []byte("#b22222"),
+ Darkgoldenrod: []byte("#b8860b"),
+ Mediumorchid: []byte("#ba55d3"),
+ Rosybrown: []byte("#bc8f8f"),
+ Darkkhaki: []byte("#bdb76b"),
+ Mediumvioletred: []byte("#c71585"),
+ Indianred: []byte("#cd5c5c"),
+ Chocolate: []byte("#d2691e"),
+ Lightgray: []byte("#d3d3d3"),
+ Goldenrod: []byte("#daa520"),
+ Palevioletred: []byte("#db7093"),
+ Gainsboro: []byte("#dcdcdc"),
+ Burlywood: []byte("#deb887"),
+ Lightcyan: []byte("#e0ffff"),
+ Lavender: []byte("#e6e6fa"),
+ Darksalmon: []byte("#e9967a"),
+ Palegoldenrod: []byte("#eee8aa"),
+ Lightcoral: []byte("#f08080"),
+ Aliceblue: []byte("#f0f8ff"),
+ Honeydew: []byte("#f0fff0"),
+ Sandybrown: []byte("#f4a460"),
+ Whitesmoke: []byte("#f5f5f5"),
+ Mintcream: []byte("#f5fffa"),
+ Ghostwhite: []byte("#f8f8ff"),
+ Antiquewhite: []byte("#faebd7"),
+ Lightgoldenrodyellow: []byte("#fafad2"),
+ Fuchsia: []byte("#f0f"),
+ Magenta: []byte("#f0f"),
+ Deeppink: []byte("#ff1493"),
+ Orangered: []byte("#ff4500"),
+ Darkorange: []byte("#ff8c00"),
+ Lightsalmon: []byte("#ffa07a"),
+ Lightpink: []byte("#ffb6c1"),
+ Peachpuff: []byte("#ffdab9"),
+ Navajowhite: []byte("#ffdead"),
+ Moccasin: []byte("#ffe4b5"),
+ Mistyrose: []byte("#ffe4e1"),
+ Blanchedalmond: []byte("#ffebcd"),
+ Papayawhip: []byte("#ffefd5"),
+ Lavenderblush: []byte("#fff0f5"),
+ Seashell: []byte("#fff5ee"),
+ Cornsilk: []byte("#fff8dc"),
+ Lemonchiffon: []byte("#fffacd"),
+ Floralwhite: []byte("#fffaf0"),
+ Yellow: []byte("#ff0"),
+ Lightyellow: []byte("#ffffe0"),
+ White: []byte("#fff"),
+}
+
+// PropertyOverrides is a map of which properties are overridden by the given property.
+var PropertyOverrides = map[Hash][]Hash{
+ Background: {Background, Background_Image, Background_Position, Background_Size, Background_Repeat, Background_Origin, Background_Clip, Background_Attachment, Background_Color},
+ Font: {Font, Font_Style, Font_Variant, Font_Weight, Font_Stretch, Font_Size, Font_Family, Line_Height},
+ Border: {Border, Border_Width, Border_Top_Width, Border_Right_Width, Border_Bottom_Width, Border_Left_Width, Border_Style, Border_Top_Style, Border_Right_Style, Border_Bottom_Style, Border_Left_Style, Border_Color, Border_Top_Color, Border_Right_Color, Border_Bottom_Color, Border_Left_Color},
+ Border_Width: {Border_Width, Border_Top_Width, Border_Right_Width, Border_Bottom_Width, Border_Left_Width},
+ Border_Style: {Border_Style, Border_Top_Style, Border_Right_Style, Border_Bottom_Style, Border_Left_Style},
+ Border_Color: {Border_Color, Border_Top_Color, Border_Right_Color, Border_Bottom_Color, Border_Left_Color},
+ Border_Top: {Border_Top, Border_Top_Width, Border_Top_Style, Border_Top_Color},
+ Border_Right: {Border_Right, Border_Right_Width, Border_Right_Style, Border_Right_Color},
+ Border_Bottom: {Border_Bottom, Border_Bottom_Width, Border_Bottom_Style, Border_Bottom_Color},
+ Border_Left: {Border_Left, Border_Left_Width, Border_Left_Style, Border_Left_Color},
+ Margin: {Margin, Margin_Top, Margin_Right, Margin_Bottom, Margin_Left},
+ Padding: {Padding, Padding_Top, Padding_Right, Padding_Bottom, Padding_Left},
+ Column_Rule: {Column_Rule, Column_Rule_Width, Column_Rule_Style, Column_Rule_Color},
+ Animation: {Animation, Animation_Name, Animation_Duration, Animation_Timing_Function, Animation_Delay, Animation_Iteration_Count, Animation_Direction, Animation_Fill_Mode, Animation_Play_State},
+ Columns: {Columns, Column_Width, Column_Count},
+ Flex: {Flex, Flex_Basis, Flex_Grow, Flex_Shrink},
+ Flex_Flow: {Flex_Flow, Flex_Direction, Flex_Wrap},
+ Grid: {Grid, Grid_Template_Rows, Grid_Template_Columns, Grid_Template_Areas, Grid_Auto_Rows, Grid_Auto_Columns, Grid_Auto_Flow, Grid_Column_Gap, Grid_Row_Gap, Column_Gap, Row_Gap},
+ Grid_Area: {Grid_Area, Grid_Row_Start, Grid_Column_Start, Grid_Row_End, Grid_Column_End},
+ Grid_Row: {Grid_Row, Grid_Row_Start, Grid_Row_End},
+ Grid_Column: {Grid_Column, Grid_Column_Start, Grid_Column_End},
+ Grid_Template: {Grid_Template, Grid_Template_Rows, Grid_Template_Columns, Grid_Template_Areas},
+ List_Style: {List_Style, List_Style_Image, List_Style_Position, List_Style_Type},
+ Offset: {Offset, Offset_Position, Offset_Path, Offset_Distance, Offset_Anchor, Offset_Rotate},
+ Outline: {Outline, Outline_Width, Outline_Style, Outline_Color},
+ Overflow: {Overflow, Overflow_X, Overflow_Y},
+ Place_Content: {Place_Content, Align_Content, Justify_Content},
+ Place_Items: {Place_Items, Align_Items, Justify_Items},
+ Place_Self: {Place_Self, Align_Self, Justify_Self},
+ Text_Decoration: {Text_Decoration, Text_Decoration_Color, Text_Decoration_Color, Text_Decoration_Line, Text_Decoration_Thickness},
+ Transition: {Transition, Transition_Property, Transition_Duration, Transition_Timing_Function, Transition_Delay},
+}
diff --git a/vendor/github.com/tdewolff/minify/v2/css/util.go b/vendor/github.com/tdewolff/minify/v2/css/util.go
new file mode 100644
index 0000000..7325aca
--- /dev/null
+++ b/vendor/github.com/tdewolff/minify/v2/css/util.go
@@ -0,0 +1,55 @@
+package css
+
+import (
+ "encoding/hex"
+
+ "github.com/tdewolff/parse/v2"
+ "github.com/tdewolff/parse/v2/css"
+)
+
+func removeMarkupNewlines(data []byte) []byte {
+ // remove any \\\r\n \\\r \\\n
+ for i := 1; i < len(data)-2; i++ {
+ if data[i] == '\\' && (data[i+1] == '\n' || data[i+1] == '\r') {
+ // encountered first replacee, now start to move bytes to the front
+ j := i + 2
+ if data[i+1] == '\r' && len(data) > i+2 && data[i+2] == '\n' {
+ j++
+ }
+ for ; j < len(data); j++ {
+ if data[j] == '\\' && len(data) > j+1 && (data[j+1] == '\n' || data[j+1] == '\r') {
+ if data[j+1] == '\r' && len(data) > j+2 && data[j+2] == '\n' {
+ j++
+ }
+ j++
+ } else {
+ data[i] = data[j]
+ i++
+ }
+ }
+ data = data[:i]
+ break
+ }
+ }
+ return data
+}
+
+func rgbToToken(r, g, b float64) Token {
+ // r, g, b are in interval [0.0, 1.0]
+ rgb := []byte{byte((r * 255.0) + 0.5), byte((g * 255.0) + 0.5), byte((b * 255.0) + 0.5)}
+
+ val := make([]byte, 7)
+ val[0] = '#'
+ hex.Encode(val[1:], rgb)
+ parse.ToLower(val)
+ if s, ok := ShortenColorHex[string(val[:7])]; ok {
+ return Token{css.IdentToken, s, nil, 0, 0}
+ } else if val[1] == val[2] && val[3] == val[4] && val[5] == val[6] {
+ val[2] = val[3]
+ val[3] = val[5]
+ val = val[:4]
+ } else {
+ val = val[:7]
+ }
+ return Token{css.HashToken, val, nil, 0, 0}
+}