tailwindcss 0.0.0-insiders.7c337f2 → 0.0.0-insiders.7d8eb21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +246 -6
- package/README.md +13 -9
- package/defaultTheme.d.ts +2 -1
- package/lib/cli/build/deps.js +54 -0
- package/lib/cli/build/index.js +48 -0
- package/lib/cli/build/plugin.js +362 -0
- package/lib/cli/build/utils.js +78 -0
- package/lib/cli/build/watching.js +178 -0
- package/lib/cli/help/index.js +71 -0
- package/lib/cli/index.js +18 -0
- package/lib/cli/init/index.js +46 -0
- package/lib/cli/shared.js +12 -0
- package/lib/cli-peer-dependencies.js +18 -5
- package/lib/cli.js +62 -592
- package/lib/constants.js +19 -12
- package/lib/corePluginList.js +5 -3
- package/lib/corePlugins.js +619 -347
- package/lib/css/preflight.css +7 -0
- package/lib/featureFlags.js +34 -22
- package/lib/index.js +16 -9
- package/lib/lib/cacheInvalidation.js +42 -21
- package/lib/lib/collapseAdjacentRules.js +16 -14
- package/lib/lib/collapseDuplicateDeclarations.js +13 -10
- package/lib/lib/content.js +177 -0
- package/lib/lib/defaultExtractor.js +230 -33
- package/lib/lib/detectNesting.js +13 -4
- package/lib/lib/evaluateTailwindFunctions.js +105 -42
- package/lib/lib/expandApplyAtRules.js +151 -92
- package/lib/lib/expandTailwindAtRules.js +134 -149
- package/lib/lib/findAtConfigPath.js +44 -0
- package/lib/lib/generateRules.js +404 -185
- package/lib/lib/getModuleDependencies.js +21 -18
- package/lib/lib/normalizeTailwindDirectives.js +11 -8
- package/lib/lib/offsets.js +285 -0
- package/lib/lib/partitionApplyAtRules.js +14 -11
- package/lib/lib/regex.js +60 -0
- package/lib/lib/remap-bitfield.js +87 -0
- package/lib/lib/resolveDefaultsAtRules.js +97 -79
- package/lib/lib/setupContextUtils.js +567 -242
- package/lib/lib/setupTrackingContext.js +77 -106
- package/lib/lib/sharedState.js +18 -10
- package/lib/lib/substituteScreenAtRules.js +9 -7
- package/lib/postcss-plugins/nesting/index.js +7 -5
- package/lib/postcss-plugins/nesting/plugin.js +10 -8
- package/lib/processTailwindFeatures.js +34 -31
- package/lib/public/colors.js +7 -5
- package/lib/public/create-plugin.js +6 -4
- package/lib/public/default-config.js +7 -5
- package/lib/public/default-theme.js +7 -5
- package/lib/public/resolve-config.js +13 -10
- package/lib/util/bigSign.js +4 -1
- package/lib/util/buildMediaQuery.js +10 -5
- package/lib/util/cloneDeep.js +6 -5
- package/lib/util/cloneNodes.js +9 -2
- package/lib/util/color.js +20 -17
- package/lib/util/configurePlugins.js +5 -2
- package/lib/util/createPlugin.js +6 -5
- package/lib/util/createUtilityPlugin.js +15 -13
- package/lib/util/dataTypes.js +75 -51
- package/lib/util/defaults.js +8 -5
- package/lib/util/escapeClassName.js +13 -10
- package/lib/util/escapeCommas.js +4 -1
- package/lib/util/flattenColorPalette.js +7 -8
- package/lib/util/formatVariantSelector.js +270 -103
- package/lib/util/getAllConfigs.js +34 -15
- package/lib/util/hashConfig.js +10 -7
- package/lib/util/isKeyframeRule.js +4 -1
- package/lib/util/isPlainObject.js +4 -1
- package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +34 -26
- package/lib/util/log.js +14 -8
- package/lib/util/nameClass.js +19 -8
- package/lib/util/negateValue.js +20 -5
- package/lib/util/normalizeConfig.js +94 -53
- package/lib/util/normalizeScreens.js +115 -4
- package/lib/util/parseAnimationValue.js +43 -41
- package/lib/util/parseBoxShadowValue.js +12 -45
- package/lib/util/parseDependency.js +37 -55
- package/lib/util/parseGlob.js +34 -0
- package/lib/util/parseObjectStyles.js +15 -12
- package/lib/util/pluginUtils.js +146 -42
- package/lib/util/prefixSelector.js +26 -9
- package/lib/util/removeAlphaVariables.js +29 -0
- package/lib/util/resolveConfig.js +104 -105
- package/lib/util/resolveConfigPath.js +20 -17
- package/lib/util/responsive.js +12 -9
- package/lib/util/splitAtTopLevelOnly.js +43 -0
- package/lib/util/tap.js +4 -1
- package/lib/util/toColorValue.js +4 -1
- package/lib/util/toPath.js +18 -2
- package/lib/util/transformThemeValue.js +23 -11
- package/lib/util/validateConfig.js +24 -0
- package/lib/util/validateFormalSyntax.js +24 -0
- package/lib/util/withAlphaVariable.js +32 -24
- package/package.json +32 -29
- package/peers/index.js +6693 -3036
- package/plugin.d.ts +10 -5
- package/resolveConfig.d.ts +12 -0
- package/scripts/generate-types.js +53 -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 +434 -0
- package/src/cli/build/utils.js +76 -0
- package/src/cli/build/watching.js +227 -0
- package/src/cli/help/index.js +70 -0
- package/src/cli/index.js +3 -0
- package/src/cli/init/index.js +50 -0
- package/src/cli/shared.js +5 -0
- package/src/cli-peer-dependencies.js +7 -1
- package/src/cli.js +46 -659
- package/src/corePlugins.js +346 -79
- package/src/css/preflight.css +7 -0
- package/src/featureFlags.js +12 -2
- package/src/index.js +5 -0
- package/src/lib/content.js +213 -0
- package/src/lib/defaultExtractor.js +202 -35
- package/src/lib/detectNesting.js +9 -1
- package/src/lib/evaluateTailwindFunctions.js +78 -7
- package/src/lib/expandApplyAtRules.js +129 -34
- package/src/lib/expandTailwindAtRules.js +12 -50
- package/src/lib/findAtConfigPath.js +48 -0
- package/src/lib/generateRules.js +379 -126
- package/src/lib/offsets.js +351 -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 +510 -120
- package/src/lib/setupTrackingContext.js +8 -45
- package/src/lib/sharedState.js +2 -0
- package/src/util/buildMediaQuery.js +5 -3
- package/src/util/cloneNodes.js +5 -1
- package/src/util/dataTypes.js +51 -26
- package/src/util/formatVariantSelector.js +317 -101
- package/src/util/getAllConfigs.js +19 -0
- package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
- package/src/util/log.js +1 -1
- package/src/util/nameClass.js +4 -0
- package/src/util/negateValue.js +10 -2
- package/src/util/normalizeConfig.js +40 -10
- 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 +132 -10
- package/src/util/prefixSelector.js +28 -10
- package/src/util/removeAlphaVariables.js +24 -0
- package/src/util/resolveConfig.js +70 -62
- package/src/util/splitAtTopLevelOnly.js +45 -0
- package/src/util/toPath.js +1 -1
- package/src/util/transformThemeValue.js +13 -3
- package/src/util/validateConfig.js +13 -0
- package/src/util/validateFormalSyntax.js +34 -0
- package/src/util/withAlphaVariable.js +1 -1
- package/stubs/defaultConfig.stub.js +165 -164
- package/stubs/simpleConfig.stub.js +1 -0
- package/types/config.d.ts +77 -37
- package/types/generated/default-theme.d.ts +342 -0
- package/types/index.d.ts +7 -1
- package/types.d.ts +0 -1
|
@@ -2,7 +2,6 @@ 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'
|
|
7
6
|
|
|
8
7
|
/** @typedef {Map<string, [any, import('postcss').Rule[]]>} ApplyCache */
|
|
@@ -34,6 +33,15 @@ function extractClasses(node) {
|
|
|
34
33
|
return Object.assign(classes, { groups: normalizedGroups })
|
|
35
34
|
}
|
|
36
35
|
|
|
36
|
+
let selectorExtractor = parser()
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {string} ruleSelectors
|
|
40
|
+
*/
|
|
41
|
+
function extractSelectors(ruleSelectors) {
|
|
42
|
+
return selectorExtractor.astSync(ruleSelectors)
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
function extractBaseCandidates(candidates, separator) {
|
|
38
46
|
let baseClasses = new Set()
|
|
39
47
|
|
|
@@ -140,9 +148,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
140
148
|
/** @type {ApplyCache} */
|
|
141
149
|
let cache = new Map()
|
|
142
150
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
root.walkRules((rule, idx) => {
|
|
151
|
+
root.walkRules((rule) => {
|
|
146
152
|
// Ignore rules generated by Tailwind
|
|
147
153
|
for (let node of pathToRoot(rule)) {
|
|
148
154
|
if (node.raws.tailwind?.layer !== undefined) {
|
|
@@ -152,6 +158,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
152
158
|
|
|
153
159
|
// Clone what's required to represent this singular rule in the tree
|
|
154
160
|
let container = nestedClone(rule)
|
|
161
|
+
let sort = context.offsets.create('user')
|
|
155
162
|
|
|
156
163
|
for (let className of extractClasses(rule)) {
|
|
157
164
|
let list = cache.get(className) || []
|
|
@@ -160,7 +167,7 @@ function buildLocalApplyCache(root, context) {
|
|
|
160
167
|
list.push([
|
|
161
168
|
{
|
|
162
169
|
layer: 'user',
|
|
163
|
-
sort
|
|
170
|
+
sort,
|
|
164
171
|
important: false,
|
|
165
172
|
},
|
|
166
173
|
container,
|
|
@@ -290,31 +297,97 @@ function processApply(root, context, localCache) {
|
|
|
290
297
|
* What happens in this function is that we prepend a `.` and escape the candidate.
|
|
291
298
|
* This will result in `.hover\:font-bold`
|
|
292
299
|
* Which means that we can replace `.hover\:font-bold` with `.abc` in `.hover\:font-bold:hover` resulting in `.abc:hover`
|
|
300
|
+
*
|
|
301
|
+
* @param {string} selector
|
|
302
|
+
* @param {string} utilitySelectors
|
|
303
|
+
* @param {string} candidate
|
|
293
304
|
*/
|
|
294
|
-
// TODO: Should we use postcss-selector-parser for this instead?
|
|
295
305
|
function replaceSelector(selector, utilitySelectors, candidate) {
|
|
296
|
-
let
|
|
297
|
-
let
|
|
298
|
-
let
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
306
|
+
let selectorList = extractSelectors(selector)
|
|
307
|
+
let utilitySelectorsList = extractSelectors(utilitySelectors)
|
|
308
|
+
let candidateList = extractSelectors(`.${escapeClassName(candidate)}`)
|
|
309
|
+
let candidateClass = candidateList.nodes[0].nodes[0]
|
|
310
|
+
|
|
311
|
+
selectorList.each((sel) => {
|
|
312
|
+
/** @type {Set<import('postcss-selector-parser').Selector>} */
|
|
313
|
+
let replaced = new Set()
|
|
314
|
+
|
|
315
|
+
utilitySelectorsList.each((utilitySelector) => {
|
|
316
|
+
let hasReplaced = false
|
|
317
|
+
utilitySelector = utilitySelector.clone()
|
|
318
|
+
|
|
319
|
+
utilitySelector.walkClasses((node) => {
|
|
320
|
+
if (node.value !== candidateClass.value) {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Don't replace multiple instances of the same class
|
|
325
|
+
// This is theoretically correct but only partially
|
|
326
|
+
// We'd need to generate every possible permutation of the replacement
|
|
327
|
+
// For example with `.foo + .foo { … }` and `section { @apply foo; }`
|
|
328
|
+
// We'd need to generate all of these:
|
|
329
|
+
// - `.foo + .foo`
|
|
330
|
+
// - `.foo + section`
|
|
331
|
+
// - `section + .foo`
|
|
332
|
+
// - `section + section`
|
|
333
|
+
if (hasReplaced) {
|
|
334
|
+
return
|
|
309
335
|
}
|
|
310
|
-
|
|
311
|
-
|
|
336
|
+
|
|
337
|
+
// Since you can only `@apply` class names this is sufficient
|
|
338
|
+
// We want to replace the matched class name with the selector the user is using
|
|
339
|
+
// Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
|
|
340
|
+
node.replaceWith(...sel.nodes.map((node) => node.clone()))
|
|
341
|
+
|
|
342
|
+
// Record that we did something and we want to use this new selector
|
|
343
|
+
replaced.add(utilitySelector)
|
|
344
|
+
|
|
345
|
+
hasReplaced = true
|
|
346
|
+
})
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
// Sort tag names before class names (but only sort each group (separated by a combinator)
|
|
350
|
+
// separately and not in total)
|
|
351
|
+
// This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
|
|
352
|
+
for (let sel of replaced) {
|
|
353
|
+
let groups = [[]]
|
|
354
|
+
for (let node of sel.nodes) {
|
|
355
|
+
if (node.type === 'combinator') {
|
|
356
|
+
groups.push(node)
|
|
357
|
+
groups.push([])
|
|
358
|
+
} else {
|
|
359
|
+
let last = groups[groups.length - 1]
|
|
360
|
+
last.push(node)
|
|
312
361
|
}
|
|
313
|
-
replaced.push(replacedSelector)
|
|
314
362
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
363
|
+
|
|
364
|
+
sel.nodes = []
|
|
365
|
+
|
|
366
|
+
for (let group of groups) {
|
|
367
|
+
if (Array.isArray(group)) {
|
|
368
|
+
group.sort((a, b) => {
|
|
369
|
+
if (a.type === 'tag' && b.type === 'class') {
|
|
370
|
+
return -1
|
|
371
|
+
} else if (a.type === 'class' && b.type === 'tag') {
|
|
372
|
+
return 1
|
|
373
|
+
} else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
|
|
374
|
+
return -1
|
|
375
|
+
} else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
|
|
376
|
+
return 1
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return 0
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
sel.nodes = sel.nodes.concat(group)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
sel.replaceWith(...replaced)
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
return selectorList.toString()
|
|
318
391
|
}
|
|
319
392
|
|
|
320
393
|
let perParentApplies = new Map()
|
|
@@ -329,7 +402,7 @@ function processApply(root, context, localCache) {
|
|
|
329
402
|
|
|
330
403
|
if (apply.parent.type === 'atrule') {
|
|
331
404
|
if (apply.parent.name === 'screen') {
|
|
332
|
-
|
|
405
|
+
let screenType = apply.parent.params
|
|
333
406
|
|
|
334
407
|
throw apply.error(
|
|
335
408
|
`@apply is not supported within nested at-rules like @screen. We suggest you write this as @apply ${applyCandidates
|
|
@@ -361,7 +434,7 @@ function processApply(root, context, localCache) {
|
|
|
361
434
|
}
|
|
362
435
|
}
|
|
363
436
|
|
|
364
|
-
for (
|
|
437
|
+
for (let [parent, [candidates, atApplySource]] of perParentApplies) {
|
|
365
438
|
let siblings = []
|
|
366
439
|
|
|
367
440
|
for (let [applyCandidate, important, rules] of candidates) {
|
|
@@ -463,7 +536,27 @@ function processApply(root, context, localCache) {
|
|
|
463
536
|
return
|
|
464
537
|
}
|
|
465
538
|
|
|
466
|
-
|
|
539
|
+
// Strip the important selector from the parent selector if at the beginning
|
|
540
|
+
let importantSelector =
|
|
541
|
+
typeof context.tailwindConfig.important === 'string'
|
|
542
|
+
? context.tailwindConfig.important
|
|
543
|
+
: null
|
|
544
|
+
|
|
545
|
+
// We only want to move the "important" selector if this is a Tailwind-generated utility
|
|
546
|
+
// We do *not* want to do this for user CSS that happens to be structured the same
|
|
547
|
+
let isGenerated = parent.raws.tailwind !== undefined
|
|
548
|
+
|
|
549
|
+
let parentSelector =
|
|
550
|
+
isGenerated && importantSelector && parent.selector.indexOf(importantSelector) === 0
|
|
551
|
+
? parent.selector.slice(importantSelector.length)
|
|
552
|
+
: parent.selector
|
|
553
|
+
|
|
554
|
+
rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate)
|
|
555
|
+
|
|
556
|
+
// And then re-add it if it was removed
|
|
557
|
+
if (importantSelector && parentSelector !== parent.selector) {
|
|
558
|
+
rule.selector = `${importantSelector} ${rule.selector}`
|
|
559
|
+
}
|
|
467
560
|
|
|
468
561
|
rule.walkDecls((d) => {
|
|
469
562
|
d.important = meta.important || important
|
|
@@ -471,17 +564,19 @@ function processApply(root, context, localCache) {
|
|
|
471
564
|
})
|
|
472
565
|
}
|
|
473
566
|
|
|
567
|
+
// It could be that the node we were inserted was removed because the class didn't match
|
|
568
|
+
// If that was the *only* rule in the parent, then we have nothing add so we skip it
|
|
569
|
+
if (!root.nodes[0]) {
|
|
570
|
+
continue
|
|
571
|
+
}
|
|
572
|
+
|
|
474
573
|
// Insert it
|
|
475
|
-
siblings.push([
|
|
476
|
-
// Ensure that when we are sorting, that we take the layer order into account
|
|
477
|
-
{ ...meta, sort: meta.sort | context.layerOrder[meta.layer] },
|
|
478
|
-
root.nodes[0],
|
|
479
|
-
])
|
|
574
|
+
siblings.push([meta.sort, root.nodes[0]])
|
|
480
575
|
}
|
|
481
576
|
}
|
|
482
577
|
|
|
483
578
|
// Inject the rules, sorted, correctly
|
|
484
|
-
let nodes =
|
|
579
|
+
let nodes = context.offsets.sort(siblings).map((s) => s[1])
|
|
485
580
|
|
|
486
581
|
// `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
|
|
487
582
|
parent.after(nodes)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import LRU from 'quick-lru'
|
|
2
2
|
import * as sharedState from './sharedState'
|
|
3
3
|
import { generateRules } from './generateRules'
|
|
4
|
-
import bigSign from '../util/bigSign'
|
|
5
4
|
import log from '../util/log'
|
|
6
5
|
import cloneNodes from '../util/cloneNodes'
|
|
7
6
|
import { defaultExtractor } from './defaultExtractor'
|
|
@@ -17,14 +16,14 @@ const builtInTransformers = {
|
|
|
17
16
|
svelte: (content) => content.replace(/(?:^|\s)class:/g, ' '),
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
function getExtractor(
|
|
21
|
-
let extractors = tailwindConfig.content.extract
|
|
19
|
+
function getExtractor(context, fileExtension) {
|
|
20
|
+
let extractors = context.tailwindConfig.content.extract
|
|
22
21
|
|
|
23
22
|
return (
|
|
24
23
|
extractors[fileExtension] ||
|
|
25
24
|
extractors.DEFAULT ||
|
|
26
25
|
builtInExtractors[fileExtension] ||
|
|
27
|
-
builtInExtractors.DEFAULT
|
|
26
|
+
builtInExtractors.DEFAULT(context)
|
|
28
27
|
)
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -74,8 +73,13 @@ function getClassCandidates(content, extractor, candidates, seen) {
|
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules
|
|
79
|
+
* @param {*} context
|
|
80
|
+
*/
|
|
77
81
|
function buildStylesheet(rules, context) {
|
|
78
|
-
let sortedRules =
|
|
82
|
+
let sortedRules = context.offsets.sort(rules)
|
|
79
83
|
|
|
80
84
|
let returnValue = {
|
|
81
85
|
base: new Set(),
|
|
@@ -83,48 +87,10 @@ function buildStylesheet(rules, context) {
|
|
|
83
87
|
components: new Set(),
|
|
84
88
|
utilities: new Set(),
|
|
85
89
|
variants: new Set(),
|
|
86
|
-
|
|
87
|
-
// All the CSS that is not Tailwind related can be put in this bucket. This
|
|
88
|
-
// will make it easier to later use this information when we want to
|
|
89
|
-
// `@apply` for example. The main reason we do this here is because we
|
|
90
|
-
// still need to make sure the order is correct. Last but not least, we
|
|
91
|
-
// will make sure to always re-inject this section into the css, even if
|
|
92
|
-
// certain rules were not used. This means that it will look like a no-op
|
|
93
|
-
// from the user's perspective, but we gathered all the useful information
|
|
94
|
-
// we need.
|
|
95
|
-
user: new Set(),
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
for (let [sort, rule] of sortedRules) {
|
|
99
|
-
|
|
100
|
-
returnValue.variants.add(rule)
|
|
101
|
-
continue
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (sort & context.layerOrder.base) {
|
|
105
|
-
returnValue.base.add(rule)
|
|
106
|
-
continue
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (sort & context.layerOrder.defaults) {
|
|
110
|
-
returnValue.defaults.add(rule)
|
|
111
|
-
continue
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (sort & context.layerOrder.components) {
|
|
115
|
-
returnValue.components.add(rule)
|
|
116
|
-
continue
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (sort & context.layerOrder.utilities) {
|
|
120
|
-
returnValue.utilities.add(rule)
|
|
121
|
-
continue
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (sort & context.layerOrder.user) {
|
|
125
|
-
returnValue.user.add(rule)
|
|
126
|
-
continue
|
|
127
|
-
}
|
|
93
|
+
returnValue[sort.layer].add(rule)
|
|
128
94
|
}
|
|
129
95
|
|
|
130
96
|
return returnValue
|
|
@@ -165,7 +131,7 @@ export default function expandTailwindAtRules(context) {
|
|
|
165
131
|
|
|
166
132
|
for (let { content, extension } of context.changedContent) {
|
|
167
133
|
let transformer = getTransformer(context.tailwindConfig, extension)
|
|
168
|
-
let extractor = getExtractor(context
|
|
134
|
+
let extractor = getExtractor(context, extension)
|
|
169
135
|
getClassCandidates(transformer(content), extractor, candidates, seen)
|
|
170
136
|
}
|
|
171
137
|
|
|
@@ -177,16 +143,12 @@ export default function expandTailwindAtRules(context) {
|
|
|
177
143
|
let classCacheCount = context.classCache.size
|
|
178
144
|
|
|
179
145
|
env.DEBUG && console.time('Generate rules')
|
|
180
|
-
|
|
146
|
+
generateRules(candidates, context)
|
|
181
147
|
env.DEBUG && console.timeEnd('Generate rules')
|
|
182
148
|
|
|
183
149
|
// We only ever add to the classCache, so if it didn't grow, there is nothing new.
|
|
184
150
|
env.DEBUG && console.time('Build stylesheet')
|
|
185
151
|
if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
|
|
186
|
-
for (let rule of rules) {
|
|
187
|
-
context.ruleCache.add(rule)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
152
|
context.stylesheetCache = buildStylesheet([...context.ruleCache], context)
|
|
191
153
|
}
|
|
192
154
|
env.DEBUG && console.timeEnd('Build stylesheet')
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find the @config at-rule in the given CSS AST and return the relative path to the config file
|
|
6
|
+
*
|
|
7
|
+
* @param {import('postcss').Root} root
|
|
8
|
+
* @param {import('postcss').Result} result
|
|
9
|
+
*/
|
|
10
|
+
export function findAtConfigPath(root, result) {
|
|
11
|
+
let configPath = null
|
|
12
|
+
let relativeTo = null
|
|
13
|
+
|
|
14
|
+
root.walkAtRules('config', (rule) => {
|
|
15
|
+
relativeTo = rule.source?.input.file ?? result.opts.from ?? null
|
|
16
|
+
|
|
17
|
+
if (relativeTo === null) {
|
|
18
|
+
throw rule.error(
|
|
19
|
+
'The `@config` directive cannot be used without setting `from` in your PostCSS config.'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (configPath) {
|
|
24
|
+
throw rule.error('Only one `@config` directive is allowed per file.')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let matches = rule.params.match(/(['"])(.*?)\1/)
|
|
28
|
+
if (!matches) {
|
|
29
|
+
throw rule.error('A path is required when using the `@config` directive.')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let inputPath = matches[2]
|
|
33
|
+
if (path.isAbsolute(inputPath)) {
|
|
34
|
+
throw rule.error('The `@config` directive cannot be used with an absolute path.')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
configPath = path.resolve(path.dirname(relativeTo), inputPath)
|
|
38
|
+
if (!fs.existsSync(configPath)) {
|
|
39
|
+
throw rule.error(
|
|
40
|
+
`The config file at "${inputPath}" does not exist. Make sure the path is correct and the file exists.`
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
rule.remove()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return configPath ? configPath : null
|
|
48
|
+
}
|