tailwindcss 0.0.0-insiders.d3e754a → 0.0.0-insiders.d3f2221
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/README.md +13 -9
- package/colors.d.ts +3 -0
- package/defaultConfig.d.ts +3 -0
- package/defaultTheme.d.ts +4 -0
- package/index.css +5 -0
- package/lib/cli/build/index.js +57 -0
- package/lib/cli/build/plugin.js +431 -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 +231 -0
- package/lib/cli/init/index.js +63 -0
- package/lib/cli.js +1 -739
- package/lib/corePluginList.js +13 -3
- package/lib/corePlugins.js +1094 -478
- package/lib/css/preflight.css +17 -4
- package/lib/featureFlags.js +49 -23
- package/lib/index.js +1 -29
- package/lib/lib/cacheInvalidation.js +92 -0
- package/lib/lib/collapseAdjacentRules.js +12 -5
- package/lib/lib/collapseDuplicateDeclarations.js +12 -7
- package/lib/lib/content.js +207 -0
- package/lib/lib/defaultExtractor.js +217 -33
- package/lib/lib/detectNesting.js +15 -4
- package/lib/lib/evaluateTailwindFunctions.js +104 -37
- package/lib/lib/expandApplyAtRules.js +312 -211
- package/lib/lib/expandTailwindAtRules.js +149 -96
- package/lib/lib/findAtConfigPath.js +46 -0
- package/lib/lib/generateRules.js +437 -188
- package/lib/lib/getModuleDependencies.js +88 -37
- package/lib/lib/handleImportAtRules.js +50 -0
- package/lib/lib/load-config.js +42 -0
- package/lib/lib/normalizeTailwindDirectives.js +9 -19
- package/lib/lib/offsets.js +306 -0
- package/lib/lib/partitionApplyAtRules.js +11 -6
- package/lib/lib/regex.js +74 -0
- package/lib/lib/remap-bitfield.js +89 -0
- package/lib/lib/resolveDefaultsAtRules.js +80 -58
- package/lib/lib/setupContextUtils.js +683 -270
- package/lib/lib/setupTrackingContext.js +63 -67
- package/lib/lib/sharedState.js +39 -10
- package/lib/lib/substituteScreenAtRules.js +13 -9
- package/lib/plugin.js +164 -0
- package/lib/postcss-plugins/nesting/README.md +2 -2
- package/lib/postcss-plugins/nesting/index.js +10 -6
- package/lib/postcss-plugins/nesting/plugin.js +15 -11
- package/lib/processTailwindFeatures.js +33 -28
- package/lib/public/colors.js +55 -29
- 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 +12 -5
- package/lib/util/cloneDeep.js +8 -5
- package/lib/util/cloneNodes.js +11 -2
- package/lib/util/color.js +59 -42
- package/lib/util/colorNames.js +752 -0
- package/lib/util/configurePlugins.js +7 -2
- package/lib/util/createPlugin.js +8 -5
- package/lib/util/createUtilityPlugin.js +15 -11
- package/lib/util/dataTypes.js +172 -47
- package/lib/util/defaults.js +12 -7
- package/lib/util/escapeClassName.js +13 -8
- package/lib/util/escapeCommas.js +6 -1
- package/lib/util/flattenColorPalette.js +9 -8
- package/lib/util/formatVariantSelector.js +230 -151
- package/lib/util/getAllConfigs.js +34 -12
- package/lib/util/hashConfig.js +9 -4
- package/lib/util/isKeyframeRule.js +6 -1
- package/lib/util/isPlainObject.js +6 -1
- package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +15 -5
- package/lib/util/log.js +36 -9
- package/lib/util/nameClass.js +24 -7
- package/lib/util/negateValue.js +23 -6
- package/lib/util/normalizeConfig.js +142 -69
- package/lib/util/normalizeScreens.js +124 -5
- package/lib/util/parseAnimationValue.js +8 -4
- package/lib/util/parseBoxShadowValue.js +16 -45
- package/lib/util/parseDependency.js +38 -54
- package/lib/util/parseGlob.js +36 -0
- package/lib/util/parseObjectStyles.js +14 -9
- package/lib/util/pluginUtils.js +146 -51
- package/lib/util/prefixSelector.js +29 -10
- package/lib/util/pseudoElements.js +209 -0
- package/lib/util/removeAlphaVariables.js +31 -0
- package/lib/util/resolveConfig.js +100 -73
- package/lib/util/resolveConfigPath.js +27 -8
- package/lib/util/responsive.js +10 -5
- package/lib/util/splitAtTopLevelOnly.js +51 -0
- package/lib/util/tap.js +6 -1
- package/lib/util/toColorValue.js +6 -1
- package/lib/util/toPath.js +20 -2
- package/lib/util/transformThemeValue.js +21 -7
- package/lib/util/validateConfig.js +48 -0
- package/lib/util/validateFormalSyntax.js +26 -0
- package/lib/util/withAlphaVariable.js +24 -12
- 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/package.json +58 -53
- package/plugin.d.ts +11 -0
- package/resolveConfig.d.ts +12 -0
- package/scripts/generate-types.js +105 -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/index.js +53 -0
- package/src/cli/build/plugin.js +469 -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 +217 -0
- package/src/cli/init/index.js +79 -0
- package/src/cli.js +1 -813
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +636 -117
- package/src/css/preflight.css +17 -4
- package/src/featureFlags.js +13 -3
- package/src/index.js +1 -28
- package/src/lib/cacheInvalidation.js +52 -0
- package/src/lib/collapseAdjacentRules.js +5 -1
- package/src/lib/content.js +240 -0
- package/src/lib/defaultExtractor.js +192 -35
- package/src/lib/detectNesting.js +9 -1
- package/src/lib/evaluateTailwindFunctions.js +82 -8
- package/src/lib/expandApplyAtRules.js +322 -189
- package/src/lib/expandTailwindAtRules.js +87 -60
- package/src/lib/findAtConfigPath.js +48 -0
- package/src/lib/generateRules.js +428 -128
- package/src/lib/getModuleDependencies.js +70 -30
- package/src/lib/handleImportAtRules.js +34 -0
- package/src/lib/load-config.ts +31 -0
- package/src/lib/normalizeTailwindDirectives.js +0 -27
- package/src/lib/offsets.js +373 -0
- package/src/lib/regex.js +74 -0
- package/src/lib/remap-bitfield.js +82 -0
- package/src/lib/resolveDefaultsAtRules.js +53 -36
- package/src/lib/setupContextUtils.js +608 -157
- package/src/lib/setupTrackingContext.js +44 -58
- package/src/lib/sharedState.js +14 -4
- package/src/plugin.js +133 -0
- package/src/postcss-plugins/nesting/README.md +2 -2
- package/src/processTailwindFeatures.js +3 -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 +5 -1
- package/src/util/color.js +39 -20
- package/src/util/colorNames.js +150 -0
- package/src/util/dataTypes.js +115 -23
- package/src/util/formatVariantSelector.js +265 -144
- package/src/util/getAllConfigs.js +21 -2
- package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
- package/src/util/log.js +25 -1
- package/src/util/nameClass.js +4 -0
- package/src/util/negateValue.js +11 -3
- package/src/util/normalizeConfig.js +78 -20
- package/src/util/normalizeScreens.js +99 -4
- package/src/util/parseBoxShadowValue.js +3 -50
- package/src/util/parseDependency.js +37 -42
- package/src/util/parseGlob.js +24 -0
- package/src/util/pluginUtils.js +118 -23
- package/src/util/prefixSelector.js +29 -10
- package/src/util/pseudoElements.js +167 -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 +36 -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} +224 -172
- package/stubs/{simpleConfig.stub.js → config.simple.js} +1 -1
- package/stubs/{defaultPostCssConfig.stub.js → postcss.config.cjs} +0 -1
- package/stubs/postcss.config.js +5 -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 +369 -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 +378 -0
- package/types/index.d.ts +7 -0
- package/CHANGELOG.md +0 -2075
- package/lib/cli-peer-dependencies.js +0 -15
- package/lib/constants.js +0 -37
- package/peers/index.js +0 -75077
- package/scripts/install-integrations.js +0 -27
- package/scripts/rebuildFixtures.js +0 -68
- package/src/cli-peer-dependencies.js +0 -9
- package/src/constants.js +0 -17
|
@@ -2,24 +2,46 @@ import postcss from 'postcss'
|
|
|
2
2
|
import parser from 'postcss-selector-parser'
|
|
3
3
|
|
|
4
4
|
import { resolveMatches } from './generateRules'
|
|
5
|
-
import bigSign from '../util/bigSign'
|
|
6
5
|
import escapeClassName from '../util/escapeClassName'
|
|
6
|
+
import { applyImportantSelector } from '../util/applyImportantSelector'
|
|
7
|
+
import { movePseudos } from '../util/pseudoElements'
|
|
7
8
|
|
|
8
9
|
/** @typedef {Map<string, [any, import('postcss').Rule[]]>} ApplyCache */
|
|
9
10
|
|
|
10
11
|
function extractClasses(node) {
|
|
11
|
-
|
|
12
|
+
/** @type {Map<string, Set<string>>} */
|
|
13
|
+
let groups = new Map()
|
|
14
|
+
|
|
12
15
|
let container = postcss.root({ nodes: [node.clone()] })
|
|
13
16
|
|
|
14
17
|
container.walkRules((rule) => {
|
|
15
18
|
parser((selectors) => {
|
|
16
19
|
selectors.walkClasses((classSelector) => {
|
|
20
|
+
let parentSelector = classSelector.parent.toString()
|
|
21
|
+
|
|
22
|
+
let classes = groups.get(parentSelector)
|
|
23
|
+
if (!classes) {
|
|
24
|
+
groups.set(parentSelector, (classes = new Set()))
|
|
25
|
+
}
|
|
26
|
+
|
|
17
27
|
classes.add(classSelector.value)
|
|
18
28
|
})
|
|
19
29
|
}).processSync(rule.selector)
|
|
20
30
|
})
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
let normalizedGroups = Array.from(groups.values(), (classes) => Array.from(classes))
|
|
33
|
+
let classes = normalizedGroups.flat()
|
|
34
|
+
|
|
35
|
+
return Object.assign(classes, { groups: normalizedGroups })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let selectorExtractor = parser()
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {string} ruleSelectors
|
|
42
|
+
*/
|
|
43
|
+
function extractSelectors(ruleSelectors) {
|
|
44
|
+
return selectorExtractor.astSync(ruleSelectors)
|
|
23
45
|
}
|
|
24
46
|
|
|
25
47
|
function extractBaseCandidates(candidates, separator) {
|
|
@@ -128,9 +150,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
128
150
|
/** @type {ApplyCache} */
|
|
129
151
|
let cache = new Map()
|
|
130
152
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
root.walkRules((rule, idx) => {
|
|
153
|
+
root.walkRules((rule) => {
|
|
134
154
|
// Ignore rules generated by Tailwind
|
|
135
155
|
for (let node of pathToRoot(rule)) {
|
|
136
156
|
if (node.raws.tailwind?.layer !== undefined) {
|
|
@@ -140,6 +160,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
140
160
|
|
|
141
161
|
// Clone what's required to represent this singular rule in the tree
|
|
142
162
|
let container = nestedClone(rule)
|
|
163
|
+
let sort = context.offsets.create('user')
|
|
143
164
|
|
|
144
165
|
for (let className of extractClasses(rule)) {
|
|
145
166
|
let list = cache.get(className) || []
|
|
@@ -148,7 +169,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
148
169
|
list.push([
|
|
149
170
|
{
|
|
150
171
|
layer: 'user',
|
|
151
|
-
sort
|
|
172
|
+
sort,
|
|
152
173
|
important: false,
|
|
153
174
|
},
|
|
154
175
|
container,
|
|
@@ -252,222 +273,334 @@ function processApply(root, context, localCache) {
|
|
|
252
273
|
})
|
|
253
274
|
|
|
254
275
|
// Start the @apply process if we have rules with @apply in them
|
|
255
|
-
if (applies.length
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
276
|
+
if (applies.length === 0) {
|
|
277
|
+
return
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Fill up some caches!
|
|
281
|
+
let applyClassCache = combineCaches([localCache, buildApplyCache(applyCandidates, context)])
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* When we have an apply like this:
|
|
285
|
+
*
|
|
286
|
+
* .abc {
|
|
287
|
+
* @apply hover:font-bold;
|
|
288
|
+
* }
|
|
289
|
+
*
|
|
290
|
+
* What we essentially will do is resolve to this:
|
|
291
|
+
*
|
|
292
|
+
* .abc {
|
|
293
|
+
* @apply .hover\:font-bold:hover {
|
|
294
|
+
* font-weight: 500;
|
|
295
|
+
* }
|
|
296
|
+
* }
|
|
297
|
+
*
|
|
298
|
+
* Notice that the to-be-applied class is `.hover\:font-bold:hover` and that the utility candidate was `hover:font-bold`.
|
|
299
|
+
* What happens in this function is that we prepend a `.` and escape the candidate.
|
|
300
|
+
* This will result in `.hover\:font-bold`
|
|
301
|
+
* Which means that we can replace `.hover\:font-bold` with `.abc` in `.hover\:font-bold:hover` resulting in `.abc:hover`
|
|
302
|
+
*
|
|
303
|
+
* @param {string} selector
|
|
304
|
+
* @param {string} utilitySelectors
|
|
305
|
+
* @param {string} candidate
|
|
306
|
+
*/
|
|
307
|
+
function replaceSelector(selector, utilitySelectors, candidate) {
|
|
308
|
+
let selectorList = extractSelectors(selector)
|
|
309
|
+
let utilitySelectorsList = extractSelectors(utilitySelectors)
|
|
310
|
+
let candidateList = extractSelectors(`.${escapeClassName(candidate)}`)
|
|
311
|
+
let candidateClass = candidateList.nodes[0].nodes[0]
|
|
312
|
+
|
|
313
|
+
selectorList.each((sel) => {
|
|
314
|
+
/** @type {Set<import('postcss-selector-parser').Selector>} */
|
|
315
|
+
let replaced = new Set()
|
|
316
|
+
|
|
317
|
+
utilitySelectorsList.each((utilitySelector) => {
|
|
318
|
+
let hasReplaced = false
|
|
319
|
+
utilitySelector = utilitySelector.clone()
|
|
320
|
+
|
|
321
|
+
utilitySelector.walkClasses((node) => {
|
|
322
|
+
if (node.value !== candidateClass.value) {
|
|
323
|
+
return
|
|
295
324
|
}
|
|
296
|
-
return replaced.join(', ')
|
|
297
|
-
})
|
|
298
|
-
.join(', ')
|
|
299
|
-
}
|
|
300
325
|
|
|
301
|
-
|
|
326
|
+
// Don't replace multiple instances of the same class
|
|
327
|
+
// This is theoretically correct but only partially
|
|
328
|
+
// We'd need to generate every possible permutation of the replacement
|
|
329
|
+
// For example with `.foo + .foo { … }` and `section { @apply foo; }`
|
|
330
|
+
// We'd need to generate all of these:
|
|
331
|
+
// - `.foo + .foo`
|
|
332
|
+
// - `.foo + section`
|
|
333
|
+
// - `section + .foo`
|
|
334
|
+
// - `section + section`
|
|
335
|
+
if (hasReplaced) {
|
|
336
|
+
return
|
|
337
|
+
}
|
|
302
338
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
339
|
+
// Since you can only `@apply` class names this is sufficient
|
|
340
|
+
// We want to replace the matched class name with the selector the user is using
|
|
341
|
+
// Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
|
|
342
|
+
node.replaceWith(...sel.nodes.map((node) => node.clone()))
|
|
306
343
|
|
|
307
|
-
|
|
344
|
+
// Record that we did something and we want to use this new selector
|
|
345
|
+
replaced.add(utilitySelector)
|
|
308
346
|
|
|
309
|
-
|
|
347
|
+
hasReplaced = true
|
|
348
|
+
})
|
|
349
|
+
})
|
|
310
350
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
351
|
+
// Sort tag names before class names (but only sort each group (separated by a combinator)
|
|
352
|
+
// separately and not in total)
|
|
353
|
+
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
|
|
354
|
+
for (let sel of replaced) {
|
|
355
|
+
let groups = [[]]
|
|
356
|
+
for (let node of sel.nodes) {
|
|
357
|
+
if (node.type === 'combinator') {
|
|
358
|
+
groups.push(node)
|
|
359
|
+
groups.push([])
|
|
360
|
+
} else {
|
|
361
|
+
let last = groups[groups.length - 1]
|
|
362
|
+
last.push(node)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
314
365
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
366
|
+
sel.nodes = []
|
|
367
|
+
|
|
368
|
+
for (let group of groups) {
|
|
369
|
+
if (Array.isArray(group)) {
|
|
370
|
+
group.sort((a, b) => {
|
|
371
|
+
if (a.type === 'tag' && b.type === 'class') {
|
|
372
|
+
return -1
|
|
373
|
+
} else if (a.type === 'class' && b.type === 'tag') {
|
|
374
|
+
return 1
|
|
375
|
+
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
|
|
376
|
+
return -1
|
|
377
|
+
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
|
|
378
|
+
return 1
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return 0
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
sel.nodes = sel.nodes.concat(group)
|
|
320
386
|
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
sel.replaceWith(...replaced)
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
return selectorList.toString()
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
let perParentApplies = new Map()
|
|
396
|
+
|
|
397
|
+
// Collect all apply candidates and their rules
|
|
398
|
+
for (let apply of applies) {
|
|
399
|
+
let [candidates] = perParentApplies.get(apply.parent) || [[], apply.source]
|
|
400
|
+
|
|
401
|
+
perParentApplies.set(apply.parent, [candidates, apply.source])
|
|
402
|
+
|
|
403
|
+
let [applyCandidates, important] = extractApplyCandidates(apply.params)
|
|
404
|
+
|
|
405
|
+
if (apply.parent.type === 'atrule') {
|
|
406
|
+
if (apply.parent.name === 'screen') {
|
|
407
|
+
let screenType = apply.parent.params
|
|
321
408
|
|
|
322
409
|
throw apply.error(
|
|
323
|
-
`@apply is not supported within nested at-rules like
|
|
410
|
+
`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates
|
|
411
|
+
.map((c) => `${screenType}:${c}`)
|
|
412
|
+
.join(' ')} instead.`
|
|
324
413
|
)
|
|
325
414
|
}
|
|
326
415
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (!applyClassCache.has(applyCandidate)) {
|
|
334
|
-
throw apply.error(
|
|
335
|
-
`The \`${applyCandidate}\` class does not exist. If \`${applyCandidate}\` is a custom class, make sure it is defined within a \`@layer\` directive.`
|
|
336
|
-
)
|
|
337
|
-
}
|
|
416
|
+
throw apply.error(
|
|
417
|
+
`@apply is not supported within nested at-rules like @${apply.parent.name}. You can fix this by un-nesting @${apply.parent.name}.`
|
|
418
|
+
)
|
|
419
|
+
}
|
|
338
420
|
|
|
339
|
-
|
|
421
|
+
for (let applyCandidate of applyCandidates) {
|
|
422
|
+
if ([prefix(context, 'group'), prefix(context, 'peer')].includes(applyCandidate)) {
|
|
423
|
+
// TODO: Link to specific documentation page with error code.
|
|
424
|
+
throw apply.error(`@apply should not be used with the '${applyCandidate}' utility`)
|
|
425
|
+
}
|
|
340
426
|
|
|
341
|
-
|
|
427
|
+
if (!applyClassCache.has(applyCandidate)) {
|
|
428
|
+
throw apply.error(
|
|
429
|
+
`The \`${applyCandidate}\` class does not exist. If \`${applyCandidate}\` is a custom class, make sure it is defined within a \`@layer\` directive.`
|
|
430
|
+
)
|
|
342
431
|
}
|
|
432
|
+
|
|
433
|
+
let rules = applyClassCache.get(applyCandidate)
|
|
434
|
+
|
|
435
|
+
candidates.push([applyCandidate, important, rules])
|
|
343
436
|
}
|
|
437
|
+
}
|
|
344
438
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// E.g.:
|
|
364
|
-
// .hover\:foo {
|
|
365
|
-
// @apply bar;
|
|
366
|
-
// }
|
|
367
|
-
// .bar {
|
|
368
|
-
// @apply foo;
|
|
369
|
-
// }
|
|
370
|
-
//
|
|
371
|
-
// This should not result in a circular dependency because we are
|
|
372
|
-
// just applying `.foo` and the rule above is `.hover\:foo` which is
|
|
373
|
-
// unrelated. However, if we were to apply `hover:foo` then we _did_
|
|
374
|
-
// have to include this one.
|
|
375
|
-
nodeClasses = nodeClasses.concat(
|
|
376
|
-
extractBaseCandidates(nodeClasses, context.tailwindConfig.separator)
|
|
439
|
+
for (let [parent, [candidates, atApplySource]] of perParentApplies) {
|
|
440
|
+
let siblings = []
|
|
441
|
+
|
|
442
|
+
for (let [applyCandidate, important, rules] of candidates) {
|
|
443
|
+
let potentialApplyCandidates = [
|
|
444
|
+
applyCandidate,
|
|
445
|
+
...extractBaseCandidates([applyCandidate], context.tailwindConfig.separator),
|
|
446
|
+
]
|
|
447
|
+
|
|
448
|
+
for (let [meta, node] of rules) {
|
|
449
|
+
let parentClasses = extractClasses(parent)
|
|
450
|
+
let nodeClasses = extractClasses(node)
|
|
451
|
+
|
|
452
|
+
// When we encounter a rule like `.dark .a, .b { … }` we only want to be left with `[.dark, .a]` if the base applyCandidate is `.a` or with `[.b]` if the base applyCandidate is `.b`
|
|
453
|
+
// So we've split them into groups
|
|
454
|
+
nodeClasses = nodeClasses.groups
|
|
455
|
+
.filter((classList) =>
|
|
456
|
+
classList.some((className) => potentialApplyCandidates.includes(className))
|
|
377
457
|
)
|
|
458
|
+
.flat()
|
|
459
|
+
|
|
460
|
+
// Add base utility classes from the @apply node to the list of
|
|
461
|
+
// classes to check whether it intersects and therefore results in a
|
|
462
|
+
// circular dependency or not.
|
|
463
|
+
//
|
|
464
|
+
// E.g.:
|
|
465
|
+
// .foo {
|
|
466
|
+
// @apply hover:a; // This applies "a" but with a modifier
|
|
467
|
+
// }
|
|
468
|
+
//
|
|
469
|
+
// We only have to do that with base classes of the `node`, not of the `parent`
|
|
470
|
+
// E.g.:
|
|
471
|
+
// .hover\:foo {
|
|
472
|
+
// @apply bar;
|
|
473
|
+
// }
|
|
474
|
+
// .bar {
|
|
475
|
+
// @apply foo;
|
|
476
|
+
// }
|
|
477
|
+
//
|
|
478
|
+
// This should not result in a circular dependency because we are
|
|
479
|
+
// just applying `.foo` and the rule above is `.hover\:foo` which is
|
|
480
|
+
// unrelated. However, if we were to apply `hover:foo` then we _did_
|
|
481
|
+
// have to include this one.
|
|
482
|
+
nodeClasses = nodeClasses.concat(
|
|
483
|
+
extractBaseCandidates(nodeClasses, context.tailwindConfig.separator)
|
|
484
|
+
)
|
|
378
485
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
486
|
+
let intersects = parentClasses.some((selector) => nodeClasses.includes(selector))
|
|
487
|
+
if (intersects) {
|
|
488
|
+
throw node.error(
|
|
489
|
+
`You cannot \`@apply\` the \`${applyCandidate}\` utility here because it creates a circular dependency.`
|
|
490
|
+
)
|
|
491
|
+
}
|
|
385
492
|
|
|
386
|
-
|
|
493
|
+
let root = postcss.root({ nodes: [node.clone()] })
|
|
387
494
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
495
|
+
// Make sure every node in the entire tree points back at the @apply rule that generated it
|
|
496
|
+
root.walk((node) => {
|
|
497
|
+
node.source = atApplySource
|
|
498
|
+
})
|
|
392
499
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
500
|
+
let canRewriteSelector =
|
|
501
|
+
node.type !== 'atrule' || (node.type === 'atrule' && node.name !== 'keyframes')
|
|
502
|
+
|
|
503
|
+
if (canRewriteSelector) {
|
|
504
|
+
root.walkRules((rule) => {
|
|
505
|
+
// Let's imagine you have the following structure:
|
|
506
|
+
//
|
|
507
|
+
// .foo {
|
|
508
|
+
// @apply bar;
|
|
509
|
+
// }
|
|
510
|
+
//
|
|
511
|
+
// @supports (a: b) {
|
|
512
|
+
// .bar {
|
|
513
|
+
// color: blue
|
|
514
|
+
// }
|
|
515
|
+
//
|
|
516
|
+
// .something-unrelated {}
|
|
517
|
+
// }
|
|
518
|
+
//
|
|
519
|
+
// In this case we want to apply `.bar` but it happens to be in
|
|
520
|
+
// an atrule node. We clone that node instead of the nested one
|
|
521
|
+
// because we still want that @supports rule to be there once we
|
|
522
|
+
// applied everything.
|
|
523
|
+
//
|
|
524
|
+
// However it happens to be that the `.something-unrelated` is
|
|
525
|
+
// also in that same shared @supports atrule. This is not good,
|
|
526
|
+
// and this should not be there. The good part is that this is
|
|
527
|
+
// a clone already and it can be safely removed. The question is
|
|
528
|
+
// how do we know we can remove it. Basically what we can do is
|
|
529
|
+
// match it against the applyCandidate that you want to apply. If
|
|
530
|
+
// it doesn't match the we can safely delete it.
|
|
531
|
+
//
|
|
532
|
+
// If we didn't do this, then the `replaceSelector` function
|
|
533
|
+
// would have replaced this with something that didn't exist and
|
|
534
|
+
// therefore it removed the selector altogether. In this specific
|
|
535
|
+
// case it would result in `{}` instead of `.something-unrelated {}`
|
|
536
|
+
if (!extractClasses(rule).some((candidate) => candidate === applyCandidate)) {
|
|
537
|
+
rule.remove()
|
|
538
|
+
return
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Strip the important selector from the parent selector if at the beginning
|
|
542
|
+
let importantSelector =
|
|
543
|
+
typeof context.tailwindConfig.important === 'string'
|
|
544
|
+
? context.tailwindConfig.important
|
|
545
|
+
: null
|
|
546
|
+
|
|
547
|
+
// We only want to move the "important" selector if this is a Tailwind-generated utility
|
|
548
|
+
// We do *not* want to do this for user CSS that happens to be structured the same
|
|
549
|
+
let isGenerated = parent.raws.tailwind !== undefined
|
|
550
|
+
|
|
551
|
+
let parentSelector =
|
|
552
|
+
isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0
|
|
553
|
+
? parent.selector.slice(importantSelector.length)
|
|
554
|
+
: parent.selector
|
|
433
555
|
|
|
434
|
-
|
|
556
|
+
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate)
|
|
435
557
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
558
|
+
// And then re-add it if it was removed
|
|
559
|
+
if (importantSelector && parentSelector !== parent.selector) {
|
|
560
|
+
rule.selector = applyImportantSelector(rule.selector, importantSelector)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
rule.walkDecls((d) => {
|
|
564
|
+
d.important = meta.important || important
|
|
439
565
|
})
|
|
440
|
-
}
|
|
441
566
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
])
|
|
567
|
+
// Move pseudo elements to the end of the selector (if necessary)
|
|
568
|
+
let selector = parser().astSync(rule.selector)
|
|
569
|
+
selector.each((sel) => movePseudos(sel))
|
|
570
|
+
rule.selector = selector.toString()
|
|
571
|
+
})
|
|
448
572
|
}
|
|
449
|
-
}
|
|
450
573
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
574
|
+
// It could be that the node we were inserted was removed because the class didn't match
|
|
575
|
+
// If that was the *only* rule in the parent, then we have nothing add so we skip it
|
|
576
|
+
if (!root.nodes[0]) {
|
|
577
|
+
continue
|
|
578
|
+
}
|
|
457
579
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if (apply.parent.nodes.length > 1) {
|
|
461
|
-
apply.remove()
|
|
462
|
-
} else {
|
|
463
|
-
// The node is empty, drop the full node
|
|
464
|
-
apply.parent.remove()
|
|
580
|
+
// Insert it
|
|
581
|
+
siblings.push([meta.sort, root.nodes[0]])
|
|
465
582
|
}
|
|
466
583
|
}
|
|
467
584
|
|
|
468
|
-
//
|
|
469
|
-
|
|
585
|
+
// Inject the rules, sorted, correctly
|
|
586
|
+
let nodes = context.offsets.sort(siblings).map((s) => s[1])
|
|
587
|
+
|
|
588
|
+
// `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
|
|
589
|
+
parent.after(nodes)
|
|
470
590
|
}
|
|
591
|
+
|
|
592
|
+
for (let apply of applies) {
|
|
593
|
+
// If there are left-over declarations, just remove the @apply
|
|
594
|
+
if (apply.parent.nodes.length > 1) {
|
|
595
|
+
apply.remove()
|
|
596
|
+
} else {
|
|
597
|
+
// The node is empty, drop the full node
|
|
598
|
+
apply.parent.remove()
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// Do it again, in case we have other `@apply` rules
|
|
603
|
+
processApply(root, context, localCache)
|
|
471
604
|
}
|
|
472
605
|
|
|
473
606
|
export default function expandApplyAtRules(context) {
|