tailwindcss 3.0.24 → 3.1.2
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/CHANGELOG.md +75 -3
- package/colors.d.ts +3 -0
- package/defaultConfig.d.ts +3 -0
- package/defaultTheme.d.ts +3 -0
- package/lib/cli-peer-dependencies.js +8 -3
- package/lib/cli.js +125 -83
- package/lib/corePluginList.js +1 -0
- package/lib/corePlugins.js +146 -117
- package/lib/css/preflight.css +1 -8
- package/lib/featureFlags.js +8 -6
- package/lib/index.js +10 -13
- package/lib/lib/cacheInvalidation.js +32 -14
- package/lib/lib/collapseAdjacentRules.js +5 -3
- package/lib/lib/defaultExtractor.js +191 -32
- package/lib/lib/evaluateTailwindFunctions.js +22 -13
- package/lib/lib/expandApplyAtRules.js +232 -195
- package/lib/lib/expandTailwindAtRules.js +40 -26
- package/lib/lib/generateRules.js +106 -42
- package/lib/lib/regex.js +52 -0
- package/lib/lib/resolveDefaultsAtRules.js +56 -45
- package/lib/lib/setupContextUtils.js +131 -79
- package/lib/lib/setupTrackingContext.js +7 -9
- package/lib/lib/sharedState.js +1 -2
- package/lib/lib/substituteScreenAtRules.js +1 -2
- package/lib/postcss-plugins/nesting/plugin.js +1 -2
- package/lib/util/buildMediaQuery.js +1 -2
- package/lib/util/cloneDeep.js +2 -4
- package/lib/util/color.js +26 -36
- package/lib/util/createPlugin.js +1 -2
- package/lib/util/createUtilityPlugin.js +1 -2
- package/lib/util/dataTypes.js +14 -12
- package/lib/util/flattenColorPalette.js +2 -5
- package/lib/util/formatVariantSelector.js +64 -57
- package/lib/util/getAllConfigs.js +10 -5
- package/lib/util/isValidArbitraryValue.js +1 -2
- package/lib/util/log.js +2 -3
- package/lib/util/negateValue.js +1 -2
- package/lib/util/normalizeConfig.js +33 -23
- package/lib/util/normalizeScreens.js +1 -2
- package/lib/util/parseAnimationValue.js +1 -2
- package/lib/util/parseBoxShadowValue.js +2 -43
- package/lib/util/pluginUtils.js +11 -3
- package/lib/util/resolveConfig.js +57 -34
- package/lib/util/splitAtTopLevelOnly.js +90 -0
- package/lib/util/transformThemeValue.js +4 -2
- package/lib/util/validateConfig.js +21 -0
- package/lib/util/withAlphaVariable.js +5 -5
- package/package.json +21 -16
- package/peers/index.js +3264 -1330
- package/plugin.d.ts +11 -0
- package/src/cli-peer-dependencies.js +7 -1
- package/src/cli.js +104 -34
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +57 -40
- package/src/css/preflight.css +1 -8
- package/src/featureFlags.js +2 -2
- package/src/index.js +0 -2
- package/src/lib/collapseAdjacentRules.js +5 -1
- package/src/lib/defaultExtractor.js +177 -35
- package/src/lib/evaluateTailwindFunctions.js +20 -4
- package/src/lib/expandApplyAtRules.js +247 -188
- package/src/lib/expandTailwindAtRules.js +4 -4
- package/src/lib/generateRules.js +69 -5
- package/src/lib/regex.js +74 -0
- package/src/lib/resolveDefaultsAtRules.js +53 -36
- package/src/lib/setupContextUtils.js +103 -39
- package/src/lib/setupTrackingContext.js +4 -0
- package/src/util/color.js +20 -18
- package/src/util/dataTypes.js +11 -5
- package/src/util/formatVariantSelector.js +79 -62
- package/src/util/getAllConfigs.js +7 -0
- package/src/util/log.js +1 -1
- package/src/util/normalizeConfig.js +0 -8
- package/src/util/parseBoxShadowValue.js +3 -50
- package/src/util/pluginUtils.js +13 -1
- package/src/util/resolveConfig.js +66 -54
- package/src/util/splitAtTopLevelOnly.js +71 -0
- package/src/util/toPath.js +1 -1
- package/src/util/transformThemeValue.js +4 -2
- package/src/util/validateConfig.js +13 -0
- package/src/util/withAlphaVariable.js +1 -1
- package/stubs/defaultConfig.stub.js +2 -3
- package/stubs/simpleConfig.stub.js +1 -0
- package/types/config.d.ts +325 -0
- package/types/generated/.gitkeep +0 -0
- package/types/generated/colors.d.ts +276 -0
- package/types/generated/corePluginList.d.ts +1 -0
- package/types/index.d.ts +7 -0
package/src/util/log.js
CHANGED
|
@@ -3,7 +3,7 @@ import colors from 'picocolors'
|
|
|
3
3
|
let alreadyShown = new Set()
|
|
4
4
|
|
|
5
5
|
function log(type, messages, key) {
|
|
6
|
-
if (process.env.JEST_WORKER_ID
|
|
6
|
+
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) return
|
|
7
7
|
|
|
8
8
|
if (key && alreadyShown.has(key)) return
|
|
9
9
|
if (key) alreadyShown.add(key)
|
|
@@ -258,13 +258,5 @@ export function normalizeConfig(config) {
|
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
if (config.content.files.length === 0) {
|
|
262
|
-
log.warn('content-problems', [
|
|
263
|
-
'The `content` option in your Tailwind CSS configuration is missing or empty.',
|
|
264
|
-
'Configure your content sources or your generated CSS will be missing styles.',
|
|
265
|
-
'https://tailwindcss.com/docs/content-configuration',
|
|
266
|
-
])
|
|
267
|
-
}
|
|
268
|
-
|
|
269
261
|
return config
|
|
270
262
|
}
|
|
@@ -1,58 +1,11 @@
|
|
|
1
|
+
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
|
|
2
|
+
|
|
1
3
|
let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
|
|
2
4
|
let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
|
|
3
5
|
let LENGTH = /^-?(\d+|\.\d+)(.*?)$/g
|
|
4
6
|
|
|
5
|
-
let SPECIALS = /[(),]/g
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* This splits a string on top-level commas.
|
|
9
|
-
*
|
|
10
|
-
* Regex doesn't support recursion (at least not the JS-flavored version).
|
|
11
|
-
* So we have to use a tiny state machine to keep track of paren vs comma
|
|
12
|
-
* placement. Before we'd only exclude commas from the inner-most nested
|
|
13
|
-
* set of parens rather than any commas that were not contained in parens
|
|
14
|
-
* at all which is the intended behavior here.
|
|
15
|
-
*
|
|
16
|
-
* Expected behavior:
|
|
17
|
-
* var(--a, 0 0 1px rgb(0, 0, 0)), 0 0 1px rgb(0, 0, 0)
|
|
18
|
-
* ─┬─ ┬ ┬ ┬
|
|
19
|
-
* x x x ╰──────── Split because top-level
|
|
20
|
-
* ╰──────────────┴──┴───────────── Ignored b/c inside >= 1 levels of parens
|
|
21
|
-
*
|
|
22
|
-
* @param {string} input
|
|
23
|
-
*/
|
|
24
|
-
function* splitByTopLevelCommas(input) {
|
|
25
|
-
SPECIALS.lastIndex = -1
|
|
26
|
-
|
|
27
|
-
let depth = 0
|
|
28
|
-
let lastIndex = 0
|
|
29
|
-
let found = false
|
|
30
|
-
|
|
31
|
-
// Find all parens & commas
|
|
32
|
-
// And only split on commas if they're top-level
|
|
33
|
-
for (let match of input.matchAll(SPECIALS)) {
|
|
34
|
-
if (match[0] === '(') depth++
|
|
35
|
-
if (match[0] === ')') depth--
|
|
36
|
-
if (match[0] === ',' && depth === 0) {
|
|
37
|
-
found = true
|
|
38
|
-
|
|
39
|
-
yield input.substring(lastIndex, match.index)
|
|
40
|
-
lastIndex = match.index + match[0].length
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Provide the last segment of the string if available
|
|
45
|
-
// Otherwise the whole string since no commas were found
|
|
46
|
-
// This mirrors the behavior of string.split()
|
|
47
|
-
if (found) {
|
|
48
|
-
yield input.substring(lastIndex)
|
|
49
|
-
} else {
|
|
50
|
-
yield input
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
7
|
export function parseBoxShadowValue(input) {
|
|
55
|
-
let shadows = Array.from(
|
|
8
|
+
let shadows = Array.from(splitAtTopLevelOnly(input, ','))
|
|
56
9
|
return shadows.map((shadow) => {
|
|
57
10
|
let value = shadow.trim()
|
|
58
11
|
let result = { raw: value }
|
package/src/util/pluginUtils.js
CHANGED
|
@@ -95,9 +95,19 @@ function splitAlpha(modifier) {
|
|
|
95
95
|
return [modifier.slice(0, slashIdx), modifier.slice(slashIdx + 1)]
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
export function parseColorFormat(value) {
|
|
99
|
+
if (typeof value === 'string' && value.includes('<alpha-value>')) {
|
|
100
|
+
let oldValue = value
|
|
101
|
+
|
|
102
|
+
return ({ opacityValue = 1 }) => oldValue.replace('<alpha-value>', opacityValue)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return value
|
|
106
|
+
}
|
|
107
|
+
|
|
98
108
|
export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
|
|
99
109
|
if (options.values?.[modifier] !== undefined) {
|
|
100
|
-
return options.values?.[modifier]
|
|
110
|
+
return parseColorFormat(options.values?.[modifier])
|
|
101
111
|
}
|
|
102
112
|
|
|
103
113
|
let [color, alpha] = splitAlpha(modifier)
|
|
@@ -110,6 +120,8 @@ export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
|
|
|
110
120
|
return undefined
|
|
111
121
|
}
|
|
112
122
|
|
|
123
|
+
normalizedColor = parseColorFormat(normalizedColor)
|
|
124
|
+
|
|
113
125
|
if (isArbitraryValue(alpha)) {
|
|
114
126
|
return withAlphaValue(normalizedColor, alpha.slice(1, -1))
|
|
115
127
|
}
|
|
@@ -8,6 +8,9 @@ import { toPath } from './toPath'
|
|
|
8
8
|
import { normalizeConfig } from './normalizeConfig'
|
|
9
9
|
import isPlainObject from './isPlainObject'
|
|
10
10
|
import { cloneDeep } from './cloneDeep'
|
|
11
|
+
import { parseColorFormat } from './pluginUtils'
|
|
12
|
+
import { withAlphaValue } from './withAlphaVariable'
|
|
13
|
+
import toColorValue from './toColorValue'
|
|
11
14
|
|
|
12
15
|
function isFunction(input) {
|
|
13
16
|
return typeof input === 'function'
|
|
@@ -66,38 +69,6 @@ const configUtils = {
|
|
|
66
69
|
{}
|
|
67
70
|
)
|
|
68
71
|
},
|
|
69
|
-
/*
|
|
70
|
-
rgb(property) {
|
|
71
|
-
if (!property.startsWith('--')) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
'The rgb() helper requires a custom property name to be passed as the first argument.'
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return ({ opacityValue }) => {
|
|
78
|
-
if (opacityValue === undefined || opacityValue === 1) {
|
|
79
|
-
return `rgb(var(${property}) / 1.0)`
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return `rgb(var(${property}) / ${opacityValue})`
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
hsl(property) {
|
|
86
|
-
if (!property.startsWith('--')) {
|
|
87
|
-
throw new Error(
|
|
88
|
-
'The hsl() helper requires a custom property name to be passed as the first argument.'
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return ({ opacityValue }) => {
|
|
93
|
-
if (opacityValue === undefined || opacityValue === 1) {
|
|
94
|
-
return `hsl(var(${property}) / 1)`
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return `hsl(var(${property}) / ${opacityValue})`
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
*/
|
|
101
72
|
}
|
|
102
73
|
|
|
103
74
|
function value(valueToResolve, ...args) {
|
|
@@ -166,40 +137,81 @@ function mergeExtensions({ extend, ...theme }) {
|
|
|
166
137
|
})
|
|
167
138
|
}
|
|
168
139
|
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @param {string} key
|
|
143
|
+
* @return {Iterable<string[] & {alpha: string | undefined}>}
|
|
144
|
+
*/
|
|
145
|
+
function* toPaths(key) {
|
|
146
|
+
let path = toPath(key)
|
|
147
|
+
|
|
148
|
+
if (path.length === 0) {
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
yield path
|
|
153
|
+
|
|
154
|
+
if (Array.isArray(key)) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let pattern = /^(.*?)\s*\/\s*([^/]+)$/
|
|
159
|
+
let matches = key.match(pattern)
|
|
160
|
+
|
|
161
|
+
if (matches !== null) {
|
|
162
|
+
let [, prefix, alpha] = matches
|
|
163
|
+
|
|
164
|
+
let newPath = toPath(prefix)
|
|
165
|
+
newPath.alpha = alpha
|
|
166
|
+
|
|
167
|
+
yield newPath
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
169
171
|
function resolveFunctionKeys(object) {
|
|
172
|
+
// theme('colors.red.500 / 0.5') -> ['colors', 'red', '500 / 0', '5]
|
|
173
|
+
|
|
170
174
|
const resolvePath = (key, defaultValue) => {
|
|
171
|
-
const path
|
|
175
|
+
for (const path of toPaths(key)) {
|
|
176
|
+
let index = 0
|
|
177
|
+
let val = object
|
|
172
178
|
|
|
173
|
-
|
|
174
|
-
|
|
179
|
+
while (val !== undefined && val !== null && index < path.length) {
|
|
180
|
+
val = val[path[index++]]
|
|
175
181
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
val = isFunction(val) ? val(resolvePath, configUtils) : val
|
|
179
|
-
}
|
|
182
|
+
let shouldResolveAsFn =
|
|
183
|
+
isFunction(val) && (path.alpha === undefined || index < path.length - 1)
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
185
|
+
val = shouldResolveAsFn ? val(resolvePath, configUtils) : val
|
|
186
|
+
}
|
|
184
187
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
+
if (val !== undefined) {
|
|
189
|
+
if (path.alpha !== undefined) {
|
|
190
|
+
let normalized = parseColorFormat(val)
|
|
188
191
|
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
return withAlphaValue(normalized, path.alpha, toColorValue(normalized))
|
|
193
|
+
}
|
|
191
194
|
|
|
192
|
-
|
|
195
|
+
if (isPlainObject(val)) {
|
|
196
|
+
return cloneDeep(val)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return val
|
|
200
|
+
}
|
|
201
|
+
}
|
|
193
202
|
|
|
194
|
-
|
|
195
|
-
resolvePath[key] = configUtils[key]
|
|
203
|
+
return defaultValue
|
|
196
204
|
}
|
|
197
205
|
|
|
206
|
+
Object.assign(resolvePath, {
|
|
207
|
+
theme: resolvePath,
|
|
208
|
+
...configUtils,
|
|
209
|
+
})
|
|
210
|
+
|
|
198
211
|
return Object.keys(object).reduce((resolved, key) => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
212
|
+
resolved[key] = isFunction(object[key]) ? object[key](resolvePath, configUtils) : object[key]
|
|
213
|
+
|
|
214
|
+
return resolved
|
|
203
215
|
}, {})
|
|
204
216
|
}
|
|
205
217
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as regex from '../lib/regex'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This splits a string on a top-level character.
|
|
5
|
+
*
|
|
6
|
+
* Regex doesn't support recursion (at least not the JS-flavored version).
|
|
7
|
+
* So we have to use a tiny state machine to keep track of paren placement.
|
|
8
|
+
*
|
|
9
|
+
* Expected behavior using commas:
|
|
10
|
+
* var(--a, 0 0 1px rgb(0, 0, 0)), 0 0 1px rgb(0, 0, 0)
|
|
11
|
+
* ─┬─ ┬ ┬ ┬
|
|
12
|
+
* x x x ╰──────── Split because top-level
|
|
13
|
+
* ╰──────────────┴──┴───────────── Ignored b/c inside >= 1 levels of parens
|
|
14
|
+
*
|
|
15
|
+
* @param {string} input
|
|
16
|
+
* @param {string} separator
|
|
17
|
+
*/
|
|
18
|
+
export function* splitAtTopLevelOnly(input, separator) {
|
|
19
|
+
let SPECIALS = new RegExp(`[(){}\\[\\]${regex.escape(separator)}]`, 'g')
|
|
20
|
+
|
|
21
|
+
let depth = 0
|
|
22
|
+
let lastIndex = 0
|
|
23
|
+
let found = false
|
|
24
|
+
let separatorIndex = 0
|
|
25
|
+
let separatorStart = 0
|
|
26
|
+
let separatorLength = separator.length
|
|
27
|
+
|
|
28
|
+
// Find all paren-like things & character
|
|
29
|
+
// And only split on commas if they're top-level
|
|
30
|
+
for (let match of input.matchAll(SPECIALS)) {
|
|
31
|
+
let matchesSeparator = match[0] === separator[separatorIndex]
|
|
32
|
+
let atEndOfSeparator = separatorIndex === separatorLength - 1
|
|
33
|
+
let matchesFullSeparator = matchesSeparator && atEndOfSeparator
|
|
34
|
+
|
|
35
|
+
if (match[0] === '(') depth++
|
|
36
|
+
if (match[0] === ')') depth--
|
|
37
|
+
if (match[0] === '[') depth++
|
|
38
|
+
if (match[0] === ']') depth--
|
|
39
|
+
if (match[0] === '{') depth++
|
|
40
|
+
if (match[0] === '}') depth--
|
|
41
|
+
|
|
42
|
+
if (matchesSeparator && depth === 0) {
|
|
43
|
+
if (separatorStart === 0) {
|
|
44
|
+
separatorStart = match.index
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
separatorIndex++
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (matchesFullSeparator && depth === 0) {
|
|
51
|
+
found = true
|
|
52
|
+
|
|
53
|
+
yield input.substring(lastIndex, separatorStart)
|
|
54
|
+
lastIndex = separatorStart + separatorLength
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (separatorIndex === separatorLength) {
|
|
58
|
+
separatorIndex = 0
|
|
59
|
+
separatorStart = 0
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Provide the last segment of the string if available
|
|
64
|
+
// Otherwise the whole string since no `char`s were found
|
|
65
|
+
// This mirrors the behavior of string.split()
|
|
66
|
+
if (found) {
|
|
67
|
+
yield input.substring(lastIndex)
|
|
68
|
+
} else {
|
|
69
|
+
yield input
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/util/toPath.js
CHANGED
|
@@ -44,8 +44,10 @@ export default function transformThemeValue(themeSection) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
return (value) => {
|
|
48
|
-
if (typeof value === 'function')
|
|
47
|
+
return (value, opts = {}) => {
|
|
48
|
+
if (typeof value === 'function') {
|
|
49
|
+
value = value(opts)
|
|
50
|
+
}
|
|
49
51
|
|
|
50
52
|
return value
|
|
51
53
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import log from './log'
|
|
2
|
+
|
|
3
|
+
export function validateConfig(config) {
|
|
4
|
+
if (config.content.files.length === 0) {
|
|
5
|
+
log.warn('content-problems', [
|
|
6
|
+
'The `content` option in your Tailwind CSS configuration is missing or empty.',
|
|
7
|
+
'Configure your content sources or your generated CSS will be missing styles.',
|
|
8
|
+
'https://tailwindcss.com/docs/content-configuration',
|
|
9
|
+
])
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return config
|
|
13
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
1
2
|
module.exports = {
|
|
2
3
|
content: [],
|
|
3
4
|
presets: [],
|
|
@@ -194,11 +195,9 @@ module.exports = {
|
|
|
194
195
|
'3xl': '1.5rem',
|
|
195
196
|
full: '9999px',
|
|
196
197
|
},
|
|
197
|
-
/*
|
|
198
198
|
borderSpacing: ({ theme }) => ({
|
|
199
199
|
...theme('spacing'),
|
|
200
200
|
}),
|
|
201
|
-
*/
|
|
202
201
|
borderWidth: {
|
|
203
202
|
DEFAULT: '1px',
|
|
204
203
|
0: '0px',
|
|
@@ -722,7 +721,7 @@ module.exports = {
|
|
|
722
721
|
8: '8px',
|
|
723
722
|
},
|
|
724
723
|
ringColor: ({ theme }) => ({
|
|
725
|
-
DEFAULT: theme(
|
|
724
|
+
DEFAULT: theme(`colors.blue.500`, '#3b82f6'),
|
|
726
725
|
...theme('colors'),
|
|
727
726
|
}),
|
|
728
727
|
ringOffsetColor: ({ theme }) => theme('colors'),
|