tailwindcss 0.0.0-insiders.df011dc → 0.0.0-insiders.e2d5f21
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 +106 -1
- package/README.md +1 -1
- package/colors.js +1 -304
- package/defaultConfig.js +1 -4
- package/defaultTheme.js +1 -4
- package/lib/cli-peer-dependencies.js +4 -9
- package/lib/cli.js +646 -705
- package/lib/constants.js +15 -15
- package/lib/corePluginList.js +174 -4
- package/lib/corePlugins.js +3637 -2934
- package/lib/css/preflight.css +14 -1
- package/lib/featureFlags.js +44 -44
- package/lib/index.js +25 -24
- package/lib/lib/collapseAdjacentRules.js +33 -35
- package/lib/lib/collapseDuplicateDeclarations.js +29 -0
- package/lib/lib/detectNesting.js +34 -0
- package/lib/lib/evaluateTailwindFunctions.js +134 -155
- package/lib/lib/expandApplyAtRules.js +183 -200
- package/lib/lib/expandTailwindAtRules.js +219 -232
- package/lib/lib/generateRules.js +478 -311
- package/lib/lib/getModuleDependencies.js +36 -41
- package/lib/lib/normalizeTailwindDirectives.js +66 -58
- package/lib/lib/resolveDefaultsAtRules.js +110 -90
- package/lib/lib/setupContextUtils.js +740 -580
- package/lib/lib/setupTrackingContext.js +142 -162
- package/lib/lib/setupWatchingContext.js +235 -278
- package/lib/lib/sharedState.js +7 -17
- package/lib/lib/substituteScreenAtRules.js +22 -26
- package/lib/processTailwindFeatures.js +38 -44
- package/lib/public/colors.js +329 -0
- package/lib/public/create-plugin.js +13 -0
- package/lib/public/default-config.js +14 -0
- package/lib/public/default-theme.js +14 -0
- package/lib/public/resolve-config.js +19 -0
- package/lib/util/bigSign.js +3 -5
- package/lib/util/buildMediaQuery.js +15 -31
- package/lib/util/cloneDeep.js +14 -13
- package/lib/util/cloneNodes.js +9 -13
- package/lib/util/color.js +69 -59
- package/lib/util/configurePlugins.js +13 -14
- package/lib/util/createPlugin.js +21 -24
- package/lib/util/createUtilityPlugin.js +47 -45
- package/lib/util/dataTypes.js +231 -0
- package/lib/util/defaults.js +10 -14
- package/lib/util/escapeClassName.js +12 -14
- package/lib/util/escapeCommas.js +3 -5
- package/lib/util/flattenColorPalette.js +14 -10
- package/lib/util/formatVariantSelector.js +186 -0
- package/lib/util/getAllConfigs.js +23 -16
- package/lib/util/hashConfig.js +10 -10
- package/lib/util/isKeyframeRule.js +3 -5
- package/lib/util/isPlainObject.js +7 -10
- package/lib/util/isValidArbitraryValue.js +64 -0
- package/lib/util/log.js +39 -30
- package/lib/util/nameClass.js +23 -23
- package/lib/util/negateValue.js +14 -15
- package/lib/util/normalizeConfig.js +208 -0
- package/lib/util/normalizeScreens.js +58 -0
- package/lib/util/parseAnimationValue.js +82 -53
- package/lib/util/parseBoxShadowValue.js +77 -0
- package/lib/util/parseDependency.js +49 -60
- package/lib/util/parseObjectStyles.js +23 -20
- package/lib/util/pluginUtils.js +153 -285
- package/lib/util/prefixSelector.js +14 -16
- package/lib/util/resolveConfig.js +194 -249
- package/lib/util/resolveConfigPath.js +38 -45
- package/lib/util/responsive.js +12 -11
- package/lib/util/tap.js +4 -6
- package/lib/util/toColorValue.js +4 -5
- package/lib/util/toPath.js +4 -6
- package/lib/util/transformThemeValue.js +57 -26
- package/lib/util/withAlphaVariable.js +56 -54
- package/package.json +27 -37
- package/peers/index.js +73099 -84294
- package/plugin.js +1 -3
- package/resolveConfig.js +1 -7
- package/scripts/create-plugin-list.js +2 -2
- package/src/cli.js +27 -18
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +2124 -1968
- package/src/css/preflight.css +14 -1
- package/src/featureFlags.js +12 -6
- package/src/lib/collapseDuplicateDeclarations.js +28 -0
- package/src/lib/detectNesting.js +39 -0
- package/src/lib/evaluateTailwindFunctions.js +5 -2
- package/src/lib/expandTailwindAtRules.js +24 -32
- package/src/lib/generateRules.js +230 -20
- package/src/lib/normalizeTailwindDirectives.js +3 -2
- package/src/lib/resolveDefaultsAtRules.js +46 -30
- package/src/lib/setupContextUtils.js +275 -113
- package/src/lib/setupTrackingContext.js +9 -8
- package/src/lib/setupWatchingContext.js +12 -7
- package/src/lib/sharedState.js +1 -4
- package/src/lib/substituteScreenAtRules.js +6 -3
- package/src/processTailwindFeatures.js +8 -1
- package/src/public/colors.js +300 -0
- package/src/public/create-plugin.js +2 -0
- package/src/public/default-config.js +4 -0
- package/src/public/default-theme.js +4 -0
- package/src/public/resolve-config.js +7 -0
- package/src/util/buildMediaQuery.js +14 -18
- package/src/util/createUtilityPlugin.js +2 -11
- package/src/util/dataTypes.js +246 -0
- package/src/util/formatVariantSelector.js +196 -0
- package/src/util/isValidArbitraryValue.js +61 -0
- package/src/util/log.js +18 -21
- package/src/util/nameClass.js +10 -6
- package/src/util/negateValue.js +4 -2
- package/src/util/normalizeConfig.js +249 -0
- package/src/util/normalizeScreens.js +42 -0
- package/src/util/parseAnimationValue.js +7 -1
- package/src/util/parseBoxShadowValue.js +71 -0
- package/src/util/parseDependency.js +4 -0
- package/src/util/pluginUtils.js +101 -204
- package/src/util/prefixSelector.js +1 -4
- package/src/util/resolveConfig.js +12 -65
- package/src/util/transformThemeValue.js +22 -7
- package/src/util/withAlphaVariable.js +13 -8
- package/stubs/defaultConfig.stub.js +163 -97
- package/stubs/simpleConfig.stub.js +0 -1
|
@@ -2,42 +2,58 @@ import postcss from 'postcss'
|
|
|
2
2
|
import selectorParser from 'postcss-selector-parser'
|
|
3
3
|
import { flagEnabled } from '../featureFlags'
|
|
4
4
|
|
|
5
|
+
let getNode = {
|
|
6
|
+
id(node) {
|
|
7
|
+
return selectorParser.attribute({
|
|
8
|
+
attribute: 'id',
|
|
9
|
+
operator: '=',
|
|
10
|
+
value: node.value,
|
|
11
|
+
quoteMark: '"',
|
|
12
|
+
})
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
function minimumImpactSelector(nodes) {
|
|
6
|
-
let
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
let rest = nodes
|
|
18
|
+
.filter((node) => {
|
|
19
|
+
// Keep non-pseudo nodes
|
|
20
|
+
if (node.type !== 'pseudo') return true
|
|
21
|
+
|
|
22
|
+
// Keep pseudo nodes that have subnodes
|
|
23
|
+
// E.g.: `:not()` contains subnodes inside the parentheses
|
|
24
|
+
if (node.nodes.length > 0) return true
|
|
25
|
+
|
|
26
|
+
// Keep pseudo `elements`
|
|
27
|
+
// This implicitly means that we ignore pseudo `classes`
|
|
28
|
+
return (
|
|
29
|
+
node.value.startsWith('::') ||
|
|
30
|
+
[':before', ':after', ':first-line', ':first-letter'].includes(node.value)
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
.reverse()
|
|
34
|
+
|
|
35
|
+
let searchFor = new Set(['tag', 'class', 'id', 'attribute'])
|
|
36
|
+
|
|
37
|
+
let splitPointIdx = rest.findIndex((n) => searchFor.has(n.type))
|
|
38
|
+
if (splitPointIdx === -1) return rest.reverse().join('').trim()
|
|
39
|
+
|
|
40
|
+
let node = rest[splitPointIdx]
|
|
41
|
+
let bestNode = getNode[node.type] ? getNode[node.type](node) : node
|
|
42
|
+
|
|
43
|
+
rest = rest.slice(0, splitPointIdx)
|
|
44
|
+
|
|
45
|
+
let combinatorIdx = rest.findIndex((n) => n.type === 'combinator' && n.value === '>')
|
|
46
|
+
if (combinatorIdx !== -1) {
|
|
47
|
+
rest.splice(0, combinatorIdx)
|
|
48
|
+
rest.unshift(selectorParser.universal())
|
|
29
49
|
}
|
|
30
50
|
|
|
31
|
-
return [bestNode, ...
|
|
51
|
+
return [bestNode, ...rest.reverse()].join('').trim()
|
|
32
52
|
}
|
|
33
53
|
|
|
34
|
-
let elementSelectorParser = selectorParser((selectors) => {
|
|
54
|
+
export let elementSelectorParser = selectorParser((selectors) => {
|
|
35
55
|
return selectors.map((s) => {
|
|
36
|
-
let nodes = s
|
|
37
|
-
.split((n) => n.type === 'combinator')
|
|
38
|
-
.pop()
|
|
39
|
-
.filter((n) => n.type !== 'pseudo' || n.value.startsWith('::'))
|
|
40
|
-
|
|
56
|
+
let nodes = s.split((n) => n.type === 'combinator' && n.value === ' ').pop()
|
|
41
57
|
return minimumImpactSelector(nodes)
|
|
42
58
|
})
|
|
43
59
|
})
|
|
@@ -9,13 +9,45 @@ import parseObjectStyles from '../util/parseObjectStyles'
|
|
|
9
9
|
import prefixSelector from '../util/prefixSelector'
|
|
10
10
|
import isPlainObject from '../util/isPlainObject'
|
|
11
11
|
import escapeClassName from '../util/escapeClassName'
|
|
12
|
-
import nameClass from '../util/nameClass'
|
|
12
|
+
import nameClass, { formatClass } from '../util/nameClass'
|
|
13
13
|
import { coerceValue } from '../util/pluginUtils'
|
|
14
14
|
import bigSign from '../util/bigSign'
|
|
15
|
-
import
|
|
15
|
+
import { variantPlugins, corePlugins } from '../corePlugins'
|
|
16
16
|
import * as sharedState from './sharedState'
|
|
17
17
|
import { env } from './sharedState'
|
|
18
18
|
import { toPath } from '../util/toPath'
|
|
19
|
+
import log from '../util/log'
|
|
20
|
+
import negateValue from '../util/negateValue'
|
|
21
|
+
import isValidArbitraryValue from '../util/isValidArbitraryValue'
|
|
22
|
+
|
|
23
|
+
function parseVariantFormatString(input) {
|
|
24
|
+
if (input.includes('{')) {
|
|
25
|
+
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
|
|
26
|
+
|
|
27
|
+
return input
|
|
28
|
+
.split(/{(.*)}/gim)
|
|
29
|
+
.flatMap((line) => parseVariantFormatString(line))
|
|
30
|
+
.filter(Boolean)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return [input.trim()]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isBalanced(input) {
|
|
37
|
+
let count = 0
|
|
38
|
+
|
|
39
|
+
for (let char of input) {
|
|
40
|
+
if (char === '{') {
|
|
41
|
+
count++
|
|
42
|
+
} else if (char === '}') {
|
|
43
|
+
if (--count < 0) {
|
|
44
|
+
return false // unbalanced
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return count === 0
|
|
50
|
+
}
|
|
19
51
|
|
|
20
52
|
function insertInto(list, value, { before = [] } = {}) {
|
|
21
53
|
before = [].concat(before)
|
|
@@ -58,11 +90,22 @@ function getClasses(selector) {
|
|
|
58
90
|
}
|
|
59
91
|
|
|
60
92
|
function extractCandidates(node) {
|
|
61
|
-
let classes =
|
|
93
|
+
let classes = []
|
|
94
|
+
|
|
95
|
+
if (node.type === 'rule') {
|
|
96
|
+
for (let selector of node.selectors) {
|
|
97
|
+
let classCandidates = getClasses(selector)
|
|
98
|
+
// At least one of the selectors contains non-"on-demandable" candidates.
|
|
99
|
+
if (classCandidates.length === 0) return []
|
|
100
|
+
|
|
101
|
+
classes = [...classes, ...classCandidates]
|
|
102
|
+
}
|
|
103
|
+
return classes
|
|
104
|
+
}
|
|
62
105
|
|
|
63
106
|
if (node.type === 'atrule') {
|
|
64
107
|
node.walkRules((rule) => {
|
|
65
|
-
classes = [...classes, ...
|
|
108
|
+
classes = [...classes, ...rule.selectors.flatMap((selector) => getClasses(selector))]
|
|
66
109
|
})
|
|
67
110
|
}
|
|
68
111
|
|
|
@@ -88,65 +131,7 @@ function withIdentifiers(styles) {
|
|
|
88
131
|
})
|
|
89
132
|
}
|
|
90
133
|
|
|
91
|
-
|
|
92
|
-
['{', '}'],
|
|
93
|
-
['[', ']'],
|
|
94
|
-
['(', ')'],
|
|
95
|
-
])
|
|
96
|
-
let inverseMatchingBrackets = new Map(
|
|
97
|
-
Array.from(matchingBrackets.entries()).map(([k, v]) => [v, k])
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
let quotes = new Set(['"', "'", '`'])
|
|
101
|
-
|
|
102
|
-
// Arbitrary values must contain balanced brackets (), [] and {}. Escaped
|
|
103
|
-
// values don't count, and brackets inside quotes also don't count.
|
|
104
|
-
//
|
|
105
|
-
// E.g.: w-[this-is]w-[weird-and-invalid]
|
|
106
|
-
// E.g.: w-[this-is\\]w-\\[weird-but-valid]
|
|
107
|
-
// E.g.: content-['this-is-also-valid]-weirdly-enough']
|
|
108
|
-
function isValidArbitraryValue(value) {
|
|
109
|
-
let stack = []
|
|
110
|
-
let inQuotes = false
|
|
111
|
-
|
|
112
|
-
for (let i = 0; i < value.length; i++) {
|
|
113
|
-
let char = value[i]
|
|
114
|
-
|
|
115
|
-
// Non-escaped quotes allow us to "allow" anything in between
|
|
116
|
-
if (quotes.has(char) && value[i - 1] !== '\\') {
|
|
117
|
-
inQuotes = !inQuotes
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (inQuotes) continue
|
|
121
|
-
if (value[i - 1] === '\\') continue // Escaped
|
|
122
|
-
|
|
123
|
-
if (matchingBrackets.has(char)) {
|
|
124
|
-
stack.push(char)
|
|
125
|
-
} else if (inverseMatchingBrackets.has(char)) {
|
|
126
|
-
let inverse = inverseMatchingBrackets.get(char)
|
|
127
|
-
|
|
128
|
-
// Nothing to pop from, therefore it is unbalanced
|
|
129
|
-
if (stack.length <= 0) {
|
|
130
|
-
return false
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Popped value must match the inverse value, otherwise it is unbalanced
|
|
134
|
-
if (stack.pop() !== inverse) {
|
|
135
|
-
return false
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// If there is still something on the stack, it is also unbalanced
|
|
141
|
-
if (stack.length > 0) {
|
|
142
|
-
return false
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// All good, totally balanced!
|
|
146
|
-
return true
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets }) {
|
|
134
|
+
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {
|
|
150
135
|
function getConfigValue(path, defaultValue) {
|
|
151
136
|
return path ? dlv(tailwindConfig, path, defaultValue) : tailwindConfig
|
|
152
137
|
}
|
|
@@ -164,16 +149,41 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
164
149
|
return identifier
|
|
165
150
|
}
|
|
166
151
|
|
|
167
|
-
if (typeof context.tailwindConfig.prefix === 'function') {
|
|
168
|
-
return prefixSelector(context.tailwindConfig.prefix, `.${identifier}`).substr(1)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
152
|
return context.tailwindConfig.prefix + identifier
|
|
172
153
|
}
|
|
173
154
|
|
|
174
155
|
return {
|
|
175
156
|
addVariant(variantName, variantFunctions, options = {}) {
|
|
176
|
-
variantFunctions = [].concat(variantFunctions)
|
|
157
|
+
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
|
|
158
|
+
if (typeof variantFunction !== 'string') {
|
|
159
|
+
// Safelist public API functions
|
|
160
|
+
return ({ modifySelectors, container, separator }) => {
|
|
161
|
+
return variantFunction({ modifySelectors, container, separator })
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
variantFunction = variantFunction
|
|
166
|
+
.replace(/\n+/g, '')
|
|
167
|
+
.replace(/\s{1,}/g, ' ')
|
|
168
|
+
.trim()
|
|
169
|
+
|
|
170
|
+
let fns = parseVariantFormatString(variantFunction)
|
|
171
|
+
.map((str) => {
|
|
172
|
+
if (!str.startsWith('@')) {
|
|
173
|
+
return ({ format }) => format(str)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let [, name, params] = /@(.*?) (.*)/g.exec(str)
|
|
177
|
+
return ({ wrap }) => wrap(postcss.atRule({ name, params }))
|
|
178
|
+
})
|
|
179
|
+
.reverse()
|
|
180
|
+
|
|
181
|
+
return (api) => {
|
|
182
|
+
for (let fn of fns) {
|
|
183
|
+
fn(api)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
})
|
|
177
187
|
|
|
178
188
|
insertInto(variantList, variantName, options)
|
|
179
189
|
variantMap.set(variantName, variantFunctions)
|
|
@@ -225,22 +235,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
225
235
|
},
|
|
226
236
|
addComponents(components, options) {
|
|
227
237
|
let defaultOptions = {
|
|
228
|
-
variants: [],
|
|
229
238
|
respectPrefix: true,
|
|
230
239
|
respectImportant: false,
|
|
231
|
-
respectVariants: true,
|
|
232
240
|
}
|
|
233
241
|
|
|
234
|
-
options = Object.assign(
|
|
235
|
-
{},
|
|
236
|
-
defaultOptions,
|
|
237
|
-
Array.isArray(options) ? { variants: options } : options
|
|
238
|
-
)
|
|
242
|
+
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options)
|
|
239
243
|
|
|
240
244
|
for (let [identifier, rule] of withIdentifiers(components)) {
|
|
241
245
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
242
246
|
let offset = offsets.components++
|
|
243
247
|
|
|
248
|
+
classList.add(prefixedIdentifier)
|
|
249
|
+
|
|
244
250
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
245
251
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
246
252
|
}
|
|
@@ -252,22 +258,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
252
258
|
},
|
|
253
259
|
addUtilities(utilities, options) {
|
|
254
260
|
let defaultOptions = {
|
|
255
|
-
variants: [],
|
|
256
261
|
respectPrefix: true,
|
|
257
262
|
respectImportant: true,
|
|
258
|
-
respectVariants: true,
|
|
259
263
|
}
|
|
260
264
|
|
|
261
|
-
options = Object.assign(
|
|
262
|
-
{},
|
|
263
|
-
defaultOptions,
|
|
264
|
-
Array.isArray(options) ? { variants: options } : options
|
|
265
|
-
)
|
|
265
|
+
options = Object.assign({}, defaultOptions, Array.isArray(options) ? {} : options)
|
|
266
266
|
|
|
267
267
|
for (let [identifier, rule] of withIdentifiers(utilities)) {
|
|
268
268
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
269
269
|
let offset = offsets.utilities++
|
|
270
270
|
|
|
271
|
+
classList.add(prefixedIdentifier)
|
|
272
|
+
|
|
271
273
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
272
274
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
273
275
|
}
|
|
@@ -279,10 +281,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
279
281
|
},
|
|
280
282
|
matchUtilities: function (utilities, options) {
|
|
281
283
|
let defaultOptions = {
|
|
282
|
-
variants: [],
|
|
283
284
|
respectPrefix: true,
|
|
284
285
|
respectImportant: true,
|
|
285
|
-
respectVariants: true,
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
options = { ...defaultOptions, ...options }
|
|
@@ -293,12 +293,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
293
293
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
294
294
|
let rule = utilities[identifier]
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
classList.add([prefixedIdentifier, options])
|
|
297
|
+
|
|
298
|
+
function wrapped(modifier, { isOnlyPlugin }) {
|
|
297
299
|
let { type = 'any' } = options
|
|
298
300
|
type = [].concat(type)
|
|
299
|
-
let [value, coercedType] = coerceValue(type, modifier, options
|
|
301
|
+
let [value, coercedType] = coerceValue(type, modifier, options, tailwindConfig)
|
|
302
|
+
|
|
303
|
+
if (value === undefined) {
|
|
304
|
+
return []
|
|
305
|
+
}
|
|
300
306
|
|
|
301
|
-
if (!type.includes(coercedType)
|
|
307
|
+
if (!type.includes(coercedType) && !isOnlyPlugin) {
|
|
302
308
|
return []
|
|
303
309
|
}
|
|
304
310
|
|
|
@@ -306,21 +312,14 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
306
312
|
return []
|
|
307
313
|
}
|
|
308
314
|
|
|
309
|
-
let includedRules = []
|
|
310
315
|
let ruleSets = []
|
|
311
|
-
.concat(
|
|
312
|
-
rule(value, {
|
|
313
|
-
includeRules(rules) {
|
|
314
|
-
includedRules.push(...rules)
|
|
315
|
-
},
|
|
316
|
-
})
|
|
317
|
-
)
|
|
316
|
+
.concat(rule(value))
|
|
318
317
|
.filter(Boolean)
|
|
319
318
|
.map((declaration) => ({
|
|
320
319
|
[nameClass(identifier, modifier)]: declaration,
|
|
321
320
|
}))
|
|
322
321
|
|
|
323
|
-
return
|
|
322
|
+
return ruleSets
|
|
324
323
|
}
|
|
325
324
|
|
|
326
325
|
let withOffsets = [{ sort: offset, layer: 'utilities', options }, wrapped]
|
|
@@ -329,6 +328,68 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
329
328
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
330
329
|
}
|
|
331
330
|
|
|
331
|
+
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
matchComponents: function (components, options) {
|
|
335
|
+
let defaultOptions = {
|
|
336
|
+
respectPrefix: true,
|
|
337
|
+
respectImportant: false,
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
options = { ...defaultOptions, ...options }
|
|
341
|
+
|
|
342
|
+
let offset = offsets.components++
|
|
343
|
+
|
|
344
|
+
for (let identifier in components) {
|
|
345
|
+
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
346
|
+
let rule = components[identifier]
|
|
347
|
+
|
|
348
|
+
classList.add([prefixedIdentifier, options])
|
|
349
|
+
|
|
350
|
+
function wrapped(modifier, { isOnlyPlugin }) {
|
|
351
|
+
let { type = 'any' } = options
|
|
352
|
+
type = [].concat(type)
|
|
353
|
+
let [value, coercedType] = coerceValue(type, modifier, options, tailwindConfig)
|
|
354
|
+
|
|
355
|
+
if (value === undefined) {
|
|
356
|
+
return []
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (!type.includes(coercedType)) {
|
|
360
|
+
if (isOnlyPlugin) {
|
|
361
|
+
log.warn([
|
|
362
|
+
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
363
|
+
`You can safely update it to \`${identifier}-${modifier.replace(
|
|
364
|
+
coercedType + ':',
|
|
365
|
+
''
|
|
366
|
+
)}\`.`,
|
|
367
|
+
])
|
|
368
|
+
} else {
|
|
369
|
+
return []
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (!isValidArbitraryValue(value)) {
|
|
374
|
+
return []
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
let ruleSets = []
|
|
378
|
+
.concat(rule(value))
|
|
379
|
+
.filter(Boolean)
|
|
380
|
+
.map((declaration) => ({
|
|
381
|
+
[nameClass(identifier, modifier)]: declaration,
|
|
382
|
+
}))
|
|
383
|
+
|
|
384
|
+
return ruleSets
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
let withOffsets = [{ sort: offset, layer: 'components', options }, wrapped]
|
|
388
|
+
|
|
389
|
+
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
390
|
+
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
391
|
+
}
|
|
392
|
+
|
|
332
393
|
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
|
|
333
394
|
}
|
|
334
395
|
},
|
|
@@ -424,8 +485,8 @@ function collectLayerPlugins(root) {
|
|
|
424
485
|
return layerPlugins
|
|
425
486
|
}
|
|
426
487
|
|
|
427
|
-
function resolvePlugins(context,
|
|
428
|
-
let corePluginList = Object.entries(corePlugins)
|
|
488
|
+
function resolvePlugins(context, root) {
|
|
489
|
+
let corePluginList = Object.entries({ ...variantPlugins, ...corePlugins })
|
|
429
490
|
.map(([name, plugin]) => {
|
|
430
491
|
if (!context.tailwindConfig.corePlugins.includes(name)) {
|
|
431
492
|
return null
|
|
@@ -443,16 +504,21 @@ function resolvePlugins(context, tailwindDirectives, root) {
|
|
|
443
504
|
return typeof plugin === 'function' ? plugin : plugin.handler
|
|
444
505
|
})
|
|
445
506
|
|
|
446
|
-
let layerPlugins = collectLayerPlugins(root
|
|
507
|
+
let layerPlugins = collectLayerPlugins(root)
|
|
447
508
|
|
|
448
509
|
// TODO: This is a workaround for backwards compatibility, since custom variants
|
|
449
510
|
// were historically sorted before screen/stackable variants.
|
|
450
|
-
let beforeVariants = [
|
|
511
|
+
let beforeVariants = [
|
|
512
|
+
variantPlugins['pseudoElementVariants'],
|
|
513
|
+
variantPlugins['pseudoClassVariants'],
|
|
514
|
+
]
|
|
451
515
|
let afterVariants = [
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
516
|
+
variantPlugins['directionVariants'],
|
|
517
|
+
variantPlugins['reducedMotionVariants'],
|
|
518
|
+
variantPlugins['darkVariants'],
|
|
519
|
+
variantPlugins['printVariant'],
|
|
520
|
+
variantPlugins['screenVariants'],
|
|
521
|
+
variantPlugins['orientationVariants'],
|
|
456
522
|
]
|
|
457
523
|
|
|
458
524
|
return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
|
|
@@ -468,10 +534,13 @@ function registerPlugins(plugins, context) {
|
|
|
468
534
|
user: 0n,
|
|
469
535
|
}
|
|
470
536
|
|
|
537
|
+
let classList = new Set()
|
|
538
|
+
|
|
471
539
|
let pluginApi = buildPluginApi(context.tailwindConfig, context, {
|
|
472
540
|
variantList,
|
|
473
541
|
variantMap,
|
|
474
542
|
offsets,
|
|
543
|
+
classList,
|
|
475
544
|
})
|
|
476
545
|
|
|
477
546
|
for (let plugin of plugins) {
|
|
@@ -492,6 +561,10 @@ function registerPlugins(plugins, context) {
|
|
|
492
561
|
])
|
|
493
562
|
let reservedBits = BigInt(highestOffset.toString(2).length)
|
|
494
563
|
|
|
564
|
+
// A number one less than the top range of the highest offset area
|
|
565
|
+
// so arbitrary properties are always sorted at the end.
|
|
566
|
+
context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
|
|
567
|
+
|
|
495
568
|
context.layerOrder = {
|
|
496
569
|
base: (1n << reservedBits) << 0n,
|
|
497
570
|
components: (1n << reservedBits) << 1n,
|
|
@@ -523,14 +596,104 @@ function registerPlugins(plugins, context) {
|
|
|
523
596
|
variantFunctions.map((variantFunction, idx) => [sort << BigInt(idx), variantFunction])
|
|
524
597
|
)
|
|
525
598
|
}
|
|
599
|
+
|
|
600
|
+
let safelist = (context.tailwindConfig.safelist ?? []).filter(Boolean)
|
|
601
|
+
if (safelist.length > 0) {
|
|
602
|
+
let checks = []
|
|
603
|
+
|
|
604
|
+
for (let value of safelist) {
|
|
605
|
+
if (typeof value === 'string') {
|
|
606
|
+
context.changedContent.push({ content: value, extension: 'html' })
|
|
607
|
+
continue
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
if (value instanceof RegExp) {
|
|
611
|
+
log.warn('root-regex', [
|
|
612
|
+
'Regular expressions in `safelist` work differently in Tailwind CSS v3.0.',
|
|
613
|
+
'Update your `safelist` configuration to eliminate this warning.',
|
|
614
|
+
// TODO: Add https://tw.wtf/regex-safelist
|
|
615
|
+
])
|
|
616
|
+
continue
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
checks.push(value)
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (checks.length > 0) {
|
|
623
|
+
let patternMatchingCount = new Map()
|
|
624
|
+
|
|
625
|
+
for (let util of classList) {
|
|
626
|
+
let utils = Array.isArray(util)
|
|
627
|
+
? (() => {
|
|
628
|
+
let [utilName, options] = util
|
|
629
|
+
return Object.keys(options?.values ?? {}).map((value) => formatClass(utilName, value))
|
|
630
|
+
})()
|
|
631
|
+
: [util]
|
|
632
|
+
|
|
633
|
+
for (let util of utils) {
|
|
634
|
+
for (let { pattern, variants = [] } of checks) {
|
|
635
|
+
// RegExp with the /g flag are stateful, so let's reset the last
|
|
636
|
+
// index pointer to reset the state.
|
|
637
|
+
pattern.lastIndex = 0
|
|
638
|
+
|
|
639
|
+
if (!patternMatchingCount.has(pattern)) {
|
|
640
|
+
patternMatchingCount.set(pattern, 0)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
if (!pattern.test(util)) continue
|
|
644
|
+
|
|
645
|
+
patternMatchingCount.set(pattern, patternMatchingCount.get(pattern) + 1)
|
|
646
|
+
|
|
647
|
+
context.changedContent.push({ content: util, extension: 'html' })
|
|
648
|
+
for (let variant of variants) {
|
|
649
|
+
context.changedContent.push({
|
|
650
|
+
content: variant + context.tailwindConfig.separator + util,
|
|
651
|
+
extension: 'html',
|
|
652
|
+
})
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
for (let [regex, count] of patternMatchingCount.entries()) {
|
|
659
|
+
if (count !== 0) continue
|
|
660
|
+
|
|
661
|
+
log.warn([
|
|
662
|
+
`The safelist pattern \`${regex}\` doesn't match any Tailwind CSS classes.`,
|
|
663
|
+
'Fix this pattern or remove it from your `safelist` configuration.',
|
|
664
|
+
])
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Generate a list of strings for autocompletion purposes, e.g.
|
|
670
|
+
// ['uppercase', 'lowercase', ...]
|
|
671
|
+
context.getClassList = function () {
|
|
672
|
+
let output = []
|
|
673
|
+
|
|
674
|
+
for (let util of classList) {
|
|
675
|
+
if (Array.isArray(util)) {
|
|
676
|
+
let [utilName, options] = util
|
|
677
|
+
let negativeClasses = []
|
|
678
|
+
|
|
679
|
+
for (let [key, value] of Object.entries(options?.values ?? {})) {
|
|
680
|
+
output.push(formatClass(utilName, key))
|
|
681
|
+
if (options?.supportsNegativeValues && negateValue(value)) {
|
|
682
|
+
negativeClasses.push(formatClass(utilName, `-${key}`))
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
output.push(...negativeClasses)
|
|
687
|
+
} else {
|
|
688
|
+
output.push(util)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
return output
|
|
693
|
+
}
|
|
526
694
|
}
|
|
527
695
|
|
|
528
|
-
export function createContext(
|
|
529
|
-
tailwindConfig,
|
|
530
|
-
changedContent = [],
|
|
531
|
-
tailwindDirectives = new Set(),
|
|
532
|
-
root = postcss.root()
|
|
533
|
-
) {
|
|
696
|
+
export function createContext(tailwindConfig, changedContent = [], root = postcss.root()) {
|
|
534
697
|
let context = {
|
|
535
698
|
disposables: [],
|
|
536
699
|
ruleCache: new Set(),
|
|
@@ -545,7 +708,7 @@ export function createContext(
|
|
|
545
708
|
stylesheetCache: null,
|
|
546
709
|
}
|
|
547
710
|
|
|
548
|
-
let resolvedPlugins = resolvePlugins(context,
|
|
711
|
+
let resolvedPlugins = resolvePlugins(context, root)
|
|
549
712
|
registerPlugins(resolvedPlugins, context)
|
|
550
713
|
|
|
551
714
|
return context
|
|
@@ -556,7 +719,6 @@ let configContextMap = sharedState.configContextMap
|
|
|
556
719
|
let contextSourcesMap = sharedState.contextSourcesMap
|
|
557
720
|
|
|
558
721
|
export function getContext(
|
|
559
|
-
tailwindDirectives,
|
|
560
722
|
root,
|
|
561
723
|
result,
|
|
562
724
|
tailwindConfig,
|
|
@@ -618,7 +780,7 @@ export function getContext(
|
|
|
618
780
|
|
|
619
781
|
env.DEBUG && console.log('Setting up new context...')
|
|
620
782
|
|
|
621
|
-
let context = createContext(tailwindConfig, [],
|
|
783
|
+
let context = createContext(tailwindConfig, [], root)
|
|
622
784
|
|
|
623
785
|
trackModified([...contextDependencies], getFileModifiedMap(context))
|
|
624
786
|
|
|
@@ -8,7 +8,7 @@ import normalizePath from 'normalize-path'
|
|
|
8
8
|
import hash from '../util/hashConfig'
|
|
9
9
|
import getModuleDependencies from '../lib/getModuleDependencies'
|
|
10
10
|
|
|
11
|
-
import resolveConfig from '
|
|
11
|
+
import resolveConfig from '../public/resolve-config'
|
|
12
12
|
|
|
13
13
|
import resolveConfigPath from '../util/resolveConfigPath'
|
|
14
14
|
|
|
@@ -26,9 +26,9 @@ function getCandidateFiles(context, tailwindConfig) {
|
|
|
26
26
|
return candidateFilesCache.get(context)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
let candidateFiles = tailwindConfig.content.
|
|
29
|
+
let candidateFiles = tailwindConfig.content.files
|
|
30
30
|
.filter((item) => typeof item === 'string')
|
|
31
|
-
.map((contentPath) => normalizePath(
|
|
31
|
+
.map((contentPath) => normalizePath(contentPath))
|
|
32
32
|
|
|
33
33
|
return candidateFilesCache.set(context, candidateFiles).get(context)
|
|
34
34
|
}
|
|
@@ -77,10 +77,9 @@ function getTailwindConfig(configOrPath) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
|
|
80
|
-
let changedContent = context.tailwindConfig.content.
|
|
80
|
+
let changedContent = context.tailwindConfig.content.files
|
|
81
81
|
.filter((item) => typeof item.raw === 'string')
|
|
82
|
-
.
|
|
83
|
-
.map(({ raw, extension }) => ({ content: raw, extension }))
|
|
82
|
+
.map(({ raw, extension = 'html' }) => ({ content: raw, extension }))
|
|
84
83
|
|
|
85
84
|
for (let changedFile of resolveChangedFiles(candidateFiles, fileModifiedMap)) {
|
|
86
85
|
let content = fs.readFileSync(changedFile, 'utf8')
|
|
@@ -138,7 +137,6 @@ export default function setupTrackingContext(configOrPath) {
|
|
|
138
137
|
}
|
|
139
138
|
|
|
140
139
|
let [context] = getContext(
|
|
141
|
-
tailwindDirectives,
|
|
142
140
|
root,
|
|
143
141
|
result,
|
|
144
142
|
tailwindConfig,
|
|
@@ -159,7 +157,10 @@ export default function setupTrackingContext(configOrPath) {
|
|
|
159
157
|
|
|
160
158
|
// Add template paths as postcss dependencies.
|
|
161
159
|
for (let fileOrGlob of candidateFiles) {
|
|
162
|
-
|
|
160
|
+
let dependency = parseDependency(fileOrGlob)
|
|
161
|
+
if (dependency) {
|
|
162
|
+
registerDependency(dependency)
|
|
163
|
+
}
|
|
163
164
|
}
|
|
164
165
|
|
|
165
166
|
for (let changedContent of resolvedChangedContent(
|