File: css_decls_animation.go

package info (click to toggle)
golang-github-evanw-esbuild 0.25.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,184 kB
  • sloc: javascript: 28,602; makefile: 856; sh: 17
file content (119 lines) | stat: -rw-r--r-- 3,125 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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]
}