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