github.com/evanw/esbuild@v0.21.4/internal/css_parser/css_decls_box_shadow.go (about) 1 package css_parser 2 3 import ( 4 "strings" 5 6 "github.com/evanw/esbuild/internal/css_ast" 7 "github.com/evanw/esbuild/internal/css_lexer" 8 ) 9 10 func (p *parser) lowerAndMangleBoxShadow(tokens []css_ast.Token, wouldClipColor *bool) []css_ast.Token { 11 insetCount := 0 12 colorCount := 0 13 numbersBegin := 0 14 numbersCount := 0 15 numbersDone := false 16 foundUnexpectedToken := false 17 18 for i, t := range tokens { 19 if t.Kind == css_lexer.TNumber || t.Kind == css_lexer.TDimension { 20 if numbersDone { 21 // Track if we found a non-number in between two numbers 22 foundUnexpectedToken = true 23 } 24 if p.options.minifySyntax && t.TurnLengthIntoNumberIfZero() { 25 // "0px" => "0" 26 tokens[i] = t 27 } 28 if numbersCount == 0 { 29 // Track the index of the first number 30 numbersBegin = i 31 } 32 numbersCount++ 33 } else { 34 if numbersCount != 0 { 35 // Track when we find a non-number after a number 36 numbersDone = true 37 } 38 39 if looksLikeColor(t) { 40 colorCount++ 41 tokens[i] = p.lowerAndMinifyColor(t, wouldClipColor) 42 } else if t.Kind == css_lexer.TIdent && strings.EqualFold(t.Text, "inset") { 43 insetCount++ 44 } else { 45 // Track if we found a token other than a number, a color, or "inset" 46 foundUnexpectedToken = true 47 } 48 } 49 } 50 51 // If everything looks like a valid rule, trim trailing zeros off the numbers. 52 // There are three valid configurations of numbers: 53 // 54 // offset-x | offset-y 55 // offset-x | offset-y | blur-radius 56 // offset-x | offset-y | blur-radius | spread-radius 57 // 58 // If omitted, blur-radius and spread-radius are implied to be zero. 59 if p.options.minifySyntax && insetCount <= 1 && colorCount <= 1 && numbersCount > 2 && numbersCount <= 4 && !foundUnexpectedToken { 60 numbersEnd := numbersBegin + numbersCount 61 for numbersCount > 2 && tokens[numbersBegin+numbersCount-1].IsZero() { 62 numbersCount-- 63 } 64 tokens = append(tokens[:numbersBegin+numbersCount], tokens[numbersEnd:]...) 65 } 66 67 // Set the whitespace flags 68 for i := range tokens { 69 var whitespace css_ast.WhitespaceFlags 70 if i > 0 || !p.options.minifyWhitespace { 71 whitespace |= css_ast.WhitespaceBefore 72 } 73 if i+1 < len(tokens) { 74 whitespace |= css_ast.WhitespaceAfter 75 } 76 tokens[i].Whitespace = whitespace 77 } 78 return tokens 79 } 80 81 func (p *parser) lowerAndMangleBoxShadows(tokens []css_ast.Token, wouldClipColor *bool) []css_ast.Token { 82 n := len(tokens) 83 end := 0 84 i := 0 85 86 for i < n { 87 // Find the comma or the end of the token list 88 comma := i 89 for comma < n && tokens[comma].Kind != css_lexer.TComma { 90 comma++ 91 } 92 93 // Mangle this individual shadow 94 end += copy(tokens[end:], p.lowerAndMangleBoxShadow(tokens[i:comma], wouldClipColor)) 95 96 // Skip over the comma 97 if comma < n { 98 tokens[end] = tokens[comma] 99 end++ 100 comma++ 101 } 102 i = comma 103 } 104 105 return tokens[:end] 106 }