tailwindcss 0.0.0-insiders.bd4dddd → 0.0.0-insiders.bda8421
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/LICENSE +1 -2
- package/README.md +13 -10
- package/colors.d.ts +3 -0
- package/defaultConfig.d.ts +3 -0
- package/defaultTheme.d.ts +4 -0
- package/lib/cli/build/deps.js +62 -0
- package/lib/cli/build/index.js +54 -0
- package/lib/cli/build/plugin.js +371 -0
- package/lib/cli/build/utils.js +88 -0
- package/lib/cli/build/watching.js +182 -0
- package/lib/cli/help/index.js +73 -0
- package/lib/cli/index.js +230 -0
- package/lib/cli/init/index.js +63 -0
- package/lib/cli-peer-dependencies.js +28 -7
- package/lib/cli.js +1 -741
- package/lib/corePluginList.js +17 -4
- package/lib/corePlugins.js +2503 -1839
- package/lib/css/preflight.css +32 -13
- package/lib/featureFlags.js +45 -28
- package/lib/index.js +1 -29
- package/lib/lib/cacheInvalidation.js +92 -0
- package/lib/lib/collapseAdjacentRules.js +30 -10
- package/lib/lib/collapseDuplicateDeclarations.js +13 -8
- package/lib/lib/content.js +214 -0
- package/lib/lib/defaultExtractor.js +240 -31
- package/lib/lib/evaluateTailwindFunctions.js +117 -50
- package/lib/lib/expandApplyAtRules.js +466 -230
- package/lib/lib/expandTailwindAtRules.js +156 -135
- package/lib/lib/findAtConfigPath.js +46 -0
- package/lib/lib/generateRules.js +554 -200
- package/lib/lib/getModuleDependencies.js +88 -37
- package/lib/lib/load-config.js +57 -0
- package/lib/lib/normalizeTailwindDirectives.js +39 -33
- package/lib/lib/offsets.js +355 -0
- package/lib/lib/partitionApplyAtRules.js +58 -0
- package/lib/lib/regex.js +74 -0
- package/lib/lib/remap-bitfield.js +89 -0
- package/lib/lib/resolveDefaultsAtRules.js +97 -69
- package/lib/lib/setupContextUtils.js +796 -341
- package/lib/lib/setupTrackingContext.js +66 -71
- package/lib/lib/sharedState.js +45 -14
- package/lib/lib/substituteScreenAtRules.js +14 -10
- package/lib/plugin.js +48 -0
- package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
- package/lib/postcss-plugins/nesting/index.js +21 -0
- package/lib/postcss-plugins/nesting/plugin.js +89 -0
- package/lib/processTailwindFeatures.js +37 -27
- package/lib/public/colors.js +272 -246
- package/lib/public/create-plugin.js +9 -5
- package/lib/public/default-config.js +10 -6
- package/lib/public/default-theme.js +10 -6
- package/lib/public/load-config.js +12 -0
- package/lib/public/resolve-config.js +11 -6
- package/lib/util/applyImportantSelector.js +36 -0
- package/lib/util/bigSign.js +6 -1
- package/lib/util/buildMediaQuery.js +13 -6
- package/lib/util/cloneDeep.js +9 -6
- package/lib/util/cloneNodes.js +44 -4
- package/lib/util/color.js +70 -53
- package/lib/util/colorNames.js +752 -0
- package/lib/util/configurePlugins.js +7 -2
- package/lib/util/createPlugin.js +8 -6
- package/lib/util/createUtilityPlugin.js +16 -16
- package/lib/util/dataTypes.js +295 -113
- package/lib/util/defaults.js +12 -7
- package/lib/util/escapeClassName.js +13 -8
- package/lib/util/escapeCommas.js +7 -2
- package/lib/util/flattenColorPalette.js +11 -12
- package/lib/util/formatVariantSelector.js +235 -151
- package/lib/util/getAllConfigs.js +33 -12
- package/lib/util/hashConfig.js +9 -4
- package/lib/util/isKeyframeRule.js +7 -2
- package/lib/util/isPlainObject.js +8 -3
- package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +25 -15
- package/lib/util/log.js +25 -15
- package/lib/util/nameClass.js +27 -10
- package/lib/util/negateValue.js +25 -8
- package/lib/util/normalizeConfig.js +127 -82
- package/lib/util/normalizeScreens.js +128 -11
- package/lib/util/parseAnimationValue.js +44 -40
- package/lib/util/parseBoxShadowValue.js +34 -23
- package/lib/util/parseDependency.js +39 -55
- package/lib/util/parseGlob.js +36 -0
- package/lib/util/parseObjectStyles.js +15 -10
- package/lib/util/pluginUtils.js +172 -69
- package/lib/util/prefixSelector.js +30 -12
- package/lib/util/pseudoElements.js +212 -0
- package/lib/util/removeAlphaVariables.js +31 -0
- package/lib/util/resolveConfig.js +101 -87
- package/lib/util/resolveConfigPath.js +30 -12
- package/lib/util/responsive.js +11 -6
- package/lib/util/splitAtTopLevelOnly.js +51 -0
- package/lib/util/tap.js +6 -1
- package/lib/util/toColorValue.js +7 -3
- package/lib/util/toPath.js +22 -4
- package/lib/util/transformThemeValue.js +40 -30
- package/lib/util/validateConfig.js +37 -0
- package/lib/util/validateFormalSyntax.js +26 -0
- package/lib/util/withAlphaVariable.js +27 -15
- package/lib/value-parser/LICENSE +22 -0
- package/lib/value-parser/README.md +3 -0
- package/lib/value-parser/index.d.js +2 -0
- package/lib/value-parser/index.js +22 -0
- package/lib/value-parser/parse.js +259 -0
- package/lib/value-parser/stringify.js +38 -0
- package/lib/value-parser/unit.js +86 -0
- package/lib/value-parser/walk.js +16 -0
- package/loadConfig.d.ts +4 -0
- package/loadConfig.js +2 -0
- package/nesting/index.d.ts +4 -0
- package/nesting/index.js +2 -12
- package/package.json +60 -55
- package/peers/index.js +75503 -55095
- package/plugin.d.ts +11 -0
- package/resolveConfig.d.ts +31 -0
- package/scripts/generate-types.js +104 -0
- package/scripts/release-channel.js +18 -0
- package/scripts/release-notes.js +21 -0
- package/scripts/type-utils.js +27 -0
- package/src/cli/build/deps.js +56 -0
- package/src/cli/build/index.js +49 -0
- package/src/cli/build/plugin.js +437 -0
- package/src/cli/build/utils.js +76 -0
- package/src/cli/build/watching.js +229 -0
- package/src/cli/help/index.js +70 -0
- package/src/cli/index.js +216 -0
- package/src/cli/init/index.js +79 -0
- package/src/cli-peer-dependencies.js +7 -1
- package/src/cli.js +1 -811
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +849 -243
- package/src/css/preflight.css +32 -13
- package/src/featureFlags.js +13 -9
- package/src/index.js +1 -28
- package/src/lib/cacheInvalidation.js +52 -0
- package/src/lib/collapseAdjacentRules.js +21 -2
- package/src/lib/content.js +249 -0
- package/src/lib/defaultExtractor.js +215 -33
- package/src/lib/evaluateTailwindFunctions.js +82 -8
- package/src/lib/expandApplyAtRules.js +512 -224
- package/src/lib/expandTailwindAtRules.js +102 -87
- package/src/lib/findAtConfigPath.js +48 -0
- package/src/lib/generateRules.js +541 -146
- package/src/lib/getModuleDependencies.js +70 -30
- package/src/lib/load-config.ts +44 -0
- package/src/lib/normalizeTailwindDirectives.js +1 -0
- package/src/lib/offsets.js +432 -0
- package/src/lib/partitionApplyAtRules.js +52 -0
- package/src/lib/regex.js +74 -0
- package/src/lib/remap-bitfield.js +82 -0
- package/src/lib/resolveDefaultsAtRules.js +55 -30
- package/src/lib/setupContextUtils.js +720 -190
- package/src/lib/setupTrackingContext.js +47 -61
- package/src/lib/sharedState.js +15 -4
- package/src/plugin.js +47 -0
- package/src/postcss-plugins/nesting/README.md +42 -0
- package/src/postcss-plugins/nesting/index.js +13 -0
- package/src/postcss-plugins/nesting/plugin.js +80 -0
- package/src/processTailwindFeatures.js +11 -4
- package/src/public/colors.js +22 -0
- package/src/public/default-config.js +1 -1
- package/src/public/default-theme.js +2 -2
- package/src/public/load-config.js +2 -0
- package/src/util/applyImportantSelector.js +27 -0
- package/src/util/buildMediaQuery.js +5 -3
- package/src/util/cloneNodes.js +40 -2
- package/src/util/color.js +39 -20
- package/src/util/colorNames.js +150 -0
- package/src/util/dataTypes.js +184 -26
- package/src/util/formatVariantSelector.js +272 -144
- package/src/util/getAllConfigs.js +21 -2
- package/src/util/isPlainObject.js +1 -1
- package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
- package/src/util/log.js +8 -8
- package/src/util/nameClass.js +4 -0
- package/src/util/negateValue.js +11 -3
- package/src/util/normalizeConfig.js +45 -6
- package/src/util/normalizeScreens.js +99 -4
- package/src/util/parseBoxShadowValue.js +4 -3
- package/src/util/parseDependency.js +37 -42
- package/src/util/parseGlob.js +24 -0
- package/src/util/pluginUtils.js +139 -24
- package/src/util/prefixSelector.js +31 -10
- package/src/util/pseudoElements.js +171 -0
- package/src/util/removeAlphaVariables.js +24 -0
- package/src/util/resolveConfig.js +70 -32
- package/src/util/resolveConfigPath.js +12 -1
- package/src/util/splitAtTopLevelOnly.js +52 -0
- package/src/util/toPath.js +1 -1
- package/src/util/transformThemeValue.js +13 -3
- package/src/util/validateConfig.js +26 -0
- package/src/util/validateFormalSyntax.js +34 -0
- package/src/util/withAlphaVariable.js +1 -1
- package/src/value-parser/LICENSE +22 -0
- package/src/value-parser/README.md +3 -0
- package/src/value-parser/index.d.ts +177 -0
- package/src/value-parser/index.js +28 -0
- package/src/value-parser/parse.js +303 -0
- package/src/value-parser/stringify.js +41 -0
- package/src/value-parser/unit.js +118 -0
- package/src/value-parser/walk.js +18 -0
- package/stubs/.gitignore +1 -0
- package/stubs/.prettierrc.json +6 -0
- package/stubs/{defaultConfig.stub.js → config.full.js} +290 -178
- package/stubs/postcss.config.js +6 -0
- package/stubs/tailwind.config.cjs +2 -0
- package/stubs/tailwind.config.js +2 -0
- package/stubs/tailwind.config.ts +3 -0
- package/types/config.d.ts +376 -0
- package/types/generated/.gitkeep +0 -0
- package/types/generated/colors.d.ts +298 -0
- package/types/generated/corePluginList.d.ts +1 -0
- package/types/generated/default-theme.d.ts +397 -0
- package/types/index.d.ts +11 -0
- package/CHANGELOG.md +0 -1959
- package/lib/constants.js +0 -37
- package/lib/lib/detectNesting.js +0 -34
- package/nesting/plugin.js +0 -41
- package/scripts/install-integrations.js +0 -27
- package/scripts/rebuildFixtures.js +0 -68
- package/src/constants.js +0 -17
- package/src/lib/detectNesting.js +0 -39
- /package/stubs/{simpleConfig.stub.js → config.simple.js} +0 -0
- /package/stubs/{defaultPostCssConfig.stub.js → postcss.config.cjs} +0 -0
|
@@ -11,42 +11,95 @@ import isPlainObject from '../util/isPlainObject'
|
|
|
11
11
|
import escapeClassName from '../util/escapeClassName'
|
|
12
12
|
import nameClass, { formatClass } from '../util/nameClass'
|
|
13
13
|
import { coerceValue } from '../util/pluginUtils'
|
|
14
|
-
import bigSign from '../util/bigSign'
|
|
15
14
|
import { variantPlugins, corePlugins } from '../corePlugins'
|
|
16
15
|
import * as sharedState from './sharedState'
|
|
17
16
|
import { env } from './sharedState'
|
|
18
17
|
import { toPath } from '../util/toPath'
|
|
19
18
|
import log from '../util/log'
|
|
20
19
|
import negateValue from '../util/negateValue'
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
import isSyntacticallyValidPropertyValue from '../util/isSyntacticallyValidPropertyValue'
|
|
21
|
+
import { generateRules, getClassNameFromSelector } from './generateRules'
|
|
22
|
+
import { hasContentChanged } from './cacheInvalidation.js'
|
|
23
|
+
import { Offsets } from './offsets.js'
|
|
24
|
+
import { flagEnabled } from '../featureFlags.js'
|
|
25
|
+
import { finalizeSelector, formatVariantSelector } from '../util/formatVariantSelector'
|
|
26
|
+
|
|
27
|
+
export const INTERNAL_FEATURES = Symbol()
|
|
28
|
+
|
|
29
|
+
const VARIANT_TYPES = {
|
|
30
|
+
AddVariant: Symbol.for('ADD_VARIANT'),
|
|
31
|
+
MatchVariant: Symbol.for('MATCH_VARIANT'),
|
|
32
|
+
}
|
|
26
33
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
34
|
+
const VARIANT_INFO = {
|
|
35
|
+
Base: 1 << 0,
|
|
36
|
+
Dynamic: 1 << 1,
|
|
37
|
+
}
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
function prefix(context, selector) {
|
|
40
|
+
let prefix = context.tailwindConfig.prefix
|
|
41
|
+
return typeof prefix === 'function' ? prefix(selector) : prefix + selector
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
function
|
|
37
|
-
let
|
|
44
|
+
function normalizeOptionTypes({ type = 'any', ...options }) {
|
|
45
|
+
let types = [].concat(type)
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...options,
|
|
49
|
+
types: types.map((type) => {
|
|
50
|
+
if (Array.isArray(type)) {
|
|
51
|
+
return { type: type[0], ...type[1] }
|
|
52
|
+
}
|
|
53
|
+
return { type, preferOnConflict: false }
|
|
54
|
+
}),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
38
57
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
function parseVariantFormatString(input) {
|
|
59
|
+
/** @type {string[]} */
|
|
60
|
+
let parts = []
|
|
61
|
+
|
|
62
|
+
// When parsing whitespace around special characters are insignificant
|
|
63
|
+
// However, _inside_ of a variant they could be
|
|
64
|
+
// Because the selector could look like this
|
|
65
|
+
// @media { &[data-name="foo bar"] }
|
|
66
|
+
// This is why we do not skip whitespace
|
|
67
|
+
|
|
68
|
+
let current = ''
|
|
69
|
+
let depth = 0
|
|
70
|
+
|
|
71
|
+
for (let idx = 0; idx < input.length; idx++) {
|
|
72
|
+
let char = input[idx]
|
|
73
|
+
|
|
74
|
+
if (char === '\\') {
|
|
75
|
+
// Escaped characters are not special
|
|
76
|
+
current += '\\' + input[++idx]
|
|
77
|
+
} else if (char === '{') {
|
|
78
|
+
// Nested rule: start
|
|
79
|
+
++depth
|
|
80
|
+
parts.push(current.trim())
|
|
81
|
+
current = ''
|
|
42
82
|
} else if (char === '}') {
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
// Nested rule: end
|
|
84
|
+
if (--depth < 0) {
|
|
85
|
+
throw new Error(`Your { and } are unbalanced.`)
|
|
45
86
|
}
|
|
87
|
+
|
|
88
|
+
parts.push(current.trim())
|
|
89
|
+
current = ''
|
|
90
|
+
} else {
|
|
91
|
+
// Normal character
|
|
92
|
+
current += char
|
|
46
93
|
}
|
|
47
94
|
}
|
|
48
95
|
|
|
49
|
-
|
|
96
|
+
if (current.length > 0) {
|
|
97
|
+
parts.push(current.trim())
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
parts = parts.filter((part) => part !== '')
|
|
101
|
+
|
|
102
|
+
return parts
|
|
50
103
|
}
|
|
51
104
|
|
|
52
105
|
function insertInto(list, value, { before = [] } = {}) {
|
|
@@ -78,35 +131,66 @@ function parseStyles(styles) {
|
|
|
78
131
|
})
|
|
79
132
|
}
|
|
80
133
|
|
|
81
|
-
function getClasses(selector) {
|
|
134
|
+
function getClasses(selector, mutate) {
|
|
82
135
|
let parser = selectorParser((selectors) => {
|
|
83
136
|
let allClasses = []
|
|
137
|
+
|
|
138
|
+
if (mutate) {
|
|
139
|
+
mutate(selectors)
|
|
140
|
+
}
|
|
141
|
+
|
|
84
142
|
selectors.walkClasses((classNode) => {
|
|
85
143
|
allClasses.push(classNode.value)
|
|
86
144
|
})
|
|
145
|
+
|
|
87
146
|
return allClasses
|
|
88
147
|
})
|
|
89
148
|
return parser.transformSync(selector)
|
|
90
149
|
}
|
|
91
150
|
|
|
92
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Ignore everything inside a :not(...). This allows you to write code like
|
|
153
|
+
* `div:not(.foo)`. If `.foo` is never found in your code, then we used to
|
|
154
|
+
* not generated it. But now we will ignore everything inside a `:not`, so
|
|
155
|
+
* that it still gets generated.
|
|
156
|
+
*
|
|
157
|
+
* @param {selectorParser.Root} selectors
|
|
158
|
+
*/
|
|
159
|
+
function ignoreNot(selectors) {
|
|
160
|
+
selectors.walkPseudos((pseudo) => {
|
|
161
|
+
if (pseudo.value === ':not') {
|
|
162
|
+
pseudo.remove()
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function extractCandidates(node, state = { containsNonOnDemandable: false }, depth = 0) {
|
|
93
168
|
let classes = []
|
|
169
|
+
let selectors = []
|
|
94
170
|
|
|
95
171
|
if (node.type === 'rule') {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
172
|
+
// Handle normal rules
|
|
173
|
+
selectors.push(...node.selectors)
|
|
174
|
+
} else if (node.type === 'atrule') {
|
|
175
|
+
// Handle at-rules (which contains nested rules)
|
|
176
|
+
node.walkRules((rule) => selectors.push(...rule.selectors))
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (let selector of selectors) {
|
|
180
|
+
let classCandidates = getClasses(selector, ignoreNot)
|
|
100
181
|
|
|
101
|
-
|
|
182
|
+
// At least one of the selectors contains non-"on-demandable" candidates.
|
|
183
|
+
if (classCandidates.length === 0) {
|
|
184
|
+
state.containsNonOnDemandable = true
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
for (let classCandidate of classCandidates) {
|
|
188
|
+
classes.push(classCandidate)
|
|
102
189
|
}
|
|
103
|
-
return classes
|
|
104
190
|
}
|
|
105
191
|
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
classes = [...classes, ...rule.selectors.flatMap((selector) => getClasses(selector))]
|
|
109
|
-
})
|
|
192
|
+
if (depth === 0) {
|
|
193
|
+
return [state.containsNonOnDemandable || classes.length === 0, classes]
|
|
110
194
|
}
|
|
111
195
|
|
|
112
196
|
return classes
|
|
@@ -115,13 +199,16 @@ function extractCandidates(node) {
|
|
|
115
199
|
function withIdentifiers(styles) {
|
|
116
200
|
return parseStyles(styles).flatMap((node) => {
|
|
117
201
|
let nodeMap = new Map()
|
|
118
|
-
let candidates = extractCandidates(node)
|
|
202
|
+
let [containsNonOnDemandableSelectors, candidates] = extractCandidates(node)
|
|
119
203
|
|
|
120
|
-
// If this isn't "on-demandable", assign it a universal candidate.
|
|
121
|
-
if (
|
|
122
|
-
|
|
204
|
+
// If this isn't "on-demandable", assign it a universal candidate to always include it.
|
|
205
|
+
if (containsNonOnDemandableSelectors) {
|
|
206
|
+
candidates.unshift(sharedState.NOT_ON_DEMAND)
|
|
123
207
|
}
|
|
124
208
|
|
|
209
|
+
// However, it could be that it also contains "on-demandable" candidates.
|
|
210
|
+
// E.g.: `span, .foo {}`, in that case it should still be possible to use
|
|
211
|
+
// `@apply foo` for example.
|
|
125
212
|
return candidates.map((c) => {
|
|
126
213
|
if (!nodeMap.has(node)) {
|
|
127
214
|
nodeMap.set(node, node)
|
|
@@ -131,6 +218,41 @@ function withIdentifiers(styles) {
|
|
|
131
218
|
})
|
|
132
219
|
}
|
|
133
220
|
|
|
221
|
+
export function isValidVariantFormatString(format) {
|
|
222
|
+
return format.startsWith('@') || format.includes('&')
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function parseVariant(variant) {
|
|
226
|
+
variant = variant
|
|
227
|
+
.replace(/\n+/g, '')
|
|
228
|
+
.replace(/\s{1,}/g, ' ')
|
|
229
|
+
.trim()
|
|
230
|
+
|
|
231
|
+
let fns = parseVariantFormatString(variant)
|
|
232
|
+
.map((str) => {
|
|
233
|
+
if (!str.startsWith('@')) {
|
|
234
|
+
return ({ format }) => format(str)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let [, name, params] = /@(\S*)( .+|[({].*)?/g.exec(str)
|
|
238
|
+
return ({ wrap }) => wrap(postcss.atRule({ name, params: params?.trim() ?? '' }))
|
|
239
|
+
})
|
|
240
|
+
.reverse()
|
|
241
|
+
|
|
242
|
+
return (api) => {
|
|
243
|
+
for (let fn of fns) {
|
|
244
|
+
fn(api)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
*
|
|
251
|
+
* @param {any} tailwindConfig
|
|
252
|
+
* @param {any} context
|
|
253
|
+
* @param {object} param2
|
|
254
|
+
* @param {Offsets} param2.offsets
|
|
255
|
+
*/
|
|
134
256
|
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {
|
|
135
257
|
function getConfigValue(path, defaultValue) {
|
|
136
258
|
return path ? dlv(tailwindConfig, path, defaultValue) : tailwindConfig
|
|
@@ -141,8 +263,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
141
263
|
}
|
|
142
264
|
|
|
143
265
|
function prefixIdentifier(identifier, options) {
|
|
144
|
-
if (identifier ===
|
|
145
|
-
return
|
|
266
|
+
if (identifier === sharedState.NOT_ON_DEMAND) {
|
|
267
|
+
return sharedState.NOT_ON_DEMAND
|
|
146
268
|
}
|
|
147
269
|
|
|
148
270
|
if (!options.respectPrefix) {
|
|
@@ -152,51 +274,19 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
152
274
|
return context.tailwindConfig.prefix + identifier
|
|
153
275
|
}
|
|
154
276
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
})
|
|
277
|
+
function resolveThemeValue(path, defaultValue, opts = {}) {
|
|
278
|
+
let parts = toPath(path)
|
|
279
|
+
let value = getConfigValue(['theme', ...parts], defaultValue)
|
|
280
|
+
return transformThemeValue(parts[0])(value, opts)
|
|
281
|
+
}
|
|
187
282
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
283
|
+
let variantIdentifier = 0
|
|
284
|
+
let api = {
|
|
191
285
|
postcss,
|
|
192
286
|
prefix: applyConfiguredPrefix,
|
|
193
287
|
e: escapeClassName,
|
|
194
288
|
config: getConfigValue,
|
|
195
|
-
theme
|
|
196
|
-
const [pathRoot, ...subPaths] = toPath(path)
|
|
197
|
-
const value = getConfigValue(['theme', pathRoot, ...subPaths], defaultValue)
|
|
198
|
-
return transformThemeValue(pathRoot)(value)
|
|
199
|
-
},
|
|
289
|
+
theme: resolveThemeValue,
|
|
200
290
|
corePlugins: (path) => {
|
|
201
291
|
if (Array.isArray(tailwindConfig.corePlugins)) {
|
|
202
292
|
return tailwindConfig.corePlugins.includes(path)
|
|
@@ -208,21 +298,10 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
208
298
|
// Preserved for backwards compatibility but not used in v3.0+
|
|
209
299
|
return []
|
|
210
300
|
},
|
|
211
|
-
addUserCss(userCss) {
|
|
212
|
-
for (let [identifier, rule] of withIdentifiers(userCss)) {
|
|
213
|
-
let offset = offsets.user++
|
|
214
|
-
|
|
215
|
-
if (!context.candidateRuleMap.has(identifier)) {
|
|
216
|
-
context.candidateRuleMap.set(identifier, [])
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
context.candidateRuleMap.get(identifier).push([{ sort: offset, layer: 'user' }, rule])
|
|
220
|
-
}
|
|
221
|
-
},
|
|
222
301
|
addBase(base) {
|
|
223
302
|
for (let [identifier, rule] of withIdentifiers(base)) {
|
|
224
303
|
let prefixedIdentifier = prefixIdentifier(identifier, {})
|
|
225
|
-
let offset = offsets.base
|
|
304
|
+
let offset = offsets.create('base')
|
|
226
305
|
|
|
227
306
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
228
307
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
@@ -244,7 +323,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
244
323
|
|
|
245
324
|
for (let [identifier, rule] of withIdentifiers(groups)) {
|
|
246
325
|
let prefixedIdentifier = prefixIdentifier(identifier, {})
|
|
247
|
-
let offset = offsets.base++
|
|
248
326
|
|
|
249
327
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
250
328
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
@@ -252,11 +330,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
252
330
|
|
|
253
331
|
context.candidateRuleMap
|
|
254
332
|
.get(prefixedIdentifier)
|
|
255
|
-
.push([{ sort:
|
|
333
|
+
.push([{ sort: offsets.create('defaults'), layer: 'defaults' }, rule])
|
|
256
334
|
}
|
|
257
335
|
},
|
|
258
336
|
addComponents(components, options) {
|
|
259
337
|
let defaultOptions = {
|
|
338
|
+
preserveSource: false,
|
|
260
339
|
respectPrefix: true,
|
|
261
340
|
respectImportant: false,
|
|
262
341
|
}
|
|
@@ -265,7 +344,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
265
344
|
|
|
266
345
|
for (let [identifier, rule] of withIdentifiers(components)) {
|
|
267
346
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
268
|
-
let offset = offsets.components++
|
|
269
347
|
|
|
270
348
|
classList.add(prefixedIdentifier)
|
|
271
349
|
|
|
@@ -275,11 +353,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
275
353
|
|
|
276
354
|
context.candidateRuleMap
|
|
277
355
|
.get(prefixedIdentifier)
|
|
278
|
-
.push([{ sort:
|
|
356
|
+
.push([{ sort: offsets.create('components'), layer: 'components', options }, rule])
|
|
279
357
|
}
|
|
280
358
|
},
|
|
281
359
|
addUtilities(utilities, options) {
|
|
282
360
|
let defaultOptions = {
|
|
361
|
+
preserveSource: false,
|
|
283
362
|
respectPrefix: true,
|
|
284
363
|
respectImportant: true,
|
|
285
364
|
}
|
|
@@ -288,7 +367,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
288
367
|
|
|
289
368
|
for (let [identifier, rule] of withIdentifiers(utilities)) {
|
|
290
369
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
291
|
-
let offset = offsets.utilities++
|
|
292
370
|
|
|
293
371
|
classList.add(prefixedIdentifier)
|
|
294
372
|
|
|
@@ -298,18 +376,19 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
298
376
|
|
|
299
377
|
context.candidateRuleMap
|
|
300
378
|
.get(prefixedIdentifier)
|
|
301
|
-
.push([{ sort:
|
|
379
|
+
.push([{ sort: offsets.create('utilities'), layer: 'utilities', options }, rule])
|
|
302
380
|
}
|
|
303
381
|
},
|
|
304
382
|
matchUtilities: function (utilities, options) {
|
|
305
383
|
let defaultOptions = {
|
|
306
384
|
respectPrefix: true,
|
|
307
385
|
respectImportant: true,
|
|
386
|
+
modifiers: false,
|
|
308
387
|
}
|
|
309
388
|
|
|
310
|
-
options = { ...defaultOptions, ...options }
|
|
389
|
+
options = normalizeOptionTypes({ ...defaultOptions, ...options })
|
|
311
390
|
|
|
312
|
-
let offset = offsets.utilities
|
|
391
|
+
let offset = offsets.create('utilities')
|
|
313
392
|
|
|
314
393
|
for (let identifier in utilities) {
|
|
315
394
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
@@ -318,24 +397,51 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
318
397
|
classList.add([prefixedIdentifier, options])
|
|
319
398
|
|
|
320
399
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
321
|
-
let
|
|
322
|
-
|
|
323
|
-
|
|
400
|
+
let [value, coercedType, utilityModifier] = coerceValue(
|
|
401
|
+
options.types,
|
|
402
|
+
modifier,
|
|
403
|
+
options,
|
|
404
|
+
tailwindConfig
|
|
405
|
+
)
|
|
324
406
|
|
|
325
407
|
if (value === undefined) {
|
|
326
408
|
return []
|
|
327
409
|
}
|
|
328
410
|
|
|
329
|
-
if (!
|
|
330
|
-
|
|
411
|
+
if (!options.types.some(({ type }) => type === coercedType)) {
|
|
412
|
+
if (isOnlyPlugin) {
|
|
413
|
+
log.warn([
|
|
414
|
+
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
415
|
+
`You can safely update it to \`${identifier}-${modifier.replace(
|
|
416
|
+
coercedType + ':',
|
|
417
|
+
''
|
|
418
|
+
)}\`.`,
|
|
419
|
+
])
|
|
420
|
+
} else {
|
|
421
|
+
return []
|
|
422
|
+
}
|
|
331
423
|
}
|
|
332
424
|
|
|
333
|
-
if (!
|
|
425
|
+
if (!isSyntacticallyValidPropertyValue(value)) {
|
|
334
426
|
return []
|
|
335
427
|
}
|
|
336
428
|
|
|
429
|
+
let extras = {
|
|
430
|
+
get modifier() {
|
|
431
|
+
if (!options.modifiers) {
|
|
432
|
+
log.warn(`modifier-used-without-options-for-${identifier}`, [
|
|
433
|
+
'Your plugin must set `modifiers: true` in its options to support modifiers.',
|
|
434
|
+
])
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
return utilityModifier
|
|
438
|
+
},
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
442
|
+
|
|
337
443
|
let ruleSets = []
|
|
338
|
-
.concat(rule(value))
|
|
444
|
+
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
|
|
339
445
|
.filter(Boolean)
|
|
340
446
|
.map((declaration) => ({
|
|
341
447
|
[nameClass(identifier, modifier)]: declaration,
|
|
@@ -357,11 +463,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
357
463
|
let defaultOptions = {
|
|
358
464
|
respectPrefix: true,
|
|
359
465
|
respectImportant: false,
|
|
466
|
+
modifiers: false,
|
|
360
467
|
}
|
|
361
468
|
|
|
362
|
-
options = { ...defaultOptions, ...options }
|
|
469
|
+
options = normalizeOptionTypes({ ...defaultOptions, ...options })
|
|
363
470
|
|
|
364
|
-
let offset = offsets.components
|
|
471
|
+
let offset = offsets.create('components')
|
|
365
472
|
|
|
366
473
|
for (let identifier in components) {
|
|
367
474
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
@@ -370,15 +477,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
370
477
|
classList.add([prefixedIdentifier, options])
|
|
371
478
|
|
|
372
479
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
373
|
-
let
|
|
374
|
-
|
|
375
|
-
|
|
480
|
+
let [value, coercedType, utilityModifier] = coerceValue(
|
|
481
|
+
options.types,
|
|
482
|
+
modifier,
|
|
483
|
+
options,
|
|
484
|
+
tailwindConfig
|
|
485
|
+
)
|
|
376
486
|
|
|
377
487
|
if (value === undefined) {
|
|
378
488
|
return []
|
|
379
489
|
}
|
|
380
490
|
|
|
381
|
-
if (!
|
|
491
|
+
if (!options.types.some(({ type }) => type === coercedType)) {
|
|
382
492
|
if (isOnlyPlugin) {
|
|
383
493
|
log.warn([
|
|
384
494
|
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
@@ -392,12 +502,26 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
392
502
|
}
|
|
393
503
|
}
|
|
394
504
|
|
|
395
|
-
if (!
|
|
505
|
+
if (!isSyntacticallyValidPropertyValue(value)) {
|
|
396
506
|
return []
|
|
397
507
|
}
|
|
398
508
|
|
|
509
|
+
let extras = {
|
|
510
|
+
get modifier() {
|
|
511
|
+
if (!options.modifiers) {
|
|
512
|
+
log.warn(`modifier-used-without-options-for-${identifier}`, [
|
|
513
|
+
'Your plugin must set `modifiers: true` in its options to support modifiers.',
|
|
514
|
+
])
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return utilityModifier
|
|
518
|
+
},
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
522
|
+
|
|
399
523
|
let ruleSets = []
|
|
400
|
-
.concat(rule(value))
|
|
524
|
+
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
|
|
401
525
|
.filter(Boolean)
|
|
402
526
|
.map((declaration) => ({
|
|
403
527
|
[nameClass(identifier, modifier)]: declaration,
|
|
@@ -415,7 +539,109 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
415
539
|
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
|
|
416
540
|
}
|
|
417
541
|
},
|
|
542
|
+
addVariant(variantName, variantFunctions, options = {}) {
|
|
543
|
+
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
|
|
544
|
+
if (typeof variantFunction !== 'string') {
|
|
545
|
+
// Safelist public API functions
|
|
546
|
+
return (api = {}) => {
|
|
547
|
+
let { args, modifySelectors, container, separator, wrap, format } = api
|
|
548
|
+
let result = variantFunction(
|
|
549
|
+
Object.assign(
|
|
550
|
+
{ modifySelectors, container, separator },
|
|
551
|
+
options.type === VARIANT_TYPES.MatchVariant && { args, wrap, format }
|
|
552
|
+
)
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
if (typeof result === 'string' && !isValidVariantFormatString(result)) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (Array.isArray(result)) {
|
|
562
|
+
return result
|
|
563
|
+
.filter((variant) => typeof variant === 'string')
|
|
564
|
+
.map((variant) => parseVariant(variant))
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// result may be undefined with legacy variants that use APIs like `modifySelectors`
|
|
568
|
+
// result may also be a postcss node if someone was returning the result from `modifySelectors`
|
|
569
|
+
return result && typeof result === 'string' && parseVariant(result)(api)
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if (!isValidVariantFormatString(variantFunction)) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
`Your custom variant \`${variantName}\` has an invalid format string. Make sure it's an at-rule or contains a \`&\` placeholder.`
|
|
576
|
+
)
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return parseVariant(variantFunction)
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
insertInto(variantList, variantName, options)
|
|
583
|
+
variantMap.set(variantName, variantFunctions)
|
|
584
|
+
context.variantOptions.set(variantName, options)
|
|
585
|
+
},
|
|
586
|
+
matchVariant(variant, variantFn, options) {
|
|
587
|
+
// A unique identifier that "groups" these variants together.
|
|
588
|
+
// This is for internal use only which is why it is not present in the types
|
|
589
|
+
let id = options?.id ?? ++variantIdentifier
|
|
590
|
+
let isSpecial = variant === '@'
|
|
591
|
+
|
|
592
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
593
|
+
|
|
594
|
+
for (let [key, value] of Object.entries(options?.values ?? {})) {
|
|
595
|
+
if (key === 'DEFAULT') continue
|
|
596
|
+
|
|
597
|
+
api.addVariant(
|
|
598
|
+
isSpecial ? `${variant}${key}` : `${variant}-${key}`,
|
|
599
|
+
({ args, container }) => {
|
|
600
|
+
return variantFn(
|
|
601
|
+
value,
|
|
602
|
+
modifiersEnabled ? { modifier: args?.modifier, container } : { container }
|
|
603
|
+
)
|
|
604
|
+
},
|
|
605
|
+
|
|
606
|
+
{
|
|
607
|
+
...options,
|
|
608
|
+
value,
|
|
609
|
+
id,
|
|
610
|
+
type: VARIANT_TYPES.MatchVariant,
|
|
611
|
+
variantInfo: VARIANT_INFO.Base,
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
let hasDefault = 'DEFAULT' in (options?.values ?? {})
|
|
617
|
+
|
|
618
|
+
api.addVariant(
|
|
619
|
+
variant,
|
|
620
|
+
({ args, container }) => {
|
|
621
|
+
if (args?.value === sharedState.NONE && !hasDefault) {
|
|
622
|
+
return null
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return variantFn(
|
|
626
|
+
args?.value === sharedState.NONE
|
|
627
|
+
? options.values.DEFAULT
|
|
628
|
+
: // Falling back to args if it is a string, otherwise '' for older intellisense
|
|
629
|
+
// (JetBrains) plugins.
|
|
630
|
+
args?.value ?? (typeof args === 'string' ? args : ''),
|
|
631
|
+
modifiersEnabled ? { modifier: args?.modifier, container } : { container }
|
|
632
|
+
)
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
...options,
|
|
636
|
+
id,
|
|
637
|
+
type: VARIANT_TYPES.MatchVariant,
|
|
638
|
+
variantInfo: VARIANT_INFO.Dynamic,
|
|
639
|
+
}
|
|
640
|
+
)
|
|
641
|
+
},
|
|
418
642
|
}
|
|
643
|
+
|
|
644
|
+
return api
|
|
419
645
|
}
|
|
420
646
|
|
|
421
647
|
let fileModifiedMapCache = new WeakMap()
|
|
@@ -428,6 +654,7 @@ export function getFileModifiedMap(context) {
|
|
|
428
654
|
|
|
429
655
|
function trackModified(files, fileModifiedMap) {
|
|
430
656
|
let changed = false
|
|
657
|
+
let mtimesToCommit = new Map()
|
|
431
658
|
|
|
432
659
|
for (let file of files) {
|
|
433
660
|
if (!file) continue
|
|
@@ -448,10 +675,10 @@ function trackModified(files, fileModifiedMap) {
|
|
|
448
675
|
changed = true
|
|
449
676
|
}
|
|
450
677
|
|
|
451
|
-
|
|
678
|
+
mtimesToCommit.set(file, newModified)
|
|
452
679
|
}
|
|
453
680
|
|
|
454
|
-
return changed
|
|
681
|
+
return [changed, mtimesToCommit]
|
|
455
682
|
}
|
|
456
683
|
|
|
457
684
|
function extractVariantAtRules(node) {
|
|
@@ -488,29 +715,20 @@ function collectLayerPlugins(root) {
|
|
|
488
715
|
} else if (layerRule.params === 'components') {
|
|
489
716
|
for (let node of layerRule.nodes) {
|
|
490
717
|
layerPlugins.push(function ({ addComponents }) {
|
|
491
|
-
addComponents(node, { respectPrefix: false })
|
|
718
|
+
addComponents(node, { respectPrefix: false, preserveSource: true })
|
|
492
719
|
})
|
|
493
720
|
}
|
|
494
721
|
layerRule.remove()
|
|
495
722
|
} else if (layerRule.params === 'utilities') {
|
|
496
723
|
for (let node of layerRule.nodes) {
|
|
497
724
|
layerPlugins.push(function ({ addUtilities }) {
|
|
498
|
-
addUtilities(node, { respectPrefix: false })
|
|
725
|
+
addUtilities(node, { respectPrefix: false, preserveSource: true })
|
|
499
726
|
})
|
|
500
727
|
}
|
|
501
728
|
layerRule.remove()
|
|
502
729
|
}
|
|
503
730
|
})
|
|
504
731
|
|
|
505
|
-
root.walkRules((rule) => {
|
|
506
|
-
// At this point it is safe to include all the left-over css from the
|
|
507
|
-
// user's css file. This is because the `@tailwind` and `@layer` directives
|
|
508
|
-
// will already be handled and will be removed from the css tree.
|
|
509
|
-
layerPlugins.push(function ({ addUserCss }) {
|
|
510
|
-
addUserCss(rule, { respectPrefix: false })
|
|
511
|
-
})
|
|
512
|
-
})
|
|
513
|
-
|
|
514
732
|
return layerPlugins
|
|
515
733
|
}
|
|
516
734
|
|
|
@@ -538,31 +756,56 @@ function resolvePlugins(context, root) {
|
|
|
538
756
|
// TODO: This is a workaround for backwards compatibility, since custom variants
|
|
539
757
|
// were historically sorted before screen/stackable variants.
|
|
540
758
|
let beforeVariants = [
|
|
759
|
+
variantPlugins['childVariant'],
|
|
541
760
|
variantPlugins['pseudoElementVariants'],
|
|
542
761
|
variantPlugins['pseudoClassVariants'],
|
|
762
|
+
variantPlugins['hasVariants'],
|
|
763
|
+
variantPlugins['ariaVariants'],
|
|
764
|
+
variantPlugins['dataVariants'],
|
|
543
765
|
]
|
|
544
766
|
let afterVariants = [
|
|
545
|
-
variantPlugins['
|
|
767
|
+
variantPlugins['supportsVariants'],
|
|
546
768
|
variantPlugins['reducedMotionVariants'],
|
|
547
|
-
variantPlugins['
|
|
548
|
-
variantPlugins['printVariant'],
|
|
769
|
+
variantPlugins['prefersContrastVariants'],
|
|
549
770
|
variantPlugins['screenVariants'],
|
|
550
771
|
variantPlugins['orientationVariants'],
|
|
772
|
+
variantPlugins['directionVariants'],
|
|
773
|
+
variantPlugins['darkVariants'],
|
|
774
|
+
variantPlugins['forcedColorsVariants'],
|
|
775
|
+
variantPlugins['printVariant'],
|
|
551
776
|
]
|
|
552
777
|
|
|
778
|
+
// This is a compatibility fix for the pre 3.4 dark mode behavior
|
|
779
|
+
// `class` retains the old behavior, but `selector` keeps the new behavior
|
|
780
|
+
let isLegacyDarkMode =
|
|
781
|
+
context.tailwindConfig.darkMode === 'class' ||
|
|
782
|
+
(Array.isArray(context.tailwindConfig.darkMode) &&
|
|
783
|
+
context.tailwindConfig.darkMode[0] === 'class')
|
|
784
|
+
|
|
785
|
+
if (isLegacyDarkMode) {
|
|
786
|
+
afterVariants = [
|
|
787
|
+
variantPlugins['supportsVariants'],
|
|
788
|
+
variantPlugins['reducedMotionVariants'],
|
|
789
|
+
variantPlugins['prefersContrastVariants'],
|
|
790
|
+
variantPlugins['darkVariants'],
|
|
791
|
+
variantPlugins['screenVariants'],
|
|
792
|
+
variantPlugins['orientationVariants'],
|
|
793
|
+
variantPlugins['directionVariants'],
|
|
794
|
+
variantPlugins['forcedColorsVariants'],
|
|
795
|
+
variantPlugins['printVariant'],
|
|
796
|
+
]
|
|
797
|
+
}
|
|
798
|
+
|
|
553
799
|
return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
|
|
554
800
|
}
|
|
555
801
|
|
|
556
802
|
function registerPlugins(plugins, context) {
|
|
557
803
|
let variantList = []
|
|
558
804
|
let variantMap = new Map()
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
utilities: 0n,
|
|
564
|
-
user: 0n,
|
|
565
|
-
}
|
|
805
|
+
context.variantMap = variantMap
|
|
806
|
+
|
|
807
|
+
let offsets = new Offsets()
|
|
808
|
+
context.offsets = offsets
|
|
566
809
|
|
|
567
810
|
let classList = new Set()
|
|
568
811
|
|
|
@@ -583,49 +826,17 @@ function registerPlugins(plugins, context) {
|
|
|
583
826
|
}
|
|
584
827
|
}
|
|
585
828
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
offsets.defaults,
|
|
589
|
-
offsets.components,
|
|
590
|
-
offsets.utilities,
|
|
591
|
-
offsets.user,
|
|
592
|
-
])
|
|
593
|
-
let reservedBits = BigInt(highestOffset.toString(2).length)
|
|
594
|
-
|
|
595
|
-
// A number one less than the top range of the highest offset area
|
|
596
|
-
// so arbitrary properties are always sorted at the end.
|
|
597
|
-
context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
|
|
598
|
-
|
|
599
|
-
context.layerOrder = {
|
|
600
|
-
defaults: (1n << reservedBits) << 0n,
|
|
601
|
-
base: (1n << reservedBits) << 1n,
|
|
602
|
-
components: (1n << reservedBits) << 2n,
|
|
603
|
-
utilities: (1n << reservedBits) << 3n,
|
|
604
|
-
user: (1n << reservedBits) << 4n,
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
reservedBits += 5n
|
|
608
|
-
|
|
609
|
-
let offset = 0
|
|
610
|
-
context.variantOrder = new Map(
|
|
611
|
-
variantList
|
|
612
|
-
.map((variant, i) => {
|
|
613
|
-
let variantFunctions = variantMap.get(variant).length
|
|
614
|
-
let bits = (1n << BigInt(i + offset)) << reservedBits
|
|
615
|
-
offset += variantFunctions - 1
|
|
616
|
-
return [variant, bits]
|
|
617
|
-
})
|
|
618
|
-
.sort(([, a], [, z]) => bigSign(a - z))
|
|
619
|
-
)
|
|
620
|
-
|
|
621
|
-
context.minimumScreen = [...context.variantOrder.values()].shift()
|
|
829
|
+
// Make sure to record bit masks for every variant
|
|
830
|
+
offsets.recordVariants(variantList, (variant) => variantMap.get(variant).length)
|
|
622
831
|
|
|
623
832
|
// Build variantMap
|
|
624
833
|
for (let [variantName, variantFunctions] of variantMap.entries()) {
|
|
625
|
-
let sort = context.variantOrder.get(variantName)
|
|
626
834
|
context.variantMap.set(
|
|
627
835
|
variantName,
|
|
628
|
-
variantFunctions.map((variantFunction, idx) => [
|
|
836
|
+
variantFunctions.map((variantFunction, idx) => [
|
|
837
|
+
offsets.forVariant(variantName, idx),
|
|
838
|
+
variantFunction,
|
|
839
|
+
])
|
|
629
840
|
)
|
|
630
841
|
}
|
|
631
842
|
|
|
@@ -643,7 +854,7 @@ function registerPlugins(plugins, context) {
|
|
|
643
854
|
log.warn('root-regex', [
|
|
644
855
|
'Regular expressions in `safelist` work differently in Tailwind CSS v3.0.',
|
|
645
856
|
'Update your `safelist` configuration to eliminate this warning.',
|
|
646
|
-
|
|
857
|
+
'https://tailwindcss.com/docs/content-configuration#safelisting-classes',
|
|
647
858
|
])
|
|
648
859
|
continue
|
|
649
860
|
}
|
|
@@ -653,17 +864,46 @@ function registerPlugins(plugins, context) {
|
|
|
653
864
|
|
|
654
865
|
if (checks.length > 0) {
|
|
655
866
|
let patternMatchingCount = new Map()
|
|
867
|
+
let prefixLength = context.tailwindConfig.prefix.length
|
|
868
|
+
let checkImportantUtils = checks.some((check) => check.pattern.source.includes('!'))
|
|
656
869
|
|
|
657
870
|
for (let util of classList) {
|
|
658
871
|
let utils = Array.isArray(util)
|
|
659
872
|
? (() => {
|
|
660
873
|
let [utilName, options] = util
|
|
661
|
-
let
|
|
662
|
-
|
|
663
|
-
)
|
|
874
|
+
let values = Object.keys(options?.values ?? {})
|
|
875
|
+
let classes = values.map((value) => formatClass(utilName, value))
|
|
664
876
|
|
|
665
877
|
if (options?.supportsNegativeValues) {
|
|
878
|
+
// This is the normal negated version
|
|
879
|
+
// e.g. `-inset-1` or `-tw-inset-1`
|
|
666
880
|
classes = [...classes, ...classes.map((cls) => '-' + cls)]
|
|
881
|
+
|
|
882
|
+
// This is the negated version *after* the prefix
|
|
883
|
+
// e.g. `tw--inset-1`
|
|
884
|
+
// The prefix is already attached to util name
|
|
885
|
+
// So we add the negative after the prefix
|
|
886
|
+
classes = [
|
|
887
|
+
...classes,
|
|
888
|
+
...classes.map(
|
|
889
|
+
(cls) => cls.slice(0, prefixLength) + '-' + cls.slice(prefixLength)
|
|
890
|
+
),
|
|
891
|
+
]
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (options.types.some(({ type }) => type === 'color')) {
|
|
895
|
+
classes = [
|
|
896
|
+
...classes,
|
|
897
|
+
...classes.flatMap((cls) =>
|
|
898
|
+
Object.keys(context.tailwindConfig.theme.opacity).map(
|
|
899
|
+
(opacity) => `${cls}/${opacity}`
|
|
900
|
+
)
|
|
901
|
+
),
|
|
902
|
+
]
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
if (checkImportantUtils && options?.respectImportant) {
|
|
906
|
+
classes = [...classes, ...classes.map((cls) => '!' + cls)]
|
|
667
907
|
}
|
|
668
908
|
|
|
669
909
|
return classes
|
|
@@ -701,25 +941,95 @@ function registerPlugins(plugins, context) {
|
|
|
701
941
|
log.warn([
|
|
702
942
|
`The safelist pattern \`${regex}\` doesn't match any Tailwind CSS classes.`,
|
|
703
943
|
'Fix this pattern or remove it from your `safelist` configuration.',
|
|
944
|
+
'https://tailwindcss.com/docs/content-configuration#safelisting-classes',
|
|
704
945
|
])
|
|
705
946
|
}
|
|
706
947
|
}
|
|
707
948
|
}
|
|
708
949
|
|
|
950
|
+
let darkClassName = [].concat(context.tailwindConfig.darkMode ?? 'media')[1] ?? 'dark'
|
|
951
|
+
|
|
952
|
+
// A list of utilities that are used by certain Tailwind CSS utilities but
|
|
953
|
+
// that don't exist on their own. This will result in them "not existing" and
|
|
954
|
+
// sorting could be weird since you still require them in order to make the
|
|
955
|
+
// host utilities work properly. (Thanks Biology)
|
|
956
|
+
let parasiteUtilities = [
|
|
957
|
+
prefix(context, darkClassName),
|
|
958
|
+
prefix(context, 'group'),
|
|
959
|
+
prefix(context, 'peer'),
|
|
960
|
+
]
|
|
961
|
+
context.getClassOrder = function getClassOrder(classes) {
|
|
962
|
+
// Sort classes so they're ordered in a deterministic manner
|
|
963
|
+
let sorted = [...classes].sort((a, z) => {
|
|
964
|
+
if (a === z) return 0
|
|
965
|
+
if (a < z) return -1
|
|
966
|
+
return 1
|
|
967
|
+
})
|
|
968
|
+
|
|
969
|
+
// Non-util classes won't be generated, so we default them to null
|
|
970
|
+
let sortedClassNames = new Map(sorted.map((className) => [className, null]))
|
|
971
|
+
|
|
972
|
+
// Sort all classes in order
|
|
973
|
+
// Non-tailwind classes won't be generated and will be left as `null`
|
|
974
|
+
let rules = generateRules(new Set(sorted), context, true)
|
|
975
|
+
rules = context.offsets.sort(rules)
|
|
976
|
+
|
|
977
|
+
let idx = BigInt(parasiteUtilities.length)
|
|
978
|
+
|
|
979
|
+
for (const [, rule] of rules) {
|
|
980
|
+
let candidate = rule.raws.tailwind.candidate
|
|
981
|
+
|
|
982
|
+
// When multiple rules match a candidate
|
|
983
|
+
// always take the position of the first one
|
|
984
|
+
sortedClassNames.set(candidate, sortedClassNames.get(candidate) ?? idx++)
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
return classes.map((className) => {
|
|
988
|
+
let order = sortedClassNames.get(className) ?? null
|
|
989
|
+
let parasiteIndex = parasiteUtilities.indexOf(className)
|
|
990
|
+
|
|
991
|
+
if (order === null && parasiteIndex !== -1) {
|
|
992
|
+
// This will make sure that it is at the very beginning of the
|
|
993
|
+
// `components` layer which technically means 'before any
|
|
994
|
+
// components'.
|
|
995
|
+
order = BigInt(parasiteIndex)
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
return [className, order]
|
|
999
|
+
})
|
|
1000
|
+
}
|
|
1001
|
+
|
|
709
1002
|
// Generate a list of strings for autocompletion purposes, e.g.
|
|
710
1003
|
// ['uppercase', 'lowercase', ...]
|
|
711
|
-
context.getClassList = function () {
|
|
1004
|
+
context.getClassList = function getClassList(options = {}) {
|
|
712
1005
|
let output = []
|
|
713
1006
|
|
|
714
1007
|
for (let util of classList) {
|
|
715
1008
|
if (Array.isArray(util)) {
|
|
716
|
-
let [utilName,
|
|
1009
|
+
let [utilName, utilOptions] = util
|
|
717
1010
|
let negativeClasses = []
|
|
718
1011
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
1012
|
+
let modifiers = Object.keys(utilOptions?.modifiers ?? {})
|
|
1013
|
+
|
|
1014
|
+
if (utilOptions?.types?.some(({ type }) => type === 'color')) {
|
|
1015
|
+
modifiers.push(...Object.keys(context.tailwindConfig.theme.opacity ?? {}))
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
let metadata = { modifiers }
|
|
1019
|
+
let includeMetadata = options.includeMetadata && modifiers.length > 0
|
|
1020
|
+
|
|
1021
|
+
for (let [key, value] of Object.entries(utilOptions?.values ?? {})) {
|
|
1022
|
+
// Ignore undefined and null values
|
|
1023
|
+
if (value == null) {
|
|
1024
|
+
continue
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
let cls = formatClass(utilName, key)
|
|
1028
|
+
output.push(includeMetadata ? [cls, metadata] : cls)
|
|
1029
|
+
|
|
1030
|
+
if (utilOptions?.supportsNegativeValues && negateValue(value)) {
|
|
1031
|
+
let cls = formatClass(utilName, `-${key}`)
|
|
1032
|
+
negativeClasses.push(includeMetadata ? [cls, metadata] : cls)
|
|
723
1033
|
}
|
|
724
1034
|
}
|
|
725
1035
|
|
|
@@ -731,21 +1041,235 @@ function registerPlugins(plugins, context) {
|
|
|
731
1041
|
|
|
732
1042
|
return output
|
|
733
1043
|
}
|
|
1044
|
+
|
|
1045
|
+
// Generate a list of available variants with meta information of the type of variant.
|
|
1046
|
+
context.getVariants = function getVariants() {
|
|
1047
|
+
// We use a unique, random ID for candidate names to avoid conflicts
|
|
1048
|
+
// We can't use characters like `_`, `:`, `@` or `.` because they might
|
|
1049
|
+
// be used as a separator
|
|
1050
|
+
let id = Math.random().toString(36).substring(7).toUpperCase()
|
|
1051
|
+
|
|
1052
|
+
let result = []
|
|
1053
|
+
for (let [name, options] of context.variantOptions.entries()) {
|
|
1054
|
+
if (options.variantInfo === VARIANT_INFO.Base) continue
|
|
1055
|
+
|
|
1056
|
+
result.push({
|
|
1057
|
+
name,
|
|
1058
|
+
isArbitrary: options.type === Symbol.for('MATCH_VARIANT'),
|
|
1059
|
+
values: Object.keys(options.values ?? {}),
|
|
1060
|
+
hasDash: name !== '@',
|
|
1061
|
+
selectors({ modifier, value } = {}) {
|
|
1062
|
+
let candidate = `TAILWINDPLACEHOLDER${id}`
|
|
1063
|
+
|
|
1064
|
+
let rule = postcss.rule({ selector: `.${candidate}` })
|
|
1065
|
+
let container = postcss.root({ nodes: [rule.clone()] })
|
|
1066
|
+
|
|
1067
|
+
let before = container.toString()
|
|
1068
|
+
|
|
1069
|
+
let fns = (context.variantMap.get(name) ?? []).flatMap(([_, fn]) => fn)
|
|
1070
|
+
let formatStrings = []
|
|
1071
|
+
for (let fn of fns) {
|
|
1072
|
+
let localFormatStrings = []
|
|
1073
|
+
|
|
1074
|
+
let api = {
|
|
1075
|
+
args: { modifier, value: options.values?.[value] ?? value },
|
|
1076
|
+
separator: context.tailwindConfig.separator,
|
|
1077
|
+
modifySelectors(modifierFunction) {
|
|
1078
|
+
// Run the modifierFunction over each rule
|
|
1079
|
+
container.each((rule) => {
|
|
1080
|
+
if (rule.type !== 'rule') {
|
|
1081
|
+
return
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
rule.selectors = rule.selectors.map((selector) => {
|
|
1085
|
+
return modifierFunction({
|
|
1086
|
+
get className() {
|
|
1087
|
+
return getClassNameFromSelector(selector)
|
|
1088
|
+
},
|
|
1089
|
+
selector,
|
|
1090
|
+
})
|
|
1091
|
+
})
|
|
1092
|
+
})
|
|
1093
|
+
|
|
1094
|
+
return container
|
|
1095
|
+
},
|
|
1096
|
+
format(str) {
|
|
1097
|
+
localFormatStrings.push(str)
|
|
1098
|
+
},
|
|
1099
|
+
wrap(wrapper) {
|
|
1100
|
+
localFormatStrings.push(`@${wrapper.name} ${wrapper.params} { & }`)
|
|
1101
|
+
},
|
|
1102
|
+
container,
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
let ruleWithVariant = fn(api)
|
|
1106
|
+
if (localFormatStrings.length > 0) {
|
|
1107
|
+
formatStrings.push(localFormatStrings)
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
if (Array.isArray(ruleWithVariant)) {
|
|
1111
|
+
for (let variantFunction of ruleWithVariant) {
|
|
1112
|
+
localFormatStrings = []
|
|
1113
|
+
variantFunction(api)
|
|
1114
|
+
formatStrings.push(localFormatStrings)
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// Reverse engineer the result of the `container`
|
|
1120
|
+
let manualFormatStrings = []
|
|
1121
|
+
let after = container.toString()
|
|
1122
|
+
|
|
1123
|
+
if (before !== after) {
|
|
1124
|
+
// Figure out all selectors
|
|
1125
|
+
container.walkRules((rule) => {
|
|
1126
|
+
let modified = rule.selector
|
|
1127
|
+
|
|
1128
|
+
// Rebuild the base selector, this is what plugin authors would do
|
|
1129
|
+
// as well. E.g.: `${variant}${separator}${className}`.
|
|
1130
|
+
// However, plugin authors probably also prepend or append certain
|
|
1131
|
+
// classes, pseudos, ids, ...
|
|
1132
|
+
let rebuiltBase = selectorParser((selectors) => {
|
|
1133
|
+
selectors.walkClasses((classNode) => {
|
|
1134
|
+
classNode.value = `${name}${context.tailwindConfig.separator}${classNode.value}`
|
|
1135
|
+
})
|
|
1136
|
+
}).processSync(modified)
|
|
1137
|
+
|
|
1138
|
+
// Now that we know the original selector, the new selector, and
|
|
1139
|
+
// the rebuild part in between, we can replace the part that plugin
|
|
1140
|
+
// authors need to rebuild with `&`, and eventually store it in the
|
|
1141
|
+
// collectedFormats. Similar to what `format('...')` would do.
|
|
1142
|
+
//
|
|
1143
|
+
// E.g.:
|
|
1144
|
+
// variant: foo
|
|
1145
|
+
// selector: .markdown > p
|
|
1146
|
+
// modified (by plugin): .foo .foo\\:markdown > p
|
|
1147
|
+
// rebuiltBase (internal): .foo\\:markdown > p
|
|
1148
|
+
// format: .foo &
|
|
1149
|
+
manualFormatStrings.push(modified.replace(rebuiltBase, '&').replace(candidate, '&'))
|
|
1150
|
+
})
|
|
1151
|
+
|
|
1152
|
+
// Figure out all atrules
|
|
1153
|
+
container.walkAtRules((atrule) => {
|
|
1154
|
+
manualFormatStrings.push(`@${atrule.name} (${atrule.params}) { & }`)
|
|
1155
|
+
})
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
let isArbitraryVariant = !(value in (options.values ?? {}))
|
|
1159
|
+
let internalFeatures = options[INTERNAL_FEATURES] ?? {}
|
|
1160
|
+
|
|
1161
|
+
let respectPrefix = (() => {
|
|
1162
|
+
if (isArbitraryVariant) return false
|
|
1163
|
+
if (internalFeatures.respectPrefix === false) return false
|
|
1164
|
+
return true
|
|
1165
|
+
})()
|
|
1166
|
+
|
|
1167
|
+
formatStrings = formatStrings.map((format) =>
|
|
1168
|
+
format.map((str) => ({
|
|
1169
|
+
format: str,
|
|
1170
|
+
respectPrefix,
|
|
1171
|
+
}))
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
manualFormatStrings = manualFormatStrings.map((format) => ({
|
|
1175
|
+
format,
|
|
1176
|
+
respectPrefix,
|
|
1177
|
+
}))
|
|
1178
|
+
|
|
1179
|
+
let opts = {
|
|
1180
|
+
candidate,
|
|
1181
|
+
context,
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
let result = formatStrings.map((formats) =>
|
|
1185
|
+
finalizeSelector(`.${candidate}`, formatVariantSelector(formats, opts), opts)
|
|
1186
|
+
.replace(`.${candidate}`, '&')
|
|
1187
|
+
.replace('{ & }', '')
|
|
1188
|
+
.trim()
|
|
1189
|
+
)
|
|
1190
|
+
|
|
1191
|
+
if (manualFormatStrings.length > 0) {
|
|
1192
|
+
result.push(
|
|
1193
|
+
formatVariantSelector(manualFormatStrings, opts)
|
|
1194
|
+
.toString()
|
|
1195
|
+
.replace(`.${candidate}`, '&')
|
|
1196
|
+
)
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
return result
|
|
1200
|
+
},
|
|
1201
|
+
})
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
return result
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
/**
|
|
1209
|
+
* Mark as class as retroactively invalid
|
|
1210
|
+
*
|
|
1211
|
+
*
|
|
1212
|
+
* @param {string} candidate
|
|
1213
|
+
*/
|
|
1214
|
+
function markInvalidUtilityCandidate(context, candidate) {
|
|
1215
|
+
if (!context.classCache.has(candidate)) {
|
|
1216
|
+
return
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
// Mark this as not being a real utility
|
|
1220
|
+
context.notClassCache.add(candidate)
|
|
1221
|
+
|
|
1222
|
+
// Remove it from any candidate-specific caches
|
|
1223
|
+
context.classCache.delete(candidate)
|
|
1224
|
+
context.applyClassCache.delete(candidate)
|
|
1225
|
+
context.candidateRuleMap.delete(candidate)
|
|
1226
|
+
context.candidateRuleCache.delete(candidate)
|
|
1227
|
+
|
|
1228
|
+
// Ensure the stylesheet gets rebuilt
|
|
1229
|
+
context.stylesheetCache = null
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* Mark as class as retroactively invalid
|
|
1234
|
+
*
|
|
1235
|
+
* @param {import('postcss').Node} node
|
|
1236
|
+
*/
|
|
1237
|
+
function markInvalidUtilityNode(context, node) {
|
|
1238
|
+
let candidate = node.raws.tailwind.candidate
|
|
1239
|
+
|
|
1240
|
+
if (!candidate) {
|
|
1241
|
+
return
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
for (const entry of context.ruleCache) {
|
|
1245
|
+
if (entry[1].raws.tailwind.candidate === candidate) {
|
|
1246
|
+
context.ruleCache.delete(entry)
|
|
1247
|
+
// context.postCssNodeCache.delete(node)
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
markInvalidUtilityCandidate(context, candidate)
|
|
734
1252
|
}
|
|
735
1253
|
|
|
736
1254
|
export function createContext(tailwindConfig, changedContent = [], root = postcss.root()) {
|
|
737
1255
|
let context = {
|
|
738
1256
|
disposables: [],
|
|
739
1257
|
ruleCache: new Set(),
|
|
1258
|
+
candidateRuleCache: new Map(),
|
|
740
1259
|
classCache: new Map(),
|
|
741
1260
|
applyClassCache: new Map(),
|
|
742
|
-
|
|
1261
|
+
// Seed the not class cache with the blocklist (which is only strings)
|
|
1262
|
+
notClassCache: new Set(tailwindConfig.blocklist ?? []),
|
|
743
1263
|
postCssNodeCache: new Map(),
|
|
744
1264
|
candidateRuleMap: new Map(),
|
|
745
1265
|
tailwindConfig,
|
|
746
1266
|
changedContent: changedContent,
|
|
747
1267
|
variantMap: new Map(),
|
|
748
1268
|
stylesheetCache: null,
|
|
1269
|
+
variantOptions: new Map(),
|
|
1270
|
+
|
|
1271
|
+
markInvalidUtilityCandidate: (candidate) => markInvalidUtilityCandidate(context, candidate),
|
|
1272
|
+
markInvalidUtilityNode: (node) => markInvalidUtilityNode(context, node),
|
|
749
1273
|
}
|
|
750
1274
|
|
|
751
1275
|
let resolvedPlugins = resolvePlugins(context, root)
|
|
@@ -783,15 +1307,17 @@ export function getContext(
|
|
|
783
1307
|
existingContext = context
|
|
784
1308
|
}
|
|
785
1309
|
|
|
1310
|
+
let cssDidChange = hasContentChanged(sourcePath, root)
|
|
1311
|
+
|
|
786
1312
|
// If there's already a context in the cache and we don't need to
|
|
787
1313
|
// reset the context, return the cached context.
|
|
788
1314
|
if (existingContext) {
|
|
789
|
-
let contextDependenciesChanged = trackModified(
|
|
1315
|
+
let [contextDependenciesChanged, mtimesToCommit] = trackModified(
|
|
790
1316
|
[...contextDependencies],
|
|
791
1317
|
getFileModifiedMap(existingContext)
|
|
792
1318
|
)
|
|
793
|
-
if (!contextDependenciesChanged) {
|
|
794
|
-
return [existingContext, false]
|
|
1319
|
+
if (!contextDependenciesChanged && !cssDidChange) {
|
|
1320
|
+
return [existingContext, false, mtimesToCommit]
|
|
795
1321
|
}
|
|
796
1322
|
}
|
|
797
1323
|
|
|
@@ -822,7 +1348,11 @@ export function getContext(
|
|
|
822
1348
|
|
|
823
1349
|
let context = createContext(tailwindConfig, [], root)
|
|
824
1350
|
|
|
825
|
-
|
|
1351
|
+
Object.assign(context, {
|
|
1352
|
+
userConfigPath,
|
|
1353
|
+
})
|
|
1354
|
+
|
|
1355
|
+
let [, mtimesToCommit] = trackModified([...contextDependencies], getFileModifiedMap(context))
|
|
826
1356
|
|
|
827
1357
|
// ---
|
|
828
1358
|
|
|
@@ -837,5 +1367,5 @@ export function getContext(
|
|
|
837
1367
|
|
|
838
1368
|
contextSourcesMap.get(context).add(sourcePath)
|
|
839
1369
|
|
|
840
|
-
return [context, true]
|
|
1370
|
+
return [context, true, mtimesToCommit]
|
|
841
1371
|
}
|