mirror of
https://github.com/hanzoai/esbuild.git
synced 2026-09-24 16:58:50 +00:00
120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
package css_parser
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/evanw/esbuild/internal/css_ast"
|
|
"github.com/evanw/esbuild/internal/css_lexer"
|
|
)
|
|
|
|
// Scan for animation names in the "animation" shorthand property
|
|
func (p *parser) processAnimationShorthand(tokens []css_ast.Token) {
|
|
type foundFlags struct {
|
|
timingFunction bool
|
|
iterationCount bool
|
|
direction bool
|
|
fillMode bool
|
|
playState bool
|
|
name bool
|
|
}
|
|
|
|
found := foundFlags{}
|
|
|
|
for i, t := range tokens {
|
|
switch t.Kind {
|
|
case css_lexer.TComma:
|
|
// Reset the flags when we encounter a comma
|
|
found = foundFlags{}
|
|
|
|
case css_lexer.TNumber:
|
|
if !found.iterationCount {
|
|
found.iterationCount = true
|
|
continue
|
|
}
|
|
|
|
case css_lexer.TIdent:
|
|
if !found.timingFunction {
|
|
switch strings.ToLower(t.Text) {
|
|
case "linear", "ease", "ease-in", "ease-out", "ease-in-out", "step-start", "step-end":
|
|
found.timingFunction = true
|
|
continue
|
|
}
|
|
}
|
|
|
|
if !found.iterationCount && strings.ToLower(t.Text) == "infinite" {
|
|
found.iterationCount = true
|
|
continue
|
|
}
|
|
|
|
if !found.direction {
|
|
switch strings.ToLower(t.Text) {
|
|
case "normal", "reverse", "alternate", "alternate-reverse":
|
|
found.direction = true
|
|
continue
|
|
}
|
|
}
|
|
|
|
if !found.fillMode {
|
|
switch strings.ToLower(t.Text) {
|
|
case "none", "forwards", "backwards", "both":
|
|
found.fillMode = true
|
|
continue
|
|
}
|
|
}
|
|
|
|
if !found.playState {
|
|
switch strings.ToLower(t.Text) {
|
|
case "running", "paused":
|
|
found.playState = true
|
|
continue
|
|
}
|
|
}
|
|
|
|
if !found.name {
|
|
p.handleSingleAnimationName(&tokens[i])
|
|
found.name = true
|
|
continue
|
|
}
|
|
|
|
case css_lexer.TString:
|
|
if !found.name {
|
|
p.handleSingleAnimationName(&tokens[i])
|
|
found.name = true
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *parser) processAnimationName(tokens []css_ast.Token) {
|
|
for i, t := range tokens {
|
|
if t.Kind == css_lexer.TIdent || t.Kind == css_lexer.TString {
|
|
p.handleSingleAnimationName(&tokens[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *parser) handleSingleAnimationName(token *css_ast.Token) {
|
|
// Do not transform CSS keywords into symbols because they have special
|
|
// meaning in declarations. For example, "animation-name: none" clears
|
|
// the animation name. It does not set it to the animation named "none".
|
|
// You need to use "animation-name: 'none'" to do that.
|
|
//
|
|
// Also don't transform strings containing CSS keywords into global symbols
|
|
// because global symbols are passed through without being renamed, which
|
|
// will print them as keywords. However, we still want to unconditionally
|
|
// transform strings into local symbols because local symbols are always
|
|
// renamed, so they will never be printed as keywords.
|
|
if (token.Kind == css_lexer.TIdent || (token.Kind == css_lexer.TString && !p.makeLocalSymbols)) && isInvalidAnimationName(token.Text) {
|
|
return
|
|
}
|
|
|
|
token.Kind = css_lexer.TSymbol
|
|
token.PayloadIndex = p.symbolForName(token.Loc, token.Text).Ref.InnerIndex
|
|
}
|
|
|
|
func isInvalidAnimationName(text string) bool {
|
|
lower := strings.ToLower(text)
|
|
return lower == "none" || cssWideAndReservedKeywords[lower]
|
|
}
|