source: frontend/node_modules/tailwindcss/src/util/math-operators.ts

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.2 KB
Line 
1const LOWER_A = 0x61
2const LOWER_Z = 0x7a
3const UPPER_A = 0x41
4const UPPER_Z = 0x5a
5const LOWER_E = 0x65
6const UPPER_E = 0x45
7const ZERO = 0x30
8const NINE = 0x39
9const ADD = 0x2b
10const SUB = 0x2d
11const MUL = 0x2a
12const DIV = 0x2f
13const OPEN_PAREN = 0x28
14const CLOSE_PAREN = 0x29
15const COMMA = 0x2c
16const SPACE = 0x20
17const PERCENT = 0x25
18
19const MATH_FUNCTIONS = [
20 'calc',
21 'min',
22 'max',
23 'clamp',
24 'mod',
25 'rem',
26 'sin',
27 'cos',
28 'tan',
29 'asin',
30 'acos',
31 'atan',
32 'atan2',
33 'pow',
34 'sqrt',
35 'hypot',
36 'log',
37 'exp',
38 'round',
39]
40
41export function hasMathFn(input: string) {
42 return input.indexOf('(') !== -1 && MATH_FUNCTIONS.some((fn) => input.includes(`${fn}(`))
43}
44
45export function addWhitespaceAroundMathOperators(input: string) {
46 // Bail early if there are no math functions in the input
47 if (!MATH_FUNCTIONS.some((fn) => input.includes(fn))) {
48 return input
49 }
50
51 let result = ''
52 let formattable: boolean[] = []
53
54 let valuePos = null
55 let lastValuePos = null
56
57 for (let i = 0; i < input.length; i++) {
58 let char = input.charCodeAt(i)
59
60 // Track if we see a number followed by a unit, then we know for sure that
61 // this is not a function call.
62 if (char >= ZERO && char <= NINE) {
63 valuePos = i
64 }
65
66 // If we saw a number before, and we see normal a-z character, then we
67 // assume this is a value such as `123px`
68 else if (
69 valuePos !== null &&
70 (char === PERCENT ||
71 (char >= LOWER_A && char <= LOWER_Z) ||
72 (char >= UPPER_A && char <= UPPER_Z))
73 ) {
74 valuePos = i
75 }
76
77 // Once we see something else, we reset the value position
78 else {
79 lastValuePos = valuePos
80 valuePos = null
81 }
82
83 // Determine if we're inside a math function
84 if (char === OPEN_PAREN) {
85 result += input[i]
86
87 // Scan backwards to determine the function name. This assumes math
88 // functions are named with lowercase alphanumeric characters.
89 let start = i
90
91 for (let j = i - 1; j >= 0; j--) {
92 let inner = input.charCodeAt(j)
93
94 if (inner >= ZERO && inner <= NINE) {
95 start = j // 0-9
96 } else if (inner >= LOWER_A && inner <= LOWER_Z) {
97 start = j // a-z
98 } else {
99 break
100 }
101 }
102
103 let fn = input.slice(start, i)
104
105 // This is a known math function so start formatting
106 if (MATH_FUNCTIONS.includes(fn)) {
107 formattable.unshift(true)
108 continue
109 }
110
111 // We've encountered nested parens inside a math function, record that and
112 // keep formatting until we've closed all parens.
113 else if (formattable[0] && fn === '') {
114 formattable.unshift(true)
115 continue
116 }
117
118 // This is not a known math function so don't format it
119 formattable.unshift(false)
120 continue
121 }
122
123 // We've exited the function so format according to the parent function's
124 // type.
125 else if (char === CLOSE_PAREN) {
126 result += input[i]
127 formattable.shift()
128 }
129
130 // Add spaces after commas in math functions
131 else if (char === COMMA && formattable[0]) {
132 result += `, `
133 continue
134 }
135
136 // Skip over consecutive whitespace
137 else if (char === SPACE && formattable[0] && result.charCodeAt(result.length - 1) === SPACE) {
138 continue
139 }
140
141 // Add whitespace around operators inside math functions
142 else if ((char === ADD || char === MUL || char === DIV || char === SUB) && formattable[0]) {
143 let trimmed = result.trimEnd()
144 let prev = trimmed.charCodeAt(trimmed.length - 1)
145 let prevPrev = trimmed.charCodeAt(trimmed.length - 2)
146 let next = input.charCodeAt(i + 1)
147
148 // Do not add spaces for scientific notation, e.g.: `-3.4e-2`
149 if ((prev === LOWER_E || prev === UPPER_E) && prevPrev >= ZERO && prevPrev <= NINE) {
150 result += input[i]
151 continue
152 }
153
154 // If we're preceded by an operator don't add spaces
155 else if (prev === ADD || prev === MUL || prev === DIV || prev === SUB) {
156 result += input[i]
157 continue
158 }
159
160 // If we're at the beginning of an argument don't add spaces
161 else if (prev === OPEN_PAREN || prev === COMMA) {
162 result += input[i]
163 continue
164 }
165
166 // Add spaces only after the operator if we already have spaces before it
167 else if (input.charCodeAt(i - 1) === SPACE) {
168 result += `${input[i]} `
169 }
170
171 // Add spaces around the operator, if...
172 else if (
173 // Previous is a digit
174 (prev >= ZERO && prev <= NINE) ||
175 // Next is a digit
176 (next >= ZERO && next <= NINE) ||
177 // Previous is end of a function call (or parenthesized expression)
178 prev === CLOSE_PAREN ||
179 // Next is start of a parenthesized expression
180 next === OPEN_PAREN ||
181 // Next is an operator
182 next === ADD ||
183 next === MUL ||
184 next === DIV ||
185 next === SUB ||
186 // Previous position was a value (+ unit)
187 (lastValuePos !== null && lastValuePos === i - 1)
188 ) {
189 result += ` ${input[i]} `
190 }
191
192 // Everything else
193 else {
194 result += input[i]
195 }
196 }
197
198 // Handle all other characters
199 else {
200 result += input[i]
201 }
202 }
203
204 return result
205}
Note: See TracBrowser for help on using the repository browser.