tailwindcss 3.4.17 → 3.4.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli/build/plugin.js +5 -2
- package/lib/corePlugins.js +2 -2
- package/lib/lib/generateRules.js +6 -1
- package/lib/lib/load-config.js +1 -8
- package/lib/lib/setupTrackingContext.js +3 -0
- package/lib/util/dataTypes.js +2 -108
- package/lib/util/math-operators.js +152 -0
- package/package.json +10 -4
- package/peers/index.js +166 -287
- package/src/cli/build/plugin.js +5 -2
- package/src/corePlugins.js +2 -2
- package/src/lib/generateRules.js +8 -1
- package/src/lib/load-config.ts +1 -16
- package/src/lib/setupTrackingContext.js +3 -0
- package/src/util/dataTypes.js +2 -117
- package/src/util/math-operators.ts +205 -0
- package/CHANGELOG.md +0 -2713
package/src/util/dataTypes.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseColor } from './color'
|
|
2
|
+
import { addWhitespaceAroundMathOperators } from './math-operators'
|
|
2
3
|
import { parseBoxShadowValue } from './parseBoxShadowValue'
|
|
3
4
|
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
|
4
5
|
|
|
@@ -76,7 +77,7 @@ export function normalize(value, context = null, isRoot = true) {
|
|
|
76
77
|
value = value.trim()
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
value =
|
|
80
|
+
value = addWhitespaceAroundMathOperators(value)
|
|
80
81
|
|
|
81
82
|
return value
|
|
82
83
|
}
|
|
@@ -109,122 +110,6 @@ export function normalizeAttributeSelectors(value) {
|
|
|
109
110
|
return value
|
|
110
111
|
}
|
|
111
112
|
|
|
112
|
-
/**
|
|
113
|
-
* Add spaces around operators inside math functions
|
|
114
|
-
* like calc() that do not follow an operator, '(', or `,`.
|
|
115
|
-
*
|
|
116
|
-
* @param {string} value
|
|
117
|
-
* @returns {string}
|
|
118
|
-
*/
|
|
119
|
-
function normalizeMathOperatorSpacing(value) {
|
|
120
|
-
let preventFormattingInFunctions = ['theme']
|
|
121
|
-
let preventFormattingKeywords = [
|
|
122
|
-
'min-content',
|
|
123
|
-
'max-content',
|
|
124
|
-
'fit-content',
|
|
125
|
-
|
|
126
|
-
// Env
|
|
127
|
-
'safe-area-inset-top',
|
|
128
|
-
'safe-area-inset-right',
|
|
129
|
-
'safe-area-inset-bottom',
|
|
130
|
-
'safe-area-inset-left',
|
|
131
|
-
|
|
132
|
-
'titlebar-area-x',
|
|
133
|
-
'titlebar-area-y',
|
|
134
|
-
'titlebar-area-width',
|
|
135
|
-
'titlebar-area-height',
|
|
136
|
-
|
|
137
|
-
'keyboard-inset-top',
|
|
138
|
-
'keyboard-inset-right',
|
|
139
|
-
'keyboard-inset-bottom',
|
|
140
|
-
'keyboard-inset-left',
|
|
141
|
-
'keyboard-inset-width',
|
|
142
|
-
'keyboard-inset-height',
|
|
143
|
-
|
|
144
|
-
'radial-gradient',
|
|
145
|
-
'linear-gradient',
|
|
146
|
-
'conic-gradient',
|
|
147
|
-
'repeating-radial-gradient',
|
|
148
|
-
'repeating-linear-gradient',
|
|
149
|
-
'repeating-conic-gradient',
|
|
150
|
-
|
|
151
|
-
'anchor-size',
|
|
152
|
-
]
|
|
153
|
-
|
|
154
|
-
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
|
155
|
-
let result = ''
|
|
156
|
-
|
|
157
|
-
function lastChar() {
|
|
158
|
-
let char = result.trimEnd()
|
|
159
|
-
return char[char.length - 1]
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
for (let i = 0; i < match.length; i++) {
|
|
163
|
-
function peek(word) {
|
|
164
|
-
return word.split('').every((char, j) => match[i + j] === char)
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function consumeUntil(chars) {
|
|
168
|
-
let minIndex = Infinity
|
|
169
|
-
for (let char of chars) {
|
|
170
|
-
let index = match.indexOf(char, i)
|
|
171
|
-
if (index !== -1 && index < minIndex) {
|
|
172
|
-
minIndex = index
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
let result = match.slice(i, minIndex)
|
|
177
|
-
i += result.length - 1
|
|
178
|
-
return result
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
let char = match[i]
|
|
182
|
-
|
|
183
|
-
// Handle `var(--variable)`
|
|
184
|
-
if (peek('var')) {
|
|
185
|
-
// When we consume until `)`, then we are dealing with this scenario:
|
|
186
|
-
// `var(--example)`
|
|
187
|
-
//
|
|
188
|
-
// When we consume until `,`, then we are dealing with this scenario:
|
|
189
|
-
// `var(--example, 1rem)`
|
|
190
|
-
//
|
|
191
|
-
// In this case we do want to "format", the default value as well
|
|
192
|
-
result += consumeUntil([')', ','])
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Skip formatting of known keywords
|
|
196
|
-
else if (preventFormattingKeywords.some((keyword) => peek(keyword))) {
|
|
197
|
-
let keyword = preventFormattingKeywords.find((keyword) => peek(keyword))
|
|
198
|
-
result += keyword
|
|
199
|
-
i += keyword.length - 1
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Skip formatting inside known functions
|
|
203
|
-
else if (preventFormattingInFunctions.some((fn) => peek(fn))) {
|
|
204
|
-
result += consumeUntil([')'])
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Don't break CSS grid track names
|
|
208
|
-
else if (peek('[')) {
|
|
209
|
-
result += consumeUntil([']'])
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Handle operators
|
|
213
|
-
else if (
|
|
214
|
-
['+', '-', '*', '/'].includes(char) &&
|
|
215
|
-
!['(', '+', '-', '*', '/', ','].includes(lastChar())
|
|
216
|
-
) {
|
|
217
|
-
result += ` ${char} `
|
|
218
|
-
} else {
|
|
219
|
-
result += char
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Simplify multiple spaces
|
|
224
|
-
return result.replace(/\s+/g, ' ')
|
|
225
|
-
})
|
|
226
|
-
}
|
|
227
|
-
|
|
228
113
|
export function url(value) {
|
|
229
114
|
return value.startsWith('url(')
|
|
230
115
|
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
const LOWER_A = 0x61
|
|
2
|
+
const LOWER_Z = 0x7a
|
|
3
|
+
const UPPER_A = 0x41
|
|
4
|
+
const UPPER_Z = 0x5a
|
|
5
|
+
const LOWER_E = 0x65
|
|
6
|
+
const UPPER_E = 0x45
|
|
7
|
+
const ZERO = 0x30
|
|
8
|
+
const NINE = 0x39
|
|
9
|
+
const ADD = 0x2b
|
|
10
|
+
const SUB = 0x2d
|
|
11
|
+
const MUL = 0x2a
|
|
12
|
+
const DIV = 0x2f
|
|
13
|
+
const OPEN_PAREN = 0x28
|
|
14
|
+
const CLOSE_PAREN = 0x29
|
|
15
|
+
const COMMA = 0x2c
|
|
16
|
+
const SPACE = 0x20
|
|
17
|
+
const PERCENT = 0x25
|
|
18
|
+
|
|
19
|
+
const 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
|
+
|
|
41
|
+
export function hasMathFn(input: string) {
|
|
42
|
+
return input.indexOf('(') !== -1 && MATH_FUNCTIONS.some((fn) => input.includes(`${fn}(`))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export 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
|
+
}
|